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