* [PATCH 0/3] Refactor Microchip MCP47FEB02 I2C driver in separate modules to add support for MCP48FEB02 SPI driver
@ 2026-07-23 13:43 Ariana Lazar
2026-07-23 13:43 ` [PATCH 1/3] iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules Ariana Lazar
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Ariana Lazar @ 2026-07-23 13:43 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-iio, devicetree, Ariana Lazar
Refactor I2C driver implementation into separate modules in order to add
support for SPI MCP48FxBy1/2/4/8 DAC family on top of the I2C implementation.
The I2C and SPI devices have the same memory map and supported
functionalities.
Signed-off-by: Ariana Lazar <ariana.lazar@microchip.com>
---
Ariana Lazar (3):
iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules
dt-bindings: iio: dac: add support for MCP48FEB02 SPI
iio: dac: add support for Microchip MCP48FEB02
.../bindings/iio/dac/microchip,mcp47feb02.yaml | 244 +++++++++---
MAINTAINERS | 5 +-
drivers/iio/dac/Kconfig | 33 +-
drivers/iio/dac/Makefile | 4 +-
.../iio/dac/{mcp47feb02.c => mcp47feb02-core.c} | 414 +--------------------
drivers/iio/dac/mcp47feb02-i2c.c | 145 ++++++++
drivers/iio/dac/mcp47feb02-spi.c | 146 ++++++++
drivers/iio/dac/mcp47feb02.h | 153 ++++++++
8 files changed, 693 insertions(+), 451 deletions(-)
---
base-commit: 9c6acc6e6555d34198e45cb0d309569dfbadf929
change-id: 20260625-mcp47feb02_refactor-fa8420ae3282
Best regards,
--
Ariana Lazar <ariana.lazar@microchip.com>
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/3] iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules
2026-07-23 13:43 [PATCH 0/3] Refactor Microchip MCP47FEB02 I2C driver in separate modules to add support for MCP48FEB02 SPI driver Ariana Lazar
@ 2026-07-23 13:43 ` Ariana Lazar
2026-07-23 14:01 ` sashiko-bot
2026-07-23 13:43 ` [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI Ariana Lazar
2026-07-23 13:43 ` [PATCH 3/3] iio: dac: add support for Microchip MCP48FEB02 Ariana Lazar
2 siblings, 1 reply; 9+ messages in thread
From: Ariana Lazar @ 2026-07-23 13:43 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-iio, devicetree, Ariana Lazar
Prepare the driver for the bus-specific code refactoring into
separate files. The renamed file will contain the common DAC functionality
shared by the MCP47FxBy1/2/4/8 I2C and MCP48FxBy1/2/4/8 SPI drivers. The
MCP47FEB02 driver was refactored into two modules: mcp47feb02-core.c
and mcp47feb02-i2c.c in order to prepare the support for SPI
MCP48FxBy1/2/4/8 DAC family on top of the current implementation.
Signed-off-by: Ariana Lazar <ariana.lazar@microchip.com>
---
MAINTAINERS | 4 +-
drivers/iio/dac/Kconfig | 10 +-
drivers/iio/dac/Makefile | 3 +-
.../iio/dac/{mcp47feb02.c => mcp47feb02-core.c} | 414 +--------------------
drivers/iio/dac/mcp47feb02-i2c.c | 145 ++++++++
drivers/iio/dac/mcp47feb02.h | 153 ++++++++
6 files changed, 325 insertions(+), 404 deletions(-)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6b4560681b51cfabf0b0e98fd89b69d8c527228b..fc87609865f26a9f484edc42058f7df659a0fa4f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16118,7 +16118,9 @@ M: Ariana Lazar <ariana.lazar@microchip.com>
L: linux-iio@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
-F: drivers/iio/dac/mcp47feb02.c
+F: drivers/iio/dac/mcp47feb02-core.c
+F: drivers/iio/dac/mcp47feb02-i2c.c
+F: drivers/iio/dac/mcp47feb02.h
MCP4821 DAC DRIVER
M: Anshul Dalal <anshulusr@gmail.com>
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 657c68e75542e47ad5603165bcbc3660e90c6450..cc10d43ffd1e89bbf945ef89ea5af0abe1a91084 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -550,8 +550,13 @@ config MCP4728
will be called mcp4728.
config MCP47FEB02
- tristate "MCP47F(E/V)B01/02/04/08/11/12/14/18/21/22/24/28 DAC driver"
+ tristate
+
+config MCP47FEB02_I2C
+ tristate "MCP47F(E/V)B01/02/04/08/11/12/14/18/21/22/24/28 I2C DAC driver"
depends on I2C
+ select REGMAP_I2C
+ select MCP47FEB02
help
Say yes here if you want to build the driver for the Microchip:
- 8-bit DAC:
@@ -567,7 +572,8 @@ config MCP47FEB02
(DAC) with I2C interface.
To compile this driver as a module, choose M here: the module
- will be called mcp47feb02.
+ will be called mcp47feb02_i2c and you will also get
+ mcp47feb02_core for the core module.
config MCP4821
tristate "MCP4801/02/11/12/21/22 DAC driver"
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 0034317984985035f7987a744899924bfd4612e3..28c8646a987cff1ac4d693fe86898d66c901d5bd 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -54,7 +54,8 @@ obj-$(CONFIG_MAX5522) += max5522.o
obj-$(CONFIG_MAX5821) += max5821.o
obj-$(CONFIG_MCP4725) += mcp4725.o
obj-$(CONFIG_MCP4728) += mcp4728.o
-obj-$(CONFIG_MCP47FEB02) += mcp47feb02.o
+obj-$(CONFIG_MCP47FEB02) += mcp47feb02-core.o
+obj-$(CONFIG_MCP47FEB02_I2C) += mcp47feb02-i2c.o
obj-$(CONFIG_MCP4821) += mcp4821.o
obj-$(CONFIG_MCP4922) += mcp4922.o
obj-$(CONFIG_STM32_DAC_CORE) += stm32-dac-core.o
diff --git a/drivers/iio/dac/mcp47feb02.c b/drivers/iio/dac/mcp47feb02-core.c
similarity index 64%
rename from drivers/iio/dac/mcp47feb02.c
rename to drivers/iio/dac/mcp47feb02-core.c
index a823c2a673a26d70e5829cb587034da435af0451..6c86fa40e6eb2f1f602cac4c75265b6af7000c72 100644
--- a/drivers/iio/dac/mcp47feb02.c
+++ b/drivers/iio/dac/mcp47feb02-core.c
@@ -2,7 +2,7 @@
/*
* IIO driver for MCP47FEB02 Multi-Channel DAC with I2C interface
*
- * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries
+ * Copyright (C) 2026 Microchip Technology Inc. and its subsidiaries
*
* Author: Ariana Lazar <ariana.lazar@microchip.com>
*
@@ -16,7 +16,6 @@
#include <linux/bitfield.h>
#include <linux/delay.h>
#include <linux/err.h>
-#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/kstrtox.h>
@@ -30,324 +29,14 @@
#include <linux/types.h>
#include <linux/units.h>
-/* Register addresses must be left shifted with 3 positions in order to append command mask */
-#define MCP47FEB02_DAC0_REG_ADDR 0x00
-#define MCP47FEB02_VREF_REG_ADDR 0x40
-#define MCP47FEB02_POWER_DOWN_REG_ADDR 0x48
-#define MCP47FEB02_DAC_CTRL_MASK GENMASK(1, 0)
-
-#define MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR 0x50
-#define MCP47FEB02_GAIN_BIT_MASK BIT(0)
-#define MCP47FEB02_GAIN_BIT_STATUS_EEWA_MASK BIT(6)
-#define MCP47FEB02_GAIN_BITS_MASK GENMASK(15, 8)
-
-#define MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR 0x58
-
-#define MCP47FEB02_NV_DAC0_REG_ADDR 0x80
-#define MCP47FEB02_NV_VREF_REG_ADDR 0xC0
-#define MCP47FEB02_NV_POWER_DOWN_REG_ADDR 0xC8
-#define MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR 0xD0
-#define MCP47FEB02_NV_I2C_SLAVE_ADDR_MASK GENMASK(7, 0)
-
-/* Voltage reference, Power-Down control register and DAC Wiperlock status register fields */
-#define DAC_CTRL_MASK(ch) (GENMASK(1, 0) << (2 * (ch)))
-#define DAC_CTRL_VAL(ch, val) ((val) << (2 * (ch)))
-
-/* Gain Control and I2C Slave Address Reguster fields */
-#define DAC_GAIN_MASK(ch) (BIT(0) << (8 + (ch)))
-#define DAC_GAIN_VAL(ch, val) ((val) << (8 + (ch)))
-
-#define REG_ADDR(reg) ((reg) << 3)
-#define NV_REG_ADDR(reg) ((NV_DAC_ADDR_OFFSET + (reg)) << 3)
-#define READFLAG_MASK GENMASK(2, 1)
-
-#define MCP47FEB02_MAX_CH 8
-#define MCP47FEB02_MAX_SCALES_CH 3
-#define MCP47FEB02_DAC_WIPER_UNLOCKED 0
-#define MCP47FEB02_NORMAL_OPERATION 0
-#define MCP47FEB02_INTERNAL_BAND_GAP_uV 2440000
-#define NV_DAC_ADDR_OFFSET 0x10
-
-enum mcp47feb02_vref_mode {
- MCP47FEB02_VREF_VDD = 0,
- MCP47FEB02_INTERNAL_BAND_GAP = 1,
- MCP47FEB02_EXTERNAL_VREF_UNBUFFERED = 2,
- MCP47FEB02_EXTERNAL_VREF_BUFFERED = 3,
-};
-
-enum mcp47feb02_scale {
- MCP47FEB02_SCALE_VDD = 0,
- MCP47FEB02_SCALE_GAIN_X1 = 1,
- MCP47FEB02_SCALE_GAIN_X2 = 2,
-};
-
-enum mcp47feb02_gain_bit_mode {
- MCP47FEB02_GAIN_BIT_X1 = 0,
- MCP47FEB02_GAIN_BIT_X2 = 1,
-};
+#include "mcp47feb02.h"
-static const char * const mcp47feb02_powerdown_modes[] = {
+const char * const mcp47feb02_powerdown_modes[] = {
"1kohm_to_gnd",
"100kohm_to_gnd",
"open_circuit",
};
-/**
- * struct mcp47feb02_features - chip specific data
- * @name: device name
- * @phys_channels: number of hardware channels
- * @resolution: DAC resolution
- * @have_ext_vref1: does the hardware have an the second external voltage reference?
- * @have_eeprom: does the hardware have an internal eeprom?
- */
-struct mcp47feb02_features {
- const char *name;
- unsigned int phys_channels;
- unsigned int resolution;
- bool have_ext_vref1;
- bool have_eeprom;
-};
-
-static const struct mcp47feb02_features mcp47feb01_chip_features = {
- .name = "mcp47feb01",
- .phys_channels = 1,
- .resolution = 8,
- .have_ext_vref1 = false,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb02_chip_features = {
- .name = "mcp47feb02",
- .phys_channels = 2,
- .resolution = 8,
- .have_ext_vref1 = false,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb04_chip_features = {
- .name = "mcp47feb04",
- .phys_channels = 4,
- .resolution = 8,
- .have_ext_vref1 = true,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb08_chip_features = {
- .name = "mcp47feb08",
- .phys_channels = 8,
- .resolution = 8,
- .have_ext_vref1 = true,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb11_chip_features = {
- .name = "mcp47feb11",
- .phys_channels = 1,
- .resolution = 10,
- .have_ext_vref1 = false,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb12_chip_features = {
- .name = "mcp47feb12",
- .phys_channels = 2,
- .resolution = 10,
- .have_ext_vref1 = false,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb14_chip_features = {
- .name = "mcp47feb14",
- .phys_channels = 4,
- .resolution = 10,
- .have_ext_vref1 = true,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb18_chip_features = {
- .name = "mcp47feb18",
- .phys_channels = 8,
- .resolution = 10,
- .have_ext_vref1 = true,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb21_chip_features = {
- .name = "mcp47feb21",
- .phys_channels = 1,
- .resolution = 12,
- .have_ext_vref1 = false,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb22_chip_features = {
- .name = "mcp47feb22",
- .phys_channels = 2,
- .resolution = 12,
- .have_ext_vref1 = false,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb24_chip_features = {
- .name = "mcp47feb24",
- .phys_channels = 4,
- .resolution = 12,
- .have_ext_vref1 = true,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47feb28_chip_features = {
- .name = "mcp47feb28",
- .phys_channels = 8,
- .resolution = 12,
- .have_ext_vref1 = true,
- .have_eeprom = true,
-};
-
-static const struct mcp47feb02_features mcp47fvb01_chip_features = {
- .name = "mcp47fvb01",
- .phys_channels = 1,
- .resolution = 8,
- .have_ext_vref1 = false,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb02_chip_features = {
- .name = "mcp47fvb02",
- .phys_channels = 2,
- .resolution = 8,
- .have_ext_vref1 = false,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb04_chip_features = {
- .name = "mcp47fvb04",
- .phys_channels = 4,
- .resolution = 8,
- .have_ext_vref1 = true,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb08_chip_features = {
- .name = "mcp47fvb08",
- .phys_channels = 8,
- .resolution = 8,
- .have_ext_vref1 = true,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb11_chip_features = {
- .name = "mcp47fvb11",
- .phys_channels = 1,
- .resolution = 10,
- .have_ext_vref1 = false,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb12_chip_features = {
- .name = "mcp47fvb12",
- .phys_channels = 2,
- .resolution = 10,
- .have_ext_vref1 = false,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb14_chip_features = {
- .name = "mcp47fvb14",
- .phys_channels = 4,
- .resolution = 10,
- .have_ext_vref1 = true,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb18_chip_features = {
- .name = "mcp47fvb18",
- .phys_channels = 8,
- .resolution = 10,
- .have_ext_vref1 = true,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb21_chip_features = {
- .name = "mcp47fvb21",
- .phys_channels = 1,
- .resolution = 12,
- .have_ext_vref1 = false,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb22_chip_features = {
- .name = "mcp47fvb22",
- .phys_channels = 2,
- .resolution = 12,
- .have_ext_vref1 = false,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb24_chip_features = {
- .name = "mcp47fvb24",
- .phys_channels = 4,
- .resolution = 12,
- .have_ext_vref1 = true,
- .have_eeprom = false,
-};
-
-static const struct mcp47feb02_features mcp47fvb28_chip_features = {
- .name = "mcp47fvb28",
- .phys_channels = 8,
- .resolution = 12,
- .have_ext_vref1 = true,
- .have_eeprom = false,
-};
-
-/**
- * struct mcp47feb02_channel_data - channel configuration
- * @ref_mode: chosen voltage for reference
- * @use_2x_gain: output driver gain control
- * @powerdown: is false if the channel is in normal operation mode
- * @powerdown_mode: selected power-down mode
- * @dac_data: dac value
- */
-struct mcp47feb02_channel_data {
- u8 ref_mode;
- bool use_2x_gain;
- bool powerdown;
- u8 powerdown_mode;
- u16 dac_data;
-};
-
-/**
- * struct mcp47feb02_data - chip configuration
- * @chdata: options configured for each channel on the device
- * @lock: prevents concurrent reads/writes to driver's state members
- * @chip_features: pointer to features struct
- * @scale_1: scales set on channels that are based on Vref1
- * @scale: scales set on channels that are based on Vref/Vref0
- * @active_channels_mask: enabled channels
- * @regmap: regmap for directly accessing device register
- * @labels: table with channels labels
- * @phys_channels: physical channels on the device
- * @vref1_buffered: Vref1 buffer is enabled
- * @vref_buffered: Vref/Vref0 buffer is enabled
- * @use_vref1: vref1-supply is defined
- * @use_vref: vref-supply is defined
- */
-struct mcp47feb02_data {
- struct mcp47feb02_channel_data chdata[MCP47FEB02_MAX_CH];
- struct mutex lock; /* prevents concurrent reads/writes to driver's state members */
- const struct mcp47feb02_features *chip_features;
- int scale_1[2 * MCP47FEB02_MAX_SCALES_CH];
- int scale[2 * MCP47FEB02_MAX_SCALES_CH];
- unsigned long active_channels_mask;
- struct regmap *regmap;
- const char *labels[MCP47FEB02_MAX_CH];
- u16 phys_channels;
- bool vref1_buffered;
- bool vref_buffered;
- bool use_vref1;
- bool use_vref;
-};
-
static const struct regmap_range mcp47feb02_readable_ranges[] = {
regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR),
regmap_reg_range(MCP47FEB02_NV_DAC0_REG_ADDR, MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR),
@@ -380,7 +69,7 @@ static const struct regmap_access_table mcp47feb02_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(mcp47feb02_volatile_ranges),
};
-static const struct regmap_config mcp47feb02_regmap_config = {
+const struct regmap_config mcp47feb02_regmap_config = {
.name = "mcp47feb02_regmap",
.reg_bits = 8,
.val_bits = 16,
@@ -392,6 +81,7 @@ static const struct regmap_config mcp47feb02_regmap_config = {
.cache_type = REGCACHE_MAPLE,
.val_format_endian = REGMAP_ENDIAN_BIG,
};
+EXPORT_SYMBOL_NS_GPL(mcp47feb02_regmap_config, "IIO_MCP47FEB02");
/* For devices that doesn't have nonvolatile memory */
static const struct regmap_range mcp47fvb02_readable_ranges[] = {
@@ -422,7 +112,7 @@ static const struct regmap_access_table mcp47fvb02_volatile_table = {
.n_yes_ranges = ARRAY_SIZE(mcp47fvb02_volatile_ranges),
};
-static const struct regmap_config mcp47fvb02_regmap_config = {
+const struct regmap_config mcp47fvb02_regmap_config = {
.name = "mcp47fvb02_regmap",
.reg_bits = 8,
.val_bits = 16,
@@ -434,6 +124,7 @@ static const struct regmap_config mcp47fvb02_regmap_config = {
.cache_type = REGCACHE_MAPLE,
.val_format_endian = REGMAP_ENDIAN_BIG,
};
+EXPORT_SYMBOL_NS_GPL(mcp47fvb02_regmap_config, "IIO_MCP47FEB02");
static int mcp47feb02_write_to_eeprom(struct mcp47feb02_data *data, unsigned int reg,
unsigned int val)
@@ -666,7 +357,7 @@ static ssize_t mcp47feb02_write_powerdown(struct iio_dev *indio_dev, uintptr_t p
return len;
}
-static DEFINE_SIMPLE_DEV_PM_OPS(mcp47feb02_pm_ops, mcp47feb02_suspend, mcp47feb02_resume);
+EXPORT_SIMPLE_DEV_PM_OPS(mcp47feb02_pm_ops, mcp47feb02_suspend, mcp47feb02_resume);
static const struct iio_enum mcp47febxx_powerdown_mode_enum = {
.items = mcp47feb02_powerdown_modes,
@@ -1091,10 +782,9 @@ static int mcp47feb02_init_ch_scales(struct mcp47feb02_data *data, int vdd_uV,
return 0;
}
-static int mcp47feb02_probe(struct i2c_client *client)
+int mcp47feb02_common_probe(const struct mcp47feb02_features *chip_features, struct regmap *regmap)
{
- const struct mcp47feb02_features *chip_features;
- struct device *dev = &client->dev;
+ struct device *dev = regmap_get_device(regmap);
struct mcp47feb02_data *data;
struct iio_dev *indio_dev;
int vref1_uV, vref_uV, vdd_uV, ret;
@@ -1104,21 +794,13 @@ static int mcp47feb02_probe(struct i2c_client *client)
return -ENOMEM;
data = iio_priv(indio_dev);
- chip_features = i2c_get_match_data(client);
- if (!chip_features)
- return -EINVAL;
-
data->chip_features = chip_features;
+ data->regmap = regmap;
- if (chip_features->have_eeprom) {
- data->regmap = devm_regmap_init_i2c(client, &mcp47feb02_regmap_config);
+ if (chip_features->have_eeprom)
indio_dev->info = &mcp47feb02_info;
- } else {
- data->regmap = devm_regmap_init_i2c(client, &mcp47fvb02_regmap_config);
+ else
indio_dev->info = &mcp47fvb02_info;
- }
- if (IS_ERR(data->regmap))
- return dev_err_probe(dev, PTR_ERR(data->regmap), "Error initializing i2c regmap\n");
indio_dev->name = chip_features->name;
@@ -1175,75 +857,7 @@ static int mcp47feb02_probe(struct i2c_client *client)
return devm_iio_device_register(dev, indio_dev);
}
-
-static const struct i2c_device_id mcp47feb02_id[] = {
- { .name = "mcp47feb01", .driver_data = (kernel_ulong_t)&mcp47feb01_chip_features },
- { .name = "mcp47feb02", .driver_data = (kernel_ulong_t)&mcp47feb02_chip_features },
- { .name = "mcp47feb04", .driver_data = (kernel_ulong_t)&mcp47feb04_chip_features },
- { .name = "mcp47feb08", .driver_data = (kernel_ulong_t)&mcp47feb08_chip_features },
- { .name = "mcp47feb11", .driver_data = (kernel_ulong_t)&mcp47feb11_chip_features },
- { .name = "mcp47feb12", .driver_data = (kernel_ulong_t)&mcp47feb12_chip_features },
- { .name = "mcp47feb14", .driver_data = (kernel_ulong_t)&mcp47feb14_chip_features },
- { .name = "mcp47feb18", .driver_data = (kernel_ulong_t)&mcp47feb18_chip_features },
- { .name = "mcp47feb21", .driver_data = (kernel_ulong_t)&mcp47feb21_chip_features },
- { .name = "mcp47feb22", .driver_data = (kernel_ulong_t)&mcp47feb22_chip_features },
- { .name = "mcp47feb24", .driver_data = (kernel_ulong_t)&mcp47feb24_chip_features },
- { .name = "mcp47feb28", .driver_data = (kernel_ulong_t)&mcp47feb28_chip_features },
- { .name = "mcp47fvb01", .driver_data = (kernel_ulong_t)&mcp47fvb01_chip_features },
- { .name = "mcp47fvb02", .driver_data = (kernel_ulong_t)&mcp47fvb02_chip_features },
- { .name = "mcp47fvb04", .driver_data = (kernel_ulong_t)&mcp47fvb04_chip_features },
- { .name = "mcp47fvb08", .driver_data = (kernel_ulong_t)&mcp47fvb08_chip_features },
- { .name = "mcp47fvb11", .driver_data = (kernel_ulong_t)&mcp47fvb11_chip_features },
- { .name = "mcp47fvb12", .driver_data = (kernel_ulong_t)&mcp47fvb12_chip_features },
- { .name = "mcp47fvb14", .driver_data = (kernel_ulong_t)&mcp47fvb14_chip_features },
- { .name = "mcp47fvb18", .driver_data = (kernel_ulong_t)&mcp47fvb18_chip_features },
- { .name = "mcp47fvb21", .driver_data = (kernel_ulong_t)&mcp47fvb21_chip_features },
- { .name = "mcp47fvb22", .driver_data = (kernel_ulong_t)&mcp47fvb22_chip_features },
- { .name = "mcp47fvb24", .driver_data = (kernel_ulong_t)&mcp47fvb24_chip_features },
- { .name = "mcp47fvb28", .driver_data = (kernel_ulong_t)&mcp47fvb28_chip_features },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, mcp47feb02_id);
-
-static const struct of_device_id mcp47feb02_of_match[] = {
- { .compatible = "microchip,mcp47feb01", .data = &mcp47feb01_chip_features },
- { .compatible = "microchip,mcp47feb02", .data = &mcp47feb02_chip_features },
- { .compatible = "microchip,mcp47feb04", .data = &mcp47feb04_chip_features },
- { .compatible = "microchip,mcp47feb08", .data = &mcp47feb08_chip_features },
- { .compatible = "microchip,mcp47feb11", .data = &mcp47feb11_chip_features },
- { .compatible = "microchip,mcp47feb12", .data = &mcp47feb12_chip_features },
- { .compatible = "microchip,mcp47feb14", .data = &mcp47feb14_chip_features },
- { .compatible = "microchip,mcp47feb18", .data = &mcp47feb18_chip_features },
- { .compatible = "microchip,mcp47feb21", .data = &mcp47feb21_chip_features },
- { .compatible = "microchip,mcp47feb22", .data = &mcp47feb22_chip_features },
- { .compatible = "microchip,mcp47feb24", .data = &mcp47feb24_chip_features },
- { .compatible = "microchip,mcp47feb28", .data = &mcp47feb28_chip_features },
- { .compatible = "microchip,mcp47fvb01", .data = &mcp47fvb01_chip_features },
- { .compatible = "microchip,mcp47fvb02", .data = &mcp47fvb02_chip_features },
- { .compatible = "microchip,mcp47fvb04", .data = &mcp47fvb04_chip_features },
- { .compatible = "microchip,mcp47fvb08", .data = &mcp47fvb08_chip_features },
- { .compatible = "microchip,mcp47fvb11", .data = &mcp47fvb11_chip_features },
- { .compatible = "microchip,mcp47fvb12", .data = &mcp47fvb12_chip_features },
- { .compatible = "microchip,mcp47fvb14", .data = &mcp47fvb14_chip_features },
- { .compatible = "microchip,mcp47fvb18", .data = &mcp47fvb18_chip_features },
- { .compatible = "microchip,mcp47fvb21", .data = &mcp47fvb21_chip_features },
- { .compatible = "microchip,mcp47fvb22", .data = &mcp47fvb22_chip_features },
- { .compatible = "microchip,mcp47fvb24", .data = &mcp47fvb24_chip_features },
- { .compatible = "microchip,mcp47fvb28", .data = &mcp47fvb28_chip_features },
- { }
-};
-MODULE_DEVICE_TABLE(of, mcp47feb02_of_match);
-
-static struct i2c_driver mcp47feb02_driver = {
- .driver = {
- .name = "mcp47feb02",
- .of_match_table = mcp47feb02_of_match,
- .pm = pm_sleep_ptr(&mcp47feb02_pm_ops),
- },
- .probe = mcp47feb02_probe,
- .id_table = mcp47feb02_id,
-};
-module_i2c_driver(mcp47feb02_driver);
+EXPORT_SYMBOL_NS(mcp47feb02_common_probe, "IIO_MCP47FEB02");
MODULE_AUTHOR("Ariana Lazar <ariana.lazar@microchip.com>");
MODULE_DESCRIPTION("IIO driver for MCP47FEB02 Multi-Channel DAC with I2C interface");
diff --git a/drivers/iio/dac/mcp47feb02-i2c.c b/drivers/iio/dac/mcp47feb02-i2c.c
new file mode 100644
index 0000000000000000000000000000000000000000..808c51d0afdf564321abcd46a5a7d9595c5472da
--- /dev/null
+++ b/drivers/iio/dac/mcp47feb02-i2c.c
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * IIO driver for MCP47FEB02 Multi-Channel DAC with I2C interface
+ *
+ * Copyright (C) 2026 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Ariana Lazar <ariana.lazar@microchip.com>
+ *
+ * Datasheet links for devices with I2C interface:
+ * [MCP47FEBxx] https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005375A.pdf
+ * [MCP47FVBxx] https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005405A.pdf
+ * [MCP47FxBx4/8] https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP47FXBX48-Data-Sheet-DS200006368A.pdf
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+
+#include "mcp47feb02.h"
+
+/* Parts with EEPROM memory */
+MCP47FEB02_CHIP_INFO(mcp47feb01, 1, 8, false, true);
+MCP47FEB02_CHIP_INFO(mcp47feb02, 2, 8, false, true);
+MCP47FEB02_CHIP_INFO(mcp47feb04, 4, 8, true, true);
+MCP47FEB02_CHIP_INFO(mcp47feb08, 8, 8, true, true);
+MCP47FEB02_CHIP_INFO(mcp47feb11, 1, 10, false, true);
+MCP47FEB02_CHIP_INFO(mcp47feb12, 2, 10, false, true);
+MCP47FEB02_CHIP_INFO(mcp47feb14, 4, 10, true, true);
+MCP47FEB02_CHIP_INFO(mcp47feb18, 8, 10, true, true);
+MCP47FEB02_CHIP_INFO(mcp47feb21, 1, 12, false, true);
+MCP47FEB02_CHIP_INFO(mcp47feb22, 2, 12, false, true);
+MCP47FEB02_CHIP_INFO(mcp47feb24, 4, 12, true, true);
+MCP47FEB02_CHIP_INFO(mcp47feb28, 8, 12, true, true);
+
+/* Parts without EEPROM memory */
+MCP47FEB02_CHIP_INFO(mcp47fvb01, 1, 8, false, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb02, 2, 8, false, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb04, 4, 8, true, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb08, 8, 8, true, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb11, 1, 10, false, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb12, 2, 10, false, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb14, 4, 10, true, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb18, 8, 10, true, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb21, 1, 12, false, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb22, 2, 12, false, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb24, 4, 12, true, false);
+MCP47FEB02_CHIP_INFO(mcp47fvb28, 8, 12, true, false);
+
+static int mcp47feb02_i2c_probe(struct i2c_client *client)
+{
+ const struct mcp47feb02_features *chip_features;
+ struct device *dev = &client->dev;
+ struct regmap *regmap;
+
+ chip_features = i2c_get_match_data(client);
+ if (!chip_features)
+ return -EINVAL;
+
+ if (chip_features->have_eeprom)
+ regmap = devm_regmap_init_i2c(client, &mcp47feb02_regmap_config);
+ else
+ regmap = devm_regmap_init_i2c(client, &mcp47fvb02_regmap_config);
+
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing I2C regmap\n");
+
+ return mcp47feb02_common_probe(chip_features, regmap);
+}
+
+static const struct i2c_device_id mcp47feb02_i2c_id[] = {
+ { "mcp47feb01", (kernel_ulong_t)&mcp47feb01_chip_features },
+ { "mcp47feb02", (kernel_ulong_t)&mcp47feb02_chip_features },
+ { "mcp47feb04", (kernel_ulong_t)&mcp47feb04_chip_features },
+ { "mcp47feb08", (kernel_ulong_t)&mcp47feb08_chip_features },
+ { "mcp47feb11", (kernel_ulong_t)&mcp47feb11_chip_features },
+ { "mcp47feb12", (kernel_ulong_t)&mcp47feb12_chip_features },
+ { "mcp47feb14", (kernel_ulong_t)&mcp47feb14_chip_features },
+ { "mcp47feb18", (kernel_ulong_t)&mcp47feb18_chip_features },
+ { "mcp47feb21", (kernel_ulong_t)&mcp47feb21_chip_features },
+ { "mcp47feb22", (kernel_ulong_t)&mcp47feb22_chip_features },
+ { "mcp47feb24", (kernel_ulong_t)&mcp47feb24_chip_features },
+ { "mcp47feb28", (kernel_ulong_t)&mcp47feb28_chip_features },
+ { "mcp47fvb01", (kernel_ulong_t)&mcp47fvb01_chip_features },
+ { "mcp47fvb02", (kernel_ulong_t)&mcp47fvb02_chip_features },
+ { "mcp47fvb04", (kernel_ulong_t)&mcp47fvb04_chip_features },
+ { "mcp47fvb08", (kernel_ulong_t)&mcp47fvb08_chip_features },
+ { "mcp47fvb11", (kernel_ulong_t)&mcp47fvb11_chip_features },
+ { "mcp47fvb12", (kernel_ulong_t)&mcp47fvb12_chip_features },
+ { "mcp47fvb14", (kernel_ulong_t)&mcp47fvb14_chip_features },
+ { "mcp47fvb18", (kernel_ulong_t)&mcp47fvb18_chip_features },
+ { "mcp47fvb21", (kernel_ulong_t)&mcp47fvb21_chip_features },
+ { "mcp47fvb22", (kernel_ulong_t)&mcp47fvb22_chip_features },
+ { "mcp47fvb24", (kernel_ulong_t)&mcp47fvb24_chip_features },
+ { "mcp47fvb28", (kernel_ulong_t)&mcp47fvb28_chip_features },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, mcp47feb02_i2c_id);
+
+static const struct of_device_id mcp47feb02_of_i2c_match[] = {
+ { .compatible = "microchip,mcp47feb01", .data = &mcp47feb01_chip_features },
+ { .compatible = "microchip,mcp47feb02", .data = &mcp47feb02_chip_features },
+ { .compatible = "microchip,mcp47feb04", .data = &mcp47feb04_chip_features },
+ { .compatible = "microchip,mcp47feb08", .data = &mcp47feb08_chip_features },
+ { .compatible = "microchip,mcp47feb11", .data = &mcp47feb11_chip_features },
+ { .compatible = "microchip,mcp47feb12", .data = &mcp47feb12_chip_features },
+ { .compatible = "microchip,mcp47feb14", .data = &mcp47feb14_chip_features },
+ { .compatible = "microchip,mcp47feb18", .data = &mcp47feb18_chip_features },
+ { .compatible = "microchip,mcp47feb21", .data = &mcp47feb21_chip_features },
+ { .compatible = "microchip,mcp47feb22", .data = &mcp47feb22_chip_features },
+ { .compatible = "microchip,mcp47feb24", .data = &mcp47feb24_chip_features },
+ { .compatible = "microchip,mcp47feb28", .data = &mcp47feb28_chip_features },
+ { .compatible = "microchip,mcp47fvb01", .data = &mcp47fvb01_chip_features },
+ { .compatible = "microchip,mcp47fvb02", .data = &mcp47fvb02_chip_features },
+ { .compatible = "microchip,mcp47fvb04", .data = &mcp47fvb04_chip_features },
+ { .compatible = "microchip,mcp47fvb08", .data = &mcp47fvb08_chip_features },
+ { .compatible = "microchip,mcp47fvb11", .data = &mcp47fvb11_chip_features },
+ { .compatible = "microchip,mcp47fvb12", .data = &mcp47fvb12_chip_features },
+ { .compatible = "microchip,mcp47fvb14", .data = &mcp47fvb14_chip_features },
+ { .compatible = "microchip,mcp47fvb18", .data = &mcp47fvb18_chip_features },
+ { .compatible = "microchip,mcp47fvb21", .data = &mcp47fvb21_chip_features },
+ { .compatible = "microchip,mcp47fvb22", .data = &mcp47fvb22_chip_features },
+ { .compatible = "microchip,mcp47fvb24", .data = &mcp47fvb24_chip_features },
+ { .compatible = "microchip,mcp47fvb28", .data = &mcp47fvb28_chip_features },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mcp47feb02_of_i2c_match);
+
+static struct i2c_driver mcp47feb02_i2c_driver = {
+ .driver = {
+ .name = "mcp47feb02",
+ .of_match_table = mcp47feb02_of_i2c_match,
+ .pm = pm_sleep_ptr(&mcp47feb02_pm_ops),
+ },
+ .probe = mcp47feb02_i2c_probe,
+ .id_table = mcp47feb02_i2c_id,
+};
+module_i2c_driver(mcp47feb02_i2c_driver);
+
+MODULE_AUTHOR("Ariana Lazar <ariana.lazar@microchip.com>");
+MODULE_DESCRIPTION("IIO driver for MCP47FEB02 Multi-Channel DAC with I2C interface");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_MCP47FEB02");
diff --git a/drivers/iio/dac/mcp47feb02.h b/drivers/iio/dac/mcp47feb02.h
new file mode 100644
index 0000000000000000000000000000000000000000..7dbf157d7d6dcfeda7e47141ad447dfa0a79fd51
--- /dev/null
+++ b/drivers/iio/dac/mcp47feb02.h
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef __DRIVERS_IIO_DAC_MCP47FEB02_H__
+#define __DRIVERS_IIO_DAC_MCP47FEB02_H__
+
+#include <linux/bitops.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#include <linux/iio/iio.h>
+
+/* Register addresses must be left shifted with 3 positions in order to append command mask */
+#define MCP47FEB02_DAC0_REG_ADDR 0x00
+#define MCP47FEB02_VREF_REG_ADDR 0x40
+#define MCP47FEB02_POWER_DOWN_REG_ADDR 0x48
+#define MCP47FEB02_DAC_CTRL_MASK GENMASK(1, 0)
+
+#define MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR 0x50
+#define MCP47FEB02_GAIN_BIT_MASK BIT(0)
+#define MCP47FEB02_GAIN_BIT_STATUS_EEWA_MASK BIT(6)
+#define MCP47FEB02_GAIN_BITS_MASK GENMASK(15, 8)
+
+#define MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR 0x58
+
+#define MCP47FEB02_NV_DAC0_REG_ADDR 0x80
+#define MCP47FEB02_NV_VREF_REG_ADDR 0xC0
+#define MCP47FEB02_NV_POWER_DOWN_REG_ADDR 0xC8
+#define MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR 0xD0
+#define MCP47FEB02_NV_I2C_SLAVE_ADDR_MASK GENMASK(7, 0)
+
+/* Voltage reference, Power-Down control register and DAC Wiperlock status register fields */
+#define DAC_CTRL_MASK(ch) (GENMASK(1, 0) << (2 * (ch)))
+#define DAC_CTRL_VAL(ch, val) ((val) << (2 * (ch)))
+
+/* Gain Control and I2C Slave Address Reguster fields */
+#define DAC_GAIN_MASK(ch) (BIT(0) << (8 + (ch)))
+#define DAC_GAIN_VAL(ch, val) ((val) << (8 + (ch)))
+
+#define REG_ADDR(reg) ((reg) << 3)
+#define NV_REG_ADDR(reg) ((NV_DAC_ADDR_OFFSET + (reg)) << 3)
+#define READFLAG_MASK GENMASK(2, 1)
+
+#define MCP47FEB02_MAX_CH 8
+#define MCP47FEB02_MAX_SCALES_CH 3
+#define MCP47FEB02_DAC_WIPER_UNLOCKED 0
+#define MCP47FEB02_NORMAL_OPERATION 0
+#define MCP47FEB02_INTERNAL_BAND_GAP_uV 2440000
+#define NV_DAC_ADDR_OFFSET 0x10
+
+/* Macro used for generating chip features structures */
+#define MCP47FEB02_CHIP_INFO(_name, _channels, _res, _vref1, _eeprom) \
+static const struct mcp47feb02_features _name##_chip_features = { \
+ .name = #_name, \
+ .phys_channels = _channels, \
+ .resolution = _res, \
+ .have_ext_vref1 = _vref1, \
+ .have_eeprom = _eeprom, \
+}
+
+enum mcp47feb02_vref_mode {
+ MCP47FEB02_VREF_VDD = 0,
+ MCP47FEB02_INTERNAL_BAND_GAP = 1,
+ MCP47FEB02_EXTERNAL_VREF_UNBUFFERED = 2,
+ MCP47FEB02_EXTERNAL_VREF_BUFFERED = 3,
+};
+
+enum mcp47feb02_scale {
+ MCP47FEB02_SCALE_VDD = 0,
+ MCP47FEB02_SCALE_GAIN_X1 = 1,
+ MCP47FEB02_SCALE_GAIN_X2 = 2,
+};
+
+enum mcp47feb02_gain_bit_mode {
+ MCP47FEB02_GAIN_BIT_X1 = 0,
+ MCP47FEB02_GAIN_BIT_X2 = 1,
+};
+
+extern const char * const mcp47feb02_powerdown_modes[];
+
+/**
+ * struct mcp47feb02_features - chip specific data
+ * @name: device name
+ * @phys_channels: number of hardware channels
+ * @resolution: DAC resolution
+ * @have_ext_vref1: does the hardware have an the second external voltage reference?
+ * @have_eeprom: does the hardware have an internal eeprom?
+ */
+struct mcp47feb02_features {
+ const char *name;
+ unsigned int phys_channels;
+ unsigned int resolution;
+ bool have_ext_vref1;
+ bool have_eeprom;
+};
+
+/**
+ * struct mcp47feb02_channel_data - channel configuration
+ * @ref_mode: chosen voltage for reference
+ * @use_2x_gain: output driver gain control
+ * @powerdown: is false if the channel is in normal operation mode
+ * @powerdown_mode: selected power-down mode
+ * @dac_data: dac value
+ */
+struct mcp47feb02_channel_data {
+ u8 ref_mode;
+ bool use_2x_gain;
+ bool powerdown;
+ u8 powerdown_mode;
+ u16 dac_data;
+};
+
+/**
+ * struct mcp47feb02_data - chip configuration
+ * @chdata: options configured for each channel on the device
+ * @lock: prevents concurrent reads/writes to driver's state members
+ * @chip_features: pointer to features struct
+ * @scale_1: scales set on channels that are based on Vref1
+ * @scale: scales set on channels that are based on Vref/Vref0
+ * @active_channels_mask: enabled channels
+ * @regmap: regmap for directly accessing device register
+ * @labels: table with channels labels
+ * @phys_channels: physical channels on the device
+ * @vref1_buffered: Vref1 buffer is enabled
+ * @vref_buffered: Vref/Vref0 buffer is enabled
+ * @use_vref1: vref1-supply is defined
+ * @use_vref: vref-supply is defined
+ */
+struct mcp47feb02_data {
+ struct mcp47feb02_channel_data chdata[MCP47FEB02_MAX_CH];
+ struct mutex lock; /* prevents concurrent reads/writes to driver's state members */
+ const struct mcp47feb02_features *chip_features;
+ int scale_1[2 * MCP47FEB02_MAX_SCALES_CH];
+ int scale[2 * MCP47FEB02_MAX_SCALES_CH];
+ unsigned long active_channels_mask;
+ struct regmap *regmap;
+ const char *labels[MCP47FEB02_MAX_CH];
+ u16 phys_channels;
+ bool vref1_buffered;
+ bool vref_buffered;
+ bool use_vref1;
+ bool use_vref;
+};
+
+extern const struct regmap_config mcp47feb02_regmap_config;
+extern const struct regmap_config mcp47fvb02_regmap_config;
+
+/* Properties shared by I2C and SPI families */
+int mcp47feb02_common_probe(const struct mcp47feb02_features *chip_features, struct regmap *regmap);
+
+extern const struct dev_pm_ops mcp47feb02_pm_ops;
+
+#endif /* __DRIVERS_IIO_DAC_MCP47FEB02_H__ */
+
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI
2026-07-23 13:43 [PATCH 0/3] Refactor Microchip MCP47FEB02 I2C driver in separate modules to add support for MCP48FEB02 SPI driver Ariana Lazar
2026-07-23 13:43 ` [PATCH 1/3] iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules Ariana Lazar
@ 2026-07-23 13:43 ` Ariana Lazar
2026-07-23 13:50 ` sashiko-bot
2026-07-23 16:38 ` Conor Dooley
2026-07-23 13:43 ` [PATCH 3/3] iio: dac: add support for Microchip MCP48FEB02 Ariana Lazar
2 siblings, 2 replies; 9+ messages in thread
From: Ariana Lazar @ 2026-07-23 13:43 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-iio, devicetree, Ariana Lazar
Add the SPI MCP48FxBy1/2/4/8 part numbers, the spi-max-frequency property
and a devicetree example for SPI usage to the existing binding.
Signed-off-by: Ariana Lazar <ariana.lazar@microchip.com>
---
.../bindings/iio/dac/microchip,mcp47feb02.yaml | 244 +++++++++++++++++----
1 file changed, 197 insertions(+), 47 deletions(-)
diff --git a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
index d131f136bd15161666932261bcacd6d124b23ede..d25c763241a4f4b147e690213a26efa06282c7c0 100644
--- a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
@@ -4,58 +4,92 @@
$id: http://devicetree.org/schemas/iio/dac/microchip,mcp47feb02.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Microchip MCP47F(E/V)B(0/1/2)(1/2/4/8) DAC with I2C Interface Families
+title: Microchip MCP4(7/8)F(E/V)B(0/1/2)(1/2/4/8) DAC with I2C/SPI Interface Families
maintainers:
- Ariana Lazar <ariana.lazar@microchip.com>
description: |
- Datasheet for MCP47FEB01, MCP47FEB11, MCP47FEB21, MCP47FEB02, MCP47FEB12,
- MCP47FEB22 can be found here:
- https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005375A.pdf
- Datasheet for MCP47FVB01, MCP47FVB11, MCP47FVB21, MCP47FVB02, MCP47FVB12,
- MCP47FVB22 can be found here:
- https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005405A.pdf
- Datasheet for MCP47FEB04, MCP47FEB14, MCP47FEB24, MCP47FEB08, MCP47FEB18,
- MCP47FEB28, MCP47FVB04, MCP47FVB14, MCP47FVB24, MCP47FVB08, MCP47FVB18,
- MCP47FVB28 can be found here:
- https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP47FXBX48-Data-Sheet-DS200006368A.pdf
-
- +------------+--------------+-------------+-------------+------------+
- | Device | Resolution | Channels | Vref number | Memory |
- |------------|--------------|-------------|-------------|------------|
- | MCP47FEB01 | 8-bit | 1 | 1 | EEPROM |
- | MCP47FEB11 | 10-bit | 1 | 1 | EEPROM |
- | MCP47FEB21 | 12-bit | 1 | 1 | EEPROM |
- |------------|--------------|-------------|-------------|------------|
- | MCP47FEB02 | 8-bit | 2 | 1 | EEPROM |
- | MCP47FEB12 | 10-bit | 2 | 1 | EEPROM |
- | MCP47FEB22 | 12-bit | 2 | 1 | EEPROM |
- |------------|--------------|-------------|-------------|------------|
- | MCP47FVB01 | 8-bit | 1 | 1 | RAM |
- | MCP47FVB11 | 10-bit | 1 | 1 | RAM |
- | MCP47FVB21 | 12-bit | 1 | 1 | RAM |
- |------------|--------------|-------------|-------------|------------|
- | MCP47FVB02 | 8-bit | 2 | 1 | RAM |
- | MCP47FVB12 | 10-bit | 2 | 1 | RAM |
- | MCP47FVB22 | 12-bit | 2 | 1 | RAM |
- |------------|--------------|-------------|-------------|------------|
- | MCP47FVB04 | 8-bit | 4 | 2 | RAM |
- | MCP47FVB14 | 10-bit | 4 | 2 | RAM |
- | MCP47FVB24 | 12-bit | 4 | 2 | RAM |
- |------------|--------------|-------------|-------------|------------|
- | MCP47FVB08 | 8-bit | 8 | 2 | RAM |
- | MCP47FVB18 | 10-bit | 8 | 2 | RAM |
- | MCP47FVB28 | 12-bit | 8 | 2 | RAM |
- |------------|--------------|-------------|-------------|------------|
- | MCP47FEB04 | 8-bit | 4 | 2 | EEPROM |
- | MCP47FEB14 | 10-bit | 4 | 2 | EEPROM |
- | MCP47FEB24 | 12-bit | 4 | 2 | EEPROM |
- |------------|--------------|-------------|-------------|------------|
- | MCP47FEB08 | 8-bit | 8 | 2 | EEPROM |
- | MCP47FEB18 | 10-bit | 8 | 2 | EEPROM |
- | MCP47FEB28 | 12-bit | 8 | 2 | EEPROM |
- +------------+--------------+-------------+-------------+------------+
+ Datasheets for MCP47F(E/V)B(0/1/2)(1/2/4/8) DAC with I2C Interface Families:
+ Datasheet for MCP47FEB01, MCP47FEB11, MCP47FEB21, MCP47FEB02, MCP47FEB12,
+ MCP47FEB22 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005375A.pdf
+ Datasheet for MCP47FVB01, MCP47FVB11, MCP47FVB21, MCP47FVB02, MCP47FVB12,
+ MCP47FVB22 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005405A.pdf
+ Datasheet for MCP47FEB04, MCP47FEB14, MCP47FEB24, MCP47FEB08, MCP47FEB18,
+ MCP47FEB28, MCP47FVB04, MCP47FVB14, MCP47FVB24, MCP47FVB08, MCP47FVB18,
+ MCP47FVB28 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP47FXBX48-Data-Sheet-DS200006368A.pdf
+ Datasheets for MCP48F(E/V)B(0/1/2)(1/2/4/8) DAC with SPI Interface Families:
+ Datasheet for MCP48FEB01, MCP48FEB02, MCP48FEB11, MCP48FEB12, MCP48FEB21,
+ MCP48FEB22 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005429B.pdf
+ Datasheet for MCP48FVB01, MCP48FVB02, MCP48FVB11, MCP48FVB12, MCP48FVB21,
+ MCP48FVB22 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005466A.pdf
+ Datasheet for MCP48FEB04, MCP48FEB14, MCP48FEB24, MCP48FEB08, MCP48FEB18,
+ MCP48FEB28, MCP48FVB04, MCP48FVB14, MCP48FVB24, MCP48FVB08, MCP48FVB18,
+ MCP48FVB28 can be found here:
+ https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP48FXBX4-8-Family-Data-Sheet-DS20006362A.pdf
+
+ +------------+--------------+-------------+-------------+------------+------------+
+ | Device | Resolution | Channels | Vref number | Memory | Interface |
+ |------------|--------------|-------------|-------------|------------|------------|
+ | MCP47FEB01 | | 1 | 1 | EEPROM | I2C |
+ | MCP47FEB02 | | 2 | 1 | EEPROM | I2C |
+ | MCP47FEB04 | | 4 | 2 | EEPROM | I2C |
+ | MCP47FEB08 | 8-bit | 8 | 2 | EEPROM | I2C |
+ | MCP48FEB01 | | 1 | 1 | EEPROM | SPI |
+ | MCP48FEB02 | | 2 | 1 | EEPROM | SPI |
+ | MCP48FEB04 | | 4 | 2 | EEPROM | SPI |
+ | MCP48FEB08 | | 8 | 2 | EEPROM | SPI |
+ |------------|--------------|-------------|-------------|------------|------------|
+ | MCP47FEB11 | | 1 | 1 | EEPROM | I2C |
+ | MCP47FEB12 | | 2 | 1 | EEPROM | I2C |
+ | MCP47FEB14 | | 4 | 2 | EEPROM | I2C |
+ | MCP47FEB18 | 10-bit | 8 | 2 | EEPROM | I2C |
+ | MCP48FEB11 | | 1 | 1 | EEPROM | SPI |
+ | MCP48FEB12 | | 2 | 1 | EEPROM | SPI |
+ | MCP48FEB14 | | 4 | 2 | EEPROM | SPI |
+ | MCP48FEB18 | | 8 | 2 | EEPROM | SPI |
+ |------------|--------------|-------------|-------------|------------|------------|
+ | MCP47FEB21 | | 1 | 1 | EEPROM | I2C |
+ | MCP47FEB22 | | 2 | 1 | EEPROM | I2C |
+ | MCP47FEB24 | | 4 | 2 | EEPROM | I2C |
+ | MCP47FEB28 | 12-bit | 8 | 2 | EEPROM | I2C |
+ | MCP48FEB21 | | 1 | 1 | EEPROM | SPI |
+ | MCP48FEB22 | | 2 | 1 | EEPROM | SPI |
+ | MCP48FEB24 | | 4 | 2 | EEPROM | SPI |
+ | MCP48FEB28 | | 8 | 2 | EEPROM | SPI |
+ |------------|--------------|-------------|-------------|------------|------------|
+ | MCP47FVB01 | | 1 | 1 | RAM | I2C |
+ | MCP47FVB02 | | 2 | 1 | RAM | I2C |
+ | MCP47FVB04 | | 4 | 2 | RAM | I2C |
+ | MCP47FVB08 | 8-bit | 8 | 2 | RAM | I2C |
+ | MCP48FVB01 | | 1 | 1 | RAM | SPI |
+ | MCP48FVB02 | | 2 | 1 | RAM | SPI |
+ | MCP48FVB04 | | 4 | 2 | RAM | SPI |
+ | MCP48FVB08 | | 8 | 2 | RAM | SPI |
+ |------------|--------------|-------------|-------------|------------|------------|
+ | MCP47FVB11 | | 1 | 1 | RAM | I2C |
+ | MCP47FVB12 | | 2 | 1 | RAM | I2C |
+ | MCP47FVB14 | | 4 | 2 | RAM | I2C |
+ | MCP47FVB18 | 10-bit | 8 | 2 | RAM | I2C |
+ | MCP48FVB11 | | 1 | 1 | RAM | SPI |
+ | MCP48FVB12 | | 2 | 1 | RAM | SPI |
+ | MCP48FVB14 | | 4 | 2 | RAM | SPI |
+ | MCP48FVB18 | | 8 | 2 | RAM | SPI |
+ |------------|--------------|-------------|-------------|------------|------------|
+ | MCP47FVB21 | | 1 | 1 | RAM | I2C |
+ | MCP47FVB22 | | 2 | 1 | RAM | I2C |
+ | MCP47FVB24 | | 4 | 2 | RAM | I2C |
+ | MCP47FVB28 | 12-bit | 8 | 2 | RAM | I2C |
+ | MCP48FVB21 | | 1 | 1 | RAM | SPI |
+ | MCP48FVB22 | | 2 | 1 | RAM | SPI |
+ | MCP48FVB24 | | 4 | 2 | RAM | SPI |
+ | MCP48FVB28 | | 8 | 2 | RAM | SPI |
+ +------------+--------------+-------------+-------------+------------+------------+
properties:
compatible:
@@ -84,10 +118,37 @@ properties:
- microchip,mcp47feb08
- microchip,mcp47feb18
- microchip,mcp47feb28
+ - microchip,mcp48feb01
+ - microchip,mcp48feb02
+ - microchip,mcp48feb04
+ - microchip,mcp48feb08
+ - microchip,mcp48feb11
+ - microchip,mcp48feb12
+ - microchip,mcp48feb14
+ - microchip,mcp48feb18
+ - microchip,mcp48feb21
+ - microchip,mcp48feb22
+ - microchip,mcp48feb24
+ - microchip,mcp48feb28
+ - microchip,mcp48fvb01
+ - microchip,mcp48fvb02
+ - microchip,mcp48fvb04
+ - microchip,mcp48fvb08
+ - microchip,mcp48fvb11
+ - microchip,mcp48fvb12
+ - microchip,mcp48fvb14
+ - microchip,mcp48fvb18
+ - microchip,mcp48fvb21
+ - microchip,mcp48fvb22
+ - microchip,mcp48fvb24
+ - microchip,mcp48fvb28
reg:
maxItems: 1
+ spi-max-frequency:
+ maximum: 10000000
+
"#address-cells":
const: 1
@@ -178,6 +239,13 @@ required:
- vdd-supply
allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ pattern: "^microchip,mcp48f[ev]b[0-2][1248]$"
+ then:
+ $ref: /schemas/spi/spi-peripheral-props.yaml#
- if:
properties:
compatible:
@@ -189,6 +257,12 @@ allOf:
- microchip,mcp47fvb01
- microchip,mcp47fvb11
- microchip,mcp47fvb21
+ - microchip,mcp48feb01
+ - microchip,mcp48feb11
+ - microchip,mcp48feb21
+ - microchip,mcp48fvb01
+ - microchip,mcp48fvb11
+ - microchip,mcp48fvb21
then:
properties:
lat1-gpios: false
@@ -211,6 +285,12 @@ allOf:
- microchip,mcp47fvb02
- microchip,mcp47fvb12
- microchip,mcp47fvb22
+ - microchip,mcp48feb02
+ - microchip,mcp48feb12
+ - microchip,mcp48feb22
+ - microchip,mcp48fvb02
+ - microchip,mcp48fvb12
+ - microchip,mcp48fvb22
then:
properties:
lat1-gpios: false
@@ -233,6 +313,12 @@ allOf:
- microchip,mcp47feb04
- microchip,mcp47feb14
- microchip,mcp47feb24
+ - microchip,mcp48feb04
+ - microchip,mcp48feb14
+ - microchip,mcp48feb24
+ - microchip,mcp48fvb04
+ - microchip,mcp48fvb14
+ - microchip,mcp48fvb24
then:
patternProperties:
"^channel@[0-3]$":
@@ -251,6 +337,12 @@ allOf:
- microchip,mcp47feb08
- microchip,mcp47feb18
- microchip,mcp47feb28
+ - microchip,mcp48feb08
+ - microchip,mcp48feb18
+ - microchip,mcp48feb28
+ - microchip,mcp48fvb08
+ - microchip,mcp48fvb18
+ - microchip,mcp48fvb28
then:
patternProperties:
"^channel@[0-7]$":
@@ -272,6 +364,39 @@ allOf:
properties:
microchip,vref1-buffered: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - microchip,mcp47feb01
+ - microchip,mcp47feb02
+ - microchip,mcp47feb04
+ - microchip,mcp47feb08
+ - microchip,mcp47feb11
+ - microchip,mcp47feb12
+ - microchip,mcp47feb14
+ - microchip,mcp47feb18
+ - microchip,mcp47feb21
+ - microchip,mcp47feb22
+ - microchip,mcp47feb24
+ - microchip,mcp47feb28
+ - microchip,mcp47fvb01
+ - microchip,mcp47fvb02
+ - microchip,mcp47fvb04
+ - microchip,mcp47fvb08
+ - microchip,mcp47fvb11
+ - microchip,mcp47fvb12
+ - microchip,mcp47fvb14
+ - microchip,mcp47fvb18
+ - microchip,mcp47fvb21
+ - microchip,mcp47fvb22
+ - microchip,mcp47fvb24
+ - microchip,mcp47fvb28
+ then:
+ properties:
+ spi-max-frequency: false
+
additionalProperties: false
examples:
@@ -299,4 +424,29 @@ examples:
};
};
};
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@60 {
+ compatible = "microchip,mcp48feb02";
+ reg = <0x60>;
+ vdd-supply = <&vdac_vdd>;
+ vref-supply = <&vref_reg>;
+ spi-max-frequency = <10000000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ channel@0 {
+ reg = <0>;
+ label = "Adjustable_voltage_ch0";
+ };
+
+ channel@1 {
+ reg = <0x1>;
+ label = "Adjustable_voltage_ch1";
+ };
+ };
+ };
...
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/3] iio: dac: add support for Microchip MCP48FEB02
2026-07-23 13:43 [PATCH 0/3] Refactor Microchip MCP47FEB02 I2C driver in separate modules to add support for MCP48FEB02 SPI driver Ariana Lazar
2026-07-23 13:43 ` [PATCH 1/3] iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules Ariana Lazar
2026-07-23 13:43 ` [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI Ariana Lazar
@ 2026-07-23 13:43 ` Ariana Lazar
2026-07-23 14:03 ` sashiko-bot
2 siblings, 1 reply; 9+ messages in thread
From: Ariana Lazar @ 2026-07-23 13:43 UTC (permalink / raw)
To: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: linux-kernel, linux-iio, devicetree, Ariana Lazar
This is the iio driver for Microchip MCP48FxBy1/2/4/8 series of
buffered voltage output Digital-to-Analog Converters with nonvolatile or
volatile memory and an SPI Interface.
The families support up to 8 output channels.
The devices can be 8-bit, 10-bit and 12-bit.
Signed-off-by: Ariana Lazar <ariana.lazar@microchip.com>
---
MAINTAINERS | 1 +
drivers/iio/dac/Kconfig | 23 ++++++
drivers/iio/dac/Makefile | 1 +
drivers/iio/dac/mcp47feb02-spi.c | 146 +++++++++++++++++++++++++++++++++++++++
4 files changed, 171 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index fc87609865f26a9f484edc42058f7df659a0fa4f..b2ffcc0161ba0d147df35558312cbf99052ed13e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16120,6 +16120,7 @@ S: Supported
F: Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
F: drivers/iio/dac/mcp47feb02-core.c
F: drivers/iio/dac/mcp47feb02-i2c.c
+F: drivers/iio/dac/mcp47feb02-spi.c
F: drivers/iio/dac/mcp47feb02.h
MCP4821 DAC DRIVER
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index cc10d43ffd1e89bbf945ef89ea5af0abe1a91084..d941f78f7110b185fee6f025be829bae1e4534da 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -575,6 +575,29 @@ config MCP47FEB02_I2C
will be called mcp47feb02_i2c and you will also get
mcp47feb02_core for the core module.
+config MCP47FEB02_SPI
+ tristate "MCP48F(E/V)B01/02/04/08/11/12/14/18/21/22/24/28 SPI DAC driver"
+ depends on SPI
+ select REGMAP_SPI
+ select MCP47FEB02
+ help
+ Say yes here if you want to build the driver for the Microchip:
+ - 8-bit DAC:
+ MCP48FEB01, MCP48FEB02, MCP48FEB04, MCP48FEB08,
+ MCP48FVB01, MCP48FVB02, MCP48FVB04, MCP48FVB08
+ - 10-bit DAC:
+ MCP48FEB11, MCP48FEB12, MCP48FEB14, MCP48FEB18,
+ MCP48FVB11, MCP48FVB12, MCP48FVB14, MCP48FVB18
+ - 12-bit DAC:
+ MCP48FEB21, MCP48FEB22, MCP48FEB24, MCP48FEB28,
+ MCP48FVB21, MCP48FVB22, MCP48FVB24, MCP48FVB28
+ having 1 to 8 channels, 8/10/12-bit digital-to-analog converter
+ (DAC) with SPI interface.
+
+ To compile this driver as a module, choose M here: the module
+ will be called mcp47feb02_spi and you will also get
+ mcp47feb02_core for the core module.
+
config MCP4821
tristate "MCP4801/02/11/12/21/22 DAC driver"
depends on SPI
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 28c8646a987cff1ac4d693fe86898d66c901d5bd..9903198b934e8b66a4ea6562b662d8073ed9cc59 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -56,6 +56,7 @@ obj-$(CONFIG_MCP4725) += mcp4725.o
obj-$(CONFIG_MCP4728) += mcp4728.o
obj-$(CONFIG_MCP47FEB02) += mcp47feb02-core.o
obj-$(CONFIG_MCP47FEB02_I2C) += mcp47feb02-i2c.o
+obj-$(CONFIG_MCP47FEB02_SPI) += mcp47feb02-spi.o
obj-$(CONFIG_MCP4821) += mcp4821.o
obj-$(CONFIG_MCP4922) += mcp4922.o
obj-$(CONFIG_STM32_DAC_CORE) += stm32-dac-core.o
diff --git a/drivers/iio/dac/mcp47feb02-spi.c b/drivers/iio/dac/mcp47feb02-spi.c
new file mode 100644
index 0000000000000000000000000000000000000000..4395d49405dd818dac5a411257e84ca8bfd5deec
--- /dev/null
+++ b/drivers/iio/dac/mcp47feb02-spi.c
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * IIO driver for MCP48FEB02 Multi-Channel DAC with SPI interface
+ *
+ * Copyright (C) 2026 Microchip Technology Inc. and its subsidiaries
+ *
+ * Author: Ariana Lazar <ariana.lazar@microchip.com>
+ *
+ * Datasheet links for devices with SPI interface:
+ * [MCP48FEBxx] https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005429B.pdf
+ * [MCP48FVBxx] https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005466A.pdf
+ * [MCP48FxBx4/8] https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP48FXBX4-8-Family-Data-Sheet-DS20006362A.pdf
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/pm.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "mcp47feb02.h"
+
+/* Parts with EEPROM memory */
+MCP47FEB02_CHIP_INFO(mcp48feb01, 1, 8, false, true);
+MCP47FEB02_CHIP_INFO(mcp48feb02, 2, 8, false, true);
+MCP47FEB02_CHIP_INFO(mcp48feb04, 4, 8, true, true);
+MCP47FEB02_CHIP_INFO(mcp48feb08, 8, 8, true, true);
+MCP47FEB02_CHIP_INFO(mcp48feb11, 1, 10, false, true);
+MCP47FEB02_CHIP_INFO(mcp48feb12, 2, 10, false, true);
+MCP47FEB02_CHIP_INFO(mcp48feb14, 4, 10, true, true);
+MCP47FEB02_CHIP_INFO(mcp48feb18, 8, 10, true, true);
+MCP47FEB02_CHIP_INFO(mcp48feb21, 1, 12, false, true);
+MCP47FEB02_CHIP_INFO(mcp48feb22, 2, 12, false, true);
+MCP47FEB02_CHIP_INFO(mcp48feb24, 4, 12, true, true);
+MCP47FEB02_CHIP_INFO(mcp48feb28, 8, 12, true, true);
+
+/* Parts without EEPROM memory */
+MCP47FEB02_CHIP_INFO(mcp48fvb01, 1, 8, false, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb02, 2, 8, false, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb04, 4, 8, true, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb08, 8, 8, true, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb11, 1, 10, false, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb12, 2, 10, false, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb14, 4, 10, true, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb18, 8, 10, true, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb21, 1, 12, false, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb22, 2, 12, false, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb24, 4, 12, true, false);
+MCP47FEB02_CHIP_INFO(mcp48fvb28, 8, 12, true, false);
+
+static int mcp47feb02_spi_probe(struct spi_device *spi)
+{
+ const struct mcp47feb02_features *chip_features;
+ struct device *dev = &spi->dev;
+ struct regmap *regmap;
+
+ chip_features = spi_get_device_match_data(spi);
+ if (!chip_features)
+ return -EINVAL;
+
+ if (chip_features->have_eeprom)
+ regmap = devm_regmap_init_spi(spi, &mcp47feb02_regmap_config);
+ else
+ regmap = devm_regmap_init_spi(spi, &mcp47fvb02_regmap_config);
+
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing SPI regmap\n");
+
+ return mcp47feb02_common_probe(chip_features, regmap);
+}
+
+static const struct spi_device_id mcp47feb02_spi_id[] = {
+ { "mcp48feb01", (kernel_ulong_t)&mcp48feb01_chip_features },
+ { "mcp48feb02", (kernel_ulong_t)&mcp48feb02_chip_features },
+ { "mcp48feb04", (kernel_ulong_t)&mcp48feb04_chip_features },
+ { "mcp48feb08", (kernel_ulong_t)&mcp48feb08_chip_features },
+ { "mcp48feb11", (kernel_ulong_t)&mcp48feb11_chip_features },
+ { "mcp48feb12", (kernel_ulong_t)&mcp48feb12_chip_features },
+ { "mcp48feb14", (kernel_ulong_t)&mcp48feb14_chip_features },
+ { "mcp48feb18", (kernel_ulong_t)&mcp48feb18_chip_features },
+ { "mcp48feb21", (kernel_ulong_t)&mcp48feb21_chip_features },
+ { "mcp48feb22", (kernel_ulong_t)&mcp48feb22_chip_features },
+ { "mcp48feb24", (kernel_ulong_t)&mcp48feb24_chip_features },
+ { "mcp48feb28", (kernel_ulong_t)&mcp48feb28_chip_features },
+ { "mcp48fvb01", (kernel_ulong_t)&mcp48fvb01_chip_features },
+ { "mcp48fvb02", (kernel_ulong_t)&mcp48fvb02_chip_features },
+ { "mcp48fvb04", (kernel_ulong_t)&mcp48fvb04_chip_features },
+ { "mcp48fvb08", (kernel_ulong_t)&mcp48fvb08_chip_features },
+ { "mcp48fvb11", (kernel_ulong_t)&mcp48fvb11_chip_features },
+ { "mcp48fvb12", (kernel_ulong_t)&mcp48fvb12_chip_features },
+ { "mcp48fvb14", (kernel_ulong_t)&mcp48fvb14_chip_features },
+ { "mcp48fvb18", (kernel_ulong_t)&mcp48fvb18_chip_features },
+ { "mcp48fvb21", (kernel_ulong_t)&mcp48fvb21_chip_features },
+ { "mcp48fvb22", (kernel_ulong_t)&mcp48fvb22_chip_features },
+ { "mcp48fvb24", (kernel_ulong_t)&mcp48fvb24_chip_features },
+ { "mcp48fvb28", (kernel_ulong_t)&mcp48fvb28_chip_features },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, mcp47feb02_spi_id);
+
+static const struct of_device_id mcp47feb02_of_spi_match[] = {
+ { .compatible = "microchip,mcp48feb01", .data = &mcp48feb01_chip_features },
+ { .compatible = "microchip,mcp48feb02", .data = &mcp48feb02_chip_features },
+ { .compatible = "microchip,mcp48feb04", .data = &mcp48feb04_chip_features },
+ { .compatible = "microchip,mcp48feb08", .data = &mcp48feb08_chip_features },
+ { .compatible = "microchip,mcp48feb11", .data = &mcp48feb11_chip_features },
+ { .compatible = "microchip,mcp48feb12", .data = &mcp48feb12_chip_features },
+ { .compatible = "microchip,mcp48feb14", .data = &mcp48feb14_chip_features },
+ { .compatible = "microchip,mcp48feb18", .data = &mcp48feb18_chip_features },
+ { .compatible = "microchip,mcp48feb21", .data = &mcp48feb21_chip_features },
+ { .compatible = "microchip,mcp48feb22", .data = &mcp48feb22_chip_features },
+ { .compatible = "microchip,mcp48feb24", .data = &mcp48feb24_chip_features },
+ { .compatible = "microchip,mcp48feb28", .data = &mcp48feb28_chip_features },
+ { .compatible = "microchip,mcp48fvb01", .data = &mcp48fvb01_chip_features },
+ { .compatible = "microchip,mcp48fvb02", .data = &mcp48fvb02_chip_features },
+ { .compatible = "microchip,mcp48fvb04", .data = &mcp48fvb04_chip_features },
+ { .compatible = "microchip,mcp48fvb08", .data = &mcp48fvb08_chip_features },
+ { .compatible = "microchip,mcp48fvb11", .data = &mcp48fvb11_chip_features },
+ { .compatible = "microchip,mcp48fvb12", .data = &mcp48fvb12_chip_features },
+ { .compatible = "microchip,mcp48fvb14", .data = &mcp48fvb14_chip_features },
+ { .compatible = "microchip,mcp48fvb18", .data = &mcp48fvb18_chip_features },
+ { .compatible = "microchip,mcp48fvb21", .data = &mcp48fvb21_chip_features },
+ { .compatible = "microchip,mcp48fvb22", .data = &mcp48fvb22_chip_features },
+ { .compatible = "microchip,mcp48fvb24", .data = &mcp48fvb24_chip_features },
+ { .compatible = "microchip,mcp48fvb28", .data = &mcp48fvb28_chip_features },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mcp47feb02_of_spi_match);
+
+static struct spi_driver mcp47feb02_spi_driver = {
+ .driver = {
+ .name = "mcp47feb02",
+ .of_match_table = mcp47feb02_of_spi_match,
+ .pm = pm_sleep_ptr(&mcp47feb02_pm_ops),
+ },
+ .probe = mcp47feb02_spi_probe,
+ .id_table = mcp47feb02_spi_id,
+};
+module_spi_driver(mcp47feb02_spi_driver);
+
+MODULE_AUTHOR("Ariana Lazar <ariana.lazar@microchip.com>");
+MODULE_DESCRIPTION("IIO driver for MCP48FEB02 Multi-Channel DAC with SPI interface");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_MCP47FEB02");
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI
2026-07-23 13:43 ` [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI Ariana Lazar
@ 2026-07-23 13:50 ` sashiko-bot
2026-07-23 16:36 ` Conor Dooley
2026-07-23 16:38 ` Conor Dooley
1 sibling, 1 reply; 9+ messages in thread
From: sashiko-bot @ 2026-07-23 13:50 UTC (permalink / raw)
To: Ariana Lazar; +Cc: conor+dt, devicetree, robh
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The schema retains `additionalProperties: false` at the root level while introducing a conditional `$ref` to `spi-peripheral-props.yaml` in the `allOf` block. This breaks schema validation for standard SPI properties.
- [Low] The newly added SPI device tree example uses an inappropriate SPI chip select value (`0x60`), copied from the I2C device address example.
--
--- Patch [2]: [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI ---
commit a357ffde05c7807cd64bca71103d780d8dde416b
Author: Ariana Lazar <ariana.lazar@microchip.com>
dt-bindings: iio: dac: add support for MCP48FEB02 SPI
This commit adds SPI support for the MCP48FxBy1/2/4/8 DAC families to the
existing MCP47FEB02 device tree binding. It introduces the new compatible
strings, the spi-max-frequency property, and a devicetree example for SPI.
> diff --git a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
> index d131f136bd151..d25c763241a4f 100644
> --- a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
> +++ b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
> @@ -178,6 +239,13 @@ required:
> - vdd-supply
>
> allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + pattern: "^microchip,mcp48f[ev]b[0-2][1248]$"
> + then:
> + $ref: /schemas/spi/spi-peripheral-props.yaml#
[ ... ]
> + then:
> + properties:
> + spi-max-frequency: false
> +
> additionalProperties: false
[Severity: Medium]
Since this schema now includes a conditional $ref to spi-peripheral-props.yaml
in the allOf block, should this be changed to unevaluatedProperties: false?
JSON Schema limits additionalProperties: false to only evaluating properties
explicitly declared in the root properties or patternProperties. Any standard
SPI properties pulled in via the conditional $ref will be incorrectly rejected
by dt_binding_check.
> examples:
> @@ -299,4 +424,29 @@ examples:
> };
> };
> };
> + - |
> + spi {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + dac@60 {
> + compatible = "microchip,mcp48feb02";
> + reg = <0x60>;
[Severity: Low]
Is 0x60 intended to be used as an SPI chip select here, or was this copied
from the I2C example?
Typically, an SPI chip select would be 0 or 1, and the node would be named
dac@0 with reg = <0>.
> + vdd-supply = <&vdac_vdd>;
> + vref-supply = <&vref_reg>;
> + spi-max-frequency = <10000000>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> + channel@0 {
> + reg = <0>;
> + label = "Adjustable_voltage_ch0";
> + };
> +
> + channel@1 {
> + reg = <0x1>;
> + label = "Adjustable_voltage_ch1";
> + };
> + };
> + };
> ...
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260723-mcp47feb02_refactor-v1-0-ee59e63672bc@microchip.com?part=2
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules
2026-07-23 13:43 ` [PATCH 1/3] iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules Ariana Lazar
@ 2026-07-23 14:01 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-07-23 14:01 UTC (permalink / raw)
To: Ariana Lazar; +Cc: devicetree, robh, conor+dt
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [Low] I2C Subsystem Guideline Violation: Positional Initializers
Pre-existing issues:
- [High] NULL Pointer Dereference in power management callbacks due to missing driver data
- [High] Hardware register corruption in `mcp47feb02_resume` due to a copy-paste error updating VREF
- [High] Resume path unconditionally overrides user's manual power-down configuration
--
--- Patch [1]: [PATCH 1/3] iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules ---
commit bb66896c21fa2d6229e950c6190b3d83baedb5ad
Author: Ariana Lazar <ariana.lazar@microchip.com>
iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules
This commit refactors the MCP47FEB02 driver into a core module and an
I2C-specific module to prepare for future SPI support. It separates the
bus-specific code from the common DAC functionality.
> diff --git a/drivers/iio/dac/mcp47feb02.c b/drivers/iio/dac/mcp47feb02-core.c
> similarity index 64%
> rename from drivers/iio/dac/mcp47feb02.c
> rename to drivers/iio/dac/mcp47feb02-core.c
> index a823c2a673a26..6c86fa40e6eb2 100644
> --- a/drivers/iio/dac/mcp47feb02.c
> +++ b/drivers/iio/dac/mcp47feb02-core.c
[ ... ]
> @@ -666,7 +357,7 @@ static ssize_t mcp47feb02_write_powerdown(struct iio_dev *indio_dev, uintptr_t p
> return len;
> }
>
> -static DEFINE_SIMPLE_DEV_PM_OPS(mcp47feb02_pm_ops, mcp47feb02_suspend, mcp47feb02_resume);
> +EXPORT_SIMPLE_DEV_PM_OPS(mcp47feb02_pm_ops, mcp47feb02_suspend, mcp47feb02_resume);
[Severity: High]
This is a pre-existing issue, but does mcp47feb02_resume() write pd_mode
to the VREF register instead of the expected reference mode?
Looking at mcp47feb02_resume() in the core module:
ret = regmap_update_bits(data->regmap, MCP47FEB02_VREF_REG_ADDR,
DAC_CTRL_MASK(ch), DAC_CTRL_VAL(ch, pd_mode));
This writes the power-down mode to the voltage reference register, leading
to incorrect analog output voltages upon system resume.
[Severity: High]
This isn't a bug introduced by this patch, but does mcp47feb02_resume()
also unconditionally clear the powerdown state and force normal operation?
Looking at mcp47feb02_resume() in the core module:
data->chdata[ch].powerdown = false;
This completely wipes out any explicit channel power-down state previously
configured by the user via sysfs.
[ ... ]
> @@ -1175,75 +857,7 @@ static int mcp47feb02_probe(struct i2c_client *client)
>
> return devm_iio_device_register(dev, indio_dev);
> }
[Severity: High]
This isn't a bug introduced by this patch, but does mcp47feb02_common_probe()
miss a call to dev_set_drvdata() before returning?
Without setting the driver data, dev_get_drvdata(dev) in
mcp47feb02_suspend() and mcp47feb02_resume() returns NULL:
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mcp47feb02_data *data = iio_priv(indio_dev);
This causes a NULL pointer dereference when passed to iio_priv() during
system power state transitions.
> diff --git a/drivers/iio/dac/mcp47feb02-i2c.c b/drivers/iio/dac/mcp47feb02-i2c.c
> new file mode 100644
> index 0000000000000..808c51d0afdf5
> --- /dev/null
> +++ b/drivers/iio/dac/mcp47feb02-i2c.c
[ ... ]
> +static const struct i2c_device_id mcp47feb02_i2c_id[] = {
> + { "mcp47feb01", (kernel_ulong_t)&mcp47feb01_chip_features },
> + { "mcp47feb02", (kernel_ulong_t)&mcp47feb02_chip_features },
[Severity: Low]
Does this array need to use named initializers to align with I2C subsystem
guidelines?
The refactored mcp47feb02_i2c_id array uses positional initializers,
dropping the named initializers present in the original code.
> + { "mcp47feb04", (kernel_ulong_t)&mcp47feb04_chip_features },
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260723-mcp47feb02_refactor-v1-0-ee59e63672bc@microchip.com?part=1
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] iio: dac: add support for Microchip MCP48FEB02
2026-07-23 13:43 ` [PATCH 3/3] iio: dac: add support for Microchip MCP48FEB02 Ariana Lazar
@ 2026-07-23 14:03 ` sashiko-bot
0 siblings, 0 replies; 9+ messages in thread
From: sashiko-bot @ 2026-07-23 14:03 UTC (permalink / raw)
To: Ariana Lazar; +Cc: devicetree, conor+dt, robh
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Missing initialization of driver data causes NULL pointer dereference in PM suspend/resume callbacks.
- [High] Lack of locking across the EEPROM snapshot sequence causes data corruption and inconsistent state saves.
--
--- Patch [3]: [PATCH 3/3] iio: dac: add support for Microchip MCP48FEB02 ---
commit 438874da57433396f6f194cc2238c897dfc234a2
Author: Ariana Lazar <ariana.lazar@microchip.com>
iio: dac: add support for Microchip MCP48FEB02
This is the iio driver for Microchip MCP48FxBy1/2/4/8 series of
buffered voltage output Digital-to-Analog Converters with nonvolatile or
volatile memory and an SPI Interface.
> diff --git a/drivers/iio/dac/mcp47feb02-spi.c b/drivers/iio/dac/mcp47feb02-spi.c
> new file mode 100644
> index 0000000000000..4395d49405dd8
> --- /dev/null
> +++ b/drivers/iio/dac/mcp47feb02-spi.c
[ ... ]
> +static int mcp47feb02_spi_probe(struct spi_device *spi)
> +{
[ ... ]
> + if (IS_ERR(regmap))
> + return dev_err_probe(dev, PTR_ERR(regmap), "Error initializing SPI regmap\n");
> +
> + return mcp47feb02_common_probe(chip_features, regmap);
> +}
[Severity: Critical]
This is a pre-existing issue, but since the new SPI driver uses
mcp47feb02_common_probe(), will this result in a NULL pointer dereference
during suspend and resume transitions?
Looking at mcp47feb02_common_probe() in the core driver, it allocates the IIO
device with devm_iio_device_alloc() but misses setting the driver data on the
parent device. Neither the I2C nor the new SPI probe explicitly calls
spi_set_drvdata() or dev_set_drvdata().
When the system undergoes PM suspend, mcp47feb02_suspend() runs:
drivers/iio/dac/mcp47feb02-core.c:mcp47feb02_suspend() {
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct mcp47feb02_data *data = iio_priv(indio_dev);
...
guard(mutex)(&data->lock);
...
}
Because the driver data is never set, dev_get_drvdata(dev) returns NULL.
Passing NULL to iio_priv() computes an invalid pointer for data, causing the
guard(mutex) call to dereference unmapped memory.
[Severity: High]
This is also a pre-existing issue in the core code, but could the lack of
locking across the EEPROM snapshot sequence cause data corruption?
In the sysfs attribute handler store_eeprom_store(), the driver loops over
channels to perform EEPROM writes:
drivers/iio/dac/mcp47feb02-core.c:store_eeprom_store() {
...
for_each_set_bit(i, &data->active_channels_mask, data->phys_channels) {
ret = mcp47feb02_write_to_eeprom(data, NV_REG_ADDR(i),
data->chdata[i].dac_data);
...
}
The function mcp47feb02_write_to_eeprom() acquires and releases data->lock
internally for each write. This leaves the overall loop sequence in
store_eeprom_store() unprotected.
Can a concurrent sysfs operation, such as mcp47feb02_write_raw(), alter the
channel software state and hardware registers in the middle of this loop?
This might lead to a torn or inconsistent state being persisted to the
non-volatile memory.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260723-mcp47feb02_refactor-v1-0-ee59e63672bc@microchip.com?part=3
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI
2026-07-23 13:50 ` sashiko-bot
@ 2026-07-23 16:36 ` Conor Dooley
0 siblings, 0 replies; 9+ messages in thread
From: Conor Dooley @ 2026-07-23 16:36 UTC (permalink / raw)
To: sashiko-reviews; +Cc: Ariana Lazar, conor+dt, devicetree, robh
[-- Attachment #1: Type: text/plain, Size: 3759 bytes --]
On Thu, Jul 23, 2026 at 01:50:59PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [Medium] The schema retains `additionalProperties: false` at the root level while introducing a conditional `$ref` to `spi-peripheral-props.yaml` in the `allOf` block. This breaks schema validation for standard SPI properties.
> - [Low] The newly added SPI device tree example uses an inappropriate SPI chip select value (`0x60`), copied from the I2C device address example.
> --
>
> --- Patch [2]: [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI ---
> commit a357ffde05c7807cd64bca71103d780d8dde416b
> Author: Ariana Lazar <ariana.lazar@microchip.com>
>
> dt-bindings: iio: dac: add support for MCP48FEB02 SPI
>
> This commit adds SPI support for the MCP48FxBy1/2/4/8 DAC families to the
> existing MCP47FEB02 device tree binding. It introduces the new compatible
> strings, the spi-max-frequency property, and a devicetree example for SPI.
>
> > diff --git a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
> > index d131f136bd151..d25c763241a4f 100644
> > --- a/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
> > +++ b/Documentation/devicetree/bindings/iio/dac/microchip,mcp47feb02.yaml
> > @@ -178,6 +239,13 @@ required:
> > - vdd-supply
> >
> > allOf:
> > + - if:
> > + properties:
> > + compatible:
> > + contains:
> > + pattern: "^microchip,mcp48f[ev]b[0-2][1248]$"
> > + then:
> > + $ref: /schemas/spi/spi-peripheral-props.yaml#
>
> [ ... ]
>
> > + then:
> > + properties:
> > + spi-max-frequency: false
> > +
> > additionalProperties: false
>
> [Severity: Medium]
> Since this schema now includes a conditional $ref to spi-peripheral-props.yaml
> in the allOf block, should this be changed to unevaluatedProperties: false?
>
> JSON Schema limits additionalProperties: false to only evaluating properties
> explicitly declared in the root properties or patternProperties. Any standard
> SPI properties pulled in via the conditional $ref will be incorrectly rejected
> by dt_binding_check.
This trips up Sashiko a lot.
This additionalProperties is fine if spi-max-frequency is the only
property from that binding that this device uses.
>
> > examples:
> > @@ -299,4 +424,29 @@ examples:
> > };
> > };
> > };
> > + - |
> > + spi {
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > +
> > + dac@60 {
> > + compatible = "microchip,mcp48feb02";
> > + reg = <0x60>;
>
> [Severity: Low]
> Is 0x60 intended to be used as an SPI chip select here, or was this copied
> from the I2C example?
>
> Typically, an SPI chip select would be 0 or 1, and the node would be named
> dac@0 with reg = <0>.
It's an example, so it doesn't matter. But yes, looks like a copy-paste
mistake.
>
> > + vdd-supply = <&vdac_vdd>;
> > + vref-supply = <&vref_reg>;
> > + spi-max-frequency = <10000000>;
> > +
> > + #address-cells = <1>;
> > + #size-cells = <0>;
> > + channel@0 {
> > + reg = <0>;
> > + label = "Adjustable_voltage_ch0";
> > + };
> > +
> > + channel@1 {
> > + reg = <0x1>;
> > + label = "Adjustable_voltage_ch1";
> > + };
> > + };
> > + };
> > ...
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260723-mcp47feb02_refactor-v1-0-ee59e63672bc@microchip.com?part=2
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI
2026-07-23 13:43 ` [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI Ariana Lazar
2026-07-23 13:50 ` sashiko-bot
@ 2026-07-23 16:38 ` Conor Dooley
1 sibling, 0 replies; 9+ messages in thread
From: Conor Dooley @ 2026-07-23 16:38 UTC (permalink / raw)
To: Ariana Lazar
Cc: Jonathan Cameron, David Lechner, Nuno Sá, Andy Shevchenko,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, linux-kernel,
linux-iio, devicetree
[-- Attachment #1: Type: text/plain, Size: 1927 bytes --]
On Thu, Jul 23, 2026 at 04:43:11PM +0300, Ariana Lazar wrote:
> Add the SPI MCP48FxBy1/2/4/8 part numbers, the spi-max-frequency property
> and a devicetree example for SPI usage to the existing binding.
>
> Signed-off-by: Ariana Lazar <ariana.lazar@microchip.com>
This is actually a v2, right? This was submitted before using a bit of a
different approach IIRC?
> allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + pattern: "^microchip,mcp48f[ev]b[0-2][1248]$"
> + then:
> + $ref: /schemas/spi/spi-peripheral-props.yaml#
>
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - microchip,mcp47feb01
> + - microchip,mcp47feb02
> + - microchip,mcp47feb04
> + - microchip,mcp47feb08
> + - microchip,mcp47feb11
> + - microchip,mcp47feb12
> + - microchip,mcp47feb14
> + - microchip,mcp47feb18
> + - microchip,mcp47feb21
> + - microchip,mcp47feb22
> + - microchip,mcp47feb24
> + - microchip,mcp47feb28
> + - microchip,mcp47fvb01
> + - microchip,mcp47fvb02
> + - microchip,mcp47fvb04
> + - microchip,mcp47fvb08
> + - microchip,mcp47fvb11
> + - microchip,mcp47fvb12
> + - microchip,mcp47fvb14
> + - microchip,mcp47fvb18
> + - microchip,mcp47fvb21
> + - microchip,mcp47fvb22
> + - microchip,mcp47fvb24
> + - microchip,mcp47fvb28
> + then:
> + properties:
> + spi-max-frequency: false
I think these should be squashed into one conditional, since you can
just do "else: spi-max-frequency: false".
pw-bot: changes-requested
Cheers,
Conor.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-07-23 16:38 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-23 13:43 [PATCH 0/3] Refactor Microchip MCP47FEB02 I2C driver in separate modules to add support for MCP48FEB02 SPI driver Ariana Lazar
2026-07-23 13:43 ` [PATCH 1/3] iio: dac: mcp47feb02: refactor MCP47FEB02 I2C driver into two modules Ariana Lazar
2026-07-23 14:01 ` sashiko-bot
2026-07-23 13:43 ` [PATCH 2/3] dt-bindings: iio: dac: add support for MCP48FEB02 SPI Ariana Lazar
2026-07-23 13:50 ` sashiko-bot
2026-07-23 16:36 ` Conor Dooley
2026-07-23 16:38 ` Conor Dooley
2026-07-23 13:43 ` [PATCH 3/3] iio: dac: add support for Microchip MCP48FEB02 Ariana Lazar
2026-07-23 14:03 ` sashiko-bot
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.