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