From f399f54493bed69b8fddf23555c1e4d7c392b246 Mon Sep 17 00:00:00 2001 From: Paul Pop Date: Wed, 22 Apr 2026 14:30:12 +0300 Subject: [PATCH 1/9] dt-bindings: iio: adc: add adi,hmcad15xx Add device tree binding documentation for Analog Devices HMCAD1511 and HMCAD1520 high-speed ADCs with LVDS outputs. Signed-off-by: Paul Pop --- .../bindings/iio/adc/adi,hmcad15xx.yaml | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml diff --git a/Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml b/Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml new file mode 100644 index 00000000000000..76b06ea7cb191d --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml @@ -0,0 +1,112 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +# Copyright 2025 Analog Devices Inc. +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/iio/adc/adi,hmcad15xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices HMCAD15xx High-Speed ADC + +maintainers: + - Paul Pop + +description: | + The HMCAD1511 and HMCAD1520 are high-speed analog-to-digital converters + with LVDS outputs. The HMCAD1511 is a 12-bit ADC supporting up to 1 GSPS + in single-channel mode. The HMCAD1520 is a 14-bit ADC supporting up to + 105 MSPS in quad-channel precision mode. + + Both devices support flexible channel configurations: + - Single channel: highest sample rate + - Dual channel: half sample rate per channel + - Quad channel: quarter sample rate per channel + + The driver supports 8-bit, 12-bit, and 14-bit resolution modes with + appropriate LVDS output configurations. + + https://www.ti.com/product/HMCAD1511 + https://www.ti.com/product/HMCAD1520 + +properties: + compatible: + const: adi,hmcad15xx + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + description: + ADC input clock. Maximum frequency depends on resolution and channel + configuration. + + clock-names: + const: clk + + reset-gpios: + maxItems: 1 + description: + Active low GPIO for hardware reset. + + pd-gpios: + maxItems: 1 + description: + Active high GPIO for power down control. + + adi,num-channels: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 4] + default: 1 + description: + Number of ADC channels to enable. Affects sample rate per channel. + + adi,resolution: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [8, 12, 14] + default: 8 + description: | + ADC resolution in bits. + 8-bit: High-speed mode, up to 1000/500/250 MSPS for 1/2/4 channels + 12-bit: Mid-speed mode, up to 660/330/165 MSPS for 1/2/4 channels + 14-bit: Precision mode, dual 8-bit LVDS, up to 105 MSPS + + adi,pol-mask: + $ref: /schemas/types.yaml#/definitions/uint32 + default: 0 + description: + 8-bit polarity mask for LVDS data lanes. Each bit controls the + polarity inversion of one LVDS lane. Used to compensate for PCB + routing constraints. + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +required: + - compatible + - reg + - clocks + - clock-names + +unevaluatedProperties: false + +examples: + - | + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + adc@0 { + compatible = "adi,hmcad15xx"; + reg = <0>; + clocks = <&adc_clk>; + clock-names = "clk"; + reset-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>; + pd-gpios = <&gpio0 86 GPIO_ACTIVE_HIGH>; + adi,num-channels = <1>; + adi,resolution = <12>; + adi,pol-mask = <239>; + }; + }; +... From 6b8b59771299e0f7378ca70e0a34b7e014f4991a Mon Sep 17 00:00:00 2001 From: Paul Pop Date: Wed, 22 Apr 2026 14:47:04 +0300 Subject: [PATCH 2/9] iio: adc: cf_axi_adc: add ADC config register definitions Add ADI_REG_ADC_CONFIG_WR and ADI_REG_ADC_CONFIG_RD register definitions for custom ADC configuration in the AXI ADC core. Signed-off-by: Paul Pop --- drivers/iio/adc/cf_axi_adc.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/iio/adc/cf_axi_adc.h b/drivers/iio/adc/cf_axi_adc.h index ac602549b47054..4b73c43e5db419 100644 --- a/drivers/iio/adc/cf_axi_adc.h +++ b/drivers/iio/adc/cf_axi_adc.h @@ -91,6 +91,9 @@ #define ADI_DRP_RDATA(x) (((x) & 0xFFFF) << 0) #define ADI_TO_DRP_RDATA(x) (((x) >> 0) & 0xFFFF) +#define ADI_REG_ADC_CONFIG_WR 0x0080 +#define ADI_REG_ADC_CONFIG_RD 0x0084 + #define ADI_REG_DMA_STATUS 0x0088 #define ADI_DMA_OVF (1 << 2) #define ADI_DMA_UNF (1 << 1) From a291d2b83afc3589ca234a553f4ff3c9f4c8f338 Mon Sep 17 00:00:00 2001 From: Paul Pop Date: Wed, 22 Apr 2026 14:32:15 +0300 Subject: [PATCH 3/9] iio: adc: add support for HMCAD15xx high-speed ADC Add support for Analog Devices HMCAD1511 and HMCAD1520 high-speed ADCs with LVDS outputs. Features: - Flexible 1/2/4 channel configurations - 8-bit, 12-bit, and 14-bit resolution modes - Input multiplexer control per channel - Integration with ADI AXI ADC core Signed-off-by: Paul Pop --- MAINTAINERS | 8 + drivers/iio/Kconfig.adi | 1 + drivers/iio/adc/Kconfig | 15 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/hmcad15xx.c | 674 ++++++++++++++++++++++++++++++++++++ 5 files changed, 699 insertions(+) create mode 100644 drivers/iio/adc/hmcad15xx.c diff --git a/MAINTAINERS b/MAINTAINERS index 8c75d385358a86..044c45a2c00c53 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10549,6 +10549,14 @@ F: lib/test_hmm* F: mm/hmm* F: tools/testing/selftests/mm/*hmm* +HMCAD15XX IIO ADC DRIVER +M: Paul Pop +L: linux-iio@vger.kernel.org +S: Supported +W: https://ez.analog.com/linux-software-drivers +F: Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml +F: drivers/iio/adc/hmcad15xx.c + HONEYWELL HSC030PA PRESSURE SENSOR SERIES IIO DRIVER M: Petre Rodan L: linux-iio@vger.kernel.org diff --git a/drivers/iio/Kconfig.adi b/drivers/iio/Kconfig.adi index 31f0699d84ea84..80e0bd44e52139 100644 --- a/drivers/iio/Kconfig.adi +++ b/drivers/iio/Kconfig.adi @@ -94,6 +94,7 @@ config IIO_ALL_ADI_DRIVERS imply AD8366 imply ADA4250 imply HMC425 + imply HMCAD15XX imply AD5270 imply AD5360 imply AD5380 diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index cae86f7837e06a..3328e4be0c1d58 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -902,6 +902,21 @@ config FSL_MX25_ADC Generic Conversion Queue driver used for general purpose ADC in the MX25. This driver supports single measurements using the MX25 ADC. +config HMCAD15XX + tristate "Analog Devices HMCAD15XX ADC" + depends on SPI + select CF_AXI_ADC + help + Say yes here to build support for Analog Devices HMCAD1511 and + HMCAD1520 high-speed analog-to-digital converters with LVDS outputs. + The HMCAD1511 is a 12-bit ADC supporting up to 1 GSPS in single-channel + mode. The HMCAD1520 is a 14-bit ADC supporting up to 105 MSPS in + quad-channel precision mode. Both devices support flexible 1/2/4 + channel configurations with 8-bit, 12-bit, or 14-bit resolution modes. + + To compile this driver as a module, choose M here: the module will + be called hmcad15xx. + config HI8435 tristate "Holt Integrated Circuits HI-8435 threshold detector" select IIO_TRIGGERED_EVENT diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index e53747da674127..2e02d721b01f1b 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -141,6 +141,7 @@ obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o +obj-$(CONFIG_HMCAD15XX) += hmcad15xx.o obj-$(CONFIG_HI8435) += hi8435.o obj-$(CONFIG_HX711) += hx711.o obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o diff --git a/drivers/iio/adc/hmcad15xx.c b/drivers/iio/adc/hmcad15xx.c new file mode 100644 index 00000000000000..ecc76d83506717 --- /dev/null +++ b/drivers/iio/adc/hmcad15xx.c @@ -0,0 +1,674 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * HMCAD15XX Analog to digital converters driver + * + * Copyright 2025 Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cf_axi_adc.h" + +/* HMCAD15XX register addresses */ +#define HMCAD15XX_REG_RST 0x00 +#define HMCAD15XX_REG_PD 0x0F +#define HMCAD15XX_REG_OPERATION_MODE 0x31 +#define HMCAD15XX_REG_INP_SEL_ADC1_ADC2 0x3A +#define HMCAD15XX_REG_INP_SEL_ADC3_ADC4 0x3B +#define HMCAD15XX_REG_PHASE_DDR 0x42 +#define HMCAD15XX_REG_BTC_MODE 0x46 +#define HMCAD15XX_REG_LVDS_OUTPUT_MODE 0x53 + +/* HMCAD15XX_REG_RST (0x00) */ +#define HMCAD15XX_RST_SW_RESET 0x0001 + +/* HMCAD15XX_REG_PD (0x0F) */ +#define HMCAD15XX_PD_MSK BIT(9) +#define HMCAD15XX_PD_POWER_DOWN BIT(9) +#define HMCAD15XX_PD_POWER_UP 0 + +/* HMCAD15XX_REG_PHASE_DDR (0x42) */ +#define HMCAD15XX_PHASE_DDR_MSK GENMASK(15, 0) + +/* HMCAD15XX_REG_LVDS_OUTPUT_MODE (0x53) */ +#define HMCAD15XX_LVDS_OUTPUT_MODE_MSK GENMASK(2, 0) +#define HMCAD15XX_LVDS_OUTPUT_8BIT 0x0 +#define HMCAD15XX_LVDS_OUTPUT_12BIT 0x1 +#define HMCAD15XX_LVDS_OUTPUT_DUAL_8BIT 0x4 + +/* HMCAD15XX_REG_OPERATION_MODE (0x31) - combined high_speed + clk_divide */ +#define HMCAD15XX_OP_MODE_MSK (GENMASK(9, 8) | GENMASK(2, 0)) +#define HMCAD15XX_OP_MODE_SINGLE_CH 0x0001 +#define HMCAD15XX_OP_MODE_DUAL_CH 0x0102 +#define HMCAD15XX_OP_MODE_QUAD_CH 0x0204 + +/* HMCAD15XX_REG_INP_SEL */ +#define HMCAD15XX_INP_SEL_ADC1_MSK GENMASK(4, 1) +#define HMCAD15XX_INP_SEL_ADC2_MSK GENMASK(12, 9) + +#define HMCAD15XX_ADC_1_3_GET_SEL(x) (__builtin_ctz(((x) & HMCAD15XX_INP_SEL_ADC1_MSK) >> 1)) +#define HMCAD15XX_ADC_2_4_GET_SEL(x) (__builtin_ctz(((x) & HMCAD15XX_INP_SEL_ADC2_MSK) >> 9)) + +#define HMCAD15XX_INP_1_3_SEL(x) (((1 << (x)) & 0xf) << 1) +#define HMCAD15XX_INP_2_4_SEL(x) (((1 << (x)) & 0xf) << 9) + +/* HMCAD15XX_REG_BTC_MODE (0x46) */ +#define HMCAD15XX_BTC_MODE_MSK BIT(2) +#define HMCAD15XX_BTC_MODE_TWOS_COMPLEMENT BIT(2) +#define HMCAD15XX_BTC_MODE_OFFSET_BINARY 0 + +/* Output mode for AXI ADC converter */ +#define HMCAD15XX_OUTPUT_MODE_OFFSET_BINARY 0x00 + +enum hmcad15xx_clk_div { + CLK_DIV_1 = 0, + CLK_DIV_2 = 1, + CLK_DIV_4 = 2, +}; + +enum hmcad15xx_input_select { + IP1_IN1, + IP2_IN2, + IP3_IN3, + IP4_IN4 +}; + +enum hmcad15xx_resolution { + RES_8BIT = 0, + RES_12BIT = 2, + RES_14BIT = 1 +}; + +static const int hmcad15xx_clk_div_value[] = { + [CLK_DIV_1] = 1, + [CLK_DIV_2] = 2, + [CLK_DIV_4] = 4, +}; + +struct hmcad15xx_state { + struct spi_device *spi; + struct clk *clk; + /* Protects against concurrent register access */ + struct mutex lock; + struct gpio_desc *gpio_reset; + struct gpio_desc *gpio_pd; + unsigned long regs_hw[86]; + enum hmcad15xx_clk_div clk_div; + unsigned int en_channels; + unsigned int pol_mask; + enum hmcad15xx_resolution resolution; + const struct axiadc_chip_info *chip_info; + __be32 d32; +}; + +static bool hmcad15xx_has_axi_adc(struct device *dev) +{ + return device_property_present(dev, "spibus-connected"); +} + +static struct hmcad15xx_state *hmcad15xx_get_data(struct iio_dev *indio_dev) +{ + struct axiadc_converter *conv; + + if (hmcad15xx_has_axi_adc(&indio_dev->dev)) { + conv = iio_device_get_drvdata(indio_dev); + return conv->phy; + } else { + return iio_priv(indio_dev); + } +} + +static int hmcad15xx_spi_reg_read(struct hmcad15xx_state *st, unsigned int addr, + unsigned int *val) +{ + *val = st->regs_hw[addr]; + return 0; +} + +static int hmcad15xx_spi_reg_write(struct hmcad15xx_state *st, + unsigned int addr, unsigned int val) +{ + st->d32 = cpu_to_be32(((addr & 0xFF) << 24) | ((val & 0xFFFF) << 8)); + st->regs_hw[addr] = val; + return spi_write(st->spi, &st->d32, sizeof(st->d32)); +} + +static int hmcad15xx_spi_write_mask(struct hmcad15xx_state *st, + unsigned int addr, unsigned long mask, + unsigned int val) +{ + unsigned int regval; + int ret; + + ret = hmcad15xx_spi_reg_read(st, addr, ®val); + if (ret < 0) + return ret; + + regval &= ~mask; + regval |= val; + + return hmcad15xx_spi_reg_write(st, addr, regval); +} + +static int hmcad15xx_reg_access(struct iio_dev *indio_dev, unsigned int reg, + unsigned int writeval, unsigned int *readval) +{ + struct hmcad15xx_state *st = hmcad15xx_get_data(indio_dev); + int ret; + + mutex_lock(&st->lock); + if (readval) { + ret = hmcad15xx_spi_reg_read(st, reg, readval); + if (ret < 0) + goto exit; + ret = 0; + } else { + ret = hmcad15xx_spi_reg_write(st, reg, writeval); + } +exit: + mutex_unlock(&st->lock); + return ret; +} + +static int hmcad15xx_set_input_select(struct iio_dev *dev, + const struct iio_chan_spec *chan, + unsigned int mode) +{ + struct hmcad15xx_state *st = hmcad15xx_get_data(dev); + + switch (chan->channel) { + case 0: + return hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_INP_SEL_ADC1_ADC2, + HMCAD15XX_INP_SEL_ADC1_MSK, + HMCAD15XX_INP_1_3_SEL(mode)); + case 1: + return hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_INP_SEL_ADC1_ADC2, + HMCAD15XX_INP_SEL_ADC2_MSK, + HMCAD15XX_INP_2_4_SEL(mode)); + case 2: + return hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_INP_SEL_ADC3_ADC4, + HMCAD15XX_INP_SEL_ADC1_MSK, + HMCAD15XX_INP_1_3_SEL(mode)); + case 3: + return hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_INP_SEL_ADC3_ADC4, + HMCAD15XX_INP_SEL_ADC2_MSK, + HMCAD15XX_INP_2_4_SEL(mode)); + default: + return -EINVAL; + } +} + +static int hmcad15xx_get_input_select(struct iio_dev *dev, + const struct iio_chan_spec *chan) +{ + struct hmcad15xx_state *st = hmcad15xx_get_data(dev); + unsigned int regval; + int ret; + + switch (chan->channel) { + case 0: + ret = hmcad15xx_spi_reg_read(st, HMCAD15XX_REG_INP_SEL_ADC1_ADC2, ®val); + if (ret < 0) + return ret; + return HMCAD15XX_ADC_1_3_GET_SEL(regval); + case 1: + ret = hmcad15xx_spi_reg_read(st, HMCAD15XX_REG_INP_SEL_ADC1_ADC2, ®val); + if (ret < 0) + return ret; + return HMCAD15XX_ADC_2_4_GET_SEL(regval); + case 2: + ret = hmcad15xx_spi_reg_read(st, HMCAD15XX_REG_INP_SEL_ADC3_ADC4, ®val); + if (ret < 0) + return ret; + return HMCAD15XX_ADC_1_3_GET_SEL(regval); + case 3: + ret = hmcad15xx_spi_reg_read(st, HMCAD15XX_REG_INP_SEL_ADC3_ADC4, ®val); + if (ret < 0) + return ret; + return HMCAD15XX_ADC_2_4_GET_SEL(regval); + default: + return -EINVAL; + } +} + +static const char * const hmcad15xx_input_select_iio_enum[] = { + [IP1_IN1] = "IP1_IN1", + [IP2_IN2] = "IP2_IN2", + [IP3_IN3] = "IP3_IN3", + [IP4_IN4] = "IP4_IN4" +}; + +static const struct iio_enum hmcad15xx_input_select_enum = { + .items = hmcad15xx_input_select_iio_enum, + .num_items = ARRAY_SIZE(hmcad15xx_input_select_iio_enum), + .set = hmcad15xx_set_input_select, + .get = hmcad15xx_get_input_select, +}; + +static ssize_t hmcad15xx_scale(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct iio_dev *indio_dev = dev_to_iio_dev(dev); + const struct iio_chan_spec *chan = &indio_dev->channels[0]; + u64 scale; + + scale = div64_ul(1000000, BIT(chan->scan_type.realbits)); + return scnprintf(buf, PAGE_SIZE, "0.%012llu\n", scale); +} + +static IIO_DEVICE_ATTR(in_voltage_scale, 0444, hmcad15xx_scale, NULL, 0); + +static unsigned int hmcad15xx_get_sampling_freq(struct hmcad15xx_state *st) +{ + unsigned long clk_rate = clk_get_rate(st->clk); + unsigned int clk_div = hmcad15xx_clk_div_value[st->clk_div]; + unsigned int valid_div; + + if (st->resolution == RES_14BIT) + valid_div = 2; + else + valid_div = 1; + + return DIV_ROUND_CLOSEST(clk_rate, clk_div * valid_div); +} + +static int hmcad15xx_read_raw(struct iio_dev *indio_dev, + const struct iio_chan_spec *chan, + int *val, int *val2, long info) +{ + struct hmcad15xx_state *st = hmcad15xx_get_data(indio_dev); + + switch (info) { + case IIO_CHAN_INFO_SAMP_FREQ: + *val = hmcad15xx_get_sampling_freq(st); + return IIO_VAL_INT; + default: + return -EINVAL; + } +} + +static int hmcad15xx_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + switch (mask) { + case IIO_CHAN_INFO_SAMP_FREQ: + return -EINVAL; + default: + return -EINVAL; + } +} + +static struct iio_chan_spec_ext_info hmcad15xx_ext_info[] = { + IIO_ENUM("input_select", IIO_SEPARATE, &hmcad15xx_input_select_enum), + IIO_ENUM_AVAILABLE("input_select", IIO_SHARED_BY_TYPE, + &hmcad15xx_input_select_enum), + { }, +}; + +static struct attribute *hmcad15xx_attributes[] = { + &iio_dev_attr_in_voltage_scale.dev_attr.attr, + NULL +}; + +static const struct attribute_group hmcad15xx_group = { + .attrs = hmcad15xx_attributes, +}; + +static const struct iio_info hmcad15xx_info = { + .attrs = &hmcad15xx_group, + .read_raw = &hmcad15xx_read_raw, + .write_raw = &hmcad15xx_write_raw, + .debugfs_reg_access = &hmcad15xx_reg_access, +}; + +#define HMCAD15XX_CHAN(_idx, _realbits, _storagebits, _shift) \ + { \ + .type = IIO_VOLTAGE, \ + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \ + .address = _idx, \ + .indexed = 1, \ + .channel = _idx, \ + .scan_index = _idx, \ + .ext_info = hmcad15xx_ext_info, \ + .scan_type = { \ + .sign = 's', \ + .realbits = _realbits, \ + .storagebits = _storagebits, \ + .shift = _shift, \ + }, \ + } + +static const struct axiadc_chip_info hmcad15xx_chip_info_8bit = { + .id = 0, + .name = "hmcad15xx_axi_adc", + .num_channels = 4, + .channel[0] = HMCAD15XX_CHAN(0, 8, 8, 0), + .channel[1] = HMCAD15XX_CHAN(1, 8, 8, 0), + .channel[2] = HMCAD15XX_CHAN(2, 8, 8, 0), + .channel[3] = HMCAD15XX_CHAN(3, 8, 8, 0), +}; + +static const struct axiadc_chip_info hmcad15xx_chip_info_12bit = { + .id = 0, + .name = "hmcad15xx_axi_adc", + .num_channels = 4, + .channel[0] = HMCAD15XX_CHAN(0, 12, 16, 4), + .channel[1] = HMCAD15XX_CHAN(1, 12, 16, 4), + .channel[2] = HMCAD15XX_CHAN(2, 12, 16, 4), + .channel[3] = HMCAD15XX_CHAN(3, 12, 16, 4), +}; + +static const struct axiadc_chip_info hmcad15xx_chip_info_14bit = { + .id = 0, + .name = "hmcad15xx_axi_adc", + .num_channels = 4, + .channel[0] = HMCAD15XX_CHAN(0, 14, 16, 2), + .channel[1] = HMCAD15XX_CHAN(1, 14, 16, 2), + .channel[2] = HMCAD15XX_CHAN(2, 14, 16, 2), + .channel[3] = HMCAD15XX_CHAN(3, 14, 16, 2), +}; + +static const struct axiadc_chip_info * +hmcad15xx_get_chip_info(enum hmcad15xx_resolution resolution) +{ + switch (resolution) { + case RES_14BIT: + return &hmcad15xx_chip_info_14bit; + case RES_12BIT: + return &hmcad15xx_chip_info_12bit; + case RES_8BIT: + default: + return &hmcad15xx_chip_info_8bit; + } +} + +/* HDL ADI_REG_CNTRL_3 bit fields for HMCAD15xx */ +#define HMCAD15XX_HDL_MODE_MSK GENMASK(4, 2) +#define HMCAD15XX_HDL_MODE(x) (((x) & 0x7) << 2) +#define HMCAD15XX_HDL_RES_MSK GENMASK(1, 0) + +/* HDL ADI_REG_ADC_CONFIG_WR bit fields */ +#define HMCAD15XX_HDL_POL_MSK GENMASK(7, 0) + +static int hmcad15xx_post_setup(struct iio_dev *indio_dev) +{ + struct axiadc_state *axiadc_st = iio_priv(indio_dev); + struct axiadc_converter *conv = iio_device_get_drvdata(indio_dev); + struct hmcad15xx_state *st = conv->phy; + unsigned int hdl_mode; + unsigned int reg; + + switch (st->en_channels) { + case 4: + hdl_mode = 4; + break; + case 2: + hdl_mode = 2; + break; + case 1: + default: + hdl_mode = 1; + break; + } + + reg = axiadc_read(axiadc_st, ADI_REG_CNTRL_3); + reg &= ~(HMCAD15XX_HDL_MODE_MSK | HMCAD15XX_HDL_RES_MSK); + reg |= HMCAD15XX_HDL_MODE(hdl_mode) | st->resolution; + axiadc_write(axiadc_st, ADI_REG_CNTRL_3, reg); + + reg = axiadc_read(axiadc_st, ADI_REG_ADC_CONFIG_WR); + reg &= ~HMCAD15XX_HDL_POL_MSK; + reg |= st->pol_mask & HMCAD15XX_HDL_POL_MSK; + axiadc_write(axiadc_st, ADI_REG_ADC_CONFIG_WR, reg); + + return 0; +} + +static int hmcad15xx_register_axi_adc(struct hmcad15xx_state *st) +{ + struct axiadc_converter *conv; + + conv = devm_kzalloc(&st->spi->dev, sizeof(*conv), GFP_KERNEL); + if (!conv) + return -ENOMEM; + + conv->spi = st->spi; + conv->chip_info = st->chip_info; + conv->adc_output_mode = HMCAD15XX_OUTPUT_MODE_OFFSET_BINARY; + conv->reg_access = &hmcad15xx_reg_access; + conv->write_raw = &hmcad15xx_write_raw; + conv->read_raw = &hmcad15xx_read_raw; + conv->post_setup = &hmcad15xx_post_setup; + conv->attrs = &hmcad15xx_group; + conv->phy = st; + spi_set_drvdata(st->spi, conv); + + return 0; +} + +static int hmcad15xx_probe(struct spi_device *spi) +{ + struct hmcad15xx_state *st; + struct iio_dev *indio_dev; + unsigned int resolution_bits; + unsigned int regval; + int ret; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + memset(st->regs_hw, 0x00, sizeof(st->regs_hw)); + + st->clk = devm_clk_get_enabled(&spi->dev, "clk"); + if (IS_ERR(st->clk)) + return PTR_ERR(st->clk); + + st->spi = spi; + + st->en_channels = 1; + ret = device_property_read_u32(&spi->dev, "adi,num-channels", + &st->en_channels); + if (ret < 0 && ret != -EINVAL) + return ret; + + resolution_bits = 8; + ret = device_property_read_u32(&spi->dev, "adi,resolution", + &resolution_bits); + if (ret < 0 && ret != -EINVAL) + return ret; + + switch (resolution_bits) { + case 8: + st->resolution = RES_8BIT; + break; + case 12: + st->resolution = RES_12BIT; + break; + case 14: + st->resolution = RES_14BIT; + break; + default: + dev_err(&spi->dev, "Invalid resolution %u (must be 8, 12, or 14)\n", + resolution_bits); + return -EINVAL; + } + + st->chip_info = hmcad15xx_get_chip_info(st->resolution); + + ret = device_property_read_u32(&spi->dev, "adi,pol-mask", &st->pol_mask); + if (ret < 0 && ret != -EINVAL) + return ret; + + st->gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(st->gpio_reset)) + return PTR_ERR(st->gpio_reset); + + st->gpio_pd = devm_gpiod_get_optional(&spi->dev, "pd", GPIOD_OUT_HIGH); + if (IS_ERR(st->gpio_pd)) + return PTR_ERR(st->gpio_pd); + + if (st->gpio_reset) { + gpiod_set_value_cansleep(st->gpio_reset, 1); + fsleep(100); + gpiod_set_value_cansleep(st->gpio_reset, 0); + fsleep(100); + } else { + ret = hmcad15xx_spi_reg_write(st, HMCAD15XX_REG_RST, + HMCAD15XX_RST_SW_RESET); + if (ret < 0) + return ret; + fsleep(100); + } + + if (st->gpio_pd) { + gpiod_set_value_cansleep(st->gpio_pd, 1); + fsleep(1660); + } else { + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_PD, + HMCAD15XX_PD_MSK, + HMCAD15XX_PD_POWER_DOWN); + if (ret < 0) + return ret; + fsleep(100); + } + + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_PHASE_DDR, + HMCAD15XX_PHASE_DDR_MSK, 0x00); + if (ret < 0) + return ret; + + switch (st->resolution) { + case RES_14BIT: + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_LVDS_OUTPUT_MODE, + HMCAD15XX_LVDS_OUTPUT_MODE_MSK, + HMCAD15XX_LVDS_OUTPUT_DUAL_8BIT); + break; + case RES_12BIT: + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_LVDS_OUTPUT_MODE, + HMCAD15XX_LVDS_OUTPUT_MODE_MSK, + HMCAD15XX_LVDS_OUTPUT_12BIT); + break; + case RES_8BIT: + default: + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_LVDS_OUTPUT_MODE, + HMCAD15XX_LVDS_OUTPUT_MODE_MSK, + HMCAD15XX_LVDS_OUTPUT_8BIT); + break; + } + if (ret < 0) + return ret; + + switch (st->en_channels) { + case 1: + regval = HMCAD15XX_OP_MODE_SINGLE_CH; + st->clk_div = CLK_DIV_1; + break; + case 2: + regval = HMCAD15XX_OP_MODE_DUAL_CH; + st->clk_div = CLK_DIV_2; + break; + case 4: + default: + regval = HMCAD15XX_OP_MODE_QUAD_CH; + st->clk_div = CLK_DIV_4; + break; + } + + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_OPERATION_MODE, + HMCAD15XX_OP_MODE_MSK, regval); + if (ret < 0) + return ret; + + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_INP_SEL_ADC1_ADC2, + HMCAD15XX_INP_SEL_ADC1_MSK, + HMCAD15XX_INP_1_3_SEL(IP4_IN4)); + if (ret < 0) + return ret; + + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_INP_SEL_ADC1_ADC2, + HMCAD15XX_INP_SEL_ADC2_MSK, + HMCAD15XX_INP_2_4_SEL(IP4_IN4)); + if (ret < 0) + return ret; + + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_INP_SEL_ADC3_ADC4, + HMCAD15XX_INP_SEL_ADC1_MSK, + HMCAD15XX_INP_1_3_SEL(IP4_IN4)); + if (ret < 0) + return ret; + + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_INP_SEL_ADC3_ADC4, + HMCAD15XX_INP_SEL_ADC2_MSK, + HMCAD15XX_INP_2_4_SEL(IP4_IN4)); + if (ret < 0) + return ret; + + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_BTC_MODE, + HMCAD15XX_BTC_MODE_MSK, + HMCAD15XX_BTC_MODE_TWOS_COMPLEMENT); + if (ret < 0) + return ret; + + if (st->gpio_pd) { + gpiod_set_value_cansleep(st->gpio_pd, 0); + fsleep(2000); + } else { + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_PD, + HMCAD15XX_PD_MSK, + HMCAD15XX_PD_POWER_UP); + if (ret < 0) + return ret; + fsleep(2000); + } + + mutex_init(&st->lock); + + return hmcad15xx_register_axi_adc(st); +} + +static const struct spi_device_id hmcad15xx_id[] = { + { "hmcad15xx", 0 }, + { } +}; +MODULE_DEVICE_TABLE(spi, hmcad15xx_id); + +static const struct of_device_id hmcad15xx_of_match[] = { + { .compatible = "adi,hmcad15xx" }, + { } +}; +MODULE_DEVICE_TABLE(of, hmcad15xx_of_match); + +static struct spi_driver hmcad15xx_driver = { + .driver = { + .name = "hmcad15xx", + .of_match_table = hmcad15xx_of_match, + }, + .probe = hmcad15xx_probe, + .id_table = hmcad15xx_id, +}; +module_spi_driver(hmcad15xx_driver); + +MODULE_AUTHOR("Paul Pop "); +MODULE_DESCRIPTION("Analog Devices HMCAD15XX ADC"); +MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER); From 0fb61f6f5f874f057242ac806bfc256860a8b87e Mon Sep 17 00:00:00 2001 From: Paul Pop Date: Wed, 22 Apr 2026 14:47:57 +0300 Subject: [PATCH 4/9] iio: frequency: adf5355: set CLK_GET_RATE_NOCACHE for clock output The ADF5355 is a programmable PLL whose output frequency can change at runtime. Set CLK_GET_RATE_NOCACHE to ensure the clock framework queries the actual rate instead of returning a cached value. Signed-off-by: Paul Pop --- drivers/iio/frequency/adf5355.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iio/frequency/adf5355.c b/drivers/iio/frequency/adf5355.c index becae556e884f7..cfaddba0b211b4 100644 --- a/drivers/iio/frequency/adf5355.c +++ b/drivers/iio/frequency/adf5355.c @@ -995,7 +995,7 @@ static int adf5355_probe(struct spi_device *spi) init.name = clk_name; init.ops = &clkout_ops; - init.flags = 0; + init.flags = CLK_GET_RATE_NOCACHE; parent_name = __clk_get_name(clk); init.parent_names = &parent_name; From 29b1381e293826bbcf4420ac21add6f12de4d7c5 Mon Sep 17 00:00:00 2001 From: Paul Pop Date: Wed, 22 Apr 2026 14:41:54 +0300 Subject: [PATCH 5/9] arm: dts: zynq: add Sharkbyte board support Add devicetree support for the Sharkbyte dual HMCAD1520 ADC data acquisition platform. Signed-off-by: Paul Pop --- arch/arm/boot/dts/xilinx/zynq-sharkbyte.dts | 333 ++++++++++++++++++ .../boot/dts/xilinx/zynq-sharkbyte_12b.dts | 26 ++ .../boot/dts/xilinx/zynq-sharkbyte_14b.dts | 22 ++ 3 files changed, 381 insertions(+) create mode 100644 arch/arm/boot/dts/xilinx/zynq-sharkbyte.dts create mode 100644 arch/arm/boot/dts/xilinx/zynq-sharkbyte_12b.dts create mode 100644 arch/arm/boot/dts/xilinx/zynq-sharkbyte_14b.dts diff --git a/arch/arm/boot/dts/xilinx/zynq-sharkbyte.dts b/arch/arm/boot/dts/xilinx/zynq-sharkbyte.dts new file mode 100644 index 00000000000000..1c9f5705b47f1c --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-sharkbyte.dts @@ -0,0 +1,333 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices Sharkbyte - Dual HMCAD15xx ADC Platform + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2025 Analog Devices Inc. + */ +/dts-v1/; + +#include "zynq.dtsi" +#include +#include + +/ { + model = "Analog Devices Sharkbyte"; + + memory { + device_type = "memory"; + reg = <0x00000000 0x20000000>; + }; + + chosen { + stdout-path = "/amba@0/uart@E0001000"; + }; + + clocks { + adf4355_clkin: clock@0 { + compatible = "fixed-clock"; + clock-frequency = <10000000>; + clock-output-names = "clkin"; + #clock-cells = <0>; + }; + + tdd_ref: clock@1 { + compatible = "fixed-clock"; + clock-frequency = <12500000>; + clock-output-names = "tdd_ref_clk"; + #clock-cells = <0>; + }; + }; + + vref: regulator-vref { + compatible = "regulator-fixed"; + regulator-name = "fixed-supply"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + one-bit-adc-dac@0 { + compatible = "adi,one-bit-adc-dac"; + #address-cells = <1>; + #size-cells = <0>; + out-gpios = <&gpio_exp 13 GPIO_ACTIVE_LOW>, + <&gpio_exp 14 GPIO_ACTIVE_LOW>, + <&gpio_exp 15 GPIO_ACTIVE_LOW>; + + channel@0 { + reg = <0>; + label = "ldac"; + }; + + channel@1 { + reg = <1>; + label = "rstn_dac"; + }; + + channel@2 { + reg = <2>; + label = "clk_sel"; + }; + }; + + leds { + compatible = "gpio-leds"; + + led0 { + label = "led0:green"; + gpios = <&gpio_exp 12 GPIO_ACTIVE_HIGH>; + linux,default-trigger = "heartbeat"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + #address-cells = <1>; + #size-cells = <0>; + autorepeat; + }; + + fpga_axi: fpga-axi@0 { + compatible = "simple-bus"; + #address-cells = <0x1>; + #size-cells = <0x1>; + ranges; + + axi_i2c0: i2c@41600000 { + compatible = "xlnx,axi-iic-1.02.a", "xlnx,xps-iic-2.00.a"; + reg = <0x41600000 0x10000>; + interrupt-parent = <&intc>; + interrupts = <0 59 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 15>; + clock-names = "pclk"; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + gpio_exp: gpio@34 { + compatible = "adi,adp5589"; + reg = <0x34>; + #gpio-cells = <2>; + gpio-controller; + }; + + ad5696: dac@c { + compatible = "adi,ad5696"; + reg = <0x0c>; + vcc-supply = <&vref>; + }; + + max31827: temperature-sensor@5f { + compatible = "adi,max31827"; + label = "sharkbyte-temp"; + reg = <0x5f>; + vref-supply = <&vref>; + adi,comp-int; + adi,alarm-pol = <0>; + adi,fault-q = <1>; + adi,timeout-enable; + }; + }; + + axi_adc1_hmcad15xx: hmcad15xx-adc-a@44a00000 { + compatible = "adi,axi-adc-legacy-10.0.a"; + reg = <0x44a00000 0x10000>; + dmas = <&rx1_dma 0>; + dma-names = "rx"; + spibus-connected = <&hmcad15xx_1>; + }; + + adc1_data_offload: axi-data-offload@44b00000 { + compatible = "adi,axi-data-offload-1.0.a"; + reg = <0x44b00000 0x10000>; + adi,oneshot; + adi,sync-config = <1>; + }; + + rx1_dma: dma-controller@44a30000 { + compatible = "adi,axi-dmac-1.00.a"; + reg = <0x44a30000 0x10000>; + #dma-cells = <1>; + interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 17>; + + adi,channels { + #size-cells = <0>; + #address-cells = <1>; + + dma-channel@0 { + reg = <0>; + adi,source-bus-width = <64>; + adi,source-bus-type = <1>; + adi,destination-bus-width = <64>; + adi,destination-bus-type = <0>; + }; + }; + }; + + axi_adc2_hmcad15xx: hmcad15xx-adc-b@44a60000 { + compatible = "adi,axi-adc-legacy-10.0.a"; + reg = <0x44a60000 0x10000>; + dmas = <&rx2_dma 0>; + dma-names = "rx"; + spibus-connected = <&hmcad15xx_2>; + }; + + adc2_data_offload: axi-data-offload@44b10000 { + compatible = "adi,axi-data-offload-1.0.a"; + reg = <0x44b10000 0x10000>; + adi,oneshot; + adi,sync-config = <1>; + }; + + rx2_dma: dma-controller@44a90000 { + compatible = "adi,axi-dmac-1.00.a"; + reg = <0x44a90000 0x10000>; + #dma-cells = <1>; + interrupts = <0 57 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clkc 17>; + + adi,channels { + #size-cells = <0>; + #address-cells = <1>; + + dma-channel@0 { + reg = <0>; + adi,source-bus-width = <64>; + adi,source-bus-type = <1>; + adi,destination-bus-width = <64>; + adi,destination-bus-type = <0>; + }; + }; + }; + + axi_tdd_0: axi-tdd@44ac0000 { + compatible = "adi,axi-tdd"; + reg = <0x44ac0000 0x10000>; + clocks = <&clkc 15>, <&tdd_ref>; + clock-names = "s_axi_aclk", "intf_clk"; + }; + + iio_axi_tdd_0: iio-axi-tdd@0 { + compatible = "adi,iio-fake-platform-device"; + adi,faked-dev = <&axi_tdd_0>; + adi,attribute-names = + "version", "core_id", "scratch", "magic", + "sync_soft", "sync_external", "sync_internal", "sync_reset", + "enable", "startup_delay_raw", "startup_delay_ms", + "burst_count", "frame_length_raw", "frame_length_ms", + "state", "internal_sync_period_raw", "internal_sync_period_ms", + "out_channel0_enable", "out_channel0_polarity", + "out_channel0_on_raw", "out_channel0_on_ms", + "out_channel0_off_raw", "out_channel0_off_ms", + "out_channel1_enable", "out_channel1_polarity", + "out_channel1_on_raw", "out_channel1_on_ms", + "out_channel1_off_raw", "out_channel1_off_ms"; + label = "axi-core-tdd"; + }; + }; +}; + +&sdhci0 { + status = "disabled"; +}; + +&watchdog0 { + status = "okay"; + reset-on-timeout; +}; + +&usb0 { + xlnx,phy-reset-gpio = <&gpio0 52 0>; + dr_mode = "otg"; + status = "okay"; +}; + +&qspi { + status = "okay"; + is-dual = <0>; + num-cs = <1>; + spi-nor-locking-disable; + + primary_flash: flash@0 { + #address-cells = <1>; + #size-cells = <1>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + compatible = "jedec,spi-nor"; + reg = <0x0>; + spi-max-frequency = <50000000>; + + partition@0 { + label = "qspi-fsbl-uboot"; + reg = <0x0 0x100000>; + }; + + partition@100000 { + label = "qspi-uboot-env"; + reg = <0x100000 0x20000>; + }; + + partition@120000 { + label = "qspi-nvmfs"; + reg = <0x120000 0xe0000>; + }; + + partition@200000 { + label = "qspi-linux"; + reg = <0x200000 0x1e00000>; + }; + }; +}; + +&spi0 { + status = "okay"; + + hmcad15xx_1: adc@0 { + compatible = "adi,hmcad15xx"; + reg = <0>; + clocks = <&adf4355_clk>; + clock-names = "clk"; + reset-gpios = <&gpio_exp 9 GPIO_ACTIVE_LOW>; + pd-gpios = <&gpio_exp 10 GPIO_ACTIVE_HIGH>; + adi,num-channels = <1>; + adi,resolution = <8>; + adi,pol-mask = <239>; + }; + + hmcad15xx_2: adc@1 { + compatible = "adi,hmcad15xx"; + reg = <1>; + clocks = <&adf4355_clk>; + clock-names = "clk"; + reset-gpios = <&gpio_exp 8 GPIO_ACTIVE_LOW>; + pd-gpios = <&gpio_exp 11 GPIO_ACTIVE_HIGH>; + adi,num-channels = <1>; + adi,resolution = <8>; + adi,pol-mask = <32>; + }; + + adf4355_clk: pll@2 { + compatible = "adi,adf4355-2"; + reg = <2>; + spi-max-frequency = <10000000>; + clocks = <&adf4355_clkin>; + clock-names = "clkin"; + clock-output-names = "adf4355_pll"; + #clock-cells = <0>; + adi,charge-pump-current = <900>; + adi,muxout-select = <6>; + adi,output-a-power = <3>; + adi,output-b-power = <3>; + adi,mute-till-lock-enable; + adi,charge-pump-negative-bleed-enable; + adi,reference-differential-input-enable; + adi,power-up-frequency = /bits/ 64 <1000000000>; + adi,output-a-enable; + adi,output-b-enable; + adi,clock-shift = <0>; + }; +}; diff --git a/arch/arm/boot/dts/xilinx/zynq-sharkbyte_12b.dts b/arch/arm/boot/dts/xilinx/zynq-sharkbyte_12b.dts new file mode 100644 index 00000000000000..3ffecd41ee483f --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-sharkbyte_12b.dts @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices Sharkbyte - 12-bit Configuration + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2025 Analog Devices Inc. + */ +/dts-v1/; + +#include "zynq-sharkbyte.dts" + +&hmcad15xx_1 { + adi,num-channels = <1>; + adi,resolution = <12>; +}; + +&hmcad15xx_2 { + adi,num-channels = <1>; + adi,resolution = <12>; +}; + +&adf4355_clk { + adi,power-up-frequency = /bits/ 64 <640000000>; +}; diff --git a/arch/arm/boot/dts/xilinx/zynq-sharkbyte_14b.dts b/arch/arm/boot/dts/xilinx/zynq-sharkbyte_14b.dts new file mode 100644 index 00000000000000..f7e438f180705f --- /dev/null +++ b/arch/arm/boot/dts/xilinx/zynq-sharkbyte_14b.dts @@ -0,0 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices Sharkbyte - 14-bit Configuration + * + * hdl_project: + * board_revision: <> + * + * Copyright (C) 2025 Analog Devices Inc. + */ +/dts-v1/; + +#include "zynq-sharkbyte.dts" + +&hmcad15xx_1 { + adi,num-channels = <4>; + adi,resolution = <14>; +}; + +&hmcad15xx_2 { + adi,num-channels = <4>; + adi,resolution = <14>; +}; From 03d266598f667c7f43657a1b59ef1ec3827063ce Mon Sep 17 00:00:00 2001 From: Paul Pop Date: Wed, 22 Apr 2026 14:44:43 +0300 Subject: [PATCH 6/9] arm: configs: add zynq_sharkbyte_defconfig Add default kernel configuration for the Sharkbyte platform. Signed-off-by: Paul Pop --- arch/arm/configs/zynq_sharkbyte_defconfig | 255 ++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 arch/arm/configs/zynq_sharkbyte_defconfig diff --git a/arch/arm/configs/zynq_sharkbyte_defconfig b/arch/arm/configs/zynq_sharkbyte_defconfig new file mode 100644 index 00000000000000..72209e37550f96 --- /dev/null +++ b/arch/arm/configs/zynq_sharkbyte_defconfig @@ -0,0 +1,255 @@ +CONFIG_SYSVIPC=y +CONFIG_USELIB=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=15 +CONFIG_CGROUPS=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_PERF_EVENTS=y +CONFIG_ARCH_ZYNQ=y +CONFIG_XILINX_RESET_CODE=y +CONFIG_PL310_ERRATA_588369=y +CONFIG_PL310_ERRATA_727915=y +CONFIG_PL310_ERRATA_769419=y +# CONFIG_ARM_ERRATA_643719 is not set +CONFIG_ARM_ERRATA_754322=y +CONFIG_ARM_ERRATA_754327=y +CONFIG_ARM_ERRATA_764369=y +CONFIG_ARM_ERRATA_775420=y +CONFIG_SMP=y +CONFIG_SCHED_MC=y +CONFIG_SCHED_SMT=y +CONFIG_HIGHMEM=y +CONFIG_CMDLINE="console=ttyPS0,115200n8 root=/dev/ram rw earlyprintk" +CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_ARM_ZYNQ_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_COMPACTION is not set +CONFIG_CMA=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_IP_PNP_BOOTP=y +CONFIG_IP_PNP_RARP=y +CONFIG_NET_IPIP=m +CONFIG_VLAN_8021Q=m +CONFIG_CFG80211=y +CONFIG_MAC80211=y +CONFIG_MAC80211_LEDS=y +CONFIG_RFKILL=y +CONFIG_UEVENT_HELPER=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_CONNECTOR=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_ADI_AXI_TDD=y +CONFIG_SRAM=y +# CONFIG_MATHWORKS_IP_CORE is not set +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_SG=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CIRRUS is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_HISILICON is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SMSC is not set +# CONFIG_NET_VENDOR_STMICRO is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_USB_RTL8152=y +CONFIG_USB_LAN78XX=y +CONFIG_USB_USBNET=y +# CONFIG_USB_NET_CDC_NCM is not set +CONFIG_USB_NET_DM9601=y +CONFIG_USB_NET_SMSC75XX=y +CONFIG_USB_NET_SMSC95XX=y +# CONFIG_USB_NET_NET1080 is not set +CONFIG_USB_NET_RNDIS_HOST=y +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +CONFIG_RT2X00=y +CONFIG_RT2500USB=y +CONFIG_RT73USB=y +CONFIG_RT2800USB=y +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RTL8187=y +CONFIG_RTL8192CU=y +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8XXXU=y +CONFIG_RTL8XXXU_UNTESTED=y +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +CONFIG_INPUT_SPARSEKMAP=y +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_GPIO=y +# CONFIG_INPUT_MOUSE is not set +CONFIG_VT_HW_CONSOLE_BINDING=y +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_XILINX_PS_UART=y +CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y +# CONFIG_HW_RANDOM is not set +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_CADENCE=y +CONFIG_I2C_GPIO=y +CONFIG_I2C_XILINX=y +CONFIG_SPI=y +CONFIG_SPI_AXI_SPI_ENGINE=y +CONFIG_SPI_CADENCE=y +CONFIG_SPI_XILINX=y +CONFIG_SPI_ZYNQ_QSPI=y +CONFIG_SPI_SPIDEV=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_ZYNQ=y +CONFIG_POWER_SUPPLY=y +CONFIG_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_XILINX_WATCHDOG=y +CONFIG_CADENCE_WATCHDOG=y +CONFIG_SSB=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_HIDRAW=y +CONFIG_USB_HIDDEV=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_OTG=y +CONFIG_USB_EHCI_HCD=y +# CONFIG_USB_EHCI_TT_NEWSCHED is not set +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_FTDI_SIO=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_XILINX=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_DMADEVICES=y +CONFIG_AXI_DMAC=y +CONFIG_ADI_AXI_DATA_OFFLOAD=y +CONFIG_UIO=y +CONFIG_UIO_PDRV_GENIRQ=y +CONFIG_UIO_DMEM_GENIRQ=y +CONFIG_UIO_XILINX_APM=y +CONFIG_STAGING=y +CONFIG_R8712U=y +CONFIG_COMMON_CLK_AXI_CLKGEN=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_MEMORY=y +CONFIG_IIO=y +CONFIG_HMCAD15XX=y +CONFIG_AD5696_I2C=y +CONFIG_KEYBOARD_ADP5589=y +CONFIG_MAX31827=y +CONFIG_ADF5355=y +CONFIG_ADMC=y +CONFIG_XILINX_XADC=y +CONFIG_ONE_BIT_ADC_DAC=y +CONFIG_CF_AXI_DDS=y +CONFIG_ADI_IIO_FAKEDEV=y +CONFIG_CF_AXI_ADC=y +CONFIG_FPGA=y +CONFIG_FPGA_MGR_ZYNQ_FPGA=y +CONFIG_EXT4_FS=y +# CONFIG_DNOTIFY is not set +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_COMPRESSION_OPTIONS=y +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_DMA_CMA=y +CONFIG_CMA_SIZE_MBYTES=256 +CONFIG_DEBUG_FS=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 From 2fa372ad134a6549e1a9a67049957bb51c977f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Codepr=C3=BCfer?= Date: Thu, 23 Apr 2026 20:12:07 +0000 Subject: [PATCH 7/9] fixup! iio: frequency: adf5355: set CLK_GET_RATE_NOCACHE for clock output --- drivers/iio/frequency/adf5355.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/iio/frequency/adf5355.c b/drivers/iio/frequency/adf5355.c index cfaddba0b211b4..d9985898d50497 100644 --- a/drivers/iio/frequency/adf5355.c +++ b/drivers/iio/frequency/adf5355.c @@ -1002,8 +1002,6 @@ static int adf5355_probe(struct spi_device *spi) init.num_parents = 1; clk_out = clk_register(&spi->dev, &clk_priv->hw); - if (IS_ERR(clk_out)) - kfree(clk_priv); if (!IS_ERR(clk_out)) of_clk_add_provider(spi->dev.of_node, of_clk_src_simple_get, clk_out); From adbdf436adee6eda14a0a72d81ae0ecf267fbd19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Codepr=C3=BCfer?= Date: Thu, 23 Apr 2026 20:12:25 +0000 Subject: [PATCH 8/9] fixup! dt-bindings: iio: adc: add adi,hmcad15xx --- .../devicetree/bindings/iio/adc/adi,hmcad15xx.yaml | 6 +++--- drivers/iio/adc/Kconfig | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml b/Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml index 76b06ea7cb191d..86a321362ad49a 100644 --- a/Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml +++ b/Documentation/devicetree/bindings/iio/adc/adi,hmcad15xx.yaml @@ -12,7 +12,7 @@ maintainers: description: | The HMCAD1511 and HMCAD1520 are high-speed analog-to-digital converters - with LVDS outputs. The HMCAD1511 is a 12-bit ADC supporting up to 1 GSPS + with LVDS outputs. The HMCAD1511 is an 8-bit ADC supporting up to 1 GSPS in single-channel mode. The HMCAD1520 is a 14-bit ADC supporting up to 105 MSPS in quad-channel precision mode. @@ -24,8 +24,8 @@ description: | The driver supports 8-bit, 12-bit, and 14-bit resolution modes with appropriate LVDS output configurations. - https://www.ti.com/product/HMCAD1511 - https://www.ti.com/product/HMCAD1520 + https://www.analog.com/en/products/hmcad1511.html + https://www.analog.com/en/products/hmcad1520.html properties: compatible: diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 3328e4be0c1d58..af303ab587dd3e 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -909,10 +909,10 @@ config HMCAD15XX help Say yes here to build support for Analog Devices HMCAD1511 and HMCAD1520 high-speed analog-to-digital converters with LVDS outputs. - The HMCAD1511 is a 12-bit ADC supporting up to 1 GSPS in single-channel + The HMCAD1511 is an 8-bit ADC supporting up to 1 GSPS in single-channel mode. The HMCAD1520 is a 14-bit ADC supporting up to 105 MSPS in quad-channel precision mode. Both devices support flexible 1/2/4 - channel configurations with 8-bit, 12-bit, or 14-bit resolution modes. + channel configurations. To compile this driver as a module, choose M here: the module will be called hmcad15xx. From 47ae62fcb5c2c902529001c1e7815b6f36747505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Codepr=C3=BCfer?= Date: Thu, 23 Apr 2026 20:13:16 +0000 Subject: [PATCH 9/9] fixup! iio: adc: add support for HMCAD15xx high-speed ADC fix HMCAD1520 14-bit precision mode register 0x31 configuration and kfree fix --- drivers/iio/adc/hmcad15xx.c | 49 +++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/drivers/iio/adc/hmcad15xx.c b/drivers/iio/adc/hmcad15xx.c index ecc76d83506717..c374860ae979d3 100644 --- a/drivers/iio/adc/hmcad15xx.c +++ b/drivers/iio/adc/hmcad15xx.c @@ -53,10 +53,15 @@ #define HMCAD15XX_LVDS_OUTPUT_DUAL_8BIT 0x4 /* HMCAD15XX_REG_OPERATION_MODE (0x31) - combined high_speed + clk_divide */ +/* HMCAD1511: D[2:0]=channel_num (1/2/4), D[9:8]=clk_divide */ +/* HMCAD1520: D[2:0]=high_speed_mode, D[3]=precision_mode, D[9:8]=clk_divide */ #define HMCAD15XX_OP_MODE_MSK (GENMASK(9, 8) | GENMASK(2, 0)) +#define HMCAD1520_OP_MODE_MSK (GENMASK(9, 8) | GENMASK(3, 0)) #define HMCAD15XX_OP_MODE_SINGLE_CH 0x0001 #define HMCAD15XX_OP_MODE_DUAL_CH 0x0102 #define HMCAD15XX_OP_MODE_QUAD_CH 0x0204 +/* HMCAD1520 14-bit precision: precision_mode=1, high_speed_mode=0, clk_divide=8 */ +#define HMCAD1520_OP_MODE_PRECISION 0x0308 /* HMCAD15XX_REG_INP_SEL */ #define HMCAD15XX_INP_SEL_ADC1_MSK GENMASK(4, 1) @@ -578,24 +583,36 @@ static int hmcad15xx_probe(struct spi_device *spi) if (ret < 0) return ret; - switch (st->en_channels) { - case 1: - regval = HMCAD15XX_OP_MODE_SINGLE_CH; - st->clk_div = CLK_DIV_1; - break; - case 2: - regval = HMCAD15XX_OP_MODE_DUAL_CH; - st->clk_div = CLK_DIV_2; - break; - case 4: - default: - regval = HMCAD15XX_OP_MODE_QUAD_CH; + /* + * HMCAD1520 14-bit precision mode uses a dedicated precision_mode bit + * (D[3]) in reg 0x31 with high_speed_mode=0 and clk_divide=8. + * All other modes use the high_speed_mode field (D[2:0]) shared with + * HMCAD1511 channel_num encoding. + */ + if (st->resolution == RES_14BIT) { + regval = HMCAD1520_OP_MODE_PRECISION; st->clk_div = CLK_DIV_4; - break; + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_OPERATION_MODE, + HMCAD1520_OP_MODE_MSK, regval); + } else { + switch (st->en_channels) { + case 1: + regval = HMCAD15XX_OP_MODE_SINGLE_CH; + st->clk_div = CLK_DIV_1; + break; + case 2: + regval = HMCAD15XX_OP_MODE_DUAL_CH; + st->clk_div = CLK_DIV_2; + break; + case 4: + default: + regval = HMCAD15XX_OP_MODE_QUAD_CH; + st->clk_div = CLK_DIV_4; + break; + } + ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_OPERATION_MODE, + HMCAD15XX_OP_MODE_MSK, regval); } - - ret = hmcad15xx_spi_write_mask(st, HMCAD15XX_REG_OPERATION_MODE, - HMCAD15XX_OP_MODE_MSK, regval); if (ret < 0) return ret;