linux/drivers/iio/magnetometer/mag3110.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * mag3110.c - Support for Freescale MAG3110 magnetometer sensor
   4 *
   5 * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
   6 *
   7 * (7-bit I2C slave address 0x0e)
   8 *
   9 * TODO: irq, user offset, oversampling, continuous mode
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/i2c.h>
  14#include <linux/iio/iio.h>
  15#include <linux/iio/sysfs.h>
  16#include <linux/iio/trigger_consumer.h>
  17#include <linux/iio/buffer.h>
  18#include <linux/iio/triggered_buffer.h>
  19#include <linux/delay.h>
  20#include <linux/regulator/consumer.h>
  21
  22#define MAG3110_STATUS 0x00
  23#define MAG3110_OUT_X 0x01 /* MSB first */
  24#define MAG3110_OUT_Y 0x03
  25#define MAG3110_OUT_Z 0x05
  26#define MAG3110_WHO_AM_I 0x07
  27#define MAG3110_SYSMOD 0x08
  28#define MAG3110_OFF_X 0x09 /* MSB first */
  29#define MAG3110_OFF_Y 0x0b
  30#define MAG3110_OFF_Z 0x0d
  31#define MAG3110_DIE_TEMP 0x0f
  32#define MAG3110_CTRL_REG1 0x10
  33#define MAG3110_CTRL_REG2 0x11
  34
  35#define MAG3110_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
  36
  37#define MAG3110_CTRL_DR_MASK (BIT(7) | BIT(6) | BIT(5))
  38#define MAG3110_CTRL_DR_SHIFT 5
  39#define MAG3110_CTRL_DR_DEFAULT 0
  40
  41#define MAG3110_SYSMOD_MODE_MASK GENMASK(1, 0)
  42
  43#define MAG3110_CTRL_TM BIT(1) /* trigger single measurement */
  44#define MAG3110_CTRL_AC BIT(0) /* continuous measurements */
  45
  46#define MAG3110_CTRL_AUTO_MRST_EN BIT(7) /* magnetic auto-reset */
  47#define MAG3110_CTRL_RAW BIT(5) /* measurements not user-offset corrected */
  48
  49#define MAG3110_DEVICE_ID 0xc4
  50
  51/* Each client has this additional data */
  52struct mag3110_data {
  53        struct i2c_client *client;
  54        struct mutex lock;
  55        u8 ctrl_reg1;
  56        int sleep_val;
  57        struct regulator *vdd_reg;
  58        struct regulator *vddio_reg;
  59};
  60
  61static int mag3110_request(struct mag3110_data *data)
  62{
  63        int ret, tries = 150;
  64
  65        if ((data->ctrl_reg1 & MAG3110_CTRL_AC) == 0) {
  66                /* trigger measurement */
  67                ret = i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
  68                        data->ctrl_reg1 | MAG3110_CTRL_TM);
  69                if (ret < 0)
  70                        return ret;
  71        }
  72
  73        while (tries-- > 0) {
  74                ret = i2c_smbus_read_byte_data(data->client, MAG3110_STATUS);
  75                if (ret < 0)
  76                        return ret;
  77                /* wait for data ready */
  78                if ((ret & MAG3110_STATUS_DRDY) == MAG3110_STATUS_DRDY)
  79                        break;
  80
  81                if (data->sleep_val <= 20)
  82                        usleep_range(data->sleep_val * 250, data->sleep_val * 500);
  83                else
  84                        msleep(20);
  85        }
  86
  87        if (tries < 0) {
  88                dev_err(&data->client->dev, "data not ready\n");
  89                return -EIO;
  90        }
  91
  92        return 0;
  93}
  94
  95static int mag3110_read(struct mag3110_data *data, __be16 buf[3])
  96{
  97        int ret;
  98
  99        mutex_lock(&data->lock);
 100        ret = mag3110_request(data);
 101        if (ret < 0) {
 102                mutex_unlock(&data->lock);
 103                return ret;
 104        }
 105        ret = i2c_smbus_read_i2c_block_data(data->client,
 106                MAG3110_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
 107        mutex_unlock(&data->lock);
 108
 109        return ret;
 110}
 111
 112static ssize_t mag3110_show_int_plus_micros(char *buf,
 113        const int (*vals)[2], int n)
 114{
 115        size_t len = 0;
 116
 117        while (n-- > 0)
 118                len += scnprintf(buf + len, PAGE_SIZE - len,
 119                        "%d.%06d ", vals[n][0], vals[n][1]);
 120
 121        /* replace trailing space by newline */
 122        buf[len - 1] = '\n';
 123
 124        return len;
 125}
 126
 127static int mag3110_get_int_plus_micros_index(const int (*vals)[2], int n,
 128                                        int val, int val2)
 129{
 130        while (n-- > 0)
 131                if (val == vals[n][0] && val2 == vals[n][1])
 132                        return n;
 133
 134        return -EINVAL;
 135}
 136
 137static const int mag3110_samp_freq[8][2] = {
 138        {80, 0}, {40, 0}, {20, 0}, {10, 0}, {5, 0}, {2, 500000},
 139        {1, 250000}, {0, 625000}
 140};
 141
 142static ssize_t mag3110_show_samp_freq_avail(struct device *dev,
 143                                struct device_attribute *attr, char *buf)
 144{
 145        return mag3110_show_int_plus_micros(buf, mag3110_samp_freq, 8);
 146}
 147
 148static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mag3110_show_samp_freq_avail);
 149
 150static int mag3110_get_samp_freq_index(struct mag3110_data *data,
 151        int val, int val2)
 152{
 153        return mag3110_get_int_plus_micros_index(mag3110_samp_freq, 8, val,
 154                val2);
 155}
 156
 157static int mag3110_calculate_sleep(struct mag3110_data *data)
 158{
 159        int ret, i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
 160
 161        if (mag3110_samp_freq[i][0] > 0)
 162                ret = 1000 / mag3110_samp_freq[i][0];
 163        else
 164                ret = 1000;
 165
 166        return ret == 0 ? 1 : ret;
 167}
 168
 169static int mag3110_standby(struct mag3110_data *data)
 170{
 171        return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
 172                data->ctrl_reg1 & ~MAG3110_CTRL_AC);
 173}
 174
 175static int mag3110_wait_standby(struct mag3110_data *data)
 176{
 177        int ret, tries = 30;
 178
 179        /*
 180         * Takes up to 1/ODR to come out of active mode into stby
 181         * Longest expected period is 12.5seconds.
 182         * We'll sleep for 500ms between checks
 183         */
 184        while (tries-- > 0) {
 185                ret = i2c_smbus_read_byte_data(data->client, MAG3110_SYSMOD);
 186                if (ret < 0) {
 187                        dev_err(&data->client->dev, "i2c error\n");
 188                        return ret;
 189                }
 190                /* wait for standby */
 191                if ((ret & MAG3110_SYSMOD_MODE_MASK) == 0)
 192                        break;
 193
 194                msleep_interruptible(500);
 195        }
 196
 197        if (tries < 0) {
 198                dev_err(&data->client->dev, "device not entering standby mode\n");
 199                return -EIO;
 200        }
 201
 202        return 0;
 203}
 204
 205static int mag3110_active(struct mag3110_data *data)
 206{
 207        return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
 208                                         data->ctrl_reg1);
 209}
 210
 211/* returns >0 if active, 0 if in standby and <0 on error */
 212static int mag3110_is_active(struct mag3110_data *data)
 213{
 214        int reg;
 215
 216        reg = i2c_smbus_read_byte_data(data->client, MAG3110_CTRL_REG1);
 217        if (reg < 0)
 218                return reg;
 219
 220        return reg & MAG3110_CTRL_AC;
 221}
 222
 223static int mag3110_change_config(struct mag3110_data *data, u8 reg, u8 val)
 224{
 225        int ret;
 226        int is_active;
 227
 228        mutex_lock(&data->lock);
 229
 230        is_active = mag3110_is_active(data);
 231        if (is_active < 0) {
 232                ret = is_active;
 233                goto fail;
 234        }
 235
 236        /* config can only be changed when in standby */
 237        if (is_active > 0) {
 238                ret = mag3110_standby(data);
 239                if (ret < 0)
 240                        goto fail;
 241        }
 242
 243        /*
 244         * After coming out of active we must wait for the part
 245         * to transition to STBY. This can take up to 1 /ODR to occur
 246         */
 247        ret = mag3110_wait_standby(data);
 248        if (ret < 0)
 249                goto fail;
 250
 251        ret = i2c_smbus_write_byte_data(data->client, reg, val);
 252        if (ret < 0)
 253                goto fail;
 254
 255        if (is_active > 0) {
 256                ret = mag3110_active(data);
 257                if (ret < 0)
 258                        goto fail;
 259        }
 260
 261        ret = 0;
 262fail:
 263        mutex_unlock(&data->lock);
 264
 265        return ret;
 266}
 267
 268static int mag3110_read_raw(struct iio_dev *indio_dev,
 269                            struct iio_chan_spec const *chan,
 270                            int *val, int *val2, long mask)
 271{
 272        struct mag3110_data *data = iio_priv(indio_dev);
 273        __be16 buffer[3];
 274        int i, ret;
 275
 276        switch (mask) {
 277        case IIO_CHAN_INFO_RAW:
 278                ret = iio_device_claim_direct_mode(indio_dev);
 279                if (ret)
 280                        return ret;
 281
 282                switch (chan->type) {
 283                case IIO_MAGN: /* in 0.1 uT / LSB */
 284                        ret = mag3110_read(data, buffer);
 285                        if (ret < 0)
 286                                goto release;
 287                        *val = sign_extend32(
 288                                be16_to_cpu(buffer[chan->scan_index]), 15);
 289                        ret = IIO_VAL_INT;
 290                        break;
 291                case IIO_TEMP: /* in 1 C / LSB */
 292                        mutex_lock(&data->lock);
 293                        ret = mag3110_request(data);
 294                        if (ret < 0) {
 295                                mutex_unlock(&data->lock);
 296                                goto release;
 297                        }
 298                        ret = i2c_smbus_read_byte_data(data->client,
 299                                MAG3110_DIE_TEMP);
 300                        mutex_unlock(&data->lock);
 301                        if (ret < 0)
 302                                goto release;
 303                        *val = sign_extend32(ret, 7);
 304                        ret = IIO_VAL_INT;
 305                        break;
 306                default:
 307                        ret = -EINVAL;
 308                }
 309release:
 310                iio_device_release_direct_mode(indio_dev);
 311                return ret;
 312
 313        case IIO_CHAN_INFO_SCALE:
 314                switch (chan->type) {
 315                case IIO_MAGN:
 316                        *val = 0;
 317                        *val2 = 1000;
 318                        return IIO_VAL_INT_PLUS_MICRO;
 319                case IIO_TEMP:
 320                        *val = 1000;
 321                        return IIO_VAL_INT;
 322                default:
 323                        return -EINVAL;
 324                }
 325        case IIO_CHAN_INFO_SAMP_FREQ:
 326                i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
 327                *val = mag3110_samp_freq[i][0];
 328                *val2 = mag3110_samp_freq[i][1];
 329                return IIO_VAL_INT_PLUS_MICRO;
 330        case IIO_CHAN_INFO_CALIBBIAS:
 331                ret = i2c_smbus_read_word_swapped(data->client,
 332                        MAG3110_OFF_X + 2 * chan->scan_index);
 333                if (ret < 0)
 334                        return ret;
 335                *val = sign_extend32(ret >> 1, 14);
 336                return IIO_VAL_INT;
 337        }
 338        return -EINVAL;
 339}
 340
 341static int mag3110_write_raw(struct iio_dev *indio_dev,
 342                             struct iio_chan_spec const *chan,
 343                             int val, int val2, long mask)
 344{
 345        struct mag3110_data *data = iio_priv(indio_dev);
 346        int rate, ret;
 347
 348        ret = iio_device_claim_direct_mode(indio_dev);
 349        if (ret)
 350                return ret;
 351
 352        switch (mask) {
 353        case IIO_CHAN_INFO_SAMP_FREQ:
 354                rate = mag3110_get_samp_freq_index(data, val, val2);
 355                if (rate < 0) {
 356                        ret = -EINVAL;
 357                        break;
 358                }
 359                data->ctrl_reg1 &= 0xff & ~MAG3110_CTRL_DR_MASK
 360                                        & ~MAG3110_CTRL_AC;
 361                data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT;
 362                data->sleep_val = mag3110_calculate_sleep(data);
 363                if (data->sleep_val < 40)
 364                        data->ctrl_reg1 |= MAG3110_CTRL_AC;
 365
 366                ret = mag3110_change_config(data, MAG3110_CTRL_REG1,
 367                                            data->ctrl_reg1);
 368                break;
 369        case IIO_CHAN_INFO_CALIBBIAS:
 370                if (val < -10000 || val > 10000) {
 371                        ret = -EINVAL;
 372                        break;
 373                }
 374                ret = i2c_smbus_write_word_swapped(data->client,
 375                        MAG3110_OFF_X + 2 * chan->scan_index, val << 1);
 376                break;
 377        default:
 378                ret = -EINVAL;
 379                break;
 380        }
 381        iio_device_release_direct_mode(indio_dev);
 382        return ret;
 383}
 384
 385static irqreturn_t mag3110_trigger_handler(int irq, void *p)
 386{
 387        struct iio_poll_func *pf = p;
 388        struct iio_dev *indio_dev = pf->indio_dev;
 389        struct mag3110_data *data = iio_priv(indio_dev);
 390        u8 buffer[16]; /* 3 16-bit channels + 1 byte temp + padding + ts */
 391        int ret;
 392
 393        ret = mag3110_read(data, (__be16 *) buffer);
 394        if (ret < 0)
 395                goto done;
 396
 397        if (test_bit(3, indio_dev->active_scan_mask)) {
 398                ret = i2c_smbus_read_byte_data(data->client,
 399                        MAG3110_DIE_TEMP);
 400                if (ret < 0)
 401                        goto done;
 402                buffer[6] = ret;
 403        }
 404
 405        iio_push_to_buffers_with_timestamp(indio_dev, buffer,
 406                iio_get_time_ns(indio_dev));
 407
 408done:
 409        iio_trigger_notify_done(indio_dev->trig);
 410        return IRQ_HANDLED;
 411}
 412
 413#define MAG3110_CHANNEL(axis, idx) { \
 414        .type = IIO_MAGN, \
 415        .modified = 1, \
 416        .channel2 = IIO_MOD_##axis, \
 417        .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
 418                BIT(IIO_CHAN_INFO_CALIBBIAS), \
 419        .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
 420                BIT(IIO_CHAN_INFO_SCALE), \
 421        .scan_index = idx, \
 422        .scan_type = { \
 423                .sign = 's', \
 424                .realbits = 16, \
 425                .storagebits = 16, \
 426                .endianness = IIO_BE, \
 427        }, \
 428}
 429
 430static const struct iio_chan_spec mag3110_channels[] = {
 431        MAG3110_CHANNEL(X, 0),
 432        MAG3110_CHANNEL(Y, 1),
 433        MAG3110_CHANNEL(Z, 2),
 434        {
 435                .type = IIO_TEMP,
 436                .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
 437                        BIT(IIO_CHAN_INFO_SCALE),
 438                .scan_index = 3,
 439                .scan_type = {
 440                        .sign = 's',
 441                        .realbits = 8,
 442                        .storagebits = 8,
 443                        },
 444        },
 445        IIO_CHAN_SOFT_TIMESTAMP(4),
 446};
 447
 448static struct attribute *mag3110_attributes[] = {
 449        &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 450        NULL
 451};
 452
 453static const struct attribute_group mag3110_group = {
 454        .attrs = mag3110_attributes,
 455};
 456
 457static const struct iio_info mag3110_info = {
 458        .attrs = &mag3110_group,
 459        .read_raw = &mag3110_read_raw,
 460        .write_raw = &mag3110_write_raw,
 461};
 462
 463static const unsigned long mag3110_scan_masks[] = {0x7, 0xf, 0};
 464
 465static int mag3110_probe(struct i2c_client *client,
 466                         const struct i2c_device_id *id)
 467{
 468        struct mag3110_data *data;
 469        struct iio_dev *indio_dev;
 470        int ret;
 471
 472        indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
 473        if (!indio_dev)
 474                return -ENOMEM;
 475
 476        data = iio_priv(indio_dev);
 477
 478        data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
 479        if (IS_ERR(data->vdd_reg)) {
 480                if (PTR_ERR(data->vdd_reg) == -EPROBE_DEFER)
 481                        return -EPROBE_DEFER;
 482
 483                dev_err(&client->dev, "failed to get VDD regulator!\n");
 484                return PTR_ERR(data->vdd_reg);
 485        }
 486
 487        data->vddio_reg = devm_regulator_get(&client->dev, "vddio");
 488        if (IS_ERR(data->vddio_reg)) {
 489                if (PTR_ERR(data->vddio_reg) == -EPROBE_DEFER)
 490                        return -EPROBE_DEFER;
 491
 492                dev_err(&client->dev, "failed to get VDDIO regulator!\n");
 493                return PTR_ERR(data->vddio_reg);
 494        }
 495
 496        ret = regulator_enable(data->vdd_reg);
 497        if (ret) {
 498                dev_err(&client->dev, "failed to enable VDD regulator!\n");
 499                return ret;
 500        }
 501
 502        ret = regulator_enable(data->vddio_reg);
 503        if (ret) {
 504                dev_err(&client->dev, "failed to enable VDDIO regulator!\n");
 505                goto disable_regulator_vdd;
 506        }
 507
 508        ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I);
 509        if (ret < 0)
 510                goto disable_regulators;
 511        if (ret != MAG3110_DEVICE_ID) {
 512                ret = -ENODEV;
 513                goto disable_regulators;
 514        }
 515
 516        data->client = client;
 517        mutex_init(&data->lock);
 518
 519        i2c_set_clientdata(client, indio_dev);
 520        indio_dev->info = &mag3110_info;
 521        indio_dev->name = id->name;
 522        indio_dev->dev.parent = &client->dev;
 523        indio_dev->modes = INDIO_DIRECT_MODE;
 524        indio_dev->channels = mag3110_channels;
 525        indio_dev->num_channels = ARRAY_SIZE(mag3110_channels);
 526        indio_dev->available_scan_masks = mag3110_scan_masks;
 527
 528        data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT << MAG3110_CTRL_DR_SHIFT;
 529        data->sleep_val = mag3110_calculate_sleep(data);
 530        if (data->sleep_val < 40)
 531                data->ctrl_reg1 |= MAG3110_CTRL_AC;
 532
 533        ret = mag3110_change_config(data, MAG3110_CTRL_REG1, data->ctrl_reg1);
 534        if (ret < 0)
 535                goto disable_regulators;
 536
 537        ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2,
 538                MAG3110_CTRL_AUTO_MRST_EN);
 539        if (ret < 0)
 540                goto standby_on_error;
 541
 542        ret = iio_triggered_buffer_setup(indio_dev, NULL,
 543                mag3110_trigger_handler, NULL);
 544        if (ret < 0)
 545                goto standby_on_error;
 546
 547        ret = iio_device_register(indio_dev);
 548        if (ret < 0)
 549                goto buffer_cleanup;
 550        return 0;
 551
 552buffer_cleanup:
 553        iio_triggered_buffer_cleanup(indio_dev);
 554standby_on_error:
 555        mag3110_standby(iio_priv(indio_dev));
 556disable_regulators:
 557        regulator_disable(data->vddio_reg);
 558disable_regulator_vdd:
 559        regulator_disable(data->vdd_reg);
 560
 561        return ret;
 562}
 563
 564static int mag3110_remove(struct i2c_client *client)
 565{
 566        struct iio_dev *indio_dev = i2c_get_clientdata(client);
 567        struct mag3110_data *data = iio_priv(indio_dev);
 568
 569        iio_device_unregister(indio_dev);
 570        iio_triggered_buffer_cleanup(indio_dev);
 571        mag3110_standby(iio_priv(indio_dev));
 572        regulator_disable(data->vddio_reg);
 573        regulator_disable(data->vdd_reg);
 574
 575        return 0;
 576}
 577
 578#ifdef CONFIG_PM_SLEEP
 579static int mag3110_suspend(struct device *dev)
 580{
 581        struct mag3110_data *data = iio_priv(i2c_get_clientdata(
 582                to_i2c_client(dev)));
 583        int ret;
 584
 585        ret = mag3110_standby(iio_priv(i2c_get_clientdata(
 586                to_i2c_client(dev))));
 587        if (ret)
 588                return ret;
 589
 590        ret = regulator_disable(data->vddio_reg);
 591        if (ret) {
 592                dev_err(dev, "failed to disable VDDIO regulator\n");
 593                return ret;
 594        }
 595
 596        ret = regulator_disable(data->vdd_reg);
 597        if (ret) {
 598                dev_err(dev, "failed to disable VDD regulator\n");
 599                return ret;
 600        }
 601
 602        return 0;
 603}
 604
 605static int mag3110_resume(struct device *dev)
 606{
 607        struct mag3110_data *data = iio_priv(i2c_get_clientdata(
 608                to_i2c_client(dev)));
 609        int ret;
 610
 611        ret = regulator_enable(data->vdd_reg);
 612        if (ret) {
 613                dev_err(dev, "failed to enable VDD regulator\n");
 614                return ret;
 615        }
 616
 617        ret = regulator_enable(data->vddio_reg);
 618        if (ret) {
 619                dev_err(dev, "failed to enable VDDIO regulator\n");
 620                regulator_disable(data->vdd_reg);
 621                return ret;
 622        }
 623
 624        return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
 625                data->ctrl_reg1);
 626}
 627
 628static SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend, mag3110_resume);
 629#define MAG3110_PM_OPS (&mag3110_pm_ops)
 630#else
 631#define MAG3110_PM_OPS NULL
 632#endif
 633
 634static const struct i2c_device_id mag3110_id[] = {
 635        { "mag3110", 0 },
 636        { }
 637};
 638MODULE_DEVICE_TABLE(i2c, mag3110_id);
 639
 640static const struct of_device_id mag3110_of_match[] = {
 641        { .compatible = "fsl,mag3110" },
 642        { }
 643};
 644MODULE_DEVICE_TABLE(of, mag3110_of_match);
 645
 646static struct i2c_driver mag3110_driver = {
 647        .driver = {
 648                .name   = "mag3110",
 649                .of_match_table = mag3110_of_match,
 650                .pm     = MAG3110_PM_OPS,
 651        },
 652        .probe = mag3110_probe,
 653        .remove = mag3110_remove,
 654        .id_table = mag3110_id,
 655};
 656module_i2c_driver(mag3110_driver);
 657
 658MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
 659MODULE_DESCRIPTION("Freescale MAG3110 magnetometer driver");
 660MODULE_LICENSE("GPL");
 661