linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC
@ 2014-06-11 11:11 Adam Thomson
  2014-06-11 11:11 ` [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
                   ` (7 more replies)
  0 siblings, 8 replies; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

This patch set adds initial support for the Dialog DA9150 Integrated Charger &
Fuel-Gauge IC. The device also provides GPIO and GPADC functionality.

In this patch set the following is provided:
 - MFD Core support and DT bindings documentation.
 - Fix to IIO framework (inkern.c, of_iio_channel_get_by_name()) to correctly
   return NULL for failure cases.
 - IIO GPADC support and DT bindings documentation.
 - Power Supply Charger support and DT bindings documentation.
 - Add Dialog vendor prefix for DT.

 To keep patch submission from being too large, support for GPIO and Fuel-Gauge
 will come after initial support patches are accepted.

 This patch set is baselined against the v3.15 kernel version.

Adam Thomson (8):
  mfd: Add support for DA9150 combined charger & fuel-gauge device
  mfd: da9150: Add DT binding documentation for core
  iio: of_iio_channel_get_by_name() returns non-null pointers for error
    legs
  iio: Add support for DA9150 GPADC
  iio: da9150: Add DT binding documentation for GPADC
  power: Add support for DA9150 Charger
  power: da9150: Add DT binding documentation for charger
  DT: Add vendor prefix for Dialog Semiconductor Ltd.

 .../devicetree/bindings/iio/da9150-gpadc.txt       |   16 +
 Documentation/devicetree/bindings/mfd/da9150.txt   |   53 +
 .../devicetree/bindings/power/da9150-charger.txt   |   29 +
 .../devicetree/bindings/vendor-prefixes.txt        |    1 +
 drivers/iio/adc/Kconfig                            |    9 +
 drivers/iio/adc/Makefile                           |    1 +
 drivers/iio/adc/da9150-gpadc.c                     |  396 +++++++
 drivers/iio/inkern.c                               |    6 +-
 drivers/mfd/Kconfig                                |   12 +
 drivers/mfd/Makefile                               |    2 +
 drivers/mfd/da9150-core.c                          |  398 +++++++
 drivers/mfd/da9150-i2c.c                           |  268 +++++
 drivers/power/Kconfig                              |   23 +
 drivers/power/Makefile                             |    1 +
 drivers/power/da9150-charger.c                     |  790 +++++++++++++
 include/linux/mfd/da9150/charger.h                 |   58 +
 include/linux/mfd/da9150/core.h                    |  125 +++
 include/linux/mfd/da9150/gpadc.h                   |   71 ++
 include/linux/mfd/da9150/pdata.h                   |  148 +++
 include/linux/mfd/da9150/registers.h               | 1160 ++++++++++++++++++++
 20 files changed, 3565 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/da9150-gpadc.txt
 create mode 100644 Documentation/devicetree/bindings/mfd/da9150.txt
 create mode 100644 Documentation/devicetree/bindings/power/da9150-charger.txt
 create mode 100644 drivers/iio/adc/da9150-gpadc.c
 create mode 100644 drivers/mfd/da9150-core.c
 create mode 100644 drivers/mfd/da9150-i2c.c
 create mode 100644 drivers/power/da9150-charger.c
 create mode 100644 include/linux/mfd/da9150/charger.h
 create mode 100644 include/linux/mfd/da9150/core.h
 create mode 100644 include/linux/mfd/da9150/gpadc.h
 create mode 100644 include/linux/mfd/da9150/pdata.h
 create mode 100644 include/linux/mfd/da9150/registers.h

--
1.9.3


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

* [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
@ 2014-06-11 11:11 ` Adam Thomson
  2014-06-15 19:49   ` Jonathan Cameron
  2014-06-11 11:11 ` [PATCH 2/8] mfd: da9150: Add DT binding documentation for core Adam Thomson
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

DA9150 is a combined Charger and Fuel-Gauge IC, with additional
GPIO and GPADC functionality.

This patch adds core support for the device.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 drivers/mfd/Kconfig                  |   12 +
 drivers/mfd/Makefile                 |    2 +
 drivers/mfd/da9150-core.c            |  398 ++++++++++++
 drivers/mfd/da9150-i2c.c             |  268 ++++++++
 include/linux/mfd/da9150/core.h      |  125 ++++
 include/linux/mfd/da9150/pdata.h     |  148 +++++
 include/linux/mfd/da9150/registers.h | 1160 ++++++++++++++++++++++++++++++++++
 7 files changed, 2113 insertions(+)
 create mode 100644 drivers/mfd/da9150-core.c
 create mode 100644 drivers/mfd/da9150-i2c.c
 create mode 100644 include/linux/mfd/da9150/core.h
 create mode 100644 include/linux/mfd/da9150/pdata.h
 create mode 100644 include/linux/mfd/da9150/registers.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3383412..4af7cc4 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -171,6 +171,18 @@ config MFD_DA9063
 	  Additional drivers must be enabled in order to use the functionality
 	  of the device.

+config MFD_DA9150
+	bool "Dialog Semiconductor DA9150 Charger Fuel-Gauge chip"
+	depends on I2C=y
+	select MFD_CORE
+	select REGMAP_I2C
+	select REGMAP_IRQ
+	help
+	  This adds support for the DA9150 integrated charger and fuel-gauge
+	  chip. This driver provides common support for accessing the device.
+	  Additional drivers must be enabled in order to use the specific
+	  features of the device.
+
 config MFD_MC13XXX
 	tristate
 	depends on (SPI_MASTER || I2C)
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 2851275..0344494 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -112,6 +112,8 @@ obj-$(CONFIG_MFD_DA9055)	+= da9055.o
 da9063-objs			:= da9063-core.o da9063-irq.o da9063-i2c.o
 obj-$(CONFIG_MFD_DA9063)	+= da9063.o

+obj-$(CONFIG_MFD_DA9150)	+= da9150-core.o da9150-i2c.o
+
 obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
 obj-$(CONFIG_MFD_MAX77686)	+= max77686.o max77686-irq.o
 obj-$(CONFIG_MFD_MAX77693)	+= max77693.o max77693-irq.o
diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c
new file mode 100644
index 0000000..24c62ba
--- /dev/null
+++ b/drivers/mfd/da9150-core.c
@@ -0,0 +1,398 @@
+/*
+ * DA9150 Core MFD Driver
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/core.h>
+
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/registers.h>
+#include <linux/mfd/da9150/pdata.h>
+
+
+/*
+ * Register/Device Access
+ */
+
+int da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf)
+{
+	int ret;
+
+	ret = da9150->read_dev(da9150->core_qif, addr, count, buf);
+	if (ret < 0)
+		dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n",
+			addr, ret);
+
+	return ret;
+}
+
+int da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf)
+{
+	int ret;
+
+	ret = da9150->write_dev(da9150->core_qif, addr, count, buf);
+	if (ret < 0)
+		dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n",
+			addr, ret);
+
+	return ret;
+}
+
+u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
+{
+	int val, ret;
+
+	ret = regmap_read(da9150->regmap, reg, &val);
+	if (ret < 0)
+		dev_err(da9150->dev, "Failed to read from reg 0x%x: %d\n",
+			reg, ret);
+
+	return (u8) val;
+}
+
+int da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val)
+{
+	int ret;
+
+	ret = regmap_write(da9150->regmap, reg, val);
+	if (ret < 0)
+		dev_err(da9150->dev, "Failed to write to reg 0x%x: %d\n",
+			reg, ret);
+
+	return ret;
+}
+
+int da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val)
+{
+	int ret;
+
+	ret = regmap_update_bits(da9150->regmap, reg, mask, val);
+	if (ret < 0)
+		dev_err(da9150->dev, "Failed to set bits in reg 0x%x: %d\n",
+			reg, ret);
+
+	return ret;
+}
+
+int da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf)
+{
+	int ret;
+
+	ret = regmap_bulk_read(da9150->regmap, reg, buf, count);
+	if (ret < 0)
+		dev_err(da9150->dev, "Failed to bulk read from reg 0x%x: %d\n",
+			reg, ret);
+
+	return ret;
+}
+
+int da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf)
+{
+	int ret;
+
+	ret = regmap_raw_write(da9150->regmap, reg, buf, count);
+	if (ret < 0)
+		dev_err(da9150->dev, "Failed to bulk write to reg 0x%x %d\n",
+			reg, ret);
+
+	return ret;
+}
+
+
+/*
+ * IRQ Handling
+ */
+
+static struct regmap_irq da9150_irqs[] = {
+	[DA9150_IRQ_VBUS] = {
+		.reg_offset = 0,
+		.mask = DA9150_E_VBUS_MASK,
+	},
+	[DA9150_IRQ_CHG] = {
+		.reg_offset = 0,
+		.mask = DA9150_E_CHG_MASK,
+	},
+	[DA9150_IRQ_TCLASS] = {
+		.reg_offset = 0,
+		.mask = DA9150_E_TCLASS_MASK,
+	},
+	[DA9150_IRQ_TJUNC] = {
+		.reg_offset = 0,
+		.mask = DA9150_E_TJUNC_MASK,
+	},
+	[DA9150_IRQ_VFAULT] = {
+		.reg_offset = 0,
+		.mask = DA9150_E_VFAULT_MASK,
+	},
+	[DA9150_IRQ_CONF] = {
+		.reg_offset = 1,
+		.mask = DA9150_E_CONF_MASK,
+	},
+	[DA9150_IRQ_DAT] = {
+		.reg_offset = 1,
+		.mask = DA9150_E_DAT_MASK,
+	},
+	[DA9150_IRQ_DTYPE] = {
+		.reg_offset = 1,
+		.mask = DA9150_E_DTYPE_MASK,
+	},
+	[DA9150_IRQ_ID] = {
+		.reg_offset = 1,
+		.mask = DA9150_E_ID_MASK,
+	},
+	[DA9150_IRQ_ADP] = {
+		.reg_offset = 1,
+		.mask = DA9150_E_ADP_MASK,
+	},
+	[DA9150_IRQ_SESS_END] = {
+		.reg_offset = 1,
+		.mask = DA9150_E_SESS_END_MASK,
+	},
+	[DA9150_IRQ_SESS_VLD] = {
+		.reg_offset = 1,
+		.mask = DA9150_E_SESS_VLD_MASK,
+	},
+	[DA9150_IRQ_FG] = {
+		.reg_offset = 2,
+		.mask = DA9150_E_FG_MASK,
+	},
+	[DA9150_IRQ_GP] = {
+		.reg_offset = 2,
+		.mask = DA9150_E_GP_MASK,
+	},
+	[DA9150_IRQ_TBAT] = {
+		.reg_offset = 2,
+		.mask = DA9150_E_TBAT_MASK,
+	},
+	[DA9150_IRQ_GPIOA] = {
+		.reg_offset = 2,
+		.mask = DA9150_E_GPIOA_MASK,
+	},
+	[DA9150_IRQ_GPIOB] = {
+		.reg_offset = 2,
+		.mask = DA9150_E_GPIOB_MASK,
+	},
+	[DA9150_IRQ_GPIOC] = {
+		.reg_offset = 2,
+		.mask = DA9150_E_GPIOC_MASK,
+	},
+	[DA9150_IRQ_GPIOD] = {
+		.reg_offset = 2,
+		.mask = DA9150_E_GPIOD_MASK,
+	},
+	[DA9150_IRQ_GPADC] = {
+		.reg_offset = 2,
+		.mask = DA9150_E_GPADC_MASK,
+	},
+	[DA9150_IRQ_WKUP] = {
+		.reg_offset = 3,
+		.mask = DA9150_E_WKUP_MASK,
+	},
+};
+
+static struct regmap_irq_chip da9150_regmap_irq_chip = {
+	.name = "da9150_irq",
+	.status_base = DA9150_EVENT_E,
+	.mask_base = DA9150_IRQ_MASK_E,
+	.ack_base = DA9150_EVENT_E,
+	.num_regs = DA9150_NUM_IRQ_REGS,
+	.irqs = da9150_irqs,
+	.num_irqs = ARRAY_SIZE(da9150_irqs),
+};
+
+/* Helper function for sub-devices to request IRQs */
+int da9150_register_irq(struct platform_device *pdev, void *dev_id,
+			irq_handler_t handler, const char *name)
+{
+	int irq, ret;
+
+	irq = platform_get_irq_byname(pdev, name);
+	if (irq < 0)
+		return irq;
+
+	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, handler,
+					IRQF_ONESHOT, name, dev_id);
+	if (ret)
+		dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n", irq, ret);
+
+	return ret;
+}
+
+
+/*
+ * MFDs
+ */
+
+static struct resource da9150_gpio_resources[] = {
+	{
+		.name = "GPIOA",
+		.start = DA9150_IRQ_GPIOA,
+		.end = DA9150_IRQ_GPIOA,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource da9150_gpadc_resources[] = {
+	{
+		.name = "GPADC",
+		.start = DA9150_IRQ_GPADC,
+		.end = DA9150_IRQ_GPADC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource da9150_charger_resources[] = {
+	{
+		.name = "CHG_STATUS",
+		.start = DA9150_IRQ_CHG,
+		.end = DA9150_IRQ_CHG,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "CHG_TJUNC",
+		.start = DA9150_IRQ_TJUNC,
+		.end = DA9150_IRQ_TJUNC,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "CHG_VFAULT",
+		.start = DA9150_IRQ_VFAULT,
+		.end = DA9150_IRQ_VFAULT,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "CHG_VBUS",
+		.start = DA9150_IRQ_VBUS,
+		.end = DA9150_IRQ_VBUS,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource da9150_fg_resources[] = {
+	{
+		.name = "FG",
+		.start = DA9150_IRQ_FG,
+		.end = DA9150_IRQ_FG,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell da9150_devs[] = {
+	{
+		.name = "da9150-gpio",
+		.of_compatible = "dlg,da9150-gpio",
+		.resources = da9150_gpio_resources,
+		.num_resources = ARRAY_SIZE(da9150_gpio_resources),
+	},
+	{
+		.name = "da9150-gpadc",
+		.of_compatible = "dlg,da9150-gpadc",
+		.resources = da9150_gpadc_resources,
+		.num_resources = ARRAY_SIZE(da9150_gpadc_resources),
+	},
+	{
+		.name = "da9150-charger",
+		.of_compatible = "dlg,da9150-charger",
+		.resources = da9150_charger_resources,
+		.num_resources = ARRAY_SIZE(da9150_charger_resources),
+	},
+	{
+		.name = "da9150-fuelgauge",
+		.of_compatible = "dlg,da9150-fg",
+		.resources = da9150_fg_resources,
+		.num_resources = ARRAY_SIZE(da9150_fg_resources),
+	},
+};
+
+
+/*
+ * Device Init/Exit
+ */
+
+int da9150_device_init(struct da9150 *da9150)
+{
+	struct da9150_pdata *pdata = da9150->dev->platform_data;
+	int ret;
+
+	/* Handle platform data */
+	if (pdata) {
+		da9150->irq_base = pdata->irq_base;
+
+		da9150_devs[0].platform_data = pdata->gpio_pdata;
+		da9150_devs[0].pdata_size = sizeof(struct da9150_gpio_pdata);
+		da9150_devs[2].platform_data = pdata->charger_pdata;
+		da9150_devs[2].pdata_size = sizeof(struct da9150_charger_pdata);
+		da9150_devs[3].platform_data = pdata->fg_pdata;
+		da9150_devs[3].pdata_size = sizeof(struct da9150_fg_pdata);
+	} else {
+		da9150->irq_base = -1;
+	}
+
+	/* Init IRQs */
+	ret = regmap_add_irq_chip(da9150->regmap, da9150->irq,
+				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+				  da9150->irq_base, &da9150_regmap_irq_chip,
+				  &da9150->regmap_irq_data);
+	if (ret < 0)
+		goto err_irq;
+
+	da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
+
+	/* Make the IRQ line a wake source */
+	enable_irq_wake(da9150->irq);
+
+	/* Add MFD Devices */
+	ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
+			      ARRAY_SIZE(da9150_devs), NULL,
+			      da9150->irq_base, NULL);
+	if (ret < 0) {
+		dev_err(da9150->dev, "Failed to add child devices: %d\n", ret);
+		goto err_mfd;
+	}
+
+	return 0;
+
+err_mfd:
+	regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
+err_irq:
+	return ret;
+}
+
+void da9150_device_exit(struct da9150 *da9150)
+{
+	regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
+	mfd_remove_devices(da9150->dev);
+	return;
+}
+
+void da9150_device_shutdown(struct da9150 *da9150)
+{
+	if (da9150->can_shutdown) {
+		/* Make sure we have a wakup source for the device */
+		da9150_set_bits(da9150, DA9150_CONFIG_D,
+				DA9150_WKUP_PM_EN_MASK,
+				DA9150_WKUP_PM_EN_MASK);
+
+		/* Set device to DISABLED mode */
+		da9150_set_bits(da9150, DA9150_CONTROL_C,
+				DA9150_DISABLE_MASK, DA9150_DISABLE_MASK);
+	}
+}
+
+MODULE_DESCRIPTION("MFD Core Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mfd/da9150-i2c.c b/drivers/mfd/da9150-i2c.c
new file mode 100644
index 0000000..725aaef
--- /dev/null
+++ b/drivers/mfd/da9150-i2c.c
@@ -0,0 +1,268 @@
+/*
+ * DA9150 I2C Driver
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/registers.h>
+
+
+/*
+ * Regmap Config
+ */
+
+static bool da9150_volatile_reg(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case DA9150_PAGE_CON:
+	case DA9150_STATUS_A:
+	case DA9150_STATUS_B:
+	case DA9150_STATUS_C:
+	case DA9150_STATUS_D:
+	case DA9150_STATUS_E:
+	case DA9150_STATUS_F:
+	case DA9150_STATUS_G:
+	case DA9150_STATUS_H:
+	case DA9150_STATUS_I:
+	case DA9150_STATUS_J:
+	case DA9150_STATUS_K:
+	case DA9150_STATUS_L:
+	case DA9150_STATUS_N:
+	case DA9150_FAULT_LOG_A:
+	case DA9150_FAULT_LOG_B:
+	case DA9150_EVENT_E:
+	case DA9150_EVENT_F:
+	case DA9150_EVENT_G:
+	case DA9150_EVENT_H:
+	case DA9150_CONTROL_B:
+	case DA9150_CONTROL_C:
+	case DA9150_GPADC_MAN:
+	case DA9150_GPADC_RES_A:
+	case DA9150_GPADC_RES_B:
+	case DA9150_ADETVB_CFG_C:
+	case DA9150_ADETD_STAT:
+	case DA9150_ADET_CMPSTAT:
+	case DA9150_ADET_CTRL_A:
+	case DA9150_PPR_TCTR_B:
+	case DA9150_COREBTLD_STAT_A:
+	case DA9150_CORE_DATA_A:
+	case DA9150_CORE_DATA_B:
+	case DA9150_CORE_DATA_C:
+	case DA9150_CORE_DATA_D:
+	case DA9150_CORE2WIRE_STAT_A:
+	case DA9150_FW_CTRL_C:
+	case DA9150_FG_CTRL_B:
+	case DA9150_FW_CTRL_B:
+	case DA9150_GPADC_CMAN:
+	case DA9150_GPADC_CRES_A:
+	case DA9150_GPADC_CRES_B:
+	case DA9150_CC_ICHG_RES_A:
+	case DA9150_CC_ICHG_RES_B:
+	case DA9150_CC_IAVG_RES_A:
+	case DA9150_CC_IAVG_RES_B:
+	case DA9150_TAUX_CTRL_A:
+	case DA9150_TAUX_VALUE_H:
+	case DA9150_TAUX_VALUE_L:
+	case DA9150_TBAT_RES_A:
+	case DA9150_TBAT_RES_B:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static const struct regmap_range_cfg da9150_range_cfg[] = {
+	{
+		.range_min = DA9150_PAGE_CON,
+		.range_max = DA9150_TBAT_RES_B,
+		.selector_reg = DA9150_PAGE_CON,
+		.selector_mask = DA9150_I2C_PAGE_MASK,
+		.selector_shift = DA9150_I2C_PAGE_SHIFT,
+		.window_start = 0,
+		.window_len = 256,
+	},
+};
+
+static struct regmap_config da9150_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+	.ranges = da9150_range_cfg,
+	.num_ranges = ARRAY_SIZE(da9150_range_cfg),
+	.max_register = DA9150_TBAT_RES_B,
+
+	.cache_type = REGCACHE_RBTREE,
+
+	.volatile_reg = da9150_volatile_reg,
+};
+
+
+/*
+ * Device access for QIF interface
+ */
+
+static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count,
+				  u8 *buf)
+{
+	struct i2c_msg xfer;
+	int ret;
+
+	/*
+	 * Read is split into two transfers as device expects STOP/START rather
+	 * than repeated start to carry out this kind of access.
+	 */
+
+	/* Write address */
+	xfer.addr = client->addr;
+	xfer.flags = 0;
+	xfer.len = 1;
+	xfer.buf = &addr;
+
+	ret = i2c_transfer(client->adapter, &xfer, 1);
+	if (ret != 1) {
+		if (ret < 0)
+			return ret;
+		else
+			return -EIO;
+	}
+
+	/* Read data */
+	xfer.addr = client->addr;
+	xfer.flags = I2C_M_RD;
+	xfer.len = count;
+	xfer.buf = buf;
+
+	ret = i2c_transfer(client->adapter, &xfer, 1);
+	if (ret == 1)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+static int da9150_i2c_write_device(struct i2c_client *client, u8 addr, int count,
+				   const u8 *buf)
+{
+	struct i2c_msg xfer;
+	u8 *reg_data;
+	int ret;
+
+	reg_data = kzalloc(1 + count, GFP_KERNEL);
+	if (!reg_data)
+		return -ENOMEM;
+
+	reg_data[0] = addr;
+	memcpy(&reg_data[1], buf, count);
+
+	/* Write address & data */
+	xfer.addr = client->addr;
+	xfer.flags = 0;
+	xfer.len = 1 + count;
+	xfer.buf = reg_data;
+
+	ret = i2c_transfer(client->adapter, &xfer, 1);
+	kfree(reg_data);
+	if (ret == 1)
+		return 0;
+	else if (ret < 0)
+		return ret;
+	else
+		return -EIO;
+}
+
+
+/*
+ * Driver top level functions
+ */
+
+static int da9150_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct da9150 *da9150;
+	int ret;
+
+	da9150 = devm_kzalloc(&client->dev, sizeof(struct da9150), GFP_KERNEL);
+	if (da9150 == NULL)
+		return -ENOMEM;
+	da9150->dev = &client->dev;
+	da9150->irq = client->irq;
+	i2c_set_clientdata(client, da9150);
+	dev_set_drvdata(da9150->dev, da9150);
+
+	da9150->core_qif = i2c_new_dummy(client->adapter, DA9150_QIF_I2C_ADDR);
+	i2c_set_clientdata(da9150->core_qif, da9150);
+
+	da9150->regmap = devm_regmap_init_i2c(client, &da9150_regmap_config);
+	if (IS_ERR(da9150->regmap)) {
+		ret = PTR_ERR(da9150->regmap);
+		dev_err(da9150->dev, "Failed to allocate register map: %d\n",
+			ret);
+		return ret;
+	}
+
+	da9150->read_dev = (read_dev_t) da9150_i2c_read_device;
+	da9150->write_dev = (write_dev_t) da9150_i2c_write_device;
+
+	return da9150_device_init(da9150);
+}
+
+static int da9150_remove(struct i2c_client *client)
+{
+	struct da9150 *da9150 = i2c_get_clientdata(client);
+
+	da9150_device_exit(da9150);
+	i2c_unregister_device(da9150->core_qif);
+
+	return 0;
+}
+
+static void da9150_shutdown(struct i2c_client *client)
+{
+	struct da9150 *da9150 = i2c_get_clientdata(client);
+
+	da9150_device_shutdown(da9150);
+}
+
+static const struct i2c_device_id da9150_i2c_id[] = {
+	{ "da9150", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, da9150_i2c_id);
+
+static const struct of_device_id da9150_of_match[] = {
+	{ .compatible = "dlg,da9150", },
+	{ }
+};
+
+static struct i2c_driver da9150_driver = {
+	.driver	= {
+		.name	= "da9150",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(da9150_of_match),
+	},
+	.probe		= da9150_probe,
+	.remove		= da9150_remove,
+	.shutdown	= da9150_shutdown,
+	.id_table	= da9150_i2c_id,
+};
+
+module_i2c_driver(da9150_driver);
+
+MODULE_DESCRIPTION("I2C Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/da9150/core.h b/include/linux/mfd/da9150/core.h
new file mode 100644
index 0000000..39997406
--- /dev/null
+++ b/include/linux/mfd/da9150/core.h
@@ -0,0 +1,125 @@
+/*
+ * DA9150 MFD Driver - Core Data
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#ifndef _DA9150_CORE_H
+#define _DA9150_CORE_H
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/regmap.h>
+#include <linux/mutex.h>
+
+/*
+ * Defines
+ */
+
+/* I2C sub-device addresses */
+#define DA9150_QIF_I2C_ADDR	0x6D
+
+/* I2C address paging */
+#define DA9150_REG_PAGE_SHIFT	8
+#define DA9150_REG_PAGE_MASK	0xFF
+
+/* IRQs */
+#define DA9150_NUM_IRQ_REGS	4
+#define DA9150_IRQ_VBUS		0
+#define DA9150_IRQ_CHG		1
+#define DA9150_IRQ_TCLASS	2
+#define DA9150_IRQ_TJUNC	3
+#define DA9150_IRQ_VFAULT	4
+#define DA9150_IRQ_CONF		5
+#define DA9150_IRQ_DAT		6
+#define DA9150_IRQ_DTYPE	7
+#define DA9150_IRQ_ID		8
+#define DA9150_IRQ_ADP		9
+#define DA9150_IRQ_SESS_END	10
+#define DA9150_IRQ_SESS_VLD	11
+#define DA9150_IRQ_FG		12
+#define DA9150_IRQ_GP		13
+#define DA9150_IRQ_TBAT		14
+#define DA9150_IRQ_GPIOA	15
+#define DA9150_IRQ_GPIOB	16
+#define DA9150_IRQ_GPIOC	17
+#define DA9150_IRQ_GPIOD	18
+#define DA9150_IRQ_GPADC	19
+#define DA9150_IRQ_WKUP		20
+
+/* Helper macros to convert real world values to register values */
+#define DA9150_CHG_IBAT_FACTOR		25000
+#define DA9150_CHG_IEND_FACTOR		4800
+#define DA9150_CHG_IBAT_UA_TO_REG(val)	(val / DA9150_CHG_IBAT_FACTOR)
+#define DA9150_CHG_IEND_UA_TO_REG(val)	(val / DA9150_CHG_IEND_FACTOR)
+#define DA9150_CHG_IBAT_REG_TO_UA(val)	(val * DA9150_CHG_IBAT_FACTOR)
+#define DA9150_CHG_IEND_REG_TO_UA(val)	(val * DA9150_CHG_IEND_FACTOR)
+
+
+/*
+ * I/O Function Typedefs
+ */
+
+typedef int (*read_dev_t)(void *client, u8 addr, int count, u8 *buf);
+typedef int (*write_dev_t)(void *client, u8 addr, int count, const u8 *buf);
+
+/*
+ * Main structure
+ */
+
+struct da9150 {
+	struct device *dev;
+
+	struct regmap *regmap;
+	struct i2c_client *core_qif;
+
+	read_dev_t read_dev;
+	write_dev_t write_dev;
+
+	struct regmap_irq_chip_data *regmap_irq_data;
+	int irq;
+	int irq_base;
+
+	bool can_shutdown;
+	bool gpadc_ready;
+};
+
+/*
+ * APIs
+ */
+
+/* Device I/O */
+int da9150_read_core(struct da9150 *da9150, u8 addr, int count, u8 *buf);
+int da9150_write_core(struct da9150 *da9150, u8 addr, int count, const u8 *buf);
+
+int da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf);
+int da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf);
+
+int da9150_read_fwdl(struct da9150 *da9150, u8 addr, int count, u8 *buf);
+int da9150_write_fwdl(struct da9150 *da9150, u8 addr, int count, const u8 *buf);
+
+u8 da9150_reg_read(struct da9150 *da9150, u16 reg);
+int da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val);
+int da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val);
+
+int da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf);
+int da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf);
+
+/* IRQ */
+int da9150_register_irq(struct platform_device *pdev, void *dev_id,
+			irq_handler_t handler, const char *name);
+
+/* Init/Exit */
+int da9150_device_init(struct da9150 *da9150);
+void da9150_device_exit(struct da9150 *da9150);
+void da9150_device_shutdown(struct da9150 *da9150);
+
+#endif /* _DA9150_CORE_H */
diff --git a/include/linux/mfd/da9150/pdata.h b/include/linux/mfd/da9150/pdata.h
new file mode 100644
index 0000000..c1dd2b3
--- /dev/null
+++ b/include/linux/mfd/da9150/pdata.h
@@ -0,0 +1,148 @@
+/*
+ * DA9150 MFD Driver - Platform Data
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#ifndef _DA9150_PDATA_H
+#define _DA9150_PDATA_H
+
+/*
+ * GPIO
+ */
+
+#define DA9150_NUM_GPIOS	4
+
+/* Values are as bit fields for registers */
+enum da9150_gpi_trigger {
+	DA9150_GPI_ACTIVE_LOW = 0,
+	DA9150_GPI_ACTIVE_HIGH,
+};
+
+enum da9150_gpi_mode {
+	DA9150_GPI_DIG = 0,
+	DA9150_GPI_ANA = 3,
+};
+
+enum da9150_gpo_mode {
+	DA9150_GPO_OD = 1,
+	DA9150_GPO_PP,
+};
+
+enum da9150_gpo_supply {
+	DA9150_GPO_SUPPLY_VDDIO1 = 0,
+	DA9150_GPO_SUPPLY_VDDIO2,
+};
+
+enum da9150_gpio_pupd {
+	DA9150_GPIO_PUPD_DISABLED = 0,
+	DA9150_GPIO_PUPD_ENABLED,
+};
+
+struct da9150_gpio_cfg {
+	enum da9150_gpi_trigger gpi_trigger;
+	enum da9150_gpi_mode gpi_mode;
+	enum da9150_gpo_mode gpo_mode;
+	enum da9150_gpo_supply gpo_supply;
+	enum da9150_gpio_pupd gpio_pupd;
+};
+
+enum da9150_gpi_debounce_time {
+	DA9150_GPI_DEBOUNCE_TIME_OFF = 0,
+	DA9150_GPI_DEBOUNCE_TIME_100US,
+	DA9150_GPI_DEBOUNCE_TIME_1MS,
+	DA9150_GPI_DEBOUNCE_TIME_10MS24,
+	DA9150_GPI_DEBOUNCE_TIME_51MS20,
+	DA9150_GPI_DEBOUNCE_TIME_256MS,
+	DA9150_GPI_DEBOUNCE_TIME_512MS,
+	DA9150_GPI_DEBOUNCE_TIME_1024MS,
+};
+
+/* Charging LED Data */
+enum da9150_led_freq {
+	DA9150_LED_FREQ_ALWAYS_ON = 0,
+	DA9150_LED_FREQ_1_S,
+	DA9150_LED_FREQ_2_S,
+	DA9150_LED_FREQ_4_S,
+};
+
+enum da9150_led_ontime {
+	DA9150_LED_ONTIME_10_MS = 0,
+	DA9150_LED_ONTIME_20_MS,
+	DA9150_LED_ONTIME_40_MS,
+	DA9150_LED_ONTIME_HALF_FREQ,
+};
+
+enum da9150_pin {
+	DA9150_PIN_OFF = 0,
+	DA9150_PIN_GPIOA = 1,
+	DA9150_PIN_GPIOB = 2,
+	DA9150_PIN_GPIOC = 3,
+	DA9150_PIN_GPIOD = 4,
+};
+
+
+/* Fault Pin Data */
+enum da9150_fault_type {
+	DA9150_FAULT_TYPE_VFAULT = 0,
+	DA9150_FAULT_TYPE_RESET,
+};
+
+
+/* GPIO data */
+struct da9150_gpio_pdata {
+	int base;
+
+	/* General GPIO config */
+	struct da9150_gpio_cfg gpio_cfg[DA9150_NUM_GPIOS];
+	enum da9150_gpi_debounce_time gpi_debounce_time;
+
+	/* Charge LED features */
+	enum da9150_led_freq led_frequency;
+	bool led_dbl_flash;
+	enum da9150_led_ontime led_ontime;
+	enum da9150_pin led_pin;
+
+	/* Fault Pin features */
+	enum da9150_pin fault_pin;
+	enum da9150_fault_type fault_type;
+};
+
+/*
+ * Fuel-Gauge
+ */
+
+struct da9150_fg_pdata {
+	u32 update_interval;	/* msecs */
+	u8 warn_soc_lvl;	/* % value */
+	u8 crit_soc_lvl;	/* % value */
+};
+
+/*
+ * Charger
+ */
+
+struct da9150_charger_pdata {
+	bool invalid_tbat;
+};
+
+
+/*
+ * Main struct
+ */
+
+struct da9150_pdata {
+	int irq_base;
+	struct da9150_gpio_pdata *gpio_pdata;
+	struct da9150_fg_pdata *fg_pdata;
+	struct da9150_charger_pdata *charger_pdata;
+};
+
+#endif /* _DA9150_PDATA_H */
diff --git a/include/linux/mfd/da9150/registers.h b/include/linux/mfd/da9150/registers.h
new file mode 100644
index 0000000..a6a8e28
--- /dev/null
+++ b/include/linux/mfd/da9150/registers.h
@@ -0,0 +1,1160 @@
+/*
+ * DA9150 MFD Driver - Registers
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#ifndef _DA9150_REGISTERS_H
+#define _DA9150_REGISTERS_H
+
+/*
+ * Registers
+ */
+
+#define DA9150_PAGE_CON			0x000
+#define DA9150_STATUS_A			0x068
+#define DA9150_STATUS_B			0x069
+#define DA9150_STATUS_C			0x06A
+#define DA9150_STATUS_D			0x06B
+#define DA9150_STATUS_E			0x06C
+#define DA9150_STATUS_F			0x06D
+#define DA9150_STATUS_G			0x06E
+#define DA9150_STATUS_H			0x06F
+#define DA9150_STATUS_I			0x070
+#define DA9150_STATUS_J			0x071
+#define DA9150_STATUS_K			0x072
+#define DA9150_STATUS_L			0x073
+#define DA9150_STATUS_N			0x074
+#define DA9150_FAULT_LOG_A		0x076
+#define DA9150_FAULT_LOG_B		0x077
+#define DA9150_EVENT_E			0x078
+#define DA9150_EVENT_F			0x079
+#define DA9150_EVENT_G			0x07A
+#define DA9150_EVENT_H			0x07B
+#define DA9150_IRQ_MASK_E		0x07C
+#define DA9150_IRQ_MASK_F		0x07D
+#define DA9150_IRQ_MASK_G		0x07E
+#define DA9150_IRQ_MASK_H		0x07F
+#define DA9150_PAGE_CON_1		0x080
+#define DA9150_CONFIG_A			0x0E0
+#define DA9150_CONFIG_B			0x0E1
+#define DA9150_CONFIG_C			0x0E2
+#define DA9150_CONFIG_D			0x0E3
+#define DA9150_CONFIG_E			0x0E4
+#define DA9150_CONTROL_A		0x0E5
+#define DA9150_CONTROL_B		0x0E6
+#define DA9150_CONTROL_C		0x0E7
+#define DA9150_GPIO_A_B			0x0E8
+#define DA9150_GPIO_C_D			0x0E9
+#define DA9150_GPIO_MODE_CONT		0x0EA
+#define DA9150_GPIO_CTRL_B		0x0EB
+#define DA9150_GPIO_CTRL_A		0x0EC
+#define DA9150_GPIO_CTRL_C		0x0ED
+#define DA9150_GPIO_CFG_A		0x0EE
+#define DA9150_GPIO_CFG_B		0x0EF
+#define DA9150_GPIO_CFG_C		0x0F0
+#define DA9150_GPADC_MAN		0x0F2
+#define DA9150_GPADC_RES_A		0x0F4
+#define DA9150_GPADC_RES_B		0x0F5
+#define DA9150_PAGE_CON_2		0x100
+#define DA9150_OTP_CONT_SHARED		0x101
+#define DA9150_INTERFACE_SHARED		0x105
+#define DA9150_CONFIG_A_SHARED		0x106
+#define DA9150_CONFIG_D_SHARED		0x109
+#define DA9150_ADETVB_CFG_C		0x150
+#define DA9150_ADETD_STAT		0x151
+#define DA9150_ADET_CMPSTAT		0x152
+#define DA9150_ADET_CTRL_A		0x153
+#define DA9150_ADETVB_CFG_B		0x154
+#define DA9150_ADETVB_CFG_A		0x155
+#define DA9150_ADETAC_CFG_A		0x156
+#define DA9150_ADDETAC_CFG_B		0x157
+#define DA9150_ADETAC_CFG_C		0x158
+#define DA9150_ADETAC_CFG_D		0x159
+#define DA9150_ADETVB_CFG_D		0x15A
+#define DA9150_ADETID_CFG_A		0x15B
+#define DA9150_ADET_RID_PT_CHG_H	0x15C
+#define DA9150_ADET_RID_PT_CHG_L	0x15D
+#define DA9150_PPR_TCTR_B		0x160
+#define DA9150_PPR_BKCTRL_A		0x163
+#define DA9150_PPR_BKCFG_A		0x164
+#define DA9150_PPR_BKCFG_B		0x165
+#define DA9150_PPR_CHGCTRL_A		0x166
+#define DA9150_PPR_CHGCTRL_B		0x167
+#define DA9150_PPR_CHGCTRL_C		0x168
+#define DA9150_PPR_TCTR_A		0x169
+#define DA9150_PPR_CHGCTRL_D		0x16A
+#define DA9150_PPR_CHGCTRL_E		0x16B
+#define DA9150_PPR_CHGCTRL_F		0x16C
+#define DA9150_PPR_CHGCTRL_G		0x16D
+#define DA9150_PPR_CHGCTRL_H		0x16E
+#define DA9150_PPR_CHGCTRL_I		0x16F
+#define DA9150_PPR_CHGCTRL_J		0x170
+#define DA9150_PPR_CHGCTRL_K		0x171
+#define DA9150_PPR_CHGCTRL_L		0x172
+#define DA9150_PPR_CHGCTRL_M		0x173
+#define DA9150_PPR_THYST_A		0x174
+#define DA9150_PPR_THYST_B		0x175
+#define DA9150_PPR_THYST_C		0x176
+#define DA9150_PPR_THYST_D		0x177
+#define DA9150_PPR_THYST_E		0x178
+#define DA9150_PPR_THYST_F		0x179
+#define DA9150_PPR_THYST_G		0x17A
+#define DA9150_PAGE_CON_3		0x180
+#define DA9150_PAGE_CON_4		0x200
+#define DA9150_PAGE_CON_5		0x280
+#define DA9150_PAGE_CON_6		0x300
+#define DA9150_COREBTLD_STAT_A		0x302
+#define DA9150_COREBTLD_CTRL_A		0x303
+#define DA9150_CORE_CONFIG_A		0x304
+#define DA9150_CORE_CONFIG_C		0x305
+#define DA9150_CORE_CONFIG_B		0x306
+#define DA9150_CORE_CFG_DATA_A		0x307
+#define DA9150_CORE_CFG_DATA_B		0x308
+#define DA9150_CORE_CMD_A		0x309
+#define DA9150_CORE_DATA_A		0x30A
+#define DA9150_CORE_DATA_B		0x30B
+#define DA9150_CORE_DATA_C		0x30C
+#define DA9150_CORE_DATA_D		0x30D
+#define DA9150_CORE2WIRE_STAT_A		0x310
+#define DA9150_CORE2WIRE_CTRL_A		0x311
+#define DA9150_FW_CTRL_A		0x312
+#define DA9150_FW_CTRL_C		0x313
+#define DA9150_FW_CTRL_D		0x314
+#define DA9150_FG_CTRL_A		0x315
+#define DA9150_FG_CTRL_B		0x316
+#define DA9150_FW_CTRL_E		0x317
+#define DA9150_FW_CTRL_B		0x318
+#define DA9150_GPADC_CMAN		0x320
+#define DA9150_GPADC_CRES_A		0x322
+#define DA9150_GPADC_CRES_B		0x323
+#define DA9150_CC_CFG_A			0x328
+#define DA9150_CC_CFG_B			0x329
+#define DA9150_CC_ICHG_RES_A		0x32A
+#define DA9150_CC_ICHG_RES_B		0x32B
+#define DA9150_CC_IAVG_RES_A		0x32C
+#define DA9150_CC_IAVG_RES_B		0x32D
+#define DA9150_TAUX_CTRL_A		0x330
+#define DA9150_TAUX_RELOAD_H		0x332
+#define DA9150_TAUX_RELOAD_L		0x333
+#define DA9150_TAUX_VALUE_H		0x334
+#define DA9150_TAUX_VALUE_L		0x335
+#define DA9150_AUX_DATA_0		0x338
+#define DA9150_AUX_DATA_1		0x339
+#define DA9150_AUX_DATA_2		0x33A
+#define DA9150_AUX_DATA_3		0x33B
+#define DA9150_BIF_CTRL			0x340
+#define DA9150_TBAT_CTRL_A		0x342
+#define DA9150_TBAT_CTRL_B		0x343
+#define DA9150_TBAT_RES_A		0x344
+#define DA9150_TBAT_RES_B		0x345
+
+
+/*
+ * Bit fields
+ */
+
+/* DA9150_PAGE_CON = 0x000 */
+#define DA9150_PAGE_SHIFT			0
+#define DA9150_PAGE_MASK			(0x3f << 0)
+#define DA9150_I2C_PAGE_SHIFT			1
+#define DA9150_I2C_PAGE_MASK			(0x1f << 1)
+#define DA9150_WRITE_MODE_SHIFT			6
+#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			(0x01 << 7)
+
+/* DA9150_STATUS_A = 0x068 */
+#define DA9150_WKUP_STAT_SHIFT			2
+#define DA9150_WKUP_STAT_MASK			(0x0f << 2)
+#define DA9150_SLEEP_STAT_SHIFT			6
+#define DA9150_SLEEP_STAT_MASK			(0x03 << 6)
+
+/* DA9150_STATUS_B = 0x069 */
+#define DA9150_VFAULT_STAT_SHIFT		0
+#define DA9150_VFAULT_STAT_MASK			(0x01 << 0)
+#define DA9150_TFAULT_STAT_SHIFT		1
+#define DA9150_TFAULT_STAT_MASK			(0x01 << 1)
+
+/* DA9150_STATUS_C = 0x06A */
+#define DA9150_VDD33_STAT_SHIFT			0
+#define DA9150_VDD33_STAT_MASK			(0x01 << 0)
+#define DA9150_VDD33_SLEEP_SHIFT		1
+#define DA9150_VDD33_SLEEP_MASK			(0x01 << 1)
+#define DA9150_LFOSC_STAT_SHIFT			7
+#define DA9150_LFOSC_STAT_MASK			(0x01 << 7)
+
+/* DA9150_STATUS_D = 0x06B */
+#define DA9150_GPIOA_STAT_SHIFT			0
+#define DA9150_GPIOA_STAT_MASK			(0x01 << 0)
+#define DA9150_GPIOB_STAT_SHIFT			1
+#define DA9150_GPIOB_STAT_MASK			(0x01 << 1)
+#define DA9150_GPIOC_STAT_SHIFT			2
+#define DA9150_GPIOC_STAT_MASK			(0x01 << 2)
+#define DA9150_GPIOD_STAT_SHIFT			3
+#define DA9150_GPIOD_STAT_MASK			(0x01 << 3)
+
+/* DA9150_STATUS_E = 0x06C */
+#define DA9150_DTYPE_SHIFT			0
+#define DA9150_DTYPE_MASK			(0x1f << 0)
+#define DA9150_DTYPE_DT_NIL			(0x00 << 0)
+#define DA9150_DTYPE_DT_USB_OTG			(0x01 << 0)
+#define DA9150_DTYPE_DT_USB_STD			(0x02 << 0)
+#define DA9150_DTYPE_DT_USB_CHG			(0x03 << 0)
+#define DA9150_DTYPE_DT_ACA_CHG			(0x04 << 0)
+#define DA9150_DTYPE_DT_ACA_OTG			(0x05 << 0)
+#define DA9150_DTYPE_DT_ACA_DOC			(0x06 << 0)
+#define DA9150_DTYPE_DT_DED_CHG			(0x07 << 0)
+#define DA9150_DTYPE_DT_CR5_CHG			(0x08 << 0)
+#define DA9150_DTYPE_DT_CR4_CHG			(0x0c << 0)
+#define DA9150_DTYPE_DT_PT_CHG			(0x11 << 0)
+#define DA9150_DTYPE_DT_NN_ACC			(0x16 << 0)
+#define DA9150_DTYPE_DT_NN_CHG			(0x17 << 0)
+
+/* DA9150_STATUS_F = 0x06D */
+#define DA9150_SESS_VLD_SHIFT			0
+#define DA9150_SESS_VLD_MASK			(0x01 << 0)
+#define DA9150_ID_ERR_SHIFT			1
+#define DA9150_ID_ERR_MASK			(0x01 << 1)
+#define DA9150_PT_CHG_SHIFT			2
+#define DA9150_PT_CHG_MASK			(0x01 << 2)
+
+/* DA9150_STATUS_G = 0x06E */
+#define DA9150_RID_SHIFT			0
+#define DA9150_RID_MASK				(0xff << 0)
+
+/* DA9150_STATUS_H = 0x06F */
+#define DA9150_VBUS_STAT_SHIFT			0
+#define DA9150_VBUS_STAT_MASK			(0x07 << 0)
+#define DA9150_VBUS_STAT_OFF			(0x00 << 0)
+#define DA9150_VBUS_STAT_WAIT			(0x01 << 0)
+#define DA9150_VBUS_STAT_CHG			(0x02 << 0)
+#define DA9150_VBUS_TRED_SHIFT			3
+#define DA9150_VBUS_TRED_MASK			(0x01 << 3)
+#define DA9150_VBUS_DROP_STAT_SHIFT		4
+#define DA9150_VBUS_DROP_STAT_MASK		(0x0f << 4)
+
+/* DA9150_STATUS_I = 0x070 */
+#define DA9150_VBUS_ISET_STAT_SHIFT		0
+#define DA9150_VBUS_ISET_STAT_MASK		(0x1f << 0)
+#define DA9150_VBUS_OT_SHIFT			7
+#define DA9150_VBUS_OT_MASK			(0x01 << 7)
+
+/* DA9150_STATUS_J = 0x071 */
+#define DA9150_CHG_STAT_SHIFT			0
+#define DA9150_CHG_STAT_MASK			(0x0f << 0)
+#define DA9150_CHG_STAT_OFF			(0x00 << 0)
+#define DA9150_CHG_STAT_SUSP			(0x01 << 0)
+#define DA9150_CHG_STAT_ACT			(0x02 << 0)
+#define DA9150_CHG_STAT_PRE			(0x03 << 0)
+#define DA9150_CHG_STAT_CC			(0x04 << 0)
+#define DA9150_CHG_STAT_CV			(0x05 << 0)
+#define DA9150_CHG_STAT_FULL			(0x06 << 0)
+#define DA9150_CHG_STAT_TEMP			(0x07 << 0)
+#define DA9150_CHG_STAT_TIME			(0x08 << 0)
+#define DA9150_CHG_STAT_BAT			(0x09 << 0)
+#define DA9150_CHG_TEMP_SHIFT			4
+#define DA9150_CHG_TEMP_MASK			(0x07 << 4)
+#define DA9150_CHG_TEMP_UNDER			(0x06 << 4)
+#define DA9150_CHG_TEMP_OVER			(0x07 << 4)
+#define DA9150_CHG_IEND_STAT_SHIFT		7
+#define DA9150_CHG_IEND_STAT_MASK		(0x01 << 7)
+
+/* DA9150_STATUS_K = 0x072 */
+#define DA9150_CHG_IAV_H_SHIFT			0
+#define DA9150_CHG_IAV_H_MASK			(0xff << 0)
+
+/* DA9150_STATUS_L = 0x073 */
+#define DA9150_CHG_IAV_L_SHIFT			5
+#define DA9150_CHG_IAV_L_MASK			(0x07 << 5)
+
+/* DA9150_STATUS_N = 0x074 */
+#define DA9150_CHG_TIME_SHIFT			1
+#define DA9150_CHG_TIME_MASK			(0x01 << 1)
+#define DA9150_CHG_TRED_SHIFT			2
+#define DA9150_CHG_TRED_MASK			(0x01 << 2)
+#define DA9150_CHG_TJUNC_CLASS_SHIFT		3
+#define DA9150_CHG_TJUNC_CLASS_MASK		(0x07 << 3)
+#define DA9150_CHG_TJUNC_CLASS_6		(0x06 << 3)
+#define DA9150_EBS_STAT_SHIFT			6
+#define DA9150_EBS_STAT_MASK			(0x01 << 6)
+#define DA9150_CHG_BAT_REMOVED_SHIFT		7
+#define DA9150_CHG_BAT_REMOVED_MASK		(0x01 << 7)
+
+/* DA9150_FAULT_LOG_A = 0x076 */
+#define DA9150_TEMP_FAULT_SHIFT			0
+#define DA9150_TEMP_FAULT_MASK			(0x01 << 0)
+#define DA9150_VSYS_FAULT_SHIFT			1
+#define DA9150_VSYS_FAULT_MASK			(0x01 << 1)
+#define DA9150_START_FAULT_SHIFT		2
+#define DA9150_START_FAULT_MASK			(0x01 << 2)
+#define DA9150_EXT_FAULT_SHIFT			3
+#define DA9150_EXT_FAULT_MASK			(0x01 << 3)
+#define DA9150_POR_FAULT_SHIFT			4
+#define DA9150_POR_FAULT_MASK			(0x01 << 4)
+
+/* DA9150_FAULT_LOG_B = 0x077 */
+#define DA9150_VBUS_FAULT_SHIFT			0
+#define DA9150_VBUS_FAULT_MASK			(0x01 << 0)
+#define DA9150_OTG_FAULT_SHIFT			1
+#define DA9150_OTG_FAULT_MASK			(0x01 << 1)
+
+/* DA9150_EVENT_E = 0x078 */
+#define DA9150_E_VBUS_SHIFT			0
+#define DA9150_E_VBUS_MASK			(0x01 << 0)
+#define DA9150_E_CHG_SHIFT			1
+#define DA9150_E_CHG_MASK			(0x01 << 1)
+#define DA9150_E_TCLASS_SHIFT			2
+#define DA9150_E_TCLASS_MASK			(0x01 << 2)
+#define DA9150_E_TJUNC_SHIFT			3
+#define DA9150_E_TJUNC_MASK			(0x01 << 3)
+#define DA9150_E_VFAULT_SHIFT			4
+#define DA9150_E_VFAULT_MASK			(0x01 << 4)
+#define DA9150_EVENTS_H_SHIFT			5
+#define DA9150_EVENTS_H_MASK			(0x01 << 5)
+#define DA9150_EVENTS_G_SHIFT			6
+#define DA9150_EVENTS_G_MASK			(0x01 << 6)
+#define DA9150_EVENTS_F_SHIFT			7
+#define DA9150_EVENTS_F_MASK			(0x01 << 7)
+
+/* DA9150_EVENT_F = 0x079 */
+#define DA9150_E_CONF_SHIFT			0
+#define DA9150_E_CONF_MASK			(0x01 << 0)
+#define DA9150_E_DAT_SHIFT			1
+#define DA9150_E_DAT_MASK			(0x01 << 1)
+#define DA9150_E_DTYPE_SHIFT			3
+#define DA9150_E_DTYPE_MASK			(0x01 << 3)
+#define DA9150_E_ID_SHIFT			4
+#define DA9150_E_ID_MASK			(0x01 << 4)
+#define DA9150_E_ADP_SHIFT			5
+#define DA9150_E_ADP_MASK			(0x01 << 5)
+#define DA9150_E_SESS_END_SHIFT			6
+#define DA9150_E_SESS_END_MASK			(0x01 << 6)
+#define DA9150_E_SESS_VLD_SHIFT			7
+#define DA9150_E_SESS_VLD_MASK			(0x01 << 7)
+
+/* DA9150_EVENT_G = 0x07A */
+#define DA9150_E_FG_SHIFT			0
+#define DA9150_E_FG_MASK			(0x01 << 0)
+#define DA9150_E_GP_SHIFT			1
+#define DA9150_E_GP_MASK			(0x01 << 1)
+#define DA9150_E_TBAT_SHIFT			2
+#define DA9150_E_TBAT_MASK			(0x01 << 2)
+#define DA9150_E_GPIOA_SHIFT			3
+#define DA9150_E_GPIOA_MASK			(0x01 << 3)
+#define DA9150_E_GPIOB_SHIFT			4
+#define DA9150_E_GPIOB_MASK			(0x01 << 4)
+#define DA9150_E_GPIOC_SHIFT			5
+#define DA9150_E_GPIOC_MASK			(0x01 << 5)
+#define DA9150_E_GPIOD_SHIFT			6
+#define DA9150_E_GPIOD_MASK			(0x01 << 6)
+#define DA9150_E_GPADC_SHIFT			7
+#define DA9150_E_GPADC_MASK			(0x01 << 7)
+
+/* DA9150_EVENT_H = 0x07B */
+#define DA9150_E_WKUP_SHIFT			0
+#define DA9150_E_WKUP_MASK			(0x01 << 0)
+
+/* DA9150_IRQ_MASK_E = 0x07C */
+#define DA9150_M_VBUS_SHIFT			0
+#define DA9150_M_VBUS_MASK			(0x01 << 0)
+#define DA9150_M_CHG_SHIFT			1
+#define DA9150_M_CHG_MASK			(0x01 << 1)
+#define DA9150_M_TJUNC_SHIFT			3
+#define DA9150_M_TJUNC_MASK			(0x01 << 3)
+#define DA9150_M_VFAULT_SHIFT			4
+#define DA9150_M_VFAULT_MASK			(0x01 << 4)
+
+/* DA9150_IRQ_MASK_F = 0x07D */
+#define DA9150_M_CONF_SHIFT			0
+#define DA9150_M_CONF_MASK			(0x01 << 0)
+#define DA9150_M_DAT_SHIFT			1
+#define DA9150_M_DAT_MASK			(0x01 << 1)
+#define DA9150_M_DTYPE_SHIFT			3
+#define DA9150_M_DTYPE_MASK			(0x01 << 3)
+#define DA9150_M_ID_SHIFT			4
+#define DA9150_M_ID_MASK			(0x01 << 4)
+#define DA9150_M_ADP_SHIFT			5
+#define DA9150_M_ADP_MASK			(0x01 << 5)
+#define DA9150_M_SESS_END_SHIFT			6
+#define DA9150_M_SESS_END_MASK			(0x01 << 6)
+#define DA9150_M_SESS_VLD_SHIFT			7
+#define DA9150_M_SESS_VLD_MASK			(0x01 << 7)
+
+/* DA9150_IRQ_MASK_G = 0x07E */
+#define DA9150_M_FG_SHIFT			0
+#define DA9150_M_FG_MASK			(0x01 << 0)
+#define DA9150_M_GP_SHIFT			1
+#define DA9150_M_GP_MASK			(0x01 << 1)
+#define DA9150_M_TBAT_SHIFT			2
+#define DA9150_M_TBAT_MASK			(0x01 << 2)
+#define DA9150_M_GPIOA_SHIFT			3
+#define DA9150_M_GPIOA_MASK			(0x01 << 3)
+#define DA9150_M_GPIOB_SHIFT			4
+#define DA9150_M_GPIOB_MASK			(0x01 << 4)
+#define DA9150_M_GPIOC_SHIFT			5
+#define DA9150_M_GPIOC_MASK			(0x01 << 5)
+#define DA9150_M_GPIOD_SHIFT			6
+#define DA9150_M_GPIOD_MASK			(0x01 << 6)
+#define DA9150_M_GPADC_SHIFT			7
+#define DA9150_M_GPADC_MASK			(0x01 << 7)
+
+/* DA9150_IRQ_MASK_H = 0x07F */
+#define DA9150_M_WKUP_SHIFT			0
+#define DA9150_M_WKUP_MASK			(0x01 << 0)
+
+/* DA9150_PAGE_CON_1 = 0x080 */
+#define DA9150_PAGE_SHIFT			0
+#define DA9150_PAGE_MASK			(0x3f << 0)
+#define DA9150_WRITE_MODE_SHIFT			6
+#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			(0x01 << 7)
+
+/* DA9150_CONFIG_A = 0x0E0 */
+#define DA9150_RESET_DUR_SHIFT			0
+#define DA9150_RESET_DUR_MASK			(0x03 << 0)
+#define DA9150_RESET_EXT_SHIFT			2
+#define DA9150_RESET_EXT_MASK			(0x03 << 2)
+#define DA9150_START_MAX_SHIFT			4
+#define DA9150_START_MAX_MASK			(0x03 << 4)
+#define DA9150_PS_WAIT_EN_SHIFT			6
+#define DA9150_PS_WAIT_EN_MASK			(0x01 << 6)
+#define DA9150_PS_DISABLE_DIRECT_SHIFT		7
+#define DA9150_PS_DISABLE_DIRECT_MASK		(0x01 << 7)
+
+/* DA9150_CONFIG_B = 0x0E1 */
+#define DA9150_VFAULT_ADJ_SHIFT			0
+#define DA9150_VFAULT_ADJ_MASK			(0x0f << 0)
+#define DA9150_VFAULT_HYST_SHIFT		4
+#define DA9150_VFAULT_HYST_MASK			(0x07 << 4)
+#define DA9150_VFAULT_EN_SHIFT			7
+#define DA9150_VFAULT_EN_MASK			(0x01 << 7)
+
+/* DA9150_CONFIG_C = 0x0E2 */
+#define DA9150_VSYS_MIN_SHIFT			3
+#define DA9150_VSYS_MIN_MASK			(0x1f << 3)
+
+/* DA9150_CONFIG_D = 0x0E3 */
+#define DA9150_LFOSC_EXT_SHIFT			0
+#define DA9150_LFOSC_EXT_MASK			(0x01 << 0)
+#define DA9150_VDD33_DWN_SHIFT			1
+#define DA9150_VDD33_DWN_MASK			(0x01 << 1)
+#define DA9150_WKUP_PM_EN_SHIFT			2
+#define DA9150_WKUP_PM_EN_MASK			(0x01 << 2)
+#define DA9150_WKUP_CE_SEL_SHIFT		3
+#define DA9150_WKUP_CE_SEL_MASK			(0x03 << 3)
+#define DA9150_WKUP_CLK32K_EN_SHIFT		5
+#define DA9150_WKUP_CLK32K_EN_MASK		(0x01 << 5)
+#define DA9150_DISABLE_DEL_SHIFT		7
+#define DA9150_DISABLE_DEL_MASK			(0x01 << 7)
+
+/* DA9150_CONFIG_E = 0x0E4 */
+#define DA9150_PM_SPKSUP_DIS_SHIFT		0
+#define DA9150_PM_SPKSUP_DIS_MASK		(0x01 << 0)
+#define DA9150_PM_MERGE_SHIFT			1
+#define DA9150_PM_MERGE_MASK			(0x01 << 1)
+#define DA9150_PM_SR_OFF_SHIFT			2
+#define DA9150_PM_SR_OFF_MASK			(0x01 << 2)
+#define DA9150_PM_TIMEOUT_EN_SHIFT		3
+#define DA9150_PM_TIMEOUT_EN_MASK		(0x01 << 3)
+#define DA9150_PM_DLY_SEL_SHIFT			4
+#define DA9150_PM_DLY_SEL_MASK			(0x07 << 4)
+#define DA9150_PM_OUT_DLY_SEL_SHIFT		7
+#define DA9150_PM_OUT_DLY_SEL_MASK		(0x01 << 7)
+
+/* DA9150_CONTROL_A = 0x0E5 */
+#define DA9150_VDD33_SL_SHIFT			0
+#define DA9150_VDD33_SL_MASK			(0x01 << 0)
+#define DA9150_VDD33_LPM_SHIFT			1
+#define DA9150_VDD33_LPM_MASK			(0x03 << 1)
+#define DA9150_VDD33_EN_SHIFT			3
+#define DA9150_VDD33_EN_MASK			(0x01 << 3)
+#define DA9150_GPI_LPM_SHIFT			6
+#define DA9150_GPI_LPM_MASK			(0x01 << 6)
+#define DA9150_PM_IF_LPM_SHIFT			7
+#define DA9150_PM_IF_LPM_MASK			(0x01 << 7)
+
+/* DA9150_CONTROL_B = 0x0E6 */
+#define DA9150_LPM_SHIFT			0
+#define DA9150_LPM_MASK				(0x01 << 0)
+#define DA9150_RESET_SHIFT			1
+#define DA9150_RESET_MASK			(0x01 << 1)
+#define DA9150_RESET_USRCONF_EN_SHIFT		2
+#define DA9150_RESET_USRCONF_EN_MASK		(0x01 << 2)
+
+/* DA9150_CONTROL_C = 0x0E7 */
+#define DA9150_DISABLE_SHIFT			0
+#define DA9150_DISABLE_MASK			(0x01 << 0)
+
+/* DA9150_GPIO_A_B = 0x0E8 */
+#define DA9150_GPIOA_PIN_SHIFT			0
+#define DA9150_GPIOA_PIN_MASK			(0x07 << 0)
+#define DA9150_GPIOA_PIN_GPI			(0x00 << 0)
+#define DA9150_GPIOA_PIN_GPO_OD			(0x01 << 0)
+#define DA9150_GPIOA_TYPE_SHIFT			3
+#define DA9150_GPIOA_TYPE_MASK			(0x01 << 3)
+#define DA9150_GPIOB_PIN_SHIFT			4
+#define DA9150_GPIOB_PIN_MASK			(0x07 << 4)
+#define DA9150_GPIOB_PIN_GPI			(0x00 << 4)
+#define DA9150_GPIOB_PIN_GPO_OD			(0x01 << 4)
+#define DA9150_GPIOB_TYPE_SHIFT			7
+#define DA9150_GPIOB_TYPE_MASK			(0x01 << 7)
+
+/* DA9150_GPIO_C_D = 0x0E9 */
+#define DA9150_GPIOC_PIN_SHIFT			0
+#define DA9150_GPIOC_PIN_MASK			(0x07 << 0)
+#define DA9150_GPIOC_PIN_GPI			(0x00 << 0)
+#define DA9150_GPIOC_PIN_GPO_OD			(0x01 << 0)
+#define DA9150_GPIOC_TYPE_SHIFT			3
+#define DA9150_GPIOC_TYPE_MASK			(0x01 << 3)
+#define DA9150_GPIOD_PIN_SHIFT			4
+#define DA9150_GPIOD_PIN_MASK			(0x07 << 4)
+#define DA9150_GPIOD_PIN_GPI			(0x00 << 4)
+#define DA9150_GPIOD_PIN_GPO_OD			(0x01 << 4)
+#define DA9150_GPIOD_TYPE_SHIFT			7
+#define DA9150_GPIOD_TYPE_MASK			(0x01 << 7)
+
+/* DA9150_GPIO_MODE_CONT = 0x0EA */
+#define DA9150_GPIOA_MODE_SHIFT			0
+#define DA9150_GPIOA_MODE_MASK			(0x01 << 0)
+#define DA9150_GPIOB_MODE_SHIFT			1
+#define DA9150_GPIOB_MODE_MASK			(0x01 << 1)
+#define DA9150_GPIOC_MODE_SHIFT			2
+#define DA9150_GPIOC_MODE_MASK			(0x01 << 2)
+#define DA9150_GPIOD_MODE_SHIFT			3
+#define DA9150_GPIOD_MODE_MASK			(0x01 << 3)
+#define DA9150_GPIOA_CONT_SHIFT			4
+#define DA9150_GPIOA_CONT_MASK			(0x01 << 4)
+#define DA9150_GPIOB_CONT_SHIFT			5
+#define DA9150_GPIOB_CONT_MASK			(0x01 << 5)
+#define DA9150_GPIOC_CONT_SHIFT			6
+#define DA9150_GPIOC_CONT_MASK			(0x01 << 6)
+#define DA9150_GPIOD_CONT_SHIFT			7
+#define DA9150_GPIOD_CONT_MASK			(0x01 << 7)
+
+/* DA9150_GPIO_CTRL_B = 0x0EB */
+#define DA9150_WAKE_PIN_SHIFT			0
+#define DA9150_WAKE_PIN_MASK			(0x03 << 0)
+#define DA9150_WAKE_MODE_SHIFT			2
+#define DA9150_WAKE_MODE_MASK			(0x01 << 2)
+#define DA9150_WAKE_CONT_SHIFT			3
+#define DA9150_WAKE_CONT_MASK			(0x01 << 3)
+#define DA9150_WAKE_DLY_SHIFT			4
+#define DA9150_WAKE_DLY_MASK			(0x01 << 4)
+
+/* DA9150_GPIO_CTRL_A = 0x0EC */
+#define DA9150_GPIOA_ANAEN_SHIFT		0
+#define DA9150_GPIOA_ANAEN_MASK			(0x01 << 0)
+#define DA9150_GPIOB_ANAEN_SHIFT		1
+#define DA9150_GPIOB_ANAEN_MASK			(0x01 << 1)
+#define DA9150_GPIOC_ANAEN_SHIFT		2
+#define DA9150_GPIOC_ANAEN_MASK			(0x01 << 2)
+#define DA9150_GPIOD_ANAEN_SHIFT		3
+#define DA9150_GPIOD_ANAEN_MASK			(0x01 << 3)
+#define DA9150_GPIO_ANAEN			0x01
+#define DA9150_GPIO_ANAEN_MASK			0x0F
+#define DA9150_CHGLED_PIN_SHIFT			5
+#define DA9150_CHGLED_PIN_MASK			(0x07 << 5)
+
+/* DA9150_GPIO_CTRL_C = 0x0ED */
+#define DA9150_CHGBL_DUR_SHIFT			0
+#define DA9150_CHGBL_DUR_MASK			(0x03 << 0)
+#define DA9150_CHGBL_DBL_SHIFT			2
+#define DA9150_CHGBL_DBL_MASK			(0x01 << 2)
+#define DA9150_CHGBL_FRQ_SHIFT			3
+#define DA9150_CHGBL_FRQ_MASK			(0x03 << 3)
+#define DA9150_CHGBL_FLKR_SHIFT			5
+#define DA9150_CHGBL_FLKR_MASK			(0x01 << 5)
+
+/* DA9150_GPIO_CFG_A = 0x0EE */
+#define DA9150_CE_LPM_DEB_SHIFT			0
+#define DA9150_CE_LPM_DEB_MASK			(0x07 << 0)
+
+/* DA9150_GPIO_CFG_B = 0x0EF */
+#define DA9150_GPIOA_PUPD_SHIFT			0
+#define DA9150_GPIOA_PUPD_MASK			(0x01 << 0)
+#define DA9150_GPIOB_PUPD_SHIFT			1
+#define DA9150_GPIOB_PUPD_MASK			(0x01 << 1)
+#define DA9150_GPIOC_PUPD_SHIFT			2
+#define DA9150_GPIOC_PUPD_MASK			(0x01 << 2)
+#define DA9150_GPIOD_PUPD_SHIFT			3
+#define DA9150_GPIOD_PUPD_MASK			(0x01 << 3)
+#define DA9150_GPIO_PUPD_MASK			(0xF << 0)
+#define DA9150_GPI_DEB_SHIFT			4
+#define DA9150_GPI_DEB_MASK			(0x07 << 4)
+#define DA9150_LPM_EN_SHIFT			7
+#define DA9150_LPM_EN_MASK			(0x01 << 7)
+
+/* DA9150_GPIO_CFG_C = 0x0F0 */
+#define DA9150_GPI_V_SHIFT			0
+#define DA9150_GPI_V_MASK			(0x01 << 0)
+#define DA9150_VDDIO_INT_SHIFT			1
+#define DA9150_VDDIO_INT_MASK			(0x01 << 1)
+#define DA9150_FAULT_PIN_SHIFT			3
+#define DA9150_FAULT_PIN_MASK			(0x07 << 3)
+#define DA9150_FAULT_TYPE_SHIFT			6
+#define DA9150_FAULT_TYPE_MASK			(0x01 << 6)
+#define DA9150_NIRQ_PUPD_SHIFT			7
+#define DA9150_NIRQ_PUPD_MASK			(0x01 << 7)
+
+/* DA9150_GPADC_MAN = 0x0F2 */
+#define DA9150_GPADC_EN_SHIFT			0
+#define DA9150_GPADC_EN_MASK			(0x01 << 0)
+#define DA9150_GPADC_MUX_SHIFT			1
+#define DA9150_GPADC_MUX_MASK			(0x1f << 1)
+
+/* DA9150_GPADC_RES_A = 0x0F4 */
+#define DA9150_GPADC_RES_H_SHIFT		0
+#define DA9150_GPADC_RES_H_MASK			(0xff << 0)
+
+/* DA9150_GPADC_RES_B = 0x0F5 */
+#define DA9150_GPADC_RUN_SHIFT			0
+#define DA9150_GPADC_RUN_MASK			(0x01 << 0)
+#define DA9150_GPADC_RES_L_SHIFT		6
+#define DA9150_GPADC_RES_L_MASK			(0x03 << 6)
+
+/* DA9150_PAGE_CON_2 = 0x100 */
+#define DA9150_PAGE_SHIFT			0
+#define DA9150_PAGE_MASK			(0x3f << 0)
+#define DA9150_WRITE_MODE_SHIFT			6
+#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			(0x01 << 7)
+
+/* DA9150_OTP_CONT_SHARED = 0x101 */
+#define DA9150_PC_DONE_SHIFT			3
+#define DA9150_PC_DONE_MASK			(0x01 << 3)
+
+/* DA9150_INTERFACE_SHARED = 0x105 */
+#define DA9150_IF_BASE_ADDR_SHIFT		4
+#define DA9150_IF_BASE_ADDR_MASK		(0x0f << 4)
+
+/* DA9150_CONFIG_A_SHARED = 0x106 */
+#define DA9150_NIRQ_VDD_SHIFT			1
+#define DA9150_NIRQ_VDD_MASK			(0x01 << 1)
+#define DA9150_NIRQ_PIN_SHIFT			2
+#define DA9150_NIRQ_PIN_MASK			(0x01 << 2)
+#define DA9150_NIRQ_TYPE_SHIFT			3
+#define DA9150_NIRQ_TYPE_MASK			(0x01 << 3)
+#define DA9150_PM_IF_V_SHIFT			4
+#define DA9150_PM_IF_V_MASK			(0x01 << 4)
+#define DA9150_PM_IF_FMP_SHIFT			5
+#define DA9150_PM_IF_FMP_MASK			(0x01 << 5)
+#define DA9150_PM_IF_HSM_SHIFT			6
+#define DA9150_PM_IF_HSM_MASK			(0x01 << 6)
+
+/* DA9150_CONFIG_D_SHARED = 0x109 */
+#define DA9150_NIRQ_MODE_SHIFT			1
+#define DA9150_NIRQ_MODE_MASK			(0x01 << 1)
+
+/* DA9150_ADETVB_CFG_C = 0x150 */
+#define DA9150_TADP_RISE_SHIFT			0
+#define DA9150_TADP_RISE_MASK			(0xff << 0)
+
+/* DA9150_ADETD_STAT = 0x151 */
+#define DA9150_DCD_STAT_SHIFT			0
+#define DA9150_DCD_STAT_MASK			(0x01 << 0)
+#define DA9150_PCD_STAT_SHIFT			1
+#define DA9150_PCD_STAT_MASK			(0x03 << 1)
+#define DA9150_SCD_STAT_SHIFT			3
+#define DA9150_SCD_STAT_MASK			(0x03 << 3)
+#define DA9150_DP_STAT_SHIFT			5
+#define DA9150_DP_STAT_MASK			(0x01 << 5)
+#define DA9150_DM_STAT_SHIFT			6
+#define DA9150_DM_STAT_MASK			(0x01 << 6)
+
+/* DA9150_ADET_CMPSTAT = 0x152 */
+#define DA9150_DP_COMP_SHIFT			1
+#define DA9150_DP_COMP_MASK			(0x01 << 1)
+#define DA9150_DM_COMP_SHIFT			2
+#define DA9150_DM_COMP_MASK			(0x01 << 2)
+#define DA9150_ADP_SNS_COMP_SHIFT		3
+#define DA9150_ADP_SNS_COMP_MASK		(0x01 << 3)
+#define DA9150_ADP_PRB_COMP_SHIFT		4
+#define DA9150_ADP_PRB_COMP_MASK		(0x01 << 4)
+#define DA9150_ID_COMP_SHIFT			5
+#define DA9150_ID_COMP_MASK			(0x01 << 5)
+
+/* DA9150_ADET_CTRL_A = 0x153 */
+#define DA9150_AID_DAT_SHIFT			0
+#define DA9150_AID_DAT_MASK			(0x01 << 0)
+#define DA9150_AID_ID_SHIFT			1
+#define DA9150_AID_ID_MASK			(0x01 << 1)
+#define DA9150_AID_TRIG_SHIFT			2
+#define DA9150_AID_TRIG_MASK			(0x01 << 2)
+
+/* DA9150_ADETVB_CFG_B = 0x154 */
+#define DA9150_VB_MODE_SHIFT			0
+#define DA9150_VB_MODE_MASK			(0x03 << 0)
+#define DA9150_VB_MODE_VB_SESS			(0x01 << 0)
+
+#define DA9150_TADP_PRB_SHIFT			2
+#define DA9150_TADP_PRB_MASK			(0x01 << 2)
+#define DA9150_DAT_RPD_EXT_SHIFT		5
+#define DA9150_DAT_RPD_EXT_MASK			(0x01 << 5)
+#define DA9150_CONF_RPD_SHIFT			6
+#define DA9150_CONF_RPD_MASK			(0x01 << 6)
+#define DA9150_CONF_SRP_SHIFT			7
+#define DA9150_CONF_SRP_MASK			(0x01 << 7)
+
+/* DA9150_ADETVB_CFG_A = 0x155 */
+#define DA9150_AID_MODE_SHIFT			0
+#define DA9150_AID_MODE_MASK			(0x03 << 0)
+#define DA9150_AID_EXT_POL_SHIFT		2
+#define DA9150_AID_EXT_POL_MASK			(0x01 << 2)
+
+/* DA9150_ADETAC_CFG_A = 0x156 */
+#define DA9150_ISET_CDP_SHIFT			0
+#define DA9150_ISET_CDP_MASK			(0x1f << 0)
+#define DA9150_CONF_DBP_SHIFT			5
+#define DA9150_CONF_DBP_MASK			(0x01 << 5)
+
+/* DA9150_ADDETAC_CFG_B = 0x157 */
+#define DA9150_ISET_DCHG_SHIFT			0
+#define DA9150_ISET_DCHG_MASK			(0x1f << 0)
+#define DA9150_CONF_GPIOA_SHIFT			5
+#define DA9150_CONF_GPIOA_MASK			(0x01 << 5)
+#define DA9150_CONF_GPIOB_SHIFT			6
+#define DA9150_CONF_GPIOB_MASK			(0x01 << 6)
+#define DA9150_AID_VB_SHIFT			7
+#define DA9150_AID_VB_MASK			(0x01 << 7)
+
+/* DA9150_ADETAC_CFG_C = 0x158 */
+#define DA9150_ISET_DEF_SHIFT			0
+#define DA9150_ISET_DEF_MASK			(0x1f << 0)
+#define DA9150_CONF_MODE_SHIFT			5
+#define DA9150_CONF_MODE_MASK			(0x03 << 5)
+#define DA9150_AID_CR_DIS_SHIFT			7
+#define DA9150_AID_CR_DIS_MASK			(0x01 << 7)
+
+/* DA9150_ADETAC_CFG_D = 0x159 */
+#define DA9150_ISET_UNIT_SHIFT			0
+#define DA9150_ISET_UNIT_MASK			(0x1f << 0)
+#define DA9150_AID_UNCLAMP_SHIFT		5
+#define DA9150_AID_UNCLAMP_MASK			(0x01 << 5)
+
+/* DA9150_ADETVB_CFG_D = 0x15A */
+#define DA9150_ID_MODE_SHIFT			0
+#define DA9150_ID_MODE_MASK			(0x03 << 0)
+#define DA9150_DAT_MODE_SHIFT			2
+#define DA9150_DAT_MODE_MASK			(0x0f << 2)
+#define DA9150_DAT_SWP_SHIFT			6
+#define DA9150_DAT_SWP_MASK			(0x01 << 6)
+#define DA9150_DAT_CLAMP_EXT_SHIFT		7
+#define DA9150_DAT_CLAMP_EXT_MASK		(0x01 << 7)
+
+/* DA9150_ADETID_CFG_A = 0x15B */
+#define DA9150_TID_POLL_SHIFT			0
+#define DA9150_TID_POLL_MASK			(0x07 << 0)
+#define DA9150_RID_CONV_SHIFT			3
+#define DA9150_RID_CONV_MASK			(0x01 << 3)
+
+/* DA9150_ADET_RID_PT_CHG_H = 0x15C */
+#define DA9150_RID_PT_CHG_H_SHIFT		0
+#define DA9150_RID_PT_CHG_H_MASK		(0xff << 0)
+
+/* DA9150_ADET_RID_PT_CHG_L = 0x15D */
+#define DA9150_RID_PT_CHG_L_SHIFT		6
+#define DA9150_RID_PT_CHG_L_MASK		(0x03 << 6)
+
+/* DA9150_PPR_TCTR_B = 0x160 */
+#define DA9150_CHG_TCTR_VAL_SHIFT		0
+#define DA9150_CHG_TCTR_VAL_MASK		(0xff << 0)
+
+/* DA9150_PPR_BKCTRL_A = 0x163 */
+#define DA9150_VBUS_MODE_SHIFT			0
+#define DA9150_VBUS_MODE_MASK			(0x03 << 0)
+#define DA9150_VBUS_MODE_CHG			(0x01 << 0)
+#define DA9150_VBUS_MODE_OTG			(0x02 << 0)
+#define DA9150_VBUS_LPM_SHIFT			2
+#define DA9150_VBUS_LPM_MASK			(0x03 << 2)
+#define DA9150_VBUS_SUSP_SHIFT			4
+#define DA9150_VBUS_SUSP_MASK			(0x01 << 4)
+#define DA9150_VBUS_PWM_SHIFT			5
+#define DA9150_VBUS_PWM_MASK			(0x01 << 5)
+#define DA9150_VBUS_ISO_SHIFT			6
+#define DA9150_VBUS_ISO_MASK			(0x01 << 6)
+#define DA9150_VBUS_LDO_SHIFT			7
+#define DA9150_VBUS_LDO_MASK			(0x01 << 7)
+
+/* DA9150_PPR_BKCFG_A = 0x164 */
+#define DA9150_VBUS_ISET_SHIFT			0
+#define DA9150_VBUS_ISET_MASK			(0x1f << 0)
+#define DA9150_VBUS_IMAX_SHIFT			5
+#define DA9150_VBUS_IMAX_MASK			(0x01 << 5)
+#define DA9150_VBUS_IOTG_SHIFT			6
+#define DA9150_VBUS_IOTG_MASK			(0x03 << 6)
+
+/* DA9150_PPR_BKCFG_B = 0x165 */
+#define DA9150_VBUS_DROP_SHIFT			0
+#define DA9150_VBUS_DROP_MASK			(0x0f << 0)
+#define DA9150_VBUS_FAULT_DIS_SHIFT		6
+#define DA9150_VBUS_FAULT_DIS_MASK		(0x01 << 6)
+#define DA9150_OTG_FAULT_DIS_SHIFT		7
+#define DA9150_OTG_FAULT_DIS_MASK		(0x01 << 7)
+
+/* DA9150_PPR_CHGCTRL_A = 0x166 */
+#define DA9150_CHG_EN_SHIFT			0
+#define DA9150_CHG_EN_MASK			(0x01 << 0)
+
+/* DA9150_PPR_CHGCTRL_B = 0x167 */
+#define DA9150_CHG_VBAT_SHIFT			0
+#define DA9150_CHG_VBAT_MASK			(0x1f << 0)
+#define DA9150_CHG_VDROP_SHIFT			6
+#define DA9150_CHG_VDROP_MASK			(0x03 << 6)
+
+/* DA9150_PPR_CHGCTRL_C = 0x168 */
+#define DA9150_CHG_VFAULT_SHIFT			0
+#define DA9150_CHG_VFAULT_MASK			(0x0f << 0)
+#define DA9150_CHG_IPRE_SHIFT			4
+#define DA9150_CHG_IPRE_MASK			(0x03 << 4)
+
+/* DA9150_PPR_TCTR_A = 0x169 */
+#define DA9150_CHG_TCTR_SHIFT			0
+#define DA9150_CHG_TCTR_MASK			(0x07 << 0)
+#define DA9150_CHG_TCTR_MODE_SHIFT		4
+#define DA9150_CHG_TCTR_MODE_MASK		(0x01 << 4)
+
+/* DA9150_PPR_CHGCTRL_D = 0x16A */
+#define DA9150_CHG_IBAT_SHIFT			0
+#define DA9150_CHG_IBAT_MASK			(0xff << 0)
+
+/* DA9150_PPR_CHGCTRL_E = 0x16B */
+#define DA9150_CHG_IEND_SHIFT			0
+#define DA9150_CHG_IEND_MASK			(0xff << 0)
+
+/* DA9150_PPR_CHGCTRL_F = 0x16C */
+#define DA9150_CHG_VCOLD_SHIFT			0
+#define DA9150_CHG_VCOLD_MASK			(0x1f << 0)
+#define DA9150_TBAT_TQA_EN_SHIFT		6
+#define DA9150_TBAT_TQA_EN_MASK			(0x01 << 6)
+#define DA9150_TBAT_TDP_EN_SHIFT		7
+#define DA9150_TBAT_TDP_EN_MASK			(0x01 << 7)
+
+/* DA9150_PPR_CHGCTRL_G = 0x16D */
+#define DA9150_CHG_VWARM_SHIFT			0
+#define DA9150_CHG_VWARM_MASK			(0x1f << 0)
+
+/* DA9150_PPR_CHGCTRL_H = 0x16E */
+#define DA9150_CHG_VHOT_SHIFT			0
+#define DA9150_CHG_VHOT_MASK			(0x1f << 0)
+
+/* DA9150_PPR_CHGCTRL_I = 0x16F */
+#define DA9150_CHG_ICOLD_SHIFT			0
+#define DA9150_CHG_ICOLD_MASK			(0xff << 0)
+
+/* DA9150_PPR_CHGCTRL_J = 0x170 */
+#define DA9150_CHG_IWARM_SHIFT			0
+#define DA9150_CHG_IWARM_MASK			(0xff << 0)
+
+/* DA9150_PPR_CHGCTRL_K = 0x171 */
+#define DA9150_CHG_IHOT_SHIFT			0
+#define DA9150_CHG_IHOT_MASK			(0xff << 0)
+
+/* DA9150_PPR_CHGCTRL_L = 0x172 */
+#define DA9150_CHG_IBAT_TRED_SHIFT		0
+#define DA9150_CHG_IBAT_TRED_MASK		(0xff << 0)
+
+/* DA9150_PPR_CHGCTRL_M = 0x173 */
+#define DA9150_CHG_VFLOAT_SHIFT			0
+#define DA9150_CHG_VFLOAT_MASK			(0x0f << 0)
+#define DA9150_CHG_LPM_SHIFT			5
+#define DA9150_CHG_LPM_MASK			(0x01 << 5)
+#define DA9150_CHG_NBLO_SHIFT			6
+#define DA9150_CHG_NBLO_MASK			(0x01 << 6)
+#define DA9150_EBS_EN_SHIFT			7
+#define DA9150_EBS_EN_MASK			(0x01 << 7)
+
+/* DA9150_PPR_THYST_A = 0x174 */
+#define DA9150_TBAT_T1_SHIFT			0
+#define DA9150_TBAT_T1_MASK			(0xff << 0)
+
+/* DA9150_PPR_THYST_B = 0x175 */
+#define DA9150_TBAT_T2_SHIFT			0
+#define DA9150_TBAT_T2_MASK			(0xff << 0)
+
+/* DA9150_PPR_THYST_C = 0x176 */
+#define DA9150_TBAT_T3_SHIFT			0
+#define DA9150_TBAT_T3_MASK			(0xff << 0)
+
+/* DA9150_PPR_THYST_D = 0x177 */
+#define DA9150_TBAT_T4_SHIFT			0
+#define DA9150_TBAT_T4_MASK			(0xff << 0)
+
+/* DA9150_PPR_THYST_E = 0x178 */
+#define DA9150_TBAT_T5_SHIFT			0
+#define DA9150_TBAT_T5_MASK			(0xff << 0)
+
+/* DA9150_PPR_THYST_F = 0x179 */
+#define DA9150_TBAT_H1_SHIFT			0
+#define DA9150_TBAT_H1_MASK			(0xff << 0)
+
+/* DA9150_PPR_THYST_G = 0x17A */
+#define DA9150_TBAT_H5_SHIFT			0
+#define DA9150_TBAT_H5_MASK			(0xff << 0)
+
+/* DA9150_PAGE_CON_3 = 0x180 */
+#define DA9150_PAGE_SHIFT			0
+#define DA9150_PAGE_MASK			(0x3f << 0)
+#define DA9150_WRITE_MODE_SHIFT			6
+#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			(0x01 << 7)
+
+/* DA9150_PAGE_CON_4 = 0x200 */
+#define DA9150_PAGE_SHIFT			0
+#define DA9150_PAGE_MASK			(0x3f << 0)
+#define DA9150_WRITE_MODE_SHIFT			6
+#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			(0x01 << 7)
+
+/* DA9150_PAGE_CON_5 = 0x280 */
+#define DA9150_PAGE_SHIFT			0
+#define DA9150_PAGE_MASK			(0x3f << 0)
+#define DA9150_WRITE_MODE_SHIFT			6
+#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			(0x01 << 7)
+
+/* DA9150_PAGE_CON_6 = 0x300 */
+#define DA9150_PAGE_SHIFT			0
+#define DA9150_PAGE_MASK			(0x3f << 0)
+#define DA9150_WRITE_MODE_SHIFT			6
+#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			(0x01 << 7)
+
+/* DA9150_COREBTLD_STAT_A = 0x302 */
+#define DA9150_BOOTLD_STAT_SHIFT		0
+#define DA9150_BOOTLD_STAT_MASK			(0x03 << 0)
+#define DA9150_CORE_LOCKUP_SHIFT		2
+#define DA9150_CORE_LOCKUP_MASK			(0x01 << 2)
+
+/* DA9150_COREBTLD_CTRL_A = 0x303 */
+#define DA9150_CORE_RESET_SHIFT			0
+#define DA9150_CORE_RESET_MASK			(0x01 << 0)
+#define DA9150_CORE_STOP_SHIFT			1
+#define DA9150_CORE_STOP_MASK			(0x01 << 1)
+
+/* DA9150_CORE_CONFIG_A = 0x304 */
+#define DA9150_CORE_MEMMUX_SHIFT		0
+#define DA9150_CORE_MEMMUX_MASK			(0x03 << 0)
+#define DA9150_WDT_AUTO_START_SHIFT		2
+#define DA9150_WDT_AUTO_START_MASK		(0x01 << 2)
+#define DA9150_WDT_AUTO_LOCK_SHIFT		3
+#define DA9150_WDT_AUTO_LOCK_MASK		(0x01 << 3)
+#define DA9150_WDT_HLT_NO_CLK_SHIFT		4
+#define DA9150_WDT_HLT_NO_CLK_MASK		(0x01 << 4)
+
+/* DA9150_CORE_CONFIG_C = 0x305 */
+#define DA9150_CORE_SW_SIZE_SHIFT		0
+#define DA9150_CORE_SW_SIZE_MASK		(0xff << 0)
+
+/* DA9150_CORE_CONFIG_B = 0x306 */
+#define DA9150_BOOTLD_EN_SHIFT			0
+#define DA9150_BOOTLD_EN_MASK			(0x01 << 0)
+#define DA9150_CORE_EN_SHIFT			2
+#define DA9150_CORE_EN_MASK			(0x01 << 2)
+#define DA9150_CORE_SW_SRC_SHIFT		3
+#define DA9150_CORE_SW_SRC_MASK			(0x07 << 3)
+#define DA9150_DEEP_SLEEP_EN_SHIFT		7
+#define DA9150_DEEP_SLEEP_EN_MASK		(0x01 << 7)
+
+/* DA9150_CORE_CFG_DATA_A = 0x307 */
+#define DA9150_CORE_CFG_DT_A_SHIFT		0
+#define DA9150_CORE_CFG_DT_A_MASK		(0xff << 0)
+
+/* DA9150_CORE_CFG_DATA_B = 0x308 */
+#define DA9150_CORE_CFG_DT_B_SHIFT		0
+#define DA9150_CORE_CFG_DT_B_MASK		(0xff << 0)
+
+/* DA9150_CORE_CMD_A = 0x309 */
+#define DA9150_CORE_CMD_SHIFT			0
+#define DA9150_CORE_CMD_MASK			(0xff << 0)
+
+/* DA9150_CORE_DATA_A = 0x30A */
+#define DA9150_CORE_DATA_0_SHIFT		0
+#define DA9150_CORE_DATA_0_MASK			(0xff << 0)
+
+/* DA9150_CORE_DATA_B = 0x30B */
+#define DA9150_CORE_DATA_1_SHIFT		0
+#define DA9150_CORE_DATA_1_MASK			(0xff << 0)
+
+/* DA9150_CORE_DATA_C = 0x30C */
+#define DA9150_CORE_DATA_2_SHIFT		0
+#define DA9150_CORE_DATA_2_MASK			(0xff << 0)
+
+/* DA9150_CORE_DATA_D = 0x30D */
+#define DA9150_CORE_DATA_3_SHIFT		0
+#define DA9150_CORE_DATA_3_MASK			(0xff << 0)
+
+/* DA9150_CORE2WIRE_STAT_A = 0x310 */
+#define DA9150_FW_FWDL_ERR_SHIFT		7
+#define DA9150_FW_FWDL_ERR_MASK			(0x01 << 7)
+
+/* DA9150_CORE2WIRE_CTRL_A = 0x311 */
+#define DA9150_FW_FWDL_EN_SHIFT			0
+#define DA9150_FW_FWDL_EN_MASK			(0x01 << 0)
+#define DA9150_FG_QIF_EN_SHIFT			1
+#define DA9150_FG_QIF_EN_MASK			(0x01 << 1)
+#define DA9150_CORE_BASE_ADDR_SHIFT		4
+#define DA9150_CORE_BASE_ADDR_MASK		(0x0f << 4)
+
+/* DA9150_FW_CTRL_A = 0x312 */
+#define DA9150_FW_SEAL_SHIFT			0
+#define DA9150_FW_SEAL_MASK			(0xff << 0)
+
+/* DA9150_FW_CTRL_C = 0x313 */
+#define DA9150_FW_FWDL_CRC_SHIFT		0
+#define DA9150_FW_FWDL_CRC_MASK			(0xff << 0)
+
+/* DA9150_FW_CTRL_D = 0x314 */
+#define DA9150_FW_FWDL_BASE_SHIFT		0
+#define DA9150_FW_FWDL_BASE_MASK		(0x0f << 0)
+
+/* DA9150_FG_CTRL_A = 0x315 */
+#define DA9150_FG_QIF_CODE_SHIFT		0
+#define DA9150_FG_QIF_CODE_MASK			(0xff << 0)
+
+/* DA9150_FG_CTRL_B = 0x316 */
+#define DA9150_FG_QIF_VALUE_SHIFT		0
+#define DA9150_FG_QIF_VALUE_MASK		(0xff << 0)
+
+/* DA9150_FW_CTRL_E = 0x317 */
+#define DA9150_FW_FWDL_SEG_SHIFT		0
+#define DA9150_FW_FWDL_SEG_MASK			(0xff << 0)
+
+/* DA9150_FW_CTRL_B = 0x318 */
+#define DA9150_FW_FWDL_VALUE_SHIFT		0
+#define DA9150_FW_FWDL_VALUE_MASK		(0xff << 0)
+
+/* DA9150_GPADC_CMAN = 0x320 */
+#define DA9150_GPADC_CEN_SHIFT			0
+#define DA9150_GPADC_CEN_MASK			(0x01 << 0)
+#define DA9150_GPADC_CMUX_SHIFT			1
+#define DA9150_GPADC_CMUX_MASK			(0x1f << 1)
+
+/* DA9150_GPADC_CRES_A = 0x322 */
+#define DA9150_GPADC_CRES_H_SHIFT		0
+#define DA9150_GPADC_CRES_H_MASK		(0xff << 0)
+
+/* DA9150_GPADC_CRES_B = 0x323 */
+#define DA9150_GPADC_CRUN_SHIFT			0
+#define DA9150_GPADC_CRUN_MASK			(0x01 << 0)
+#define DA9150_GPADC_CRES_L_SHIFT		6
+#define DA9150_GPADC_CRES_L_MASK		(0x03 << 6)
+
+/* DA9150_CC_CFG_A = 0x328 */
+#define DA9150_CC_EN_SHIFT			0
+#define DA9150_CC_EN_MASK			(0x01 << 0)
+#define DA9150_CC_TIMEBASE_SHIFT		1
+#define DA9150_CC_TIMEBASE_MASK			(0x03 << 1)
+#define DA9150_CC_CFG_SHIFT			5
+#define DA9150_CC_CFG_MASK			(0x03 << 5)
+#define DA9150_CC_ENDLESS_MODE_SHIFT		7
+#define DA9150_CC_ENDLESS_MODE_MASK		(0x01 << 7)
+
+/* DA9150_CC_CFG_B = 0x329 */
+#define DA9150_CC_OPT_SHIFT			0
+#define DA9150_CC_OPT_MASK			(0x03 << 0)
+#define DA9150_CC_PREAMP_SHIFT			2
+#define DA9150_CC_PREAMP_MASK			(0x03 << 2)
+
+/* DA9150_CC_ICHG_RES_A = 0x32A */
+#define DA9150_CC_ICHG_RES_H_SHIFT		0
+#define DA9150_CC_ICHG_RES_H_MASK		(0xff << 0)
+
+/* DA9150_CC_ICHG_RES_B = 0x32B */
+#define DA9150_CC_ICHG_RES_L_SHIFT		3
+#define DA9150_CC_ICHG_RES_L_MASK		(0x1f << 3)
+
+/* DA9150_CC_IAVG_RES_A = 0x32C */
+#define DA9150_CC_IAVG_RES_H_SHIFT		0
+#define DA9150_CC_IAVG_RES_H_MASK		(0xff << 0)
+
+/* DA9150_CC_IAVG_RES_B = 0x32D */
+#define DA9150_CC_IAVG_RES_L_SHIFT		0
+#define DA9150_CC_IAVG_RES_L_MASK		(0xff << 0)
+
+/* DA9150_TAUX_CTRL_A = 0x330 */
+#define DA9150_TAUX_EN_SHIFT			0
+#define DA9150_TAUX_EN_MASK			(0x01 << 0)
+#define DA9150_TAUX_MOD_SHIFT			1
+#define DA9150_TAUX_MOD_MASK			(0x01 << 1)
+#define DA9150_TAUX_UPDATE_SHIFT		2
+#define DA9150_TAUX_UPDATE_MASK			(0x01 << 2)
+
+/* DA9150_TAUX_RELOAD_H = 0x332 */
+#define DA9150_TAUX_RLD_H_SHIFT			0
+#define DA9150_TAUX_RLD_H_MASK			(0xff << 0)
+
+/* DA9150_TAUX_RELOAD_L = 0x333 */
+#define DA9150_TAUX_RLD_L_SHIFT			3
+#define DA9150_TAUX_RLD_L_MASK			(0x1f << 3)
+
+/* DA9150_TAUX_VALUE_H = 0x334 */
+#define DA9150_TAUX_VAL_H_SHIFT			0
+#define DA9150_TAUX_VAL_H_MASK			(0xff << 0)
+
+/* DA9150_TAUX_VALUE_L = 0x335 */
+#define DA9150_TAUX_VAL_L_SHIFT			3
+#define DA9150_TAUX_VAL_L_MASK			(0x1f << 3)
+
+/* DA9150_AUX_DATA_0 = 0x338 */
+#define DA9150_AUX_DAT_0_SHIFT			0
+#define DA9150_AUX_DAT_0_MASK			(0xff << 0)
+
+/* DA9150_AUX_DATA_1 = 0x339 */
+#define DA9150_AUX_DAT_1_SHIFT			0
+#define DA9150_AUX_DAT_1_MASK			(0xff << 0)
+
+/* DA9150_AUX_DATA_2 = 0x33A */
+#define DA9150_AUX_DAT_2_SHIFT			0
+#define DA9150_AUX_DAT_2_MASK			(0xff << 0)
+
+/* DA9150_AUX_DATA_3 = 0x33B */
+#define DA9150_AUX_DAT_3_SHIFT			0
+#define DA9150_AUX_DAT_3_MASK			(0xff << 0)
+
+/* DA9150_BIF_CTRL = 0x340 */
+#define DA9150_BIF_ISRC_EN_SHIFT		0
+#define DA9150_BIF_ISRC_EN_MASK			(0x01 << 0)
+
+/* DA9150_TBAT_CTRL_A = 0x342 */
+#define DA9150_TBAT_EN_SHIFT			0
+#define DA9150_TBAT_EN_MASK			(0x01 << 0)
+#define DA9150_TBAT_SW1_SHIFT			1
+#define DA9150_TBAT_SW1_MASK			(0x01 << 1)
+#define DA9150_TBAT_SW2_SHIFT			2
+#define DA9150_TBAT_SW2_MASK			(0x01 << 2)
+
+/* DA9150_TBAT_CTRL_B = 0x343 */
+#define DA9150_TBAT_SW_FRC_SHIFT		0
+#define DA9150_TBAT_SW_FRC_MASK			(0x01 << 0)
+#define DA9150_TBAT_STAT_SW1_SHIFT		1
+#define DA9150_TBAT_STAT_SW1_MASK		(0x01 << 1)
+#define DA9150_TBAT_STAT_SW2_SHIFT		2
+#define DA9150_TBAT_STAT_SW2_MASK		(0x01 << 2)
+#define DA9150_TBAT_HIGH_CURR_SHIFT		3
+#define DA9150_TBAT_HIGH_CURR_MASK		(0x01 << 3)
+
+/* DA9150_TBAT_RES_A = 0x344 */
+#define DA9150_TBAT_RES_H_SHIFT			0
+#define DA9150_TBAT_RES_H_MASK			(0xff << 0)
+
+/* DA9150_TBAT_RES_B = 0x345 */
+#define DA9150_TBAT_RES_DIS_SHIFT		0
+#define DA9150_TBAT_RES_DIS_MASK		(0x01 << 0)
+#define DA9150_TBAT_RES_L_SHIFT			6
+#define DA9150_TBAT_RES_L_MASK			(0x03 << 6)
+
+#endif /* _DA9150_REGISTERS_H */
--
1.9.3


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

* [PATCH 2/8] mfd: da9150: Add DT binding documentation for core
  2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
  2014-06-11 11:11 ` [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
@ 2014-06-11 11:11 ` Adam Thomson
  2014-06-11 11:11 ` [PATCH 3/8] iio: of_iio_channel_get_by_name() returns non-null pointers for error legs Adam Thomson
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 Documentation/devicetree/bindings/mfd/da9150.txt | 53 ++++++++++++++++++++++++
 1 file changed, 53 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/da9150.txt

diff --git a/Documentation/devicetree/bindings/mfd/da9150.txt b/Documentation/devicetree/bindings/mfd/da9150.txt
new file mode 100644
index 0000000..5c9adc3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/da9150.txt
@@ -0,0 +1,53 @@
+Dialog Semiconductor DA9150 Combined Charger/Fuel-Gauge MFD bindings
+
+DA9150 consists of a group of sub-devices (I2C Only):
+
+Device			 Description
+------			 -----------
+da9150-gpio		: GPIOs
+da9150-gpadc		: IIO - GPADC
+da9150-charger		: Power Supply (Charger)
+da9150-fg		: Power Supply (Fuel-Gauge)
+
+======
+
+Required properties:
+- compatible : Should be "dlg,da9150"
+- reg: Specifies the I2C slave address
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the IRQs from da9150 are delivered to.
+- interrupts: IRQ line info for da9150 chip.
+- interrupt-controller: da9150 has internal IRQs (own IRQ domain).
+
+Sub-devices:
+- da9150-gpio: See Documentation/devicetree/bindings/gpio/gpio-da9150.txt
+- da9150-gpadc: See Documentation/devicetree/bindings/iio/da9150-gpadc.txt
+- da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt
+- da9150-fg: See Documentation/devicetree/bindings/power/da9150-fg.txt
+
+
+Example:
+
+	charger_fg: da9150@58 {
+		compatible = "dlg,da9150";
+		reg = <0x58>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+
+		da9150-gpio {
+			...
+		};
+
+		gpadc: da9150-gpadc {
+			...
+		};
+
+		da9150-charger {
+			...
+		};
+
+		da9150-fg {
+			...
+		};
+	};
--
1.9.3


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

* [PATCH 3/8] iio: of_iio_channel_get_by_name() returns non-null pointers for error legs
  2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
  2014-06-11 11:11 ` [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
  2014-06-11 11:11 ` [PATCH 2/8] mfd: da9150: Add DT binding documentation for core Adam Thomson
@ 2014-06-11 11:11 ` Adam Thomson
  2014-06-15 20:20   ` Jonathan Cameron
  2014-06-11 11:11 ` [PATCH 4/8] iio: Add support for DA9150 GPADC Adam Thomson
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

Currently in the inkern.c code for IIO framework, the function
of_iio_channel_get_by_name() will return a non-NULL pointer when
it cannot find a channel using of_iio_channel_get() and when it
tries to search for 'io-channel-ranges' property and fails. This
is incorrect behaviour as the function which calls this expects
a NULL pointer for failure. This patch rectifies the issue.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 drivers/iio/inkern.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 0cf5f8e..1e8e94d 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -183,7 +183,7 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
 		else if (name && index >= 0) {
 			pr_err("ERROR: could not get IIO channel %s:%s(%i)\n",
 				np->full_name, name ? name : "", index);
-			return chan;
+			return NULL;
 		}

 		/*
@@ -193,8 +193,9 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
 		 */
 		np = np->parent;
 		if (np && !of_get_property(np, "io-channel-ranges", NULL))
-			break;
+			return NULL;
 	}
+
 	return chan;
 }

@@ -317,6 +318,7 @@ struct iio_channel *iio_channel_get(struct device *dev,
 		if (channel != NULL)
 			return channel;
 	}
+
 	return iio_channel_get_sys(name, channel_name);
 }
 EXPORT_SYMBOL_GPL(iio_channel_get);
--
1.9.3


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

* [PATCH 4/8] iio: Add support for DA9150 GPADC
  2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (2 preceding siblings ...)
  2014-06-11 11:11 ` [PATCH 3/8] iio: of_iio_channel_get_by_name() returns non-null pointers for error legs Adam Thomson
@ 2014-06-11 11:11 ` Adam Thomson
  2014-06-11 16:34   ` Jonathan Cameron
  2014-06-15 20:19   ` Jonathan Cameron
  2014-06-11 11:11 ` [PATCH 5/8] iio: da9150: Add DT binding documentation for GPADC Adam Thomson
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

This patch adds support for DA9150 Charger & Fuel-Gauge IC GPADC.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 drivers/iio/adc/Kconfig          |   9 +
 drivers/iio/adc/Makefile         |   1 +
 drivers/iio/adc/da9150-gpadc.c   | 396 +++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/da9150/gpadc.h |  71 +++++++
 4 files changed, 477 insertions(+)
 create mode 100644 drivers/iio/adc/da9150-gpadc.c
 create mode 100644 include/linux/mfd/da9150/gpadc.h

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 24c28e3..f5e9f72 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -105,6 +105,15 @@ config AT91_ADC
 	help
 	  Say yes here to build support for Atmel AT91 ADC.

+config DA9150_GPADC
+	tristate "Dialog DA9150 GPADC driver support"
+	depends on MFD_DA9150
+	help
+	  Say yes here to build support for Dialog DA9150 GPADC.
+
+	  This driver can also be built as a module. If chosen, the module name
+	  will be da9150-gpadc.
+
 config EXYNOS_ADC
 	tristate "Exynos ADC driver support"
 	depends on OF
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index ab346d8..414b22f 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AD7793) += ad7793.o
 obj-$(CONFIG_AD7887) += ad7887.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
+obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
 obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
 obj-$(CONFIG_MAX1363) += max1363.o
diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
new file mode 100644
index 0000000..2107f86
--- /dev/null
+++ b/drivers/iio/adc/da9150-gpadc.c
@@ -0,0 +1,396 @@
+/*
+ * DA9150 GPADC Driver
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/pdata.h>
+#include <linux/mfd/da9150/registers.h>
+#include <linux/mfd/da9150/gpadc.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+
+
+/*
+ * IRQ Handling
+ */
+
+static irqreturn_t da9150_gpadc_irq(int irq, void *data)
+{
+
+	struct da9150_gpadc *gpadc = data;
+
+	complete(&gpadc->complete);
+
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * GPADC access
+ */
+
+static inline int da9150_gpadc_gpio_2v_voltage_now(int raw_val)
+{
+	/* Convert to uV */
+	return (((3 * ((raw_val * 1000) + 500)) / 2048) * 1000);
+}
+
+static inline int da9150_gpadc_gpio_5v_voltage_now(int raw_val)
+{
+	/* Convert to uV */
+	return (((6 * ((raw_val * 1000) + 500)) / 1024) * 1000);
+}
+
+static inline int da9150_gpadc_ibus_current_avg(int raw_val)
+{
+	/* Convert to uA */
+	return (((4 * ((raw_val * 1000) + 500)) / 2048) * 1000);
+}
+
+static inline int da9150_gpadc_vbus_6v_voltage_now(int raw_val)
+{
+	/* Convert to uV */
+	return (((3 * ((raw_val * 1000) + 500)) / 512) * 1000);
+}
+
+static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
+{
+	/* Convert to uV */
+	return (((21 * ((raw_val * 1000) + 500)) / 1024) * 1000);
+}
+
+static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
+{
+	/* Convert to uV */
+	return (((3 * ((raw_val * 1000) + 500)) / 512) * 1000);
+}
+
+static inline int da9150_gpadc_vsys_1_5v_voltage_now(int raw_val)
+{
+	/* Convert to uV */
+	return (((3 * ((raw_val * 1000) + 500)) / 2048) * 1000);
+}
+
+static inline int da9150_gpadc_tjunc_temp(int raw_val)
+{
+	/* Convert to 0.1 degrees C */
+	return (((879 - (1023 - raw_val)) * 10000) / 4420);
+}
+
+static inline int da9150_gpadc_vbat_voltage_now(int raw_val)
+{
+	/* Convert to uV */
+	return ((2932 * raw_val) + 1500000);
+}
+
+int da9150_gpadc_read_process(int channel, int raw_val)
+{
+	int ret;
+
+	switch (channel) {
+	case DA9150_GPADC_CHAN_GPIOA_2V:
+	case DA9150_GPADC_CHAN_GPIOA_2V_:
+	case DA9150_GPADC_CHAN_GPIOB_2V:
+	case DA9150_GPADC_CHAN_GPIOB_2V_:
+	case DA9150_GPADC_CHAN_GPIOC_2V:
+	case DA9150_GPADC_CHAN_GPIOC_2V_:
+	case DA9150_GPADC_CHAN_GPIOD_2V:
+	case DA9150_GPADC_CHAN_GPIOD_2V_:
+		ret = da9150_gpadc_gpio_2v_voltage_now(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_IBUS_SENSE:
+	case DA9150_GPADC_CHAN_IBUS_SENSE_:
+		ret = da9150_gpadc_ibus_current_avg(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_VBUS_DIV:
+		ret = da9150_gpadc_vbus_6v_voltage_now(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_VBUS_DIV_:
+		ret = da9150_gpadc_vbus_21v_voltage_now(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_VSYS:
+		ret = da9150_gpadc_vsys_6v_voltage_now(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_VSYS_:
+		ret = da9150_gpadc_vsys_1_5v_voltage_now(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_GPIOA_5V:
+	case DA9150_GPADC_CHAN_GPIOA_5V_:
+	case DA9150_GPADC_CHAN_GPIOB_5V:
+	case DA9150_GPADC_CHAN_GPIOB_5V_:
+	case DA9150_GPADC_CHAN_GPIOC_5V:
+	case DA9150_GPADC_CHAN_GPIOC_5V_:
+	case DA9150_GPADC_CHAN_GPIOD_5V:
+	case DA9150_GPADC_CHAN_GPIOD_5V_:
+		ret = da9150_gpadc_gpio_5v_voltage_now(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_TJUNC_CORE:
+	case DA9150_GPADC_CHAN_TJUNC_CORE_:
+	case DA9150_GPADC_CHAN_TJUNC_OVP:
+	case DA9150_GPADC_CHAN_TJUNC_OVP_:
+		ret = da9150_gpadc_tjunc_temp(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_VBAT:
+		ret = da9150_gpadc_vbat_voltage_now(raw_val);
+		break;
+	default:
+		/* No processing for other channels so return raw value */
+		ret = raw_val;
+		break;
+	}
+
+	return ret;
+}
+
+int da9150_gpadc_read_raw(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	struct da9150_gpadc *gpadc = iio_priv(indio_dev);
+	u8 reg = 0;
+	u8 result_regs[2];
+	u16 result;
+
+	if ((mask != IIO_CHAN_INFO_RAW) && (mask != IIO_CHAN_INFO_PROCESSED))
+		return -EINVAL;
+
+	if ((chan->channel < DA9150_GPADC_CHAN_GPIOA_2V) ||
+	    (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP_))
+		return -EINVAL;
+
+	mutex_lock(&gpadc->lock);
+
+	/* Set channel & enable measurement */
+	reg |= DA9150_GPADC_EN_MASK;
+	reg |= chan->channel << DA9150_GPADC_MUX_SHIFT;
+	da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN, reg);
+
+	/* Consume left-over completion from a previous timeout */
+	try_wait_for_completion(&gpadc->complete);
+
+	/* Check for actual completion */
+	wait_for_completion_timeout(&gpadc->complete, msecs_to_jiffies(5));
+
+	/* Read result and status from device */
+	da9150_bulk_read(gpadc->da9150, DA9150_GPADC_RES_A, 2, result_regs);
+
+	/* Check to make sure device really has completed reading */
+	if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
+		mutex_unlock(&gpadc->lock);
+		dev_err(gpadc->dev, "Timeout on channel %d of GP-ADC\n",
+			chan->channel);
+		return -ETIMEDOUT;
+	}
+
+	mutex_unlock(&gpadc->lock);
+
+	/* LSBs - 2 bits */
+	result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
+		 DA9150_GPADC_RES_L_SHIFT;
+	/* MSBs - 8 bits */
+	result |= result_regs[0] << 2;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_PROCESSED:
+		*val = da9150_gpadc_read_process(chan->channel, result);
+		break;
+	case IIO_CHAN_INFO_RAW:
+		*val = result;
+		break;
+	}
+
+	return IIO_VAL_INT;
+}
+
+
+static const struct iio_info da9150_gpadc_info = {
+	.read_raw = &da9150_gpadc_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+#define GPADC_CHANNEL(_id, _type, chan_info, _ext_name) {		\
+	.type = _type,							\
+	.indexed = 1,							\
+	.channel = DA9150_GPADC_CHAN_##_id,				\
+	.info_mask_separate = chan_info,				\
+	.extend_name = _ext_name,					\
+	.datasheet_name = #_id,						\
+}
+
+#define GPADC_CHANNEL_RAW(_id, _type, _ext_name)	\
+	GPADC_CHANNEL(_id, _type, BIT(IIO_CHAN_INFO_RAW), _ext_name)
+
+#define GPADC_CHANNEL_RAW_PROCESSED(_id, _type, _ext_name)			\
+	GPADC_CHANNEL(_id, _type,						\
+		      BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),	\
+		      _ext_name)
+
+/* Supported channels */
+static const struct iio_chan_spec da9150_gpadc_channels[] = {
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_2V, IIO_VOLTAGE, "GPIOA_2V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_2V_, IIO_VOLTAGE, "GPIOA_2V_"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_2V, IIO_VOLTAGE, "GPIOB_2V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_2V_, IIO_VOLTAGE, "GPIOB_2V_"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_2V, IIO_VOLTAGE, "GPIOC_2V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_2V_, IIO_VOLTAGE, "GPIOC_2V_"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_2V, IIO_VOLTAGE, "GPIOD_2V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_2V_, IIO_VOLTAGE, "GPIOD_2V_"),
+	GPADC_CHANNEL_RAW_PROCESSED(IBUS_SENSE, IIO_CURRENT, "IBUS"),
+	GPADC_CHANNEL_RAW_PROCESSED(IBUS_SENSE_, IIO_CURRENT, "IBUS_"),
+	GPADC_CHANNEL_RAW_PROCESSED(VBUS_DIV, IIO_VOLTAGE, "VBUS_6V"),
+	GPADC_CHANNEL_RAW_PROCESSED(VBUS_DIV_, IIO_VOLTAGE, "VBUS_21V"),
+	GPADC_CHANNEL_RAW(ID, IIO_VOLTAGE, "ID"),
+	GPADC_CHANNEL_RAW(ID_, IIO_VOLTAGE, "ID_"),
+	GPADC_CHANNEL_RAW_PROCESSED(VSYS, IIO_VOLTAGE, "VSYS_6V"),
+	GPADC_CHANNEL_RAW_PROCESSED(VSYS_, IIO_VOLTAGE, "VSYS_1_5V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_5V, IIO_VOLTAGE, "GPIOA_5V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_5V_, IIO_VOLTAGE, "GPIOA_5V_"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_5V, IIO_VOLTAGE, "GPIOB_5V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_5V_, IIO_VOLTAGE, "GPIOB_5V_"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_5V, IIO_VOLTAGE, "GPIOC_5V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_5V_, IIO_VOLTAGE, "GPIOC_5V_"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_5V, IIO_VOLTAGE, "GPIOD_5V"),
+	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_5V_, IIO_VOLTAGE, "GPIOD_5V_"),
+	GPADC_CHANNEL_RAW_PROCESSED(VBAT, IIO_VOLTAGE, "VBAT"),
+	GPADC_CHANNEL_RAW_PROCESSED(VBAT_, IIO_VOLTAGE, "VBAT_"),
+	GPADC_CHANNEL_RAW(TBAT, IIO_VOLTAGE, "TBAT"),
+	GPADC_CHANNEL_RAW(TBAT_, IIO_VOLTAGE, "TBAT_"),
+	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_CORE, IIO_TEMP, "TJUNC_CORE"),
+	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_CORE_, IIO_TEMP, "TJUNC_CORE_"),
+	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_OVP, IIO_TEMP, "TJUNC_OVP"),
+	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_OVP_, IIO_TEMP, "TJUNC_OVP_"),
+};
+
+/* Default maps used by da9150-charger */
+static struct iio_map da9150_gpadc_default_maps[] = {
+	{
+		.consumer_dev_name = "da9150-charger",
+		.consumer_channel = "CHAN_IBUS",
+		.adc_channel_label = "IBUS_SENSE",
+	},
+	{
+		.consumer_dev_name = "da9150-charger",
+		.consumer_channel = "CHAN_VBUS",
+		.adc_channel_label = "VBUS_DIV_",
+	},
+	{
+		.consumer_dev_name = "da9150-charger",
+		.consumer_channel = "CHAN_TJUNC",
+		.adc_channel_label = "TJUNC_CORE",
+	},
+	{
+		.consumer_dev_name = "da9150-charger",
+		.consumer_channel = "CHAN_VBAT",
+		.adc_channel_label = "VBAT",
+	},
+	{},
+};
+
+
+/*
+ * Driver top level functions
+ */
+
+static int da9150_gpadc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct da9150 *da9150 = dev_get_drvdata(dev->parent);
+	struct da9150_gpadc *gpadc;
+	struct iio_dev *indio_dev;
+
+	int ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev,
+					  sizeof(struct da9150_gpadc));
+	if (!indio_dev) {
+		dev_err(&pdev->dev, "Failed to allocate IIO device\n");
+		return -ENOMEM;
+	}
+	gpadc = iio_priv(indio_dev);
+
+	platform_set_drvdata(pdev, indio_dev);
+	gpadc->da9150 = da9150;
+	gpadc->dev = dev;
+
+	ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
+	if (ret) {
+		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
+		goto iio_map_fail;
+	}
+
+	indio_dev->name = dev_name(dev);
+	indio_dev->dev.parent = dev;
+	indio_dev->dev.of_node = pdev->dev.of_node;
+	indio_dev->info = &da9150_gpadc_info;
+	indio_dev->modes = INDIO_DIRECT_MODE;
+	indio_dev->channels = da9150_gpadc_channels;
+	indio_dev->num_channels = ARRAY_SIZE(da9150_gpadc_channels);
+
+	ret = iio_device_register(indio_dev);
+	if (ret) {
+		dev_err(dev, "Failed to register IIO device: %d\n", ret);
+		goto iio_dev_fail;
+	}
+
+	mutex_init(&gpadc->lock);
+	init_completion(&gpadc->complete);
+
+	/* Register IRQ */
+	ret = da9150_register_irq(pdev, gpadc, da9150_gpadc_irq, "GPADC");
+	if (ret < 0)
+		goto irq_fail;
+
+	da9150->gpadc_ready = true;
+	return ret;
+
+irq_fail:
+	iio_device_unregister(indio_dev);
+
+iio_dev_fail:
+	iio_map_array_unregister(indio_dev);
+
+iio_map_fail:
+	return ret;
+}
+
+static int da9150_gpadc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	iio_map_array_unregister(indio_dev);
+	iio_device_unregister(indio_dev);
+
+	return 0;
+}
+
+static struct platform_driver da9150_gpadc_driver = {
+	.driver = {
+		.name = "da9150-gpadc",
+		.owner = THIS_MODULE,
+	},
+	.probe = da9150_gpadc_probe,
+	.remove = da9150_gpadc_remove,
+};
+
+module_platform_driver(da9150_gpadc_driver);
+
+MODULE_DESCRIPTION("GPADC Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/da9150/gpadc.h b/include/linux/mfd/da9150/gpadc.h
new file mode 100644
index 0000000..3e46164
--- /dev/null
+++ b/include/linux/mfd/da9150/gpadc.h
@@ -0,0 +1,71 @@
+/*
+ * DA9150 GPADC Driver - GPADC Data
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#ifndef _DA9150_GPADC_H
+#define _DA9150_GPADC_H
+
+#include <linux/device.h>
+#include <linux/iio/machine.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+
+#include <linux/mfd/da9150/core.h>
+
+
+/* Channels */
+enum da9150_gpadc_channel {
+	DA9150_GPADC_CHAN_GPIOA_2V = 0,
+	DA9150_GPADC_CHAN_GPIOA_2V_,
+	DA9150_GPADC_CHAN_GPIOB_2V,
+	DA9150_GPADC_CHAN_GPIOB_2V_,
+	DA9150_GPADC_CHAN_GPIOC_2V,
+	DA9150_GPADC_CHAN_GPIOC_2V_,
+	DA9150_GPADC_CHAN_GPIOD_2V,
+	DA9150_GPADC_CHAN_GPIOD_2V_,
+	DA9150_GPADC_CHAN_IBUS_SENSE,
+	DA9150_GPADC_CHAN_IBUS_SENSE_,
+	DA9150_GPADC_CHAN_VBUS_DIV,
+	DA9150_GPADC_CHAN_VBUS_DIV_,
+	DA9150_GPADC_CHAN_ID,
+	DA9150_GPADC_CHAN_ID_,
+	DA9150_GPADC_CHAN_VSYS,
+	DA9150_GPADC_CHAN_VSYS_,
+	DA9150_GPADC_CHAN_GPIOA_5V,
+	DA9150_GPADC_CHAN_GPIOA_5V_,
+	DA9150_GPADC_CHAN_GPIOB_5V,
+	DA9150_GPADC_CHAN_GPIOB_5V_,
+	DA9150_GPADC_CHAN_GPIOC_5V,
+	DA9150_GPADC_CHAN_GPIOC_5V_,
+	DA9150_GPADC_CHAN_GPIOD_5V,
+	DA9150_GPADC_CHAN_GPIOD_5V_,
+	DA9150_GPADC_CHAN_VBAT,
+	DA9150_GPADC_CHAN_VBAT_,
+	DA9150_GPADC_CHAN_TBAT,
+	DA9150_GPADC_CHAN_TBAT_,
+	DA9150_GPADC_CHAN_TJUNC_CORE,
+	DA9150_GPADC_CHAN_TJUNC_CORE_,
+	DA9150_GPADC_CHAN_TJUNC_OVP,
+	DA9150_GPADC_CHAN_TJUNC_OVP_,
+};
+
+
+/* Private data */
+struct da9150_gpadc {
+	struct da9150 *da9150;
+	struct device *dev;
+
+	struct mutex lock;
+	struct completion complete;
+};
+
+#endif /* _DA9150_GPADC_H */
--
1.9.3

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

* [PATCH 5/8] iio: da9150: Add DT binding documentation for GPADC
  2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (3 preceding siblings ...)
  2014-06-11 11:11 ` [PATCH 4/8] iio: Add support for DA9150 GPADC Adam Thomson
@ 2014-06-11 11:11 ` Adam Thomson
  2014-06-11 11:11 ` [PATCH 6/8] power: Add support for DA9150 Charger Adam Thomson
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 Documentation/devicetree/bindings/iio/da9150-gpadc.txt | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/iio/da9150-gpadc.txt

diff --git a/Documentation/devicetree/bindings/iio/da9150-gpadc.txt b/Documentation/devicetree/bindings/iio/da9150-gpadc.txt
new file mode 100644
index 0000000..c07228d
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/da9150-gpadc.txt
@@ -0,0 +1,16 @@
+Dialog Semiconductor DA9150 IIO GPADC bindings
+
+Required properties:
+- compatible: "dlg,da9150-gpadc" for DA9150 IIO GPADC
+- #io-channel-cells: Should be set to <1>
+  (See Documentation/devicetree/bindings/iio/iio-bindings.txt for further info)
+
+For further information on GPADC channels, see device datasheet.
+
+
+Example:
+
+	gpadc: da9150-gpadc {
+		compatible = "dlg,da9150-gpadc";
+		#io-channel-cells = <1>;
+	};
--
1.9.3


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

* [PATCH 6/8] power: Add support for DA9150 Charger
  2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (4 preceding siblings ...)
  2014-06-11 11:11 ` [PATCH 5/8] iio: da9150: Add DT binding documentation for GPADC Adam Thomson
@ 2014-06-11 11:11 ` Adam Thomson
  2014-06-16 13:27   ` Lee Jones
  2014-06-11 11:11 ` [PATCH 7/8] power: da9150: Add DT binding documentation for charger Adam Thomson
  2014-06-11 11:11 ` [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd Adam Thomson
  7 siblings, 1 reply; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

This patch adds support for DA9150 Charger & Fuel-Guage IC Charger.

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 drivers/power/Kconfig              |  23 ++
 drivers/power/Makefile             |   1 +
 drivers/power/da9150-charger.c     | 790 +++++++++++++++++++++++++++++++++++++
 include/linux/mfd/da9150/charger.h |  58 +++
 4 files changed, 872 insertions(+)
 create mode 100644 drivers/power/da9150-charger.c
 create mode 100644 include/linux/mfd/da9150/charger.h

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index ba69751..9835a78 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -185,6 +185,29 @@ config BATTERY_DA9052
 	  Say Y here to enable support for batteries charger integrated into
 	  DA9052 PMIC.

+config CHARGER_DA9150
+	tristate "Dialog Semiconductor DA9150 Charger support"
+	depends on MFD_DA9150
+	depends on DA9150_GPADC
+	depends on IIO
+	help
+	  Say Y here to enable support for charger unit of the DA9150
+	  Integrated Charger & Fuel-Gauge IC.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called da9150-charger.
+
+config CHARGER_DA9150_OTG_VBUS_EVENT
+	bool "Dialog Semiconductor DA9150 OTG VBUS event support"
+	depends on CHARGER_DA9150
+	help
+	  Say Y here if you have an OTG device driver which can supply events,
+	  using the otg transceiver, for when a USB host or charger is connected
+	  which provides power over VBUS. This setting overrides the default
+	  DA9150 support to indicate this type of event. Note that the default
+	  support cannot determine the type of device that is providing VBUS
+	  power and therefore assumes AC charger type.
+
 config BATTERY_MAX17040
 	tristate "Maxim MAX17040 Fuel Gauge"
 	depends on I2C
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index ee54a3e..2cdefaa 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_BATTERY_SBS)	+= sbs-battery.o
 obj-$(CONFIG_BATTERY_BQ27x00)	+= bq27x00_battery.o
 obj-$(CONFIG_BATTERY_DA9030)	+= da9030_battery.o
 obj-$(CONFIG_BATTERY_DA9052)	+= da9052-battery.o
+obj-$(CONFIG_CHARGER_DA9150)	+= da9150-charger.o
 obj-$(CONFIG_BATTERY_MAX17040)	+= max17040_battery.o
 obj-$(CONFIG_BATTERY_MAX17042)	+= max17042_battery.o
 obj-$(CONFIG_BATTERY_Z2)	+= z2_battery.o
diff --git a/drivers/power/da9150-charger.c b/drivers/power/da9150-charger.c
new file mode 100644
index 0000000..dd93fb4
--- /dev/null
+++ b/drivers/power/da9150-charger.c
@@ -0,0 +1,790 @@
+/*
+ * DA9150 Charger Driver
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/power_supply.h>
+#include <linux/notifier.h>
+#include <linux/usb/phy.h>
+#include <linux/iio/consumer.h>
+#include <linux/sysfs.h>
+
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/pdata.h>
+#include <linux/mfd/da9150/registers.h>
+#include <linux/mfd/da9150/charger.h>
+
+
+/*
+ * Common property functions
+ */
+
+static inline int da9150_charger_supply_online(struct da9150_charger *charger,
+					       struct power_supply *psy,
+					       union power_supply_propval *val)
+{
+	val->intval = (psy == charger->supply_online) ? 1 : 0;
+
+	return 0;
+}
+
+static int da9150_charger_vbus_voltage_now(struct da9150_charger *charger,
+					   union power_supply_propval *val)
+{
+	struct iio_channel *chan = charger->vbus_chan;
+
+	if (!chan)
+		return -EINVAL;
+
+	/* Read processed value - uV units */
+	return iio_read_channel_processed(chan, &val->intval);
+}
+
+static int da9150_charger_ibus_current_avg(struct da9150_charger *charger,
+					   union power_supply_propval *val)
+{
+	struct iio_channel *chan = charger->ibus_chan;
+
+	if (!chan)
+		return -EINVAL;
+
+	/* Read processed value - uA degrees C units */
+	return iio_read_channel_processed(chan, &val->intval);
+}
+
+static int da9150_charger_tjunc_temp(struct da9150_charger *charger,
+				     union power_supply_propval *val)
+{
+	struct iio_channel *chan = charger->tjunc_chan;
+
+	if (!chan)
+		return -EINVAL;
+
+	/* Read processed value - 0.1 degrees C units */
+	return iio_read_channel_processed(chan, &val->intval);
+}
+
+
+/*
+ * USB Properties
+ */
+
+static enum power_supply_property da9150_charger_props[] = {
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_AVG,
+	POWER_SUPPLY_PROP_TEMP,
+};
+
+static int da9150_charger_get_prop(struct power_supply *psy,
+				   enum power_supply_property psp,
+				   union power_supply_propval *val)
+{
+	struct da9150_charger *charger = dev_get_drvdata(psy->dev->parent);
+	int ret;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = da9150_charger_supply_online(charger, psy, val);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = da9150_charger_vbus_voltage_now(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_AVG:
+		ret = da9150_charger_ibus_current_avg(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_TEMP:
+		ret = da9150_charger_tjunc_temp(charger, val);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+/*
+ * Battery Properties
+ */
+
+static int da9150_charger_battery_status(struct da9150_charger *charger,
+					 union power_supply_propval *val)
+{
+	u8 reg;
+
+	/* Check to see if battery is discharging */
+	reg = da9150_reg_read(charger->da9150, DA9150_STATUS_H);
+
+	if (((reg & DA9150_VBUS_STAT_MASK) == DA9150_VBUS_STAT_OFF) ||
+	    ((reg & DA9150_VBUS_STAT_MASK) == DA9150_VBUS_STAT_WAIT)) {
+		val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+
+		return 0;
+	}
+
+	reg = da9150_reg_read(charger->da9150, DA9150_STATUS_J);
+
+	/* Now check for other states */
+	switch (reg & DA9150_CHG_STAT_MASK) {
+	case DA9150_CHG_STAT_ACT:
+	case DA9150_CHG_STAT_PRE:
+	case DA9150_CHG_STAT_CC:
+	case DA9150_CHG_STAT_CV:
+		val->intval = POWER_SUPPLY_STATUS_CHARGING;
+		break;
+	case DA9150_CHG_STAT_OFF:
+	case DA9150_CHG_STAT_SUSP:
+	case DA9150_CHG_STAT_TEMP:
+	case DA9150_CHG_STAT_TIME:
+	case DA9150_CHG_STAT_BAT:
+		val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+		break;
+	case DA9150_CHG_STAT_FULL:
+		val->intval = POWER_SUPPLY_STATUS_FULL;
+		break;
+	default:
+		val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
+		break;
+	}
+
+	return 0;
+}
+
+static int da9150_charger_battery_health(struct da9150_charger *charger,
+					 union power_supply_propval *val)
+{
+	u8 reg;
+
+	reg = da9150_reg_read(charger->da9150, DA9150_STATUS_J);
+
+	/* Check if temperature limit reached */
+	switch (reg & DA9150_CHG_TEMP_MASK) {
+	case DA9150_CHG_TEMP_UNDER:
+		val->intval = POWER_SUPPLY_HEALTH_COLD;
+		return 0;
+	case DA9150_CHG_TEMP_OVER:
+		val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+		return 0;
+	default:
+		break;
+	}
+
+	/* Check for other health states */
+	switch (reg & DA9150_CHG_STAT_MASK) {
+	case DA9150_CHG_STAT_ACT:
+	case DA9150_CHG_STAT_PRE:
+		val->intval = POWER_SUPPLY_HEALTH_DEAD;
+		break;
+	case DA9150_CHG_STAT_TIME:
+		val->intval = POWER_SUPPLY_HEALTH_UNSPEC_FAILURE;
+		break;
+	default:
+		val->intval = POWER_SUPPLY_HEALTH_GOOD;
+		break;
+	}
+
+	return 0;
+}
+
+static int da9150_charger_battery_present(struct da9150_charger *charger,
+					  union power_supply_propval *val)
+{
+	u8 reg;
+
+	/* No valid TBAT reading so assume battery present */
+	if (charger->invalid_tbat) {
+		val->intval = 1;
+		return 0;
+	}
+
+	/* Check if battery present or removed */
+	reg = da9150_reg_read(charger->da9150, DA9150_STATUS_J);
+	if ((reg & DA9150_CHG_STAT_MASK) == DA9150_CHG_STAT_BAT)
+		val->intval = 0;
+	else
+		val->intval = 1;
+
+	return 0;
+}
+
+static int da9150_charger_battery_charge_type(struct da9150_charger *charger,
+					      union power_supply_propval *val)
+{
+	u8 reg;
+
+	reg = da9150_reg_read(charger->da9150, DA9150_STATUS_J);
+
+	switch (reg & DA9150_CHG_STAT_MASK) {
+	case DA9150_CHG_STAT_CC:
+		val->intval = POWER_SUPPLY_CHARGE_TYPE_FAST;
+		break;
+	case DA9150_CHG_STAT_ACT:
+	case DA9150_CHG_STAT_PRE:
+	case DA9150_CHG_STAT_CV:
+		val->intval = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
+		break;
+	default:
+		val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
+		break;
+	}
+
+	return 0;
+}
+
+static int da9150_charger_battery_voltage_min(struct da9150_charger *charger,
+					      union power_supply_propval *val)
+{
+	u8 reg;
+
+	reg = da9150_reg_read(charger->da9150, DA9150_PPR_CHGCTRL_C);
+
+	/* Value starts at 2500 mV, 50 mV increments, presented in uV */
+	val->intval = ((reg & DA9150_CHG_VFAULT_MASK) * 50000) + 2500000;
+
+	return 0;
+}
+
+static int da9150_charger_battery_voltage_now(struct da9150_charger *charger,
+					      union power_supply_propval *val)
+{
+	struct iio_channel *chan = charger->vbat_chan;
+
+	if (!chan)
+		return -EINVAL;
+
+	/* Read processed value - uV units */
+	return iio_read_channel_processed(chan, &val->intval);
+}
+
+static int da9150_charger_battery_current_max(struct da9150_charger *charger,
+					      union power_supply_propval *val)
+{
+	int reg;
+
+	reg = da9150_reg_read(charger->da9150, DA9150_PPR_CHGCTRL_D);
+
+	val->intval = DA9150_CHG_IBAT_REG_TO_UA(reg);
+
+	return 0;
+}
+
+static int da9150_charger_battery_voltage_max(struct da9150_charger *charger,
+					      union power_supply_propval *val)
+{
+	u8 reg;
+
+	reg = da9150_reg_read(charger->da9150, DA9150_PPR_CHGCTRL_B);
+
+	/* Value starts at 3650 mV, 25 mV increments, presented in uV */
+	val->intval = ((reg & DA9150_CHG_VBAT_MASK) * 25000) + 3650000;
+	return 0;
+}
+
+static enum power_supply_property da9150_charger_bat_props[] = {
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+	POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX,
+};
+
+static int da9150_charger_battery_get_prop(struct power_supply *psy,
+					   enum power_supply_property psp,
+					   union power_supply_propval *val)
+{
+	struct da9150_charger *charger = dev_get_drvdata(psy->dev->parent);
+	int ret;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_STATUS:
+		ret = da9150_charger_battery_status(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		ret = da9150_charger_supply_online(charger, psy, val);
+		break;
+	case POWER_SUPPLY_PROP_HEALTH:
+		ret = da9150_charger_battery_health(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		ret = da9150_charger_battery_present(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_TYPE:
+		ret = da9150_charger_battery_charge_type(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+		ret = da9150_charger_battery_voltage_min(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = da9150_charger_battery_voltage_now(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+		ret = da9150_charger_battery_current_max(charger, val);
+		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE_MAX:
+		ret = da9150_charger_battery_voltage_max(charger, val);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+/*
+ * Other properties
+ */
+
+static ssize_t da9150_charger_attr_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf);
+
+#define DA9150_CHARGER_ATTR(_name, _reg, _shift, _mask)		\
+	{							\
+		.attr = __ATTR(_name, S_IRUGO,			\
+			       da9150_charger_attr_show,	\
+			       NULL),				\
+		.reg = _reg,					\
+		.shift = _shift,				\
+		.mask = _mask,					\
+	}
+
+static struct da9150_charger_attr_map da9150_charger_attrs[] = {
+	DA9150_CHARGER_ATTR(chg_en, DA9150_PPR_CHGCTRL_A,
+			    DA9150_CHG_EN_SHIFT, DA9150_CHG_EN_MASK),
+	DA9150_CHARGER_ATTR(chg_ipre, DA9150_PPR_CHGCTRL_C,
+			    DA9150_CHG_IPRE_SHIFT, DA9150_CHG_IPRE_MASK),
+	DA9150_CHARGER_ATTR(chg_iend, DA9150_PPR_CHGCTRL_E,
+			    DA9150_CHG_IEND_SHIFT, DA9150_CHG_IEND_MASK),
+	DA9150_CHARGER_ATTR(chg_temp, DA9150_STATUS_J,
+			    DA9150_CHG_TEMP_SHIFT, DA9150_CHG_TEMP_MASK),
+	DA9150_CHARGER_ATTR(chg_vdrop, DA9150_PPR_CHGCTRL_B,
+			    DA9150_CHG_VDROP_SHIFT, DA9150_CHG_VDROP_MASK),
+	DA9150_CHARGER_ATTR(tbat_upper, DA9150_PPR_THYST_E,
+			    DA9150_TBAT_T5_SHIFT, DA9150_TBAT_T5_MASK),
+	DA9150_CHARGER_ATTR(tbat_lower, DA9150_PPR_THYST_A,
+			    DA9150_TBAT_T1_SHIFT, DA9150_TBAT_T1_MASK),
+	DA9150_CHARGER_ATTR(vbus_mode, DA9150_PPR_BKCTRL_A,
+			    DA9150_VBUS_MODE_SHIFT, DA9150_VBUS_MODE_MASK),
+	DA9150_CHARGER_ATTR(vbus_tred, DA9150_STATUS_H,
+			    DA9150_VBUS_TRED_SHIFT, DA9150_VBUS_TRED_MASK),
+	DA9150_CHARGER_ATTR(vbus_drop_stat, DA9150_STATUS_H,
+			    DA9150_VBUS_DROP_STAT_SHIFT,
+			    DA9150_VBUS_DROP_STAT_MASK),
+};
+
+static ssize_t da9150_charger_attr_show(struct device *dev,
+					struct device_attribute *attr,
+					char *buf)
+{
+	struct da9150_charger *charger = dev_get_drvdata(dev);
+	struct da9150_charger_attr_map *charger_attrs;
+	int i;
+
+	/* Find attribute, and print out register field contents. */
+	for (i = 0, charger_attrs = da9150_charger_attrs;
+	     i < ARRAY_SIZE(da9150_charger_attrs);
+	     ++i, ++charger_attrs) {
+		if (attr == &charger_attrs->attr) {
+			u8 val;
+
+			val = da9150_reg_read(charger->da9150,
+					      charger_attrs->reg);
+			val &= charger_attrs->mask;
+			val = val >> charger_attrs->shift;
+
+			return sprintf(buf, "0x%x\n", val);
+		}
+	}
+
+	return 0;
+}
+
+
+/*
+ * IRQs
+ */
+
+static irqreturn_t da9150_charger_chg_irq(int irq, void *data)
+{
+	struct da9150_charger *charger = data;
+
+	power_supply_changed(&charger->battery);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t da9150_charger_tjunc_irq(int irq, void *data)
+{
+	struct da9150_charger *charger = data;
+
+	/* Nothing we can really do except report this. */
+	dev_crit(charger->dev, "TJunc over temperature!!!\n");
+	power_supply_changed(&charger->ac);
+	power_supply_changed(&charger->usb);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t da9150_charger_vfault_irq(int irq, void *data)
+{
+	struct da9150_charger *charger = data;
+
+	/* Nothing we can really do except report this. */
+	dev_crit(charger->dev, "VSYS under voltage!!!\n");
+	power_supply_changed(&charger->ac);
+	power_supply_changed(&charger->usb);
+	power_supply_changed(&charger->battery);
+
+	return IRQ_HANDLED;
+}
+
+#ifndef CONFIG_CHARGER_DA9150_OTG_VBUS_EVENT
+static irqreturn_t da9150_charger_vbus_irq(int irq, void *data)
+{
+	struct da9150_charger *charger = data;
+	u8 reg;
+
+	reg = da9150_reg_read(charger->da9150, DA9150_STATUS_H);
+
+	/* Charger plugged in or battery only */
+	switch (reg & DA9150_VBUS_STAT_MASK) {
+	case DA9150_VBUS_STAT_OFF:
+	case DA9150_VBUS_STAT_WAIT:
+		charger->supply_online = &charger->battery;
+		break;
+	case DA9150_VBUS_STAT_CHG:
+		/* Cannot determine charger type so assume AC */
+		charger->supply_online = &charger->ac;
+		break;
+	default:
+		dev_warn(charger->dev, "Unknown VBUS state - reg = 0x%x\n",
+			 reg);
+		charger->supply_online = NULL;
+		break;
+	}
+
+	power_supply_changed(&charger->ac);
+	power_supply_changed(&charger->battery);
+
+	return IRQ_HANDLED;
+}
+#endif /* CONFIG_CHARGER_DA9150_OTG_VBUS_EVENT */
+
+
+/*
+ * Power Management
+ */
+
+static void da9150_charger_shutdown(struct platform_device *pdev)
+{
+	struct da9150_charger *charger = platform_get_drvdata(pdev);
+
+	/* Only allow device into shutdown state if we're not charging. */
+	if ((charger->supply_online != &charger->ac) &&
+	    (charger->supply_online != &charger->usb))
+		charger->da9150->can_shutdown = true;
+}
+
+
+/*
+ * OTG Notification & handling
+ */
+static void da9150_charger_otg_work(struct work_struct *data)
+{
+	struct da9150_charger *charger =
+		container_of(data, struct da9150_charger, otg_work);
+
+	switch (charger->usb_event) {
+#ifdef CONFIG_CHARGER_DA9150_OTG_VBUS_EVENT
+	case USB_EVENT_CHARGER:
+		/* AC Supply online */
+		charger->supply_online = &charger->ac;
+		power_supply_changed(&charger->ac);
+		power_supply_changed(&charger->battery);
+		break;
+	case USB_EVENT_VBUS:
+	case USB_EVENT_ENUMERATED:
+		/* USB Supply online */
+		charger->supply_online = &charger->usb;
+		power_supply_changed(&charger->usb);
+		power_supply_changed(&charger->battery);
+		break;
+#endif /* CONFIG_CHARGER_DA9150_OTG_VBUS_EVENT */
+	case USB_EVENT_ID:
+		/* Enable OTG Boost */
+		da9150_set_bits(charger->da9150, DA9150_PPR_BKCTRL_A,
+				DA9150_VBUS_MODE_MASK, DA9150_VBUS_MODE_OTG);
+		break;
+	case USB_EVENT_NONE:
+		/* Revert to charge mode */
+		power_supply_changed(&charger->ac);
+		power_supply_changed(&charger->usb);
+		power_supply_changed(&charger->battery);
+		da9150_set_bits(charger->da9150, DA9150_PPR_BKCTRL_A,
+				DA9150_VBUS_MODE_MASK, DA9150_VBUS_MODE_CHG);
+		break;
+	}
+}
+
+static int da9150_charger_otg_ncb(struct notifier_block *nb, unsigned long val,
+				  void *priv)
+{
+	struct da9150_charger *charger =
+		container_of(nb, struct da9150_charger, otg_nb);
+
+	dev_dbg(charger->dev, "DA9150 OTG notify %lu\n", val);
+
+	charger->usb_event = val;
+	schedule_work(&charger->otg_work);
+
+	return NOTIFY_OK;
+}
+
+
+/*
+ * DT Platform Data
+ */
+
+static struct da9150_charger_pdata *da9150_charger_dt_pdata(struct device *dev)
+{
+	struct device_node *charger_node = dev->of_node;
+	struct da9150_charger_pdata *pdata;
+
+	pdata = devm_kzalloc(dev, sizeof(struct da9150_charger_pdata),
+			     GFP_KERNEL);
+	if (!pdata)
+		return NULL;
+
+	pdata->invalid_tbat =
+		of_property_read_bool(charger_node, "dlg,invalid-tbat");
+
+	return pdata;
+}
+
+
+/*
+ * Driver top level functions
+ */
+
+static int da9150_charger_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct da9150_charger_pdata *charger_pdata = dev_get_platdata(dev);
+	struct da9150 *da9150 = dev_get_drvdata(dev->parent);
+	struct da9150_charger *charger;
+	struct power_supply *ac, *usb, *battery;
+	struct iio_channel *chan;
+	u8 reg;
+	int i, ret;
+
+	/* Check GPADC is available, if not defer until it is */
+	if (!da9150->gpadc_ready)
+		return -EPROBE_DEFER;
+
+	charger = devm_kzalloc(dev, sizeof(struct da9150_charger), GFP_KERNEL);
+	if (charger == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, charger);
+	charger->da9150 = da9150;
+	charger->dev = dev;
+
+	/* Handle DT data if provided */
+	if (dev->of_node) {
+		charger_pdata = da9150_charger_dt_pdata(dev);
+		dev->platform_data = charger_pdata;
+	}
+
+	/* Handle any platform data */
+	if (charger_pdata) {
+		/* Does platform expect battery to have valid tbat? */
+		reg = da9150_reg_read(da9150, DA9150_PPR_CHGCTRL_F);
+		if (charger_pdata->invalid_tbat &&
+		    (reg & DA9150_TBAT_TQA_EN_MASK))
+			dev_warn(dev, "TBAT based charging expected, "
+				 "but not enabled\n");
+
+		charger->invalid_tbat = charger_pdata->invalid_tbat;
+	}
+
+	/* Acquire ADC channels */
+	chan = iio_channel_get(dev, "CHAN_IBUS");
+	charger->ibus_chan = IS_ERR(chan) ? NULL : chan;
+
+	chan = iio_channel_get(dev, "CHAN_VBUS");
+	charger->vbus_chan = IS_ERR(chan) ? NULL : chan;
+
+	chan = iio_channel_get(dev, "CHAN_TJUNC");
+	charger->tjunc_chan = IS_ERR(chan) ? NULL : chan;
+
+	chan = iio_channel_get(dev, "CHAN_VBAT");
+	charger->vbat_chan = IS_ERR(chan) ? NULL : chan;
+
+	/* Register power supplies */
+	ac = &charger->ac;
+	usb = &charger->usb;
+	battery = &charger->battery;
+
+	ac->name = "da9150-ac",
+	ac->type = POWER_SUPPLY_TYPE_MAINS;
+	ac->properties = da9150_charger_props;
+	ac->num_properties = ARRAY_SIZE(da9150_charger_props);
+	ac->get_property = da9150_charger_get_prop;
+	ret = power_supply_register(dev, ac);
+	if (ret)
+		return ret;
+
+	usb->name = "da9150-usb",
+	usb->type = POWER_SUPPLY_TYPE_USB;
+	usb->properties = da9150_charger_props;
+	usb->num_properties = ARRAY_SIZE(da9150_charger_props);
+	usb->get_property = da9150_charger_get_prop;
+	ret = power_supply_register(dev, usb);
+	if (ret)
+		goto usb_fail;
+
+	battery->name = "da9150-battery";
+	battery->type = POWER_SUPPLY_TYPE_BATTERY;
+	battery->properties = da9150_charger_bat_props;
+	battery->num_properties = ARRAY_SIZE(da9150_charger_bat_props);
+	battery->get_property = da9150_charger_battery_get_prop;
+	ret = power_supply_register(dev, battery);
+	if (ret)
+		goto battery_fail;
+
+	/* Create additional sysfs attributes */
+	for (i = 0; i < ARRAY_SIZE(da9150_charger_attrs); ++i) {
+		ret = device_create_file(dev, &da9150_charger_attrs[i].attr);
+		if (ret < 0)
+			goto sysfs_fail;
+	}
+
+	/* Get initial online supply */
+	reg = da9150_reg_read(da9150, DA9150_STATUS_H);
+
+	/* Charger plugged in or battery only */
+	switch (reg & DA9150_VBUS_STAT_MASK) {
+	case DA9150_VBUS_STAT_OFF:
+	case DA9150_VBUS_STAT_WAIT:
+		charger->supply_online = &charger->battery;
+		break;
+	case DA9150_VBUS_STAT_CHG:
+		/* Default to AC charger as we don't know yet */
+		charger->supply_online = &charger->ac;
+		break;
+	default:
+		dev_warn(dev, "Unknown VBUS state - reg = 0x%x\n", reg);
+		charger->supply_online = NULL;
+		break;
+	}
+
+	/* Setup OTG reporting & configuration */
+	charger->usb_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+	if (charger->usb_phy != NULL) {
+		INIT_WORK(&charger->otg_work, da9150_charger_otg_work);
+		charger->otg_nb.notifier_call = da9150_charger_otg_ncb;
+		usb_register_notifier(charger->usb_phy, &charger->otg_nb);
+	}
+
+	/* Register IRQs */
+	ret = da9150_register_irq(pdev, charger, da9150_charger_chg_irq,
+				  "CHG_STATUS");
+	if (ret < 0)
+		goto irq_fail;
+
+	ret = da9150_register_irq(pdev, charger, da9150_charger_tjunc_irq,
+				  "CHG_TJUNC");
+	if (ret < 0)
+		goto irq_fail;
+
+	ret = da9150_register_irq(pdev, charger, da9150_charger_vfault_irq,
+				  "CHG_VFAULT");
+	if (ret < 0)
+		goto irq_fail;
+
+#ifndef CONFIG_CHARGER_DA9150_OTG_VBUS_EVENT
+	da9150_register_irq(pdev, charger, da9150_charger_vbus_irq, "CHG_VBUS");
+	if (ret < 0)
+		goto irq_fail;
+#endif /* CONFIG_CHARGER_DA9150_OTG_VBUS_EVENT */
+
+	return ret;
+
+irq_fail:
+sysfs_fail:
+	while (--i >= 0)
+		device_remove_file(&pdev->dev, &da9150_charger_attrs[i].attr);
+
+battery_fail:
+	power_supply_unregister(usb);
+
+usb_fail:
+	power_supply_unregister(ac);
+
+	return ret;
+}
+
+static int da9150_charger_remove(struct platform_device *pdev)
+{
+	struct da9150_charger *charger = platform_get_drvdata(pdev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(da9150_charger_attrs); ++i)
+		device_remove_file(&pdev->dev, &da9150_charger_attrs[i].attr);
+
+	/* Release ADC channels */
+	if (charger->ibus_chan)
+		iio_channel_release(charger->ibus_chan);
+	if (charger->vbus_chan)
+		iio_channel_release(charger->vbus_chan);
+	if (charger->tjunc_chan)
+		iio_channel_release(charger->tjunc_chan);
+	if (charger->vbat_chan)
+		iio_channel_release(charger->vbat_chan);
+
+	power_supply_unregister(&charger->battery);
+	power_supply_unregister(&charger->usb);
+	power_supply_unregister(&charger->ac);
+
+	return 0;
+}
+
+static struct platform_driver da9150_charger_driver = {
+	.driver = {
+		.name = "da9150-charger",
+		.owner = THIS_MODULE,
+	},
+	.probe = da9150_charger_probe,
+	.remove = da9150_charger_remove,
+	.shutdown = da9150_charger_shutdown,
+};
+
+module_platform_driver(da9150_charger_driver);
+
+MODULE_DESCRIPTION("Charger Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/mfd/da9150/charger.h b/include/linux/mfd/da9150/charger.h
new file mode 100644
index 0000000..73c41b3
--- /dev/null
+++ b/include/linux/mfd/da9150/charger.h
@@ -0,0 +1,58 @@
+/*
+ * DA9150 MFD Driver - Charger Data
+ *
+ * Copyright (c) 2014 Dialog Semiconductor
+ *
+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
+ *
+ * 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.
+ */
+
+#ifndef _DA9150_CHARGER_H
+#define _DA9150_CHARGER_H
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/power_supply.h>
+#include <linux/notifier.h>
+#include <linux/usb/otg.h>
+#include <linux/timer.h>
+#include <linux/iio/consumer.h>
+
+#include <linux/mfd/da9150/core.h>
+
+
+struct da9150_charger_attr_map {
+	struct device_attribute attr;
+	u16 reg;
+	u8 shift;
+	u8 mask;
+};
+
+/* Private data */
+struct da9150_charger {
+	struct da9150 *da9150;
+	struct device *dev;
+
+	struct power_supply ac;
+	struct power_supply usb;
+	struct power_supply battery;
+	struct power_supply *supply_online;
+
+	struct usb_phy *usb_phy;
+	struct notifier_block otg_nb;
+	struct work_struct otg_work;
+	unsigned long usb_event;
+
+	struct iio_channel *ibus_chan;
+	struct iio_channel *vbus_chan;
+	struct iio_channel *tjunc_chan;
+	struct iio_channel *vbat_chan;
+
+	bool invalid_tbat;
+};
+
+#endif /* _DA9150_CHARGER_H */
--
1.9.3


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

* [PATCH 7/8] power: da9150: Add DT binding documentation for charger
  2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (5 preceding siblings ...)
  2014-06-11 11:11 ` [PATCH 6/8] power: Add support for DA9150 Charger Adam Thomson
@ 2014-06-11 11:11 ` Adam Thomson
  2014-06-11 11:11 ` [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd Adam Thomson
  7 siblings, 0 replies; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 .../devicetree/bindings/power/da9150-charger.txt   | 29 ++++++++++++++++++++++
 1 file changed, 29 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/power/da9150-charger.txt

diff --git a/Documentation/devicetree/bindings/power/da9150-charger.txt b/Documentation/devicetree/bindings/power/da9150-charger.txt
new file mode 100644
index 0000000..079931b
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/da9150-charger.txt
@@ -0,0 +1,29 @@
+Dialog Semiconductor DA9150 Charger Power Supply bindings
+
+Required properties:
+- compatible: "dlg,da9150-charger" for DA9150 Charger Power Supply
+
+Optional properties:
+- io-channels: List of phandle and IIO specifier pairs
+- io-channel-names: List of channel names used by charger
+      ["CHAN_IBUS", "CHAN_VBUS", "CHAN_TJUNC", "CHAN_VBAT"]
+  (See Documentation/devicetree/bindings/iio/iio-bindings.txt for further info)
+- dlg,invalid-tbat: bool flag to indicate no valid TBAT pin provided in system.
+
+
+Example:
+
+	da9150-charger {
+		compatible = "dlg,da9150-charger";
+
+		io-channels = <&gpadc 0>,
+			      <&gpadc 2>,
+			      <&gpadc 8>,
+			      <&gpadc 5>;
+		io-channel-names = "CHAN_IBUS",
+				   "CHAN_VBUS",
+				   "CHAN_TJUNC",
+				   "CHAN_VBAT";
+
+		dlg,invalid-tbat;
+	};
--
1.9.3

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

* [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd.
  2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (6 preceding siblings ...)
  2014-06-11 11:11 ` [PATCH 7/8] power: da9150: Add DT binding documentation for charger Adam Thomson
@ 2014-06-11 11:11 ` Adam Thomson
  2014-06-11 12:09   ` Geert Uytterhoeven
  7 siblings, 1 reply; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 11:11 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index abc3080..cf9e582 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -36,6 +36,7 @@ dallas	Maxim Integrated Products (formerly Dallas Semiconductor)
 davicom	DAVICOM Semiconductor, Inc.
 denx	Denx Software Engineering
 digi	Digi International Inc.
+dlg	Dialog Semiconductor Ltd.
 dlink	D-Link Corporation
 dmo	Data Modul AG
 ebv	EBV Elektronik
--
1.9.3

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

* Re: [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd.
  2014-06-11 11:11 ` [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd Adam Thomson
@ 2014-06-11 12:09   ` Geert Uytterhoeven
  2014-06-11 12:43     ` Rob Herring
  0 siblings, 1 reply; 29+ messages in thread
From: Geert Uytterhoeven @ 2014-06-11 12:09 UTC (permalink / raw)
  To: Adam Thomson
  Cc: Lee Jones, Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	support.opensource, Guennadi Liakhovetski

On Wed, Jun 11, 2014 at 1:11 PM, Adam Thomson
<Adam.Thomson.Opensource@diasemi.com> wrote:
> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
> @@ -36,6 +36,7 @@ dallas        Maxim Integrated Products (formerly Dallas Semiconductor)
>  davicom        DAVICOM Semiconductor, Inc.
>  denx   Denx Software Engineering
>  digi   Digi International Inc.
> +dlg    Dialog Semiconductor Ltd.

"diasemi" has been proposed before
https://groups.google.com/forum/#!msg/linux.kernel/htUxLpV_Ng0/ClJVAxgK4e4J

"dialog", "diasemi", and "dlg" all seem to be already in use...

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd.
  2014-06-11 12:09   ` Geert Uytterhoeven
@ 2014-06-11 12:43     ` Rob Herring
  2014-06-11 13:01       ` Geert Uytterhoeven
                         ` (2 more replies)
  0 siblings, 3 replies; 29+ messages in thread
From: Rob Herring @ 2014-06-11 12:43 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Adam Thomson, Lee Jones, Samuel Ortiz, Jonathan Cameron,
	linux-iio, Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	support.opensource, Guennadi Liakhovetski

On Wed, Jun 11, 2014 at 7:09 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Wed, Jun 11, 2014 at 1:11 PM, Adam Thomson
> <Adam.Thomson.Opensource@diasemi.com> wrote:
>> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
>> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
>> @@ -36,6 +36,7 @@ dallas        Maxim Integrated Products (formerly Dallas Semiconductor)
>>  davicom        DAVICOM Semiconductor, Inc.
>>  denx   Denx Software Engineering
>>  digi   Digi International Inc.
>> +dlg    Dialog Semiconductor Ltd.
>
> "diasemi" has been proposed before
> https://groups.google.com/forum/#!msg/linux.kernel/htUxLpV_Ng0/ClJVAxgK4e4J
>
> "dialog", "diasemi", and "dlg" all seem to be already in use...

dlg is the correct one and seems to be the most widely used, so we
should go with that and mark the others deprecated.

diasemi is documented for the da9210, but not used anywhere.

There appears to be 2 different da9053 bindings. I'd guess the dialog
variant used on 2 i.MX boards is not used. Other i.MX boards use the
dlg version. I'm not sure what is going on with da9055. Please sort
these out.

Rob

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

* Re: [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd.
  2014-06-11 12:43     ` Rob Herring
@ 2014-06-11 13:01       ` Geert Uytterhoeven
  2014-06-11 13:17       ` Opensource [Adam Thomson]
  2014-06-11 13:31       ` Adam Thomson
  2 siblings, 0 replies; 29+ messages in thread
From: Geert Uytterhoeven @ 2014-06-11 13:01 UTC (permalink / raw)
  To: Rob Herring
  Cc: Adam Thomson, Lee Jones, Samuel Ortiz, Jonathan Cameron,
	linux-iio, Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring,
	Pawel Moll, Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	support.opensource, Guennadi Liakhovetski, Benoit Cousson,
	Simon Horman, Linux-sh list

On Wed, Jun 11, 2014 at 2:43 PM, Rob Herring <robherring2@gmail.com> wrote:
> On Wed, Jun 11, 2014 at 7:09 AM, Geert Uytterhoeven
> <geert@linux-m68k.org> wrote:
>> On Wed, Jun 11, 2014 at 1:11 PM, Adam Thomson
>> <Adam.Thomson.Opensource@diasemi.com> wrote:
>>> --- a/Documentation/devicetree/bindings/vendor-prefixes.txt
>>> +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
>>> @@ -36,6 +36,7 @@ dallas        Maxim Integrated Products (formerly Dallas Semiconductor)
>>>  davicom        DAVICOM Semiconductor, Inc.
>>>  denx   Denx Software Engineering
>>>  digi   Digi International Inc.
>>> +dlg    Dialog Semiconductor Ltd.
>>
>> "diasemi" has been proposed before
>> https://groups.google.com/forum/#!msg/linux.kernel/htUxLpV_Ng0/ClJVAxgK4e4J
>>
>> "dialog", "diasemi", and "dlg" all seem to be already in use...
>
> dlg is the correct one and seems to be the most widely used, so we
> should go with that and mark the others deprecated.
>
> diasemi is documented for the da9210, but not used anywhere.

It users are queued in Simon's tree, for two Renesas boards.

> There appears to be 2 different da9053 bindings. I'd guess the dialog
> variant used on 2 i.MX boards is not used. Other i.MX boards use the
> dlg version. I'm not sure what is going on with da9055. Please sort
> these out.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* RE: [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd.
  2014-06-11 12:43     ` Rob Herring
  2014-06-11 13:01       ` Geert Uytterhoeven
@ 2014-06-11 13:17       ` Opensource [Adam Thomson]
  2014-06-11 14:22         ` Rob Herring
  2014-06-11 13:31       ` Adam Thomson
  2 siblings, 1 reply; 29+ messages in thread
From: Opensource [Adam Thomson] @ 2014-06-11 13:17 UTC (permalink / raw)
  To: Rob Herring, Geert Uytterhoeven
  Cc: Opensource [Adam Thomson], Lee Jones, Samuel Ortiz,
	Jonathan Cameron, linux-iio@vger.kernel.org,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Support Opensource, Guennadi Liakhovetski

PiBPbiBXZWQsIEp1biAxMSwgMjAxNCBhdCAxMzo0MywgUm9iIEhlcnJpbmcgd3JvdGU6DQo+IA0K
PiBkbGcgaXMgdGhlIGNvcnJlY3Qgb25lIGFuZCBzZWVtcyB0byBiZSB0aGUgbW9zdCB3aWRlbHkg
dXNlZCwgc28gd2UNCj4gc2hvdWxkIGdvIHdpdGggdGhhdCBhbmQgbWFyayB0aGUgb3RoZXJzIGRl
cHJlY2F0ZWQuDQo+IA0KPiBkaWFzZW1pIGlzIGRvY3VtZW50ZWQgZm9yIHRoZSBkYTkyMTAsIGJ1
dCBub3QgdXNlZCBhbnl3aGVyZS4NCj4gDQo+IFRoZXJlIGFwcGVhcnMgdG8gYmUgMiBkaWZmZXJl
bnQgZGE5MDUzIGJpbmRpbmdzLiBJJ2QgZ3Vlc3MgdGhlIGRpYWxvZw0KPiB2YXJpYW50IHVzZWQg
b24gMiBpLk1YIGJvYXJkcyBpcyBub3QgdXNlZC4gT3RoZXIgaS5NWCBib2FyZHMgdXNlIHRoZQ0K
PiBkbGcgdmVyc2lvbi4gSSdtIG5vdCBzdXJlIHdoYXQgaXMgZ29pbmcgb24gd2l0aCBkYTkwNTUu
IFBsZWFzZSBzb3J0DQo+IHRoZXNlIG91dC4NCj4gDQoNClRoZSBpbnRlbnRpb24gaXMgdG8gdXBk
YXRlIHRoZSBvdGhlciBEaWFsb2cgZHJpdmVycyBhZnRlciB3ZSd2ZSBhZ3JlZWQgdGhpcw0KcHJl
Zml4LiBXaXRoIHJlZ2FyZHMgdG8gZGE5MDU1LCB3aGF0J3MgdGhlIGlzc3VlIGhlcmUgYXMgSSBi
ZWxpZXZlIHRoYXQgdXNlcw0KdGhlICdkbGcnIHByZWZpeCBhbHJlYWR5Pw0K

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

* RE: [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd.
  2014-06-11 12:43     ` Rob Herring
  2014-06-11 13:01       ` Geert Uytterhoeven
  2014-06-11 13:17       ` Opensource [Adam Thomson]
@ 2014-06-11 13:31       ` Adam Thomson
  2 siblings, 0 replies; 29+ messages in thread
From: Adam Thomson @ 2014-06-11 13:31 UTC (permalink / raw)
  To: Opensource [Adam Thomson], Rob Herring, Geert Uytterhoeven
  Cc: Lee Jones, Samuel Ortiz, Jonathan Cameron,
	linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, Support Opensource,
	Guennadi Liakhovetski

T24gV2VkLCBKdW4gMTEsIDIwMTQgYXQgMTQ6MTcsIEFkYW0gVGhvbXNvbiB3cm90ZToNCg0KPiBU
aGUgaW50ZW50aW9uIGlzIHRvIHVwZGF0ZSB0aGUgb3RoZXIgRGlhbG9nIGRyaXZlcnMgYWZ0ZXIg
d2UndmUgYWdyZWVkIHRoaXMNCj4gcHJlZml4LiBXaXRoIHJlZ2FyZHMgdG8gZGE5MDU1LCB3aGF0
J3MgdGhlIGlzc3VlIGhlcmUgYXMgSSBiZWxpZXZlIHRoYXQgdXNlcw0KPiB0aGUgJ2RsZycgcHJl
Zml4IGFscmVhZHk/DQoNCk5ldmVyIG1pbmQgYWJvdXQgbXkgREE5MDU1IHF1ZXN0aW9uLiBKdXN0
IHNwb3R0ZWQgd2hhdCB5b3UgbWVhbnQuIFdpbGwNCm1ha2Ugc3VyZSB0aGlzIGlzIHNvcnRlZC4N
CkxlZ2FsIERpc2NsYWltZXI6IFRoaXMgZS1tYWlsIGNvbW11bmljYXRpb24gKGFuZCBhbnkgYXR0
YWNobWVudC9zKSBpcyBjb25maWRlbnRpYWwgYW5kIGNvbnRhaW5zIHByb3ByaWV0YXJ5IGluZm9y
bWF0aW9uLCBzb21lIG9yIGFsbCBvZiB3aGljaCBtYXkgYmUgbGVnYWxseSBwcml2aWxlZ2VkLiBJ
dCBpcyBpbnRlbmRlZCBzb2xlbHkgZm9yIHRoZSB1c2Ugb2YgdGhlIGluZGl2aWR1YWwgb3IgZW50
aXR5IHRvIHdoaWNoIGl0IGlzIGFkZHJlc3NlZC4gQWNjZXNzIHRvIHRoaXMgZW1haWwgYnkgYW55
b25lIGVsc2UgaXMgdW5hdXRob3JpemVkLiBJZiB5b3UgYXJlIG5vdCB0aGUgaW50ZW5kZWQgcmVj
aXBpZW50LCBhbnkgZGlzY2xvc3VyZSwgY29weWluZywgZGlzdHJpYnV0aW9uIG9yIGFueSBhY3Rp
b24gdGFrZW4gb3Igb21pdHRlZCB0byBiZSB0YWtlbiBpbiByZWxpYW5jZSBvbiBpdCwgaXMgcHJv
aGliaXRlZCBhbmQgbWF5IGJlIHVubGF3ZnVsLg0KDQpQbGVhc2UgY29uc2lkZXIgdGhlIGVudmly
b25tZW50IGJlZm9yZSBwcmludGluZyB0aGlzIGUtbWFpbA0KDQoNCg==

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

* Re: [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd.
  2014-06-11 13:17       ` Opensource [Adam Thomson]
@ 2014-06-11 14:22         ` Rob Herring
  0 siblings, 0 replies; 29+ messages in thread
From: Rob Herring @ 2014-06-11 14:22 UTC (permalink / raw)
  To: Opensource [Adam Thomson]
  Cc: Geert Uytterhoeven, Lee Jones, Samuel Ortiz, Jonathan Cameron,
	linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, Support Opensource,
	Guennadi Liakhovetski

On Wed, Jun 11, 2014 at 8:17 AM, Opensource [Adam Thomson]
<Adam.Thomson.Opensource@diasemi.com> wrote:
>> On Wed, Jun 11, 2014 at 13:43, Rob Herring wrote:
>>
>> dlg is the correct one and seems to be the most widely used, so we
>> should go with that and mark the others deprecated.
>>
>> diasemi is documented for the da9210, but not used anywhere.
>>
>> There appears to be 2 different da9053 bindings. I'd guess the dialog
>> variant used on 2 i.MX boards is not used. Other i.MX boards use the
>> dlg version. I'm not sure what is going on with da9055. Please sort
>> these out.
>>
>
> The intention is to update the other Dialog drivers after we've agreed this
> prefix. With regards to da9055, what's the issue here as I believe that uses
> the 'dlg' prefix already?

In documentation it does, but I'm not sure how these strings are used:

drivers/mfd/da9055-core.c:              .of_compatible = "dialog,da9055-gpio",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-regulator",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-regulator",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-regulator",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-regulator",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-regulator",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-regulator",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-regulator",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-regulator",
drivers/mfd/da9055-core.c:              .of_compatible = "dialog,da9055-onkey",
drivers/mfd/da9055-core.c:              .of_compatible = "dialog,da9055-rtc",
drivers/mfd/da9055-core.c:              .of_compatible = "dialog,da9055-hwmon",
drivers/mfd/da9055-core.c:              .of_compatible =
"dialog,da9055-watchdog",

Rob

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

* Re: [PATCH 4/8] iio: Add support for DA9150 GPADC
  2014-06-11 11:11 ` [PATCH 4/8] iio: Add support for DA9150 GPADC Adam Thomson
@ 2014-06-11 16:34   ` Jonathan Cameron
  2014-06-11 16:56     ` Opensource [Adam Thomson]
  2014-06-15 20:19   ` Jonathan Cameron
  1 sibling, 1 reply; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-11 16:34 UTC (permalink / raw)
  To: Adam Thomson, Lee Jones, Samuel Ortiz, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource



On June 11, 2014 12:11:28 PM GMT+01:00, Adam Thomson <Adam.Thomson.Opensource@diasemi.com> wrote:
>This patch adds support for DA9150 Charger & Fuel-Gauge IC GPADC.
>
>Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Hi Adam. Silly question but what are the _ channels?

I have put in a perhaps optimistic data sheet request via the website, throwing in your name. Hope you don't mind!

Jonathan
>---
> drivers/iio/adc/Kconfig          |   9 +
> drivers/iio/adc/Makefile         |   1 +
>drivers/iio/adc/da9150-gpadc.c   | 396
>+++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/da9150/gpadc.h |  71 +++++++
> 4 files changed, 477 insertions(+)
> create mode 100644 drivers/iio/adc/da9150-gpadc.c
> create mode 100644 include/linux/mfd/da9150/gpadc.h
>
>diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
>index 24c28e3..f5e9f72 100644
>--- a/drivers/iio/adc/Kconfig
>+++ b/drivers/iio/adc/Kconfig
>@@ -105,6 +105,15 @@ config AT91_ADC
> 	help
> 	  Say yes here to build support for Atmel AT91 ADC.
>
>+config DA9150_GPADC
>+	tristate "Dialog DA9150 GPADC driver support"
>+	depends on MFD_DA9150
>+	help
>+	  Say yes here to build support for Dialog DA9150 GPADC.
>+
>+	  This driver can also be built as a module. If chosen, the module
>name
>+	  will be da9150-gpadc.
>+
> config EXYNOS_ADC
> 	tristate "Exynos ADC driver support"
> 	depends on OF
>diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
>index ab346d8..414b22f 100644
>--- a/drivers/iio/adc/Makefile
>+++ b/drivers/iio/adc/Makefile
>@@ -12,6 +12,7 @@ obj-$(CONFIG_AD7791) += ad7791.o
> obj-$(CONFIG_AD7793) += ad7793.o
> obj-$(CONFIG_AD7887) += ad7887.o
> obj-$(CONFIG_AT91_ADC) += at91_adc.o
>+obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
> obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
> obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
> obj-$(CONFIG_MAX1363) += max1363.o
>diff --git a/drivers/iio/adc/da9150-gpadc.c
>b/drivers/iio/adc/da9150-gpadc.c
>new file mode 100644
>index 0000000..2107f86
>--- /dev/null
>+++ b/drivers/iio/adc/da9150-gpadc.c
>@@ -0,0 +1,396 @@
>+/*
>+ * DA9150 GPADC Driver
>+ *
>+ * Copyright (c) 2014 Dialog Semiconductor
>+ *
>+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
>+ *
>+ * 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.
>+ */
>+
>+#include <linux/kernel.h>
>+#include <linux/slab.h>
>+#include <linux/module.h>
>+#include <linux/platform_device.h>
>+#include <linux/interrupt.h>
>+
>+#include <linux/mfd/da9150/core.h>
>+#include <linux/mfd/da9150/pdata.h>
>+#include <linux/mfd/da9150/registers.h>
>+#include <linux/mfd/da9150/gpadc.h>
>+
>+#include <linux/iio/iio.h>
>+#include <linux/iio/machine.h>
>+#include <linux/iio/driver.h>
>+
>+
>+/*
>+ * IRQ Handling
>+ */
>+
>+static irqreturn_t da9150_gpadc_irq(int irq, void *data)
>+{
>+
>+	struct da9150_gpadc *gpadc = data;
>+
>+	complete(&gpadc->complete);
>+
>+	return IRQ_HANDLED;
>+}
>+
>+
>+/*
>+ * GPADC access
>+ */
>+
>+static inline int da9150_gpadc_gpio_2v_voltage_now(int raw_val)
>+{
>+	/* Convert to uV */
>+	return (((3 * ((raw_val * 1000) + 500)) / 2048) * 1000);
>+}
>+
>+static inline int da9150_gpadc_gpio_5v_voltage_now(int raw_val)
>+{
>+	/* Convert to uV */
>+	return (((6 * ((raw_val * 1000) + 500)) / 1024) * 1000);
>+}
>+
>+static inline int da9150_gpadc_ibus_current_avg(int raw_val)
>+{
>+	/* Convert to uA */
>+	return (((4 * ((raw_val * 1000) + 500)) / 2048) * 1000);
>+}
>+
>+static inline int da9150_gpadc_vbus_6v_voltage_now(int raw_val)
>+{
>+	/* Convert to uV */
>+	return (((3 * ((raw_val * 1000) + 500)) / 512) * 1000);
>+}
>+
>+static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
>+{
>+	/* Convert to uV */
>+	return (((21 * ((raw_val * 1000) + 500)) / 1024) * 1000);
>+}
>+
>+static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
>+{
>+	/* Convert to uV */
>+	return (((3 * ((raw_val * 1000) + 500)) / 512) * 1000);
>+}
>+
>+static inline int da9150_gpadc_vsys_1_5v_voltage_now(int raw_val)
>+{
>+	/* Convert to uV */
>+	return (((3 * ((raw_val * 1000) + 500)) / 2048) * 1000);
>+}
>+
>+static inline int da9150_gpadc_tjunc_temp(int raw_val)
>+{
>+	/* Convert to 0.1 degrees C */
>+	return (((879 - (1023 - raw_val)) * 10000) / 4420);
>+}
>+
>+static inline int da9150_gpadc_vbat_voltage_now(int raw_val)
>+{
>+	/* Convert to uV */
>+	return ((2932 * raw_val) + 1500000);
>+}
>+
>+int da9150_gpadc_read_process(int channel, int raw_val)
>+{
>+	int ret;
>+
>+	switch (channel) {
>+	case DA9150_GPADC_CHAN_GPIOA_2V:
>+	case DA9150_GPADC_CHAN_GPIOA_2V_:
>+	case DA9150_GPADC_CHAN_GPIOB_2V:
>+	case DA9150_GPADC_CHAN_GPIOB_2V_:
>+	case DA9150_GPADC_CHAN_GPIOC_2V:
>+	case DA9150_GPADC_CHAN_GPIOC_2V_:
>+	case DA9150_GPADC_CHAN_GPIOD_2V:
>+	case DA9150_GPADC_CHAN_GPIOD_2V_:
>+		ret = da9150_gpadc_gpio_2v_voltage_now(raw_val);
>+		break;
>+	case DA9150_GPADC_CHAN_IBUS_SENSE:
>+	case DA9150_GPADC_CHAN_IBUS_SENSE_:
>+		ret = da9150_gpadc_ibus_current_avg(raw_val);
>+		break;
>+	case DA9150_GPADC_CHAN_VBUS_DIV:
>+		ret = da9150_gpadc_vbus_6v_voltage_now(raw_val);
>+		break;
>+	case DA9150_GPADC_CHAN_VBUS_DIV_:
>+		ret = da9150_gpadc_vbus_21v_voltage_now(raw_val);
>+		break;
>+	case DA9150_GPADC_CHAN_VSYS:
>+		ret = da9150_gpadc_vsys_6v_voltage_now(raw_val);
>+		break;
>+	case DA9150_GPADC_CHAN_VSYS_:
>+		ret = da9150_gpadc_vsys_1_5v_voltage_now(raw_val);
>+		break;
>+	case DA9150_GPADC_CHAN_GPIOA_5V:
>+	case DA9150_GPADC_CHAN_GPIOA_5V_:
>+	case DA9150_GPADC_CHAN_GPIOB_5V:
>+	case DA9150_GPADC_CHAN_GPIOB_5V_:
>+	case DA9150_GPADC_CHAN_GPIOC_5V:
>+	case DA9150_GPADC_CHAN_GPIOC_5V_:
>+	case DA9150_GPADC_CHAN_GPIOD_5V:
>+	case DA9150_GPADC_CHAN_GPIOD_5V_:
>+		ret = da9150_gpadc_gpio_5v_voltage_now(raw_val);
>+		break;
>+	case DA9150_GPADC_CHAN_TJUNC_CORE:
>+	case DA9150_GPADC_CHAN_TJUNC_CORE_:
>+	case DA9150_GPADC_CHAN_TJUNC_OVP:
>+	case DA9150_GPADC_CHAN_TJUNC_OVP_:
>+		ret = da9150_gpadc_tjunc_temp(raw_val);
>+		break;
>+	case DA9150_GPADC_CHAN_VBAT:
>+		ret = da9150_gpadc_vbat_voltage_now(raw_val);
>+		break;
>+	default:
>+		/* No processing for other channels so return raw value */
>+		ret = raw_val;
>+		break;
>+	}
>+
>+	return ret;
>+}
>+
>+int da9150_gpadc_read_raw(struct iio_dev *indio_dev,
>+			  struct iio_chan_spec const *chan,
>+			  int *val, int *val2, long mask)
>+{
>+	struct da9150_gpadc *gpadc = iio_priv(indio_dev);
>+	u8 reg = 0;
>+	u8 result_regs[2];
>+	u16 result;
>+
>+	if ((mask != IIO_CHAN_INFO_RAW) && (mask != IIO_CHAN_INFO_PROCESSED))
>+		return -EINVAL;
>+
>+	if ((chan->channel < DA9150_GPADC_CHAN_GPIOA_2V) ||
>+	    (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP_))
>+		return -EINVAL;
>+
>+	mutex_lock(&gpadc->lock);
>+
>+	/* Set channel & enable measurement */
>+	reg |= DA9150_GPADC_EN_MASK;
>+	reg |= chan->channel << DA9150_GPADC_MUX_SHIFT;
>+	da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN, reg);
>+
>+	/* Consume left-over completion from a previous timeout */
>+	try_wait_for_completion(&gpadc->complete);
>+
>+	/* Check for actual completion */
>+	wait_for_completion_timeout(&gpadc->complete, msecs_to_jiffies(5));
>+
>+	/* Read result and status from device */
>+	da9150_bulk_read(gpadc->da9150, DA9150_GPADC_RES_A, 2, result_regs);
>+
>+	/* Check to make sure device really has completed reading */
>+	if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
>+		mutex_unlock(&gpadc->lock);
>+		dev_err(gpadc->dev, "Timeout on channel %d of GP-ADC\n",
>+			chan->channel);
>+		return -ETIMEDOUT;
>+	}
>+
>+	mutex_unlock(&gpadc->lock);
>+
>+	/* LSBs - 2 bits */
>+	result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
>+		 DA9150_GPADC_RES_L_SHIFT;
>+	/* MSBs - 8 bits */
>+	result |= result_regs[0] << 2;
>+
>+	switch (mask) {
>+	case IIO_CHAN_INFO_PROCESSED:
>+		*val = da9150_gpadc_read_process(chan->channel, result);
>+		break;
>+	case IIO_CHAN_INFO_RAW:
>+		*val = result;
>+		break;
>+	}
>+
>+	return IIO_VAL_INT;
>+}
>+
>+
>+static const struct iio_info da9150_gpadc_info = {
>+	.read_raw = &da9150_gpadc_read_raw,
>+	.driver_module = THIS_MODULE,
>+};
>+
>+#define GPADC_CHANNEL(_id, _type, chan_info, _ext_name) {		\
>+	.type = _type,							\
>+	.indexed = 1,							\
>+	.channel = DA9150_GPADC_CHAN_##_id,				\
>+	.info_mask_separate = chan_info,				\
>+	.extend_name = _ext_name,					\
>+	.datasheet_name = #_id,						\
>+}
>+
>+#define GPADC_CHANNEL_RAW(_id, _type, _ext_name)	\
>+	GPADC_CHANNEL(_id, _type, BIT(IIO_CHAN_INFO_RAW), _ext_name)
>+
>+#define GPADC_CHANNEL_RAW_PROCESSED(_id, _type, _ext_name)			\
>+	GPADC_CHANNEL(_id, _type,						\
>+		      BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),	\
>+		      _ext_name)
>+
>+/* Supported channels */
>+static const struct iio_chan_spec da9150_gpadc_channels[] = {
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_2V, IIO_VOLTAGE, "GPIOA_2V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_2V_, IIO_VOLTAGE, "GPIOA_2V_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_2V, IIO_VOLTAGE, "GPIOB_2V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_2V_, IIO_VOLTAGE, "GPIOB_2V_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_2V, IIO_VOLTAGE, "GPIOC_2V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_2V_, IIO_VOLTAGE, "GPIOC_2V_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_2V, IIO_VOLTAGE, "GPIOD_2V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_2V_, IIO_VOLTAGE, "GPIOD_2V_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(IBUS_SENSE, IIO_CURRENT, "IBUS"),
>+	GPADC_CHANNEL_RAW_PROCESSED(IBUS_SENSE_, IIO_CURRENT, "IBUS_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(VBUS_DIV, IIO_VOLTAGE, "VBUS_6V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(VBUS_DIV_, IIO_VOLTAGE, "VBUS_21V"),
>+	GPADC_CHANNEL_RAW(ID, IIO_VOLTAGE, "ID"),
>+	GPADC_CHANNEL_RAW(ID_, IIO_VOLTAGE, "ID_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(VSYS, IIO_VOLTAGE, "VSYS_6V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(VSYS_, IIO_VOLTAGE, "VSYS_1_5V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_5V, IIO_VOLTAGE, "GPIOA_5V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_5V_, IIO_VOLTAGE, "GPIOA_5V_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_5V, IIO_VOLTAGE, "GPIOB_5V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_5V_, IIO_VOLTAGE, "GPIOB_5V_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_5V, IIO_VOLTAGE, "GPIOC_5V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_5V_, IIO_VOLTAGE, "GPIOC_5V_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_5V, IIO_VOLTAGE, "GPIOD_5V"),
>+	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_5V_, IIO_VOLTAGE, "GPIOD_5V_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(VBAT, IIO_VOLTAGE, "VBAT"),
>+	GPADC_CHANNEL_RAW_PROCESSED(VBAT_, IIO_VOLTAGE, "VBAT_"),
>+	GPADC_CHANNEL_RAW(TBAT, IIO_VOLTAGE, "TBAT"),
>+	GPADC_CHANNEL_RAW(TBAT_, IIO_VOLTAGE, "TBAT_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_CORE, IIO_TEMP, "TJUNC_CORE"),
>+	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_CORE_, IIO_TEMP, "TJUNC_CORE_"),
>+	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_OVP, IIO_TEMP, "TJUNC_OVP"),
>+	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_OVP_, IIO_TEMP, "TJUNC_OVP_"),
>+};
>+
>+/* Default maps used by da9150-charger */
>+static struct iio_map da9150_gpadc_default_maps[] = {
>+	{
>+		.consumer_dev_name = "da9150-charger",
>+		.consumer_channel = "CHAN_IBUS",
>+		.adc_channel_label = "IBUS_SENSE",
>+	},
>+	{
>+		.consumer_dev_name = "da9150-charger",
>+		.consumer_channel = "CHAN_VBUS",
>+		.adc_channel_label = "VBUS_DIV_",
>+	},
>+	{
>+		.consumer_dev_name = "da9150-charger",
>+		.consumer_channel = "CHAN_TJUNC",
>+		.adc_channel_label = "TJUNC_CORE",
>+	},
>+	{
>+		.consumer_dev_name = "da9150-charger",
>+		.consumer_channel = "CHAN_VBAT",
>+		.adc_channel_label = "VBAT",
>+	},
>+	{},
>+};
>+
>+
>+/*
>+ * Driver top level functions
>+ */
>+
>+static int da9150_gpadc_probe(struct platform_device *pdev)
>+{
>+	struct device *dev = &pdev->dev;
>+	struct da9150 *da9150 = dev_get_drvdata(dev->parent);
>+	struct da9150_gpadc *gpadc;
>+	struct iio_dev *indio_dev;
>+
>+	int ret;
>+
>+	indio_dev = devm_iio_device_alloc(&pdev->dev,
>+					  sizeof(struct da9150_gpadc));
>+	if (!indio_dev) {
>+		dev_err(&pdev->dev, "Failed to allocate IIO device\n");
>+		return -ENOMEM;
>+	}
>+	gpadc = iio_priv(indio_dev);
>+
>+	platform_set_drvdata(pdev, indio_dev);
>+	gpadc->da9150 = da9150;
>+	gpadc->dev = dev;
>+
>+	ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
>+	if (ret) {
>+		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
>+		goto iio_map_fail;
>+	}
>+
>+	indio_dev->name = dev_name(dev);
>+	indio_dev->dev.parent = dev;
>+	indio_dev->dev.of_node = pdev->dev.of_node;
>+	indio_dev->info = &da9150_gpadc_info;
>+	indio_dev->modes = INDIO_DIRECT_MODE;
>+	indio_dev->channels = da9150_gpadc_channels;
>+	indio_dev->num_channels = ARRAY_SIZE(da9150_gpadc_channels);
>+
>+	ret = iio_device_register(indio_dev);
>+	if (ret) {
>+		dev_err(dev, "Failed to register IIO device: %d\n", ret);
>+		goto iio_dev_fail;
>+	}
>+
>+	mutex_init(&gpadc->lock);
>+	init_completion(&gpadc->complete);
>+
>+	/* Register IRQ */
>+	ret = da9150_register_irq(pdev, gpadc, da9150_gpadc_irq, "GPADC");
>+	if (ret < 0)
>+		goto irq_fail;
>+
>+	da9150->gpadc_ready = true;
>+	return ret;
>+
>+irq_fail:
>+	iio_device_unregister(indio_dev);
>+
>+iio_dev_fail:
>+	iio_map_array_unregister(indio_dev);
>+
>+iio_map_fail:
>+	return ret;
>+}
>+
>+static int da9150_gpadc_remove(struct platform_device *pdev)
>+{
>+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>+
>+	iio_map_array_unregister(indio_dev);
>+	iio_device_unregister(indio_dev);
>+
>+	return 0;
>+}
>+
>+static struct platform_driver da9150_gpadc_driver = {
>+	.driver = {
>+		.name = "da9150-gpadc",
>+		.owner = THIS_MODULE,
>+	},
>+	.probe = da9150_gpadc_probe,
>+	.remove = da9150_gpadc_remove,
>+};
>+
>+module_platform_driver(da9150_gpadc_driver);
>+
>+MODULE_DESCRIPTION("GPADC Driver for DA9150");
>+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com");
>+MODULE_LICENSE("GPL");
>diff --git a/include/linux/mfd/da9150/gpadc.h
>b/include/linux/mfd/da9150/gpadc.h
>new file mode 100644
>index 0000000..3e46164
>--- /dev/null
>+++ b/include/linux/mfd/da9150/gpadc.h
>@@ -0,0 +1,71 @@
>+/*
>+ * DA9150 GPADC Driver - GPADC Data
>+ *
>+ * Copyright (c) 2014 Dialog Semiconductor
>+ *
>+ * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
>+ *
>+ * 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.
>+ */
>+
>+#ifndef _DA9150_GPADC_H
>+#define _DA9150_GPADC_H
>+
>+#include <linux/device.h>
>+#include <linux/iio/machine.h>
>+#include <linux/mutex.h>
>+#include <linux/completion.h>
>+
>+#include <linux/mfd/da9150/core.h>
>+
>+
>+/* Channels */
>+enum da9150_gpadc_channel {
>+	DA9150_GPADC_CHAN_GPIOA_2V = 0,
>+	DA9150_GPADC_CHAN_GPIOA_2V_,
>+	DA9150_GPADC_CHAN_GPIOB_2V,
>+	DA9150_GPADC_CHAN_GPIOB_2V_,
>+	DA9150_GPADC_CHAN_GPIOC_2V,
>+	DA9150_GPADC_CHAN_GPIOC_2V_,
>+	DA9150_GPADC_CHAN_GPIOD_2V,
>+	DA9150_GPADC_CHAN_GPIOD_2V_,
>+	DA9150_GPADC_CHAN_IBUS_SENSE,
>+	DA9150_GPADC_CHAN_IBUS_SENSE_,
>+	DA9150_GPADC_CHAN_VBUS_DIV,
>+	DA9150_GPADC_CHAN_VBUS_DIV_,
>+	DA9150_GPADC_CHAN_ID,
>+	DA9150_GPADC_CHAN_ID_,
>+	DA9150_GPADC_CHAN_VSYS,
>+	DA9150_GPADC_CHAN_VSYS_,
>+	DA9150_GPADC_CHAN_GPIOA_5V,
>+	DA9150_GPADC_CHAN_GPIOA_5V_,
>+	DA9150_GPADC_CHAN_GPIOB_5V,
>+	DA9150_GPADC_CHAN_GPIOB_5V_,
>+	DA9150_GPADC_CHAN_GPIOC_5V,
>+	DA9150_GPADC_CHAN_GPIOC_5V_,
>+	DA9150_GPADC_CHAN_GPIOD_5V,
>+	DA9150_GPADC_CHAN_GPIOD_5V_,
>+	DA9150_GPADC_CHAN_VBAT,
>+	DA9150_GPADC_CHAN_VBAT_,
>+	DA9150_GPADC_CHAN_TBAT,
>+	DA9150_GPADC_CHAN_TBAT_,
>+	DA9150_GPADC_CHAN_TJUNC_CORE,
>+	DA9150_GPADC_CHAN_TJUNC_CORE_,
>+	DA9150_GPADC_CHAN_TJUNC_OVP,
>+	DA9150_GPADC_CHAN_TJUNC_OVP_,
>+};
>+
>+
>+/* Private data */
>+struct da9150_gpadc {
>+	struct da9150 *da9150;
>+	struct device *dev;
>+
>+	struct mutex lock;
>+	struct completion complete;
>+};
>+
>+#endif /* _DA9150_GPADC_H */
>--
>1.9.3
>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>the body of a message to majordomo@vger.kernel.org
>More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Sent from my Android phone with K-9 Mail. Please excuse my brevity.

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

* RE: [PATCH 4/8] iio: Add support for DA9150 GPADC
  2014-06-11 16:34   ` Jonathan Cameron
@ 2014-06-11 16:56     ` Opensource [Adam Thomson]
  2014-06-15 19:55       ` Jonathan Cameron
  0 siblings, 1 reply; 29+ messages in thread
From: Opensource [Adam Thomson] @ 2014-06-11 16:56 UTC (permalink / raw)
  To: Jonathan Cameron, Opensource [Adam Thomson], Lee Jones,
	Samuel Ortiz, linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org
  Cc: linux-kernel@vger.kernel.org, Support Opensource

T24gSnVuZSAxMSwgMjAxNCAxNzozNSwgSm9uYXRob24gQ2FtZXJvbiB3cm90ZToNCg0KPiBIaSBB
ZGFtLiBTaWxseSBxdWVzdGlvbiBidXQgd2hhdCBhcmUgdGhlIF8gY2hhbm5lbHM/DQo+IA0KPiBJ
IGhhdmUgcHV0IGluIGEgcGVyaGFwcyBvcHRpbWlzdGljIGRhdGEgc2hlZXQgcmVxdWVzdCB2aWEg
dGhlIHdlYnNpdGUsIHRocm93aW5nIGluDQo+IHlvdXIgbmFtZS4gSG9wZSB5b3UgZG9uJ3QgbWlu
ZCENCj4gDQo+IEpvbmF0aGFuDQoNCkhpIEpvbmF0aG9uLiBTb21lIG9mIHRoZSBfY2hhbm5lbHMg
YXJlIGEgZGlmZmVyZW50IHJlcHJlc2VudGF0aW9uIG9mIHRoZSByZWFkaW5nDQooZS5nLiBkaWZm
ZXJlbnQgc2NhbGUgLSBvbmUgd291bGQgYmUgMC02ViByYW5nZSwgYW5kIG9uZSB3b3VsZCBiZSAw
LTIxViBmb3INCmV4YW1wbGUpLiBPdGhlcnMgcHJvdmlkZSBpZGVudGljYWwgcmVhZGluZ3MgdG8g
dGhlIG5vbiBfY2hhbm5lbCBidXQgaGF2ZSBsZWZ0DQp0aG9zZSBpbiB0byBrZWVwIHRoZSBjaGFu
bmVsIG51bWJlcmluZyBzYW5lIGFuZCBlYXN5IHRvIHJlZmVyZW5jZS4NCg0KTm8gcHJvYmxlbSBy
ZWdhcmRpbmcgdGhlIHJlcXVlc3QuDQo=

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

* Re: [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2014-06-11 11:11 ` [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
@ 2014-06-15 19:49   ` Jonathan Cameron
  2014-06-16 13:12     ` Opensource [Adam Thomson]
  0 siblings, 1 reply; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-15 19:49 UTC (permalink / raw)
  To: Adam Thomson, Lee Jones, Samuel Ortiz, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

On 11/06/14 12:11, Adam Thomson wrote:
> DA9150 is a combined Charger and Fuel-Gauge IC, with additional
> GPIO and GPADC functionality.
>
> This patch adds core support for the device.
>
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Hi Adam,

Some general comments inline.

It's been a while since I've looked at any particularly similar parts,
but it seems to me that a lot of indirection gets added here that
if anything makes the codes slightly harder to follow...

Feel free to disagree with me though!
> ---
>   drivers/mfd/Kconfig                  |   12 +
>   drivers/mfd/Makefile                 |    2 +
>   drivers/mfd/da9150-core.c            |  398 ++++++++++++
>   drivers/mfd/da9150-i2c.c             |  268 ++++++++
>   include/linux/mfd/da9150/core.h      |  125 ++++
>   include/linux/mfd/da9150/pdata.h     |  148 +++++
>   include/linux/mfd/da9150/registers.h | 1160 ++++++++++++++++++++++++++++++++++
>   7 files changed, 2113 insertions(+)
>   create mode 100644 drivers/mfd/da9150-core.c
>   create mode 100644 drivers/mfd/da9150-i2c.c
>   create mode 100644 include/linux/mfd/da9150/core.h
>   create mode 100644 include/linux/mfd/da9150/pdata.h
>   create mode 100644 include/linux/mfd/da9150/registers.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 3383412..4af7cc4 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -171,6 +171,18 @@ config MFD_DA9063
>   	  Additional drivers must be enabled in order to use the functionality
>   	  of the device.
>
> +config MFD_DA9150
> +	bool "Dialog Semiconductor DA9150 Charger Fuel-Gauge chip"
> +	depends on I2C=y
> +	select MFD_CORE
> +	select REGMAP_I2C
> +	select REGMAP_IRQ
> +	help
> +	  This adds support for the DA9150 integrated charger and fuel-gauge
> +	  chip. This driver provides common support for accessing the device.
> +	  Additional drivers must be enabled in order to use the specific
> +	  features of the device.
> +
>   config MFD_MC13XXX
>   	tristate
>   	depends on (SPI_MASTER || I2C)
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 2851275..0344494 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -112,6 +112,8 @@ obj-$(CONFIG_MFD_DA9055)	+= da9055.o
>   da9063-objs			:= da9063-core.o da9063-irq.o da9063-i2c.o
>   obj-$(CONFIG_MFD_DA9063)	+= da9063.o
>
> +obj-$(CONFIG_MFD_DA9150)	+= da9150-core.o da9150-i2c.o
> +
>   obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
>   obj-$(CONFIG_MFD_MAX77686)	+= max77686.o max77686-irq.o
>   obj-$(CONFIG_MFD_MAX77693)	+= max77693.o max77693-irq.o
> diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c
> new file mode 100644
> index 0000000..24c62ba
> --- /dev/null
> +++ b/drivers/mfd/da9150-core.c
> @@ -0,0 +1,398 @@
> +/*
> + * DA9150 Core MFD Driver
> + *
> + * Copyright (c) 2014 Dialog Semiconductor
> + *
> + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/irq.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/core.h>
> +
> +#include <linux/mfd/da9150/core.h>
> +#include <linux/mfd/da9150/registers.h>
> +#include <linux/mfd/da9150/pdata.h>
> +
> +
Single line comment syntax.
> +/*
> + * Register/Device Access
> + */
> +
To my mind all these wrappers add nothing significant so you might as well
just call da9150->read_dev etc directly.

Also, what are the read_qif and write_qif for?  They don't seem to be used
anywhere.
> +int da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf)
> +{
> +	int ret;
> +
> +	ret = da9150->read_dev(da9150->core_qif, addr, count, buf);
> +	if (ret < 0)
> +		dev_err(da9150->dev, "Failed to read from QIF 0x%x: %d\n",
> +			addr, ret);
> +
> +	return ret;
> +}
> +
> +int da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf)
> +{
> +	int ret;
> +
> +	ret = da9150->write_dev(da9150->core_qif, addr, count, buf);
> +	if (ret < 0)
> +		dev_err(da9150->dev, "Failed to write to QIF 0x%x: %d\n",
> +			addr, ret);
> +
> +	return ret;
> +}
> +
The only real reason I can see for these wrappers is because you want
to hide the struct da9150 contents from the children of the mfd. As you
aren't doing that, you might as well drop these in favour of direct
calls to regmap_read and friends.
> +u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
> +{
> +	int val, ret;
> +
> +	ret = regmap_read(da9150->regmap, reg, &val);
> +	if (ret < 0)
> +		dev_err(da9150->dev, "Failed to read from reg 0x%x: %d\n",
> +			reg, ret);
> +
> +	return (u8) val;
> +}
> +
> +int da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val)
> +{
> +	int ret;
> +
> +	ret = regmap_write(da9150->regmap, reg, val);
> +	if (ret < 0)
> +		dev_err(da9150->dev, "Failed to write to reg 0x%x: %d\n",
> +			reg, ret);
> +
> +	return ret;
> +}
> +
> +int da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val)
> +{
> +	int ret;
> +
> +	ret = regmap_update_bits(da9150->regmap, reg, mask, val);
> +	if (ret < 0)
> +		dev_err(da9150->dev, "Failed to set bits in reg 0x%x: %d\n",
> +			reg, ret);
> +
> +	return ret;
> +}
> +
> +int da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf)
> +{
> +	int ret;
> +
> +	ret = regmap_bulk_read(da9150->regmap, reg, buf, count);
> +	if (ret < 0)
> +		dev_err(da9150->dev, "Failed to bulk read from reg 0x%x: %d\n",
> +			reg, ret);
> +
> +	return ret;
> +}
> +
> +int da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf)
> +{
> +	int ret;
> +
> +	ret = regmap_raw_write(da9150->regmap, reg, buf, count);
> +	if (ret < 0)
> +		dev_err(da9150->dev, "Failed to bulk write to reg 0x%x %d\n",
> +			reg, ret);
> +
> +	return ret;
> +}
> +
> +
> +/*
> + * IRQ Handling
> + */
> +
> +static struct regmap_irq da9150_irqs[] = {
> +	[DA9150_IRQ_VBUS] = {
> +		.reg_offset = 0,
> +		.mask = DA9150_E_VBUS_MASK,
> +	},
> +	[DA9150_IRQ_CHG] = {
> +		.reg_offset = 0,
> +		.mask = DA9150_E_CHG_MASK,
> +	},
> +	[DA9150_IRQ_TCLASS] = {
> +		.reg_offset = 0,
> +		.mask = DA9150_E_TCLASS_MASK,
> +	},
> +	[DA9150_IRQ_TJUNC] = {
> +		.reg_offset = 0,
> +		.mask = DA9150_E_TJUNC_MASK,
> +	},
> +	[DA9150_IRQ_VFAULT] = {
> +		.reg_offset = 0,
> +		.mask = DA9150_E_VFAULT_MASK,
> +	},
> +	[DA9150_IRQ_CONF] = {
> +		.reg_offset = 1,
> +		.mask = DA9150_E_CONF_MASK,
> +	},
> +	[DA9150_IRQ_DAT] = {
> +		.reg_offset = 1,
> +		.mask = DA9150_E_DAT_MASK,
> +	},
> +	[DA9150_IRQ_DTYPE] = {
> +		.reg_offset = 1,
> +		.mask = DA9150_E_DTYPE_MASK,
> +	},
> +	[DA9150_IRQ_ID] = {
> +		.reg_offset = 1,
> +		.mask = DA9150_E_ID_MASK,
> +	},
> +	[DA9150_IRQ_ADP] = {
> +		.reg_offset = 1,
> +		.mask = DA9150_E_ADP_MASK,
> +	},
> +	[DA9150_IRQ_SESS_END] = {
> +		.reg_offset = 1,
> +		.mask = DA9150_E_SESS_END_MASK,
> +	},
> +	[DA9150_IRQ_SESS_VLD] = {
> +		.reg_offset = 1,
> +		.mask = DA9150_E_SESS_VLD_MASK,
> +	},
> +	[DA9150_IRQ_FG] = {
> +		.reg_offset = 2,
> +		.mask = DA9150_E_FG_MASK,
> +	},
> +	[DA9150_IRQ_GP] = {
> +		.reg_offset = 2,
> +		.mask = DA9150_E_GP_MASK,
> +	},
> +	[DA9150_IRQ_TBAT] = {
> +		.reg_offset = 2,
> +		.mask = DA9150_E_TBAT_MASK,
> +	},
> +	[DA9150_IRQ_GPIOA] = {
> +		.reg_offset = 2,
> +		.mask = DA9150_E_GPIOA_MASK,
> +	},
> +	[DA9150_IRQ_GPIOB] = {
> +		.reg_offset = 2,
> +		.mask = DA9150_E_GPIOB_MASK,
> +	},
> +	[DA9150_IRQ_GPIOC] = {
> +		.reg_offset = 2,
> +		.mask = DA9150_E_GPIOC_MASK,
> +	},
> +	[DA9150_IRQ_GPIOD] = {
> +		.reg_offset = 2,
> +		.mask = DA9150_E_GPIOD_MASK,
> +	},
> +	[DA9150_IRQ_GPADC] = {
> +		.reg_offset = 2,
> +		.mask = DA9150_E_GPADC_MASK,
> +	},
> +	[DA9150_IRQ_WKUP] = {
> +		.reg_offset = 3,
> +		.mask = DA9150_E_WKUP_MASK,
> +	},
> +};
> +
> +static struct regmap_irq_chip da9150_regmap_irq_chip = {
> +	.name = "da9150_irq",
> +	.status_base = DA9150_EVENT_E,
> +	.mask_base = DA9150_IRQ_MASK_E,
> +	.ack_base = DA9150_EVENT_E,
> +	.num_regs = DA9150_NUM_IRQ_REGS,
> +	.irqs = da9150_irqs,
> +	.num_irqs = ARRAY_SIZE(da9150_irqs),
> +};
> +
> +/* Helper function for sub-devices to request IRQs */
> +int da9150_register_irq(struct platform_device *pdev, void *dev_id,
> +			irq_handler_t handler, const char *name)
> +{
> +	int irq, ret;
> +
> +	irq = platform_get_irq_byname(pdev, name);
> +	if (irq < 0)
> +		return irq;
> +
> +	ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, handler,
> +					IRQF_ONESHOT, name, dev_id);
> +	if (ret)
> +		dev_err(&pdev->dev, "Failed to request IRQ %d: %d\n", irq, ret);
> +
> +	return ret;
> +}
> +
> +
> +/*
> + * MFDs
Multi function devices?  Elements of perhaps.
> + */
> +
> +static struct resource da9150_gpio_resources[] = {
> +	{
> +		.name = "GPIOA",
> +		.start = DA9150_IRQ_GPIOA,
> +		.end = DA9150_IRQ_GPIOA,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct resource da9150_gpadc_resources[] = {
> +	{
> +		.name = "GPADC",
> +		.start = DA9150_IRQ_GPADC,
> +		.end = DA9150_IRQ_GPADC,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct resource da9150_charger_resources[] = {
> +	{
> +		.name = "CHG_STATUS",
> +		.start = DA9150_IRQ_CHG,
> +		.end = DA9150_IRQ_CHG,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +	{
> +		.name = "CHG_TJUNC",
> +		.start = DA9150_IRQ_TJUNC,
> +		.end = DA9150_IRQ_TJUNC,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +	{
> +		.name = "CHG_VFAULT",
> +		.start = DA9150_IRQ_VFAULT,
> +		.end = DA9150_IRQ_VFAULT,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +	{
> +		.name = "CHG_VBUS",
> +		.start = DA9150_IRQ_VBUS,
> +		.end = DA9150_IRQ_VBUS,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct resource da9150_fg_resources[] = {
> +	{
> +		.name = "FG",
> +		.start = DA9150_IRQ_FG,
> +		.end = DA9150_IRQ_FG,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct mfd_cell da9150_devs[] = {
> +	{
> +		.name = "da9150-gpio",
> +		.of_compatible = "dlg,da9150-gpio",
> +		.resources = da9150_gpio_resources,
> +		.num_resources = ARRAY_SIZE(da9150_gpio_resources),
> +	},
> +	{
> +		.name = "da9150-gpadc",
> +		.of_compatible = "dlg,da9150-gpadc",
> +		.resources = da9150_gpadc_resources,
> +		.num_resources = ARRAY_SIZE(da9150_gpadc_resources),
> +	},
> +	{
> +		.name = "da9150-charger",
> +		.of_compatible = "dlg,da9150-charger",
> +		.resources = da9150_charger_resources,
> +		.num_resources = ARRAY_SIZE(da9150_charger_resources),
> +	},
> +	{
> +		.name = "da9150-fuelgauge",
> +		.of_compatible = "dlg,da9150-fg",
> +		.resources = da9150_fg_resources,
> +		.num_resources = ARRAY_SIZE(da9150_fg_resources),
> +	},
> +};
> +
> +
> +/*
> + * Device Init/Exit
> + */
I'll continue my tirade against obvious comments. Wrong format and
adds nothing to what is here as init and exit functions are clearly
doing what there name suggests (it's one of my pet hates ;)
> +
> +int da9150_device_init(struct da9150 *da9150)
> +{
> +	struct da9150_pdata *pdata = da9150->dev->platform_data;
> +	int ret;
> +
> +	/* Handle platform data */
> +	if (pdata) {
> +		da9150->irq_base = pdata->irq_base;
> +
As a general good practice point, I'd rather that the driver supported
more than one instance of the chip.. Hence you'd take a copy of da9150_devs
to use here.  I guess it is relatively unlikely with one of these, but
you never know ;)
> +		da9150_devs[0].platform_data = pdata->gpio_pdata;
> +		da9150_devs[0].pdata_size = sizeof(struct da9150_gpio_pdata);
> +		da9150_devs[2].platform_data = pdata->charger_pdata;
> +		da9150_devs[2].pdata_size = sizeof(struct da9150_charger_pdata);
> +		da9150_devs[3].platform_data = pdata->fg_pdata;
> +		da9150_devs[3].pdata_size = sizeof(struct da9150_fg_pdata);
> +	} else {
> +		da9150->irq_base = -1;
> +	}
> +
> +	/* Init IRQs */
> +	ret = regmap_add_irq_chip(da9150->regmap, da9150->irq,
> +				  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> +				  da9150->irq_base, &da9150_regmap_irq_chip,
> +				  &da9150->regmap_irq_data);
> +	if (ret < 0)
> +		goto err_irq;
> +
> +	da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
> +
> +	/* Make the IRQ line a wake source */
> +	enable_irq_wake(da9150->irq);
> +
> +	/* Add MFD Devices */
> +	ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
> +			      ARRAY_SIZE(da9150_devs), NULL,
> +			      da9150->irq_base, NULL);
> +	if (ret < 0) {
> +		dev_err(da9150->dev, "Failed to add child devices: %d\n", ret);
> +		goto err_mfd;
> +	}
> +
> +	return 0;
> +
> +err_mfd:
> +	regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
> +err_irq:
> +	return ret;
> +}
> +
> +void da9150_device_exit(struct da9150 *da9150)
> +{
> +	regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
> +	mfd_remove_devices(da9150->dev);
> +	return;
> +}
> +
> +void da9150_device_shutdown(struct da9150 *da9150)
> +{
> +	if (da9150->can_shutdown) {
> +		/* Make sure we have a wakup source for the device */
> +		da9150_set_bits(da9150, DA9150_CONFIG_D,
> +				DA9150_WKUP_PM_EN_MASK,
> +				DA9150_WKUP_PM_EN_MASK);
> +
> +		/* Set device to DISABLED mode */
> +		da9150_set_bits(da9150, DA9150_CONTROL_C,
> +				DA9150_DISABLE_MASK, DA9150_DISABLE_MASK);
> +	}
> +}
> +
> +MODULE_DESCRIPTION("MFD Core Driver for DA9150");
> +MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/mfd/da9150-i2c.c b/drivers/mfd/da9150-i2c.c
> new file mode 100644
> index 0000000..725aaef
> --- /dev/null
> +++ b/drivers/mfd/da9150-i2c.c
> @@ -0,0 +1,268 @@
> +/*
> + * DA9150 I2C Driver
Why does this need it's own file?  Does the DA9150 support any other
interfaces?
> + *
> + * Copyright (c) 2014 Dialog Semiconductor
> + *
> + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/i2c.h>
> +#include <linux/regmap.h>
> +#include <linux/slab.h>
> +
> +#include <linux/mfd/da9150/core.h>
> +#include <linux/mfd/da9150/registers.h>
> +
> +
> +/*
> + * Regmap Config
> + */
> +
> +static bool da9150_volatile_reg(struct device *dev, unsigned int reg)
> +{
> +	switch (reg) {
> +	case DA9150_PAGE_CON:
> +	case DA9150_STATUS_A:
> +	case DA9150_STATUS_B:
> +	case DA9150_STATUS_C:
> +	case DA9150_STATUS_D:
> +	case DA9150_STATUS_E:
> +	case DA9150_STATUS_F:
> +	case DA9150_STATUS_G:
> +	case DA9150_STATUS_H:
> +	case DA9150_STATUS_I:
> +	case DA9150_STATUS_J:
> +	case DA9150_STATUS_K:
> +	case DA9150_STATUS_L:
> +	case DA9150_STATUS_N:
> +	case DA9150_FAULT_LOG_A:
> +	case DA9150_FAULT_LOG_B:
> +	case DA9150_EVENT_E:
> +	case DA9150_EVENT_F:
> +	case DA9150_EVENT_G:
> +	case DA9150_EVENT_H:
> +	case DA9150_CONTROL_B:
> +	case DA9150_CONTROL_C:
> +	case DA9150_GPADC_MAN:
> +	case DA9150_GPADC_RES_A:
> +	case DA9150_GPADC_RES_B:
> +	case DA9150_ADETVB_CFG_C:
> +	case DA9150_ADETD_STAT:
> +	case DA9150_ADET_CMPSTAT:
> +	case DA9150_ADET_CTRL_A:
> +	case DA9150_PPR_TCTR_B:
> +	case DA9150_COREBTLD_STAT_A:
> +	case DA9150_CORE_DATA_A:
> +	case DA9150_CORE_DATA_B:
> +	case DA9150_CORE_DATA_C:
> +	case DA9150_CORE_DATA_D:
> +	case DA9150_CORE2WIRE_STAT_A:
> +	case DA9150_FW_CTRL_C:
> +	case DA9150_FG_CTRL_B:
> +	case DA9150_FW_CTRL_B:
> +	case DA9150_GPADC_CMAN:
> +	case DA9150_GPADC_CRES_A:
> +	case DA9150_GPADC_CRES_B:
> +	case DA9150_CC_ICHG_RES_A:
> +	case DA9150_CC_ICHG_RES_B:
> +	case DA9150_CC_IAVG_RES_A:
> +	case DA9150_CC_IAVG_RES_B:
> +	case DA9150_TAUX_CTRL_A:
> +	case DA9150_TAUX_VALUE_H:
> +	case DA9150_TAUX_VALUE_L:
> +	case DA9150_TBAT_RES_A:
> +	case DA9150_TBAT_RES_B:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
> +static const struct regmap_range_cfg da9150_range_cfg[] = {
> +	{
> +		.range_min = DA9150_PAGE_CON,
> +		.range_max = DA9150_TBAT_RES_B,
> +		.selector_reg = DA9150_PAGE_CON,
> +		.selector_mask = DA9150_I2C_PAGE_MASK,
> +		.selector_shift = DA9150_I2C_PAGE_SHIFT,
> +		.window_start = 0,
> +		.window_len = 256,
> +	},
> +};
> +
> +static struct regmap_config da9150_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.ranges = da9150_range_cfg,
> +	.num_ranges = ARRAY_SIZE(da9150_range_cfg),
> +	.max_register = DA9150_TBAT_RES_B,
> +
> +	.cache_type = REGCACHE_RBTREE,
> +
> +	.volatile_reg = da9150_volatile_reg,
> +};
> +
> +
> +/*
> + * Device access for QIF interface
> + */
> +
> +static int da9150_i2c_read_device(struct i2c_client *client, u8 addr, int count,
> +				  u8 *buf)
> +{
> +	struct i2c_msg xfer;
> +	int ret;
> +
> +	/*
> +	 * Read is split into two transfers as device expects STOP/START rather
> +	 * than repeated start to carry out this kind of access.
> +	 */
> +
> +	/* Write address */
> +	xfer.addr = client->addr;
> +	xfer.flags = 0;
> +	xfer.len = 1;
> +	xfer.buf = &addr;
> +
> +	ret = i2c_transfer(client->adapter, &xfer, 1);
> +	if (ret != 1) {
> +		if (ret < 0)
> +			return ret;
> +		else
> +			return -EIO;
> +	}
	Not equivalent of i2c_smbus_write_byte?
> +
> +	/* Read data */
> +	xfer.addr = client->addr;
> +	xfer.flags = I2C_M_RD;
> +	xfer.len = count;
> +	xfer.buf = buf;
> +
> +	ret = i2c_transfer(client->adapter, &xfer, 1);
> +	if (ret == 1)
> +		return 0;
There is indeed nothing equivalent to this one...
> +	else if (ret < 0)
> +		return ret;
> +	else
> +		return -EIO;
> +}
> +
> +static int da9150_i2c_write_device(struct i2c_client *client, u8 addr, int count,
> +				   const u8 *buf)
> +{
> +	struct i2c_msg xfer;
> +	u8 *reg_data;
> +	int ret;
> +
> +	reg_data = kzalloc(1 + count, GFP_KERNEL);
> +	if (!reg_data)
> +		return -ENOMEM;
> +
This at least superficialy looks like i2c_smbus_i2c_write_block_data.
> +	reg_data[0] = addr;
> +	memcpy(&reg_data[1], buf, count);
> +
> +	/* Write address & data */
> +	xfer.addr = client->addr;
> +	xfer.flags = 0;
> +	xfer.len = 1 + count;
> +	xfer.buf = reg_data;
> +
> +	ret = i2c_transfer(client->adapter, &xfer, 1);
> +	kfree(reg_data);
> +	if (ret == 1)
> +		return 0;
> +	else if (ret < 0)
> +		return ret;
> +	else
> +		return -EIO;
> +}
> +
> +
> +/*
> + * Driver top level functions
> + */
> +
> +static int da9150_probe(struct i2c_client *client,
> +			const struct i2c_device_id *id)
> +{
> +	struct da9150 *da9150;
> +	int ret;
> +
> +	da9150 = devm_kzalloc(&client->dev, sizeof(struct da9150), GFP_KERNEL);
> +	if (da9150 == NULL)
> +		return -ENOMEM;
> +	da9150->dev = &client->dev;
> +	da9150->irq = client->irq;
> +	i2c_set_clientdata(client, da9150);
> +	dev_set_drvdata(da9150->dev, da9150);
> +
> +	da9150->core_qif = i2c_new_dummy(client->adapter, DA9150_QIF_I2C_ADDR);
> +	i2c_set_clientdata(da9150->core_qif, da9150);
> +
> +	da9150->regmap = devm_regmap_init_i2c(client, &da9150_regmap_config);
> +	if (IS_ERR(da9150->regmap)) {
> +		ret = PTR_ERR(da9150->regmap);
> +		dev_err(da9150->dev, "Failed to allocate register map: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	da9150->read_dev = (read_dev_t) da9150_i2c_read_device;
> +	da9150->write_dev = (write_dev_t) da9150_i2c_write_device;
Why the indirection?  The da9150 only supports i2c as far as I can see.

> +
> +	return da9150_device_init(da9150);
> +}
> +
> +static int da9150_remove(struct i2c_client *client)
> +{
> +	struct da9150 *da9150 = i2c_get_clientdata(client);
> +
> +	da9150_device_exit(da9150);
> +	i2c_unregister_device(da9150->core_qif);
> +
> +	return 0;
> +}
> +
> +static void da9150_shutdown(struct i2c_client *client)
> +{
> +	struct da9150 *da9150 = i2c_get_clientdata(client);
> +
> +	da9150_device_shutdown(da9150);
I'd roll this into one line and not bother with the local variable...

> +}
> +
> +static const struct i2c_device_id da9150_i2c_id[] = {
> +	{ "da9150", 0 },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(i2c, da9150_i2c_id);
> +
> +static const struct of_device_id da9150_of_match[] = {
> +	{ .compatible = "dlg,da9150", },
> +	{ }
> +};
> +
> +static struct i2c_driver da9150_driver = {
> +	.driver	= {
> +		.name	= "da9150",
> +		.owner	= THIS_MODULE,
> +		.of_match_table = of_match_ptr(da9150_of_match),
> +	},
> +	.probe		= da9150_probe,
> +	.remove		= da9150_remove,
> +	.shutdown	= da9150_shutdown,
> +	.id_table	= da9150_i2c_id,
> +};
> +
> +module_i2c_driver(da9150_driver);
> +
> +MODULE_DESCRIPTION("I2C Driver for DA9150");
> +MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/da9150/core.h b/include/linux/mfd/da9150/core.h
> new file mode 100644
> index 0000000..39997406
> --- /dev/null
> +++ b/include/linux/mfd/da9150/core.h
> @@ -0,0 +1,125 @@
> +/*
> + * DA9150 MFD Driver - Core Data
> + *
> + * Copyright (c) 2014 Dialog Semiconductor
> + *
> + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> + *
> + * 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.
> + */
> +
> +#ifndef _DA9150_CORE_H
> +#define _DA9150_CORE_H
> +
> +#include <linux/device.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/regmap.h>
> +#include <linux/mutex.h>
> +
> +/*
> + * Defines
> + */
> +
> +/* I2C sub-device addresses */
> +#define DA9150_QIF_I2C_ADDR	0x6D
> +
> +/* I2C address paging */
> +#define DA9150_REG_PAGE_SHIFT	8
> +#define DA9150_REG_PAGE_MASK	0xFF
> +
> +/* IRQs */
> +#define DA9150_NUM_IRQ_REGS	4
> +#define DA9150_IRQ_VBUS		0
> +#define DA9150_IRQ_CHG		1
> +#define DA9150_IRQ_TCLASS	2
> +#define DA9150_IRQ_TJUNC	3
> +#define DA9150_IRQ_VFAULT	4
> +#define DA9150_IRQ_CONF		5
> +#define DA9150_IRQ_DAT		6
> +#define DA9150_IRQ_DTYPE	7
> +#define DA9150_IRQ_ID		8
> +#define DA9150_IRQ_ADP		9
> +#define DA9150_IRQ_SESS_END	10
> +#define DA9150_IRQ_SESS_VLD	11
> +#define DA9150_IRQ_FG		12
> +#define DA9150_IRQ_GP		13
> +#define DA9150_IRQ_TBAT		14
> +#define DA9150_IRQ_GPIOA	15
> +#define DA9150_IRQ_GPIOB	16
> +#define DA9150_IRQ_GPIOC	17
> +#define DA9150_IRQ_GPIOD	18
> +#define DA9150_IRQ_GPADC	19
> +#define DA9150_IRQ_WKUP		20
> +
> +/* Helper macros to convert real world values to register values */
> +#define DA9150_CHG_IBAT_FACTOR		25000
> +#define DA9150_CHG_IEND_FACTOR		4800
> +#define DA9150_CHG_IBAT_UA_TO_REG(val)	(val / DA9150_CHG_IBAT_FACTOR)
> +#define DA9150_CHG_IEND_UA_TO_REG(val)	(val / DA9150_CHG_IEND_FACTOR)
> +#define DA9150_CHG_IBAT_REG_TO_UA(val)	(val * DA9150_CHG_IBAT_FACTOR)
> +#define DA9150_CHG_IEND_REG_TO_UA(val)	(val * DA9150_CHG_IEND_FACTOR)
> +
> +
> +/*
> + * I/O Function Typedefs
> + */
> +
> +typedef int (*read_dev_t)(void *client, u8 addr, int count, u8 *buf);
> +typedef int (*write_dev_t)(void *client, u8 addr, int count, const u8 *buf);
> +
> +/*
> + * Main structure
> + */
> +
> +struct da9150 {
> +	struct device *dev;
> +
> +	struct regmap *regmap;
> +	struct i2c_client *core_qif;
> +
> +	read_dev_t read_dev;
> +	write_dev_t write_dev;
> +
> +	struct regmap_irq_chip_data *regmap_irq_data;
> +	int irq;
> +	int irq_base;
> +
> +	bool can_shutdown;
> +	bool gpadc_ready;
> +};
> +
> +/*
> + * APIs
> + */
> +
> +/* Device I/O */
> +int da9150_read_core(struct da9150 *da9150, u8 addr, int count, u8 *buf);
> +int da9150_write_core(struct da9150 *da9150, u8 addr, int count, const u8 *buf);
> +
> +int da9150_read_qif(struct da9150 *da9150, u8 addr, int count, u8 *buf);
> +int da9150_write_qif(struct da9150 *da9150, u8 addr, int count, const u8 *buf);
> +
> +int da9150_read_fwdl(struct da9150 *da9150, u8 addr, int count, u8 *buf);
> +int da9150_write_fwdl(struct da9150 *da9150, u8 addr, int count, const u8 *buf);
> +
> +u8 da9150_reg_read(struct da9150 *da9150, u16 reg);
> +int da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val);
> +int da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val);
> +
> +int da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf);
> +int da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf);
> +
> +/* IRQ */
> +int da9150_register_irq(struct platform_device *pdev, void *dev_id,
> +			irq_handler_t handler, const char *name);
> +
> +/* Init/Exit */
> +int da9150_device_init(struct da9150 *da9150);
> +void da9150_device_exit(struct da9150 *da9150);
> +void da9150_device_shutdown(struct da9150 *da9150);
> +
> +#endif /* _DA9150_CORE_H */
> diff --git a/include/linux/mfd/da9150/pdata.h b/include/linux/mfd/da9150/pdata.h
> new file mode 100644
> index 0000000..c1dd2b3
> --- /dev/null
> +++ b/include/linux/mfd/da9150/pdata.h
> @@ -0,0 +1,148 @@
> +/*
> + * DA9150 MFD Driver - Platform Data
> + *
> + * Copyright (c) 2014 Dialog Semiconductor
> + *
> + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> + *
> + * 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.
> + */
> +
> +#ifndef _DA9150_PDATA_H
> +#define _DA9150_PDATA_H
> +
> +/*
> + * GPIO
> + */
> +
> +#define DA9150_NUM_GPIOS	4
> +
> +/* Values are as bit fields for registers */
> +enum da9150_gpi_trigger {
> +	DA9150_GPI_ACTIVE_LOW = 0,
> +	DA9150_GPI_ACTIVE_HIGH,
> +};
> +
> +enum da9150_gpi_mode {
> +	DA9150_GPI_DIG = 0,
> +	DA9150_GPI_ANA = 3,
> +};
> +
> +enum da9150_gpo_mode {
> +	DA9150_GPO_OD = 1,
> +	DA9150_GPO_PP,
> +};
> +
> +enum da9150_gpo_supply {
> +	DA9150_GPO_SUPPLY_VDDIO1 = 0,
> +	DA9150_GPO_SUPPLY_VDDIO2,
> +};
> +
> +enum da9150_gpio_pupd {
> +	DA9150_GPIO_PUPD_DISABLED = 0,
> +	DA9150_GPIO_PUPD_ENABLED,
> +};
> +
> +struct da9150_gpio_cfg {
> +	enum da9150_gpi_trigger gpi_trigger;
> +	enum da9150_gpi_mode gpi_mode;
> +	enum da9150_gpo_mode gpo_mode;
> +	enum da9150_gpo_supply gpo_supply;
> +	enum da9150_gpio_pupd gpio_pupd;
> +};
> +
> +enum da9150_gpi_debounce_time {
> +	DA9150_GPI_DEBOUNCE_TIME_OFF = 0,
> +	DA9150_GPI_DEBOUNCE_TIME_100US,
> +	DA9150_GPI_DEBOUNCE_TIME_1MS,
> +	DA9150_GPI_DEBOUNCE_TIME_10MS24,
> +	DA9150_GPI_DEBOUNCE_TIME_51MS20,
> +	DA9150_GPI_DEBOUNCE_TIME_256MS,
> +	DA9150_GPI_DEBOUNCE_TIME_512MS,
> +	DA9150_GPI_DEBOUNCE_TIME_1024MS,
> +};
> +
> +/* Charging LED Data */
> +enum da9150_led_freq {
> +	DA9150_LED_FREQ_ALWAYS_ON = 0,
> +	DA9150_LED_FREQ_1_S,
> +	DA9150_LED_FREQ_2_S,
> +	DA9150_LED_FREQ_4_S,
> +};
> +
> +enum da9150_led_ontime {
> +	DA9150_LED_ONTIME_10_MS = 0,
> +	DA9150_LED_ONTIME_20_MS,
> +	DA9150_LED_ONTIME_40_MS,
> +	DA9150_LED_ONTIME_HALF_FREQ,
> +};
> +
> +enum da9150_pin {
> +	DA9150_PIN_OFF = 0,
> +	DA9150_PIN_GPIOA = 1,
> +	DA9150_PIN_GPIOB = 2,
> +	DA9150_PIN_GPIOC = 3,
> +	DA9150_PIN_GPIOD = 4,
> +};
> +
> +
> +/* Fault Pin Data */
> +enum da9150_fault_type {
> +	DA9150_FAULT_TYPE_VFAULT = 0,
> +	DA9150_FAULT_TYPE_RESET,
> +};
> +
> +
> +/* GPIO data */
> +struct da9150_gpio_pdata {
> +	int base;
> +
> +	/* General GPIO config */
> +	struct da9150_gpio_cfg gpio_cfg[DA9150_NUM_GPIOS];
> +	enum da9150_gpi_debounce_time gpi_debounce_time;
> +
> +	/* Charge LED features */
> +	enum da9150_led_freq led_frequency;
> +	bool led_dbl_flash;
> +	enum da9150_led_ontime led_ontime;
> +	enum da9150_pin led_pin;
> +
> +	/* Fault Pin features */
> +	enum da9150_pin fault_pin;
> +	enum da9150_fault_type fault_type;
> +};
> +
> +/*
> + * Fuel-Gauge
> + */
> +
> +struct da9150_fg_pdata {
> +	u32 update_interval;	/* msecs */
> +	u8 warn_soc_lvl;	/* % value */
> +	u8 crit_soc_lvl;	/* % value */
> +};
> +
> +/*
> + * Charger
> + */
> +
> +struct da9150_charger_pdata {
> +	bool invalid_tbat;
> +};
> +
> +
> +/*
> + * Main struct
> + */
Drop comments on things that are self evident.  Also these are one
line comments so should be using the single line comment syntax.
> +
> +struct da9150_pdata {
> +	int irq_base;
> +	struct da9150_gpio_pdata *gpio_pdata;
> +	struct da9150_fg_pdata *fg_pdata;
> +	struct da9150_charger_pdata *charger_pdata;
> +};
> +
> +#endif /* _DA9150_PDATA_H */
> diff --git a/include/linux/mfd/da9150/registers.h b/include/linux/mfd/da9150/registers.h
> new file mode 100644
> index 0000000..a6a8e28
> --- /dev/null
> +++ b/include/linux/mfd/da9150/registers.h
> @@ -0,0 +1,1160 @@
> +/*
> + * DA9150 MFD Driver - Registers
> + *
> + * Copyright (c) 2014 Dialog Semiconductor
> + *
> + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> + *
> + * 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.
> + */
> +
> +#ifndef _DA9150_REGISTERS_H
> +#define _DA9150_REGISTERS_H
> +
> +/*
> + * Registers
> + */
> +
> +#define DA9150_PAGE_CON			0x000
> +#define DA9150_STATUS_A			0x068
> +#define DA9150_STATUS_B			0x069
> +#define DA9150_STATUS_C			0x06A
> +#define DA9150_STATUS_D			0x06B
> +#define DA9150_STATUS_E			0x06C
> +#define DA9150_STATUS_F			0x06D
> +#define DA9150_STATUS_G			0x06E
> +#define DA9150_STATUS_H			0x06F
> +#define DA9150_STATUS_I			0x070
> +#define DA9150_STATUS_J			0x071
> +#define DA9150_STATUS_K			0x072
> +#define DA9150_STATUS_L			0x073
> +#define DA9150_STATUS_N			0x074
> +#define DA9150_FAULT_LOG_A		0x076
> +#define DA9150_FAULT_LOG_B		0x077
> +#define DA9150_EVENT_E			0x078
> +#define DA9150_EVENT_F			0x079
> +#define DA9150_EVENT_G			0x07A
> +#define DA9150_EVENT_H			0x07B
> +#define DA9150_IRQ_MASK_E		0x07C
> +#define DA9150_IRQ_MASK_F		0x07D
> +#define DA9150_IRQ_MASK_G		0x07E
> +#define DA9150_IRQ_MASK_H		0x07F
> +#define DA9150_PAGE_CON_1		0x080
> +#define DA9150_CONFIG_A			0x0E0
> +#define DA9150_CONFIG_B			0x0E1
> +#define DA9150_CONFIG_C			0x0E2
> +#define DA9150_CONFIG_D			0x0E3
> +#define DA9150_CONFIG_E			0x0E4
> +#define DA9150_CONTROL_A		0x0E5
> +#define DA9150_CONTROL_B		0x0E6
> +#define DA9150_CONTROL_C		0x0E7
> +#define DA9150_GPIO_A_B			0x0E8
> +#define DA9150_GPIO_C_D			0x0E9
> +#define DA9150_GPIO_MODE_CONT		0x0EA
> +#define DA9150_GPIO_CTRL_B		0x0EB
> +#define DA9150_GPIO_CTRL_A		0x0EC
> +#define DA9150_GPIO_CTRL_C		0x0ED
> +#define DA9150_GPIO_CFG_A		0x0EE
> +#define DA9150_GPIO_CFG_B		0x0EF
> +#define DA9150_GPIO_CFG_C		0x0F0
> +#define DA9150_GPADC_MAN		0x0F2
> +#define DA9150_GPADC_RES_A		0x0F4
> +#define DA9150_GPADC_RES_B		0x0F5
> +#define DA9150_PAGE_CON_2		0x100
> +#define DA9150_OTP_CONT_SHARED		0x101
> +#define DA9150_INTERFACE_SHARED		0x105
> +#define DA9150_CONFIG_A_SHARED		0x106
> +#define DA9150_CONFIG_D_SHARED		0x109
> +#define DA9150_ADETVB_CFG_C		0x150
> +#define DA9150_ADETD_STAT		0x151
> +#define DA9150_ADET_CMPSTAT		0x152
> +#define DA9150_ADET_CTRL_A		0x153
> +#define DA9150_ADETVB_CFG_B		0x154
> +#define DA9150_ADETVB_CFG_A		0x155
> +#define DA9150_ADETAC_CFG_A		0x156
> +#define DA9150_ADDETAC_CFG_B		0x157
> +#define DA9150_ADETAC_CFG_C		0x158
> +#define DA9150_ADETAC_CFG_D		0x159
> +#define DA9150_ADETVB_CFG_D		0x15A
> +#define DA9150_ADETID_CFG_A		0x15B
> +#define DA9150_ADET_RID_PT_CHG_H	0x15C
> +#define DA9150_ADET_RID_PT_CHG_L	0x15D
> +#define DA9150_PPR_TCTR_B		0x160
> +#define DA9150_PPR_BKCTRL_A		0x163
> +#define DA9150_PPR_BKCFG_A		0x164
> +#define DA9150_PPR_BKCFG_B		0x165
> +#define DA9150_PPR_CHGCTRL_A		0x166
> +#define DA9150_PPR_CHGCTRL_B		0x167
> +#define DA9150_PPR_CHGCTRL_C		0x168
> +#define DA9150_PPR_TCTR_A		0x169
> +#define DA9150_PPR_CHGCTRL_D		0x16A
> +#define DA9150_PPR_CHGCTRL_E		0x16B
> +#define DA9150_PPR_CHGCTRL_F		0x16C
> +#define DA9150_PPR_CHGCTRL_G		0x16D
> +#define DA9150_PPR_CHGCTRL_H		0x16E
> +#define DA9150_PPR_CHGCTRL_I		0x16F
> +#define DA9150_PPR_CHGCTRL_J		0x170
> +#define DA9150_PPR_CHGCTRL_K		0x171
> +#define DA9150_PPR_CHGCTRL_L		0x172
> +#define DA9150_PPR_CHGCTRL_M		0x173
> +#define DA9150_PPR_THYST_A		0x174
> +#define DA9150_PPR_THYST_B		0x175
> +#define DA9150_PPR_THYST_C		0x176
> +#define DA9150_PPR_THYST_D		0x177
> +#define DA9150_PPR_THYST_E		0x178
> +#define DA9150_PPR_THYST_F		0x179
> +#define DA9150_PPR_THYST_G		0x17A
> +#define DA9150_PAGE_CON_3		0x180
> +#define DA9150_PAGE_CON_4		0x200
> +#define DA9150_PAGE_CON_5		0x280
> +#define DA9150_PAGE_CON_6		0x300
> +#define DA9150_COREBTLD_STAT_A		0x302
> +#define DA9150_COREBTLD_CTRL_A		0x303
> +#define DA9150_CORE_CONFIG_A		0x304
> +#define DA9150_CORE_CONFIG_C		0x305
> +#define DA9150_CORE_CONFIG_B		0x306
> +#define DA9150_CORE_CFG_DATA_A		0x307
> +#define DA9150_CORE_CFG_DATA_B		0x308
> +#define DA9150_CORE_CMD_A		0x309
> +#define DA9150_CORE_DATA_A		0x30A
> +#define DA9150_CORE_DATA_B		0x30B
> +#define DA9150_CORE_DATA_C		0x30C
> +#define DA9150_CORE_DATA_D		0x30D
> +#define DA9150_CORE2WIRE_STAT_A		0x310
> +#define DA9150_CORE2WIRE_CTRL_A		0x311
> +#define DA9150_FW_CTRL_A		0x312
> +#define DA9150_FW_CTRL_C		0x313
> +#define DA9150_FW_CTRL_D		0x314
> +#define DA9150_FG_CTRL_A		0x315
> +#define DA9150_FG_CTRL_B		0x316
> +#define DA9150_FW_CTRL_E		0x317
> +#define DA9150_FW_CTRL_B		0x318
> +#define DA9150_GPADC_CMAN		0x320
> +#define DA9150_GPADC_CRES_A		0x322
> +#define DA9150_GPADC_CRES_B		0x323
> +#define DA9150_CC_CFG_A			0x328
> +#define DA9150_CC_CFG_B			0x329
> +#define DA9150_CC_ICHG_RES_A		0x32A
> +#define DA9150_CC_ICHG_RES_B		0x32B
> +#define DA9150_CC_IAVG_RES_A		0x32C
> +#define DA9150_CC_IAVG_RES_B		0x32D
> +#define DA9150_TAUX_CTRL_A		0x330
> +#define DA9150_TAUX_RELOAD_H		0x332
> +#define DA9150_TAUX_RELOAD_L		0x333
> +#define DA9150_TAUX_VALUE_H		0x334
> +#define DA9150_TAUX_VALUE_L		0x335
> +#define DA9150_AUX_DATA_0		0x338
> +#define DA9150_AUX_DATA_1		0x339
> +#define DA9150_AUX_DATA_2		0x33A
> +#define DA9150_AUX_DATA_3		0x33B
> +#define DA9150_BIF_CTRL			0x340
> +#define DA9150_TBAT_CTRL_A		0x342
> +#define DA9150_TBAT_CTRL_B		0x343
> +#define DA9150_TBAT_RES_A		0x344
> +#define DA9150_TBAT_RES_B		0x345
> +
> +
> +/*
> + * Bit fields
> + */
> +
> +/* DA9150_PAGE_CON = 0x000 */
> +#define DA9150_PAGE_SHIFT			0
> +#define DA9150_PAGE_MASK			(0x3f << 0)
> +#define DA9150_I2C_PAGE_SHIFT			1
> +#define DA9150_I2C_PAGE_MASK			(0x1f << 1)
> +#define DA9150_WRITE_MODE_SHIFT			6
> +#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
> +#define DA9150_REVERT_SHIFT			7
> +#define DA9150_REVERT_MASK			(0x01 << 7)
> +
> +/* DA9150_STATUS_A = 0x068 */
> +#define DA9150_WKUP_STAT_SHIFT			2
> +#define DA9150_WKUP_STAT_MASK			(0x0f << 2)
> +#define DA9150_SLEEP_STAT_SHIFT			6
> +#define DA9150_SLEEP_STAT_MASK			(0x03 << 6)
> +
> +/* DA9150_STATUS_B = 0x069 */
> +#define DA9150_VFAULT_STAT_SHIFT		0
> +#define DA9150_VFAULT_STAT_MASK			(0x01 << 0)
> +#define DA9150_TFAULT_STAT_SHIFT		1
> +#define DA9150_TFAULT_STAT_MASK			(0x01 << 1)
> +
> +/* DA9150_STATUS_C = 0x06A */
> +#define DA9150_VDD33_STAT_SHIFT			0
> +#define DA9150_VDD33_STAT_MASK			(0x01 << 0)
> +#define DA9150_VDD33_SLEEP_SHIFT		1
> +#define DA9150_VDD33_SLEEP_MASK			(0x01 << 1)
> +#define DA9150_LFOSC_STAT_SHIFT			7
> +#define DA9150_LFOSC_STAT_MASK			(0x01 << 7)
> +
> +/* DA9150_STATUS_D = 0x06B */
> +#define DA9150_GPIOA_STAT_SHIFT			0
> +#define DA9150_GPIOA_STAT_MASK			(0x01 << 0)
> +#define DA9150_GPIOB_STAT_SHIFT			1
> +#define DA9150_GPIOB_STAT_MASK			(0x01 << 1)
> +#define DA9150_GPIOC_STAT_SHIFT			2
> +#define DA9150_GPIOC_STAT_MASK			(0x01 << 2)
> +#define DA9150_GPIOD_STAT_SHIFT			3
> +#define DA9150_GPIOD_STAT_MASK			(0x01 << 3)
> +
> +/* DA9150_STATUS_E = 0x06C */
> +#define DA9150_DTYPE_SHIFT			0
> +#define DA9150_DTYPE_MASK			(0x1f << 0)
> +#define DA9150_DTYPE_DT_NIL			(0x00 << 0)
> +#define DA9150_DTYPE_DT_USB_OTG			(0x01 << 0)
> +#define DA9150_DTYPE_DT_USB_STD			(0x02 << 0)
> +#define DA9150_DTYPE_DT_USB_CHG			(0x03 << 0)
> +#define DA9150_DTYPE_DT_ACA_CHG			(0x04 << 0)
> +#define DA9150_DTYPE_DT_ACA_OTG			(0x05 << 0)
> +#define DA9150_DTYPE_DT_ACA_DOC			(0x06 << 0)
> +#define DA9150_DTYPE_DT_DED_CHG			(0x07 << 0)
> +#define DA9150_DTYPE_DT_CR5_CHG			(0x08 << 0)
> +#define DA9150_DTYPE_DT_CR4_CHG			(0x0c << 0)
> +#define DA9150_DTYPE_DT_PT_CHG			(0x11 << 0)
> +#define DA9150_DTYPE_DT_NN_ACC			(0x16 << 0)
> +#define DA9150_DTYPE_DT_NN_CHG			(0x17 << 0)
> +
> +/* DA9150_STATUS_F = 0x06D */
> +#define DA9150_SESS_VLD_SHIFT			0
> +#define DA9150_SESS_VLD_MASK			(0x01 << 0)
> +#define DA9150_ID_ERR_SHIFT			1
> +#define DA9150_ID_ERR_MASK			(0x01 << 1)
> +#define DA9150_PT_CHG_SHIFT			2
> +#define DA9150_PT_CHG_MASK			(0x01 << 2)
> +
> +/* DA9150_STATUS_G = 0x06E */
> +#define DA9150_RID_SHIFT			0
> +#define DA9150_RID_MASK				(0xff << 0)
> +
> +/* DA9150_STATUS_H = 0x06F */
> +#define DA9150_VBUS_STAT_SHIFT			0
> +#define DA9150_VBUS_STAT_MASK			(0x07 << 0)
> +#define DA9150_VBUS_STAT_OFF			(0x00 << 0)
> +#define DA9150_VBUS_STAT_WAIT			(0x01 << 0)
> +#define DA9150_VBUS_STAT_CHG			(0x02 << 0)
> +#define DA9150_VBUS_TRED_SHIFT			3
> +#define DA9150_VBUS_TRED_MASK			(0x01 << 3)
> +#define DA9150_VBUS_DROP_STAT_SHIFT		4
> +#define DA9150_VBUS_DROP_STAT_MASK		(0x0f << 4)
> +
> +/* DA9150_STATUS_I = 0x070 */
> +#define DA9150_VBUS_ISET_STAT_SHIFT		0
> +#define DA9150_VBUS_ISET_STAT_MASK		(0x1f << 0)
> +#define DA9150_VBUS_OT_SHIFT			7
> +#define DA9150_VBUS_OT_MASK			(0x01 << 7)
> +
> +/* DA9150_STATUS_J = 0x071 */
> +#define DA9150_CHG_STAT_SHIFT			0
> +#define DA9150_CHG_STAT_MASK			(0x0f << 0)
> +#define DA9150_CHG_STAT_OFF			(0x00 << 0)
> +#define DA9150_CHG_STAT_SUSP			(0x01 << 0)
> +#define DA9150_CHG_STAT_ACT			(0x02 << 0)
> +#define DA9150_CHG_STAT_PRE			(0x03 << 0)
> +#define DA9150_CHG_STAT_CC			(0x04 << 0)
> +#define DA9150_CHG_STAT_CV			(0x05 << 0)
> +#define DA9150_CHG_STAT_FULL			(0x06 << 0)
> +#define DA9150_CHG_STAT_TEMP			(0x07 << 0)
> +#define DA9150_CHG_STAT_TIME			(0x08 << 0)
> +#define DA9150_CHG_STAT_BAT			(0x09 << 0)
> +#define DA9150_CHG_TEMP_SHIFT			4
> +#define DA9150_CHG_TEMP_MASK			(0x07 << 4)
> +#define DA9150_CHG_TEMP_UNDER			(0x06 << 4)
> +#define DA9150_CHG_TEMP_OVER			(0x07 << 4)
> +#define DA9150_CHG_IEND_STAT_SHIFT		7
> +#define DA9150_CHG_IEND_STAT_MASK		(0x01 << 7)
> +
> +/* DA9150_STATUS_K = 0x072 */
> +#define DA9150_CHG_IAV_H_SHIFT			0
> +#define DA9150_CHG_IAV_H_MASK			(0xff << 0)
> +
> +/* DA9150_STATUS_L = 0x073 */
> +#define DA9150_CHG_IAV_L_SHIFT			5
> +#define DA9150_CHG_IAV_L_MASK			(0x07 << 5)
> +
> +/* DA9150_STATUS_N = 0x074 */
> +#define DA9150_CHG_TIME_SHIFT			1
> +#define DA9150_CHG_TIME_MASK			(0x01 << 1)
> +#define DA9150_CHG_TRED_SHIFT			2
> +#define DA9150_CHG_TRED_MASK			(0x01 << 2)
> +#define DA9150_CHG_TJUNC_CLASS_SHIFT		3
> +#define DA9150_CHG_TJUNC_CLASS_MASK		(0x07 << 3)
> +#define DA9150_CHG_TJUNC_CLASS_6		(0x06 << 3)
> +#define DA9150_EBS_STAT_SHIFT			6
> +#define DA9150_EBS_STAT_MASK			(0x01 << 6)
> +#define DA9150_CHG_BAT_REMOVED_SHIFT		7
> +#define DA9150_CHG_BAT_REMOVED_MASK		(0x01 << 7)
> +
> +/* DA9150_FAULT_LOG_A = 0x076 */
> +#define DA9150_TEMP_FAULT_SHIFT			0
> +#define DA9150_TEMP_FAULT_MASK			(0x01 << 0)
> +#define DA9150_VSYS_FAULT_SHIFT			1
> +#define DA9150_VSYS_FAULT_MASK			(0x01 << 1)
> +#define DA9150_START_FAULT_SHIFT		2
> +#define DA9150_START_FAULT_MASK			(0x01 << 2)
> +#define DA9150_EXT_FAULT_SHIFT			3
> +#define DA9150_EXT_FAULT_MASK			(0x01 << 3)
> +#define DA9150_POR_FAULT_SHIFT			4
> +#define DA9150_POR_FAULT_MASK			(0x01 << 4)
> +
> +/* DA9150_FAULT_LOG_B = 0x077 */
> +#define DA9150_VBUS_FAULT_SHIFT			0
> +#define DA9150_VBUS_FAULT_MASK			(0x01 << 0)
> +#define DA9150_OTG_FAULT_SHIFT			1
> +#define DA9150_OTG_FAULT_MASK			(0x01 << 1)
> +
> +/* DA9150_EVENT_E = 0x078 */
> +#define DA9150_E_VBUS_SHIFT			0
> +#define DA9150_E_VBUS_MASK			(0x01 << 0)
> +#define DA9150_E_CHG_SHIFT			1
> +#define DA9150_E_CHG_MASK			(0x01 << 1)
> +#define DA9150_E_TCLASS_SHIFT			2
> +#define DA9150_E_TCLASS_MASK			(0x01 << 2)
> +#define DA9150_E_TJUNC_SHIFT			3
> +#define DA9150_E_TJUNC_MASK			(0x01 << 3)
> +#define DA9150_E_VFAULT_SHIFT			4
> +#define DA9150_E_VFAULT_MASK			(0x01 << 4)
> +#define DA9150_EVENTS_H_SHIFT			5
> +#define DA9150_EVENTS_H_MASK			(0x01 << 5)
> +#define DA9150_EVENTS_G_SHIFT			6
> +#define DA9150_EVENTS_G_MASK			(0x01 << 6)
> +#define DA9150_EVENTS_F_SHIFT			7
> +#define DA9150_EVENTS_F_MASK			(0x01 << 7)
> +
> +/* DA9150_EVENT_F = 0x079 */
> +#define DA9150_E_CONF_SHIFT			0
> +#define DA9150_E_CONF_MASK			(0x01 << 0)
> +#define DA9150_E_DAT_SHIFT			1
> +#define DA9150_E_DAT_MASK			(0x01 << 1)
> +#define DA9150_E_DTYPE_SHIFT			3
> +#define DA9150_E_DTYPE_MASK			(0x01 << 3)
> +#define DA9150_E_ID_SHIFT			4
> +#define DA9150_E_ID_MASK			(0x01 << 4)
> +#define DA9150_E_ADP_SHIFT			5
> +#define DA9150_E_ADP_MASK			(0x01 << 5)
> +#define DA9150_E_SESS_END_SHIFT			6
> +#define DA9150_E_SESS_END_MASK			(0x01 << 6)
> +#define DA9150_E_SESS_VLD_SHIFT			7
> +#define DA9150_E_SESS_VLD_MASK			(0x01 << 7)
> +
> +/* DA9150_EVENT_G = 0x07A */
> +#define DA9150_E_FG_SHIFT			0
> +#define DA9150_E_FG_MASK			(0x01 << 0)
> +#define DA9150_E_GP_SHIFT			1
> +#define DA9150_E_GP_MASK			(0x01 << 1)
> +#define DA9150_E_TBAT_SHIFT			2
> +#define DA9150_E_TBAT_MASK			(0x01 << 2)
> +#define DA9150_E_GPIOA_SHIFT			3
> +#define DA9150_E_GPIOA_MASK			(0x01 << 3)
> +#define DA9150_E_GPIOB_SHIFT			4
> +#define DA9150_E_GPIOB_MASK			(0x01 << 4)
> +#define DA9150_E_GPIOC_SHIFT			5
> +#define DA9150_E_GPIOC_MASK			(0x01 << 5)
> +#define DA9150_E_GPIOD_SHIFT			6
> +#define DA9150_E_GPIOD_MASK			(0x01 << 6)
> +#define DA9150_E_GPADC_SHIFT			7
> +#define DA9150_E_GPADC_MASK			(0x01 << 7)
> +
> +/* DA9150_EVENT_H = 0x07B */
> +#define DA9150_E_WKUP_SHIFT			0
> +#define DA9150_E_WKUP_MASK			(0x01 << 0)
> +
> +/* DA9150_IRQ_MASK_E = 0x07C */
> +#define DA9150_M_VBUS_SHIFT			0
> +#define DA9150_M_VBUS_MASK			(0x01 << 0)
> +#define DA9150_M_CHG_SHIFT			1
> +#define DA9150_M_CHG_MASK			(0x01 << 1)
> +#define DA9150_M_TJUNC_SHIFT			3
> +#define DA9150_M_TJUNC_MASK			(0x01 << 3)
> +#define DA9150_M_VFAULT_SHIFT			4
> +#define DA9150_M_VFAULT_MASK			(0x01 << 4)
> +
> +/* DA9150_IRQ_MASK_F = 0x07D */
> +#define DA9150_M_CONF_SHIFT			0
> +#define DA9150_M_CONF_MASK			(0x01 << 0)
> +#define DA9150_M_DAT_SHIFT			1
> +#define DA9150_M_DAT_MASK			(0x01 << 1)
> +#define DA9150_M_DTYPE_SHIFT			3
> +#define DA9150_M_DTYPE_MASK			(0x01 << 3)
> +#define DA9150_M_ID_SHIFT			4
> +#define DA9150_M_ID_MASK			(0x01 << 4)
> +#define DA9150_M_ADP_SHIFT			5
> +#define DA9150_M_ADP_MASK			(0x01 << 5)
> +#define DA9150_M_SESS_END_SHIFT			6
> +#define DA9150_M_SESS_END_MASK			(0x01 << 6)
> +#define DA9150_M_SESS_VLD_SHIFT			7
> +#define DA9150_M_SESS_VLD_MASK			(0x01 << 7)
> +
> +/* DA9150_IRQ_MASK_G = 0x07E */
> +#define DA9150_M_FG_SHIFT			0
> +#define DA9150_M_FG_MASK			(0x01 << 0)
> +#define DA9150_M_GP_SHIFT			1
> +#define DA9150_M_GP_MASK			(0x01 << 1)
> +#define DA9150_M_TBAT_SHIFT			2
> +#define DA9150_M_TBAT_MASK			(0x01 << 2)
> +#define DA9150_M_GPIOA_SHIFT			3
> +#define DA9150_M_GPIOA_MASK			(0x01 << 3)
> +#define DA9150_M_GPIOB_SHIFT			4
> +#define DA9150_M_GPIOB_MASK			(0x01 << 4)
> +#define DA9150_M_GPIOC_SHIFT			5
> +#define DA9150_M_GPIOC_MASK			(0x01 << 5)
> +#define DA9150_M_GPIOD_SHIFT			6
> +#define DA9150_M_GPIOD_MASK			(0x01 << 6)
> +#define DA9150_M_GPADC_SHIFT			7
> +#define DA9150_M_GPADC_MASK			(0x01 << 7)
> +
> +/* DA9150_IRQ_MASK_H = 0x07F */
> +#define DA9150_M_WKUP_SHIFT			0
> +#define DA9150_M_WKUP_MASK			(0x01 << 0)
> +
> +/* DA9150_PAGE_CON_1 = 0x080 */
> +#define DA9150_PAGE_SHIFT			0
> +#define DA9150_PAGE_MASK			(0x3f << 0)
> +#define DA9150_WRITE_MODE_SHIFT			6
> +#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
> +#define DA9150_REVERT_SHIFT			7
> +#define DA9150_REVERT_MASK			(0x01 << 7)
> +
> +/* DA9150_CONFIG_A = 0x0E0 */
> +#define DA9150_RESET_DUR_SHIFT			0
> +#define DA9150_RESET_DUR_MASK			(0x03 << 0)
> +#define DA9150_RESET_EXT_SHIFT			2
> +#define DA9150_RESET_EXT_MASK			(0x03 << 2)
> +#define DA9150_START_MAX_SHIFT			4
> +#define DA9150_START_MAX_MASK			(0x03 << 4)
> +#define DA9150_PS_WAIT_EN_SHIFT			6
> +#define DA9150_PS_WAIT_EN_MASK			(0x01 << 6)
> +#define DA9150_PS_DISABLE_DIRECT_SHIFT		7
> +#define DA9150_PS_DISABLE_DIRECT_MASK		(0x01 << 7)
> +
> +/* DA9150_CONFIG_B = 0x0E1 */
> +#define DA9150_VFAULT_ADJ_SHIFT			0
> +#define DA9150_VFAULT_ADJ_MASK			(0x0f << 0)
> +#define DA9150_VFAULT_HYST_SHIFT		4
> +#define DA9150_VFAULT_HYST_MASK			(0x07 << 4)
> +#define DA9150_VFAULT_EN_SHIFT			7
> +#define DA9150_VFAULT_EN_MASK			(0x01 << 7)
> +
> +/* DA9150_CONFIG_C = 0x0E2 */
> +#define DA9150_VSYS_MIN_SHIFT			3
> +#define DA9150_VSYS_MIN_MASK			(0x1f << 3)
> +
> +/* DA9150_CONFIG_D = 0x0E3 */
> +#define DA9150_LFOSC_EXT_SHIFT			0
> +#define DA9150_LFOSC_EXT_MASK			(0x01 << 0)
> +#define DA9150_VDD33_DWN_SHIFT			1
> +#define DA9150_VDD33_DWN_MASK			(0x01 << 1)
> +#define DA9150_WKUP_PM_EN_SHIFT			2
> +#define DA9150_WKUP_PM_EN_MASK			(0x01 << 2)
> +#define DA9150_WKUP_CE_SEL_SHIFT		3
> +#define DA9150_WKUP_CE_SEL_MASK			(0x03 << 3)
> +#define DA9150_WKUP_CLK32K_EN_SHIFT		5
> +#define DA9150_WKUP_CLK32K_EN_MASK		(0x01 << 5)
> +#define DA9150_DISABLE_DEL_SHIFT		7
> +#define DA9150_DISABLE_DEL_MASK			(0x01 << 7)
> +
> +/* DA9150_CONFIG_E = 0x0E4 */
> +#define DA9150_PM_SPKSUP_DIS_SHIFT		0
> +#define DA9150_PM_SPKSUP_DIS_MASK		(0x01 << 0)
> +#define DA9150_PM_MERGE_SHIFT			1
> +#define DA9150_PM_MERGE_MASK			(0x01 << 1)
> +#define DA9150_PM_SR_OFF_SHIFT			2
> +#define DA9150_PM_SR_OFF_MASK			(0x01 << 2)
> +#define DA9150_PM_TIMEOUT_EN_SHIFT		3
> +#define DA9150_PM_TIMEOUT_EN_MASK		(0x01 << 3)
> +#define DA9150_PM_DLY_SEL_SHIFT			4
> +#define DA9150_PM_DLY_SEL_MASK			(0x07 << 4)
> +#define DA9150_PM_OUT_DLY_SEL_SHIFT		7
> +#define DA9150_PM_OUT_DLY_SEL_MASK		(0x01 << 7)
> +
> +/* DA9150_CONTROL_A = 0x0E5 */
> +#define DA9150_VDD33_SL_SHIFT			0
> +#define DA9150_VDD33_SL_MASK			(0x01 << 0)
> +#define DA9150_VDD33_LPM_SHIFT			1
> +#define DA9150_VDD33_LPM_MASK			(0x03 << 1)
> +#define DA9150_VDD33_EN_SHIFT			3
> +#define DA9150_VDD33_EN_MASK			(0x01 << 3)
> +#define DA9150_GPI_LPM_SHIFT			6
> +#define DA9150_GPI_LPM_MASK			(0x01 << 6)
> +#define DA9150_PM_IF_LPM_SHIFT			7
> +#define DA9150_PM_IF_LPM_MASK			(0x01 << 7)
> +
> +/* DA9150_CONTROL_B = 0x0E6 */
> +#define DA9150_LPM_SHIFT			0
> +#define DA9150_LPM_MASK				(0x01 << 0)
> +#define DA9150_RESET_SHIFT			1
> +#define DA9150_RESET_MASK			(0x01 << 1)
> +#define DA9150_RESET_USRCONF_EN_SHIFT		2
> +#define DA9150_RESET_USRCONF_EN_MASK		(0x01 << 2)
> +
> +/* DA9150_CONTROL_C = 0x0E7 */
> +#define DA9150_DISABLE_SHIFT			0
> +#define DA9150_DISABLE_MASK			(0x01 << 0)
> +
> +/* DA9150_GPIO_A_B = 0x0E8 */
> +#define DA9150_GPIOA_PIN_SHIFT			0
> +#define DA9150_GPIOA_PIN_MASK			(0x07 << 0)
> +#define DA9150_GPIOA_PIN_GPI			(0x00 << 0)
> +#define DA9150_GPIOA_PIN_GPO_OD			(0x01 << 0)
> +#define DA9150_GPIOA_TYPE_SHIFT			3
> +#define DA9150_GPIOA_TYPE_MASK			(0x01 << 3)
> +#define DA9150_GPIOB_PIN_SHIFT			4
> +#define DA9150_GPIOB_PIN_MASK			(0x07 << 4)
> +#define DA9150_GPIOB_PIN_GPI			(0x00 << 4)
> +#define DA9150_GPIOB_PIN_GPO_OD			(0x01 << 4)
> +#define DA9150_GPIOB_TYPE_SHIFT			7
> +#define DA9150_GPIOB_TYPE_MASK			(0x01 << 7)
> +
> +/* DA9150_GPIO_C_D = 0x0E9 */
> +#define DA9150_GPIOC_PIN_SHIFT			0
> +#define DA9150_GPIOC_PIN_MASK			(0x07 << 0)
> +#define DA9150_GPIOC_PIN_GPI			(0x00 << 0)
> +#define DA9150_GPIOC_PIN_GPO_OD			(0x01 << 0)
> +#define DA9150_GPIOC_TYPE_SHIFT			3
> +#define DA9150_GPIOC_TYPE_MASK			(0x01 << 3)
> +#define DA9150_GPIOD_PIN_SHIFT			4
> +#define DA9150_GPIOD_PIN_MASK			(0x07 << 4)
> +#define DA9150_GPIOD_PIN_GPI			(0x00 << 4)
> +#define DA9150_GPIOD_PIN_GPO_OD			(0x01 << 4)
> +#define DA9150_GPIOD_TYPE_SHIFT			7
> +#define DA9150_GPIOD_TYPE_MASK			(0x01 << 7)
> +
> +/* DA9150_GPIO_MODE_CONT = 0x0EA */
> +#define DA9150_GPIOA_MODE_SHIFT			0
> +#define DA9150_GPIOA_MODE_MASK			(0x01 << 0)
> +#define DA9150_GPIOB_MODE_SHIFT			1
> +#define DA9150_GPIOB_MODE_MASK			(0x01 << 1)
> +#define DA9150_GPIOC_MODE_SHIFT			2
> +#define DA9150_GPIOC_MODE_MASK			(0x01 << 2)
> +#define DA9150_GPIOD_MODE_SHIFT			3
> +#define DA9150_GPIOD_MODE_MASK			(0x01 << 3)
> +#define DA9150_GPIOA_CONT_SHIFT			4
> +#define DA9150_GPIOA_CONT_MASK			(0x01 << 4)
> +#define DA9150_GPIOB_CONT_SHIFT			5
> +#define DA9150_GPIOB_CONT_MASK			(0x01 << 5)
> +#define DA9150_GPIOC_CONT_SHIFT			6
> +#define DA9150_GPIOC_CONT_MASK			(0x01 << 6)
> +#define DA9150_GPIOD_CONT_SHIFT			7
> +#define DA9150_GPIOD_CONT_MASK			(0x01 << 7)
> +
> +/* DA9150_GPIO_CTRL_B = 0x0EB */
> +#define DA9150_WAKE_PIN_SHIFT			0
> +#define DA9150_WAKE_PIN_MASK			(0x03 << 0)
> +#define DA9150_WAKE_MODE_SHIFT			2
> +#define DA9150_WAKE_MODE_MASK			(0x01 << 2)
> +#define DA9150_WAKE_CONT_SHIFT			3
> +#define DA9150_WAKE_CONT_MASK			(0x01 << 3)
> +#define DA9150_WAKE_DLY_SHIFT			4
> +#define DA9150_WAKE_DLY_MASK			(0x01 << 4)
> +
> +/* DA9150_GPIO_CTRL_A = 0x0EC */
> +#define DA9150_GPIOA_ANAEN_SHIFT		0
> +#define DA9150_GPIOA_ANAEN_MASK			(0x01 << 0)
> +#define DA9150_GPIOB_ANAEN_SHIFT		1
> +#define DA9150_GPIOB_ANAEN_MASK			(0x01 << 1)
> +#define DA9150_GPIOC_ANAEN_SHIFT		2
> +#define DA9150_GPIOC_ANAEN_MASK			(0x01 << 2)
> +#define DA9150_GPIOD_ANAEN_SHIFT		3
> +#define DA9150_GPIOD_ANAEN_MASK			(0x01 << 3)
> +#define DA9150_GPIO_ANAEN			0x01
> +#define DA9150_GPIO_ANAEN_MASK			0x0F
> +#define DA9150_CHGLED_PIN_SHIFT			5
> +#define DA9150_CHGLED_PIN_MASK			(0x07 << 5)
> +
> +/* DA9150_GPIO_CTRL_C = 0x0ED */
> +#define DA9150_CHGBL_DUR_SHIFT			0
> +#define DA9150_CHGBL_DUR_MASK			(0x03 << 0)
> +#define DA9150_CHGBL_DBL_SHIFT			2
> +#define DA9150_CHGBL_DBL_MASK			(0x01 << 2)
> +#define DA9150_CHGBL_FRQ_SHIFT			3
> +#define DA9150_CHGBL_FRQ_MASK			(0x03 << 3)
> +#define DA9150_CHGBL_FLKR_SHIFT			5
> +#define DA9150_CHGBL_FLKR_MASK			(0x01 << 5)
> +
> +/* DA9150_GPIO_CFG_A = 0x0EE */
> +#define DA9150_CE_LPM_DEB_SHIFT			0
> +#define DA9150_CE_LPM_DEB_MASK			(0x07 << 0)
> +
> +/* DA9150_GPIO_CFG_B = 0x0EF */
> +#define DA9150_GPIOA_PUPD_SHIFT			0
> +#define DA9150_GPIOA_PUPD_MASK			(0x01 << 0)
> +#define DA9150_GPIOB_PUPD_SHIFT			1
> +#define DA9150_GPIOB_PUPD_MASK			(0x01 << 1)
> +#define DA9150_GPIOC_PUPD_SHIFT			2
> +#define DA9150_GPIOC_PUPD_MASK			(0x01 << 2)
> +#define DA9150_GPIOD_PUPD_SHIFT			3
> +#define DA9150_GPIOD_PUPD_MASK			(0x01 << 3)
> +#define DA9150_GPIO_PUPD_MASK			(0xF << 0)
> +#define DA9150_GPI_DEB_SHIFT			4
> +#define DA9150_GPI_DEB_MASK			(0x07 << 4)
> +#define DA9150_LPM_EN_SHIFT			7
> +#define DA9150_LPM_EN_MASK			(0x01 << 7)
> +
> +/* DA9150_GPIO_CFG_C = 0x0F0 */
> +#define DA9150_GPI_V_SHIFT			0
> +#define DA9150_GPI_V_MASK			(0x01 << 0)
> +#define DA9150_VDDIO_INT_SHIFT			1
> +#define DA9150_VDDIO_INT_MASK			(0x01 << 1)
> +#define DA9150_FAULT_PIN_SHIFT			3
> +#define DA9150_FAULT_PIN_MASK			(0x07 << 3)
> +#define DA9150_FAULT_TYPE_SHIFT			6
> +#define DA9150_FAULT_TYPE_MASK			(0x01 << 6)
> +#define DA9150_NIRQ_PUPD_SHIFT			7
> +#define DA9150_NIRQ_PUPD_MASK			(0x01 << 7)
> +
> +/* DA9150_GPADC_MAN = 0x0F2 */
> +#define DA9150_GPADC_EN_SHIFT			0
> +#define DA9150_GPADC_EN_MASK			(0x01 << 0)
> +#define DA9150_GPADC_MUX_SHIFT			1
> +#define DA9150_GPADC_MUX_MASK			(0x1f << 1)
> +
> +/* DA9150_GPADC_RES_A = 0x0F4 */
> +#define DA9150_GPADC_RES_H_SHIFT		0
> +#define DA9150_GPADC_RES_H_MASK			(0xff << 0)
> +
> +/* DA9150_GPADC_RES_B = 0x0F5 */
> +#define DA9150_GPADC_RUN_SHIFT			0
> +#define DA9150_GPADC_RUN_MASK			(0x01 << 0)
> +#define DA9150_GPADC_RES_L_SHIFT		6
> +#define DA9150_GPADC_RES_L_MASK			(0x03 << 6)
> +
> +/* DA9150_PAGE_CON_2 = 0x100 */
> +#define DA9150_PAGE_SHIFT			0
> +#define DA9150_PAGE_MASK			(0x3f << 0)
> +#define DA9150_WRITE_MODE_SHIFT			6
> +#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
> +#define DA9150_REVERT_SHIFT			7
> +#define DA9150_REVERT_MASK			(0x01 << 7)
> +
> +/* DA9150_OTP_CONT_SHARED = 0x101 */
> +#define DA9150_PC_DONE_SHIFT			3
> +#define DA9150_PC_DONE_MASK			(0x01 << 3)
> +
> +/* DA9150_INTERFACE_SHARED = 0x105 */
> +#define DA9150_IF_BASE_ADDR_SHIFT		4
> +#define DA9150_IF_BASE_ADDR_MASK		(0x0f << 4)
> +
> +/* DA9150_CONFIG_A_SHARED = 0x106 */
> +#define DA9150_NIRQ_VDD_SHIFT			1
> +#define DA9150_NIRQ_VDD_MASK			(0x01 << 1)
> +#define DA9150_NIRQ_PIN_SHIFT			2
> +#define DA9150_NIRQ_PIN_MASK			(0x01 << 2)
> +#define DA9150_NIRQ_TYPE_SHIFT			3
> +#define DA9150_NIRQ_TYPE_MASK			(0x01 << 3)
> +#define DA9150_PM_IF_V_SHIFT			4
> +#define DA9150_PM_IF_V_MASK			(0x01 << 4)
> +#define DA9150_PM_IF_FMP_SHIFT			5
> +#define DA9150_PM_IF_FMP_MASK			(0x01 << 5)
> +#define DA9150_PM_IF_HSM_SHIFT			6
> +#define DA9150_PM_IF_HSM_MASK			(0x01 << 6)
> +
> +/* DA9150_CONFIG_D_SHARED = 0x109 */
> +#define DA9150_NIRQ_MODE_SHIFT			1
> +#define DA9150_NIRQ_MODE_MASK			(0x01 << 1)
> +
> +/* DA9150_ADETVB_CFG_C = 0x150 */
> +#define DA9150_TADP_RISE_SHIFT			0
> +#define DA9150_TADP_RISE_MASK			(0xff << 0)
> +
> +/* DA9150_ADETD_STAT = 0x151 */
> +#define DA9150_DCD_STAT_SHIFT			0
> +#define DA9150_DCD_STAT_MASK			(0x01 << 0)
> +#define DA9150_PCD_STAT_SHIFT			1
> +#define DA9150_PCD_STAT_MASK			(0x03 << 1)
> +#define DA9150_SCD_STAT_SHIFT			3
> +#define DA9150_SCD_STAT_MASK			(0x03 << 3)
> +#define DA9150_DP_STAT_SHIFT			5
> +#define DA9150_DP_STAT_MASK			(0x01 << 5)
> +#define DA9150_DM_STAT_SHIFT			6
> +#define DA9150_DM_STAT_MASK			(0x01 << 6)
> +
> +/* DA9150_ADET_CMPSTAT = 0x152 */
> +#define DA9150_DP_COMP_SHIFT			1
> +#define DA9150_DP_COMP_MASK			(0x01 << 1)
> +#define DA9150_DM_COMP_SHIFT			2
> +#define DA9150_DM_COMP_MASK			(0x01 << 2)
> +#define DA9150_ADP_SNS_COMP_SHIFT		3
> +#define DA9150_ADP_SNS_COMP_MASK		(0x01 << 3)
> +#define DA9150_ADP_PRB_COMP_SHIFT		4
> +#define DA9150_ADP_PRB_COMP_MASK		(0x01 << 4)
> +#define DA9150_ID_COMP_SHIFT			5
> +#define DA9150_ID_COMP_MASK			(0x01 << 5)
> +
> +/* DA9150_ADET_CTRL_A = 0x153 */
> +#define DA9150_AID_DAT_SHIFT			0
> +#define DA9150_AID_DAT_MASK			(0x01 << 0)
> +#define DA9150_AID_ID_SHIFT			1
> +#define DA9150_AID_ID_MASK			(0x01 << 1)
> +#define DA9150_AID_TRIG_SHIFT			2
> +#define DA9150_AID_TRIG_MASK			(0x01 << 2)
> +
> +/* DA9150_ADETVB_CFG_B = 0x154 */
> +#define DA9150_VB_MODE_SHIFT			0
> +#define DA9150_VB_MODE_MASK			(0x03 << 0)
> +#define DA9150_VB_MODE_VB_SESS			(0x01 << 0)
> +
> +#define DA9150_TADP_PRB_SHIFT			2
> +#define DA9150_TADP_PRB_MASK			(0x01 << 2)
> +#define DA9150_DAT_RPD_EXT_SHIFT		5
> +#define DA9150_DAT_RPD_EXT_MASK			(0x01 << 5)
> +#define DA9150_CONF_RPD_SHIFT			6
> +#define DA9150_CONF_RPD_MASK			(0x01 << 6)
> +#define DA9150_CONF_SRP_SHIFT			7
> +#define DA9150_CONF_SRP_MASK			(0x01 << 7)
> +
> +/* DA9150_ADETVB_CFG_A = 0x155 */
> +#define DA9150_AID_MODE_SHIFT			0
> +#define DA9150_AID_MODE_MASK			(0x03 << 0)
> +#define DA9150_AID_EXT_POL_SHIFT		2
> +#define DA9150_AID_EXT_POL_MASK			(0x01 << 2)
> +
> +/* DA9150_ADETAC_CFG_A = 0x156 */
> +#define DA9150_ISET_CDP_SHIFT			0
> +#define DA9150_ISET_CDP_MASK			(0x1f << 0)
> +#define DA9150_CONF_DBP_SHIFT			5
> +#define DA9150_CONF_DBP_MASK			(0x01 << 5)
> +
> +/* DA9150_ADDETAC_CFG_B = 0x157 */
> +#define DA9150_ISET_DCHG_SHIFT			0
> +#define DA9150_ISET_DCHG_MASK			(0x1f << 0)
> +#define DA9150_CONF_GPIOA_SHIFT			5
> +#define DA9150_CONF_GPIOA_MASK			(0x01 << 5)
> +#define DA9150_CONF_GPIOB_SHIFT			6
> +#define DA9150_CONF_GPIOB_MASK			(0x01 << 6)
> +#define DA9150_AID_VB_SHIFT			7
> +#define DA9150_AID_VB_MASK			(0x01 << 7)
> +
> +/* DA9150_ADETAC_CFG_C = 0x158 */
> +#define DA9150_ISET_DEF_SHIFT			0
> +#define DA9150_ISET_DEF_MASK			(0x1f << 0)
> +#define DA9150_CONF_MODE_SHIFT			5
> +#define DA9150_CONF_MODE_MASK			(0x03 << 5)
> +#define DA9150_AID_CR_DIS_SHIFT			7
> +#define DA9150_AID_CR_DIS_MASK			(0x01 << 7)
> +
> +/* DA9150_ADETAC_CFG_D = 0x159 */
> +#define DA9150_ISET_UNIT_SHIFT			0
> +#define DA9150_ISET_UNIT_MASK			(0x1f << 0)
> +#define DA9150_AID_UNCLAMP_SHIFT		5
> +#define DA9150_AID_UNCLAMP_MASK			(0x01 << 5)
> +
> +/* DA9150_ADETVB_CFG_D = 0x15A */
> +#define DA9150_ID_MODE_SHIFT			0
> +#define DA9150_ID_MODE_MASK			(0x03 << 0)
> +#define DA9150_DAT_MODE_SHIFT			2
> +#define DA9150_DAT_MODE_MASK			(0x0f << 2)
> +#define DA9150_DAT_SWP_SHIFT			6
> +#define DA9150_DAT_SWP_MASK			(0x01 << 6)
> +#define DA9150_DAT_CLAMP_EXT_SHIFT		7
> +#define DA9150_DAT_CLAMP_EXT_MASK		(0x01 << 7)
> +
> +/* DA9150_ADETID_CFG_A = 0x15B */
> +#define DA9150_TID_POLL_SHIFT			0
> +#define DA9150_TID_POLL_MASK			(0x07 << 0)
> +#define DA9150_RID_CONV_SHIFT			3
> +#define DA9150_RID_CONV_MASK			(0x01 << 3)
> +
> +/* DA9150_ADET_RID_PT_CHG_H = 0x15C */
> +#define DA9150_RID_PT_CHG_H_SHIFT		0
> +#define DA9150_RID_PT_CHG_H_MASK		(0xff << 0)
> +
> +/* DA9150_ADET_RID_PT_CHG_L = 0x15D */
> +#define DA9150_RID_PT_CHG_L_SHIFT		6
> +#define DA9150_RID_PT_CHG_L_MASK		(0x03 << 6)
> +
> +/* DA9150_PPR_TCTR_B = 0x160 */
> +#define DA9150_CHG_TCTR_VAL_SHIFT		0
> +#define DA9150_CHG_TCTR_VAL_MASK		(0xff << 0)
> +
> +/* DA9150_PPR_BKCTRL_A = 0x163 */
> +#define DA9150_VBUS_MODE_SHIFT			0
> +#define DA9150_VBUS_MODE_MASK			(0x03 << 0)
> +#define DA9150_VBUS_MODE_CHG			(0x01 << 0)
> +#define DA9150_VBUS_MODE_OTG			(0x02 << 0)
> +#define DA9150_VBUS_LPM_SHIFT			2
> +#define DA9150_VBUS_LPM_MASK			(0x03 << 2)
> +#define DA9150_VBUS_SUSP_SHIFT			4
> +#define DA9150_VBUS_SUSP_MASK			(0x01 << 4)
> +#define DA9150_VBUS_PWM_SHIFT			5
> +#define DA9150_VBUS_PWM_MASK			(0x01 << 5)
> +#define DA9150_VBUS_ISO_SHIFT			6
> +#define DA9150_VBUS_ISO_MASK			(0x01 << 6)
> +#define DA9150_VBUS_LDO_SHIFT			7
> +#define DA9150_VBUS_LDO_MASK			(0x01 << 7)
> +
> +/* DA9150_PPR_BKCFG_A = 0x164 */
> +#define DA9150_VBUS_ISET_SHIFT			0
> +#define DA9150_VBUS_ISET_MASK			(0x1f << 0)
> +#define DA9150_VBUS_IMAX_SHIFT			5
> +#define DA9150_VBUS_IMAX_MASK			(0x01 << 5)
> +#define DA9150_VBUS_IOTG_SHIFT			6
> +#define DA9150_VBUS_IOTG_MASK			(0x03 << 6)
> +
> +/* DA9150_PPR_BKCFG_B = 0x165 */
> +#define DA9150_VBUS_DROP_SHIFT			0
> +#define DA9150_VBUS_DROP_MASK			(0x0f << 0)
> +#define DA9150_VBUS_FAULT_DIS_SHIFT		6
> +#define DA9150_VBUS_FAULT_DIS_MASK		(0x01 << 6)
> +#define DA9150_OTG_FAULT_DIS_SHIFT		7
> +#define DA9150_OTG_FAULT_DIS_MASK		(0x01 << 7)
> +
> +/* DA9150_PPR_CHGCTRL_A = 0x166 */
> +#define DA9150_CHG_EN_SHIFT			0
> +#define DA9150_CHG_EN_MASK			(0x01 << 0)
> +
> +/* DA9150_PPR_CHGCTRL_B = 0x167 */
> +#define DA9150_CHG_VBAT_SHIFT			0
> +#define DA9150_CHG_VBAT_MASK			(0x1f << 0)
> +#define DA9150_CHG_VDROP_SHIFT			6
> +#define DA9150_CHG_VDROP_MASK			(0x03 << 6)
> +
> +/* DA9150_PPR_CHGCTRL_C = 0x168 */
> +#define DA9150_CHG_VFAULT_SHIFT			0
> +#define DA9150_CHG_VFAULT_MASK			(0x0f << 0)
> +#define DA9150_CHG_IPRE_SHIFT			4
> +#define DA9150_CHG_IPRE_MASK			(0x03 << 4)
> +
> +/* DA9150_PPR_TCTR_A = 0x169 */
> +#define DA9150_CHG_TCTR_SHIFT			0
> +#define DA9150_CHG_TCTR_MASK			(0x07 << 0)
> +#define DA9150_CHG_TCTR_MODE_SHIFT		4
> +#define DA9150_CHG_TCTR_MODE_MASK		(0x01 << 4)
> +
> +/* DA9150_PPR_CHGCTRL_D = 0x16A */
> +#define DA9150_CHG_IBAT_SHIFT			0
> +#define DA9150_CHG_IBAT_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_CHGCTRL_E = 0x16B */
> +#define DA9150_CHG_IEND_SHIFT			0
> +#define DA9150_CHG_IEND_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_CHGCTRL_F = 0x16C */
> +#define DA9150_CHG_VCOLD_SHIFT			0
> +#define DA9150_CHG_VCOLD_MASK			(0x1f << 0)
> +#define DA9150_TBAT_TQA_EN_SHIFT		6
> +#define DA9150_TBAT_TQA_EN_MASK			(0x01 << 6)
> +#define DA9150_TBAT_TDP_EN_SHIFT		7
> +#define DA9150_TBAT_TDP_EN_MASK			(0x01 << 7)
> +
> +/* DA9150_PPR_CHGCTRL_G = 0x16D */
> +#define DA9150_CHG_VWARM_SHIFT			0
> +#define DA9150_CHG_VWARM_MASK			(0x1f << 0)
> +
> +/* DA9150_PPR_CHGCTRL_H = 0x16E */
> +#define DA9150_CHG_VHOT_SHIFT			0
> +#define DA9150_CHG_VHOT_MASK			(0x1f << 0)
> +
> +/* DA9150_PPR_CHGCTRL_I = 0x16F */
> +#define DA9150_CHG_ICOLD_SHIFT			0
> +#define DA9150_CHG_ICOLD_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_CHGCTRL_J = 0x170 */
> +#define DA9150_CHG_IWARM_SHIFT			0
> +#define DA9150_CHG_IWARM_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_CHGCTRL_K = 0x171 */
> +#define DA9150_CHG_IHOT_SHIFT			0
> +#define DA9150_CHG_IHOT_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_CHGCTRL_L = 0x172 */
> +#define DA9150_CHG_IBAT_TRED_SHIFT		0
> +#define DA9150_CHG_IBAT_TRED_MASK		(0xff << 0)
> +
> +/* DA9150_PPR_CHGCTRL_M = 0x173 */
> +#define DA9150_CHG_VFLOAT_SHIFT			0
> +#define DA9150_CHG_VFLOAT_MASK			(0x0f << 0)
> +#define DA9150_CHG_LPM_SHIFT			5
> +#define DA9150_CHG_LPM_MASK			(0x01 << 5)
> +#define DA9150_CHG_NBLO_SHIFT			6
> +#define DA9150_CHG_NBLO_MASK			(0x01 << 6)
> +#define DA9150_EBS_EN_SHIFT			7
> +#define DA9150_EBS_EN_MASK			(0x01 << 7)
> +
> +/* DA9150_PPR_THYST_A = 0x174 */
> +#define DA9150_TBAT_T1_SHIFT			0
> +#define DA9150_TBAT_T1_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_THYST_B = 0x175 */
> +#define DA9150_TBAT_T2_SHIFT			0
> +#define DA9150_TBAT_T2_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_THYST_C = 0x176 */
> +#define DA9150_TBAT_T3_SHIFT			0
> +#define DA9150_TBAT_T3_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_THYST_D = 0x177 */
> +#define DA9150_TBAT_T4_SHIFT			0
> +#define DA9150_TBAT_T4_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_THYST_E = 0x178 */
> +#define DA9150_TBAT_T5_SHIFT			0
> +#define DA9150_TBAT_T5_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_THYST_F = 0x179 */
> +#define DA9150_TBAT_H1_SHIFT			0
> +#define DA9150_TBAT_H1_MASK			(0xff << 0)
> +
> +/* DA9150_PPR_THYST_G = 0x17A */
> +#define DA9150_TBAT_H5_SHIFT			0
> +#define DA9150_TBAT_H5_MASK			(0xff << 0)
> +
> +/* DA9150_PAGE_CON_3 = 0x180 */
> +#define DA9150_PAGE_SHIFT			0
> +#define DA9150_PAGE_MASK			(0x3f << 0)
> +#define DA9150_WRITE_MODE_SHIFT			6
> +#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
> +#define DA9150_REVERT_SHIFT			7
> +#define DA9150_REVERT_MASK			(0x01 << 7)
> +
> +/* DA9150_PAGE_CON_4 = 0x200 */
> +#define DA9150_PAGE_SHIFT			0
> +#define DA9150_PAGE_MASK			(0x3f << 0)
> +#define DA9150_WRITE_MODE_SHIFT			6
> +#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
> +#define DA9150_REVERT_SHIFT			7
> +#define DA9150_REVERT_MASK			(0x01 << 7)
> +
> +/* DA9150_PAGE_CON_5 = 0x280 */
> +#define DA9150_PAGE_SHIFT			0
> +#define DA9150_PAGE_MASK			(0x3f << 0)
> +#define DA9150_WRITE_MODE_SHIFT			6
> +#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
> +#define DA9150_REVERT_SHIFT			7
> +#define DA9150_REVERT_MASK			(0x01 << 7)
> +
> +/* DA9150_PAGE_CON_6 = 0x300 */
> +#define DA9150_PAGE_SHIFT			0
> +#define DA9150_PAGE_MASK			(0x3f << 0)
> +#define DA9150_WRITE_MODE_SHIFT			6
> +#define DA9150_WRITE_MODE_MASK			(0x01 << 6)
> +#define DA9150_REVERT_SHIFT			7
> +#define DA9150_REVERT_MASK			(0x01 << 7)
> +
> +/* DA9150_COREBTLD_STAT_A = 0x302 */
> +#define DA9150_BOOTLD_STAT_SHIFT		0
> +#define DA9150_BOOTLD_STAT_MASK			(0x03 << 0)
> +#define DA9150_CORE_LOCKUP_SHIFT		2
> +#define DA9150_CORE_LOCKUP_MASK			(0x01 << 2)
> +
> +/* DA9150_COREBTLD_CTRL_A = 0x303 */
> +#define DA9150_CORE_RESET_SHIFT			0
> +#define DA9150_CORE_RESET_MASK			(0x01 << 0)
> +#define DA9150_CORE_STOP_SHIFT			1
> +#define DA9150_CORE_STOP_MASK			(0x01 << 1)
> +
> +/* DA9150_CORE_CONFIG_A = 0x304 */
> +#define DA9150_CORE_MEMMUX_SHIFT		0
> +#define DA9150_CORE_MEMMUX_MASK			(0x03 << 0)
> +#define DA9150_WDT_AUTO_START_SHIFT		2
> +#define DA9150_WDT_AUTO_START_MASK		(0x01 << 2)
> +#define DA9150_WDT_AUTO_LOCK_SHIFT		3
> +#define DA9150_WDT_AUTO_LOCK_MASK		(0x01 << 3)
> +#define DA9150_WDT_HLT_NO_CLK_SHIFT		4
> +#define DA9150_WDT_HLT_NO_CLK_MASK		(0x01 << 4)
> +
> +/* DA9150_CORE_CONFIG_C = 0x305 */
> +#define DA9150_CORE_SW_SIZE_SHIFT		0
> +#define DA9150_CORE_SW_SIZE_MASK		(0xff << 0)
> +
> +/* DA9150_CORE_CONFIG_B = 0x306 */
> +#define DA9150_BOOTLD_EN_SHIFT			0
> +#define DA9150_BOOTLD_EN_MASK			(0x01 << 0)
> +#define DA9150_CORE_EN_SHIFT			2
> +#define DA9150_CORE_EN_MASK			(0x01 << 2)
> +#define DA9150_CORE_SW_SRC_SHIFT		3
> +#define DA9150_CORE_SW_SRC_MASK			(0x07 << 3)
> +#define DA9150_DEEP_SLEEP_EN_SHIFT		7
> +#define DA9150_DEEP_SLEEP_EN_MASK		(0x01 << 7)
> +
> +/* DA9150_CORE_CFG_DATA_A = 0x307 */
> +#define DA9150_CORE_CFG_DT_A_SHIFT		0
> +#define DA9150_CORE_CFG_DT_A_MASK		(0xff << 0)
> +
> +/* DA9150_CORE_CFG_DATA_B = 0x308 */
> +#define DA9150_CORE_CFG_DT_B_SHIFT		0
> +#define DA9150_CORE_CFG_DT_B_MASK		(0xff << 0)
> +
> +/* DA9150_CORE_CMD_A = 0x309 */
> +#define DA9150_CORE_CMD_SHIFT			0
> +#define DA9150_CORE_CMD_MASK			(0xff << 0)
> +
> +/* DA9150_CORE_DATA_A = 0x30A */
> +#define DA9150_CORE_DATA_0_SHIFT		0
> +#define DA9150_CORE_DATA_0_MASK			(0xff << 0)
> +
> +/* DA9150_CORE_DATA_B = 0x30B */
> +#define DA9150_CORE_DATA_1_SHIFT		0
> +#define DA9150_CORE_DATA_1_MASK			(0xff << 0)
> +
> +/* DA9150_CORE_DATA_C = 0x30C */
> +#define DA9150_CORE_DATA_2_SHIFT		0
> +#define DA9150_CORE_DATA_2_MASK			(0xff << 0)
> +
> +/* DA9150_CORE_DATA_D = 0x30D */
> +#define DA9150_CORE_DATA_3_SHIFT		0
> +#define DA9150_CORE_DATA_3_MASK			(0xff << 0)
> +
> +/* DA9150_CORE2WIRE_STAT_A = 0x310 */
> +#define DA9150_FW_FWDL_ERR_SHIFT		7
> +#define DA9150_FW_FWDL_ERR_MASK			(0x01 << 7)
> +
> +/* DA9150_CORE2WIRE_CTRL_A = 0x311 */
> +#define DA9150_FW_FWDL_EN_SHIFT			0
> +#define DA9150_FW_FWDL_EN_MASK			(0x01 << 0)
> +#define DA9150_FG_QIF_EN_SHIFT			1
> +#define DA9150_FG_QIF_EN_MASK			(0x01 << 1)
> +#define DA9150_CORE_BASE_ADDR_SHIFT		4
> +#define DA9150_CORE_BASE_ADDR_MASK		(0x0f << 4)
> +
> +/* DA9150_FW_CTRL_A = 0x312 */
> +#define DA9150_FW_SEAL_SHIFT			0
> +#define DA9150_FW_SEAL_MASK			(0xff << 0)
> +
> +/* DA9150_FW_CTRL_C = 0x313 */
> +#define DA9150_FW_FWDL_CRC_SHIFT		0
> +#define DA9150_FW_FWDL_CRC_MASK			(0xff << 0)
> +
> +/* DA9150_FW_CTRL_D = 0x314 */
> +#define DA9150_FW_FWDL_BASE_SHIFT		0
> +#define DA9150_FW_FWDL_BASE_MASK		(0x0f << 0)
> +
> +/* DA9150_FG_CTRL_A = 0x315 */
> +#define DA9150_FG_QIF_CODE_SHIFT		0
> +#define DA9150_FG_QIF_CODE_MASK			(0xff << 0)
> +
> +/* DA9150_FG_CTRL_B = 0x316 */
> +#define DA9150_FG_QIF_VALUE_SHIFT		0
> +#define DA9150_FG_QIF_VALUE_MASK		(0xff << 0)
> +
> +/* DA9150_FW_CTRL_E = 0x317 */
> +#define DA9150_FW_FWDL_SEG_SHIFT		0
> +#define DA9150_FW_FWDL_SEG_MASK			(0xff << 0)
> +
> +/* DA9150_FW_CTRL_B = 0x318 */
> +#define DA9150_FW_FWDL_VALUE_SHIFT		0
> +#define DA9150_FW_FWDL_VALUE_MASK		(0xff << 0)
> +
> +/* DA9150_GPADC_CMAN = 0x320 */
> +#define DA9150_GPADC_CEN_SHIFT			0
> +#define DA9150_GPADC_CEN_MASK			(0x01 << 0)
> +#define DA9150_GPADC_CMUX_SHIFT			1
> +#define DA9150_GPADC_CMUX_MASK			(0x1f << 1)
> +
> +/* DA9150_GPADC_CRES_A = 0x322 */
> +#define DA9150_GPADC_CRES_H_SHIFT		0
> +#define DA9150_GPADC_CRES_H_MASK		(0xff << 0)
> +
> +/* DA9150_GPADC_CRES_B = 0x323 */
> +#define DA9150_GPADC_CRUN_SHIFT			0
> +#define DA9150_GPADC_CRUN_MASK			(0x01 << 0)
> +#define DA9150_GPADC_CRES_L_SHIFT		6
> +#define DA9150_GPADC_CRES_L_MASK		(0x03 << 6)
> +
> +/* DA9150_CC_CFG_A = 0x328 */
> +#define DA9150_CC_EN_SHIFT			0
> +#define DA9150_CC_EN_MASK			(0x01 << 0)
> +#define DA9150_CC_TIMEBASE_SHIFT		1
> +#define DA9150_CC_TIMEBASE_MASK			(0x03 << 1)
> +#define DA9150_CC_CFG_SHIFT			5
> +#define DA9150_CC_CFG_MASK			(0x03 << 5)
> +#define DA9150_CC_ENDLESS_MODE_SHIFT		7
> +#define DA9150_CC_ENDLESS_MODE_MASK		(0x01 << 7)
> +
> +/* DA9150_CC_CFG_B = 0x329 */
> +#define DA9150_CC_OPT_SHIFT			0
> +#define DA9150_CC_OPT_MASK			(0x03 << 0)
> +#define DA9150_CC_PREAMP_SHIFT			2
> +#define DA9150_CC_PREAMP_MASK			(0x03 << 2)
> +
> +/* DA9150_CC_ICHG_RES_A = 0x32A */
> +#define DA9150_CC_ICHG_RES_H_SHIFT		0
> +#define DA9150_CC_ICHG_RES_H_MASK		(0xff << 0)
> +
> +/* DA9150_CC_ICHG_RES_B = 0x32B */
> +#define DA9150_CC_ICHG_RES_L_SHIFT		3
> +#define DA9150_CC_ICHG_RES_L_MASK		(0x1f << 3)
> +
> +/* DA9150_CC_IAVG_RES_A = 0x32C */
> +#define DA9150_CC_IAVG_RES_H_SHIFT		0
> +#define DA9150_CC_IAVG_RES_H_MASK		(0xff << 0)
> +
> +/* DA9150_CC_IAVG_RES_B = 0x32D */
> +#define DA9150_CC_IAVG_RES_L_SHIFT		0
> +#define DA9150_CC_IAVG_RES_L_MASK		(0xff << 0)
> +
> +/* DA9150_TAUX_CTRL_A = 0x330 */
> +#define DA9150_TAUX_EN_SHIFT			0
> +#define DA9150_TAUX_EN_MASK			(0x01 << 0)
> +#define DA9150_TAUX_MOD_SHIFT			1
> +#define DA9150_TAUX_MOD_MASK			(0x01 << 1)
> +#define DA9150_TAUX_UPDATE_SHIFT		2
> +#define DA9150_TAUX_UPDATE_MASK			(0x01 << 2)
> +
> +/* DA9150_TAUX_RELOAD_H = 0x332 */
> +#define DA9150_TAUX_RLD_H_SHIFT			0
> +#define DA9150_TAUX_RLD_H_MASK			(0xff << 0)
> +
> +/* DA9150_TAUX_RELOAD_L = 0x333 */
> +#define DA9150_TAUX_RLD_L_SHIFT			3
> +#define DA9150_TAUX_RLD_L_MASK			(0x1f << 3)
> +
> +/* DA9150_TAUX_VALUE_H = 0x334 */
> +#define DA9150_TAUX_VAL_H_SHIFT			0
> +#define DA9150_TAUX_VAL_H_MASK			(0xff << 0)
> +
> +/* DA9150_TAUX_VALUE_L = 0x335 */
> +#define DA9150_TAUX_VAL_L_SHIFT			3
> +#define DA9150_TAUX_VAL_L_MASK			(0x1f << 3)
> +
> +/* DA9150_AUX_DATA_0 = 0x338 */
> +#define DA9150_AUX_DAT_0_SHIFT			0
> +#define DA9150_AUX_DAT_0_MASK			(0xff << 0)
> +
> +/* DA9150_AUX_DATA_1 = 0x339 */
> +#define DA9150_AUX_DAT_1_SHIFT			0
> +#define DA9150_AUX_DAT_1_MASK			(0xff << 0)
> +
> +/* DA9150_AUX_DATA_2 = 0x33A */
> +#define DA9150_AUX_DAT_2_SHIFT			0
> +#define DA9150_AUX_DAT_2_MASK			(0xff << 0)
> +
> +/* DA9150_AUX_DATA_3 = 0x33B */
> +#define DA9150_AUX_DAT_3_SHIFT			0
> +#define DA9150_AUX_DAT_3_MASK			(0xff << 0)
> +
> +/* DA9150_BIF_CTRL = 0x340 */
> +#define DA9150_BIF_ISRC_EN_SHIFT		0
> +#define DA9150_BIF_ISRC_EN_MASK			(0x01 << 0)
> +
> +/* DA9150_TBAT_CTRL_A = 0x342 */
> +#define DA9150_TBAT_EN_SHIFT			0
> +#define DA9150_TBAT_EN_MASK			(0x01 << 0)
> +#define DA9150_TBAT_SW1_SHIFT			1
> +#define DA9150_TBAT_SW1_MASK			(0x01 << 1)
> +#define DA9150_TBAT_SW2_SHIFT			2
> +#define DA9150_TBAT_SW2_MASK			(0x01 << 2)
> +
> +/* DA9150_TBAT_CTRL_B = 0x343 */
> +#define DA9150_TBAT_SW_FRC_SHIFT		0
> +#define DA9150_TBAT_SW_FRC_MASK			(0x01 << 0)
> +#define DA9150_TBAT_STAT_SW1_SHIFT		1
> +#define DA9150_TBAT_STAT_SW1_MASK		(0x01 << 1)
> +#define DA9150_TBAT_STAT_SW2_SHIFT		2
> +#define DA9150_TBAT_STAT_SW2_MASK		(0x01 << 2)
> +#define DA9150_TBAT_HIGH_CURR_SHIFT		3
> +#define DA9150_TBAT_HIGH_CURR_MASK		(0x01 << 3)
> +
> +/* DA9150_TBAT_RES_A = 0x344 */
> +#define DA9150_TBAT_RES_H_SHIFT			0
> +#define DA9150_TBAT_RES_H_MASK			(0xff << 0)
> +
> +/* DA9150_TBAT_RES_B = 0x345 */
> +#define DA9150_TBAT_RES_DIS_SHIFT		0
> +#define DA9150_TBAT_RES_DIS_MASK		(0x01 << 0)
> +#define DA9150_TBAT_RES_L_SHIFT			6
> +#define DA9150_TBAT_RES_L_MASK			(0x03 << 6)
> +
> +#endif /* _DA9150_REGISTERS_H */
> --
> 1.9.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


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

* Re: [PATCH 4/8] iio: Add support for DA9150 GPADC
  2014-06-11 16:56     ` Opensource [Adam Thomson]
@ 2014-06-15 19:55       ` Jonathan Cameron
  0 siblings, 0 replies; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-15 19:55 UTC (permalink / raw)
  To: Opensource [Adam Thomson], Lee Jones, Samuel Ortiz,
	linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org
  Cc: linux-kernel@vger.kernel.org, Support Opensource

On 11/06/14 17:56, Opensource [Adam Thomson] wrote:
> On June 11, 2014 17:35, Jonathon Cameron wrote:
>
>> Hi Adam. Silly question but what are the _ channels?
>>
>> I have put in a perhaps optimistic data sheet request via the website, throwing in
>> your name. Hope you don't mind!
>>
>> Jonathan
>
> Hi Jonathon. Some of the _channels are a different representation of the reading
> (e.g. different scale - one would be 0-6V range, and one would be 0-21V for
> example).
Why? That is, why present the data twice with the different scales?


> Others provide identical readings to the non _channel but have left
> those in to keep the channel numbering sane and easy to reference.
If there is a reason to support this functionality, this is not a sensible
way to do it!
>
> No problem regarding the request.
> N�����r��y���b�X��ǧv�^�)޺{.n�+����{��*"��^n�r���z�\x1a��h����&��\x1e�G���h�\x03(�階�ݢj"��\x1a�^[m�����z�ޖ���f���h���~�mml==
>


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

* Re: [PATCH 4/8] iio: Add support for DA9150 GPADC
  2014-06-11 11:11 ` [PATCH 4/8] iio: Add support for DA9150 GPADC Adam Thomson
  2014-06-11 16:34   ` Jonathan Cameron
@ 2014-06-15 20:19   ` Jonathan Cameron
  2014-06-16 15:58     ` Opensource [Adam Thomson]
  1 sibling, 1 reply; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-15 20:19 UTC (permalink / raw)
  To: Adam Thomson, Lee Jones, Samuel Ortiz, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

On 11/06/14 12:11, Adam Thomson wrote:
> This patch adds support for DA9150 Charger & Fuel-Gauge IC GPADC.
>
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Hi Adam

Reasonably clean code, but the _ channels stuff doesn't comply with the ABI
and is rather confusing.

If it really does make sense to allow reading these channels at different
ranges (presumably to enhance the effective adc resolution) then we need
to control this via existing ABIs. Controlling it via scale with a
range attribute if required (read only but changes with whatever the
scale attribute it set to).

Often, for slow parts at least it makes little sense to have provide
software support for variable input ranges.

Looking at what is covered, is it the case that only one option will make
sense for a given hardware setup? (cover the required range and nothing more).

If so, perhaps this wants to go into the device tree or similar?

Jonathan
> ---
>   drivers/iio/adc/Kconfig          |   9 +
>   drivers/iio/adc/Makefile         |   1 +
>   drivers/iio/adc/da9150-gpadc.c   | 396 +++++++++++++++++++++++++++++++++++++++
>   include/linux/mfd/da9150/gpadc.h |  71 +++++++
>   4 files changed, 477 insertions(+)
>   create mode 100644 drivers/iio/adc/da9150-gpadc.c
>   create mode 100644 include/linux/mfd/da9150/gpadc.h
>
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 24c28e3..f5e9f72 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -105,6 +105,15 @@ config AT91_ADC
>   	help
>   	  Say yes here to build support for Atmel AT91 ADC.
>
> +config DA9150_GPADC
> +	tristate "Dialog DA9150 GPADC driver support"
> +	depends on MFD_DA9150
> +	help
> +	  Say yes here to build support for Dialog DA9150 GPADC.
> +
> +	  This driver can also be built as a module. If chosen, the module name
> +	  will be da9150-gpadc.
> +
>   config EXYNOS_ADC
>   	tristate "Exynos ADC driver support"
>   	depends on OF
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index ab346d8..414b22f 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -12,6 +12,7 @@ obj-$(CONFIG_AD7791) += ad7791.o
>   obj-$(CONFIG_AD7793) += ad7793.o
>   obj-$(CONFIG_AD7887) += ad7887.o
>   obj-$(CONFIG_AT91_ADC) += at91_adc.o
> +obj-$(CONFIG_DA9150_GPADC) += da9150-gpadc.o
>   obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
>   obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
>   obj-$(CONFIG_MAX1363) += max1363.o
> diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
> new file mode 100644
> index 0000000..2107f86
> --- /dev/null
> +++ b/drivers/iio/adc/da9150-gpadc.c
> @@ -0,0 +1,396 @@
> +/*
> + * DA9150 GPADC Driver
> + *
> + * Copyright (c) 2014 Dialog Semiconductor
> + *
> + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> + *
> + * 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.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/slab.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/interrupt.h>
> +
> +#include <linux/mfd/da9150/core.h>
> +#include <linux/mfd/da9150/pdata.h>
> +#include <linux/mfd/da9150/registers.h>
> +#include <linux/mfd/da9150/gpadc.h>
> +
> +#include <linux/iio/iio.h>
> +#include <linux/iio/machine.h>
> +#include <linux/iio/driver.h>
> +
> +
> +/*
> + * IRQ Handling
Please get rid of excess white space and comments that just tell you
something obvious about the code following them.
> + */
> +
> +static irqreturn_t da9150_gpadc_irq(int irq, void *data)
> +{
> +
> +	struct da9150_gpadc *gpadc = data;
> +
> +	complete(&gpadc->complete);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +
> +/*
> + * GPADC access
> + */
> +
> +static inline int da9150_gpadc_gpio_2v_voltage_now(int raw_val)
> +{
> +	/* Convert to uV */
> +	return (((3 * ((raw_val * 1000) + 500)) / 2048) * 1000);
> +}
> +
> +static inline int da9150_gpadc_gpio_5v_voltage_now(int raw_val)
> +{
> +	/* Convert to uV */
> +	return (((6 * ((raw_val * 1000) + 500)) / 1024) * 1000);
> +}
> +
> +static inline int da9150_gpadc_ibus_current_avg(int raw_val)
> +{
> +	/* Convert to uA */
> +	return (((4 * ((raw_val * 1000) + 500)) / 2048) * 1000);
> +}
> +
> +static inline int da9150_gpadc_vbus_6v_voltage_now(int raw_val)
> +{
> +	/* Convert to uV */
> +	return (((3 * ((raw_val * 1000) + 500)) / 512) * 1000);
> +}
> +
> +static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
> +{
> +	/* Convert to uV */
> +	return (((21 * ((raw_val * 1000) + 500)) / 1024) * 1000);
> +}
> +
> +static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
> +{
> +	/* Convert to uV */
> +	return (((3 * ((raw_val * 1000) + 500)) / 512) * 1000);
> +}
> +
> +static inline int da9150_gpadc_vsys_1_5v_voltage_now(int raw_val)
> +{
> +	/* Convert to uV */
> +	return (((3 * ((raw_val * 1000) + 500)) / 2048) * 1000);
> +}
> +
> +static inline int da9150_gpadc_tjunc_temp(int raw_val)
> +{
> +	/* Convert to 0.1 degrees C */
> +	return (((879 - (1023 - raw_val)) * 10000) / 4420);
Linear in the coeeficients, so fine for raw output with a scale and offset.
> +}
> +
> +static inline int da9150_gpadc_vbat_voltage_now(int raw_val)
> +{
> +	/* Convert to uV */
> +	return ((2932 * raw_val) + 1500000);
> +}
> +
> +int da9150_gpadc_read_process(int channel, int raw_val)
> +{
> +	int ret;
> +
> +	switch (channel) {
> +	case DA9150_GPADC_CHAN_GPIOA_2V:
> +	case DA9150_GPADC_CHAN_GPIOA_2V_:
> +	case DA9150_GPADC_CHAN_GPIOB_2V:
> +	case DA9150_GPADC_CHAN_GPIOB_2V_:
> +	case DA9150_GPADC_CHAN_GPIOC_2V:
> +	case DA9150_GPADC_CHAN_GPIOC_2V_:
> +	case DA9150_GPADC_CHAN_GPIOD_2V:
> +	case DA9150_GPADC_CHAN_GPIOD_2V_:
> +		ret = da9150_gpadc_gpio_2v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_IBUS_SENSE:
> +	case DA9150_GPADC_CHAN_IBUS_SENSE_:
> +		ret = da9150_gpadc_ibus_current_avg(raw_val);
> +		break;
Ah, so here is your reasoning behind the 'interesting' underscore channels.
This is just doing different range checks on the channel?  If so allow one
at a time and provide a writable scale info_mask element to control which
is used..

Looks like there are only thes two channels doing this, so shouldn't be
too hard to support it via more conventional means.

> +	case DA9150_GPADC_CHAN_VBUS_DIV:
> +		ret = da9150_gpadc_vbus_6v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_VBUS_DIV_:
> +		ret = da9150_gpadc_vbus_21v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_VSYS:
> +		ret = da9150_gpadc_vsys_6v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_VSYS_:
> +		ret = da9150_gpadc_vsys_1_5v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_GPIOA_5V:
> +	case DA9150_GPADC_CHAN_GPIOA_5V_:
> +	case DA9150_GPADC_CHAN_GPIOB_5V:
> +	case DA9150_GPADC_CHAN_GPIOB_5V_:
> +	case DA9150_GPADC_CHAN_GPIOC_5V:
> +	case DA9150_GPADC_CHAN_GPIOC_5V_:
> +	case DA9150_GPADC_CHAN_GPIOD_5V:
> +	case DA9150_GPADC_CHAN_GPIOD_5V_:
> +		ret = da9150_gpadc_gpio_5v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_TJUNC_CORE:
> +	case DA9150_GPADC_CHAN_TJUNC_CORE_:
> +	case DA9150_GPADC_CHAN_TJUNC_OVP:
> +	case DA9150_GPADC_CHAN_TJUNC_OVP_:
> +		ret = da9150_gpadc_tjunc_temp(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_VBAT:
> +		ret = da9150_gpadc_vbat_voltage_now(raw_val);
> +		break;
> +	default:
> +		/* No processing for other channels so return raw value */
> +		ret = raw_val;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +int da9150_gpadc_read_raw(struct iio_dev *indio_dev,
> +			  struct iio_chan_spec const *chan,
> +			  int *val, int *val2, long mask)
> +{
> +	struct da9150_gpadc *gpadc = iio_priv(indio_dev);
> +	u8 reg = 0;
> +	u8 result_regs[2];
> +	u16 result;
> +
> +	if ((mask != IIO_CHAN_INFO_RAW) && (mask != IIO_CHAN_INFO_PROCESSED))
> +		return -EINVAL;
> +
> +	if ((chan->channel < DA9150_GPADC_CHAN_GPIOA_2V) ||
> +	    (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP_))
> +		return -EINVAL;
> +
> +	mutex_lock(&gpadc->lock);
> +
> +	/* Set channel & enable measurement */
> +	reg |= DA9150_GPADC_EN_MASK;
Don't use the |=, just = and you can't avoid assigning reg above.
Actually, it's not complex enough that you couldn't just do it directly into
the write function and skip this local variable.
> +	reg |= chan->channel << DA9150_GPADC_MUX_SHIFT;
> +	da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN, reg);
> +
> +	/* Consume left-over completion from a previous timeout */
> +	try_wait_for_completion(&gpadc->complete);
> +
> +	/* Check for actual completion */
> +	wait_for_completion_timeout(&gpadc->complete, msecs_to_jiffies(5));
> +
> +	/* Read result and status from device */
> +	da9150_bulk_read(gpadc->da9150, DA9150_GPADC_RES_A, 2, result_regs);
> +
> +	/* Check to make sure device really has completed reading */
> +	if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
> +		mutex_unlock(&gpadc->lock);
Unlock first, then check for error.
> +		dev_err(gpadc->dev, "Timeout on channel %d of GP-ADC\n",
> +			chan->channel);
> +		return -ETIMEDOUT;
> +	}
> +
> +	mutex_unlock(&gpadc->lock);
> +
> +	/* LSBs - 2 bits */
> +	result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
> +		 DA9150_GPADC_RES_L_SHIFT;
The mixture of having defs here for the shift.
> +	/* MSBs - 8 bits */
> +	result |= result_regs[0] << 2;
and not here is inconsistent.  I honestly don't mind which way, but
just use one style.

You could just use an endian conversion and shift the combined 16bit result
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_PROCESSED:
> +		*val = da9150_gpadc_read_process(chan->channel, result);
> +		break;
> +	case IIO_CHAN_INFO_RAW:
> +		*val = result;
> +		break;
> +	}
> +
> +	return IIO_VAL_INT;
> +}
> +
> +
> +static const struct iio_info da9150_gpadc_info = {
> +	.read_raw = &da9150_gpadc_read_raw,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +#define GPADC_CHANNEL(_id, _type, chan_info, _ext_name) {		\
> +	.type = _type,							\
> +	.indexed = 1,							\
> +	.channel = DA9150_GPADC_CHAN_##_id,				\
> +	.info_mask_separate = chan_info,				\
> +	.extend_name = _ext_name,					\
> +	.datasheet_name = #_id,						\
> +}
> +
> +#define GPADC_CHANNEL_RAW(_id, _type, _ext_name)	\
> +	GPADC_CHANNEL(_id, _type, BIT(IIO_CHAN_INFO_RAW), _ext_name)
> +
> +#define GPADC_CHANNEL_RAW_PROCESSED(_id, _type, _ext_name)			\
> +	GPADC_CHANNEL(_id, _type,						\
> +		      BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),	\
It very rarely makes sense to provide both raw and processed interfaces.
If the transform is nasty and non linear then userspace won't have the info
to do anything with it.  If the transform is linear, then provide scale
and offset and let userspace perform the computation.

> +		      _ext_name)
> +
> +/* Supported channels */
Another comment that doesn't add any information.
> +static const struct iio_chan_spec da9150_gpadc_channels[] = {
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_2V, IIO_VOLTAGE, "GPIOA_2V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_2V_, IIO_VOLTAGE, "GPIOA_2V_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_2V, IIO_VOLTAGE, "GPIOB_2V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_2V_, IIO_VOLTAGE, "GPIOB_2V_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_2V, IIO_VOLTAGE, "GPIOC_2V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_2V_, IIO_VOLTAGE, "GPIOC_2V_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_2V, IIO_VOLTAGE, "GPIOD_2V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_2V_, IIO_VOLTAGE, "GPIOD_2V_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(IBUS_SENSE, IIO_CURRENT, "IBUS"),
> +	GPADC_CHANNEL_RAW_PROCESSED(IBUS_SENSE_, IIO_CURRENT, "IBUS_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(VBUS_DIV, IIO_VOLTAGE, "VBUS_6V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(VBUS_DIV_, IIO_VOLTAGE, "VBUS_21V"),
> +	GPADC_CHANNEL_RAW(ID, IIO_VOLTAGE, "ID"),
> +	GPADC_CHANNEL_RAW(ID_, IIO_VOLTAGE, "ID_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(VSYS, IIO_VOLTAGE, "VSYS_6V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(VSYS_, IIO_VOLTAGE, "VSYS_1_5V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_5V, IIO_VOLTAGE, "GPIOA_5V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOA_5V_, IIO_VOLTAGE, "GPIOA_5V_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_5V, IIO_VOLTAGE, "GPIOB_5V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOB_5V_, IIO_VOLTAGE, "GPIOB_5V_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_5V, IIO_VOLTAGE, "GPIOC_5V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOC_5V_, IIO_VOLTAGE, "GPIOC_5V_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_5V, IIO_VOLTAGE, "GPIOD_5V"),
> +	GPADC_CHANNEL_RAW_PROCESSED(GPIOD_5V_, IIO_VOLTAGE, "GPIOD_5V_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(VBAT, IIO_VOLTAGE, "VBAT"),
> +	GPADC_CHANNEL_RAW_PROCESSED(VBAT_, IIO_VOLTAGE, "VBAT_"),
> +	GPADC_CHANNEL_RAW(TBAT, IIO_VOLTAGE, "TBAT"),
> +	GPADC_CHANNEL_RAW(TBAT_, IIO_VOLTAGE, "TBAT_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_CORE, IIO_TEMP, "TJUNC_CORE"),
> +	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_CORE_, IIO_TEMP, "TJUNC_CORE_"),
> +	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_OVP, IIO_TEMP, "TJUNC_OVP"),
> +	GPADC_CHANNEL_RAW_PROCESSED(TJUNC_OVP_, IIO_TEMP, "TJUNC_OVP_"),
> +};
> +
> +/* Default maps used by da9150-charger */
> +static struct iio_map da9150_gpadc_default_maps[] = {
> +	{
> +		.consumer_dev_name = "da9150-charger",
> +		.consumer_channel = "CHAN_IBUS",
> +		.adc_channel_label = "IBUS_SENSE",
> +	},
> +	{
> +		.consumer_dev_name = "da9150-charger",
> +		.consumer_channel = "CHAN_VBUS",
> +		.adc_channel_label = "VBUS_DIV_",
> +	},
> +	{
> +		.consumer_dev_name = "da9150-charger",
> +		.consumer_channel = "CHAN_TJUNC",
> +		.adc_channel_label = "TJUNC_CORE",
> +	},
> +	{
> +		.consumer_dev_name = "da9150-charger",
> +		.consumer_channel = "CHAN_VBAT",
> +		.adc_channel_label = "VBAT",
> +	},
> +	{},
> +};
> +
> +
> +/*
> + * Driver top level functions
Get rid of this comment and any other ones that don't add any
actual information.  Also this is single line comment, please
check the comment syntax.
> + */
> +
> +static int da9150_gpadc_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct da9150 *da9150 = dev_get_drvdata(dev->parent);
> +	struct da9150_gpadc *gpadc;
> +	struct iio_dev *indio_dev;
> +
Why a blank line here.
> +	int ret;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev,
> +					  sizeof(struct da9150_gpadc));
> +	if (!indio_dev) {
> +		dev_err(&pdev->dev, "Failed to allocate IIO device\n");
> +		return -ENOMEM;
> +	}
> +	gpadc = iio_priv(indio_dev);
> +
> +	platform_set_drvdata(pdev, indio_dev);
> +	gpadc->da9150 = da9150;
> +	gpadc->dev = dev;
> +
> +	ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
> +	if (ret) {
> +		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
> +		goto iio_map_fail;
> +	}
> +
> +	indio_dev->name = dev_name(dev);
> +	indio_dev->dev.parent = dev;
> +	indio_dev->dev.of_node = pdev->dev.of_node;
> +	indio_dev->info = &da9150_gpadc_info;
> +	indio_dev->modes = INDIO_DIRECT_MODE;
> +	indio_dev->channels = da9150_gpadc_channels;
> +	indio_dev->num_channels = ARRAY_SIZE(da9150_gpadc_channels);
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret) {
> +		dev_err(dev, "Failed to register IIO device: %d\n", ret);
> +		goto iio_dev_fail;
> +	}
The device register call is the one that exposes userspace interfaces. As
a general rule it wants to be the last thing in probe as everything
else should be setup first.
> +
> +	mutex_init(&gpadc->lock);
> +	init_completion(&gpadc->complete);
> +
> +	/* Register IRQ */
> +	ret = da9150_register_irq(pdev, gpadc, da9150_gpadc_irq, "GPADC");
> +	if (ret < 0)
> +		goto irq_fail;
> +
> +	da9150->gpadc_ready = true;
> +	return ret;
> +
> +irq_fail:
> +	iio_device_unregister(indio_dev);
> +
> +iio_dev_fail:
> +	iio_map_array_unregister(indio_dev);
> +
> +iio_map_fail:
> +	return ret;
> +}
> +
> +static int da9150_gpadc_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +	iio_map_array_unregister(indio_dev);
> +	iio_device_unregister(indio_dev);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver da9150_gpadc_driver = {
> +	.driver = {
> +		.name = "da9150-gpadc",
> +		.owner = THIS_MODULE,
> +	},
> +	.probe = da9150_gpadc_probe,
> +	.remove = da9150_gpadc_remove,
> +};
> +
> +module_platform_driver(da9150_gpadc_driver);
> +
> +MODULE_DESCRIPTION("GPADC Driver for DA9150");
> +MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com");
> +MODULE_LICENSE("GPL");
> diff --git a/include/linux/mfd/da9150/gpadc.h b/include/linux/mfd/da9150/gpadc.h
> new file mode 100644
> index 0000000..3e46164
> --- /dev/null
> +++ b/include/linux/mfd/da9150/gpadc.h
> @@ -0,0 +1,71 @@
> +/*
> + * DA9150 GPADC Driver - GPADC Data
> + *
> + * Copyright (c) 2014 Dialog Semiconductor
> + *
> + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> + *
> + * 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.
> + */
> +
> +#ifndef _DA9150_GPADC_H
> +#define _DA9150_GPADC_H
> +
> +#include <linux/device.h>
> +#include <linux/iio/machine.h>
This isn't used in the header, so should be included in the c file, not here.

> +#include <linux/mutex.h>
> +#include <linux/completion.h>
> +
> +#include <linux/mfd/da9150/core.h>
Having moved the struct definition into the c file
this header include will not want to be here.
> +
> +
> +/* Channels */
> +enum da9150_gpadc_channel {
> +	DA9150_GPADC_CHAN_GPIOA_2V = 0,
> +	DA9150_GPADC_CHAN_GPIOA_2V_,
> +	DA9150_GPADC_CHAN_GPIOB_2V,
> +	DA9150_GPADC_CHAN_GPIOB_2V_,
> +	DA9150_GPADC_CHAN_GPIOC_2V,
> +	DA9150_GPADC_CHAN_GPIOC_2V_,
> +	DA9150_GPADC_CHAN_GPIOD_2V,
> +	DA9150_GPADC_CHAN_GPIOD_2V_,
> +	DA9150_GPADC_CHAN_IBUS_SENSE,
> +	DA9150_GPADC_CHAN_IBUS_SENSE_,
> +	DA9150_GPADC_CHAN_VBUS_DIV,
> +	DA9150_GPADC_CHAN_VBUS_DIV_,
> +	DA9150_GPADC_CHAN_ID,
> +	DA9150_GPADC_CHAN_ID_,
> +	DA9150_GPADC_CHAN_VSYS,
> +	DA9150_GPADC_CHAN_VSYS_,
> +	DA9150_GPADC_CHAN_GPIOA_5V,
> +	DA9150_GPADC_CHAN_GPIOA_5V_,
> +	DA9150_GPADC_CHAN_GPIOB_5V,
> +	DA9150_GPADC_CHAN_GPIOB_5V_,
> +	DA9150_GPADC_CHAN_GPIOC_5V,
> +	DA9150_GPADC_CHAN_GPIOC_5V_,
> +	DA9150_GPADC_CHAN_GPIOD_5V,
> +	DA9150_GPADC_CHAN_GPIOD_5V_,
> +	DA9150_GPADC_CHAN_VBAT,
> +	DA9150_GPADC_CHAN_VBAT_,
> +	DA9150_GPADC_CHAN_TBAT,
> +	DA9150_GPADC_CHAN_TBAT_,
> +	DA9150_GPADC_CHAN_TJUNC_CORE,
> +	DA9150_GPADC_CHAN_TJUNC_CORE_,
> +	DA9150_GPADC_CHAN_TJUNC_OVP,
> +	DA9150_GPADC_CHAN_TJUNC_OVP_,
> +};
> +
> +
> +/* Private data */
Why is this in the header?  Should be defined directly in the c file
as nothing outside the driver should be touching it.

> +struct da9150_gpadc {
> +	struct da9150 *da9150;
> +	struct device *dev;
> +
> +	struct mutex lock;
> +	struct completion complete;
> +};
> +
> +#endif /* _DA9150_GPADC_H */
> --
> 1.9.3
>


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

* Re: [PATCH 3/8] iio: of_iio_channel_get_by_name() returns non-null pointers for error legs
  2014-06-11 11:11 ` [PATCH 3/8] iio: of_iio_channel_get_by_name() returns non-null pointers for error legs Adam Thomson
@ 2014-06-15 20:20   ` Jonathan Cameron
  2014-06-21 11:32     ` Jonathan Cameron
  0 siblings, 1 reply; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-15 20:20 UTC (permalink / raw)
  To: Adam Thomson, Lee Jones, Samuel Ortiz, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

On 11/06/14 12:11, Adam Thomson wrote:
> Currently in the inkern.c code for IIO framework, the function
> of_iio_channel_get_by_name() will return a non-NULL pointer when
> it cannot find a channel using of_iio_channel_get() and when it
> tries to search for 'io-channel-ranges' property and fails. This
> is incorrect behaviour as the function which calls this expects
> a NULL pointer for failure. This patch rectifies the issue.
>
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Hi Adam,

Good find.  I've only recently sent a pull request for fixes upstream,
so I'll pick this up in a day or so once that has gone.

J
> ---
>   drivers/iio/inkern.c | 6 ++++--
>   1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
> index 0cf5f8e..1e8e94d 100644
> --- a/drivers/iio/inkern.c
> +++ b/drivers/iio/inkern.c
> @@ -183,7 +183,7 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
>   		else if (name && index >= 0) {
>   			pr_err("ERROR: could not get IIO channel %s:%s(%i)\n",
>   				np->full_name, name ? name : "", index);
> -			return chan;
> +			return NULL;
>   		}
>
>   		/*
> @@ -193,8 +193,9 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
>   		 */
>   		np = np->parent;
>   		if (np && !of_get_property(np, "io-channel-ranges", NULL))
> -			break;
> +			return NULL;
>   	}
> +
>   	return chan;
>   }
>
> @@ -317,6 +318,7 @@ struct iio_channel *iio_channel_get(struct device *dev,
>   		if (channel != NULL)
>   			return channel;
>   	}
> +
>   	return iio_channel_get_sys(name, channel_name);
>   }
>   EXPORT_SYMBOL_GPL(iio_channel_get);
> --
> 1.9.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>


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

* RE: [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2014-06-15 19:49   ` Jonathan Cameron
@ 2014-06-16 13:12     ` Opensource [Adam Thomson]
  2014-06-16 20:13       ` Jonathan Cameron
  2014-06-21 11:38       ` Jonathan Cameron
  0 siblings, 2 replies; 29+ messages in thread
From: Opensource [Adam Thomson] @ 2014-06-16 13:12 UTC (permalink / raw)
  To: Jonathan Cameron, Opensource [Adam Thomson], Lee Jones,
	Samuel Ortiz, linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org
  Cc: linux-kernel@vger.kernel.org, Support Opensource

T24gU3VuLCBKdW4gMTUsIDIwMTQgYXQgMjA6NDksIEpvbmF0aGFuIENhbWVyb24gd3JvdGU6IA0K
DQo+IEhpIEFkYW0sDQo+IA0KPiBTb21lIGdlbmVyYWwgY29tbWVudHMgaW5saW5lLg0KPiANCj4g
SXQncyBiZWVuIGEgd2hpbGUgc2luY2UgSSd2ZSBsb29rZWQgYXQgYW55IHBhcnRpY3VsYXJseSBz
aW1pbGFyIHBhcnRzLA0KPiBidXQgaXQgc2VlbXMgdG8gbWUgdGhhdCBhIGxvdCBvZiBpbmRpcmVj
dGlvbiBnZXRzIGFkZGVkIGhlcmUgdGhhdA0KPiBpZiBhbnl0aGluZyBtYWtlcyB0aGUgY29kZXMg
c2xpZ2h0bHkgaGFyZGVyIHRvIGZvbGxvdy4uLg0KPiANCj4gRmVlbCBmcmVlIHRvIGRpc2FncmVl
IHdpdGggbWUgdGhvdWdoIQ0KDQpXaWxsIGRvIDopDQoNCj4gVG8gbXkgbWluZCBhbGwgdGhlc2Ug
d3JhcHBlcnMgYWRkIG5vdGhpbmcgc2lnbmlmaWNhbnQgc28geW91IG1pZ2h0IGFzIHdlbGwNCj4g
anVzdCBjYWxsIGRhOTE1MC0+cmVhZF9kZXYgZXRjIGRpcmVjdGx5Lg0KPiANCj4gQWxzbywgd2hh
dCBhcmUgdGhlIHJlYWRfcWlmIGFuZCB3cml0ZV9xaWYgZm9yPyAgVGhleSBkb24ndCBzZWVtIHRv
IGJlIHVzZWQNCj4gYW55d2hlcmUuDQoNCnJlYWRfcWlmIGFuZCB3cml0ZV9xaWYgYXJlIGZvciB0
aGUgRnVlbC1HYXVnZSBmdW5jdGlvbmFsaXR5IG9mIHRoZSBjaGlwLiBUaGUNCmFzc29jaWF0ZWQg
ZHJpdmVyIHdpbGwgYmUgc3VibWl0dGVkIGFmdGVyIGFjY2VwdGFuY2Ugb2YgaW5pdGlhbCBkcml2
ZXIgY29kZSwNCmFuZCB3aWxsIG1ha2UgdXNlIG9mIHRoZXNlIGZ1bmN0aW9ucy4NCg0KVGhlIHdy
YXBwZXJzIGF1dG9tYXRpY2FsbHkgY2hvb3NlIHRoZSBjb3JyZWN0IGNsaWVudCB0byB1c2UgKFFJ
RiB1c2VzIGENCmRpZmZlcmVudCBzbGF2ZSBhZGRyZXNzIHRvIHRoZSBtYWluIGNoaXAgb25lKS4g
TWVhbnMgdGhlIGNoaWxkIGRyaXZlcnMgb25seSBuZWVkDQp0byBwYXNzIHRocm91Z2ggdGhlIGRh
OTE1MCBzdHJ1Y3QgYW5kIHRoZSByZXN0IGlzIGRlYWx0IHdpdGggdW5kZXJuZWF0aC4NCg0KPiBU
aGUgb25seSByZWFsIHJlYXNvbiBJIGNhbiBzZWUgZm9yIHRoZXNlIHdyYXBwZXJzIGlzIGJlY2F1
c2UgeW91IHdhbnQNCj4gdG8gaGlkZSB0aGUgc3RydWN0IGRhOTE1MCBjb250ZW50cyBmcm9tIHRo
ZSBjaGlsZHJlbiBvZiB0aGUgbWZkLiBBcyB5b3UNCj4gYXJlbid0IGRvaW5nIHRoYXQsIHlvdSBt
aWdodCBhcyB3ZWxsIGRyb3AgdGhlc2UgaW4gZmF2b3VyIG9mIGRpcmVjdA0KPiBjYWxscyB0byBy
ZWdtYXBfcmVhZCBhbmQgZnJpZW5kcy4NCg0KQXMgSSBoYXZlIGEgbmVlZCB0byBwYXNzIHRocm91
Z2ggdGhlIG1haW4gZGE5MTUwIHN0cnVjdCBwb2ludCBmb3IgdGhlDQphZm9yZW1lbnRpb25lZCB3
cmFwcGVycywgaXQgc2VlbWVkIGNsZWFuZXIgYW5kIG1vcmUgY29uc2lzdGVudCB0byBoYXZlIHdy
YXBwZXJzDQpmb3IgdGhlc2UgYXMgd2VsbCwgd2hpY2ggZGlkIHRoZSBqb2Igb2YgcmVnbWFwIGFj
Y2Vzcy4gTWVhbnMgYWxsIEhXIGFjY2Vzcw0KdXNlcyB0aGUgc2FtZSBraW5kIG9mIGFwcHJvYWNo
LCBhbmQgYWxsIHN1Yi1kZXZpY2VzIGp1c3QgbmVlZCBhIHBvaW50IHRvIHRoZQ0KbWFpbiBkYTkx
NTAgc3RydWN0IHRvIGJlIGFibGUgdG8gdXNlIHRoZSBmdW5jdGlvbnMuDQoNCj4gSSdsbCBjb250
aW51ZSBteSB0aXJhZGUgYWdhaW5zdCBvYnZpb3VzIGNvbW1lbnRzLiBXcm9uZyBmb3JtYXQgYW5k
DQo+IGFkZHMgbm90aGluZyB0byB3aGF0IGlzIGhlcmUgYXMgaW5pdCBhbmQgZXhpdCBmdW5jdGlv
bnMgYXJlIGNsZWFybHkNCj4gZG9pbmcgd2hhdCB0aGVpciBuYW1lIHN1Z2dlc3RzIChpdCdzIG9u
ZSBvZiBteSBwZXQgaGF0ZXMgOykNCg0KSSBhZ3JlZSB0aGUgY29tbWVudCBkb2Vzbid0IGFkZCBt
dWNoIGluIHRlcm1zIG9mIGRlc2NyaXB0aW9uIGJ1dCBmb3IgbWUgaXQNCmJyZWFrcyB1cCB0aGUg
Y29kZSB0byBtYWtlIGl0IGVhc2llciB0byBmb2xsb3cuIEhvd2V2ZXIgaWYgSSBnZXQgYW4gb3Zl
cndoZWxtaW5nDQpoYXRyZWQgZm9yIHRoaXMgSSBjYW4gY2hhbmdlIGl0LiBBbHNvLCBJIGtub3cg
dGhlIHJ1bGUgcmVnYXJkaW5nIHNpbmdsZS9tdWx0aXBsZQ0KbGluZSBjb21tZW50cyBidXQgaGVy
ZSBhZ2FpbiBJIGZlZWwgaXQgaGVscHMgc2VwYXJhdGUgdGhlIGNvZGUgYW5kIG1ha2VzIGl0DQpl
YXNpZXIgdG8gcmVhZC4NCg0KPiBBcyBhIGdlbmVyYWwgZ29vZCBwcmFjdGljZSBwb2ludCwgSSdk
IHJhdGhlciB0aGF0IHRoZSBkcml2ZXIgc3VwcG9ydGVkDQo+IG1vcmUgdGhhbiBvbmUgaW5zdGFu
Y2Ugb2YgdGhlIGNoaXAuLiBIZW5jZSB5b3UnZCB0YWtlIGEgY29weSBvZiBkYTkxNTBfZGV2cw0K
PiB0byB1c2UgaGVyZS4gIEkgZ3Vlc3MgaXQgaXMgcmVsYXRpdmVseSB1bmxpa2VseSB3aXRoIG9u
ZSBvZiB0aGVzZSwgYnV0DQo+IHlvdSBuZXZlciBrbm93IDspDQoNCkhhdmUgZm9sbG93ZWQgdGhl
IGdlbmVyYWwgbWV0aG9kcyBmb3IgTUZEIGhlcmUsIGFuZCBhIG51bWJlciBvZiBkcml2ZXJzIHRh
a2UgdGhlDQpzYW1lIGFwcHJvYWNoLiBBbHNvLCBJIHRoaW5rIGl0IHdvdWxkIGJlIHVuZGVzaXJh
YmxlIHRvIGhhdmUgbXVsdGlwbGUgY2hhcmdlcg0KY2hpcHMgb2YgdGhlIHNhbWUgdHlwZSBpbiBv
bmUgcGxhdGZvcm0uIEkgYWdyZWUgZ2VuZXJhbGx5IGl0J3MgYmVzdCB0byBzdXBwb3J0DQptdWx0
aXBsZSBpbnN0YW5jZXMsIGJ1dCBoZXJlIEkgZG9uJ3QgdGhpbmsgd2Ugc2hvdWxkLg0KDQo+IFdo
eSBkb2VzIHRoaXMgbmVlZCBpdCdzIG93biBmaWxlPyAgRG9lcyB0aGUgREE5MTUwIHN1cHBvcnQg
YW55IG90aGVyDQo+IGludGVyZmFjZXM/DQoNClllcywgdGhlIERBOTE1MCBhbHNvIGhhcyBhIFNQ
SSBpbnRlcmZhY2UuIEF0IHByZXNlbnQgdGhlIHBsYW4gaXMgdG8ganVzdCBhZGQgSTJDDQpzdXBw
b3J0IGZvciBub3csIGJ1dCBpbiB0aGUgZnV0dXJlIHdlIG1heSBhZGQgU1BJIHN1cHBvcnQsIHNv
IGhhdmUgd3JpdHRlbiB0aGUNCmNvZGUgd2l0aCB0aGlzIGluIG1pbmQuDQoNCj4gV2h5IHRoZSBp
bmRpcmVjdGlvbj8gIFRoZSBkYTkxNTAgb25seSBzdXBwb3J0cyBpMmMgYXMgZmFyIGFzIEkgY2Fu
IHNlZS4NCg0KQXMgcGVyIG15IGxhc3QgY29tbWVudC4gDQoNCj4gSSdkIHJvbGwgdGhpcyBpbnRv
IG9uZSBsaW5lIGFuZCBub3QgYm90aGVyIHdpdGggdGhlIGxvY2FsIHZhcmlhYmxlLi4uDQoNCkZh
aXIgZW5vdWdoIGJ1dCBJIHRoaW5rIHRoaXMga2VlcHMgdGhlIGNvZGUgY2xlYW5lciwgYW5kIHRv
IG1lIGl0IG1ha2VzIHNlbnNlDQpmb3IgdGhlIGFjdHVhbCBsb2dpYyB0byBiZSBpbiBjb3JlIGZp
bGUgYXMgdGhhdCdzIGludGVyZmFjZSBhZ25vc3RpYy4NCg0KPiBEcm9wIGNvbW1lbnRzIG9uIHRo
aW5ncyB0aGF0IGFyZSBzZWxmLWV2aWRlbnQuICBBbHNvIHRoZXNlIGFyZSBvbmUNCj4gbGluZSBj
b21tZW50cyBzbyBzaG91bGQgYmUgdXNpbmcgdGhlIHNpbmdsZSBsaW5lIGNvbW1lbnQgc3ludGF4
Lg0KDQpBcyBwZXIgbXkgcHJldmlvdXMgY29tbWVudCBJIHRoaW5rIGl0IGp1c3QgaGVscHMgdG8g
YnJlYWsgdXAgdGhlIGNvZGUgYW5kIG1ha2VzDQppdCBtb3JlIHJlYWRhYmxlLiBXaWxsIGNoYW5n
ZSBpdCB0aG91Z2ggaWYgdGhlIGdlbmVyYWwgY29uc2Vuc3VzIGlzIHRvIHJlbW92ZQ0KaXQuDQo=

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

* Re: [PATCH 6/8] power: Add support for DA9150 Charger
  2014-06-11 11:11 ` [PATCH 6/8] power: Add support for DA9150 Charger Adam Thomson
@ 2014-06-16 13:27   ` Lee Jones
  2014-06-17  8:21     ` Opensource [Adam Thomson]
  0 siblings, 1 reply; 29+ messages in thread
From: Lee Jones @ 2014-06-16 13:27 UTC (permalink / raw)
  To: Adam Thomson
  Cc: Samuel Ortiz, Jonathan Cameron, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree, linux-kernel,
	support.opensource

On Wed, 11 Jun 2014, Adam Thomson wrote:

> This patch adds support for DA9150 Charger & Fuel-Guage IC Charger.
> 
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> ---
>  drivers/power/Kconfig              |  23 ++
>  drivers/power/Makefile             |   1 +
>  drivers/power/da9150-charger.c     | 790 +++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/da9150/charger.h |  58 +++
>  4 files changed, 872 insertions(+)
>  create mode 100644 drivers/power/da9150-charger.c
>  create mode 100644 include/linux/mfd/da9150/charger.h

[...]

> diff --git a/include/linux/mfd/da9150/charger.h b/include/linux/mfd/da9150/charger.h
> new file mode 100644
> index 0000000..73c41b3
> --- /dev/null
> +++ b/include/linux/mfd/da9150/charger.h
> @@ -0,0 +1,58 @@
> +/*
> + * DA9150 MFD Driver - Charger Data
> + *
> + * Copyright (c) 2014 Dialog Semiconductor
> + *
> + * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> + *
> + * 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.
> + */
> +
> +#ifndef _DA9150_CHARGER_H
> +#define _DA9150_CHARGER_H

Two '_'s are normally preferred.

> +#include <linux/device.h>
> +#include <linux/i2c.h>

What are you using this for?

> +#include <linux/power_supply.h>
> +#include <linux/notifier.h>
> +#include <linux/usb/otg.h>
> +#include <linux/timer.h>
> +#include <linux/iio/consumer.h>
> +
> +#include <linux/mfd/da9150/core.h>
> +
> +

Extra '\n' here.

> +struct da9150_charger_attr_map {
> +	struct device_attribute attr;
> +	u16 reg;
> +	u8 shift;
> +	u8 mask;
> +};
> +
> +/* Private data */
> +struct da9150_charger {
> +	struct da9150 *da9150;
> +	struct device *dev;
> +
> +	struct power_supply ac;
> +	struct power_supply usb;
> +	struct power_supply battery;

Do you want these (or pointers to these) here?

How much space do they take up?

> +	struct power_supply *supply_online;
> +
> +	struct usb_phy *usb_phy;
> +	struct notifier_block otg_nb;
> +	struct work_struct otg_work;
> +	unsigned long usb_event;
> +
> +	struct iio_channel *ibus_chan;
> +	struct iio_channel *vbus_chan;
> +	struct iio_channel *tjunc_chan;
> +	struct iio_channel *vbat_chan;
> +
> +	bool invalid_tbat;
> +};
> +
> +#endif /* _DA9150_CHARGER_H */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* RE: [PATCH 4/8] iio: Add support for DA9150 GPADC
  2014-06-15 20:19   ` Jonathan Cameron
@ 2014-06-16 15:58     ` Opensource [Adam Thomson]
  2014-06-21 11:29       ` Jonathan Cameron
  0 siblings, 1 reply; 29+ messages in thread
From: Opensource [Adam Thomson] @ 2014-06-16 15:58 UTC (permalink / raw)
  To: Jonathan Cameron, Opensource [Adam Thomson], Lee Jones,
	Samuel Ortiz, linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org
  Cc: linux-kernel@vger.kernel.org, Support Opensource

T24gSnVuZSAxNSwgMjAxNCAyMToxOSwgSm9uYXRob24gQ2FtZXJvbiB3cm90ZToNCg0KPiBIaSBB
ZGFtDQo+IA0KPiBSZWFzb25hYmx5IGNsZWFuIGNvZGUsIGJ1dCB0aGUgXyBjaGFubmVscyBzdHVm
ZiBkb2Vzbid0IGNvbXBseSB3aXRoIHRoZSBBQkkNCj4gYW5kIGlzIHJhdGhlciBjb25mdXNpbmcu
DQoNClRvIGJlIGhvbmVzdCBJIGRpZCBkZWJhdGUgdGhpcyBpbiBteSBoZWFkIGZvciBhIHdoaWxl
LiBUaGUgcmVhc29uIEkgd2VudCB3aXRoDQp0aGUgY3VycmVudCBhcHByb2FjaCB3YXMgdG8gbWFr
ZSB0aGUgZHJpdmVyIGNoYW5uZWwgbGF5b3V0IG1hdGNoIHRoYXQgb2YgdGhlIA0KZGF0YXNoZWV0
IGZvciB0aGUgZGV2aWNlLiBTb3VuZHMgbGlrZSBpdCB3YXNuJ3QgdGhlIGNvcnJlY3QgZGlyZWN0
aW9uIHRob3VnaC4NCg0KPiBJZiBpdCByZWFsbHkgZG9lcyBtYWtlIHNlbnNlIHRvIGFsbG93IHJl
YWRpbmcgdGhlc2UgY2hhbm5lbHMgYXQgZGlmZmVyZW50DQo+IHJhbmdlcyAocHJlc3VtYWJseSB0
byBlbmhhbmNlIHRoZSBlZmZlY3RpdmUgYWRjIHJlc29sdXRpb24pIHRoZW4gd2UgbmVlZA0KPiB0
byBjb250cm9sIHRoaXMgdmlhIGV4aXN0aW5nIEFCSXMuIENvbnRyb2xsaW5nIGl0IHZpYSBzY2Fs
ZSB3aXRoIGENCj4gcmFuZ2UgYXR0cmlidXRlIGlmIHJlcXVpcmVkIChyZWFkIG9ubHkgYnV0IGNo
YW5nZXMgd2l0aCB3aGF0ZXZlciB0aGUNCj4gc2NhbGUgYXR0cmlidXRlIGl0IHNldCB0bykuDQoN
Clllcywgd2l0aCBzbWFsbGVyIHJhbmdlIHRoZW4geW91IGdldCBhIGJldHRlciBkZWdyZWUgb2Yg
YWNjdXJhY3kuIE9rLCB3aWxsIGhhdmUNCmEgbG9vayBhdCB0aGlzIGFuZCBzZWUgaWYgSSBjYW4g
aW1wcm92ZSB0aGluZ3MgYmFzZWQgb24geW91ciBjb21tZW50cy4NCg0KPiBPZnRlbiwgZm9yIHNs
b3cgcGFydHMgYXQgbGVhc3QgaXQgbWFrZXMgbGl0dGxlIHNlbnNlIHRvIGhhdmUgcHJvdmlkZQ0K
PiBzb2Z0d2FyZSBzdXBwb3J0IGZvciB2YXJpYWJsZSBpbnB1dCByYW5nZXMuDQo+IA0KPiBMb29r
aW5nIGF0IHdoYXQgaXMgY292ZXJlZCwgaXMgaXQgdGhlIGNhc2UgdGhhdCBvbmx5IG9uZSBvcHRp
b24gd2lsbCBtYWtlDQo+IHNlbnNlIGZvciBhIGdpdmVuIGhhcmR3YXJlIHNldHVwPyAoY292ZXIg
dGhlIHJlcXVpcmVkIHJhbmdlIGFuZCBub3RoaW5nIG1vcmUpLg0KPiANCj4gSWYgc28sIHBlcmhh
cHMgdGhpcyB3YW50cyB0byBnbyBpbnRvIHRoZSBkZXZpY2UgdHJlZSBvciBzaW1pbGFyPw0KDQpQ
b3NzaWJseS4gSGF2aW5nIHJlYWQgeW91ciBjb21tZW50cyBmdXJ0aGVyIG9uIHRob3VnaCwgYW5k
IGdpdmVuIHRoYXQNCml0IHNlZW1zIHJlYXNvbmFibGUgdG8gdXNlIHRoZSByYW5nZS9zY2FsZSBh
dHRyaWJ1dGUgdG8gY2hvb3NlIHRoZSByZXNvbHV0aW9uLA0KSSdkIHByZWZlciB0byBvcHQgZm9y
IHRoYXQgYXBwcm9hY2ggKHNlZW1zIG1vcmUgZmxleGlibGUpLg0KDQo+IFBsZWFzZSBnZXQgcmlk
IG9mIGV4Y2VzcyB3aGl0ZSBzcGFjZSBhbmQgY29tbWVudHMgdGhhdCBqdXN0IHRlbGwgeW91DQo+
IHNvbWV0aGluZyBvYnZpb3VzIGFib3V0IHRoZSBjb2RlIGZvbGxvd2luZyB0aGVtLg0KDQpQcmVm
ZXJhYmx5IEknZCBsaWtlIHRvIGtlZXAgaXQgdGhpcyB3YXkgYXMgSSB0aGluayBpdCBtYWtlcyB0
aGUgY29kZQ0KZWFzaWVyIHRvIHJlYWQsIGJ1dCBpZiB5b3UncmUgZGVhZCBhZ2FpbnN0IGl0IHRo
ZW4gSSdsbCByZW1vdmUgdGhlbS4NCg0KPiBMaW5lYXIgaW4gdGhlIGNvZWVmaWNpZW50cywgc28g
ZmluZSBmb3IgcmF3IG91dHB1dCB3aXRoIGEgc2NhbGUgYW5kIG9mZnNldC4NCg0KT2sgd2lsbCBo
YXZlIGEgbG9vayBhdCByZS13b3JraW5nIHRoaXMgYXMgcGVyIHlvdXIgY29tbWVudC4NCg0KPiBB
aCwgc28gaGVyZSBpcyB5b3VyIHJlYXNvbmluZyBiZWhpbmQgdGhlICdpbnRlcmVzdGluZycgdW5k
ZXJzY29yZSBjaGFubmVscy4NCj4gVGhpcyBpcyBqdXN0IGRvaW5nIGRpZmZlcmVudCByYW5nZSBj
aGVja3Mgb24gdGhlIGNoYW5uZWw/ICBJZiBzbyBhbGxvdyBvbmUNCj4gYXQgYSB0aW1lIGFuZCBw
cm92aWRlIGEgd3JpdGFibGUgc2NhbGUgaW5mb19tYXNrIGVsZW1lbnQgdG8gY29udHJvbCB3aGlj
aA0KPiBpcyB1c2VkLi4NCj4gDQo+IExvb2tzIGxpa2UgdGhlcmUgYXJlIG9ubHkgdGhlcyB0d28g
Y2hhbm5lbHMgZG9pbmcgdGhpcywgc28gc2hvdWxkbid0IGJlDQo+IHRvbyBoYXJkIHRvIHN1cHBv
cnQgaXQgdmlhIG1vcmUgY29udmVudGlvbmFsIG1lYW5zLg0KDQpUaGUgR1BJTywgVkJVUyBhbmQg
VlNZUyByZWxhdGVkIGNoYW5uZWxzIHByb3ZpZGUgZGlmZmVyZW50IHJhbmdlcy4gSSBndWVzcyB0
aGV5DQpzaG91bGQgYWxsIGZvbGxvdyB0aGUgc2FtZSBhcHByb2FjaCBmb3IgaW1wbGVtZW50aW5n
IHRoaXMgYWx0ZXJuYXRlIHJhbmdlLiBTbyBJDQp3aWxsIGFzc3VtZSB0aGF0IGZvciB0aGUgJ3Jl
cGVhdCcgY2hhbm5lbHMgd2hlcmUgdGhlIHNhbWUgcmF3IHZhbHVlIGlzIHByb3ZpZGVkDQpvbiBi
b3RoIHRoZSBfIGFuZCBub24gXyBjaGFubmVscyBvbmx5IG9uZSBjaGFubmVsIHNob3VsZCBiZSBw
cm92aWRlZC4NCg0KPiBEb24ndCB1c2UgdGhlIHw9LCBqdXN0ID0gYW5kIHlvdSBjYW4ndCBhdm9p
ZCBhc3NpZ25pbmcgcmVnIGFib3ZlLg0KPiBBY3R1YWxseSwgaXQncyBub3QgY29tcGxleCBlbm91
Z2ggdGhhdCB5b3UgY291bGRuJ3QganVzdCBkbyBpdCBkaXJlY3RseSBpbnRvDQo+IHRoZSB3cml0
ZSBmdW5jdGlvbiBhbmQgc2tpcCB0aGlzIGxvY2FsIHZhcmlhYmxlLg0KDQpPayBmaW5lLiBXaWxs
IHVwZGF0ZSB0byB0aWR5IHVwLg0KDQo+IFVubG9jayBmaXJzdCwgdGhlbiBjaGVjayBmb3IgZXJy
b3IuDQoNClllcC4gTWFrZXMgc2Vuc2UuIFdpbGwgdXBkYXRlLg0KDQo+IFRoZSBtaXh0dXJlIG9m
IGhhdmluZyBkZWZzIGhlcmUgZm9yIHRoZSBzaGlmdC4NCj4gPiArCS8qIE1TQnMgLSA4IGJpdHMg
Ki8NCj4gPiArCXJlc3VsdCB8PSByZXN1bHRfcmVnc1swXSA8PCAyOw0KPiBhbmQgbm90IGhlcmUg
aXMgaW5jb25zaXN0ZW50LiAgSSBob25lc3RseSBkb24ndCBtaW5kIHdoaWNoIHdheSwgYnV0DQo+
IGp1c3QgdXNlIG9uZSBzdHlsZS4NCj4gDQo+IFlvdSBjb3VsZCBqdXN0IHVzZSBhbiBlbmRpYW4g
Y29udmVyc2lvbiBhbmQgc2hpZnQgdGhlIGNvbWJpbmVkIDE2Yml0IHJlc3VsdA0KDQpGYWlyIHBv
aW50LiBXaWxsIG1ha2UgdGhpcyBjbGVhbmVyLg0KDQo+IEl0IHZlcnkgcmFyZWx5IG1ha2VzIHNl
bnNlIHRvIHByb3ZpZGUgYm90aCByYXcgYW5kIHByb2Nlc3NlZCBpbnRlcmZhY2VzLg0KPiBJZiB0
aGUgdHJhbnNmb3JtIGlzIG5hc3R5IGFuZCBub24gbGluZWFyIHRoZW4gdXNlcnNwYWNlIHdvbid0
IGhhdmUgdGhlIGluZm8NCj4gdG8gZG8gYW55dGhpbmcgd2l0aCBpdC4gIElmIHRoZSB0cmFuc2Zv
cm0gaXMgbGluZWFyLCB0aGVuIHByb3ZpZGUgc2NhbGUNCj4gYW5kIG9mZnNldCBhbmQgbGV0IHVz
ZXJzcGFjZSBwZXJmb3JtIHRoZSBjb21wdXRhdGlvbi4NCg0KVGhlIGNoYXJnZXIgbW9kdWxlIHVz
ZXMgY2VydGFpbiBjaGFubmVscyBmb3IgaXRzIHJlYWRpbmdzLCBhbmQgdG8gbWUgaXQgbWFrZXMN
Cm1vcmUgc2Vuc2UgZm9yIHRoYXQgY2FsY3VsYXRpb24gdG8gYmUgZG9uZSBieSB0aGUgR1BBREMu
IEhvd2V2ZXIgaGF2aW5nIGxvb2tlZA0KYXQgdGhlIGlua2Vybi5jIGZyYW1ld29yayBjb2RlIGl0
IGxvb2tzIGxpa2UgaWYgeW91IHJlcXVlc3QgYSBwcm9jZXNzZWQgY2hhbm5lbA0KYW5kIGl0J3Mg
ZG9lc24ndCBwcm92aWRlIHRoYXQgZmVhdHVyZSwgdGhlbiB0aGUgY29kZSBkcm9wcyB0byBsaW5l
YXIgc2NhbGluZyBpZg0KcG9zc2libGUgdG8gcHJvdmlkZSB0aGUgcHJvY2Vzc2VkIHZhbHVlLiBJ
IHRha2UgaXQgdGhpcyBpcyB0aGUgcHJlZmVycmVkDQphcHByb2FjaCB0aGVuPyBKdXN0IHRob3Vn
aHQgaXQgd2FzIG1vcmUgY29uc2lzdGVudCB0byBzZWUgdGhlIGNhbGN1bGF0aW9uIHVzaW5nDQpk
ZWRpY2F0ZWQgZnVuY3Rpb25zIChwcm9jZXNzZWQgY2hhbm5lbCBhcHByb2FjaCkuDQoNCj4gR2V0
IHJpZCBvZiB0aGlzIGNvbW1lbnQgYW5kIGFueSBvdGhlciBvbmVzIHRoYXQgZG9uJ3QgYWRkIGFu
eQ0KPiBhY3R1YWwgaW5mb3JtYXRpb24uICBBbHNvIHRoaXMgaXMgc2luZ2xlIGxpbmUgY29tbWVu
dCwgcGxlYXNlDQo+IGNoZWNrIHRoZSBjb21tZW50IHN5bnRheC4NCg0KQXMgcGVyIHByZXZpb3Vz
IGNvbW1lbnQgb24gdGhpcyB0b3BpYy4NCg0KPiBXaHkgYSBibGFuayBsaW5lIGhlcmUuDQoNCkFj
Y2lkZW50YWwuIFdpbGwgcmVtb3ZlIGl0Lg0KDQo+IFRoZSBkZXZpY2UgcmVnaXN0ZXIgY2FsbCBp
cyB0aGUgb25lIHRoYXQgZXhwb3NlcyB1c2Vyc3BhY2UgaW50ZXJmYWNlcy4gQXMNCj4gYSBnZW5l
cmFsIHJ1bGUgaXQgd2FudHMgdG8gYmUgdGhlIGxhc3QgdGhpbmcgaW4gcHJvYmUgYXMgZXZlcnl0
aGluZw0KPiBlbHNlIHNob3VsZCBiZSBzZXR1cCBmaXJzdC4NCg0KT2ssIHRoYXQncyBzb21ldGhp
bmcgSSBtaXNzZWQuIFdpbGwgbWFrZSB0aGUgY2hhbmdlLg0KDQo+ID4gKyNpbmNsdWRlIDxsaW51
eC9paW8vbWFjaGluZS5oPg0KPiBUaGlzIGlzbid0IHVzZWQgaW4gdGhlIGhlYWRlciwgc28gc2hv
dWxkIGJlIGluY2x1ZGVkIGluIHRoZSBjIGZpbGUsIG5vdCBoZXJlLg0KDQpZZXMsIGlzIHNvbWV0
aGluZyBJIG1lYW50IHRvIHJlbW92ZSBkdXJpbmcgZGV2ZWxvcG1lbnQgaW5jcmVtZW50cy4gQ29u
c2lkZXIgaXQNCmdvbmUuDQoNCj4gPiArI2luY2x1ZGUgPGxpbnV4L21mZC9kYTkxNTAvY29yZS5o
Pg0KPiBIYXZpbmcgbW92ZWQgdGhlIHN0cnVjdCBkZWZpbml0aW9uIGludG8gdGhlIGMgZmlsZQ0K
PiB0aGlzIGhlYWRlciBpbmNsdWRlIHdpbGwgbm90IHdhbnQgdG8gYmUgaGVyZS4NCg0KSSBwZXJz
b25hbGx5IHdvdWxkIHByZWZlciBhIHNlcGFyYXRlIGhlYWRlciBmb3IgdGhlIGRlZmluaXRpb25z
IGFzIEkgYmVsaWV2ZQ0KdGhpcyBpcyB0aWRpZXIuIEhhdmUgbmV2ZXIgcmVhbGx5IGxpa2VkIHN0
cnVjdCBkZWZpbml0aW9ucyBpbiBjIGZpbGVzLiBJIGNvdWxkDQptb3ZlIHRoaXMgaGVhZGVyIHRv
IHRoZSBzYW1lIGRpcmVjdG9yeSBhcyB0aGUgc291cmNlIGZpbGUsIGlmIHRoYXQgaXMgcHJlZmVy
cmVkLg0KQXMgaXQgc3RhbmRzIHRoaXMgaGVhZGVyIGlzIG9ubHkgcmVsYXRlZCB0byBEQTkxNTAg
aW4gaXRzIGN1cnJlbnQgbG9jYXRpb24sIHNvDQppcyB0aGlzIGEgYmlnIGlzc3VlPyBJZiBub3Qg
dGhlbiBJJ2QgcmF0aGVyIGtlZXAgaXQgYXMgaXMuDQoNCj4gPiArLyogUHJpdmF0ZSBkYXRhICov
DQo+IFdoeSBpcyB0aGlzIGluIHRoZSBoZWFkZXI/ICBTaG91bGQgYmUgZGVmaW5lZCBkaXJlY3Rs
eSBpbiB0aGUgYyBmaWxlDQo+IGFzIG5vdGhpbmcgb3V0c2lkZSB0aGUgZHJpdmVyIHNob3VsZCBi
ZSB0b3VjaGluZyBpdC4NCg0KQXMgcGVyIHByZXZpb3VzIGNvbW1lbnQuDQo=

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

* Re: [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2014-06-16 13:12     ` Opensource [Adam Thomson]
@ 2014-06-16 20:13       ` Jonathan Cameron
  2014-06-21 11:38       ` Jonathan Cameron
  1 sibling, 0 replies; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-16 20:13 UTC (permalink / raw)
  To: Opensource [Adam Thomson], Lee Jones, Samuel Ortiz,
	linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org
  Cc: linux-kernel@vger.kernel.org, Support Opensource

On 16/06/14 14:12, Opensource [Adam Thomson] wrote:
> On Sun, Jun 15, 2014 at 20:49, Jonathan Cameron wrote:
>
>> Hi Adam,
>>
>> Some general comments inline.
>>
>> It's been a while since I've looked at any particularly similar parts,
>> but it seems to me that a lot of indirection gets added here that
>> if anything makes the codes slightly harder to follow...
>>
>> Feel free to disagree with me though!
>
> Will do :)
>
>> To my mind all these wrappers add nothing significant so you might as well
>> just call da9150->read_dev etc directly.
>>
>> Also, what are the read_qif and write_qif for?  They don't seem to be used
>> anywhere.
>
> read_qif and write_qif are for the Fuel-Gauge functionality of the chip. The
> associated driver will be submitted after acceptance of initial driver code,
> and will make use of these functions.
I'll be interested to see how this interacts with the rest of the driver.
Or does it?  Often these dual i2c address devices are best handled as two
entirely separate drivers sitting on the same bus.  No idea if that
is true here as don't have a datasheet!
>
> The wrappers automatically choose the correct client to use (QIF uses a
> different slave address to the main chip one). Means the child drivers only need
> to pass through the da9150 struct and the rest is dealt with underneath.
>
>> The only real reason I can see for these wrappers is because you want
>> to hide the struct da9150 contents from the children of the mfd. As you
>> aren't doing that, you might as well drop these in favour of direct
>> calls to regmap_read and friends.
>
> As I have a need to pass through the main da9150 struct point for the
> aforementioned wrappers, it seemed cleaner and more consistent to have wrappers
> for these as well, which did the job of regmap access. Means all HW access
> uses the same kind of approach, and all sub-devices just need a point to the
> main da9150 struct to be able to use the functions.
>
>> I'll continue my tirade against obvious comments. Wrong format and
>> adds nothing to what is here as init and exit functions are clearly
>> doing what their name suggests (it's one of my pet hates ;)
>
> I agree the comment doesn't add much in terms of description but for me it
> breaks up the code to make it easier to follow. However if I get an overwhelming
> hatred for this I can change it. Also, I know the rule regarding single/multiple
> line comments but here again I feel it helps separate the code and makes it
> easier to read.
Kernel code generally has to keep to the kernel coding style.  If you leave the
single line comments as are, then chances are the mfd maintainers will get a
patch soon after 'fixing' them which is always irritating.

Having said that, mfd is their area not mine, so up to Lee / Samuel.
The same is true of the code structure comments. Now for the IIO driver
I get to be picky ;)
>
>> As a general good practice point, I'd rather that the driver supported
>> more than one instance of the chip.. Hence you'd take a copy of da9150_devs
>> to use here.  I guess it is relatively unlikely with one of these, but
>> you never know ;)
>
> Have followed the general methods for MFD here, and a number of drivers take the
> same approach. Also, I think it would be undesirable to have multiple charger
> chips of the same type in one platform. I agree generally it's best to support
> multiple instances, but here I don't think we should.
I'm happy to let this go if it is something that would not be done, but we
certainly should not be preventing it if someone wants to build hardware
with more than one of these.  If they submit a patch later allowing it because
they have hardware that does this, then there is no way anyone is going to
block it.
>
>> Why does this need it's own file?  Does the DA9150 support any other
>> interfaces?
>
> Yes, the DA9150 also has a SPI interface. At present the plan is to just add I2C
> support for now, but in the future we may add SPI support, so have written the
> code with this in mind.
>
>> Why the indirection?  The da9150 only supports i2c as far as I can see.
>
> As per my last comment.
Fair enough.  I couldn't find a datasheet and the product brief only seemed to mention
i2c.
>
>> I'd roll this into one line and not bother with the local variable...
>
> Fair enough but I think this keeps the code cleaner, and to me it makes sense
> for the actual logic to be in core file as that's interface agnostic.
>
>> Drop comments on things that are self-evident.  Also these are one
>> line comments so should be using the single line comment syntax.
>
> As per my previous comment I think it just helps to break up the code and makes
> it more readable. Will change it though if the general consensus is to remove
> it.



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

* RE: [PATCH 6/8] power: Add support for DA9150 Charger
  2014-06-16 13:27   ` Lee Jones
@ 2014-06-17  8:21     ` Opensource [Adam Thomson]
  0 siblings, 0 replies; 29+ messages in thread
From: Opensource [Adam Thomson] @ 2014-06-17  8:21 UTC (permalink / raw)
  To: Lee Jones, Opensource [Adam Thomson]
  Cc: Samuel Ortiz, Jonathan Cameron, linux-iio@vger.kernel.org,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Support Opensource

T24gSnVuZSAxNiwgMjAxNCAxNDoyOCwgTGVlIEpvbmVzIHdyb3RlOg0KDQo+ID4gKyNpZm5kZWYg
X0RBOTE1MF9DSEFSR0VSX0gNCj4gPiArI2RlZmluZSBfREE5MTUwX0NIQVJHRVJfSA0KPiANCj4g
VHdvICdfJ3MgYXJlIG5vcm1hbGx5IHByZWZlcnJlZC4NCg0KT2ssIGNhbiBjaGFuZ2UgaXQgYWNj
b3JkaW5nbHkuDQoNCj4gDQo+ID4gKyNpbmNsdWRlIDxsaW51eC9kZXZpY2UuaD4NCj4gPiArI2lu
Y2x1ZGUgPGxpbnV4L2kyYy5oPg0KPiANCj4gV2hhdCBhcmUgeW91IHVzaW5nIHRoaXMgZm9yPw0K
DQpOb3RoaW5nLiBXaWxsIHJlbW92ZSB0aGVtLiBUaGFua3MuDQoNCj4gPiArI2luY2x1ZGUgPGxp
bnV4L21mZC9kYTkxNTAvY29yZS5oPg0KPiA+ICsNCj4gPiArDQo+IA0KPiBFeHRyYSAnXG4nIGhl
cmUuDQoNClllcywganVzdCBzZXBhcmF0ZSBpbmNsdWRlcyBmcm9tIHRoZSByZXN0IG9mIHRoZSBm
aWxlLiBGaW5kIGl0IG1vcmUgcmVhZGFibGUuDQpJZiBpdCdzIGFuIGlzc3VlIHRob3VnaCBJIGNh
biByZW1vdmUgaXQuDQoNCj4gPiArCXN0cnVjdCBwb3dlcl9zdXBwbHkgYWM7DQo+ID4gKwlzdHJ1
Y3QgcG93ZXJfc3VwcGx5IHVzYjsNCj4gPiArCXN0cnVjdCBwb3dlcl9zdXBwbHkgYmF0dGVyeTsN
Cj4gDQo+IERvIHlvdSB3YW50IHRoZXNlIChvciBwb2ludGVycyB0byB0aGVzZSkgaGVyZT8NCj4g
DQo+IEhvdyBtdWNoIHNwYWNlIGRvIHRoZXkgdGFrZSB1cD8NCg0KWWVzIHRoZXNlIGFyZSByZXF1
aXJlZCBpbiB0aGF0IHN0cnVjdHVyZS4gVGhpcyBpcyB0aGUgY29tbW9uIGFwcHJvYWNoIGZvcg0K
cG93ZXJfc3VwcGx5IGRyaXZlcnMuIFRoZSBzdHJ1Y3R1cmVzLCBoYXZpbmcgaGFkIGEgdmVyeSBx
dWljayBsb29rLCBhcmUgYXJvdW5kDQptYXliZSA3MCBieXRlcyBlYWNoLg0K

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

* Re: [PATCH 4/8] iio: Add support for DA9150 GPADC
  2014-06-16 15:58     ` Opensource [Adam Thomson]
@ 2014-06-21 11:29       ` Jonathan Cameron
  0 siblings, 0 replies; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-21 11:29 UTC (permalink / raw)
  To: Opensource [Adam Thomson], Lee Jones, Samuel Ortiz,
	linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org
  Cc: linux-kernel@vger.kernel.org, Support Opensource

On 16/06/14 16:58, Opensource [Adam Thomson] wrote:
> On June 15, 2014 21:19, Jonathon Cameron wrote:
>
>> Hi Adam
>>
>> Reasonably clean code, but the _ channels stuff doesn't comply with the ABI
>> and is rather confusing.
>
> To be honest I did debate this in my head for a while. The reason I went with
> the current approach was to make the driver channel layout match that of the
> datasheet for the device. Sounds like it wasn't the correct direction though.
>
>> If it really does make sense to allow reading these channels at different
>> ranges (presumably to enhance the effective adc resolution) then we need
>> to control this via existing ABIs. Controlling it via scale with a
>> range attribute if required (read only but changes with whatever the
>> scale attribute it set to).
>
> Yes, with smaller range then you get a better degree of accuracy. Ok, will have
> a look at this and see if I can improve things based on your comments.
>
>> Often, for slow parts at least it makes little sense to have provide
>> software support for variable input ranges.
>>
>> Looking at what is covered, is it the case that only one option will make
>> sense for a given hardware setup? (cover the required range and nothing more).
>>
>> If so, perhaps this wants to go into the device tree or similar?
>
> Possibly. Having read your comments further on though, and given that
> it seems reasonable to use the range/scale attribute to choose the resolution,
> I'd prefer to opt for that approach (seems more flexible).
Perhaps, but if the reason for these differing ranges is that they tend
to be wired to lines that have well defined voltage ranges, then I'd move
it into setup data.  Leads to a cleaner driver.  Flexibility is good, but
only if actually helps anyone!
>
>> Please get rid of excess white space and comments that just tell you
>> something obvious about the code following them.
>
> Preferably I'd like to keep it this way as I think it makes the code
> easier to read, but if you're dead against it then I'll remove them.
The issue here is about making kernel review as easy as possible.  That often
involves making code (and particularly comments) conform to somewhat arbitrary
rules and conventions.  Just makes the reviewer/maintainers life somewhat easier.
You'll also probably get follow up patches removing all this stuff on the basis
of kernel style soon after we merge the driver anyway and those just get
irritating ;)
>
>> Linear in the coeeficients, so fine for raw output with a scale and offset.
>
> Ok will have a look at re-working this as per your comment.
>
>> Ah, so here is your reasoning behind the 'interesting' underscore channels.
>> This is just doing different range checks on the channel?  If so allow one
>> at a time and provide a writable scale info_mask element to control which
>> is used..
>>
>> Looks like there are only thes two channels doing this, so shouldn't be
>> too hard to support it via more conventional means.
>
> The GPIO, VBUS and VSYS related channels provide different ranges. I guess they
> should all follow the same approach for implementing this alternate range. So I
> will assume that for the 'repeat' channels where the same raw value is provided
> on both the _ and non _ channels only one channel should be provided.
Definitely.
>
>> Don't use the |=, just = and you can't avoid assigning reg above.
>> Actually, it's not complex enough that you couldn't just do it directly into
>> the write function and skip this local variable.
>
> Ok fine. Will update to tidy up.
>
>> Unlock first, then check for error.
>
> Yep. Makes sense. Will update.
>
>> The mixture of having defs here for the shift.
>>> +	/* MSBs - 8 bits */
>>> +	result |= result_regs[0] << 2;
>> and not here is inconsistent.  I honestly don't mind which way, but
>> just use one style.
>>
>> You could just use an endian conversion and shift the combined 16bit result
>
> Fair point. Will make this cleaner.
>
>> It very rarely makes sense to provide both raw and processed interfaces.
>> If the transform is nasty and non linear then userspace won't have the info
>> to do anything with it.  If the transform is linear, then provide scale
>> and offset and let userspace perform the computation.
>
> The charger module uses certain channels for its readings, and to me it makes
> more sense for that calculation to be done by the GPADC. However having looked
> at the inkern.c framework code it looks like if you request a processed channel
> and it's doesn't provide that feature, then the code drops to linear scaling if
> possible to provide the processed value. I take it this is the preferred
> approach then?
Yup.  Saves on replicating code.  Mostly the raw access stuff is there for consistency
with buffered access (where speed matters and we may or may not want to convert to
real units).  So you should provide the information to do the scaling anyway, so
just let the core code handle it for you.
> Just thought it was more consistent to see the calculation using
> dedicated functions (processed channel approach).
>
>> Get rid of this comment and any other ones that don't add any
>> actual information.  Also this is single line comment, please
>> check the comment syntax.
>
> As per previous comment on this topic.
>
>> Why a blank line here.
>
> Accidental. Will remove it.
>
>> The device register call is the one that exposes userspace interfaces. As
>> a general rule it wants to be the last thing in probe as everything
>> else should be setup first.
>
> Ok, that's something I missed. Will make the change.
>
>>> +#include <linux/iio/machine.h>
>> This isn't used in the header, so should be included in the c file, not here.
>
> Yes, is something I meant to remove during development increments. Consider it
> gone.
>
>>> +#include <linux/mfd/da9150/core.h>
>> Having moved the struct definition into the c file
>> this header include will not want to be here.
>
> I personally would prefer a separate header for the definitions as I believe
> this is tidier. Have never really liked struct definitions in c files.
Again, kernel coding style. Have everything as local as you can.
Makes it obvious nothing else uses the structure and also ever so slightly
cuts down on compile time (all helps!)

Anyhow, please bring them into the c code.   Have only stuff that is genuinely
shared between different c files in headers.  If those c files are in the same
directory then have the header within the directory as well.
> I could
> move this header to the same directory as the source file, if that is preferred.
> As it stands this header is only related to DA9150 in its current location, so
> is this a big issue? If not then I'd rather keep it as is.
>
>>> +/* Private data */
>> Why is this in the header?  Should be defined directly in the c file
>> as nothing outside the driver should be touching it.
>
> As per previous comment.
>


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

* Re: [PATCH 3/8] iio: of_iio_channel_get_by_name() returns non-null pointers for error legs
  2014-06-15 20:20   ` Jonathan Cameron
@ 2014-06-21 11:32     ` Jonathan Cameron
  0 siblings, 0 replies; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-21 11:32 UTC (permalink / raw)
  To: Adam Thomson, Lee Jones, Samuel Ortiz, linux-iio,
	Dmitry Eremin-Solenikov, David Woodhouse, Rob Herring, Pawel Moll,
	Mark Rutland, Ian Campbell, Kumar Gala, devicetree
  Cc: linux-kernel, support.opensource

On 15/06/14 21:20, Jonathan Cameron wrote:
> On 11/06/14 12:11, Adam Thomson wrote:
>> Currently in the inkern.c code for IIO framework, the function
>> of_iio_channel_get_by_name() will return a non-NULL pointer when
>> it cannot find a channel using of_iio_channel_get() and when it
>> tries to search for 'io-channel-ranges' property and fails. This
>> is incorrect behaviour as the function which calls this expects
>> a NULL pointer for failure. This patch rectifies the issue.
>>
>> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> Hi Adam,
>
> Good find.  I've only recently sent a pull request for fixes upstream,
> so I'll pick this up in a day or so once that has gone.
Applied to the fixes-togreg branch of iio.git and cc'd to stable.

Thanks,

Jonathan
>
> J
>> ---
>>   drivers/iio/inkern.c | 6 ++++--
>>   1 file changed, 4 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
>> index 0cf5f8e..1e8e94d 100644
>> --- a/drivers/iio/inkern.c
>> +++ b/drivers/iio/inkern.c
>> @@ -183,7 +183,7 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
>>           else if (name && index >= 0) {
>>               pr_err("ERROR: could not get IIO channel %s:%s(%i)\n",
>>                   np->full_name, name ? name : "", index);
>> -            return chan;
>> +            return NULL;
>>           }
>>
>>           /*
>> @@ -193,8 +193,9 @@ static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
>>            */
>>           np = np->parent;
>>           if (np && !of_get_property(np, "io-channel-ranges", NULL))
>> -            break;
>> +            return NULL;
>>       }
>> +
>>       return chan;
>>   }
>>
>> @@ -317,6 +318,7 @@ struct iio_channel *iio_channel_get(struct device *dev,
>>           if (channel != NULL)
>>               return channel;
>>       }
>> +
>>       return iio_channel_get_sys(name, channel_name);
>>   }
>>   EXPORT_SYMBOL_GPL(iio_channel_get);
>> --
>> 1.9.3
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* Re: [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2014-06-16 13:12     ` Opensource [Adam Thomson]
  2014-06-16 20:13       ` Jonathan Cameron
@ 2014-06-21 11:38       ` Jonathan Cameron
  1 sibling, 0 replies; 29+ messages in thread
From: Jonathan Cameron @ 2014-06-21 11:38 UTC (permalink / raw)
  To: Opensource [Adam Thomson], Lee Jones, Samuel Ortiz,
	linux-iio@vger.kernel.org, Dmitry Eremin-Solenikov,
	David Woodhouse, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, devicetree@vger.kernel.org
  Cc: linux-kernel@vger.kernel.org, Support Opensource

On 16/06/14 14:12, Opensource [Adam Thomson] wrote:
> On Sun, Jun 15, 2014 at 20:49, Jonathan Cameron wrote:
>
>> Hi Adam,
>>
>> Some general comments inline.
>>
>> It's been a while since I've looked at any particularly similar parts,
>> but it seems to me that a lot of indirection gets added here that
>> if anything makes the codes slightly harder to follow...
>>
>> Feel free to disagree with me though!
>
> Will do :)
>
>> To my mind all these wrappers add nothing significant so you might as well
>> just call da9150->read_dev etc directly.
>>
>> Also, what are the read_qif and write_qif for?  They don't seem to be used
>> anywhere.
>
> read_qif and write_qif are for the Fuel-Gauge functionality of the chip. The
> associated driver will be submitted after acceptance of initial driver code,
> and will make use of these functions.
Ideally drop these for now and bring them in as a precursor patch in the series
that introduces them being used.
>
> The wrappers automatically choose the correct client to use (QIF uses a
> different slave address to the main chip one). Means the child drivers only need
> to pass through the da9150 struct and the rest is dealt with underneath.
>
>> The only real reason I can see for these wrappers is because you want
>> to hide the struct da9150 contents from the children of the mfd. As you
>> aren't doing that, you might as well drop these in favour of direct
>> calls to regmap_read and friends.
>
> As I have a need to pass through the main da9150 struct point for the
> aforementioned wrappers, it seemed cleaner and more consistent to have wrappers
> for these as well, which did the job of regmap access. Means all HW access
> uses the same kind of approach, and all sub-devices just need a point to the
> main da9150 struct to be able to use the functions.
>
>> I'll continue my tirade against obvious comments. Wrong format and
>> adds nothing to what is here as init and exit functions are clearly
>> doing what their name suggests (it's one of my pet hates ;)
>
> I agree the comment doesn't add much in terms of description but for me it
> breaks up the code to make it easier to follow.
They really don't make it significantly easier to follow and after a few
cycles of the driver being patched with new stuff etc, they tend to become
actively misleading.
>However if I get an overwhelming
> hatred for this I can change it. Also, I know the rule regarding single/multiple
> line comments but here again I feel it helps separate the code and makes it
> easier to read.
I'll leave it up to the other maintainers to say they don't mind.  But for IIO
please keep strictly to the style (including all the unwritten bits ;)

>
>> As a general good practice point, I'd rather that the driver supported
>> more than one instance of the chip.. Hence you'd take a copy of da9150_devs
>> to use here.  I guess it is relatively unlikely with one of these, but
>> you never know ;)
>
> Have followed the general methods for MFD here, and a number of drivers take the
> same approach. Also, I think it would be undesirable to have multiple charger
> chips of the same type in one platform. I agree generally it's best to support
> multiple instances, but here I don't think we should.
You are a brave man to tell your customers what to do.  If some crazy person
does use multiple of these chips on a device you get to deal with the inevitable
question of why doesn't it work ;)
>
>> Why does this need it's own file?  Does the DA9150 support any other
>> interfaces?
>
> Yes, the DA9150 also has a SPI interface. At present the plan is to just add I2C
> support for now, but in the future we may add SPI support, so have written the
> code with this in mind.
Ah, I didn't find that from the details I could find via google.  In that
case fair enough.
>
>> Why the indirection?  The da9150 only supports i2c as far as I can see.
>
> As per my last comment.
>
>> I'd roll this into one line and not bother with the local variable...
>
> Fair enough but I think this keeps the code cleaner, and to me it makes sense
> for the actual logic to be in core file as that's interface agnostic.
>
>> Drop comments on things that are self-evident.  Also these are one
>> line comments so should be using the single line comment syntax.
>
> As per my previous comment I think it just helps to break up the code and makes
> it more readable. Will change it though if the general consensus is to remove
> it.


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

end of thread, other threads:[~2014-06-21 11:36 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-06-11 11:11 [PATCH 0/8] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
2014-06-11 11:11 ` [PATCH 1/8] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
2014-06-15 19:49   ` Jonathan Cameron
2014-06-16 13:12     ` Opensource [Adam Thomson]
2014-06-16 20:13       ` Jonathan Cameron
2014-06-21 11:38       ` Jonathan Cameron
2014-06-11 11:11 ` [PATCH 2/8] mfd: da9150: Add DT binding documentation for core Adam Thomson
2014-06-11 11:11 ` [PATCH 3/8] iio: of_iio_channel_get_by_name() returns non-null pointers for error legs Adam Thomson
2014-06-15 20:20   ` Jonathan Cameron
2014-06-21 11:32     ` Jonathan Cameron
2014-06-11 11:11 ` [PATCH 4/8] iio: Add support for DA9150 GPADC Adam Thomson
2014-06-11 16:34   ` Jonathan Cameron
2014-06-11 16:56     ` Opensource [Adam Thomson]
2014-06-15 19:55       ` Jonathan Cameron
2014-06-15 20:19   ` Jonathan Cameron
2014-06-16 15:58     ` Opensource [Adam Thomson]
2014-06-21 11:29       ` Jonathan Cameron
2014-06-11 11:11 ` [PATCH 5/8] iio: da9150: Add DT binding documentation for GPADC Adam Thomson
2014-06-11 11:11 ` [PATCH 6/8] power: Add support for DA9150 Charger Adam Thomson
2014-06-16 13:27   ` Lee Jones
2014-06-17  8:21     ` Opensource [Adam Thomson]
2014-06-11 11:11 ` [PATCH 7/8] power: da9150: Add DT binding documentation for charger Adam Thomson
2014-06-11 11:11 ` [PATCH 8/8] DT: Add vendor prefix for Dialog Semiconductor Ltd Adam Thomson
2014-06-11 12:09   ` Geert Uytterhoeven
2014-06-11 12:43     ` Rob Herring
2014-06-11 13:01       ` Geert Uytterhoeven
2014-06-11 13:17       ` Opensource [Adam Thomson]
2014-06-11 14:22         ` Rob Herring
2014-06-11 13:31       ` Adam Thomson

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).