diff options
Diffstat (limited to 'drivers/iio/adc/adi-axi-adc.c')
-rw-r--r-- | drivers/iio/adc/adi-axi-adc.c | 71 |
1 files changed, 65 insertions, 6 deletions
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c index 21ce7564e83d..5c8c87eb36d1 100644 --- a/drivers/iio/adc/adi-axi-adc.c +++ b/drivers/iio/adc/adi-axi-adc.c @@ -61,6 +61,10 @@ #define ADI_AXI_ADC_REG_CHAN_STATUS(c) (0x0404 + (c) * 0x40) #define ADI_AXI_ADC_CHAN_STAT_PN_MASK GENMASK(2, 1) +/* out of sync */ +#define ADI_AXI_ADC_CHAN_STAT_PN_OOS BIT(1) +/* spurious out of sync */ +#define ADI_AXI_ADC_CHAN_STAT_PN_ERR BIT(2) #define ADI_AXI_ADC_REG_CHAN_CTRL_3(c) (0x0418 + (c) * 0x40) #define ADI_AXI_ADC_CHAN_PN_SEL_MASK GENMASK(19, 16) @@ -199,17 +203,19 @@ static int axi_adc_test_pattern_set(struct iio_backend *back, return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CHAN_CTRL_3(chan), ADI_AXI_ADC_CHAN_PN_SEL_MASK, FIELD_PREP(ADI_AXI_ADC_CHAN_PN_SEL_MASK, 0)); + case IIO_BACKEND_ADI_PRBS_23A: + return regmap_update_bits(st->regmap, ADI_AXI_ADC_REG_CHAN_CTRL_3(chan), + ADI_AXI_ADC_CHAN_PN_SEL_MASK, + FIELD_PREP(ADI_AXI_ADC_CHAN_PN_SEL_MASK, 1)); default: return -EINVAL; } } -static int axi_adc_chan_status(struct iio_backend *back, unsigned int chan, - bool *error) +static int axi_adc_read_chan_status(struct adi_axi_adc_state *st, unsigned int chan, + unsigned int *status) { - struct adi_axi_adc_state *st = iio_backend_get_priv(back); int ret; - u32 val; guard(mutex)(&st->lock); /* reset test bits by setting them */ @@ -221,7 +227,18 @@ static int axi_adc_chan_status(struct iio_backend *back, unsigned int chan, /* let's give enough time to validate or erroring the incoming pattern */ fsleep(1000); - ret = regmap_read(st->regmap, ADI_AXI_ADC_REG_CHAN_STATUS(chan), &val); + return regmap_read(st->regmap, ADI_AXI_ADC_REG_CHAN_STATUS(chan), + status); +} + +static int axi_adc_chan_status(struct iio_backend *back, unsigned int chan, + bool *error) +{ + struct adi_axi_adc_state *st = iio_backend_get_priv(back); + u32 val; + int ret; + + ret = axi_adc_read_chan_status(st, chan, &val); if (ret) return ret; @@ -233,6 +250,30 @@ static int axi_adc_chan_status(struct iio_backend *back, unsigned int chan, return 0; } +static int axi_adc_debugfs_print_chan_status(struct iio_backend *back, + unsigned int chan, char *buf, + size_t len) +{ + struct adi_axi_adc_state *st = iio_backend_get_priv(back); + u32 val; + int ret; + + ret = axi_adc_read_chan_status(st, chan, &val); + if (ret) + return ret; + + /* + * PN_ERR is cleared in case out of sync is set. Hence, no point in + * checking both bits. + */ + if (val & ADI_AXI_ADC_CHAN_STAT_PN_OOS) + return scnprintf(buf, len, "CH%u: Out of Sync.\n", chan); + if (val & ADI_AXI_ADC_CHAN_STAT_PN_ERR) + return scnprintf(buf, len, "CH%u: Spurious Out of Sync.\n", chan); + + return scnprintf(buf, len, "CH%u: OK.\n", chan); +} + static int axi_adc_chan_enable(struct iio_backend *back, unsigned int chan) { struct adi_axi_adc_state *st = iio_backend_get_priv(back); @@ -267,13 +308,24 @@ static void axi_adc_free_buffer(struct iio_backend *back, iio_dmaengine_buffer_free(buffer); } +static int axi_adc_reg_access(struct iio_backend *back, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct adi_axi_adc_state *st = iio_backend_get_priv(back); + + if (readval) + return regmap_read(st->regmap, reg, readval); + + return regmap_write(st->regmap, reg, writeval); +} + static const struct regmap_config axi_adc_regmap_config = { .val_bits = 32, .reg_bits = 32, .reg_stride = 4, }; -static const struct iio_backend_ops adi_axi_adc_generic = { +static const struct iio_backend_ops adi_axi_adc_ops = { .enable = axi_adc_enable, .disable = axi_adc_disable, .data_format_set = axi_adc_data_format_set, @@ -285,6 +337,13 @@ static const struct iio_backend_ops adi_axi_adc_generic = { .iodelay_set = axi_adc_iodelays_set, .test_pattern_set = axi_adc_test_pattern_set, .chan_status = axi_adc_chan_status, + .debugfs_reg_access = iio_backend_debugfs_ptr(axi_adc_reg_access), + .debugfs_print_chan_status = iio_backend_debugfs_ptr(axi_adc_debugfs_print_chan_status), +}; + +static const struct iio_backend_info adi_axi_adc_generic = { + .name = "axi-adc", + .ops = &adi_axi_adc_ops, }; static int adi_axi_adc_probe(struct platform_device *pdev) |