linux/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c
<<
>>
Prefs
   1/*
   2 * STMicroelectronics st_lsm6dsx i2c controller driver
   3 *
   4 * i2c controller embedded in lsm6dx series can connect up to four
   5 * slave devices using accelerometer sensor as trigger for i2c
   6 * read/write operations. Current implementation relies on SLV0 channel
   7 * for slave configuration and SLV{1,2,3} to read data and push them into
   8 * the hw FIFO
   9 *
  10 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
  11 *
  12 * Permission to use, copy, modify, and/or distribute this software for any
  13 * purpose with or without fee is hereby granted, provided that the above
  14 * copyright notice and this permission notice appear in all copies.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  17 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  18 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  19 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  21 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  22 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  23 *
  24 */
  25#include <linux/module.h>
  26#include <linux/regmap.h>
  27#include <linux/iio/iio.h>
  28#include <linux/iio/sysfs.h>
  29#include <linux/bitfield.h>
  30
  31#include "st_lsm6dsx.h"
  32
  33#define ST_LSM6DSX_SLV_ADDR(n, base)            ((base) + (n) * 3)
  34#define ST_LSM6DSX_SLV_SUB_ADDR(n, base)        ((base) + 1 + (n) * 3)
  35#define ST_LSM6DSX_SLV_CONFIG(n, base)          ((base) + 2 + (n) * 3)
  36
  37#define ST_LS6DSX_READ_OP_MASK                  GENMASK(2, 0)
  38
  39static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
  40        /* LIS2MDL */
  41        {
  42                .i2c_addr = { 0x1e },
  43                .wai = {
  44                        .addr = 0x4f,
  45                        .val = 0x40,
  46                },
  47                .id = ST_LSM6DSX_ID_MAGN,
  48                .odr_table = {
  49                        .reg = {
  50                                .addr = 0x60,
  51                                .mask = GENMASK(3, 2),
  52                        },
  53                        .odr_avl[0] = {  10000, 0x0 },
  54                        .odr_avl[1] = {  20000, 0x1 },
  55                        .odr_avl[2] = {  50000, 0x2 },
  56                        .odr_avl[3] = { 100000, 0x3 },
  57                        .odr_len = 4,
  58                },
  59                .fs_table = {
  60                        .fs_avl[0] = {
  61                                .gain = 1500,
  62                                .val = 0x0,
  63                        }, /* 1500 uG/LSB */
  64                        .fs_len = 1,
  65                },
  66                .temp_comp = {
  67                        .addr = 0x60,
  68                        .mask = BIT(7),
  69                },
  70                .pwr_table = {
  71                        .reg = {
  72                                .addr = 0x60,
  73                                .mask = GENMASK(1, 0),
  74                        },
  75                        .off_val = 0x2,
  76                        .on_val = 0x0,
  77                },
  78                .off_canc = {
  79                        .addr = 0x61,
  80                        .mask = BIT(1),
  81                },
  82                .bdu = {
  83                        .addr = 0x62,
  84                        .mask = BIT(4),
  85                },
  86                .out = {
  87                        .addr = 0x68,
  88                        .len = 6,
  89                },
  90        },
  91        /* LIS3MDL */
  92        {
  93                .i2c_addr = { 0x1e },
  94                .wai = {
  95                        .addr = 0x0f,
  96                        .val = 0x3d,
  97                },
  98                .id = ST_LSM6DSX_ID_MAGN,
  99                .odr_table = {
 100                        .reg = {
 101                                .addr = 0x20,
 102                                .mask = GENMASK(4, 2),
 103                        },
 104                        .odr_avl[0] = {  1000, 0x0 },
 105                        .odr_avl[1] = {  2000, 0x1 },
 106                        .odr_avl[2] = {  3000, 0x2 },
 107                        .odr_avl[3] = {  5000, 0x3 },
 108                        .odr_avl[4] = { 10000, 0x4 },
 109                        .odr_avl[5] = { 20000, 0x5 },
 110                        .odr_avl[6] = { 40000, 0x6 },
 111                        .odr_avl[7] = { 80000, 0x7 },
 112                        .odr_len = 8,
 113                },
 114                .fs_table = {
 115                        .reg = {
 116                                .addr = 0x21,
 117                                .mask = GENMASK(6, 5),
 118                        },
 119                        .fs_avl[0] = {
 120                                .gain = 146,
 121                                .val = 0x00,
 122                        }, /* 4000 uG/LSB */
 123                        .fs_avl[1] = {
 124                                .gain = 292,
 125                                .val = 0x01,
 126                        }, /* 8000 uG/LSB */
 127                        .fs_avl[2] = {
 128                                .gain = 438,
 129                                .val = 0x02,
 130                        }, /* 12000 uG/LSB */
 131                        .fs_avl[3] = {
 132                                .gain = 584,
 133                                .val = 0x03,
 134                        }, /* 16000 uG/LSB */
 135                        .fs_len = 4,
 136                },
 137                .pwr_table = {
 138                        .reg = {
 139                                .addr = 0x22,
 140                                .mask = GENMASK(1, 0),
 141                        },
 142                        .off_val = 0x2,
 143                        .on_val = 0x0,
 144                },
 145                .bdu = {
 146                        .addr = 0x24,
 147                        .mask = BIT(6),
 148                },
 149                .out = {
 150                        .addr = 0x28,
 151                        .len = 6,
 152                },
 153        },
 154};
 155
 156static void st_lsm6dsx_shub_wait_complete(struct st_lsm6dsx_hw *hw)
 157{
 158        struct st_lsm6dsx_sensor *sensor;
 159        u32 odr, timeout;
 160
 161        sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
 162        odr = (hw->enable_mask & BIT(ST_LSM6DSX_ID_ACC)) ? sensor->odr : 12500;
 163        /* set 10ms as minimum timeout for i2c slave configuration */
 164        timeout = max_t(u32, 2000000U / odr + 1, 10);
 165        msleep(timeout);
 166}
 167
 168/*
 169 * st_lsm6dsx_shub_read_output - read i2c controller register
 170 *
 171 * Read st_lsm6dsx i2c controller register
 172 */
 173static int
 174st_lsm6dsx_shub_read_output(struct st_lsm6dsx_hw *hw, u8 *data,
 175                            int len)
 176{
 177        const struct st_lsm6dsx_shub_settings *hub_settings;
 178        int err;
 179
 180        mutex_lock(&hw->page_lock);
 181
 182        hub_settings = &hw->settings->shub_settings;
 183        if (hub_settings->shub_out.sec_page) {
 184                err = st_lsm6dsx_set_page(hw, true);
 185                if (err < 0)
 186                        goto out;
 187        }
 188
 189        err = regmap_bulk_read(hw->regmap, hub_settings->shub_out.addr,
 190                               data, len);
 191
 192        if (hub_settings->shub_out.sec_page)
 193                st_lsm6dsx_set_page(hw, false);
 194out:
 195        mutex_unlock(&hw->page_lock);
 196
 197        return err;
 198}
 199
 200/*
 201 * st_lsm6dsx_shub_write_reg - write i2c controller register
 202 *
 203 * Write st_lsm6dsx i2c controller register
 204 */
 205static int st_lsm6dsx_shub_write_reg(struct st_lsm6dsx_hw *hw, u8 addr,
 206                                     u8 *data, int len)
 207{
 208        int err;
 209
 210        mutex_lock(&hw->page_lock);
 211        err = st_lsm6dsx_set_page(hw, true);
 212        if (err < 0)
 213                goto out;
 214
 215        err = regmap_bulk_write(hw->regmap, addr, data, len);
 216
 217        st_lsm6dsx_set_page(hw, false);
 218out:
 219        mutex_unlock(&hw->page_lock);
 220
 221        return err;
 222}
 223
 224static int
 225st_lsm6dsx_shub_write_reg_with_mask(struct st_lsm6dsx_hw *hw, u8 addr,
 226                                    u8 mask, u8 val)
 227{
 228        int err;
 229
 230        mutex_lock(&hw->page_lock);
 231        err = st_lsm6dsx_set_page(hw, true);
 232        if (err < 0)
 233                goto out;
 234
 235        err = regmap_update_bits(hw->regmap, addr, mask, val);
 236
 237        st_lsm6dsx_set_page(hw, false);
 238out:
 239        mutex_unlock(&hw->page_lock);
 240
 241        return err;
 242}
 243
 244static int st_lsm6dsx_shub_master_enable(struct st_lsm6dsx_sensor *sensor,
 245                                         bool enable)
 246{
 247        const struct st_lsm6dsx_shub_settings *hub_settings;
 248        struct st_lsm6dsx_hw *hw = sensor->hw;
 249        unsigned int data;
 250        int err;
 251
 252        /* enable acc sensor as trigger */
 253        err = st_lsm6dsx_sensor_set_enable(sensor, enable);
 254        if (err < 0)
 255                return err;
 256
 257        mutex_lock(&hw->page_lock);
 258
 259        hub_settings = &hw->settings->shub_settings;
 260        if (hub_settings->master_en.sec_page) {
 261                err = st_lsm6dsx_set_page(hw, true);
 262                if (err < 0)
 263                        goto out;
 264        }
 265
 266        data = ST_LSM6DSX_SHIFT_VAL(enable, hub_settings->master_en.mask);
 267        err = regmap_update_bits(hw->regmap, hub_settings->master_en.addr,
 268                                 hub_settings->master_en.mask, data);
 269
 270        if (hub_settings->master_en.sec_page)
 271                st_lsm6dsx_set_page(hw, false);
 272out:
 273        mutex_unlock(&hw->page_lock);
 274
 275        return err;
 276}
 277
 278/*
 279 * st_lsm6dsx_shub_read - read data from slave device register
 280 *
 281 * Read data from slave device register. SLV0 is used for
 282 * one-shot read operation
 283 */
 284static int
 285st_lsm6dsx_shub_read(struct st_lsm6dsx_sensor *sensor, u8 addr,
 286                     u8 *data, int len)
 287{
 288        const struct st_lsm6dsx_shub_settings *hub_settings;
 289        u8 config[3], slv_addr, slv_config = 0;
 290        struct st_lsm6dsx_hw *hw = sensor->hw;
 291        const struct st_lsm6dsx_reg *aux_sens;
 292        int err;
 293
 294        hub_settings = &hw->settings->shub_settings;
 295        slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr);
 296        aux_sens = &hw->settings->shub_settings.aux_sens;
 297        /* do not overwrite aux_sens */
 298        if (slv_addr + 2 == aux_sens->addr)
 299                slv_config = ST_LSM6DSX_SHIFT_VAL(3, aux_sens->mask);
 300
 301        config[0] = (sensor->ext_info.addr << 1) | 1;
 302        config[1] = addr;
 303        config[2] = (len & ST_LS6DSX_READ_OP_MASK) | slv_config;
 304
 305        err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config,
 306                                        sizeof(config));
 307        if (err < 0)
 308                return err;
 309
 310        err = st_lsm6dsx_shub_master_enable(sensor, true);
 311        if (err < 0)
 312                return err;
 313
 314        st_lsm6dsx_shub_wait_complete(hw);
 315
 316        err = st_lsm6dsx_shub_read_output(hw, data,
 317                                          len & ST_LS6DSX_READ_OP_MASK);
 318        if (err < 0)
 319                return err;
 320
 321        st_lsm6dsx_shub_master_enable(sensor, false);
 322
 323        config[0] = hub_settings->pause;
 324        config[1] = 0;
 325        config[2] = slv_config;
 326        return st_lsm6dsx_shub_write_reg(hw, slv_addr, config,
 327                                         sizeof(config));
 328}
 329
 330/*
 331 * st_lsm6dsx_shub_write - write data to slave device register
 332 *
 333 * Write data from slave device register. SLV0 is used for
 334 * one-shot write operation
 335 */
 336static int
 337st_lsm6dsx_shub_write(struct st_lsm6dsx_sensor *sensor, u8 addr,
 338                      u8 *data, int len)
 339{
 340        const struct st_lsm6dsx_shub_settings *hub_settings;
 341        struct st_lsm6dsx_hw *hw = sensor->hw;
 342        u8 config[2], slv_addr;
 343        int err, i;
 344
 345        hub_settings = &hw->settings->shub_settings;
 346        if (hub_settings->wr_once.addr) {
 347                unsigned int data;
 348
 349                data = ST_LSM6DSX_SHIFT_VAL(1, hub_settings->wr_once.mask);
 350                err = st_lsm6dsx_shub_write_reg_with_mask(hw,
 351                        hub_settings->wr_once.addr,
 352                        hub_settings->wr_once.mask,
 353                        data);
 354                if (err < 0)
 355                        return err;
 356        }
 357
 358        slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr);
 359        config[0] = sensor->ext_info.addr << 1;
 360        for (i = 0 ; i < len; i++) {
 361                config[1] = addr + i;
 362
 363                err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config,
 364                                                sizeof(config));
 365                if (err < 0)
 366                        return err;
 367
 368                err = st_lsm6dsx_shub_write_reg(hw, hub_settings->dw_slv0_addr,
 369                                                &data[i], 1);
 370                if (err < 0)
 371                        return err;
 372
 373                err = st_lsm6dsx_shub_master_enable(sensor, true);
 374                if (err < 0)
 375                        return err;
 376
 377                st_lsm6dsx_shub_wait_complete(hw);
 378
 379                st_lsm6dsx_shub_master_enable(sensor, false);
 380        }
 381
 382        config[0] = hub_settings->pause;
 383        config[1] = 0;
 384        return st_lsm6dsx_shub_write_reg(hw, slv_addr, config, sizeof(config));
 385}
 386
 387static int
 388st_lsm6dsx_shub_write_with_mask(struct st_lsm6dsx_sensor *sensor,
 389                                u8 addr, u8 mask, u8 val)
 390{
 391        int err;
 392        u8 data;
 393
 394        err = st_lsm6dsx_shub_read(sensor, addr, &data, sizeof(data));
 395        if (err < 0)
 396                return err;
 397
 398        data = ((data & ~mask) | (val << __ffs(mask) & mask));
 399
 400        return st_lsm6dsx_shub_write(sensor, addr, &data, sizeof(data));
 401}
 402
 403static int
 404st_lsm6dsx_shub_get_odr_val(struct st_lsm6dsx_sensor *sensor,
 405                            u32 odr, u16 *val)
 406{
 407        const struct st_lsm6dsx_ext_dev_settings *settings;
 408        int i;
 409
 410        settings = sensor->ext_info.settings;
 411        for (i = 0; i < settings->odr_table.odr_len; i++) {
 412                if (settings->odr_table.odr_avl[i].milli_hz == odr)
 413                        break;
 414        }
 415
 416        if (i == settings->odr_table.odr_len)
 417                return -EINVAL;
 418
 419        *val = settings->odr_table.odr_avl[i].val;
 420        return 0;
 421}
 422
 423static int
 424st_lsm6dsx_shub_set_odr(struct st_lsm6dsx_sensor *sensor, u32 odr)
 425{
 426        const struct st_lsm6dsx_ext_dev_settings *settings;
 427        u16 val;
 428        int err;
 429
 430        err = st_lsm6dsx_shub_get_odr_val(sensor, odr, &val);
 431        if (err < 0)
 432                return err;
 433
 434        settings = sensor->ext_info.settings;
 435        return st_lsm6dsx_shub_write_with_mask(sensor,
 436                                               settings->odr_table.reg.addr,
 437                                               settings->odr_table.reg.mask,
 438                                               val);
 439}
 440
 441/* use SLV{1,2,3} for FIFO read operations */
 442static int
 443st_lsm6dsx_shub_config_channels(struct st_lsm6dsx_sensor *sensor,
 444                                bool enable)
 445{
 446        const struct st_lsm6dsx_shub_settings *hub_settings;
 447        const struct st_lsm6dsx_ext_dev_settings *settings;
 448        u8 config[9] = {}, enable_mask, slv_addr;
 449        struct st_lsm6dsx_hw *hw = sensor->hw;
 450        struct st_lsm6dsx_sensor *cur_sensor;
 451        int i, j = 0;
 452
 453        hub_settings = &hw->settings->shub_settings;
 454        if (enable)
 455                enable_mask = hw->enable_mask | BIT(sensor->id);
 456        else
 457                enable_mask = hw->enable_mask & ~BIT(sensor->id);
 458
 459        for (i = ST_LSM6DSX_ID_EXT0; i <= ST_LSM6DSX_ID_EXT2; i++) {
 460                if (!hw->iio_devs[i])
 461                        continue;
 462
 463                cur_sensor = iio_priv(hw->iio_devs[i]);
 464                if (!(enable_mask & BIT(cur_sensor->id)))
 465                        continue;
 466
 467                settings = cur_sensor->ext_info.settings;
 468                config[j] = (sensor->ext_info.addr << 1) | 1;
 469                config[j + 1] = settings->out.addr;
 470                config[j + 2] = (settings->out.len & ST_LS6DSX_READ_OP_MASK) |
 471                                hub_settings->batch_en;
 472                j += 3;
 473        }
 474
 475        slv_addr = ST_LSM6DSX_SLV_ADDR(1, hub_settings->slv0_addr);
 476        return st_lsm6dsx_shub_write_reg(hw, slv_addr, config,
 477                                         sizeof(config));
 478}
 479
 480int st_lsm6dsx_shub_set_enable(struct st_lsm6dsx_sensor *sensor, bool enable)
 481{
 482        const struct st_lsm6dsx_ext_dev_settings *settings;
 483        int err;
 484
 485        err = st_lsm6dsx_shub_config_channels(sensor, enable);
 486        if (err < 0)
 487                return err;
 488
 489        settings = sensor->ext_info.settings;
 490        if (enable) {
 491                err = st_lsm6dsx_shub_set_odr(sensor,
 492                                              sensor->ext_info.slv_odr);
 493                if (err < 0)
 494                        return err;
 495        } else {
 496                err = st_lsm6dsx_shub_write_with_mask(sensor,
 497                                        settings->odr_table.reg.addr,
 498                                        settings->odr_table.reg.mask, 0);
 499                if (err < 0)
 500                        return err;
 501        }
 502
 503        if (settings->pwr_table.reg.addr) {
 504                u8 val;
 505
 506                val = enable ? settings->pwr_table.on_val
 507                             : settings->pwr_table.off_val;
 508                err = st_lsm6dsx_shub_write_with_mask(sensor,
 509                                        settings->pwr_table.reg.addr,
 510                                        settings->pwr_table.reg.mask, val);
 511                if (err < 0)
 512                        return err;
 513        }
 514
 515        return st_lsm6dsx_shub_master_enable(sensor, enable);
 516}
 517
 518static int
 519st_lsm6dsx_shub_read_oneshot(struct st_lsm6dsx_sensor *sensor,
 520                             struct iio_chan_spec const *ch,
 521                             int *val)
 522{
 523        int err, delay, len;
 524        u8 data[4];
 525
 526        err = st_lsm6dsx_shub_set_enable(sensor, true);
 527        if (err < 0)
 528                return err;
 529
 530        delay = 1000000000 / sensor->ext_info.slv_odr;
 531        usleep_range(delay, 2 * delay);
 532
 533        len = min_t(int, sizeof(data), ch->scan_type.realbits >> 3);
 534        err = st_lsm6dsx_shub_read(sensor, ch->address, data, len);
 535        if (err < 0)
 536                return err;
 537
 538        err = st_lsm6dsx_shub_set_enable(sensor, false);
 539        if (err < 0)
 540                return err;
 541
 542        switch (len) {
 543        case 2:
 544                *val = (s16)le16_to_cpu(*((__le16 *)data));
 545                break;
 546        default:
 547                return -EINVAL;
 548        }
 549
 550        return IIO_VAL_INT;
 551}
 552
 553static int
 554st_lsm6dsx_shub_read_raw(struct iio_dev *iio_dev,
 555                         struct iio_chan_spec const *ch,
 556                         int *val, int *val2, long mask)
 557{
 558        struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
 559        int ret;
 560
 561        switch (mask) {
 562        case IIO_CHAN_INFO_RAW:
 563                ret = iio_device_claim_direct_mode(iio_dev);
 564                if (ret)
 565                        break;
 566
 567                ret = st_lsm6dsx_shub_read_oneshot(sensor, ch, val);
 568                iio_device_release_direct_mode(iio_dev);
 569                break;
 570        case IIO_CHAN_INFO_SAMP_FREQ:
 571                *val = sensor->ext_info.slv_odr / 1000;
 572                *val2 = (sensor->ext_info.slv_odr % 1000) * 1000;
 573                ret = IIO_VAL_INT_PLUS_MICRO;
 574                break;
 575        case IIO_CHAN_INFO_SCALE:
 576                *val = 0;
 577                *val2 = sensor->gain;
 578                ret = IIO_VAL_INT_PLUS_MICRO;
 579                break;
 580        default:
 581                ret = -EINVAL;
 582                break;
 583        }
 584
 585        return ret;
 586}
 587
 588static int
 589st_lsm6dsx_shub_set_full_scale(struct st_lsm6dsx_sensor *sensor,
 590                               u32 gain)
 591{
 592        const struct st_lsm6dsx_fs_table_entry *fs_table;
 593        int i, err;
 594
 595        fs_table = &sensor->ext_info.settings->fs_table;
 596        if (!fs_table->reg.addr)
 597                return -ENOTSUPP;
 598
 599        for (i = 0; i < fs_table->fs_len; i++) {
 600                if (fs_table->fs_avl[i].gain == gain)
 601                        break;
 602        }
 603
 604        if (i == fs_table->fs_len)
 605                return -EINVAL;
 606
 607        err = st_lsm6dsx_shub_write_with_mask(sensor, fs_table->reg.addr,
 608                                              fs_table->reg.mask,
 609                                              fs_table->fs_avl[i].val);
 610        if (err < 0)
 611                return err;
 612
 613        sensor->gain = gain;
 614
 615        return 0;
 616}
 617
 618static int
 619st_lsm6dsx_shub_write_raw(struct iio_dev *iio_dev,
 620                          struct iio_chan_spec const *chan,
 621                          int val, int val2, long mask)
 622{
 623        struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
 624        int err;
 625
 626        err = iio_device_claim_direct_mode(iio_dev);
 627        if (err)
 628                return err;
 629
 630        switch (mask) {
 631        case IIO_CHAN_INFO_SAMP_FREQ: {
 632                u16 data;
 633
 634                val = val * 1000 + val2 / 1000;
 635                err = st_lsm6dsx_shub_get_odr_val(sensor, val, &data);
 636                if (!err) {
 637                        struct st_lsm6dsx_hw *hw = sensor->hw;
 638                        struct st_lsm6dsx_sensor *ref_sensor;
 639                        u8 odr_val;
 640                        int odr;
 641
 642                        ref_sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
 643                        odr = st_lsm6dsx_check_odr(ref_sensor, val, &odr_val);
 644                        if (odr < 0) {
 645                                err = odr;
 646                                goto release;
 647                        }
 648
 649                        sensor->ext_info.slv_odr = val;
 650                        sensor->odr = odr;
 651                }
 652                break;
 653        }
 654        case IIO_CHAN_INFO_SCALE:
 655                err = st_lsm6dsx_shub_set_full_scale(sensor, val2);
 656                break;
 657        default:
 658                err = -EINVAL;
 659                break;
 660        }
 661
 662release:
 663        iio_device_release_direct_mode(iio_dev);
 664
 665        return err;
 666}
 667
 668static ssize_t
 669st_lsm6dsx_shub_sampling_freq_avail(struct device *dev,
 670                                    struct device_attribute *attr,
 671                                    char *buf)
 672{
 673        struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev));
 674        const struct st_lsm6dsx_ext_dev_settings *settings;
 675        int i, len = 0;
 676
 677        settings = sensor->ext_info.settings;
 678        for (i = 0; i < settings->odr_table.odr_len; i++) {
 679                u32 val = settings->odr_table.odr_avl[i].milli_hz;
 680
 681                len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%03d ",
 682                                 val / 1000, val % 1000);
 683        }
 684        buf[len - 1] = '\n';
 685
 686        return len;
 687}
 688
 689static ssize_t st_lsm6dsx_shub_scale_avail(struct device *dev,
 690                                           struct device_attribute *attr,
 691                                           char *buf)
 692{
 693        struct st_lsm6dsx_sensor *sensor = iio_priv(dev_get_drvdata(dev));
 694        const struct st_lsm6dsx_ext_dev_settings *settings;
 695        int i, len = 0;
 696
 697        settings = sensor->ext_info.settings;
 698        for (i = 0; i < settings->fs_table.fs_len; i++)
 699                len += scnprintf(buf + len, PAGE_SIZE - len, "0.%06u ",
 700                                 settings->fs_table.fs_avl[i].gain);
 701        buf[len - 1] = '\n';
 702
 703        return len;
 704}
 705
 706static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(st_lsm6dsx_shub_sampling_freq_avail);
 707static IIO_DEVICE_ATTR(in_scale_available, 0444,
 708                       st_lsm6dsx_shub_scale_avail, NULL, 0);
 709static struct attribute *st_lsm6dsx_ext_attributes[] = {
 710        &iio_dev_attr_sampling_frequency_available.dev_attr.attr,
 711        &iio_dev_attr_in_scale_available.dev_attr.attr,
 712        NULL,
 713};
 714
 715static const struct attribute_group st_lsm6dsx_ext_attribute_group = {
 716        .attrs = st_lsm6dsx_ext_attributes,
 717};
 718
 719static const struct iio_info st_lsm6dsx_ext_info = {
 720        .attrs = &st_lsm6dsx_ext_attribute_group,
 721        .read_raw = st_lsm6dsx_shub_read_raw,
 722        .write_raw = st_lsm6dsx_shub_write_raw,
 723        .hwfifo_set_watermark = st_lsm6dsx_set_watermark,
 724};
 725
 726static struct iio_dev *
 727st_lsm6dsx_shub_alloc_iiodev(struct st_lsm6dsx_hw *hw,
 728                             enum st_lsm6dsx_sensor_id id,
 729                             const struct st_lsm6dsx_ext_dev_settings *info,
 730                             u8 i2c_addr, const char *name)
 731{
 732        enum st_lsm6dsx_sensor_id ref_id = ST_LSM6DSX_ID_ACC;
 733        struct iio_chan_spec *ext_channels;
 734        struct st_lsm6dsx_sensor *sensor;
 735        struct iio_dev *iio_dev;
 736
 737        iio_dev = devm_iio_device_alloc(hw->dev, sizeof(*sensor));
 738        if (!iio_dev)
 739                return NULL;
 740
 741        iio_dev->modes = INDIO_DIRECT_MODE;
 742        iio_dev->info = &st_lsm6dsx_ext_info;
 743
 744        sensor = iio_priv(iio_dev);
 745        sensor->id = id;
 746        sensor->hw = hw;
 747        sensor->odr = hw->settings->odr_table[ref_id].odr_avl[0].milli_hz;
 748        sensor->ext_info.slv_odr = info->odr_table.odr_avl[0].milli_hz;
 749        sensor->gain = info->fs_table.fs_avl[0].gain;
 750        sensor->ext_info.settings = info;
 751        sensor->ext_info.addr = i2c_addr;
 752        sensor->watermark = 1;
 753
 754        switch (info->id) {
 755        case ST_LSM6DSX_ID_MAGN: {
 756                const struct iio_chan_spec magn_channels[] = {
 757                        ST_LSM6DSX_CHANNEL(IIO_MAGN, info->out.addr,
 758                                           IIO_MOD_X, 0),
 759                        ST_LSM6DSX_CHANNEL(IIO_MAGN, info->out.addr + 2,
 760                                           IIO_MOD_Y, 1),
 761                        ST_LSM6DSX_CHANNEL(IIO_MAGN, info->out.addr + 4,
 762                                           IIO_MOD_Z, 2),
 763                        IIO_CHAN_SOFT_TIMESTAMP(3),
 764                };
 765
 766                ext_channels = devm_kzalloc(hw->dev, sizeof(magn_channels),
 767                                            GFP_KERNEL);
 768                if (!ext_channels)
 769                        return NULL;
 770
 771                memcpy(ext_channels, magn_channels, sizeof(magn_channels));
 772                iio_dev->available_scan_masks = st_lsm6dsx_available_scan_masks;
 773                iio_dev->channels = ext_channels;
 774                iio_dev->num_channels = ARRAY_SIZE(magn_channels);
 775
 776                scnprintf(sensor->name, sizeof(sensor->name), "%s_magn",
 777                          name);
 778                break;
 779        }
 780        default:
 781                return NULL;
 782        }
 783        iio_dev->name = sensor->name;
 784
 785        return iio_dev;
 786}
 787
 788static int st_lsm6dsx_shub_init_device(struct st_lsm6dsx_sensor *sensor)
 789{
 790        const struct st_lsm6dsx_ext_dev_settings *settings;
 791        int err;
 792
 793        settings = sensor->ext_info.settings;
 794        if (settings->bdu.addr) {
 795                err = st_lsm6dsx_shub_write_with_mask(sensor,
 796                                                      settings->bdu.addr,
 797                                                      settings->bdu.mask, 1);
 798                if (err < 0)
 799                        return err;
 800        }
 801
 802        if (settings->temp_comp.addr) {
 803                err = st_lsm6dsx_shub_write_with_mask(sensor,
 804                                        settings->temp_comp.addr,
 805                                        settings->temp_comp.mask, 1);
 806                if (err < 0)
 807                        return err;
 808        }
 809
 810        if (settings->off_canc.addr) {
 811                err = st_lsm6dsx_shub_write_with_mask(sensor,
 812                                        settings->off_canc.addr,
 813                                        settings->off_canc.mask, 1);
 814                if (err < 0)
 815                        return err;
 816        }
 817
 818        return 0;
 819}
 820
 821static int
 822st_lsm6dsx_shub_check_wai(struct st_lsm6dsx_hw *hw, u8 *i2c_addr,
 823                          const struct st_lsm6dsx_ext_dev_settings *settings)
 824{
 825        const struct st_lsm6dsx_shub_settings *hub_settings;
 826        u8 config[3], data, slv_addr, slv_config = 0;
 827        const struct st_lsm6dsx_reg *aux_sens;
 828        struct st_lsm6dsx_sensor *sensor;
 829        bool found = false;
 830        int i, err;
 831
 832        sensor = iio_priv(hw->iio_devs[ST_LSM6DSX_ID_ACC]);
 833        hub_settings = &hw->settings->shub_settings;
 834        aux_sens = &hw->settings->shub_settings.aux_sens;
 835        slv_addr = ST_LSM6DSX_SLV_ADDR(0, hub_settings->slv0_addr);
 836        /* do not overwrite aux_sens */
 837        if (slv_addr + 2 == aux_sens->addr)
 838                slv_config = ST_LSM6DSX_SHIFT_VAL(3, aux_sens->mask);
 839
 840        for (i = 0; i < ARRAY_SIZE(settings->i2c_addr); i++) {
 841                if (!settings->i2c_addr[i])
 842                        continue;
 843
 844                /* read wai slave register */
 845                config[0] = (settings->i2c_addr[i] << 1) | 0x1;
 846                config[1] = settings->wai.addr;
 847                config[2] = 0x1 | slv_config;
 848
 849                err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config,
 850                                                sizeof(config));
 851                if (err < 0)
 852                        return err;
 853
 854                err = st_lsm6dsx_shub_master_enable(sensor, true);
 855                if (err < 0)
 856                        return err;
 857
 858                st_lsm6dsx_shub_wait_complete(hw);
 859
 860                err = st_lsm6dsx_shub_read_output(hw, &data, sizeof(data));
 861
 862                st_lsm6dsx_shub_master_enable(sensor, false);
 863
 864                if (err < 0)
 865                        return err;
 866
 867                if (data != settings->wai.val)
 868                        continue;
 869
 870                *i2c_addr = settings->i2c_addr[i];
 871                found = true;
 872                break;
 873        }
 874
 875        /* reset SLV0 channel */
 876        config[0] = hub_settings->pause;
 877        config[1] = 0;
 878        config[2] = slv_config;
 879        err = st_lsm6dsx_shub_write_reg(hw, slv_addr, config,
 880                                        sizeof(config));
 881        if (err < 0)
 882                return err;
 883
 884        return found ? 0 : -ENODEV;
 885}
 886
 887int st_lsm6dsx_shub_probe(struct st_lsm6dsx_hw *hw, const char *name)
 888{
 889        enum st_lsm6dsx_sensor_id id = ST_LSM6DSX_ID_EXT0;
 890        struct st_lsm6dsx_sensor *sensor;
 891        int err, i, num_ext_dev = 0;
 892        u8 i2c_addr = 0;
 893
 894        for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_ext_dev_table); i++) {
 895                err = st_lsm6dsx_shub_check_wai(hw, &i2c_addr,
 896                                        &st_lsm6dsx_ext_dev_table[i]);
 897                if (err == -ENODEV)
 898                        continue;
 899                else if (err < 0)
 900                        return err;
 901
 902                hw->iio_devs[id] = st_lsm6dsx_shub_alloc_iiodev(hw, id,
 903                                                &st_lsm6dsx_ext_dev_table[i],
 904                                                i2c_addr, name);
 905                if (!hw->iio_devs[id])
 906                        return -ENOMEM;
 907
 908                sensor = iio_priv(hw->iio_devs[id]);
 909                err = st_lsm6dsx_shub_init_device(sensor);
 910                if (err < 0)
 911                        return err;
 912
 913                if (++num_ext_dev >= hw->settings->shub_settings.num_ext_dev)
 914                        break;
 915                id++;
 916        }
 917
 918        return 0;
 919}
 920