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