devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] iio: accel: Add 3 new drivers
@ 2016-10-08 12:34 Hans de Goede
       [not found] ` <20161008123426.8991-1-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Hans de Goede @ 2016-10-08 12:34 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

Hi Jonathan, et al.,

Here is 1. a patch to add some missing compatibles to
i2c/trivial-devices.txt, 2. Version 3 of 2 new accelerometer drivers
which I've submitted before, addressing all the review comments and;
3. a new driver for MiraMEMS DA280 / DA226 accelerometers (*).

I'm sending this as a patch-set since there is a potential for conflicts
if these are not applied in the right order.

Regards,

Hans

*) I've bought 2 second hand Allwinner A33 tablets and both ended up having
a DA280 and I borrowed another A33 tablet from a friend which turned out to
have a DA226, this driver has been tested on all 3 devices.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 1/4] dt: bindings: i2c/trivial-devices.txt: Add 2 iio supported accelerometers
       [not found] ` <20161008123426.8991-1-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2016-10-08 12:34   ` Hans de Goede
       [not found]     ` <20161008123426.8991-2-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2016-10-08 12:34   ` [PATCH 2/4] iio: accel: Add driver for dmard10 3-axis Accelerometer Hans de Goede
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 17+ messages in thread
From: Hans de Goede @ 2016-10-08 12:34 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree, Hans de Goede

Add compatible strings for 2 accelerometers which follow the trivial
i2c device bindings and have been supported by the iio subsystem for
a while now.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 Documentation/devicetree/bindings/i2c/trivial-devices.txt | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index fbbad64..ce9db50 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -44,6 +44,7 @@ epson,rx8025		High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE
 epson,rx8581		I2C-BUS INTERFACE REAL TIME CLOCK MODULE
 fsl,mag3110		MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
 fsl,mc13892		MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
+fsl,mma7660		MMA7660FC: 3-Axis Orientation/Motion Detection Sensor
 fsl,mma8450		MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
 fsl,mpl3115		MPL3115: Absolute Digital Pressure Sensor
 fsl,mpr121		MPR121: Proximity Capacitive Touch Sensor Controller
@@ -57,6 +58,7 @@ maxim,max1237		Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
 maxim,max6625		9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
 mc,rv3029c2		Real Time Clock Module with I2C-Bus
 mcube,mc3230		mCube 3-axis 8-bit digital accelerometer
+memsic,mxc6225		MEMSIC 2-axis 8-bit digital accelerometer
 microchip,mcp4531-502	Microchip 7-bit Single I2C Digital Potentiometer (5k)
 microchip,mcp4531-103	Microchip 7-bit Single I2C Digital Potentiometer (10k)
 microchip,mcp4531-503	Microchip 7-bit Single I2C Digital Potentiometer (50k)
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 2/4] iio: accel: Add driver for dmard10 3-axis Accelerometer
       [not found] ` <20161008123426.8991-1-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2016-10-08 12:34   ` [PATCH 1/4] dt: bindings: i2c/trivial-devices.txt: Add 2 iio supported accelerometers Hans de Goede
@ 2016-10-08 12:34   ` Hans de Goede
       [not found]     ` <20161008123426.8991-3-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2016-10-08 12:34   ` [PATCH 3/4] iio: accel: Add driver for the MiraMEMS DA311 3-axis 12-bit digital accelerometer Hans de Goede
  2016-10-08 12:34   ` [PATCH 4/4] iio: accel: Add driver for the MiraMEMS DA280 3-axis 14-bit " Hans de Goede
  3 siblings, 1 reply; 17+ messages in thread
From: Hans de Goede @ 2016-10-08 12:34 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree, Hans de Goede

Add a driver for the Domintech ARD10 3-axis Accelerometer, based on the
android driver found here: https://github.com/domintech/dmard10

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
Changes in v2:
-prefix all defines with DMARD10_ and uppercase them all
-Cleanup typography of some comments
-Use defines for offsets in databuffer
-Use i2c_smbus_write_byte_data() where applicable
-Reduce unnecessarily large buffer size in dmard10_shutdown()
-Use __le16 buffer in dmard10_read_raw()
Changes in v3:
-Express unit in m/s^2 instead of in "G"
---
 .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +
 drivers/iio/accel/Kconfig                          |  10 +
 drivers/iio/accel/Makefile                         |   1 +
 drivers/iio/accel/dmard10.c                        | 266 +++++++++++++++++++++
 4 files changed, 278 insertions(+)
 create mode 100644 drivers/iio/accel/dmard10.c

diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index ce9db50..4689b31 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -39,6 +39,7 @@ dallas,ds75		Digital Thermometer and Thermostat
 dlg,da9053		DA9053: flexible system level PMIC with multicore support
 dlg,da9063		DA9063: system PMIC for quad-core application processors
 domintech,dmard09	DMARD09: 3-axis Accelerometer
+domintech,dmard10	DMARD10: 3-axis Accelerometer
 epson,rx8010		I2C-BUS INTERFACE REAL TIME CLOCK MODULE
 epson,rx8025		High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE
 epson,rx8581		I2C-BUS INTERFACE REAL TIME CLOCK MODULE
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 6bf1b64..6236fd5 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -73,6 +73,16 @@ config DMARD09
 	  Choosing M will build the driver as a module. If so, the module
 	  will be called dmard09.
 
+config DMARD10
+	tristate "Domintech DMARD10 3-axis Accelerometer Driver"
+	depends on I2C
+	help
+	  Say yes here to get support for the Domintech DMARD10 3-axis
+	  accelerometer.
+
+	  Choosing M will build the driver as a module. If so, the module
+	  will be called dmard10.
+
 config HID_SENSOR_ACCEL_3D
 	depends on HID_SENSOR_HUB
 	select IIO_BUFFER
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 07a0c72..9f51559 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
 obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
 obj-$(CONFIG_DMARD06)	+= dmard06.o
 obj-$(CONFIG_DMARD09)	+= dmard09.o
+obj-$(CONFIG_DMARD10)	+= dmard10.o
 obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
 obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
 obj-$(CONFIG_KXSD9)	+= kxsd9.o
diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c
new file mode 100644
index 0000000..b8736cc
--- /dev/null
+++ b/drivers/iio/accel/dmard10.c
@@ -0,0 +1,266 @@
+/**
+ * IIO driver for the 3-axis accelerometer Domintech ARD10.
+ *
+ * Copyright (c) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+ * Copyright (c) 2012 Domintech Technology Co., Ltd
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/byteorder/generic.h>
+
+#define DMARD10_REG_ACTR			0x00
+#define DMARD10_REG_AFEM			0x0c
+#define DMARD10_REG_STADR			0x12
+#define DMARD10_REG_STAINT			0x1c
+#define DMARD10_REG_MISC2			0x1f
+#define DMARD10_REG_PD				0x21
+
+#define DMARD10_MODE_OFF			0x00
+#define DMARD10_MODE_STANDBY			0x02
+#define DMARD10_MODE_ACTIVE			0x06
+#define DMARD10_MODE_READ_OTP			0x12
+#define DMARD10_MODE_RESET_DATA_PATH		0x82
+
+/* AFEN set 1, ATM[2:0]=b'000 (normal), EN_Z/Y/X/T=1 */
+#define DMARD10_VALUE_AFEM_AFEN_NORMAL		0x8f
+/* ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ) */
+#define DMARD10_VALUE_CKSEL_ODR_100_204		0x74
+/* INTC[6:5]=b'00 */
+#define DMARD10_VALUE_INTC			0x00
+/* TAP1/TAP2 Average 2 */
+#define DMARD10_VALUE_TAPNS_AVE_2		0x11
+
+#define DMARD10_VALUE_STADR			0x55
+#define DMARD10_VALUE_STAINT			0xaa
+#define DMARD10_VALUE_MISC2_OSCA_EN		0x08
+#define DMARD10_VALUE_PD_RST			0x52
+
+/* Offsets into the buffer read in dmard10_read_raw() */
+#define DMARD10_X_OFFSET			1
+#define DMARD10_Y_OFFSET			2
+#define DMARD10_Z_OFFSET			3
+
+/*
+ * a value of + or -128 corresponds to + or - 1G
+ * scale = 9.81 / 128 = 0.076640625
+ */
+
+static const int dmard10_nscale = 76640625;
+
+#define DMARD10_CHANNEL(reg, axis) {	\
+	.type = IIO_ACCEL,	\
+	.address = reg,	\
+	.modified = 1,	\
+	.channel2 = IIO_MOD_##axis,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec dmard10_channels[] = {
+	DMARD10_CHANNEL(DMARD10_X_OFFSET, X),
+	DMARD10_CHANNEL(DMARD10_Y_OFFSET, Y),
+	DMARD10_CHANNEL(DMARD10_Z_OFFSET, Z),
+};
+
+struct dmard10_data {
+	struct i2c_client *client;
+};
+
+/* Init sequence taken from the android driver */
+static int dmard10_reset(struct i2c_client *client)
+{
+	unsigned char buffer[7];
+	int ret;
+
+	/* 1. Powerdown reset */
+	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_PD,
+						DMARD10_VALUE_PD_RST);
+	if (ret < 0)
+		return ret;
+
+	/*
+	 * 2. ACTR => Standby mode => Download OTP to parameter reg =>
+	 *    Standby mode => Reset data path => Standby mode
+	 */
+	buffer[0] = DMARD10_REG_ACTR;
+	buffer[1] = DMARD10_MODE_STANDBY;
+	buffer[2] = DMARD10_MODE_READ_OTP;
+	buffer[3] = DMARD10_MODE_STANDBY;
+	buffer[4] = DMARD10_MODE_RESET_DATA_PATH;
+	buffer[5] = DMARD10_MODE_STANDBY;
+	ret = i2c_master_send(client, buffer, 6);
+	if (ret < 0)
+		return ret;
+
+	/* 3. OSCA_EN = 1, TSTO = b'000 (INT1 = normal, TEST0 = normal) */
+	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_MISC2,
+						DMARD10_VALUE_MISC2_OSCA_EN);
+	if (ret < 0)
+		return ret;
+
+	/* 4. AFEN = 1 (AFE will powerdown after ADC) */
+	buffer[0] = DMARD10_REG_AFEM;
+	buffer[1] = DMARD10_VALUE_AFEM_AFEN_NORMAL;
+	buffer[2] = DMARD10_VALUE_CKSEL_ODR_100_204;
+	buffer[3] = DMARD10_VALUE_INTC;
+	buffer[4] = DMARD10_VALUE_TAPNS_AVE_2;
+	buffer[5] = 0x00; /* DLYC, no delay timing */
+	buffer[6] = 0x07; /* INTD=1 push-pull, INTA=1 active high, AUTOT=1 */
+	ret = i2c_master_send(client, buffer, 7);
+	if (ret < 0)
+		return ret;
+
+	/* 5. Activation mode */
+	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_ACTR,
+						DMARD10_MODE_ACTIVE);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* Shutdown sequence taken from the android driver */
+static int dmard10_shutdown(struct i2c_client *client)
+{
+	unsigned char buffer[3];
+
+	buffer[0] = DMARD10_REG_ACTR;
+	buffer[1] = DMARD10_MODE_STANDBY;
+	buffer[2] = DMARD10_MODE_OFF;
+
+	return i2c_master_send(client, buffer, 3);
+}
+
+static int dmard10_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct dmard10_data *data = iio_priv(indio_dev);
+	__le16 buf[4];
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		/*
+		 * Read 8 bytes starting at the REG_STADR register, trying to
+		 * read the individual X, Y, Z registers will always read 0.
+		 */
+		ret = i2c_smbus_read_i2c_block_data(data->client,
+						    DMARD10_REG_STADR,
+						    sizeof(buf), (u8 *)buf);
+		if (ret < 0)
+			return ret;
+		ret = le16_to_cpu(buf[chan->address]);
+		*val = sign_extend32(ret, 12);
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = dmard10_nscale;
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info dmard10_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= dmard10_read_raw,
+};
+
+static int dmard10_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct iio_dev *indio_dev;
+	struct dmard10_data *data;
+
+	/* These 2 registers have special POR reset values used for id */
+	ret = i2c_smbus_read_byte_data(client, DMARD10_REG_STADR);
+	if (ret != DMARD10_VALUE_STADR)
+		return (ret < 0) ? ret : -ENODEV;
+
+	ret = i2c_smbus_read_byte_data(client, DMARD10_REG_STAINT);
+	if (ret != DMARD10_VALUE_STAINT)
+		return (ret < 0) ? ret : -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev) {
+		dev_err(&client->dev, "iio allocation failed!\n");
+		return -ENOMEM;
+	}
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	i2c_set_clientdata(client, indio_dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &dmard10_info;
+	indio_dev->name = "dmard10";
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = dmard10_channels;
+	indio_dev->num_channels = ARRAY_SIZE(dmard10_channels);
+
+	ret = dmard10_reset(client);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "device_register failed\n");
+		dmard10_shutdown(client);
+	}
+
+	return ret;
+}
+
+static int dmard10_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+
+	return dmard10_shutdown(client);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int dmard10_suspend(struct device *dev)
+{
+	return dmard10_shutdown(to_i2c_client(dev));
+}
+
+static int dmard10_resume(struct device *dev)
+{
+	return dmard10_reset(to_i2c_client(dev));
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend, dmard10_resume);
+
+static const struct i2c_device_id dmard10_i2c_id[] = {
+	{"dmard10", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id);
+
+static struct i2c_driver dmard10_driver = {
+	.driver = {
+		.name = "dmard10",
+		.pm = &dmard10_pm_ops,
+	},
+	.probe		= dmard10_probe,
+	.remove		= dmard10_remove,
+	.id_table	= dmard10_i2c_id,
+};
+
+module_i2c_driver(dmard10_driver);
+
+MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
+MODULE_DESCRIPTION("Domintech ARD10 3-Axis Accelerometer driver");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3

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

* [PATCH 3/4] iio: accel: Add driver for the MiraMEMS DA311 3-axis 12-bit digital accelerometer
       [not found] ` <20161008123426.8991-1-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2016-10-08 12:34   ` [PATCH 1/4] dt: bindings: i2c/trivial-devices.txt: Add 2 iio supported accelerometers Hans de Goede
  2016-10-08 12:34   ` [PATCH 2/4] iio: accel: Add driver for dmard10 3-axis Accelerometer Hans de Goede
@ 2016-10-08 12:34   ` Hans de Goede
       [not found]     ` <20161008123426.8991-4-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2016-10-08 12:34   ` [PATCH 4/4] iio: accel: Add driver for the MiraMEMS DA280 3-axis 14-bit " Hans de Goede
  3 siblings, 1 reply; 17+ messages in thread
From: Hans de Goede @ 2016-10-08 12:34 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree, Hans de Goede

This driver is based on the DA311 Android driver which can be found here:
https://git.matricom.net/Firmware/kernel_amlogic_meson-common/tree/1e70113a5befd07debb68f537156def84c5be57a/drivers/amlogic/input/sensor
the mir3da_* files are the DA311 driver.

Unfortunately there is no datasheet.

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
Changes in v2:
-Add proper prefix to patch Subject
-Use i2c_smbus_read_word_data() instead of i2c_smbus_read_i2c_block_data()
Changes in v3:
-Express unit in m/s^2 instead of in "G"
-Drop le16_to_cpu, i2c_smbus_read_word_data() already does this
---
 .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +
 drivers/iio/accel/Kconfig                          |  10 +
 drivers/iio/accel/Makefile                         |   1 +
 drivers/iio/accel/da311.c                          | 305 +++++++++++++++++++++
 4 files changed, 317 insertions(+)
 create mode 100644 drivers/iio/accel/da311.c

diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index 4689b31..b23ded3 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -124,6 +124,7 @@ microchip,mcp4662-502	Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem
 microchip,mcp4662-103	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
 microchip,mcp4662-503	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
 microchip,mcp4662-104	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
+miramems,da311		MiraMEMS DA311 3-axis 12-bit digital accelerometer
 national,lm63		Temperature sensor with integrated fan control
 national,lm75		I2C TEMP SENSOR
 national,lm80		Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 6236fd5..c94348f 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -52,6 +52,16 @@ config BMC150_ACCEL_SPI
 	tristate
 	select REGMAP_SPI
 
+config DA311
+	tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver"
+	depends on I2C
+	help
+	  Say yes here to build support for the MiraMEMS DA311 3-axis 12-bit
+	  digital accelerometer.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called da311.
+
 config DMARD06
 	tristate "Domintech DMARD06 Digital Accelerometer Driver"
 	depends on OF || COMPILE_TEST
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 9f51559..601ca59 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
 obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
 obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
+obj-$(CONFIG_DA311)	+= da311.o
 obj-$(CONFIG_DMARD06)	+= dmard06.o
 obj-$(CONFIG_DMARD09)	+= dmard09.o
 obj-$(CONFIG_DMARD10)	+= dmard10.o
diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c
new file mode 100644
index 0000000..537cfa8
--- /dev/null
+++ b/drivers/iio/accel/da311.c
@@ -0,0 +1,305 @@
+/**
+ * IIO driver for the MiraMEMS DA311 3-axis accelerometer
+ *
+ * Copyright (c) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+ * Copyright (c) 2011-2013 MiraMEMS Sensing Technology Co., Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/byteorder/generic.h>
+
+#define DA311_CHIP_ID			0x13
+
+/*
+ * Note register addressed go from 0 - 0x3f and then wrap.
+ * For some reason there are 2 banks with 0 - 0x3f addresses,
+ * rather then a single 0-0x7f bank.
+ */
+
+/* Bank 0 regs */
+#define DA311_REG_BANK			0x0000
+#define DA311_REG_LDO_REG		0x0006
+#define DA311_REG_CHIP_ID		0x000f
+#define DA311_REG_TEMP_CFG_REG		0x001f
+#define DA311_REG_CTRL_REG1		0x0020
+#define DA311_REG_CTRL_REG3		0x0022
+#define DA311_REG_CTRL_REG4		0x0023
+#define DA311_REG_CTRL_REG5		0x0024
+#define DA311_REG_CTRL_REG6		0x0025
+#define DA311_REG_STATUS_REG		0x0027
+#define DA311_REG_OUT_X_L		0x0028
+#define DA311_REG_OUT_X_H		0x0029
+#define DA311_REG_OUT_Y_L		0x002a
+#define DA311_REG_OUT_Y_H		0x002b
+#define DA311_REG_OUT_Z_L		0x002c
+#define DA311_REG_OUT_Z_H		0x002d
+#define DA311_REG_INT1_CFG		0x0030
+#define DA311_REG_INT1_SRC		0x0031
+#define DA311_REG_INT1_THS		0x0032
+#define DA311_REG_INT1_DURATION		0x0033
+#define DA311_REG_INT2_CFG		0x0034
+#define DA311_REG_INT2_SRC		0x0035
+#define DA311_REG_INT2_THS		0x0036
+#define DA311_REG_INT2_DURATION		0x0037
+#define DA311_REG_CLICK_CFG		0x0038
+#define DA311_REG_CLICK_SRC		0x0039
+#define DA311_REG_CLICK_THS		0x003a
+#define DA311_REG_TIME_LIMIT		0x003b
+#define DA311_REG_TIME_LATENCY		0x003c
+#define DA311_REG_TIME_WINDOW		0x003d
+
+/* Bank 1 regs */
+#define DA311_REG_SOFT_RESET		0x0105
+#define DA311_REG_OTP_XOFF_L		0x0110
+#define DA311_REG_OTP_XOFF_H		0x0111
+#define DA311_REG_OTP_YOFF_L		0x0112
+#define DA311_REG_OTP_YOFF_H		0x0113
+#define DA311_REG_OTP_ZOFF_L		0x0114
+#define DA311_REG_OTP_ZOFF_H		0x0115
+#define DA311_REG_OTP_XSO		0x0116
+#define DA311_REG_OTP_YSO		0x0117
+#define DA311_REG_OTP_ZSO		0x0118
+#define DA311_REG_OTP_TRIM_OSC		0x011b
+#define DA311_REG_LPF_ABSOLUTE		0x011c
+#define DA311_REG_TEMP_OFF1		0x0127
+#define DA311_REG_TEMP_OFF2		0x0128
+#define DA311_REG_TEMP_OFF3		0x0129
+#define DA311_REG_OTP_TRIM_THERM_H	0x011a
+
+/*
+ * a value of + or -1024 corresponds to + or - 1G
+ * scale = 9.81 / 1024 = 0.009580078
+ */
+
+static const int da311_nscale = 9580078;
+
+#define DA311_CHANNEL(reg, axis) {	\
+	.type = IIO_ACCEL,	\
+	.address = reg,	\
+	.modified = 1,	\
+	.channel2 = IIO_MOD_##axis,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec da311_channels[] = {
+	/* | 0x80 comes from the android driver */
+	DA311_CHANNEL(DA311_REG_OUT_X_L | 0x80, X),
+	DA311_CHANNEL(DA311_REG_OUT_Y_L | 0x80, Y),
+	DA311_CHANNEL(DA311_REG_OUT_Z_L | 0x80, Z),
+};
+
+struct da311_data {
+	struct i2c_client *client;
+};
+
+static int da311_register_mask_write(struct i2c_client *client, u16 addr,
+				     u8 mask, u8 data)
+{
+	int ret;
+	u8 tmp_data = 0;
+
+	if (addr & 0xff00) {
+		/* Select bank 1 */
+		ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x01);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (mask != 0xff) {
+		ret = i2c_smbus_read_byte_data(client, addr);
+		if (ret < 0)
+			return ret;
+		tmp_data = ret;
+	}
+
+	tmp_data &= ~mask;
+	tmp_data |= data & mask;
+	ret = i2c_smbus_write_byte_data(client, addr & 0xff, tmp_data);
+	if (ret < 0)
+		return ret;
+
+	if (addr & 0xff00) {
+		/* Back to bank 0 */
+		ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x00);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* Init sequence taken from the android driver */
+static int da311_reset(struct i2c_client *client)
+{
+	const struct {
+		u16 addr;
+		u8 mask;
+		u8 data;
+	} init_data[] = {
+		{ DA311_REG_TEMP_CFG_REG,       0xff,   0x08 },
+		{ DA311_REG_CTRL_REG5,          0xff,   0x80 },
+		{ DA311_REG_CTRL_REG4,          0x30,   0x00 },
+		{ DA311_REG_CTRL_REG1,          0xff,   0x6f },
+		{ DA311_REG_TEMP_CFG_REG,       0xff,   0x88 },
+		{ DA311_REG_LDO_REG,            0xff,   0x02 },
+		{ DA311_REG_OTP_TRIM_OSC,       0xff,   0x27 },
+		{ DA311_REG_LPF_ABSOLUTE,       0xff,   0x30 },
+		{ DA311_REG_TEMP_OFF1,          0xff,   0x3f },
+		{ DA311_REG_TEMP_OFF2,          0xff,   0xff },
+		{ DA311_REG_TEMP_OFF3,          0xff,   0x0f },
+	};
+	int i, ret;
+
+	/* Reset */
+	ret = da311_register_mask_write(client, DA311_REG_SOFT_RESET,
+					0xff, 0xaa);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < ARRAY_SIZE(init_data); i++) {
+		ret = da311_register_mask_write(client,
+						init_data[i].addr,
+						init_data[i].mask,
+						init_data[i].data);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int da311_enable(struct i2c_client *client, bool enable)
+{
+	u8 data = enable ? 0x00 : 0x20;
+
+	return da311_register_mask_write(client, DA311_REG_TEMP_CFG_REG,
+					 0x20, data);
+}
+
+static int da311_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct da311_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = i2c_smbus_read_word_data(data->client, chan->address);
+		if (ret < 0)
+			return ret;
+		/*
+		 * Values are 12 bits, stored as 16 bits with the 4
+		 * least significant bits always 0.
+		 */
+		*val = (short)ret >> 4;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = da311_nscale;
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info da311_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= da311_read_raw,
+};
+
+static int da311_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct iio_dev *indio_dev;
+	struct da311_data *data;
+
+	ret = i2c_smbus_read_byte_data(client, DA311_REG_CHIP_ID);
+	if (ret != DA311_CHIP_ID)
+		return (ret < 0) ? ret : -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	i2c_set_clientdata(client, indio_dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &da311_info;
+	indio_dev->name = "da311";
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = da311_channels;
+	indio_dev->num_channels = ARRAY_SIZE(da311_channels);
+
+	ret = da311_reset(client);
+	if (ret < 0)
+		return ret;
+
+	ret = da311_enable(client, true);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "device_register failed\n");
+		da311_enable(client, false);
+	}
+
+	return ret;
+}
+
+static int da311_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+
+	return da311_enable(client, false);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int da311_suspend(struct device *dev)
+{
+	return da311_enable(to_i2c_client(dev), false);
+}
+
+static int da311_resume(struct device *dev)
+{
+	return da311_enable(to_i2c_client(dev), true);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume);
+
+static const struct i2c_device_id da311_i2c_id[] = {
+	{"da311", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, da311_i2c_id);
+
+static struct i2c_driver da311_driver = {
+	.driver = {
+		.name = "da311",
+		.pm = &da311_pm_ops,
+	},
+	.probe		= da311_probe,
+	.remove		= da311_remove,
+	.id_table	= da311_i2c_id,
+};
+
+module_i2c_driver(da311_driver);
+
+MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
+MODULE_DESCRIPTION("MiraMEMS DA311 3-Axis Accelerometer driver");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH 4/4] iio: accel: Add driver for the MiraMEMS DA280 3-axis 14-bit digital accelerometer
       [not found] ` <20161008123426.8991-1-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
                     ` (2 preceding siblings ...)
  2016-10-08 12:34   ` [PATCH 3/4] iio: accel: Add driver for the MiraMEMS DA311 3-axis 12-bit digital accelerometer Hans de Goede
@ 2016-10-08 12:34   ` Hans de Goede
       [not found]     ` <20161008123426.8991-5-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  3 siblings, 1 reply; 17+ messages in thread
From: Hans de Goede @ 2016-10-08 12:34 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree, Hans de Goede

Add an iio driver for the MiraMEMS DA280 3-axis 14-bit accelerometer, as
well as for the DA226 which is a fully compatible 2-axis version.

Datasheets for the DA280 and DA226 can be found at the manufacturers site:
http://www.miramems.com/en/products.asp?list=1

Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
---
 .../devicetree/bindings/i2c/trivial-devices.txt    |   2 +
 drivers/iio/accel/Kconfig                          |  10 ++
 drivers/iio/accel/Makefile                         |   1 +
 drivers/iio/accel/da280.c                          | 183 +++++++++++++++++++++
 4 files changed, 196 insertions(+)
 create mode 100644 drivers/iio/accel/da280.c

diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
index b23ded3..6e4ba81 100644
--- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
+++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
@@ -124,6 +124,8 @@ microchip,mcp4662-502	Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem
 microchip,mcp4662-103	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
 microchip,mcp4662-503	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
 microchip,mcp4662-104	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
+miramems,da226		MiraMEMS DA226 2-axis 14-bit digital accelerometer
+miramems,da280		MiraMEMS DA280 3-axis 14-bit digital accelerometer
 miramems,da311		MiraMEMS DA311 3-axis 12-bit digital accelerometer
 national,lm63		Temperature sensor with integrated fan control
 national,lm75		I2C TEMP SENSOR
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index c94348f..c2ed6cf 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -52,6 +52,16 @@ config BMC150_ACCEL_SPI
 	tristate
 	select REGMAP_SPI
 
+config DA280
+	tristate "MiraMEMS DA280 3-axis 14-bit digital accelerometer driver"
+	depends on I2C
+	help
+	  Say yes here to build support for the MiraMEMS DA280 3-axis 14-bit
+	  digital accelerometer.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called da280.
+
 config DA311
 	tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver"
 	depends on I2C
diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
index 601ca59..b7a9ba7 100644
--- a/drivers/iio/accel/Makefile
+++ b/drivers/iio/accel/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o
 obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
 obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
 obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
+obj-$(CONFIG_DA280)	+= da280.o
 obj-$(CONFIG_DA311)	+= da311.o
 obj-$(CONFIG_DMARD06)	+= dmard06.o
 obj-$(CONFIG_DMARD09)	+= dmard09.o
diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c
new file mode 100644
index 0000000..7b1fe88
--- /dev/null
+++ b/drivers/iio/accel/da280.c
@@ -0,0 +1,183 @@
+/**
+ * IIO driver for the MiraMEMS DA280 3-axis accelerometer and
+ * IIO driver for the MiraMEMS DA226 2-axis accelerometer
+ *
+ * Copyright (c) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/byteorder/generic.h>
+
+#define DA280_REG_CHIP_ID		0x01
+#define DA280_REG_ACC_X_LSB		0x02
+#define DA280_REG_ACC_Y_LSB		0x04
+#define DA280_REG_ACC_Z_LSB		0x06
+#define DA280_REG_MODE_BW		0x11
+
+#define DA280_CHIP_ID			0x13
+#define DA280_MODE_ENABLE		0x1e
+#define DA280_MODE_DISABLE		0x9e
+
+enum { da226, da280 };
+
+/*
+ * a value of + or -4096 corresponds to + or - 1G
+ * scale = 9.81 / 4096 = 0.002395019
+ */
+
+static const int da280_nscale = 2395019;
+
+#define DA280_CHANNEL(reg, axis) {	\
+	.type = IIO_ACCEL,	\
+	.address = reg,	\
+	.modified = 1,	\
+	.channel2 = IIO_MOD_##axis,	\
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
+}
+
+static const struct iio_chan_spec da280_channels[] = {
+	DA280_CHANNEL(DA280_REG_ACC_X_LSB, X),
+	DA280_CHANNEL(DA280_REG_ACC_Y_LSB, Y),
+	DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z),
+};
+
+struct da280_data {
+	struct i2c_client *client;
+};
+
+static int da280_enable(struct i2c_client *client, bool enable)
+{
+	u8 data = enable ? DA280_MODE_ENABLE : DA280_MODE_DISABLE;
+
+	return i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW, data);
+}
+
+static int da280_read_raw(struct iio_dev *indio_dev,
+				struct iio_chan_spec const *chan,
+				int *val, int *val2, long mask)
+{
+	struct da280_data *data = iio_priv(indio_dev);
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = i2c_smbus_read_word_data(data->client, chan->address);
+		if (ret < 0)
+			return ret;
+		/*
+		 * Values are 14 bits, stored as 16 bits with the 2
+		 * least significant bits always 0.
+		 */
+		*val = ((short)le16_to_cpu(ret)) >> 2;
+		return IIO_VAL_INT;
+	case IIO_CHAN_INFO_SCALE:
+		*val = 0;
+		*val2 = da280_nscale;
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info da280_info = {
+	.driver_module	= THIS_MODULE,
+	.read_raw	= da280_read_raw,
+};
+
+static int da280_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	int ret;
+	struct iio_dev *indio_dev;
+	struct da280_data *data;
+
+	ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
+	if (ret != DA280_CHIP_ID)
+		return (ret < 0) ? ret : -ENODEV;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	data = iio_priv(indio_dev);
+	data->client = client;
+	i2c_set_clientdata(client, indio_dev);
+
+	indio_dev->dev.parent = &client->dev;
+	indio_dev->info = &da280_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = da280_channels;
+	if (id->driver_data == da226) {
+		indio_dev->name = "da226";
+		indio_dev->num_channels = 2;
+	} else {
+		indio_dev->name = "da280";
+		indio_dev->num_channels = 3;
+	}
+
+	ret = da280_enable(client, true);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "device_register failed\n");
+		da280_enable(client, false);
+	}
+
+	return ret;
+}
+
+static int da280_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+
+	return da280_enable(client, false);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int da280_suspend(struct device *dev)
+{
+	return da280_enable(to_i2c_client(dev), false);
+}
+
+static int da280_resume(struct device *dev)
+{
+	return da280_enable(to_i2c_client(dev), true);
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);
+
+static const struct i2c_device_id da280_i2c_id[] = {
+	{ "da226", da226 },
+	{ "da280", da280 },
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
+
+static struct i2c_driver da280_driver = {
+	.driver = {
+		.name = "da280",
+		.pm = &da280_pm_ops,
+	},
+	.probe		= da280_probe,
+	.remove		= da280_remove,
+	.id_table	= da280_i2c_id,
+};
+
+module_i2c_driver(da280_driver);
+
+MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
+MODULE_DESCRIPTION("MiraMEMS DA280 3-Axis Accelerometer driver");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3

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

* Re: [PATCH 1/4] dt: bindings: i2c/trivial-devices.txt: Add 2 iio supported accelerometers
       [not found]     ` <20161008123426.8991-2-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2016-10-08 17:02       ` Jonathan Cameron
  2016-10-10 21:40       ` Rob Herring
  1 sibling, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2016-10-08 17:02 UTC (permalink / raw)
  To: Hans de Goede, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

On 08/10/16 13:34, Hans de Goede wrote:
> Add compatible strings for 2 accelerometers which follow the trivial
> i2c device bindings and have been supported by the iio subsystem for
> a while now.
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Applied and pushed out as testing for the autobuilders to ignore it ;)

Thanks,

Jonathan
> ---
>  Documentation/devicetree/bindings/i2c/trivial-devices.txt | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> index fbbad64..ce9db50 100644
> --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> @@ -44,6 +44,7 @@ epson,rx8025		High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE
>  epson,rx8581		I2C-BUS INTERFACE REAL TIME CLOCK MODULE
>  fsl,mag3110		MAG3110: Xtrinsic High Accuracy, 3D Magnetometer
>  fsl,mc13892		MC13892: Power Management Integrated Circuit (PMIC) for i.MX35/51
> +fsl,mma7660		MMA7660FC: 3-Axis Orientation/Motion Detection Sensor
>  fsl,mma8450		MMA8450Q: Xtrinsic Low-power, 3-axis Xtrinsic Accelerometer
>  fsl,mpl3115		MPL3115: Absolute Digital Pressure Sensor
>  fsl,mpr121		MPR121: Proximity Capacitive Touch Sensor Controller
> @@ -57,6 +58,7 @@ maxim,max1237		Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
>  maxim,max6625		9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
>  mc,rv3029c2		Real Time Clock Module with I2C-Bus
>  mcube,mc3230		mCube 3-axis 8-bit digital accelerometer
> +memsic,mxc6225		MEMSIC 2-axis 8-bit digital accelerometer
>  microchip,mcp4531-502	Microchip 7-bit Single I2C Digital Potentiometer (5k)
>  microchip,mcp4531-103	Microchip 7-bit Single I2C Digital Potentiometer (10k)
>  microchip,mcp4531-503	Microchip 7-bit Single I2C Digital Potentiometer (50k)
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/4] iio: accel: Add driver for dmard10 3-axis Accelerometer
       [not found]     ` <20161008123426.8991-3-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2016-10-08 17:10       ` Jonathan Cameron
  2016-10-10 21:41       ` Rob Herring
  1 sibling, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2016-10-08 17:10 UTC (permalink / raw)
  To: Hans de Goede, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

On 08/10/16 13:34, Hans de Goede wrote:
> Add a driver for the Domintech ARD10 3-axis Accelerometer, based on the
> android driver found here: https://github.com/domintech/dmard10
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
> Changes in v2:
> -prefix all defines with DMARD10_ and uppercase them all
> -Cleanup typography of some comments
> -Use defines for offsets in databuffer
> -Use i2c_smbus_write_byte_data() where applicable
> -Reduce unnecessarily large buffer size in dmard10_shutdown()
> -Use __le16 buffer in dmard10_read_raw()
> Changes in v3:
> -Express unit in m/s^2 instead of in "G"
Looks good to me. I thought about leaving it for a few days, but as the change
is so minor I would guess anyone who cared would have had plenty of time
to look at V2.

It'll be sat in my testing branch until next weekend anyway if anyone does
get a chance to take a look!

Applied to the togreg branch of iio.git and pushed out as testing for
the autobuilders to play with it.

Thanks. Another nice neat little driver.  Will be interesting to see
if anyone wants to ultimately try doing 'push' type data flows on these
devices.  Easy to add later though and I always like the approach where
the driver gains that feature after we are sure the simple stuff is
working well.

Jonathan
> ---
>  .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +
>  drivers/iio/accel/Kconfig                          |  10 +
>  drivers/iio/accel/Makefile                         |   1 +
>  drivers/iio/accel/dmard10.c                        | 266 +++++++++++++++++++++
>  4 files changed, 278 insertions(+)
>  create mode 100644 drivers/iio/accel/dmard10.c
> 
> diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> index ce9db50..4689b31 100644
> --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> @@ -39,6 +39,7 @@ dallas,ds75		Digital Thermometer and Thermostat
>  dlg,da9053		DA9053: flexible system level PMIC with multicore support
>  dlg,da9063		DA9063: system PMIC for quad-core application processors
>  domintech,dmard09	DMARD09: 3-axis Accelerometer
> +domintech,dmard10	DMARD10: 3-axis Accelerometer
>  epson,rx8010		I2C-BUS INTERFACE REAL TIME CLOCK MODULE
>  epson,rx8025		High-Stability. I2C-Bus INTERFACE REAL TIME CLOCK MODULE
>  epson,rx8581		I2C-BUS INTERFACE REAL TIME CLOCK MODULE
> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> index 6bf1b64..6236fd5 100644
> --- a/drivers/iio/accel/Kconfig
> +++ b/drivers/iio/accel/Kconfig
> @@ -73,6 +73,16 @@ config DMARD09
>  	  Choosing M will build the driver as a module. If so, the module
>  	  will be called dmard09.
>  
> +config DMARD10
> +	tristate "Domintech DMARD10 3-axis Accelerometer Driver"
> +	depends on I2C
> +	help
> +	  Say yes here to get support for the Domintech DMARD10 3-axis
> +	  accelerometer.
> +
> +	  Choosing M will build the driver as a module. If so, the module
> +	  will be called dmard10.
> +
>  config HID_SENSOR_ACCEL_3D
>  	depends on HID_SENSOR_HUB
>  	select IIO_BUFFER
> diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
> index 07a0c72..9f51559 100644
> --- a/drivers/iio/accel/Makefile
> +++ b/drivers/iio/accel/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
>  obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
>  obj-$(CONFIG_DMARD06)	+= dmard06.o
>  obj-$(CONFIG_DMARD09)	+= dmard09.o
> +obj-$(CONFIG_DMARD10)	+= dmard10.o
>  obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
>  obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
>  obj-$(CONFIG_KXSD9)	+= kxsd9.o
> diff --git a/drivers/iio/accel/dmard10.c b/drivers/iio/accel/dmard10.c
> new file mode 100644
> index 0000000..b8736cc
> --- /dev/null
> +++ b/drivers/iio/accel/dmard10.c
> @@ -0,0 +1,266 @@
> +/**
> + * IIO driver for the 3-axis accelerometer Domintech ARD10.
> + *
> + * Copyright (c) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> + * Copyright (c) 2012 Domintech Technology Co., Ltd
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/i2c.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/byteorder/generic.h>
> +
> +#define DMARD10_REG_ACTR			0x00
> +#define DMARD10_REG_AFEM			0x0c
> +#define DMARD10_REG_STADR			0x12
> +#define DMARD10_REG_STAINT			0x1c
> +#define DMARD10_REG_MISC2			0x1f
> +#define DMARD10_REG_PD				0x21
> +
> +#define DMARD10_MODE_OFF			0x00
> +#define DMARD10_MODE_STANDBY			0x02
> +#define DMARD10_MODE_ACTIVE			0x06
> +#define DMARD10_MODE_READ_OTP			0x12
> +#define DMARD10_MODE_RESET_DATA_PATH		0x82
> +
> +/* AFEN set 1, ATM[2:0]=b'000 (normal), EN_Z/Y/X/T=1 */
> +#define DMARD10_VALUE_AFEM_AFEN_NORMAL		0x8f
> +/* ODR[3:0]=b'0111 (100Hz), CCK[3:0]=b'0100 (204.8kHZ) */
> +#define DMARD10_VALUE_CKSEL_ODR_100_204		0x74
> +/* INTC[6:5]=b'00 */
> +#define DMARD10_VALUE_INTC			0x00
> +/* TAP1/TAP2 Average 2 */
> +#define DMARD10_VALUE_TAPNS_AVE_2		0x11
> +
> +#define DMARD10_VALUE_STADR			0x55
> +#define DMARD10_VALUE_STAINT			0xaa
> +#define DMARD10_VALUE_MISC2_OSCA_EN		0x08
> +#define DMARD10_VALUE_PD_RST			0x52
> +
> +/* Offsets into the buffer read in dmard10_read_raw() */
> +#define DMARD10_X_OFFSET			1
> +#define DMARD10_Y_OFFSET			2
> +#define DMARD10_Z_OFFSET			3
> +
> +/*
> + * a value of + or -128 corresponds to + or - 1G
> + * scale = 9.81 / 128 = 0.076640625
> + */
> +
> +static const int dmard10_nscale = 76640625;
> +
> +#define DMARD10_CHANNEL(reg, axis) {	\
> +	.type = IIO_ACCEL,	\
> +	.address = reg,	\
> +	.modified = 1,	\
> +	.channel2 = IIO_MOD_##axis,	\
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
> +}
> +
> +static const struct iio_chan_spec dmard10_channels[] = {
> +	DMARD10_CHANNEL(DMARD10_X_OFFSET, X),
> +	DMARD10_CHANNEL(DMARD10_Y_OFFSET, Y),
> +	DMARD10_CHANNEL(DMARD10_Z_OFFSET, Z),
> +};
> +
> +struct dmard10_data {
> +	struct i2c_client *client;
> +};
> +
> +/* Init sequence taken from the android driver */
> +static int dmard10_reset(struct i2c_client *client)
> +{
> +	unsigned char buffer[7];
> +	int ret;
> +
> +	/* 1. Powerdown reset */
> +	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_PD,
> +						DMARD10_VALUE_PD_RST);
> +	if (ret < 0)
> +		return ret;
> +
> +	/*
> +	 * 2. ACTR => Standby mode => Download OTP to parameter reg =>
> +	 *    Standby mode => Reset data path => Standby mode
> +	 */
> +	buffer[0] = DMARD10_REG_ACTR;
> +	buffer[1] = DMARD10_MODE_STANDBY;
> +	buffer[2] = DMARD10_MODE_READ_OTP;
> +	buffer[3] = DMARD10_MODE_STANDBY;
> +	buffer[4] = DMARD10_MODE_RESET_DATA_PATH;
> +	buffer[5] = DMARD10_MODE_STANDBY;
> +	ret = i2c_master_send(client, buffer, 6);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* 3. OSCA_EN = 1, TSTO = b'000 (INT1 = normal, TEST0 = normal) */
> +	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_MISC2,
> +						DMARD10_VALUE_MISC2_OSCA_EN);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* 4. AFEN = 1 (AFE will powerdown after ADC) */
> +	buffer[0] = DMARD10_REG_AFEM;
> +	buffer[1] = DMARD10_VALUE_AFEM_AFEN_NORMAL;
> +	buffer[2] = DMARD10_VALUE_CKSEL_ODR_100_204;
> +	buffer[3] = DMARD10_VALUE_INTC;
> +	buffer[4] = DMARD10_VALUE_TAPNS_AVE_2;
> +	buffer[5] = 0x00; /* DLYC, no delay timing */
> +	buffer[6] = 0x07; /* INTD=1 push-pull, INTA=1 active high, AUTOT=1 */
> +	ret = i2c_master_send(client, buffer, 7);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* 5. Activation mode */
> +	ret = i2c_smbus_write_byte_data(client, DMARD10_REG_ACTR,
> +						DMARD10_MODE_ACTIVE);
> +	if (ret < 0)
> +		return ret;
> +
> +	return 0;
> +}
> +
> +/* Shutdown sequence taken from the android driver */
> +static int dmard10_shutdown(struct i2c_client *client)
> +{
> +	unsigned char buffer[3];
> +
> +	buffer[0] = DMARD10_REG_ACTR;
> +	buffer[1] = DMARD10_MODE_STANDBY;
> +	buffer[2] = DMARD10_MODE_OFF;
> +
> +	return i2c_master_send(client, buffer, 3);
> +}
> +
> +static int dmard10_read_raw(struct iio_dev *indio_dev,
> +				struct iio_chan_spec const *chan,
> +				int *val, int *val2, long mask)
> +{
> +	struct dmard10_data *data = iio_priv(indio_dev);
> +	__le16 buf[4];
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		/*
> +		 * Read 8 bytes starting at the REG_STADR register, trying to
> +		 * read the individual X, Y, Z registers will always read 0.
> +		 */
> +		ret = i2c_smbus_read_i2c_block_data(data->client,
> +						    DMARD10_REG_STADR,
> +						    sizeof(buf), (u8 *)buf);
> +		if (ret < 0)
> +			return ret;
> +		ret = le16_to_cpu(buf[chan->address]);
> +		*val = sign_extend32(ret, 12);
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = 0;
> +		*val2 = dmard10_nscale;
> +		return IIO_VAL_INT_PLUS_NANO;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static const struct iio_info dmard10_info = {
> +	.driver_module	= THIS_MODULE,
> +	.read_raw	= dmard10_read_raw,
> +};
> +
> +static int dmard10_probe(struct i2c_client *client,
> +			const struct i2c_device_id *id)
> +{
> +	int ret;
> +	struct iio_dev *indio_dev;
> +	struct dmard10_data *data;
> +
> +	/* These 2 registers have special POR reset values used for id */
> +	ret = i2c_smbus_read_byte_data(client, DMARD10_REG_STADR);
> +	if (ret != DMARD10_VALUE_STADR)
> +		return (ret < 0) ? ret : -ENODEV;
> +
> +	ret = i2c_smbus_read_byte_data(client, DMARD10_REG_STAINT);
> +	if (ret != DMARD10_VALUE_STAINT)
> +		return (ret < 0) ? ret : -ENODEV;
> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> +	if (!indio_dev) {
> +		dev_err(&client->dev, "iio allocation failed!\n");
> +		return -ENOMEM;
> +	}
> +
> +	data = iio_priv(indio_dev);
> +	data->client = client;
> +	i2c_set_clientdata(client, indio_dev);
> +
> +	indio_dev->dev.parent = &client->dev;
> +	indio_dev->info = &dmard10_info;
> +	indio_dev->name = "dmard10";
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = dmard10_channels;
> +	indio_dev->num_channels = ARRAY_SIZE(dmard10_channels);
> +
> +	ret = dmard10_reset(client);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "device_register failed\n");
> +		dmard10_shutdown(client);
> +	}
> +
> +	return ret;
> +}
> +
> +static int dmard10_remove(struct i2c_client *client)
> +{
> +	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> +	iio_device_unregister(indio_dev);
> +
> +	return dmard10_shutdown(client);
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int dmard10_suspend(struct device *dev)
> +{
> +	return dmard10_shutdown(to_i2c_client(dev));
> +}
> +
> +static int dmard10_resume(struct device *dev)
> +{
> +	return dmard10_reset(to_i2c_client(dev));
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(dmard10_pm_ops, dmard10_suspend, dmard10_resume);
> +
> +static const struct i2c_device_id dmard10_i2c_id[] = {
> +	{"dmard10", 0},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, dmard10_i2c_id);
> +
> +static struct i2c_driver dmard10_driver = {
> +	.driver = {
> +		.name = "dmard10",
> +		.pm = &dmard10_pm_ops,
> +	},
> +	.probe		= dmard10_probe,
> +	.remove		= dmard10_remove,
> +	.id_table	= dmard10_i2c_id,
> +};
> +
> +module_i2c_driver(dmard10_driver);
> +
> +MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
> +MODULE_DESCRIPTION("Domintech ARD10 3-Axis Accelerometer driver");
> +MODULE_LICENSE("GPL v2");
> 

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/4] iio: accel: Add driver for the MiraMEMS DA311 3-axis 12-bit digital accelerometer
       [not found]     ` <20161008123426.8991-4-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2016-10-08 17:14       ` Jonathan Cameron
  2016-10-10 21:41       ` Rob Herring
  1 sibling, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2016-10-08 17:14 UTC (permalink / raw)
  To: Hans de Goede, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

On 08/10/16 13:34, Hans de Goede wrote:
> This driver is based on the DA311 Android driver which can be found here:
> https://git.matricom.net/Firmware/kernel_amlogic_meson-common/tree/1e70113a5befd07debb68f537156def84c5be57a/drivers/amlogic/input/sensor
> the mir3da_* files are the DA311 driver.
> 
> Unfortunately there is no datasheet.
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Again, minor well defined changes from V2 so I'm happy to take
this without it staying on the list for long first.

Lars, plenty of time to add Reviewed-by/Acked-by if you
want to give them. Not to worry if not (though you and
all other reviewers never get enough credit in my view!)

Applied to the togreg branch of iio.git - initially pushed out
as testing for the autobuilders to play with it.

Thanks,

Jonathan
> ---
> Changes in v2:
> -Add proper prefix to patch Subject
> -Use i2c_smbus_read_word_data() instead of i2c_smbus_read_i2c_block_data()
> Changes in v3:
> -Express unit in m/s^2 instead of in "G"
> -Drop le16_to_cpu, i2c_smbus_read_word_data() already does this
> ---
>  .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +
>  drivers/iio/accel/Kconfig                          |  10 +
>  drivers/iio/accel/Makefile                         |   1 +
>  drivers/iio/accel/da311.c                          | 305 +++++++++++++++++++++
>  4 files changed, 317 insertions(+)
>  create mode 100644 drivers/iio/accel/da311.c
> 
> diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> index 4689b31..b23ded3 100644
> --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> @@ -124,6 +124,7 @@ microchip,mcp4662-502	Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem
>  microchip,mcp4662-103	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
>  microchip,mcp4662-503	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
>  microchip,mcp4662-104	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
> +miramems,da311		MiraMEMS DA311 3-axis 12-bit digital accelerometer
>  national,lm63		Temperature sensor with integrated fan control
>  national,lm75		I2C TEMP SENSOR
>  national,lm80		Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor
> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> index 6236fd5..c94348f 100644
> --- a/drivers/iio/accel/Kconfig
> +++ b/drivers/iio/accel/Kconfig
> @@ -52,6 +52,16 @@ config BMC150_ACCEL_SPI
>  	tristate
>  	select REGMAP_SPI
>  
> +config DA311
> +	tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver"
> +	depends on I2C
> +	help
> +	  Say yes here to build support for the MiraMEMS DA311 3-axis 12-bit
> +	  digital accelerometer.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called da311.
> +
>  config DMARD06
>  	tristate "Domintech DMARD06 Digital Accelerometer Driver"
>  	depends on OF || COMPILE_TEST
> diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
> index 9f51559..601ca59 100644
> --- a/drivers/iio/accel/Makefile
> +++ b/drivers/iio/accel/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o
>  obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
>  obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
>  obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
> +obj-$(CONFIG_DA311)	+= da311.o
>  obj-$(CONFIG_DMARD06)	+= dmard06.o
>  obj-$(CONFIG_DMARD09)	+= dmard09.o
>  obj-$(CONFIG_DMARD10)	+= dmard10.o
> diff --git a/drivers/iio/accel/da311.c b/drivers/iio/accel/da311.c
> new file mode 100644
> index 0000000..537cfa8
> --- /dev/null
> +++ b/drivers/iio/accel/da311.c
> @@ -0,0 +1,305 @@
> +/**
> + * IIO driver for the MiraMEMS DA311 3-axis accelerometer
> + *
> + * Copyright (c) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> + * Copyright (c) 2011-2013 MiraMEMS Sensing Technology Co., Ltd.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/i2c.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/byteorder/generic.h>
> +
> +#define DA311_CHIP_ID			0x13
> +
> +/*
> + * Note register addressed go from 0 - 0x3f and then wrap.
> + * For some reason there are 2 banks with 0 - 0x3f addresses,
> + * rather then a single 0-0x7f bank.
> + */
> +
> +/* Bank 0 regs */
> +#define DA311_REG_BANK			0x0000
> +#define DA311_REG_LDO_REG		0x0006
> +#define DA311_REG_CHIP_ID		0x000f
> +#define DA311_REG_TEMP_CFG_REG		0x001f
> +#define DA311_REG_CTRL_REG1		0x0020
> +#define DA311_REG_CTRL_REG3		0x0022
> +#define DA311_REG_CTRL_REG4		0x0023
> +#define DA311_REG_CTRL_REG5		0x0024
> +#define DA311_REG_CTRL_REG6		0x0025
> +#define DA311_REG_STATUS_REG		0x0027
> +#define DA311_REG_OUT_X_L		0x0028
> +#define DA311_REG_OUT_X_H		0x0029
> +#define DA311_REG_OUT_Y_L		0x002a
> +#define DA311_REG_OUT_Y_H		0x002b
> +#define DA311_REG_OUT_Z_L		0x002c
> +#define DA311_REG_OUT_Z_H		0x002d
> +#define DA311_REG_INT1_CFG		0x0030
> +#define DA311_REG_INT1_SRC		0x0031
> +#define DA311_REG_INT1_THS		0x0032
> +#define DA311_REG_INT1_DURATION		0x0033
> +#define DA311_REG_INT2_CFG		0x0034
> +#define DA311_REG_INT2_SRC		0x0035
> +#define DA311_REG_INT2_THS		0x0036
> +#define DA311_REG_INT2_DURATION		0x0037
> +#define DA311_REG_CLICK_CFG		0x0038
> +#define DA311_REG_CLICK_SRC		0x0039
> +#define DA311_REG_CLICK_THS		0x003a
> +#define DA311_REG_TIME_LIMIT		0x003b
> +#define DA311_REG_TIME_LATENCY		0x003c
> +#define DA311_REG_TIME_WINDOW		0x003d
> +
> +/* Bank 1 regs */
> +#define DA311_REG_SOFT_RESET		0x0105
> +#define DA311_REG_OTP_XOFF_L		0x0110
> +#define DA311_REG_OTP_XOFF_H		0x0111
> +#define DA311_REG_OTP_YOFF_L		0x0112
> +#define DA311_REG_OTP_YOFF_H		0x0113
> +#define DA311_REG_OTP_ZOFF_L		0x0114
> +#define DA311_REG_OTP_ZOFF_H		0x0115
> +#define DA311_REG_OTP_XSO		0x0116
> +#define DA311_REG_OTP_YSO		0x0117
> +#define DA311_REG_OTP_ZSO		0x0118
> +#define DA311_REG_OTP_TRIM_OSC		0x011b
> +#define DA311_REG_LPF_ABSOLUTE		0x011c
> +#define DA311_REG_TEMP_OFF1		0x0127
> +#define DA311_REG_TEMP_OFF2		0x0128
> +#define DA311_REG_TEMP_OFF3		0x0129
> +#define DA311_REG_OTP_TRIM_THERM_H	0x011a
> +
> +/*
> + * a value of + or -1024 corresponds to + or - 1G
> + * scale = 9.81 / 1024 = 0.009580078
> + */
> +
> +static const int da311_nscale = 9580078;
> +
> +#define DA311_CHANNEL(reg, axis) {	\
> +	.type = IIO_ACCEL,	\
> +	.address = reg,	\
> +	.modified = 1,	\
> +	.channel2 = IIO_MOD_##axis,	\
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
> +}
> +
> +static const struct iio_chan_spec da311_channels[] = {
> +	/* | 0x80 comes from the android driver */
> +	DA311_CHANNEL(DA311_REG_OUT_X_L | 0x80, X),
> +	DA311_CHANNEL(DA311_REG_OUT_Y_L | 0x80, Y),
> +	DA311_CHANNEL(DA311_REG_OUT_Z_L | 0x80, Z),
> +};
> +
> +struct da311_data {
> +	struct i2c_client *client;
> +};
> +
> +static int da311_register_mask_write(struct i2c_client *client, u16 addr,
> +				     u8 mask, u8 data)
> +{
> +	int ret;
> +	u8 tmp_data = 0;
> +
> +	if (addr & 0xff00) {
> +		/* Select bank 1 */
> +		ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x01);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	if (mask != 0xff) {
> +		ret = i2c_smbus_read_byte_data(client, addr);
> +		if (ret < 0)
> +			return ret;
> +		tmp_data = ret;
> +	}
> +
> +	tmp_data &= ~mask;
> +	tmp_data |= data & mask;
> +	ret = i2c_smbus_write_byte_data(client, addr & 0xff, tmp_data);
> +	if (ret < 0)
> +		return ret;
> +
> +	if (addr & 0xff00) {
> +		/* Back to bank 0 */
> +		ret = i2c_smbus_write_byte_data(client, DA311_REG_BANK, 0x00);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/* Init sequence taken from the android driver */
> +static int da311_reset(struct i2c_client *client)
> +{
> +	const struct {
> +		u16 addr;
> +		u8 mask;
> +		u8 data;
> +	} init_data[] = {
> +		{ DA311_REG_TEMP_CFG_REG,       0xff,   0x08 },
> +		{ DA311_REG_CTRL_REG5,          0xff,   0x80 },
> +		{ DA311_REG_CTRL_REG4,          0x30,   0x00 },
> +		{ DA311_REG_CTRL_REG1,          0xff,   0x6f },
> +		{ DA311_REG_TEMP_CFG_REG,       0xff,   0x88 },
> +		{ DA311_REG_LDO_REG,            0xff,   0x02 },
> +		{ DA311_REG_OTP_TRIM_OSC,       0xff,   0x27 },
> +		{ DA311_REG_LPF_ABSOLUTE,       0xff,   0x30 },
> +		{ DA311_REG_TEMP_OFF1,          0xff,   0x3f },
> +		{ DA311_REG_TEMP_OFF2,          0xff,   0xff },
> +		{ DA311_REG_TEMP_OFF3,          0xff,   0x0f },
> +	};
> +	int i, ret;
> +
> +	/* Reset */
> +	ret = da311_register_mask_write(client, DA311_REG_SOFT_RESET,
> +					0xff, 0xaa);
> +	if (ret < 0)
> +		return ret;
> +
> +	for (i = 0; i < ARRAY_SIZE(init_data); i++) {
> +		ret = da311_register_mask_write(client,
> +						init_data[i].addr,
> +						init_data[i].mask,
> +						init_data[i].data);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int da311_enable(struct i2c_client *client, bool enable)
> +{
> +	u8 data = enable ? 0x00 : 0x20;
> +
> +	return da311_register_mask_write(client, DA311_REG_TEMP_CFG_REG,
> +					 0x20, data);
> +}
> +
> +static int da311_read_raw(struct iio_dev *indio_dev,
> +				struct iio_chan_spec const *chan,
> +				int *val, int *val2, long mask)
> +{
> +	struct da311_data *data = iio_priv(indio_dev);
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		ret = i2c_smbus_read_word_data(data->client, chan->address);
> +		if (ret < 0)
> +			return ret;
> +		/*
> +		 * Values are 12 bits, stored as 16 bits with the 4
> +		 * least significant bits always 0.
> +		 */
> +		*val = (short)ret >> 4;
> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = 0;
> +		*val2 = da311_nscale;
> +		return IIO_VAL_INT_PLUS_NANO;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static const struct iio_info da311_info = {
> +	.driver_module	= THIS_MODULE,
> +	.read_raw	= da311_read_raw,
> +};
> +
> +static int da311_probe(struct i2c_client *client,
> +			const struct i2c_device_id *id)
> +{
> +	int ret;
> +	struct iio_dev *indio_dev;
> +	struct da311_data *data;
> +
> +	ret = i2c_smbus_read_byte_data(client, DA311_REG_CHIP_ID);
> +	if (ret != DA311_CHIP_ID)
> +		return (ret < 0) ? ret : -ENODEV;
> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	data = iio_priv(indio_dev);
> +	data->client = client;
> +	i2c_set_clientdata(client, indio_dev);
> +
> +	indio_dev->dev.parent = &client->dev;
> +	indio_dev->info = &da311_info;
> +	indio_dev->name = "da311";
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = da311_channels;
> +	indio_dev->num_channels = ARRAY_SIZE(da311_channels);
> +
> +	ret = da311_reset(client);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = da311_enable(client, true);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "device_register failed\n");
> +		da311_enable(client, false);
> +	}
> +
> +	return ret;
> +}
> +
> +static int da311_remove(struct i2c_client *client)
> +{
> +	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> +	iio_device_unregister(indio_dev);
> +
> +	return da311_enable(client, false);
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int da311_suspend(struct device *dev)
> +{
> +	return da311_enable(to_i2c_client(dev), false);
> +}
> +
> +static int da311_resume(struct device *dev)
> +{
> +	return da311_enable(to_i2c_client(dev), true);
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(da311_pm_ops, da311_suspend, da311_resume);
> +
> +static const struct i2c_device_id da311_i2c_id[] = {
> +	{"da311", 0},
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, da311_i2c_id);
> +
> +static struct i2c_driver da311_driver = {
> +	.driver = {
> +		.name = "da311",
> +		.pm = &da311_pm_ops,
> +	},
> +	.probe		= da311_probe,
> +	.remove		= da311_remove,
> +	.id_table	= da311_i2c_id,
> +};
> +
> +module_i2c_driver(da311_driver);
> +
> +MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
> +MODULE_DESCRIPTION("MiraMEMS DA311 3-Axis Accelerometer driver");
> +MODULE_LICENSE("GPL v2");
> 

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

* Re: [PATCH 4/4] iio: accel: Add driver for the MiraMEMS DA280 3-axis 14-bit digital accelerometer
       [not found]     ` <20161008123426.8991-5-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2016-10-08 17:17       ` Jonathan Cameron
       [not found]         ` <11db85a2-23a1-8f25-4ce1-061e88f02c32-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Jonathan Cameron @ 2016-10-08 17:17 UTC (permalink / raw)
  To: Hans de Goede, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

On 08/10/16 13:34, Hans de Goede wrote:
> Add an iio driver for the MiraMEMS DA280 3-axis 14-bit accelerometer, as
> well as for the DA226 which is a fully compatible 2-axis version.
> 
> Datasheets for the DA280 and DA226 can be found at the manufacturers site:
> http://www.miramems.com/en/products.asp?list=1
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
How many more of these devices do you have? :)

You have another unwanted le16_to_cpu conversion of data coming off
the back of an smbus word read.

Otherwise, looks good to me.

Jonathan
> ---
>  .../devicetree/bindings/i2c/trivial-devices.txt    |   2 +
>  drivers/iio/accel/Kconfig                          |  10 ++
>  drivers/iio/accel/Makefile                         |   1 +
>  drivers/iio/accel/da280.c                          | 183 +++++++++++++++++++++
>  4 files changed, 196 insertions(+)
>  create mode 100644 drivers/iio/accel/da280.c
> 
> diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> index b23ded3..6e4ba81 100644
> --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
> @@ -124,6 +124,8 @@ microchip,mcp4662-502	Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem
>  microchip,mcp4662-103	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
>  microchip,mcp4662-503	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
>  microchip,mcp4662-104	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
> +miramems,da226		MiraMEMS DA226 2-axis 14-bit digital accelerometer
> +miramems,da280		MiraMEMS DA280 3-axis 14-bit digital accelerometer
>  miramems,da311		MiraMEMS DA311 3-axis 12-bit digital accelerometer
>  national,lm63		Temperature sensor with integrated fan control
>  national,lm75		I2C TEMP SENSOR
> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
> index c94348f..c2ed6cf 100644
> --- a/drivers/iio/accel/Kconfig
> +++ b/drivers/iio/accel/Kconfig
> @@ -52,6 +52,16 @@ config BMC150_ACCEL_SPI
>  	tristate
>  	select REGMAP_SPI
>  
> +config DA280
> +	tristate "MiraMEMS DA280 3-axis 14-bit digital accelerometer driver"
> +	depends on I2C
> +	help
> +	  Say yes here to build support for the MiraMEMS DA280 3-axis 14-bit
> +	  digital accelerometer.
> +
> +	  To compile this driver as a module, choose M here: the
> +	  module will be called da280.
> +
>  config DA311
>  	tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver"
>  	depends on I2C
> diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
> index 601ca59..b7a9ba7 100644
> --- a/drivers/iio/accel/Makefile
> +++ b/drivers/iio/accel/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o
>  obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
>  obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
>  obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
> +obj-$(CONFIG_DA280)	+= da280.o
>  obj-$(CONFIG_DA311)	+= da311.o
>  obj-$(CONFIG_DMARD06)	+= dmard06.o
>  obj-$(CONFIG_DMARD09)	+= dmard09.o
> diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c
> new file mode 100644
> index 0000000..7b1fe88
> --- /dev/null
> +++ b/drivers/iio/accel/da280.c
> @@ -0,0 +1,183 @@
> +/**
> + * IIO driver for the MiraMEMS DA280 3-axis accelerometer and
> + * IIO driver for the MiraMEMS DA226 2-axis accelerometer
> + *
> + * Copyright (c) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/i2c.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/sysfs.h>
> +#include <linux/byteorder/generic.h>
> +
> +#define DA280_REG_CHIP_ID		0x01
> +#define DA280_REG_ACC_X_LSB		0x02
> +#define DA280_REG_ACC_Y_LSB		0x04
> +#define DA280_REG_ACC_Z_LSB		0x06
> +#define DA280_REG_MODE_BW		0x11
> +
> +#define DA280_CHIP_ID			0x13
> +#define DA280_MODE_ENABLE		0x1e
> +#define DA280_MODE_DISABLE		0x9e
> +
> +enum { da226, da280 };
> +
> +/*
> + * a value of + or -4096 corresponds to + or - 1G
> + * scale = 9.81 / 4096 = 0.002395019
> + */
> +
> +static const int da280_nscale = 2395019;
> +
> +#define DA280_CHANNEL(reg, axis) {	\
> +	.type = IIO_ACCEL,	\
> +	.address = reg,	\
> +	.modified = 1,	\
> +	.channel2 = IIO_MOD_##axis,	\
> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
> +}
> +
> +static const struct iio_chan_spec da280_channels[] = {
> +	DA280_CHANNEL(DA280_REG_ACC_X_LSB, X),
> +	DA280_CHANNEL(DA280_REG_ACC_Y_LSB, Y),
> +	DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z),
> +};
> +
> +struct da280_data {
> +	struct i2c_client *client;
> +};
> +
> +static int da280_enable(struct i2c_client *client, bool enable)
> +{
> +	u8 data = enable ? DA280_MODE_ENABLE : DA280_MODE_DISABLE;
> +
> +	return i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW, data);
> +}
> +
> +static int da280_read_raw(struct iio_dev *indio_dev,
> +				struct iio_chan_spec const *chan,
> +				int *val, int *val2, long mask)
> +{
> +	struct da280_data *data = iio_priv(indio_dev);
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		ret = i2c_smbus_read_word_data(data->client, chan->address);
> +		if (ret < 0)
> +			return ret;
> +		/*
> +		 * Values are 14 bits, stored as 16 bits with the 2
> +		 * least significant bits always 0.
> +		 */
> +		*val = ((short)le16_to_cpu(ret)) >> 2;
Same thing Lars picked up on before I think...  It's already in cpu endian.

> +		return IIO_VAL_INT;
> +	case IIO_CHAN_INFO_SCALE:
> +		*val = 0;
> +		*val2 = da280_nscale;
> +		return IIO_VAL_INT_PLUS_NANO;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static const struct iio_info da280_info = {
> +	.driver_module	= THIS_MODULE,
> +	.read_raw	= da280_read_raw,
> +};
> +
> +static int da280_probe(struct i2c_client *client,
> +			const struct i2c_device_id *id)
> +{
> +	int ret;
> +	struct iio_dev *indio_dev;
> +	struct da280_data *data;
> +
> +	ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
> +	if (ret != DA280_CHIP_ID)
> +		return (ret < 0) ? ret : -ENODEV;
> +
> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	data = iio_priv(indio_dev);
> +	data->client = client;
> +	i2c_set_clientdata(client, indio_dev);
> +
> +	indio_dev->dev.parent = &client->dev;
> +	indio_dev->info = &da280_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = da280_channels;
> +	if (id->driver_data == da226) {
> +		indio_dev->name = "da226";
> +		indio_dev->num_channels = 2;
> +	} else {
> +		indio_dev->name = "da280";
> +		indio_dev->num_channels = 3;
> +	}
> +
> +	ret = da280_enable(client, true);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "device_register failed\n");
> +		da280_enable(client, false);
> +	}
> +
> +	return ret;
> +}
> +
> +static int da280_remove(struct i2c_client *client)
> +{
> +	struct iio_dev *indio_dev = i2c_get_clientdata(client);
> +
> +	iio_device_unregister(indio_dev);
> +
> +	return da280_enable(client, false);
> +}
> +
> +#ifdef CONFIG_PM_SLEEP
> +static int da280_suspend(struct device *dev)
> +{
> +	return da280_enable(to_i2c_client(dev), false);
> +}
> +
> +static int da280_resume(struct device *dev)
> +{
> +	return da280_enable(to_i2c_client(dev), true);
> +}
> +#endif
> +
> +static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);
> +
> +static const struct i2c_device_id da280_i2c_id[] = {
> +	{ "da226", da226 },
> +	{ "da280", da280 },
> +	{}
> +};
> +MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
> +
> +static struct i2c_driver da280_driver = {
> +	.driver = {
> +		.name = "da280",
> +		.pm = &da280_pm_ops,
> +	},
> +	.probe		= da280_probe,
> +	.remove		= da280_remove,
> +	.id_table	= da280_i2c_id,
> +};
> +
> +module_i2c_driver(da280_driver);
> +
> +MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
> +MODULE_DESCRIPTION("MiraMEMS DA280 3-Axis Accelerometer driver");
> +MODULE_LICENSE("GPL v2");
> 

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

* Re: [PATCH 4/4] iio: accel: Add driver for the MiraMEMS DA280 3-axis 14-bit digital accelerometer
       [not found]         ` <11db85a2-23a1-8f25-4ce1-061e88f02c32-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
@ 2016-10-08 18:02           ` Hans de Goede
       [not found]             ` <c7959854-781d-699b-3bde-8a8edc0e32a6-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 17+ messages in thread
From: Hans de Goede @ 2016-10-08 18:02 UTC (permalink / raw)
  To: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

Hi,

On 08-10-16 19:17, Jonathan Cameron wrote:
> On 08/10/16 13:34, Hans de Goede wrote:
>> Add an iio driver for the MiraMEMS DA280 3-axis 14-bit accelerometer, as
>> well as for the DA226 which is a fully compatible 2-axis version.
>>
>> Datasheets for the DA280 and DA226 can be found at the manufacturers site:
>> http://www.miramems.com/en/products.asp?list=1
>>
>> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> How many more of these devices do you have? :)

I own 13 identical (on the outside) 7" android tablets with an
Allwinner A13/A23/A33 SoC, and I've access to 3 friends of mine own.

And I'm trying to run Fedora with the mainline kernel on all 16 of them.
I'm actually working on hardware auto-detection for devicetree to deal
with the internal differences these "identical" tablets have, see:

https://openiotelceurope2016.sched.org/event/7rqw/devicetree-hardware-autoconfiguration-hans-de-goede-red-hat?iframe=no&w=i:100;&sidebar=yes&bg=no

I've the accelerometer working on all of them (now), so this should
be my last patch for a while. Although I do plan to add orientation
support to all the accel drivers used in those tablets, so I
guess that will be another round of patches.

> You have another unwanted le16_to_cpu conversion of data coming off
> the back of an smbus word read.

Ugh, I distinctly remember thinking that I needed to take that
out in this driver too, but clearly I did not. I'll post a fixed
v2 soon.

> Otherwise, looks good to me.

Thank you for the quick response and review. I must say I find
the iio subsys a very welcoming subsys to contribute too.

Regards,

Hans


>
> Jonathan
>> ---
>>  .../devicetree/bindings/i2c/trivial-devices.txt    |   2 +
>>  drivers/iio/accel/Kconfig                          |  10 ++
>>  drivers/iio/accel/Makefile                         |   1 +
>>  drivers/iio/accel/da280.c                          | 183 +++++++++++++++++++++
>>  4 files changed, 196 insertions(+)
>>  create mode 100644 drivers/iio/accel/da280.c
>>
>> diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
>> index b23ded3..6e4ba81 100644
>> --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
>> +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
>> @@ -124,6 +124,8 @@ microchip,mcp4662-502	Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem
>>  microchip,mcp4662-103	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
>>  microchip,mcp4662-503	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
>>  microchip,mcp4662-104	Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
>> +miramems,da226		MiraMEMS DA226 2-axis 14-bit digital accelerometer
>> +miramems,da280		MiraMEMS DA280 3-axis 14-bit digital accelerometer
>>  miramems,da311		MiraMEMS DA311 3-axis 12-bit digital accelerometer
>>  national,lm63		Temperature sensor with integrated fan control
>>  national,lm75		I2C TEMP SENSOR
>> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
>> index c94348f..c2ed6cf 100644
>> --- a/drivers/iio/accel/Kconfig
>> +++ b/drivers/iio/accel/Kconfig
>> @@ -52,6 +52,16 @@ config BMC150_ACCEL_SPI
>>  	tristate
>>  	select REGMAP_SPI
>>
>> +config DA280
>> +	tristate "MiraMEMS DA280 3-axis 14-bit digital accelerometer driver"
>> +	depends on I2C
>> +	help
>> +	  Say yes here to build support for the MiraMEMS DA280 3-axis 14-bit
>> +	  digital accelerometer.
>> +
>> +	  To compile this driver as a module, choose M here: the
>> +	  module will be called da280.
>> +
>>  config DA311
>>  	tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver"
>>  	depends on I2C
>> diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
>> index 601ca59..b7a9ba7 100644
>> --- a/drivers/iio/accel/Makefile
>> +++ b/drivers/iio/accel/Makefile
>> @@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o
>>  obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
>>  obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
>>  obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
>> +obj-$(CONFIG_DA280)	+= da280.o
>>  obj-$(CONFIG_DA311)	+= da311.o
>>  obj-$(CONFIG_DMARD06)	+= dmard06.o
>>  obj-$(CONFIG_DMARD09)	+= dmard09.o
>> diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c
>> new file mode 100644
>> index 0000000..7b1fe88
>> --- /dev/null
>> +++ b/drivers/iio/accel/da280.c
>> @@ -0,0 +1,183 @@
>> +/**
>> + * IIO driver for the MiraMEMS DA280 3-axis accelerometer and
>> + * IIO driver for the MiraMEMS DA226 2-axis accelerometer
>> + *
>> + * Copyright (c) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms and conditions of the GNU General Public License,
>> + * version 2, as published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/i2c.h>
>> +#include <linux/iio/iio.h>
>> +#include <linux/iio/sysfs.h>
>> +#include <linux/byteorder/generic.h>
>> +
>> +#define DA280_REG_CHIP_ID		0x01
>> +#define DA280_REG_ACC_X_LSB		0x02
>> +#define DA280_REG_ACC_Y_LSB		0x04
>> +#define DA280_REG_ACC_Z_LSB		0x06
>> +#define DA280_REG_MODE_BW		0x11
>> +
>> +#define DA280_CHIP_ID			0x13
>> +#define DA280_MODE_ENABLE		0x1e
>> +#define DA280_MODE_DISABLE		0x9e
>> +
>> +enum { da226, da280 };
>> +
>> +/*
>> + * a value of + or -4096 corresponds to + or - 1G
>> + * scale = 9.81 / 4096 = 0.002395019
>> + */
>> +
>> +static const int da280_nscale = 2395019;
>> +
>> +#define DA280_CHANNEL(reg, axis) {	\
>> +	.type = IIO_ACCEL,	\
>> +	.address = reg,	\
>> +	.modified = 1,	\
>> +	.channel2 = IIO_MOD_##axis,	\
>> +	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
>> +	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
>> +}
>> +
>> +static const struct iio_chan_spec da280_channels[] = {
>> +	DA280_CHANNEL(DA280_REG_ACC_X_LSB, X),
>> +	DA280_CHANNEL(DA280_REG_ACC_Y_LSB, Y),
>> +	DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z),
>> +};
>> +
>> +struct da280_data {
>> +	struct i2c_client *client;
>> +};
>> +
>> +static int da280_enable(struct i2c_client *client, bool enable)
>> +{
>> +	u8 data = enable ? DA280_MODE_ENABLE : DA280_MODE_DISABLE;
>> +
>> +	return i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW, data);
>> +}
>> +
>> +static int da280_read_raw(struct iio_dev *indio_dev,
>> +				struct iio_chan_spec const *chan,
>> +				int *val, int *val2, long mask)
>> +{
>> +	struct da280_data *data = iio_priv(indio_dev);
>> +	int ret;
>> +
>> +	switch (mask) {
>> +	case IIO_CHAN_INFO_RAW:
>> +		ret = i2c_smbus_read_word_data(data->client, chan->address);
>> +		if (ret < 0)
>> +			return ret;
>> +		/*
>> +		 * Values are 14 bits, stored as 16 bits with the 2
>> +		 * least significant bits always 0.
>> +		 */
>> +		*val = ((short)le16_to_cpu(ret)) >> 2;
> Same thing Lars picked up on before I think...  It's already in cpu endian.
>
>> +		return IIO_VAL_INT;
>> +	case IIO_CHAN_INFO_SCALE:
>> +		*val = 0;
>> +		*val2 = da280_nscale;
>> +		return IIO_VAL_INT_PLUS_NANO;
>> +	default:
>> +		return -EINVAL;
>> +	}
>> +}
>> +
>> +static const struct iio_info da280_info = {
>> +	.driver_module	= THIS_MODULE,
>> +	.read_raw	= da280_read_raw,
>> +};
>> +
>> +static int da280_probe(struct i2c_client *client,
>> +			const struct i2c_device_id *id)
>> +{
>> +	int ret;
>> +	struct iio_dev *indio_dev;
>> +	struct da280_data *data;
>> +
>> +	ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
>> +	if (ret != DA280_CHIP_ID)
>> +		return (ret < 0) ? ret : -ENODEV;
>> +
>> +	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>> +	if (!indio_dev)
>> +		return -ENOMEM;
>> +
>> +	data = iio_priv(indio_dev);
>> +	data->client = client;
>> +	i2c_set_clientdata(client, indio_dev);
>> +
>> +	indio_dev->dev.parent = &client->dev;
>> +	indio_dev->info = &da280_info;
>> +	indio_dev->modes = INDIO_DIRECT_MODE;
>> +	indio_dev->channels = da280_channels;
>> +	if (id->driver_data == da226) {
>> +		indio_dev->name = "da226";
>> +		indio_dev->num_channels = 2;
>> +	} else {
>> +		indio_dev->name = "da280";
>> +		indio_dev->num_channels = 3;
>> +	}
>> +
>> +	ret = da280_enable(client, true);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	ret = iio_device_register(indio_dev);
>> +	if (ret < 0) {
>> +		dev_err(&client->dev, "device_register failed\n");
>> +		da280_enable(client, false);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +static int da280_remove(struct i2c_client *client)
>> +{
>> +	struct iio_dev *indio_dev = i2c_get_clientdata(client);
>> +
>> +	iio_device_unregister(indio_dev);
>> +
>> +	return da280_enable(client, false);
>> +}
>> +
>> +#ifdef CONFIG_PM_SLEEP
>> +static int da280_suspend(struct device *dev)
>> +{
>> +	return da280_enable(to_i2c_client(dev), false);
>> +}
>> +
>> +static int da280_resume(struct device *dev)
>> +{
>> +	return da280_enable(to_i2c_client(dev), true);
>> +}
>> +#endif
>> +
>> +static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);
>> +
>> +static const struct i2c_device_id da280_i2c_id[] = {
>> +	{ "da226", da226 },
>> +	{ "da280", da280 },
>> +	{}
>> +};
>> +MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
>> +
>> +static struct i2c_driver da280_driver = {
>> +	.driver = {
>> +		.name = "da280",
>> +		.pm = &da280_pm_ops,
>> +	},
>> +	.probe		= da280_probe,
>> +	.remove		= da280_remove,
>> +	.id_table	= da280_i2c_id,
>> +};
>> +
>> +module_i2c_driver(da280_driver);
>> +
>> +MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
>> +MODULE_DESCRIPTION("MiraMEMS DA280 3-Axis Accelerometer driver");
>> +MODULE_LICENSE("GPL v2");
>>
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 4/4] iio: accel: Add driver for the MiraMEMS DA280 3-axis 14-bit digital accelerometer
       [not found]             ` <c7959854-781d-699b-3bde-8a8edc0e32a6-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2016-10-09  7:22               ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2016-10-09  7:22 UTC (permalink / raw)
  To: Hans de Goede, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

On 08/10/16 19:02, Hans de Goede wrote:
> Hi,
> 
> On 08-10-16 19:17, Jonathan Cameron wrote:
>> On 08/10/16 13:34, Hans de Goede wrote:
>>> Add an iio driver for the MiraMEMS DA280 3-axis 14-bit accelerometer, as
>>> well as for the DA226 which is a fully compatible 2-axis version.
>>>
>>> Datasheets for the DA280 and DA226 can be found at the manufacturers site:
>>> http://www.miramems.com/en/products.asp?list=1
>>>
>>> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> How many more of these devices do you have? :)
> 
> I own 13 identical (on the outside) 7" android tablets with an
> Allwinner A13/A23/A33 SoC, and I've access to 3 friends of mine own.
> 
> And I'm trying to run Fedora with the mainline kernel on all 16 of them.
> I'm actually working on hardware auto-detection for devicetree to deal
> with the internal differences these "identical" tablets have, see:
> 
> https://openiotelceurope2016.sched.org/event/7rqw/devicetree-hardware-autoconfiguration-hans-de-goede-red-hat?iframe=no&w=i:100;&sidebar=yes&bg=no
> 
> I've the accelerometer working on all of them (now), so this should
> be my last patch for a while. Although I do plan to add orientation
> support to all the accel drivers used in those tablets, so I
> guess that will be another round of patches.
> 
>> You have another unwanted le16_to_cpu conversion of data coming off
>> the back of an smbus word read.
> 
> Ugh, I distinctly remember thinking that I needed to take that
> out in this driver too, but clearly I did not. I'll post a fixed
> v2 soon.
Meh, happens to us all :)
> 
>> Otherwise, looks good to me.
> 
> Thank you for the quick response and review. I must say I find
> the iio subsys a very welcoming subsys to contribute too.
It is indeed a nice corner of the kernel to work in.  If it
wasn't I'd have burnt out long ago!

Stuff like Daniel and co + now Alison mentoring outreachy
certainly helps + a steady stream of other people just getting
started keeps a level of enthusiasm going.  Might help that generally
the parts are cheap and getting something going as you've seen
is simple + we are in the classic (advanced) maker territory.

Anyhow, I thoroughly agree and would just like to add thanks
to everyone who does review - I wouldn't keep up (anywhere near)
without you all!

Anyhow enough soppy stuff - back to reviewing ;)

Jonathan
> 
> Regards,
> 
> Hans
> 
> 
>>
>> Jonathan
>>> ---
>>>  .../devicetree/bindings/i2c/trivial-devices.txt    |   2 +
>>>  drivers/iio/accel/Kconfig                          |  10 ++
>>>  drivers/iio/accel/Makefile                         |   1 +
>>>  drivers/iio/accel/da280.c                          | 183 +++++++++++++++++++++
>>>  4 files changed, 196 insertions(+)
>>>  create mode 100644 drivers/iio/accel/da280.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
>>> index b23ded3..6e4ba81 100644
>>> --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt
>>> +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt
>>> @@ -124,6 +124,8 @@ microchip,mcp4662-502    Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem
>>>  microchip,mcp4662-103    Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (10k)
>>>  microchip,mcp4662-503    Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (50k)
>>>  microchip,mcp4662-104    Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
>>> +miramems,da226        MiraMEMS DA226 2-axis 14-bit digital accelerometer
>>> +miramems,da280        MiraMEMS DA280 3-axis 14-bit digital accelerometer
>>>  miramems,da311        MiraMEMS DA311 3-axis 12-bit digital accelerometer
>>>  national,lm63        Temperature sensor with integrated fan control
>>>  national,lm75        I2C TEMP SENSOR
>>> diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
>>> index c94348f..c2ed6cf 100644
>>> --- a/drivers/iio/accel/Kconfig
>>> +++ b/drivers/iio/accel/Kconfig
>>> @@ -52,6 +52,16 @@ config BMC150_ACCEL_SPI
>>>      tristate
>>>      select REGMAP_SPI
>>>
>>> +config DA280
>>> +    tristate "MiraMEMS DA280 3-axis 14-bit digital accelerometer driver"
>>> +    depends on I2C
>>> +    help
>>> +      Say yes here to build support for the MiraMEMS DA280 3-axis 14-bit
>>> +      digital accelerometer.
>>> +
>>> +      To compile this driver as a module, choose M here: the
>>> +      module will be called da280.
>>> +
>>>  config DA311
>>>      tristate "MiraMEMS DA311 3-axis 12-bit digital accelerometer driver"
>>>      depends on I2C
>>> diff --git a/drivers/iio/accel/Makefile b/drivers/iio/accel/Makefile
>>> index 601ca59..b7a9ba7 100644
>>> --- a/drivers/iio/accel/Makefile
>>> +++ b/drivers/iio/accel/Makefile
>>> @@ -8,6 +8,7 @@ obj-$(CONFIG_BMA220) += bma220_spi.o
>>>  obj-$(CONFIG_BMC150_ACCEL) += bmc150-accel-core.o
>>>  obj-$(CONFIG_BMC150_ACCEL_I2C) += bmc150-accel-i2c.o
>>>  obj-$(CONFIG_BMC150_ACCEL_SPI) += bmc150-accel-spi.o
>>> +obj-$(CONFIG_DA280)    += da280.o
>>>  obj-$(CONFIG_DA311)    += da311.o
>>>  obj-$(CONFIG_DMARD06)    += dmard06.o
>>>  obj-$(CONFIG_DMARD09)    += dmard09.o
>>> diff --git a/drivers/iio/accel/da280.c b/drivers/iio/accel/da280.c
>>> new file mode 100644
>>> index 0000000..7b1fe88
>>> --- /dev/null
>>> +++ b/drivers/iio/accel/da280.c
>>> @@ -0,0 +1,183 @@
>>> +/**
>>> + * IIO driver for the MiraMEMS DA280 3-axis accelerometer and
>>> + * IIO driver for the MiraMEMS DA226 2-axis accelerometer
>>> + *
>>> + * Copyright (c) 2016 Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify it
>>> + * under the terms and conditions of the GNU General Public License,
>>> + * version 2, as published by the Free Software Foundation.
>>> + */
>>> +
>>> +#include <linux/module.h>
>>> +#include <linux/i2c.h>
>>> +#include <linux/iio/iio.h>
>>> +#include <linux/iio/sysfs.h>
>>> +#include <linux/byteorder/generic.h>
>>> +
>>> +#define DA280_REG_CHIP_ID        0x01
>>> +#define DA280_REG_ACC_X_LSB        0x02
>>> +#define DA280_REG_ACC_Y_LSB        0x04
>>> +#define DA280_REG_ACC_Z_LSB        0x06
>>> +#define DA280_REG_MODE_BW        0x11
>>> +
>>> +#define DA280_CHIP_ID            0x13
>>> +#define DA280_MODE_ENABLE        0x1e
>>> +#define DA280_MODE_DISABLE        0x9e
>>> +
>>> +enum { da226, da280 };
>>> +
>>> +/*
>>> + * a value of + or -4096 corresponds to + or - 1G
>>> + * scale = 9.81 / 4096 = 0.002395019
>>> + */
>>> +
>>> +static const int da280_nscale = 2395019;
>>> +
>>> +#define DA280_CHANNEL(reg, axis) {    \
>>> +    .type = IIO_ACCEL,    \
>>> +    .address = reg,    \
>>> +    .modified = 1,    \
>>> +    .channel2 = IIO_MOD_##axis,    \
>>> +    .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),    \
>>> +    .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),    \
>>> +}
>>> +
>>> +static const struct iio_chan_spec da280_channels[] = {
>>> +    DA280_CHANNEL(DA280_REG_ACC_X_LSB, X),
>>> +    DA280_CHANNEL(DA280_REG_ACC_Y_LSB, Y),
>>> +    DA280_CHANNEL(DA280_REG_ACC_Z_LSB, Z),
>>> +};
>>> +
>>> +struct da280_data {
>>> +    struct i2c_client *client;
>>> +};
>>> +
>>> +static int da280_enable(struct i2c_client *client, bool enable)
>>> +{
>>> +    u8 data = enable ? DA280_MODE_ENABLE : DA280_MODE_DISABLE;
>>> +
>>> +    return i2c_smbus_write_byte_data(client, DA280_REG_MODE_BW, data);
>>> +}
>>> +
>>> +static int da280_read_raw(struct iio_dev *indio_dev,
>>> +                struct iio_chan_spec const *chan,
>>> +                int *val, int *val2, long mask)
>>> +{
>>> +    struct da280_data *data = iio_priv(indio_dev);
>>> +    int ret;
>>> +
>>> +    switch (mask) {
>>> +    case IIO_CHAN_INFO_RAW:
>>> +        ret = i2c_smbus_read_word_data(data->client, chan->address);
>>> +        if (ret < 0)
>>> +            return ret;
>>> +        /*
>>> +         * Values are 14 bits, stored as 16 bits with the 2
>>> +         * least significant bits always 0.
>>> +         */
>>> +        *val = ((short)le16_to_cpu(ret)) >> 2;
>> Same thing Lars picked up on before I think...  It's already in cpu endian.
>>
>>> +        return IIO_VAL_INT;
>>> +    case IIO_CHAN_INFO_SCALE:
>>> +        *val = 0;
>>> +        *val2 = da280_nscale;
>>> +        return IIO_VAL_INT_PLUS_NANO;
>>> +    default:
>>> +        return -EINVAL;
>>> +    }
>>> +}
>>> +
>>> +static const struct iio_info da280_info = {
>>> +    .driver_module    = THIS_MODULE,
>>> +    .read_raw    = da280_read_raw,
>>> +};
>>> +
>>> +static int da280_probe(struct i2c_client *client,
>>> +            const struct i2c_device_id *id)
>>> +{
>>> +    int ret;
>>> +    struct iio_dev *indio_dev;
>>> +    struct da280_data *data;
>>> +
>>> +    ret = i2c_smbus_read_byte_data(client, DA280_REG_CHIP_ID);
>>> +    if (ret != DA280_CHIP_ID)
>>> +        return (ret < 0) ? ret : -ENODEV;
>>> +
>>> +    indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
>>> +    if (!indio_dev)
>>> +        return -ENOMEM;
>>> +
>>> +    data = iio_priv(indio_dev);
>>> +    data->client = client;
>>> +    i2c_set_clientdata(client, indio_dev);
>>> +
>>> +    indio_dev->dev.parent = &client->dev;
>>> +    indio_dev->info = &da280_info;
>>> +    indio_dev->modes = INDIO_DIRECT_MODE;
>>> +    indio_dev->channels = da280_channels;
>>> +    if (id->driver_data == da226) {
>>> +        indio_dev->name = "da226";
>>> +        indio_dev->num_channels = 2;
>>> +    } else {
>>> +        indio_dev->name = "da280";
>>> +        indio_dev->num_channels = 3;
>>> +    }
>>> +
>>> +    ret = da280_enable(client, true);
>>> +    if (ret < 0)
>>> +        return ret;
>>> +
>>> +    ret = iio_device_register(indio_dev);
>>> +    if (ret < 0) {
>>> +        dev_err(&client->dev, "device_register failed\n");
>>> +        da280_enable(client, false);
>>> +    }
>>> +
>>> +    return ret;
>>> +}
>>> +
>>> +static int da280_remove(struct i2c_client *client)
>>> +{
>>> +    struct iio_dev *indio_dev = i2c_get_clientdata(client);
>>> +
>>> +    iio_device_unregister(indio_dev);
>>> +
>>> +    return da280_enable(client, false);
>>> +}
>>> +
>>> +#ifdef CONFIG_PM_SLEEP
>>> +static int da280_suspend(struct device *dev)
>>> +{
>>> +    return da280_enable(to_i2c_client(dev), false);
>>> +}
>>> +
>>> +static int da280_resume(struct device *dev)
>>> +{
>>> +    return da280_enable(to_i2c_client(dev), true);
>>> +}
>>> +#endif
>>> +
>>> +static SIMPLE_DEV_PM_OPS(da280_pm_ops, da280_suspend, da280_resume);
>>> +
>>> +static const struct i2c_device_id da280_i2c_id[] = {
>>> +    { "da226", da226 },
>>> +    { "da280", da280 },
>>> +    {}
>>> +};
>>> +MODULE_DEVICE_TABLE(i2c, da280_i2c_id);
>>> +
>>> +static struct i2c_driver da280_driver = {
>>> +    .driver = {
>>> +        .name = "da280",
>>> +        .pm = &da280_pm_ops,
>>> +    },
>>> +    .probe        = da280_probe,
>>> +    .remove        = da280_remove,
>>> +    .id_table    = da280_i2c_id,
>>> +};
>>> +
>>> +module_i2c_driver(da280_driver);
>>> +
>>> +MODULE_AUTHOR("Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>");
>>> +MODULE_DESCRIPTION("MiraMEMS DA280 3-Axis Accelerometer driver");
>>> +MODULE_LICENSE("GPL v2");
>>>
>>

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 1/4] dt: bindings: i2c/trivial-devices.txt: Add 2 iio supported accelerometers
       [not found]     ` <20161008123426.8991-2-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2016-10-08 17:02       ` Jonathan Cameron
@ 2016-10-10 21:40       ` Rob Herring
  2016-10-11 18:38         ` Jonathan Cameron
  1 sibling, 1 reply; 17+ messages in thread
From: Rob Herring @ 2016-10-10 21:40 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree

On Sat, Oct 08, 2016 at 02:34:23PM +0200, Hans de Goede wrote:
> Add compatible strings for 2 accelerometers which follow the trivial
> i2c device bindings and have been supported by the iio subsystem for
> a while now.
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
>  Documentation/devicetree/bindings/i2c/trivial-devices.txt | 2 ++
>  1 file changed, 2 insertions(+)

Jonathan's already applied it, but FWIW:

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

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

* Re: [PATCH 2/4] iio: accel: Add driver for dmard10 3-axis Accelerometer
       [not found]     ` <20161008123426.8991-3-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2016-10-08 17:10       ` Jonathan Cameron
@ 2016-10-10 21:41       ` Rob Herring
  2016-10-11 18:39         ` Jonathan Cameron
  1 sibling, 1 reply; 17+ messages in thread
From: Rob Herring @ 2016-10-10 21:41 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree

On Sat, Oct 08, 2016 at 02:34:24PM +0200, Hans de Goede wrote:
> Add a driver for the Domintech ARD10 3-axis Accelerometer, based on the
> android driver found here: https://github.com/domintech/dmard10
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
> Changes in v2:
> -prefix all defines with DMARD10_ and uppercase them all
> -Cleanup typography of some comments
> -Use defines for offsets in databuffer
> -Use i2c_smbus_write_byte_data() where applicable
> -Reduce unnecessarily large buffer size in dmard10_shutdown()
> -Use __le16 buffer in dmard10_read_raw()
> Changes in v3:
> -Express unit in m/s^2 instead of in "G"
> ---
>  .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>  drivers/iio/accel/Kconfig                          |  10 +
>  drivers/iio/accel/Makefile                         |   1 +
>  drivers/iio/accel/dmard10.c                        | 266 +++++++++++++++++++++
>  4 files changed, 278 insertions(+)
>  create mode 100644 drivers/iio/accel/dmard10.c
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 3/4] iio: accel: Add driver for the MiraMEMS DA311 3-axis 12-bit digital accelerometer
       [not found]     ` <20161008123426.8991-4-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  2016-10-08 17:14       ` Jonathan Cameron
@ 2016-10-10 21:41       ` Rob Herring
  2016-10-11 18:39         ` Jonathan Cameron
  1 sibling, 1 reply; 17+ messages in thread
From: Rob Herring @ 2016-10-10 21:41 UTC (permalink / raw)
  To: Hans de Goede
  Cc: Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree

On Sat, Oct 08, 2016 at 02:34:25PM +0200, Hans de Goede wrote:
> This driver is based on the DA311 Android driver which can be found here:
> https://git.matricom.net/Firmware/kernel_amlogic_meson-common/tree/1e70113a5befd07debb68f537156def84c5be57a/drivers/amlogic/input/sensor
> the mir3da_* files are the DA311 driver.
> 
> Unfortunately there is no datasheet.
> 
> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> ---
> Changes in v2:
> -Add proper prefix to patch Subject
> -Use i2c_smbus_read_word_data() instead of i2c_smbus_read_i2c_block_data()
> Changes in v3:
> -Express unit in m/s^2 instead of in "G"
> -Drop le16_to_cpu, i2c_smbus_read_word_data() already does this
> ---
>  .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +

Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

>  drivers/iio/accel/Kconfig                          |  10 +
>  drivers/iio/accel/Makefile                         |   1 +
>  drivers/iio/accel/da311.c                          | 305 +++++++++++++++++++++
>  4 files changed, 317 insertions(+)
>  create mode 100644 drivers/iio/accel/da311.c
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 1/4] dt: bindings: i2c/trivial-devices.txt: Add 2 iio supported accelerometers
  2016-10-10 21:40       ` Rob Herring
@ 2016-10-11 18:38         ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2016-10-11 18:38 UTC (permalink / raw)
  To: Rob Herring, Hans de Goede
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

On 10/10/16 22:40, Rob Herring wrote:
> On Sat, Oct 08, 2016 at 02:34:23PM +0200, Hans de Goede wrote:
>> Add compatible strings for 2 accelerometers which follow the trivial
>> i2c device bindings and have been supported by the iio subsystem for
>> a while now.
>>
>> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> ---
>>  Documentation/devicetree/bindings/i2c/trivial-devices.txt | 2 ++
>>  1 file changed, 2 insertions(+)
> 
> Jonathan's already applied it, but FWIW:
But not to a non rebasing tree yet :)
> 
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Added.  Thanks Rob!

Jonathan
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

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

* Re: [PATCH 2/4] iio: accel: Add driver for dmard10 3-axis Accelerometer
  2016-10-10 21:41       ` Rob Herring
@ 2016-10-11 18:39         ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2016-10-11 18:39 UTC (permalink / raw)
  To: Rob Herring, Hans de Goede
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

On 10/10/16 22:41, Rob Herring wrote:
> On Sat, Oct 08, 2016 at 02:34:24PM +0200, Hans de Goede wrote:
>> Add a driver for the Domintech ARD10 3-axis Accelerometer, based on the
>> android driver found here: https://github.com/domintech/dmard10
>>
>> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> ---
>> Changes in v2:
>> -prefix all defines with DMARD10_ and uppercase them all
>> -Cleanup typography of some comments
>> -Use defines for offsets in databuffer
>> -Use i2c_smbus_write_byte_data() where applicable
>> -Reduce unnecessarily large buffer size in dmard10_shutdown()
>> -Use __le16 buffer in dmard10_read_raw()
>> Changes in v3:
>> -Express unit in m/s^2 instead of in "G"
>> ---
>>  .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +
> 
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Added.
> 
>>  drivers/iio/accel/Kconfig                          |  10 +
>>  drivers/iio/accel/Makefile                         |   1 +
>>  drivers/iio/accel/dmard10.c                        | 266 +++++++++++++++++++++
>>  4 files changed, 278 insertions(+)
>>  create mode 100644 drivers/iio/accel/dmard10.c

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

* Re: [PATCH 3/4] iio: accel: Add driver for the MiraMEMS DA311 3-axis 12-bit digital accelerometer
  2016-10-10 21:41       ` Rob Herring
@ 2016-10-11 18:39         ` Jonathan Cameron
  0 siblings, 0 replies; 17+ messages in thread
From: Jonathan Cameron @ 2016-10-11 18:39 UTC (permalink / raw)
  To: Rob Herring, Hans de Goede
  Cc: Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	linux-iio-u79uwXL29TY76Z2rM5mHXA, devicetree

On 10/10/16 22:41, Rob Herring wrote:
> On Sat, Oct 08, 2016 at 02:34:25PM +0200, Hans de Goede wrote:
>> This driver is based on the DA311 Android driver which can be found here:
>> https://git.matricom.net/Firmware/kernel_amlogic_meson-common/tree/1e70113a5befd07debb68f537156def84c5be57a/drivers/amlogic/input/sensor
>> the mir3da_* files are the DA311 driver.
>>
>> Unfortunately there is no datasheet.
>>
>> Signed-off-by: Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
>> ---
>> Changes in v2:
>> -Add proper prefix to patch Subject
>> -Use i2c_smbus_read_word_data() instead of i2c_smbus_read_i2c_block_data()
>> Changes in v3:
>> -Express unit in m/s^2 instead of in "G"
>> -Drop le16_to_cpu, i2c_smbus_read_word_data() already does this
>> ---
>>  .../devicetree/bindings/i2c/trivial-devices.txt    |   1 +
> 
> Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
added.
> 
>>  drivers/iio/accel/Kconfig                          |  10 +
>>  drivers/iio/accel/Makefile                         |   1 +
>>  drivers/iio/accel/da311.c                          | 305 +++++++++++++++++++++
>>  4 files changed, 317 insertions(+)
>>  create mode 100644 drivers/iio/accel/da311.c

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

end of thread, other threads:[~2016-10-11 18:39 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-08 12:34 [PATCH 0/4] iio: accel: Add 3 new drivers Hans de Goede
     [not found] ` <20161008123426.8991-1-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-08 12:34   ` [PATCH 1/4] dt: bindings: i2c/trivial-devices.txt: Add 2 iio supported accelerometers Hans de Goede
     [not found]     ` <20161008123426.8991-2-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-08 17:02       ` Jonathan Cameron
2016-10-10 21:40       ` Rob Herring
2016-10-11 18:38         ` Jonathan Cameron
2016-10-08 12:34   ` [PATCH 2/4] iio: accel: Add driver for dmard10 3-axis Accelerometer Hans de Goede
     [not found]     ` <20161008123426.8991-3-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-08 17:10       ` Jonathan Cameron
2016-10-10 21:41       ` Rob Herring
2016-10-11 18:39         ` Jonathan Cameron
2016-10-08 12:34   ` [PATCH 3/4] iio: accel: Add driver for the MiraMEMS DA311 3-axis 12-bit digital accelerometer Hans de Goede
     [not found]     ` <20161008123426.8991-4-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-08 17:14       ` Jonathan Cameron
2016-10-10 21:41       ` Rob Herring
2016-10-11 18:39         ` Jonathan Cameron
2016-10-08 12:34   ` [PATCH 4/4] iio: accel: Add driver for the MiraMEMS DA280 3-axis 14-bit " Hans de Goede
     [not found]     ` <20161008123426.8991-5-hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-08 17:17       ` Jonathan Cameron
     [not found]         ` <11db85a2-23a1-8f25-4ce1-061e88f02c32-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2016-10-08 18:02           ` Hans de Goede
     [not found]             ` <c7959854-781d-699b-3bde-8a8edc0e32a6-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-09  7:22               ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).