|
7 | 7 | #include <linux/clk.h>
|
8 | 8 | #include <linux/platform_device.h>
|
9 | 9 | #include <linux/dmaengine.h>
|
| 10 | +#include <linux/bitfield.h> |
10 | 11 |
|
11 | 12 | #include <linux/iio/iio.h>
|
12 | 13 | #include <linux/iio/sysfs.h>
|
|
28 | 29 | #define M2K_LA_REG_TRIGGER_DELAY 0x44
|
29 | 30 | #define M2K_LA_REG_TRIGGERED 0x48
|
30 | 31 | #define M2K_LA_REG_STREAMING 0x4c
|
| 32 | +#define M2K_LA_REG_INSTRUMENT_TRIGGER 0x54 |
31 | 33 |
|
32 | 34 | #define M2K_LA_TRIGGER_EDGE_ANY 0
|
33 | 35 | #
8000
define M2K_LA_TRIGGER_EDGE_RISING 1
|
|
38 | 40 | #define M2K_LA_TRIGGER_LOGIC_MODE_OR 0
|
39 | 41 | #define M2K_LA_TRIGGER_LOGIC_MODE_AND 1
|
40 | 42 |
|
| 43 | +#define M2K_LA_TRIGGER_CONDITION_MASK(x) (0x155 << x) |
| 44 | +#define M2K_LA_TRIGGER_SOURCE_MASK GENMASK(19, 16) |
| 45 | +#define M2K_LA_TRIGGER_EXT_SOURCE_MASK GENMASK(17, 16) |
| 46 | + |
41 | 47 | struct m2k_la {
|
42 | 48 | void __iomem *regs;
|
43 | 49 |
|
@@ -69,6 +75,17 @@ static unsigned int m2k_la_read(struct m2k_la *m2k_la, unsigned int reg)
|
69 | 75 | return readl_relaxed(m2k_la->regs + reg);
|
70 | 76 | }
|
71 | 77 |
|
| 78 | +static void m2k_la_update(struct m2k_la *m2k_la, unsigned int reg, |
| 79 | + unsigned int writeval, const unsigned int mask) |
| 80 | +{ |
| 81 | + unsigned int regval; |
| 82 | + |
| 83 | + regval = m2k_la_read(m2k_la, reg); |
| 84 | + regval &= ~mask; |
| 85 | + writeval &= mask; |
| 86 | + m2k_la_write(m2k_la, reg, writeval | regval); |
| 87 | +} |
| 88 | + |
72 | 89 | static int m2k_la_read_raw(struct iio_dev *indio_dev,
|
73 | 90 | const struct iio_chan_spec *chan, int *val, int *val2, long info)
|
74 | 91 | {
|
@@ -433,6 +450,129 @@ static const struct iio_chan_spec_ext_info m2k_la_rx_ext_info[] = {
|
433 | 450 | {}
|
434 | 451 | };
|
435 | 452 |
|
| 453 | +static int m2k_la_set_trig_condition(struct iio_dev *indio_dev, |
| 454 | + const struct iio_chan_spec *chan, unsigned int val) |
| 455 | +{ |
| 456 | + struct m2k_la *m2k_la = iio_device_get_drvdata(indio_dev); |
| 457 | + int trig_src; |
| 458 | + |
| 459 | + mutex_lock(&m2k_la->lock); |
| 460 | + /* Read Trig SRC */ |
| 461 | + trig_src = m2k_la_read(m2k_la, M2K_LA_REG_INSTRUMENT_TRIGGER); |
| 462 | + trig_src = FIELD_GET(M2K_LA_TRIGGER_EXT_SOURCE_MASK, trig_src); |
| 463 | + |
| 464 | + if (trig_src) { |
| 465 | + trig_src -= 1; |
| 466 | + if (val) |
| 467 | + /* Subtract 1 because of the none item. Multiply with 2 |
| 468 | + * and shift with trig_src due to channel selection |
| 469 | + */ |
| 470 | + val = BIT(2 * (val - 1)) << trig_src; |
| 471 | + |
| 472 | + m2k_la_update(m2k_la, M2K_LA_REG_INSTRUMENT_TRIGGER, val, |
| 473 | + M2K_LA_TRIGGER_CONDITION_MASK(trig_src)); |
| 474 | + } |
| 475 | + |
| 476 | + mutex_unlock(&m2k_la->lock); |
| 477 | + |
| 478 | + return 0; |
| 479 | +} |
| 480 | + |
| 481 | +static int m2k_la_get_trig_condition(struct iio_dev *indio_dev, |
| 482 | + const struct iio_chan_spec *chan) |
| 483 | +{ |
| 484 | + struct m2k_la *m2k_la = iio_device_get_drvdata(indio_dev); |
| 485 | + int val, trig_src; |
| 486 | + |
| 487 | + /* Read Trig SRC */ |
| 488 | + trig_src = val = m2k_la_read(m2k_la, M2K_LA_REG_INSTRUMENT_TRIGGER); |
| 489 | + trig_src = FIELD_GET(M2K_LA_TRIGGER_EXT_SOURCE_MASK, trig_src); |
| 490 | + |
| 491 | + if (trig_src) { |
| 492 | + trig_src -= 1; |
| 493 | + val &= M2K_LA_TRIGGER_CONDITION_MASK(trig_src); |
| 494 | + return ((fls(val >> trig_src) + 1) / 2); |
| 495 | + } |
| 496 | + |
| 497 | + return 0; |
| 498 | +} |
| 499 | + |
| 500 | +static const char * const m2k_la_trigger_tx_items[] = { |
| 501 | + "none", |
| 502 | + "level-low", |
| 503 | + "level-high", |
| 504 | + "edge-any", |
| 505 | + "edge-rising", |
| 506 | + "edge-falling", |
| 507 | +}; |
| 508 | + |
| 509 | +static const struct iio_enum m2k_la_trig_condition_enum = { |
| 510 | + .items = m2k_la_trigger_tx_items, |
| 511 | + .num_items = ARRAY_SIZE(m2k_la_trigger_tx_items), |
| 512 | + .set = m2k_la_set_trig_condition, |
| 513 | + .get = m2k_la_get_trig_condition, |
| 514 | +}; |
| 515 | + |
| 516 | +static int m2k_la_set_trig_src(struct iio_dev *indio_dev, |
| 517 | + const struct iio_chan_spec *chan, unsigned int val) |
| 518 | +{ |
| 519 | + struct m2k_la *m2k_la = iio_device_get_drvdata(indio_dev); |
| 520 | + |
| 521 | + mutex_lock(&m2k_la->lock); |
| 522 | + |
| 523 | + /* reset required by HDL */ |
| 524 | + m2k_la_update(m2k_la, M2K_LA_REG_INSTRUMENT_TRIGGER, 0x0, |
| 525 | + M2K_LA_TRIGGER_SOURCE_MASK); |
| 526 | + |
| 527 | + val = BIT(val) << 15; |
| 528 | + m2k_la_update(m2k_la, M2K_LA_REG_INSTRUMENT_TRIGGER, val, |
| 529 | + M2K_LA_TRIGGER_SOURCE_MASK); |
| 530 | + |
| 531 | + mutex_unlock(&m2k_la->lock); |
| 532 | + |
| 533 | + return 0; |
| 534 | +} |
| 535 | + |
| 536 | +static int m2k_la_get_trig_src(struct iio_dev *indio_dev, |
| 537 | + const struct iio_chan_spec *chan) |
| 538 | +{ |
| 539 | + struct m2k_la *m2k_la = iio_device_get_drvdata(indio_dev); |
| 540 | + int val; |
| 541 | + |
| 542 | + val = m2k_la_read(m2k_la, M2K_LA_REG_INSTRUMENT_TRIGGER); |
| 543 | + |
| 544 | + if (val & M2K_LA_TRIGGER_SOURCE_MASK) |
| 545 | + return fls(val) - 16; |
| 546 | + |
| 547 | + return 0; |
| 548 | +} |
| 549 | + |
| 550 | +static const char * const m2k_la_trig_src_items[] = { |
| 551 | + "none", |
| 552 | + "trigger-i_0", |
| 553 | + "trigger-i_1", |
| 554 | + "trigger-adc", |
| 555 | + "trigger-la", |
| 556 | +}; |
| 557 | + |
| 558 | +static const struct iio_enum m2k_la_trig_src_enum = { |
| 559 | + .items = m2k_la_trig_src_items, |
| 560 | + .num_items = ARRAY_SIZE(m2k_la_trig_src_items), |
| 561 | + .set = m2k_la_set_trig_src, |
| 562 | + .get = m2k_la_get_trig_src, |
| 563 | +}; |
| 564 | + |
| 565 | +static const struct iio_chan_spec_ext_info m2k_la_tx_ext_info[] = { |
| 566 | + IIO_ENUM_AVAILABLE_SHARED("trigger_src", IIO_SHARED_BY_ALL, |
| 567 | + &m2k_la_trig_src_enum), |
| 568 | + IIO_ENUM("trigger_src", IIO_SHARED_BY_ALL, &m2k_la_trig_src_enum), |
| 569 | + IIO_ENUM_AVAILABLE_SHARED("trigger_condition", IIO_SHARED_BY_ALL, |
| 570 | + &m2k_la_trig_condition_enum), |
| 571 | + IIO_ENUM("trigger_condition", IIO_SHARED_BY_ALL, |
| 572 | + &m2k_la_trig_condition_enum), |
| 573 | + { }, |
| 574 | +}; |
| 575 | + |
436 | 576 | static int m2k_la_set_direction(struct iio_dev *indio_dev,
|
437 | 577 | const struct iio_chan_spec *chan, unsigned int val)
|
438 | 578 | {
|
@@ -603,6 +743,7 @@ static const struct iio_chan_spec_ext_info m2k_la_ext_info[] = {
|
603 | 743 | .output = 1, \
|
604 | 744 | .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
|
605 | 745 | .scan_index = 0, \
|
| 746 | + .ext_info = m2k_la_tx_ext_info, \ |
606 | 747 | .scan_type = { \
|
607 | 748 | .sign = 'u', \
|
608 | 749 | .realbits = 1, \
|
|
0 commit comments