1*cf890fe8SJonathan Cameron // SPDX-License-Identifier: GPL-2.0 2*cf890fe8SJonathan Cameron /* 3*cf890fe8SJonathan Cameron * AD7280A Lithium Ion Battery Monitoring System 4*cf890fe8SJonathan Cameron * 5*cf890fe8SJonathan Cameron * Copyright 2011 Analog Devices Inc. 6*cf890fe8SJonathan Cameron */ 7*cf890fe8SJonathan Cameron 8*cf890fe8SJonathan Cameron #include <linux/bitfield.h> 9*cf890fe8SJonathan Cameron #include <linux/bits.h> 10*cf890fe8SJonathan Cameron #include <linux/crc8.h> 11*cf890fe8SJonathan Cameron #include <linux/delay.h> 12*cf890fe8SJonathan Cameron #include <linux/device.h> 13*cf890fe8SJonathan Cameron #include <linux/err.h> 14*cf890fe8SJonathan Cameron #include <linux/interrupt.h> 15*cf890fe8SJonathan Cameron #include <linux/kernel.h> 16*cf890fe8SJonathan Cameron #include <linux/module.h> 17*cf890fe8SJonathan Cameron #include <linux/mod_devicetable.h> 18*cf890fe8SJonathan Cameron #include <linux/mutex.h> 19*cf890fe8SJonathan Cameron #include <linux/slab.h> 20*cf890fe8SJonathan Cameron #include <linux/sysfs.h> 21*cf890fe8SJonathan Cameron #include <linux/spi/spi.h> 22*cf890fe8SJonathan Cameron 23*cf890fe8SJonathan Cameron #include <linux/iio/events.h> 24*cf890fe8SJonathan Cameron #include <linux/iio/iio.h> 25*cf890fe8SJonathan Cameron 26*cf890fe8SJonathan Cameron /* Registers */ 27*cf890fe8SJonathan Cameron 28*cf890fe8SJonathan Cameron #define AD7280A_CELL_VOLTAGE_1_REG 0x0 /* D11 to D0, Read only */ 29*cf890fe8SJonathan Cameron #define AD7280A_CELL_VOLTAGE_2_REG 0x1 /* D11 to D0, Read only */ 30*cf890fe8SJonathan Cameron #define AD7280A_CELL_VOLTAGE_3_REG 0x2 /* D11 to D0, Read only */ 31*cf890fe8SJonathan Cameron #define AD7280A_CELL_VOLTAGE_4_REG 0x3 /* D11 to D0, Read only */ 32*cf890fe8SJonathan Cameron #define AD7280A_CELL_VOLTAGE_5_REG 0x4 /* D11 to D0, Read only */ 33*cf890fe8SJonathan Cameron #define AD7280A_CELL_VOLTAGE_6_REG 0x5 /* D11 to D0, Read only */ 34*cf890fe8SJonathan Cameron #define AD7280A_AUX_ADC_1_REG 0x6 /* D11 to D0, Read only */ 35*cf890fe8SJonathan Cameron #define AD7280A_AUX_ADC_2_REG 0x7 /* D11 to D0, Read only */ 36*cf890fe8SJonathan Cameron #define AD7280A_AUX_ADC_3_REG 0x8 /* D11 to D0, Read only */ 37*cf890fe8SJonathan Cameron #define AD7280A_AUX_ADC_4_REG 0x9 /* D11 to D0, Read only */ 38*cf890fe8SJonathan Cameron #define AD7280A_AUX_ADC_5_REG 0xA /* D11 to D0, Read only */ 39*cf890fe8SJonathan Cameron #define AD7280A_AUX_ADC_6_REG 0xB /* D11 to D0, Read only */ 40*cf890fe8SJonathan Cameron #define AD7280A_SELF_TEST_REG 0xC /* D11 to D0, Read only */ 41*cf890fe8SJonathan Cameron 42*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_REG 0xD /* D15 to D8, Read/write */ 43*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_INPUT_MSK GENMASK(7, 6) 44*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_INPUT_ALL 0 45*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_INPUT_6CELL_AUX1_3_5 1 46*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_INPUT_6CELL 2 47*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_INPUT_SELF_TEST 3 48*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_RREAD_MSK GENMASK(5, 4) 49*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_RREAD_ALL 0 50*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_RREAD_6CELL_AUX1_3_5 1 51*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_RREAD_6CELL 2 52*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_RREAD_NO 3 53*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_START_MSK BIT(3) 54*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_START_CNVST 0 55*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_START_CS 1 56*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_AVG_MSK GENMASK(2, 1) 57*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_AVG_DIS 0 58*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_AVG_2 1 59*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_AVG_4 2 60*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_CONV_AVG_8 3 61*cf890fe8SJonathan Cameron #define AD7280A_CTRL_HB_PWRDN_SW BIT(0) 62*cf890fe8SJonathan Cameron 63*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_REG 0xE /* D7 to D0, Read/write */ 64*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_SWRST_MSK BIT(7) 65*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_ACQ_TIME_MSK GENMASK(6, 5) 66*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_ACQ_TIME_400ns 0 67*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_ACQ_TIME_800ns 1 68*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_ACQ_TIME_1200ns 2 69*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_ACQ_TIME_1600ns 3 70*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_MUST_SET BIT(4) 71*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_THERMISTOR_MSK BIT(3) 72*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_LOCK_DEV_ADDR_MSK BIT(2) 73*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_INC_DEV_ADDR_MSK BIT(1) 74*cf890fe8SJonathan Cameron #define AD7280A_CTRL_LB_DAISY_CHAIN_RB_MSK BIT(0) 75*cf890fe8SJonathan Cameron 76*cf890fe8SJonathan Cameron #define AD7280A_CELL_OVERVOLTAGE_REG 0xF /* D7 to D0, Read/write */ 77*cf890fe8SJonathan Cameron #define AD7280A_CELL_UNDERVOLTAGE_REG 0x10 /* D7 to D0, Read/write */ 78*cf890fe8SJonathan Cameron #define AD7280A_AUX_ADC_OVERVOLTAGE_REG 0x11 /* D7 to D0, Read/write */ 79*cf890fe8SJonathan Cameron #define AD7280A_AUX_ADC_UNDERVOLTAGE_REG 0x12 /* D7 to D0, Read/write */ 80*cf890fe8SJonathan Cameron 81*cf890fe8SJonathan Cameron #define AD7280A_ALERT_REG 0x13 /* D7 to D0, Read/write */ 82*cf890fe8SJonathan Cameron #define AD7280A_ALERT_REMOVE_MSK GENMASK(3, 0) 83*cf890fe8SJonathan Cameron #define AD7280A_ALERT_REMOVE_AUX5 BIT(0) 84*cf890fe8SJonathan Cameron #define AD7280A_ALERT_REMOVE_AUX3_AUX5 BIT(1) 85*cf890fe8SJonathan Cameron #define AD7280A_ALERT_REMOVE_VIN5 BIT(2) 86*cf890fe8SJonathan Cameron #define AD7280A_ALERT_REMOVE_VIN4_VIN5 BIT(3) 87*cf890fe8SJonathan Cameron #define AD7280A_ALERT_GEN_STATIC_HIGH BIT(6) 88*cf890fe8SJonathan Cameron #define AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN (BIT(7) | BIT(6)) 89*cf890fe8SJonathan Cameron 90*cf890fe8SJonathan Cameron #define AD7280A_CELL_BALANCE_REG 0x14 /* D7 to D0, Read/write */ 91*cf890fe8SJonathan Cameron #define AD7280A_CELL_BALANCE_CHAN_BITMAP_MSK GENMASK(7, 2) 92*cf890fe8SJonathan Cameron #define AD7280A_CB1_TIMER_REG 0x15 /* D7 to D0, Read/write */ 93*cf890fe8SJonathan Cameron #define AD7280A_CB_TIMER_VAL_MSK GENMASK(7, 3) 94*cf890fe8SJonathan Cameron #define AD7280A_CB2_TIMER_REG 0x16 /* D7 to D0, Read/write */ 95*cf890fe8SJonathan Cameron #define AD7280A_CB3_TIMER_REG 0x17 /* D7 to D0, Read/write */ 96*cf890fe8SJonathan Cameron #define AD7280A_CB4_TIMER_REG 0x18 /* D7 to D0, Read/write */ 97*cf890fe8SJonathan Cameron #define AD7280A_CB5_TIMER_REG 0x19 /* D7 to D0, Read/write */ 98*cf890fe8SJonathan Cameron #define AD7280A_CB6_TIMER_REG 0x1A /* D7 to D0, Read/write */ 99*cf890fe8SJonathan Cameron #define AD7280A_PD_TIMER_REG 0x1B /* D7 to D0, Read/write */ 100*cf890fe8SJonathan Cameron #define AD7280A_READ_REG 0x1C /* D7 to D0, Read/write */ 101*cf890fe8SJonathan Cameron #define AD7280A_READ_ADDR_MSK GENMASK(7, 2) 102*cf890fe8SJonathan Cameron #define AD7280A_CNVST_CTRL_REG 0x1D /* D7 to D0, Read/write */ 103*cf890fe8SJonathan Cameron 104*cf890fe8SJonathan Cameron /* Transfer fields */ 105*cf890fe8SJonathan Cameron #define AD7280A_TRANS_WRITE_DEVADDR_MSK GENMASK(31, 27) 106*cf890fe8SJonathan Cameron #define AD7280A_TRANS_WRITE_ADDR_MSK GENMASK(26, 21) 107*cf890fe8SJonathan Cameron #define AD7280A_TRANS_WRITE_VAL_MSK GENMASK(20, 13) 108*cf890fe8SJonathan Cameron #define AD7280A_TRANS_WRITE_ALL_MSK BIT(12) 109*cf890fe8SJonathan Cameron #define AD7280A_TRANS_WRITE_CRC_MSK GENMASK(10, 3) 110*cf890fe8SJonathan Cameron #define AD7280A_TRANS_WRITE_RES_PATTERN 0x2 111*cf890fe8SJonathan Cameron 112*cf890fe8SJonathan Cameron /* Layouts differ for channel vs other registers */ 113*cf890fe8SJonathan Cameron #define AD7280A_TRANS_READ_DEVADDR_MSK GENMASK(31, 27) 114*cf890fe8SJonathan Cameron #define AD7280A_TRANS_READ_CONV_CHANADDR_MSK GENMASK(26, 23) 115*cf890fe8SJonathan Cameron #define AD7280A_TRANS_READ_CONV_DATA_MSK GENMASK(22, 11) 116*cf890fe8SJonathan Cameron #define AD7280A_TRANS_READ_REG_REGADDR_MSK GENMASK(26, 21) 117*cf890fe8SJonathan Cameron #define AD7280A_TRANS_READ_REG_DATA_MSK GENMASK(20, 13) 118*cf890fe8SJonathan Cameron #define AD7280A_TRANS_READ_WRITE_ACK_MSK BIT(10) 119*cf890fe8SJonathan Cameron #define AD7280A_TRANS_READ_CRC_MSK GENMASK(9, 2) 120*cf890fe8SJonathan Cameron 121*cf890fe8SJonathan Cameron /* Magic value used to indicate this special case */ 122*cf890fe8SJonathan Cameron #define AD7280A_ALL_CELLS (0xAD << 16) 123*cf890fe8SJonathan Cameron 124*cf890fe8SJonathan Cameron #define AD7280A_MAX_SPI_CLK_HZ 700000 /* < 1MHz */ 125*cf890fe8SJonathan Cameron #define AD7280A_MAX_CHAIN 8 126*cf890fe8SJonathan Cameron #define AD7280A_CELLS_PER_DEV 6 127*cf890fe8SJonathan Cameron #define AD7280A_BITS 12 128*cf890fe8SJonathan Cameron #define AD7280A_NUM_CH (AD7280A_AUX_ADC_6_REG - \ 129*cf890fe8SJonathan Cameron AD7280A_CELL_VOLTAGE_1_REG + 1) 130*cf890fe8SJonathan Cameron 131*cf890fe8SJonathan Cameron #define AD7280A_CALC_VOLTAGE_CHAN_NUM(d, c) (((d) * AD7280A_CELLS_PER_DEV) + \ 132*cf890fe8SJonathan Cameron (c)) 133*cf890fe8SJonathan Cameron #define AD7280A_CALC_TEMP_CHAN_NUM(d, c) (((d) * AD7280A_CELLS_PER_DEV) + \ 134*cf890fe8SJonathan Cameron (c) - AD7280A_CELLS_PER_DEV) 135*cf890fe8SJonathan Cameron 136*cf890fe8SJonathan Cameron #define AD7280A_DEVADDR_MASTER 0 137*cf890fe8SJonathan Cameron #define AD7280A_DEVADDR_ALL 0x1F 138*cf890fe8SJonathan Cameron 139*cf890fe8SJonathan Cameron static const unsigned short ad7280a_n_avg[4] = {1, 2, 4, 8}; 140*cf890fe8SJonathan Cameron static const unsigned short ad7280a_t_acq_ns[4] = {470, 1030, 1510, 1945}; 141*cf890fe8SJonathan Cameron 142*cf890fe8SJonathan Cameron /* 5-bit device address is sent LSB first */ 143*cf890fe8SJonathan Cameron static unsigned int ad7280a_devaddr(unsigned int addr) 144*cf890fe8SJonathan Cameron { 145*cf890fe8SJonathan Cameron return ((addr & 0x1) << 4) | 146*cf890fe8SJonathan Cameron ((addr & 0x2) << 2) | 147*cf890fe8SJonathan Cameron (addr & 0x4) | 148*cf890fe8SJonathan Cameron ((addr & 0x8) >> 2) | 149*cf890fe8SJonathan Cameron ((addr & 0x10) >> 4); 150*cf890fe8SJonathan Cameron } 151*cf890fe8SJonathan Cameron 152*cf890fe8SJonathan Cameron /* 153*cf890fe8SJonathan Cameron * During a read a valid write is mandatory. 154*cf890fe8SJonathan Cameron * So writing to the highest available address (Address 0x1F) and setting the 155*cf890fe8SJonathan Cameron * address all parts bit to 0 is recommended. 156*cf890fe8SJonathan Cameron * So the TXVAL is AD7280A_DEVADDR_ALL + CRC 157*cf890fe8SJonathan Cameron */ 158*cf890fe8SJonathan Cameron #define AD7280A_READ_TXVAL 0xF800030A 159*cf890fe8SJonathan Cameron 160*cf890fe8SJonathan Cameron /* 161*cf890fe8SJonathan Cameron * AD7280 CRC 162*cf890fe8SJonathan Cameron * 163*cf890fe8SJonathan Cameron * P(x) = x^8 + x^5 + x^3 + x^2 + x^1 + x^0 = 0b100101111 => 0x2F 164*cf890fe8SJonathan Cameron */ 165*cf890fe8SJonathan Cameron #define POLYNOM 0x2F 166*cf890fe8SJonathan Cameron 167*cf890fe8SJonathan Cameron struct ad7280_state { 168*cf890fe8SJonathan Cameron struct spi_device *spi; 169*cf890fe8SJonathan Cameron struct iio_chan_spec *channels; 170*cf890fe8SJonathan Cameron unsigned int chain_last_alert_ignore; 171*cf890fe8SJonathan Cameron bool thermistor_term_en; 172*cf890fe8SJonathan Cameron int slave_num; 173*cf890fe8SJonathan Cameron int scan_cnt; 174*cf890fe8SJonathan Cameron int readback_delay_us; 175*cf890fe8SJonathan Cameron unsigned char crc_tab[CRC8_TABLE_SIZE]; 176*cf890fe8SJonathan Cameron u8 oversampling_ratio; 177*cf890fe8SJonathan Cameron u8 acquisition_time; 178*cf890fe8SJonathan Cameron unsigned char ctrl_lb; 179*cf890fe8SJonathan Cameron unsigned char cell_threshhigh; 180*cf890fe8SJonathan Cameron unsigned char cell_threshlow; 181*cf890fe8SJonathan Cameron unsigned char aux_threshhigh; 182*cf890fe8SJonathan Cameron unsigned char aux_threshlow; 183*cf890fe8SJonathan Cameron unsigned char cb_mask[AD7280A_MAX_CHAIN]; 184*cf890fe8SJonathan Cameron struct mutex lock; /* protect sensor state */ 185*cf890fe8SJonathan Cameron 186*cf890fe8SJonathan Cameron __be32 tx ____cacheline_aligned; 187*cf890fe8SJonathan Cameron __be32 rx; 188*cf890fe8SJonathan Cameron }; 189*cf890fe8SJonathan Cameron 190*cf890fe8SJonathan Cameron static unsigned char ad7280_calc_crc8(unsigned char *crc_tab, unsigned int val) 191*cf890fe8SJonathan Cameron { 192*cf890fe8SJonathan Cameron unsigned char crc; 193*cf890fe8SJonathan Cameron 194*cf890fe8SJonathan Cameron crc = crc_tab[val >> 16 & 0xFF]; 195*cf890fe8SJonathan Cameron crc = crc_tab[crc ^ (val >> 8 & 0xFF)]; 196*cf890fe8SJonathan Cameron 197*cf890fe8SJonathan Cameron return crc ^ (val & 0xFF); 198*cf890fe8SJonathan Cameron } 199*cf890fe8SJonathan Cameron 200*cf890fe8SJonathan Cameron static int ad7280_check_crc(struct ad7280_state *st, unsigned int val) 201*cf890fe8SJonathan Cameron { 202*cf890fe8SJonathan Cameron unsigned char crc = ad7280_calc_crc8(st->crc_tab, val >> 10); 203*cf890fe8SJonathan Cameron 204*cf890fe8SJonathan Cameron if (crc != ((val >> 2) & 0xFF)) 205*cf890fe8SJonathan Cameron return -EIO; 206*cf890fe8SJonathan Cameron 207*cf890fe8SJonathan Cameron return 0; 208*cf890fe8SJonathan Cameron } 209*cf890fe8SJonathan Cameron 210*cf890fe8SJonathan Cameron /* 211*cf890fe8SJonathan Cameron * After initiating a conversion sequence we need to wait until the conversion 212*cf890fe8SJonathan Cameron * is done. The delay is typically in the range of 15..30us however depending on 213*cf890fe8SJonathan Cameron * the number of devices in the daisy chain, the number of averages taken, 214*cf890fe8SJonathan Cameron * conversion delays and acquisition time options it may take up to 250us, in 215*cf890fe8SJonathan Cameron * this case we better sleep instead of busy wait. 216*cf890fe8SJonathan Cameron */ 217*cf890fe8SJonathan Cameron 218*cf890fe8SJonathan Cameron static void ad7280_delay(struct ad7280_state *st) 219*cf890fe8SJonathan Cameron { 220*cf890fe8SJonathan Cameron if (st->readback_delay_us < 50) 221*cf890fe8SJonathan Cameron udelay(st->readback_delay_us); 222*cf890fe8SJonathan Cameron else 223*cf890fe8SJonathan Cameron usleep_range(250, 500); 224*cf890fe8SJonathan Cameron } 225*cf890fe8SJonathan Cameron 226*cf890fe8SJonathan Cameron static int __ad7280_read32(struct ad7280_state *st, unsigned int *val) 227*cf890fe8SJonathan Cameron { 228*cf890fe8SJonathan Cameron int ret; 229*cf890fe8SJonathan Cameron struct spi_transfer t = { 230*cf890fe8SJonathan Cameron .tx_buf = &st->tx, 231*cf890fe8SJonathan Cameron .rx_buf = &st->rx, 232*cf890fe8SJonathan Cameron .len = sizeof(st->tx), 233*cf890fe8SJonathan Cameron }; 234*cf890fe8SJonathan Cameron 235*cf890fe8SJonathan Cameron st->tx = cpu_to_be32(AD7280A_READ_TXVAL); 236*cf890fe8SJonathan Cameron 237*cf890fe8SJonathan Cameron ret = spi_sync_transfer(st->spi, &t, 1); 238*cf890fe8SJonathan Cameron if (ret) 239*cf890fe8SJonathan Cameron return ret; 240*cf890fe8SJonathan Cameron 241*cf890fe8SJonathan Cameron *val = be32_to_cpu(st->rx); 242*cf890fe8SJonathan Cameron 243*cf890fe8SJonathan Cameron return 0; 244*cf890fe8SJonathan Cameron } 245*cf890fe8SJonathan Cameron 246*cf890fe8SJonathan Cameron static int ad7280_write(struct ad7280_state *st, unsigned int devaddr, 247*cf890fe8SJonathan Cameron unsigned int addr, bool all, unsigned int val) 248*cf890fe8SJonathan Cameron { 249*cf890fe8SJonathan Cameron unsigned int reg = FIELD_PREP(AD7280A_TRANS_WRITE_DEVADDR_MSK, devaddr) | 250*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_TRANS_WRITE_ADDR_MSK, addr) | 251*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_TRANS_WRITE_VAL_MSK, val) | 252*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_TRANS_WRITE_ALL_MSK, all); 253*cf890fe8SJonathan Cameron 254*cf890fe8SJonathan Cameron reg |= FIELD_PREP(AD7280A_TRANS_WRITE_CRC_MSK, 255*cf890fe8SJonathan Cameron ad7280_calc_crc8(st->crc_tab, reg >> 11)); 256*cf890fe8SJonathan Cameron /* Reserved b010 pattern not included crc calc */ 257*cf890fe8SJonathan Cameron reg |= AD7280A_TRANS_WRITE_RES_PATTERN; 258*cf890fe8SJonathan Cameron 259*cf890fe8SJonathan Cameron st->tx = cpu_to_be32(reg); 260*cf890fe8SJonathan Cameron 261*cf890fe8SJonathan Cameron return spi_write(st->spi, &st->tx, sizeof(st->tx)); 262*cf890fe8SJonathan Cameron } 263*cf890fe8SJonathan Cameron 264*cf890fe8SJonathan Cameron static int ad7280_read_reg(struct ad7280_state *st, unsigned int devaddr, 265*cf890fe8SJonathan Cameron unsigned int addr) 266*cf890fe8SJonathan Cameron { 267*cf890fe8SJonathan Cameron int ret; 268*cf890fe8SJonathan Cameron unsigned int tmp; 269*cf890fe8SJonathan Cameron 270*cf890fe8SJonathan Cameron /* turns off the read operation on all parts */ 271*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, 272*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, 273*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_INPUT_ALL) | 274*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, 275*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_RREAD_NO) | 276*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, 277*cf890fe8SJonathan Cameron st->oversampling_ratio)); 278*cf890fe8SJonathan Cameron if (ret) 279*cf890fe8SJonathan Cameron return ret; 280*cf890fe8SJonathan Cameron 281*cf890fe8SJonathan Cameron /* turns on the read operation on the addressed part */ 282*cf890fe8SJonathan Cameron ret = ad7280_write(st, devaddr, AD7280A_CTRL_HB_REG, 0, 283*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, 284*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_INPUT_ALL) | 285*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, 286*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_RREAD_ALL) | 287*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, 288*cf890fe8SJonathan Cameron st->oversampling_ratio)); 289*cf890fe8SJonathan Cameron if (ret) 290*cf890fe8SJonathan Cameron return ret; 291*cf890fe8SJonathan Cameron 292*cf890fe8SJonathan Cameron /* Set register address on the part to be read from */ 293*cf890fe8SJonathan Cameron ret = ad7280_write(st, devaddr, AD7280A_READ_REG, 0, 294*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_READ_ADDR_MSK, addr)); 295*cf890fe8SJonathan Cameron if (ret) 296*cf890fe8SJonathan Cameron return ret; 297*cf890fe8SJonathan Cameron 298*cf890fe8SJonathan Cameron ret = __ad7280_read32(st, &tmp); 299*cf890fe8SJonathan Cameron if (ret) 300*cf890fe8SJonathan Cameron return ret; 301*cf890fe8SJonathan Cameron 302*cf890fe8SJonathan Cameron if (ad7280_check_crc(st, tmp)) 303*cf890fe8SJonathan Cameron return -EIO; 304*cf890fe8SJonathan Cameron 305*cf890fe8SJonathan Cameron if ((FIELD_GET(AD7280A_TRANS_READ_DEVADDR_MSK, tmp) != devaddr) || 306*cf890fe8SJonathan Cameron (FIELD_GET(AD7280A_TRANS_READ_REG_REGADDR_MSK, tmp) != addr)) 307*cf890fe8SJonathan Cameron return -EFAULT; 308*cf890fe8SJonathan Cameron 309*cf890fe8SJonathan Cameron return FIELD_GET(AD7280A_TRANS_READ_REG_DATA_MSK, tmp); 310*cf890fe8SJonathan Cameron } 311*cf890fe8SJonathan Cameron 312*cf890fe8SJonathan Cameron static int ad7280_read_channel(struct ad7280_state *st, unsigned int devaddr, 313*cf890fe8SJonathan Cameron unsigned int addr) 314*cf890fe8SJonathan Cameron { 315*cf890fe8SJonathan Cameron int ret; 316*cf890fe8SJonathan Cameron unsigned int tmp; 317*cf890fe8SJonathan Cameron 318*cf890fe8SJonathan Cameron ret = ad7280_write(st, devaddr, AD7280A_READ_REG, 0, 319*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_READ_ADDR_MSK, addr)); 320*cf890fe8SJonathan Cameron if (ret) 321*cf890fe8SJonathan Cameron return ret; 322*cf890fe8SJonathan Cameron 323*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, 324*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, 325*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_INPUT_ALL) | 326*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, 327*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_RREAD_NO) | 328*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, 329*cf890fe8SJonathan Cameron st->oversampling_ratio)); 330*cf890fe8SJonathan Cameron if (ret) 331*cf890fe8SJonathan Cameron return ret; 332*cf890fe8SJonathan Cameron 333*cf890fe8SJonathan Cameron ret = ad7280_write(st, devaddr, AD7280A_CTRL_HB_REG, 0, 334*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, 335*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_INPUT_ALL) | 336*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, 337*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_RREAD_ALL) | 338*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_START_MSK, 339*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_START_CS) | 340*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, 341*cf890fe8SJonathan Cameron st->oversampling_ratio)); 342*cf890fe8SJonathan Cameron if (ret) 343*cf890fe8SJonathan Cameron return ret; 344*cf890fe8SJonathan Cameron 345*cf890fe8SJonathan Cameron ad7280_delay(st); 346*cf890fe8SJonathan Cameron 347*cf890fe8SJonathan Cameron ret = __ad7280_read32(st, &tmp); 348*cf890fe8SJonathan Cameron if (ret) 349*cf890fe8SJonathan Cameron return ret; 350*cf890fe8SJonathan Cameron 351*cf890fe8SJonathan Cameron if (ad7280_check_crc(st, tmp)) 352*cf890fe8SJonathan Cameron return -EIO; 353*cf890fe8SJonathan Cameron 354*cf890fe8SJonathan Cameron if ((FIELD_GET(AD7280A_TRANS_READ_DEVADDR_MSK, tmp) != devaddr) || 355*cf890fe8SJonathan Cameron (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, tmp) != addr)) 356*cf890fe8SJonathan Cameron return -EFAULT; 357*cf890fe8SJonathan Cameron 358*cf890fe8SJonathan Cameron return FIELD_GET(AD7280A_TRANS_READ_CONV_DATA_MSK, tmp); 359*cf890fe8SJonathan Cameron } 360*cf890fe8SJonathan Cameron 361*cf890fe8SJonathan Cameron static int ad7280_read_all_channels(struct ad7280_state *st, unsigned int cnt, 362*cf890fe8SJonathan Cameron unsigned int *array) 363*cf890fe8SJonathan Cameron { 364*cf890fe8SJonathan Cameron int i, ret; 365*cf890fe8SJonathan Cameron unsigned int tmp, sum = 0; 366*cf890fe8SJonathan Cameron 367*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ_REG, 1, 368*cf890fe8SJonathan Cameron AD7280A_CELL_VOLTAGE_1_REG << 2); 369*cf890fe8SJonathan Cameron if (ret) 370*cf890fe8SJonathan Cameron return ret; 371*cf890fe8SJonathan Cameron 372*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, 373*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_INPUT_MSK, 374*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_INPUT_ALL) | 375*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_RREAD_MSK, 376*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_RREAD_ALL) | 377*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_START_MSK, 378*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_CONV_START_CS) | 379*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, 380*cf890fe8SJonathan Cameron st->oversampling_ratio)); 381*cf890fe8SJonathan Cameron if (ret) 382*cf890fe8SJonathan Cameron return ret; 383*cf890fe8SJonathan Cameron 384*cf890fe8SJonathan Cameron ad7280_delay(st); 385*cf890fe8SJonathan Cameron 386*cf890fe8SJonathan Cameron for (i = 0; i < cnt; i++) { 387*cf890fe8SJonathan Cameron ret = __ad7280_read32(st, &tmp); 388*cf890fe8SJonathan Cameron if (ret) 389*cf890fe8SJonathan Cameron return ret; 390*cf890fe8SJonathan Cameron 391*cf890fe8SJonathan Cameron if (ad7280_check_crc(st, tmp)) 392*cf890fe8SJonathan Cameron return -EIO; 393*cf890fe8SJonathan Cameron 394*cf890fe8SJonathan Cameron if (array) 395*cf890fe8SJonathan Cameron array[i] = tmp; 396*cf890fe8SJonathan Cameron /* only sum cell voltages */ 397*cf890fe8SJonathan Cameron if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, tmp) <= 398*cf890fe8SJonathan Cameron AD7280A_CELL_VOLTAGE_6_REG) 399*cf890fe8SJonathan Cameron sum += FIELD_GET(AD7280A_TRANS_READ_CONV_DATA_MSK, tmp); 400*cf890fe8SJonathan Cameron } 401*cf890fe8SJonathan Cameron 402*cf890fe8SJonathan Cameron return sum; 403*cf890fe8SJonathan Cameron } 404*cf890fe8SJonathan Cameron 405*cf890fe8SJonathan Cameron static void ad7280_sw_power_down(void *data) 406*cf890fe8SJonathan Cameron { 407*cf890fe8SJonathan Cameron struct ad7280_state *st = data; 408*cf890fe8SJonathan Cameron 409*cf890fe8SJonathan Cameron ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, 410*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_PWRDN_SW | 411*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, st->oversampling_ratio)); 412*cf890fe8SJonathan Cameron } 413*cf890fe8SJonathan Cameron 414*cf890fe8SJonathan Cameron static int ad7280_chain_setup(struct ad7280_state *st) 415*cf890fe8SJonathan Cameron { 416*cf890fe8SJonathan Cameron unsigned int val, n; 417*cf890fe8SJonathan Cameron int ret; 418*cf890fe8SJonathan Cameron 419*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_LB_REG, 1, 420*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_LB_DAISY_CHAIN_RB_MSK, 1) | 421*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_LB_LOCK_DEV_ADDR_MSK, 1) | 422*cf890fe8SJonathan Cameron AD7280A_CTRL_LB_MUST_SET | 423*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_LB_SWRST_MSK, 1) | 424*cf890fe8SJonathan Cameron st->ctrl_lb); 425*cf890fe8SJonathan Cameron if (ret) 426*cf890fe8SJonathan Cameron return ret; 427*cf890fe8SJonathan Cameron 428*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_LB_REG, 1, 429*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_LB_DAISY_CHAIN_RB_MSK, 1) | 430*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_LB_LOCK_DEV_ADDR_MSK, 1) | 431*cf890fe8SJonathan Cameron AD7280A_CTRL_LB_MUST_SET | 432*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_LB_SWRST_MSK, 0) | 433*cf890fe8SJonathan Cameron st->ctrl_lb); 434*cf890fe8SJonathan Cameron if (ret) 435*cf890fe8SJonathan Cameron goto error_power_down; 436*cf890fe8SJonathan Cameron 437*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_READ_REG, 1, 438*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_READ_ADDR_MSK, AD7280A_CTRL_LB_REG)); 439*cf890fe8SJonathan Cameron if (ret) 440*cf890fe8SJonathan Cameron goto error_power_down; 441*cf890fe8SJonathan Cameron 442*cf890fe8SJonathan Cameron for (n = 0; n <= AD7280A_MAX_CHAIN; n++) { 443*cf890fe8SJonathan Cameron ret = __ad7280_read32(st, &val); 444*cf890fe8SJonathan Cameron if (ret) 445*cf890fe8SJonathan Cameron goto error_power_down; 446*cf890fe8SJonathan Cameron 447*cf890fe8SJonathan Cameron if (val == 0) 448*cf890fe8SJonathan Cameron return n - 1; 449*cf890fe8SJonathan Cameron 450*cf890fe8SJonathan Cameron if (ad7280_check_crc(st, val)) { 451*cf890fe8SJonathan Cameron ret = -EIO; 452*cf890fe8SJonathan Cameron goto error_power_down; 453*cf890fe8SJonathan Cameron } 454*cf890fe8SJonathan Cameron 455*cf890fe8SJonathan Cameron if (n != ad7280a_devaddr(FIELD_GET(AD7280A_TRANS_READ_DEVADDR_MSK, val))) { 456*cf890fe8SJonathan Cameron ret = -EIO; 457*cf890fe8SJonathan Cameron goto error_power_down; 458*cf890fe8SJonathan Cameron } 459*cf890fe8SJonathan Cameron } 460*cf890fe8SJonathan Cameron ret = -EFAULT; 461*cf890fe8SJonathan Cameron 462*cf890fe8SJonathan Cameron error_power_down: 463*cf890fe8SJonathan Cameron ad7280_write(st, AD7280A_DEVADDR_MASTER, AD7280A_CTRL_HB_REG, 1, 464*cf890fe8SJonathan Cameron AD7280A_CTRL_HB_PWRDN_SW | 465*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_HB_CONV_AVG_MSK, st->oversampling_ratio)); 466*cf890fe8SJonathan Cameron 467*cf890fe8SJonathan Cameron return ret; 468*cf890fe8SJonathan Cameron } 469*cf890fe8SJonathan Cameron 470*cf890fe8SJonathan Cameron static ssize_t ad7280_show_balance_sw(struct iio_dev *indio_dev, 471*cf890fe8SJonathan Cameron uintptr_t private, 472*cf890fe8SJonathan Cameron const struct iio_chan_spec *chan, char *buf) 473*cf890fe8SJonathan Cameron { 474*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 475*cf890fe8SJonathan Cameron 476*cf890fe8SJonathan Cameron return sysfs_emit(buf, "%d\n", 477*cf890fe8SJonathan Cameron !!(st->cb_mask[chan->address >> 8] & 478*cf890fe8SJonathan Cameron BIT(chan->address & 0xFF))); 479*cf890fe8SJonathan Cameron } 480*cf890fe8SJonathan Cameron 481*cf890fe8SJonathan Cameron static ssize_t ad7280_store_balance_sw(struct iio_dev *indio_dev, 482*cf890fe8SJonathan Cameron uintptr_t private, 483*cf890fe8SJonathan Cameron const struct iio_chan_spec *chan, 484*cf890fe8SJonathan Cameron const char *buf, size_t len) 485*cf890fe8SJonathan Cameron { 486*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 487*cf890fe8SJonathan Cameron unsigned int devaddr, ch; 488*cf890fe8SJonathan Cameron bool readin; 489*cf890fe8SJonathan Cameron int ret; 490*cf890fe8SJonathan Cameron 491*cf890fe8SJonathan Cameron ret = strtobool(buf, &readin); 492*cf890fe8SJonathan Cameron if (ret) 493*cf890fe8SJonathan Cameron return ret; 494*cf890fe8SJonathan Cameron 495*cf890fe8SJonathan Cameron devaddr = chan->address >> 8; 496*cf890fe8SJonathan Cameron ch = chan->address & 0xFF; 497*cf890fe8SJonathan Cameron 498*cf890fe8SJonathan Cameron mutex_lock(&st->lock); 499*cf890fe8SJonathan Cameron if (readin) 500*cf890fe8SJonathan Cameron st->cb_mask[devaddr] |= BIT(ch); 501*cf890fe8SJonathan Cameron else 502*cf890fe8SJonathan Cameron st->cb_mask[devaddr] &= ~BIT(ch); 503*cf890fe8SJonathan Cameron 504*cf890fe8SJonathan Cameron ret = ad7280_write(st, devaddr, AD7280A_CELL_BALANCE_REG, 0, 505*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CELL_BALANCE_CHAN_BITMAP_MSK, 506*cf890fe8SJonathan Cameron st->cb_mask[devaddr])); 507*cf890fe8SJonathan Cameron mutex_unlock(&st->lock); 508*cf890fe8SJonathan Cameron 509*cf890fe8SJonathan Cameron return ret ? ret : len; 510*cf890fe8SJonathan Cameron } 511*cf890fe8SJonathan Cameron 512*cf890fe8SJonathan Cameron static ssize_t ad7280_show_balance_timer(struct iio_dev *indio_dev, 513*cf890fe8SJonathan Cameron uintptr_t private, 514*cf890fe8SJonathan Cameron const struct iio_chan_spec *chan, 515*cf890fe8SJonathan Cameron char *buf) 516*cf890fe8SJonathan Cameron { 517*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 518*cf890fe8SJonathan Cameron unsigned int msecs; 519*cf890fe8SJonathan Cameron int ret; 520*cf890fe8SJonathan Cameron 521*cf890fe8SJonathan Cameron mutex_lock(&st->lock); 522*cf890fe8SJonathan Cameron ret = ad7280_read_reg(st, chan->address >> 8, 523*cf890fe8SJonathan Cameron (chan->address & 0xFF) + AD7280A_CB1_TIMER_REG); 524*cf890fe8SJonathan Cameron mutex_unlock(&st->lock); 525*cf890fe8SJonathan Cameron 526*cf890fe8SJonathan Cameron if (ret < 0) 527*cf890fe8SJonathan Cameron return ret; 528*cf890fe8SJonathan Cameron 529*cf890fe8SJonathan Cameron msecs = FIELD_GET(AD7280A_CB_TIMER_VAL_MSK, ret) * 71500; 530*cf890fe8SJonathan Cameron 531*cf890fe8SJonathan Cameron return sysfs_emit(buf, "%u.%u\n", msecs / 1000, msecs % 1000); 532*cf890fe8SJonathan Cameron } 533*cf890fe8SJonathan Cameron 534*cf890fe8SJonathan Cameron static ssize_t ad7280_store_balance_timer(struct iio_dev *indio_dev, 535*cf890fe8SJonathan Cameron uintptr_t private, 536*cf890fe8SJonathan Cameron const struct iio_chan_spec *chan, 537*cf890fe8SJonathan Cameron const char *buf, size_t len) 538*cf890fe8SJonathan Cameron { 539*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 540*cf890fe8SJonathan Cameron int val, val2; 541*cf890fe8SJonathan Cameron int ret; 542*cf890fe8SJonathan Cameron 543*cf890fe8SJonathan Cameron ret = iio_str_to_fixpoint(buf, 1000, &val, &val2); 544*cf890fe8SJonathan Cameron if (ret) 545*cf890fe8SJonathan Cameron return ret; 546*cf890fe8SJonathan Cameron 547*cf890fe8SJonathan Cameron val = val * 1000 + val2; 548*cf890fe8SJonathan Cameron val /= 71500; 549*cf890fe8SJonathan Cameron 550*cf890fe8SJonathan Cameron if (val > 31) 551*cf890fe8SJonathan Cameron return -EINVAL; 552*cf890fe8SJonathan Cameron 553*cf890fe8SJonathan Cameron mutex_lock(&st->lock); 554*cf890fe8SJonathan Cameron ret = ad7280_write(st, chan->address >> 8, 555*cf890fe8SJonathan Cameron (chan->address & 0xFF) + AD7280A_CB1_TIMER_REG, 0, 556*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CB_TIMER_VAL_MSK, val)); 557*cf890fe8SJonathan Cameron mutex_unlock(&st->lock); 558*cf890fe8SJonathan Cameron 559*cf890fe8SJonathan Cameron return ret ? ret : len; 560*cf890fe8SJonathan Cameron } 561*cf890fe8SJonathan Cameron 562*cf890fe8SJonathan Cameron static const struct iio_chan_spec_ext_info ad7280_cell_ext_info[] = { 563*cf890fe8SJonathan Cameron { 564*cf890fe8SJonathan Cameron .name = "balance_switch_en", 565*cf890fe8SJonathan Cameron .read = ad7280_show_balance_sw, 566*cf890fe8SJonathan Cameron .write = ad7280_store_balance_sw, 567*cf890fe8SJonathan Cameron .shared = IIO_SEPARATE, 568*cf890fe8SJonathan Cameron }, { 569*cf890fe8SJonathan Cameron .name = "balance_switch_timer", 570*cf890fe8SJonathan Cameron .read = ad7280_show_balance_timer, 571*cf890fe8SJonathan Cameron .write = ad7280_store_balance_timer, 572*cf890fe8SJonathan Cameron .shared = IIO_SEPARATE, 573*cf890fe8SJonathan Cameron }, 574*cf890fe8SJonathan Cameron {} 575*cf890fe8SJonathan Cameron }; 576*cf890fe8SJonathan Cameron 577*cf890fe8SJonathan Cameron static const struct iio_event_spec ad7280_events[] = { 578*cf890fe8SJonathan Cameron { 579*cf890fe8SJonathan Cameron .type = IIO_EV_TYPE_THRESH, 580*cf890fe8SJonathan Cameron .dir = IIO_EV_DIR_RISING, 581*cf890fe8SJonathan Cameron .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), 582*cf890fe8SJonathan Cameron }, { 583*cf890fe8SJonathan Cameron .type = IIO_EV_TYPE_THRESH, 584*cf890fe8SJonathan Cameron .dir = IIO_EV_DIR_FALLING, 585*cf890fe8SJonathan Cameron .mask_shared_by_type = BIT(IIO_EV_INFO_VALUE), 586*cf890fe8SJonathan Cameron }, 587*cf890fe8SJonathan Cameron }; 588*cf890fe8SJonathan Cameron 589*cf890fe8SJonathan Cameron static void ad7280_voltage_channel_init(struct iio_chan_spec *chan, int i, 590*cf890fe8SJonathan Cameron bool irq_present) 591*cf890fe8SJonathan Cameron { 592*cf890fe8SJonathan Cameron chan->type = IIO_VOLTAGE; 593*cf890fe8SJonathan Cameron chan->differential = 1; 594*cf890fe8SJonathan Cameron chan->channel = i; 595*cf890fe8SJonathan Cameron chan->channel2 = chan->channel + 1; 596*cf890fe8SJonathan Cameron if (irq_present) { 597*cf890fe8SJonathan Cameron chan->event_spec = ad7280_events; 598*cf890fe8SJonathan Cameron chan->num_event_specs = ARRAY_SIZE(ad7280_events); 599*cf890fe8SJonathan Cameron } 600*cf890fe8SJonathan Cameron chan->ext_info = ad7280_cell_ext_info; 601*cf890fe8SJonathan Cameron } 602*cf890fe8SJonathan Cameron 603*cf890fe8SJonathan Cameron static void ad7280_temp_channel_init(struct iio_chan_spec *chan, int i, 604*cf890fe8SJonathan Cameron bool irq_present) 605*cf890fe8SJonathan Cameron { 606*cf890fe8SJonathan Cameron chan->type = IIO_TEMP; 607*cf890fe8SJonathan Cameron chan->channel = i; 608*cf890fe8SJonathan Cameron if (irq_present) { 609*cf890fe8SJonathan Cameron chan->event_spec = ad7280_events; 610*cf890fe8SJonathan Cameron chan->num_event_specs = ARRAY_SIZE(ad7280_events); 611*cf890fe8SJonathan Cameron } 612*cf890fe8SJonathan Cameron } 613*cf890fe8SJonathan Cameron 614*cf890fe8SJonathan Cameron static void ad7280_common_fields_init(struct iio_chan_spec *chan, int addr, 615*cf890fe8SJonathan Cameron int cnt) 616*cf890fe8SJonathan Cameron { 617*cf890fe8SJonathan Cameron chan->indexed = 1; 618*cf890fe8SJonathan Cameron chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); 619*cf890fe8SJonathan Cameron chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); 620*cf890fe8SJonathan Cameron chan->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); 621*cf890fe8SJonathan Cameron chan->address = addr; 622*cf890fe8SJonathan Cameron chan->scan_index = cnt; 623*cf890fe8SJonathan Cameron chan->scan_type.sign = 'u'; 624*cf890fe8SJonathan Cameron chan->scan_type.realbits = 12; 625*cf890fe8SJonathan Cameron chan->scan_type.storagebits = 32; 626*cf890fe8SJonathan Cameron } 627*cf890fe8SJonathan Cameron 628*cf890fe8SJonathan Cameron static void ad7280_total_voltage_channel_init(struct iio_chan_spec *chan, 629*cf890fe8SJonathan Cameron int cnt, int dev) 630*cf890fe8SJonathan Cameron { 631*cf890fe8SJonathan Cameron chan->type = IIO_VOLTAGE; 632*cf890fe8SJonathan Cameron chan->differential = 1; 633*cf890fe8SJonathan Cameron chan->channel = 0; 634*cf890fe8SJonathan Cameron chan->channel2 = dev * AD7280A_CELLS_PER_DEV; 635*cf890fe8SJonathan Cameron chan->address = AD7280A_ALL_CELLS; 636*cf890fe8SJonathan Cameron chan->indexed = 1; 637*cf890fe8SJonathan Cameron chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); 638*cf890fe8SJonathan Cameron chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); 639*cf890fe8SJonathan Cameron chan->scan_index = cnt; 640*cf890fe8SJonathan Cameron chan->scan_type.sign = 'u'; 641*cf890fe8SJonathan Cameron chan->scan_type.realbits = 32; 642*cf890fe8SJonathan Cameron chan->scan_type.storagebits = 32; 643*cf890fe8SJonathan Cameron } 644*cf890fe8SJonathan Cameron 645*cf890fe8SJonathan Cameron static void ad7280_init_dev_channels(struct ad7280_state *st, int dev, int *cnt, 646*cf890fe8SJonathan Cameron bool irq_present) 647*cf890fe8SJonathan Cameron { 648*cf890fe8SJonathan Cameron int addr, ch, i; 649*cf890fe8SJonathan Cameron struct iio_chan_spec *chan; 650*cf890fe8SJonathan Cameron 651*cf890fe8SJonathan Cameron for (ch = AD7280A_CELL_VOLTAGE_1_REG; ch <= AD7280A_AUX_ADC_6_REG; ch++) { 652*cf890fe8SJonathan Cameron chan = &st->channels[*cnt]; 653*cf890fe8SJonathan Cameron 654*cf890fe8SJonathan Cameron if (ch < AD7280A_AUX_ADC_1_REG) { 655*cf890fe8SJonathan Cameron i = AD7280A_CALC_VOLTAGE_CHAN_NUM(dev, ch); 656*cf890fe8SJonathan Cameron ad7280_voltage_channel_init(chan, i, irq_present); 657*cf890fe8SJonathan Cameron } else { 658*cf890fe8SJonathan Cameron i = AD7280A_CALC_TEMP_CHAN_NUM(dev, ch); 659*cf890fe8SJonathan Cameron ad7280_temp_channel_init(chan, i, irq_present); 660*cf890fe8SJonathan Cameron } 661*cf890fe8SJonathan Cameron 662*cf890fe8SJonathan Cameron addr = ad7280a_devaddr(dev) << 8 | ch; 663*cf890fe8SJonathan Cameron ad7280_common_fields_init(chan, addr, *cnt); 664*cf890fe8SJonathan Cameron 665*cf890fe8SJonathan Cameron (*cnt)++; 666*cf890fe8SJonathan Cameron } 667*cf890fe8SJonathan Cameron } 668*cf890fe8SJonathan Cameron 669*cf890fe8SJonathan Cameron static int ad7280_channel_init(struct ad7280_state *st, bool irq_present) 670*cf890fe8SJonathan Cameron { 671*cf890fe8SJonathan Cameron int dev, cnt = 0; 672*cf890fe8SJonathan Cameron 673*cf890fe8SJonathan Cameron st->channels = devm_kcalloc(&st->spi->dev, (st->slave_num + 1) * 12 + 1, 674*cf890fe8SJonathan Cameron sizeof(*st->channels), GFP_KERNEL); 675*cf890fe8SJonathan Cameron if (!st->channels) 676*cf890fe8SJonathan Cameron return -ENOMEM; 677*cf890fe8SJonathan Cameron 678*cf890fe8SJonathan Cameron for (dev = 0; dev <= st->slave_num; dev++) 679*cf890fe8SJonathan Cameron ad7280_init_dev_channels(st, dev, &cnt, irq_present); 680*cf890fe8SJonathan Cameron 681*cf890fe8SJonathan Cameron ad7280_total_voltage_channel_init(&st->channels[cnt], cnt, dev); 682*cf890fe8SJonathan Cameron 683*cf890fe8SJonathan Cameron return cnt + 1; 684*cf890fe8SJonathan Cameron } 685*cf890fe8SJonathan Cameron 686*cf890fe8SJonathan Cameron static int ad7280a_read_thresh(struct iio_dev *indio_dev, 687*cf890fe8SJonathan Cameron const struct iio_chan_spec *chan, 688*cf890fe8SJonathan Cameron enum iio_event_type type, 689*cf890fe8SJonathan Cameron enum iio_event_direction dir, 690*cf890fe8SJonathan Cameron enum iio_event_info info, int *val, int *val2) 691*cf890fe8SJonathan Cameron { 692*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 693*cf890fe8SJonathan Cameron 694*cf890fe8SJonathan Cameron switch (chan->type) { 695*cf890fe8SJonathan Cameron case IIO_VOLTAGE: 696*cf890fe8SJonathan Cameron switch (dir) { 697*cf890fe8SJonathan Cameron case IIO_EV_DIR_RISING: 698*cf890fe8SJonathan Cameron *val = 1000 + (st->cell_threshhigh * 1568L) / 100; 699*cf890fe8SJonathan Cameron return IIO_VAL_INT; 700*cf890fe8SJonathan Cameron case IIO_EV_DIR_FALLING: 701*cf890fe8SJonathan Cameron *val = 1000 + (st->cell_threshlow * 1568L) / 100; 702*cf890fe8SJonathan Cameron return IIO_VAL_INT; 703*cf890fe8SJonathan Cameron default: 704*cf890fe8SJonathan Cameron return -EINVAL; 705*cf890fe8SJonathan Cameron } 706*cf890fe8SJonathan Cameron break; 707*cf890fe8SJonathan Cameron case IIO_TEMP: 708*cf890fe8SJonathan Cameron switch (dir) { 709*cf890fe8SJonathan Cameron case IIO_EV_DIR_RISING: 710*cf890fe8SJonathan Cameron *val = ((st->aux_threshhigh) * 196L) / 10; 711*cf890fe8SJonathan Cameron return IIO_VAL_INT; 712*cf890fe8SJonathan Cameron case IIO_EV_DIR_FALLING: 713*cf890fe8SJonathan Cameron *val = (st->aux_threshlow * 196L) / 10; 714*cf890fe8SJonathan Cameron return IIO_VAL_INT; 715*cf890fe8SJonathan Cameron default: 716*cf890fe8SJonathan Cameron return -EINVAL; 717*cf890fe8SJonathan Cameron } 718*cf890fe8SJonathan Cameron break; 719*cf890fe8SJonathan Cameron default: 720*cf890fe8SJonathan Cameron return -EINVAL; 721*cf890fe8SJonathan Cameron } 722*cf890fe8SJonathan Cameron } 723*cf890fe8SJonathan Cameron 724*cf890fe8SJonathan Cameron static int ad7280a_write_thresh(struct iio_dev *indio_dev, 725*cf890fe8SJonathan Cameron const struct iio_chan_spec *chan, 726*cf890fe8SJonathan Cameron enum iio_event_type type, 727*cf890fe8SJonathan Cameron enum iio_event_direction dir, 728*cf890fe8SJonathan Cameron enum iio_event_info info, 729*cf890fe8SJonathan Cameron int val, int val2) 730*cf890fe8SJonathan Cameron { 731*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 732*cf890fe8SJonathan Cameron unsigned int addr; 733*cf890fe8SJonathan Cameron long value; 734*cf890fe8SJonathan Cameron int ret; 735*cf890fe8SJonathan Cameron 736*cf890fe8SJonathan Cameron if (val2 != 0) 737*cf890fe8SJonathan Cameron return -EINVAL; 738*cf890fe8SJonathan Cameron 739*cf890fe8SJonathan Cameron mutex_lock(&st->lock); 740*cf890fe8SJonathan Cameron switch (chan->type) { 741*cf890fe8SJonathan Cameron case IIO_VOLTAGE: 742*cf890fe8SJonathan Cameron value = ((val - 1000) * 100) / 1568; /* LSB 15.68mV */ 743*cf890fe8SJonathan Cameron value = clamp(value, 0L, 0xFFL); 744*cf890fe8SJonathan Cameron switch (dir) { 745*cf890fe8SJonathan Cameron case IIO_EV_DIR_RISING: 746*cf890fe8SJonathan Cameron addr = AD7280A_CELL_OVERVOLTAGE_REG; 747*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, 748*cf890fe8SJonathan Cameron 1, val); 749*cf890fe8SJonathan Cameron if (ret) 750*cf890fe8SJonathan Cameron break; 751*cf890fe8SJonathan Cameron st->cell_threshhigh = value; 752*cf890fe8SJonathan Cameron break; 753*cf890fe8SJonathan Cameron case IIO_EV_DIR_FALLING: 754*cf890fe8SJonathan Cameron addr = AD7280A_CELL_UNDERVOLTAGE_REG; 755*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, 756*cf890fe8SJonathan Cameron 1, val); 757*cf890fe8SJonathan Cameron if (ret) 758*cf890fe8SJonathan Cameron break; 759*cf890fe8SJonathan Cameron st->cell_threshlow = value; 760*cf890fe8SJonathan Cameron break; 761*cf890fe8SJonathan Cameron default: 762*cf890fe8SJonathan Cameron ret = -EINVAL; 763*cf890fe8SJonathan Cameron goto err_unlock; 764*cf890fe8SJonathan Cameron } 765*cf890fe8SJonathan Cameron break; 766*cf890fe8SJonathan Cameron case IIO_TEMP: 767*cf890fe8SJonathan Cameron value = (val * 10) / 196; /* LSB 19.6mV */ 768*cf890fe8SJonathan Cameron value = clamp(value, 0L, 0xFFL); 769*cf890fe8SJonathan Cameron switch (dir) { 770*cf890fe8SJonathan Cameron case IIO_EV_DIR_RISING: 771*cf890fe8SJonathan Cameron addr = AD7280A_AUX_ADC_OVERVOLTAGE_REG; 772*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, 773*cf890fe8SJonathan Cameron 1, val); 774*cf890fe8SJonathan Cameron if (ret) 775*cf890fe8SJonathan Cameron break; 776*cf890fe8SJonathan Cameron st->aux_threshhigh = val; 777*cf890fe8SJonathan Cameron break; 778*cf890fe8SJonathan Cameron case IIO_EV_DIR_FALLING: 779*cf890fe8SJonathan Cameron addr = AD7280A_AUX_ADC_UNDERVOLTAGE_REG; 780*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, addr, 781*cf890fe8SJonathan Cameron 1, val); 782*cf890fe8SJonathan Cameron if (ret) 783*cf890fe8SJonathan Cameron break; 784*cf890fe8SJonathan Cameron st->aux_threshlow = val; 785*cf890fe8SJonathan Cameron break; 786*cf890fe8SJonathan Cameron default: 787*cf890fe8SJonathan Cameron ret = -EINVAL; 788*cf890fe8SJonathan Cameron goto err_unlock; 789*cf890fe8SJonathan Cameron } 790*cf890fe8SJonathan Cameron break; 791*cf890fe8SJonathan Cameron default: 792*cf890fe8SJonathan Cameron ret = -EINVAL; 793*cf890fe8SJonathan Cameron goto err_unlock; 794*cf890fe8SJonathan Cameron } 795*cf890fe8SJonathan Cameron 796*cf890fe8SJonathan Cameron err_unlock: 797*cf890fe8SJonathan Cameron mutex_unlock(&st->lock); 798*cf890fe8SJonathan Cameron 799*cf890fe8SJonathan Cameron return ret; 800*cf890fe8SJonathan Cameron } 801*cf890fe8SJonathan Cameron 802*cf890fe8SJonathan Cameron static irqreturn_t ad7280_event_handler(int irq, void *private) 803*cf890fe8SJonathan Cameron { 804*cf890fe8SJonathan Cameron struct iio_dev *indio_dev = private; 805*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 806*cf890fe8SJonathan Cameron unsigned int *channels; 807*cf890fe8SJonathan Cameron int i, ret; 808*cf890fe8SJonathan Cameron 809*cf890fe8SJonathan Cameron channels = kcalloc(st->scan_cnt, sizeof(*channels), GFP_KERNEL); 810*cf890fe8SJonathan Cameron if (!channels) 811*cf890fe8SJonathan Cameron return IRQ_HANDLED; 812*cf890fe8SJonathan Cameron 813*cf890fe8SJonathan Cameron ret = ad7280_read_all_channels(st, st->scan_cnt, channels); 814*cf890fe8SJonathan Cameron if (ret < 0) 815*cf890fe8SJonathan Cameron goto out; 816*cf890fe8SJonathan Cameron 817*cf890fe8SJonathan Cameron for (i = 0; i < st->scan_cnt; i++) { 818*cf890fe8SJonathan Cameron unsigned int val; 819*cf890fe8SJonathan Cameron 820*cf890fe8SJonathan Cameron val = FIELD_GET(AD7280A_TRANS_READ_CONV_DATA_MSK, channels[i]); 821*cf890fe8SJonathan Cameron if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, channels[i]) <= 822*cf890fe8SJonathan Cameron AD7280A_CELL_VOLTAGE_6_REG) { 823*cf890fe8SJonathan Cameron if (val >= st->cell_threshhigh) { 824*cf890fe8SJonathan Cameron u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0, 825*cf890fe8SJonathan Cameron IIO_EV_DIR_RISING, 826*cf890fe8SJonathan Cameron IIO_EV_TYPE_THRESH, 827*cf890fe8SJonathan Cameron 0, 0, 0); 828*cf890fe8SJonathan Cameron iio_push_event(indio_dev, tmp, 829*cf890fe8SJonathan Cameron iio_get_time_ns(indio_dev)); 830*cf890fe8SJonathan Cameron } else if (val <= st->cell_threshlow) { 831*cf890fe8SJonathan Cameron u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0, 832*cf890fe8SJonathan Cameron IIO_EV_DIR_FALLING, 833*cf890fe8SJonathan Cameron IIO_EV_TYPE_THRESH, 834*cf890fe8SJonathan Cameron 0, 0, 0); 835*cf890fe8SJonathan Cameron iio_push_event(indio_dev, tmp, 836*cf890fe8SJonathan Cameron iio_get_time_ns(indio_dev)); 837*cf890fe8SJonathan Cameron } 838*cf890fe8SJonathan Cameron } else { 839*cf890fe8SJonathan Cameron if (val >= st->aux_threshhigh) { 840*cf890fe8SJonathan Cameron u64 tmp = IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, 841*cf890fe8SJonathan Cameron IIO_EV_TYPE_THRESH, 842*cf890fe8SJonathan Cameron IIO_EV_DIR_RISING); 843*cf890fe8SJonathan Cameron iio_push_event(indio_dev, tmp, 844*cf890fe8SJonathan Cameron iio_get_time_ns(indio_dev)); 845*cf890fe8SJonathan Cameron } else if (val <= st->aux_threshlow) { 846*cf890fe8SJonathan Cameron u64 tmp = IIO_UNMOD_EVENT_CODE(IIO_TEMP, 0, 847*cf890fe8SJonathan Cameron IIO_EV_TYPE_THRESH, 848*cf890fe8SJonathan Cameron IIO_EV_DIR_FALLING); 849*cf890fe8SJonathan Cameron iio_push_event(indio_dev, tmp, 850*cf890fe8SJonathan Cameron iio_get_time_ns(indio_dev)); 851*cf890fe8SJonathan Cameron } 852*cf890fe8SJonathan Cameron } 853*cf890fe8SJonathan Cameron } 854*cf890fe8SJonathan Cameron 855*cf890fe8SJonathan Cameron out: 856*cf890fe8SJonathan Cameron kfree(channels); 857*cf890fe8SJonathan Cameron 858*cf890fe8SJonathan Cameron return IRQ_HANDLED; 859*cf890fe8SJonathan Cameron } 860*cf890fe8SJonathan Cameron 861*cf890fe8SJonathan Cameron static void ad7280_update_delay(struct ad7280_state *st) 862*cf890fe8SJonathan Cameron { 863*cf890fe8SJonathan Cameron /* 864*cf890fe8SJonathan Cameron * Total Conversion Time = ((tACQ + tCONV) * 865*cf890fe8SJonathan Cameron * (Number of Conversions per Part)) − 866*cf890fe8SJonathan Cameron * tACQ + ((N - 1) * tDELAY) 867*cf890fe8SJonathan Cameron * 868*cf890fe8SJonathan Cameron * Readback Delay = Total Conversion Time + tWAIT 869*cf890fe8SJonathan Cameron */ 870*cf890fe8SJonathan Cameron 871*cf890fe8SJonathan Cameron st->readback_delay_us = 872*cf890fe8SJonathan Cameron ((ad7280a_t_acq_ns[st->acquisition_time & 0x3] + 720) * 873*cf890fe8SJonathan Cameron (AD7280A_NUM_CH * ad7280a_n_avg[st->oversampling_ratio & 0x3])) - 874*cf890fe8SJonathan Cameron ad7280a_t_acq_ns[st->acquisition_time & 0x3] + st->slave_num * 250; 875*cf890fe8SJonathan Cameron 876*cf890fe8SJonathan Cameron /* Convert to usecs */ 877*cf890fe8SJonathan Cameron st->readback_delay_us = DIV_ROUND_UP(st->readback_delay_us, 1000); 878*cf890fe8SJonathan Cameron st->readback_delay_us += 5; /* Add tWAIT */ 879*cf890fe8SJonathan Cameron } 880*cf890fe8SJonathan Cameron 881*cf890fe8SJonathan Cameron static int ad7280_read_raw(struct iio_dev *indio_dev, 882*cf890fe8SJonathan Cameron struct iio_chan_spec const *chan, 883*cf890fe8SJonathan Cameron int *val, 884*cf890fe8SJonathan Cameron int *val2, 885*cf890fe8SJonathan Cameron long m) 886*cf890fe8SJonathan Cameron { 887*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 888*cf890fe8SJonathan Cameron int ret; 889*cf890fe8SJonathan Cameron 890*cf890fe8SJonathan Cameron switch (m) { 891*cf890fe8SJonathan Cameron case IIO_CHAN_INFO_RAW: 892*cf890fe8SJonathan Cameron mutex_lock(&st->lock); 893*cf890fe8SJonathan Cameron if (chan->address == AD7280A_ALL_CELLS) 894*cf890fe8SJonathan Cameron ret = ad7280_read_all_channels(st, st->scan_cnt, NULL); 895*cf890fe8SJonathan Cameron else 896*cf890fe8SJonathan Cameron ret = ad7280_read_channel(st, chan->address >> 8, 897*cf890fe8SJonathan Cameron chan->address & 0xFF); 898*cf890fe8SJonathan Cameron mutex_unlock(&st->lock); 899*cf890fe8SJonathan Cameron 900*cf890fe8SJonathan Cameron if (ret < 0) 901*cf890fe8SJonathan Cameron return ret; 902*cf890fe8SJonathan Cameron 903*cf890fe8SJonathan Cameron *val = ret; 904*cf890fe8SJonathan Cameron 905*cf890fe8SJonathan Cameron return IIO_VAL_INT; 906*cf890fe8SJonathan Cameron case IIO_CHAN_INFO_SCALE: 907*cf890fe8SJonathan Cameron if ((chan->address & 0xFF) <= AD7280A_CELL_VOLTAGE_6_REG) 908*cf890fe8SJonathan Cameron *val = 4000; 909*cf890fe8SJonathan Cameron else 910*cf890fe8SJonathan Cameron *val = 5000; 911*cf890fe8SJonathan Cameron 912*cf890fe8SJonathan Cameron *val2 = AD7280A_BITS; 913*cf890fe8SJonathan Cameron return IIO_VAL_FRACTIONAL_LOG2; 914*cf890fe8SJonathan Cameron case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 915*cf890fe8SJonathan Cameron *val = ad7280a_n_avg[st->oversampling_ratio]; 916*cf890fe8SJonathan Cameron return IIO_VAL_INT; 917*cf890fe8SJonathan Cameron } 918*cf890fe8SJonathan Cameron return -EINVAL; 919*cf890fe8SJonathan Cameron } 920*cf890fe8SJonathan Cameron 921*cf890fe8SJonathan Cameron static int ad7280_write_raw(struct iio_dev *indio_dev, 922*cf890fe8SJonathan Cameron struct iio_chan_spec const *chan, 923*cf890fe8SJonathan Cameron int val, int val2, long mask) 924*cf890fe8SJonathan Cameron { 925*cf890fe8SJonathan Cameron struct ad7280_state *st = iio_priv(indio_dev); 926*cf890fe8SJonathan Cameron int i; 927*cf890fe8SJonathan Cameron 928*cf890fe8SJonathan Cameron switch (mask) { 929*cf890fe8SJonathan Cameron case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 930*cf890fe8SJonathan Cameron if (val2 != 0) 931*cf890fe8SJonathan Cameron return -EINVAL; 932*cf890fe8SJonathan Cameron for (i = 0; i < ARRAY_SIZE(ad7280a_n_avg); i++) { 933*cf890fe8SJonathan Cameron if (val == ad7280a_n_avg[i]) { 934*cf890fe8SJonathan Cameron st->oversampling_ratio = i; 935*cf890fe8SJonathan Cameron ad7280_update_delay(st); 936*cf890fe8SJonathan Cameron return 0; 937*cf890fe8SJonathan Cameron } 938*cf890fe8SJonathan Cameron } 939*cf890fe8SJonathan Cameron return -EINVAL; 940*cf890fe8SJonathan Cameron default: 941*cf890fe8SJonathan Cameron return -EINVAL; 942*cf890fe8SJonathan Cameron } 943*cf890fe8SJonathan Cameron } 944*cf890fe8SJonathan Cameron 945*cf890fe8SJonathan Cameron static const struct iio_info ad7280_info = { 946*cf890fe8SJonathan Cameron .read_raw = ad7280_read_raw, 947*cf890fe8SJonathan Cameron .write_raw = ad7280_write_raw, 948*cf890fe8SJonathan Cameron .read_event_value = &ad7280a_read_thresh, 949*cf890fe8SJonathan Cameron .write_event_value = &ad7280a_write_thresh, 950*cf890fe8SJonathan Cameron }; 951*cf890fe8SJonathan Cameron 952*cf890fe8SJonathan Cameron static const struct iio_info ad7280_info_no_irq = { 953*cf890fe8SJonathan Cameron .read_raw = ad7280_read_raw, 954*cf890fe8SJonathan Cameron .write_raw = ad7280_write_raw, 955*cf890fe8SJonathan Cameron }; 956*cf890fe8SJonathan Cameron 957*cf890fe8SJonathan Cameron static int ad7280_probe(struct spi_device *spi) 958*cf890fe8SJonathan Cameron { 959*cf890fe8SJonathan Cameron struct device *dev = &spi->dev; 960*cf890fe8SJonathan Cameron struct ad7280_state *st; 961*cf890fe8SJonathan Cameron int ret; 962*cf890fe8SJonathan Cameron struct iio_dev *indio_dev; 963*cf890fe8SJonathan Cameron 964*cf890fe8SJonathan Cameron indio_dev = devm_iio_device_alloc(dev, sizeof(*st)); 965*cf890fe8SJonathan Cameron if (!indio_dev) 966*cf890fe8SJonathan Cameron return -ENOMEM; 967*cf890fe8SJonathan Cameron 968*cf890fe8SJonathan Cameron st = iio_priv(indio_dev); 969*cf890fe8SJonathan Cameron spi_set_drvdata(spi, indio_dev); 970*cf890fe8SJonathan Cameron st->spi = spi; 971*cf890fe8SJonathan Cameron mutex_init(&st->lock); 972*cf890fe8SJonathan Cameron 973*cf890fe8SJonathan Cameron st->thermistor_term_en = 974*cf890fe8SJonathan Cameron device_property_read_bool(dev, "adi,thermistor-termination"); 975*cf890fe8SJonathan Cameron 976*cf890fe8SJonathan Cameron if (device_property_present(dev, "adi,acquisition-time-ns")) { 977*cf890fe8SJonathan Cameron u32 val; 978*cf890fe8SJonathan Cameron 979*cf890fe8SJonathan Cameron ret = device_property_read_u32(dev, "adi,acquisition-time-ns", &val); 980*cf890fe8SJonathan Cameron if (ret) 981*cf890fe8SJonathan Cameron return ret; 982*cf890fe8SJonathan Cameron 983*cf890fe8SJonathan Cameron switch (val) { 984*cf890fe8SJonathan Cameron case 400: 985*cf890fe8SJonathan Cameron st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_400ns; 986*cf890fe8SJonathan Cameron break; 987*cf890fe8SJonathan Cameron case 800: 988*cf890fe8SJonathan Cameron st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_800ns; 989*cf890fe8SJonathan Cameron break; 990*cf890fe8SJonathan Cameron case 1200: 991*cf890fe8SJonathan Cameron st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_1200ns; 992*cf890fe8SJonathan Cameron break; 993*cf890fe8SJonathan Cameron case 1600: 994*cf890fe8SJonathan Cameron st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_1600ns; 995*cf890fe8SJonathan Cameron break; 996*cf890fe8SJonathan Cameron default: 997*cf890fe8SJonathan Cameron dev_err(dev, "Firmware provided acquisition time is invalid\n"); 998*cf890fe8SJonathan Cameron return -EINVAL; 999*cf890fe8SJonathan Cameron } 1000*cf890fe8SJonathan Cameron } else { 1001*cf890fe8SJonathan Cameron st->acquisition_time = AD7280A_CTRL_LB_ACQ_TIME_400ns; 1002*cf890fe8SJonathan Cameron } 1003*cf890fe8SJonathan Cameron 1004*cf890fe8SJonathan Cameron /* Alert masks are intended for when particular inputs are not wired up */ 1005*cf890fe8SJonathan Cameron if (device_property_present(dev, "adi,voltage-alert-last-chan")) { 1006*cf890fe8SJonathan Cameron u32 val; 1007*cf890fe8SJonathan Cameron 1008*cf890fe8SJonathan Cameron ret = device_property_read_u32(dev, "adi,voltage-alert-last-chan", &val); 1009*cf890fe8SJonathan Cameron if (ret) 1010*cf890fe8SJonathan Cameron return ret; 1011*cf890fe8SJonathan Cameron 1012*cf890fe8SJonathan Cameron switch (val) { 1013*cf890fe8SJonathan Cameron case 3: 1014*cf890fe8SJonathan Cameron st->chain_last_alert_ignore |= AD7280A_ALERT_REMOVE_VIN4_VIN5; 1015*cf890fe8SJonathan Cameron break; 1016*cf890fe8SJonathan Cameron case 4: 1017*cf890fe8SJonathan Cameron st->chain_last_alert_ignore |= AD7280A_ALERT_REMOVE_VIN5; 1018*cf890fe8SJonathan Cameron break; 1019*cf890fe8SJonathan Cameron case 5: 1020*cf890fe8SJonathan Cameron break; 1021*cf890fe8SJonathan Cameron default: 1022*cf890fe8SJonathan Cameron dev_err(dev, 1023*cf890fe8SJonathan Cameron "Firmware provided last voltage alert channel invalid\n"); 1024*cf890fe8SJonathan Cameron break; 1025*cf890fe8SJonathan Cameron } 1026*cf890fe8SJonathan Cameron } 1027*cf890fe8SJonathan Cameron crc8_populate_msb(st->crc_tab, POLYNOM); 1028*cf890fe8SJonathan Cameron 1029*cf890fe8SJonathan Cameron st->spi->max_speed_hz = AD7280A_MAX_SPI_CLK_HZ; 1030*cf890fe8SJonathan Cameron st->spi->mode = SPI_MODE_1; 1031*cf890fe8SJonathan Cameron spi_setup(st->spi); 1032*cf890fe8SJonathan Cameron 1033*cf890fe8SJonathan Cameron st->ctrl_lb = FIELD_PREP(AD7280A_CTRL_LB_ACQ_TIME_MSK, st->acquisition_time) | 1034*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_CTRL_LB_THERMISTOR_MSK, st->thermistor_term_en); 1035*cf890fe8SJonathan Cameron st->oversampling_ratio = 0; /* No oversampling */ 1036*cf890fe8SJonathan Cameron 1037*cf890fe8SJonathan Cameron ret = ad7280_chain_setup(st); 1038*cf890fe8SJonathan Cameron if (ret < 0) 1039*cf890fe8SJonathan Cameron return ret; 1040*cf890fe8SJonathan Cameron 1041*cf890fe8SJonathan Cameron st->slave_num = ret; 1042*cf890fe8SJonathan Cameron st->scan_cnt = (st->slave_num + 1) * AD7280A_NUM_CH; 1043*cf890fe8SJonathan Cameron st->cell_threshhigh = 0xFF; 1044*cf890fe8SJonathan Cameron st->aux_threshhigh = 0xFF; 1045*cf890fe8SJonathan Cameron 1046*cf890fe8SJonathan Cameron ret = devm_add_action_or_reset(dev, ad7280_sw_power_down, st); 1047*cf890fe8SJonathan Cameron if (ret) 1048*cf890fe8SJonathan Cameron return ret; 1049*cf890fe8SJonathan Cameron 1050*cf890fe8SJonathan Cameron ad7280_update_delay(st); 1051*cf890fe8SJonathan Cameron 1052*cf890fe8SJonathan Cameron indio_dev->name = spi_get_device_id(spi)->name; 1053*cf890fe8SJonathan Cameron indio_dev->modes = INDIO_DIRECT_MODE; 1054*cf890fe8SJonathan Cameron 1055*cf890fe8SJonathan Cameron ret = ad7280_channel_init(st, spi->irq > 0); 1056*cf890fe8SJonathan Cameron if (ret < 0) 1057*cf890fe8SJonathan Cameron return ret; 1058*cf890fe8SJonathan Cameron 1059*cf890fe8SJonathan Cameron indio_dev->num_channels = ret; 1060*cf890fe8SJonathan Cameron indio_dev->channels = st->channels; 1061*cf890fe8SJonathan Cameron if (spi->irq > 0) { 1062*cf890fe8SJonathan Cameron ret = ad7280_write(st, AD7280A_DEVADDR_MASTER, 1063*cf890fe8SJonathan Cameron AD7280A_ALERT_REG, 1, 1064*cf890fe8SJonathan Cameron AD7280A_ALERT_RELAY_SIG_CHAIN_DOWN); 1065*cf890fe8SJonathan Cameron if (ret) 1066*cf890fe8SJonathan Cameron return ret; 1067*cf890fe8SJonathan Cameron 1068*cf890fe8SJonathan Cameron ret = ad7280_write(st, ad7280a_devaddr(st->slave_num), 1069*cf890fe8SJonathan Cameron AD7280A_ALERT_REG, 0, 1070*cf890fe8SJonathan Cameron AD7280A_ALERT_GEN_STATIC_HIGH | 1071*cf890fe8SJonathan Cameron FIELD_PREP(AD7280A_ALERT_REMOVE_MSK, 1072*cf890fe8SJonathan Cameron st->chain_last_alert_ignore)); 1073*cf890fe8SJonathan Cameron if (ret) 1074*cf890fe8SJonathan Cameron return ret; 1075*cf890fe8SJonathan Cameron 1076*cf890fe8SJonathan Cameron ret = devm_request_threaded_irq(dev, spi->irq, 1077*cf890fe8SJonathan Cameron NULL, 1078*cf890fe8SJonathan Cameron ad7280_event_handler, 1079*cf890fe8SJonathan Cameron IRQF_TRIGGER_FALLING | 1080*cf890fe8SJonathan Cameron IRQF_ONESHOT, 1081*cf890fe8SJonathan Cameron indio_dev->name, 1082*cf890fe8SJonathan Cameron indio_dev); 1083*cf890fe8SJonathan Cameron if (ret) 1084*cf890fe8SJonathan Cameron return ret; 1085*cf890fe8SJonathan Cameron 1086*cf890fe8SJonathan Cameron indio_dev->info = &ad7280_info; 1087*cf890fe8SJonathan Cameron } else { 1088*cf890fe8SJonathan Cameron indio_dev->info = &ad7280_info_no_irq; 1089*cf890fe8SJonathan Cameron } 1090*cf890fe8SJonathan Cameron 1091*cf890fe8SJonathan Cameron return devm_iio_device_register(dev, indio_dev); 1092*cf890fe8SJonathan Cameron } 1093*cf890fe8SJonathan Cameron 1094*cf890fe8SJonathan Cameron static const struct spi_device_id ad7280_id[] = { 1095*cf890fe8SJonathan Cameron {"ad7280a", 0}, 1096*cf890fe8SJonathan Cameron {} 1097*cf890fe8SJonathan Cameron }; 1098*cf890fe8SJonathan Cameron MODULE_DEVICE_TABLE(spi, ad7280_id); 1099*cf890fe8SJonathan Cameron 1100*cf890fe8SJonathan Cameron static struct spi_driver ad7280_driver = { 1101*cf890fe8SJonathan Cameron .driver = { 1102*cf890fe8SJonathan Cameron .name = "ad7280", 1103*cf890fe8SJonathan Cameron }, 1104*cf890fe8SJonathan Cameron .probe = ad7280_probe, 1105*cf890fe8SJonathan Cameron .id_table = ad7280_id, 1106*cf890fe8SJonathan Cameron }; 1107*cf890fe8SJonathan Cameron module_spi_driver(ad7280_driver); 1108*cf890fe8SJonathan Cameron 1109*cf890fe8SJonathan Cameron MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>"); 1110*cf890fe8SJonathan Cameron MODULE_DESCRIPTION("Analog Devices AD7280A"); 1111*cf890fe8SJonathan Cameron MODULE_LICENSE("GPL v2"); 1112