/*
* STMicroelectronics st_lsm6dsx i2c controller driver
*
* i2c controller embedded in lsm6dx series can connect up to four
* slave devices using accelerometer sensor as trigger for i2c
* read/write operations. Current implementation relies on SLV0 channel
* for slave configuration and SLV{1,2,3} to read data and push them into
* the hw FIFO
*
* Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/bitfield.h>
#include "st_lsm6dsx.h"
#define ST_LSM6DSX_SLV_ADDR(n, base) ((base) + (n) * 3)
#define ST_LSM6DSX_SLV_SUB_ADDR(n, base) ((base) + 1 + (n) * 3)
#define ST_LSM6DSX_SLV_CONFIG(n, base) ((base) + 2 + (n) * 3)
#define ST_LS6DSX_READ_OP_MASK GENMASK(2, 0)
static const struct st_lsm6dsx_ext_dev_settings st_lsm6dsx_ext_dev_table[] = {
/* LIS2MDL */
{
.i2c_addr = { 0x1e },
.wai = {
.addr = 0x4f,
.val = 0x40,
},
.id = ST_LSM6DSX_ID_MAGN,
.odr_table = {
.reg = {
.addr = 0x60,
.mask = GENMASK(3, 2),
},
.odr_avl[0] = { 10000, 0x0 },
.odr_avl[1] = { 20000, 0x1 },
.odr_avl[2] = { 50000, 0x2 },
.odr_avl[3] = { 100000, 0x3 },
.odr_len = 4,
},
.fs_table = {
.fs_avl[0] = {
.gain = 1500,
.val = 0x0,
}, /* 1500 uG/LSB */
.fs_len = 1,
},
.temp_comp = {
.addr = 0x60,
.mask = BIT(7),
},
.pwr_table = {
.reg = {
.addr = 0x60,
.mask = GENMASK(1, 0),
},
.off_val = 0x2,
.on_val = 0x0,
},
.off_canc = {
.addr = 0x61,
.mask = BIT(1),
},
.bdu = {
.addr = 0x62,
.mask = BIT(4),
},
.out = {
.addr = 0x68,
.len = 6,
},
},
/* LIS3MDL */
{
.i2c_addr = { 0x1e },
.wai = {
.addr = 0x0f,
.val = 0x3d,
},
.id = ST_LSM6DSX_ID_MAGN,
.odr_table = {
.reg = {
.addr = 0x20,
.mask = GENMASK(4, 2),
},
.odr_avl[0] = { 1000, 0x0 },
.odr_avl[1] = { 2000, 0x1 },
.odr_avl[2] = { 3000, 0x2 },
.odr_avl[3] = { 5000, 0x3 },
.odr_avl[4] = { 10000, 0x4 },
.odr_avl[5] = { 20000, 0x5 },
.odr_avl[6] = { 40000, 0x6 },
.odr_avl[7] = { 80000, 0x7 },
.odr_len = 8,
},
.fs_table = {
.reg = {
.addr = 0x21,
.mask = GENMASK(6, 5),
},
.fs_avl[0] = {
.gain = 146,
.val = 0x00,
}, /* 4000 uG/LSB */
.fs_avl[1] = {
.gain = 292,
.val = 0x01,
}, /* 8000 uG/LSB */
.fs_avl[2] = {
.gain = 438,
.val = 0x02,
}, /* 12000 uG/LSB */
.fs_avl[3] = {
.gain = 584,
.val = 0x03,
}, /* 16000 uG/LSB */
.fs_len = 4,
},
.pwr_table = {
.reg = {
.addr = 0x22,
.mask = GENMASK(1, 0),
},
.off_val = 0x2,
.on_val = 0x0,
},
.bdu = {
.addr = 0x24,
.mask = BIT(6),
},
.out = {
.addr = 0x28,
.len<