#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)
        .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,
 {
        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;
 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;
 }
        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,
        .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,
 {
        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:
 {
        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;
 
        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;
 
                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:
                                *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);
        },
 };
 
-#define XADC_CHAN_TEMP(_chan, _scan_index, _addr) { \
+#define XADC_CHAN_TEMP(_chan, _scan_index, _addr, _bits) { \
        .type = IIO_TEMP, \
        .indexed = 1, \
        .channel = (_chan), \
        .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), \
        .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 = {
 };
 
 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);
 {
        struct device *dev = indio_dev->dev.parent;
        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;
 
                *conf |= XADC_CONF0_MUX | XADC_CONF0_CHAN(ext_mux_chan);
        }
-
-       channels = devm_kmemdup(dev, 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 = devm_kmemdup(dev, channel_templates,
+                               sizeof(channels[0]) * max_channels, GFP_KERNEL);
        if (!channels)
                return -ENOMEM;
 
        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;
                        }
        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;
        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;