657 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * STMicroelectronics magnetometers driver4 *5 * Copyright 2012-2013 STMicroelectronics Inc.6 *7 * Denis Ciocca <denis.ciocca@st.com>8 */9 10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/mutex.h>13#include <linux/sysfs.h>14#include <linux/iio/iio.h>15#include <linux/iio/sysfs.h>16#include <linux/iio/trigger.h>17 18#include <linux/iio/common/st_sensors.h>19#include "st_magn.h"20 21#define ST_MAGN_NUMBER_DATA_CHANNELS 322 23/* DEFAULT VALUE FOR SENSORS */24#define ST_MAGN_DEFAULT_OUT_X_H_ADDR 0x0325#define ST_MAGN_DEFAULT_OUT_Y_H_ADDR 0x0726#define ST_MAGN_DEFAULT_OUT_Z_H_ADDR 0x0527 28/* FULLSCALE */29#define ST_MAGN_FS_AVL_1300MG 130030#define ST_MAGN_FS_AVL_1900MG 190031#define ST_MAGN_FS_AVL_2000MG 200032#define ST_MAGN_FS_AVL_2500MG 250033#define ST_MAGN_FS_AVL_4000MG 400034#define ST_MAGN_FS_AVL_4700MG 470035#define ST_MAGN_FS_AVL_5600MG 560036#define ST_MAGN_FS_AVL_8000MG 800037#define ST_MAGN_FS_AVL_8100MG 810038#define ST_MAGN_FS_AVL_12000MG 1200039#define ST_MAGN_FS_AVL_15000MG 1500040#define ST_MAGN_FS_AVL_16000MG 1600041 42/* Special L addresses for Sensor 2 */43#define ST_MAGN_2_OUT_X_L_ADDR 0x2844#define ST_MAGN_2_OUT_Y_L_ADDR 0x2a45#define ST_MAGN_2_OUT_Z_L_ADDR 0x2c46 47/* Special L addresses for sensor 3 */48#define ST_MAGN_3_OUT_X_L_ADDR 0x6849#define ST_MAGN_3_OUT_Y_L_ADDR 0x6a50#define ST_MAGN_3_OUT_Z_L_ADDR 0x6c51 52/* Special L addresses for sensor 4 */53#define ST_MAGN_4_OUT_X_L_ADDR 0x0854#define ST_MAGN_4_OUT_Y_L_ADDR 0x0a55#define ST_MAGN_4_OUT_Z_L_ADDR 0x0c56 57static const struct iio_mount_matrix *58st_magn_get_mount_matrix(const struct iio_dev *indio_dev,59 const struct iio_chan_spec *chan)60{61 struct st_sensor_data *mdata = iio_priv(indio_dev);62 63 return &mdata->mount_matrix;64}65 66static const struct iio_chan_spec_ext_info st_magn_mount_matrix_ext_info[] = {67 IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, st_magn_get_mount_matrix),68 { }69};70 71static const struct iio_chan_spec st_magn_16bit_channels[] = {72 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,73 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),74 ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_BE, 16, 16,75 ST_MAGN_DEFAULT_OUT_X_H_ADDR,76 st_magn_mount_matrix_ext_info),77 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,78 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),79 ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_BE, 16, 16,80 ST_MAGN_DEFAULT_OUT_Y_H_ADDR,81 st_magn_mount_matrix_ext_info),82 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,83 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),84 ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_BE, 16, 16,85 ST_MAGN_DEFAULT_OUT_Z_H_ADDR,86 st_magn_mount_matrix_ext_info),87 IIO_CHAN_SOFT_TIMESTAMP(3)88};89 90static const struct iio_chan_spec st_magn_2_16bit_channels[] = {91 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,92 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),93 ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,94 ST_MAGN_2_OUT_X_L_ADDR,95 st_magn_mount_matrix_ext_info),96 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,97 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),98 ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,99 ST_MAGN_2_OUT_Y_L_ADDR,100 st_magn_mount_matrix_ext_info),101 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,102 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),103 ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,104 ST_MAGN_2_OUT_Z_L_ADDR,105 st_magn_mount_matrix_ext_info),106 IIO_CHAN_SOFT_TIMESTAMP(3)107};108 109static const struct iio_chan_spec st_magn_3_16bit_channels[] = {110 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,111 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),112 ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,113 ST_MAGN_3_OUT_X_L_ADDR,114 st_magn_mount_matrix_ext_info),115 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,116 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),117 ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,118 ST_MAGN_3_OUT_Y_L_ADDR,119 st_magn_mount_matrix_ext_info),120 ST_SENSORS_LSM_CHANNELS_EXT(IIO_MAGN,121 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),122 ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,123 ST_MAGN_3_OUT_Z_L_ADDR,124 st_magn_mount_matrix_ext_info),125 IIO_CHAN_SOFT_TIMESTAMP(3)126};127 128static const struct iio_chan_spec st_magn_4_16bit_channels[] = {129 ST_SENSORS_LSM_CHANNELS(IIO_MAGN,130 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),131 ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,132 ST_MAGN_4_OUT_X_L_ADDR),133 ST_SENSORS_LSM_CHANNELS(IIO_MAGN,134 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),135 ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,136 ST_MAGN_4_OUT_Y_L_ADDR),137 ST_SENSORS_LSM_CHANNELS(IIO_MAGN,138 BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),139 ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,140 ST_MAGN_4_OUT_Z_L_ADDR),141 IIO_CHAN_SOFT_TIMESTAMP(3)142};143 144static const struct st_sensor_settings st_magn_sensors_settings[] = {145 {146 .wai = 0, /* This sensor has no valid WhoAmI report 0 */147 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,148 .sensors_supported = {149 [0] = LSM303DLH_MAGN_DEV_NAME,150 },151 .ch = (struct iio_chan_spec *)st_magn_16bit_channels,152 .odr = {153 .addr = 0x00,154 .mask = 0x1c,155 .odr_avl = {156 { .hz = 1, .value = 0x00 },157 { .hz = 2, .value = 0x01 },158 { .hz = 3, .value = 0x02 },159 { .hz = 8, .value = 0x03 },160 { .hz = 15, .value = 0x04 },161 { .hz = 30, .value = 0x05 },162 { .hz = 75, .value = 0x06 },163 /* 220 Hz, 0x07 reportedly exist */164 },165 },166 .pw = {167 .addr = 0x02,168 .mask = 0x03,169 .value_on = 0x00,170 .value_off = 0x03,171 },172 .fs = {173 .addr = 0x01,174 .mask = 0xe0,175 .fs_avl = {176 [0] = {177 .num = ST_MAGN_FS_AVL_1300MG,178 .value = 0x01,179 .gain = 1100,180 .gain2 = 980,181 },182 [1] = {183 .num = ST_MAGN_FS_AVL_1900MG,184 .value = 0x02,185 .gain = 855,186 .gain2 = 760,187 },188 [2] = {189 .num = ST_MAGN_FS_AVL_2500MG,190 .value = 0x03,191 .gain = 670,192 .gain2 = 600,193 },194 [3] = {195 .num = ST_MAGN_FS_AVL_4000MG,196 .value = 0x04,197 .gain = 450,198 .gain2 = 400,199 },200 [4] = {201 .num = ST_MAGN_FS_AVL_4700MG,202 .value = 0x05,203 .gain = 400,204 .gain2 = 355,205 },206 [5] = {207 .num = ST_MAGN_FS_AVL_5600MG,208 .value = 0x06,209 .gain = 330,210 .gain2 = 295,211 },212 [6] = {213 .num = ST_MAGN_FS_AVL_8100MG,214 .value = 0x07,215 .gain = 230,216 .gain2 = 205,217 },218 },219 },220 .multi_read_bit = false,221 .bootime = 2,222 },223 {224 .wai = 0x3c,225 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,226 .sensors_supported = {227 [0] = LSM303DLHC_MAGN_DEV_NAME,228 [1] = LSM303DLM_MAGN_DEV_NAME,229 },230 .ch = (struct iio_chan_spec *)st_magn_16bit_channels,231 .odr = {232 .addr = 0x00,233 .mask = 0x1c,234 .odr_avl = {235 { .hz = 1, .value = 0x00 },236 { .hz = 2, .value = 0x01 },237 { .hz = 3, .value = 0x02 },238 { .hz = 8, .value = 0x03 },239 { .hz = 15, .value = 0x04 },240 { .hz = 30, .value = 0x05 },241 { .hz = 75, .value = 0x06 },242 { .hz = 220, .value = 0x07 },243 },244 },245 .pw = {246 .addr = 0x02,247 .mask = 0x03,248 .value_on = 0x00,249 .value_off = 0x03,250 },251 .fs = {252 .addr = 0x01,253 .mask = 0xe0,254 .fs_avl = {255 [0] = {256 .num = ST_MAGN_FS_AVL_1300MG,257 .value = 0x01,258 .gain = 909,259 .gain2 = 1020,260 },261 [1] = {262 .num = ST_MAGN_FS_AVL_1900MG,263 .value = 0x02,264 .gain = 1169,265 .gain2 = 1315,266 },267 [2] = {268 .num = ST_MAGN_FS_AVL_2500MG,269 .value = 0x03,270 .gain = 1492,271 .gain2 = 1666,272 },273 [3] = {274 .num = ST_MAGN_FS_AVL_4000MG,275 .value = 0x04,276 .gain = 2222,277 .gain2 = 2500,278 },279 [4] = {280 .num = ST_MAGN_FS_AVL_4700MG,281 .value = 0x05,282 .gain = 2500,283 .gain2 = 2816,284 },285 [5] = {286 .num = ST_MAGN_FS_AVL_5600MG,287 .value = 0x06,288 .gain = 3030,289 .gain2 = 3389,290 },291 [6] = {292 .num = ST_MAGN_FS_AVL_8100MG,293 .value = 0x07,294 .gain = 4347,295 .gain2 = 4878,296 },297 },298 },299 .multi_read_bit = false,300 .bootime = 2,301 },302 {303 .wai = 0x3d,304 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,305 .sensors_supported = {306 [0] = LIS3MDL_MAGN_DEV_NAME,307 [1] = LSM9DS1_MAGN_DEV_NAME,308 [2] = LSM303C_MAGN_DEV_NAME,309 },310 .ch = (struct iio_chan_spec *)st_magn_2_16bit_channels,311 .odr = {312 .addr = 0x20,313 .mask = 0x1c,314 .odr_avl = {315 { .hz = 1, .value = 0x00 },316 { .hz = 2, .value = 0x01 },317 { .hz = 3, .value = 0x02 },318 { .hz = 5, .value = 0x03 },319 { .hz = 10, .value = 0x04 },320 { .hz = 20, .value = 0x05 },321 { .hz = 40, .value = 0x06 },322 { .hz = 80, .value = 0x07 },323 },324 },325 .pw = {326 .addr = 0x22,327 .mask = 0x03,328 .value_on = 0x00,329 .value_off = 0x03,330 },331 .fs = {332 .addr = 0x21,333 .mask = 0x60,334 .fs_avl = {335 [0] = {336 .num = ST_MAGN_FS_AVL_4000MG,337 .value = 0x00,338 .gain = 146,339 },340 [1] = {341 .num = ST_MAGN_FS_AVL_8000MG,342 .value = 0x01,343 .gain = 292,344 },345 [2] = {346 .num = ST_MAGN_FS_AVL_12000MG,347 .value = 0x02,348 .gain = 438,349 },350 [3] = {351 .num = ST_MAGN_FS_AVL_16000MG,352 .value = 0x03,353 .gain = 584,354 },355 },356 },357 .bdu = {358 .addr = 0x24,359 .mask = 0x40,360 },361 .drdy_irq = {362 /* drdy line is routed drdy pin */363 .stat_drdy = {364 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,365 .mask = 0x07,366 },367 },368 .sim = {369 .addr = 0x22,370 .value = BIT(2),371 },372 .multi_read_bit = true,373 .bootime = 2,374 },375 {376 .wai = 0x40,377 .wai_addr = 0x4f,378 .sensors_supported = {379 [0] = LSM303AGR_MAGN_DEV_NAME,380 [1] = LIS2MDL_MAGN_DEV_NAME,381 [2] = IIS2MDC_MAGN_DEV_NAME,382 },383 .ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,384 .odr = {385 .addr = 0x60,386 .mask = 0x0c,387 .odr_avl = {388 { .hz = 10, .value = 0x00 },389 { .hz = 20, .value = 0x01 },390 { .hz = 50, .value = 0x02 },391 { .hz = 100, .value = 0x03 },392 },393 },394 .pw = {395 .addr = 0x60,396 .mask = 0x03,397 .value_on = 0x00,398 .value_off = 0x03,399 },400 .fs = {401 .fs_avl = {402 [0] = {403 .num = ST_MAGN_FS_AVL_15000MG,404 .gain = 1500,405 },406 },407 },408 .bdu = {409 .addr = 0x62,410 .mask = 0x10,411 },412 .drdy_irq = {413 .int1 = {414 .addr = 0x62,415 .mask = 0x01,416 },417 .stat_drdy = {418 .addr = 0x67,419 .mask = 0x07,420 },421 },422 .multi_read_bit = false,423 .bootime = 2,424 },425 {426 .wai = 0x49,427 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,428 .sensors_supported = {429 [0] = LSM9DS0_IMU_DEV_NAME,430 [1] = LSM303D_IMU_DEV_NAME,431 },432 .ch = (struct iio_chan_spec *)st_magn_4_16bit_channels,433 .odr = {434 .addr = 0x24,435 .mask = GENMASK(4, 2),436 .odr_avl = {437 { 3, 0x00, },438 { 6, 0x01, },439 { 12, 0x02, },440 { 25, 0x03, },441 { 50, 0x04, },442 { 100, 0x05, },443 },444 },445 .pw = {446 .addr = 0x26,447 .mask = GENMASK(1, 0),448 .value_on = 0x00,449 .value_off = 0x03,450 },451 .fs = {452 .addr = 0x25,453 .mask = GENMASK(6, 5),454 .fs_avl = {455 [0] = {456 .num = ST_MAGN_FS_AVL_2000MG,457 .value = 0x00,458 .gain = 73,459 },460 [1] = {461 .num = ST_MAGN_FS_AVL_4000MG,462 .value = 0x01,463 .gain = 146,464 },465 [2] = {466 .num = ST_MAGN_FS_AVL_8000MG,467 .value = 0x02,468 .gain = 292,469 },470 [3] = {471 .num = ST_MAGN_FS_AVL_12000MG,472 .value = 0x03,473 .gain = 438,474 },475 },476 },477 .bdu = {478 .addr = 0x20,479 .mask = BIT(3),480 },481 .drdy_irq = {482 .int1 = {483 .addr = 0x22,484 .mask = BIT(1),485 },486 .int2 = {487 .addr = 0x23,488 .mask = BIT(2),489 },490 .stat_drdy = {491 .addr = 0x07,492 .mask = GENMASK(2, 0),493 },494 },495 .sim = {496 .addr = 0x21,497 .value = BIT(0),498 },499 .multi_read_bit = true,500 .bootime = 2,501 },502};503 504/* Default magn DRDY is available on INT2 pin */505static const struct st_sensors_platform_data default_magn_pdata = {506 .drdy_int_pin = 2,507};508 509static int st_magn_read_raw(struct iio_dev *indio_dev,510 struct iio_chan_spec const *ch, int *val,511 int *val2, long mask)512{513 int err;514 struct st_sensor_data *mdata = iio_priv(indio_dev);515 516 switch (mask) {517 case IIO_CHAN_INFO_RAW:518 err = st_sensors_read_info_raw(indio_dev, ch, val);519 if (err < 0)520 goto read_error;521 522 return IIO_VAL_INT;523 case IIO_CHAN_INFO_SCALE:524 *val = 0;525 if ((ch->scan_index == ST_SENSORS_SCAN_Z) &&526 (mdata->current_fullscale->gain2 != 0))527 *val2 = mdata->current_fullscale->gain2;528 else529 *val2 = mdata->current_fullscale->gain;530 return IIO_VAL_INT_PLUS_MICRO;531 case IIO_CHAN_INFO_SAMP_FREQ:532 *val = mdata->odr;533 return IIO_VAL_INT;534 default:535 return -EINVAL;536 }537 538read_error:539 return err;540}541 542static int st_magn_write_raw(struct iio_dev *indio_dev,543 struct iio_chan_spec const *chan, int val, int val2, long mask)544{545 switch (mask) {546 case IIO_CHAN_INFO_SCALE:547 return st_sensors_set_fullscale_by_gain(indio_dev, val2);548 case IIO_CHAN_INFO_SAMP_FREQ:549 if (val2)550 return -EINVAL;551 552 return st_sensors_set_odr(indio_dev, val);553 default:554 return -EINVAL;555 }556}557 558static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();559static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);560 561static struct attribute *st_magn_attributes[] = {562 &iio_dev_attr_sampling_frequency_available.dev_attr.attr,563 &iio_dev_attr_in_magn_scale_available.dev_attr.attr,564 NULL,565};566 567static const struct attribute_group st_magn_attribute_group = {568 .attrs = st_magn_attributes,569};570 571static const struct iio_info magn_info = {572 .attrs = &st_magn_attribute_group,573 .read_raw = &st_magn_read_raw,574 .write_raw = &st_magn_write_raw,575 .debugfs_reg_access = &st_sensors_debugfs_reg_access,576};577 578#ifdef CONFIG_IIO_TRIGGER579static const struct iio_trigger_ops st_magn_trigger_ops = {580 .set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,581 .validate_device = st_sensors_validate_device,582};583#define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)584#else585#define ST_MAGN_TRIGGER_OPS NULL586#endif587 588/*589 * st_magn_get_settings() - get sensor settings from device name590 * @name: device name buffer reference.591 *592 * Return: valid reference on success, NULL otherwise.593 */594const struct st_sensor_settings *st_magn_get_settings(const char *name)595{596 int index = st_sensors_get_settings_index(name,597 st_magn_sensors_settings,598 ARRAY_SIZE(st_magn_sensors_settings));599 if (index < 0)600 return NULL;601 602 return &st_magn_sensors_settings[index];603}604EXPORT_SYMBOL_NS(st_magn_get_settings, IIO_ST_SENSORS);605 606int st_magn_common_probe(struct iio_dev *indio_dev)607{608 struct st_sensor_data *mdata = iio_priv(indio_dev);609 struct device *parent = indio_dev->dev.parent;610 struct st_sensors_platform_data *pdata = dev_get_platdata(parent);611 int err;612 613 indio_dev->modes = INDIO_DIRECT_MODE;614 indio_dev->info = &magn_info;615 616 err = st_sensors_verify_id(indio_dev);617 if (err < 0)618 return err;619 620 mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;621 indio_dev->channels = mdata->sensor_settings->ch;622 indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;623 624 err = iio_read_mount_matrix(parent, &mdata->mount_matrix);625 if (err)626 return err;627 628 mdata->current_fullscale = &mdata->sensor_settings->fs.fs_avl[0];629 mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz;630 631 if (!pdata)632 pdata = (struct st_sensors_platform_data *)&default_magn_pdata;633 634 err = st_sensors_init_sensor(indio_dev, pdata);635 if (err < 0)636 return err;637 638 err = st_magn_allocate_ring(indio_dev);639 if (err < 0)640 return err;641 642 if (mdata->irq > 0) {643 err = st_sensors_allocate_trigger(indio_dev,644 ST_MAGN_TRIGGER_OPS);645 if (err < 0)646 return err;647 }648 649 return devm_iio_device_register(parent, indio_dev);650}651EXPORT_SYMBOL_NS(st_magn_common_probe, IIO_ST_SENSORS);652 653MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");654MODULE_DESCRIPTION("STMicroelectronics magnetometers driver");655MODULE_LICENSE("GPL v2");656MODULE_IMPORT_NS(IIO_ST_SENSORS);657