All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality
@ 2016-02-02 15:02 Adriana Reus
  2016-02-02 15:02 ` [PATCH v1 1/4] iio: imu: inv-mpu6050: Fix interrupt pin configuration Adriana Reus
                   ` (3 more replies)
  0 siblings, 4 replies; 12+ messages in thread
From: Adriana Reus @ 2016-02-02 15:02 UTC (permalink / raw)
  To: jic23; +Cc: linux-iio, srinivas.pandruvada, ggao, Adriana Reus

This series splits this driver into general and I2C/SPI specific funtionality.
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.

Since the initial version there have been minor changes according to the
comments received.

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    |  14 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c    | 253 +++++---------------------
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c     | 207 +++++++++++++++++++++
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h     |  13 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c    |  35 ++--
 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c     |  80 ++++++++
 drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c |  10 +-
 9 files changed, 402 insertions(+), 239 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] 12+ messages in thread

* [PATCH v1 1/4] iio: imu: inv-mpu6050: Fix interrupt pin configuration
  2016-02-02 15:02 [PATCH v1 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
@ 2016-02-02 15:02 ` Adriana Reus
  2016-02-02 15:02 ` [PATCH v1 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions Adriana Reus
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 12+ messages in thread
From: Adriana Reus @ 2016-02-02 15:02 UTC (permalink / raw)
  To: jic23; +Cc: linux-iio, srinivas.pandruvada, ggao, 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 change since the previous submitted version

 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] 12+ messages in thread

* [PATCH v1 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions
  2016-02-02 15:02 [PATCH v1 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
  2016-02-02 15:02 ` [PATCH v1 1/4] iio: imu: inv-mpu6050: Fix interrupt pin configuration Adriana Reus
@ 2016-02-02 15:02 ` Adriana Reus
  2016-02-02 15:02 ` [PATCH v1 3/4] iio: imu: inv_mpu6050: Separate driver into core and i2c functionality Adriana Reus
  2016-02-02 15:02 ` [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000 Adriana Reus
  3 siblings, 0 replies; 12+ messages in thread
From: Adriana Reus @ 2016-02-02 15:02 UTC (permalink / raw)
  To: jic23; +Cc: linux-iio, srinivas.pandruvada, ggao, 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 change since the initial submitted version for this patch either

 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, &timestamp, 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] 12+ messages in thread

* [PATCH v1 3/4] iio: imu: inv_mpu6050: Separate driver into core and i2c functionality.
  2016-02-02 15:02 [PATCH v1 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
  2016-02-02 15:02 ` [PATCH v1 1/4] iio: imu: inv-mpu6050: Fix interrupt pin configuration Adriana Reus
  2016-02-02 15:02 ` [PATCH v1 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions Adriana Reus
@ 2016-02-02 15:02 ` Adriana Reus
  2016-02-02 15:02 ` [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000 Adriana Reus
  3 siblings, 0 replies; 12+ messages in thread
From: Adriana Reus @ 2016-02-02 15:02 UTC (permalink / raw)
  To: jic23; +Cc: linux-iio, srinivas.pandruvada, ggao, 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 initial version:
 * Modified Kconfig in order to make the i2c driver select the core component
   instead of the other way around.
 * Minor change: removed a cast to (char*) in core probe as it was not needed.
 * In write_reg_unlocked - initialize the buffer at declaration as suggested
 * Retrieve dev from regmap_get_device instead of having a separate copy
   of the pointer.

 drivers/iio/imu/inv_mpu6050/Kconfig           |  15 +-
 drivers/iio/imu/inv_mpu6050/Makefile          |   5 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c    |  14 +-
 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     |   9 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c    |   5 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c |   4 +-
 8 files changed, 267 insertions(+), 200 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..483f52d 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"
+	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..36d7067 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);
 }
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..af406a3 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -120,13 +120,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 +255,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] 12+ messages in thread

* [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
  2016-02-02 15:02 [PATCH v1 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
                   ` (2 preceding siblings ...)
  2016-02-02 15:02 ` [PATCH v1 3/4] iio: imu: inv_mpu6050: Separate driver into core and i2c functionality Adriana Reus
@ 2016-02-02 15:02 ` Adriana Reus
  2016-02-02 15:29   ` Crt Mori
  2016-02-03  3:39   ` Lucas De Marchi
  3 siblings, 2 replies; 12+ messages in thread
From: Adriana Reus @ 2016-02-02 15:02 UTC (permalink / raw)
  To: jic23; +Cc: linux-iio, srinivas.pandruvada, ggao, 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 initial version:
 * Modified Kconfig so that the SPI component selects the core component
   instead of the other way around.

 drivers/iio/imu/inv_mpu6050/Kconfig       |  7 +++
 drivers/iio/imu/inv_mpu6050/Makefile      |  3 ++
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  1 +
 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 80 +++++++++++++++++++++++++++++++
 4 files changed, 91 insertions(+)
 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 483f52d..6f6a419 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"
+	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_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index af406a3..758fe2b 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
 };
 
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..484171e
--- /dev/null
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
@@ -0,0 +1,80 @@
+/*
+* 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_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;
+
+	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);
+	}
+
+	return inv_mpu_core_probe(regmap, spi->irq, name);
+}
+
+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[] = {
+	{"mpu6050", INV_MPU6050},
+	{"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-mpu6050 spi driver",
+		.pm     =       &inv_mpu_pmops,
+	},
+};
+
+module_spi_driver(inv_mpu_driver);
+
+MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
+MODULE_DESCRIPTION("Invensense device MPU6050 driver");
+MODULE_LICENSE("GPL");
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
  2016-02-02 15:02 ` [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000 Adriana Reus
@ 2016-02-02 15:29   ` Crt Mori
  2016-02-02 15:34     ` Crt Mori
  2016-02-03  3:39   ` Lucas De Marchi
  1 sibling, 1 reply; 12+ messages in thread
From: Crt Mori @ 2016-02-02 15:29 UTC (permalink / raw)
  To: Adriana Reus; +Cc: Johnathan Iain Cameron, linux-iio, Srinivas Pandruvada, ggao

As far as I understand regmap, you do not need to add a separate file
like that - but you can combine them all together with just passing
i2c or spi device to them depending on the connection type (can be
linked to dt).

Is there a reason for this kind of change?


On 2 February 2016 at 16:02, Adriana Reus <adriana.reus@intel.com> wrote:
> 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 initial version:
>  * Modified Kconfig so that the SPI component selects the core component
>    instead of the other way around.
>
>  drivers/iio/imu/inv_mpu6050/Kconfig       |  7 +++
>  drivers/iio/imu/inv_mpu6050/Makefile      |  3 ++
>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  1 +
>  drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 80 +++++++++++++++++++++++++++++++
>  4 files changed, 91 insertions(+)
>  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 483f52d..6f6a419 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"
> +       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_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> index af406a3..758fe2b 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
>  };
>
> 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..484171e
> --- /dev/null
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
> @@ -0,0 +1,80 @@
> +/*
> +* 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_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;
> +
> +       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);
> +       }
> +
> +       return inv_mpu_core_probe(regmap, spi->irq, name);
> +}
> +
> +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[] = {
> +       {"mpu6050", INV_MPU6050},
> +       {"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-mpu6050 spi driver",
> +               .pm     =       &inv_mpu_pmops,
> +       },
> +};
> +
> +module_spi_driver(inv_mpu_driver);
> +
> +MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
> +MODULE_DESCRIPTION("Invensense device MPU6050 driver");
> +MODULE_LICENSE("GPL");
> --
> 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] 12+ messages in thread

* Re: [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
  2016-02-02 15:29   ` Crt Mori
@ 2016-02-02 15:34     ` Crt Mori
  2016-02-02 15:48       ` Adriana Reus
  0 siblings, 1 reply; 12+ messages in thread
From: Crt Mori @ 2016-02-02 15:34 UTC (permalink / raw)
  To: Adriana Reus; +Cc: Johnathan Iain Cameron, linux-iio, Srinivas Pandruvada, ggao

Nevermind, saw the trick with other patches (3/4) and I get the point.
You just split up the spi and i2c parts, but retained the rest.


On 2 February 2016 at 16:29, Crt Mori <cmo@melexis.com> wrote:
> As far as I understand regmap, you do not need to add a separate file
> like that - but you can combine them all together with just passing
> i2c or spi device to them depending on the connection type (can be
> linked to dt).
>
> Is there a reason for this kind of change?
>
>
> On 2 February 2016 at 16:02, Adriana Reus <adriana.reus@intel.com> wrote:
>> 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 initial version:
>>  * Modified Kconfig so that the SPI component selects the core component
>>    instead of the other way around.
>>
>>  drivers/iio/imu/inv_mpu6050/Kconfig       |  7 +++
>>  drivers/iio/imu/inv_mpu6050/Makefile      |  3 ++
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  1 +
>>  drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 80 +++++++++++++++++++++++++++++++
>>  4 files changed, 91 insertions(+)
>>  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 483f52d..6f6a419 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"
>> +       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_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> index af406a3..758fe2b 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
>>  };
>>
>> 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..484171e
>> --- /dev/null
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
>> @@ -0,0 +1,80 @@
>> +/*
>> +* 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_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;
>> +
>> +       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);
>> +       }
>> +
>> +       return inv_mpu_core_probe(regmap, spi->irq, name);
>> +}
>> +
>> +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[] = {
>> +       {"mpu6050", INV_MPU6050},
>> +       {"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-mpu6050 spi driver",
>> +               .pm     =       &inv_mpu_pmops,
>> +       },
>> +};
>> +
>> +module_spi_driver(inv_mpu_driver);
>> +
>> +MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
>> +MODULE_DESCRIPTION("Invensense device MPU6050 driver");
>> +MODULE_LICENSE("GPL");
>> --
>> 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] 12+ messages in thread

* Re: [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
  2016-02-02 15:34     ` Crt Mori
@ 2016-02-02 15:48       ` Adriana Reus
  0 siblings, 0 replies; 12+ messages in thread
From: Adriana Reus @ 2016-02-02 15:48 UTC (permalink / raw)
  To: Crt Mori; +Cc: Johnathan Iain Cameron, linux-iio, Srinivas Pandruvada, ggao

Right, there's now going to be a common part, an i2c specific part and 
an spi one.

On a different note I just saw that I did not delete the "mpu6050" from 
the spi_device_id table - I'll do so in the next version.

On 02.02.2016 17:34, Crt Mori wrote:
> Nevermind, saw the trick with other patches (3/4) and I get the point.
> You just split up the spi and i2c parts, but retained the rest.
>
>
> On 2 February 2016 at 16:29, Crt Mori <cmo@melexis.com> wrote:
>> As far as I understand regmap, you do not need to add a separate file
>> like that - but you can combine them all together with just passing
>> i2c or spi device to them depending on the connection type (can be
>> linked to dt).
>>
>> Is there a reason for this kind of change?
>>
>>
>> On 2 February 2016 at 16:02, Adriana Reus <adriana.reus@intel.com> wrote:
>>> 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 initial version:
>>>   * Modified Kconfig so that the SPI component selects the core component
>>>     instead of the other way around.
>>>
>>>   drivers/iio/imu/inv_mpu6050/Kconfig       |  7 +++
>>>   drivers/iio/imu/inv_mpu6050/Makefile      |  3 ++
>>>   drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  1 +
>>>   drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 80 +++++++++++++++++++++++++++++++
>>>   4 files changed, 91 insertions(+)
>>>   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 483f52d..6f6a419 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"
>>> +       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_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>>> index af406a3..758fe2b 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
>>>   };
>>>
>>> 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..484171e
>>> --- /dev/null
>>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
>>> @@ -0,0 +1,80 @@
>>> +/*
>>> +* 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_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;
>>> +
>>> +       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);
>>> +       }
>>> +
>>> +       return inv_mpu_core_probe(regmap, spi->irq, name);
>>> +}
>>> +
>>> +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[] = {
>>> +       {"mpu6050", INV_MPU6050},
>>> +       {"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-mpu6050 spi driver",
>>> +               .pm     =       &inv_mpu_pmops,
>>> +       },
>>> +};
>>> +
>>> +module_spi_driver(inv_mpu_driver);
>>> +
>>> +MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
>>> +MODULE_DESCRIPTION("Invensense device MPU6050 driver");
>>> +MODULE_LICENSE("GPL");
>>> --
>>> 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] 12+ messages in thread

* Re: [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
  2016-02-02 15:02 ` [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000 Adriana Reus
  2016-02-02 15:29   ` Crt Mori
@ 2016-02-03  3:39   ` Lucas De Marchi
  2016-02-03  6:42     ` Ge Gao
  1 sibling, 1 reply; 12+ messages in thread
From: Lucas De Marchi @ 2016-02-03  3:39 UTC (permalink / raw)
  To: Adriana Reus; +Cc: jic23, linux-iio, srinivas.pandruvada, ggao

Hi Adriana,

On Tue, Feb 2, 2016 at 1:02 PM, Adriana Reus <adriana.reus@intel.com> wrote:
> 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 initial version:
>  * Modified Kconfig so that the SPI component selects the core component
>    instead of the other way around.
>
>  drivers/iio/imu/inv_mpu6050/Kconfig       |  7 +++
>  drivers/iio/imu/inv_mpu6050/Makefile      |  3 ++
>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  1 +
>  drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 80 +++++++++++++++++++++++++++++++
>  4 files changed, 91 insertions(+)
>  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 483f52d..6f6a419 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"
> +       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_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
> index af406a3..758fe2b 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
>  };
>
> 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..484171e
> --- /dev/null
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
> @@ -0,0 +1,80 @@
> +/*
> +* 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_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;
> +
> +       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);
> +       }
> +
> +       return inv_mpu_core_probe(regmap, spi->irq, name);

I think there's still some spi-only initialization missing. As per
datasheet we should disable the I2C interface when using the SPI
interface.

Lucas De Marchi

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
  2016-02-03  3:39   ` Lucas De Marchi
@ 2016-02-03  6:42     ` Ge Gao
  2016-02-03  9:17       ` Adriana Reus
  0 siblings, 1 reply; 12+ messages in thread
From: Ge Gao @ 2016-02-03  6:42 UTC (permalink / raw)
  To: Lucas De Marchi; +Cc: Adriana Reus, jic23, linux-iio, srinivas.pandruvada

That is a good point.  That register should be set in case chip get confused if the spi signal mimic a I2C signal

Ge

> On Feb 2, 2016, at 10:31 PM, Lucas De Marchi <lucas.de.marchi@gmail.com> wrote:
> 
> Hi Adriana,
> 
>> On Tue, Feb 2, 2016 at 1:02 PM, Adriana Reus <adriana.reus@intel.com> wrote:
>> 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 initial version:
>> * Modified Kconfig so that the SPI component selects the core component
>>   instead of the other way around.
>> 
>> drivers/iio/imu/inv_mpu6050/Kconfig       |  7 +++
>> drivers/iio/imu/inv_mpu6050/Makefile      |  3 ++
>> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  1 +
>> drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 80 +++++++++++++++++++++++++++++++
>> 4 files changed, 91 insertions(+)
>> 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 483f52d..6f6a419 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"
>> +       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_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>> index af406a3..758fe2b 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
>> };
>> 
>> 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..484171e
>> --- /dev/null
>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
>> @@ -0,0 +1,80 @@
>> +/*
>> +* 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_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;
>> +
>> +       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);
>> +       }
>> +
>> +       return inv_mpu_core_probe(regmap, spi->irq, name);
> 
> I think there's still some spi-only initialization missing. As per
> datasheet we should disable the I2C interface when using the SPI
> interface.
> 
> Lucas De Marchi

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
  2016-02-03  6:42     ` Ge Gao
@ 2016-02-03  9:17       ` Adriana Reus
  2016-02-03 15:21         ` Ge Gao
  0 siblings, 1 reply; 12+ messages in thread
From: Adriana Reus @ 2016-02-03  9:17 UTC (permalink / raw)
  To: Ge Gao, Lucas De Marchi; +Cc: jic23, linux-iio, srinivas.pandruvada

Hi Lucas, Ge,


Thanks for pointing that out Lucas, I'm looking into it.

Ge, would it suffice to set the I2C_IF_DIS via an SPI transaction 
(spi_write or regmap_write)?
Couldn't the chip get confused during that transaction also?


On 03.02.2016 08:42, Ge Gao wrote:
> That is a good point.  That register should be set in case chip get confused if the spi signal mimic a I2C signal
>
> Ge
>
>> On Feb 2, 2016, at 10:31 PM, Lucas De Marchi <lucas.de.marchi@gmail.com> wrote:
>>
>> Hi Adriana,
>>
>>> On Tue, Feb 2, 2016 at 1:02 PM, Adriana Reus <adriana.reus@intel.com> wrote:
>>> 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 initial version:
>>> * Modified Kconfig so that the SPI component selects the core component
>>>    instead of the other way around.
>>>
>>> drivers/iio/imu/inv_mpu6050/Kconfig       |  7 +++
>>> drivers/iio/imu/inv_mpu6050/Makefile      |  3 ++
>>> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  1 +
>>> drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 80 +++++++++++++++++++++++++++++++
>>> 4 files changed, 91 insertions(+)
>>> 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 483f52d..6f6a419 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"
>>> +       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_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
>>> index af406a3..758fe2b 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
>>> };
>>>
>>> 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..484171e
>>> --- /dev/null
>>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
>>> @@ -0,0 +1,80 @@
>>> +/*
>>> +* 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_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;
>>> +
>>> +       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);
>>> +       }
>>> +
>>> +       return inv_mpu_core_probe(regmap, spi->irq, name);
>>
>> I think there's still some spi-only initialization missing. As per
>> datasheet we should disable the I2C interface when using the SPI
>> interface.
>>
>> Lucas De Marchi

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000
  2016-02-03  9:17       ` Adriana Reus
@ 2016-02-03 15:21         ` Ge Gao
  0 siblings, 0 replies; 12+ messages in thread
From: Ge Gao @ 2016-02-03 15:21 UTC (permalink / raw)
  To: Adriana Reus, Lucas De Marchi; +Cc: jic23, linux-iio, srinivas.pandruvada

Hi Adriana,
    Chip only gets confused when a SPI signal could simulate a I2C address.=
 Setting the bit tells chip to completely forget about I2C at all.  Without=
 setting the bit, it still works. But it might risk of triggering I2C if th=
e SPI signal accidentally simulates an I2C address that matches the chip ad=
dress and triggers a subsequent action.

Thanks.

Best Regards,

Ge Gao

________________________________________
From: Adriana Reus <adriana.reus@intel.com>
Sent: Wednesday, February 3, 2016 1:17 AM
To: Ge Gao; Lucas De Marchi
Cc: jic23@kernel.org; linux-iio@vger.kernel.org; srinivas.pandruvada@linux.=
intel.com
Subject: Re: [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6=
000

Hi Lucas, Ge,


Thanks for pointing that out Lucas, I'm looking into it.

Ge, would it suffice to set the I2C_IF_DIS via an SPI transaction
(spi_write or regmap_write)?
Couldn't the chip get confused during that transaction also?


On 03.02.2016 08:42, Ge Gao wrote:
> That is a good point.  That register should be set in case chip get confu=
sed if the spi signal mimic a I2C signal
>
> Ge
>
>> On Feb 2, 2016, at 10:31 PM, Lucas De Marchi <lucas.de.marchi@gmail.com>=
 wrote:
>>
>> Hi Adriana,
>>
>>> On Tue, Feb 2, 2016 at 1:02 PM, Adriana Reus <adriana.reus@intel.com> w=
rote:
>>> 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 initial version:
>>> * Modified Kconfig so that the SPI component selects the core component
>>>    instead of the other way around.
>>>
>>> drivers/iio/imu/inv_mpu6050/Kconfig       |  7 +++
>>> drivers/iio/imu/inv_mpu6050/Makefile      |  3 ++
>>> drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  1 +
>>> drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c | 80 ++++++++++++++++++++++++=
+++++++
>>> 4 files changed, 91 insertions(+)
>>> 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 483f52d..6f6a419 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 call=
ed
>>>           inv-mpu6050-i2c.
>>>
>>> +config INV_MPU6050_SPI
>>> +       tristate "Invensense MPU6050 devices"
>>> +       select INV_MPU6050_IIO
>>> +       select REGMAP_SPI
>>> +       help
>>> +         This driver can be built as a module. The module will be call=
ed
>>> +         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 :=3D inv_mpu_core.o inv_mpu_ring.o inv=
_mpu_trigger.o
>>>
>>> obj-$(CONFIG_INV_MPU6050_I2C) +=3D inv-mpu6050-i2c.o
>>> inv-mpu6050-i2c-objs :=3D inv_mpu_i2c.o inv_mpu_acpi.o
>>> +
>>> +obj-$(CONFIG_INV_MPU6050_SPI) +=3D inv-mpu6050-spi.o
>>> +inv-mpu6050-spi-objs :=3D inv_mpu_spi.o
>>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/im=
u/inv_mpu6050/inv_mpu_iio.h
>>> index af406a3..758fe2b 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
>>> };
>>>
>>> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/im=
u/inv_mpu6050/inv_mpu_spi.c
>>> new file mode 100644
>>> index 0000000..484171e
>>> --- /dev/null
>>> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
>>> @@ -0,0 +1,80 @@
>>> +/*
>>> +* 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 =3D {
>>> +       .reg_bits =3D 8,
>>> +       .val_bits =3D 8,
>>> +};
>>> +
>>> +static int inv_mpu_probe(struct spi_device *spi)
>>> +{
>>> +       struct regmap *regmap;
>>> +       const struct spi_device_id *id =3D spi_get_device_id(spi);
>>> +       const char *name =3D id ? id->name : NULL;
>>> +
>>> +       regmap =3D 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);
>>> +       }
>>> +
>>> +       return inv_mpu_core_probe(regmap, spi->irq, name);
>>
>> I think there's still some spi-only initialization missing. As per
>> datasheet we should disable the I2C interface when using the SPI
>> interface.
>>
>> Lucas De Marchi

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2016-02-03 15:21 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-02 15:02 [PATCH v1 0/4] iio: imu: inv_mpu6050: Split driver into core and I2C/SPI functionality Adriana Reus
2016-02-02 15:02 ` [PATCH v1 1/4] iio: imu: inv-mpu6050: Fix interrupt pin configuration Adriana Reus
2016-02-02 15:02 ` [PATCH v1 2/4] iio: imu: inv_mpu6050: Use regmap instead of i2c specific functions Adriana Reus
2016-02-02 15:02 ` [PATCH v1 3/4] iio: imu: inv_mpu6050: Separate driver into core and i2c functionality Adriana Reus
2016-02-02 15:02 ` [PATCH v1 4/4] iio: imu: inv_mpu6050: Add SPI support for MPU6000 Adriana Reus
2016-02-02 15:29   ` Crt Mori
2016-02-02 15:34     ` Crt Mori
2016-02-02 15:48       ` Adriana Reus
2016-02-03  3:39   ` Lucas De Marchi
2016-02-03  6:42     ` Ge Gao
2016-02-03  9:17       ` Adriana Reus
2016-02-03 15:21         ` Ge Gao

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.