* [PATCH v3 1/4] iio: imu: inv-mpu6050: Fix interrupt pin configuration
2016-02-09 15:38 [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
@ 2016-02-09 15:38 ` Adriana Reus
2016-02-09 15:38 ` [PATCH v3 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions Adriana Reus
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Adriana Reus @ 2016-02-09 15:38 UTC (permalink / raw)
To: jic23
Cc: linux-iio, srinivas.pandruvada, ggao, daniel.baluta, mwelling,
lucas.de.marchi, adi.reus, Adriana Reus
The select/deselect_bypass duo writes the irq number into the interrupt
configuration register.
If there is a i2c slave device connected to the mpu (eg. a magnetometer)
then this can hinder interrupt delivery for the accelerometer and
gyroscope.
Set this register to the default configuration.
Signed-off-by: Adriana Reus <adriana.reus@intel.com>
---
* No changes since v2
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 4 ++--
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 0852b7f..1121f4e 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -129,7 +129,7 @@ static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
if (!ret) {
st->powerup_count++;
ret = inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg,
- st->client->irq |
+ INV_MPU6050_INT_PIN_CFG |
INV_MPU6050_BIT_BYPASS_EN);
}
write_error:
@@ -147,7 +147,7 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
mutex_lock(&indio_dev->mlock);
/* It doesn't really mattter, if any of the calls fails */
inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg,
- st->client->irq);
+ INV_MPU6050_INT_PIN_CFG);
st->powerup_count--;
if (!st->powerup_count)
inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1,
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index db0a4a2..455b99d 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -185,6 +185,7 @@ struct inv_mpu6050_state {
#define INV_MPU6050_REG_INT_PIN_CFG 0x37
#define INV_MPU6050_BIT_BYPASS_EN 0x2
+#define INV_MPU6050_INT_PIN_CFG 0
/* init parameters */
#define INV_MPU6050_INIT_FIFO_RATE 50
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions
2016-02-09 15:38 [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
2016-02-09 15:38 ` [PATCH v3 1/4] iio: imu: inv-mpu6050: Fix interrupt pin configuration Adriana Reus
@ 2016-02-09 15:38 ` Adriana Reus
2016-02-10 9:57 ` Crt Mori
2016-02-09 15:38 ` [PATCH v3 3/4] iio: imu: inv_mpu6050: Separate driver into core and i2c functionality Adriana Reus
` (3 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: Adriana Reus @ 2016-02-09 15:38 UTC (permalink / raw)
To: jic23
Cc: linux-iio, srinivas.pandruvada, ggao, daniel.baluta, mwelling,
lucas.de.marchi, adi.reus, Adriana Reus
Use regmap instead of i2c specific functions.
This is in preparation of splitting this driver into core and
i2c specific functionality.
Signed-off-by: Adriana Reus <adriana.reus@intel.com>
---
* No changes since v2
drivers/iio/imu/inv_mpu6050/Kconfig | 1 +
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 71 ++++++++++++++-------------
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 +
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 30 ++++++-----
drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 6 +--
5 files changed, 57 insertions(+), 53 deletions(-)
diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
index 48fbc0b..f301f3a 100644
--- a/drivers/iio/imu/inv_mpu6050/Kconfig
+++ b/drivers/iio/imu/inv_mpu6050/Kconfig
@@ -8,6 +8,7 @@ config INV_MPU6050_IIO
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select I2C_MUX
+ select REGMAP_I2C
help
This driver supports the Invensense MPU6050 devices.
This driver can also support MPU6500 in MPU6050 compatibility mode
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 1121f4e..151a378 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -27,6 +27,11 @@
#include <linux/acpi.h>
#include "inv_mpu_iio.h"
+static const struct regmap_config inv_mpu_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
/*
* this is the gyro scale translated from dynamic range plus/minus
* {250, 500, 1000, 2000} to rad/s
@@ -75,11 +80,6 @@ static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = {
},
};
-int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d)
-{
- return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d);
-}
-
/*
* The i2c read/write needs to happen in unlocked mode. As the parent
* adapter is common. If we use locked versions, it will fail as
@@ -159,16 +159,15 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
{
- u8 d, mgmt_1;
+ unsigned int d, mgmt_1;
int result;
/* switch clock needs to be careful. Only when gyro is on, can
clock source be switched to gyro. Otherwise, it must be set to
internal clock */
if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
- result = i2c_smbus_read_i2c_block_data(st->client,
- st->reg->pwr_mgmt_1, 1, &mgmt_1);
- if (result != 1)
+ result = regmap_read(st->map, st->reg->pwr_mgmt_1, &mgmt_1);
+ if (result)
return result;
mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK;
@@ -178,20 +177,19 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
/* turning off gyro requires switch to internal clock first.
Then turn off gyro engine */
mgmt_1 |= INV_CLK_INTERNAL;
- result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, mgmt_1);
+ result = regmap_write(st->map, st->reg->pwr_mgmt_1, mgmt_1);
if (result)
return result;
}
- result = i2c_smbus_read_i2c_block_data(st->client,
- st->reg->pwr_mgmt_2, 1, &d);
- if (result != 1)
+ result = regmap_read(st->map, st->reg->pwr_mgmt_2, &d);
+ if (result)
return result;
if (en)
d &= ~mask;
else
d |= mask;
- result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_2, d);
+ result = regmap_write(st->map, st->reg->pwr_mgmt_2, d);
if (result)
return result;
@@ -201,7 +199,7 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
/* switch internal clock to PLL */
mgmt_1 |= INV_CLK_PLL;
- result = inv_mpu6050_write_reg(st,
+ result = regmap_write(st->map,
st->reg->pwr_mgmt_1, mgmt_1);
if (result)
return result;
@@ -218,15 +216,14 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
if (power_on) {
/* Already under indio-dev->mlock mutex */
if (!st->powerup_count)
- result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
- 0);
+ result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
if (!result)
st->powerup_count++;
} else {
st->powerup_count--;
if (!st->powerup_count)
- result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
- INV_MPU6050_BIT_SLEEP);
+ result = regmap_write(st->map, st->reg->pwr_mgmt_1,
+ INV_MPU6050_BIT_SLEEP);
}
if (result)
@@ -257,22 +254,22 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
if (result)
return result;
d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
- result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d);
+ result = regmap_write(st->map, st->reg->gyro_config, d);
if (result)
return result;
d = INV_MPU6050_FILTER_20HZ;
- result = inv_mpu6050_write_reg(st, st->reg->lpf, d);
+ result = regmap_write(st->map, st->reg->lpf, d);
if (result)
return result;
d = INV_MPU6050_ONE_K_HZ / INV_MPU6050_INIT_FIFO_RATE - 1;
- result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
+ result = regmap_write(st->map, st->reg->sample_rate_div, d);
if (result)
return result;
d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
- result = inv_mpu6050_write_reg(st, st->reg->accl_config, d);
+ result = regmap_write(st->map, st->reg->accl_config, d);
if (result)
return result;
@@ -290,9 +287,8 @@ static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg,
__be16 d;
ind = (axis - IIO_MOD_X) * 2;
- result = i2c_smbus_read_i2c_block_data(st->client, reg + ind, 2,
- (u8 *)&d);
- if (result != 2)
+ result = regmap_bulk_read(st->map, reg + ind, (u8 *)&d, 2);
+ if (result)
return -EINVAL;
*val = (short)be16_to_cpup(&d);
@@ -418,8 +414,7 @@ static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val)
for (i = 0; i < ARRAY_SIZE(gyro_scale_6050); ++i) {
if (gyro_scale_6050[i] == val) {
d = (i << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
- result = inv_mpu6050_write_reg(st,
- st->reg->gyro_config, d);
+ result = regmap_write(st->map, st->reg->gyro_config, d);
if (result)
return result;
@@ -456,8 +451,7 @@ static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val)
for (i = 0; i < ARRAY_SIZE(accel_scale); ++i) {
if (accel_scale[i] == val) {
d = (i << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
- result = inv_mpu6050_write_reg(st,
- st->reg->accl_config, d);
+ result = regmap_write(st->map, st->reg->accl_config, d);
if (result)
return result;
@@ -537,7 +531,7 @@ static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
i++;
data = d[i];
- result = inv_mpu6050_write_reg(st, st->reg->lpf, data);
+ result = regmap_write(st->map, st->reg->lpf, data);
if (result)
return result;
st->chip_config.lpf = data;
@@ -575,7 +569,7 @@ static ssize_t inv_mpu6050_fifo_rate_store(struct device *dev,
goto fifo_rate_fail;
d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
- result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
+ result = regmap_write(st->map, st->reg->sample_rate_div, d);
if (result)
goto fifo_rate_fail;
st->chip_config.fifo_rate = fifo_rate;
@@ -736,8 +730,8 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
st->reg = hw_info[st->chip_type].reg;
/* reset to make sure previous state are not there */
- result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
- INV_MPU6050_BIT_H_RESET);
+ result = regmap_write(st->map, st->reg->pwr_mgmt_1,
+ INV_MPU6050_BIT_H_RESET);
if (result)
return result;
msleep(INV_MPU6050_POWER_UP_TIME);
@@ -778,11 +772,19 @@ static int inv_mpu_probe(struct i2c_client *client,
struct iio_dev *indio_dev;
struct inv_mpu6050_platform_data *pdata;
int result;
+ struct regmap *regmap;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_I2C_BLOCK))
return -ENOSYS;
+ regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+ (int)PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -790,6 +792,7 @@ static int inv_mpu_probe(struct i2c_client *client,
st = iio_priv(indio_dev);
st->client = client;
st->powerup_count = 0;
+ st->map = regmap;
pdata = dev_get_platdata(&client->dev);
if (pdata)
st->plat_data = *pdata;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 455b99d..469cd1f 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -15,6 +15,7 @@
#include <linux/spinlock.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
+#include <linux/regmap.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
@@ -125,6 +126,7 @@ struct inv_mpu6050_state {
unsigned int powerup_count;
struct inv_mpu6050_platform_data plat_data;
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
+ struct regmap *map;
};
/*register and associated bit definition*/
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index ba27e27..eb19dae 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/sysfs.h>
@@ -41,22 +40,22 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
struct inv_mpu6050_state *st = iio_priv(indio_dev);
/* disable interrupt */
- result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
+ result = regmap_write(st->map, st->reg->int_enable, 0);
if (result) {
dev_err(&st->client->dev, "int_enable failed %d\n", result);
return result;
}
/* disable the sensor output to FIFO */
- result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
+ result = regmap_write(st->map, st->reg->fifo_en, 0);
if (result)
goto reset_fifo_fail;
/* disable fifo reading */
- result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
+ result = regmap_write(st->map, st->reg->user_ctrl, 0);
if (result)
goto reset_fifo_fail;
/* reset FIFO*/
- result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
+ result = regmap_write(st->map, st->reg->user_ctrl,
INV_MPU6050_BIT_FIFO_RST);
if (result)
goto reset_fifo_fail;
@@ -67,13 +66,13 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
/* enable interrupt */
if (st->chip_config.accl_fifo_enable ||
st->chip_config.gyro_fifo_enable) {
- result = inv_mpu6050_write_reg(st, st->reg->int_enable,
+ result = regmap_write(st->map, st->reg->int_enable,
INV_MPU6050_BIT_DATA_RDY_EN);
if (result)
return result;
}
/* enable FIFO reading and I2C master interface*/
- result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
+ result = regmap_write(st->map, st->reg->user_ctrl,
INV_MPU6050_BIT_FIFO_EN);
if (result)
goto reset_fifo_fail;
@@ -83,7 +82,7 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
d |= INV_MPU6050_BITS_GYRO_OUT;
if (st->chip_config.accl_fifo_enable)
d |= INV_MPU6050_BIT_ACCEL_OUT;
- result = inv_mpu6050_write_reg(st, st->reg->fifo_en, d);
+ result = regmap_write(st->map, st->reg->fifo_en, d);
if (result)
goto reset_fifo_fail;
@@ -91,7 +90,7 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
reset_fifo_fail:
dev_err(&st->client->dev, "reset fifo failed %d\n", result);
- result = inv_mpu6050_write_reg(st, st->reg->int_enable,
+ result = regmap_write(st->map, st->reg->int_enable,
INV_MPU6050_BIT_DATA_RDY_EN);
return result;
@@ -143,10 +142,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
* read fifo_count register to know how many bytes inside FIFO
* right now
*/
- result = i2c_smbus_read_i2c_block_data(st->client,
+ result = regmap_bulk_read(st->map,
st->reg->fifo_count_h,
- INV_MPU6050_FIFO_COUNT_BYTE, data);
- if (result != INV_MPU6050_FIFO_COUNT_BYTE)
+ data, INV_MPU6050_FIFO_COUNT_BYTE);
+ if (result)
goto end_session;
fifo_count = be16_to_cpup((__be16 *)(&data[0]));
if (fifo_count < bytes_per_datum)
@@ -161,10 +160,9 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
goto flush_fifo;
while (fifo_count >= bytes_per_datum) {
- result = i2c_smbus_read_i2c_block_data(st->client,
- st->reg->fifo_r_w,
- bytes_per_datum, data);
- if (result != bytes_per_datum)
+ result = regmap_bulk_read(st->map, st->reg->fifo_r_w,
+ data, bytes_per_datum);
+ if (result)
goto flush_fifo;
result = kfifo_out(&st->timestamps, ×tamp, 1);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index 844610c..ee9e66d 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -65,15 +65,15 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
if (result)
return result;
} else {
- result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
+ result = regmap_write(st->map, st->reg->fifo_en, 0);
if (result)
return result;
- result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
+ result = regmap_write(st->map, st->reg->int_enable, 0);
if (result)
return result;
- result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
+ result = regmap_write(st->map, st->reg->user_ctrl, 0);
if (result)
return result;
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions
2016-02-09 15:38 ` [PATCH v3 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions Adriana Reus
@ 2016-02-10 9:57 ` Crt Mori
0 siblings, 0 replies; 9+ messages in thread
From: Crt Mori @ 2016-02-10 9:57 UTC (permalink / raw)
To: Adriana Reus
Cc: Johnathan Iain Cameron, linux-iio, Srinivas Pandruvada, ggao,
Daniel Baluta, mwelling, lucas.de.marchi, adi.reus
Well I have read this series few times and could not find anything
strange. I am also working on regmap driver and this seems like a nice
general way to go.
Acked-by: Crt Mori <cmo@melexis.com>
On 9 February 2016 at 16:38, Adriana Reus <adriana.reus@intel.com> wrote:
> Use regmap instead of i2c specific functions.
> This is in preparation of splitting this driver into core and
> i2c specific functionality.
>
> Signed-off-by: Adriana Reus <adriana.reus@intel.com>
> ---
> * No changes since v2
> drivers/iio/imu/inv_mpu6050/Kconfig | 1 +
> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 71 ++++++++++++++-------------
> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 2 +
> drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 30 ++++++-----
> drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 6 +--
> 5 files changed, 57 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
> index 48fbc0b..f301f3a 100644
> --- a/drivers/iio/imu/inv_mpu6050/Kconfig
> +++ b/drivers/iio/imu/inv_mpu6050/Kconfig
> @@ -8,6 +8,7 @@ config INV_MPU6050_IIO
> select IIO_BUFFER
> select IIO_TRIGGERED_BUFFER
> select I2C_MUX
> + select REGMAP_I2C
> help
> This driver supports the Invensense MPU6050 devices.
> This driver can also support MPU6500 in MPU6050 compatibility mode
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 1121f4e..151a378 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -27,6 +27,11 @@
> #include <linux/acpi.h>
> #include "inv_mpu_iio.h"
>
> +static const struct regmap_config inv_mpu_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +};
> +
> /*
> * this is the gyro scale translated from dynamic range plus/minus
> * {250, 500, 1000, 2000} to rad/s
> @@ -75,11 +80,6 @@ static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = {
> },
> };
>
> -int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d)
> -{
> - return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d);
> -}
> -
> /*
> * The i2c read/write needs to happen in unlocked mode. As the parent
> * adapter is common. If we use locked versions, it will fail as
> @@ -159,16 +159,15 @@ static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
>
> int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
> {
> - u8 d, mgmt_1;
> + unsigned int d, mgmt_1;
> int result;
>
> /* switch clock needs to be careful. Only when gyro is on, can
> clock source be switched to gyro. Otherwise, it must be set to
> internal clock */
> if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
> - result = i2c_smbus_read_i2c_block_data(st->client,
> - st->reg->pwr_mgmt_1, 1, &mgmt_1);
> - if (result != 1)
> + result = regmap_read(st->map, st->reg->pwr_mgmt_1, &mgmt_1);
> + if (result)
> return result;
>
> mgmt_1 &= ~INV_MPU6050_BIT_CLK_MASK;
> @@ -178,20 +177,19 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
> /* turning off gyro requires switch to internal clock first.
> Then turn off gyro engine */
> mgmt_1 |= INV_CLK_INTERNAL;
> - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, mgmt_1);
> + result = regmap_write(st->map, st->reg->pwr_mgmt_1, mgmt_1);
> if (result)
> return result;
> }
>
> - result = i2c_smbus_read_i2c_block_data(st->client,
> - st->reg->pwr_mgmt_2, 1, &d);
> - if (result != 1)
> + result = regmap_read(st->map, st->reg->pwr_mgmt_2, &d);
> + if (result)
> return result;
> if (en)
> d &= ~mask;
> else
> d |= mask;
> - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_2, d);
> + result = regmap_write(st->map, st->reg->pwr_mgmt_2, d);
> if (result)
> return result;
>
> @@ -201,7 +199,7 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
> if (INV_MPU6050_BIT_PWR_GYRO_STBY == mask) {
> /* switch internal clock to PLL */
> mgmt_1 |= INV_CLK_PLL;
> - result = inv_mpu6050_write_reg(st,
> + result = regmap_write(st->map,
> st->reg->pwr_mgmt_1, mgmt_1);
> if (result)
> return result;
> @@ -218,15 +216,14 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
> if (power_on) {
> /* Already under indio-dev->mlock mutex */
> if (!st->powerup_count)
> - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
> - 0);
> + result = regmap_write(st->map, st->reg->pwr_mgmt_1, 0);
> if (!result)
> st->powerup_count++;
> } else {
> st->powerup_count--;
> if (!st->powerup_count)
> - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
> - INV_MPU6050_BIT_SLEEP);
> + result = regmap_write(st->map, st->reg->pwr_mgmt_1,
> + INV_MPU6050_BIT_SLEEP);
> }
>
> if (result)
> @@ -257,22 +254,22 @@ static int inv_mpu6050_init_config(struct iio_dev *indio_dev)
> if (result)
> return result;
> d = (INV_MPU6050_FSR_2000DPS << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
> - result = inv_mpu6050_write_reg(st, st->reg->gyro_config, d);
> + result = regmap_write(st->map, st->reg->gyro_config, d);
> if (result)
> return result;
>
> d = INV_MPU6050_FILTER_20HZ;
> - result = inv_mpu6050_write_reg(st, st->reg->lpf, d);
> + result = regmap_write(st->map, st->reg->lpf, d);
> if (result)
> return result;
>
> d = INV_MPU6050_ONE_K_HZ / INV_MPU6050_INIT_FIFO_RATE - 1;
> - result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
> + result = regmap_write(st->map, st->reg->sample_rate_div, d);
> if (result)
> return result;
>
> d = (INV_MPU6050_FS_02G << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
> - result = inv_mpu6050_write_reg(st, st->reg->accl_config, d);
> + result = regmap_write(st->map, st->reg->accl_config, d);
> if (result)
> return result;
>
> @@ -290,9 +287,8 @@ static int inv_mpu6050_sensor_show(struct inv_mpu6050_state *st, int reg,
> __be16 d;
>
> ind = (axis - IIO_MOD_X) * 2;
> - result = i2c_smbus_read_i2c_block_data(st->client, reg + ind, 2,
> - (u8 *)&d);
> - if (result != 2)
> + result = regmap_bulk_read(st->map, reg + ind, (u8 *)&d, 2);
> + if (result)
> return -EINVAL;
> *val = (short)be16_to_cpup(&d);
>
> @@ -418,8 +414,7 @@ static int inv_mpu6050_write_gyro_scale(struct inv_mpu6050_state *st, int val)
> for (i = 0; i < ARRAY_SIZE(gyro_scale_6050); ++i) {
> if (gyro_scale_6050[i] == val) {
> d = (i << INV_MPU6050_GYRO_CONFIG_FSR_SHIFT);
> - result = inv_mpu6050_write_reg(st,
> - st->reg->gyro_config, d);
> + result = regmap_write(st->map, st->reg->gyro_config, d);
> if (result)
> return result;
>
> @@ -456,8 +451,7 @@ static int inv_mpu6050_write_accel_scale(struct inv_mpu6050_state *st, int val)
> for (i = 0; i < ARRAY_SIZE(accel_scale); ++i) {
> if (accel_scale[i] == val) {
> d = (i << INV_MPU6050_ACCL_CONFIG_FSR_SHIFT);
> - result = inv_mpu6050_write_reg(st,
> - st->reg->accl_config, d);
> + result = regmap_write(st->map, st->reg->accl_config, d);
> if (result)
> return result;
>
> @@ -537,7 +531,7 @@ static int inv_mpu6050_set_lpf(struct inv_mpu6050_state *st, int rate)
> while ((h < hz[i]) && (i < ARRAY_SIZE(d) - 1))
> i++;
> data = d[i];
> - result = inv_mpu6050_write_reg(st, st->reg->lpf, data);
> + result = regmap_write(st->map, st->reg->lpf, data);
> if (result)
> return result;
> st->chip_config.lpf = data;
> @@ -575,7 +569,7 @@ static ssize_t inv_mpu6050_fifo_rate_store(struct device *dev,
> goto fifo_rate_fail;
>
> d = INV_MPU6050_ONE_K_HZ / fifo_rate - 1;
> - result = inv_mpu6050_write_reg(st, st->reg->sample_rate_div, d);
> + result = regmap_write(st->map, st->reg->sample_rate_div, d);
> if (result)
> goto fifo_rate_fail;
> st->chip_config.fifo_rate = fifo_rate;
> @@ -736,8 +730,8 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
> st->reg = hw_info[st->chip_type].reg;
>
> /* reset to make sure previous state are not there */
> - result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
> - INV_MPU6050_BIT_H_RESET);
> + result = regmap_write(st->map, st->reg->pwr_mgmt_1,
> + INV_MPU6050_BIT_H_RESET);
> if (result)
> return result;
> msleep(INV_MPU6050_POWER_UP_TIME);
> @@ -778,11 +772,19 @@ static int inv_mpu_probe(struct i2c_client *client,
> struct iio_dev *indio_dev;
> struct inv_mpu6050_platform_data *pdata;
> int result;
> + struct regmap *regmap;
>
> if (!i2c_check_functionality(client->adapter,
> I2C_FUNC_SMBUS_I2C_BLOCK))
> return -ENOSYS;
>
> + regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
> + if (IS_ERR(regmap)) {
> + dev_err(&client->dev, "Failed to register i2c regmap %d\n",
> + (int)PTR_ERR(regmap));
> + return PTR_ERR(regmap);
> + }
> +
> indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
> if (!indio_dev)
> return -ENOMEM;
> @@ -790,6 +792,7 @@ static int inv_mpu_probe(struct i2c_client *client,
> st = iio_priv(indio_dev);
> st->client = client;
> st->powerup_count = 0;
> + st->map = regmap;
> pdata = dev_get_platdata(&client->dev);
> if (pdata)
> st->plat_data = *pdata;
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> index 455b99d..469cd1f 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> @@ -15,6 +15,7 @@
> #include <linux/spinlock.h>
> #include <linux/iio/iio.h>
> #include <linux/iio/buffer.h>
> +#include <linux/regmap.h>
> #include <linux/iio/sysfs.h>
> #include <linux/iio/kfifo_buf.h>
> #include <linux/iio/trigger.h>
> @@ -125,6 +126,7 @@ struct inv_mpu6050_state {
> unsigned int powerup_count;
> struct inv_mpu6050_platform_data plat_data;
> DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
> + struct regmap *map;
> };
>
> /*register and associated bit definition*/
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
> index ba27e27..eb19dae 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
> @@ -13,7 +13,6 @@
>
> #include <linux/module.h>
> #include <linux/slab.h>
> -#include <linux/i2c.h>
> #include <linux/err.h>
> #include <linux/delay.h>
> #include <linux/sysfs.h>
> @@ -41,22 +40,22 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
> struct inv_mpu6050_state *st = iio_priv(indio_dev);
>
> /* disable interrupt */
> - result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
> + result = regmap_write(st->map, st->reg->int_enable, 0);
> if (result) {
> dev_err(&st->client->dev, "int_enable failed %d\n", result);
> return result;
> }
> /* disable the sensor output to FIFO */
> - result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
> + result = regmap_write(st->map, st->reg->fifo_en, 0);
> if (result)
> goto reset_fifo_fail;
> /* disable fifo reading */
> - result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
> + result = regmap_write(st->map, st->reg->user_ctrl, 0);
> if (result)
> goto reset_fifo_fail;
>
> /* reset FIFO*/
> - result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
> + result = regmap_write(st->map, st->reg->user_ctrl,
> INV_MPU6050_BIT_FIFO_RST);
> if (result)
> goto reset_fifo_fail;
> @@ -67,13 +66,13 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
> /* enable interrupt */
> if (st->chip_config.accl_fifo_enable ||
> st->chip_config.gyro_fifo_enable) {
> - result = inv_mpu6050_write_reg(st, st->reg->int_enable,
> + result = regmap_write(st->map, st->reg->int_enable,
> INV_MPU6050_BIT_DATA_RDY_EN);
> if (result)
> return result;
> }
> /* enable FIFO reading and I2C master interface*/
> - result = inv_mpu6050_write_reg(st, st->reg->user_ctrl,
> + result = regmap_write(st->map, st->reg->user_ctrl,
> INV_MPU6050_BIT_FIFO_EN);
> if (result)
> goto reset_fifo_fail;
> @@ -83,7 +82,7 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
> d |= INV_MPU6050_BITS_GYRO_OUT;
> if (st->chip_config.accl_fifo_enable)
> d |= INV_MPU6050_BIT_ACCEL_OUT;
> - result = inv_mpu6050_write_reg(st, st->reg->fifo_en, d);
> + result = regmap_write(st->map, st->reg->fifo_en, d);
> if (result)
> goto reset_fifo_fail;
>
> @@ -91,7 +90,7 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
>
> reset_fifo_fail:
> dev_err(&st->client->dev, "reset fifo failed %d\n", result);
> - result = inv_mpu6050_write_reg(st, st->reg->int_enable,
> + result = regmap_write(st->map, st->reg->int_enable,
> INV_MPU6050_BIT_DATA_RDY_EN);
>
> return result;
> @@ -143,10 +142,10 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
> * read fifo_count register to know how many bytes inside FIFO
> * right now
> */
> - result = i2c_smbus_read_i2c_block_data(st->client,
> + result = regmap_bulk_read(st->map,
> st->reg->fifo_count_h,
> - INV_MPU6050_FIFO_COUNT_BYTE, data);
> - if (result != INV_MPU6050_FIFO_COUNT_BYTE)
> + data, INV_MPU6050_FIFO_COUNT_BYTE);
> + if (result)
> goto end_session;
> fifo_count = be16_to_cpup((__be16 *)(&data[0]));
> if (fifo_count < bytes_per_datum)
> @@ -161,10 +160,9 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
> fifo_count / bytes_per_datum + INV_MPU6050_TIME_STAMP_TOR)
> goto flush_fifo;
> while (fifo_count >= bytes_per_datum) {
> - result = i2c_smbus_read_i2c_block_data(st->client,
> - st->reg->fifo_r_w,
> - bytes_per_datum, data);
> - if (result != bytes_per_datum)
> + result = regmap_bulk_read(st->map, st->reg->fifo_r_w,
> + data, bytes_per_datum);
> + if (result)
> goto flush_fifo;
>
> result = kfifo_out(&st->timestamps, ×tamp, 1);
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> index 844610c..ee9e66d 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
> @@ -65,15 +65,15 @@ static int inv_mpu6050_set_enable(struct iio_dev *indio_dev, bool enable)
> if (result)
> return result;
> } else {
> - result = inv_mpu6050_write_reg(st, st->reg->fifo_en, 0);
> + result = regmap_write(st->map, st->reg->fifo_en, 0);
> if (result)
> return result;
>
> - result = inv_mpu6050_write_reg(st, st->reg->int_enable, 0);
> + result = regmap_write(st->map, st->reg->int_enable, 0);
> if (result)
> return result;
>
> - result = inv_mpu6050_write_reg(st, st->reg->user_ctrl, 0);
> + result = regmap_write(st->map, st->reg->user_ctrl, 0);
> if (result)
> return result;
>
> --
> 1.9.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 3/4] iio: imu: inv_mpu6050: Separate driver into core and i2c functionality.
2016-02-09 15:38 [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
2016-02-09 15:38 ` [PATCH v3 1/4] iio: imu: inv-mpu6050: Fix interrupt pin configuration Adriana Reus
2016-02-09 15:38 ` [PATCH v3 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions Adriana Reus
@ 2016-02-09 15:38 ` Adriana Reus
2016-02-09 15:38 ` [PATCH v3 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000 Adriana Reus
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Adriana Reus @ 2016-02-09 15:38 UTC (permalink / raw)
To: jic23
Cc: linux-iio, srinivas.pandruvada, ggao, daniel.baluta, mwelling,
lucas.de.marchi, adi.reus, Adriana Reus
Separate this driver into core and i2c functionality.
This is in preparation for adding spi support.
Signed-off-by: Adriana Reus <adriana.reus@intel.com>
---
Changes since v2:
* Fix the compilation error that occurs if CONFIG_ACPI is not defined
drivers/iio/imu/inv_mpu6050/Kconfig | 15 +-
drivers/iio/imu/inv_mpu6050/Makefile | 5 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c | 18 ++-
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 208 ++++----------------------
drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 207 +++++++++++++++++++++++++
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 12 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 5 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 4 +-
8 files changed, 271 insertions(+), 203 deletions(-)
create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
index f301f3a..4e8ea9e 100644
--- a/drivers/iio/imu/inv_mpu6050/Kconfig
+++ b/drivers/iio/imu/inv_mpu6050/Kconfig
@@ -4,11 +4,9 @@
config INV_MPU6050_IIO
tristate "Invensense MPU6050 devices"
- depends on I2C && SYSFS
+ depends on SYSFS
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
- select I2C_MUX
- select REGMAP_I2C
help
This driver supports the Invensense MPU6050 devices.
This driver can also support MPU6500 in MPU6050 compatibility mode
@@ -16,3 +14,14 @@ config INV_MPU6050_IIO
It is a gyroscope/accelerometer combo device.
This driver can be built as a module. The module will be called
inv-mpu6050.
+
+config INV_MPU6050_I2C
+ tristate "Invensense MPU6050 devices (I2C)"
+ depends on I2C
+ select INV_MPU6050_IIO
+ select I2C_MUX
+ select REGMAP_I2C
+ help
+ This driver can be built as a module. The module will be called
+ inv-mpu6050-i2c.
+
diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile
index f566f6a..ca4941d 100644
--- a/drivers/iio/imu/inv_mpu6050/Makefile
+++ b/drivers/iio/imu/inv_mpu6050/Makefile
@@ -3,4 +3,7 @@
#
obj-$(CONFIG_INV_MPU6050_IIO) += inv-mpu6050.o
-inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o inv_mpu_acpi.o
+inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o
+
+obj-$(CONFIG_INV_MPU6050_I2C) += inv-mpu6050-i2c.o
+inv-mpu6050-i2c-objs := inv_mpu_i2c.o inv_mpu_acpi.o
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
index 1c982a5..0bcfa8d 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
@@ -139,22 +139,23 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
return 0;
}
-int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st)
+int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
{
+ struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(&client->dev));
st->mux_client = NULL;
- if (ACPI_HANDLE(&st->client->dev)) {
+ if (ACPI_HANDLE(&client->dev)) {
struct i2c_board_info info;
struct acpi_device *adev;
int ret = -1;
- adev = ACPI_COMPANION(&st->client->dev);
+ adev = ACPI_COMPANION(&client->dev);
memset(&info, 0, sizeof(info));
dmi_check_system(inv_mpu_dev_list);
switch (matched_product_name) {
case INV_MPU_ASUS_T100TA:
- ret = asus_acpi_get_sensor_info(adev, st->client,
+ ret = asus_acpi_get_sensor_info(adev, client,
&info);
break;
/* Add more matched product processing here */
@@ -166,7 +167,7 @@ int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st)
/* No matching DMI, so create device on INV6XX type */
unsigned short primary, secondary;
- ret = inv_mpu_process_acpi_config(st->client, &primary,
+ ret = inv_mpu_process_acpi_config(client, &primary,
&secondary);
if (!ret && secondary) {
char *name;
@@ -191,8 +192,9 @@ int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st)
return 0;
}
-void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st)
+void inv_mpu_acpi_delete_mux_client(struct i2c_client *client)
{
+ struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(&client->dev));
if (st->mux_client)
i2c_unregister_device(st->mux_client);
}
@@ -200,12 +202,12 @@ void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st)
#include "inv_mpu_iio.h"
-int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st)
+int inv_mpu_acpi_create_mux_client(struct i2c_client *client)
{
return 0;
}
-void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st)
+void inv_mpu_acpi_delete_mux_client(struct i2c_client *client)
{
}
#endif
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 151a378..7b46db5 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -27,11 +27,6 @@
#include <linux/acpi.h>
#include "inv_mpu_iio.h"
-static const struct regmap_config inv_mpu_regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
-};
-
/*
* this is the gyro scale translated from dynamic range plus/minus
* {250, 500, 1000, 2000} to rad/s
@@ -80,83 +75,6 @@ static const struct inv_mpu6050_hw hw_info[INV_NUM_PARTS] = {
},
};
-/*
- * The i2c read/write needs to happen in unlocked mode. As the parent
- * adapter is common. If we use locked versions, it will fail as
- * the mux adapter will lock the parent i2c adapter, while calling
- * select/deselect functions.
- */
-static int inv_mpu6050_write_reg_unlocked(struct inv_mpu6050_state *st,
- u8 reg, u8 d)
-{
- int ret;
- u8 buf[2];
- struct i2c_msg msg[1] = {
- {
- .addr = st->client->addr,
- .flags = 0,
- .len = sizeof(buf),
- .buf = buf,
- }
- };
-
- buf[0] = reg;
- buf[1] = d;
- ret = __i2c_transfer(st->client->adapter, msg, 1);
- if (ret != 1)
- return ret;
-
- return 0;
-}
-
-static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
- u32 chan_id)
-{
- struct iio_dev *indio_dev = mux_priv;
- struct inv_mpu6050_state *st = iio_priv(indio_dev);
- int ret = 0;
-
- /* Use the same mutex which was used everywhere to protect power-op */
- mutex_lock(&indio_dev->mlock);
- if (!st->powerup_count) {
- ret = inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1,
- 0);
- if (ret)
- goto write_error;
-
- msleep(INV_MPU6050_REG_UP_TIME);
- }
- if (!ret) {
- st->powerup_count++;
- ret = inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg,
- INV_MPU6050_INT_PIN_CFG |
- INV_MPU6050_BIT_BYPASS_EN);
- }
-write_error:
- mutex_unlock(&indio_dev->mlock);
-
- return ret;
-}
-
-static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
- void *mux_priv, u32 chan_id)
-{
- struct iio_dev *indio_dev = mux_priv;
- struct inv_mpu6050_state *st = iio_priv(indio_dev);
-
- mutex_lock(&indio_dev->mlock);
- /* It doesn't really mattter, if any of the calls fails */
- inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg,
- INV_MPU6050_INT_PIN_CFG);
- st->powerup_count--;
- if (!st->powerup_count)
- inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1,
- INV_MPU6050_BIT_SLEEP);
- mutex_unlock(&indio_dev->mlock);
-
- return 0;
-}
-
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
{
unsigned int d, mgmt_1;
@@ -758,42 +676,23 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
return 0;
}
-/**
- * inv_mpu_probe() - probe function.
- * @client: i2c client.
- * @id: i2c device id.
- *
- * Returns 0 on success, a negative error code otherwise.
- */
-static int inv_mpu_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name)
{
struct inv_mpu6050_state *st;
struct iio_dev *indio_dev;
struct inv_mpu6050_platform_data *pdata;
+ struct device *dev = regmap_get_device(regmap);
int result;
- struct regmap *regmap;
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_I2C_BLOCK))
- return -ENOSYS;
-
- regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&client->dev, "Failed to register i2c regmap %d\n",
- (int)PTR_ERR(regmap));
- return PTR_ERR(regmap);
- }
-
- indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->client = client;
st->powerup_count = 0;
+ st->irq = irq;
st->map = regmap;
- pdata = dev_get_platdata(&client->dev);
+ pdata = dev_get_platdata(dev);
if (pdata)
st->plat_data = *pdata;
/* power is turned on inside check chip type*/
@@ -803,18 +702,17 @@ static int inv_mpu_probe(struct i2c_client *client,
result = inv_mpu6050_init_config(indio_dev);
if (result) {
- dev_err(&client->dev,
- "Could not initialize device.\n");
+ dev_err(dev, "Could not initialize device.\n");
return result;
}
- i2c_set_clientdata(client, indio_dev);
- indio_dev->dev.parent = &client->dev;
- /* id will be NULL when enumerated via ACPI */
- if (id)
- indio_dev->name = (char *)id->name;
+ dev_set_drvdata(dev, indio_dev);
+ indio_dev->dev.parent = dev;
+ /* name will be NULL when enumerated via ACPI */
+ if (name)
+ indio_dev->name = name;
else
- indio_dev->name = (char *)dev_name(&client->dev);
+ indio_dev->name = dev_name(dev);
indio_dev->channels = inv_mpu_channels;
indio_dev->num_channels = ARRAY_SIZE(inv_mpu_channels);
@@ -826,13 +724,12 @@ static int inv_mpu_probe(struct i2c_client *client,
inv_mpu6050_read_fifo,
NULL);
if (result) {
- dev_err(&st->client->dev, "configure buffer fail %d\n",
- result);
+ dev_err(dev, "configure buffer fail %d\n", result);
return result;
}
result = inv_mpu6050_probe_trigger(indio_dev);
if (result) {
- dev_err(&st->client->dev, "trigger probe fail %d\n", result);
+ dev_err(dev, "trigger probe fail %d\n", result);
goto out_unreg_ring;
}
@@ -840,102 +737,47 @@ static int inv_mpu_probe(struct i2c_client *client,
spin_lock_init(&st->time_stamp_lock);
result = iio_device_register(indio_dev);
if (result) {
- dev_err(&st->client->dev, "IIO register fail %d\n", result);
+ dev_err(dev, "IIO register fail %d\n", result);
goto out_remove_trigger;
}
- st->mux_adapter = i2c_add_mux_adapter(client->adapter,
- &client->dev,
- indio_dev,
- 0, 0, 0,
- inv_mpu6050_select_bypass,
- inv_mpu6050_deselect_bypass);
- if (!st->mux_adapter) {
- result = -ENODEV;
- goto out_unreg_device;
- }
-
- result = inv_mpu_acpi_create_mux_client(st);
- if (result)
- goto out_del_mux;
-
return 0;
-out_del_mux:
- i2c_del_mux_adapter(st->mux_adapter);
-out_unreg_device:
- iio_device_unregister(indio_dev);
out_remove_trigger:
inv_mpu6050_remove_trigger(st);
out_unreg_ring:
iio_triggered_buffer_cleanup(indio_dev);
return result;
}
+EXPORT_SYMBOL_GPL(inv_mpu_core_probe);
-static int inv_mpu_remove(struct i2c_client *client)
+int inv_mpu_core_remove(struct device *dev)
{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
- inv_mpu_acpi_delete_mux_client(st);
- i2c_del_mux_adapter(st->mux_adapter);
iio_device_unregister(indio_dev);
- inv_mpu6050_remove_trigger(st);
+ inv_mpu6050_remove_trigger(iio_priv(indio_dev));
iio_triggered_buffer_cleanup(indio_dev);
return 0;
}
+EXPORT_SYMBOL_GPL(inv_mpu_core_remove);
+
#ifdef CONFIG_PM_SLEEP
static int inv_mpu_resume(struct device *dev)
{
- return inv_mpu6050_set_power_itg(
- iio_priv(i2c_get_clientdata(to_i2c_client(dev))), true);
+ return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), true);
}
static int inv_mpu_suspend(struct device *dev)
{
- return inv_mpu6050_set_power_itg(
- iio_priv(i2c_get_clientdata(to_i2c_client(dev))), false);
+ return inv_mpu6050_set_power_itg(iio_priv(dev_get_drvdata(dev)), false);
}
-static SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume);
-
-#define INV_MPU6050_PMOPS (&inv_mpu_pmops)
-#else
-#define INV_MPU6050_PMOPS NULL
#endif /* CONFIG_PM_SLEEP */
-/*
- * device id table is used to identify what device can be
- * supported by this driver
- */
-static const struct i2c_device_id inv_mpu_id[] = {
- {"mpu6050", INV_MPU6050},
- {"mpu6500", INV_MPU6500},
- {}
-};
-
-MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
-
-static const struct acpi_device_id inv_acpi_match[] = {
- {"INVN6500", 0},
- { },
-};
-
-MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
-
-static struct i2c_driver inv_mpu_driver = {
- .probe = inv_mpu_probe,
- .remove = inv_mpu_remove,
- .id_table = inv_mpu_id,
- .driver = {
- .name = "inv-mpu6050",
- .pm = INV_MPU6050_PMOPS,
- .acpi_match_table = ACPI_PTR(inv_acpi_match),
- },
-};
-
-module_i2c_driver(inv_mpu_driver);
+SIMPLE_DEV_PM_OPS(inv_mpu_pmops, inv_mpu_suspend, inv_mpu_resume);
+EXPORT_SYMBOL_GPL(inv_mpu_pmops);
MODULE_AUTHOR("Invensense Corporation");
MODULE_DESCRIPTION("Invensense device MPU6050 driver");
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
new file mode 100644
index 0000000..6c225a0
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -0,0 +1,207 @@
+/*
+* Copyright (C) 2012 Invensense, Inc.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*/
+
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/i2c-mux.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include "inv_mpu_iio.h"
+
+static const struct regmap_config inv_mpu_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+/*
+ * The i2c read/write needs to happen in unlocked mode. As the parent
+ * adapter is common. If we use locked versions, it will fail as
+ * the mux adapter will lock the parent i2c adapter, while calling
+ * select/deselect functions.
+ */
+static int inv_mpu6050_write_reg_unlocked(struct i2c_client *client,
+ u8 reg, u8 d)
+{
+ int ret;
+ u8 buf[2] = {reg, d};
+ struct i2c_msg msg[1] = {
+ {
+ .addr = client->addr,
+ .flags = 0,
+ .len = sizeof(buf),
+ .buf = buf,
+ }
+ };
+
+ ret = __i2c_transfer(client->adapter, msg, 1);
+ if (ret != 1)
+ return ret;
+
+ return 0;
+}
+
+static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
+ u32 chan_id)
+{
+ struct i2c_client *client = mux_priv;
+ struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ int ret = 0;
+
+ /* Use the same mutex which was used everywhere to protect power-op */
+ mutex_lock(&indio_dev->mlock);
+ if (!st->powerup_count) {
+ ret = inv_mpu6050_write_reg_unlocked(client,
+ st->reg->pwr_mgmt_1, 0);
+ if (ret)
+ goto write_error;
+
+ msleep(INV_MPU6050_REG_UP_TIME);
+ }
+ if (!ret) {
+ st->powerup_count++;
+ ret = inv_mpu6050_write_reg_unlocked(client,
+ st->reg->int_pin_cfg,
+ INV_MPU6050_INT_PIN_CFG |
+ INV_MPU6050_BIT_BYPASS_EN);
+ }
+write_error:
+ mutex_unlock(&indio_dev->mlock);
+
+ return ret;
+}
+
+static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
+ void *mux_priv, u32 chan_id)
+{
+ struct i2c_client *client = mux_priv;
+ struct iio_dev *indio_dev = dev_get_drvdata(&client->dev);
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+ mutex_lock(&indio_dev->mlock);
+ /* It doesn't really mattter, if any of the calls fails */
+ inv_mpu6050_write_reg_unlocked(client, st->reg->int_pin_cfg,
+ INV_MPU6050_INT_PIN_CFG);
+ st->powerup_count--;
+ if (!st->powerup_count)
+ inv_mpu6050_write_reg_unlocked(client, st->reg->pwr_mgmt_1,
+ INV_MPU6050_BIT_SLEEP);
+ mutex_unlock(&indio_dev->mlock);
+
+ return 0;
+}
+
+/**
+ * inv_mpu_probe() - probe function.
+ * @client: i2c client.
+ * @id: i2c device id.
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static int inv_mpu_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct inv_mpu6050_state *st;
+ int result;
+ const char *name = id ? id->name : NULL;
+ struct regmap *regmap;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -ENOSYS;
+
+ regmap = devm_regmap_init_i2c(client, &inv_mpu_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "Failed to register i2c regmap %d\n",
+ (int)PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ result = inv_mpu_core_probe(regmap, client->irq, name);
+ if (result < 0)
+ return result;
+
+ st = iio_priv(dev_get_drvdata(&client->dev));
+ st->mux_adapter = i2c_add_mux_adapter(client->adapter,
+ &client->dev,
+ client,
+ 0, 0, 0,
+ inv_mpu6050_select_bypass,
+ inv_mpu6050_deselect_bypass);
+ if (!st->mux_adapter) {
+ result = -ENODEV;
+ goto out_unreg_device;
+ }
+
+ result = inv_mpu_acpi_create_mux_client(client);
+ if (result)
+ goto out_del_mux;
+
+ return 0;
+
+out_del_mux:
+ i2c_del_mux_adapter(st->mux_adapter);
+out_unreg_device:
+ inv_mpu_core_remove(&client->dev);
+ return result;
+}
+
+static int inv_mpu_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+
+ inv_mpu_acpi_delete_mux_client(client);
+ i2c_del_mux_adapter(st->mux_adapter);
+
+ return inv_mpu_core_remove(&client->dev);
+}
+
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct i2c_device_id inv_mpu_id[] = {
+ {"mpu6050", INV_MPU6050},
+ {"mpu6500", INV_MPU6500},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
+
+static const struct acpi_device_id inv_acpi_match[] = {
+ {"INVN6500", 0},
+ { },
+};
+
+MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
+
+static struct i2c_driver inv_mpu_driver = {
+ .probe = inv_mpu_probe,
+ .remove = inv_mpu_remove,
+ .id_table = inv_mpu_id,
+ .driver = {
+ .owner = THIS_MODULE,
+ .acpi_match_table = ACPI_PTR(inv_acpi_match),
+ .name = "inv-mpu6050 i2c driver",
+ .pm = &inv_mpu_pmops,
+ },
+};
+
+module_i2c_driver(inv_mpu_driver);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Invensense device MPU6050 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 469cd1f..1bf65a0 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -108,9 +108,10 @@ struct inv_mpu6050_hw {
* @hw: Other hardware-specific information.
* @chip_type: chip type.
* @time_stamp_lock: spin lock to time stamp.
- * @client: i2c client handle.
* @plat_data: platform data.
* @timestamps: kfifo queue to store time stamp.
+ * @map regmap pointer.
+ * @irq interrupt number.
*/
struct inv_mpu6050_state {
#define TIMESTAMP_FIFO_SIZE 16
@@ -120,13 +121,13 @@ struct inv_mpu6050_state {
const struct inv_mpu6050_hw *hw;
enum inv_devices chip_type;
spinlock_t time_stamp_lock;
- struct i2c_client *client;
struct i2c_adapter *mux_adapter;
struct i2c_client *mux_client;
unsigned int powerup_count;
struct inv_mpu6050_platform_data plat_data;
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
struct regmap *map;
+ int irq;
};
/*register and associated bit definition*/
@@ -255,5 +256,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev);
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask);
int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
-int inv_mpu_acpi_create_mux_client(struct inv_mpu6050_state *st);
-void inv_mpu_acpi_delete_mux_client(struct inv_mpu6050_state *st);
+int inv_mpu_acpi_create_mux_client(struct i2c_client *client);
+void inv_mpu_acpi_delete_mux_client(struct i2c_client *client);
+int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name);
+int inv_mpu_core_remove(struct device *dev);
+extern const struct dev_pm_ops inv_mpu_pmops;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
index eb19dae..1fc5fd9 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
@@ -42,7 +42,8 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
/* disable interrupt */
result = regmap_write(st->map, st->reg->int_enable, 0);
if (result) {
- dev_err(&st->client->dev, "int_enable failed %d\n", result);
+ dev_err(regmap_get_device(st->map), "int_enable failed %d\n",
+ result);
return result;
}
/* disable the sensor output to FIFO */
@@ -89,7 +90,7 @@ int inv_reset_fifo(struct iio_dev *indio_dev)
return 0;
reset_fifo_fail:
- dev_err(&st->client->dev, "reset fifo failed %d\n", result);
+ dev_err(regmap_get_device(st->map), "reset fifo failed %d\n", result);
result = regmap_write(st->map, st->reg->int_enable,
INV_MPU6050_BIT_DATA_RDY_EN);
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index ee9e66d..72d6aae 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -123,7 +123,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
if (!st->trig)
return -ENOMEM;
- ret = devm_request_irq(&indio_dev->dev, st->client->irq,
+ ret = devm_request_irq(&indio_dev->dev, st->irq,
&iio_trigger_generic_data_rdy_poll,
IRQF_TRIGGER_RISING,
"inv_mpu",
@@ -131,7 +131,7 @@ int inv_mpu6050_probe_trigger(struct iio_dev *indio_dev)
if (ret)
return ret;
- st->trig->dev.parent = &st->client->dev;
+ st->trig->dev.parent = regmap_get_device(st->map);
st->trig->ops = &inv_mpu_trigger_ops;
iio_trigger_set_drvdata(st->trig, indio_dev);
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
2016-02-09 15:38 [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
` (2 preceding siblings ...)
2016-02-09 15:38 ` [PATCH v3 3/4] iio: imu: inv_mpu6050: Separate driver into core and i2c functionality Adriana Reus
@ 2016-02-09 15:38 ` Adriana Reus
2016-02-09 16:28 ` [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Michael Welling
2016-02-09 20:44 ` Jonathan Cameron
5 siblings, 0 replies; 9+ messages in thread
From: Adriana Reus @ 2016-02-09 15:38 UTC (permalink / raw)
To: jic23
Cc: linux-iio, srinivas.pandruvada, ggao, daniel.baluta, mwelling,
lucas.de.marchi, adi.reus, Adriana Reus
The only difference between the MPU6000 and the
MPU6050 is that the first also supports SPI.
Add SPI driver for this chip.
Signed-off-by: Adriana Reus <adriana.reus@intel.com>
---
Changes since v2:
* Added a callback that disables the I2C interface
drivers/iio/imu/inv_mpu6050/Kconfig | 7 ++
drivers/iio/imu/inv_mpu6050/Makefile | 3 +
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 7 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 2 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 6 +-
drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 106 +++++++++++++++++++++++++++++
6 files changed, 128 insertions(+), 3 deletions(-)
create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig
index 4e8ea9e..75c3820 100644
--- a/drivers/iio/imu/inv_mpu6050/Kconfig
+++ b/drivers/iio/imu/inv_mpu6050/Kconfig
@@ -25,3 +25,10 @@ config INV_MPU6050_I2C
This driver can be built as a module. The module will be called
inv-mpu6050-i2c.
+config INV_MPU6050_SPI
+ tristate "Invensense MPU6050 devices (SPI)"
+ select INV_MPU6050_IIO
+ select REGMAP_SPI
+ help
+ This driver can be built as a module. The module will be called
+ inv-mpu6050-spi.
diff --git a/drivers/iio/imu/inv_mpu6050/Makefile b/drivers/iio/imu/inv_mpu6050/Makefile
index ca4941d..734af5e 100644
--- a/drivers/iio/imu/inv_mpu6050/Makefile
+++ b/drivers/iio/imu/inv_mpu6050/Makefile
@@ -7,3 +7,6 @@ inv-mpu6050-objs := inv_mpu_core.o inv_mpu_ring.o inv_mpu_trigger.o
obj-$(CONFIG_INV_MPU6050_I2C) += inv-mpu6050-i2c.o
inv-mpu6050-i2c-objs := inv_mpu_i2c.o inv_mpu_acpi.o
+
+obj-$(CONFIG_INV_MPU6050_SPI) += inv-mpu6050-spi.o
+inv-mpu6050-spi-objs := inv_mpu_spi.o
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 7b46db5..2258600 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -152,6 +152,7 @@ int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
return 0;
}
+EXPORT_SYMBOL_GPL(inv_mpu6050_set_power_itg);
/**
* inv_mpu6050_init_config() - Initialize hardware, disable FIFO.
@@ -676,7 +677,8 @@ static int inv_check_and_setup_chip(struct inv_mpu6050_state *st)
return 0;
}
-int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name)
+int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
+ int (*inv_mpu_bus_setup)(struct iio_dev *))
{
struct inv_mpu6050_state *st;
struct iio_dev *indio_dev;
@@ -700,6 +702,9 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name)
if (result)
return result;
+ if (inv_mpu_bus_setup)
+ inv_mpu_bus_setup(indio_dev);
+
result = inv_mpu6050_init_config(indio_dev);
if (result) {
dev_err(dev, "Could not initialize device.\n");
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 6c225a0..54d9cfa 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -129,7 +129,7 @@ static int inv_mpu_probe(struct i2c_client *client,
return PTR_ERR(regmap);
}
- result = inv_mpu_core_probe(regmap, client->irq, name);
+ result = inv_mpu_core_probe(regmap, client->irq, name, NULL);
if (result < 0)
return result;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index 1bf65a0..fcc2f3d 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -62,6 +62,7 @@ struct inv_mpu6050_reg_map {
enum inv_devices {
INV_MPU6050,
INV_MPU6500,
+ INV_MPU6000,
INV_NUM_PARTS
};
@@ -154,6 +155,7 @@ struct inv_mpu6050_state {
#define INV_MPU6050_BIT_I2C_MST_EN 0x20
#define INV_MPU6050_BIT_FIFO_EN 0x40
#define INV_MPU6050_BIT_DMP_EN 0x80
+#define INV_MPU6050_BIT_I2C_IF_DIS 0x10
#define INV_MPU6050_REG_PWR_MGMT_1 0x6B
#define INV_MPU6050_BIT_H_RESET 0x80
@@ -258,6 +260,8 @@ int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 val);
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
int inv_mpu_acpi_create_mux_client(struct i2c_client *client);
void inv_mpu_acpi_delete_mux_client(struct i2c_client *client);
-int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name);
+int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
+ int (*inv_mpu_bus_setup)(struct iio_dev *));
int inv_mpu_core_remove(struct device *dev);
+int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on);
extern const struct dev_pm_ops inv_mpu_pmops;
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
new file mode 100644
index 0000000..1980d21
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
@@ -0,0 +1,106 @@
+/*
+* Copyright (C) 2015 Intel Corporation Inc.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*/
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include "inv_mpu_iio.h"
+
+static const struct regmap_config inv_mpu_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int inv_mpu_i2c_disable(struct iio_dev *indio_dev)
+{
+ struct inv_mpu6050_state *st = iio_priv(indio_dev);
+ int ret = 0;
+
+ ret = inv_mpu6050_set_power_itg(st, true);
+ if (ret)
+ return ret;
+
+ ret = regmap_write(st->map, INV_MPU6050_REG_USER_CTRL,
+ INV_MPU6050_BIT_I2C_IF_DIS);
+ if (ret) {
+ inv_mpu6050_set_power_itg(st, false);
+ return ret;
+ }
+
+ return inv_mpu6050_set_power_itg(st, false);
+}
+
+static int inv_mpu_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+ const struct spi_device_id *id = spi_get_device_id(spi);
+ const char *name = id ? id->name : NULL;
+ int result;
+
+ regmap = devm_regmap_init_spi(spi, &inv_mpu_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&spi->dev, "Failed to register spi regmap %d\n",
+ (int)PTR_ERR(regmap));
+ return PTR_ERR(regmap);
+ }
+
+ result = regmap_write(regmap, INV_MPU6050_REG_USER_CTRL,
+ INV_MPU6050_BIT_I2C_IF_DIS);
+ if (result) {
+ dev_err(&spi->dev, "Failed to disable I2C interface\n");
+ return result;
+ }
+
+ return inv_mpu_core_probe(regmap, spi->irq, name, inv_mpu_i2c_disable);
+}
+
+static int inv_mpu_remove(struct spi_device *spi)
+{
+ return inv_mpu_core_remove(&spi->dev);
+}
+
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct spi_device_id inv_mpu_id[] = {
+ {"mpu6000", INV_MPU6000},
+ {}
+};
+
+MODULE_DEVICE_TABLE(spi, inv_mpu_id);
+
+static const struct acpi_device_id inv_acpi_match[] = {
+ {"INVN6000", 0},
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
+
+static struct spi_driver inv_mpu_driver = {
+ .probe = inv_mpu_probe,
+ .remove = inv_mpu_remove,
+ .id_table = inv_mpu_id,
+ .driver = {
+ .owner = THIS_MODULE,
+ .acpi_match_table = ACPI_PTR(inv_acpi_match),
+ .name = "inv-mpu6000 spi driver",
+ .pm = &inv_mpu_pmops,
+ },
+};
+
+module_spi_driver(inv_mpu_driver);
+
+MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
+MODULE_DESCRIPTION("Invensense device MPU6000 driver");
+MODULE_LICENSE("GPL");
--
1.9.1
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality
2016-02-09 15:38 [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
` (3 preceding siblings ...)
2016-02-09 15:38 ` [PATCH v3 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000 Adriana Reus
@ 2016-02-09 16:28 ` Michael Welling
2016-02-09 20:44 ` Jonathan Cameron
5 siblings, 0 replies; 9+ messages in thread
From: Michael Welling @ 2016-02-09 16:28 UTC (permalink / raw)
To: Adriana Reus
Cc: jic23, linux-iio, srinivas.pandruvada, ggao, daniel.baluta,
lucas.de.marchi, adi.reus
On Tue, Feb 09, 2016 at 05:38:16PM +0200, Adriana Reus wrote:
> This series splits this driver into general and I2C/SPI specific functionality.
> The first patch is a fix for a bug in the interrupt pin configuration.
> The second patch changes all the I2C specific calls into regmap calls.
> The third patch separated the remaining I2C specific part into a different component.
> Finally the fourth patch adds SPI support for the MPU6000 chip.
>
> No changes since v2 for the first two patches.
> Adressed comments for the last two patches
>
Tested-by: Michael Welling <mwelling@ieee.org>
> Adriana Reus (4):
> iio: imu: inv-mpu6050: Fix interrupt pin configuration
> iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions
> iio: imu: inv_mpu6050: Separate driver into core and i2c
> functionality.
> iio: imu: inv_mpu6050: Add SPI support for MPU6000
>
> drivers/iio/imu/inv_mpu6050/Kconfig | 21 ++-
> drivers/iio/imu/inv_mpu6050/Makefile | 8 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c | 18 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 258 ++++++--------------------
> drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 207 +++++++++++++++++++++
> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 19 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 35 ++--
> drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 106 +++++++++++
> drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 10 +-
> 9 files changed, 440 insertions(+), 242 deletions(-)
> create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
>
> --
> 1.9.1
>
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality
2016-02-09 15:38 [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
` (4 preceding siblings ...)
2016-02-09 16:28 ` [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Michael Welling
@ 2016-02-09 20:44 ` Jonathan Cameron
2016-02-09 20:47 ` Lars-Peter Clausen
5 siblings, 1 reply; 9+ messages in thread
From: Jonathan Cameron @ 2016-02-09 20:44 UTC (permalink / raw)
To: Adriana Reus
Cc: linux-iio, srinivas.pandruvada, ggao, daniel.baluta, mwelling,
lucas.de.marchi, adi.reus
On 09/02/16 15:38, Adriana Reus wrote:
> This series splits this driver into general and I2C/SPI specific functionality.
> The first patch is a fix for a bug in the interrupt pin configuration.
> The second patch changes all the I2C specific calls into regmap calls.
> The third patch separated the remaining I2C specific part into a different component.
> Finally the fourth patch adds SPI support for the MPU6000 chip.
>
> No changes since v2 for the first two patches.
> Adressed comments for the last two patches
>
> Adriana Reus (4):
> iio: imu: inv-mpu6050: Fix interrupt pin configuration
> iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions
> iio: imu: inv_mpu6050: Separate driver into core and i2c
> functionality.
> iio: imu: inv_mpu6050: Add SPI support for MPU6000
>
> drivers/iio/imu/inv_mpu6050/Kconfig | 21 ++-
> drivers/iio/imu/inv_mpu6050/Makefile | 8 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c | 18 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 258 ++++++--------------------
> drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 207 +++++++++++++++++++++
> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 19 +-
> drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 35 ++--
> drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 106 +++++++++++
> drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 10 +-
> 9 files changed, 440 insertions(+), 242 deletions(-)
> create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
> create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
>
Just to make sure you don't miss it, (and for my reference as I
might forget those emails before I apply this)
there are some additional comments on V2 from Lars that crossed
with V3 that need addressing.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality
2016-02-09 20:44 ` Jonathan Cameron
@ 2016-02-09 20:47 ` Lars-Peter Clausen
0 siblings, 0 replies; 9+ messages in thread
From: Lars-Peter Clausen @ 2016-02-09 20:47 UTC (permalink / raw)
To: Jonathan Cameron, Adriana Reus
Cc: linux-iio, srinivas.pandruvada, ggao, daniel.baluta, mwelling,
lucas.de.marchi, adi.reus
On 02/09/2016 09:44 PM, Jonathan Cameron wrote:
> On 09/02/16 15:38, Adriana Reus wrote:
>> This series splits this driver into general and I2C/SPI specific functionality.
>> The first patch is a fix for a bug in the interrupt pin configuration.
>> The second patch changes all the I2C specific calls into regmap calls.
>> The third patch separated the remaining I2C specific part into a different component.
>> Finally the fourth patch adds SPI support for the MPU6000 chip.
>>
>> No changes since v2 for the first two patches.
>> Adressed comments for the last two patches
>>
>> Adriana Reus (4):
>> iio: imu: inv-mpu6050: Fix interrupt pin configuration
>> iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions
>> iio: imu: inv_mpu6050: Separate driver into core and i2c
>> functionality.
>> iio: imu: inv_mpu6050: Add SPI support for MPU6000
>>
>> drivers/iio/imu/inv_mpu6050/Kconfig | 21 ++-
>> drivers/iio/imu/inv_mpu6050/Makefile | 8 +-
>> drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c | 18 +-
>> drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 258 ++++++--------------------
>> drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c | 207 +++++++++++++++++++++
>> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h | 19 +-
>> drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 35 ++--
>> drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 106 +++++++++++
>> drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c | 10 +-
>> 9 files changed, 440 insertions(+), 242 deletions(-)
>> create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
>> create mode 100644 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
>>
> Just to make sure you don't miss it, (and for my reference as I
> might forget those emails before I apply this)
> there are some additional comments on V2 from Lars that crossed
> with V3 that need addressing.
Oh, sorry, I though I was replying to v3, but yeah, same issues still in v3.
^ permalink raw reply [flat|nested] 9+ messages in thread