From: Jonathan Cameron <jic23@kernel.org>
To: Lars-Peter Clausen <lars@metafoo.de>
Cc: Peter Meerwald-Stadler <pmeerw@pmeerw.net>,
Michal Simek <michal.simek@xilinx.com>,
linux-iio@vger.kernel.org
Subject: Re: [PATCH 2/2] iio: xilinx-xadc: Add basic support for Ultrascale System Monitor
Date: Wed, 23 Sep 2020 21:47:28 +0100 [thread overview]
Message-ID: <20200923214728.6e0c07b0@archlinux> (raw)
In-Reply-To: <20200922134624.13191-2-lars@metafoo.de>
On Tue, 22 Sep 2020 15:46:24 +0200
Lars-Peter Clausen <lars@metafoo.de> wrote:
> The xilinx-xadc IIO driver currently has support for the XADC in the Xilinx
> 7 series FPGAs. The system-monitor is the equivalent to the XADC in the
> Xilinx UltraScale and UltraScale+ FPGAs.
>
> The IP designers did a good job at maintaining backwards compatibility and
> only minor changes are required to add basic support for the system-monitor
> core.
>
> The non backwards compatible changes are:
> * Register map offset was moved from 0x200 to 0x400
> * Only one ADC compared to two in the XADC
> * 10 bit ADC instead of 12 bit ADC
> * Two of the channels monitor different supplies
>
> Add the necessary logic to accommodate these changes to support the
> system-monitor in the XADC driver.
>
> Note that this patch does not include support for some new features found
> in the system-monitor like additional alarms, user supply monitoring and
> secondary system-monitor access. This might be added at a later time.
>
> Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Very nice. Will let this sit on the mailing list a bit longer
but looks good to me.
Thanks,
Jonathan
> ---
> drivers/iio/adc/Kconfig | 11 +-
> drivers/iio/adc/xilinx-xadc-core.c | 202 ++++++++++++++++++++-------
> drivers/iio/adc/xilinx-xadc-events.c | 9 +-
> drivers/iio/adc/xilinx-xadc.h | 6 +
> 4 files changed, 172 insertions(+), 56 deletions(-)
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index e7a9c1834d39..c31fb6b8f8e3 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -1215,8 +1215,15 @@ config XILINX_XADC
> select IIO_BUFFER
> select IIO_TRIGGERED_BUFFER
> help
> - Say yes here to have support for the Xilinx XADC. The driver does support
> - both the ZYNQ interface to the XADC as well as the AXI-XADC interface.
> + Say yes here to have support for the Xilinx 7 Series XADC or
> + UltraScale/UltraScale+ System Management Wizard.
> +
> + For the 7 Series the driver does support both the ZYNQ interface
> + to the XADC as well as the AXI-XADC interface.
> +
> + The driver also support the Xilinx System Management Wizard IP core
> + that can be used to access the System Monitor ADC on the Xilinx
> + UltraScale and UltraScale+ FPGAs.
>
> The driver can also be build as a module. If so, the module will be called
> xilinx-xadc.
> diff --git a/drivers/iio/adc/xilinx-xadc-core.c b/drivers/iio/adc/xilinx-xadc-core.c
> index d0b7ef296afb..294ca3455587 100644
> --- a/drivers/iio/adc/xilinx-xadc-core.c
> +++ b/drivers/iio/adc/xilinx-xadc-core.c
> @@ -92,7 +92,12 @@ static const unsigned int XADC_ZYNQ_UNMASK_TIMEOUT = 500;
> #define XADC_AXI_REG_GIER 0x5c
> #define XADC_AXI_REG_IPISR 0x60
> #define XADC_AXI_REG_IPIER 0x68
> -#define XADC_AXI_ADC_REG_OFFSET 0x200
> +
> +/* 7 Series */
> +#define XADC_7S_AXI_ADC_REG_OFFSET 0x200
> +
> +/* UltraScale */
> +#define XADC_US_AXI_ADC_REG_OFFSET 0x400
>
> #define XADC_AXI_RESET_MAGIC 0xa
> #define XADC_AXI_GIER_ENABLE BIT(31)
> @@ -447,6 +452,12 @@ static const struct xadc_ops xadc_zynq_ops = {
> .get_dclk_rate = xadc_zynq_get_dclk_rate,
> .interrupt_handler = xadc_zynq_interrupt_handler,
> .update_alarm = xadc_zynq_update_alarm,
> + .type = XADC_TYPE_S7,
> +};
> +
> +static const unsigned int xadc_axi_reg_offsets[] = {
> + [XADC_TYPE_S7] = XADC_7S_AXI_ADC_REG_OFFSET,
> + [XADC_TYPE_US] = XADC_US_AXI_ADC_REG_OFFSET,
> };
>
> static int xadc_axi_read_adc_reg(struct xadc *xadc, unsigned int reg,
> @@ -454,7 +465,8 @@ static int xadc_axi_read_adc_reg(struct xadc *xadc, unsigned int reg,
> {
> uint32_t val32;
>
> - xadc_read_reg(xadc, XADC_AXI_ADC_REG_OFFSET + reg * 4, &val32);
> + xadc_read_reg(xadc, xadc_axi_reg_offsets[xadc->ops->type] + reg * 4,
> + &val32);
> *val = val32 & 0xffff;
>
> return 0;
> @@ -463,7 +475,8 @@ static int xadc_axi_read_adc_reg(struct xadc *xadc, unsigned int reg,
> static int xadc_axi_write_adc_reg(struct xadc *xadc, unsigned int reg,
> uint16_t val)
> {
> - xadc_write_reg(xadc, XADC_AXI_ADC_REG_OFFSET + reg * 4, val);
> + xadc_write_reg(xadc, xadc_axi_reg_offsets[xadc->ops->type] + reg * 4,
> + val);
>
> return 0;
> }
> @@ -541,7 +554,7 @@ static unsigned long xadc_axi_get_dclk(struct xadc *xadc)
> return clk_get_rate(xadc->clk);
> }
>
> -static const struct xadc_ops xadc_axi_ops = {
> +static const struct xadc_ops xadc_7s_axi_ops = {
> .read = xadc_axi_read_adc_reg,
> .write = xadc_axi_write_adc_reg,
> .setup = xadc_axi_setup,
> @@ -549,6 +562,18 @@ static const struct xadc_ops xadc_axi_ops = {
> .update_alarm = xadc_axi_update_alarm,
> .interrupt_handler = xadc_axi_interrupt_handler,
> .flags = XADC_FLAGS_BUFFERED,
> + .type = XADC_TYPE_S7,
> +};
> +
> +static const struct xadc_ops xadc_us_axi_ops = {
> + .read = xadc_axi_read_adc_reg,
> + .write = xadc_axi_write_adc_reg,
> + .setup = xadc_axi_setup,
> + .get_dclk_rate = xadc_axi_get_dclk,
> + .update_alarm = xadc_axi_update_alarm,
> + .interrupt_handler = xadc_axi_interrupt_handler,
> + .flags = XADC_FLAGS_BUFFERED,
> + .type = XADC_TYPE_US,
> };
>
> static int _xadc_update_adc_reg(struct xadc *xadc, unsigned int reg,
> @@ -732,6 +757,15 @@ static int xadc_power_adc_b(struct xadc *xadc, unsigned int seq_mode)
> {
> uint16_t val;
>
> + /*
> + * As per datasheet the power-down bits are don't care in the
> + * UltraScale, but as per reality setting the power-down bit for the
> + * non-existing ADC-B powers down the main ADC, so just return and don't
> + * do anything.
> + */
> + if (xadc->ops->type == XADC_TYPE_US)
> + return 0;
> +
> /* Powerdown the ADC-B when it is not needed. */
> switch (seq_mode) {
> case XADC_CONF1_SEQ_SIMULTANEOUS:
> @@ -751,6 +785,10 @@ static int xadc_get_seq_mode(struct xadc *xadc, unsigned long scan_mode)
> {
> unsigned int aux_scan_mode = scan_mode >> 16;
>
> + /* UltraScale has only one ADC and supports only continuous mode */
> + if (xadc->ops->type == XADC_TYPE_US)
> + return XADC_CONF1_SEQ_CONTINUOUS;
> +
> if (xadc->external_mux_mode == XADC_EXTERNAL_MUX_DUAL)
> return XADC_CONF1_SEQ_SIMULTANEOUS;
>
> @@ -863,6 +901,7 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
> struct iio_chan_spec const *chan, int *val, int *val2, long info)
> {
> struct xadc *xadc = iio_priv(indio_dev);
> + unsigned int bits = chan->scan_type.realbits;
> uint16_t val16;
> int ret;
>
> @@ -874,17 +913,17 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
> if (ret < 0)
> return ret;
>
> - val16 >>= 4;
> + val16 >>= chan->scan_type.shift;
> if (chan->scan_type.sign == 'u')
> *val = val16;
> else
> - *val = sign_extend32(val16, 11);
> + *val = sign_extend32(val16, bits - 1);
>
> return IIO_VAL_INT;
> case IIO_CHAN_INFO_SCALE:
> switch (chan->type) {
> case IIO_VOLTAGE:
> - /* V = (val * 3.0) / 4096 */
> + /* V = (val * 3.0) / 2**bits */
> switch (chan->address) {
> case XADC_REG_VCCINT:
> case XADC_REG_VCCAUX:
> @@ -900,19 +939,19 @@ static int xadc_read_raw(struct iio_dev *indio_dev,
> *val = 1000;
> break;
> }
> - *val2 = 12;
> + *val2 = chan->scan_type.realbits;
> return IIO_VAL_FRACTIONAL_LOG2;
> case IIO_TEMP:
> - /* Temp in C = (val * 503.975) / 4096 - 273.15 */
> + /* Temp in C = (val * 503.975) / 2**bits - 273.15 */
> *val = 503975;
> - *val2 = 12;
> + *val2 = bits;
> return IIO_VAL_FRACTIONAL_LOG2;
> default:
> return -EINVAL;
> }
> case IIO_CHAN_INFO_OFFSET:
> /* Only the temperature channel has an offset */
> - *val = -((273150 << 12) / 503975);
> + *val = -((273150 << bits) / 503975);
> return IIO_VAL_INT;
> case IIO_CHAN_INFO_SAMP_FREQ:
> ret = xadc_read_samplerate(xadc);
> @@ -1001,7 +1040,7 @@ static const struct iio_event_spec xadc_voltage_events[] = {
> },
> };
>
> -#define XADC_CHAN_TEMP(_chan, _scan_index, _addr) { \
> +#define XADC_CHAN_TEMP(_chan, _scan_index, _addr, _bits) { \
> .type = IIO_TEMP, \
> .indexed = 1, \
> .channel = (_chan), \
> @@ -1015,14 +1054,14 @@ static const struct iio_event_spec xadc_voltage_events[] = {
> .scan_index = (_scan_index), \
> .scan_type = { \
> .sign = 'u', \
> - .realbits = 12, \
> + .realbits = (_bits), \
> .storagebits = 16, \
> - .shift = 4, \
> + .shift = 16 - (_bits), \
> .endianness = IIO_CPU, \
> }, \
> }
>
> -#define XADC_CHAN_VOLTAGE(_chan, _scan_index, _addr, _ext, _alarm) { \
> +#define XADC_CHAN_VOLTAGE(_chan, _scan_index, _addr, _bits, _ext, _alarm) { \
> .type = IIO_VOLTAGE, \
> .indexed = 1, \
> .channel = (_chan), \
> @@ -1035,41 +1074,82 @@ static const struct iio_event_spec xadc_voltage_events[] = {
> .scan_index = (_scan_index), \
> .scan_type = { \
> .sign = ((_addr) == XADC_REG_VREFN) ? 's' : 'u', \
> - .realbits = 12, \
> + .realbits = (_bits), \
> .storagebits = 16, \
> - .shift = 4, \
> + .shift = 16 - (_bits), \
> .endianness = IIO_CPU, \
> }, \
> .extend_name = _ext, \
> }
>
> -static const struct iio_chan_spec xadc_channels[] = {
> - XADC_CHAN_TEMP(0, 8, XADC_REG_TEMP),
> - XADC_CHAN_VOLTAGE(0, 9, XADC_REG_VCCINT, "vccint", true),
> - XADC_CHAN_VOLTAGE(1, 10, XADC_REG_VCCAUX, "vccaux", true),
> - XADC_CHAN_VOLTAGE(2, 14, XADC_REG_VCCBRAM, "vccbram", true),
> - XADC_CHAN_VOLTAGE(3, 5, XADC_REG_VCCPINT, "vccpint", true),
> - XADC_CHAN_VOLTAGE(4, 6, XADC_REG_VCCPAUX, "vccpaux", true),
> - XADC_CHAN_VOLTAGE(5, 7, XADC_REG_VCCO_DDR, "vccoddr", true),
> - XADC_CHAN_VOLTAGE(6, 12, XADC_REG_VREFP, "vrefp", false),
> - XADC_CHAN_VOLTAGE(7, 13, XADC_REG_VREFN, "vrefn", false),
> - XADC_CHAN_VOLTAGE(8, 11, XADC_REG_VPVN, NULL, false),
> - XADC_CHAN_VOLTAGE(9, 16, XADC_REG_VAUX(0), NULL, false),
> - XADC_CHAN_VOLTAGE(10, 17, XADC_REG_VAUX(1), NULL, false),
> - XADC_CHAN_VOLTAGE(11, 18, XADC_REG_VAUX(2), NULL, false),
> - XADC_CHAN_VOLTAGE(12, 19, XADC_REG_VAUX(3), NULL, false),
> - XADC_CHAN_VOLTAGE(13, 20, XADC_REG_VAUX(4), NULL, false),
> - XADC_CHAN_VOLTAGE(14, 21, XADC_REG_VAUX(5), NULL, false),
> - XADC_CHAN_VOLTAGE(15, 22, XADC_REG_VAUX(6), NULL, false),
> - XADC_CHAN_VOLTAGE(16, 23, XADC_REG_VAUX(7), NULL, false),
> - XADC_CHAN_VOLTAGE(17, 24, XADC_REG_VAUX(8), NULL, false),
> - XADC_CHAN_VOLTAGE(18, 25, XADC_REG_VAUX(9), NULL, false),
> - XADC_CHAN_VOLTAGE(19, 26, XADC_REG_VAUX(10), NULL, false),
> - XADC_CHAN_VOLTAGE(20, 27, XADC_REG_VAUX(11), NULL, false),
> - XADC_CHAN_VOLTAGE(21, 28, XADC_REG_VAUX(12), NULL, false),
> - XADC_CHAN_VOLTAGE(22, 29, XADC_REG_VAUX(13), NULL, false),
> - XADC_CHAN_VOLTAGE(23, 30, XADC_REG_VAUX(14), NULL, false),
> - XADC_CHAN_VOLTAGE(24, 31, XADC_REG_VAUX(15), NULL, false),
> +/* 7 Series */
> +#define XADC_7S_CHAN_TEMP(_chan, _scan_index, _addr) \
> + XADC_CHAN_TEMP(_chan, _scan_index, _addr, 12)
> +#define XADC_7S_CHAN_VOLTAGE(_chan, _scan_index, _addr, _ext, _alarm) \
> + XADC_CHAN_VOLTAGE(_chan, _scan_index, _addr, 12, _ext, _alarm)
> +
> +static const struct iio_chan_spec xadc_7s_channels[] = {
> + XADC_7S_CHAN_TEMP(0, 8, XADC_REG_TEMP),
> + XADC_7S_CHAN_VOLTAGE(0, 9, XADC_REG_VCCINT, "vccint", true),
> + XADC_7S_CHAN_VOLTAGE(1, 10, XADC_REG_VCCAUX, "vccaux", true),
> + XADC_7S_CHAN_VOLTAGE(2, 14, XADC_REG_VCCBRAM, "vccbram", true),
> + XADC_7S_CHAN_VOLTAGE(3, 5, XADC_REG_VCCPINT, "vccpint", true),
> + XADC_7S_CHAN_VOLTAGE(4, 6, XADC_REG_VCCPAUX, "vccpaux", true),
> + XADC_7S_CHAN_VOLTAGE(5, 7, XADC_REG_VCCO_DDR, "vccoddr", true),
> + XADC_7S_CHAN_VOLTAGE(6, 12, XADC_REG_VREFP, "vrefp", false),
> + XADC_7S_CHAN_VOLTAGE(7, 13, XADC_REG_VREFN, "vrefn", false),
> + XADC_7S_CHAN_VOLTAGE(8, 11, XADC_REG_VPVN, NULL, false),
> + XADC_7S_CHAN_VOLTAGE(9, 16, XADC_REG_VAUX(0), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(10, 17, XADC_REG_VAUX(1), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(11, 18, XADC_REG_VAUX(2), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(12, 19, XADC_REG_VAUX(3), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(13, 20, XADC_REG_VAUX(4), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(14, 21, XADC_REG_VAUX(5), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(15, 22, XADC_REG_VAUX(6), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(16, 23, XADC_REG_VAUX(7), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(17, 24, XADC_REG_VAUX(8), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(18, 25, XADC_REG_VAUX(9), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(19, 26, XADC_REG_VAUX(10), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(20, 27, XADC_REG_VAUX(11), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(21, 28, XADC_REG_VAUX(12), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(22, 29, XADC_REG_VAUX(13), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(23, 30, XADC_REG_VAUX(14), NULL, false),
> + XADC_7S_CHAN_VOLTAGE(24, 31, XADC_REG_VAUX(15), NULL, false),
> +};
> +
> +/* UltraScale */
> +#define XADC_US_CHAN_TEMP(_chan, _scan_index, _addr) \
> + XADC_CHAN_TEMP(_chan, _scan_index, _addr, 10)
> +#define XADC_US_CHAN_VOLTAGE(_chan, _scan_index, _addr, _ext, _alarm) \
> + XADC_CHAN_VOLTAGE(_chan, _scan_index, _addr, 10, _ext, _alarm)
> +
> +static const struct iio_chan_spec xadc_us_channels[] = {
> + XADC_US_CHAN_TEMP(0, 8, XADC_REG_TEMP),
> + XADC_US_CHAN_VOLTAGE(0, 9, XADC_REG_VCCINT, "vccint", true),
> + XADC_US_CHAN_VOLTAGE(1, 10, XADC_REG_VCCAUX, "vccaux", true),
> + XADC_US_CHAN_VOLTAGE(2, 14, XADC_REG_VCCBRAM, "vccbram", true),
> + XADC_US_CHAN_VOLTAGE(3, 5, XADC_REG_VCCPINT, "vccpsintlp", true),
> + XADC_US_CHAN_VOLTAGE(4, 6, XADC_REG_VCCPAUX, "vccpsintfp", true),
> + XADC_US_CHAN_VOLTAGE(5, 7, XADC_REG_VCCO_DDR, "vccpsaux", true),
> + XADC_US_CHAN_VOLTAGE(6, 12, XADC_REG_VREFP, "vrefp", false),
> + XADC_US_CHAN_VOLTAGE(7, 13, XADC_REG_VREFN, "vrefn", false),
> + XADC_US_CHAN_VOLTAGE(8, 11, XADC_REG_VPVN, NULL, false),
> + XADC_US_CHAN_VOLTAGE(9, 16, XADC_REG_VAUX(0), NULL, false),
> + XADC_US_CHAN_VOLTAGE(10, 17, XADC_REG_VAUX(1), NULL, false),
> + XADC_US_CHAN_VOLTAGE(11, 18, XADC_REG_VAUX(2), NULL, false),
> + XADC_US_CHAN_VOLTAGE(12, 19, XADC_REG_VAUX(3), NULL, false),
> + XADC_US_CHAN_VOLTAGE(13, 20, XADC_REG_VAUX(4), NULL, false),
> + XADC_US_CHAN_VOLTAGE(14, 21, XADC_REG_VAUX(5), NULL, false),
> + XADC_US_CHAN_VOLTAGE(15, 22, XADC_REG_VAUX(6), NULL, false),
> + XADC_US_CHAN_VOLTAGE(16, 23, XADC_REG_VAUX(7), NULL, false),
> + XADC_US_CHAN_VOLTAGE(17, 24, XADC_REG_VAUX(8), NULL, false),
> + XADC_US_CHAN_VOLTAGE(18, 25, XADC_REG_VAUX(9), NULL, false),
> + XADC_US_CHAN_VOLTAGE(19, 26, XADC_REG_VAUX(10), NULL, false),
> + XADC_US_CHAN_VOLTAGE(20, 27, XADC_REG_VAUX(11), NULL, false),
> + XADC_US_CHAN_VOLTAGE(21, 28, XADC_REG_VAUX(12), NULL, false),
> + XADC_US_CHAN_VOLTAGE(22, 29, XADC_REG_VAUX(13), NULL, false),
> + XADC_US_CHAN_VOLTAGE(23, 30, XADC_REG_VAUX(14), NULL, false),
> + XADC_US_CHAN_VOLTAGE(24, 31, XADC_REG_VAUX(15), NULL, false),
> };
>
> static const struct iio_info xadc_info = {
> @@ -1083,8 +1163,16 @@ static const struct iio_info xadc_info = {
> };
>
> static const struct of_device_id xadc_of_match_table[] = {
> - { .compatible = "xlnx,zynq-xadc-1.00.a", (void *)&xadc_zynq_ops },
> - { .compatible = "xlnx,axi-xadc-1.00.a", (void *)&xadc_axi_ops },
> + {
> + .compatible = "xlnx,zynq-xadc-1.00.a",
> + .data = &xadc_zynq_ops
> + }, {
> + .compatible = "xlnx,axi-xadc-1.00.a",
> + .data = &xadc_7s_axi_ops
> + }, {
> + .compatible = "xlnx,system-management-wiz-1.3",
> + .data = &xadc_us_axi_ops
> + },
> { },
> };
> MODULE_DEVICE_TABLE(of, xadc_of_match_table);
> @@ -1093,8 +1181,10 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
> unsigned int *conf)
> {
> struct xadc *xadc = iio_priv(indio_dev);
> + const struct iio_chan_spec *channel_templates;
> struct iio_chan_spec *channels, *chan;
> struct device_node *chan_node, *child;
> + unsigned int max_channels;
> unsigned int num_channels;
> const char *external_mux;
> u32 ext_mux_chan;
> @@ -1136,7 +1226,16 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
> *conf |= XADC_CONF0_MUX | XADC_CONF0_CHAN(ext_mux_chan);
> }
>
> - channels = kmemdup(xadc_channels, sizeof(xadc_channels), GFP_KERNEL);
> + if (xadc->ops->type == XADC_TYPE_S7) {
> + channel_templates = xadc_7s_channels;
> + max_channels = ARRAY_SIZE(xadc_7s_channels);
> + } else {
> + channel_templates = xadc_us_channels;
> + max_channels = ARRAY_SIZE(xadc_us_channels);
> + }
> + channels = kmemdup(channel_templates,
> + sizeof(channels[0]) * max_channels, GFP_KERNEL);
> +
> if (!channels)
> return -ENOMEM;
>
> @@ -1146,7 +1245,7 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
> chan_node = of_get_child_by_name(np, "xlnx,channels");
> if (chan_node) {
> for_each_child_of_node(chan_node, child) {
> - if (num_channels >= ARRAY_SIZE(xadc_channels)) {
> + if (num_channels >= max_channels) {
> of_node_put(child);
> break;
> }
> @@ -1181,6 +1280,11 @@ static int xadc_parse_dt(struct iio_dev *indio_dev, struct device_node *np,
> return 0;
> }
>
> +static const char * const xadc_type_names[] = {
> + [XADC_TYPE_S7] = "xadc",
> + [XADC_TYPE_US] = "xilinx-system-monitor",
> +};
> +
> static int xadc_probe(struct platform_device *pdev)
> {
> const struct of_device_id *id;
> @@ -1219,7 +1323,7 @@ static int xadc_probe(struct platform_device *pdev)
> if (IS_ERR(xadc->base))
> return PTR_ERR(xadc->base);
>
> - indio_dev->name = "xadc";
> + indio_dev->name = xadc_type_names[xadc->ops->type];
> indio_dev->modes = INDIO_DIRECT_MODE;
> indio_dev->info = &xadc_info;
>
> diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c
> index 2357f585720a..1bd375fb10e0 100644
> --- a/drivers/iio/adc/xilinx-xadc-events.c
> +++ b/drivers/iio/adc/xilinx-xadc-events.c
> @@ -155,9 +155,6 @@ int xadc_write_event_config(struct iio_dev *indio_dev,
> return ret;
> }
>
> -/* Register value is msb aligned, the lower 4 bits are ignored */
> -#define XADC_THRESHOLD_VALUE_SHIFT 4
> -
> int xadc_read_event_value(struct iio_dev *indio_dev,
> const struct iio_chan_spec *chan, enum iio_event_type type,
> enum iio_event_direction dir, enum iio_event_info info,
> @@ -177,7 +174,8 @@ int xadc_read_event_value(struct iio_dev *indio_dev,
> return -EINVAL;
> }
>
> - *val >>= XADC_THRESHOLD_VALUE_SHIFT;
> + /* MSB aligned */
> + *val >>= 16 - chan->scan_type.realbits;
>
> return IIO_VAL_INT;
> }
> @@ -191,7 +189,8 @@ int xadc_write_event_value(struct iio_dev *indio_dev,
> struct xadc *xadc = iio_priv(indio_dev);
> int ret = 0;
>
> - val <<= XADC_THRESHOLD_VALUE_SHIFT;
> + /* MSB aligned */
> + val <<= 16 - chan->scan_type.realbits;
>
> if (val < 0 || val > 0xffff)
> return -EINVAL;
> diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h
> index 25abed9c0285..8b80195725e9 100644
> --- a/drivers/iio/adc/xilinx-xadc.h
> +++ b/drivers/iio/adc/xilinx-xadc.h
> @@ -70,6 +70,11 @@ struct xadc {
> int irq;
> };
>
> +enum xadc_type {
> + XADC_TYPE_S7, /* Series 7 */
> + XADC_TYPE_US, /* UltraScale and UltraScale+ */
> +};
> +
> struct xadc_ops {
> int (*read)(struct xadc *xadc, unsigned int reg, uint16_t *val);
> int (*write)(struct xadc *xadc, unsigned int reg, uint16_t val);
> @@ -80,6 +85,7 @@ struct xadc_ops {
> irqreturn_t (*interrupt_handler)(int irq, void *devid);
>
> unsigned int flags;
> + enum xadc_type type;
> };
>
> static inline int _xadc_read_adc_reg(struct xadc *xadc, unsigned int reg,
next prev parent reply other threads:[~2020-09-23 20:47 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-09-22 13:46 [PATCH 1/2] devicetree: Add Xilinx System Management Wizard binding documentation Lars-Peter Clausen
2020-09-22 13:46 ` [PATCH 2/2] iio: xilinx-xadc: Add basic support for Ultrascale System Monitor Lars-Peter Clausen
2020-09-23 20:47 ` Jonathan Cameron [this message]
2020-09-24 6:08 ` Michal Simek
2020-11-29 13:14 ` Jonathan Cameron
2020-11-30 8:47 ` Anand Ashok Dumbre
2020-12-11 9:57 ` Anand Ashok Dumbre
2020-12-13 11:57 ` Jonathan Cameron
2020-12-15 15:49 ` Lars-Peter Clausen
2020-12-15 18:28 ` Jonathan Cameron
2020-12-16 11:50 ` Lars-Peter Clausen
2020-12-13 12:03 ` [PATCH 1/2] devicetree: Add Xilinx System Management Wizard binding documentation Jonathan Cameron
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200923214728.6e0c07b0@archlinux \
--to=jic23@kernel.org \
--cc=lars@metafoo.de \
--cc=linux-iio@vger.kernel.org \
--cc=michal.simek@xilinx.com \
--cc=pmeerw@pmeerw.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.