1*bf394cc8SAriana Lazar // SPDX-License-Identifier: GPL-2.0+ 2*bf394cc8SAriana Lazar /* 3*bf394cc8SAriana Lazar * IIO driver for MCP47FEB02 Multi-Channel DAC with I2C interface 4*bf394cc8SAriana Lazar * 5*bf394cc8SAriana Lazar * Copyright (C) 2025 Microchip Technology Inc. and its subsidiaries 6*bf394cc8SAriana Lazar * 7*bf394cc8SAriana Lazar * Author: Ariana Lazar <ariana.lazar@microchip.com> 8*bf394cc8SAriana Lazar * 9*bf394cc8SAriana Lazar * Datasheet links: 10*bf394cc8SAriana Lazar * [MCP47FEBxx] https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005375A.pdf 11*bf394cc8SAriana Lazar * [MCP47FVBxx] https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/20005405A.pdf 12*bf394cc8SAriana Lazar * [MCP47FxBx4/8] https://ww1.microchip.com/downloads/aemDocuments/documents/MSLD/ProductDocuments/DataSheets/MCP47FXBX48-Data-Sheet-DS200006368A.pdf 13*bf394cc8SAriana Lazar */ 14*bf394cc8SAriana Lazar #include <linux/array_size.h> 15*bf394cc8SAriana Lazar #include <linux/bits.h> 16*bf394cc8SAriana Lazar #include <linux/bitfield.h> 17*bf394cc8SAriana Lazar #include <linux/delay.h> 18*bf394cc8SAriana Lazar #include <linux/err.h> 19*bf394cc8SAriana Lazar #include <linux/i2c.h> 20*bf394cc8SAriana Lazar #include <linux/iio/iio.h> 21*bf394cc8SAriana Lazar #include <linux/iio/sysfs.h> 22*bf394cc8SAriana Lazar #include <linux/kstrtox.h> 23*bf394cc8SAriana Lazar #include <linux/module.h> 24*bf394cc8SAriana Lazar #include <linux/mod_devicetable.h> 25*bf394cc8SAriana Lazar #include <linux/mutex.h> 26*bf394cc8SAriana Lazar #include <linux/property.h> 27*bf394cc8SAriana Lazar #include <linux/regmap.h> 28*bf394cc8SAriana Lazar #include <linux/regulator/consumer.h> 29*bf394cc8SAriana Lazar #include <linux/time64.h> 30*bf394cc8SAriana Lazar #include <linux/types.h> 31*bf394cc8SAriana Lazar #include <linux/units.h> 32*bf394cc8SAriana Lazar 33*bf394cc8SAriana Lazar /* Register addresses must be left shifted with 3 positions in order to append command mask */ 34*bf394cc8SAriana Lazar #define MCP47FEB02_DAC0_REG_ADDR 0x00 35*bf394cc8SAriana Lazar #define MCP47FEB02_VREF_REG_ADDR 0x40 36*bf394cc8SAriana Lazar #define MCP47FEB02_POWER_DOWN_REG_ADDR 0x48 37*bf394cc8SAriana Lazar #define MCP47FEB02_DAC_CTRL_MASK GENMASK(1, 0) 38*bf394cc8SAriana Lazar 39*bf394cc8SAriana Lazar #define MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR 0x50 40*bf394cc8SAriana Lazar #define MCP47FEB02_GAIN_BIT_MASK BIT(0) 41*bf394cc8SAriana Lazar #define MCP47FEB02_GAIN_BIT_STATUS_EEWA_MASK BIT(6) 42*bf394cc8SAriana Lazar #define MCP47FEB02_GAIN_BITS_MASK GENMASK(15, 8) 43*bf394cc8SAriana Lazar 44*bf394cc8SAriana Lazar #define MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR 0x58 45*bf394cc8SAriana Lazar 46*bf394cc8SAriana Lazar #define MCP47FEB02_NV_DAC0_REG_ADDR 0x80 47*bf394cc8SAriana Lazar #define MCP47FEB02_NV_VREF_REG_ADDR 0xC0 48*bf394cc8SAriana Lazar #define MCP47FEB02_NV_POWER_DOWN_REG_ADDR 0xC8 49*bf394cc8SAriana Lazar #define MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR 0xD0 50*bf394cc8SAriana Lazar #define MCP47FEB02_NV_I2C_SLAVE_ADDR_MASK GENMASK(7, 0) 51*bf394cc8SAriana Lazar 52*bf394cc8SAriana Lazar /* Voltage reference, Power-Down control register and DAC Wiperlock status register fields */ 53*bf394cc8SAriana Lazar #define DAC_CTRL_MASK(ch) (GENMASK(1, 0) << (2 * (ch))) 54*bf394cc8SAriana Lazar #define DAC_CTRL_VAL(ch, val) ((val) << (2 * (ch))) 55*bf394cc8SAriana Lazar 56*bf394cc8SAriana Lazar /* Gain Control and I2C Slave Address Reguster fields */ 57*bf394cc8SAriana Lazar #define DAC_GAIN_MASK(ch) (BIT(0) << (8 + (ch))) 58*bf394cc8SAriana Lazar #define DAC_GAIN_VAL(ch, val) ((val) << (8 + (ch))) 59*bf394cc8SAriana Lazar 60*bf394cc8SAriana Lazar #define REG_ADDR(reg) ((reg) << 3) 61*bf394cc8SAriana Lazar #define NV_REG_ADDR(reg) ((NV_DAC_ADDR_OFFSET + (reg)) << 3) 62*bf394cc8SAriana Lazar #define READFLAG_MASK GENMASK(2, 1) 63*bf394cc8SAriana Lazar 64*bf394cc8SAriana Lazar #define MCP47FEB02_MAX_CH 8 65*bf394cc8SAriana Lazar #define MCP47FEB02_MAX_SCALES_CH 3 66*bf394cc8SAriana Lazar #define MCP47FEB02_DAC_WIPER_UNLOCKED 0 67*bf394cc8SAriana Lazar #define MCP47FEB02_NORMAL_OPERATION 0 68*bf394cc8SAriana Lazar #define MCP47FEB02_INTERNAL_BAND_GAP_mV 2440 69*bf394cc8SAriana Lazar #define NV_DAC_ADDR_OFFSET 0x10 70*bf394cc8SAriana Lazar 71*bf394cc8SAriana Lazar enum mcp47feb02_vref_mode { 72*bf394cc8SAriana Lazar MCP47FEB02_VREF_VDD = 0, 73*bf394cc8SAriana Lazar MCP47FEB02_INTERNAL_BAND_GAP = 1, 74*bf394cc8SAriana Lazar MCP47FEB02_EXTERNAL_VREF_UNBUFFERED = 2, 75*bf394cc8SAriana Lazar MCP47FEB02_EXTERNAL_VREF_BUFFERED = 3, 76*bf394cc8SAriana Lazar }; 77*bf394cc8SAriana Lazar 78*bf394cc8SAriana Lazar enum mcp47feb02_scale { 79*bf394cc8SAriana Lazar MCP47FEB02_SCALE_VDD = 0, 80*bf394cc8SAriana Lazar MCP47FEB02_SCALE_GAIN_X1 = 1, 81*bf394cc8SAriana Lazar MCP47FEB02_SCALE_GAIN_X2 = 2, 82*bf394cc8SAriana Lazar }; 83*bf394cc8SAriana Lazar 84*bf394cc8SAriana Lazar enum mcp47feb02_gain_bit_mode { 85*bf394cc8SAriana Lazar MCP47FEB02_GAIN_BIT_X1 = 0, 86*bf394cc8SAriana Lazar MCP47FEB02_GAIN_BIT_X2 = 1, 87*bf394cc8SAriana Lazar }; 88*bf394cc8SAriana Lazar 89*bf394cc8SAriana Lazar static const char * const mcp47feb02_powerdown_modes[] = { 90*bf394cc8SAriana Lazar "1kohm_to_gnd", 91*bf394cc8SAriana Lazar "100kohm_to_gnd", 92*bf394cc8SAriana Lazar "open_circuit", 93*bf394cc8SAriana Lazar }; 94*bf394cc8SAriana Lazar 95*bf394cc8SAriana Lazar /** 96*bf394cc8SAriana Lazar * struct mcp47feb02_features - chip specific data 97*bf394cc8SAriana Lazar * @name: device name 98*bf394cc8SAriana Lazar * @phys_channels: number of hardware channels 99*bf394cc8SAriana Lazar * @resolution: DAC resolution 100*bf394cc8SAriana Lazar * @have_ext_vref1: does the hardware have an the second external voltage reference? 101*bf394cc8SAriana Lazar * @have_eeprom: does the hardware have an internal eeprom? 102*bf394cc8SAriana Lazar */ 103*bf394cc8SAriana Lazar struct mcp47feb02_features { 104*bf394cc8SAriana Lazar const char *name; 105*bf394cc8SAriana Lazar unsigned int phys_channels; 106*bf394cc8SAriana Lazar unsigned int resolution; 107*bf394cc8SAriana Lazar bool have_ext_vref1; 108*bf394cc8SAriana Lazar bool have_eeprom; 109*bf394cc8SAriana Lazar }; 110*bf394cc8SAriana Lazar 111*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb01_chip_features = { 112*bf394cc8SAriana Lazar .name = "mcp47feb01", 113*bf394cc8SAriana Lazar .phys_channels = 1, 114*bf394cc8SAriana Lazar .resolution = 8, 115*bf394cc8SAriana Lazar .have_ext_vref1 = false, 116*bf394cc8SAriana Lazar .have_eeprom = true, 117*bf394cc8SAriana Lazar }; 118*bf394cc8SAriana Lazar 119*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb02_chip_features = { 120*bf394cc8SAriana Lazar .name = "mcp47feb02", 121*bf394cc8SAriana Lazar .phys_channels = 2, 122*bf394cc8SAriana Lazar .resolution = 8, 123*bf394cc8SAriana Lazar .have_ext_vref1 = false, 124*bf394cc8SAriana Lazar .have_eeprom = true, 125*bf394cc8SAriana Lazar }; 126*bf394cc8SAriana Lazar 127*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb04_chip_features = { 128*bf394cc8SAriana Lazar .name = "mcp47feb04", 129*bf394cc8SAriana Lazar .phys_channels = 4, 130*bf394cc8SAriana Lazar .resolution = 8, 131*bf394cc8SAriana Lazar .have_ext_vref1 = true, 132*bf394cc8SAriana Lazar .have_eeprom = true, 133*bf394cc8SAriana Lazar }; 134*bf394cc8SAriana Lazar 135*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb08_chip_features = { 136*bf394cc8SAriana Lazar .name = "mcp47feb08", 137*bf394cc8SAriana Lazar .phys_channels = 8, 138*bf394cc8SAriana Lazar .resolution = 8, 139*bf394cc8SAriana Lazar .have_ext_vref1 = true, 140*bf394cc8SAriana Lazar .have_eeprom = true, 141*bf394cc8SAriana Lazar }; 142*bf394cc8SAriana Lazar 143*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb11_chip_features = { 144*bf394cc8SAriana Lazar .name = "mcp47feb11", 145*bf394cc8SAriana Lazar .phys_channels = 1, 146*bf394cc8SAriana Lazar .resolution = 10, 147*bf394cc8SAriana Lazar .have_ext_vref1 = false, 148*bf394cc8SAriana Lazar .have_eeprom = true, 149*bf394cc8SAriana Lazar }; 150*bf394cc8SAriana Lazar 151*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb12_chip_features = { 152*bf394cc8SAriana Lazar .name = "mcp47feb12", 153*bf394cc8SAriana Lazar .phys_channels = 2, 154*bf394cc8SAriana Lazar .resolution = 10, 155*bf394cc8SAriana Lazar .have_ext_vref1 = false, 156*bf394cc8SAriana Lazar .have_eeprom = true, 157*bf394cc8SAriana Lazar }; 158*bf394cc8SAriana Lazar 159*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb14_chip_features = { 160*bf394cc8SAriana Lazar .name = "mcp47feb14", 161*bf394cc8SAriana Lazar .phys_channels = 4, 162*bf394cc8SAriana Lazar .resolution = 10, 163*bf394cc8SAriana Lazar .have_ext_vref1 = true, 164*bf394cc8SAriana Lazar .have_eeprom = true, 165*bf394cc8SAriana Lazar }; 166*bf394cc8SAriana Lazar 167*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb18_chip_features = { 168*bf394cc8SAriana Lazar .name = "mcp47feb18", 169*bf394cc8SAriana Lazar .phys_channels = 8, 170*bf394cc8SAriana Lazar .resolution = 10, 171*bf394cc8SAriana Lazar .have_ext_vref1 = true, 172*bf394cc8SAriana Lazar .have_eeprom = true, 173*bf394cc8SAriana Lazar }; 174*bf394cc8SAriana Lazar 175*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb21_chip_features = { 176*bf394cc8SAriana Lazar .name = "mcp47feb21", 177*bf394cc8SAriana Lazar .phys_channels = 1, 178*bf394cc8SAriana Lazar .resolution = 12, 179*bf394cc8SAriana Lazar .have_ext_vref1 = false, 180*bf394cc8SAriana Lazar .have_eeprom = true, 181*bf394cc8SAriana Lazar }; 182*bf394cc8SAriana Lazar 183*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb22_chip_features = { 184*bf394cc8SAriana Lazar .name = "mcp47feb22", 185*bf394cc8SAriana Lazar .phys_channels = 2, 186*bf394cc8SAriana Lazar .resolution = 12, 187*bf394cc8SAriana Lazar .have_ext_vref1 = false, 188*bf394cc8SAriana Lazar .have_eeprom = true, 189*bf394cc8SAriana Lazar }; 190*bf394cc8SAriana Lazar 191*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb24_chip_features = { 192*bf394cc8SAriana Lazar .name = "mcp47feb24", 193*bf394cc8SAriana Lazar .phys_channels = 4, 194*bf394cc8SAriana Lazar .resolution = 12, 195*bf394cc8SAriana Lazar .have_ext_vref1 = true, 196*bf394cc8SAriana Lazar .have_eeprom = true, 197*bf394cc8SAriana Lazar }; 198*bf394cc8SAriana Lazar 199*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47feb28_chip_features = { 200*bf394cc8SAriana Lazar .name = "mcp47feb28", 201*bf394cc8SAriana Lazar .phys_channels = 8, 202*bf394cc8SAriana Lazar .resolution = 12, 203*bf394cc8SAriana Lazar .have_ext_vref1 = true, 204*bf394cc8SAriana Lazar .have_eeprom = true, 205*bf394cc8SAriana Lazar }; 206*bf394cc8SAriana Lazar 207*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb01_chip_features = { 208*bf394cc8SAriana Lazar .name = "mcp47fvb01", 209*bf394cc8SAriana Lazar .phys_channels = 1, 210*bf394cc8SAriana Lazar .resolution = 8, 211*bf394cc8SAriana Lazar .have_ext_vref1 = false, 212*bf394cc8SAriana Lazar .have_eeprom = false, 213*bf394cc8SAriana Lazar }; 214*bf394cc8SAriana Lazar 215*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb02_chip_features = { 216*bf394cc8SAriana Lazar .name = "mcp47fvb02", 217*bf394cc8SAriana Lazar .phys_channels = 2, 218*bf394cc8SAriana Lazar .resolution = 8, 219*bf394cc8SAriana Lazar .have_ext_vref1 = false, 220*bf394cc8SAriana Lazar .have_eeprom = false, 221*bf394cc8SAriana Lazar }; 222*bf394cc8SAriana Lazar 223*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb04_chip_features = { 224*bf394cc8SAriana Lazar .name = "mcp47fvb04", 225*bf394cc8SAriana Lazar .phys_channels = 4, 226*bf394cc8SAriana Lazar .resolution = 8, 227*bf394cc8SAriana Lazar .have_ext_vref1 = true, 228*bf394cc8SAriana Lazar .have_eeprom = false, 229*bf394cc8SAriana Lazar }; 230*bf394cc8SAriana Lazar 231*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb08_chip_features = { 232*bf394cc8SAriana Lazar .name = "mcp47fvb08", 233*bf394cc8SAriana Lazar .phys_channels = 8, 234*bf394cc8SAriana Lazar .resolution = 8, 235*bf394cc8SAriana Lazar .have_ext_vref1 = true, 236*bf394cc8SAriana Lazar .have_eeprom = false, 237*bf394cc8SAriana Lazar }; 238*bf394cc8SAriana Lazar 239*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb11_chip_features = { 240*bf394cc8SAriana Lazar .name = "mcp47fvb11", 241*bf394cc8SAriana Lazar .phys_channels = 1, 242*bf394cc8SAriana Lazar .resolution = 10, 243*bf394cc8SAriana Lazar .have_ext_vref1 = false, 244*bf394cc8SAriana Lazar .have_eeprom = false, 245*bf394cc8SAriana Lazar }; 246*bf394cc8SAriana Lazar 247*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb12_chip_features = { 248*bf394cc8SAriana Lazar .name = "mcp47fvb12", 249*bf394cc8SAriana Lazar .phys_channels = 2, 250*bf394cc8SAriana Lazar .resolution = 10, 251*bf394cc8SAriana Lazar .have_ext_vref1 = false, 252*bf394cc8SAriana Lazar .have_eeprom = false, 253*bf394cc8SAriana Lazar }; 254*bf394cc8SAriana Lazar 255*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb14_chip_features = { 256*bf394cc8SAriana Lazar .name = "mcp47fvb14", 257*bf394cc8SAriana Lazar .phys_channels = 4, 258*bf394cc8SAriana Lazar .resolution = 10, 259*bf394cc8SAriana Lazar .have_ext_vref1 = true, 260*bf394cc8SAriana Lazar .have_eeprom = false, 261*bf394cc8SAriana Lazar }; 262*bf394cc8SAriana Lazar 263*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb18_chip_features = { 264*bf394cc8SAriana Lazar .name = "mcp47fvb18", 265*bf394cc8SAriana Lazar .phys_channels = 8, 266*bf394cc8SAriana Lazar .resolution = 10, 267*bf394cc8SAriana Lazar .have_ext_vref1 = true, 268*bf394cc8SAriana Lazar .have_eeprom = false, 269*bf394cc8SAriana Lazar }; 270*bf394cc8SAriana Lazar 271*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb21_chip_features = { 272*bf394cc8SAriana Lazar .name = "mcp47fvb21", 273*bf394cc8SAriana Lazar .phys_channels = 1, 274*bf394cc8SAriana Lazar .resolution = 12, 275*bf394cc8SAriana Lazar .have_ext_vref1 = false, 276*bf394cc8SAriana Lazar .have_eeprom = false, 277*bf394cc8SAriana Lazar }; 278*bf394cc8SAriana Lazar 279*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb22_chip_features = { 280*bf394cc8SAriana Lazar .name = "mcp47fvb22", 281*bf394cc8SAriana Lazar .phys_channels = 2, 282*bf394cc8SAriana Lazar .resolution = 12, 283*bf394cc8SAriana Lazar .have_ext_vref1 = false, 284*bf394cc8SAriana Lazar .have_eeprom = false, 285*bf394cc8SAriana Lazar }; 286*bf394cc8SAriana Lazar 287*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb24_chip_features = { 288*bf394cc8SAriana Lazar .name = "mcp47fvb24", 289*bf394cc8SAriana Lazar .phys_channels = 4, 290*bf394cc8SAriana Lazar .resolution = 12, 291*bf394cc8SAriana Lazar .have_ext_vref1 = true, 292*bf394cc8SAriana Lazar .have_eeprom = false, 293*bf394cc8SAriana Lazar }; 294*bf394cc8SAriana Lazar 295*bf394cc8SAriana Lazar static const struct mcp47feb02_features mcp47fvb28_chip_features = { 296*bf394cc8SAriana Lazar .name = "mcp47fvb28", 297*bf394cc8SAriana Lazar .phys_channels = 8, 298*bf394cc8SAriana Lazar .resolution = 12, 299*bf394cc8SAriana Lazar .have_ext_vref1 = true, 300*bf394cc8SAriana Lazar .have_eeprom = false, 301*bf394cc8SAriana Lazar }; 302*bf394cc8SAriana Lazar 303*bf394cc8SAriana Lazar /** 304*bf394cc8SAriana Lazar * struct mcp47feb02_channel_data - channel configuration 305*bf394cc8SAriana Lazar * @ref_mode: chosen voltage for reference 306*bf394cc8SAriana Lazar * @use_2x_gain: output driver gain control 307*bf394cc8SAriana Lazar * @powerdown: is false if the channel is in normal operation mode 308*bf394cc8SAriana Lazar * @powerdown_mode: selected power-down mode 309*bf394cc8SAriana Lazar * @dac_data: dac value 310*bf394cc8SAriana Lazar */ 311*bf394cc8SAriana Lazar struct mcp47feb02_channel_data { 312*bf394cc8SAriana Lazar u8 ref_mode; 313*bf394cc8SAriana Lazar bool use_2x_gain; 314*bf394cc8SAriana Lazar bool powerdown; 315*bf394cc8SAriana Lazar u8 powerdown_mode; 316*bf394cc8SAriana Lazar u16 dac_data; 317*bf394cc8SAriana Lazar }; 318*bf394cc8SAriana Lazar 319*bf394cc8SAriana Lazar /** 320*bf394cc8SAriana Lazar * struct mcp47feb02_data - chip configuration 321*bf394cc8SAriana Lazar * @chdata: options configured for each channel on the device 322*bf394cc8SAriana Lazar * @lock: prevents concurrent reads/writes to driver's state members 323*bf394cc8SAriana Lazar * @chip_features: pointer to features struct 324*bf394cc8SAriana Lazar * @scale_1: scales set on channels that are based on Vref1 325*bf394cc8SAriana Lazar * @scale: scales set on channels that are based on Vref/Vref0 326*bf394cc8SAriana Lazar * @active_channels_mask: enabled channels 327*bf394cc8SAriana Lazar * @regmap: regmap for directly accessing device register 328*bf394cc8SAriana Lazar * @labels: table with channels labels 329*bf394cc8SAriana Lazar * @phys_channels: physical channels on the device 330*bf394cc8SAriana Lazar * @vref1_buffered: Vref1 buffer is enabled 331*bf394cc8SAriana Lazar * @vref_buffered: Vref/Vref0 buffer is enabled 332*bf394cc8SAriana Lazar * @use_vref1: vref1-supply is defined 333*bf394cc8SAriana Lazar * @use_vref: vref-supply is defined 334*bf394cc8SAriana Lazar */ 335*bf394cc8SAriana Lazar struct mcp47feb02_data { 336*bf394cc8SAriana Lazar struct mcp47feb02_channel_data chdata[MCP47FEB02_MAX_CH]; 337*bf394cc8SAriana Lazar struct mutex lock; /* prevents concurrent reads/writes to driver's state members */ 338*bf394cc8SAriana Lazar const struct mcp47feb02_features *chip_features; 339*bf394cc8SAriana Lazar int scale_1[2 * MCP47FEB02_MAX_SCALES_CH]; 340*bf394cc8SAriana Lazar int scale[2 * MCP47FEB02_MAX_SCALES_CH]; 341*bf394cc8SAriana Lazar unsigned long active_channels_mask; 342*bf394cc8SAriana Lazar struct regmap *regmap; 343*bf394cc8SAriana Lazar const char *labels[MCP47FEB02_MAX_CH]; 344*bf394cc8SAriana Lazar u16 phys_channels; 345*bf394cc8SAriana Lazar bool vref1_buffered; 346*bf394cc8SAriana Lazar bool vref_buffered; 347*bf394cc8SAriana Lazar bool use_vref1; 348*bf394cc8SAriana Lazar bool use_vref; 349*bf394cc8SAriana Lazar }; 350*bf394cc8SAriana Lazar 351*bf394cc8SAriana Lazar static const struct regmap_range mcp47feb02_readable_ranges[] = { 352*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR), 353*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_NV_DAC0_REG_ADDR, MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR), 354*bf394cc8SAriana Lazar }; 355*bf394cc8SAriana Lazar 356*bf394cc8SAriana Lazar static const struct regmap_range mcp47feb02_writable_ranges[] = { 357*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR), 358*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_NV_DAC0_REG_ADDR, MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR), 359*bf394cc8SAriana Lazar }; 360*bf394cc8SAriana Lazar 361*bf394cc8SAriana Lazar static const struct regmap_range mcp47feb02_volatile_ranges[] = { 362*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR), 363*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_NV_DAC0_REG_ADDR, MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR), 364*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR), 365*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_NV_DAC0_REG_ADDR, MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR), 366*bf394cc8SAriana Lazar }; 367*bf394cc8SAriana Lazar 368*bf394cc8SAriana Lazar static const struct regmap_access_table mcp47feb02_readable_table = { 369*bf394cc8SAriana Lazar .yes_ranges = mcp47feb02_readable_ranges, 370*bf394cc8SAriana Lazar .n_yes_ranges = ARRAY_SIZE(mcp47feb02_readable_ranges), 371*bf394cc8SAriana Lazar }; 372*bf394cc8SAriana Lazar 373*bf394cc8SAriana Lazar static const struct regmap_access_table mcp47feb02_writable_table = { 374*bf394cc8SAriana Lazar .yes_ranges = mcp47feb02_writable_ranges, 375*bf394cc8SAriana Lazar .n_yes_ranges = ARRAY_SIZE(mcp47feb02_writable_ranges), 376*bf394cc8SAriana Lazar }; 377*bf394cc8SAriana Lazar 378*bf394cc8SAriana Lazar static const struct regmap_access_table mcp47feb02_volatile_table = { 379*bf394cc8SAriana Lazar .yes_ranges = mcp47feb02_volatile_ranges, 380*bf394cc8SAriana Lazar .n_yes_ranges = ARRAY_SIZE(mcp47feb02_volatile_ranges), 381*bf394cc8SAriana Lazar }; 382*bf394cc8SAriana Lazar 383*bf394cc8SAriana Lazar static const struct regmap_config mcp47feb02_regmap_config = { 384*bf394cc8SAriana Lazar .name = "mcp47feb02_regmap", 385*bf394cc8SAriana Lazar .reg_bits = 8, 386*bf394cc8SAriana Lazar .val_bits = 16, 387*bf394cc8SAriana Lazar .rd_table = &mcp47feb02_readable_table, 388*bf394cc8SAriana Lazar .wr_table = &mcp47feb02_writable_table, 389*bf394cc8SAriana Lazar .volatile_table = &mcp47feb02_volatile_table, 390*bf394cc8SAriana Lazar .max_register = MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR, 391*bf394cc8SAriana Lazar .read_flag_mask = READFLAG_MASK, 392*bf394cc8SAriana Lazar .cache_type = REGCACHE_MAPLE, 393*bf394cc8SAriana Lazar .val_format_endian = REGMAP_ENDIAN_BIG, 394*bf394cc8SAriana Lazar }; 395*bf394cc8SAriana Lazar 396*bf394cc8SAriana Lazar /* For devices that doesn't have nonvolatile memory */ 397*bf394cc8SAriana Lazar static const struct regmap_range mcp47fvb02_readable_ranges[] = { 398*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR), 399*bf394cc8SAriana Lazar }; 400*bf394cc8SAriana Lazar 401*bf394cc8SAriana Lazar static const struct regmap_range mcp47fvb02_writable_ranges[] = { 402*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR), 403*bf394cc8SAriana Lazar }; 404*bf394cc8SAriana Lazar 405*bf394cc8SAriana Lazar static const struct regmap_range mcp47fvb02_volatile_ranges[] = { 406*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR), 407*bf394cc8SAriana Lazar regmap_reg_range(MCP47FEB02_DAC0_REG_ADDR, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR), 408*bf394cc8SAriana Lazar }; 409*bf394cc8SAriana Lazar 410*bf394cc8SAriana Lazar static const struct regmap_access_table mcp47fvb02_readable_table = { 411*bf394cc8SAriana Lazar .yes_ranges = mcp47fvb02_readable_ranges, 412*bf394cc8SAriana Lazar .n_yes_ranges = ARRAY_SIZE(mcp47fvb02_readable_ranges), 413*bf394cc8SAriana Lazar }; 414*bf394cc8SAriana Lazar 415*bf394cc8SAriana Lazar static const struct regmap_access_table mcp47fvb02_writable_table = { 416*bf394cc8SAriana Lazar .yes_ranges = mcp47fvb02_writable_ranges, 417*bf394cc8SAriana Lazar .n_yes_ranges = ARRAY_SIZE(mcp47fvb02_writable_ranges), 418*bf394cc8SAriana Lazar }; 419*bf394cc8SAriana Lazar 420*bf394cc8SAriana Lazar static const struct regmap_access_table mcp47fvb02_volatile_table = { 421*bf394cc8SAriana Lazar .yes_ranges = mcp47fvb02_volatile_ranges, 422*bf394cc8SAriana Lazar .n_yes_ranges = ARRAY_SIZE(mcp47fvb02_volatile_ranges), 423*bf394cc8SAriana Lazar }; 424*bf394cc8SAriana Lazar 425*bf394cc8SAriana Lazar static const struct regmap_config mcp47fvb02_regmap_config = { 426*bf394cc8SAriana Lazar .name = "mcp47fvb02_regmap", 427*bf394cc8SAriana Lazar .reg_bits = 8, 428*bf394cc8SAriana Lazar .val_bits = 16, 429*bf394cc8SAriana Lazar .rd_table = &mcp47fvb02_readable_table, 430*bf394cc8SAriana Lazar .wr_table = &mcp47fvb02_writable_table, 431*bf394cc8SAriana Lazar .volatile_table = &mcp47fvb02_volatile_table, 432*bf394cc8SAriana Lazar .max_register = MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR, 433*bf394cc8SAriana Lazar .read_flag_mask = READFLAG_MASK, 434*bf394cc8SAriana Lazar .cache_type = REGCACHE_MAPLE, 435*bf394cc8SAriana Lazar .val_format_endian = REGMAP_ENDIAN_BIG, 436*bf394cc8SAriana Lazar }; 437*bf394cc8SAriana Lazar 438*bf394cc8SAriana Lazar static int mcp47feb02_write_to_eeprom(struct mcp47feb02_data *data, unsigned int reg, 439*bf394cc8SAriana Lazar unsigned int val) 440*bf394cc8SAriana Lazar { 441*bf394cc8SAriana Lazar int eewa_val, ret; 442*bf394cc8SAriana Lazar 443*bf394cc8SAriana Lazar /* 444*bf394cc8SAriana Lazar * Wait until the currently occurring EEPROM Write Cycle is completed. 445*bf394cc8SAriana Lazar * Only serial commands to the volatile memory are allowed. 446*bf394cc8SAriana Lazar */ 447*bf394cc8SAriana Lazar guard(mutex)(&data->lock); 448*bf394cc8SAriana Lazar 449*bf394cc8SAriana Lazar ret = regmap_read_poll_timeout(data->regmap, MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR, 450*bf394cc8SAriana Lazar eewa_val, 451*bf394cc8SAriana Lazar !(eewa_val & MCP47FEB02_GAIN_BIT_STATUS_EEWA_MASK), 452*bf394cc8SAriana Lazar USEC_PER_MSEC, USEC_PER_MSEC * 5); 453*bf394cc8SAriana Lazar if (ret) 454*bf394cc8SAriana Lazar return ret; 455*bf394cc8SAriana Lazar 456*bf394cc8SAriana Lazar return regmap_write(data->regmap, reg, val); 457*bf394cc8SAriana Lazar } 458*bf394cc8SAriana Lazar 459*bf394cc8SAriana Lazar static ssize_t store_eeprom_store(struct device *dev, struct device_attribute *attr, 460*bf394cc8SAriana Lazar const char *buf, size_t len) 461*bf394cc8SAriana Lazar { 462*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(dev_to_iio_dev(dev)); 463*bf394cc8SAriana Lazar unsigned int i, val, val1, eewa_val; 464*bf394cc8SAriana Lazar bool state; 465*bf394cc8SAriana Lazar int ret; 466*bf394cc8SAriana Lazar 467*bf394cc8SAriana Lazar ret = kstrtobool(buf, &state); 468*bf394cc8SAriana Lazar if (ret) 469*bf394cc8SAriana Lazar return ret; 470*bf394cc8SAriana Lazar 471*bf394cc8SAriana Lazar if (!state) 472*bf394cc8SAriana Lazar return 0; 473*bf394cc8SAriana Lazar 474*bf394cc8SAriana Lazar /* 475*bf394cc8SAriana Lazar * Verify DAC Wiper and DAC Configuration are unlocked. If both are disabled, 476*bf394cc8SAriana Lazar * writing to EEPROM is available. 477*bf394cc8SAriana Lazar */ 478*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, MCP47FEB02_WIPERLOCK_STATUS_REG_ADDR, &val); 479*bf394cc8SAriana Lazar if (ret) 480*bf394cc8SAriana Lazar return ret; 481*bf394cc8SAriana Lazar 482*bf394cc8SAriana Lazar if (val) { 483*bf394cc8SAriana Lazar dev_err(dev, "DAC Wiper and DAC Configuration not are unlocked.\n"); 484*bf394cc8SAriana Lazar return -EINVAL; 485*bf394cc8SAriana Lazar } 486*bf394cc8SAriana Lazar 487*bf394cc8SAriana Lazar for_each_set_bit(i, &data->active_channels_mask, data->phys_channels) { 488*bf394cc8SAriana Lazar ret = mcp47feb02_write_to_eeprom(data, NV_REG_ADDR(i), 489*bf394cc8SAriana Lazar data->chdata[i].dac_data); 490*bf394cc8SAriana Lazar if (ret) 491*bf394cc8SAriana Lazar return ret; 492*bf394cc8SAriana Lazar } 493*bf394cc8SAriana Lazar 494*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, MCP47FEB02_VREF_REG_ADDR, &val); 495*bf394cc8SAriana Lazar if (ret) 496*bf394cc8SAriana Lazar return ret; 497*bf394cc8SAriana Lazar 498*bf394cc8SAriana Lazar ret = mcp47feb02_write_to_eeprom(data, MCP47FEB02_NV_VREF_REG_ADDR, val); 499*bf394cc8SAriana Lazar if (ret) 500*bf394cc8SAriana Lazar return ret; 501*bf394cc8SAriana Lazar 502*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, MCP47FEB02_POWER_DOWN_REG_ADDR, &val); 503*bf394cc8SAriana Lazar if (ret) 504*bf394cc8SAriana Lazar return ret; 505*bf394cc8SAriana Lazar 506*bf394cc8SAriana Lazar ret = mcp47feb02_write_to_eeprom(data, MCP47FEB02_NV_POWER_DOWN_REG_ADDR, val); 507*bf394cc8SAriana Lazar if (ret) 508*bf394cc8SAriana Lazar return ret; 509*bf394cc8SAriana Lazar 510*bf394cc8SAriana Lazar ret = regmap_read_poll_timeout(data->regmap, MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR, eewa_val, 511*bf394cc8SAriana Lazar !(eewa_val & MCP47FEB02_GAIN_BIT_STATUS_EEWA_MASK), 512*bf394cc8SAriana Lazar USEC_PER_MSEC, USEC_PER_MSEC * 5); 513*bf394cc8SAriana Lazar if (ret) 514*bf394cc8SAriana Lazar return ret; 515*bf394cc8SAriana Lazar 516*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR, &val); 517*bf394cc8SAriana Lazar if (ret) 518*bf394cc8SAriana Lazar return ret; 519*bf394cc8SAriana Lazar 520*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR, &val1); 521*bf394cc8SAriana Lazar if (ret) 522*bf394cc8SAriana Lazar return ret; 523*bf394cc8SAriana Lazar 524*bf394cc8SAriana Lazar ret = mcp47feb02_write_to_eeprom(data, MCP47FEB02_NV_GAIN_CTRL_I2C_SLAVE_REG_ADDR, 525*bf394cc8SAriana Lazar (val1 & MCP47FEB02_GAIN_BITS_MASK) | 526*bf394cc8SAriana Lazar (val & MCP47FEB02_NV_I2C_SLAVE_ADDR_MASK)); 527*bf394cc8SAriana Lazar if (ret) 528*bf394cc8SAriana Lazar return ret; 529*bf394cc8SAriana Lazar 530*bf394cc8SAriana Lazar return len; 531*bf394cc8SAriana Lazar } 532*bf394cc8SAriana Lazar 533*bf394cc8SAriana Lazar static IIO_DEVICE_ATTR_WO(store_eeprom, 0); 534*bf394cc8SAriana Lazar 535*bf394cc8SAriana Lazar static struct attribute *mcp47feb02_attributes[] = { 536*bf394cc8SAriana Lazar &iio_dev_attr_store_eeprom.dev_attr.attr, 537*bf394cc8SAriana Lazar NULL 538*bf394cc8SAriana Lazar }; 539*bf394cc8SAriana Lazar 540*bf394cc8SAriana Lazar static const struct attribute_group mcp47feb02_attribute_group = { 541*bf394cc8SAriana Lazar .attrs = mcp47feb02_attributes, 542*bf394cc8SAriana Lazar }; 543*bf394cc8SAriana Lazar 544*bf394cc8SAriana Lazar static int mcp47feb02_suspend(struct device *dev) 545*bf394cc8SAriana Lazar { 546*bf394cc8SAriana Lazar struct iio_dev *indio_dev = dev_get_drvdata(dev); 547*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 548*bf394cc8SAriana Lazar int ret; 549*bf394cc8SAriana Lazar u8 ch; 550*bf394cc8SAriana Lazar 551*bf394cc8SAriana Lazar guard(mutex)(&data->lock); 552*bf394cc8SAriana Lazar 553*bf394cc8SAriana Lazar for_each_set_bit(ch, &data->active_channels_mask, data->phys_channels) { 554*bf394cc8SAriana Lazar u8 pd_mode; 555*bf394cc8SAriana Lazar 556*bf394cc8SAriana Lazar data->chdata[ch].powerdown = true; 557*bf394cc8SAriana Lazar pd_mode = data->chdata[ch].powerdown_mode + 1; 558*bf394cc8SAriana Lazar ret = regmap_update_bits(data->regmap, MCP47FEB02_POWER_DOWN_REG_ADDR, 559*bf394cc8SAriana Lazar DAC_CTRL_MASK(ch), DAC_CTRL_VAL(ch, pd_mode)); 560*bf394cc8SAriana Lazar if (ret) 561*bf394cc8SAriana Lazar return ret; 562*bf394cc8SAriana Lazar 563*bf394cc8SAriana Lazar ret = regmap_write(data->regmap, REG_ADDR(ch), data->chdata[ch].dac_data); 564*bf394cc8SAriana Lazar if (ret) 565*bf394cc8SAriana Lazar return ret; 566*bf394cc8SAriana Lazar } 567*bf394cc8SAriana Lazar 568*bf394cc8SAriana Lazar return 0; 569*bf394cc8SAriana Lazar } 570*bf394cc8SAriana Lazar 571*bf394cc8SAriana Lazar static int mcp47feb02_resume(struct device *dev) 572*bf394cc8SAriana Lazar { 573*bf394cc8SAriana Lazar struct iio_dev *indio_dev = dev_get_drvdata(dev); 574*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 575*bf394cc8SAriana Lazar u8 ch; 576*bf394cc8SAriana Lazar 577*bf394cc8SAriana Lazar guard(mutex)(&data->lock); 578*bf394cc8SAriana Lazar 579*bf394cc8SAriana Lazar for_each_set_bit(ch, &data->active_channels_mask, data->phys_channels) { 580*bf394cc8SAriana Lazar u8 pd_mode; 581*bf394cc8SAriana Lazar int ret; 582*bf394cc8SAriana Lazar 583*bf394cc8SAriana Lazar data->chdata[ch].powerdown = false; 584*bf394cc8SAriana Lazar pd_mode = data->chdata[ch].powerdown_mode + 1; 585*bf394cc8SAriana Lazar 586*bf394cc8SAriana Lazar ret = regmap_write(data->regmap, REG_ADDR(ch), data->chdata[ch].dac_data); 587*bf394cc8SAriana Lazar if (ret) 588*bf394cc8SAriana Lazar return ret; 589*bf394cc8SAriana Lazar 590*bf394cc8SAriana Lazar ret = regmap_update_bits(data->regmap, MCP47FEB02_VREF_REG_ADDR, 591*bf394cc8SAriana Lazar DAC_CTRL_MASK(ch), DAC_CTRL_VAL(ch, pd_mode)); 592*bf394cc8SAriana Lazar if (ret) 593*bf394cc8SAriana Lazar return ret; 594*bf394cc8SAriana Lazar 595*bf394cc8SAriana Lazar ret = regmap_update_bits(data->regmap, MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR, 596*bf394cc8SAriana Lazar DAC_GAIN_MASK(ch), 597*bf394cc8SAriana Lazar DAC_GAIN_VAL(ch, data->chdata[ch].use_2x_gain)); 598*bf394cc8SAriana Lazar if (ret) 599*bf394cc8SAriana Lazar return ret; 600*bf394cc8SAriana Lazar 601*bf394cc8SAriana Lazar ret = regmap_update_bits(data->regmap, MCP47FEB02_POWER_DOWN_REG_ADDR, 602*bf394cc8SAriana Lazar DAC_CTRL_MASK(ch), 603*bf394cc8SAriana Lazar DAC_CTRL_VAL(ch, MCP47FEB02_NORMAL_OPERATION)); 604*bf394cc8SAriana Lazar if (ret) 605*bf394cc8SAriana Lazar return ret; 606*bf394cc8SAriana Lazar } 607*bf394cc8SAriana Lazar 608*bf394cc8SAriana Lazar return 0; 609*bf394cc8SAriana Lazar } 610*bf394cc8SAriana Lazar 611*bf394cc8SAriana Lazar static int mcp47feb02_get_powerdown_mode(struct iio_dev *indio_dev, 612*bf394cc8SAriana Lazar const struct iio_chan_spec *chan) 613*bf394cc8SAriana Lazar { 614*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 615*bf394cc8SAriana Lazar 616*bf394cc8SAriana Lazar return data->chdata[chan->address].powerdown_mode; 617*bf394cc8SAriana Lazar } 618*bf394cc8SAriana Lazar 619*bf394cc8SAriana Lazar static int mcp47feb02_set_powerdown_mode(struct iio_dev *indio_dev, const struct iio_chan_spec *ch, 620*bf394cc8SAriana Lazar unsigned int mode) 621*bf394cc8SAriana Lazar { 622*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 623*bf394cc8SAriana Lazar 624*bf394cc8SAriana Lazar data->chdata[ch->address].powerdown_mode = mode; 625*bf394cc8SAriana Lazar 626*bf394cc8SAriana Lazar return 0; 627*bf394cc8SAriana Lazar } 628*bf394cc8SAriana Lazar 629*bf394cc8SAriana Lazar static ssize_t mcp47feb02_read_powerdown(struct iio_dev *indio_dev, uintptr_t private, 630*bf394cc8SAriana Lazar const struct iio_chan_spec *ch, char *buf) 631*bf394cc8SAriana Lazar { 632*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 633*bf394cc8SAriana Lazar 634*bf394cc8SAriana Lazar /* Print if channel is in a power-down mode or not */ 635*bf394cc8SAriana Lazar return sysfs_emit(buf, "%d\n", data->chdata[ch->address].powerdown); 636*bf394cc8SAriana Lazar } 637*bf394cc8SAriana Lazar 638*bf394cc8SAriana Lazar static ssize_t mcp47feb02_write_powerdown(struct iio_dev *indio_dev, uintptr_t private, 639*bf394cc8SAriana Lazar const struct iio_chan_spec *ch, const char *buf, 640*bf394cc8SAriana Lazar size_t len) 641*bf394cc8SAriana Lazar { 642*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 643*bf394cc8SAriana Lazar u32 reg = ch->address; 644*bf394cc8SAriana Lazar u8 tmp_pd_mode; 645*bf394cc8SAriana Lazar bool state; 646*bf394cc8SAriana Lazar int ret; 647*bf394cc8SAriana Lazar 648*bf394cc8SAriana Lazar guard(mutex)(&data->lock); 649*bf394cc8SAriana Lazar 650*bf394cc8SAriana Lazar ret = kstrtobool(buf, &state); 651*bf394cc8SAriana Lazar if (ret) 652*bf394cc8SAriana Lazar return ret; 653*bf394cc8SAriana Lazar 654*bf394cc8SAriana Lazar /* 655*bf394cc8SAriana Lazar * Set the channel to the specified power-down mode. Exiting power-down mode 656*bf394cc8SAriana Lazar * requires writing normal operation mode (0) to the channel-specific register bits. 657*bf394cc8SAriana Lazar */ 658*bf394cc8SAriana Lazar tmp_pd_mode = state ? (data->chdata[reg].powerdown_mode + 1) : MCP47FEB02_NORMAL_OPERATION; 659*bf394cc8SAriana Lazar ret = regmap_update_bits(data->regmap, MCP47FEB02_POWER_DOWN_REG_ADDR, 660*bf394cc8SAriana Lazar DAC_CTRL_MASK(reg), DAC_CTRL_VAL(reg, tmp_pd_mode)); 661*bf394cc8SAriana Lazar if (ret) 662*bf394cc8SAriana Lazar return ret; 663*bf394cc8SAriana Lazar 664*bf394cc8SAriana Lazar data->chdata[reg].powerdown = state; 665*bf394cc8SAriana Lazar 666*bf394cc8SAriana Lazar return len; 667*bf394cc8SAriana Lazar } 668*bf394cc8SAriana Lazar 669*bf394cc8SAriana Lazar static DEFINE_SIMPLE_DEV_PM_OPS(mcp47feb02_pm_ops, mcp47feb02_suspend, mcp47feb02_resume); 670*bf394cc8SAriana Lazar 671*bf394cc8SAriana Lazar static const struct iio_enum mcp47febxx_powerdown_mode_enum = { 672*bf394cc8SAriana Lazar .items = mcp47feb02_powerdown_modes, 673*bf394cc8SAriana Lazar .num_items = ARRAY_SIZE(mcp47feb02_powerdown_modes), 674*bf394cc8SAriana Lazar .get = mcp47feb02_get_powerdown_mode, 675*bf394cc8SAriana Lazar .set = mcp47feb02_set_powerdown_mode, 676*bf394cc8SAriana Lazar }; 677*bf394cc8SAriana Lazar 678*bf394cc8SAriana Lazar static const struct iio_chan_spec_ext_info mcp47feb02_ext_info[] = { 679*bf394cc8SAriana Lazar { 680*bf394cc8SAriana Lazar .name = "powerdown", 681*bf394cc8SAriana Lazar .read = mcp47feb02_read_powerdown, 682*bf394cc8SAriana Lazar .write = mcp47feb02_write_powerdown, 683*bf394cc8SAriana Lazar .shared = IIO_SEPARATE, 684*bf394cc8SAriana Lazar }, 685*bf394cc8SAriana Lazar IIO_ENUM("powerdown_mode", IIO_SEPARATE, &mcp47febxx_powerdown_mode_enum), 686*bf394cc8SAriana Lazar IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &mcp47febxx_powerdown_mode_enum), 687*bf394cc8SAriana Lazar { } 688*bf394cc8SAriana Lazar }; 689*bf394cc8SAriana Lazar 690*bf394cc8SAriana Lazar static const struct iio_chan_spec mcp47febxx_ch_template = { 691*bf394cc8SAriana Lazar .type = IIO_VOLTAGE, 692*bf394cc8SAriana Lazar .output = 1, 693*bf394cc8SAriana Lazar .indexed = 1, 694*bf394cc8SAriana Lazar .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE), 695*bf394cc8SAriana Lazar .info_mask_separate_available = BIT(IIO_CHAN_INFO_SCALE), 696*bf394cc8SAriana Lazar .ext_info = mcp47feb02_ext_info, 697*bf394cc8SAriana Lazar }; 698*bf394cc8SAriana Lazar 699*bf394cc8SAriana Lazar static void mcp47feb02_init_scale(struct mcp47feb02_data *data, enum mcp47feb02_scale scale, 700*bf394cc8SAriana Lazar int vref_mV, int scale_avail[]) 701*bf394cc8SAriana Lazar { 702*bf394cc8SAriana Lazar u32 value_micro, value_int; 703*bf394cc8SAriana Lazar u64 tmp; 704*bf394cc8SAriana Lazar 705*bf394cc8SAriana Lazar /* vref_mV should not be negative */ 706*bf394cc8SAriana Lazar tmp = (u64)vref_mV * MICRO >> data->chip_features->resolution; 707*bf394cc8SAriana Lazar value_int = div_u64_rem(tmp, MICRO, &value_micro); 708*bf394cc8SAriana Lazar scale_avail[scale * 2] = value_int; 709*bf394cc8SAriana Lazar scale_avail[scale * 2 + 1] = value_micro; 710*bf394cc8SAriana Lazar } 711*bf394cc8SAriana Lazar 712*bf394cc8SAriana Lazar static int mcp47feb02_init_scales_avail(struct mcp47feb02_data *data, int vdd_mV, 713*bf394cc8SAriana Lazar int vref_mV, int vref1_mV) 714*bf394cc8SAriana Lazar { 715*bf394cc8SAriana Lazar struct device *dev = regmap_get_device(data->regmap); 716*bf394cc8SAriana Lazar int tmp_vref; 717*bf394cc8SAriana Lazar 718*bf394cc8SAriana Lazar mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale); 719*bf394cc8SAriana Lazar 720*bf394cc8SAriana Lazar if (data->use_vref) 721*bf394cc8SAriana Lazar tmp_vref = vref_mV; 722*bf394cc8SAriana Lazar else 723*bf394cc8SAriana Lazar tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV; 724*bf394cc8SAriana Lazar 725*bf394cc8SAriana Lazar mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, tmp_vref, data->scale); 726*bf394cc8SAriana Lazar mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, tmp_vref * 2, data->scale); 727*bf394cc8SAriana Lazar 728*bf394cc8SAriana Lazar if (data->phys_channels >= 4) { 729*bf394cc8SAriana Lazar mcp47feb02_init_scale(data, MCP47FEB02_SCALE_VDD, vdd_mV, data->scale_1); 730*bf394cc8SAriana Lazar 731*bf394cc8SAriana Lazar if (data->use_vref1 && vref1_mV <= 0) 732*bf394cc8SAriana Lazar return dev_err_probe(dev, vref1_mV, "Invalid voltage for Vref1\n"); 733*bf394cc8SAriana Lazar 734*bf394cc8SAriana Lazar if (data->use_vref1) 735*bf394cc8SAriana Lazar tmp_vref = vref1_mV; 736*bf394cc8SAriana Lazar else 737*bf394cc8SAriana Lazar tmp_vref = MCP47FEB02_INTERNAL_BAND_GAP_mV; 738*bf394cc8SAriana Lazar 739*bf394cc8SAriana Lazar mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X1, 740*bf394cc8SAriana Lazar tmp_vref, data->scale_1); 741*bf394cc8SAriana Lazar mcp47feb02_init_scale(data, MCP47FEB02_SCALE_GAIN_X2, 742*bf394cc8SAriana Lazar tmp_vref * 2, data->scale_1); 743*bf394cc8SAriana Lazar } 744*bf394cc8SAriana Lazar 745*bf394cc8SAriana Lazar return 0; 746*bf394cc8SAriana Lazar } 747*bf394cc8SAriana Lazar 748*bf394cc8SAriana Lazar static int mcp47feb02_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, 749*bf394cc8SAriana Lazar const int **vals, int *type, int *length, long info) 750*bf394cc8SAriana Lazar { 751*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 752*bf394cc8SAriana Lazar 753*bf394cc8SAriana Lazar switch (info) { 754*bf394cc8SAriana Lazar case IIO_CHAN_INFO_SCALE: 755*bf394cc8SAriana Lazar switch (ch->type) { 756*bf394cc8SAriana Lazar case IIO_VOLTAGE: 757*bf394cc8SAriana Lazar if (data->phys_channels >= 4 && (ch->address % 2)) 758*bf394cc8SAriana Lazar *vals = data->scale_1; 759*bf394cc8SAriana Lazar else 760*bf394cc8SAriana Lazar *vals = data->scale; 761*bf394cc8SAriana Lazar 762*bf394cc8SAriana Lazar *length = 2 * MCP47FEB02_MAX_SCALES_CH; 763*bf394cc8SAriana Lazar *type = IIO_VAL_INT_PLUS_MICRO; 764*bf394cc8SAriana Lazar return IIO_AVAIL_LIST; 765*bf394cc8SAriana Lazar default: 766*bf394cc8SAriana Lazar return -EINVAL; 767*bf394cc8SAriana Lazar } 768*bf394cc8SAriana Lazar default: 769*bf394cc8SAriana Lazar return -EINVAL; 770*bf394cc8SAriana Lazar } 771*bf394cc8SAriana Lazar } 772*bf394cc8SAriana Lazar 773*bf394cc8SAriana Lazar static void mcp47feb02_get_scale(int ch, struct mcp47feb02_data *data, int *val, int *val2) 774*bf394cc8SAriana Lazar { 775*bf394cc8SAriana Lazar enum mcp47feb02_scale current_scale; 776*bf394cc8SAriana Lazar 777*bf394cc8SAriana Lazar if (data->chdata[ch].ref_mode == MCP47FEB02_VREF_VDD) 778*bf394cc8SAriana Lazar current_scale = MCP47FEB02_SCALE_VDD; 779*bf394cc8SAriana Lazar else if (data->chdata[ch].use_2x_gain) 780*bf394cc8SAriana Lazar current_scale = MCP47FEB02_SCALE_GAIN_X2; 781*bf394cc8SAriana Lazar else 782*bf394cc8SAriana Lazar current_scale = MCP47FEB02_SCALE_GAIN_X1; 783*bf394cc8SAriana Lazar 784*bf394cc8SAriana Lazar if (data->phys_channels >= 4 && (ch % 2)) { 785*bf394cc8SAriana Lazar *val = data->scale_1[current_scale * 2]; 786*bf394cc8SAriana Lazar *val2 = data->scale_1[current_scale * 2 + 1]; 787*bf394cc8SAriana Lazar } else { 788*bf394cc8SAriana Lazar *val = data->scale[current_scale * 2]; 789*bf394cc8SAriana Lazar *val2 = data->scale[current_scale * 2 + 1]; 790*bf394cc8SAriana Lazar } 791*bf394cc8SAriana Lazar } 792*bf394cc8SAriana Lazar 793*bf394cc8SAriana Lazar static int mcp47feb02_check_scale(struct mcp47feb02_data *data, int val, int val2, int scale[]) 794*bf394cc8SAriana Lazar { 795*bf394cc8SAriana Lazar unsigned int i; 796*bf394cc8SAriana Lazar 797*bf394cc8SAriana Lazar for (i = 0; i < MCP47FEB02_MAX_SCALES_CH; i++) { 798*bf394cc8SAriana Lazar if (scale[i * 2] == val && scale[i * 2 + 1] == val2) 799*bf394cc8SAriana Lazar return i; 800*bf394cc8SAriana Lazar } 801*bf394cc8SAriana Lazar 802*bf394cc8SAriana Lazar return -EINVAL; 803*bf394cc8SAriana Lazar } 804*bf394cc8SAriana Lazar 805*bf394cc8SAriana Lazar static int mcp47feb02_ch_scale(struct mcp47feb02_data *data, int ch, int scale) 806*bf394cc8SAriana Lazar { 807*bf394cc8SAriana Lazar int tmp_val, ret; 808*bf394cc8SAriana Lazar 809*bf394cc8SAriana Lazar if (scale == MCP47FEB02_SCALE_VDD) { 810*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_VREF_VDD; 811*bf394cc8SAriana Lazar } else if (data->phys_channels >= 4 && (ch % 2)) { 812*bf394cc8SAriana Lazar if (data->use_vref1) { 813*bf394cc8SAriana Lazar if (data->vref1_buffered) 814*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_EXTERNAL_VREF_BUFFERED; 815*bf394cc8SAriana Lazar else 816*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_EXTERNAL_VREF_UNBUFFERED; 817*bf394cc8SAriana Lazar } else { 818*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_INTERNAL_BAND_GAP; 819*bf394cc8SAriana Lazar } 820*bf394cc8SAriana Lazar } else if (data->use_vref) { 821*bf394cc8SAriana Lazar if (data->vref_buffered) 822*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_EXTERNAL_VREF_BUFFERED; 823*bf394cc8SAriana Lazar else 824*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_EXTERNAL_VREF_UNBUFFERED; 825*bf394cc8SAriana Lazar } else { 826*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_INTERNAL_BAND_GAP; 827*bf394cc8SAriana Lazar } 828*bf394cc8SAriana Lazar 829*bf394cc8SAriana Lazar ret = regmap_update_bits(data->regmap, MCP47FEB02_VREF_REG_ADDR, 830*bf394cc8SAriana Lazar DAC_CTRL_MASK(ch), DAC_CTRL_VAL(ch, tmp_val)); 831*bf394cc8SAriana Lazar if (ret) 832*bf394cc8SAriana Lazar return ret; 833*bf394cc8SAriana Lazar 834*bf394cc8SAriana Lazar data->chdata[ch].ref_mode = tmp_val; 835*bf394cc8SAriana Lazar 836*bf394cc8SAriana Lazar return 0; 837*bf394cc8SAriana Lazar } 838*bf394cc8SAriana Lazar 839*bf394cc8SAriana Lazar /* 840*bf394cc8SAriana Lazar * Setting the scale in order to choose between VDD and (Vref or Band Gap) from the user 841*bf394cc8SAriana Lazar * space. The VREF pin is either an input or an output, therefore the user cannot 842*bf394cc8SAriana Lazar * simultaneously connect an external voltage reference to the pin and select the 843*bf394cc8SAriana Lazar * internal Band Gap. 844*bf394cc8SAriana Lazar * When the DAC’s voltage reference is configured as the VREF pin, the pin is an input. 845*bf394cc8SAriana Lazar * When the DAC’s voltage reference is configured as the internal Band Gap, 846*bf394cc8SAriana Lazar * the VREF pin is an output. 847*bf394cc8SAriana Lazar * If Vref/Vref1 voltage is not available, then the internal Band Gap will be used 848*bf394cc8SAriana Lazar * to calculate the values for the scale. 849*bf394cc8SAriana Lazar */ 850*bf394cc8SAriana Lazar static int mcp47feb02_set_scale(struct mcp47feb02_data *data, int ch, int scale) 851*bf394cc8SAriana Lazar { 852*bf394cc8SAriana Lazar int tmp_val, ret; 853*bf394cc8SAriana Lazar 854*bf394cc8SAriana Lazar ret = mcp47feb02_ch_scale(data, ch, scale); 855*bf394cc8SAriana Lazar if (ret) 856*bf394cc8SAriana Lazar return ret; 857*bf394cc8SAriana Lazar 858*bf394cc8SAriana Lazar if (scale == MCP47FEB02_SCALE_GAIN_X2) 859*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_GAIN_BIT_X2; 860*bf394cc8SAriana Lazar else 861*bf394cc8SAriana Lazar tmp_val = MCP47FEB02_GAIN_BIT_X1; 862*bf394cc8SAriana Lazar 863*bf394cc8SAriana Lazar ret = regmap_update_bits(data->regmap, MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR, 864*bf394cc8SAriana Lazar DAC_GAIN_MASK(ch), DAC_GAIN_VAL(ch, tmp_val)); 865*bf394cc8SAriana Lazar if (ret) 866*bf394cc8SAriana Lazar return ret; 867*bf394cc8SAriana Lazar 868*bf394cc8SAriana Lazar data->chdata[ch].use_2x_gain = tmp_val; 869*bf394cc8SAriana Lazar 870*bf394cc8SAriana Lazar return 0; 871*bf394cc8SAriana Lazar } 872*bf394cc8SAriana Lazar 873*bf394cc8SAriana Lazar static int mcp47feb02_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, 874*bf394cc8SAriana Lazar int *val, int *val2, long mask) 875*bf394cc8SAriana Lazar { 876*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 877*bf394cc8SAriana Lazar int ret; 878*bf394cc8SAriana Lazar 879*bf394cc8SAriana Lazar switch (mask) { 880*bf394cc8SAriana Lazar case IIO_CHAN_INFO_RAW: 881*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, REG_ADDR(ch->address), val); 882*bf394cc8SAriana Lazar if (ret) 883*bf394cc8SAriana Lazar return ret; 884*bf394cc8SAriana Lazar return IIO_VAL_INT; 885*bf394cc8SAriana Lazar case IIO_CHAN_INFO_SCALE: 886*bf394cc8SAriana Lazar mcp47feb02_get_scale(ch->address, data, val, val2); 887*bf394cc8SAriana Lazar return IIO_VAL_INT_PLUS_MICRO; 888*bf394cc8SAriana Lazar default: 889*bf394cc8SAriana Lazar return -EINVAL; 890*bf394cc8SAriana Lazar } 891*bf394cc8SAriana Lazar } 892*bf394cc8SAriana Lazar 893*bf394cc8SAriana Lazar static int mcp47feb02_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, 894*bf394cc8SAriana Lazar int val, int val2, long mask) 895*bf394cc8SAriana Lazar { 896*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 897*bf394cc8SAriana Lazar int *tmp_scale, ret; 898*bf394cc8SAriana Lazar 899*bf394cc8SAriana Lazar guard(mutex)(&data->lock); 900*bf394cc8SAriana Lazar 901*bf394cc8SAriana Lazar switch (mask) { 902*bf394cc8SAriana Lazar case IIO_CHAN_INFO_RAW: 903*bf394cc8SAriana Lazar ret = regmap_write(data->regmap, REG_ADDR(ch->address), val); 904*bf394cc8SAriana Lazar if (ret) 905*bf394cc8SAriana Lazar return ret; 906*bf394cc8SAriana Lazar 907*bf394cc8SAriana Lazar data->chdata[ch->address].dac_data = val; 908*bf394cc8SAriana Lazar return 0; 909*bf394cc8SAriana Lazar case IIO_CHAN_INFO_SCALE: 910*bf394cc8SAriana Lazar if (data->phys_channels >= 4 && (ch->address % 2)) 911*bf394cc8SAriana Lazar tmp_scale = data->scale_1; 912*bf394cc8SAriana Lazar else 913*bf394cc8SAriana Lazar tmp_scale = data->scale; 914*bf394cc8SAriana Lazar 915*bf394cc8SAriana Lazar ret = mcp47feb02_check_scale(data, val, val2, tmp_scale); 916*bf394cc8SAriana Lazar if (ret < 0) 917*bf394cc8SAriana Lazar return ret; 918*bf394cc8SAriana Lazar 919*bf394cc8SAriana Lazar return mcp47feb02_set_scale(data, ch->address, ret); 920*bf394cc8SAriana Lazar default: 921*bf394cc8SAriana Lazar return -EINVAL; 922*bf394cc8SAriana Lazar } 923*bf394cc8SAriana Lazar } 924*bf394cc8SAriana Lazar 925*bf394cc8SAriana Lazar static int mcp47feb02_read_label(struct iio_dev *indio_dev, struct iio_chan_spec const *ch, 926*bf394cc8SAriana Lazar char *label) 927*bf394cc8SAriana Lazar { 928*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 929*bf394cc8SAriana Lazar 930*bf394cc8SAriana Lazar return sysfs_emit(label, "%s\n", data->labels[ch->address]); 931*bf394cc8SAriana Lazar } 932*bf394cc8SAriana Lazar 933*bf394cc8SAriana Lazar static const struct iio_info mcp47feb02_info = { 934*bf394cc8SAriana Lazar .read_raw = mcp47feb02_read_raw, 935*bf394cc8SAriana Lazar .write_raw = mcp47feb02_write_raw, 936*bf394cc8SAriana Lazar .read_label = mcp47feb02_read_label, 937*bf394cc8SAriana Lazar .read_avail = &mcp47feb02_read_avail, 938*bf394cc8SAriana Lazar .attrs = &mcp47feb02_attribute_group, 939*bf394cc8SAriana Lazar }; 940*bf394cc8SAriana Lazar 941*bf394cc8SAriana Lazar static const struct iio_info mcp47fvb02_info = { 942*bf394cc8SAriana Lazar .read_raw = mcp47feb02_read_raw, 943*bf394cc8SAriana Lazar .write_raw = mcp47feb02_write_raw, 944*bf394cc8SAriana Lazar .read_label = mcp47feb02_read_label, 945*bf394cc8SAriana Lazar .read_avail = &mcp47feb02_read_avail, 946*bf394cc8SAriana Lazar }; 947*bf394cc8SAriana Lazar 948*bf394cc8SAriana Lazar static int mcp47feb02_parse_fw(struct iio_dev *indio_dev, 949*bf394cc8SAriana Lazar const struct mcp47feb02_features *chip_features) 950*bf394cc8SAriana Lazar { 951*bf394cc8SAriana Lazar struct iio_chan_spec chanspec = mcp47febxx_ch_template; 952*bf394cc8SAriana Lazar struct mcp47feb02_data *data = iio_priv(indio_dev); 953*bf394cc8SAriana Lazar struct device *dev = regmap_get_device(data->regmap); 954*bf394cc8SAriana Lazar struct iio_chan_spec *channels; 955*bf394cc8SAriana Lazar u32 num_channels; 956*bf394cc8SAriana Lazar u8 chan_idx = 0; 957*bf394cc8SAriana Lazar 958*bf394cc8SAriana Lazar guard(mutex)(&data->lock); 959*bf394cc8SAriana Lazar 960*bf394cc8SAriana Lazar num_channels = device_get_child_node_count(dev); 961*bf394cc8SAriana Lazar if (num_channels > chip_features->phys_channels) 962*bf394cc8SAriana Lazar return dev_err_probe(dev, -EINVAL, "More channels than the chip supports\n"); 963*bf394cc8SAriana Lazar 964*bf394cc8SAriana Lazar if (!num_channels) 965*bf394cc8SAriana Lazar return dev_err_probe(dev, -EINVAL, "No channel specified in the devicetree.\n"); 966*bf394cc8SAriana Lazar 967*bf394cc8SAriana Lazar channels = devm_kcalloc(dev, num_channels, sizeof(*channels), GFP_KERNEL); 968*bf394cc8SAriana Lazar if (!channels) 969*bf394cc8SAriana Lazar return -ENOMEM; 970*bf394cc8SAriana Lazar 971*bf394cc8SAriana Lazar device_for_each_child_node_scoped(dev, child) { 972*bf394cc8SAriana Lazar u32 reg = 0; 973*bf394cc8SAriana Lazar int ret; 974*bf394cc8SAriana Lazar 975*bf394cc8SAriana Lazar ret = fwnode_property_read_u32(child, "reg", ®); 976*bf394cc8SAriana Lazar if (ret) 977*bf394cc8SAriana Lazar return dev_err_probe(dev, ret, "Invalid channel number\n"); 978*bf394cc8SAriana Lazar 979*bf394cc8SAriana Lazar if (reg >= chip_features->phys_channels) 980*bf394cc8SAriana Lazar return dev_err_probe(dev, -EINVAL, 981*bf394cc8SAriana Lazar "The index of the channels does not match the chip\n"); 982*bf394cc8SAriana Lazar 983*bf394cc8SAriana Lazar set_bit(reg, &data->active_channels_mask); 984*bf394cc8SAriana Lazar 985*bf394cc8SAriana Lazar ret = fwnode_property_read_string(child, "label", &data->labels[reg]); 986*bf394cc8SAriana Lazar if (ret) 987*bf394cc8SAriana Lazar return dev_err_probe(dev, ret, "%pfw: invalid label\n", 988*bf394cc8SAriana Lazar fwnode_get_name(child)); 989*bf394cc8SAriana Lazar 990*bf394cc8SAriana Lazar chanspec.address = reg; 991*bf394cc8SAriana Lazar chanspec.channel = reg; 992*bf394cc8SAriana Lazar channels[chan_idx] = chanspec; 993*bf394cc8SAriana Lazar chan_idx++; 994*bf394cc8SAriana Lazar } 995*bf394cc8SAriana Lazar 996*bf394cc8SAriana Lazar indio_dev->num_channels = num_channels; 997*bf394cc8SAriana Lazar indio_dev->channels = channels; 998*bf394cc8SAriana Lazar indio_dev->modes = INDIO_DIRECT_MODE; 999*bf394cc8SAriana Lazar data->phys_channels = chip_features->phys_channels; 1000*bf394cc8SAriana Lazar 1001*bf394cc8SAriana Lazar data->vref_buffered = device_property_read_bool(dev, "microchip,vref-buffered"); 1002*bf394cc8SAriana Lazar 1003*bf394cc8SAriana Lazar if (chip_features->have_ext_vref1) 1004*bf394cc8SAriana Lazar data->vref1_buffered = device_property_read_bool(dev, "microchip,vref1-buffered"); 1005*bf394cc8SAriana Lazar 1006*bf394cc8SAriana Lazar return 0; 1007*bf394cc8SAriana Lazar } 1008*bf394cc8SAriana Lazar 1009*bf394cc8SAriana Lazar static int mcp47feb02_init_ctrl_regs(struct mcp47feb02_data *data) 1010*bf394cc8SAriana Lazar { 1011*bf394cc8SAriana Lazar unsigned int i, vref_ch, gain_ch, pd_ch; 1012*bf394cc8SAriana Lazar int ret; 1013*bf394cc8SAriana Lazar 1014*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, MCP47FEB02_VREF_REG_ADDR, &vref_ch); 1015*bf394cc8SAriana Lazar if (ret) 1016*bf394cc8SAriana Lazar return ret; 1017*bf394cc8SAriana Lazar 1018*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, MCP47FEB02_GAIN_CTRL_STATUS_REG_ADDR, &gain_ch); 1019*bf394cc8SAriana Lazar if (ret) 1020*bf394cc8SAriana Lazar return ret; 1021*bf394cc8SAriana Lazar 1022*bf394cc8SAriana Lazar ret = regmap_read(data->regmap, MCP47FEB02_POWER_DOWN_REG_ADDR, &pd_ch); 1023*bf394cc8SAriana Lazar if (ret) 1024*bf394cc8SAriana Lazar return ret; 1025*bf394cc8SAriana Lazar 1026*bf394cc8SAriana Lazar gain_ch = gain_ch & MCP47FEB02_GAIN_BITS_MASK; 1027*bf394cc8SAriana Lazar for_each_set_bit(i, &data->active_channels_mask, data->phys_channels) { 1028*bf394cc8SAriana Lazar struct device *dev = regmap_get_device(data->regmap); 1029*bf394cc8SAriana Lazar unsigned int pd_tmp; 1030*bf394cc8SAriana Lazar 1031*bf394cc8SAriana Lazar data->chdata[i].ref_mode = (vref_ch >> (2 * i)) & MCP47FEB02_DAC_CTRL_MASK; 1032*bf394cc8SAriana Lazar data->chdata[i].use_2x_gain = (gain_ch >> i) & MCP47FEB02_GAIN_BIT_MASK; 1033*bf394cc8SAriana Lazar 1034*bf394cc8SAriana Lazar /* 1035*bf394cc8SAriana Lazar * Inform the user that the current voltage reference read from the volatile 1036*bf394cc8SAriana Lazar * register of the chip is different from the one specified in the device tree. 1037*bf394cc8SAriana Lazar * Considering that the user cannot have an external voltage reference connected 1038*bf394cc8SAriana Lazar * to the pin and select the internal Band Gap at the same time, in order to avoid 1039*bf394cc8SAriana Lazar * miscofiguring the reference voltage, the volatile register will not be written. 1040*bf394cc8SAriana Lazar * In order to overwrite the setting from volatile register with the one from the 1041*bf394cc8SAriana Lazar * device tree, the user needs to write the chosen scale. 1042*bf394cc8SAriana Lazar */ 1043*bf394cc8SAriana Lazar switch (data->chdata[i].ref_mode) { 1044*bf394cc8SAriana Lazar case MCP47FEB02_INTERNAL_BAND_GAP: 1045*bf394cc8SAriana Lazar if (data->phys_channels >= 4 && (i % 2) && data->use_vref1) { 1046*bf394cc8SAriana Lazar dev_dbg(dev, "ch[%u]: was configured to use internal band gap", i); 1047*bf394cc8SAriana Lazar dev_dbg(dev, "ch[%u]: reference voltage set to VREF1", i); 1048*bf394cc8SAriana Lazar break; 1049*bf394cc8SAriana Lazar } 1050*bf394cc8SAriana Lazar if ((data->phys_channels < 4 || (data->phys_channels >= 4 && !(i % 2))) && 1051*bf394cc8SAriana Lazar data->use_vref) { 1052*bf394cc8SAriana Lazar dev_dbg(dev, "ch[%u]: was configured to use internal band gap", i); 1053*bf394cc8SAriana Lazar dev_dbg(dev, "ch[%u]: reference voltage set to VREF", i); 1054*bf394cc8SAriana Lazar break; 1055*bf394cc8SAriana Lazar } 1056*bf394cc8SAriana Lazar break; 1057*bf394cc8SAriana Lazar case MCP47FEB02_EXTERNAL_VREF_UNBUFFERED: 1058*bf394cc8SAriana Lazar case MCP47FEB02_EXTERNAL_VREF_BUFFERED: 1059*bf394cc8SAriana Lazar if (data->phys_channels >= 4 && (i % 2) && !data->use_vref1) { 1060*bf394cc8SAriana Lazar dev_dbg(dev, "ch[%u]: was configured to use VREF1", i); 1061*bf394cc8SAriana Lazar dev_dbg(dev, 1062*bf394cc8SAriana Lazar "ch[%u]: reference voltage set to internal band gap", i); 1063*bf394cc8SAriana Lazar break; 1064*bf394cc8SAriana Lazar } 1065*bf394cc8SAriana Lazar if ((data->phys_channels < 4 || (data->phys_channels >= 4 && !(i % 2))) && 1066*bf394cc8SAriana Lazar !data->use_vref) { 1067*bf394cc8SAriana Lazar dev_dbg(dev, "ch[%u]: was configured to use VREF", i); 1068*bf394cc8SAriana Lazar dev_dbg(dev, 1069*bf394cc8SAriana Lazar "ch[%u]: reference voltage set to internal band gap", i); 1070*bf394cc8SAriana Lazar break; 1071*bf394cc8SAriana Lazar } 1072*bf394cc8SAriana Lazar break; 1073*bf394cc8SAriana Lazar } 1074*bf394cc8SAriana Lazar 1075*bf394cc8SAriana Lazar pd_tmp = (pd_ch >> (2 * i)) & MCP47FEB02_DAC_CTRL_MASK; 1076*bf394cc8SAriana Lazar data->chdata[i].powerdown_mode = pd_tmp ? (pd_tmp - 1) : pd_tmp; 1077*bf394cc8SAriana Lazar data->chdata[i].powerdown = !!(data->chdata[i].powerdown_mode); 1078*bf394cc8SAriana Lazar } 1079*bf394cc8SAriana Lazar 1080*bf394cc8SAriana Lazar return 0; 1081*bf394cc8SAriana Lazar } 1082*bf394cc8SAriana Lazar 1083*bf394cc8SAriana Lazar static int mcp47feb02_init_ch_scales(struct mcp47feb02_data *data, int vdd_mV, 1084*bf394cc8SAriana Lazar int vref_mV, int vref1_mV) 1085*bf394cc8SAriana Lazar { 1086*bf394cc8SAriana Lazar unsigned int i; 1087*bf394cc8SAriana Lazar 1088*bf394cc8SAriana Lazar for_each_set_bit(i, &data->active_channels_mask, data->phys_channels) { 1089*bf394cc8SAriana Lazar struct device *dev = regmap_get_device(data->regmap); 1090*bf394cc8SAriana Lazar int ret; 1091*bf394cc8SAriana Lazar 1092*bf394cc8SAriana Lazar ret = mcp47feb02_init_scales_avail(data, vdd_mV, vref_mV, vref1_mV); 1093*bf394cc8SAriana Lazar if (ret) 1094*bf394cc8SAriana Lazar return dev_err_probe(dev, ret, "failed to init scales for ch %u\n", i); 1095*bf394cc8SAriana Lazar } 1096*bf394cc8SAriana Lazar 1097*bf394cc8SAriana Lazar return 0; 1098*bf394cc8SAriana Lazar } 1099*bf394cc8SAriana Lazar 1100*bf394cc8SAriana Lazar static int mcp47feb02_probe(struct i2c_client *client) 1101*bf394cc8SAriana Lazar { 1102*bf394cc8SAriana Lazar const struct mcp47feb02_features *chip_features; 1103*bf394cc8SAriana Lazar struct device *dev = &client->dev; 1104*bf394cc8SAriana Lazar struct mcp47feb02_data *data; 1105*bf394cc8SAriana Lazar struct iio_dev *indio_dev; 1106*bf394cc8SAriana Lazar int vref1_mV = 0; 1107*bf394cc8SAriana Lazar int vref_mV = 0; 1108*bf394cc8SAriana Lazar int vdd_mV; 1109*bf394cc8SAriana Lazar int ret; 1110*bf394cc8SAriana Lazar 1111*bf394cc8SAriana Lazar indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 1112*bf394cc8SAriana Lazar if (!indio_dev) 1113*bf394cc8SAriana Lazar return -ENOMEM; 1114*bf394cc8SAriana Lazar 1115*bf394cc8SAriana Lazar data = iio_priv(indio_dev); 1116*bf394cc8SAriana Lazar chip_features = i2c_get_match_data(client); 1117*bf394cc8SAriana Lazar if (!chip_features) 1118*bf394cc8SAriana Lazar return -EINVAL; 1119*bf394cc8SAriana Lazar 1120*bf394cc8SAriana Lazar data->chip_features = chip_features; 1121*bf394cc8SAriana Lazar 1122*bf394cc8SAriana Lazar if (chip_features->have_eeprom) { 1123*bf394cc8SAriana Lazar data->regmap = devm_regmap_init_i2c(client, &mcp47feb02_regmap_config); 1124*bf394cc8SAriana Lazar indio_dev->info = &mcp47feb02_info; 1125*bf394cc8SAriana Lazar } else { 1126*bf394cc8SAriana Lazar data->regmap = devm_regmap_init_i2c(client, &mcp47fvb02_regmap_config); 1127*bf394cc8SAriana Lazar indio_dev->info = &mcp47fvb02_info; 1128*bf394cc8SAriana Lazar } 1129*bf394cc8SAriana Lazar if (IS_ERR(data->regmap)) 1130*bf394cc8SAriana Lazar return dev_err_probe(dev, PTR_ERR(data->regmap), "Error initializing i2c regmap\n"); 1131*bf394cc8SAriana Lazar 1132*bf394cc8SAriana Lazar indio_dev->name = chip_features->name; 1133*bf394cc8SAriana Lazar 1134*bf394cc8SAriana Lazar ret = mcp47feb02_parse_fw(indio_dev, chip_features); 1135*bf394cc8SAriana Lazar if (ret) 1136*bf394cc8SAriana Lazar return dev_err_probe(dev, ret, "Error parsing firmware data\n"); 1137*bf394cc8SAriana Lazar 1138*bf394cc8SAriana Lazar ret = devm_mutex_init(dev, &data->lock); 1139*bf394cc8SAriana Lazar if (ret) 1140*bf394cc8SAriana Lazar return ret; 1141*bf394cc8SAriana Lazar 1142*bf394cc8SAriana Lazar ret = devm_regulator_get_enable_read_voltage(dev, "vdd"); 1143*bf394cc8SAriana Lazar if (ret < 0) 1144*bf394cc8SAriana Lazar return ret; 1145*bf394cc8SAriana Lazar 1146*bf394cc8SAriana Lazar vdd_mV = ret / MILLI; 1147*bf394cc8SAriana Lazar 1148*bf394cc8SAriana Lazar ret = devm_regulator_get_enable_read_voltage(dev, "vref"); 1149*bf394cc8SAriana Lazar if (ret > 0) { 1150*bf394cc8SAriana Lazar vref_mV = ret / MILLI; 1151*bf394cc8SAriana Lazar data->use_vref = true; 1152*bf394cc8SAriana Lazar } else { 1153*bf394cc8SAriana Lazar dev_dbg(dev, "using internal band gap as voltage reference.\n"); 1154*bf394cc8SAriana Lazar dev_dbg(dev, "Vref is unavailable.\n"); 1155*bf394cc8SAriana Lazar } 1156*bf394cc8SAriana Lazar 1157*bf394cc8SAriana Lazar if (chip_features->have_ext_vref1) { 1158*bf394cc8SAriana Lazar ret = devm_regulator_get_enable_read_voltage(dev, "vref1"); 1159*bf394cc8SAriana Lazar if (ret > 0) { 1160*bf394cc8SAriana Lazar vref1_mV = ret / MILLI; 1161*bf394cc8SAriana Lazar data->use_vref1 = true; 1162*bf394cc8SAriana Lazar } else { 1163*bf394cc8SAriana Lazar dev_dbg(dev, "using internal band gap as voltage reference 1.\n"); 1164*bf394cc8SAriana Lazar dev_dbg(dev, "Vref1 is unavailable.\n"); 1165*bf394cc8SAriana Lazar } 1166*bf394cc8SAriana Lazar } 1167*bf394cc8SAriana Lazar 1168*bf394cc8SAriana Lazar ret = mcp47feb02_init_ctrl_regs(data); 1169*bf394cc8SAriana Lazar if (ret) 1170*bf394cc8SAriana Lazar return dev_err_probe(dev, ret, "Error initialising vref register\n"); 1171*bf394cc8SAriana Lazar 1172*bf394cc8SAriana Lazar ret = mcp47feb02_init_ch_scales(data, vdd_mV, vref_mV, vref1_mV); 1173*bf394cc8SAriana Lazar if (ret) 1174*bf394cc8SAriana Lazar return ret; 1175*bf394cc8SAriana Lazar 1176*bf394cc8SAriana Lazar return devm_iio_device_register(dev, indio_dev); 1177*bf394cc8SAriana Lazar } 1178*bf394cc8SAriana Lazar 1179*bf394cc8SAriana Lazar static const struct i2c_device_id mcp47feb02_id[] = { 1180*bf394cc8SAriana Lazar { "mcp47feb01", (kernel_ulong_t)&mcp47feb01_chip_features }, 1181*bf394cc8SAriana Lazar { "mcp47feb02", (kernel_ulong_t)&mcp47feb02_chip_features }, 1182*bf394cc8SAriana Lazar { "mcp47feb04", (kernel_ulong_t)&mcp47feb04_chip_features }, 1183*bf394cc8SAriana Lazar { "mcp47feb08", (kernel_ulong_t)&mcp47feb08_chip_features }, 1184*bf394cc8SAriana Lazar { "mcp47feb11", (kernel_ulong_t)&mcp47feb11_chip_features }, 1185*bf394cc8SAriana Lazar { "mcp47feb12", (kernel_ulong_t)&mcp47feb12_chip_features }, 1186*bf394cc8SAriana Lazar { "mcp47feb14", (kernel_ulong_t)&mcp47feb14_chip_features }, 1187*bf394cc8SAriana Lazar { "mcp47feb18", (kernel_ulong_t)&mcp47feb18_chip_features }, 1188*bf394cc8SAriana Lazar { "mcp47feb21", (kernel_ulong_t)&mcp47feb21_chip_features }, 1189*bf394cc8SAriana Lazar { "mcp47feb22", (kernel_ulong_t)&mcp47feb22_chip_features }, 1190*bf394cc8SAriana Lazar { "mcp47feb24", (kernel_ulong_t)&mcp47feb24_chip_features }, 1191*bf394cc8SAriana Lazar { "mcp47feb28", (kernel_ulong_t)&mcp47feb28_chip_features }, 1192*bf394cc8SAriana Lazar { "mcp47fvb01", (kernel_ulong_t)&mcp47fvb01_chip_features }, 1193*bf394cc8SAriana Lazar { "mcp47fvb02", (kernel_ulong_t)&mcp47fvb02_chip_features }, 1194*bf394cc8SAriana Lazar { "mcp47fvb04", (kernel_ulong_t)&mcp47fvb04_chip_features }, 1195*bf394cc8SAriana Lazar { "mcp47fvb08", (kernel_ulong_t)&mcp47fvb08_chip_features }, 1196*bf394cc8SAriana Lazar { "mcp47fvb11", (kernel_ulong_t)&mcp47fvb11_chip_features }, 1197*bf394cc8SAriana Lazar { "mcp47fvb12", (kernel_ulong_t)&mcp47fvb12_chip_features }, 1198*bf394cc8SAriana Lazar { "mcp47fvb14", (kernel_ulong_t)&mcp47fvb14_chip_features }, 1199*bf394cc8SAriana Lazar { "mcp47fvb18", (kernel_ulong_t)&mcp47fvb18_chip_features }, 1200*bf394cc8SAriana Lazar { "mcp47fvb21", (kernel_ulong_t)&mcp47fvb21_chip_features }, 1201*bf394cc8SAriana Lazar { "mcp47fvb22", (kernel_ulong_t)&mcp47fvb22_chip_features }, 1202*bf394cc8SAriana Lazar { "mcp47fvb24", (kernel_ulong_t)&mcp47fvb24_chip_features }, 1203*bf394cc8SAriana Lazar { "mcp47fvb28", (kernel_ulong_t)&mcp47fvb28_chip_features }, 1204*bf394cc8SAriana Lazar { } 1205*bf394cc8SAriana Lazar }; 1206*bf394cc8SAriana Lazar MODULE_DEVICE_TABLE(i2c, mcp47feb02_id); 1207*bf394cc8SAriana Lazar 1208*bf394cc8SAriana Lazar static const struct of_device_id mcp47feb02_of_match[] = { 1209*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb01", .data = &mcp47feb01_chip_features }, 1210*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb02", .data = &mcp47feb02_chip_features }, 1211*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb04", .data = &mcp47feb04_chip_features }, 1212*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb08", .data = &mcp47feb08_chip_features }, 1213*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb11", .data = &mcp47feb11_chip_features }, 1214*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb12", .data = &mcp47feb12_chip_features }, 1215*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb14", .data = &mcp47feb14_chip_features }, 1216*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb18", .data = &mcp47feb18_chip_features }, 1217*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb21", .data = &mcp47feb21_chip_features }, 1218*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb22", .data = &mcp47feb22_chip_features }, 1219*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb24", .data = &mcp47feb24_chip_features }, 1220*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47feb28", .data = &mcp47feb28_chip_features }, 1221*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb01", .data = &mcp47fvb01_chip_features }, 1222*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb02", .data = &mcp47fvb02_chip_features }, 1223*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb04", .data = &mcp47fvb04_chip_features }, 1224*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb08", .data = &mcp47fvb08_chip_features }, 1225*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb11", .data = &mcp47fvb11_chip_features }, 1226*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb12", .data = &mcp47fvb12_chip_features }, 1227*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb14", .data = &mcp47fvb14_chip_features }, 1228*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb18", .data = &mcp47fvb18_chip_features }, 1229*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb21", .data = &mcp47fvb21_chip_features }, 1230*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb22", .data = &mcp47fvb22_chip_features }, 1231*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb24", .data = &mcp47fvb24_chip_features }, 1232*bf394cc8SAriana Lazar { .compatible = "microchip,mcp47fvb28", .data = &mcp47fvb28_chip_features }, 1233*bf394cc8SAriana Lazar { } 1234*bf394cc8SAriana Lazar }; 1235*bf394cc8SAriana Lazar MODULE_DEVICE_TABLE(of, mcp47feb02_of_match); 1236*bf394cc8SAriana Lazar 1237*bf394cc8SAriana Lazar static struct i2c_driver mcp47feb02_driver = { 1238*bf394cc8SAriana Lazar .driver = { 1239*bf394cc8SAriana Lazar .name = "mcp47feb02", 1240*bf394cc8SAriana Lazar .of_match_table = mcp47feb02_of_match, 1241*bf394cc8SAriana Lazar .pm = pm_sleep_ptr(&mcp47feb02_pm_ops), 1242*bf394cc8SAriana Lazar }, 1243*bf394cc8SAriana Lazar .probe = mcp47feb02_probe, 1244*bf394cc8SAriana Lazar .id_table = mcp47feb02_id, 1245*bf394cc8SAriana Lazar }; 1246*bf394cc8SAriana Lazar module_i2c_driver(mcp47feb02_driver); 1247*bf394cc8SAriana Lazar 1248*bf394cc8SAriana Lazar MODULE_AUTHOR("Ariana Lazar <ariana.lazar@microchip.com>"); 1249*bf394cc8SAriana Lazar MODULE_DESCRIPTION("IIO driver for MCP47FEB02 Multi-Channel DAC with I2C interface"); 1250*bf394cc8SAriana Lazar MODULE_LICENSE("GPL"); 1251