All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] staging:iio:hmc5843: Few adjustments and support for hmc5983
@ 2014-07-07 20:33 Josef Gajdusek
  2014-07-07 20:34 ` [PATCH v2 1/5] staging:iio:hmc5843: Added regmap support Josef Gajdusek
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Josef Gajdusek @ 2014-07-07 20:33 UTC (permalink / raw)
  To: linux-iio; +Cc: devel, gregkh, jic23, linux-kernel, pmeerw

This patch series modifies the hmc5843 driver to support the hmc5983 i2c and
spi interfaces.

Josef Gajdusek (5):
  staging:iio:hmc5843: Added regmap support
  staging:iio:hmc5843: Split hmc5843.c to multiple files
  staging:iio:hmc5843: register <-> value arrays now can have different
    lengths
  staging:iio:hmc5843: Add support for i2c hmc5983
  staging:iio:hmc5843: Add support for spi hmc5983

 drivers/staging/iio/magnetometer/Kconfig        |  23 +-
 drivers/staging/iio/magnetometer/Makefile       |   4 +-
 drivers/staging/iio/magnetometer/hmc5843.c      | 652 ------------------------
 drivers/staging/iio/magnetometer/hmc5843.h      |  76 +++
 drivers/staging/iio/magnetometer/hmc5843_core.c | 626 +++++++++++++++++++++++
 drivers/staging/iio/magnetometer/hmc5843_i2c.c  | 107 ++++
 drivers/staging/iio/magnetometer/hmc5843_spi.c  | 105 ++++
 7 files changed, 937 insertions(+), 656 deletions(-)
 delete mode 100644 drivers/staging/iio/magnetometer/hmc5843.c
 create mode 100644 drivers/staging/iio/magnetometer/hmc5843.h
 create mode 100644 drivers/staging/iio/magnetometer/hmc5843_core.c
 create mode 100644 drivers/staging/iio/magnetometer/hmc5843_i2c.c
 create mode 100644 drivers/staging/iio/magnetometer/hmc5843_spi.c

-- 
1.8.5.5


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

* [PATCH v2 1/5] staging:iio:hmc5843: Added regmap support
  2014-07-07 20:33 [PATCH v2 0/5] staging:iio:hmc5843: Few adjustments and support for hmc5983 Josef Gajdusek
@ 2014-07-07 20:34 ` Josef Gajdusek
  2014-07-07 20:36 ` [PATCH v2 2/5] staging:iio:hmc5843: Split hmc5843.c to multiple files Josef Gajdusek
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Josef Gajdusek @ 2014-07-07 20:34 UTC (permalink / raw)
  To: linux-iio; +Cc: devel, gregkh, jic23, linux-kernel, pmeerw

This patch changes hmc5843.c to use regmap. This provides transparent caching
to the code as well as abstraction necessary to add support for SPI-based
hmc5983.

Signed-off-by: Josef Gajdusek <atx@atx.name>
---
 drivers/staging/iio/magnetometer/Kconfig   |   1 +
 drivers/staging/iio/magnetometer/hmc5843.c | 139 +++++++++++++++++++----------
 2 files changed, 95 insertions(+), 45 deletions(-)

diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig
index 34634da..ad88d61 100644
--- a/drivers/staging/iio/magnetometer/Kconfig
+++ b/drivers/staging/iio/magnetometer/Kconfig
@@ -8,6 +8,7 @@ config SENSORS_HMC5843
 	depends on I2C
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
+	select REGMAP_I2C
 	help
 	  Say Y here to add support for the Honeywell HMC5843, HMC5883 and
 	  HMC5883L 3-Axis Magnetometer (digital compass).
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
index d4f4dd9..1a48799 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ b/drivers/staging/iio/magnetometer/hmc5843.c
@@ -21,6 +21,7 @@
 
 #include <linux/module.h>
 #include <linux/i2c.h>
+#include <linux/regmap.h>
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/iio/trigger_consumer.h>
@@ -34,6 +35,7 @@
 #define HMC5843_DATA_OUT_MSB_REGS		0x03
 #define HMC5843_STATUS_REG			0x09
 #define HMC5843_ID_REG				0x0a
+#define HMC5843_ID_END				0x0c
 
 enum hmc5843_ids {
 	HMC5843_ID,
@@ -49,6 +51,7 @@ enum hmc5843_ids {
 #define HMC5843_RANGE_GAIN_OFFSET		0x05
 #define HMC5843_RANGE_GAIN_DEFAULT		0x01
 #define HMC5843_RANGE_GAINS			8
+#define HMC5843_RANGE_GAIN_MASK		0xe0
 
 /* Device status */
 #define HMC5843_DATA_READY			0x01
@@ -68,6 +71,7 @@ enum hmc5843_ids {
 #define HMC5843_RATE_OFFSET			0x02
 #define HMC5843_RATE_DEFAULT			0x04
 #define HMC5843_RATES				7
+#define HMC5843_RATE_MASK		0x1c
 
 /* Device measurement configuration */
 #define HMC5843_MEAS_CONF_NORMAL		0x00
@@ -121,10 +125,7 @@ struct hmc5843_chip_info {
 struct hmc5843_data {
 	struct i2c_client *client;
 	struct mutex lock;
-	u8 rate;
-	u8 meas_conf;
-	u8 operating_mode;
-	u8 range;
+	struct regmap *regmap;
 	const struct hmc5843_chip_info *variant;
 	__be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */
 };
@@ -135,10 +136,8 @@ static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
 	int ret;
 
 	mutex_lock(&data->lock);
-	ret = i2c_smbus_write_byte_data(data->client, HMC5843_MODE_REG,
-					operating_mode & HMC5843_MODE_MASK);
-	if (ret >= 0)
-		data->operating_mode = operating_mode;
+	ret = regmap_update_bits(data->regmap, HMC5843_MODE_REG,
+			HMC5843_MODE_MASK, operating_mode);
 	mutex_unlock(&data->lock);
 
 	return ret;
@@ -146,15 +145,15 @@ static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
 
 static int hmc5843_wait_measurement(struct hmc5843_data *data)
 {
-	s32 result;
 	int tries = 150;
+	int val;
+	int ret;
 
 	while (tries-- > 0) {
-		result = i2c_smbus_read_byte_data(data->client,
-			HMC5843_STATUS_REG);
-		if (result < 0)
-			return result;
-		if (result & HMC5843_DATA_READY)
+		ret = regmap_read(data->regmap, HMC5843_STATUS_REG, &val);
+		if (ret < 0)
+			return ret;
+		if (val & HMC5843_DATA_READY)
 			break;
 		msleep(20);
 	}
@@ -171,20 +170,20 @@ static int hmc5843_wait_measurement(struct hmc5843_data *data)
 static int hmc5843_read_measurement(struct hmc5843_data *data,
 				    int idx, int *val)
 {
-	s32 result;
 	__be16 values[3];
+	int ret;
 
 	mutex_lock(&data->lock);
-	result = hmc5843_wait_measurement(data);
-	if (result < 0) {
+	ret = hmc5843_wait_measurement(data);
+	if (ret < 0) {
 		mutex_unlock(&data->lock);
-		return result;
+		return ret;
 	}
-	result = i2c_smbus_read_i2c_block_data(data->client,
-		HMC5843_DATA_OUT_MSB_REGS, sizeof(values), (u8 *) values);
+	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
+			values, sizeof(values));
 	mutex_unlock(&data->lock);
-	if (result < 0)
-		return -EINVAL;
+	if (ret < 0)
+		return ret;
 
 	*val = sign_extend32(be16_to_cpu(values[idx]), 15);
 	return IIO_VAL_INT;
@@ -208,16 +207,13 @@ static int hmc5843_read_measurement(struct hmc5843_data *data,
  *     and BN.
  *
  */
-static s32 hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
+static int hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
 {
 	int ret;
 
 	mutex_lock(&data->lock);
-	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A,
-		(meas_conf & HMC5843_MEAS_CONF_MASK) |
-		(data->rate << HMC5843_RATE_OFFSET));
-	if (ret >= 0)
-		data->meas_conf = meas_conf;
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
+			HMC5843_MEAS_CONF_MASK, meas_conf);
 	mutex_unlock(&data->lock);
 
 	return ret;
@@ -228,7 +224,15 @@ static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
 						char *buf)
 {
 	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-	return sprintf(buf, "%d\n", data->meas_conf);
+	int val;
+	int ret;
+
+	ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &val);
+	if (ret)
+		return ret;
+	val &= HMC5843_MEAS_CONF_MASK;
+
+	return sprintf(buf, "%d\n", val);
 }
 
 static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
@@ -282,10 +286,8 @@ static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate)
 	int ret;
 
 	mutex_lock(&data->lock);
-	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_A,
-		data->meas_conf | (rate << HMC5843_RATE_OFFSET));
-	if (ret >= 0)
-		data->rate = rate;
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
+			HMC5843_RATE_MASK, rate << HMC5843_RATE_OFFSET);
 	mutex_unlock(&data->lock);
 
 	return ret;
@@ -309,10 +311,9 @@ static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range)
 	int ret;
 
 	mutex_lock(&data->lock);
-	ret = i2c_smbus_write_byte_data(data->client, HMC5843_CONFIG_REG_B,
-		range << HMC5843_RANGE_GAIN_OFFSET);
-	if (ret >= 0)
-		data->range = range;
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_B,
+			HMC5843_RANGE_GAIN_MASK,
+			range << HMC5843_RANGE_GAIN_OFFSET);
 	mutex_unlock(&data->lock);
 
 	return ret;
@@ -358,17 +359,26 @@ static int hmc5843_read_raw(struct iio_dev *indio_dev,
 			    int *val, int *val2, long mask)
 {
 	struct hmc5843_data *data = iio_priv(indio_dev);
+	int rval;
+	int ret;
 
 	switch (mask) {
 	case IIO_CHAN_INFO_RAW:
 		return hmc5843_read_measurement(data, chan->scan_index, val);
 	case IIO_CHAN_INFO_SCALE:
+		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval);
+		if (ret < 0)
+			return ret;
 		*val = 0;
-		*val2 = data->variant->regval_to_nanoscale[data->range];
+		*val2 = data->variant->regval_to_nanoscale[rval >> HMC5843_RANGE_GAIN_OFFSET];
 		return IIO_VAL_INT_PLUS_NANO;
 	case IIO_CHAN_INFO_SAMP_FREQ:
-		*val = data->variant->regval_to_samp_freq[data->rate][0];
-		*val2 = data->variant->regval_to_samp_freq[data->rate][1];
+		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval);
+		if (ret < 0)
+			return ret;
+		rval &= HMC5843_RATE_MASK;
+		*val = data->variant->regval_to_samp_freq[rval][0];
+		*val2 = data->variant->regval_to_samp_freq[rval][1];
 		return IIO_VAL_INT_PLUS_MICRO;
 	}
 	return -EINVAL;
@@ -426,9 +436,9 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
 		goto done;
 	}
 
-	ret = i2c_smbus_read_i2c_block_data(data->client,
-		HMC5843_DATA_OUT_MSB_REGS, 3 * sizeof(__be16),
-			(u8 *) data->buffer);
+	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
+			data->buffer, 3 * sizeof(__be16));
+
 	mutex_unlock(&data->lock);
 	if (ret < 0)
 		goto done;
@@ -508,8 +518,8 @@ static int hmc5843_init(struct hmc5843_data *data)
 	int ret;
 	u8 id[3];
 
-	ret = i2c_smbus_read_i2c_block_data(data->client, HMC5843_ID_REG,
-		sizeof(id), id);
+	ret = regmap_bulk_read(data->regmap, HMC5843_ID_REG,
+			id, ARRAY_SIZE(id));
 	if (ret < 0)
 		return ret;
 	if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
@@ -539,6 +549,44 @@ static const struct iio_info hmc5843_info = {
 
 static const unsigned long hmc5843_scan_masks[] = {0x7, 0};
 
+static const struct regmap_range hmc5843_readable_ranges[] = {
+		regmap_reg_range(0, HMC5843_ID_END),
+};
+
+static struct regmap_access_table hmc5843_readable_table = {
+		.yes_ranges = hmc5843_readable_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges),
+};
+
+static const struct regmap_range hmc5843_writable_ranges[] = {
+		regmap_reg_range(0, HMC5843_MODE_REG),
+};
+
+static struct regmap_access_table hmc5843_writable_table = {
+		.yes_ranges = hmc5843_writable_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges),
+};
+
+static const struct regmap_range hmc5843_volatile_ranges[] = {
+		regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG),
+};
+
+static struct regmap_access_table hmc5843_volatile_table = {
+		.yes_ranges = hmc5843_volatile_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges),
+};
+
+static struct regmap_config hmc5843_regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+
+		.rd_table = &hmc5843_readable_table,
+		.wr_table = &hmc5843_writable_table,
+		.volatile_table = &hmc5843_volatile_table,
+
+		.cache_type = REGCACHE_RBTREE,
+};
+
 static int hmc5843_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
@@ -554,6 +602,7 @@ static int hmc5843_probe(struct i2c_client *client,
 	data = iio_priv(indio_dev);
 	data->client = client;
 	data->variant = &hmc5843_chip_info_tbl[id->driver_data];
+	data->regmap = devm_regmap_init_i2c(client, &hmc5843_regmap_config);
 	mutex_init(&data->lock);
 
 	i2c_set_clientdata(client, indio_dev);
-- 
1.8.5.5


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

* [PATCH v2 2/5] staging:iio:hmc5843: Split hmc5843.c to multiple files
  2014-07-07 20:33 [PATCH v2 0/5] staging:iio:hmc5843: Few adjustments and support for hmc5983 Josef Gajdusek
  2014-07-07 20:34 ` [PATCH v2 1/5] staging:iio:hmc5843: Added regmap support Josef Gajdusek
@ 2014-07-07 20:36 ` Josef Gajdusek
  2014-07-08  8:23   ` Dan Carpenter
  2014-07-07 20:37 ` [PATCH v2 3/5] staging:iio:hmc5843: register <-> value arrays now can have different lengths Josef Gajdusek
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Josef Gajdusek @ 2014-07-07 20:36 UTC (permalink / raw)
  To: linux-iio; +Cc: devel, gregkh, jic23, linux-kernel, pmeerw

This patch splits hmc5843.c to multiple files - the interface-agnostic
hmc5843_core.c, i2c specific hmc5843_i2c.c and header file hmc5843.h. This is
another step to add support of SPI-enabled hmc5983.

Signed-off-by: Josef Gajdusek <atx@atx.name>
---
 drivers/staging/iio/magnetometer/Kconfig        |  16 +-
 drivers/staging/iio/magnetometer/Makefile       |   3 +-
 drivers/staging/iio/magnetometer/hmc5843.c      | 701 ------------------------
 drivers/staging/iio/magnetometer/hmc5843.h      |  75 +++
 drivers/staging/iio/magnetometer/hmc5843_core.c | 600 ++++++++++++++++++++
 drivers/staging/iio/magnetometer/hmc5843_i2c.c  | 106 ++++
 6 files changed, 795 insertions(+), 706 deletions(-)
 delete mode 100644 drivers/staging/iio/magnetometer/hmc5843.c
 create mode 100644 drivers/staging/iio/magnetometer/hmc5843.h
 create mode 100644 drivers/staging/iio/magnetometer/hmc5843_core.c
 create mode 100644 drivers/staging/iio/magnetometer/hmc5843_i2c.c

diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig
index ad88d61..28c2612 100644
--- a/drivers/staging/iio/magnetometer/Kconfig
+++ b/drivers/staging/iio/magnetometer/Kconfig
@@ -5,15 +5,23 @@ menu "Magnetometer sensors"
 
 config SENSORS_HMC5843
 	tristate "Honeywell HMC5843/5883/5883L 3-Axis Magnetometer"
-	depends on I2C
+	depends on (I2C || SPI_MASTER)
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
-	select REGMAP_I2C
+	select SENSORS_HMC5843_I2C if (I2C)
 	help
 	  Say Y here to add support for the Honeywell HMC5843, HMC5883 and
 	  HMC5883L 3-Axis Magnetometer (digital compass).
 
-	  To compile this driver as a module, choose M here: the module
-	  will be called hmc5843.
+	  This driver can also be compiled as a set of modules.
+	  If so, these modules will be created:
+	  - hmc5843_core (core functions)
+	  - hmc5843_i2c (support for HMC5843, HMC5883 and HMC5883L)
+
+config SENSORS_HMC5843_I2C
+	tristate
+	depends on I2C
+	depends on SENSORS_HMC5843
+	select REGMAP_I2C
 
 endmenu
diff --git a/drivers/staging/iio/magnetometer/Makefile b/drivers/staging/iio/magnetometer/Makefile
index f9bfb2e..65baf1c 100644
--- a/drivers/staging/iio/magnetometer/Makefile
+++ b/drivers/staging/iio/magnetometer/Makefile
@@ -2,4 +2,5 @@
 # Makefile for industrial I/O Magnetometer sensors
 #
 
-obj-$(CONFIG_SENSORS_HMC5843)	+= hmc5843.o
+obj-$(CONFIG_SENSORS_HMC5843)		+= hmc5843_core.o
+obj-$(CONFIG_SENSORS_HMC5843_I2C)	+= hmc5843_i2c.o
diff --git a/drivers/staging/iio/magnetometer/hmc5843.c b/drivers/staging/iio/magnetometer/hmc5843.c
deleted file mode 100644
index 1a48799..0000000
--- a/drivers/staging/iio/magnetometer/hmc5843.c
+++ /dev/null
@@ -1,701 +0,0 @@
-/*  Copyright (C) 2010 Texas Instruments
-    Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
-    Acknowledgement: Jonathan Cameron <jic23@kernel.org> for valuable inputs.
-
-    Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#include <linux/module.h>
-#include <linux/i2c.h>
-#include <linux/regmap.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
-#include <linux/iio/trigger_consumer.h>
-#include <linux/iio/buffer.h>
-#include <linux/iio/triggered_buffer.h>
-#include <linux/delay.h>
-
-#define HMC5843_CONFIG_REG_A			0x00
-#define HMC5843_CONFIG_REG_B			0x01
-#define HMC5843_MODE_REG			0x02
-#define HMC5843_DATA_OUT_MSB_REGS		0x03
-#define HMC5843_STATUS_REG			0x09
-#define HMC5843_ID_REG				0x0a
-#define HMC5843_ID_END				0x0c
-
-enum hmc5843_ids {
-	HMC5843_ID,
-	HMC5883_ID,
-	HMC5883L_ID,
-};
-
-/*
- * Range gain settings in (+-)Ga
- * Beware: HMC5843 and HMC5883 have different recommended sensor field
- * ranges; default corresponds to +-1.0 Ga and +-1.3 Ga, respectively
- */
-#define HMC5843_RANGE_GAIN_OFFSET		0x05
-#define HMC5843_RANGE_GAIN_DEFAULT		0x01
-#define HMC5843_RANGE_GAINS			8
-#define HMC5843_RANGE_GAIN_MASK		0xe0
-
-/* Device status */
-#define HMC5843_DATA_READY			0x01
-#define HMC5843_DATA_OUTPUT_LOCK		0x02
-
-/* Mode register configuration */
-#define HMC5843_MODE_CONVERSION_CONTINUOUS	0x00
-#define HMC5843_MODE_CONVERSION_SINGLE		0x01
-#define HMC5843_MODE_IDLE			0x02
-#define HMC5843_MODE_SLEEP			0x03
-#define HMC5843_MODE_MASK			0x03
-
-/*
- * HMC5843: Minimum data output rate
- * HMC5883: Typical data output rate
- */
-#define HMC5843_RATE_OFFSET			0x02
-#define HMC5843_RATE_DEFAULT			0x04
-#define HMC5843_RATES				7
-#define HMC5843_RATE_MASK		0x1c
-
-/* Device measurement configuration */
-#define HMC5843_MEAS_CONF_NORMAL		0x00
-#define HMC5843_MEAS_CONF_POSITIVE_BIAS		0x01
-#define HMC5843_MEAS_CONF_NEGATIVE_BIAS		0x02
-#define HMC5843_MEAS_CONF_MASK			0x03
-
-/* Scaling factors: 10000000/Gain */
-static const int hmc5843_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
-	6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
-};
-
-static const int hmc5883_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
-	7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662
-};
-
-static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
-	7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478
-};
-
-/*
- * From the datasheet:
- * Value	| HMC5843		| HMC5883/HMC5883L
- *		| Data output rate (Hz)	| Data output rate (Hz)
- * 0		| 0.5			| 0.75
- * 1		| 1			| 1.5
- * 2		| 2			| 3
- * 3		| 5			| 7.5
- * 4		| 10 (default)		| 15
- * 5		| 20			| 30
- * 6		| 50			| 75
- * 7		| Not used		| Not used
- */
-static const int hmc5843_regval_to_samp_freq[7][2] = {
-	{0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0}
-};
-
-static const int hmc5883_regval_to_samp_freq[7][2] = {
-	{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
-	{75, 0}
-};
-
-/* Describe chip variants */
-struct hmc5843_chip_info {
-	const struct iio_chan_spec *channels;
-	const int (*regval_to_samp_freq)[2];
-	const int *regval_to_nanoscale;
-};
-
-/* Each client has this additional data */
-struct hmc5843_data {
-	struct i2c_client *client;
-	struct mutex lock;
-	struct regmap *regmap;
-	const struct hmc5843_chip_info *variant;
-	__be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */
-};
-
-/* The lower two bits contain the current conversion mode */
-static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
-{
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = regmap_update_bits(data->regmap, HMC5843_MODE_REG,
-			HMC5843_MODE_MASK, operating_mode);
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static int hmc5843_wait_measurement(struct hmc5843_data *data)
-{
-	int tries = 150;
-	int val;
-	int ret;
-
-	while (tries-- > 0) {
-		ret = regmap_read(data->regmap, HMC5843_STATUS_REG, &val);
-		if (ret < 0)
-			return ret;
-		if (val & HMC5843_DATA_READY)
-			break;
-		msleep(20);
-	}
-
-	if (tries < 0) {
-		dev_err(&data->client->dev, "data not ready\n");
-		return -EIO;
-	}
-
-	return 0;
-}
-
-/* Return the measurement value from the specified channel */
-static int hmc5843_read_measurement(struct hmc5843_data *data,
-				    int idx, int *val)
-{
-	__be16 values[3];
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = hmc5843_wait_measurement(data);
-	if (ret < 0) {
-		mutex_unlock(&data->lock);
-		return ret;
-	}
-	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
-			values, sizeof(values));
-	mutex_unlock(&data->lock);
-	if (ret < 0)
-		return ret;
-
-	*val = sign_extend32(be16_to_cpu(values[idx]), 15);
-	return IIO_VAL_INT;
-}
-
-/*
- * API for setting the measurement configuration to
- * Normal, Positive bias and Negative bias
- *
- * From the datasheet:
- * 0 - Normal measurement configuration (default): In normal measurement
- *     configuration the device follows normal measurement flow. Pins BP
- *     and BN are left floating and high impedance.
- *
- * 1 - Positive bias configuration: In positive bias configuration, a
- *     positive current is forced across the resistive load on pins BP
- *     and BN.
- *
- * 2 - Negative bias configuration. In negative bias configuration, a
- *     negative current is forced across the resistive load on pins BP
- *     and BN.
- *
- */
-static int hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
-{
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
-			HMC5843_MEAS_CONF_MASK, meas_conf);
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
-						struct device_attribute *attr,
-						char *buf)
-{
-	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-	int val;
-	int ret;
-
-	ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &val);
-	if (ret)
-		return ret;
-	val &= HMC5843_MEAS_CONF_MASK;
-
-	return sprintf(buf, "%d\n", val);
-}
-
-static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
-						struct device_attribute *attr,
-						const char *buf,
-						size_t count)
-{
-	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-	unsigned long meas_conf = 0;
-	int ret;
-
-	ret = kstrtoul(buf, 10, &meas_conf);
-	if (ret)
-		return ret;
-	if (meas_conf >= HMC5843_MEAS_CONF_MASK)
-		return -EINVAL;
-
-	ret = hmc5843_set_meas_conf(data, meas_conf);
-
-	return (ret < 0) ? ret : count;
-}
-
-static IIO_DEVICE_ATTR(meas_conf,
-			S_IWUSR | S_IRUGO,
-			hmc5843_show_measurement_configuration,
-			hmc5843_set_measurement_configuration,
-			0);
-
-static ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-	size_t len = 0;
-	int i;
-
-	for (i = 0; i < HMC5843_RATES; i++)
-		len += scnprintf(buf + len, PAGE_SIZE - len,
-			"%d.%d ", data->variant->regval_to_samp_freq[i][0],
-			data->variant->regval_to_samp_freq[i][1]);
-
-	/* replace trailing space by newline */
-	buf[len - 1] = '\n';
-
-	return len;
-}
-
-static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail);
-
-static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate)
-{
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
-			HMC5843_RATE_MASK, rate << HMC5843_RATE_OFFSET);
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static int hmc5843_get_samp_freq_index(struct hmc5843_data *data,
-				   int val, int val2)
-{
-	int i;
-
-	for (i = 0; i < HMC5843_RATES; i++)
-		if (val == data->variant->regval_to_samp_freq[i][0] &&
-			val2 == data->variant->regval_to_samp_freq[i][1])
-			return i;
-
-	return -EINVAL;
-}
-
-static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range)
-{
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_B,
-			HMC5843_RANGE_GAIN_MASK,
-			range << HMC5843_RANGE_GAIN_OFFSET);
-	mutex_unlock(&data->lock);
-
-	return ret;
-}
-
-static ssize_t hmc5843_show_scale_avail(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
-
-	size_t len = 0;
-	int i;
-
-	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
-		len += scnprintf(buf + len, PAGE_SIZE - len,
-			"0.%09d ", data->variant->regval_to_nanoscale[i]);
-
-	/* replace trailing space by newline */
-	buf[len - 1] = '\n';
-
-	return len;
-}
-
-static IIO_DEVICE_ATTR(scale_available, S_IRUGO,
-	hmc5843_show_scale_avail, NULL, 0);
-
-static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2)
-{
-	int i;
-
-	if (val != 0)
-		return -EINVAL;
-
-	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
-		if (val2 == data->variant->regval_to_nanoscale[i])
-			return i;
-
-	return -EINVAL;
-}
-
-static int hmc5843_read_raw(struct iio_dev *indio_dev,
-			    struct iio_chan_spec const *chan,
-			    int *val, int *val2, long mask)
-{
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	int rval;
-	int ret;
-
-	switch (mask) {
-	case IIO_CHAN_INFO_RAW:
-		return hmc5843_read_measurement(data, chan->scan_index, val);
-	case IIO_CHAN_INFO_SCALE:
-		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval);
-		if (ret < 0)
-			return ret;
-		*val = 0;
-		*val2 = data->variant->regval_to_nanoscale[rval >> HMC5843_RANGE_GAIN_OFFSET];
-		return IIO_VAL_INT_PLUS_NANO;
-	case IIO_CHAN_INFO_SAMP_FREQ:
-		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval);
-		if (ret < 0)
-			return ret;
-		rval &= HMC5843_RATE_MASK;
-		*val = data->variant->regval_to_samp_freq[rval][0];
-		*val2 = data->variant->regval_to_samp_freq[rval][1];
-		return IIO_VAL_INT_PLUS_MICRO;
-	}
-	return -EINVAL;
-}
-
-static int hmc5843_write_raw(struct iio_dev *indio_dev,
-			     struct iio_chan_spec const *chan,
-			     int val, int val2, long mask)
-{
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	int rate, range;
-
-	switch (mask) {
-	case IIO_CHAN_INFO_SAMP_FREQ:
-		rate = hmc5843_get_samp_freq_index(data, val, val2);
-		if (rate < 0)
-			return -EINVAL;
-
-		return hmc5843_set_samp_freq(data, rate);
-	case IIO_CHAN_INFO_SCALE:
-		range = hmc5843_get_scale_index(data, val, val2);
-		if (range < 0)
-			return -EINVAL;
-
-		return hmc5843_set_range_gain(data, range);
-	default:
-		return -EINVAL;
-	}
-}
-
-static int hmc5843_write_raw_get_fmt(struct iio_dev *indio_dev,
-			       struct iio_chan_spec const *chan, long mask)
-{
-	switch (mask) {
-	case IIO_CHAN_INFO_SAMP_FREQ:
-		return IIO_VAL_INT_PLUS_MICRO;
-	case IIO_CHAN_INFO_SCALE:
-		return IIO_VAL_INT_PLUS_NANO;
-	default:
-		return -EINVAL;
-	}
-}
-
-static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
-{
-	struct iio_poll_func *pf = p;
-	struct iio_dev *indio_dev = pf->indio_dev;
-	struct hmc5843_data *data = iio_priv(indio_dev);
-	int ret;
-
-	mutex_lock(&data->lock);
-	ret = hmc5843_wait_measurement(data);
-	if (ret < 0) {
-		mutex_unlock(&data->lock);
-		goto done;
-	}
-
-	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
-			data->buffer, 3 * sizeof(__be16));
-
-	mutex_unlock(&data->lock);
-	if (ret < 0)
-		goto done;
-
-	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
-		iio_get_time_ns());
-
-done:
-	iio_trigger_notify_done(indio_dev->trig);
-
-	return IRQ_HANDLED;
-}
-
-#define HMC5843_CHANNEL(axis, idx)					\
-	{								\
-		.type = IIO_MAGN,					\
-		.modified = 1,						\
-		.channel2 = IIO_MOD_##axis,				\
-		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
-			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
-		.scan_index = idx,					\
-		.scan_type = {						\
-			.sign = 's',					\
-			.realbits = 16,					\
-			.storagebits = 16,				\
-			.endianness = IIO_BE,				\
-		},							\
-	}
-
-static const struct iio_chan_spec hmc5843_channels[] = {
-	HMC5843_CHANNEL(X, 0),
-	HMC5843_CHANNEL(Y, 1),
-	HMC5843_CHANNEL(Z, 2),
-	IIO_CHAN_SOFT_TIMESTAMP(3),
-};
-
-/* Beware: Y and Z are exchanged on HMC5883 */
-static const struct iio_chan_spec hmc5883_channels[] = {
-	HMC5843_CHANNEL(X, 0),
-	HMC5843_CHANNEL(Z, 1),
-	HMC5843_CHANNEL(Y, 2),
-	IIO_CHAN_SOFT_TIMESTAMP(3),
-};
-
-static struct attribute *hmc5843_attributes[] = {
-	&iio_dev_attr_meas_conf.dev_attr.attr,
-	&iio_dev_attr_scale_available.dev_attr.attr,
-	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
-	NULL
-};
-
-static const struct attribute_group hmc5843_group = {
-	.attrs = hmc5843_attributes,
-};
-
-static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
-	[HMC5843_ID] = {
-		.channels = hmc5843_channels,
-		.regval_to_samp_freq = hmc5843_regval_to_samp_freq,
-		.regval_to_nanoscale = hmc5843_regval_to_nanoscale,
-	},
-	[HMC5883_ID] = {
-		.channels = hmc5883_channels,
-		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
-		.regval_to_nanoscale = hmc5883_regval_to_nanoscale,
-	},
-	[HMC5883L_ID] = {
-		.channels = hmc5883_channels,
-		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
-		.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
-	},
-};
-
-static int hmc5843_init(struct hmc5843_data *data)
-{
-	int ret;
-	u8 id[3];
-
-	ret = regmap_bulk_read(data->regmap, HMC5843_ID_REG,
-			id, ARRAY_SIZE(id));
-	if (ret < 0)
-		return ret;
-	if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
-		dev_err(&data->client->dev, "no HMC5843/5883/5883L sensor\n");
-		return -ENODEV;
-	}
-
-	ret = hmc5843_set_meas_conf(data, HMC5843_MEAS_CONF_NORMAL);
-	if (ret < 0)
-		return ret;
-	ret = hmc5843_set_samp_freq(data, HMC5843_RATE_DEFAULT);
-	if (ret < 0)
-		return ret;
-	ret = hmc5843_set_range_gain(data, HMC5843_RANGE_GAIN_DEFAULT);
-	if (ret < 0)
-		return ret;
-	return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS);
-}
-
-static const struct iio_info hmc5843_info = {
-	.attrs = &hmc5843_group,
-	.read_raw = &hmc5843_read_raw,
-	.write_raw = &hmc5843_write_raw,
-	.write_raw_get_fmt = &hmc5843_write_raw_get_fmt,
-	.driver_module = THIS_MODULE,
-};
-
-static const unsigned long hmc5843_scan_masks[] = {0x7, 0};
-
-static const struct regmap_range hmc5843_readable_ranges[] = {
-		regmap_reg_range(0, HMC5843_ID_END),
-};
-
-static struct regmap_access_table hmc5843_readable_table = {
-		.yes_ranges = hmc5843_readable_ranges,
-		.n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges),
-};
-
-static const struct regmap_range hmc5843_writable_ranges[] = {
-		regmap_reg_range(0, HMC5843_MODE_REG),
-};
-
-static struct regmap_access_table hmc5843_writable_table = {
-		.yes_ranges = hmc5843_writable_ranges,
-		.n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges),
-};
-
-static const struct regmap_range hmc5843_volatile_ranges[] = {
-		regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG),
-};
-
-static struct regmap_access_table hmc5843_volatile_table = {
-		.yes_ranges = hmc5843_volatile_ranges,
-		.n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges),
-};
-
-static struct regmap_config hmc5843_regmap_config = {
-		.reg_bits = 8,
-		.val_bits = 8,
-
-		.rd_table = &hmc5843_readable_table,
-		.wr_table = &hmc5843_writable_table,
-		.volatile_table = &hmc5843_volatile_table,
-
-		.cache_type = REGCACHE_RBTREE,
-};
-
-static int hmc5843_probe(struct i2c_client *client,
-			 const struct i2c_device_id *id)
-{
-	struct hmc5843_data *data;
-	struct iio_dev *indio_dev;
-	int ret;
-
-	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
-	if (indio_dev == NULL)
-		return -ENOMEM;
-
-	/* default settings at probe */
-	data = iio_priv(indio_dev);
-	data->client = client;
-	data->variant = &hmc5843_chip_info_tbl[id->driver_data];
-	data->regmap = devm_regmap_init_i2c(client, &hmc5843_regmap_config);
-	mutex_init(&data->lock);
-
-	i2c_set_clientdata(client, indio_dev);
-	indio_dev->info = &hmc5843_info;
-	indio_dev->name = id->name;
-	indio_dev->dev.parent = &client->dev;
-	indio_dev->modes = INDIO_DIRECT_MODE;
-	indio_dev->channels = data->variant->channels;
-	indio_dev->num_channels = 4;
-	indio_dev->available_scan_masks = hmc5843_scan_masks;
-
-	ret = hmc5843_init(data);
-	if (ret < 0)
-		return ret;
-
-	ret = iio_triggered_buffer_setup(indio_dev, NULL,
-		hmc5843_trigger_handler, NULL);
-	if (ret < 0)
-		return ret;
-
-	ret = iio_device_register(indio_dev);
-	if (ret < 0)
-		goto buffer_cleanup;
-
-	return 0;
-
-buffer_cleanup:
-	iio_triggered_buffer_cleanup(indio_dev);
-	return ret;
-}
-
-static int hmc5843_remove(struct i2c_client *client)
-{
-	struct iio_dev *indio_dev = i2c_get_clientdata(client);
-
-	iio_device_unregister(indio_dev);
-	iio_triggered_buffer_cleanup(indio_dev);
-
-	/*  sleep mode to save power */
-	hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int hmc5843_suspend(struct device *dev)
-{
-	struct hmc5843_data *data = iio_priv(i2c_get_clientdata(
-		to_i2c_client(dev)));
-
-	return hmc5843_set_mode(data, HMC5843_MODE_SLEEP);
-}
-
-static int hmc5843_resume(struct device *dev)
-{
-	struct hmc5843_data *data = iio_priv(i2c_get_clientdata(
-		to_i2c_client(dev)));
-
-	return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS);
-}
-
-static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops, hmc5843_suspend, hmc5843_resume);
-#define HMC5843_PM_OPS (&hmc5843_pm_ops)
-#else
-#define HMC5843_PM_OPS NULL
-#endif
-
-static const struct i2c_device_id hmc5843_id[] = {
-	{ "hmc5843", HMC5843_ID },
-	{ "hmc5883", HMC5883_ID },
-	{ "hmc5883l", HMC5883L_ID },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, hmc5843_id);
-
-static const struct of_device_id hmc5843_of_match[] = {
-	{ .compatible = "honeywell,hmc5843" },
-	{}
-};
-MODULE_DEVICE_TABLE(of, hmc5843_of_match);
-
-static struct i2c_driver hmc5843_driver = {
-	.driver = {
-		.name	= "hmc5843",
-		.pm	= HMC5843_PM_OPS,
-		.of_match_table = hmc5843_of_match,
-	},
-	.id_table	= hmc5843_id,
-	.probe		= hmc5843_probe,
-	.remove		= hmc5843_remove,
-};
-module_i2c_driver(hmc5843_driver);
-
-MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>");
-MODULE_DESCRIPTION("HMC5843/5883/5883L driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/magnetometer/hmc5843.h b/drivers/staging/iio/magnetometer/hmc5843.h
new file mode 100644
index 0000000..4e3cce3
--- /dev/null
+++ b/drivers/staging/iio/magnetometer/hmc5843.h
@@ -0,0 +1,75 @@
+/*
+ * Header file for hmc5843 driver
+ *
+ * Split from hmc5843.c
+ * Copyright (C) Josef Gajdusek <atx@atx.name>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * */
+
+
+#ifndef HMC5843_CORE_H
+#define HMC5843_CORE_H
+
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+
+#define HMC5843_CONFIG_REG_A			0x00
+#define HMC5843_CONFIG_REG_B			0x01
+#define HMC5843_MODE_REG			0x02
+#define HMC5843_DATA_OUT_MSB_REGS		0x03
+#define HMC5843_STATUS_REG			0x09
+#define HMC5843_ID_REG				0x0a
+#define HMC5843_ID_END				0x0c
+
+enum hmc5843_ids {
+	HMC5843_ID,
+	HMC5883_ID,
+	HMC5883L_ID,
+};
+
+struct hmc5843_data {
+	struct device *dev;
+	struct mutex lock;
+	struct regmap *regmap;
+	const struct hmc5843_chip_info *variant;
+	__be16 buffer[8]; /* 3x 16-bit channels + padding + 64-bit timestamp */
+};
+
+int hmc5843_common_probe(struct iio_dev *indio_dev, enum hmc5843_ids id);
+int hmc5843_common_remove(struct iio_dev *indio_dev);
+
+int hmc5843_common_suspend(struct iio_dev *indio_dev);
+int hmc5843_common_resume(struct iio_dev *indio_dev);
+
+static const struct regmap_range hmc5843_readable_ranges[] = {
+		regmap_reg_range(0, HMC5843_ID_END),
+};
+
+static struct regmap_access_table hmc5843_readable_table = {
+		.yes_ranges = hmc5843_readable_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_readable_ranges),
+};
+
+static const struct regmap_range hmc5843_writable_ranges[] = {
+		regmap_reg_range(0, HMC5843_MODE_REG),
+};
+
+static struct regmap_access_table hmc5843_writable_table = {
+		.yes_ranges = hmc5843_writable_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_writable_ranges),
+};
+
+static const struct regmap_range hmc5843_volatile_ranges[] = {
+		regmap_reg_range(HMC5843_DATA_OUT_MSB_REGS, HMC5843_STATUS_REG),
+};
+
+static struct regmap_access_table hmc5843_volatile_table = {
+		.yes_ranges = hmc5843_volatile_ranges,
+		.n_yes_ranges = ARRAY_SIZE(hmc5843_volatile_ranges),
+};
+
+#endif /* HMC5843_CORE_H */
diff --git a/drivers/staging/iio/magnetometer/hmc5843_core.c b/drivers/staging/iio/magnetometer/hmc5843_core.c
new file mode 100644
index 0000000..efabca5
--- /dev/null
+++ b/drivers/staging/iio/magnetometer/hmc5843_core.c
@@ -0,0 +1,600 @@
+/*  Copyright (C) 2010 Texas Instruments
+    Author: Shubhrajyoti Datta <shubhrajyoti@ti.com>
+    Acknowledgement: Jonathan Cameron <jic23@kernel.org> for valuable inputs.
+
+    Support for HMC5883 and HMC5883L by Peter Meerwald <pmeerw@pmeerw.net>.
+
+    Split to multiple files by Josef Gajdusek <atx@atx.name> - 2014
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/delay.h>
+
+#include "hmc5843.h"
+
+/*
+ * Range gain settings in (+-)Ga
+ * Beware: HMC5843 and HMC5883 have different recommended sensor field
+ * ranges; default corresponds to +-1.0 Ga and +-1.3 Ga, respectively
+ */
+#define HMC5843_RANGE_GAIN_OFFSET		0x05
+#define HMC5843_RANGE_GAIN_DEFAULT		0x01
+#define HMC5843_RANGE_GAINS			8
+#define HMC5843_RANGE_GAIN_MASK		0xe0
+
+/* Device status */
+#define HMC5843_DATA_READY			0x01
+#define HMC5843_DATA_OUTPUT_LOCK		0x02
+
+/* Mode register configuration */
+#define HMC5843_MODE_CONVERSION_CONTINUOUS	0x00
+#define HMC5843_MODE_CONVERSION_SINGLE		0x01
+#define HMC5843_MODE_IDLE			0x02
+#define HMC5843_MODE_SLEEP			0x03
+#define HMC5843_MODE_MASK			0x03
+
+/*
+ * HMC5843: Minimum data output rate
+ * HMC5883: Typical data output rate
+ */
+#define HMC5843_RATE_OFFSET			0x02
+#define HMC5843_RATE_DEFAULT			0x04
+#define HMC5843_RATES				7
+#define HMC5843_RATE_MASK		0x1c
+
+/* Device measurement configuration */
+#define HMC5843_MEAS_CONF_NORMAL		0x00
+#define HMC5843_MEAS_CONF_POSITIVE_BIAS		0x01
+#define HMC5843_MEAS_CONF_NEGATIVE_BIAS		0x02
+#define HMC5843_MEAS_CONF_MASK			0x03
+
+/* Scaling factors: 10000000/Gain */
+static const int hmc5843_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
+	6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
+};
+
+static const int hmc5883_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
+	7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662
+};
+
+static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
+	7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478
+};
+
+/*
+ * 
+ * Value	| HMC5843		| HMC5883/HMC5883L
+ *		| Data output rate (Hz)	| Data output rate (Hz)
+ * 0		| 0.5			| 0.75
+ * 1		| 1			| 1.5
+ * 2		| 2			| 3
+ * 3		| 5			| 7.5
+ * 4		| 10 (default)		| 15
+ * 5		| 20			| 30
+ * 6		| 50			| 75
+ * 7		| Not used		| Not used
+ */
+static const int hmc5843_regval_to_samp_freq[7][2] = {
+	{0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0}
+};
+
+static const int hmc5883_regval_to_samp_freq[7][2] = {
+	{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
+	{75, 0}
+};
+
+/* Describe chip variants */
+struct hmc5843_chip_info {
+	const struct iio_chan_spec *channels;
+	const int (*regval_to_samp_freq)[2];
+	const int *regval_to_nanoscale;
+};
+
+/* The lower two bits contain the current conversion mode */
+static s32 hmc5843_set_mode(struct hmc5843_data *data, u8 operating_mode)
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = regmap_update_bits(data->regmap, HMC5843_MODE_REG,
+			HMC5843_MODE_MASK, operating_mode);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static int hmc5843_wait_measurement(struct hmc5843_data *data)
+{
+	int tries = 150;
+	int val;
+	int ret;
+
+	while (tries-- > 0) {
+		ret = regmap_read(data->regmap, HMC5843_STATUS_REG, &val);
+		if (ret < 0)
+			return ret;
+		if (val & HMC5843_DATA_READY)
+			break;
+		msleep(20);
+	}
+
+	if (tries < 0) {
+		dev_err(data->dev, "data not ready\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/* Return the measurement value from the specified channel */
+static int hmc5843_read_measurement(struct hmc5843_data *data,
+				    int idx, int *val)
+{
+	__be16 values[3];
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = hmc5843_wait_measurement(data);
+	if (ret < 0) {
+		mutex_unlock(&data->lock);
+		return ret;
+	}
+	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
+			values, sizeof(values));
+	mutex_unlock(&data->lock);
+	if (ret < 0)
+		return ret;
+
+	*val = sign_extend32(be16_to_cpu(values[idx]), 15);
+	return IIO_VAL_INT;
+}
+
+/*
+ * API for setting the measurement configuration to
+ * Normal, Positive bias and Negative bias
+ *
+ * 
+ * 0 - Normal measurement configuration (default): In normal measurement
+ *     configuration the device follows normal measurement flow. Pins BP
+ *     and BN are left floating and high impedance.
+ *
+ * 1 - Positive bias configuration: In positive bias configuration, a
+ *     positive current is forced across the resistive load on pins BP
+ *     and BN.
+ *
+ * 2 - Negative bias configuration. In negative bias configuration, a
+ *     negative current is forced across the resistive load on pins BP
+ *     and BN.
+ *
+ */
+static int hmc5843_set_meas_conf(struct hmc5843_data *data, u8 meas_conf)
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
+			HMC5843_MEAS_CONF_MASK, meas_conf);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static ssize_t hmc5843_show_measurement_configuration(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+	int val;
+	int ret;
+
+	ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &val);
+	if (ret)
+		return ret;
+	val &= HMC5843_MEAS_CONF_MASK;
+
+	return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t hmc5843_set_measurement_configuration(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf,
+						size_t count)
+{
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+	unsigned long meas_conf = 0;
+	int ret;
+
+	ret = kstrtoul(buf, 10, &meas_conf);
+	if (ret)
+		return ret;
+	if (meas_conf >= HMC5843_MEAS_CONF_MASK)
+		return -EINVAL;
+
+	ret = hmc5843_set_meas_conf(data, meas_conf);
+
+	return (ret < 0) ? ret : count;
+}
+
+static IIO_DEVICE_ATTR(meas_conf,
+			S_IWUSR | S_IRUGO,
+			hmc5843_show_measurement_configuration,
+			hmc5843_set_measurement_configuration,
+			0);
+
+static ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+	size_t len = 0;
+	int i;
+
+	for (i = 0; i < HMC5843_RATES; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len,
+			"%d.%d ", data->variant->regval_to_samp_freq[i][0],
+			data->variant->regval_to_samp_freq[i][1]);
+
+	/* replace trailing space by newline */
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(hmc5843_show_samp_freq_avail);
+
+static int hmc5843_set_samp_freq(struct hmc5843_data *data, u8 rate)
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_A,
+			HMC5843_RATE_MASK, rate << HMC5843_RATE_OFFSET);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static int hmc5843_get_samp_freq_index(struct hmc5843_data *data,
+				   int val, int val2)
+{
+	int i;
+
+	for (i = 0; i < HMC5843_RATES; i++)
+		if (val == data->variant->regval_to_samp_freq[i][0] &&
+			val2 == data->variant->regval_to_samp_freq[i][1])
+			return i;
+
+	return -EINVAL;
+}
+
+static int hmc5843_set_range_gain(struct hmc5843_data *data, u8 range)
+{
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = regmap_update_bits(data->regmap, HMC5843_CONFIG_REG_B,
+			HMC5843_RANGE_GAIN_MASK,
+			range << HMC5843_RANGE_GAIN_OFFSET);
+	mutex_unlock(&data->lock);
+
+	return ret;
+}
+
+static ssize_t hmc5843_show_scale_avail(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct hmc5843_data *data = iio_priv(dev_to_iio_dev(dev));
+
+	size_t len = 0;
+	int i;
+
+	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
+		len += scnprintf(buf + len, PAGE_SIZE - len,
+			"0.%09d ", data->variant->regval_to_nanoscale[i]);
+
+	/* replace trailing space by newline */
+	buf[len - 1] = '\n';
+
+	return len;
+}
+
+static IIO_DEVICE_ATTR(scale_available, S_IRUGO,
+	hmc5843_show_scale_avail, NULL, 0);
+
+static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2)
+{
+	int i;
+
+	if (val != 0)
+		return -EINVAL;
+
+	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
+		if (val2 == data->variant->regval_to_nanoscale[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static int hmc5843_read_raw(struct iio_dev *indio_dev,
+			    struct iio_chan_spec const *chan,
+			    int *val, int *val2, long mask)
+{
+	struct hmc5843_data *data = iio_priv(indio_dev);
+	int rval;
+	int ret;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		return hmc5843_read_measurement(data, chan->scan_index, val);
+	case IIO_CHAN_INFO_SCALE:
+		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval);
+		if (ret < 0)
+			return ret;
+		rval >>= HMC5843_RANGE_GAIN_OFFSET;
+		*val = 0;
+		*val2 = data->variant->regval_to_nanoscale[rval];
+		return IIO_VAL_INT_PLUS_NANO;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval);
+		if (ret < 0)
+			return ret;
+		rval >>= HMC5843_RATE_OFFSET;
+		*val = data->variant->regval_to_samp_freq[rval][0];
+		*val2 = data->variant->regval_to_samp_freq[rval][1];
+		return IIO_VAL_INT_PLUS_MICRO;
+	}
+	return -EINVAL;
+}
+
+static int hmc5843_write_raw(struct iio_dev *indio_dev,
+			     struct iio_chan_spec const *chan,
+			     int val, int val2, long mask)
+{
+	struct hmc5843_data *data = iio_priv(indio_dev);
+	int rate, range;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		rate = hmc5843_get_samp_freq_index(data, val, val2);
+		if (rate < 0)
+			return -EINVAL;
+
+		return hmc5843_set_samp_freq(data, rate);
+	case IIO_CHAN_INFO_SCALE:
+		range = hmc5843_get_scale_index(data, val, val2);
+		if (range < 0)
+			return -EINVAL;
+
+		return hmc5843_set_range_gain(data, range);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int hmc5843_write_raw_get_fmt(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan, long mask)
+{
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		return IIO_VAL_INT_PLUS_MICRO;
+	case IIO_CHAN_INFO_SCALE:
+		return IIO_VAL_INT_PLUS_NANO;
+	default:
+		return -EINVAL;
+	}
+}
+
+static irqreturn_t hmc5843_trigger_handler(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct hmc5843_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->lock);
+	ret = hmc5843_wait_measurement(data);
+	if (ret < 0) {
+		mutex_unlock(&data->lock);
+		goto done;
+	}
+
+	ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS,
+			data->buffer, 3 * sizeof(__be16));
+
+	mutex_unlock(&data->lock);
+	if (ret < 0)
+		goto done;
+
+	iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+		iio_get_time_ns());
+
+done:
+	iio_trigger_notify_done(indio_dev->trig);
+
+	return IRQ_HANDLED;
+}
+
+#define HMC5843_CHANNEL(axis, idx)					\
+	{								\
+		.type = IIO_MAGN,					\
+		.modified = 1,						\
+		.channel2 = IIO_MOD_##axis,				\
+		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |	\
+			BIT(IIO_CHAN_INFO_SAMP_FREQ),			\
+		.scan_index = idx,					\
+		.scan_type = {						\
+			.sign = 's',					\
+			.realbits = 16,					\
+			.storagebits = 16,				\
+			.endianness = IIO_BE,				\
+		},							\
+	}
+
+static const struct iio_chan_spec hmc5843_channels[] = {
+	HMC5843_CHANNEL(X, 0),
+	HMC5843_CHANNEL(Y, 1),
+	HMC5843_CHANNEL(Z, 2),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+/* Beware: Y and Z are exchanged on HMC5883 */
+static const struct iio_chan_spec hmc5883_channels[] = {
+	HMC5843_CHANNEL(X, 0),
+	HMC5843_CHANNEL(Z, 1),
+	HMC5843_CHANNEL(Y, 2),
+	IIO_CHAN_SOFT_TIMESTAMP(3),
+};
+
+static struct attribute *hmc5843_attributes[] = {
+	&iio_dev_attr_meas_conf.dev_attr.attr,
+	&iio_dev_attr_scale_available.dev_attr.attr,
+	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group hmc5843_group = {
+	.attrs = hmc5843_attributes,
+};
+
+static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
+	[HMC5843_ID] = {
+		.channels = hmc5843_channels,
+		.regval_to_samp_freq = hmc5843_regval_to_samp_freq,
+		.regval_to_nanoscale = hmc5843_regval_to_nanoscale,
+	},
+	[HMC5883_ID] = {
+		.channels = hmc5883_channels,
+		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
+		.regval_to_nanoscale = hmc5883_regval_to_nanoscale,
+	},
+	[HMC5883L_ID] = {
+		.channels = hmc5883_channels,
+		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
+		.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
+	},
+};
+
+static int hmc5843_init(struct hmc5843_data *data)
+{
+	int ret;
+	u8 id[3];
+
+	ret = regmap_bulk_read(data->regmap, HMC5843_ID_REG,
+			id, ARRAY_SIZE(id));
+	if (ret < 0)
+		return ret;
+	if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
+		dev_err(data->dev, "no HMC5843/5883/5883L sensor\n");
+		return -ENODEV;
+	}
+
+	ret = hmc5843_set_meas_conf(data, HMC5843_MEAS_CONF_NORMAL);
+	if (ret < 0)
+		return ret;
+	ret = hmc5843_set_samp_freq(data, HMC5843_RATE_DEFAULT);
+	if (ret < 0)
+		return ret;
+	ret = hmc5843_set_range_gain(data, HMC5843_RANGE_GAIN_DEFAULT);
+	if (ret < 0)
+		return ret;
+	return hmc5843_set_mode(data, HMC5843_MODE_CONVERSION_CONTINUOUS);
+}
+
+static const struct iio_info hmc5843_info = {
+	.attrs = &hmc5843_group,
+	.read_raw = &hmc5843_read_raw,
+	.write_raw = &hmc5843_write_raw,
+	.write_raw_get_fmt = &hmc5843_write_raw_get_fmt,
+	.driver_module = THIS_MODULE,
+};
+
+static const unsigned long hmc5843_scan_masks[] = {0x7, 0};
+
+
+int hmc5843_common_suspend(struct iio_dev *indio_dev)
+{
+	return hmc5843_set_mode(iio_priv(indio_dev),
+			HMC5843_MODE_CONVERSION_CONTINUOUS);
+}
+EXPORT_SYMBOL(hmc5843_common_suspend);
+
+int hmc5843_common_resume(struct iio_dev *indio_dev)
+{
+	return hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
+}
+EXPORT_SYMBOL(hmc5843_common_resume);
+
+int hmc5843_common_probe(struct iio_dev *indio_dev, enum hmc5843_ids id)
+{
+	struct hmc5843_data *data;
+	int ret;
+
+	/* default settings at probe */
+	data = iio_priv(indio_dev);
+	data->variant = &hmc5843_chip_info_tbl[id];
+	mutex_init(&data->lock);
+
+	indio_dev->info = &hmc5843_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = data->variant->channels;
+	indio_dev->num_channels = 4;
+	indio_dev->available_scan_masks = hmc5843_scan_masks;
+
+	ret = hmc5843_init(data);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+		hmc5843_trigger_handler, NULL);
+	if (ret < 0)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret < 0)
+		goto buffer_cleanup;
+
+	return 0;
+
+buffer_cleanup:
+	iio_triggered_buffer_cleanup(indio_dev);
+	return ret;
+}
+EXPORT_SYMBOL(hmc5843_common_probe);
+
+int hmc5843_common_remove(struct iio_dev *indio_dev)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	/*  sleep mode to save power */
+	hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
+
+	return 0;
+}
+EXPORT_SYMBOL(hmc5843_common_remove);
+
+MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>");
+MODULE_DESCRIPTION("HMC5843/5883/5883L core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/magnetometer/hmc5843_i2c.c b/drivers/staging/iio/magnetometer/hmc5843_i2c.c
new file mode 100644
index 0000000..b3c92d9
--- /dev/null
+++ b/drivers/staging/iio/magnetometer/hmc5843_i2c.c
@@ -0,0 +1,106 @@
+/*
+ * i2c driver for hmc5843/5843/5883/5883l
+ *
+ * Split from hmc5843.c
+ * Copyright (C) Josef Gajdusek <atx@atx.name>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms 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/regmap.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/triggered_buffer.h>
+
+#include "hmc5843.h"
+
+struct regmap_config hmc5843_i2c_regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+
+		.rd_table = &hmc5843_readable_table,
+		.wr_table = &hmc5843_writable_table,
+		.volatile_table = &hmc5843_volatile_table,
+
+		.cache_type = REGCACHE_RBTREE,
+};
+
+static int hmc5843_i2c_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct hmc5843_data *data;
+	struct iio_dev *indio_dev;
+
+	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, indio_dev);
+
+	data = iio_priv(indio_dev);
+	data->dev = &client->dev;
+	data->regmap = devm_regmap_init_i2c(client, &hmc5843_i2c_regmap_config);
+
+	indio_dev->name = id->name;
+	indio_dev->dev.parent = &client->dev;
+
+	return hmc5843_common_probe(indio_dev, id->driver_data);
+}
+
+static int hmc5843_i2c_remove(struct i2c_client *client)
+{
+	struct iio_dev *indio_dev = i2c_get_clientdata(client);
+	return hmc5843_common_remove(indio_dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int hmc5843_i2c_suspend(struct device *dev)
+{
+	return hmc5843_common_suspend(i2c_get_clientdata(to_i2c_client(dev)));
+}
+
+static int hmc5843_i2c_resume(struct device *dev)
+{
+	return hmc5843_common_resume(i2c_get_clientdata(to_i2c_client(dev)));
+}
+
+static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops,
+		hmc5843_i2c_suspend, hmc5843_i2c_resume);
+#define HMC5843_PM_OPS (&hmc5843_pm_ops)
+#else
+#define HMC5843_PM_OPS NULL
+#endif
+
+static const struct i2c_device_id hmc5843_id[] = {
+	{ "hmc5843", HMC5843_ID },
+	{ "hmc5883", HMC5883_ID },
+	{ "hmc5883l", HMC5883L_ID },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, hmc5843_id);
+
+static const struct of_device_id hmc5843_of_match[] = {
+	{ .compatible = "honeywell,hmc5843" },
+	{}
+};
+MODULE_DEVICE_TABLE(of, hmc5843_of_match);
+
+static struct i2c_driver hmc5843_driver = {
+	.driver = {
+		.name	= "hmc5843",
+		.pm	= HMC5843_PM_OPS,
+		.of_match_table = hmc5843_of_match,
+	},
+	.id_table	= hmc5843_id,
+	.probe		= hmc5843_i2c_probe,
+	.remove		= hmc5843_i2c_remove,
+};
+module_i2c_driver(hmc5843_driver);
+
+MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>");
+MODULE_DESCRIPTION("HMC5843/5883/5883L i2c driver");
+MODULE_LICENSE("GPL");
-- 
1.8.5.5


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

* [PATCH v2 3/5] staging:iio:hmc5843: register <-> value arrays now can have different lengths
  2014-07-07 20:33 [PATCH v2 0/5] staging:iio:hmc5843: Few adjustments and support for hmc5983 Josef Gajdusek
  2014-07-07 20:34 ` [PATCH v2 1/5] staging:iio:hmc5843: Added regmap support Josef Gajdusek
  2014-07-07 20:36 ` [PATCH v2 2/5] staging:iio:hmc5843: Split hmc5843.c to multiple files Josef Gajdusek
@ 2014-07-07 20:37 ` Josef Gajdusek
  2014-07-07 20:37 ` [PATCH v2 4/5] staging:iio:hmc5843: Add support for i2c hmc5983 Josef Gajdusek
  2014-07-07 20:38 ` [PATCH v2 5/5] staging:iio:hmc5843: Add support for spi hmc5983 Josef Gajdusek
  4 siblings, 0 replies; 8+ messages in thread
From: Josef Gajdusek @ 2014-07-07 20:37 UTC (permalink / raw)
  To: linux-iio; +Cc: devel, gregkh, jic23, linux-kernel, pmeerw

Changed structure of struct hmc5843_chip_info to include length of translation
arrays. Code previously using #defined constant has been changed accordingly.
This allows to integrate devices which do have different amounts of available
rates/scales.

Signed-off-by: Josef Gajdusek <atx@atx.name>
---
 drivers/staging/iio/magnetometer/hmc5843_core.c | 34 +++++++++++++++++--------
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/staging/iio/magnetometer/hmc5843_core.c b/drivers/staging/iio/magnetometer/hmc5843_core.c
index efabca5..a808e4e 100644
--- a/drivers/staging/iio/magnetometer/hmc5843_core.c
+++ b/drivers/staging/iio/magnetometer/hmc5843_core.c
@@ -39,7 +39,6 @@
  */
 #define HMC5843_RANGE_GAIN_OFFSET		0x05
 #define HMC5843_RANGE_GAIN_DEFAULT		0x01
-#define HMC5843_RANGE_GAINS			8
 #define HMC5843_RANGE_GAIN_MASK		0xe0
 
 /* Device status */
@@ -59,7 +58,6 @@
  */
 #define HMC5843_RATE_OFFSET			0x02
 #define HMC5843_RATE_DEFAULT			0x04
-#define HMC5843_RATES				7
 #define HMC5843_RATE_MASK		0x1c
 
 /* Device measurement configuration */
@@ -69,15 +67,15 @@
 #define HMC5843_MEAS_CONF_MASK			0x03
 
 /* Scaling factors: 10000000/Gain */
-static const int hmc5843_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
+static const int hmc5843_regval_to_nanoscale[] = {
 	6173, 7692, 10309, 12821, 18868, 21739, 25641, 35714
 };
 
-static const int hmc5883_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
+static const int hmc5883_regval_to_nanoscale[] = {
 	7812, 9766, 13021, 16287, 24096, 27701, 32573, 45662
 };
 
-static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
+static const int hmc5883l_regval_to_nanoscale[] = {
 	7299, 9174, 12195, 15152, 22727, 25641, 30303, 43478
 };
 
@@ -94,11 +92,11 @@ static const int hmc5883l_regval_to_nanoscale[HMC5843_RANGE_GAINS] = {
  * 6		| 50			| 75
  * 7		| Not used		| Not used
  */
-static const int hmc5843_regval_to_samp_freq[7][2] = {
+static const int hmc5843_regval_to_samp_freq[][2] = {
 	{0, 500000}, {1, 0}, {2, 0}, {5, 0}, {10, 0}, {20, 0}, {50, 0}
 };
 
-static const int hmc5883_regval_to_samp_freq[7][2] = {
+static const int hmc5883_regval_to_samp_freq[][2] = {
 	{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
 	{75, 0}
 };
@@ -107,7 +105,9 @@ static const int hmc5883_regval_to_samp_freq[7][2] = {
 struct hmc5843_chip_info {
 	const struct iio_chan_spec *channels;
 	const int (*regval_to_samp_freq)[2];
+	const int n_regval_to_samp_freq;
 	const int *regval_to_nanoscale;
+	const int n_regval_to_nanoscale;
 };
 
 /* The lower two bits contain the current conversion mode */
@@ -248,7 +248,7 @@ static ssize_t hmc5843_show_samp_freq_avail(struct device *dev,
 	size_t len = 0;
 	int i;
 
-	for (i = 0; i < HMC5843_RATES; i++)
+	for (i = 0; i < data->variant->n_regval_to_samp_freq; i++)
 		len += scnprintf(buf + len, PAGE_SIZE - len,
 			"%d.%d ", data->variant->regval_to_samp_freq[i][0],
 			data->variant->regval_to_samp_freq[i][1]);
@@ -278,7 +278,7 @@ static int hmc5843_get_samp_freq_index(struct hmc5843_data *data,
 {
 	int i;
 
-	for (i = 0; i < HMC5843_RATES; i++)
+	for (i = 0; i < data->variant->n_regval_to_samp_freq; i++)
 		if (val == data->variant->regval_to_samp_freq[i][0] &&
 			val2 == data->variant->regval_to_samp_freq[i][1])
 			return i;
@@ -307,7 +307,7 @@ static ssize_t hmc5843_show_scale_avail(struct device *dev,
 	size_t len = 0;
 	int i;
 
-	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
+	for (i = 0; i < data->variant->n_regval_to_nanoscale; i++)
 		len += scnprintf(buf + len, PAGE_SIZE - len,
 			"0.%09d ", data->variant->regval_to_nanoscale[i]);
 
@@ -327,7 +327,7 @@ static int hmc5843_get_scale_index(struct hmc5843_data *data, int val, int val2)
 	if (val != 0)
 		return -EINVAL;
 
-	for (i = 0; i < HMC5843_RANGE_GAINS; i++)
+	for (i = 0; i < data->variant->n_regval_to_nanoscale; i++)
 		if (val2 == data->variant->regval_to_nanoscale[i])
 			return i;
 
@@ -480,17 +480,29 @@ static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
 	[HMC5843_ID] = {
 		.channels = hmc5843_channels,
 		.regval_to_samp_freq = hmc5843_regval_to_samp_freq,
+		.n_regval_to_samp_freq =
+				ARRAY_SIZE(hmc5843_regval_to_samp_freq),
 		.regval_to_nanoscale = hmc5843_regval_to_nanoscale,
+		.n_regval_to_nanoscale =
+				ARRAY_SIZE(hmc5843_regval_to_nanoscale),
 	},
 	[HMC5883_ID] = {
 		.channels = hmc5883_channels,
 		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
+		.n_regval_to_samp_freq =
+				ARRAY_SIZE(hmc5883_regval_to_samp_freq),
 		.regval_to_nanoscale = hmc5883_regval_to_nanoscale,
+		.n_regval_to_nanoscale =
+				ARRAY_SIZE(hmc5883_regval_to_nanoscale),
 	},
 	[HMC5883L_ID] = {
 		.channels = hmc5883_channels,
 		.regval_to_samp_freq = hmc5883_regval_to_samp_freq,
+		.n_regval_to_samp_freq =
+				ARRAY_SIZE(hmc5883_regval_to_samp_freq),
 		.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
+		.n_regval_to_nanoscale =
+				ARRAY_SIZE(hmc5883l_regval_to_nanoscale),
 	},
 };
 
-- 
1.8.5.5


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

* [PATCH v2 4/5] staging:iio:hmc5843: Add support for i2c hmc5983
  2014-07-07 20:33 [PATCH v2 0/5] staging:iio:hmc5843: Few adjustments and support for hmc5983 Josef Gajdusek
                   ` (2 preceding siblings ...)
  2014-07-07 20:37 ` [PATCH v2 3/5] staging:iio:hmc5843: register <-> value arrays now can have different lengths Josef Gajdusek
@ 2014-07-07 20:37 ` Josef Gajdusek
  2014-07-07 20:38 ` [PATCH v2 5/5] staging:iio:hmc5843: Add support for spi hmc5983 Josef Gajdusek
  4 siblings, 0 replies; 8+ messages in thread
From: Josef Gajdusek @ 2014-07-07 20:37 UTC (permalink / raw)
  To: linux-iio; +Cc: devel, gregkh, jic23, linux-kernel, pmeerw

This patch adds support for the hmc5983 i2c interface.
This chip is almost identical to the hmc5883. The difference being added
temperature compensation, additional available sample rate (220Hz) and an SPI
interface.

Signed-off-by: Josef Gajdusek <atx@atx.name>
---
 drivers/staging/iio/magnetometer/Kconfig        |  2 +-
 drivers/staging/iio/magnetometer/hmc5843.h      |  1 +
 drivers/staging/iio/magnetometer/hmc5843_core.c | 20 +++++++++++++++++---
 drivers/staging/iio/magnetometer/hmc5843_i2c.c  |  5 +++--
 4 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig
index 28c2612..32c69c0 100644
--- a/drivers/staging/iio/magnetometer/Kconfig
+++ b/drivers/staging/iio/magnetometer/Kconfig
@@ -16,7 +16,7 @@ config SENSORS_HMC5843
 	  This driver can also be compiled as a set of modules.
 	  If so, these modules will be created:
 	  - hmc5843_core (core functions)
-	  - hmc5843_i2c (support for HMC5843, HMC5883 and HMC5883L)
+	  - hmc5843_i2c (support for HMC5843, HMC5883, HMC5883L and HMC5983)
 
 config SENSORS_HMC5843_I2C
 	tristate
diff --git a/drivers/staging/iio/magnetometer/hmc5843.h b/drivers/staging/iio/magnetometer/hmc5843.h
index 4e3cce3..c36041a 100644
--- a/drivers/staging/iio/magnetometer/hmc5843.h
+++ b/drivers/staging/iio/magnetometer/hmc5843.h
@@ -29,6 +29,7 @@ enum hmc5843_ids {
 	HMC5843_ID,
 	HMC5883_ID,
 	HMC5883L_ID,
+	HMC5983_ID,
 };
 
 struct hmc5843_data {
diff --git a/drivers/staging/iio/magnetometer/hmc5843_core.c b/drivers/staging/iio/magnetometer/hmc5843_core.c
index a808e4e..fe7a79a 100644
--- a/drivers/staging/iio/magnetometer/hmc5843_core.c
+++ b/drivers/staging/iio/magnetometer/hmc5843_core.c
@@ -101,6 +101,11 @@ static const int hmc5883_regval_to_samp_freq[][2] = {
 	{75, 0}
 };
 
+static const int hmc5983_regval_to_samp_freq[][2] = {
+	{0, 750000}, {1, 500000}, {3, 0}, {7, 500000}, {15, 0}, {30, 0},
+	{75, 0}, {220, 0}
+};
+
 /* Describe chip variants */
 struct hmc5843_chip_info {
 	const struct iio_chan_spec *channels;
@@ -457,7 +462,7 @@ static const struct iio_chan_spec hmc5843_channels[] = {
 	IIO_CHAN_SOFT_TIMESTAMP(3),
 };
 
-/* Beware: Y and Z are exchanged on HMC5883 */
+/* Beware: Y and Z are exchanged on HMC5883 and 5983 */
 static const struct iio_chan_spec hmc5883_channels[] = {
 	HMC5843_CHANNEL(X, 0),
 	HMC5843_CHANNEL(Z, 1),
@@ -504,6 +509,15 @@ static const struct hmc5843_chip_info hmc5843_chip_info_tbl[] = {
 		.n_regval_to_nanoscale =
 				ARRAY_SIZE(hmc5883l_regval_to_nanoscale),
 	},
+	[HMC5983_ID] = {
+		.channels = hmc5883_channels,
+		.regval_to_samp_freq = hmc5983_regval_to_samp_freq,
+		.n_regval_to_samp_freq =
+				ARRAY_SIZE(hmc5983_regval_to_samp_freq),
+		.regval_to_nanoscale = hmc5883l_regval_to_nanoscale,
+		.n_regval_to_nanoscale =
+				ARRAY_SIZE(hmc5883l_regval_to_nanoscale),
+	}
 };
 
 static int hmc5843_init(struct hmc5843_data *data)
@@ -516,7 +530,7 @@ static int hmc5843_init(struct hmc5843_data *data)
 	if (ret < 0)
 		return ret;
 	if (id[0] != 'H' || id[1] != '4' || id[2] != '3') {
-		dev_err(data->dev, "no HMC5843/5883/5883L sensor\n");
+		dev_err(data->dev, "no HMC5843/5883/5883L/5983 sensor\n");
 		return -ENODEV;
 	}
 
@@ -608,5 +622,5 @@ int hmc5843_common_remove(struct iio_dev *indio_dev)
 EXPORT_SYMBOL(hmc5843_common_remove);
 
 MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>");
-MODULE_DESCRIPTION("HMC5843/5883/5883L core driver");
+MODULE_DESCRIPTION("HMC5843/5883/5883L/5983 core driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/staging/iio/magnetometer/hmc5843_i2c.c b/drivers/staging/iio/magnetometer/hmc5843_i2c.c
index b3c92d9..753c914 100644
--- a/drivers/staging/iio/magnetometer/hmc5843_i2c.c
+++ b/drivers/staging/iio/magnetometer/hmc5843_i2c.c
@@ -1,5 +1,5 @@
 /*
- * i2c driver for hmc5843/5843/5883/5883l
+ * i2c driver for hmc5843/5843/5883/5883l/5983
  *
  * Split from hmc5843.c
  * Copyright (C) Josef Gajdusek <atx@atx.name>
@@ -79,6 +79,7 @@ static const struct i2c_device_id hmc5843_id[] = {
 	{ "hmc5843", HMC5843_ID },
 	{ "hmc5883", HMC5883_ID },
 	{ "hmc5883l", HMC5883L_ID },
+	{ "hmc5983", HMC5983_ID },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, hmc5843_id);
@@ -102,5 +103,5 @@ static struct i2c_driver hmc5843_driver = {
 module_i2c_driver(hmc5843_driver);
 
 MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>");
-MODULE_DESCRIPTION("HMC5843/5883/5883L i2c driver");
+MODULE_DESCRIPTION("HMC5843/5883/5883L/5983 i2c driver");
 MODULE_LICENSE("GPL");
-- 
1.8.5.5



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

* [PATCH v2 5/5] staging:iio:hmc5843: Add support for spi hmc5983
  2014-07-07 20:33 [PATCH v2 0/5] staging:iio:hmc5843: Few adjustments and support for hmc5983 Josef Gajdusek
                   ` (3 preceding siblings ...)
  2014-07-07 20:37 ` [PATCH v2 4/5] staging:iio:hmc5843: Add support for i2c hmc5983 Josef Gajdusek
@ 2014-07-07 20:38 ` Josef Gajdusek
  4 siblings, 0 replies; 8+ messages in thread
From: Josef Gajdusek @ 2014-07-07 20:38 UTC (permalink / raw)
  To: linux-iio; +Cc: devel, gregkh, jic23, linux-kernel, pmeerw

This patch adds support for the hmc5983 spi interface.
This chip is almost identical to the hmc5883. The difference being added
temperature compensation, additional available sample rate (220Hz) and an SPI
interface.

Signed-off-by: Josef Gajdusek <atx@atx.name>
---
 drivers/staging/iio/magnetometer/Kconfig       |   8 ++
 drivers/staging/iio/magnetometer/Makefile      |   1 +
 drivers/staging/iio/magnetometer/hmc5843_spi.c | 105 +++++++++++++++++++++++++
 3 files changed, 114 insertions(+)
 create mode 100644 drivers/staging/iio/magnetometer/hmc5843_spi.c

diff --git a/drivers/staging/iio/magnetometer/Kconfig b/drivers/staging/iio/magnetometer/Kconfig
index 32c69c0..bc5c355 100644
--- a/drivers/staging/iio/magnetometer/Kconfig
+++ b/drivers/staging/iio/magnetometer/Kconfig
@@ -9,6 +9,7 @@ config SENSORS_HMC5843
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	select SENSORS_HMC5843_I2C if (I2C)
+	select SENSORS_HMC5843_SPI if (SPI_MASTER)
 	help
 	  Say Y here to add support for the Honeywell HMC5843, HMC5883 and
 	  HMC5883L 3-Axis Magnetometer (digital compass).
@@ -17,6 +18,7 @@ config SENSORS_HMC5843
 	  If so, these modules will be created:
 	  - hmc5843_core (core functions)
 	  - hmc5843_i2c (support for HMC5843, HMC5883, HMC5883L and HMC5983)
+	  - hmc5843_spi (support for HMC5983)
 
 config SENSORS_HMC5843_I2C
 	tristate
@@ -24,4 +26,10 @@ config SENSORS_HMC5843_I2C
 	depends on SENSORS_HMC5843
 	select REGMAP_I2C
 
+config SENSORS_HMC5843_SPI
+	tristate
+	depends on SPI_MASTER
+	depends on SENSORS_HMC5843
+	select REGMAP_SPI
+
 endmenu
diff --git a/drivers/staging/iio/magnetometer/Makefile b/drivers/staging/iio/magnetometer/Makefile
index 65baf1c..33761a1 100644
--- a/drivers/staging/iio/magnetometer/Makefile
+++ b/drivers/staging/iio/magnetometer/Makefile
@@ -4,3 +4,4 @@
 
 obj-$(CONFIG_SENSORS_HMC5843)		+= hmc5843_core.o
 obj-$(CONFIG_SENSORS_HMC5843_I2C)	+= hmc5843_i2c.o
+obj-$(CONFIG_SENSORS_HMC5843_SPI)	+= hmc5843_spi.o
diff --git a/drivers/staging/iio/magnetometer/hmc5843_spi.c b/drivers/staging/iio/magnetometer/hmc5843_spi.c
new file mode 100644
index 0000000..3f71ee0
--- /dev/null
+++ b/drivers/staging/iio/magnetometer/hmc5843_spi.c
@@ -0,0 +1,105 @@
+/*
+ * SPI driver for hmc5983
+ *
+ * Copyright (C) Josef Gajdusek <atx@atx.name>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * */
+
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/iio/iio.h>
+
+#include "hmc5843.h"
+
+struct regmap_config hmc5843_spi_regmap_config = {
+		.reg_bits = 8,
+		.val_bits = 8,
+
+		.rd_table = &hmc5843_readable_table,
+		.wr_table = &hmc5843_writable_table,
+		.volatile_table = &hmc5843_volatile_table,
+
+		/* Autoincrement address pointer */
+		.read_flag_mask = 0xc0,
+
+		.cache_type = REGCACHE_RBTREE,
+};
+
+static int hmc5843_spi_probe(struct spi_device *spi)
+{
+	struct hmc5843_data *data;
+	struct iio_dev *indio_dev;
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));
+	if (indio_dev == NULL)
+		return -ENOMEM;
+
+	spi->mode = SPI_MODE_3;
+	spi->max_speed_hz = 8000000;
+	spi->bits_per_word = 8;
+	ret = spi_setup(spi);
+	if (ret)
+		return ret;
+
+	spi_set_drvdata(spi, indio_dev);
+
+	data = iio_priv(indio_dev);
+	data->dev = &spi->dev;
+	data->regmap = devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config);
+
+	indio_dev->dev.parent = &spi->dev;
+
+	return hmc5843_common_probe(indio_dev, HMC5983_ID);
+}
+
+static int hmc5843_spi_remove(struct spi_device *spi)
+{
+	struct iio_dev *indio_dev = spi_get_drvdata(spi);
+	return hmc5843_common_remove(indio_dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int hmc5843_spi_suspend(struct device *dev)
+{
+	return hmc5843_common_suspend(spi_get_drvdata(to_spi_device(dev)));
+}
+
+static int hmc5843_spi_resume(struct device *dev)
+{
+	return hmc5843_common_resume(spi_get_drvdata(to_spi_device(dev)));
+}
+
+static SIMPLE_DEV_PM_OPS(hmc5843_pm_ops,
+		hmc5843_spi_suspend, hmc5843_spi_resume);
+#define HMC5843_PM_OPS (&hmc5843_pm_ops)
+#else
+#define HMC5843_PM_OPS NULL
+#endif
+
+
+static const struct spi_device_id hmc5843_id[] = {
+	{ "hmc5983", HMC5983_ID },
+	{ }
+};
+
+static struct spi_driver hmc5843_driver = {
+		.driver = {
+				.name = "hmc5843",
+				.pm = HMC5843_PM_OPS,
+				.owner = THIS_MODULE,
+		},
+		.id_table = hmc5843_id,
+		.probe = hmc5843_spi_probe,
+		.remove = hmc5843_spi_remove,
+};
+
+module_spi_driver(hmc5843_driver);
+
+MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>");
+MODULE_DESCRIPTION("HMC5983 SPI driver");
+MODULE_LICENSE("GPL");
-- 
1.8.5.5


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

* Re: [PATCH v2 2/5] staging:iio:hmc5843: Split hmc5843.c to multiple files
  2014-07-07 20:36 ` [PATCH v2 2/5] staging:iio:hmc5843: Split hmc5843.c to multiple files Josef Gajdusek
@ 2014-07-08  8:23   ` Dan Carpenter
  2014-07-08 13:20     ` Josef Gajdusek
  0 siblings, 1 reply; 8+ messages in thread
From: Dan Carpenter @ 2014-07-08  8:23 UTC (permalink / raw)
  To: Josef Gajdusek; +Cc: linux-iio, devel, gregkh, pmeerw, linux-kernel, jic23

When you compare the old and new versions of hmc5843_read_raw() then it
appears there is a bug fix or something which hasn't been documentented
in the changelog.

> -static int hmc5843_read_raw(struct iio_dev *indio_dev,
> -			    struct iio_chan_spec const *chan,
> -			    int *val, int *val2, long mask)
> -{
> -	struct hmc5843_data *data = iio_priv(indio_dev);
> -	int rval;
> -	int ret;
> -
> -	switch (mask) {
> -	case IIO_CHAN_INFO_RAW:
> -		return hmc5843_read_measurement(data, chan->scan_index, val);
> -	case IIO_CHAN_INFO_SCALE:
> -		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval);
> -		if (ret < 0)
> -			return ret;
> -		*val = 0;
> -		*val2 = data->variant->regval_to_nanoscale[rval >> HMC5843_RANGE_GAIN_OFFSET];
> -		return IIO_VAL_INT_PLUS_NANO;
> -	case IIO_CHAN_INFO_SAMP_FREQ:
> -		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval);
> -		if (ret < 0)
> -			return ret;
> -		rval &= HMC5843_RATE_MASK;
                ^^^^^^^^^^^^^^^^^^^^^^^^^
HMC5843_RATE_MASK is 0x1c.

> -		*val = data->variant->regval_to_samp_freq[rval][0];
> -		*val2 = data->variant->regval_to_samp_freq[rval][1];
> -		return IIO_VAL_INT_PLUS_MICRO;
> -	}
> -	return -EINVAL;
> -}

> +static int hmc5843_read_raw(struct iio_dev *indio_dev,
> +			    struct iio_chan_spec const *chan,
> +			    int *val, int *val2, long mask)
> +{
> +	struct hmc5843_data *data = iio_priv(indio_dev);
> +	int rval;
> +	int ret;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		return hmc5843_read_measurement(data, chan->scan_index, val);
> +	case IIO_CHAN_INFO_SCALE:
> +		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval);
> +		if (ret < 0)
> +			return ret;
> +		rval >>= HMC5843_RANGE_GAIN_OFFSET;
> +		*val = 0;
> +		*val2 = data->variant->regval_to_nanoscale[rval];
> +		return IIO_VAL_INT_PLUS_NANO;
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval);
> +		if (ret < 0)
> +			return ret;
> +		rval >>= HMC5843_RATE_OFFSET;
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
HMC5843_RATE_OFFSET is 0x02.

> +		*val = data->variant->regval_to_samp_freq[rval][0];
> +		*val2 = data->variant->regval_to_samp_freq[rval][1];
> +		return IIO_VAL_INT_PLUS_MICRO;
> +	}
> +	return -EINVAL;
> +}

Ideally this patch would be a straight move and no code changes.

regards,
dan carpenter

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

* Re: [PATCH v2 2/5] staging:iio:hmc5843: Split hmc5843.c to multiple files
  2014-07-08  8:23   ` Dan Carpenter
@ 2014-07-08 13:20     ` Josef Gajdusek
  0 siblings, 0 replies; 8+ messages in thread
From: Josef Gajdusek @ 2014-07-08 13:20 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: linux-iio, devel, gregkh, pmeerw, linux-kernel, jic23

On Tue, Jul 08, 2014 at 11:23:51AM +0300, Dan Carpenter wrote:
> When you compare the old and new versions of hmc5843_read_raw() then it
> appears there is a bug fix or something which hasn't been documentented
> in the changelog.
> 
> > -static int hmc5843_read_raw(struct iio_dev *indio_dev,
> > -			    struct iio_chan_spec const *chan,
> > -			    int *val, int *val2, long mask)
> > -{
> > -	struct hmc5843_data *data = iio_priv(indio_dev);
> > -	int rval;
> > -	int ret;
> > -
> > -	switch (mask) {
> > -	case IIO_CHAN_INFO_RAW:
> > -		return hmc5843_read_measurement(data, chan->scan_index, val);
> > -	case IIO_CHAN_INFO_SCALE:
> > -		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval);
> > -		if (ret < 0)
> > -			return ret;
> > -		*val = 0;
> > -		*val2 = data->variant->regval_to_nanoscale[rval >> HMC5843_RANGE_GAIN_OFFSET];
> > -		return IIO_VAL_INT_PLUS_NANO;
> > -	case IIO_CHAN_INFO_SAMP_FREQ:
> > -		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval);
> > -		if (ret < 0)
> > -			return ret;
> > -		rval &= HMC5843_RATE_MASK;
>                 ^^^^^^^^^^^^^^^^^^^^^^^^^
> HMC5843_RATE_MASK is 0x1c.
> 
> > -		*val = data->variant->regval_to_samp_freq[rval][0];
> > -		*val2 = data->variant->regval_to_samp_freq[rval][1];
> > -		return IIO_VAL_INT_PLUS_MICRO;
> > -	}
> > -	return -EINVAL;
> > -}
> 
> > +static int hmc5843_read_raw(struct iio_dev *indio_dev,
> > +			    struct iio_chan_spec const *chan,
> > +			    int *val, int *val2, long mask)
> > +{
> > +	struct hmc5843_data *data = iio_priv(indio_dev);
> > +	int rval;
> > +	int ret;
> > +
> > +	switch (mask) {
> > +	case IIO_CHAN_INFO_RAW:
> > +		return hmc5843_read_measurement(data, chan->scan_index, val);
> > +	case IIO_CHAN_INFO_SCALE:
> > +		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_B, &rval);
> > +		if (ret < 0)
> > +			return ret;
> > +		rval >>= HMC5843_RANGE_GAIN_OFFSET;
> > +		*val = 0;
> > +		*val2 = data->variant->regval_to_nanoscale[rval];
> > +		return IIO_VAL_INT_PLUS_NANO;
> > +	case IIO_CHAN_INFO_SAMP_FREQ:
> > +		ret = regmap_read(data->regmap, HMC5843_CONFIG_REG_A, &rval);
> > +		if (ret < 0)
> > +			return ret;
> > +		rval >>= HMC5843_RATE_OFFSET;
>                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> HMC5843_RATE_OFFSET is 0x02.
> 
> > +		*val = data->variant->regval_to_samp_freq[rval][0];
> > +		*val2 = data->variant->regval_to_samp_freq[rval][1];
> > +		return IIO_VAL_INT_PLUS_MICRO;
> > +	}
> > +	return -EINVAL;
> > +}
> 
> Ideally this patch would be a straight move and no code changes.
> 
> regards,
> dan carpenter

It seems I forgot to change the first commit when I discovered this
bug. I will resend fixed version within few minutes.

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

end of thread, other threads:[~2014-07-08 13:20 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-07 20:33 [PATCH v2 0/5] staging:iio:hmc5843: Few adjustments and support for hmc5983 Josef Gajdusek
2014-07-07 20:34 ` [PATCH v2 1/5] staging:iio:hmc5843: Added regmap support Josef Gajdusek
2014-07-07 20:36 ` [PATCH v2 2/5] staging:iio:hmc5843: Split hmc5843.c to multiple files Josef Gajdusek
2014-07-08  8:23   ` Dan Carpenter
2014-07-08 13:20     ` Josef Gajdusek
2014-07-07 20:37 ` [PATCH v2 3/5] staging:iio:hmc5843: register <-> value arrays now can have different lengths Josef Gajdusek
2014-07-07 20:37 ` [PATCH v2 4/5] staging:iio:hmc5843: Add support for i2c hmc5983 Josef Gajdusek
2014-07-07 20:38 ` [PATCH v2 5/5] staging:iio:hmc5843: Add support for spi hmc5983 Josef Gajdusek

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