add MCP4728 I2C DAC driver
Subsystems (2)
v4 cover add MCP4728 I2C DAC driver
Changes v3->v4:
- sorted includes
- driver name inlined
- used FIELD_PREP() / FIELD_GET() to define/access regs
- fix comment style
- removed infrastructur form multiple support devices
- wrapped up custom ABI in the standard ABI of _scale
- used dev_get_drvdata(dev) to cleanup code
- used devm_add_action_or_reset to cleanup code
Changes v2->v3:
- fix wrong i2c_device_id array indentation
- removed double blank line in Kconfig
- added description in dt-bindings
- use uppercase letters for device name
Changes v1->v2:
- fix mcp4728_remove prototype
- improve indentation
- various fixes suggested by checkscript.pl
- removed unused of_device_id.data field
- removed unuseful mcp4728_data.id field
- various fixes suggested by dt_binding_check
Andrea Collamati (2):
dt-bindings: iio: dac: add mcp4728.yaml
iio: add MCP4728 I2C DAC driver
.../bindings/iio/dac/microchip,mcp4728.yaml | 49 ++ drivers/iio/dac/Kconfig | 11 + drivers/iio/dac/Makefile | 1 + drivers/iio/dac/mcp4728.c | 626 ++++++++++++++++++ 4 files changed, 687 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/dac/microchip,mcp4728.yaml create mode 100644 drivers/iio/dac/mcp4728.c
Signature · 1 line
2.34.1
PATCH v4 1/2 dt-bindings: iio: dac: add mcp4728.yaml
Add documentation for MCP4728
--- .../bindings/iio/dac/microchip,mcp4728.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/dac/microchip,mcp4728.yaml
Documentation/devicetree/bindings/iio/dac/microchip,mcp4728.yaml new file +49 -0
@@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- + +$id: http://devicetree.org/schemas/iio/dac/microchip,mcp4728.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip MCP4728 DAC + +maintainers: + - Andrea Collamati <[email protected]> + +description: | + MCP4728 is a quad channel, 12-bit voltage output + Digital-to-Analog Converter with non-volatile + memory and I2C compatible Serial Interface. + https://www.microchip.com/en-us/product/mcp4728 + +properties: + compatible: + const: microchip,mcp4728 + + reg: + maxItems: 1 + + vdd-supply: + description: | + Provides both power and acts as the reference supply on the MCP4728 + when Internal Vref is not selected. + +required: + - compatible + - reg + - vdd-supply + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + dac@60 { + compatible = "microchip,mcp4728"; + reg = <0x60>; + vdd-supply = <&vdac_vdd>; + }; + };
Signature · 1 line
2.34.1
Re: [PATCH v4 1/2] dt-bindings: iio: dac: add mcp4728.yaml
Quoted 3 lines · Andrea Collamati
Add documentation for MCP4728
Signed-off-by Andrea Collamati <[email protected]>
I gave you a reviewed-by on v3, is there a reason that you dropped it?
Thanks,
Conor.
Quoted 63 lines
--- .../bindings/iio/dac/microchip,mcp4728.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/dac/microchip,mcp4728.yamlDocumentation/devicetree/bindings/iio/dac/microchip,mcp4728.yaml new file +49
-0@@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- + +$id: http://devicetree.org/schemas/iio/dac/microchip,mcp4728.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip MCP4728 DAC + +maintainers: + - Andrea Collamati <[email protected]> + +description: | + MCP4728 is a quad channel, 12-bit voltage output + Digital-to-Analog Converter with non-volatile + memory and I2C compatible Serial Interface. + https://www.microchip.com/en-us/product/mcp4728 + +properties: + compatible: + const: microchip,mcp4728 + + reg: + maxItems: 1 + + vdd-supply: + description: | + Provides both power and acts as the reference supply on the MCP4728 + when Internal Vref is not selected. + +required: + - compatible + - reg + - vdd-supply + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + dac@60 { + compatible = "microchip,mcp4728"; + reg = <0x60>; + vdd-supply = <&vdac_vdd>; + }; + };Signature · 1 line
2.34.1
Andrea Collamati
Reviewed-by Conor DooleyRe: [PATCH v4 1/2] dt-bindings: iio: dac: add mcp4728.yaml
Sorry it's the first time I try to submit a driver.
So after your positive review I should add...
I will do in v5..
Andrea
Quoted 72 lines · Conor Dooley
Quoted 3 lines · Andrea Collamati
Add documentation for MCP4728
Signed-off-by Andrea Collamati <[email protected]>I gave you a reviewed-by on v3, is there a reason that you dropped it?
Thanks,
Conor.Quoted 63 lines
--- .../bindings/iio/dac/microchip,mcp4728.yaml | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/dac/microchip,mcp4728.yamlDocumentation/devicetree/bindings/iio/dac/microchip,mcp4728.yaml new file +49
-0@@ -0,0 +1,49 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- + +$id: http://devicetree.org/schemas/iio/dac/microchip,mcp4728.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip MCP4728 DAC + +maintainers: + - Andrea Collamati <[email protected]> + +description: | + MCP4728 is a quad channel, 12-bit voltage output + Digital-to-Analog Converter with non-volatile + memory and I2C compatible Serial Interface. + https://www.microchip.com/en-us/product/mcp4728 + +properties: + compatible: + const: microchip,mcp4728 + + reg: + maxItems: 1 + + vdd-supply: + description: | + Provides both power and acts as the reference supply on the MCP4728 + when Internal Vref is not selected. + +required: + - compatible + - reg + - vdd-supply + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + dac@60 { + compatible = "microchip,mcp4728"; + reg = <0x60>; + vdd-supply = <&vdac_vdd>; + }; + };Signature · 1 line
2.34.1
Re: [PATCH v4 1/2] dt-bindings: iio: dac: add mcp4728.yaml
Quoted 8 lines · Andrea Collamati
Quoted 5 lines · Conor Dooley
Quoted 3 lines · Andrea Collamati
Add documentation for MCP4728
Signed-off-by Andrea Collamati <[email protected]>I gave you a reviewed-by on v3, is there a reason that you dropped it?
Sorry it's the first time I try to submit a driver.
No worries. It's just hard to know if people do things intentionally or not!
Quoted 5 lines
So after your positive review I should add...
Reviewed-by Conor Dooley <[email protected]>I will do in v5.
But don't post a v5 for that alone, if this version is fine then it can be picked up on application.
PATCH v4 2/2 iio: add MCP4728 I2C DAC driver
In reply to Andrea CollamatiMCP4728 is a 12-bit quad channel DAC with I2C interface.
support for:
* per-channel gain
* per-channel power state
* per-channel power down mode control
* per-channel vref selection internal/vdd
* store current state to on-chip EEPROM
--- drivers/iio/dac/Kconfig | 11 + drivers/iio/dac/Makefile | 1 + drivers/iio/dac/mcp4728.c | 626 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 638 insertions(+) create mode 100644 drivers/iio/dac/mcp4728.c
drivers/iio/dac/Kconfig +11 -0
@@ -389,6 +389,17 @@ config MCP4725 To compile this driver as a module, choose M here: the module will be called mcp4725. +config MCP4728 + tristate "MCP4728 DAC driver" + depends on I2C + help + Say Y here if you want to build a driver for the Microchip + MCP4728 quad channel, 12-bit digital-to-analog converter (DAC) + with I2C interface. + + To compile this driver as a module, choose M here: the module + will be called mcp4728. + config MCP4922 tristate "MCP4902, MCP4912, MCP4922 DAC driver" depends on SPI
drivers/iio/dac/Makefile +1 -0
@@ -41,6 +41,7 @@ obj-$(CONFIG_MAX517) += max517.o obj-$(CONFIG_MAX5522) += max5522.o obj-$(CONFIG_MAX5821) += max5821.o obj-$(CONFIG_MCP4725) += mcp4725.o +obj-$(CONFIG_MCP4728) += mcp4728.o obj-$(CONFIG_MCP4922) += mcp4922.o obj-$(CONFIG_STM32_DAC_CORE) += stm32-dac-core.o obj-$(CONFIG_STM32_DAC) += stm32-dac.o
drivers/iio/dac/mcp4728.c new file +626 -0
626 lines not on this page · raw message
Signature · 1 line
2.34.1
Jonathan Cameron
maintainerRe: [PATCH v4 2/2] iio: add MCP4728 I2C DAC driver
Quoted 10 lines · On Thu, 3 Aug 2023 14:56:35 +0200 Andrea Collamati…
MCP4728 is a 12-bit quad channel DAC with I2C interface.
support for:
* per-channel gain
* per-channel power state
* per-channel power down mode control
* per-channel vref selection internal/vdd
* store current state to on-chip EEPROMSigned-off-by Andrea Collamati <[email protected]>
Hi Andrea,
On this final read through I noticed a few minor things. Rather than get you to do a v5 I've made the changes whilst applying. Please take a sanity check at
https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git/log/?h=testing
to make sure I didn't break anything and let me know if I did!
Applied with the below mentioned changes to the togreg branch of iio.git which is initially pushed out as testing to let 0-day poke at it and see if it can find any problems.
Thanks,
Jonathan
Quoted 6 lines
drivers/iio/dac/mcp4728.c new file +0
-0@@ -0,0 +1,626 @@
...
Quoted 15 lines
drivers/iio/dac/mcp4728.c new file +15
-0+ +static int mcp4728_set_scale (int channel,struct mcp4728_data *data,int val, +int val2) +{ +int scale =mcp4728_find_matching_scale (data, val, val2); + +if (scale <0 ) +return scale; + +switch (scale) { +case MCP4728_SCALE_VDD : + data->chdata[channel].ref_mode =MCP4728_VREF_EXTERNAL_VDD ; +break ; +case MCP4728_SCALE_VINT_NO_GAIN : + data->chdata[channel].ref_mode = MCP4728_VREF_INTERNAL_2048mV;
drivers/iio/dac/mcp4728.c line 361
Quoted 10 lines
drivers/iio/dac/mcp4728.c new file +10
-0+ data->chdata[channel].g_mode =MCP4728_GAIN_X1 ; +break ; +case MCP4728_SCALE_VINT_GAIN_X2 : + data->chdata[channel].ref_mode = MCP4728_VREF_INTERNAL_2048mV; + data->chdata[channel].g_mode =MCP4728_GAIN_X2 ; +break ; +default : +return -EINVAL ; + } +return 0 ;
return instead of breaking above as nothing to be done after the switch. Side effect of that is this return 0 not needed.
Quoted 1 line
+}
...
Quoted 4 lines
drivers/iio/dac/mcp4728.c new file +4
-0+static int mcp4728_write_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan,int val, +int val2,long mask) +{
drivers/iio/dac/mcp4728.c line 394
Quoted 10 lines
drivers/iio/dac/mcp4728.c new file +10
-0+struct mcp4728_data *data =iio_priv (indio_dev); +int ret; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +if (val <0 || val >GENMASK (MCP4728_RESOLUTION -1 ,0 )) +return -EINVAL ; + data->chdata[chan->channel].dac_value = val; + ret =mcp4728_program_channel_cfg (chan->channel, indio_dev); +break ;
Direct returns preferred if no cleanup to do.
Quoted 18 lines
drivers/iio/dac/mcp4728.c new file +15
-0+case IIO_CHAN_INFO_SCALE : + ret =mcp4728_set_scale (chan->channel, data, val, val2); +if (ret) +break ; + + ret =mcp4728_program_channel_cfg (chan->channel, indio_dev); +break ; +default : + ret = -EINVAL ; +break ; + } + +return ret; +} +static int mcp4728_init_channels_data (struct mcp4728_data *data)
drivers/iio/dac/mcp4728.c line 518
Quoted 10 lines
drivers/iio/dac/mcp4728.c new file +10
-0+{ +u8 inbuf[MCP4728_READ_RESPONSE_LEN ]; +int ret; +unsigned int i; + + ret =i2c_master_recv (data->client, inbuf,MCP4728_READ_RESPONSE_LEN ); +if (ret <0 ) { +dev_err (&data->client->dev, +"failed to read mcp4728 conf. Err=%d\n" , ret); +return ret;
As this is only called from probe, we should still use dev_err_probe() in here as mentioned below.
Quoted 21 lines
drivers/iio/dac/mcp4728.c new file +21
-0+ }else if (ret !=MCP4728_READ_RESPONSE_LEN ) { +dev_err (&data->client->dev, +"failed to read mcp4728 conf. Wrong Response Len ret=%d\n" , + ret); +return -EIO ; + } + +for (i =0 ; i <MCP4728_N_CHANNELS ; i++) { +struct mcp4728_channel_data *ch = &data->chdata[i]; +u8 r2 = inbuf[i *6 +1 ]; +u8 r3 = inbuf[i *6 +2 ]; + + ch->dac_value =FIELD_GET (MCP4728_DAC_H_MASK , r2) <<8 | +FIELD_GET (MCP4728_DAC_L_MASK , r3); + ch->ref_mode =FIELD_GET (MCP4728_VREF_MASK , r2); + ch->pd_mode =FIELD_GET (MCP4728_PDMODE_MASK , r2); + ch->g_mode =FIELD_GET (MCP4728_GAIN_MASK , r2); + } + +return 0 ; +}
...
Quoted 19 lines
drivers/iio/dac/mcp4728.c new file +19
-0+static int mcp4728_probe (struct i2c_client *client) +{ +const struct i2c_device_id *id =i2c_client_get_device_id (client); +struct mcp4728_data *data; +struct iio_dev *indio_dev; +int err; + + indio_dev =devm_iio_device_alloc (&client->dev,sizeof (*data)); +if (!indio_dev) +return -ENOMEM ; + + data =iio_priv (indio_dev); +i2c_set_clientdata (client, indio_dev); + data->client = client; + + data->vdd_reg =devm_regulator_get (&client->dev,"vdd" ); +if (IS_ERR (data->vdd_reg)) +return PTR_ERR (data->vdd_reg); +
drivers/iio/dac/mcp4728.c line 574
Quoted 10 lines
drivers/iio/dac/mcp4728.c new file +10
-0+ err =regulator_enable (data->vdd_reg); +if (err) +return err; + + err =devm_add_action_or_reset (&client->dev, mcp4728_reg_disable, + data->vdd_reg); +if (err) +return err; + +/* MCP4728 has internal EEPROM that save each channel boot configuration.
Trivial but comment syntax in IIO (there are some differences in a few other subsystems) is
/* * MCP...
drivers/iio/dac/mcp4728.c line 580
Quoted 6 lines
drivers/iio/dac/mcp4728.c new file +6
-0+* It means that device configuration is unknown to the driver at kernel boot. +* mcp4728_init_channels_data reads back DAC settings and stores them in data +* structure. +*/ + err =mcp4728_init_channels_data (data); +if (err) {
I'd missed this previously but dev_err_probe() has several advantages in that it handles deferring neatly and also ends up with less code.
Quoted 19 lines
drivers/iio/dac/mcp4728.c new file +19
-0+dev_err (&client->dev, +"failed to read mcp4728 current configuration\n" ); +return err; + } + + err =mcp4728_init_scales_avail (data); +if (err) { +dev_err (&client->dev,"failed to init scales\n" ); +return err; + } + + indio_dev->name = id->name; + indio_dev->info = &mcp4728_info; + indio_dev->channels = mcp4728_channels; + indio_dev->num_channels =MCP4728_N_CHANNELS ; + indio_dev->modes =INDIO_DIRECT_MODE ; + +return devm_iio_device_register (&client->dev, indio_dev); +}
Re: [PATCH v4 2/2] iio: add MCP4728 I2C DAC driver
Hi Jonathan,
I tested the driver and I didn't find any issue.
These are the tests I performed:
Test Configuration:
SW:git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git
commit: ee812337ee74cc403b4fbd85840dbe1b21d9a60f
HW:
- Aster board from Toradex hosting imx7d processor
- Adafruit MCP4728 https://www.adafruit.com/product/4470
TEST:
Probe Test OK #> insmod mcp4728.ko
Read Scales OK
~# cat /sys/devices/platform/soc/30800000.bus/30a50000.i2c/i2c-3/3-0064/iio:device1/out_voltage_scale_available 0.805664 0.500000 1.000000
Write DAC CH0 OK #>iio_attr -c mcp4728 voltage0 scale 1.000000 #>iio_attr -c mcp4728 voltage0 raw 750 Voltage Monitor Reading: 749 mV
Write DAC CH1 OK #>iio_attr -c mcp4728 voltage1 scale 0.5 #>iio_attr -c mcp4728 voltage1 raw 750 Voltage Monitor Reading: 378 mV
Write DAC CH2 OK
#>iio_attr -c mcp4728 voltage2 scale 0.805664
#>iio_attr -c mcp4728 voltage2 raw 750
Voltage Monitor Reading: 603 mV ~ 750*0.805664 ~ 604 mV
Write DAC CH3 OK #>iio_attr -c mcp4728 voltage3 scale 1.000000 #>iio_attr -c mcp4728 voltage3 raw 350 Voltage Monitor Reading: 354 mV
Store EEPROM OK
#>echo y > /sys/devices/platform/soc/30800000.bus/30a50000.i2c/i2c-3/3-0064/iio:device1/store_eeprom #>power cycle board
Voltage Monitor Reading CH0 749 mV
Voltage Monitor Reading CH1 378 mV
Voltage Monitor Reading CH2 605 mV
Voltage Monitor Reading CH3 355 mV
Power Down CH0
#>iio_attr -c mcp4728 voltage0 powerdown_mode 1kohm_to_gnd #>iio_attr -c mcp4728 voltage0 powerdown 1 Voltage Monitor Reading CH0 0 mV
Power Down CH1
#>iio_attr -c mcp4728 voltage1 powerdown_mode 1kohm_to_gnd #>iio_attr -c mcp4728 voltage1 powerdown 1 Voltage Monitor Reading CH1 0 mV
Power Down CH2
#>iio_attr -c mcp4728 voltage2 powerdown_mode 1kohm_to_gnd #>iio_attr -c mcp4728 voltage2 powerdown 1 Voltage Monitor Reading CH2 0 mV
Power Down CH3
#>iio_attr -c mcp4728 voltage3 powerdown_mode 1kohm_to_gnd #>iio_attr -c mcp4728 voltage3 powerdown 1 Voltage Monitor Reading CH3 0 mV
Regards
Andrea
Quoted 202 lines · Jonathan Cameron
Quoted 10 lines · On Thu, 3 Aug 2023 14:56:35 +0200 Andrea Collamati…
MCP4728 is a 12-bit quad channel DAC with I2C interface.
support for:
* per-channel gain
* per-channel power state
* per-channel power down mode control
* per-channel vref selection internal/vdd
* store current state to on-chip EEPROMSigned-off-by Andrea Collamati <[email protected]>Hi Andrea,
On this final read through I noticed a few minor things. Rather than get you to do a v5 I've made the changes whilst applying. Please take a sanity check at
https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git/log/?h=testing
to make sure I didn't break anything and let me know if I did!Applied with the below mentioned changes to the togreg branch of iio.git which is initially pushed out as testing to let 0-day poke at it and see if it can find any problems.
Thanks,
Jonathan
Quoted 6 lines
drivers/iio/dac/mcp4728.c new file +0
-0@@ -0,0 +1,626 @@...
Quoted 15 lines
drivers/iio/dac/mcp4728.c new file +15
-0+ +static int mcp4728_set_scale (int channel,struct mcp4728_data *data,int val, +int val2) +{ +int scale =mcp4728_find_matching_scale (data, val, val2); + +if (scale <0 ) +return scale; + +switch (scale) { +case MCP4728_SCALE_VDD : + data->chdata[channel].ref_mode =MCP4728_VREF_EXTERNAL_VDD ; +break ; +case MCP4728_SCALE_VINT_NO_GAIN : + data->chdata[channel].ref_mode = MCP4728_VREF_INTERNAL_2048mV;drivers/iio/dac/mcp4728.c line 361
Quoted 10 lines
drivers/iio/dac/mcp4728.c new file +10
-0+ data->chdata[channel].g_mode =MCP4728_GAIN_X1 ; +break ; +case MCP4728_SCALE_VINT_GAIN_X2 : + data->chdata[channel].ref_mode = MCP4728_VREF_INTERNAL_2048mV; + data->chdata[channel].g_mode =MCP4728_GAIN_X2 ; +break ; +default : +return -EINVAL ; + } +return 0 ;return instead of breaking above as nothing to be done after the switch. Side effect of that is this return 0 not needed.
Quoted 1 line
+}
...
Quoted 4 lines
drivers/iio/dac/mcp4728.c new file +4
-0+static int mcp4728_write_raw (struct iio_dev *indio_dev, +struct iio_chan_spec const *chan,int val, +int val2,long mask) +{drivers/iio/dac/mcp4728.c line 394
Quoted 10 lines
drivers/iio/dac/mcp4728.c new file +10
-0+struct mcp4728_data *data =iio_priv (indio_dev); +int ret; + +switch (mask) { +case IIO_CHAN_INFO_RAW : +if (val <0 || val >GENMASK (MCP4728_RESOLUTION -1 ,0 )) +return -EINVAL ; + data->chdata[chan->channel].dac_value = val; + ret =mcp4728_program_channel_cfg (chan->channel, indio_dev); +break ;Direct returns preferred if no cleanup to do.
Quoted 17 lines
drivers/iio/dac/mcp4728.c new file +15
-0+case IIO_CHAN_INFO_SCALE : + ret =mcp4728_set_scale (chan->channel, data, val, val2); +if (ret) +break ; + + ret =mcp4728_program_channel_cfg (chan->channel, indio_dev); +break ; +default : + ret = -EINVAL ; +break ; + } + +return ret; +} +static int mcp4728_init_channels_data (struct mcp4728_data *data)drivers/iio/dac/mcp4728.c line 518
Quoted 10 lines
drivers/iio/dac/mcp4728.c new file +10
-0+{ +u8 inbuf[MCP4728_READ_RESPONSE_LEN ]; +int ret; +unsigned int i; + + ret =i2c_master_recv (data->client, inbuf,MCP4728_READ_RESPONSE_LEN ); +if (ret <0 ) { +dev_err (&data->client->dev, +"failed to read mcp4728 conf. Err=%d\n" , ret); +return ret;As this is only called from probe, we should still use
dev_err_probe()in here as mentioned below.Quoted 21 lines
drivers/iio/dac/mcp4728.c new file +21
-0+ }else if (ret !=MCP4728_READ_RESPONSE_LEN ) { +dev_err (&data->client->dev, +"failed to read mcp4728 conf. Wrong Response Len ret=%d\n" , + ret); +return -EIO ; + } + +for (i =0 ; i <MCP4728_N_CHANNELS ; i++) { +struct mcp4728_channel_data *ch = &data->chdata[i]; +u8 r2 = inbuf[i *6 +1 ]; +u8 r3 = inbuf[i *6 +2 ]; + + ch->dac_value =FIELD_GET (MCP4728_DAC_H_MASK , r2) <<8 | +FIELD_GET (MCP4728_DAC_L_MASK , r3); + ch->ref_mode =FIELD_GET (MCP4728_VREF_MASK , r2); + ch->pd_mode =FIELD_GET (MCP4728_PDMODE_MASK , r2); + ch->g_mode =FIELD_GET (MCP4728_GAIN_MASK , r2); + } + +return 0 ; +}...
Quoted 19 lines
drivers/iio/dac/mcp4728.c new file +19
-0+static int mcp4728_probe (struct i2c_client *client) +{ +const struct i2c_device_id *id =i2c_client_get_device_id (client); +struct mcp4728_data *data; +struct iio_dev *indio_dev; +int err; + + indio_dev =devm_iio_device_alloc (&client->dev,sizeof (*data)); +if (!indio_dev) +return -ENOMEM ; + + data =iio_priv (indio_dev); +i2c_set_clientdata (client, indio_dev); + data->client = client; + + data->vdd_reg =devm_regulator_get (&client->dev,"vdd" ); +if (IS_ERR (data->vdd_reg)) +return PTR_ERR (data->vdd_reg); +drivers/iio/dac/mcp4728.c line 574
Quoted 10 lines
drivers/iio/dac/mcp4728.c new file +10
-0+ err =regulator_enable (data->vdd_reg); +if (err) +return err; + + err =devm_add_action_or_reset (&client->dev, mcp4728_reg_disable, + data->vdd_reg); +if (err) +return err; + +/* MCP4728 has internal EEPROM that save each channel boot configuration. Trivial but comment syntax in IIO (there are some differences in a few other subsystems) is
/* * MCP...drivers/iio/dac/mcp4728.c line 580
Quoted 6 lines
drivers/iio/dac/mcp4728.c new file +6
-0+* It means that device configuration is unknown to the driver at kernel boot. +* mcp4728_init_channels_data reads back DAC settings and stores them in data +* structure. +*/ + err =mcp4728_init_channels_data (data); +if (err) {I'd missed this previously but
dev_err_probe()has several advantages in that it handles deferring neatly and also ends up with less code.Quoted 19 lines
drivers/iio/dac/mcp4728.c new file +19
-0+dev_err (&client->dev, +"failed to read mcp4728 current configuration\n" ); +return err; + } + + err =mcp4728_init_scales_avail (data); +if (err) { +dev_err (&client->dev,"failed to init scales\n" ); +return err; + } + + indio_dev->name = id->name; + indio_dev->info = &mcp4728_info; + indio_dev->channels = mcp4728_channels; + indio_dev->num_channels =MCP4728_N_CHANNELS ; + indio_dev->modes =INDIO_DIRECT_MODE ; + +return devm_iio_device_register (&client->dev, indio_dev); +}