585 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * MMC35240 - MEMSIC 3-axis Magnetic Sensor4 *5 * Copyright (c) 2015, Intel Corporation.6 *7 * IIO driver for MMC35240 (7-bit I2C slave address 0x30).8 *9 * TODO: offset, ACPI, continuous measurement mode, PM10 */11 12#include <linux/module.h>13#include <linux/mod_devicetable.h>14#include <linux/init.h>15#include <linux/i2c.h>16#include <linux/delay.h>17#include <linux/regmap.h>18#include <linux/pm.h>19 20#include <linux/iio/iio.h>21#include <linux/iio/sysfs.h>22 23#define MMC35240_DRV_NAME "mmc35240"24#define MMC35240_REGMAP_NAME "mmc35240_regmap"25 26#define MMC35240_REG_XOUT_L 0x0027#define MMC35240_REG_XOUT_H 0x0128#define MMC35240_REG_YOUT_L 0x0229#define MMC35240_REG_YOUT_H 0x0330#define MMC35240_REG_ZOUT_L 0x0431#define MMC35240_REG_ZOUT_H 0x0532 33#define MMC35240_REG_STATUS 0x0634#define MMC35240_REG_CTRL0 0x0735#define MMC35240_REG_CTRL1 0x0836 37#define MMC35240_REG_ID 0x2038 39#define MMC35240_STATUS_MEAS_DONE_BIT BIT(0)40 41#define MMC35240_CTRL0_REFILL_BIT BIT(7)42#define MMC35240_CTRL0_RESET_BIT BIT(6)43#define MMC35240_CTRL0_SET_BIT BIT(5)44#define MMC35240_CTRL0_CMM_BIT BIT(1)45#define MMC35240_CTRL0_TM_BIT BIT(0)46 47/* output resolution bits */48#define MMC35240_CTRL1_BW0_BIT BIT(0)49#define MMC35240_CTRL1_BW1_BIT BIT(1)50 51#define MMC35240_CTRL1_BW_MASK (MMC35240_CTRL1_BW0_BIT | \52 MMC35240_CTRL1_BW1_BIT)53#define MMC35240_CTRL1_BW_SHIFT 054 55#define MMC35240_WAIT_CHARGE_PUMP 50000 /* us */56#define MMC35240_WAIT_SET_RESET 1000 /* us */57 58/*59 * Memsic OTP process code piece is put here for reference:60 *61 * #define OTP_CONVERT(REG) ((float)((REG) >=32 ? (32 - (REG)) : (REG)) * 0.00662 * 1) For X axis, the COEFFICIENT is always 1.63 * 2) For Y axis, the COEFFICIENT is as below:64 * f_OTP_matrix[4] = OTP_CONVERT(((reg_data[1] & 0x03) << 4) |65 * (reg_data[2] >> 4)) + 1.0;66 * 3) For Z axis, the COEFFICIENT is as below:67 * f_OTP_matrix[8] = (OTP_CONVERT(reg_data[3] & 0x3f) + 1) * 1.35;68 * We implemented the OTP logic into driver.69 */70 71/* scale = 1000 here for Y otp */72#define MMC35240_OTP_CONVERT_Y(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 6)73 74/* 0.6 * 1.35 = 0.81, scale 10000 for Z otp */75#define MMC35240_OTP_CONVERT_Z(REG) (((REG) >= 32 ? (32 - (REG)) : (REG)) * 81)76 77#define MMC35240_X_COEFF(x) (x)78#define MMC35240_Y_COEFF(y) (y + 1000)79#define MMC35240_Z_COEFF(z) (z + 13500)80 81#define MMC35240_OTP_START_ADDR 0x1B82 83enum mmc35240_resolution {84 MMC35240_16_BITS_SLOW = 0, /* 7.92 ms */85 MMC35240_16_BITS_FAST, /* 4.08 ms */86 MMC35240_14_BITS, /* 2.16 ms */87 MMC35240_12_BITS, /* 1.20 ms */88};89 90enum mmc35240_axis {91 AXIS_X = 0,92 AXIS_Y,93 AXIS_Z,94};95 96static const struct {97 int sens[3]; /* sensitivity per X, Y, Z axis */98 int nfo; /* null field output */99} mmc35240_props_table[] = {100 /* 16 bits, 125Hz ODR */101 {102 {1024, 1024, 1024},103 32768,104 },105 /* 16 bits, 250Hz ODR */106 {107 {1024, 1024, 770},108 32768,109 },110 /* 14 bits, 450Hz ODR */111 {112 {256, 256, 193},113 8192,114 },115 /* 12 bits, 800Hz ODR */116 {117 {64, 64, 48},118 2048,119 },120};121 122struct mmc35240_data {123 struct i2c_client *client;124 struct mutex mutex;125 struct regmap *regmap;126 enum mmc35240_resolution res;127 128 /* OTP compensation */129 int axis_coef[3];130 int axis_scale[3];131};132 133static const struct {134 int val;135 int val2;136} mmc35240_samp_freq[] = { {1, 500000},137 {13, 0},138 {25, 0},139 {50, 0} };140 141static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("1.5 13 25 50");142 143#define MMC35240_CHANNEL(_axis) { \144 .type = IIO_MAGN, \145 .modified = 1, \146 .channel2 = IIO_MOD_ ## _axis, \147 .address = AXIS_ ## _axis, \148 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \149 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \150 BIT(IIO_CHAN_INFO_SCALE), \151}152 153static const struct iio_chan_spec mmc35240_channels[] = {154 MMC35240_CHANNEL(X),155 MMC35240_CHANNEL(Y),156 MMC35240_CHANNEL(Z),157};158 159static struct attribute *mmc35240_attributes[] = {160 &iio_const_attr_sampling_frequency_available.dev_attr.attr,161 NULL162};163 164static const struct attribute_group mmc35240_attribute_group = {165 .attrs = mmc35240_attributes,166};167 168static int mmc35240_get_samp_freq_index(struct mmc35240_data *data,169 int val, int val2)170{171 int i;172 173 for (i = 0; i < ARRAY_SIZE(mmc35240_samp_freq); i++)174 if (mmc35240_samp_freq[i].val == val &&175 mmc35240_samp_freq[i].val2 == val2)176 return i;177 return -EINVAL;178}179 180static int mmc35240_hw_set(struct mmc35240_data *data, bool set)181{182 int ret;183 u8 coil_bit;184 185 /*186 * Recharge the capacitor at VCAP pin, requested to be issued187 * before a SET/RESET command.188 */189 ret = regmap_set_bits(data->regmap, MMC35240_REG_CTRL0,190 MMC35240_CTRL0_REFILL_BIT);191 if (ret < 0)192 return ret;193 usleep_range(MMC35240_WAIT_CHARGE_PUMP, MMC35240_WAIT_CHARGE_PUMP + 1);194 195 if (set)196 coil_bit = MMC35240_CTRL0_SET_BIT;197 else198 coil_bit = MMC35240_CTRL0_RESET_BIT;199 200 return regmap_set_bits(data->regmap, MMC35240_REG_CTRL0, coil_bit);201 202}203 204static int mmc35240_init(struct mmc35240_data *data)205{206 int ret, y_convert, z_convert;207 unsigned int reg_id;208 u8 otp_data[6];209 210 ret = regmap_read(data->regmap, MMC35240_REG_ID, ®_id);211 if (ret < 0) {212 dev_err(&data->client->dev, "Error reading product id\n");213 return ret;214 }215 216 dev_dbg(&data->client->dev, "MMC35240 chip id %x\n", reg_id);217 218 /*219 * make sure we restore sensor characteristics, by doing220 * a SET/RESET sequence, the axis polarity being naturally221 * aligned after RESET222 */223 ret = mmc35240_hw_set(data, true);224 if (ret < 0)225 return ret;226 usleep_range(MMC35240_WAIT_SET_RESET, MMC35240_WAIT_SET_RESET + 1);227 228 ret = mmc35240_hw_set(data, false);229 if (ret < 0)230 return ret;231 232 /* set default sampling frequency */233 ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1,234 MMC35240_CTRL1_BW_MASK,235 data->res << MMC35240_CTRL1_BW_SHIFT);236 if (ret < 0)237 return ret;238 239 ret = regmap_bulk_read(data->regmap, MMC35240_OTP_START_ADDR,240 otp_data, sizeof(otp_data));241 if (ret < 0)242 return ret;243 244 y_convert = MMC35240_OTP_CONVERT_Y(((otp_data[1] & 0x03) << 4) |245 (otp_data[2] >> 4));246 z_convert = MMC35240_OTP_CONVERT_Z(otp_data[3] & 0x3f);247 248 data->axis_coef[0] = MMC35240_X_COEFF(1);249 data->axis_coef[1] = MMC35240_Y_COEFF(y_convert);250 data->axis_coef[2] = MMC35240_Z_COEFF(z_convert);251 252 data->axis_scale[0] = 1;253 data->axis_scale[1] = 1000;254 data->axis_scale[2] = 10000;255 256 return 0;257}258 259static int mmc35240_take_measurement(struct mmc35240_data *data)260{261 int ret, tries = 100;262 unsigned int reg_status;263 264 ret = regmap_write(data->regmap, MMC35240_REG_CTRL0,265 MMC35240_CTRL0_TM_BIT);266 if (ret < 0)267 return ret;268 269 while (tries-- > 0) {270 ret = regmap_read(data->regmap, MMC35240_REG_STATUS,271 ®_status);272 if (ret < 0)273 return ret;274 if (reg_status & MMC35240_STATUS_MEAS_DONE_BIT)275 break;276 /* minimum wait time to complete measurement is 10 ms */277 usleep_range(10000, 11000);278 }279 280 if (tries < 0) {281 dev_err(&data->client->dev, "data not ready\n");282 return -EIO;283 }284 285 return 0;286}287 288static int mmc35240_read_measurement(struct mmc35240_data *data, __le16 buf[3])289{290 int ret;291 292 ret = mmc35240_take_measurement(data);293 if (ret < 0)294 return ret;295 296 return regmap_bulk_read(data->regmap, MMC35240_REG_XOUT_L, buf,297 3 * sizeof(__le16));298}299 300/**301 * mmc35240_raw_to_mgauss - convert raw readings to milli gauss. Also apply302 * compensation for output value.303 *304 * @data: device private data305 * @index: axis index for which we want the conversion306 * @buf: raw data to be converted, 2 bytes in little endian format307 * @val: compensated output reading (unit is milli gauss)308 *309 * Returns: 0 in case of success, -EINVAL when @index is not valid310 */311static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,312 __le16 buf[], int *val)313{314 int raw[3];315 int sens[3];316 int nfo;317 318 raw[AXIS_X] = le16_to_cpu(buf[AXIS_X]);319 raw[AXIS_Y] = le16_to_cpu(buf[AXIS_Y]);320 raw[AXIS_Z] = le16_to_cpu(buf[AXIS_Z]);321 322 sens[AXIS_X] = mmc35240_props_table[data->res].sens[AXIS_X];323 sens[AXIS_Y] = mmc35240_props_table[data->res].sens[AXIS_Y];324 sens[AXIS_Z] = mmc35240_props_table[data->res].sens[AXIS_Z];325 326 nfo = mmc35240_props_table[data->res].nfo;327 328 switch (index) {329 case AXIS_X:330 *val = (raw[AXIS_X] - nfo) * 1000 / sens[AXIS_X];331 break;332 case AXIS_Y:333 *val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] -334 (raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z];335 break;336 case AXIS_Z:337 *val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] +338 (raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z];339 break;340 default:341 return -EINVAL;342 }343 /* apply OTP compensation */344 *val = (*val) * data->axis_coef[index] / data->axis_scale[index];345 346 return 0;347}348 349static int mmc35240_read_raw(struct iio_dev *indio_dev,350 struct iio_chan_spec const *chan, int *val,351 int *val2, long mask)352{353 struct mmc35240_data *data = iio_priv(indio_dev);354 int ret, i;355 unsigned int reg;356 __le16 buf[3];357 358 switch (mask) {359 case IIO_CHAN_INFO_RAW:360 mutex_lock(&data->mutex);361 ret = mmc35240_read_measurement(data, buf);362 mutex_unlock(&data->mutex);363 if (ret < 0)364 return ret;365 ret = mmc35240_raw_to_mgauss(data, chan->address, buf, val);366 if (ret < 0)367 return ret;368 return IIO_VAL_INT;369 case IIO_CHAN_INFO_SCALE:370 *val = 0;371 *val2 = 1000;372 return IIO_VAL_INT_PLUS_MICRO;373 case IIO_CHAN_INFO_SAMP_FREQ:374 mutex_lock(&data->mutex);375 ret = regmap_read(data->regmap, MMC35240_REG_CTRL1, ®);376 mutex_unlock(&data->mutex);377 if (ret < 0)378 return ret;379 380 i = (reg & MMC35240_CTRL1_BW_MASK) >> MMC35240_CTRL1_BW_SHIFT;381 if (i < 0 || i >= ARRAY_SIZE(mmc35240_samp_freq))382 return -EINVAL;383 384 *val = mmc35240_samp_freq[i].val;385 *val2 = mmc35240_samp_freq[i].val2;386 return IIO_VAL_INT_PLUS_MICRO;387 default:388 return -EINVAL;389 }390}391 392static int mmc35240_write_raw(struct iio_dev *indio_dev,393 struct iio_chan_spec const *chan, int val,394 int val2, long mask)395{396 struct mmc35240_data *data = iio_priv(indio_dev);397 int i, ret;398 399 switch (mask) {400 case IIO_CHAN_INFO_SAMP_FREQ:401 i = mmc35240_get_samp_freq_index(data, val, val2);402 if (i < 0)403 return -EINVAL;404 mutex_lock(&data->mutex);405 ret = regmap_update_bits(data->regmap, MMC35240_REG_CTRL1,406 MMC35240_CTRL1_BW_MASK,407 i << MMC35240_CTRL1_BW_SHIFT);408 mutex_unlock(&data->mutex);409 return ret;410 default:411 return -EINVAL;412 }413}414 415static const struct iio_info mmc35240_info = {416 .read_raw = mmc35240_read_raw,417 .write_raw = mmc35240_write_raw,418 .attrs = &mmc35240_attribute_group,419};420 421static bool mmc35240_is_writeable_reg(struct device *dev, unsigned int reg)422{423 switch (reg) {424 case MMC35240_REG_CTRL0:425 case MMC35240_REG_CTRL1:426 return true;427 default:428 return false;429 }430}431 432static bool mmc35240_is_readable_reg(struct device *dev, unsigned int reg)433{434 switch (reg) {435 case MMC35240_REG_XOUT_L:436 case MMC35240_REG_XOUT_H:437 case MMC35240_REG_YOUT_L:438 case MMC35240_REG_YOUT_H:439 case MMC35240_REG_ZOUT_L:440 case MMC35240_REG_ZOUT_H:441 case MMC35240_REG_STATUS:442 case MMC35240_REG_ID:443 return true;444 default:445 return false;446 }447}448 449static bool mmc35240_is_volatile_reg(struct device *dev, unsigned int reg)450{451 switch (reg) {452 case MMC35240_REG_CTRL0:453 case MMC35240_REG_CTRL1:454 return false;455 default:456 return true;457 }458}459 460static const struct reg_default mmc35240_reg_defaults[] = {461 { MMC35240_REG_CTRL0, 0x00 },462 { MMC35240_REG_CTRL1, 0x00 },463};464 465static const struct regmap_config mmc35240_regmap_config = {466 .name = MMC35240_REGMAP_NAME,467 468 .reg_bits = 8,469 .val_bits = 8,470 471 .max_register = MMC35240_REG_ID,472 .cache_type = REGCACHE_FLAT,473 474 .writeable_reg = mmc35240_is_writeable_reg,475 .readable_reg = mmc35240_is_readable_reg,476 .volatile_reg = mmc35240_is_volatile_reg,477 478 .reg_defaults = mmc35240_reg_defaults,479 .num_reg_defaults = ARRAY_SIZE(mmc35240_reg_defaults),480};481 482static int mmc35240_probe(struct i2c_client *client)483{484 struct mmc35240_data *data;485 struct iio_dev *indio_dev;486 struct regmap *regmap;487 int ret;488 489 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));490 if (!indio_dev)491 return -ENOMEM;492 493 regmap = devm_regmap_init_i2c(client, &mmc35240_regmap_config);494 if (IS_ERR(regmap)) {495 dev_err(&client->dev, "regmap initialization failed\n");496 return PTR_ERR(regmap);497 }498 499 data = iio_priv(indio_dev);500 i2c_set_clientdata(client, indio_dev);501 data->client = client;502 data->regmap = regmap;503 data->res = MMC35240_16_BITS_SLOW;504 505 mutex_init(&data->mutex);506 507 indio_dev->info = &mmc35240_info;508 indio_dev->name = MMC35240_DRV_NAME;509 indio_dev->channels = mmc35240_channels;510 indio_dev->num_channels = ARRAY_SIZE(mmc35240_channels);511 indio_dev->modes = INDIO_DIRECT_MODE;512 513 ret = mmc35240_init(data);514 if (ret < 0) {515 dev_err(&client->dev, "mmc35240 chip init failed\n");516 return ret;517 }518 return devm_iio_device_register(&client->dev, indio_dev);519}520 521static int mmc35240_suspend(struct device *dev)522{523 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));524 struct mmc35240_data *data = iio_priv(indio_dev);525 526 regcache_cache_only(data->regmap, true);527 528 return 0;529}530 531static int mmc35240_resume(struct device *dev)532{533 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));534 struct mmc35240_data *data = iio_priv(indio_dev);535 int ret;536 537 regcache_mark_dirty(data->regmap);538 ret = regcache_sync_region(data->regmap, MMC35240_REG_CTRL0,539 MMC35240_REG_CTRL1);540 if (ret < 0)541 dev_err(dev, "Failed to restore control registers\n");542 543 regcache_cache_only(data->regmap, false);544 545 return 0;546}547 548static DEFINE_SIMPLE_DEV_PM_OPS(mmc35240_pm_ops, mmc35240_suspend,549 mmc35240_resume);550 551static const struct of_device_id mmc35240_of_match[] = {552 { .compatible = "memsic,mmc35240", },553 { }554};555MODULE_DEVICE_TABLE(of, mmc35240_of_match);556 557static const struct acpi_device_id mmc35240_acpi_match[] = {558 {"MMC35240", 0},559 { },560};561MODULE_DEVICE_TABLE(acpi, mmc35240_acpi_match);562 563static const struct i2c_device_id mmc35240_id[] = {564 { "mmc35240" },565 {}566};567MODULE_DEVICE_TABLE(i2c, mmc35240_id);568 569static struct i2c_driver mmc35240_driver = {570 .driver = {571 .name = MMC35240_DRV_NAME,572 .of_match_table = mmc35240_of_match,573 .pm = pm_sleep_ptr(&mmc35240_pm_ops),574 .acpi_match_table = mmc35240_acpi_match,575 },576 .probe = mmc35240_probe,577 .id_table = mmc35240_id,578};579 580module_i2c_driver(mmc35240_driver);581 582MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");583MODULE_DESCRIPTION("MEMSIC MMC35240 magnetic sensor driver");584MODULE_LICENSE("GPL v2");585