1*15dbaed4SAntoni Pokusinski // SPDX-License-Identifier: GPL-2.0 2*15dbaed4SAntoni Pokusinski /* 3*15dbaed4SAntoni Pokusinski * Silicon Labs Si7210 Hall Effect sensor driver 4*15dbaed4SAntoni Pokusinski * 5*15dbaed4SAntoni Pokusinski * Copyright (c) 2024 Antoni Pokusinski <apokusinski01@gmail.com> 6*15dbaed4SAntoni Pokusinski * 7*15dbaed4SAntoni Pokusinski * Datasheet: 8*15dbaed4SAntoni Pokusinski * https://www.silabs.com/documents/public/data-sheets/si7210-datasheet.pdf 9*15dbaed4SAntoni Pokusinski */ 10*15dbaed4SAntoni Pokusinski 11*15dbaed4SAntoni Pokusinski #include <linux/array_size.h> 12*15dbaed4SAntoni Pokusinski #include <linux/bitfield.h> 13*15dbaed4SAntoni Pokusinski #include <linux/bits.h> 14*15dbaed4SAntoni Pokusinski #include <linux/cleanup.h> 15*15dbaed4SAntoni Pokusinski #include <linux/err.h> 16*15dbaed4SAntoni Pokusinski #include <linux/i2c.h> 17*15dbaed4SAntoni Pokusinski #include <linux/iio/iio.h> 18*15dbaed4SAntoni Pokusinski #include <linux/math64.h> 19*15dbaed4SAntoni Pokusinski #include <linux/mod_devicetable.h> 20*15dbaed4SAntoni Pokusinski #include <linux/mutex.h> 21*15dbaed4SAntoni Pokusinski #include <linux/regmap.h> 22*15dbaed4SAntoni Pokusinski #include <linux/regulator/consumer.h> 23*15dbaed4SAntoni Pokusinski #include <linux/types.h> 24*15dbaed4SAntoni Pokusinski #include <linux/units.h> 25*15dbaed4SAntoni Pokusinski #include <asm/byteorder.h> 26*15dbaed4SAntoni Pokusinski 27*15dbaed4SAntoni Pokusinski /* Registers offsets and masks */ 28*15dbaed4SAntoni Pokusinski #define SI7210_REG_DSPSIGM 0xC1 29*15dbaed4SAntoni Pokusinski #define SI7210_REG_DSPSIGL 0xC2 30*15dbaed4SAntoni Pokusinski 31*15dbaed4SAntoni Pokusinski #define SI7210_MASK_DSPSIGSEL GENMASK(2, 0) 32*15dbaed4SAntoni Pokusinski #define SI7210_REG_DSPSIGSEL 0xC3 33*15dbaed4SAntoni Pokusinski 34*15dbaed4SAntoni Pokusinski #define SI7210_MASK_STOP BIT(1) 35*15dbaed4SAntoni Pokusinski #define SI7210_MASK_ONEBURST BIT(2) 36*15dbaed4SAntoni Pokusinski #define SI7210_REG_POWER_CTRL 0xC4 37*15dbaed4SAntoni Pokusinski 38*15dbaed4SAntoni Pokusinski #define SI7210_MASK_ARAUTOINC BIT(0) 39*15dbaed4SAntoni Pokusinski #define SI7210_REG_ARAUTOINC 0xC5 40*15dbaed4SAntoni Pokusinski 41*15dbaed4SAntoni Pokusinski #define SI7210_REG_A0 0xCA 42*15dbaed4SAntoni Pokusinski #define SI7210_REG_A1 0xCB 43*15dbaed4SAntoni Pokusinski #define SI7210_REG_A2 0xCC 44*15dbaed4SAntoni Pokusinski #define SI7210_REG_A3 0xCE 45*15dbaed4SAntoni Pokusinski #define SI7210_REG_A4 0xCF 46*15dbaed4SAntoni Pokusinski #define SI7210_REG_A5 0xD0 47*15dbaed4SAntoni Pokusinski 48*15dbaed4SAntoni Pokusinski #define SI7210_REG_OTP_ADDR 0xE1 49*15dbaed4SAntoni Pokusinski #define SI7210_REG_OTP_DATA 0xE2 50*15dbaed4SAntoni Pokusinski 51*15dbaed4SAntoni Pokusinski #define SI7210_MASK_OTP_READ_EN BIT(1) 52*15dbaed4SAntoni Pokusinski #define SI7210_REG_OTP_CTRL 0xE3 53*15dbaed4SAntoni Pokusinski 54*15dbaed4SAntoni Pokusinski /* OTP data registers offsets */ 55*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_TMP_OFF 0x1D 56*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_TMP_GAIN 0x1E 57*15dbaed4SAntoni Pokusinski 58*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A0_20 0x21 59*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A1_20 0x22 60*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A2_20 0x23 61*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A3_20 0x24 62*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A4_20 0x25 63*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A5_20 0x26 64*15dbaed4SAntoni Pokusinski 65*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A0_200 0x27 66*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A1_200 0x28 67*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A2_200 0x29 68*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A3_200 0x2A 69*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A4_200 0x2B 70*15dbaed4SAntoni Pokusinski #define SI7210_OTPREG_A5_200 0x2C 71*15dbaed4SAntoni Pokusinski 72*15dbaed4SAntoni Pokusinski #define A_REGS_COUNT 6 73*15dbaed4SAntoni Pokusinski 74*15dbaed4SAntoni Pokusinski static const unsigned int a20_otp_regs[A_REGS_COUNT] = { 75*15dbaed4SAntoni Pokusinski SI7210_OTPREG_A0_20, SI7210_OTPREG_A1_20, SI7210_OTPREG_A2_20, 76*15dbaed4SAntoni Pokusinski SI7210_OTPREG_A3_20, SI7210_OTPREG_A4_20, SI7210_OTPREG_A5_20, 77*15dbaed4SAntoni Pokusinski }; 78*15dbaed4SAntoni Pokusinski 79*15dbaed4SAntoni Pokusinski static const unsigned int a200_otp_regs[A_REGS_COUNT] = { 80*15dbaed4SAntoni Pokusinski SI7210_OTPREG_A0_200, SI7210_OTPREG_A1_200, SI7210_OTPREG_A2_200, 81*15dbaed4SAntoni Pokusinski SI7210_OTPREG_A3_200, SI7210_OTPREG_A4_200, SI7210_OTPREG_A5_200, 82*15dbaed4SAntoni Pokusinski }; 83*15dbaed4SAntoni Pokusinski 84*15dbaed4SAntoni Pokusinski static const struct regmap_range si7210_read_reg_ranges[] = { 85*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_DSPSIGM, SI7210_REG_ARAUTOINC), 86*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_A0, SI7210_REG_A2), 87*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_A3, SI7210_REG_A5), 88*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_OTP_ADDR, SI7210_REG_OTP_CTRL), 89*15dbaed4SAntoni Pokusinski }; 90*15dbaed4SAntoni Pokusinski 91*15dbaed4SAntoni Pokusinski static const struct regmap_access_table si7210_readable_regs = { 92*15dbaed4SAntoni Pokusinski .yes_ranges = si7210_read_reg_ranges, 93*15dbaed4SAntoni Pokusinski .n_yes_ranges = ARRAY_SIZE(si7210_read_reg_ranges), 94*15dbaed4SAntoni Pokusinski }; 95*15dbaed4SAntoni Pokusinski 96*15dbaed4SAntoni Pokusinski static const struct regmap_range si7210_write_reg_ranges[] = { 97*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_DSPSIGSEL, SI7210_REG_ARAUTOINC), 98*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_A0, SI7210_REG_A2), 99*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_A3, SI7210_REG_A5), 100*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_OTP_ADDR, SI7210_REG_OTP_CTRL), 101*15dbaed4SAntoni Pokusinski }; 102*15dbaed4SAntoni Pokusinski 103*15dbaed4SAntoni Pokusinski static const struct regmap_access_table si7210_writeable_regs = { 104*15dbaed4SAntoni Pokusinski .yes_ranges = si7210_write_reg_ranges, 105*15dbaed4SAntoni Pokusinski .n_yes_ranges = ARRAY_SIZE(si7210_write_reg_ranges), 106*15dbaed4SAntoni Pokusinski }; 107*15dbaed4SAntoni Pokusinski 108*15dbaed4SAntoni Pokusinski static const struct regmap_range si7210_volatile_reg_ranges[] = { 109*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_DSPSIGM, SI7210_REG_DSPSIGL), 110*15dbaed4SAntoni Pokusinski regmap_reg_range(SI7210_REG_POWER_CTRL, SI7210_REG_POWER_CTRL), 111*15dbaed4SAntoni Pokusinski }; 112*15dbaed4SAntoni Pokusinski 113*15dbaed4SAntoni Pokusinski static const struct regmap_access_table si7210_volatile_regs = { 114*15dbaed4SAntoni Pokusinski .yes_ranges = si7210_volatile_reg_ranges, 115*15dbaed4SAntoni Pokusinski .n_yes_ranges = ARRAY_SIZE(si7210_volatile_reg_ranges), 116*15dbaed4SAntoni Pokusinski }; 117*15dbaed4SAntoni Pokusinski 118*15dbaed4SAntoni Pokusinski static const struct regmap_config si7210_regmap_conf = { 119*15dbaed4SAntoni Pokusinski .reg_bits = 8, 120*15dbaed4SAntoni Pokusinski .val_bits = 8, 121*15dbaed4SAntoni Pokusinski .max_register = SI7210_REG_OTP_CTRL, 122*15dbaed4SAntoni Pokusinski 123*15dbaed4SAntoni Pokusinski .rd_table = &si7210_readable_regs, 124*15dbaed4SAntoni Pokusinski .wr_table = &si7210_writeable_regs, 125*15dbaed4SAntoni Pokusinski .volatile_table = &si7210_volatile_regs, 126*15dbaed4SAntoni Pokusinski }; 127*15dbaed4SAntoni Pokusinski 128*15dbaed4SAntoni Pokusinski struct si7210_data { 129*15dbaed4SAntoni Pokusinski struct regmap *regmap; 130*15dbaed4SAntoni Pokusinski struct i2c_client *client; 131*15dbaed4SAntoni Pokusinski struct regulator *vdd; 132*15dbaed4SAntoni Pokusinski struct mutex fetch_lock; /* lock for a single measurement fetch */ 133*15dbaed4SAntoni Pokusinski s8 temp_offset; 134*15dbaed4SAntoni Pokusinski s8 temp_gain; 135*15dbaed4SAntoni Pokusinski s8 scale_20_a[A_REGS_COUNT]; 136*15dbaed4SAntoni Pokusinski s8 scale_200_a[A_REGS_COUNT]; 137*15dbaed4SAntoni Pokusinski u8 curr_scale; 138*15dbaed4SAntoni Pokusinski }; 139*15dbaed4SAntoni Pokusinski 140*15dbaed4SAntoni Pokusinski static const struct iio_chan_spec si7210_channels[] = { 141*15dbaed4SAntoni Pokusinski { 142*15dbaed4SAntoni Pokusinski .type = IIO_MAGN, 143*15dbaed4SAntoni Pokusinski .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 144*15dbaed4SAntoni Pokusinski BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET), 145*15dbaed4SAntoni Pokusinski }, { 146*15dbaed4SAntoni Pokusinski .type = IIO_TEMP, 147*15dbaed4SAntoni Pokusinski .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), 148*15dbaed4SAntoni Pokusinski }, 149*15dbaed4SAntoni Pokusinski }; 150*15dbaed4SAntoni Pokusinski 151*15dbaed4SAntoni Pokusinski static int si7210_fetch_measurement(struct si7210_data *data, 152*15dbaed4SAntoni Pokusinski struct iio_chan_spec const *chan, 153*15dbaed4SAntoni Pokusinski u16 *buf) 154*15dbaed4SAntoni Pokusinski { 155*15dbaed4SAntoni Pokusinski u8 dspsigsel = chan->type == IIO_MAGN ? 0 : 1; 156*15dbaed4SAntoni Pokusinski int ret; 157*15dbaed4SAntoni Pokusinski __be16 result; 158*15dbaed4SAntoni Pokusinski 159*15dbaed4SAntoni Pokusinski guard(mutex)(&data->fetch_lock); 160*15dbaed4SAntoni Pokusinski 161*15dbaed4SAntoni Pokusinski ret = regmap_update_bits(data->regmap, SI7210_REG_DSPSIGSEL, 162*15dbaed4SAntoni Pokusinski SI7210_MASK_DSPSIGSEL, dspsigsel); 163*15dbaed4SAntoni Pokusinski if (ret) 164*15dbaed4SAntoni Pokusinski return ret; 165*15dbaed4SAntoni Pokusinski 166*15dbaed4SAntoni Pokusinski ret = regmap_update_bits(data->regmap, SI7210_REG_POWER_CTRL, 167*15dbaed4SAntoni Pokusinski SI7210_MASK_ONEBURST | SI7210_MASK_STOP, 168*15dbaed4SAntoni Pokusinski SI7210_MASK_ONEBURST & ~SI7210_MASK_STOP); 169*15dbaed4SAntoni Pokusinski if (ret) 170*15dbaed4SAntoni Pokusinski return ret; 171*15dbaed4SAntoni Pokusinski 172*15dbaed4SAntoni Pokusinski /* 173*15dbaed4SAntoni Pokusinski * Read the contents of the 174*15dbaed4SAntoni Pokusinski * registers containing the result: DSPSIGM, DSPSIGL 175*15dbaed4SAntoni Pokusinski */ 176*15dbaed4SAntoni Pokusinski ret = regmap_bulk_read(data->regmap, SI7210_REG_DSPSIGM, 177*15dbaed4SAntoni Pokusinski &result, sizeof(result)); 178*15dbaed4SAntoni Pokusinski if (ret) 179*15dbaed4SAntoni Pokusinski return ret; 180*15dbaed4SAntoni Pokusinski 181*15dbaed4SAntoni Pokusinski *buf = be16_to_cpu(result); 182*15dbaed4SAntoni Pokusinski 183*15dbaed4SAntoni Pokusinski return 0; 184*15dbaed4SAntoni Pokusinski } 185*15dbaed4SAntoni Pokusinski 186*15dbaed4SAntoni Pokusinski static int si7210_read_raw(struct iio_dev *indio_dev, 187*15dbaed4SAntoni Pokusinski struct iio_chan_spec const *chan, 188*15dbaed4SAntoni Pokusinski int *val, int *val2, long mask) 189*15dbaed4SAntoni Pokusinski { 190*15dbaed4SAntoni Pokusinski struct si7210_data *data = iio_priv(indio_dev); 191*15dbaed4SAntoni Pokusinski long long temp; 192*15dbaed4SAntoni Pokusinski u16 dspsig; 193*15dbaed4SAntoni Pokusinski int ret; 194*15dbaed4SAntoni Pokusinski 195*15dbaed4SAntoni Pokusinski switch (mask) { 196*15dbaed4SAntoni Pokusinski case IIO_CHAN_INFO_RAW: 197*15dbaed4SAntoni Pokusinski ret = si7210_fetch_measurement(data, chan, &dspsig); 198*15dbaed4SAntoni Pokusinski if (ret) 199*15dbaed4SAntoni Pokusinski return ret; 200*15dbaed4SAntoni Pokusinski 201*15dbaed4SAntoni Pokusinski *val = dspsig & GENMASK(14, 0); 202*15dbaed4SAntoni Pokusinski return IIO_VAL_INT; 203*15dbaed4SAntoni Pokusinski case IIO_CHAN_INFO_SCALE: 204*15dbaed4SAntoni Pokusinski *val = 0; 205*15dbaed4SAntoni Pokusinski if (data->curr_scale == 20) 206*15dbaed4SAntoni Pokusinski *val2 = 12500; 207*15dbaed4SAntoni Pokusinski else /* data->curr_scale == 200 */ 208*15dbaed4SAntoni Pokusinski *val2 = 125000; 209*15dbaed4SAntoni Pokusinski return IIO_VAL_INT_PLUS_MICRO; 210*15dbaed4SAntoni Pokusinski case IIO_CHAN_INFO_OFFSET: 211*15dbaed4SAntoni Pokusinski *val = -16384; 212*15dbaed4SAntoni Pokusinski return IIO_VAL_INT; 213*15dbaed4SAntoni Pokusinski case IIO_CHAN_INFO_PROCESSED: 214*15dbaed4SAntoni Pokusinski ret = si7210_fetch_measurement(data, chan, &dspsig); 215*15dbaed4SAntoni Pokusinski if (ret) 216*15dbaed4SAntoni Pokusinski return ret; 217*15dbaed4SAntoni Pokusinski 218*15dbaed4SAntoni Pokusinski /* temp = 32 * Dspsigm[6:0] + (Dspsigl[7:0] >> 3) */ 219*15dbaed4SAntoni Pokusinski temp = FIELD_GET(GENMASK(14, 3), dspsig); 220*15dbaed4SAntoni Pokusinski temp = div_s64(-383 * temp * temp, 100) + 160940 * temp - 279800000; 221*15dbaed4SAntoni Pokusinski temp *= (1 + (data->temp_gain / 2048)); 222*15dbaed4SAntoni Pokusinski temp += (int)(MICRO / 16) * data->temp_offset; 223*15dbaed4SAntoni Pokusinski 224*15dbaed4SAntoni Pokusinski ret = regulator_get_voltage(data->vdd); 225*15dbaed4SAntoni Pokusinski if (ret < 0) 226*15dbaed4SAntoni Pokusinski return ret; 227*15dbaed4SAntoni Pokusinski 228*15dbaed4SAntoni Pokusinski /* temp -= 0.222 * VDD */ 229*15dbaed4SAntoni Pokusinski temp -= 222 * div_s64(ret, MILLI); 230*15dbaed4SAntoni Pokusinski 231*15dbaed4SAntoni Pokusinski *val = div_s64(temp, MILLI); 232*15dbaed4SAntoni Pokusinski 233*15dbaed4SAntoni Pokusinski return IIO_VAL_INT; 234*15dbaed4SAntoni Pokusinski default: 235*15dbaed4SAntoni Pokusinski return -EINVAL; 236*15dbaed4SAntoni Pokusinski } 237*15dbaed4SAntoni Pokusinski } 238*15dbaed4SAntoni Pokusinski 239*15dbaed4SAntoni Pokusinski static int si7210_set_scale(struct si7210_data *data, unsigned int scale) 240*15dbaed4SAntoni Pokusinski { 241*15dbaed4SAntoni Pokusinski s8 *a_otp_values; 242*15dbaed4SAntoni Pokusinski int ret; 243*15dbaed4SAntoni Pokusinski 244*15dbaed4SAntoni Pokusinski if (scale == 20) 245*15dbaed4SAntoni Pokusinski a_otp_values = data->scale_20_a; 246*15dbaed4SAntoni Pokusinski else if (scale == 200) 247*15dbaed4SAntoni Pokusinski a_otp_values = data->scale_200_a; 248*15dbaed4SAntoni Pokusinski else 249*15dbaed4SAntoni Pokusinski return -EINVAL; 250*15dbaed4SAntoni Pokusinski 251*15dbaed4SAntoni Pokusinski guard(mutex)(&data->fetch_lock); 252*15dbaed4SAntoni Pokusinski 253*15dbaed4SAntoni Pokusinski /* Write the registers 0xCA - 0xCC */ 254*15dbaed4SAntoni Pokusinski ret = regmap_bulk_write(data->regmap, SI7210_REG_A0, a_otp_values, 3); 255*15dbaed4SAntoni Pokusinski if (ret) 256*15dbaed4SAntoni Pokusinski return ret; 257*15dbaed4SAntoni Pokusinski 258*15dbaed4SAntoni Pokusinski /* Write the registers 0xCE - 0xD0 */ 259*15dbaed4SAntoni Pokusinski ret = regmap_bulk_write(data->regmap, SI7210_REG_A3, &a_otp_values[3], 3); 260*15dbaed4SAntoni Pokusinski if (ret) 261*15dbaed4SAntoni Pokusinski return ret; 262*15dbaed4SAntoni Pokusinski 263*15dbaed4SAntoni Pokusinski data->curr_scale = scale; 264*15dbaed4SAntoni Pokusinski 265*15dbaed4SAntoni Pokusinski return 0; 266*15dbaed4SAntoni Pokusinski } 267*15dbaed4SAntoni Pokusinski 268*15dbaed4SAntoni Pokusinski static int si7210_write_raw(struct iio_dev *indio_dev, 269*15dbaed4SAntoni Pokusinski struct iio_chan_spec const *chan, 270*15dbaed4SAntoni Pokusinski int val, int val2, long mask) 271*15dbaed4SAntoni Pokusinski { 272*15dbaed4SAntoni Pokusinski struct si7210_data *data = iio_priv(indio_dev); 273*15dbaed4SAntoni Pokusinski unsigned int scale; 274*15dbaed4SAntoni Pokusinski 275*15dbaed4SAntoni Pokusinski switch (mask) { 276*15dbaed4SAntoni Pokusinski case IIO_CHAN_INFO_SCALE: 277*15dbaed4SAntoni Pokusinski if (val == 0 && val2 == 12500) 278*15dbaed4SAntoni Pokusinski scale = 20; 279*15dbaed4SAntoni Pokusinski else if (val == 0 && val2 == 125000) 280*15dbaed4SAntoni Pokusinski scale = 200; 281*15dbaed4SAntoni Pokusinski else 282*15dbaed4SAntoni Pokusinski return -EINVAL; 283*15dbaed4SAntoni Pokusinski 284*15dbaed4SAntoni Pokusinski return si7210_set_scale(data, scale); 285*15dbaed4SAntoni Pokusinski default: 286*15dbaed4SAntoni Pokusinski return -EINVAL; 287*15dbaed4SAntoni Pokusinski } 288*15dbaed4SAntoni Pokusinski } 289*15dbaed4SAntoni Pokusinski 290*15dbaed4SAntoni Pokusinski static int si7210_read_otpreg_val(struct si7210_data *data, unsigned int otpreg, u8 *val) 291*15dbaed4SAntoni Pokusinski { 292*15dbaed4SAntoni Pokusinski int ret; 293*15dbaed4SAntoni Pokusinski unsigned int otpdata; 294*15dbaed4SAntoni Pokusinski 295*15dbaed4SAntoni Pokusinski ret = regmap_write(data->regmap, SI7210_REG_OTP_ADDR, otpreg); 296*15dbaed4SAntoni Pokusinski if (ret) 297*15dbaed4SAntoni Pokusinski return ret; 298*15dbaed4SAntoni Pokusinski 299*15dbaed4SAntoni Pokusinski ret = regmap_update_bits(data->regmap, SI7210_REG_OTP_CTRL, 300*15dbaed4SAntoni Pokusinski SI7210_MASK_OTP_READ_EN, SI7210_MASK_OTP_READ_EN); 301*15dbaed4SAntoni Pokusinski if (ret) 302*15dbaed4SAntoni Pokusinski return ret; 303*15dbaed4SAntoni Pokusinski 304*15dbaed4SAntoni Pokusinski ret = regmap_read(data->regmap, SI7210_REG_OTP_DATA, &otpdata); 305*15dbaed4SAntoni Pokusinski if (ret) 306*15dbaed4SAntoni Pokusinski return ret; 307*15dbaed4SAntoni Pokusinski 308*15dbaed4SAntoni Pokusinski *val = otpdata; 309*15dbaed4SAntoni Pokusinski 310*15dbaed4SAntoni Pokusinski return 0; 311*15dbaed4SAntoni Pokusinski } 312*15dbaed4SAntoni Pokusinski 313*15dbaed4SAntoni Pokusinski /* 314*15dbaed4SAntoni Pokusinski * According to the datasheet, the primary method to wake up a 315*15dbaed4SAntoni Pokusinski * device is to send an empty write. However this is not feasible 316*15dbaed4SAntoni Pokusinski * using the current API so we use the other method i.e. read a single 317*15dbaed4SAntoni Pokusinski * byte. The device should respond with 0xFF. 318*15dbaed4SAntoni Pokusinski */ 319*15dbaed4SAntoni Pokusinski static int si7210_device_wake(struct si7210_data *data) 320*15dbaed4SAntoni Pokusinski { 321*15dbaed4SAntoni Pokusinski int ret; 322*15dbaed4SAntoni Pokusinski 323*15dbaed4SAntoni Pokusinski ret = i2c_smbus_read_byte(data->client); 324*15dbaed4SAntoni Pokusinski if (ret < 0) 325*15dbaed4SAntoni Pokusinski return ret; 326*15dbaed4SAntoni Pokusinski 327*15dbaed4SAntoni Pokusinski if (ret != 0xFF) 328*15dbaed4SAntoni Pokusinski return -EIO; 329*15dbaed4SAntoni Pokusinski 330*15dbaed4SAntoni Pokusinski return 0; 331*15dbaed4SAntoni Pokusinski } 332*15dbaed4SAntoni Pokusinski 333*15dbaed4SAntoni Pokusinski static int si7210_device_init(struct si7210_data *data) 334*15dbaed4SAntoni Pokusinski { 335*15dbaed4SAntoni Pokusinski int ret; 336*15dbaed4SAntoni Pokusinski unsigned int i; 337*15dbaed4SAntoni Pokusinski 338*15dbaed4SAntoni Pokusinski ret = si7210_device_wake(data); 339*15dbaed4SAntoni Pokusinski if (ret) 340*15dbaed4SAntoni Pokusinski return ret; 341*15dbaed4SAntoni Pokusinski 342*15dbaed4SAntoni Pokusinski fsleep(1000); 343*15dbaed4SAntoni Pokusinski 344*15dbaed4SAntoni Pokusinski ret = si7210_read_otpreg_val(data, SI7210_OTPREG_TMP_GAIN, &data->temp_gain); 345*15dbaed4SAntoni Pokusinski if (ret) 346*15dbaed4SAntoni Pokusinski return ret; 347*15dbaed4SAntoni Pokusinski 348*15dbaed4SAntoni Pokusinski ret = si7210_read_otpreg_val(data, SI7210_OTPREG_TMP_OFF, &data->temp_offset); 349*15dbaed4SAntoni Pokusinski if (ret) 350*15dbaed4SAntoni Pokusinski return ret; 351*15dbaed4SAntoni Pokusinski 352*15dbaed4SAntoni Pokusinski for (i = 0; i < A_REGS_COUNT; i++) { 353*15dbaed4SAntoni Pokusinski ret = si7210_read_otpreg_val(data, a20_otp_regs[i], &data->scale_20_a[i]); 354*15dbaed4SAntoni Pokusinski if (ret) 355*15dbaed4SAntoni Pokusinski return ret; 356*15dbaed4SAntoni Pokusinski } 357*15dbaed4SAntoni Pokusinski 358*15dbaed4SAntoni Pokusinski for (i = 0; i < A_REGS_COUNT; i++) { 359*15dbaed4SAntoni Pokusinski ret = si7210_read_otpreg_val(data, a200_otp_regs[i], &data->scale_200_a[i]); 360*15dbaed4SAntoni Pokusinski if (ret) 361*15dbaed4SAntoni Pokusinski return ret; 362*15dbaed4SAntoni Pokusinski } 363*15dbaed4SAntoni Pokusinski 364*15dbaed4SAntoni Pokusinski ret = regmap_update_bits(data->regmap, SI7210_REG_ARAUTOINC, 365*15dbaed4SAntoni Pokusinski SI7210_MASK_ARAUTOINC, SI7210_MASK_ARAUTOINC); 366*15dbaed4SAntoni Pokusinski if (ret) 367*15dbaed4SAntoni Pokusinski return ret; 368*15dbaed4SAntoni Pokusinski 369*15dbaed4SAntoni Pokusinski return si7210_set_scale(data, 20); 370*15dbaed4SAntoni Pokusinski } 371*15dbaed4SAntoni Pokusinski 372*15dbaed4SAntoni Pokusinski static const struct iio_info si7210_info = { 373*15dbaed4SAntoni Pokusinski .read_raw = si7210_read_raw, 374*15dbaed4SAntoni Pokusinski .write_raw = si7210_write_raw, 375*15dbaed4SAntoni Pokusinski }; 376*15dbaed4SAntoni Pokusinski 377*15dbaed4SAntoni Pokusinski static int si7210_probe(struct i2c_client *client) 378*15dbaed4SAntoni Pokusinski { 379*15dbaed4SAntoni Pokusinski struct si7210_data *data; 380*15dbaed4SAntoni Pokusinski struct iio_dev *indio_dev; 381*15dbaed4SAntoni Pokusinski int ret; 382*15dbaed4SAntoni Pokusinski 383*15dbaed4SAntoni Pokusinski indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 384*15dbaed4SAntoni Pokusinski if (!indio_dev) 385*15dbaed4SAntoni Pokusinski return -ENOMEM; 386*15dbaed4SAntoni Pokusinski 387*15dbaed4SAntoni Pokusinski data = iio_priv(indio_dev); 388*15dbaed4SAntoni Pokusinski data->client = client; 389*15dbaed4SAntoni Pokusinski 390*15dbaed4SAntoni Pokusinski ret = devm_mutex_init(&client->dev, &data->fetch_lock); 391*15dbaed4SAntoni Pokusinski if (ret) 392*15dbaed4SAntoni Pokusinski return ret; 393*15dbaed4SAntoni Pokusinski 394*15dbaed4SAntoni Pokusinski data->regmap = devm_regmap_init_i2c(client, &si7210_regmap_conf); 395*15dbaed4SAntoni Pokusinski if (IS_ERR(data->regmap)) 396*15dbaed4SAntoni Pokusinski return dev_err_probe(&client->dev, PTR_ERR(data->regmap), 397*15dbaed4SAntoni Pokusinski "failed to register regmap\n"); 398*15dbaed4SAntoni Pokusinski 399*15dbaed4SAntoni Pokusinski data->vdd = devm_regulator_get(&client->dev, "vdd"); 400*15dbaed4SAntoni Pokusinski if (IS_ERR(data->vdd)) 401*15dbaed4SAntoni Pokusinski return dev_err_probe(&client->dev, PTR_ERR(data->vdd), 402*15dbaed4SAntoni Pokusinski "failed to get VDD regulator\n"); 403*15dbaed4SAntoni Pokusinski 404*15dbaed4SAntoni Pokusinski ret = regulator_enable(data->vdd); 405*15dbaed4SAntoni Pokusinski if (ret) 406*15dbaed4SAntoni Pokusinski return ret; 407*15dbaed4SAntoni Pokusinski 408*15dbaed4SAntoni Pokusinski indio_dev->name = dev_name(&client->dev); 409*15dbaed4SAntoni Pokusinski indio_dev->modes = INDIO_DIRECT_MODE; 410*15dbaed4SAntoni Pokusinski indio_dev->info = &si7210_info; 411*15dbaed4SAntoni Pokusinski indio_dev->channels = si7210_channels; 412*15dbaed4SAntoni Pokusinski indio_dev->num_channels = ARRAY_SIZE(si7210_channels); 413*15dbaed4SAntoni Pokusinski 414*15dbaed4SAntoni Pokusinski ret = si7210_device_init(data); 415*15dbaed4SAntoni Pokusinski if (ret) 416*15dbaed4SAntoni Pokusinski return dev_err_probe(&client->dev, ret, 417*15dbaed4SAntoni Pokusinski "device initialization failed\n"); 418*15dbaed4SAntoni Pokusinski 419*15dbaed4SAntoni Pokusinski return devm_iio_device_register(&client->dev, indio_dev); 420*15dbaed4SAntoni Pokusinski } 421*15dbaed4SAntoni Pokusinski 422*15dbaed4SAntoni Pokusinski static const struct i2c_device_id si7210_id[] = { 423*15dbaed4SAntoni Pokusinski { "si7210" }, 424*15dbaed4SAntoni Pokusinski { } 425*15dbaed4SAntoni Pokusinski }; 426*15dbaed4SAntoni Pokusinski MODULE_DEVICE_TABLE(i2c, si7210_id); 427*15dbaed4SAntoni Pokusinski 428*15dbaed4SAntoni Pokusinski static const struct of_device_id si7210_dt_ids[] = { 429*15dbaed4SAntoni Pokusinski { .compatible = "silabs,si7210" }, 430*15dbaed4SAntoni Pokusinski { } 431*15dbaed4SAntoni Pokusinski }; 432*15dbaed4SAntoni Pokusinski MODULE_DEVICE_TABLE(of, si7210_dt_ids); 433*15dbaed4SAntoni Pokusinski 434*15dbaed4SAntoni Pokusinski static struct i2c_driver si7210_driver = { 435*15dbaed4SAntoni Pokusinski .driver = { 436*15dbaed4SAntoni Pokusinski .name = "si7210", 437*15dbaed4SAntoni Pokusinski .of_match_table = si7210_dt_ids, 438*15dbaed4SAntoni Pokusinski }, 439*15dbaed4SAntoni Pokusinski .probe = si7210_probe, 440*15dbaed4SAntoni Pokusinski .id_table = si7210_id, 441*15dbaed4SAntoni Pokusinski }; 442*15dbaed4SAntoni Pokusinski module_i2c_driver(si7210_driver); 443*15dbaed4SAntoni Pokusinski 444*15dbaed4SAntoni Pokusinski MODULE_AUTHOR("Antoni Pokusinski <apokusinski01@gmail.com>"); 445*15dbaed4SAntoni Pokusinski MODULE_DESCRIPTION("Silicon Labs Si7210 Hall Effect sensor I2C driver"); 446*15dbaed4SAntoni Pokusinski MODULE_LICENSE("GPL"); 447