root/drivers/iio/magnetometer/st_magn_core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. st_magn_read_raw
  2. st_magn_write_raw
  3. st_magn_get_settings
  4. st_magn_common_probe
  5. st_magn_common_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * STMicroelectronics magnetometers driver
   4  *
   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/slab.h>
  13 #include <linux/errno.h>
  14 #include <linux/types.h>
  15 #include <linux/interrupt.h>
  16 #include <linux/i2c.h>
  17 #include <linux/gpio.h>
  18 #include <linux/irq.h>
  19 #include <linux/delay.h>
  20 #include <linux/iio/iio.h>
  21 #include <linux/iio/sysfs.h>
  22 #include <linux/iio/buffer.h>
  23 
  24 #include <linux/iio/common/st_sensors.h>
  25 #include "st_magn.h"
  26 
  27 #define ST_MAGN_NUMBER_DATA_CHANNELS            3
  28 
  29 /* DEFAULT VALUE FOR SENSORS */
  30 #define ST_MAGN_DEFAULT_OUT_X_H_ADDR            0x03
  31 #define ST_MAGN_DEFAULT_OUT_Y_H_ADDR            0x07
  32 #define ST_MAGN_DEFAULT_OUT_Z_H_ADDR            0x05
  33 
  34 /* FULLSCALE */
  35 #define ST_MAGN_FS_AVL_1300MG                   1300
  36 #define ST_MAGN_FS_AVL_1900MG                   1900
  37 #define ST_MAGN_FS_AVL_2500MG                   2500
  38 #define ST_MAGN_FS_AVL_4000MG                   4000
  39 #define ST_MAGN_FS_AVL_4700MG                   4700
  40 #define ST_MAGN_FS_AVL_5600MG                   5600
  41 #define ST_MAGN_FS_AVL_8000MG                   8000
  42 #define ST_MAGN_FS_AVL_8100MG                   8100
  43 #define ST_MAGN_FS_AVL_12000MG                  12000
  44 #define ST_MAGN_FS_AVL_15000MG                  15000
  45 #define ST_MAGN_FS_AVL_16000MG                  16000
  46 
  47 /* Special L addresses for Sensor 2 */
  48 #define ST_MAGN_2_OUT_X_L_ADDR                  0x28
  49 #define ST_MAGN_2_OUT_Y_L_ADDR                  0x2a
  50 #define ST_MAGN_2_OUT_Z_L_ADDR                  0x2c
  51 
  52 /* Special L addresses for sensor 3 */
  53 #define ST_MAGN_3_OUT_X_L_ADDR                  0x68
  54 #define ST_MAGN_3_OUT_Y_L_ADDR                  0x6a
  55 #define ST_MAGN_3_OUT_Z_L_ADDR                  0x6c
  56 
  57 static const struct iio_chan_spec st_magn_16bit_channels[] = {
  58         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  59                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  60                         ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_BE, 16, 16,
  61                         ST_MAGN_DEFAULT_OUT_X_H_ADDR),
  62         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  63                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  64                         ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_BE, 16, 16,
  65                         ST_MAGN_DEFAULT_OUT_Y_H_ADDR),
  66         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  67                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  68                         ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_BE, 16, 16,
  69                         ST_MAGN_DEFAULT_OUT_Z_H_ADDR),
  70         IIO_CHAN_SOFT_TIMESTAMP(3)
  71 };
  72 
  73 static const struct iio_chan_spec st_magn_2_16bit_channels[] = {
  74         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  75                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  76                         ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
  77                         ST_MAGN_2_OUT_X_L_ADDR),
  78         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  79                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  80                         ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
  81                         ST_MAGN_2_OUT_Y_L_ADDR),
  82         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  83                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  84                         ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
  85                         ST_MAGN_2_OUT_Z_L_ADDR),
  86         IIO_CHAN_SOFT_TIMESTAMP(3)
  87 };
  88 
  89 static const struct iio_chan_spec st_magn_3_16bit_channels[] = {
  90         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  91                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  92                         ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
  93                         ST_MAGN_3_OUT_X_L_ADDR),
  94         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  95                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
  96                         ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
  97                         ST_MAGN_3_OUT_Y_L_ADDR),
  98         ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
  99                         BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
 100                         ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
 101                         ST_MAGN_3_OUT_Z_L_ADDR),
 102         IIO_CHAN_SOFT_TIMESTAMP(3)
 103 };
 104 
 105 static const struct st_sensor_settings st_magn_sensors_settings[] = {
 106         {
 107                 .wai = 0, /* This sensor has no valid WhoAmI report 0 */
 108                 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 109                 .sensors_supported = {
 110                         [0] = LSM303DLH_MAGN_DEV_NAME,
 111                 },
 112                 .ch = (struct iio_chan_spec *)st_magn_16bit_channels,
 113                 .odr = {
 114                         .addr = 0x00,
 115                         .mask = 0x1c,
 116                         .odr_avl = {
 117                                 { .hz = 1, .value = 0x00 },
 118                                 { .hz = 2, .value = 0x01 },
 119                                 { .hz = 3, .value = 0x02 },
 120                                 { .hz = 8, .value = 0x03 },
 121                                 { .hz = 15, .value = 0x04 },
 122                                 { .hz = 30, .value = 0x05 },
 123                                 { .hz = 75, .value = 0x06 },
 124                                 /* 220 Hz, 0x07 reportedly exist */
 125                         },
 126                 },
 127                 .pw = {
 128                         .addr = 0x02,
 129                         .mask = 0x03,
 130                         .value_on = 0x00,
 131                         .value_off = 0x03,
 132                 },
 133                 .fs = {
 134                         .addr = 0x01,
 135                         .mask = 0xe0,
 136                         .fs_avl = {
 137                                 [0] = {
 138                                         .num = ST_MAGN_FS_AVL_1300MG,
 139                                         .value = 0x01,
 140                                         .gain = 1100,
 141                                         .gain2 = 980,
 142                                 },
 143                                 [1] = {
 144                                         .num = ST_MAGN_FS_AVL_1900MG,
 145                                         .value = 0x02,
 146                                         .gain = 855,
 147                                         .gain2 = 760,
 148                                 },
 149                                 [2] = {
 150                                         .num = ST_MAGN_FS_AVL_2500MG,
 151                                         .value = 0x03,
 152                                         .gain = 670,
 153                                         .gain2 = 600,
 154                                 },
 155                                 [3] = {
 156                                         .num = ST_MAGN_FS_AVL_4000MG,
 157                                         .value = 0x04,
 158                                         .gain = 450,
 159                                         .gain2 = 400,
 160                                 },
 161                                 [4] = {
 162                                         .num = ST_MAGN_FS_AVL_4700MG,
 163                                         .value = 0x05,
 164                                         .gain = 400,
 165                                         .gain2 = 355,
 166                                 },
 167                                 [5] = {
 168                                         .num = ST_MAGN_FS_AVL_5600MG,
 169                                         .value = 0x06,
 170                                         .gain = 330,
 171                                         .gain2 = 295,
 172                                 },
 173                                 [6] = {
 174                                         .num = ST_MAGN_FS_AVL_8100MG,
 175                                         .value = 0x07,
 176                                         .gain = 230,
 177                                         .gain2 = 205,
 178                                 },
 179                         },
 180                 },
 181                 .multi_read_bit = false,
 182                 .bootime = 2,
 183         },
 184         {
 185                 .wai = 0x3c,
 186                 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 187                 .sensors_supported = {
 188                         [0] = LSM303DLHC_MAGN_DEV_NAME,
 189                         [1] = LSM303DLM_MAGN_DEV_NAME,
 190                 },
 191                 .ch = (struct iio_chan_spec *)st_magn_16bit_channels,
 192                 .odr = {
 193                         .addr = 0x00,
 194                         .mask = 0x1c,
 195                         .odr_avl = {
 196                                 { .hz = 1, .value = 0x00 },
 197                                 { .hz = 2, .value = 0x01 },
 198                                 { .hz = 3, .value = 0x02 },
 199                                 { .hz = 8, .value = 0x03 },
 200                                 { .hz = 15, .value = 0x04 },
 201                                 { .hz = 30, .value = 0x05 },
 202                                 { .hz = 75, .value = 0x06 },
 203                                 { .hz = 220, .value = 0x07 },
 204                         },
 205                 },
 206                 .pw = {
 207                         .addr = 0x02,
 208                         .mask = 0x03,
 209                         .value_on = 0x00,
 210                         .value_off = 0x03,
 211                 },
 212                 .fs = {
 213                         .addr = 0x01,
 214                         .mask = 0xe0,
 215                         .fs_avl = {
 216                                 [0] = {
 217                                         .num = ST_MAGN_FS_AVL_1300MG,
 218                                         .value = 0x01,
 219                                         .gain = 909,
 220                                         .gain2 = 1020,
 221                                 },
 222                                 [1] = {
 223                                         .num = ST_MAGN_FS_AVL_1900MG,
 224                                         .value = 0x02,
 225                                         .gain = 1169,
 226                                         .gain2 = 1315,
 227                                 },
 228                                 [2] = {
 229                                         .num = ST_MAGN_FS_AVL_2500MG,
 230                                         .value = 0x03,
 231                                         .gain = 1492,
 232                                         .gain2 = 1666,
 233                                 },
 234                                 [3] = {
 235                                         .num = ST_MAGN_FS_AVL_4000MG,
 236                                         .value = 0x04,
 237                                         .gain = 2222,
 238                                         .gain2 = 2500,
 239                                 },
 240                                 [4] = {
 241                                         .num = ST_MAGN_FS_AVL_4700MG,
 242                                         .value = 0x05,
 243                                         .gain = 2500,
 244                                         .gain2 = 2816,
 245                                 },
 246                                 [5] = {
 247                                         .num = ST_MAGN_FS_AVL_5600MG,
 248                                         .value = 0x06,
 249                                         .gain = 3030,
 250                                         .gain2 = 3389,
 251                                 },
 252                                 [6] = {
 253                                         .num = ST_MAGN_FS_AVL_8100MG,
 254                                         .value = 0x07,
 255                                         .gain = 4347,
 256                                         .gain2 = 4878,
 257                                 },
 258                         },
 259                 },
 260                 .multi_read_bit = false,
 261                 .bootime = 2,
 262         },
 263         {
 264                 .wai = 0x3d,
 265                 .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
 266                 .sensors_supported = {
 267                         [0] = LIS3MDL_MAGN_DEV_NAME,
 268                         [1] = LSM9DS1_MAGN_DEV_NAME,
 269                 },
 270                 .ch = (struct iio_chan_spec *)st_magn_2_16bit_channels,
 271                 .odr = {
 272                         .addr = 0x20,
 273                         .mask = 0x1c,
 274                         .odr_avl = {
 275                                 { .hz = 1, .value = 0x00 },
 276                                 { .hz = 2, .value = 0x01 },
 277                                 { .hz = 3, .value = 0x02 },
 278                                 { .hz = 5, .value = 0x03 },
 279                                 { .hz = 10, .value = 0x04 },
 280                                 { .hz = 20, .value = 0x05 },
 281                                 { .hz = 40, .value = 0x06 },
 282                                 { .hz = 80, .value = 0x07 },
 283                         },
 284                 },
 285                 .pw = {
 286                         .addr = 0x22,
 287                         .mask = 0x03,
 288                         .value_on = 0x00,
 289                         .value_off = 0x03,
 290                 },
 291                 .fs = {
 292                         .addr = 0x21,
 293                         .mask = 0x60,
 294                         .fs_avl = {
 295                                 [0] = {
 296                                         .num = ST_MAGN_FS_AVL_4000MG,
 297                                         .value = 0x00,
 298                                         .gain = 146,
 299                                 },
 300                                 [1] = {
 301                                         .num = ST_MAGN_FS_AVL_8000MG,
 302                                         .value = 0x01,
 303                                         .gain = 292,
 304                                 },
 305                                 [2] = {
 306                                         .num = ST_MAGN_FS_AVL_12000MG,
 307                                         .value = 0x02,
 308                                         .gain = 438,
 309                                 },
 310                                 [3] = {
 311                                         .num = ST_MAGN_FS_AVL_16000MG,
 312                                         .value = 0x03,
 313                                         .gain = 584,
 314                                 },
 315                         },
 316                 },
 317                 .bdu = {
 318                         .addr = 0x24,
 319                         .mask = 0x40,
 320                 },
 321                 .drdy_irq = {
 322                         /* drdy line is routed drdy pin */
 323                         .stat_drdy = {
 324                                 .addr = ST_SENSORS_DEFAULT_STAT_ADDR,
 325                                 .mask = 0x07,
 326                         },
 327                 },
 328                 .sim = {
 329                         .addr = 0x22,
 330                         .value = BIT(2),
 331                 },
 332                 .multi_read_bit = true,
 333                 .bootime = 2,
 334         },
 335         {
 336                 .wai = 0x40,
 337                 .wai_addr = 0x4f,
 338                 .sensors_supported = {
 339                         [0] = LSM303AGR_MAGN_DEV_NAME,
 340                         [1] = LIS2MDL_MAGN_DEV_NAME,
 341                 },
 342                 .ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,
 343                 .odr = {
 344                         .addr = 0x60,
 345                         .mask = 0x0c,
 346                         .odr_avl = {
 347                                 { .hz = 10, .value = 0x00 },
 348                                 { .hz = 20, .value = 0x01 },
 349                                 { .hz = 50, .value = 0x02 },
 350                                 { .hz = 100, .value = 0x03 },
 351                         },
 352                 },
 353                 .pw = {
 354                         .addr = 0x60,
 355                         .mask = 0x03,
 356                         .value_on = 0x00,
 357                         .value_off = 0x03,
 358                 },
 359                 .fs = {
 360                         .fs_avl = {
 361                                 [0] = {
 362                                         .num = ST_MAGN_FS_AVL_15000MG,
 363                                         .gain = 1500,
 364                                 },
 365                         },
 366                 },
 367                 .bdu = {
 368                         .addr = 0x62,
 369                         .mask = 0x10,
 370                 },
 371                 .drdy_irq = {
 372                         .int1 = {
 373                                 .addr = 0x62,
 374                                 .mask = 0x01,
 375                         },
 376                         .stat_drdy = {
 377                                 .addr = 0x67,
 378                                 .mask = 0x07,
 379                         },
 380                 },
 381                 .multi_read_bit = false,
 382                 .bootime = 2,
 383         },
 384 };
 385 
 386 static int st_magn_read_raw(struct iio_dev *indio_dev,
 387                         struct iio_chan_spec const *ch, int *val,
 388                                                         int *val2, long mask)
 389 {
 390         int err;
 391         struct st_sensor_data *mdata = iio_priv(indio_dev);
 392 
 393         switch (mask) {
 394         case IIO_CHAN_INFO_RAW:
 395                 err = st_sensors_read_info_raw(indio_dev, ch, val);
 396                 if (err < 0)
 397                         goto read_error;
 398 
 399                 return IIO_VAL_INT;
 400         case IIO_CHAN_INFO_SCALE:
 401                 *val = 0;
 402                 if ((ch->scan_index == ST_SENSORS_SCAN_Z) &&
 403                                         (mdata->current_fullscale->gain2 != 0))
 404                         *val2 = mdata->current_fullscale->gain2;
 405                 else
 406                         *val2 = mdata->current_fullscale->gain;
 407                 return IIO_VAL_INT_PLUS_MICRO;
 408         case IIO_CHAN_INFO_SAMP_FREQ:
 409                 *val = mdata->odr;
 410                 return IIO_VAL_INT;
 411         default:
 412                 return -EINVAL;
 413         }
 414 
 415 read_error:
 416         return err;
 417 }
 418 
 419 static int st_magn_write_raw(struct iio_dev *indio_dev,
 420                 struct iio_chan_spec const *chan, int val, int val2, long mask)
 421 {
 422         int err;
 423 
 424         switch (mask) {
 425         case IIO_CHAN_INFO_SCALE:
 426                 err = st_sensors_set_fullscale_by_gain(indio_dev, val2);
 427                 break;
 428         case IIO_CHAN_INFO_SAMP_FREQ:
 429                 if (val2)
 430                         return -EINVAL;
 431                 mutex_lock(&indio_dev->mlock);
 432                 err = st_sensors_set_odr(indio_dev, val);
 433                 mutex_unlock(&indio_dev->mlock);
 434                 return err;
 435         default:
 436                 err = -EINVAL;
 437         }
 438 
 439         return err;
 440 }
 441 
 442 static ST_SENSORS_DEV_ATTR_SAMP_FREQ_AVAIL();
 443 static ST_SENSORS_DEV_ATTR_SCALE_AVAIL(in_magn_scale_available);
 444 
 445 static struct attribute *st_magn_attributes[] = {
 446         &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 447         &iio_dev_attr_in_magn_scale_available.dev_attr.attr,
 448         NULL,
 449 };
 450 
 451 static const struct attribute_group st_magn_attribute_group = {
 452         .attrs = st_magn_attributes,
 453 };
 454 
 455 static const struct iio_info magn_info = {
 456         .attrs = &st_magn_attribute_group,
 457         .read_raw = &st_magn_read_raw,
 458         .write_raw = &st_magn_write_raw,
 459         .debugfs_reg_access = &st_sensors_debugfs_reg_access,
 460 };
 461 
 462 #ifdef CONFIG_IIO_TRIGGER
 463 static const struct iio_trigger_ops st_magn_trigger_ops = {
 464         .set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,
 465         .validate_device = st_sensors_validate_device,
 466 };
 467 #define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)
 468 #else
 469 #define ST_MAGN_TRIGGER_OPS NULL
 470 #endif
 471 
 472 /*
 473  * st_magn_get_settings() - get sensor settings from device name
 474  * @name: device name buffer reference.
 475  *
 476  * Return: valid reference on success, NULL otherwise.
 477  */
 478 const struct st_sensor_settings *st_magn_get_settings(const char *name)
 479 {
 480         int index = st_sensors_get_settings_index(name,
 481                                         st_magn_sensors_settings,
 482                                         ARRAY_SIZE(st_magn_sensors_settings));
 483         if (index < 0)
 484                 return NULL;
 485 
 486         return &st_magn_sensors_settings[index];
 487 }
 488 EXPORT_SYMBOL(st_magn_get_settings);
 489 
 490 int st_magn_common_probe(struct iio_dev *indio_dev)
 491 {
 492         struct st_sensor_data *mdata = iio_priv(indio_dev);
 493         int err;
 494 
 495         indio_dev->modes = INDIO_DIRECT_MODE;
 496         indio_dev->info = &magn_info;
 497 
 498         err = st_sensors_power_enable(indio_dev);
 499         if (err)
 500                 return err;
 501 
 502         err = st_sensors_verify_id(indio_dev);
 503         if (err < 0)
 504                 goto st_magn_power_off;
 505 
 506         mdata->num_data_channels = ST_MAGN_NUMBER_DATA_CHANNELS;
 507         indio_dev->channels = mdata->sensor_settings->ch;
 508         indio_dev->num_channels = ST_SENSORS_NUMBER_ALL_CHANNELS;
 509 
 510         mdata->current_fullscale = (struct st_sensor_fullscale_avl *)
 511                                         &mdata->sensor_settings->fs.fs_avl[0];
 512         mdata->odr = mdata->sensor_settings->odr.odr_avl[0].hz;
 513 
 514         err = st_sensors_init_sensor(indio_dev, NULL);
 515         if (err < 0)
 516                 goto st_magn_power_off;
 517 
 518         err = st_magn_allocate_ring(indio_dev);
 519         if (err < 0)
 520                 goto st_magn_power_off;
 521 
 522         if (mdata->irq > 0) {
 523                 err = st_sensors_allocate_trigger(indio_dev,
 524                                                 ST_MAGN_TRIGGER_OPS);
 525                 if (err < 0)
 526                         goto st_magn_probe_trigger_error;
 527         }
 528 
 529         err = iio_device_register(indio_dev);
 530         if (err)
 531                 goto st_magn_device_register_error;
 532 
 533         dev_info(&indio_dev->dev, "registered magnetometer %s\n",
 534                  indio_dev->name);
 535 
 536         return 0;
 537 
 538 st_magn_device_register_error:
 539         if (mdata->irq > 0)
 540                 st_sensors_deallocate_trigger(indio_dev);
 541 st_magn_probe_trigger_error:
 542         st_magn_deallocate_ring(indio_dev);
 543 st_magn_power_off:
 544         st_sensors_power_disable(indio_dev);
 545 
 546         return err;
 547 }
 548 EXPORT_SYMBOL(st_magn_common_probe);
 549 
 550 void st_magn_common_remove(struct iio_dev *indio_dev)
 551 {
 552         struct st_sensor_data *mdata = iio_priv(indio_dev);
 553 
 554         st_sensors_power_disable(indio_dev);
 555 
 556         iio_device_unregister(indio_dev);
 557         if (mdata->irq > 0)
 558                 st_sensors_deallocate_trigger(indio_dev);
 559 
 560         st_magn_deallocate_ring(indio_dev);
 561 }
 562 EXPORT_SYMBOL(st_magn_common_remove);
 563 
 564 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
 565 MODULE_DESCRIPTION("STMicroelectronics magnetometers driver");
 566 MODULE_LICENSE("GPL v2");

/* [<][>][^][v][top][bottom][index][help] */