linux-iio.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC
@ 2014-12-22 16:50 Adam Thomson
  2014-12-22 16:51 ` [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
                   ` (6 more replies)
  0 siblings, 7 replies; 20+ messages in thread
From: Adam Thomson @ 2014-12-22 16:50 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  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.
 - IIO GPADC support and DT bindings documentation.
 - Power Supply Charger support and DT bindings documentation.
 - Update to MAINTAINERS file to add DA9150 files to Dialog support list.
 - Update to IIO ABI document to add info regarding input current readings.

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.19-rc1 kernel version.

Changes in v5:
- Use sizeof(*gpadc) instead of sizeof(struct da9150_gpadc) in GPADC driver.
- Fix erroneous goto for IRQ failure in GPADC driver. Now returns err directly.
- Remove IIO ABI document patch as this has been taken by maintainer.

Changes in v4:
- Correct MODULE_AUTHOR lines so e-mail addresses correctly surrounded with <>.
- Update to MFD binding document to remove unnecesary I2C reference, make
  module description generic, and add link to interrupt binding documentation.
- For GPADC driver, irq request moved above iio related calls in probe() to
  mirror correctly the remove() function ordering, as requested.
- For charger driver, remove additional sysfs entries as these are not necessary
  (debug only).
- For charger driver, add helper function for requesting IRQs, to make probe()
  function cleaner/simpler.

Changes in v3:
- IRQ register and remove helper functions removed from MFD, deemed unnecessary.
  Drivers using helper functions updated to use direct calls to relevant
  kernel framework functions.
- MFD I2C file removed and code folded into -core file as requested.
- MFD core now buildable as driver module.
- Platform data structure definition moved into core header, pdata.h removed.
- Update functions in GPADC driver to be static, where appropriate.
- Change units of GPADC readings to match ABI documentation. Updates to charger
  driver also made to align with this modification.
- Refactor GPADC temp calculations to use scale & offset method.
- Scale values now returned as FRACTIONAL to allow for accurate conversion in
  user-space.
- Tidy up of GPADC scale, offset and raw functions to return from case statements
  with correct return types.
- Update GPADC channel macros naming to prefix with DA9150, prevent conflict.
- GPADC GPIO voltage readings actually in 6V range, updated accordingly.
- Addition to IIO ABI document to add details on input current readings.
- Small style updates to address comments.

Changes in v2:
 - Drop devicetree prefix patch as this is being dealt with separately.
 - IIO framework fix patch removed from set, has already been accepted/merged.
 - Use __ instead of _ for protecting #ifdefs in headers.
 - Moved private data & definitions to source files and remove unwanted headers.
 - Bug fix to EXPORT_SYMBOL for common functions in MFD core used by
   sub-devices, so they can be correctly built as kernel modules.
 - Removed unnecessary channels from GPADC IIO driver to simplify code.
 - For GPADC IIO driver, VBAT reading now provides scale and offset values as it
   is a linear scale.
 - GPADC read code refactored to make it tidier.
 - Remove use of flag to indicate GPADC availability. IIO framework should
   indicate need to defer if it's not yet instantiated.
 - Unwanted comments removed.
 - Removed conditional shutdown of device (Charger/MFD) as this is not needed.
 - Removed AC type supply from charger as device cannot differentiate. Now just
   uses USB supply type.
 - Removed use of invalid-tbat flag from platform data as it doesn't really add
   anything to the driver except forcing battery present status.
 - Bug fix for checking of usb_phy validity in Charger probe() function.
 - Addition of common IRQ release function to allow sub-devices to explicitly
   tidy up IRQs when devm clean up is too late.
 - Improved tidy up of resources in charger.
 - Fix location of IIO GPADC related devicetree binding document so it now
   resides correctly under 'adc' directory.
 - Add update to MAINTAINERS file to include these files in Dialog support list.

Adam Thomson (7):
  mfd: Add support for DA9150 combined charger & fuel-gauge device
  mfd: da9150: Add DT binding documentation for core
  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
  MAINTAINERS: Include DA9150 files in Dialog Semiconductor support
    list.

 .../devicetree/bindings/iio/adc/da9150-gpadc.txt   |   16 +
 Documentation/devicetree/bindings/mfd/da9150.txt   |   43 +
 .../devicetree/bindings/power/da9150-charger.txt   |   26 +
 MAINTAINERS                                        |    4 +
 drivers/iio/adc/Kconfig                            |    9 +
 drivers/iio/adc/Makefile                           |    1 +
 drivers/iio/adc/da9150-gpadc.c                     |  409 +++++++
 drivers/mfd/Kconfig                                |   12 +
 drivers/mfd/Makefile                               |    2 +-
 drivers/mfd/da9150-core.c                          |  413 +++++++
 drivers/power/Kconfig                              |   12 +
 drivers/power/Makefile                             |    1 +
 drivers/power/da9150-charger.c                     |  666 +++++++++++
 include/linux/mfd/da9150/core.h                    |   68 ++
 include/linux/mfd/da9150/registers.h               | 1155 ++++++++++++++++++++
 15 files changed, 2836 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/iio/adc/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/power/da9150-charger.c
 create mode 100644 include/linux/mfd/da9150/core.h
 create mode 100644 include/linux/mfd/da9150/registers.h

--
1.9.3

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

* [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2014-12-22 16:50 [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
@ 2014-12-22 16:51 ` Adam Thomson
  2015-01-19 11:33   ` Lee Jones
  2014-12-22 16:51 ` [PATCH v5 2/7] mfd: da9150: Add DT binding documentation for core Adam Thomson
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 20+ messages in thread
From: Adam Thomson @ 2014-12-22 16:51 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  Cc: linux-kernel, support.opensource

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

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 drivers/mfd/Kconfig                  |   12 +
 drivers/mfd/Makefile                 |    2 +-
 drivers/mfd/da9150-core.c            |  413 ++++++++++++
 include/linux/mfd/da9150/core.h      |   68 ++
 include/linux/mfd/da9150/registers.h | 1155 ++++++++++++++++++++++++++++++++++
 5 files changed, 1649 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mfd/da9150-core.c
 create mode 100644 include/linux/mfd/da9150/core.h
 create mode 100644 include/linux/mfd/da9150/registers.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 2e6b731..56e80d2 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -195,6 +195,18 @@ config MFD_DA9063
 	  Additional drivers must be enabled in order to use the functionality
 	  of the device.

+config MFD_DA9150
+	tristate "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_DLN2
 	tristate "Diolan DLN2 support"
 	select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 53467e2..f06f4c6 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -113,7 +113,7 @@ 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
 obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
 obj-$(CONFIG_MFD_MAX77686)	+= max77686.o
 obj-$(CONFIG_MFD_MAX77693)	+= max77693.o
diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c
new file mode 100644
index 0000000..4d757b9
--- /dev/null
+++ b/drivers/mfd/da9150-core.c
@@ -0,0 +1,413 @@
+/*
+ * 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/i2c.h>
+#include <linux/regmap.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>
+
+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,
+};
+
+u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
+{
+	int val, ret;
+
+	ret = regmap_read(da9150->regmap, reg, &val);
+	if (ret)
+		dev_err(da9150->dev, "Failed to read from reg 0x%x: %d\n",
+			reg, ret);
+
+	return (u8) val;
+}
+EXPORT_SYMBOL_GPL(da9150_reg_read);
+
+void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val)
+{
+	int ret;
+
+	ret = regmap_write(da9150->regmap, reg, val);
+	if (ret)
+		dev_err(da9150->dev, "Failed to write to reg 0x%x: %d\n",
+			reg, ret);
+}
+EXPORT_SYMBOL_GPL(da9150_reg_write);
+
+void 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)
+		dev_err(da9150->dev, "Failed to set bits in reg 0x%x: %d\n",
+			reg, ret);
+}
+EXPORT_SYMBOL_GPL(da9150_set_bits);
+
+void 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)
+		dev_err(da9150->dev, "Failed to bulk read from reg 0x%x: %d\n",
+			reg, ret);
+}
+EXPORT_SYMBOL_GPL(da9150_bulk_read);
+
+void 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)
+		dev_err(da9150->dev, "Failed to bulk write to reg 0x%x %d\n",
+			reg, ret);
+}
+EXPORT_SYMBOL_GPL(da9150_bulk_write);
+
+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),
+};
+
+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 mfd_cell da9150_devs[] = {
+	{
+		.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),
+	},
+};
+
+static int da9150_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct da9150 *da9150;
+	struct da9150_pdata *pdata = dev_get_platdata(&client->dev);
+	int ret;
+
+	da9150 = devm_kzalloc(&client->dev, sizeof(*da9150), GFP_KERNEL);
+	if (!da9150)
+		return -ENOMEM;
+
+	da9150->dev = &client->dev;
+	da9150->irq = client->irq;
+	i2c_set_clientdata(client, 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->irq_base = pdata ? pdata->irq_base : -1;
+
+	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)
+		return ret;
+
+	da9150->irq_base = regmap_irq_chip_get_base(da9150->regmap_irq_data);
+	enable_irq_wake(da9150->irq);
+
+	ret = mfd_add_devices(da9150->dev, -1, da9150_devs,
+			      ARRAY_SIZE(da9150_devs), NULL,
+			      da9150->irq_base, NULL);
+	if (ret) {
+		dev_err(da9150->dev, "Failed to add child devices: %d\n", ret);
+		regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int da9150_remove(struct i2c_client *client)
+{
+	struct da9150 *da9150 = i2c_get_clientdata(client);
+
+	regmap_del_irq_chip(da9150->irq, da9150->regmap_irq_data);
+	mfd_remove_devices(da9150->dev);
+
+	return 0;
+}
+
+static void da9150_shutdown(struct i2c_client *client)
+{
+	struct da9150 *da9150 = i2c_get_clientdata(client);
+
+	/* 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);
+}
+
+static const struct i2c_device_id da9150_i2c_id[] = {
+	{ "da9150", },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, da9150_i2c_id);
+
+static const struct of_device_id da9150_of_match[] = {
+	{ .compatible = "dlg,da9150", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, da9150_of_match);
+
+static struct i2c_driver da9150_driver = {
+	.driver	= {
+		.name	= "da9150",
+		.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("MFD Core 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..76e6689
--- /dev/null
+++ b/include/linux/mfd/da9150/core.h
@@ -0,0 +1,68 @@
+/*
+ * 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/interrupt.h>
+#include <linux/regmap.h>
+
+/* 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
+
+struct da9150_pdata {
+	int irq_base;
+};
+
+struct da9150 {
+	struct device *dev;
+	struct regmap *regmap;
+	struct regmap_irq_chip_data *regmap_irq_data;
+	int irq;
+	int irq_base;
+};
+
+/* Device I/O */
+u8 da9150_reg_read(struct da9150 *da9150, u16 reg);
+void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val);
+void da9150_set_bits(struct da9150 *da9150, u16 reg, u8 mask, u8 val);
+
+void da9150_bulk_read(struct da9150 *da9150, u16 reg, int count, u8 *buf);
+void da9150_bulk_write(struct da9150 *da9150, u16 reg, int count, const u8 *buf);
+#endif /* __DA9150_CORE_H */
diff --git a/include/linux/mfd/da9150/registers.h b/include/linux/mfd/da9150/registers.h
new file mode 100644
index 0000000..27ca6ee
--- /dev/null
+++ b/include/linux/mfd/da9150/registers.h
@@ -0,0 +1,1155 @@
+/*
+ * 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
+
+#include <linux/bitops.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
+
+/* 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			BIT(6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			BIT(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			BIT(0)
+#define DA9150_TFAULT_STAT_SHIFT		1
+#define DA9150_TFAULT_STAT_MASK			BIT(1)
+
+/* DA9150_STATUS_C = 0x06A */
+#define DA9150_VDD33_STAT_SHIFT			0
+#define DA9150_VDD33_STAT_MASK			BIT(0)
+#define DA9150_VDD33_SLEEP_SHIFT		1
+#define DA9150_VDD33_SLEEP_MASK			BIT(1)
+#define DA9150_LFOSC_STAT_SHIFT			7
+#define DA9150_LFOSC_STAT_MASK			BIT(7)
+
+/* DA9150_STATUS_D = 0x06B */
+#define DA9150_GPIOA_STAT_SHIFT			0
+#define DA9150_GPIOA_STAT_MASK			BIT(0)
+#define DA9150_GPIOB_STAT_SHIFT			1
+#define DA9150_GPIOB_STAT_MASK			BIT(1)
+#define DA9150_GPIOC_STAT_SHIFT			2
+#define DA9150_GPIOC_STAT_MASK			BIT(2)
+#define DA9150_GPIOD_STAT_SHIFT			3
+#define DA9150_GPIOD_STAT_MASK			BIT(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			BIT(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			BIT(0)
+#define DA9150_ID_ERR_SHIFT			1
+#define DA9150_ID_ERR_MASK			BIT(1)
+#define DA9150_PT_CHG_SHIFT			2
+#define DA9150_PT_CHG_MASK			BIT(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			BIT(0)
+#define DA9150_VBUS_STAT_CHG			(0x02 << 0)
+#define DA9150_VBUS_TRED_SHIFT			3
+#define DA9150_VBUS_TRED_MASK			BIT(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			BIT(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			BIT(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		BIT(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			BIT(1)
+#define DA9150_CHG_TRED_SHIFT			2
+#define DA9150_CHG_TRED_MASK			BIT(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			BIT(6)
+#define DA9150_CHG_BAT_REMOVED_SHIFT		7
+#define DA9150_CHG_BAT_REMOVED_MASK		BIT(7)
+
+/* DA9150_FAULT_LOG_A = 0x076 */
+#define DA9150_TEMP_FAULT_SHIFT			0
+#define DA9150_TEMP_FAULT_MASK			BIT(0)
+#define DA9150_VSYS_FAULT_SHIFT			1
+#define DA9150_VSYS_FAULT_MASK			BIT(1)
+#define DA9150_START_FAULT_SHIFT		2
+#define DA9150_START_FAULT_MASK			BIT(2)
+#define DA9150_EXT_FAULT_SHIFT			3
+#define DA9150_EXT_FAULT_MASK			BIT(3)
+#define DA9150_POR_FAULT_SHIFT			4
+#define DA9150_POR_FAULT_MASK			BIT(4)
+
+/* DA9150_FAULT_LOG_B = 0x077 */
+#define DA9150_VBUS_FAULT_SHIFT			0
+#define DA9150_VBUS_FAULT_MASK			BIT(0)
+#define DA9150_OTG_FAULT_SHIFT			1
+#define DA9150_OTG_FAULT_MASK			BIT(1)
+
+/* DA9150_EVENT_E = 0x078 */
+#define DA9150_E_VBUS_SHIFT			0
+#define DA9150_E_VBUS_MASK			BIT(0)
+#define DA9150_E_CHG_SHIFT			1
+#define DA9150_E_CHG_MASK			BIT(1)
+#define DA9150_E_TCLASS_SHIFT			2
+#define DA9150_E_TCLASS_MASK			BIT(2)
+#define DA9150_E_TJUNC_SHIFT			3
+#define DA9150_E_TJUNC_MASK			BIT(3)
+#define DA9150_E_VFAULT_SHIFT			4
+#define DA9150_E_VFAULT_MASK			BIT(4)
+#define DA9150_EVENTS_H_SHIFT			5
+#define DA9150_EVENTS_H_MASK			BIT(5)
+#define DA9150_EVENTS_G_SHIFT			6
+#define DA9150_EVENTS_G_MASK			BIT(6)
+#define DA9150_EVENTS_F_SHIFT			7
+#define DA9150_EVENTS_F_MASK			BIT(7)
+
+/* DA9150_EVENT_F = 0x079 */
+#define DA9150_E_CONF_SHIFT			0
+#define DA9150_E_CONF_MASK			BIT(0)
+#define DA9150_E_DAT_SHIFT			1
+#define DA9150_E_DAT_MASK			BIT(1)
+#define DA9150_E_DTYPE_SHIFT			3
+#define DA9150_E_DTYPE_MASK			BIT(3)
+#define DA9150_E_ID_SHIFT			4
+#define DA9150_E_ID_MASK			BIT(4)
+#define DA9150_E_ADP_SHIFT			5
+#define DA9150_E_ADP_MASK			BIT(5)
+#define DA9150_E_SESS_END_SHIFT			6
+#define DA9150_E_SESS_END_MASK			BIT(6)
+#define DA9150_E_SESS_VLD_SHIFT			7
+#define DA9150_E_SESS_VLD_MASK			BIT(7)
+
+/* DA9150_EVENT_G = 0x07A */
+#define DA9150_E_FG_SHIFT			0
+#define DA9150_E_FG_MASK			BIT(0)
+#define DA9150_E_GP_SHIFT			1
+#define DA9150_E_GP_MASK			BIT(1)
+#define DA9150_E_TBAT_SHIFT			2
+#define DA9150_E_TBAT_MASK			BIT(2)
+#define DA9150_E_GPIOA_SHIFT			3
+#define DA9150_E_GPIOA_MASK			BIT(3)
+#define DA9150_E_GPIOB_SHIFT			4
+#define DA9150_E_GPIOB_MASK			BIT(4)
+#define DA9150_E_GPIOC_SHIFT			5
+#define DA9150_E_GPIOC_MASK			BIT(5)
+#define DA9150_E_GPIOD_SHIFT			6
+#define DA9150_E_GPIOD_MASK			BIT(6)
+#define DA9150_E_GPADC_SHIFT			7
+#define DA9150_E_GPADC_MASK			BIT(7)
+
+/* DA9150_EVENT_H = 0x07B */
+#define DA9150_E_WKUP_SHIFT			0
+#define DA9150_E_WKUP_MASK			BIT(0)
+
+/* DA9150_IRQ_MASK_E = 0x07C */
+#define DA9150_M_VBUS_SHIFT			0
+#define DA9150_M_VBUS_MASK			BIT(0)
+#define DA9150_M_CHG_SHIFT			1
+#define DA9150_M_CHG_MASK			BIT(1)
+#define DA9150_M_TJUNC_SHIFT			3
+#define DA9150_M_TJUNC_MASK			BIT(3)
+#define DA9150_M_VFAULT_SHIFT			4
+#define DA9150_M_VFAULT_MASK			BIT(4)
+
+/* DA9150_IRQ_MASK_F = 0x07D */
+#define DA9150_M_CONF_SHIFT			0
+#define DA9150_M_CONF_MASK			BIT(0)
+#define DA9150_M_DAT_SHIFT			1
+#define DA9150_M_DAT_MASK			BIT(1)
+#define DA9150_M_DTYPE_SHIFT			3
+#define DA9150_M_DTYPE_MASK			BIT(3)
+#define DA9150_M_ID_SHIFT			4
+#define DA9150_M_ID_MASK			BIT(4)
+#define DA9150_M_ADP_SHIFT			5
+#define DA9150_M_ADP_MASK			BIT(5)
+#define DA9150_M_SESS_END_SHIFT			6
+#define DA9150_M_SESS_END_MASK			BIT(6)
+#define DA9150_M_SESS_VLD_SHIFT			7
+#define DA9150_M_SESS_VLD_MASK			BIT(7)
+
+/* DA9150_IRQ_MASK_G = 0x07E */
+#define DA9150_M_FG_SHIFT			0
+#define DA9150_M_FG_MASK			BIT(0)
+#define DA9150_M_GP_SHIFT			1
+#define DA9150_M_GP_MASK			BIT(1)
+#define DA9150_M_TBAT_SHIFT			2
+#define DA9150_M_TBAT_MASK			BIT(2)
+#define DA9150_M_GPIOA_SHIFT			3
+#define DA9150_M_GPIOA_MASK			BIT(3)
+#define DA9150_M_GPIOB_SHIFT			4
+#define DA9150_M_GPIOB_MASK			BIT(4)
+#define DA9150_M_GPIOC_SHIFT			5
+#define DA9150_M_GPIOC_MASK			BIT(5)
+#define DA9150_M_GPIOD_SHIFT			6
+#define DA9150_M_GPIOD_MASK			BIT(6)
+#define DA9150_M_GPADC_SHIFT			7
+#define DA9150_M_GPADC_MASK			BIT(7)
+
+/* DA9150_IRQ_MASK_H = 0x07F */
+#define DA9150_M_WKUP_SHIFT			0
+#define DA9150_M_WKUP_MASK			BIT(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			BIT(6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			BIT(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			BIT(6)
+#define DA9150_PS_DISABLE_DIRECT_SHIFT		7
+#define DA9150_PS_DISABLE_DIRECT_MASK		BIT(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			BIT(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			BIT(0)
+#define DA9150_VDD33_DWN_SHIFT			1
+#define DA9150_VDD33_DWN_MASK			BIT(1)
+#define DA9150_WKUP_PM_EN_SHIFT			2
+#define DA9150_WKUP_PM_EN_MASK			BIT(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		BIT(5)
+#define DA9150_DISABLE_DEL_SHIFT		7
+#define DA9150_DISABLE_DEL_MASK			BIT(7)
+
+/* DA9150_CONFIG_E = 0x0E4 */
+#define DA9150_PM_SPKSUP_DIS_SHIFT		0
+#define DA9150_PM_SPKSUP_DIS_MASK		BIT(0)
+#define DA9150_PM_MERGE_SHIFT			1
+#define DA9150_PM_MERGE_MASK			BIT(1)
+#define DA9150_PM_SR_OFF_SHIFT			2
+#define DA9150_PM_SR_OFF_MASK			BIT(2)
+#define DA9150_PM_TIMEOUT_EN_SHIFT		3
+#define DA9150_PM_TIMEOUT_EN_MASK		BIT(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		BIT(7)
+
+/* DA9150_CONTROL_A = 0x0E5 */
+#define DA9150_VDD33_SL_SHIFT			0
+#define DA9150_VDD33_SL_MASK			BIT(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			BIT(3)
+#define DA9150_GPI_LPM_SHIFT			6
+#define DA9150_GPI_LPM_MASK			BIT(6)
+#define DA9150_PM_IF_LPM_SHIFT			7
+#define DA9150_PM_IF_LPM_MASK			BIT(7)
+
+/* DA9150_CONTROL_B = 0x0E6 */
+#define DA9150_LPM_SHIFT			0
+#define DA9150_LPM_MASK				BIT(0)
+#define DA9150_RESET_SHIFT			1
+#define DA9150_RESET_MASK			BIT(1)
+#define DA9150_RESET_USRCONF_EN_SHIFT		2
+#define DA9150_RESET_USRCONF_EN_MASK		BIT(2)
+
+/* DA9150_CONTROL_C = 0x0E7 */
+#define DA9150_DISABLE_SHIFT			0
+#define DA9150_DISABLE_MASK			BIT(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			BIT(0)
+#define DA9150_GPIOA_TYPE_SHIFT			3
+#define DA9150_GPIOA_TYPE_MASK			BIT(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			BIT(4)
+#define DA9150_GPIOB_TYPE_SHIFT			7
+#define DA9150_GPIOB_TYPE_MASK			BIT(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			BIT(0)
+#define DA9150_GPIOC_TYPE_SHIFT			3
+#define DA9150_GPIOC_TYPE_MASK			BIT(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			BIT(4)
+#define DA9150_GPIOD_TYPE_SHIFT			7
+#define DA9150_GPIOD_TYPE_MASK			BIT(7)
+
+/* DA9150_GPIO_MODE_CONT = 0x0EA */
+#define DA9150_GPIOA_MODE_SHIFT			0
+#define DA9150_GPIOA_MODE_MASK			BIT(0)
+#define DA9150_GPIOB_MODE_SHIFT			1
+#define DA9150_GPIOB_MODE_MASK			BIT(1)
+#define DA9150_GPIOC_MODE_SHIFT			2
+#define DA9150_GPIOC_MODE_MASK			BIT(2)
+#define DA9150_GPIOD_MODE_SHIFT			3
+#define DA9150_GPIOD_MODE_MASK			BIT(3)
+#define DA9150_GPIOA_CONT_SHIFT			4
+#define DA9150_GPIOA_CONT_MASK			BIT(4)
+#define DA9150_GPIOB_CONT_SHIFT			5
+#define DA9150_GPIOB_CONT_MASK			BIT(5)
+#define DA9150_GPIOC_CONT_SHIFT			6
+#define DA9150_GPIOC_CONT_MASK			BIT(6)
+#define DA9150_GPIOD_CONT_SHIFT			7
+#define DA9150_GPIOD_CONT_MASK			BIT(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			BIT(2)
+#define DA9150_WAKE_CONT_SHIFT			3
+#define DA9150_WAKE_CONT_MASK			BIT(3)
+#define DA9150_WAKE_DLY_SHIFT			4
+#define DA9150_WAKE_DLY_MASK			BIT(4)
+
+/* DA9150_GPIO_CTRL_A = 0x0EC */
+#define DA9150_GPIOA_ANAEN_SHIFT		0
+#define DA9150_GPIOA_ANAEN_MASK			BIT(0)
+#define DA9150_GPIOB_ANAEN_SHIFT		1
+#define DA9150_GPIOB_ANAEN_MASK			BIT(1)
+#define DA9150_GPIOC_ANAEN_SHIFT		2
+#define DA9150_GPIOC_ANAEN_MASK			BIT(2)
+#define DA9150_GPIOD_ANAEN_SHIFT		3
+#define DA9150_GPIOD_ANAEN_MASK			BIT(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			BIT(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			BIT(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			BIT(0)
+#define DA9150_GPIOB_PUPD_SHIFT			1
+#define DA9150_GPIOB_PUPD_MASK			BIT(1)
+#define DA9150_GPIOC_PUPD_SHIFT			2
+#define DA9150_GPIOC_PUPD_MASK			BIT(2)
+#define DA9150_GPIOD_PUPD_SHIFT			3
+#define DA9150_GPIOD_PUPD_MASK			BIT(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			BIT(7)
+
+/* DA9150_GPIO_CFG_C = 0x0F0 */
+#define DA9150_GPI_V_SHIFT			0
+#define DA9150_GPI_V_MASK			BIT(0)
+#define DA9150_VDDIO_INT_SHIFT			1
+#define DA9150_VDDIO_INT_MASK			BIT(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			BIT(6)
+#define DA9150_NIRQ_PUPD_SHIFT			7
+#define DA9150_NIRQ_PUPD_MASK			BIT(7)
+
+/* DA9150_GPADC_MAN = 0x0F2 */
+#define DA9150_GPADC_EN_SHIFT			0
+#define DA9150_GPADC_EN_MASK			BIT(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			BIT(0)
+#define DA9150_GPADC_RES_L_SHIFT		6
+#define DA9150_GPADC_RES_L_MASK			(0x03 << 6)
+#define DA9150_GPADC_RES_L_BITS			2
+
+/* 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			BIT(6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			BIT(7)
+
+/* DA9150_OTP_CONT_SHARED = 0x101 */
+#define DA9150_PC_DONE_SHIFT			3
+#define DA9150_PC_DONE_MASK			BIT(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			BIT(1)
+#define DA9150_NIRQ_PIN_SHIFT			2
+#define DA9150_NIRQ_PIN_MASK			BIT(2)
+#define DA9150_NIRQ_TYPE_SHIFT			3
+#define DA9150_NIRQ_TYPE_MASK			BIT(3)
+#define DA9150_PM_IF_V_SHIFT			4
+#define DA9150_PM_IF_V_MASK			BIT(4)
+#define DA9150_PM_IF_FMP_SHIFT			5
+#define DA9150_PM_IF_FMP_MASK			BIT(5)
+#define DA9150_PM_IF_HSM_SHIFT			6
+#define DA9150_PM_IF_HSM_MASK			BIT(6)
+
+/* DA9150_CONFIG_D_SHARED = 0x109 */
+#define DA9150_NIRQ_MODE_SHIFT			1
+#define DA9150_NIRQ_MODE_MASK			BIT(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			BIT(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			BIT(5)
+#define DA9150_DM_STAT_SHIFT			6
+#define DA9150_DM_STAT_MASK			BIT(6)
+
+/* DA9150_ADET_CMPSTAT = 0x152 */
+#define DA9150_DP_COMP_SHIFT			1
+#define DA9150_DP_COMP_MASK			BIT(1)
+#define DA9150_DM_COMP_SHIFT			2
+#define DA9150_DM_COMP_MASK			BIT(2)
+#define DA9150_ADP_SNS_COMP_SHIFT		3
+#define DA9150_ADP_SNS_COMP_MASK		BIT(3)
+#define DA9150_ADP_PRB_COMP_SHIFT		4
+#define DA9150_ADP_PRB_COMP_MASK		BIT(4)
+#define DA9150_ID_COMP_SHIFT			5
+#define DA9150_ID_COMP_MASK			BIT(5)
+
+/* DA9150_ADET_CTRL_A = 0x153 */
+#define DA9150_AID_DAT_SHIFT			0
+#define DA9150_AID_DAT_MASK			BIT(0)
+#define DA9150_AID_ID_SHIFT			1
+#define DA9150_AID_ID_MASK			BIT(1)
+#define DA9150_AID_TRIG_SHIFT			2
+#define DA9150_AID_TRIG_MASK			BIT(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			BIT(0)
+
+#define DA9150_TADP_PRB_SHIFT			2
+#define DA9150_TADP_PRB_MASK			BIT(2)
+#define DA9150_DAT_RPD_EXT_SHIFT		5
+#define DA9150_DAT_RPD_EXT_MASK			BIT(5)
+#define DA9150_CONF_RPD_SHIFT			6
+#define DA9150_CONF_RPD_MASK			BIT(6)
+#define DA9150_CONF_SRP_SHIFT			7
+#define DA9150_CONF_SRP_MASK			BIT(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			BIT(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			BIT(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			BIT(5)
+#define DA9150_CONF_GPIOB_SHIFT			6
+#define DA9150_CONF_GPIOB_MASK			BIT(6)
+#define DA9150_AID_VB_SHIFT			7
+#define DA9150_AID_VB_MASK			BIT(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			BIT(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			BIT(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			BIT(6)
+#define DA9150_DAT_CLAMP_EXT_SHIFT		7
+#define DA9150_DAT_CLAMP_EXT_MASK		BIT(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			BIT(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			BIT(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			BIT(4)
+#define DA9150_VBUS_PWM_SHIFT			5
+#define DA9150_VBUS_PWM_MASK			BIT(5)
+#define DA9150_VBUS_ISO_SHIFT			6
+#define DA9150_VBUS_ISO_MASK			BIT(6)
+#define DA9150_VBUS_LDO_SHIFT			7
+#define DA9150_VBUS_LDO_MASK			BIT(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			BIT(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		BIT(6)
+#define DA9150_OTG_FAULT_DIS_SHIFT		7
+#define DA9150_OTG_FAULT_DIS_MASK		BIT(7)
+
+/* DA9150_PPR_CHGCTRL_A = 0x166 */
+#define DA9150_CHG_EN_SHIFT			0
+#define DA9150_CHG_EN_MASK			BIT(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		BIT(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			BIT(6)
+#define DA9150_TBAT_TDP_EN_SHIFT		7
+#define DA9150_TBAT_TDP_EN_MASK			BIT(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			BIT(5)
+#define DA9150_CHG_NBLO_SHIFT			6
+#define DA9150_CHG_NBLO_MASK			BIT(6)
+#define DA9150_EBS_EN_SHIFT			7
+#define DA9150_EBS_EN_MASK			BIT(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			BIT(6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			BIT(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			BIT(6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			BIT(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			BIT(6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			BIT(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			BIT(6)
+#define DA9150_REVERT_SHIFT			7
+#define DA9150_REVERT_MASK			BIT(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			BIT(2)
+
+/* DA9150_COREBTLD_CTRL_A = 0x303 */
+#define DA9150_CORE_RESET_SHIFT			0
+#define DA9150_CORE_RESET_MASK			BIT(0)
+#define DA9150_CORE_STOP_SHIFT			1
+#define DA9150_CORE_STOP_MASK			BIT(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		BIT(2)
+#define DA9150_WDT_AUTO_LOCK_SHIFT		3
+#define DA9150_WDT_AUTO_LOCK_MASK		BIT(3)
+#define DA9150_WDT_HLT_NO_CLK_SHIFT		4
+#define DA9150_WDT_HLT_NO_CLK_MASK		BIT(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			BIT(0)
+#define DA9150_CORE_EN_SHIFT			2
+#define DA9150_CORE_EN_MASK			BIT(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		BIT(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			BIT(7)
+
+/* DA9150_CORE2WIRE_CTRL_A = 0x311 */
+#define DA9150_FW_FWDL_EN_SHIFT			0
+#define DA9150_FW_FWDL_EN_MASK			BIT(0)
+#define DA9150_FG_QIF_EN_SHIFT			1
+#define DA9150_FG_QIF_EN_MASK			BIT(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			BIT(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			BIT(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			BIT(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		BIT(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			BIT(0)
+#define DA9150_TAUX_MOD_SHIFT			1
+#define DA9150_TAUX_MOD_MASK			BIT(1)
+#define DA9150_TAUX_UPDATE_SHIFT		2
+#define DA9150_TAUX_UPDATE_MASK			BIT(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			BIT(0)
+
+/* DA9150_TBAT_CTRL_A = 0x342 */
+#define DA9150_TBAT_EN_SHIFT			0
+#define DA9150_TBAT_EN_MASK			BIT(0)
+#define DA9150_TBAT_SW1_SHIFT			1
+#define DA9150_TBAT_SW1_MASK			BIT(1)
+#define DA9150_TBAT_SW2_SHIFT			2
+#define DA9150_TBAT_SW2_MASK			BIT(2)
+
+/* DA9150_TBAT_CTRL_B = 0x343 */
+#define DA9150_TBAT_SW_FRC_SHIFT		0
+#define DA9150_TBAT_SW_FRC_MASK			BIT(0)
+#define DA9150_TBAT_STAT_SW1_SHIFT		1
+#define DA9150_TBAT_STAT_SW1_MASK		BIT(1)
+#define DA9150_TBAT_STAT_SW2_SHIFT		2
+#define DA9150_TBAT_STAT_SW2_MASK		BIT(2)
+#define DA9150_TBAT_HIGH_CURR_SHIFT		3
+#define DA9150_TBAT_HIGH_CURR_MASK		BIT(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		BIT(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] 20+ messages in thread

* [PATCH v5 2/7] mfd: da9150: Add DT binding documentation for core
  2014-12-22 16:50 [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
  2014-12-22 16:51 ` [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
@ 2014-12-22 16:51 ` Adam Thomson
  2014-12-22 16:51 ` [PATCH v5 3/7] iio: Add support for DA9150 GPADC Adam Thomson
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 20+ messages in thread
From: Adam Thomson @ 2014-12-22 16:51 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  Cc: linux-kernel, support.opensource

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 Documentation/devicetree/bindings/mfd/da9150.txt | 43 ++++++++++++++++++++++++
 1 file changed, 43 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..d0588ea
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/da9150.txt
@@ -0,0 +1,43 @@
+Dialog Semiconductor DA9150 Combined Charger/Fuel-Gauge MFD bindings
+
+DA9150 consists of a group of sub-devices:
+
+Device			 Description
+------			 -----------
+da9150-gpadc		: General Purpose ADC
+da9150-charger		: Battery Charger
+
+======
+
+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).
+  (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for
+   further information relating to interrupt properties)
+
+Sub-devices:
+- da9150-gpadc: See Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
+- da9150-charger: See Documentation/devicetree/bindings/power/da9150-charger.txt
+
+
+Example:
+
+	charger_fg: da9150@58 {
+		compatible = "dlg,da9150";
+		reg = <0x58>;
+		interrupt-parent = <&gpio6>;
+		interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+		interrupt-controller;
+
+		gpadc: da9150-gpadc {
+			...
+		};
+
+		da9150-charger {
+			...
+		};
+	};
--
1.9.3

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

* [PATCH v5 3/7] iio: Add support for DA9150 GPADC
  2014-12-22 16:50 [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
  2014-12-22 16:51 ` [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
  2014-12-22 16:51 ` [PATCH v5 2/7] mfd: da9150: Add DT binding documentation for core Adam Thomson
@ 2014-12-22 16:51 ` Adam Thomson
  2015-01-01 20:51   ` Hartmut Knaack
  2015-01-04 17:22   ` Jonathan Cameron
  2014-12-22 16:51 ` [PATCH v5 4/7] iio: da9150: Add DT binding documentation for GPADC Adam Thomson
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 20+ messages in thread
From: Adam Thomson @ 2014-12-22 16:51 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  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 | 409 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 419 insertions(+)
 create mode 100644 drivers/iio/adc/da9150-gpadc.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 0f79e47..6e00b81 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -135,6 +135,15 @@ config AXP288_ADC
 	  device. Depending on platform configuration, this general purpose ADC can
 	  be used for sampling sensors such as thermal resistors.

+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 ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 701fdb7..d56ee9b 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
 obj-$(CONFIG_AD799X) += ad799x.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_AXP288_ADC) += axp288_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_MAX1027) += max1027.o
diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
new file mode 100644
index 0000000..3f7bc81
--- /dev/null
+++ b/drivers/iio/adc/da9150-gpadc.c
@@ -0,0 +1,409 @@
+/*
+ * 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/mutex.h>
+#include <linux/completion.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/machine.h>
+#include <linux/iio/driver.h>
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/registers.h>
+
+/* Channels */
+enum da9150_gpadc_hw_channel {
+	DA9150_GPADC_HW_CHAN_GPIOA_2V = 0,
+	DA9150_GPADC_HW_CHAN_GPIOA_2V_,
+	DA9150_GPADC_HW_CHAN_GPIOB_2V,
+	DA9150_GPADC_HW_CHAN_GPIOB_2V_,
+	DA9150_GPADC_HW_CHAN_GPIOC_2V,
+	DA9150_GPADC_HW_CHAN_GPIOC_2V_,
+	DA9150_GPADC_HW_CHAN_GPIOD_2V,
+	DA9150_GPADC_HW_CHAN_GPIOD_2V_,
+	DA9150_GPADC_HW_CHAN_IBUS_SENSE,
+	DA9150_GPADC_HW_CHAN_IBUS_SENSE_,
+	DA9150_GPADC_HW_CHAN_VBUS_DIV,
+	DA9150_GPADC_HW_CHAN_VBUS_DIV_,
+	DA9150_GPADC_HW_CHAN_ID,
+	DA9150_GPADC_HW_CHAN_ID_,
+	DA9150_GPADC_HW_CHAN_VSYS,
+	DA9150_GPADC_HW_CHAN_VSYS_,
+	DA9150_GPADC_HW_CHAN_GPIOA_6V,
+	DA9150_GPADC_HW_CHAN_GPIOA_6V_,
+	DA9150_GPADC_HW_CHAN_GPIOB_6V,
+	DA9150_GPADC_HW_CHAN_GPIOB_6V_,
+	DA9150_GPADC_HW_CHAN_GPIOC_6V,
+	DA9150_GPADC_HW_CHAN_GPIOC_6V_,
+	DA9150_GPADC_HW_CHAN_GPIOD_6V,
+	DA9150_GPADC_HW_CHAN_GPIOD_6V_,
+	DA9150_GPADC_HW_CHAN_VBAT,
+	DA9150_GPADC_HW_CHAN_VBAT_,
+	DA9150_GPADC_HW_CHAN_TBAT,
+	DA9150_GPADC_HW_CHAN_TBAT_,
+	DA9150_GPADC_HW_CHAN_TJUNC_CORE,
+	DA9150_GPADC_HW_CHAN_TJUNC_CORE_,
+	DA9150_GPADC_HW_CHAN_TJUNC_OVP,
+	DA9150_GPADC_HW_CHAN_TJUNC_OVP_,
+};
+
+enum da9150_gpadc_channel {
+	DA9150_GPADC_CHAN_GPIOA = 0,
+	DA9150_GPADC_CHAN_GPIOB,
+	DA9150_GPADC_CHAN_GPIOC,
+	DA9150_GPADC_CHAN_GPIOD,
+	DA9150_GPADC_CHAN_IBUS,
+	DA9150_GPADC_CHAN_VBUS,
+	DA9150_GPADC_CHAN_ID,
+	DA9150_GPADC_CHAN_VSYS,
+	DA9150_GPADC_CHAN_VBAT,
+	DA9150_GPADC_CHAN_TBAT,
+	DA9150_GPADC_CHAN_TJUNC_CORE,
+	DA9150_GPADC_CHAN_TJUNC_OVP,
+};
+
+/* Private data */
+struct da9150_gpadc {
+	struct da9150 *da9150;
+	struct device *dev;
+
+	struct mutex lock;
+	struct completion complete;
+};
+
+
+static irqreturn_t da9150_gpadc_irq(int irq, void *data)
+{
+
+	struct da9150_gpadc *gpadc = data;
+
+	complete(&gpadc->complete);
+
+	return IRQ_HANDLED;
+}
+
+static int da9150_gpadc_read_adc(struct da9150_gpadc *gpadc, int hw_chan)
+{
+	u8 result_regs[2];
+	int result;
+
+	mutex_lock(&gpadc->lock);
+
+	/* Set channel & enable measurement */
+	da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN,
+			 (DA9150_GPADC_EN_MASK |
+			  hw_chan << DA9150_GPADC_MUX_SHIFT));
+
+	/* 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);
+
+	mutex_unlock(&gpadc->lock);
+
+	/* Check to make sure device really has completed reading */
+	if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
+		dev_err(gpadc->dev, "Timeout on channel %d of GPADC\n",
+			hw_chan);
+		return -ETIMEDOUT;
+	}
+
+	/* LSBs - 2 bits */
+	result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
+		 DA9150_GPADC_RES_L_SHIFT;
+	/* MSBs - 8 bits */
+	result |= result_regs[0] << DA9150_GPADC_RES_L_BITS;
+
+	return result;
+}
+
+static inline int da9150_gpadc_gpio_6v_voltage_now(int raw_val)
+{
+	/* Convert to mV */
+	return (6 * ((raw_val * 1000) + 500)) / 1024;
+}
+
+static inline int da9150_gpadc_ibus_current_avg(int raw_val)
+{
+	/* Convert to mA */
+	return (4 * ((raw_val * 1000) + 500)) / 2048;
+}
+
+static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
+{
+	/* Convert to mV */
+	return (21 * ((raw_val * 1000) + 500)) / 1024;
+}
+
+static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
+{
+	/* Convert to mV */
+	return (3 * ((raw_val * 1000) + 500)) / 512;
+}
+
+static int da9150_gpadc_read_processed(struct da9150_gpadc *gpadc, int channel,
+				       int hw_chan, int *val)
+{
+	int raw_val;
+
+	raw_val = da9150_gpadc_read_adc(gpadc, hw_chan);
+	if (raw_val < 0)
+		return raw_val;
+
+	switch (channel) {
+	case DA9150_GPADC_CHAN_GPIOA:
+	case DA9150_GPADC_CHAN_GPIOB:
+	case DA9150_GPADC_CHAN_GPIOC:
+	case DA9150_GPADC_CHAN_GPIOD:
+		*val = da9150_gpadc_gpio_6v_voltage_now(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_IBUS:
+		*val = da9150_gpadc_ibus_current_avg(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_VBUS:
+		*val = da9150_gpadc_vbus_21v_voltage_now(raw_val);
+		break;
+	case DA9150_GPADC_CHAN_VSYS:
+		*val = da9150_gpadc_vsys_6v_voltage_now(raw_val);
+		break;
+	default:
+		/* No processing for other channels so return raw value */
+		*val = raw_val;
+		break;
+	}
+
+	return IIO_VAL_INT;
+}
+
+static int da9150_gpadc_read_scale(int channel, int *val, int *val2)
+{
+	switch (channel) {
+	case DA9150_GPADC_CHAN_VBAT:
+		*val = 2932;
+		*val2 = 1000;
+		return IIO_VAL_FRACTIONAL;
+	case DA9150_GPADC_CHAN_TJUNC_CORE:
+	case DA9150_GPADC_CHAN_TJUNC_OVP:
+		*val = 1000000;
+		*val2 = 4420;
+		return IIO_VAL_FRACTIONAL;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int da9150_gpadc_read_offset(int channel, int *val)
+{
+	switch (channel) {
+	case DA9150_GPADC_CHAN_VBAT:
+		*val = 1500000 / 2932;
+		return IIO_VAL_INT;
+	case DA9150_GPADC_CHAN_TJUNC_CORE:
+	case DA9150_GPADC_CHAN_TJUNC_OVP:
+		*val = -144;
+		return IIO_VAL_INT;
+	default:
+		return -EINVAL;
+	}
+}
+
+static 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);
+
+	if ((chan->channel < DA9150_GPADC_CHAN_GPIOA) ||
+	    (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP))
+		return -EINVAL;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+	case IIO_CHAN_INFO_PROCESSED:
+		return da9150_gpadc_read_processed(gpadc, chan->channel,
+						   chan->address, val);
+	case IIO_CHAN_INFO_SCALE:
+		return da9150_gpadc_read_scale(chan->channel, val, val2);
+	case IIO_CHAN_INFO_OFFSET:
+		return da9150_gpadc_read_offset(chan->channel, val);
+	default:
+		return -EINVAL;
+	}
+}
+
+static const struct iio_info da9150_gpadc_info = {
+	.read_raw = &da9150_gpadc_read_raw,
+	.driver_module = THIS_MODULE,
+};
+
+#define DA9150_GPADC_CHANNEL(_id, _hw_id, _type, chan_info,	\
+			     _ext_name) {			\
+	.type = _type,						\
+	.indexed = 1,						\
+	.channel = DA9150_GPADC_CHAN_##_id,			\
+	.address = DA9150_GPADC_HW_CHAN_##_hw_id,		\
+	.info_mask_separate = chan_info,			\
+	.extend_name = _ext_name,				\
+	.datasheet_name = #_id,					\
+}
+
+#define DA9150_GPADC_CHANNEL_RAW(_id, _hw_id, _type, _ext_name)	\
+	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,		\
+			     BIT(IIO_CHAN_INFO_RAW), _ext_name)
+
+#define DA9150_GPADC_CHANNEL_SCALED(_id, _hw_id, _type, _ext_name)	\
+	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
+			     BIT(IIO_CHAN_INFO_RAW) |			\
+			     BIT(IIO_CHAN_INFO_SCALE) |			\
+			     BIT(IIO_CHAN_INFO_OFFSET),			\
+			     _ext_name)
+
+#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type, _ext_name)	\
+	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
+			     BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
+
+/* Supported channels */
+static const struct iio_chan_spec da9150_gpadc_channels[] = {
+	DA9150_GPADC_CHANNEL_PROCESSED(GPIOA, GPIOA_6V, IIO_VOLTAGE, "GPIOA"),
+	DA9150_GPADC_CHANNEL_PROCESSED(GPIOB, GPIOB_6V, IIO_VOLTAGE, "GPIOB"),
+	DA9150_GPADC_CHANNEL_PROCESSED(GPIOC, GPIOC_6V, IIO_VOLTAGE, "GPIOC"),
+	DA9150_GPADC_CHANNEL_PROCESSED(GPIOD, GPIOD_6V, IIO_VOLTAGE, "GPIOD"),
+	DA9150_GPADC_CHANNEL_PROCESSED(IBUS, IBUS_SENSE, IIO_CURRENT, "IBUS"),
+	DA9150_GPADC_CHANNEL_PROCESSED(VBUS, VBUS_DIV_, IIO_VOLTAGE, "VBUS"),
+	DA9150_GPADC_CHANNEL_RAW(ID, ID, IIO_VOLTAGE, "ID"),
+	DA9150_GPADC_CHANNEL_PROCESSED(VSYS, VSYS, IIO_VOLTAGE, "VSYS"),
+	DA9150_GPADC_CHANNEL_SCALED(VBAT, VBAT, IIO_VOLTAGE, "VBAT"),
+	DA9150_GPADC_CHANNEL_RAW(TBAT, TBAT, IIO_VOLTAGE, "TBAT"),
+	DA9150_GPADC_CHANNEL_SCALED(TJUNC_CORE, TJUNC_CORE, IIO_TEMP,
+				    "TJUNC_CORE"),
+	DA9150_GPADC_CHANNEL_SCALED(TJUNC_OVP, 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",
+	},
+	{
+		.consumer_dev_name = "da9150-charger",
+		.consumer_channel = "CHAN_VBUS",
+		.adc_channel_label = "VBUS",
+	},
+	{
+		.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",
+	},
+	{},
+};
+
+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 irq, ret;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*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;
+	mutex_init(&gpadc->lock);
+	init_completion(&gpadc->complete);
+
+	irq = platform_get_irq_byname(pdev, "GPADC");
+	if (irq < 0) {
+		dev_err(dev, "Failed to get IRQ: %d\n", irq);
+		return irq;
+	}
+
+	ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
+					IRQF_ONESHOT, "GPADC", gpadc);
+	if (ret) {
+		dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
+		return ret;
+	}
+
+	ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
+	if (ret) {
+		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
+		return ret;
+	}
+
+	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_map_unreg;
+	}
+
+	return 0;
+
+iio_map_unreg:
+	iio_map_array_unregister(indio_dev);
+
+	return ret;
+}
+
+static int da9150_gpadc_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	iio_device_unregister(indio_dev);
+	iio_map_array_unregister(indio_dev);
+
+	return 0;
+}
+
+static struct platform_driver da9150_gpadc_driver = {
+	.driver = {
+		.name = "da9150-gpadc",
+	},
+	.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");
--
1.9.3

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

* [PATCH v5 4/7] iio: da9150: Add DT binding documentation for GPADC
  2014-12-22 16:50 [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (2 preceding siblings ...)
  2014-12-22 16:51 ` [PATCH v5 3/7] iio: Add support for DA9150 GPADC Adam Thomson
@ 2014-12-22 16:51 ` Adam Thomson
  2014-12-22 16:51 ` [PATCH v5 5/7] power: Add support for DA9150 Charger Adam Thomson
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 20+ messages in thread
From: Adam Thomson @ 2014-12-22 16:51 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  Cc: linux-kernel, support.opensource

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

diff --git a/Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt b/Documentation/devicetree/bindings/iio/adc/da9150-gpadc.txt
new file mode 100644
index 0000000..c07228d
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/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] 20+ messages in thread

* [PATCH v5 5/7] power: Add support for DA9150 Charger
  2014-12-22 16:50 [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (3 preceding siblings ...)
  2014-12-22 16:51 ` [PATCH v5 4/7] iio: da9150: Add DT binding documentation for GPADC Adam Thomson
@ 2014-12-22 16:51 ` Adam Thomson
  2015-01-04 17:26   ` Jonathan Cameron
  2014-12-22 16:51 ` [PATCH v5 6/7] power: da9150: Add DT binding documentation for charger Adam Thomson
  2014-12-22 16:51 ` [PATCH v5 7/7] MAINTAINERS: Include DA9150 files in Dialog Semiconductor support list Adam Thomson
  6 siblings, 1 reply; 20+ messages in thread
From: Adam Thomson @ 2014-12-22 16:51 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  Cc: linux-kernel, support.opensource

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

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 drivers/power/Kconfig          |  12 +
 drivers/power/Makefile         |   1 +
 drivers/power/da9150-charger.c | 666 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 679 insertions(+)
 create mode 100644 drivers/power/da9150-charger.c

diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 0108c2a..eb79a7a 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -192,6 +192,18 @@ 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 BATTERY_MAX17040
 	tristate "Maxim MAX17040 Fuel Gauge"
 	depends on I2C
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index dfa8942..0c1896d 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -31,6 +31,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..9b1826d
--- /dev/null
+++ b/drivers/power/da9150-charger.c
@@ -0,0 +1,666 @@
+/*
+ * 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/power_supply.h>
+#include <linux/notifier.h>
+#include <linux/usb/phy.h>
+#include <linux/iio/consumer.h>
+#include <linux/mfd/da9150/core.h>
+#include <linux/mfd/da9150/registers.h>
+
+/* Private data */
+struct da9150_charger {
+	struct da9150 *da9150;
+	struct device *dev;
+
+	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;
+};
+
+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;
+}
+
+/* Charger Properties */
+static int da9150_charger_vbus_voltage_now(struct da9150_charger *charger,
+					   union power_supply_propval *val)
+{
+	int v_val, ret;
+
+	/* Read processed value - mV units */
+	ret = iio_read_channel_processed(charger->vbus_chan, &v_val);
+	if (ret < 0)
+		return ret;
+
+	/* Convert voltage to expected uV units */
+	val->intval = v_val * 1000;
+
+	return 0;
+}
+
+static int da9150_charger_ibus_current_avg(struct da9150_charger *charger,
+					   union power_supply_propval *val)
+{
+	int i_val, ret;
+
+	/* Read processed value - mA units */
+	ret = iio_read_channel_processed(charger->ibus_chan, &i_val);
+	if (ret < 0)
+		return ret;
+
+	/* Convert current to expected uA units */
+	val->intval = i_val * 1000;
+
+	return 0;
+}
+
+static int da9150_charger_tjunc_temp(struct da9150_charger *charger,
+				     union power_supply_propval *val)
+{
+	int t_val, ret;
+
+	/* Read processed value - 0.001 degrees C units */
+	ret = iio_read_channel_processed(charger->tjunc_chan, &t_val);
+	if (ret < 0)
+		return ret;
+
+	/* Convert temp to expect 0.1 degrees C units */
+	val->intval = t_val / 100;
+
+	return 0;
+}
+
+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;
+
+	/* 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)
+{
+	int v_val, ret;
+
+	/* Read processed value - mV units */
+	ret = iio_read_channel_processed(charger->vbat_chan, &v_val);
+	if (ret < 0)
+		return ret;
+
+	val->intval = v_val * 1000;
+
+	return 0;
+}
+
+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);
+
+	/* 25mA increments */
+	val->intval = reg * 25000;
+
+	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;
+}
+
+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->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->usb);
+	power_supply_changed(&charger->battery);
+
+	return IRQ_HANDLED;
+}
+
+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:
+		charger->supply_online = &charger->usb;
+		break;
+	default:
+		dev_warn(charger->dev, "Unknown VBUS state - reg = 0x%x\n",
+			 reg);
+		charger->supply_online = NULL;
+		break;
+	}
+
+	power_supply_changed(&charger->usb);
+	power_supply_changed(&charger->battery);
+
+	return IRQ_HANDLED;
+}
+
+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) {
+	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->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;
+}
+
+static int da9150_charger_register_irq(struct platform_device *pdev,
+				       irq_handler_t handler,
+				       const char *irq_name)
+{
+	struct device *dev = &pdev->dev;
+	struct da9150_charger *charger = platform_get_drvdata(pdev);
+	int irq, ret;
+
+	irq = platform_get_irq_byname(pdev, irq_name);
+	if (irq < 0) {
+		dev_err(dev, "Failed to get IRQ CHG_STATUS: %d\n", irq);
+		return irq;
+	}
+
+	ret = devm_request_threaded_irq(dev, irq, NULL, handler, IRQF_ONESHOT,
+					irq_name, charger);
+	if (ret)
+		dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
+
+	return ret;
+}
+
+static int da9150_charger_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct da9150 *da9150 = dev_get_drvdata(dev->parent);
+	struct da9150_charger *charger;
+	struct power_supply *usb, *battery;
+	u8 reg;
+	int ret;
+
+	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;
+
+	/* Acquire ADC channels */
+	charger->ibus_chan = iio_channel_get(dev, "CHAN_IBUS");
+	if (IS_ERR(charger->ibus_chan)) {
+		ret = PTR_ERR(charger->ibus_chan);
+		goto ibus_chan_fail;
+	}
+
+	charger->vbus_chan = iio_channel_get(dev, "CHAN_VBUS");
+	if (IS_ERR(charger->vbus_chan)) {
+		ret = PTR_ERR(charger->vbus_chan);
+		goto vbus_chan_fail;
+	}
+
+	charger->tjunc_chan = iio_channel_get(dev, "CHAN_TJUNC");
+	if (IS_ERR(charger->tjunc_chan)) {
+		ret = PTR_ERR(charger->tjunc_chan);
+		goto tjunc_chan_fail;
+	}
+
+	charger->vbat_chan = iio_channel_get(dev, "CHAN_VBAT");
+	if (IS_ERR(charger->vbat_chan)) {
+		ret = PTR_ERR(charger->vbat_chan);
+		goto vbat_chan_fail;
+	}
+
+	/* Register power supplies */
+	usb = &charger->usb;
+	battery = &charger->battery;
+
+	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;
+
+	/* Get initial online supply */
+	reg = da9150_reg_read(da9150, DA9150_STATUS_H);
+
+	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:
+		charger->supply_online = &charger->usb;
+		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 (!IS_ERR_OR_NULL(charger->usb_phy)) {
+		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_charger_register_irq(pdev, da9150_charger_chg_irq,
+					  "CHG_STATUS");
+	if (ret < 0)
+		goto irq_fail;
+
+	ret = da9150_charger_register_irq(pdev, da9150_charger_tjunc_irq,
+					  "CHG_TJUNC");
+	if (ret < 0)
+		goto irq_fail;
+
+	ret = da9150_charger_register_irq(pdev, da9150_charger_vfault_irq,
+					  "CHG_VFAULT");
+	if (ret < 0)
+		goto irq_fail;
+
+	ret = da9150_charger_register_irq(pdev, da9150_charger_vbus_irq,
+					  "CHG_VBUS");
+	if (ret < 0)
+		goto irq_fail;
+
+	return 0;
+
+irq_fail:
+	if (!IS_ERR_OR_NULL(charger->usb_phy))
+		usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
+battery_fail:
+	power_supply_unregister(usb);
+
+usb_fail:
+	iio_channel_release(charger->vbat_chan);
+
+vbat_chan_fail:
+	iio_channel_release(charger->tjunc_chan);
+
+tjunc_chan_fail:
+	iio_channel_release(charger->vbus_chan);
+
+vbus_chan_fail:
+	iio_channel_release(charger->ibus_chan);
+
+ibus_chan_fail:
+	return ret;
+}
+
+static int da9150_charger_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct da9150_charger *charger = platform_get_drvdata(pdev);
+	int irq;
+
+	/* Make sure IRQs are released before unregistering power supplies */
+	irq = platform_get_irq_byname(pdev, "CHG_VBUS");
+	devm_free_irq(dev, irq, charger);
+
+	irq = platform_get_irq_byname(pdev, "CHG_VFAULT");
+	devm_free_irq(dev, irq, charger);
+
+	irq = platform_get_irq_byname(pdev, "CHG_TJUNC");
+	devm_free_irq(dev, irq, charger);
+
+	irq = platform_get_irq_byname(pdev, "CHG_STATUS");
+	devm_free_irq(dev, irq, charger);
+
+	if (!IS_ERR_OR_NULL(charger->usb_phy))
+		usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
+
+	power_supply_unregister(&charger->battery);
+	power_supply_unregister(&charger->usb);
+
+	/* Release ADC channels */
+	iio_channel_release(charger->ibus_chan);
+	iio_channel_release(charger->vbus_chan);
+	iio_channel_release(charger->tjunc_chan);
+	iio_channel_release(charger->vbat_chan);
+
+	return 0;
+}
+
+static struct platform_driver da9150_charger_driver = {
+	.driver = {
+		.name = "da9150-charger",
+	},
+	.probe = da9150_charger_probe,
+	.remove = da9150_charger_remove,
+};
+
+module_platform_driver(da9150_charger_driver);
+
+MODULE_DESCRIPTION("Charger Driver for DA9150");
+MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
+MODULE_LICENSE("GPL");
--
1.9.3

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

* [PATCH v5 6/7] power: da9150: Add DT binding documentation for charger
  2014-12-22 16:50 [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (4 preceding siblings ...)
  2014-12-22 16:51 ` [PATCH v5 5/7] power: Add support for DA9150 Charger Adam Thomson
@ 2014-12-22 16:51 ` Adam Thomson
  2014-12-22 16:51 ` [PATCH v5 7/7] MAINTAINERS: Include DA9150 files in Dialog Semiconductor support list Adam Thomson
  6 siblings, 0 replies; 20+ messages in thread
From: Adam Thomson @ 2014-12-22 16:51 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  Cc: linux-kernel, support.opensource

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
---
 .../devicetree/bindings/power/da9150-charger.txt   | 26 ++++++++++++++++++++++
 1 file changed, 26 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..f390666
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/da9150-charger.txt
@@ -0,0 +1,26 @@
+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)
+
+
+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";
+	};
--
1.9.3

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

* [PATCH v5 7/7] MAINTAINERS: Include DA9150 files in Dialog Semiconductor support list.
  2014-12-22 16:50 [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
                   ` (5 preceding siblings ...)
  2014-12-22 16:51 ` [PATCH v5 6/7] power: da9150: Add DT binding documentation for charger Adam Thomson
@ 2014-12-22 16:51 ` Adam Thomson
  6 siblings, 0 replies; 20+ messages in thread
From: Adam Thomson @ 2014-12-22 16:51 UTC (permalink / raw)
  To: Lee Jones, Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  Cc: linux-kernel, support.opensource

Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
 MAINTAINERS | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ddb9ac8..bd83dfc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3084,12 +3084,15 @@ S:	Supported
 F:	Documentation/hwmon/da90??
 F:	drivers/gpio/gpio-da90??.c
 F:	drivers/hwmon/da90??-hwmon.c
+F:	drivers/iio/adc/da91??-*.c
 F:	drivers/input/misc/da90??_onkey.c
 F:	drivers/input/touchscreen/da9052_tsi.c
 F:	drivers/leds/leds-da90??.c
 F:	drivers/mfd/da903x.c
 F:	drivers/mfd/da90??-*.c
+F:	drivers/mfd/da91??-*.c
 F:	drivers/power/da9052-battery.c
+F:	drivers/power/da91??-*.c
 F:	drivers/regulator/da903x.c
 F:	drivers/regulator/da9???-regulator.[ch]
 F:	drivers/rtc/rtc-da90??.c
@@ -3099,6 +3102,7 @@ F:	include/linux/mfd/da903x.h
 F:	include/linux/mfd/da9052/
 F:	include/linux/mfd/da9055/
 F:	include/linux/mfd/da9063/
+F:	include/linux/mfd/da9150/
 F:	include/sound/da[79]*.h
 F:	sound/soc/codecs/da[79]*.[ch]

--
1.9.3

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

* Re: [PATCH v5 3/7] iio: Add support for DA9150 GPADC
  2014-12-22 16:51 ` [PATCH v5 3/7] iio: Add support for DA9150 GPADC Adam Thomson
@ 2015-01-01 20:51   ` Hartmut Knaack
  2015-01-04 17:22   ` Jonathan Cameron
  1 sibling, 0 replies; 20+ messages in thread
From: Hartmut Knaack @ 2015-01-01 20:51 UTC (permalink / raw)
  To: Adam Thomson, Lee Jones, Samuel Ortiz, Jonathan Cameron,
	linux-iio, Sebastian Reichel, Dmitry Eremin-Solenikov,
	David Woodhouse, linux-pm, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely, devicetree, Andrew Morton,
	Joe Perches
  Cc: linux-kernel, support.opensource

Adam Thomson schrieb am 22.12.2014 um 17:51:
> This patch adds support for DA9150 Charger & Fuel-Gauge IC GPADC.
> 
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
Reviewed-by: Hartmut Knaack <knaack.h@gmx.de>
> ---
>  drivers/iio/adc/Kconfig        |   9 +
>  drivers/iio/adc/Makefile       |   1 +
>  drivers/iio/adc/da9150-gpadc.c | 409 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 419 insertions(+)
>  create mode 100644 drivers/iio/adc/da9150-gpadc.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 0f79e47..6e00b81 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -135,6 +135,15 @@ config AXP288_ADC
>  	  device. Depending on platform configuration, this general purpose ADC can
>  	  be used for sampling sensors such as thermal resistors.
> 
> +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 ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 701fdb7..d56ee9b 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
>  obj-$(CONFIG_AD799X) += ad799x.o
>  obj-$(CONFIG_AT91_ADC) += at91_adc.o
>  obj-$(CONFIG_AXP288_ADC) += axp288_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_MAX1027) += max1027.o
> diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
> new file mode 100644
> index 0000000..3f7bc81
> --- /dev/null
> +++ b/drivers/iio/adc/da9150-gpadc.c
> @@ -0,0 +1,409 @@
> +/*
> + * 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/mutex.h>
> +#include <linux/completion.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/machine.h>
> +#include <linux/iio/driver.h>
> +#include <linux/mfd/da9150/core.h>
> +#include <linux/mfd/da9150/registers.h>
> +
> +/* Channels */
> +enum da9150_gpadc_hw_channel {
> +	DA9150_GPADC_HW_CHAN_GPIOA_2V = 0,
> +	DA9150_GPADC_HW_CHAN_GPIOA_2V_,
> +	DA9150_GPADC_HW_CHAN_GPIOB_2V,
> +	DA9150_GPADC_HW_CHAN_GPIOB_2V_,
> +	DA9150_GPADC_HW_CHAN_GPIOC_2V,
> +	DA9150_GPADC_HW_CHAN_GPIOC_2V_,
> +	DA9150_GPADC_HW_CHAN_GPIOD_2V,
> +	DA9150_GPADC_HW_CHAN_GPIOD_2V_,
> +	DA9150_GPADC_HW_CHAN_IBUS_SENSE,
> +	DA9150_GPADC_HW_CHAN_IBUS_SENSE_,
> +	DA9150_GPADC_HW_CHAN_VBUS_DIV,
> +	DA9150_GPADC_HW_CHAN_VBUS_DIV_,
> +	DA9150_GPADC_HW_CHAN_ID,
> +	DA9150_GPADC_HW_CHAN_ID_,
> +	DA9150_GPADC_HW_CHAN_VSYS,
> +	DA9150_GPADC_HW_CHAN_VSYS_,
> +	DA9150_GPADC_HW_CHAN_GPIOA_6V,
> +	DA9150_GPADC_HW_CHAN_GPIOA_6V_,
> +	DA9150_GPADC_HW_CHAN_GPIOB_6V,
> +	DA9150_GPADC_HW_CHAN_GPIOB_6V_,
> +	DA9150_GPADC_HW_CHAN_GPIOC_6V,
> +	DA9150_GPADC_HW_CHAN_GPIOC_6V_,
> +	DA9150_GPADC_HW_CHAN_GPIOD_6V,
> +	DA9150_GPADC_HW_CHAN_GPIOD_6V_,
> +	DA9150_GPADC_HW_CHAN_VBAT,
> +	DA9150_GPADC_HW_CHAN_VBAT_,
> +	DA9150_GPADC_HW_CHAN_TBAT,
> +	DA9150_GPADC_HW_CHAN_TBAT_,
> +	DA9150_GPADC_HW_CHAN_TJUNC_CORE,
> +	DA9150_GPADC_HW_CHAN_TJUNC_CORE_,
> +	DA9150_GPADC_HW_CHAN_TJUNC_OVP,
> +	DA9150_GPADC_HW_CHAN_TJUNC_OVP_,
> +};
> +
> +enum da9150_gpadc_channel {
> +	DA9150_GPADC_CHAN_GPIOA = 0,
> +	DA9150_GPADC_CHAN_GPIOB,
> +	DA9150_GPADC_CHAN_GPIOC,
> +	DA9150_GPADC_CHAN_GPIOD,
> +	DA9150_GPADC_CHAN_IBUS,
> +	DA9150_GPADC_CHAN_VBUS,
> +	DA9150_GPADC_CHAN_ID,
> +	DA9150_GPADC_CHAN_VSYS,
> +	DA9150_GPADC_CHAN_VBAT,
> +	DA9150_GPADC_CHAN_TBAT,
> +	DA9150_GPADC_CHAN_TJUNC_CORE,
> +	DA9150_GPADC_CHAN_TJUNC_OVP,
> +};
> +
> +/* Private data */
> +struct da9150_gpadc {
> +	struct da9150 *da9150;
> +	struct device *dev;
> +
> +	struct mutex lock;
> +	struct completion complete;
> +};
> +
> +
> +static irqreturn_t da9150_gpadc_irq(int irq, void *data)
> +{
> +
> +	struct da9150_gpadc *gpadc = data;
> +
> +	complete(&gpadc->complete);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int da9150_gpadc_read_adc(struct da9150_gpadc *gpadc, int hw_chan)
> +{
> +	u8 result_regs[2];
> +	int result;
> +
> +	mutex_lock(&gpadc->lock);
> +
> +	/* Set channel & enable measurement */
> +	da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN,
> +			 (DA9150_GPADC_EN_MASK |
> +			  hw_chan << DA9150_GPADC_MUX_SHIFT));
> +
> +	/* 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);
> +
> +	mutex_unlock(&gpadc->lock);
> +
> +	/* Check to make sure device really has completed reading */
> +	if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
> +		dev_err(gpadc->dev, "Timeout on channel %d of GPADC\n",
> +			hw_chan);
> +		return -ETIMEDOUT;
> +	}
> +
> +	/* LSBs - 2 bits */
> +	result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
> +		 DA9150_GPADC_RES_L_SHIFT;
> +	/* MSBs - 8 bits */
> +	result |= result_regs[0] << DA9150_GPADC_RES_L_BITS;
> +
> +	return result;
> +}
> +
> +static inline int da9150_gpadc_gpio_6v_voltage_now(int raw_val)
> +{
> +	/* Convert to mV */
> +	return (6 * ((raw_val * 1000) + 500)) / 1024;
> +}
> +
> +static inline int da9150_gpadc_ibus_current_avg(int raw_val)
> +{
> +	/* Convert to mA */
> +	return (4 * ((raw_val * 1000) + 500)) / 2048;
> +}
> +
> +static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
> +{
> +	/* Convert to mV */
> +	return (21 * ((raw_val * 1000) + 500)) / 1024;
> +}
> +
> +static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
> +{
> +	/* Convert to mV */
> +	return (3 * ((raw_val * 1000) + 500)) / 512;
> +}
> +
> +static int da9150_gpadc_read_processed(struct da9150_gpadc *gpadc, int channel,
> +				       int hw_chan, int *val)
> +{
> +	int raw_val;
> +
> +	raw_val = da9150_gpadc_read_adc(gpadc, hw_chan);
> +	if (raw_val < 0)
> +		return raw_val;
> +
> +	switch (channel) {
> +	case DA9150_GPADC_CHAN_GPIOA:
> +	case DA9150_GPADC_CHAN_GPIOB:
> +	case DA9150_GPADC_CHAN_GPIOC:
> +	case DA9150_GPADC_CHAN_GPIOD:
> +		*val = da9150_gpadc_gpio_6v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_IBUS:
> +		*val = da9150_gpadc_ibus_current_avg(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_VBUS:
> +		*val = da9150_gpadc_vbus_21v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_VSYS:
> +		*val = da9150_gpadc_vsys_6v_voltage_now(raw_val);
> +		break;
> +	default:
> +		/* No processing for other channels so return raw value */
> +		*val = raw_val;
> +		break;
> +	}
> +
> +	return IIO_VAL_INT;
> +}
> +
> +static int da9150_gpadc_read_scale(int channel, int *val, int *val2)
> +{
> +	switch (channel) {
> +	case DA9150_GPADC_CHAN_VBAT:
> +		*val = 2932;
> +		*val2 = 1000;
> +		return IIO_VAL_FRACTIONAL;
> +	case DA9150_GPADC_CHAN_TJUNC_CORE:
> +	case DA9150_GPADC_CHAN_TJUNC_OVP:
> +		*val = 1000000;
> +		*val2 = 4420;
> +		return IIO_VAL_FRACTIONAL;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static int da9150_gpadc_read_offset(int channel, int *val)
> +{
> +	switch (channel) {
> +	case DA9150_GPADC_CHAN_VBAT:
> +		*val = 1500000 / 2932;
> +		return IIO_VAL_INT;
> +	case DA9150_GPADC_CHAN_TJUNC_CORE:
> +	case DA9150_GPADC_CHAN_TJUNC_OVP:
> +		*val = -144;
> +		return IIO_VAL_INT;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static 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);
> +
> +	if ((chan->channel < DA9150_GPADC_CHAN_GPIOA) ||
> +	    (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP))
> +		return -EINVAL;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +	case IIO_CHAN_INFO_PROCESSED:
> +		return da9150_gpadc_read_processed(gpadc, chan->channel,
> +						   chan->address, val);
> +	case IIO_CHAN_INFO_SCALE:
> +		return da9150_gpadc_read_scale(chan->channel, val, val2);
> +	case IIO_CHAN_INFO_OFFSET:
> +		return da9150_gpadc_read_offset(chan->channel, val);
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static const struct iio_info da9150_gpadc_info = {
> +	.read_raw = &da9150_gpadc_read_raw,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +#define DA9150_GPADC_CHANNEL(_id, _hw_id, _type, chan_info,	\
> +			     _ext_name) {			\
> +	.type = _type,						\
> +	.indexed = 1,						\
> +	.channel = DA9150_GPADC_CHAN_##_id,			\
> +	.address = DA9150_GPADC_HW_CHAN_##_hw_id,		\
> +	.info_mask_separate = chan_info,			\
> +	.extend_name = _ext_name,				\
> +	.datasheet_name = #_id,					\
> +}
> +
> +#define DA9150_GPADC_CHANNEL_RAW(_id, _hw_id, _type, _ext_name)	\
> +	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,		\
> +			     BIT(IIO_CHAN_INFO_RAW), _ext_name)
> +
> +#define DA9150_GPADC_CHANNEL_SCALED(_id, _hw_id, _type, _ext_name)	\
> +	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
> +			     BIT(IIO_CHAN_INFO_RAW) |			\
> +			     BIT(IIO_CHAN_INFO_SCALE) |			\
> +			     BIT(IIO_CHAN_INFO_OFFSET),			\
> +			     _ext_name)
> +
> +#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type, _ext_name)	\
> +	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
> +			     BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
> +
> +/* Supported channels */
> +static const struct iio_chan_spec da9150_gpadc_channels[] = {
> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOA, GPIOA_6V, IIO_VOLTAGE, "GPIOA"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOB, GPIOB_6V, IIO_VOLTAGE, "GPIOB"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOC, GPIOC_6V, IIO_VOLTAGE, "GPIOC"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOD, GPIOD_6V, IIO_VOLTAGE, "GPIOD"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(IBUS, IBUS_SENSE, IIO_CURRENT, "IBUS"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(VBUS, VBUS_DIV_, IIO_VOLTAGE, "VBUS"),
> +	DA9150_GPADC_CHANNEL_RAW(ID, ID, IIO_VOLTAGE, "ID"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(VSYS, VSYS, IIO_VOLTAGE, "VSYS"),
> +	DA9150_GPADC_CHANNEL_SCALED(VBAT, VBAT, IIO_VOLTAGE, "VBAT"),
> +	DA9150_GPADC_CHANNEL_RAW(TBAT, TBAT, IIO_VOLTAGE, "TBAT"),
> +	DA9150_GPADC_CHANNEL_SCALED(TJUNC_CORE, TJUNC_CORE, IIO_TEMP,
> +				    "TJUNC_CORE"),
> +	DA9150_GPADC_CHANNEL_SCALED(TJUNC_OVP, 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",
> +	},
> +	{
> +		.consumer_dev_name = "da9150-charger",
> +		.consumer_channel = "CHAN_VBUS",
> +		.adc_channel_label = "VBUS",
> +	},
> +	{
> +		.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",
> +	},
> +	{},
> +};
> +
> +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 irq, ret;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*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;
> +	mutex_init(&gpadc->lock);
> +	init_completion(&gpadc->complete);
> +
> +	irq = platform_get_irq_byname(pdev, "GPADC");
> +	if (irq < 0) {
> +		dev_err(dev, "Failed to get IRQ: %d\n", irq);
> +		return irq;
> +	}
> +
> +	ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
> +					IRQF_ONESHOT, "GPADC", gpadc);
> +	if (ret) {
> +		dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
> +		return ret;
> +	}
> +
> +	ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
> +	if (ret) {
> +		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
> +		return ret;
> +	}
> +
> +	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_map_unreg;
> +	}
> +
> +	return 0;
> +
> +iio_map_unreg:
> +	iio_map_array_unregister(indio_dev);
> +
> +	return ret;
> +}
> +
> +static int da9150_gpadc_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +	iio_device_unregister(indio_dev);
> +	iio_map_array_unregister(indio_dev);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver da9150_gpadc_driver = {
> +	.driver = {
> +		.name = "da9150-gpadc",
> +	},
> +	.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");
> --
> 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] 20+ messages in thread

* Re: [PATCH v5 3/7] iio: Add support for DA9150 GPADC
  2014-12-22 16:51 ` [PATCH v5 3/7] iio: Add support for DA9150 GPADC Adam Thomson
  2015-01-01 20:51   ` Hartmut Knaack
@ 2015-01-04 17:22   ` Jonathan Cameron
  2015-01-07 16:03     ` Opensource [Adam Thomson]
  1 sibling, 1 reply; 20+ messages in thread
From: Jonathan Cameron @ 2015-01-04 17:22 UTC (permalink / raw)
  To: Adam Thomson, Lee Jones, Samuel Ortiz, Hartmut Knaack, linux-iio,
	Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Grant Likely, devicetree, Andrew Morton, Joe Perches
  Cc: linux-kernel, support.opensource

On 22/12/14 16:51, Adam Thomson wrote:
> This patch adds support for DA9150 Charger & Fuel-Gauge IC GPADC.
> 
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
One last query from me.

Using the extended channel names in IIO is only really appropriate when
they don't correspond to simple pins on the side of the chip. For those
just drop the extname bit.  Some of the channels you have here, definitely
need them though.

Drop those first 4 or convince me otherwise and add
Acked-by: Jonathan Cameron <jic23@kernel.org>
> ---
>  drivers/iio/adc/Kconfig        |   9 +
>  drivers/iio/adc/Makefile       |   1 +
>  drivers/iio/adc/da9150-gpadc.c | 409 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 419 insertions(+)
>  create mode 100644 drivers/iio/adc/da9150-gpadc.c
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 0f79e47..6e00b81 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -135,6 +135,15 @@ config AXP288_ADC
>  	  device. Depending on platform configuration, this general purpose ADC can
>  	  be used for sampling sensors such as thermal resistors.
> 
> +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 ARCH_EXYNOS || ARCH_S3C24XX || ARCH_S3C64XX || (OF && COMPILE_TEST)
> diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
> index 701fdb7..d56ee9b 100644
> --- a/drivers/iio/adc/Makefile
> +++ b/drivers/iio/adc/Makefile
> @@ -15,6 +15,7 @@ obj-$(CONFIG_AD7887) += ad7887.o
>  obj-$(CONFIG_AD799X) += ad799x.o
>  obj-$(CONFIG_AT91_ADC) += at91_adc.o
>  obj-$(CONFIG_AXP288_ADC) += axp288_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_MAX1027) += max1027.o
> diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
> new file mode 100644
> index 0000000..3f7bc81
> --- /dev/null
> +++ b/drivers/iio/adc/da9150-gpadc.c
> @@ -0,0 +1,409 @@
> +/*
> + * 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/mutex.h>
> +#include <linux/completion.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/machine.h>
> +#include <linux/iio/driver.h>
> +#include <linux/mfd/da9150/core.h>
> +#include <linux/mfd/da9150/registers.h>
> +
> +/* Channels */
> +enum da9150_gpadc_hw_channel {
> +	DA9150_GPADC_HW_CHAN_GPIOA_2V = 0,
> +	DA9150_GPADC_HW_CHAN_GPIOA_2V_,
> +	DA9150_GPADC_HW_CHAN_GPIOB_2V,
> +	DA9150_GPADC_HW_CHAN_GPIOB_2V_,
> +	DA9150_GPADC_HW_CHAN_GPIOC_2V,
> +	DA9150_GPADC_HW_CHAN_GPIOC_2V_,
> +	DA9150_GPADC_HW_CHAN_GPIOD_2V,
> +	DA9150_GPADC_HW_CHAN_GPIOD_2V_,
> +	DA9150_GPADC_HW_CHAN_IBUS_SENSE,
> +	DA9150_GPADC_HW_CHAN_IBUS_SENSE_,
> +	DA9150_GPADC_HW_CHAN_VBUS_DIV,
> +	DA9150_GPADC_HW_CHAN_VBUS_DIV_,
> +	DA9150_GPADC_HW_CHAN_ID,
> +	DA9150_GPADC_HW_CHAN_ID_,
> +	DA9150_GPADC_HW_CHAN_VSYS,
> +	DA9150_GPADC_HW_CHAN_VSYS_,
> +	DA9150_GPADC_HW_CHAN_GPIOA_6V,
> +	DA9150_GPADC_HW_CHAN_GPIOA_6V_,
> +	DA9150_GPADC_HW_CHAN_GPIOB_6V,
> +	DA9150_GPADC_HW_CHAN_GPIOB_6V_,
> +	DA9150_GPADC_HW_CHAN_GPIOC_6V,
> +	DA9150_GPADC_HW_CHAN_GPIOC_6V_,
> +	DA9150_GPADC_HW_CHAN_GPIOD_6V,
> +	DA9150_GPADC_HW_CHAN_GPIOD_6V_,
> +	DA9150_GPADC_HW_CHAN_VBAT,
> +	DA9150_GPADC_HW_CHAN_VBAT_,
> +	DA9150_GPADC_HW_CHAN_TBAT,
> +	DA9150_GPADC_HW_CHAN_TBAT_,
> +	DA9150_GPADC_HW_CHAN_TJUNC_CORE,
> +	DA9150_GPADC_HW_CHAN_TJUNC_CORE_,
> +	DA9150_GPADC_HW_CHAN_TJUNC_OVP,
> +	DA9150_GPADC_HW_CHAN_TJUNC_OVP_,
> +};
> +
> +enum da9150_gpadc_channel {
> +	DA9150_GPADC_CHAN_GPIOA = 0,
> +	DA9150_GPADC_CHAN_GPIOB,
> +	DA9150_GPADC_CHAN_GPIOC,
> +	DA9150_GPADC_CHAN_GPIOD,
> +	DA9150_GPADC_CHAN_IBUS,
> +	DA9150_GPADC_CHAN_VBUS,
> +	DA9150_GPADC_CHAN_ID,
> +	DA9150_GPADC_CHAN_VSYS,
> +	DA9150_GPADC_CHAN_VBAT,
> +	DA9150_GPADC_CHAN_TBAT,
> +	DA9150_GPADC_CHAN_TJUNC_CORE,
> +	DA9150_GPADC_CHAN_TJUNC_OVP,
> +};
> +
> +/* Private data */
> +struct da9150_gpadc {
> +	struct da9150 *da9150;
> +	struct device *dev;
> +
> +	struct mutex lock;
> +	struct completion complete;
> +};
> +
> +
> +static irqreturn_t da9150_gpadc_irq(int irq, void *data)
> +{
> +
> +	struct da9150_gpadc *gpadc = data;
> +
> +	complete(&gpadc->complete);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int da9150_gpadc_read_adc(struct da9150_gpadc *gpadc, int hw_chan)
> +{
> +	u8 result_regs[2];
> +	int result;
> +
> +	mutex_lock(&gpadc->lock);
> +
> +	/* Set channel & enable measurement */
> +	da9150_reg_write(gpadc->da9150, DA9150_GPADC_MAN,
> +			 (DA9150_GPADC_EN_MASK |
> +			  hw_chan << DA9150_GPADC_MUX_SHIFT));
> +
> +	/* 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);
> +
> +	mutex_unlock(&gpadc->lock);
> +
> +	/* Check to make sure device really has completed reading */
> +	if (result_regs[1] & DA9150_GPADC_RUN_MASK) {
> +		dev_err(gpadc->dev, "Timeout on channel %d of GPADC\n",
> +			hw_chan);
> +		return -ETIMEDOUT;
> +	}
> +
> +	/* LSBs - 2 bits */
> +	result = (result_regs[1] & DA9150_GPADC_RES_L_MASK) >>
> +		 DA9150_GPADC_RES_L_SHIFT;
> +	/* MSBs - 8 bits */
> +	result |= result_regs[0] << DA9150_GPADC_RES_L_BITS;
> +
> +	return result;
> +}
> +
> +static inline int da9150_gpadc_gpio_6v_voltage_now(int raw_val)
> +{
> +	/* Convert to mV */
> +	return (6 * ((raw_val * 1000) + 500)) / 1024;
> +}
> +
> +static inline int da9150_gpadc_ibus_current_avg(int raw_val)
> +{
> +	/* Convert to mA */
> +	return (4 * ((raw_val * 1000) + 500)) / 2048;
> +}
> +
> +static inline int da9150_gpadc_vbus_21v_voltage_now(int raw_val)
> +{
> +	/* Convert to mV */
> +	return (21 * ((raw_val * 1000) + 500)) / 1024;
> +}
> +
> +static inline int da9150_gpadc_vsys_6v_voltage_now(int raw_val)
> +{
> +	/* Convert to mV */
> +	return (3 * ((raw_val * 1000) + 500)) / 512;
> +}
> +
> +static int da9150_gpadc_read_processed(struct da9150_gpadc *gpadc, int channel,
> +				       int hw_chan, int *val)
> +{
> +	int raw_val;
> +
> +	raw_val = da9150_gpadc_read_adc(gpadc, hw_chan);
> +	if (raw_val < 0)
> +		return raw_val;
> +
> +	switch (channel) {
> +	case DA9150_GPADC_CHAN_GPIOA:
> +	case DA9150_GPADC_CHAN_GPIOB:
> +	case DA9150_GPADC_CHAN_GPIOC:
> +	case DA9150_GPADC_CHAN_GPIOD:
> +		*val = da9150_gpadc_gpio_6v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_IBUS:
> +		*val = da9150_gpadc_ibus_current_avg(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_VBUS:
> +		*val = da9150_gpadc_vbus_21v_voltage_now(raw_val);
> +		break;
> +	case DA9150_GPADC_CHAN_VSYS:
> +		*val = da9150_gpadc_vsys_6v_voltage_now(raw_val);
> +		break;
> +	default:
> +		/* No processing for other channels so return raw value */
> +		*val = raw_val;
> +		break;
> +	}
> +
> +	return IIO_VAL_INT;
> +}
> +
> +static int da9150_gpadc_read_scale(int channel, int *val, int *val2)
> +{
> +	switch (channel) {
> +	case DA9150_GPADC_CHAN_VBAT:
> +		*val = 2932;
> +		*val2 = 1000;
> +		return IIO_VAL_FRACTIONAL;
> +	case DA9150_GPADC_CHAN_TJUNC_CORE:
> +	case DA9150_GPADC_CHAN_TJUNC_OVP:
> +		*val = 1000000;
> +		*val2 = 4420;
> +		return IIO_VAL_FRACTIONAL;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static int da9150_gpadc_read_offset(int channel, int *val)
> +{
> +	switch (channel) {
> +	case DA9150_GPADC_CHAN_VBAT:
> +		*val = 1500000 / 2932;
> +		return IIO_VAL_INT;
> +	case DA9150_GPADC_CHAN_TJUNC_CORE:
> +	case DA9150_GPADC_CHAN_TJUNC_OVP:
> +		*val = -144;
> +		return IIO_VAL_INT;
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static 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);
> +
> +	if ((chan->channel < DA9150_GPADC_CHAN_GPIOA) ||
> +	    (chan->channel > DA9150_GPADC_CHAN_TJUNC_OVP))
> +		return -EINVAL;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +	case IIO_CHAN_INFO_PROCESSED:
> +		return da9150_gpadc_read_processed(gpadc, chan->channel,
> +						   chan->address, val);
> +	case IIO_CHAN_INFO_SCALE:
> +		return da9150_gpadc_read_scale(chan->channel, val, val2);
> +	case IIO_CHAN_INFO_OFFSET:
> +		return da9150_gpadc_read_offset(chan->channel, val);
> +	default:
> +		return -EINVAL;
> +	}
> +}
> +
> +static const struct iio_info da9150_gpadc_info = {
> +	.read_raw = &da9150_gpadc_read_raw,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +#define DA9150_GPADC_CHANNEL(_id, _hw_id, _type, chan_info,	\
> +			     _ext_name) {			\
> +	.type = _type,						\
> +	.indexed = 1,						\
> +	.channel = DA9150_GPADC_CHAN_##_id,			\
> +	.address = DA9150_GPADC_HW_CHAN_##_hw_id,		\
> +	.info_mask_separate = chan_info,			\
> +	.extend_name = _ext_name,				\
> +	.datasheet_name = #_id,					\
> +}
> +
> +#define DA9150_GPADC_CHANNEL_RAW(_id, _hw_id, _type, _ext_name)	\
> +	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,		\
> +			     BIT(IIO_CHAN_INFO_RAW), _ext_name)
> +
> +#define DA9150_GPADC_CHANNEL_SCALED(_id, _hw_id, _type, _ext_name)	\
> +	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
> +			     BIT(IIO_CHAN_INFO_RAW) |			\
> +			     BIT(IIO_CHAN_INFO_SCALE) |			\
> +			     BIT(IIO_CHAN_INFO_OFFSET),			\
> +			     _ext_name)
> +
> +#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type, _ext_name)	\
> +	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
> +			     BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
> +
> +/* Supported channels */
> +static const struct iio_chan_spec da9150_gpadc_channels[] = {
> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOA, GPIOA_6V, IIO_VOLTAGE, "GPIOA"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOB, GPIOB_6V, IIO_VOLTAGE, "GPIOB"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOC, GPIOC_6V, IIO_VOLTAGE, "GPIOC"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOD, GPIOD_6V, IIO_VOLTAGE, "GPIOD"),
I'm not sure some of these really deserve extended names.  Those are usually
reserved for naming strange internal adc channels etc.  These first 4 are
presumably just for input pins?  Those should just be channels 0..3
On another note, unless you want really weird sysfs attribute names, the
extended names want to be lowercase.

> +	DA9150_GPADC_CHANNEL_PROCESSED(IBUS, IBUS_SENSE, IIO_CURRENT, "IBUS"),
> +	DA9150_GPADC_CHANNEL_PROCESSED(VBUS, VBUS_DIV_, IIO_VOLTAGE, "VBUS"),
> +	DA9150_GPADC_CHANNEL_RAW(ID, ID, IIO_VOLTAGE, "ID"),
You hae an identifier voltage? That's certainly unusual but if so - fair enough
and it defintely needs the extname!
> +	DA9150_GPADC_CHANNEL_PROCESSED(VSYS, VSYS, IIO_VOLTAGE, "VSYS"),
> +	DA9150_GPADC_CHANNEL_SCALED(VBAT, VBAT, IIO_VOLTAGE, "VBAT"),
> +	DA9150_GPADC_CHANNEL_RAW(TBAT, TBAT, IIO_VOLTAGE, "TBAT"),
> +	DA9150_GPADC_CHANNEL_SCALED(TJUNC_CORE, TJUNC_CORE, IIO_TEMP,
> +				    "TJUNC_CORE"),
tjunc_core is a good use of extname ;)
> +	DA9150_GPADC_CHANNEL_SCALED(TJUNC_OVP, 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",
> +	},
> +	{
> +		.consumer_dev_name = "da9150-charger",
> +		.consumer_channel = "CHAN_VBUS",
> +		.adc_channel_label = "VBUS",
> +	},
> +	{
> +		.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",
> +	},
> +	{},
> +};
> +
> +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 irq, ret;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*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;
> +	mutex_init(&gpadc->lock);
> +	init_completion(&gpadc->complete);
> +
> +	irq = platform_get_irq_byname(pdev, "GPADC");
> +	if (irq < 0) {
> +		dev_err(dev, "Failed to get IRQ: %d\n", irq);
> +		return irq;
> +	}
> +
> +	ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
> +					IRQF_ONESHOT, "GPADC", gpadc);
> +	if (ret) {
> +		dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
> +		return ret;
> +	}
> +
> +	ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
> +	if (ret) {
> +		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
> +		return ret;
> +	}
> +
> +	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_map_unreg;
> +	}
> +
> +	return 0;
> +
> +iio_map_unreg:
> +	iio_map_array_unregister(indio_dev);
> +
> +	return ret;
> +}
> +
> +static int da9150_gpadc_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +	iio_device_unregister(indio_dev);
> +	iio_map_array_unregister(indio_dev);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver da9150_gpadc_driver = {
> +	.driver = {
> +		.name = "da9150-gpadc",
> +	},
> +	.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");
> --
> 1.9.3
> 


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

* Re: [PATCH v5 5/7] power: Add support for DA9150 Charger
  2014-12-22 16:51 ` [PATCH v5 5/7] power: Add support for DA9150 Charger Adam Thomson
@ 2015-01-04 17:26   ` Jonathan Cameron
  2015-01-07 16:04     ` Opensource [Adam Thomson]
  0 siblings, 1 reply; 20+ messages in thread
From: Jonathan Cameron @ 2015-01-04 17:26 UTC (permalink / raw)
  To: Adam Thomson, Lee Jones, Samuel Ortiz, Hartmut Knaack, linux-iio,
	Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Grant Likely, devicetree, Andrew Morton, Joe Perches
  Cc: linux-kernel, support.opensource

On 22/12/14 16:51, Adam Thomson wrote:
> This patch adds support for DA9150 Charger & Fuel-Gauge IC Charger.
> 
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
The IIO bits look fine, but your use of devm_free * doesn't...

As a side note, looks like we could benefit from some array versions
of the IIO channel getting and release functions.  Would save a fair bit
of boiler plate.

Jonathan
> ---
>  drivers/power/Kconfig          |  12 +
>  drivers/power/Makefile         |   1 +
>  drivers/power/da9150-charger.c | 666 +++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 679 insertions(+)
>  create mode 100644 drivers/power/da9150-charger.c
> 
> diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
> index 0108c2a..eb79a7a 100644
> --- a/drivers/power/Kconfig
> +++ b/drivers/power/Kconfig
> @@ -192,6 +192,18 @@ 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 BATTERY_MAX17040
>  	tristate "Maxim MAX17040 Fuel Gauge"
>  	depends on I2C
> diff --git a/drivers/power/Makefile b/drivers/power/Makefile
> index dfa8942..0c1896d 100644
> --- a/drivers/power/Makefile
> +++ b/drivers/power/Makefile
> @@ -31,6 +31,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..9b1826d
> --- /dev/null
> +++ b/drivers/power/da9150-charger.c
> @@ -0,0 +1,666 @@
> +/*
> + * 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/power_supply.h>
> +#include <linux/notifier.h>
> +#include <linux/usb/phy.h>
> +#include <linux/iio/consumer.h>
> +#include <linux/mfd/da9150/core.h>
> +#include <linux/mfd/da9150/registers.h>
> +
> +/* Private data */
> +struct da9150_charger {
> +	struct da9150 *da9150;
> +	struct device *dev;
> +
> +	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;
> +};
> +
> +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;
> +}
> +
> +/* Charger Properties */
> +static int da9150_charger_vbus_voltage_now(struct da9150_charger *charger,
> +					   union power_supply_propval *val)
> +{
> +	int v_val, ret;
> +
> +	/* Read processed value - mV units */
> +	ret = iio_read_channel_processed(charger->vbus_chan, &v_val);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Convert voltage to expected uV units */
> +	val->intval = v_val * 1000;
> +
> +	return 0;
> +}
> +
> +static int da9150_charger_ibus_current_avg(struct da9150_charger *charger,
> +					   union power_supply_propval *val)
> +{
> +	int i_val, ret;
> +
> +	/* Read processed value - mA units */
> +	ret = iio_read_channel_processed(charger->ibus_chan, &i_val);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Convert current to expected uA units */
> +	val->intval = i_val * 1000;
> +
> +	return 0;
> +}
> +
> +static int da9150_charger_tjunc_temp(struct da9150_charger *charger,
> +				     union power_supply_propval *val)
> +{
> +	int t_val, ret;
> +
> +	/* Read processed value - 0.001 degrees C units */
> +	ret = iio_read_channel_processed(charger->tjunc_chan, &t_val);
> +	if (ret < 0)
> +		return ret;
> +
> +	/* Convert temp to expect 0.1 degrees C units */
> +	val->intval = t_val / 100;
> +
> +	return 0;
> +}
> +
> +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;
> +
> +	/* 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)
> +{
> +	int v_val, ret;
> +
> +	/* Read processed value - mV units */
> +	ret = iio_read_channel_processed(charger->vbat_chan, &v_val);
> +	if (ret < 0)
> +		return ret;
> +
> +	val->intval = v_val * 1000;
> +
> +	return 0;
> +}
> +
> +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);
> +
> +	/* 25mA increments */
> +	val->intval = reg * 25000;
> +
> +	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;
> +}
> +
> +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->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->usb);
> +	power_supply_changed(&charger->battery);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +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:
> +		charger->supply_online = &charger->usb;
> +		break;
> +	default:
> +		dev_warn(charger->dev, "Unknown VBUS state - reg = 0x%x\n",
> +			 reg);
> +		charger->supply_online = NULL;
> +		break;
> +	}
> +
> +	power_supply_changed(&charger->usb);
> +	power_supply_changed(&charger->battery);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +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) {
> +	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->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;
> +}
> +
> +static int da9150_charger_register_irq(struct platform_device *pdev,
> +				       irq_handler_t handler,
> +				       const char *irq_name)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct da9150_charger *charger = platform_get_drvdata(pdev);
> +	int irq, ret;
> +
> +	irq = platform_get_irq_byname(pdev, irq_name);
> +	if (irq < 0) {
> +		dev_err(dev, "Failed to get IRQ CHG_STATUS: %d\n", irq);
> +		return irq;
> +	}
> +
> +	ret = devm_request_threaded_irq(dev, irq, NULL, handler, IRQF_ONESHOT,
> +					irq_name, charger);
> +	if (ret)
> +		dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
> +
> +	return ret;
> +}
> +
> +static int da9150_charger_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct da9150 *da9150 = dev_get_drvdata(dev->parent);
> +	struct da9150_charger *charger;
> +	struct power_supply *usb, *battery;
> +	u8 reg;
> +	int ret;
> +
> +	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;
> +
> +	/* Acquire ADC channels */
> +	charger->ibus_chan = iio_channel_get(dev, "CHAN_IBUS");
> +	if (IS_ERR(charger->ibus_chan)) {
> +		ret = PTR_ERR(charger->ibus_chan);
> +		goto ibus_chan_fail;
> +	}
> +
> +	charger->vbus_chan = iio_channel_get(dev, "CHAN_VBUS");
> +	if (IS_ERR(charger->vbus_chan)) {
> +		ret = PTR_ERR(charger->vbus_chan);
> +		goto vbus_chan_fail;
> +	}
> +
> +	charger->tjunc_chan = iio_channel_get(dev, "CHAN_TJUNC");
> +	if (IS_ERR(charger->tjunc_chan)) {
> +		ret = PTR_ERR(charger->tjunc_chan);
> +		goto tjunc_chan_fail;
> +	}
> +
> +	charger->vbat_chan = iio_channel_get(dev, "CHAN_VBAT");
> +	if (IS_ERR(charger->vbat_chan)) {
> +		ret = PTR_ERR(charger->vbat_chan);
> +		goto vbat_chan_fail;
> +	}
> +
> +	/* Register power supplies */
> +	usb = &charger->usb;
> +	battery = &charger->battery;
> +
> +	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;
> +
> +	/* Get initial online supply */
> +	reg = da9150_reg_read(da9150, DA9150_STATUS_H);
> +
> +	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:
> +		charger->supply_online = &charger->usb;
> +		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 (!IS_ERR_OR_NULL(charger->usb_phy)) {
> +		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_charger_register_irq(pdev, da9150_charger_chg_irq,
> +					  "CHG_STATUS");
> +	if (ret < 0)
> +		goto irq_fail;
> +
> +	ret = da9150_charger_register_irq(pdev, da9150_charger_tjunc_irq,
> +					  "CHG_TJUNC");
> +	if (ret < 0)
> +		goto irq_fail;
> +
> +	ret = da9150_charger_register_irq(pdev, da9150_charger_vfault_irq,
> +					  "CHG_VFAULT");
> +	if (ret < 0)
> +		goto irq_fail;
> +
> +	ret = da9150_charger_register_irq(pdev, da9150_charger_vbus_irq,
> +					  "CHG_VBUS");
> +	if (ret < 0)
> +		goto irq_fail;
> +
> +	return 0;
> +
> +irq_fail:
> +	if (!IS_ERR_OR_NULL(charger->usb_phy))
> +		usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
> +battery_fail:
> +	power_supply_unregister(usb);
> +
> +usb_fail:
> +	iio_channel_release(charger->vbat_chan);
> +
> +vbat_chan_fail:
> +	iio_channel_release(charger->tjunc_chan);
> +
> +tjunc_chan_fail:
> +	iio_channel_release(charger->vbus_chan);
> +
> +vbus_chan_fail:
> +	iio_channel_release(charger->ibus_chan);
> +
> +ibus_chan_fail:
> +	return ret;
> +}
> +
> +static int da9150_charger_remove(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct da9150_charger *charger = platform_get_drvdata(pdev);
> +	int irq;
> +
> +	/* Make sure IRQs are released before unregistering power supplies */
> +	irq = platform_get_irq_byname(pdev, "CHG_VBUS");
> +	devm_free_irq(dev, irq, charger);
> +
> +	irq = platform_get_irq_byname(pdev, "CHG_VFAULT");
> +	devm_free_irq(dev, irq, charger);
> +
> +	irq = platform_get_irq_byname(pdev, "CHG_TJUNC");
> +	devm_free_irq(dev, irq, charger);
> +
> +	irq = platform_get_irq_byname(pdev, "CHG_STATUS");
> +	devm_free_irq(dev, irq, charger);
If you have used a devm allocation, you generally don't need to
free them explicitly. That will happen when the device is freed.

If you do need to free them here (to maintain ordering etc) then you
don't want to be using the devm interfaces in the first place.
> +
> +	if (!IS_ERR_OR_NULL(charger->usb_phy))
> +		usb_unregister_notifier(charger->usb_phy, &charger->otg_nb);
> +
> +	power_supply_unregister(&charger->battery);
> +	power_supply_unregister(&charger->usb);
> +
> +	/* Release ADC channels */
> +	iio_channel_release(charger->ibus_chan);
> +	iio_channel_release(charger->vbus_chan);
> +	iio_channel_release(charger->tjunc_chan);
> +	iio_channel_release(charger->vbat_chan);
> +
> +	return 0;
> +}
> +
> +static struct platform_driver da9150_charger_driver = {
> +	.driver = {
> +		.name = "da9150-charger",
> +	},
> +	.probe = da9150_charger_probe,
> +	.remove = da9150_charger_remove,
> +};
> +
> +module_platform_driver(da9150_charger_driver);
> +
> +MODULE_DESCRIPTION("Charger Driver for DA9150");
> +MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>");
> +MODULE_LICENSE("GPL");
> --
> 1.9.3
> 


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

* RE: [PATCH v5 3/7] iio: Add support for DA9150 GPADC
  2015-01-04 17:22   ` Jonathan Cameron
@ 2015-01-07 16:03     ` Opensource [Adam Thomson]
  2015-01-10 22:19       ` Jonathan Cameron
  0 siblings, 1 reply; 20+ messages in thread
From: Opensource [Adam Thomson] @ 2015-01-07 16:03 UTC (permalink / raw)
  To: Jonathan Cameron, Opensource [Adam Thomson], Lee Jones,
	Samuel Ortiz, Hartmut Knaack, linux-iio@vger.kernel.org,
	Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm@vger.kernel.org, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	devicetree@vger.kernel.org, Andrew Morton, Joe Perches
  Cc: linux-kernel@vger.kernel.org, Support Opensource

T24gSmFudWFyeSA0LCAyMDE1IDE3OjIyLCBKb25hdGhhbiBDYW1lcm9uIHdyb3RlOg0KDQo+IE9u
IDIyLzEyLzE0IDE2OjUxLCBBZGFtIFRob21zb24gd3JvdGU6DQo+ID4gVGhpcyBwYXRjaCBhZGRz
IHN1cHBvcnQgZm9yIERBOTE1MCBDaGFyZ2VyICYgRnVlbC1HYXVnZSBJQyBHUEFEQy4NCj4gPg0K
PiA+IFNpZ25lZC1vZmYtYnk6IEFkYW0gVGhvbXNvbiA8QWRhbS5UaG9tc29uLk9wZW5zb3VyY2VA
ZGlhc2VtaS5jb20+DQo+IE9uZSBsYXN0IHF1ZXJ5IGZyb20gbWUuDQo+IA0KPiBVc2luZyB0aGUg
ZXh0ZW5kZWQgY2hhbm5lbCBuYW1lcyBpbiBJSU8gaXMgb25seSByZWFsbHkgYXBwcm9wcmlhdGUg
d2hlbg0KPiB0aGV5IGRvbid0IGNvcnJlc3BvbmQgdG8gc2ltcGxlIHBpbnMgb24gdGhlIHNpZGUg
b2YgdGhlIGNoaXAuIEZvciB0aG9zZQ0KPiBqdXN0IGRyb3AgdGhlIGV4dG5hbWUgYml0LiAgU29t
ZSBvZiB0aGUgY2hhbm5lbHMgeW91IGhhdmUgaGVyZSwgZGVmaW5pdGVseQ0KPiBuZWVkIHRoZW0g
dGhvdWdoLg0KPiANCj4gRHJvcCB0aG9zZSBmaXJzdCA0IG9yIGNvbnZpbmNlIG1lIG90aGVyd2lz
ZSBhbmQgYWRkDQo+IEFja2VkLWJ5OiBKb25hdGhhbiBDYW1lcm9uIDxqaWMyM0BrZXJuZWwub3Jn
Pg0KDQpIYXZlIGFkZGVkIHJlc3BvbnNlcyBiZWxvdy4gSWYgdGhlIGNvbW1lbnRzIGFyZSBhY2Nl
cHRlZCB0aGVuIEknbGwgcmVzcGluDQphbmQgYWRkIHlvdSdyZSAnQWNrZWQtYnknLiBJcyB0aGF0
IG9rPw0KDQo+ID4gLS0tDQo+ID4gIGRyaXZlcnMvaWlvL2FkYy9LY29uZmlnICAgICAgICB8ICAg
OSArDQo+ID4gIGRyaXZlcnMvaWlvL2FkYy9NYWtlZmlsZSAgICAgICB8ICAgMSArDQo+ID4gIGRy
aXZlcnMvaWlvL2FkYy9kYTkxNTAtZ3BhZGMuYyB8IDQwOQ0KPiArKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKw0KPiA+ICAzIGZpbGVzIGNoYW5nZWQsIDQxOSBpbnNlcnRp
b25zKCspDQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL2lpby9hZGMvZGE5MTUwLWdw
YWRjLmMNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2lpby9hZGMvS2NvbmZpZyBiL2Ry
aXZlcnMvaWlvL2FkYy9LY29uZmlnDQo+ID4gaW5kZXggMGY3OWU0Ny4uNmUwMGI4MSAxMDA2NDQN
Cj4gPiAtLS0gYS9kcml2ZXJzL2lpby9hZGMvS2NvbmZpZw0KPiA+ICsrKyBiL2RyaXZlcnMvaWlv
L2FkYy9LY29uZmlnDQo+ID4gQEAgLTEzNSw2ICsxMzUsMTUgQEAgY29uZmlnIEFYUDI4OF9BREMN
Cj4gPiAgCSAgZGV2aWNlLiBEZXBlbmRpbmcgb24gcGxhdGZvcm0gY29uZmlndXJhdGlvbiwgdGhp
cyBnZW5lcmFsIHB1cnBvc2UgQURDIGNhbg0KPiA+ICAJICBiZSB1c2VkIGZvciBzYW1wbGluZyBz
ZW5zb3JzIHN1Y2ggYXMgdGhlcm1hbCByZXNpc3RvcnMuDQo+ID4NCj4gPiArY29uZmlnIERBOTE1
MF9HUEFEQw0KPiA+ICsJdHJpc3RhdGUgIkRpYWxvZyBEQTkxNTAgR1BBREMgZHJpdmVyIHN1cHBv
cnQiDQo+ID4gKwlkZXBlbmRzIG9uIE1GRF9EQTkxNTANCj4gPiArCWhlbHANCj4gPiArCSAgU2F5
IHllcyBoZXJlIHRvIGJ1aWxkIHN1cHBvcnQgZm9yIERpYWxvZyBEQTkxNTAgR1BBREMuDQo+ID4g
Kw0KPiA+ICsJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1vZHVsZS4gSWYg
Y2hvc2VuLCB0aGUgbW9kdWxlIG5hbWUNCj4gPiArCSAgd2lsbCBiZSBkYTkxNTAtZ3BhZGMuDQo+
ID4gKw0KPiA+ICBjb25maWcgRVhZTk9TX0FEQw0KPiA+ICAJdHJpc3RhdGUgIkV4eW5vcyBBREMg
ZHJpdmVyIHN1cHBvcnQiDQo+ID4gIAlkZXBlbmRzIG9uIEFSQ0hfRVhZTk9TIHx8IEFSQ0hfUzND
MjRYWCB8fCBBUkNIX1MzQzY0WFggfHwgKE9GICYmDQo+IENPTVBJTEVfVEVTVCkNCj4gPiBkaWZm
IC0tZ2l0IGEvZHJpdmVycy9paW8vYWRjL01ha2VmaWxlIGIvZHJpdmVycy9paW8vYWRjL01ha2Vm
aWxlDQo+ID4gaW5kZXggNzAxZmRiNy4uZDU2ZWU5YiAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJz
L2lpby9hZGMvTWFrZWZpbGUNCj4gPiArKysgYi9kcml2ZXJzL2lpby9hZGMvTWFrZWZpbGUNCj4g
PiBAQCAtMTUsNiArMTUsNyBAQCBvYmotJChDT05GSUdfQUQ3ODg3KSArPSBhZDc4ODcubw0KPiA+
ICBvYmotJChDT05GSUdfQUQ3OTlYKSArPSBhZDc5OXgubw0KPiA+ICBvYmotJChDT05GSUdfQVQ5
MV9BREMpICs9IGF0OTFfYWRjLm8NCj4gPiAgb2JqLSQoQ09ORklHX0FYUDI4OF9BREMpICs9IGF4
cDI4OF9hZGMubw0KPiA+ICtvYmotJChDT05GSUdfREE5MTUwX0dQQURDKSArPSBkYTkxNTAtZ3Bh
ZGMubw0KPiA+ICBvYmotJChDT05GSUdfRVhZTk9TX0FEQykgKz0gZXh5bm9zX2FkYy5vDQo+ID4g
IG9iai0kKENPTkZJR19MUDg3ODhfQURDKSArPSBscDg3ODhfYWRjLm8NCj4gPiAgb2JqLSQoQ09O
RklHX01BWDEwMjcpICs9IG1heDEwMjcubw0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2lpby9h
ZGMvZGE5MTUwLWdwYWRjLmMgYi9kcml2ZXJzL2lpby9hZGMvZGE5MTUwLWdwYWRjLmMNCj4gPiBu
ZXcgZmlsZSBtb2RlIDEwMDY0NA0KPiA+IGluZGV4IDAwMDAwMDAuLjNmN2JjODENCj4gPiAtLS0g
L2Rldi9udWxsDQo+ID4gKysrIGIvZHJpdmVycy9paW8vYWRjL2RhOTE1MC1ncGFkYy5jDQo+ID4g
QEAgLTAsMCArMSw0MDkgQEANCj4gPiArLyoNCj4gPiArICogREE5MTUwIEdQQURDIERyaXZlcg0K
PiA+ICsgKg0KPiA+ICsgKiBDb3B5cmlnaHQgKGMpIDIwMTQgRGlhbG9nIFNlbWljb25kdWN0b3IN
Cj4gPiArICoNCj4gPiArICogQXV0aG9yOiBBZGFtIFRob21zb24gPEFkYW0uVGhvbXNvbi5PcGVu
c291cmNlQGRpYXNlbWkuY29tPg0KPiA+ICsgKg0KPiA+ICsgKiBUaGlzIHByb2dyYW0gaXMgZnJl
ZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgIGl0IGFuZC9vciBtb2RpZnkgaXQNCj4g
PiArICogdW5kZXIgIHRoZSB0ZXJtcyBvZiAgdGhlIEdOVSBHZW5lcmFsICBQdWJsaWMgTGljZW5z
ZSBhcyBwdWJsaXNoZWQgYnkgdGhlDQo+ID4gKyAqIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsg
IGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlICBMaWNlbnNlLCBvciAoYXQgeW91cg0KPiA+ICsgKiBv
cHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLg0KPiA+ICsgKi8NCj4gPiArDQo+ID4gKyNpbmNsdWRl
IDxsaW51eC9rZXJuZWwuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L3NsYWIuaD4NCj4gPiArI2lu
Y2x1ZGUgPGxpbnV4L21vZHVsZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2
aWNlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9pbnRlcnJ1cHQuaD4NCj4gPiArI2luY2x1ZGUg
PGxpbnV4L211dGV4Lmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9jb21wbGV0aW9uLmg+DQo+ID4g
KyNpbmNsdWRlIDxsaW51eC9paW8vaWlvLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9paW8vbWFj
aGluZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvaWlvL2RyaXZlci5oPg0KPiA+ICsjaW5jbHVk
ZSA8bGludXgvbWZkL2RhOTE1MC9jb3JlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9tZmQvZGE5
MTUwL3JlZ2lzdGVycy5oPg0KPiA+ICsNCj4gPiArLyogQ2hhbm5lbHMgKi8NCj4gPiArZW51bSBk
YTkxNTBfZ3BhZGNfaHdfY2hhbm5lbCB7DQo+ID4gKwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9HUElP
QV8yViA9IDAsDQo+ID4gKwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9HUElPQV8yVl8sDQo+ID4gKwlE
QTkxNTBfR1BBRENfSFdfQ0hBTl9HUElPQl8yViwNCj4gPiArCURBOTE1MF9HUEFEQ19IV19DSEFO
X0dQSU9CXzJWXywNCj4gPiArCURBOTE1MF9HUEFEQ19IV19DSEFOX0dQSU9DXzJWLA0KPiA+ICsJ
REE5MTUwX0dQQURDX0hXX0NIQU5fR1BJT0NfMlZfLA0KPiA+ICsJREE5MTUwX0dQQURDX0hXX0NI
QU5fR1BJT0RfMlYsDQo+ID4gKwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9HUElPRF8yVl8sDQo+ID4g
KwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9JQlVTX1NFTlNFLA0KPiA+ICsJREE5MTUwX0dQQURDX0hX
X0NIQU5fSUJVU19TRU5TRV8sDQo+ID4gKwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9WQlVTX0RJViwN
Cj4gPiArCURBOTE1MF9HUEFEQ19IV19DSEFOX1ZCVVNfRElWXywNCj4gPiArCURBOTE1MF9HUEFE
Q19IV19DSEFOX0lELA0KPiA+ICsJREE5MTUwX0dQQURDX0hXX0NIQU5fSURfLA0KPiA+ICsJREE5
MTUwX0dQQURDX0hXX0NIQU5fVlNZUywNCj4gPiArCURBOTE1MF9HUEFEQ19IV19DSEFOX1ZTWVNf
LA0KPiA+ICsJREE5MTUwX0dQQURDX0hXX0NIQU5fR1BJT0FfNlYsDQo+ID4gKwlEQTkxNTBfR1BB
RENfSFdfQ0hBTl9HUElPQV82Vl8sDQo+ID4gKwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9HUElPQl82
ViwNCj4gPiArCURBOTE1MF9HUEFEQ19IV19DSEFOX0dQSU9CXzZWXywNCj4gPiArCURBOTE1MF9H
UEFEQ19IV19DSEFOX0dQSU9DXzZWLA0KPiA+ICsJREE5MTUwX0dQQURDX0hXX0NIQU5fR1BJT0Nf
NlZfLA0KPiA+ICsJREE5MTUwX0dQQURDX0hXX0NIQU5fR1BJT0RfNlYsDQo+ID4gKwlEQTkxNTBf
R1BBRENfSFdfQ0hBTl9HUElPRF82Vl8sDQo+ID4gKwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9WQkFU
LA0KPiA+ICsJREE5MTUwX0dQQURDX0hXX0NIQU5fVkJBVF8sDQo+ID4gKwlEQTkxNTBfR1BBRENf
SFdfQ0hBTl9UQkFULA0KPiA+ICsJREE5MTUwX0dQQURDX0hXX0NIQU5fVEJBVF8sDQo+ID4gKwlE
QTkxNTBfR1BBRENfSFdfQ0hBTl9USlVOQ19DT1JFLA0KPiA+ICsJREE5MTUwX0dQQURDX0hXX0NI
QU5fVEpVTkNfQ09SRV8sDQo+ID4gKwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9USlVOQ19PVlAsDQo+
ID4gKwlEQTkxNTBfR1BBRENfSFdfQ0hBTl9USlVOQ19PVlBfLA0KPiA+ICt9Ow0KPiA+ICsNCj4g
PiArZW51bSBkYTkxNTBfZ3BhZGNfY2hhbm5lbCB7DQo+ID4gKwlEQTkxNTBfR1BBRENfQ0hBTl9H
UElPQSA9IDAsDQo+ID4gKwlEQTkxNTBfR1BBRENfQ0hBTl9HUElPQiwNCj4gPiArCURBOTE1MF9H
UEFEQ19DSEFOX0dQSU9DLA0KPiA+ICsJREE5MTUwX0dQQURDX0NIQU5fR1BJT0QsDQo+ID4gKwlE
QTkxNTBfR1BBRENfQ0hBTl9JQlVTLA0KPiA+ICsJREE5MTUwX0dQQURDX0NIQU5fVkJVUywNCj4g
PiArCURBOTE1MF9HUEFEQ19DSEFOX0lELA0KPiA+ICsJREE5MTUwX0dQQURDX0NIQU5fVlNZUywN
Cj4gPiArCURBOTE1MF9HUEFEQ19DSEFOX1ZCQVQsDQo+ID4gKwlEQTkxNTBfR1BBRENfQ0hBTl9U
QkFULA0KPiA+ICsJREE5MTUwX0dQQURDX0NIQU5fVEpVTkNfQ09SRSwNCj4gPiArCURBOTE1MF9H
UEFEQ19DSEFOX1RKVU5DX09WUCwNCj4gPiArfTsNCj4gPiArDQo+ID4gKy8qIFByaXZhdGUgZGF0
YSAqLw0KPiA+ICtzdHJ1Y3QgZGE5MTUwX2dwYWRjIHsNCj4gPiArCXN0cnVjdCBkYTkxNTAgKmRh
OTE1MDsNCj4gPiArCXN0cnVjdCBkZXZpY2UgKmRldjsNCj4gPiArDQo+ID4gKwlzdHJ1Y3QgbXV0
ZXggbG9jazsNCj4gPiArCXN0cnVjdCBjb21wbGV0aW9uIGNvbXBsZXRlOw0KPiA+ICt9Ow0KPiA+
ICsNCj4gPiArDQo+ID4gK3N0YXRpYyBpcnFyZXR1cm5fdCBkYTkxNTBfZ3BhZGNfaXJxKGludCBp
cnEsIHZvaWQgKmRhdGEpDQo+ID4gK3sNCj4gPiArDQo+ID4gKwlzdHJ1Y3QgZGE5MTUwX2dwYWRj
ICpncGFkYyA9IGRhdGE7DQo+ID4gKw0KPiA+ICsJY29tcGxldGUoJmdwYWRjLT5jb21wbGV0ZSk7
DQo+ID4gKw0KPiA+ICsJcmV0dXJuIElSUV9IQU5ETEVEOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtz
dGF0aWMgaW50IGRhOTE1MF9ncGFkY19yZWFkX2FkYyhzdHJ1Y3QgZGE5MTUwX2dwYWRjICpncGFk
YywgaW50IGh3X2NoYW4pDQo+ID4gK3sNCj4gPiArCXU4IHJlc3VsdF9yZWdzWzJdOw0KPiA+ICsJ
aW50IHJlc3VsdDsNCj4gPiArDQo+ID4gKwltdXRleF9sb2NrKCZncGFkYy0+bG9jayk7DQo+ID4g
Kw0KPiA+ICsJLyogU2V0IGNoYW5uZWwgJiBlbmFibGUgbWVhc3VyZW1lbnQgKi8NCj4gPiArCWRh
OTE1MF9yZWdfd3JpdGUoZ3BhZGMtPmRhOTE1MCwgREE5MTUwX0dQQURDX01BTiwNCj4gPiArCQkJ
IChEQTkxNTBfR1BBRENfRU5fTUFTSyB8DQo+ID4gKwkJCSAgaHdfY2hhbiA8PCBEQTkxNTBfR1BB
RENfTVVYX1NISUZUKSk7DQo+ID4gKw0KPiA+ICsJLyogQ29uc3VtZSBsZWZ0LW92ZXIgY29tcGxl
dGlvbiBmcm9tIGEgcHJldmlvdXMgdGltZW91dCAqLw0KPiA+ICsJdHJ5X3dhaXRfZm9yX2NvbXBs
ZXRpb24oJmdwYWRjLT5jb21wbGV0ZSk7DQo+ID4gKw0KPiA+ICsJLyogQ2hlY2sgZm9yIGFjdHVh
bCBjb21wbGV0aW9uICovDQo+ID4gKwl3YWl0X2Zvcl9jb21wbGV0aW9uX3RpbWVvdXQoJmdwYWRj
LT5jb21wbGV0ZSwgbXNlY3NfdG9famlmZmllcyg1KSk7DQo+ID4gKw0KPiA+ICsJLyogUmVhZCBy
ZXN1bHQgYW5kIHN0YXR1cyBmcm9tIGRldmljZSAqLw0KPiA+ICsJZGE5MTUwX2J1bGtfcmVhZChn
cGFkYy0+ZGE5MTUwLCBEQTkxNTBfR1BBRENfUkVTX0EsIDIsIHJlc3VsdF9yZWdzKTsNCj4gPiAr
DQo+ID4gKwltdXRleF91bmxvY2soJmdwYWRjLT5sb2NrKTsNCj4gPiArDQo+ID4gKwkvKiBDaGVj
ayB0byBtYWtlIHN1cmUgZGV2aWNlIHJlYWxseSBoYXMgY29tcGxldGVkIHJlYWRpbmcgKi8NCj4g
PiArCWlmIChyZXN1bHRfcmVnc1sxXSAmIERBOTE1MF9HUEFEQ19SVU5fTUFTSykgew0KPiA+ICsJ
CWRldl9lcnIoZ3BhZGMtPmRldiwgIlRpbWVvdXQgb24gY2hhbm5lbCAlZCBvZiBHUEFEQ1xuIiwN
Cj4gPiArCQkJaHdfY2hhbik7DQo+ID4gKwkJcmV0dXJuIC1FVElNRURPVVQ7DQo+ID4gKwl9DQo+
ID4gKw0KPiA+ICsJLyogTFNCcyAtIDIgYml0cyAqLw0KPiA+ICsJcmVzdWx0ID0gKHJlc3VsdF9y
ZWdzWzFdICYgREE5MTUwX0dQQURDX1JFU19MX01BU0spID4+DQo+ID4gKwkJIERBOTE1MF9HUEFE
Q19SRVNfTF9TSElGVDsNCj4gPiArCS8qIE1TQnMgLSA4IGJpdHMgKi8NCj4gPiArCXJlc3VsdCB8
PSByZXN1bHRfcmVnc1swXSA8PCBEQTkxNTBfR1BBRENfUkVTX0xfQklUUzsNCj4gPiArDQo+ID4g
KwlyZXR1cm4gcmVzdWx0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW5saW5lIGludCBk
YTkxNTBfZ3BhZGNfZ3Bpb182dl92b2x0YWdlX25vdyhpbnQgcmF3X3ZhbCkNCj4gPiArew0KPiA+
ICsJLyogQ29udmVydCB0byBtViAqLw0KPiA+ICsJcmV0dXJuICg2ICogKChyYXdfdmFsICogMTAw
MCkgKyA1MDApKSAvIDEwMjQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbmxpbmUgaW50
IGRhOTE1MF9ncGFkY19pYnVzX2N1cnJlbnRfYXZnKGludCByYXdfdmFsKQ0KPiA+ICt7DQo+ID4g
KwkvKiBDb252ZXJ0IHRvIG1BICovDQo+ID4gKwlyZXR1cm4gKDQgKiAoKHJhd192YWwgKiAxMDAw
KSArIDUwMCkpIC8gMjA0ODsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGlubGluZSBpbnQg
ZGE5MTUwX2dwYWRjX3ZidXNfMjF2X3ZvbHRhZ2Vfbm93KGludCByYXdfdmFsKQ0KPiA+ICt7DQo+
ID4gKwkvKiBDb252ZXJ0IHRvIG1WICovDQo+ID4gKwlyZXR1cm4gKDIxICogKChyYXdfdmFsICog
MTAwMCkgKyA1MDApKSAvIDEwMjQ7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbmxpbmUg
aW50IGRhOTE1MF9ncGFkY192c3lzXzZ2X3ZvbHRhZ2Vfbm93KGludCByYXdfdmFsKQ0KPiA+ICt7
DQo+ID4gKwkvKiBDb252ZXJ0IHRvIG1WICovDQo+ID4gKwlyZXR1cm4gKDMgKiAoKHJhd192YWwg
KiAxMDAwKSArIDUwMCkpIC8gNTEyOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGRh
OTE1MF9ncGFkY19yZWFkX3Byb2Nlc3NlZChzdHJ1Y3QgZGE5MTUwX2dwYWRjICpncGFkYywgaW50
DQo+IGNoYW5uZWwsDQo+ID4gKwkJCQkgICAgICAgaW50IGh3X2NoYW4sIGludCAqdmFsKQ0KPiA+
ICt7DQo+ID4gKwlpbnQgcmF3X3ZhbDsNCj4gPiArDQo+ID4gKwlyYXdfdmFsID0gZGE5MTUwX2dw
YWRjX3JlYWRfYWRjKGdwYWRjLCBod19jaGFuKTsNCj4gPiArCWlmIChyYXdfdmFsIDwgMCkNCj4g
PiArCQlyZXR1cm4gcmF3X3ZhbDsNCj4gPiArDQo+ID4gKwlzd2l0Y2ggKGNoYW5uZWwpIHsNCj4g
PiArCWNhc2UgREE5MTUwX0dQQURDX0NIQU5fR1BJT0E6DQo+ID4gKwljYXNlIERBOTE1MF9HUEFE
Q19DSEFOX0dQSU9COg0KPiA+ICsJY2FzZSBEQTkxNTBfR1BBRENfQ0hBTl9HUElPQzoNCj4gPiAr
CWNhc2UgREE5MTUwX0dQQURDX0NIQU5fR1BJT0Q6DQo+ID4gKwkJKnZhbCA9IGRhOTE1MF9ncGFk
Y19ncGlvXzZ2X3ZvbHRhZ2Vfbm93KHJhd192YWwpOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJY2Fz
ZSBEQTkxNTBfR1BBRENfQ0hBTl9JQlVTOg0KPiA+ICsJCSp2YWwgPSBkYTkxNTBfZ3BhZGNfaWJ1
c19jdXJyZW50X2F2ZyhyYXdfdmFsKTsNCj4gPiArCQlicmVhazsNCj4gPiArCWNhc2UgREE5MTUw
X0dQQURDX0NIQU5fVkJVUzoNCj4gPiArCQkqdmFsID0gZGE5MTUwX2dwYWRjX3ZidXNfMjF2X3Zv
bHRhZ2Vfbm93KHJhd192YWwpOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJY2FzZSBEQTkxNTBfR1BB
RENfQ0hBTl9WU1lTOg0KPiA+ICsJCSp2YWwgPSBkYTkxNTBfZ3BhZGNfdnN5c182dl92b2x0YWdl
X25vdyhyYXdfdmFsKTsNCj4gPiArCQlicmVhazsNCj4gPiArCWRlZmF1bHQ6DQo+ID4gKwkJLyog
Tm8gcHJvY2Vzc2luZyBmb3Igb3RoZXIgY2hhbm5lbHMgc28gcmV0dXJuIHJhdyB2YWx1ZSAqLw0K
PiA+ICsJCSp2YWwgPSByYXdfdmFsOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJfQ0KPiA+ICsNCj4g
PiArCXJldHVybiBJSU9fVkFMX0lOVDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBk
YTkxNTBfZ3BhZGNfcmVhZF9zY2FsZShpbnQgY2hhbm5lbCwgaW50ICp2YWwsIGludCAqdmFsMikN
Cj4gPiArew0KPiA+ICsJc3dpdGNoIChjaGFubmVsKSB7DQo+ID4gKwljYXNlIERBOTE1MF9HUEFE
Q19DSEFOX1ZCQVQ6DQo+ID4gKwkJKnZhbCA9IDI5MzI7DQo+ID4gKwkJKnZhbDIgPSAxMDAwOw0K
PiA+ICsJCXJldHVybiBJSU9fVkFMX0ZSQUNUSU9OQUw7DQo+ID4gKwljYXNlIERBOTE1MF9HUEFE
Q19DSEFOX1RKVU5DX0NPUkU6DQo+ID4gKwljYXNlIERBOTE1MF9HUEFEQ19DSEFOX1RKVU5DX09W
UDoNCj4gPiArCQkqdmFsID0gMTAwMDAwMDsNCj4gPiArCQkqdmFsMiA9IDQ0MjA7DQo+ID4gKwkJ
cmV0dXJuIElJT19WQUxfRlJBQ1RJT05BTDsNCj4gPiArCWRlZmF1bHQ6DQo+ID4gKwkJcmV0dXJu
IC1FSU5WQUw7DQo+ID4gKwl9DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgZGE5MTUw
X2dwYWRjX3JlYWRfb2Zmc2V0KGludCBjaGFubmVsLCBpbnQgKnZhbCkNCj4gPiArew0KPiA+ICsJ
c3dpdGNoIChjaGFubmVsKSB7DQo+ID4gKwljYXNlIERBOTE1MF9HUEFEQ19DSEFOX1ZCQVQ6DQo+
ID4gKwkJKnZhbCA9IDE1MDAwMDAgLyAyOTMyOw0KPiA+ICsJCXJldHVybiBJSU9fVkFMX0lOVDsN
Cj4gPiArCWNhc2UgREE5MTUwX0dQQURDX0NIQU5fVEpVTkNfQ09SRToNCj4gPiArCWNhc2UgREE5
MTUwX0dQQURDX0NIQU5fVEpVTkNfT1ZQOg0KPiA+ICsJCSp2YWwgPSAtMTQ0Ow0KPiA+ICsJCXJl
dHVybiBJSU9fVkFMX0lOVDsNCj4gPiArCWRlZmF1bHQ6DQo+ID4gKwkJcmV0dXJuIC1FSU5WQUw7
DQo+ID4gKwl9DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgZGE5MTUwX2dwYWRjX3Jl
YWRfcmF3KHN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXYsDQo+ID4gKwkJCQkgc3RydWN0IGlpb19j
aGFuX3NwZWMgY29uc3QgKmNoYW4sDQo+ID4gKwkJCQkgaW50ICp2YWwsIGludCAqdmFsMiwgbG9u
ZyBtYXNrKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgZGE5MTUwX2dwYWRjICpncGFkYyA9IGlpb19w
cml2KGluZGlvX2Rldik7DQo+ID4gKw0KPiA+ICsJaWYgKChjaGFuLT5jaGFubmVsIDwgREE5MTUw
X0dQQURDX0NIQU5fR1BJT0EpIHx8DQo+ID4gKwkgICAgKGNoYW4tPmNoYW5uZWwgPiBEQTkxNTBf
R1BBRENfQ0hBTl9USlVOQ19PVlApKQ0KPiA+ICsJCXJldHVybiAtRUlOVkFMOw0KPiA+ICsNCj4g
PiArCXN3aXRjaCAobWFzaykgew0KPiA+ICsJY2FzZSBJSU9fQ0hBTl9JTkZPX1JBVzoNCj4gPiAr
CWNhc2UgSUlPX0NIQU5fSU5GT19QUk9DRVNTRUQ6DQo+ID4gKwkJcmV0dXJuIGRhOTE1MF9ncGFk
Y19yZWFkX3Byb2Nlc3NlZChncGFkYywgY2hhbi0+Y2hhbm5lbCwNCj4gPiArCQkJCQkJICAgY2hh
bi0+YWRkcmVzcywgdmFsKTsNCj4gPiArCWNhc2UgSUlPX0NIQU5fSU5GT19TQ0FMRToNCj4gPiAr
CQlyZXR1cm4gZGE5MTUwX2dwYWRjX3JlYWRfc2NhbGUoY2hhbi0+Y2hhbm5lbCwgdmFsLCB2YWwy
KTsNCj4gPiArCWNhc2UgSUlPX0NIQU5fSU5GT19PRkZTRVQ6DQo+ID4gKwkJcmV0dXJuIGRhOTE1
MF9ncGFkY19yZWFkX29mZnNldChjaGFuLT5jaGFubmVsLCB2YWwpOw0KPiA+ICsJZGVmYXVsdDoN
Cj4gPiArCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiArCX0NCj4gPiArfQ0KPiA+ICsNCj4gPiArc3Rh
dGljIGNvbnN0IHN0cnVjdCBpaW9faW5mbyBkYTkxNTBfZ3BhZGNfaW5mbyA9IHsNCj4gPiArCS5y
ZWFkX3JhdyA9ICZkYTkxNTBfZ3BhZGNfcmVhZF9yYXcsDQo+ID4gKwkuZHJpdmVyX21vZHVsZSA9
IFRISVNfTU9EVUxFLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArI2RlZmluZSBEQTkxNTBfR1BBRENf
Q0hBTk5FTChfaWQsIF9od19pZCwgX3R5cGUsIGNoYW5faW5mbywJXA0KPiA+ICsJCQkgICAgIF9l
eHRfbmFtZSkgewkJCVwNCj4gPiArCS50eXBlID0gX3R5cGUsCQkJCQkJXA0KPiA+ICsJLmluZGV4
ZWQgPSAxLAkJCQkJCVwNCj4gPiArCS5jaGFubmVsID0gREE5MTUwX0dQQURDX0NIQU5fIyNfaWQs
CQkJXA0KPiA+ICsJLmFkZHJlc3MgPSBEQTkxNTBfR1BBRENfSFdfQ0hBTl8jI19od19pZCwJCVwN
Cj4gPiArCS5pbmZvX21hc2tfc2VwYXJhdGUgPSBjaGFuX2luZm8sCQkJXA0KPiA+ICsJLmV4dGVu
ZF9uYW1lID0gX2V4dF9uYW1lLAkJCQlcDQo+ID4gKwkuZGF0YXNoZWV0X25hbWUgPSAjX2lkLAkJ
CQkJXA0KPiA+ICt9DQo+ID4gKw0KPiA+ICsjZGVmaW5lIERBOTE1MF9HUEFEQ19DSEFOTkVMX1JB
VyhfaWQsIF9od19pZCwgX3R5cGUsIF9leHRfbmFtZSkJXA0KPiA+ICsJREE5MTUwX0dQQURDX0NI
QU5ORUwoX2lkLCBfaHdfaWQsIF90eXBlLAkJXA0KPiA+ICsJCQkgICAgIEJJVChJSU9fQ0hBTl9J
TkZPX1JBVyksIF9leHRfbmFtZSkNCj4gPiArDQo+ID4gKyNkZWZpbmUgREE5MTUwX0dQQURDX0NI
QU5ORUxfU0NBTEVEKF9pZCwgX2h3X2lkLCBfdHlwZSwgX2V4dF9uYW1lKQlcDQo+ID4gKwlEQTkx
NTBfR1BBRENfQ0hBTk5FTChfaWQsIF9od19pZCwgX3R5cGUsCQkJXA0KPiA+ICsJCQkgICAgIEJJ
VChJSU9fQ0hBTl9JTkZPX1JBVykgfAkJCVwNCj4gPiArCQkJICAgICBCSVQoSUlPX0NIQU5fSU5G
T19TQ0FMRSkgfAkJCVwNCj4gPiArCQkJICAgICBCSVQoSUlPX0NIQU5fSU5GT19PRkZTRVQpLAkJ
CVwNCj4gPiArCQkJICAgICBfZXh0X25hbWUpDQo+ID4gKw0KPiA+ICsjZGVmaW5lIERBOTE1MF9H
UEFEQ19DSEFOTkVMX1BST0NFU1NFRChfaWQsIF9od19pZCwgX3R5cGUsIF9leHRfbmFtZSkNCj4g
CVwNCj4gPiArCURBOTE1MF9HUEFEQ19DSEFOTkVMKF9pZCwgX2h3X2lkLCBfdHlwZSwJCQlcDQo+
ID4gKwkJCSAgICAgQklUKElJT19DSEFOX0lORk9fUFJPQ0VTU0VEKSwgX2V4dF9uYW1lKQ0KPiA+
ICsNCj4gPiArLyogU3VwcG9ydGVkIGNoYW5uZWxzICovDQo+ID4gK3N0YXRpYyBjb25zdCBzdHJ1
Y3QgaWlvX2NoYW5fc3BlYyBkYTkxNTBfZ3BhZGNfY2hhbm5lbHNbXSA9IHsNCj4gPiArCURBOTE1
MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NFRChHUElPQSwgR1BJT0FfNlYsIElJT19WT0xUQUdFLA0K
PiAiR1BJT0EiKSwNCj4gPiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NFRChHUElPQiwg
R1BJT0JfNlYsIElJT19WT0xUQUdFLA0KPiAiR1BJT0IiKSwNCj4gPiArCURBOTE1MF9HUEFEQ19D
SEFOTkVMX1BST0NFU1NFRChHUElPQywgR1BJT0NfNlYsIElJT19WT0xUQUdFLA0KPiAiR1BJT0Mi
KSwNCj4gPiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NFRChHUElPRCwgR1BJT0RfNlYs
IElJT19WT0xUQUdFLA0KPiAiR1BJT0QiKSwNCj4gSSdtIG5vdCBzdXJlIHNvbWUgb2YgdGhlc2Ug
cmVhbGx5IGRlc2VydmUgZXh0ZW5kZWQgbmFtZXMuICBUaG9zZSBhcmUgdXN1YWxseQ0KPiByZXNl
cnZlZCBmb3IgbmFtaW5nIHN0cmFuZ2UgaW50ZXJuYWwgYWRjIGNoYW5uZWxzIGV0Yy4gIFRoZXNl
IGZpcnN0IDQgYXJlDQo+IHByZXN1bWFibHkganVzdCBmb3IgaW5wdXQgcGlucz8gIFRob3NlIHNo
b3VsZCBqdXN0IGJlIGNoYW5uZWxzIDAuLjMNCj4gT24gYW5vdGhlciBub3RlLCB1bmxlc3MgeW91
IHdhbnQgcmVhbGx5IHdlaXJkIHN5c2ZzIGF0dHJpYnV0ZSBuYW1lcywgdGhlDQo+IGV4dGVuZGVk
IG5hbWVzIHdhbnQgdG8gYmUgbG93ZXJjYXNlLg0KPiANCg0KSSdkIHByZWZlciB0byBrZWVwIHRo
ZSBuYW1lcyBiZWNhdXNlIHRoZSBpbnB1dCBwaW5zIGFyZSBtdXhlZCB3aXRoIEdQSU9zIG9mIHRo
ZQ0KY2hpcCwgc28gdGhvdWdodCBpdCBzZW5zaWJsZSB0byBzaG93IHRoYXQgdGhpcyBpcyB0aGUg
Y2FzZS4gQW0gaGFwcHkgdG8gY2hhbmdlDQp0byBsb3dlci1jYXNlIHRvIGZvbGxvdyBjb252ZW50
aW9uLg0KDQo+ID4gKwlEQTkxNTBfR1BBRENfQ0hBTk5FTF9QUk9DRVNTRUQoSUJVUywgSUJVU19T
RU5TRSwgSUlPX0NVUlJFTlQsDQo+ICJJQlVTIiksDQo+ID4gKwlEQTkxNTBfR1BBRENfQ0hBTk5F
TF9QUk9DRVNTRUQoVkJVUywgVkJVU19ESVZfLCBJSU9fVk9MVEFHRSwNCj4gIlZCVVMiKSwNCj4g
PiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1JBVyhJRCwgSUQsIElJT19WT0xUQUdFLCAiSUQiKSwN
Cj4gWW91IGhhZSBhbiBpZGVudGlmaWVyIHZvbHRhZ2U/IFRoYXQncyBjZXJ0YWlubHkgdW51c3Vh
bCBidXQgaWYgc28gLSBmYWlyIGVub3VnaA0KPiBhbmQgaXQgZGVmaW50ZWx5IG5lZWRzIHRoZSBl
eHRuYW1lIQ0KDQpUaGFua3MgZm9yIHBvaW50aW5nIHRoYXQgb3V0LiBIYXZpbmcgY2hlY2tlZCBh
Z2FpbiwgdGhpcyBpcyBub3QgbmVlZGVkIGFuZCBjYW4NCmJlIGRpc3BlbnNlZCB3aXRoLg0KDQo+
ID4gKwlEQTkxNTBfR1BBRENfQ0hBTk5FTF9QUk9DRVNTRUQoVlNZUywgVlNZUywgSUlPX1ZPTFRB
R0UsICJWU1lTIiksDQo+ID4gKwlEQTkxNTBfR1BBRENfQ0hBTk5FTF9TQ0FMRUQoVkJBVCwgVkJB
VCwgSUlPX1ZPTFRBR0UsICJWQkFUIiksDQo+ID4gKwlEQTkxNTBfR1BBRENfQ0hBTk5FTF9SQVco
VEJBVCwgVEJBVCwgSUlPX1ZPTFRBR0UsICJUQkFUIiksDQo+ID4gKwlEQTkxNTBfR1BBRENfQ0hB
Tk5FTF9TQ0FMRUQoVEpVTkNfQ09SRSwgVEpVTkNfQ09SRSwNCj4gSUlPX1RFTVAsDQo+ID4gKwkJ
CQkgICAgIlRKVU5DX0NPUkUiKSwNCj4gdGp1bmNfY29yZSBpcyBhIGdvb2QgdXNlIG9mIGV4dG5h
bWUgOykNCj4gPiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1NDQUxFRChUSlVOQ19PVlAsIFRKVU5D
X09WUCwgSUlPX1RFTVAsDQo+ID4gKwkJCQkgICAgIlRKVU5DX09WUCIpLA0KPiA+ICt9Ow0KPiA+
ICsNCj4gPiArLyogRGVmYXVsdCBtYXBzIHVzZWQgYnkgZGE5MTUwLWNoYXJnZXIgKi8NCj4gPiAr
c3RhdGljIHN0cnVjdCBpaW9fbWFwIGRhOTE1MF9ncGFkY19kZWZhdWx0X21hcHNbXSA9IHsNCj4g
PiArCXsNCj4gPiArCQkuY29uc3VtZXJfZGV2X25hbWUgPSAiZGE5MTUwLWNoYXJnZXIiLA0KPiA+
ICsJCS5jb25zdW1lcl9jaGFubmVsID0gIkNIQU5fSUJVUyIsDQo+ID4gKwkJLmFkY19jaGFubmVs
X2xhYmVsID0gIklCVVMiLA0KPiA+ICsJfSwNCj4gPiArCXsNCj4gPiArCQkuY29uc3VtZXJfZGV2
X25hbWUgPSAiZGE5MTUwLWNoYXJnZXIiLA0KPiA+ICsJCS5jb25zdW1lcl9jaGFubmVsID0gIkNI
QU5fVkJVUyIsDQo+ID4gKwkJLmFkY19jaGFubmVsX2xhYmVsID0gIlZCVVMiLA0KPiA+ICsJfSwN
Cj4gPiArCXsNCj4gPiArCQkuY29uc3VtZXJfZGV2X25hbWUgPSAiZGE5MTUwLWNoYXJnZXIiLA0K
PiA+ICsJCS5jb25zdW1lcl9jaGFubmVsID0gIkNIQU5fVEpVTkMiLA0KPiA+ICsJCS5hZGNfY2hh
bm5lbF9sYWJlbCA9ICJUSlVOQ19DT1JFIiwNCj4gPiArCX0sDQo+ID4gKwl7DQo+ID4gKwkJLmNv
bnN1bWVyX2Rldl9uYW1lID0gImRhOTE1MC1jaGFyZ2VyIiwNCj4gPiArCQkuY29uc3VtZXJfY2hh
bm5lbCA9ICJDSEFOX1ZCQVQiLA0KPiA+ICsJCS5hZGNfY2hhbm5lbF9sYWJlbCA9ICJWQkFUIiwN
Cj4gPiArCX0sDQo+ID4gKwl7fSwNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgZGE5
MTUwX2dwYWRjX3Byb2JlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpDQo+ID4gK3sNCj4g
PiArCXN0cnVjdCBkZXZpY2UgKmRldiA9ICZwZGV2LT5kZXY7DQo+ID4gKwlzdHJ1Y3QgZGE5MTUw
ICpkYTkxNTAgPSBkZXZfZ2V0X2RydmRhdGEoZGV2LT5wYXJlbnQpOw0KPiA+ICsJc3RydWN0IGRh
OTE1MF9ncGFkYyAqZ3BhZGM7DQo+ID4gKwlzdHJ1Y3QgaWlvX2RldiAqaW5kaW9fZGV2Ow0KPiA+
ICsJaW50IGlycSwgcmV0Ow0KPiA+ICsNCj4gPiArCWluZGlvX2RldiA9IGRldm1faWlvX2Rldmlj
ZV9hbGxvYygmcGRldi0+ZGV2LCBzaXplb2YoKmdwYWRjKSk7DQo+ID4gKwlpZiAoIWluZGlvX2Rl
dikgew0KPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgIkZhaWxlZCB0byBhbGxvY2F0ZSBJSU8g
ZGV2aWNlXG4iKTsNCj4gPiArCQlyZXR1cm4gLUVOT01FTTsNCj4gPiArCX0NCj4gPiArCWdwYWRj
ID0gaWlvX3ByaXYoaW5kaW9fZGV2KTsNCj4gPiArDQo+ID4gKwlwbGF0Zm9ybV9zZXRfZHJ2ZGF0
YShwZGV2LCBpbmRpb19kZXYpOw0KPiA+ICsJZ3BhZGMtPmRhOTE1MCA9IGRhOTE1MDsNCj4gPiAr
CWdwYWRjLT5kZXYgPSBkZXY7DQo+ID4gKwltdXRleF9pbml0KCZncGFkYy0+bG9jayk7DQo+ID4g
Kwlpbml0X2NvbXBsZXRpb24oJmdwYWRjLT5jb21wbGV0ZSk7DQo+ID4gKw0KPiA+ICsJaXJxID0g
cGxhdGZvcm1fZ2V0X2lycV9ieW5hbWUocGRldiwgIkdQQURDIik7DQo+ID4gKwlpZiAoaXJxIDwg
MCkgew0KPiA+ICsJCWRldl9lcnIoZGV2LCAiRmFpbGVkIHRvIGdldCBJUlE6ICVkXG4iLCBpcnEp
Ow0KPiA+ICsJCXJldHVybiBpcnE7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gZGV2bV9y
ZXF1ZXN0X3RocmVhZGVkX2lycShkZXYsIGlycSwgTlVMTCwgZGE5MTUwX2dwYWRjX2lycSwNCj4g
PiArCQkJCQlJUlFGX09ORVNIT1QsICJHUEFEQyIsIGdwYWRjKTsNCj4gPiArCWlmIChyZXQpIHsN
Cj4gPiArCQlkZXZfZXJyKGRldiwgIkZhaWxlZCB0byByZXF1ZXN0IElSUSAlZDogJWRcbiIsIGly
cSwgcmV0KTsNCj4gPiArCQlyZXR1cm4gcmV0Ow0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldCA9
IGlpb19tYXBfYXJyYXlfcmVnaXN0ZXIoaW5kaW9fZGV2LCBkYTkxNTBfZ3BhZGNfZGVmYXVsdF9t
YXBzKTsNCj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIkZhaWxlZCB0byBy
ZWdpc3RlciBJSU8gbWFwczogJWRcbiIsIHJldCk7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiAr
CX0NCj4gPiArDQo+ID4gKwlpbmRpb19kZXYtPm5hbWUgPSBkZXZfbmFtZShkZXYpOw0KPiA+ICsJ
aW5kaW9fZGV2LT5kZXYucGFyZW50ID0gZGV2Ow0KPiA+ICsJaW5kaW9fZGV2LT5kZXYub2Zfbm9k
ZSA9IHBkZXYtPmRldi5vZl9ub2RlOw0KPiA+ICsJaW5kaW9fZGV2LT5pbmZvID0gJmRhOTE1MF9n
cGFkY19pbmZvOw0KPiA+ICsJaW5kaW9fZGV2LT5tb2RlcyA9IElORElPX0RJUkVDVF9NT0RFOw0K
PiA+ICsJaW5kaW9fZGV2LT5jaGFubmVscyA9IGRhOTE1MF9ncGFkY19jaGFubmVsczsNCj4gPiAr
CWluZGlvX2Rldi0+bnVtX2NoYW5uZWxzID0gQVJSQVlfU0laRShkYTkxNTBfZ3BhZGNfY2hhbm5l
bHMpOw0KPiA+ICsNCj4gPiArCXJldCA9IGlpb19kZXZpY2VfcmVnaXN0ZXIoaW5kaW9fZGV2KTsN
Cj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIkZhaWxlZCB0byByZWdpc3Rl
ciBJSU8gZGV2aWNlOiAlZFxuIiwgcmV0KTsNCj4gPiArCQlnb3RvIGlpb19tYXBfdW5yZWc7DQo+
ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICtpaW9fbWFwX3VucmVn
Og0KPiA+ICsJaWlvX21hcF9hcnJheV91bnJlZ2lzdGVyKGluZGlvX2Rldik7DQo+ID4gKw0KPiA+
ICsJcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkYTkxNTBfZ3Bh
ZGNfcmVtb3ZlKHN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYpDQo+ID4gK3sNCj4gPiArCXN0
cnVjdCBpaW9fZGV2ICppbmRpb19kZXYgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsNCj4g
PiArDQo+ID4gKwlpaW9fZGV2aWNlX3VucmVnaXN0ZXIoaW5kaW9fZGV2KTsNCj4gPiArCWlpb19t
YXBfYXJyYXlfdW5yZWdpc3RlcihpbmRpb19kZXYpOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0K
PiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBkYTkxNTBf
Z3BhZGNfZHJpdmVyID0gew0KPiA+ICsJLmRyaXZlciA9IHsNCj4gPiArCQkubmFtZSA9ICJkYTkx
NTAtZ3BhZGMiLA0KPiA+ICsJfSwNCj4gPiArCS5wcm9iZSA9IGRhOTE1MF9ncGFkY19wcm9iZSwN
Cj4gPiArCS5yZW1vdmUgPSBkYTkxNTBfZ3BhZGNfcmVtb3ZlLA0KPiA+ICt9Ow0KPiA+ICsNCj4g
PiArbW9kdWxlX3BsYXRmb3JtX2RyaXZlcihkYTkxNTBfZ3BhZGNfZHJpdmVyKTsNCj4gPiArDQo+
ID4gK01PRFVMRV9ERVNDUklQVElPTigiR1BBREMgRHJpdmVyIGZvciBEQTkxNTAiKTsNCj4gPiAr
TU9EVUxFX0FVVEhPUigiQWRhbSBUaG9tc29uDQo+IDxBZGFtLlRob21zb24uT3BlbnNvdXJjZUBk
aWFzZW1pLmNvbT4iKTsNCj4gPiArTU9EVUxFX0xJQ0VOU0UoIkdQTCIpOw0KPiA+IC0tDQo+ID4g
MS45LjMNCj4gPg0K

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

* RE: [PATCH v5 5/7] power: Add support for DA9150 Charger
  2015-01-04 17:26   ` Jonathan Cameron
@ 2015-01-07 16:04     ` Opensource [Adam Thomson]
  0 siblings, 0 replies; 20+ messages in thread
From: Opensource [Adam Thomson] @ 2015-01-07 16:04 UTC (permalink / raw)
  To: Jonathan Cameron, Opensource [Adam Thomson], Lee Jones,
	Samuel Ortiz, Hartmut Knaack, linux-iio@vger.kernel.org,
	Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm@vger.kernel.org, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	devicetree@vger.kernel.org, Andrew Morton, Joe Perches
  Cc: linux-kernel@vger.kernel.org, Support Opensource

T24gSmFudWFyeSA0LCAyMDE1IDE3OjI2LCBKb25hdGhhbiBDYW1lcm9uIHdyb3RlOg0KDQo+IE9u
IDIyLzEyLzE0IDE2OjUxLCBBZGFtIFRob21zb24gd3JvdGU6DQo+ID4gVGhpcyBwYXRjaCBhZGRz
IHN1cHBvcnQgZm9yIERBOTE1MCBDaGFyZ2VyICYgRnVlbC1HYXVnZSBJQyBDaGFyZ2VyLg0KPiA+
DQo+ID4gU2lnbmVkLW9mZi1ieTogQWRhbSBUaG9tc29uIDxBZGFtLlRob21zb24uT3BlbnNvdXJj
ZUBkaWFzZW1pLmNvbT4NCj4gVGhlIElJTyBiaXRzIGxvb2sgZmluZSwgYnV0IHlvdXIgdXNlIG9m
IGRldm1fZnJlZSAqIGRvZXNuJ3QuLi4NCj4NCj4gQXMgYSBzaWRlIG5vdGUsIGxvb2tzIGxpa2Ug
d2UgY291bGQgYmVuZWZpdCBmcm9tIHNvbWUgYXJyYXkgdmVyc2lvbnMNCj4gb2YgdGhlIElJTyBj
aGFubmVsIGdldHRpbmcgYW5kIHJlbGVhc2UgZnVuY3Rpb25zLiAgV291bGQgc2F2ZSBhIGZhaXIg
Yml0DQo+IG9mIGJvaWxlciBwbGF0ZS4NCg0KWWVzLCBJIGd1ZXNzIHdoZW4gbW9yZSBkcml2ZXJz
IGNvbWUgYWxvbmcgd2hpY2ggbmVlZCBtdWx0aXBsZSBjaGFubmVscyB0aGVuDQpzb21ldGhpbmcg
bGlrZSB5b3Ugc3VnZ2VzdCB3b3VsZCBtYWtlIHNlbnNlIHRvIGhlbHAgcmVkdWNlIGNvZGUgZHVw
bGljYXRpb24uDQpBbHNvIGRldm1fKiBmdW5jdGlvbnMgY291bGQgYmUgZ29vZCB0b28uDQoNCj4g
DQo+IEpvbmF0aGFuDQo+ID4gLS0tDQo+ID4gIGRyaXZlcnMvcG93ZXIvS2NvbmZpZyAgICAgICAg
ICB8ICAxMiArDQo+ID4gIGRyaXZlcnMvcG93ZXIvTWFrZWZpbGUgICAgICAgICB8ICAgMSArDQo+
ID4gIGRyaXZlcnMvcG93ZXIvZGE5MTUwLWNoYXJnZXIuYyB8IDY2Ng0KPiArKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrKysrKysrKw0KPiA+ICAzIGZpbGVzIGNoYW5nZWQsIDY3OSBp
bnNlcnRpb25zKCspDQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL3Bvd2VyL2RhOTE1
MC1jaGFyZ2VyLmMNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3Bvd2VyL0tjb25maWcg
Yi9kcml2ZXJzL3Bvd2VyL0tjb25maWcNCj4gPiBpbmRleCAwMTA4YzJhLi5lYjc5YTdhIDEwMDY0
NA0KPiA+IC0tLSBhL2RyaXZlcnMvcG93ZXIvS2NvbmZpZw0KPiA+ICsrKyBiL2RyaXZlcnMvcG93
ZXIvS2NvbmZpZw0KPiA+IEBAIC0xOTIsNiArMTkyLDE4IEBAIGNvbmZpZyBCQVRURVJZX0RBOTA1
Mg0KPiA+ICAJICBTYXkgWSBoZXJlIHRvIGVuYWJsZSBzdXBwb3J0IGZvciBiYXR0ZXJpZXMgY2hh
cmdlciBpbnRlZ3JhdGVkIGludG8NCj4gPiAgCSAgREE5MDUyIFBNSUMuDQo+ID4NCj4gPiArY29u
ZmlnIENIQVJHRVJfREE5MTUwDQo+ID4gKwl0cmlzdGF0ZSAiRGlhbG9nIFNlbWljb25kdWN0b3Ig
REE5MTUwIENoYXJnZXIgc3VwcG9ydCINCj4gPiArCWRlcGVuZHMgb24gTUZEX0RBOTE1MA0KPiA+
ICsJZGVwZW5kcyBvbiBEQTkxNTBfR1BBREMNCj4gPiArCWRlcGVuZHMgb24gSUlPDQo+ID4gKwlo
ZWxwDQo+ID4gKwkgIFNheSBZIGhlcmUgdG8gZW5hYmxlIHN1cHBvcnQgZm9yIGNoYXJnZXIgdW5p
dCBvZiB0aGUgREE5MTUwDQo+ID4gKwkgIEludGVncmF0ZWQgQ2hhcmdlciAmIEZ1ZWwtR2F1Z2Ug
SUMuDQo+ID4gKw0KPiA+ICsJICBUaGlzIGRyaXZlciBjYW4gYWxzbyBiZSBidWlsdCBhcyBhIG1v
ZHVsZS4gSWYgc28sIHRoZSBtb2R1bGUgd2lsbCBiZQ0KPiA+ICsJICBjYWxsZWQgZGE5MTUwLWNo
YXJnZXIuDQo+ID4gKw0KPiA+ICBjb25maWcgQkFUVEVSWV9NQVgxNzA0MA0KPiA+ICAJdHJpc3Rh
dGUgIk1heGltIE1BWDE3MDQwIEZ1ZWwgR2F1Z2UiDQo+ID4gIAlkZXBlbmRzIG9uIEkyQw0KPiA+
IGRpZmYgLS1naXQgYS9kcml2ZXJzL3Bvd2VyL01ha2VmaWxlIGIvZHJpdmVycy9wb3dlci9NYWtl
ZmlsZQ0KPiA+IGluZGV4IGRmYTg5NDIuLjBjMTg5NmQgMTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVy
cy9wb3dlci9NYWtlZmlsZQ0KPiA+ICsrKyBiL2RyaXZlcnMvcG93ZXIvTWFrZWZpbGUNCj4gPiBA
QCAtMzEsNiArMzEsNyBAQCBvYmotJChDT05GSUdfQkFUVEVSWV9TQlMpCSs9IHNicy1iYXR0ZXJ5
Lm8NCj4gPiAgb2JqLSQoQ09ORklHX0JBVFRFUllfQlEyN3gwMCkJKz0gYnEyN3gwMF9iYXR0ZXJ5
Lm8NCj4gPiAgb2JqLSQoQ09ORklHX0JBVFRFUllfREE5MDMwKQkrPSBkYTkwMzBfYmF0dGVyeS5v
DQo+ID4gIG9iai0kKENPTkZJR19CQVRURVJZX0RBOTA1MikJKz0gZGE5MDUyLWJhdHRlcnkubw0K
PiA+ICtvYmotJChDT05GSUdfQ0hBUkdFUl9EQTkxNTApCSs9IGRhOTE1MC1jaGFyZ2VyLm8NCj4g
PiAgb2JqLSQoQ09ORklHX0JBVFRFUllfTUFYMTcwNDApCSs9IG1heDE3MDQwX2JhdHRlcnkubw0K
PiA+ICBvYmotJChDT05GSUdfQkFUVEVSWV9NQVgxNzA0MikJKz0gbWF4MTcwNDJfYmF0dGVyeS5v
DQo+ID4gIG9iai0kKENPTkZJR19CQVRURVJZX1oyKQkrPSB6Ml9iYXR0ZXJ5Lm8NCj4gPiBkaWZm
IC0tZ2l0IGEvZHJpdmVycy9wb3dlci9kYTkxNTAtY2hhcmdlci5jIGIvZHJpdmVycy9wb3dlci9k
YTkxNTAtY2hhcmdlci5jDQo+ID4gbmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gPiBpbmRleCAwMDAw
MDAwLi45YjE4MjZkDQo+ID4gLS0tIC9kZXYvbnVsbA0KPiA+ICsrKyBiL2RyaXZlcnMvcG93ZXIv
ZGE5MTUwLWNoYXJnZXIuYw0KPiA+IEBAIC0wLDAgKzEsNjY2IEBADQo+ID4gKy8qDQo+ID4gKyAq
IERBOTE1MCBDaGFyZ2VyIERyaXZlcg0KPiA+ICsgKg0KPiA+ICsgKiBDb3B5cmlnaHQgKGMpIDIw
MTQgRGlhbG9nIFNlbWljb25kdWN0b3INCj4gPiArICoNCj4gPiArICogQXV0aG9yOiBBZGFtIFRo
b21zb24gPEFkYW0uVGhvbXNvbi5PcGVuc291cmNlQGRpYXNlbWkuY29tPg0KPiA+ICsgKg0KPiA+
ICsgKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUg
IGl0IGFuZC9vciBtb2RpZnkgaXQNCj4gPiArICogdW5kZXIgIHRoZSB0ZXJtcyBvZiAgdGhlIEdO
VSBHZW5lcmFsICBQdWJsaWMgTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlDQo+ID4gKyAqIEZy
ZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgIGVpdGhlciB2ZXJzaW9uIDIgb2YgdGhlICBMaWNlbnNl
LCBvciAoYXQgeW91cg0KPiA+ICsgKiBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLg0KPiA+ICsg
Ki8NCj4gPiArDQo+ID4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4NCj4gPiArI2luY2x1ZGUg
PGxpbnV4L3NsYWIuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPg0KPiA+ICsjaW5j
bHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9vZi5o
Pg0KPiA+ICsjaW5jbHVkZSA8bGludXgvb2ZfcGxhdGZvcm0uaD4NCj4gPiArI2luY2x1ZGUgPGxp
bnV4L2ludGVycnVwdC5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvcG93ZXJfc3VwcGx5Lmg+DQo+
ID4gKyNpbmNsdWRlIDxsaW51eC9ub3RpZmllci5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvdXNi
L3BoeS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvaWlvL2NvbnN1bWVyLmg+DQo+ID4gKyNpbmNs
dWRlIDxsaW51eC9tZmQvZGE5MTUwL2NvcmUuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L21mZC9k
YTkxNTAvcmVnaXN0ZXJzLmg+DQo+ID4gKw0KPiA+ICsvKiBQcml2YXRlIGRhdGEgKi8NCj4gPiAr
c3RydWN0IGRhOTE1MF9jaGFyZ2VyIHsNCj4gPiArCXN0cnVjdCBkYTkxNTAgKmRhOTE1MDsNCj4g
PiArCXN0cnVjdCBkZXZpY2UgKmRldjsNCj4gPiArDQo+ID4gKwlzdHJ1Y3QgcG93ZXJfc3VwcGx5
IHVzYjsNCj4gPiArCXN0cnVjdCBwb3dlcl9zdXBwbHkgYmF0dGVyeTsNCj4gPiArCXN0cnVjdCBw
b3dlcl9zdXBwbHkgKnN1cHBseV9vbmxpbmU7DQo+ID4gKw0KPiA+ICsJc3RydWN0IHVzYl9waHkg
KnVzYl9waHk7DQo+ID4gKwlzdHJ1Y3Qgbm90aWZpZXJfYmxvY2sgb3RnX25iOw0KPiA+ICsJc3Ry
dWN0IHdvcmtfc3RydWN0IG90Z193b3JrOw0KPiA+ICsJdW5zaWduZWQgbG9uZyB1c2JfZXZlbnQ7
DQo+ID4gKw0KPiA+ICsJc3RydWN0IGlpb19jaGFubmVsICppYnVzX2NoYW47DQo+ID4gKwlzdHJ1
Y3QgaWlvX2NoYW5uZWwgKnZidXNfY2hhbjsNCj4gPiArCXN0cnVjdCBpaW9fY2hhbm5lbCAqdGp1
bmNfY2hhbjsNCj4gPiArCXN0cnVjdCBpaW9fY2hhbm5lbCAqdmJhdF9jaGFuOw0KPiA+ICt9Ow0K
PiA+ICsNCj4gPiArc3RhdGljIGlubGluZSBpbnQgZGE5MTUwX2NoYXJnZXJfc3VwcGx5X29ubGlu
ZShzdHJ1Y3QgZGE5MTUwX2NoYXJnZXIgKmNoYXJnZXIsDQo+ID4gKwkJCQkJICAgICAgIHN0cnVj
dCBwb3dlcl9zdXBwbHkgKnBzeSwNCj4gPiArCQkJCQkgICAgICAgdW5pb24gcG93ZXJfc3VwcGx5
X3Byb3B2YWwgKnZhbCkNCj4gPiArew0KPiA+ICsJdmFsLT5pbnR2YWwgPSAocHN5ID09IGNoYXJn
ZXItPnN1cHBseV9vbmxpbmUpID8gMSA6IDA7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4g
K30NCj4gPiArDQo+ID4gKy8qIENoYXJnZXIgUHJvcGVydGllcyAqLw0KPiA+ICtzdGF0aWMgaW50
IGRhOTE1MF9jaGFyZ2VyX3ZidXNfdm9sdGFnZV9ub3coc3RydWN0IGRhOTE1MF9jaGFyZ2VyICpj
aGFyZ2VyLA0KPiA+ICsJCQkJCSAgIHVuaW9uIHBvd2VyX3N1cHBseV9wcm9wdmFsICp2YWwpDQo+
ID4gK3sNCj4gPiArCWludCB2X3ZhbCwgcmV0Ow0KPiA+ICsNCj4gPiArCS8qIFJlYWQgcHJvY2Vz
c2VkIHZhbHVlIC0gbVYgdW5pdHMgKi8NCj4gPiArCXJldCA9IGlpb19yZWFkX2NoYW5uZWxfcHJv
Y2Vzc2VkKGNoYXJnZXItPnZidXNfY2hhbiwgJnZfdmFsKTsNCj4gPiArCWlmIChyZXQgPCAwKQ0K
PiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKw0KPiA+ICsJLyogQ29udmVydCB2b2x0YWdlIHRvIGV4
cGVjdGVkIHVWIHVuaXRzICovDQo+ID4gKwl2YWwtPmludHZhbCA9IHZfdmFsICogMTAwMDsNCj4g
PiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkYTkx
NTBfY2hhcmdlcl9pYnVzX2N1cnJlbnRfYXZnKHN0cnVjdCBkYTkxNTBfY2hhcmdlciAqY2hhcmdl
ciwNCj4gPiArCQkJCQkgICB1bmlvbiBwb3dlcl9zdXBwbHlfcHJvcHZhbCAqdmFsKQ0KPiA+ICt7
DQo+ID4gKwlpbnQgaV92YWwsIHJldDsNCj4gPiArDQo+ID4gKwkvKiBSZWFkIHByb2Nlc3NlZCB2
YWx1ZSAtIG1BIHVuaXRzICovDQo+ID4gKwlyZXQgPSBpaW9fcmVhZF9jaGFubmVsX3Byb2Nlc3Nl
ZChjaGFyZ2VyLT5pYnVzX2NoYW4sICZpX3ZhbCk7DQo+ID4gKwlpZiAocmV0IDwgMCkNCj4gPiAr
CQlyZXR1cm4gcmV0Ow0KPiA+ICsNCj4gPiArCS8qIENvbnZlcnQgY3VycmVudCB0byBleHBlY3Rl
ZCB1QSB1bml0cyAqLw0KPiA+ICsJdmFsLT5pbnR2YWwgPSBpX3ZhbCAqIDEwMDA7DQo+ID4gKw0K
PiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgZGE5MTUwX2No
YXJnZXJfdGp1bmNfdGVtcChzdHJ1Y3QgZGE5MTUwX2NoYXJnZXIgKmNoYXJnZXIsDQo+ID4gKwkJ
CQkgICAgIHVuaW9uIHBvd2VyX3N1cHBseV9wcm9wdmFsICp2YWwpDQo+ID4gK3sNCj4gPiArCWlu
dCB0X3ZhbCwgcmV0Ow0KPiA+ICsNCj4gPiArCS8qIFJlYWQgcHJvY2Vzc2VkIHZhbHVlIC0gMC4w
MDEgZGVncmVlcyBDIHVuaXRzICovDQo+ID4gKwlyZXQgPSBpaW9fcmVhZF9jaGFubmVsX3Byb2Nl
c3NlZChjaGFyZ2VyLT50anVuY19jaGFuLCAmdF92YWwpOw0KPiA+ICsJaWYgKHJldCA8IDApDQo+
ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArDQo+ID4gKwkvKiBDb252ZXJ0IHRlbXAgdG8gZXhwZWN0
IDAuMSBkZWdyZWVzIEMgdW5pdHMgKi8NCj4gPiArCXZhbC0+aW50dmFsID0gdF92YWwgLyAxMDA7
DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBlbnVt
IHBvd2VyX3N1cHBseV9wcm9wZXJ0eSBkYTkxNTBfY2hhcmdlcl9wcm9wc1tdID0gew0KPiA+ICsJ
UE9XRVJfU1VQUExZX1BST1BfT05MSU5FLA0KPiA+ICsJUE9XRVJfU1VQUExZX1BST1BfVk9MVEFH
RV9OT1csDQo+ID4gKwlQT1dFUl9TVVBQTFlfUFJPUF9DVVJSRU5UX0FWRywNCj4gPiArCVBPV0VS
X1NVUFBMWV9QUk9QX1RFTVAsDQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGRhOTE1
MF9jaGFyZ2VyX2dldF9wcm9wKHN0cnVjdCBwb3dlcl9zdXBwbHkgKnBzeSwNCj4gPiArCQkJCSAg
IGVudW0gcG93ZXJfc3VwcGx5X3Byb3BlcnR5IHBzcCwNCj4gPiArCQkJCSAgIHVuaW9uIHBvd2Vy
X3N1cHBseV9wcm9wdmFsICp2YWwpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBkYTkxNTBfY2hhcmdl
ciAqY2hhcmdlciA9IGRldl9nZXRfZHJ2ZGF0YShwc3ktPmRldi0+cGFyZW50KTsNCj4gPiArCWlu
dCByZXQ7DQo+ID4gKw0KPiA+ICsJc3dpdGNoIChwc3ApIHsNCj4gPiArCWNhc2UgUE9XRVJfU1VQ
UExZX1BST1BfT05MSU5FOg0KPiA+ICsJCXJldCA9IGRhOTE1MF9jaGFyZ2VyX3N1cHBseV9vbmxp
bmUoY2hhcmdlciwgcHN5LCB2YWwpOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJY2FzZSBQT1dFUl9T
VVBQTFlfUFJPUF9WT0xUQUdFX05PVzoNCj4gPiArCQlyZXQgPSBkYTkxNTBfY2hhcmdlcl92YnVz
X3ZvbHRhZ2Vfbm93KGNoYXJnZXIsIHZhbCk7DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNlIFBP
V0VSX1NVUFBMWV9QUk9QX0NVUlJFTlRfQVZHOg0KPiA+ICsJCXJldCA9IGRhOTE1MF9jaGFyZ2Vy
X2lidXNfY3VycmVudF9hdmcoY2hhcmdlciwgdmFsKTsNCj4gPiArCQlicmVhazsNCj4gPiArCWNh
c2UgUE9XRVJfU1VQUExZX1BST1BfVEVNUDoNCj4gPiArCQlyZXQgPSBkYTkxNTBfY2hhcmdlcl90
anVuY190ZW1wKGNoYXJnZXIsIHZhbCk7DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwlkZWZhdWx0Og0K
PiA+ICsJCXJldCA9IC1FSU5WQUw7DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwl9DQo+ID4gKw0KPiA+
ICsJcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArLyogQmF0dGVyeSBQcm9wZXJ0aWVz
ICovDQo+ID4gK3N0YXRpYyBpbnQgZGE5MTUwX2NoYXJnZXJfYmF0dGVyeV9zdGF0dXMoc3RydWN0
IGRhOTE1MF9jaGFyZ2VyICpjaGFyZ2VyLA0KPiA+ICsJCQkJCSB1bmlvbiBwb3dlcl9zdXBwbHlf
cHJvcHZhbCAqdmFsKQ0KPiA+ICt7DQo+ID4gKwl1OCByZWc7DQo+ID4gKw0KPiA+ICsJLyogQ2hl
Y2sgdG8gc2VlIGlmIGJhdHRlcnkgaXMgZGlzY2hhcmdpbmcgKi8NCj4gPiArCXJlZyA9IGRhOTE1
MF9yZWdfcmVhZChjaGFyZ2VyLT5kYTkxNTAsIERBOTE1MF9TVEFUVVNfSCk7DQo+ID4gKw0KPiA+
ICsJaWYgKCgocmVnICYgREE5MTUwX1ZCVVNfU1RBVF9NQVNLKSA9PSBEQTkxNTBfVkJVU19TVEFU
X09GRikgfHwNCj4gPiArCSAgICAoKHJlZyAmIERBOTE1MF9WQlVTX1NUQVRfTUFTSykgPT0gREE5
MTUwX1ZCVVNfU1RBVF9XQUlUKSkgew0KPiA+ICsJCXZhbC0+aW50dmFsID0gUE9XRVJfU1VQUExZ
X1NUQVRVU19ESVNDSEFSR0lORzsNCj4gPiArDQo+ID4gKwkJcmV0dXJuIDA7DQo+ID4gKwl9DQo+
ID4gKw0KPiA+ICsJcmVnID0gZGE5MTUwX3JlZ19yZWFkKGNoYXJnZXItPmRhOTE1MCwgREE5MTUw
X1NUQVRVU19KKTsNCj4gPiArDQo+ID4gKwkvKiBOb3cgY2hlY2sgZm9yIG90aGVyIHN0YXRlcyAq
Lw0KPiA+ICsJc3dpdGNoIChyZWcgJiBEQTkxNTBfQ0hHX1NUQVRfTUFTSykgew0KPiA+ICsJY2Fz
ZSBEQTkxNTBfQ0hHX1NUQVRfQUNUOg0KPiA+ICsJY2FzZSBEQTkxNTBfQ0hHX1NUQVRfUFJFOg0K
PiA+ICsJY2FzZSBEQTkxNTBfQ0hHX1NUQVRfQ0M6DQo+ID4gKwljYXNlIERBOTE1MF9DSEdfU1RB
VF9DVjoNCj4gPiArCQl2YWwtPmludHZhbCA9IFBPV0VSX1NVUFBMWV9TVEFUVVNfQ0hBUkdJTkc7
DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNlIERBOTE1MF9DSEdfU1RBVF9PRkY6DQo+ID4gKwlj
YXNlIERBOTE1MF9DSEdfU1RBVF9TVVNQOg0KPiA+ICsJY2FzZSBEQTkxNTBfQ0hHX1NUQVRfVEVN
UDoNCj4gPiArCWNhc2UgREE5MTUwX0NIR19TVEFUX1RJTUU6DQo+ID4gKwljYXNlIERBOTE1MF9D
SEdfU1RBVF9CQVQ6DQo+ID4gKwkJdmFsLT5pbnR2YWwgPSBQT1dFUl9TVVBQTFlfU1RBVFVTX05P
VF9DSEFSR0lORzsNCj4gPiArCQlicmVhazsNCj4gPiArCWNhc2UgREE5MTUwX0NIR19TVEFUX0ZV
TEw6DQo+ID4gKwkJdmFsLT5pbnR2YWwgPSBQT1dFUl9TVVBQTFlfU1RBVFVTX0ZVTEw7DQo+ID4g
KwkJYnJlYWs7DQo+ID4gKwlkZWZhdWx0Og0KPiA+ICsJCXZhbC0+aW50dmFsID0gUE9XRVJfU1VQ
UExZX1NUQVRVU19VTktOT1dOOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiAr
CXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGRhOTE1MF9jaGFyZ2Vy
X2JhdHRlcnlfaGVhbHRoKHN0cnVjdCBkYTkxNTBfY2hhcmdlciAqY2hhcmdlciwNCj4gPiArCQkJ
CQkgdW5pb24gcG93ZXJfc3VwcGx5X3Byb3B2YWwgKnZhbCkNCj4gPiArew0KPiA+ICsJdTggcmVn
Ow0KPiA+ICsNCj4gPiArCXJlZyA9IGRhOTE1MF9yZWdfcmVhZChjaGFyZ2VyLT5kYTkxNTAsIERB
OTE1MF9TVEFUVVNfSik7DQo+ID4gKw0KPiA+ICsJLyogQ2hlY2sgaWYgdGVtcGVyYXR1cmUgbGlt
aXQgcmVhY2hlZCAqLw0KPiA+ICsJc3dpdGNoIChyZWcgJiBEQTkxNTBfQ0hHX1RFTVBfTUFTSykg
ew0KPiA+ICsJY2FzZSBEQTkxNTBfQ0hHX1RFTVBfVU5ERVI6DQo+ID4gKwkJdmFsLT5pbnR2YWwg
PSBQT1dFUl9TVVBQTFlfSEVBTFRIX0NPTEQ7DQo+ID4gKwkJcmV0dXJuIDA7DQo+ID4gKwljYXNl
IERBOTE1MF9DSEdfVEVNUF9PVkVSOg0KPiA+ICsJCXZhbC0+aW50dmFsID0gUE9XRVJfU1VQUExZ
X0hFQUxUSF9PVkVSSEVBVDsNCj4gPiArCQlyZXR1cm4gMDsNCj4gPiArCWRlZmF1bHQ6DQo+ID4g
KwkJYnJlYWs7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJLyogQ2hlY2sgZm9yIG90aGVyIGhlYWx0
aCBzdGF0ZXMgKi8NCj4gPiArCXN3aXRjaCAocmVnICYgREE5MTUwX0NIR19TVEFUX01BU0spIHsN
Cj4gPiArCWNhc2UgREE5MTUwX0NIR19TVEFUX0FDVDoNCj4gPiArCWNhc2UgREE5MTUwX0NIR19T
VEFUX1BSRToNCj4gPiArCQl2YWwtPmludHZhbCA9IFBPV0VSX1NVUFBMWV9IRUFMVEhfREVBRDsN
Cj4gPiArCQlicmVhazsNCj4gPiArCWNhc2UgREE5MTUwX0NIR19TVEFUX1RJTUU6DQo+ID4gKwkJ
dmFsLT5pbnR2YWwgPSBQT1dFUl9TVVBQTFlfSEVBTFRIX1VOU1BFQ19GQUlMVVJFOw0KPiA+ICsJ
CWJyZWFrOw0KPiA+ICsJZGVmYXVsdDoNCj4gPiArCQl2YWwtPmludHZhbCA9IFBPV0VSX1NVUFBM
WV9IRUFMVEhfR09PRDsNCj4gPiArCQlicmVhazsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXR1
cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkYTkxNTBfY2hhcmdlcl9iYXR0
ZXJ5X3ByZXNlbnQoc3RydWN0IGRhOTE1MF9jaGFyZ2VyICpjaGFyZ2VyLA0KPiA+ICsJCQkJCSAg
dW5pb24gcG93ZXJfc3VwcGx5X3Byb3B2YWwgKnZhbCkNCj4gPiArew0KPiA+ICsJdTggcmVnOw0K
PiA+ICsNCj4gPiArCS8qIENoZWNrIGlmIGJhdHRlcnkgcHJlc2VudCBvciByZW1vdmVkICovDQo+
ID4gKwlyZWcgPSBkYTkxNTBfcmVnX3JlYWQoY2hhcmdlci0+ZGE5MTUwLCBEQTkxNTBfU1RBVFVT
X0opOw0KPiA+ICsJaWYgKChyZWcgJiBEQTkxNTBfQ0hHX1NUQVRfTUFTSykgPT0gREE5MTUwX0NI
R19TVEFUX0JBVCkNCj4gPiArCQl2YWwtPmludHZhbCA9IDA7DQo+ID4gKwllbHNlDQo+ID4gKwkJ
dmFsLT5pbnR2YWwgPSAxOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0K
PiA+ICtzdGF0aWMgaW50IGRhOTE1MF9jaGFyZ2VyX2JhdHRlcnlfY2hhcmdlX3R5cGUoc3RydWN0
IGRhOTE1MF9jaGFyZ2VyICpjaGFyZ2VyLA0KPiA+ICsJCQkJCSAgICAgIHVuaW9uIHBvd2VyX3N1
cHBseV9wcm9wdmFsICp2YWwpDQo+ID4gK3sNCj4gPiArCXU4IHJlZzsNCj4gPiArDQo+ID4gKwly
ZWcgPSBkYTkxNTBfcmVnX3JlYWQoY2hhcmdlci0+ZGE5MTUwLCBEQTkxNTBfU1RBVFVTX0opOw0K
PiA+ICsNCj4gPiArCXN3aXRjaCAocmVnICYgREE5MTUwX0NIR19TVEFUX01BU0spIHsNCj4gPiAr
CWNhc2UgREE5MTUwX0NIR19TVEFUX0NDOg0KPiA+ICsJCXZhbC0+aW50dmFsID0gUE9XRVJfU1VQ
UExZX0NIQVJHRV9UWVBFX0ZBU1Q7DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNlIERBOTE1MF9D
SEdfU1RBVF9BQ1Q6DQo+ID4gKwljYXNlIERBOTE1MF9DSEdfU1RBVF9QUkU6DQo+ID4gKwljYXNl
IERBOTE1MF9DSEdfU1RBVF9DVjoNCj4gPiArCQl2YWwtPmludHZhbCA9IFBPV0VSX1NVUFBMWV9D
SEFSR0VfVFlQRV9UUklDS0xFOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJZGVmYXVsdDoNCj4gPiAr
CQl2YWwtPmludHZhbCA9IFBPV0VSX1NVUFBMWV9DSEFSR0VfVFlQRV9OT05FOw0KPiA+ICsJCWJy
ZWFrOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+
ICtzdGF0aWMgaW50IGRhOTE1MF9jaGFyZ2VyX2JhdHRlcnlfdm9sdGFnZV9taW4oc3RydWN0IGRh
OTE1MF9jaGFyZ2VyICpjaGFyZ2VyLA0KPiA+ICsJCQkJCSAgICAgIHVuaW9uIHBvd2VyX3N1cHBs
eV9wcm9wdmFsICp2YWwpDQo+ID4gK3sNCj4gPiArCXU4IHJlZzsNCj4gPiArDQo+ID4gKwlyZWcg
PSBkYTkxNTBfcmVnX3JlYWQoY2hhcmdlci0+ZGE5MTUwLCBEQTkxNTBfUFBSX0NIR0NUUkxfQyk7
DQo+ID4gKw0KPiA+ICsJLyogVmFsdWUgc3RhcnRzIGF0IDI1MDAgbVYsIDUwIG1WIGluY3JlbWVu
dHMsIHByZXNlbnRlZCBpbiB1ViAqLw0KPiA+ICsJdmFsLT5pbnR2YWwgPSAoKHJlZyAmIERBOTE1
MF9DSEdfVkZBVUxUX01BU0spICogNTAwMDApICsgMjUwMDAwMDsNCj4gPiArDQo+ID4gKwlyZXR1
cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkYTkxNTBfY2hhcmdlcl9iYXR0
ZXJ5X3ZvbHRhZ2Vfbm93KHN0cnVjdCBkYTkxNTBfY2hhcmdlciAqY2hhcmdlciwNCj4gPiArCQkJ
CQkgICAgICB1bmlvbiBwb3dlcl9zdXBwbHlfcHJvcHZhbCAqdmFsKQ0KPiA+ICt7DQo+ID4gKwlp
bnQgdl92YWwsIHJldDsNCj4gPiArDQo+ID4gKwkvKiBSZWFkIHByb2Nlc3NlZCB2YWx1ZSAtIG1W
IHVuaXRzICovDQo+ID4gKwlyZXQgPSBpaW9fcmVhZF9jaGFubmVsX3Byb2Nlc3NlZChjaGFyZ2Vy
LT52YmF0X2NoYW4sICZ2X3ZhbCk7DQo+ID4gKwlpZiAocmV0IDwgMCkNCj4gPiArCQlyZXR1cm4g
cmV0Ow0KPiA+ICsNCj4gPiArCXZhbC0+aW50dmFsID0gdl92YWwgKiAxMDAwOw0KPiA+ICsNCj4g
PiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGRhOTE1MF9jaGFy
Z2VyX2JhdHRlcnlfY3VycmVudF9tYXgoc3RydWN0IGRhOTE1MF9jaGFyZ2VyICpjaGFyZ2VyLA0K
PiA+ICsJCQkJCSAgICAgIHVuaW9uIHBvd2VyX3N1cHBseV9wcm9wdmFsICp2YWwpDQo+ID4gK3sN
Cj4gPiArCWludCByZWc7DQo+ID4gKw0KPiA+ICsJcmVnID0gZGE5MTUwX3JlZ19yZWFkKGNoYXJn
ZXItPmRhOTE1MCwgREE5MTUwX1BQUl9DSEdDVFJMX0QpOw0KPiA+ICsNCj4gPiArCS8qIDI1bUEg
aW5jcmVtZW50cyAqLw0KPiA+ICsJdmFsLT5pbnR2YWwgPSByZWcgKiAyNTAwMDsNCj4gPiArDQo+
ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkYTkxNTBfY2hh
cmdlcl9iYXR0ZXJ5X3ZvbHRhZ2VfbWF4KHN0cnVjdCBkYTkxNTBfY2hhcmdlciAqY2hhcmdlciwN
Cj4gPiArCQkJCQkgICAgICB1bmlvbiBwb3dlcl9zdXBwbHlfcHJvcHZhbCAqdmFsKQ0KPiA+ICt7
DQo+ID4gKwl1OCByZWc7DQo+ID4gKw0KPiA+ICsJcmVnID0gZGE5MTUwX3JlZ19yZWFkKGNoYXJn
ZXItPmRhOTE1MCwgREE5MTUwX1BQUl9DSEdDVFJMX0IpOw0KPiA+ICsNCj4gPiArCS8qIFZhbHVl
IHN0YXJ0cyBhdCAzNjUwIG1WLCAyNSBtViBpbmNyZW1lbnRzLCBwcmVzZW50ZWQgaW4gdVYgKi8N
Cj4gPiArCXZhbC0+aW50dmFsID0gKChyZWcgJiBEQTkxNTBfQ0hHX1ZCQVRfTUFTSykgKiAyNTAw
MCkgKyAzNjUwMDAwOw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRp
YyBlbnVtIHBvd2VyX3N1cHBseV9wcm9wZXJ0eSBkYTkxNTBfY2hhcmdlcl9iYXRfcHJvcHNbXSA9
IHsNCj4gPiArCVBPV0VSX1NVUFBMWV9QUk9QX1NUQVRVUywNCj4gPiArCVBPV0VSX1NVUFBMWV9Q
Uk9QX09OTElORSwNCj4gPiArCVBPV0VSX1NVUFBMWV9QUk9QX0hFQUxUSCwNCj4gPiArCVBPV0VS
X1NVUFBMWV9QUk9QX1BSRVNFTlQsDQo+ID4gKwlQT1dFUl9TVVBQTFlfUFJPUF9DSEFSR0VfVFlQ
RSwNCj4gPiArCVBPV0VSX1NVUFBMWV9QUk9QX1ZPTFRBR0VfTUlOX0RFU0lHTiwNCj4gPiArCVBP
V0VSX1NVUFBMWV9QUk9QX1ZPTFRBR0VfTk9XLA0KPiA+ICsJUE9XRVJfU1VQUExZX1BST1BfQ09O
U1RBTlRfQ0hBUkdFX0NVUlJFTlRfTUFYLA0KPiA+ICsJUE9XRVJfU1VQUExZX1BST1BfQ09OU1RB
TlRfQ0hBUkdFX1ZPTFRBR0VfTUFYLA0KPiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIGludCBk
YTkxNTBfY2hhcmdlcl9iYXR0ZXJ5X2dldF9wcm9wKHN0cnVjdCBwb3dlcl9zdXBwbHkgKnBzeSwN
Cj4gPiArCQkJCQkgICBlbnVtIHBvd2VyX3N1cHBseV9wcm9wZXJ0eSBwc3AsDQo+ID4gKwkJCQkJ
ICAgdW5pb24gcG93ZXJfc3VwcGx5X3Byb3B2YWwgKnZhbCkNCj4gPiArew0KPiA+ICsJc3RydWN0
IGRhOTE1MF9jaGFyZ2VyICpjaGFyZ2VyID0gZGV2X2dldF9kcnZkYXRhKHBzeS0+ZGV2LT5wYXJl
bnQpOw0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwlzd2l0Y2ggKHBzcCkgew0KPiA+ICsJ
Y2FzZSBQT1dFUl9TVVBQTFlfUFJPUF9TVEFUVVM6DQo+ID4gKwkJcmV0ID0gZGE5MTUwX2NoYXJn
ZXJfYmF0dGVyeV9zdGF0dXMoY2hhcmdlciwgdmFsKTsNCj4gPiArCQlicmVhazsNCj4gPiArCWNh
c2UgUE9XRVJfU1VQUExZX1BST1BfT05MSU5FOg0KPiA+ICsJCXJldCA9IGRhOTE1MF9jaGFyZ2Vy
X3N1cHBseV9vbmxpbmUoY2hhcmdlciwgcHN5LCB2YWwpOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJ
Y2FzZSBQT1dFUl9TVVBQTFlfUFJPUF9IRUFMVEg6DQo+ID4gKwkJcmV0ID0gZGE5MTUwX2NoYXJn
ZXJfYmF0dGVyeV9oZWFsdGgoY2hhcmdlciwgdmFsKTsNCj4gPiArCQlicmVhazsNCj4gPiArCWNh
c2UgUE9XRVJfU1VQUExZX1BST1BfUFJFU0VOVDoNCj4gPiArCQlyZXQgPSBkYTkxNTBfY2hhcmdl
cl9iYXR0ZXJ5X3ByZXNlbnQoY2hhcmdlciwgdmFsKTsNCj4gPiArCQlicmVhazsNCj4gPiArCWNh
c2UgUE9XRVJfU1VQUExZX1BST1BfQ0hBUkdFX1RZUEU6DQo+ID4gKwkJcmV0ID0gZGE5MTUwX2No
YXJnZXJfYmF0dGVyeV9jaGFyZ2VfdHlwZShjaGFyZ2VyLCB2YWwpOw0KPiA+ICsJCWJyZWFrOw0K
PiA+ICsJY2FzZSBQT1dFUl9TVVBQTFlfUFJPUF9WT0xUQUdFX01JTl9ERVNJR046DQo+ID4gKwkJ
cmV0ID0gZGE5MTUwX2NoYXJnZXJfYmF0dGVyeV92b2x0YWdlX21pbihjaGFyZ2VyLCB2YWwpOw0K
PiA+ICsJCWJyZWFrOw0KPiA+ICsJY2FzZSBQT1dFUl9TVVBQTFlfUFJPUF9WT0xUQUdFX05PVzoN
Cj4gPiArCQlyZXQgPSBkYTkxNTBfY2hhcmdlcl9iYXR0ZXJ5X3ZvbHRhZ2Vfbm93KGNoYXJnZXIs
IHZhbCk7DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNlIFBPV0VSX1NVUFBMWV9QUk9QX0NPTlNU
QU5UX0NIQVJHRV9DVVJSRU5UX01BWDoNCj4gPiArCQlyZXQgPSBkYTkxNTBfY2hhcmdlcl9iYXR0
ZXJ5X2N1cnJlbnRfbWF4KGNoYXJnZXIsIHZhbCk7DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwljYXNl
IFBPV0VSX1NVUFBMWV9QUk9QX0NPTlNUQU5UX0NIQVJHRV9WT0xUQUdFX01BWDoNCj4gPiArCQly
ZXQgPSBkYTkxNTBfY2hhcmdlcl9iYXR0ZXJ5X3ZvbHRhZ2VfbWF4KGNoYXJnZXIsIHZhbCk7DQo+
ID4gKwkJYnJlYWs7DQo+ID4gKwlkZWZhdWx0Og0KPiA+ICsJCXJldCA9IC1FSU5WQUw7DQo+ID4g
KwkJYnJlYWs7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIHJldDsNCj4gPiArfQ0KPiA+
ICsNCj4gPiArc3RhdGljIGlycXJldHVybl90IGRhOTE1MF9jaGFyZ2VyX2NoZ19pcnEoaW50IGly
cSwgdm9pZCAqZGF0YSkNCj4gPiArew0KPiA+ICsJc3RydWN0IGRhOTE1MF9jaGFyZ2VyICpjaGFy
Z2VyID0gZGF0YTsNCj4gPiArDQo+ID4gKwlwb3dlcl9zdXBwbHlfY2hhbmdlZCgmY2hhcmdlci0+
YmF0dGVyeSk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIElSUV9IQU5ETEVEOw0KPiA+ICt9DQo+ID4g
Kw0KPiA+ICtzdGF0aWMgaXJxcmV0dXJuX3QgZGE5MTUwX2NoYXJnZXJfdGp1bmNfaXJxKGludCBp
cnEsIHZvaWQgKmRhdGEpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBkYTkxNTBfY2hhcmdlciAqY2hh
cmdlciA9IGRhdGE7DQo+ID4gKw0KPiA+ICsJLyogTm90aGluZyB3ZSBjYW4gcmVhbGx5IGRvIGV4
Y2VwdCByZXBvcnQgdGhpcy4gKi8NCj4gPiArCWRldl9jcml0KGNoYXJnZXItPmRldiwgIlRKdW5j
IG92ZXIgdGVtcGVyYXR1cmUhISFcbiIpOw0KPiA+ICsJcG93ZXJfc3VwcGx5X2NoYW5nZWQoJmNo
YXJnZXItPnVzYik7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIElSUV9IQU5ETEVEOw0KPiA+ICt9DQo+
ID4gKw0KPiA+ICtzdGF0aWMgaXJxcmV0dXJuX3QgZGE5MTUwX2NoYXJnZXJfdmZhdWx0X2lycShp
bnQgaXJxLCB2b2lkICpkYXRhKQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3QgZGE5MTUwX2NoYXJnZXIg
KmNoYXJnZXIgPSBkYXRhOw0KPiA+ICsNCj4gPiArCS8qIE5vdGhpbmcgd2UgY2FuIHJlYWxseSBk
byBleGNlcHQgcmVwb3J0IHRoaXMuICovDQo+ID4gKwlkZXZfY3JpdChjaGFyZ2VyLT5kZXYsICJW
U1lTIHVuZGVyIHZvbHRhZ2UhISFcbiIpOw0KPiA+ICsJcG93ZXJfc3VwcGx5X2NoYW5nZWQoJmNo
YXJnZXItPnVzYik7DQo+ID4gKwlwb3dlcl9zdXBwbHlfY2hhbmdlZCgmY2hhcmdlci0+YmF0dGVy
eSk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIElSUV9IQU5ETEVEOw0KPiA+ICt9DQo+ID4gKw0KPiA+
ICtzdGF0aWMgaXJxcmV0dXJuX3QgZGE5MTUwX2NoYXJnZXJfdmJ1c19pcnEoaW50IGlycSwgdm9p
ZCAqZGF0YSkNCj4gPiArew0KPiA+ICsJc3RydWN0IGRhOTE1MF9jaGFyZ2VyICpjaGFyZ2VyID0g
ZGF0YTsNCj4gPiArCXU4IHJlZzsNCj4gPiArDQo+ID4gKwlyZWcgPSBkYTkxNTBfcmVnX3JlYWQo
Y2hhcmdlci0+ZGE5MTUwLCBEQTkxNTBfU1RBVFVTX0gpOw0KPiA+ICsNCj4gPiArCS8qIENoYXJn
ZXIgcGx1Z2dlZCBpbiBvciBiYXR0ZXJ5IG9ubHkgKi8NCj4gPiArCXN3aXRjaCAocmVnICYgREE5
MTUwX1ZCVVNfU1RBVF9NQVNLKSB7DQo+ID4gKwljYXNlIERBOTE1MF9WQlVTX1NUQVRfT0ZGOg0K
PiA+ICsJY2FzZSBEQTkxNTBfVkJVU19TVEFUX1dBSVQ6DQo+ID4gKwkJY2hhcmdlci0+c3VwcGx5
X29ubGluZSA9ICZjaGFyZ2VyLT5iYXR0ZXJ5Ow0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJY2FzZSBE
QTkxNTBfVkJVU19TVEFUX0NIRzoNCj4gPiArCQljaGFyZ2VyLT5zdXBwbHlfb25saW5lID0gJmNo
YXJnZXItPnVzYjsNCj4gPiArCQlicmVhazsNCj4gPiArCWRlZmF1bHQ6DQo+ID4gKwkJZGV2X3dh
cm4oY2hhcmdlci0+ZGV2LCAiVW5rbm93biBWQlVTIHN0YXRlIC0gcmVnID0gMHgleFxuIiwNCj4g
PiArCQkJIHJlZyk7DQo+ID4gKwkJY2hhcmdlci0+c3VwcGx5X29ubGluZSA9IE5VTEw7DQo+ID4g
KwkJYnJlYWs7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcG93ZXJfc3VwcGx5X2NoYW5nZWQoJmNo
YXJnZXItPnVzYik7DQo+ID4gKwlwb3dlcl9zdXBwbHlfY2hhbmdlZCgmY2hhcmdlci0+YmF0dGVy
eSk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIElSUV9IQU5ETEVEOw0KPiA+ICt9DQo+ID4gKw0KPiA+
ICtzdGF0aWMgdm9pZCBkYTkxNTBfY2hhcmdlcl9vdGdfd29yayhzdHJ1Y3Qgd29ya19zdHJ1Y3Qg
KmRhdGEpDQo+ID4gK3sNCj4gPiArCXN0cnVjdCBkYTkxNTBfY2hhcmdlciAqY2hhcmdlciA9DQo+
ID4gKwkJY29udGFpbmVyX29mKGRhdGEsIHN0cnVjdCBkYTkxNTBfY2hhcmdlciwgb3RnX3dvcmsp
Ow0KPiA+ICsNCj4gPiArCXN3aXRjaCAoY2hhcmdlci0+dXNiX2V2ZW50KSB7DQo+ID4gKwljYXNl
IFVTQl9FVkVOVF9JRDoNCj4gPiArCQkvKiBFbmFibGUgT1RHIEJvb3N0ICovDQo+ID4gKwkJZGE5
MTUwX3NldF9iaXRzKGNoYXJnZXItPmRhOTE1MCwgREE5MTUwX1BQUl9CS0NUUkxfQSwNCj4gPiAr
CQkJCURBOTE1MF9WQlVTX01PREVfTUFTSywNCj4gREE5MTUwX1ZCVVNfTU9ERV9PVEcpOw0KPiA+
ICsJCWJyZWFrOw0KPiA+ICsJY2FzZSBVU0JfRVZFTlRfTk9ORToNCj4gPiArCQkvKiBSZXZlcnQg
dG8gY2hhcmdlIG1vZGUgKi8NCj4gPiArCQlwb3dlcl9zdXBwbHlfY2hhbmdlZCgmY2hhcmdlci0+
dXNiKTsNCj4gPiArCQlwb3dlcl9zdXBwbHlfY2hhbmdlZCgmY2hhcmdlci0+YmF0dGVyeSk7DQo+
ID4gKwkJZGE5MTUwX3NldF9iaXRzKGNoYXJnZXItPmRhOTE1MCwgREE5MTUwX1BQUl9CS0NUUkxf
QSwNCj4gPiArCQkJCURBOTE1MF9WQlVTX01PREVfTUFTSywNCj4gREE5MTUwX1ZCVVNfTU9ERV9D
SEcpOw0KPiA+ICsJCWJyZWFrOw0KPiA+ICsJfQ0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMg
aW50IGRhOTE1MF9jaGFyZ2VyX290Z19uY2Ioc3RydWN0IG5vdGlmaWVyX2Jsb2NrICpuYiwgdW5z
aWduZWQgbG9uZyB2YWwsDQo+ID4gKwkJCQkgIHZvaWQgKnByaXYpDQo+ID4gK3sNCj4gPiArCXN0
cnVjdCBkYTkxNTBfY2hhcmdlciAqY2hhcmdlciA9DQo+ID4gKwkJY29udGFpbmVyX29mKG5iLCBz
dHJ1Y3QgZGE5MTUwX2NoYXJnZXIsIG90Z19uYik7DQo+ID4gKw0KPiA+ICsJZGV2X2RiZyhjaGFy
Z2VyLT5kZXYsICJEQTkxNTAgT1RHIG5vdGlmeSAlbHVcbiIsIHZhbCk7DQo+ID4gKw0KPiA+ICsJ
Y2hhcmdlci0+dXNiX2V2ZW50ID0gdmFsOw0KPiA+ICsJc2NoZWR1bGVfd29yaygmY2hhcmdlci0+
b3RnX3dvcmspOw0KPiA+ICsNCj4gPiArCXJldHVybiBOT1RJRllfT0s7DQo+ID4gK30NCj4gPiAr
DQo+ID4gK3N0YXRpYyBpbnQgZGE5MTUwX2NoYXJnZXJfcmVnaXN0ZXJfaXJxKHN0cnVjdCBwbGF0
Zm9ybV9kZXZpY2UgKnBkZXYsDQo+ID4gKwkJCQkgICAgICAgaXJxX2hhbmRsZXJfdCBoYW5kbGVy
LA0KPiA+ICsJCQkJICAgICAgIGNvbnN0IGNoYXIgKmlycV9uYW1lKQ0KPiA+ICt7DQo+ID4gKwlz
dHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2Ow0KPiA+ICsJc3RydWN0IGRhOTE1MF9jaGFy
Z2VyICpjaGFyZ2VyID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7DQo+ID4gKwlpbnQgaXJx
LCByZXQ7DQo+ID4gKw0KPiA+ICsJaXJxID0gcGxhdGZvcm1fZ2V0X2lycV9ieW5hbWUocGRldiwg
aXJxX25hbWUpOw0KPiA+ICsJaWYgKGlycSA8IDApIHsNCj4gPiArCQlkZXZfZXJyKGRldiwgIkZh
aWxlZCB0byBnZXQgSVJRIENIR19TVEFUVVM6ICVkXG4iLCBpcnEpOw0KPiA+ICsJCXJldHVybiBp
cnE7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0ID0gZGV2bV9yZXF1ZXN0X3RocmVhZGVkX2ly
cShkZXYsIGlycSwgTlVMTCwgaGFuZGxlciwgSVJRRl9PTkVTSE9ULA0KPiA+ICsJCQkJCWlycV9u
YW1lLCBjaGFyZ2VyKTsNCj4gPiArCWlmIChyZXQpDQo+ID4gKwkJZGV2X2VycihkZXYsICJGYWls
ZWQgdG8gcmVxdWVzdCBJUlEgJWQ6ICVkXG4iLCBpcnEsIHJldCk7DQo+ID4gKw0KPiA+ICsJcmV0
dXJuIHJldDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBkYTkxNTBfY2hhcmdlcl9w
cm9iZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQ0KPiA+ICt7DQo+ID4gKwlzdHJ1Y3Qg
ZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2Ow0KPiA+ICsJc3RydWN0IGRhOTE1MCAqZGE5MTUwID0g
ZGV2X2dldF9kcnZkYXRhKGRldi0+cGFyZW50KTsNCj4gPiArCXN0cnVjdCBkYTkxNTBfY2hhcmdl
ciAqY2hhcmdlcjsNCj4gPiArCXN0cnVjdCBwb3dlcl9zdXBwbHkgKnVzYiwgKmJhdHRlcnk7DQo+
ID4gKwl1OCByZWc7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCWNoYXJnZXIgPSBkZXZt
X2t6YWxsb2MoZGV2LCBzaXplb2Yoc3RydWN0IGRhOTE1MF9jaGFyZ2VyKSwgR0ZQX0tFUk5FTCk7
DQo+ID4gKwlpZiAoY2hhcmdlciA9PSBOVUxMKQ0KPiA+ICsJCXJldHVybiAtRU5PTUVNOw0KPiA+
ICsNCj4gPiArCXBsYXRmb3JtX3NldF9kcnZkYXRhKHBkZXYsIGNoYXJnZXIpOw0KPiA+ICsJY2hh
cmdlci0+ZGE5MTUwID0gZGE5MTUwOw0KPiA+ICsJY2hhcmdlci0+ZGV2ID0gZGV2Ow0KPiA+ICsN
Cj4gPiArCS8qIEFjcXVpcmUgQURDIGNoYW5uZWxzICovDQo+ID4gKwljaGFyZ2VyLT5pYnVzX2No
YW4gPSBpaW9fY2hhbm5lbF9nZXQoZGV2LCAiQ0hBTl9JQlVTIik7DQo+ID4gKwlpZiAoSVNfRVJS
KGNoYXJnZXItPmlidXNfY2hhbikpIHsNCj4gPiArCQlyZXQgPSBQVFJfRVJSKGNoYXJnZXItPmli
dXNfY2hhbik7DQo+ID4gKwkJZ290byBpYnVzX2NoYW5fZmFpbDsNCj4gPiArCX0NCj4gPiArDQo+
ID4gKwljaGFyZ2VyLT52YnVzX2NoYW4gPSBpaW9fY2hhbm5lbF9nZXQoZGV2LCAiQ0hBTl9WQlVT
Iik7DQo+ID4gKwlpZiAoSVNfRVJSKGNoYXJnZXItPnZidXNfY2hhbikpIHsNCj4gPiArCQlyZXQg
PSBQVFJfRVJSKGNoYXJnZXItPnZidXNfY2hhbik7DQo+ID4gKwkJZ290byB2YnVzX2NoYW5fZmFp
bDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwljaGFyZ2VyLT50anVuY19jaGFuID0gaWlvX2NoYW5u
ZWxfZ2V0KGRldiwgIkNIQU5fVEpVTkMiKTsNCj4gPiArCWlmIChJU19FUlIoY2hhcmdlci0+dGp1
bmNfY2hhbikpIHsNCj4gPiArCQlyZXQgPSBQVFJfRVJSKGNoYXJnZXItPnRqdW5jX2NoYW4pOw0K
PiA+ICsJCWdvdG8gdGp1bmNfY2hhbl9mYWlsOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCWNoYXJn
ZXItPnZiYXRfY2hhbiA9IGlpb19jaGFubmVsX2dldChkZXYsICJDSEFOX1ZCQVQiKTsNCj4gPiAr
CWlmIChJU19FUlIoY2hhcmdlci0+dmJhdF9jaGFuKSkgew0KPiA+ICsJCXJldCA9IFBUUl9FUlIo
Y2hhcmdlci0+dmJhdF9jaGFuKTsNCj4gPiArCQlnb3RvIHZiYXRfY2hhbl9mYWlsOw0KPiA+ICsJ
fQ0KPiA+ICsNCj4gPiArCS8qIFJlZ2lzdGVyIHBvd2VyIHN1cHBsaWVzICovDQo+ID4gKwl1c2Ig
PSAmY2hhcmdlci0+dXNiOw0KPiA+ICsJYmF0dGVyeSA9ICZjaGFyZ2VyLT5iYXR0ZXJ5Ow0KPiA+
ICsNCj4gPiArCXVzYi0+bmFtZSA9ICJkYTkxNTAtdXNiIiwNCj4gPiArCXVzYi0+dHlwZSA9IFBP
V0VSX1NVUFBMWV9UWVBFX1VTQjsNCj4gPiArCXVzYi0+cHJvcGVydGllcyA9IGRhOTE1MF9jaGFy
Z2VyX3Byb3BzOw0KPiA+ICsJdXNiLT5udW1fcHJvcGVydGllcyA9IEFSUkFZX1NJWkUoZGE5MTUw
X2NoYXJnZXJfcHJvcHMpOw0KPiA+ICsJdXNiLT5nZXRfcHJvcGVydHkgPSBkYTkxNTBfY2hhcmdl
cl9nZXRfcHJvcDsNCj4gPiArCXJldCA9IHBvd2VyX3N1cHBseV9yZWdpc3RlcihkZXYsIHVzYik7
DQo+ID4gKwlpZiAocmV0KQ0KPiA+ICsJCWdvdG8gdXNiX2ZhaWw7DQo+ID4gKw0KPiA+ICsJYmF0
dGVyeS0+bmFtZSA9ICJkYTkxNTAtYmF0dGVyeSI7DQo+ID4gKwliYXR0ZXJ5LT50eXBlID0gUE9X
RVJfU1VQUExZX1RZUEVfQkFUVEVSWTsNCj4gPiArCWJhdHRlcnktPnByb3BlcnRpZXMgPSBkYTkx
NTBfY2hhcmdlcl9iYXRfcHJvcHM7DQo+ID4gKwliYXR0ZXJ5LT5udW1fcHJvcGVydGllcyA9IEFS
UkFZX1NJWkUoZGE5MTUwX2NoYXJnZXJfYmF0X3Byb3BzKTsNCj4gPiArCWJhdHRlcnktPmdldF9w
cm9wZXJ0eSA9IGRhOTE1MF9jaGFyZ2VyX2JhdHRlcnlfZ2V0X3Byb3A7DQo+ID4gKwlyZXQgPSBw
b3dlcl9zdXBwbHlfcmVnaXN0ZXIoZGV2LCBiYXR0ZXJ5KTsNCj4gPiArCWlmIChyZXQpDQo+ID4g
KwkJZ290byBiYXR0ZXJ5X2ZhaWw7DQo+ID4gKw0KPiA+ICsJLyogR2V0IGluaXRpYWwgb25saW5l
IHN1cHBseSAqLw0KPiA+ICsJcmVnID0gZGE5MTUwX3JlZ19yZWFkKGRhOTE1MCwgREE5MTUwX1NU
QVRVU19IKTsNCj4gPiArDQo+ID4gKwlzd2l0Y2ggKHJlZyAmIERBOTE1MF9WQlVTX1NUQVRfTUFT
Sykgew0KPiA+ICsJY2FzZSBEQTkxNTBfVkJVU19TVEFUX09GRjoNCj4gPiArCWNhc2UgREE5MTUw
X1ZCVVNfU1RBVF9XQUlUOg0KPiA+ICsJCWNoYXJnZXItPnN1cHBseV9vbmxpbmUgPSAmY2hhcmdl
ci0+YmF0dGVyeTsNCj4gPiArCQlicmVhazsNCj4gPiArCWNhc2UgREE5MTUwX1ZCVVNfU1RBVF9D
SEc6DQo+ID4gKwkJY2hhcmdlci0+c3VwcGx5X29ubGluZSA9ICZjaGFyZ2VyLT51c2I7DQo+ID4g
KwkJYnJlYWs7DQo+ID4gKwlkZWZhdWx0Og0KPiA+ICsJCWRldl93YXJuKGRldiwgIlVua25vd24g
VkJVUyBzdGF0ZSAtIHJlZyA9IDB4JXhcbiIsIHJlZyk7DQo+ID4gKwkJY2hhcmdlci0+c3VwcGx5
X29ubGluZSA9IE5VTEw7DQo+ID4gKwkJYnJlYWs7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJLyog
U2V0dXAgT1RHIHJlcG9ydGluZyAmIGNvbmZpZ3VyYXRpb24gKi8NCj4gPiArCWNoYXJnZXItPnVz
Yl9waHkgPSBkZXZtX3VzYl9nZXRfcGh5KGRldiwgVVNCX1BIWV9UWVBFX1VTQjIpOw0KPiA+ICsJ
aWYgKCFJU19FUlJfT1JfTlVMTChjaGFyZ2VyLT51c2JfcGh5KSkgew0KPiA+ICsJCUlOSVRfV09S
SygmY2hhcmdlci0+b3RnX3dvcmssIGRhOTE1MF9jaGFyZ2VyX290Z193b3JrKTsNCj4gPiArCQlj
aGFyZ2VyLT5vdGdfbmIubm90aWZpZXJfY2FsbCA9IGRhOTE1MF9jaGFyZ2VyX290Z19uY2I7DQo+
ID4gKwkJdXNiX3JlZ2lzdGVyX25vdGlmaWVyKGNoYXJnZXItPnVzYl9waHksICZjaGFyZ2VyLT5v
dGdfbmIpOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCS8qIFJlZ2lzdGVyIElSUXMgKi8NCj4gPiAr
CXJldCA9IGRhOTE1MF9jaGFyZ2VyX3JlZ2lzdGVyX2lycShwZGV2LCBkYTkxNTBfY2hhcmdlcl9j
aGdfaXJxLA0KPiA+ICsJCQkJCSAgIkNIR19TVEFUVVMiKTsNCj4gPiArCWlmIChyZXQgPCAwKQ0K
PiA+ICsJCWdvdG8gaXJxX2ZhaWw7DQo+ID4gKw0KPiA+ICsJcmV0ID0gZGE5MTUwX2NoYXJnZXJf
cmVnaXN0ZXJfaXJxKHBkZXYsIGRhOTE1MF9jaGFyZ2VyX3RqdW5jX2lycSwNCj4gPiArCQkJCQkg
ICJDSEdfVEpVTkMiKTsNCj4gPiArCWlmIChyZXQgPCAwKQ0KPiA+ICsJCWdvdG8gaXJxX2ZhaWw7
DQo+ID4gKw0KPiA+ICsJcmV0ID0gZGE5MTUwX2NoYXJnZXJfcmVnaXN0ZXJfaXJxKHBkZXYsIGRh
OTE1MF9jaGFyZ2VyX3ZmYXVsdF9pcnEsDQo+ID4gKwkJCQkJICAiQ0hHX1ZGQVVMVCIpOw0KPiA+
ICsJaWYgKHJldCA8IDApDQo+ID4gKwkJZ290byBpcnFfZmFpbDsNCj4gPiArDQo+ID4gKwlyZXQg
PSBkYTkxNTBfY2hhcmdlcl9yZWdpc3Rlcl9pcnEocGRldiwgZGE5MTUwX2NoYXJnZXJfdmJ1c19p
cnEsDQo+ID4gKwkJCQkJICAiQ0hHX1ZCVVMiKTsNCj4gPiArCWlmIChyZXQgPCAwKQ0KPiA+ICsJ
CWdvdG8gaXJxX2ZhaWw7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gKw0KPiA+ICtpcnFf
ZmFpbDoNCj4gPiArCWlmICghSVNfRVJSX09SX05VTEwoY2hhcmdlci0+dXNiX3BoeSkpDQo+ID4g
KwkJdXNiX3VucmVnaXN0ZXJfbm90aWZpZXIoY2hhcmdlci0+dXNiX3BoeSwgJmNoYXJnZXItPm90
Z19uYik7DQo+ID4gK2JhdHRlcnlfZmFpbDoNCj4gPiArCXBvd2VyX3N1cHBseV91bnJlZ2lzdGVy
KHVzYik7DQo+ID4gKw0KPiA+ICt1c2JfZmFpbDoNCj4gPiArCWlpb19jaGFubmVsX3JlbGVhc2Uo
Y2hhcmdlci0+dmJhdF9jaGFuKTsNCj4gPiArDQo+ID4gK3ZiYXRfY2hhbl9mYWlsOg0KPiA+ICsJ
aWlvX2NoYW5uZWxfcmVsZWFzZShjaGFyZ2VyLT50anVuY19jaGFuKTsNCj4gPiArDQo+ID4gK3Rq
dW5jX2NoYW5fZmFpbDoNCj4gPiArCWlpb19jaGFubmVsX3JlbGVhc2UoY2hhcmdlci0+dmJ1c19j
aGFuKTsNCj4gPiArDQo+ID4gK3ZidXNfY2hhbl9mYWlsOg0KPiA+ICsJaWlvX2NoYW5uZWxfcmVs
ZWFzZShjaGFyZ2VyLT5pYnVzX2NoYW4pOw0KPiA+ICsNCj4gPiAraWJ1c19jaGFuX2ZhaWw6DQo+
ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGRhOTE1MF9j
aGFyZ2VyX3JlbW92ZShzdHJ1Y3QgcGxhdGZvcm1fZGV2aWNlICpwZGV2KQ0KPiA+ICt7DQo+ID4g
KwlzdHJ1Y3QgZGV2aWNlICpkZXYgPSAmcGRldi0+ZGV2Ow0KPiA+ICsJc3RydWN0IGRhOTE1MF9j
aGFyZ2VyICpjaGFyZ2VyID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7DQo+ID4gKwlpbnQg
aXJxOw0KPiA+ICsNCj4gPiArCS8qIE1ha2Ugc3VyZSBJUlFzIGFyZSByZWxlYXNlZCBiZWZvcmUg
dW5yZWdpc3RlcmluZyBwb3dlciBzdXBwbGllcyAqLw0KPiA+ICsJaXJxID0gcGxhdGZvcm1fZ2V0
X2lycV9ieW5hbWUocGRldiwgIkNIR19WQlVTIik7DQo+ID4gKwlkZXZtX2ZyZWVfaXJxKGRldiwg
aXJxLCBjaGFyZ2VyKTsNCj4gPiArDQo+ID4gKwlpcnEgPSBwbGF0Zm9ybV9nZXRfaXJxX2J5bmFt
ZShwZGV2LCAiQ0hHX1ZGQVVMVCIpOw0KPiA+ICsJZGV2bV9mcmVlX2lycShkZXYsIGlycSwgY2hh
cmdlcik7DQo+ID4gKw0KPiA+ICsJaXJxID0gcGxhdGZvcm1fZ2V0X2lycV9ieW5hbWUocGRldiwg
IkNIR19USlVOQyIpOw0KPiA+ICsJZGV2bV9mcmVlX2lycShkZXYsIGlycSwgY2hhcmdlcik7DQo+
ID4gKw0KPiA+ICsJaXJxID0gcGxhdGZvcm1fZ2V0X2lycV9ieW5hbWUocGRldiwgIkNIR19TVEFU
VVMiKTsNCj4gPiArCWRldm1fZnJlZV9pcnEoZGV2LCBpcnEsIGNoYXJnZXIpOw0KPiBJZiB5b3Ug
aGF2ZSB1c2VkIGEgZGV2bSBhbGxvY2F0aW9uLCB5b3UgZ2VuZXJhbGx5IGRvbid0IG5lZWQgdG8N
Cj4gZnJlZSB0aGVtIGV4cGxpY2l0bHkuIFRoYXQgd2lsbCBoYXBwZW4gd2hlbiB0aGUgZGV2aWNl
IGlzIGZyZWVkLg0KPiANCj4gSWYgeW91IGRvIG5lZWQgdG8gZnJlZSB0aGVtIGhlcmUgKHRvIG1h
aW50YWluIG9yZGVyaW5nIGV0YykgdGhlbiB5b3UNCj4gZG9uJ3Qgd2FudCB0byBiZSB1c2luZyB0
aGUgZGV2bSBpbnRlcmZhY2VzIGluIHRoZSBmaXJzdCBwbGFjZS4NCg0KVGhlIG9yZGVyaW5nIG9u
IHJlbGVhc2UgaXMgaW1wb3J0YW50IGFzIHBvd2VyX3N1cHBseV9jaGFuZ2VkKCkgaXMgY2FsbGVk
IGJ5IElSUQ0KdGhyZWFkIGZ1bmN0aW9ucywgc28gdGhlIElSUXMgbmVlZCByZWxlYXNpbmcgZmly
c3QgYmVmb3JlIHVucmVnaXN0ZXJpbmcgcG93ZXINCnN1cHBseSBjbGFzc2VzLiBUaGUgb3JpZ2lu
YWwgaW50ZW50aW9uIHdpdGggdXNpbmcgZGV2bSBoZXJlIHdhcyB0byBrZWVwIHRoZQ0KY2xlYW51
cCBvbiBmYWlsdXJlIHNpbXBsZSBmb3IgdGhlIHByb2JlIGZ1bmN0aW9uIHdpdGggcmVnYXJkcyB0
byBJUlFzLCBidXQNCmxvb2tpbmcgYXQgaXQgYWdhaW4gdGhhdCdzIG5vdCBnb2luZyB0byB3b3Jr
IHNvIEkgbmVlZCB0byBkcm9wIGJhY2sgdG8gdGhlDQpub24gZGV2bV8qIHZlcnNpb25zIGluc3Rl
YWQuIFRoYW5rcyBmb3IgcG9pbnRpbmcgdG8gaXQuDQoNCj4gPiArDQo+ID4gKwlpZiAoIUlTX0VS
Ul9PUl9OVUxMKGNoYXJnZXItPnVzYl9waHkpKQ0KPiA+ICsJCXVzYl91bnJlZ2lzdGVyX25vdGlm
aWVyKGNoYXJnZXItPnVzYl9waHksICZjaGFyZ2VyLT5vdGdfbmIpOw0KPiA+ICsNCj4gPiArCXBv
d2VyX3N1cHBseV91bnJlZ2lzdGVyKCZjaGFyZ2VyLT5iYXR0ZXJ5KTsNCj4gPiArCXBvd2VyX3N1
cHBseV91bnJlZ2lzdGVyKCZjaGFyZ2VyLT51c2IpOw0KPiA+ICsNCj4gPiArCS8qIFJlbGVhc2Ug
QURDIGNoYW5uZWxzICovDQo+ID4gKwlpaW9fY2hhbm5lbF9yZWxlYXNlKGNoYXJnZXItPmlidXNf
Y2hhbik7DQo+ID4gKwlpaW9fY2hhbm5lbF9yZWxlYXNlKGNoYXJnZXItPnZidXNfY2hhbik7DQo+
ID4gKwlpaW9fY2hhbm5lbF9yZWxlYXNlKGNoYXJnZXItPnRqdW5jX2NoYW4pOw0KPiA+ICsJaWlv
X2NoYW5uZWxfcmVsZWFzZShjaGFyZ2VyLT52YmF0X2NoYW4pOw0KPiA+ICsNCj4gPiArCXJldHVy
biAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgc3RydWN0IHBsYXRmb3JtX2RyaXZlciBk
YTkxNTBfY2hhcmdlcl9kcml2ZXIgPSB7DQo+ID4gKwkuZHJpdmVyID0gew0KPiA+ICsJCS5uYW1l
ID0gImRhOTE1MC1jaGFyZ2VyIiwNCj4gPiArCX0sDQo+ID4gKwkucHJvYmUgPSBkYTkxNTBfY2hh
cmdlcl9wcm9iZSwNCj4gPiArCS5yZW1vdmUgPSBkYTkxNTBfY2hhcmdlcl9yZW1vdmUsDQo+ID4g
K307DQo+ID4gKw0KPiA+ICttb2R1bGVfcGxhdGZvcm1fZHJpdmVyKGRhOTE1MF9jaGFyZ2VyX2Ry
aXZlcik7DQo+ID4gKw0KPiA+ICtNT0RVTEVfREVTQ1JJUFRJT04oIkNoYXJnZXIgRHJpdmVyIGZv
ciBEQTkxNTAiKTsNCj4gPiArTU9EVUxFX0FVVEhPUigiQWRhbSBUaG9tc29uDQo+IDxBZGFtLlRo
b21zb24uT3BlbnNvdXJjZUBkaWFzZW1pLmNvbT4iKTsNCj4gPiArTU9EVUxFX0xJQ0VOU0UoIkdQ
TCIpOw0KPiA+IC0tDQo+ID4gMS45LjMNCj4gPg0K

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

* Re: [PATCH v5 3/7] iio: Add support for DA9150 GPADC
  2015-01-07 16:03     ` Opensource [Adam Thomson]
@ 2015-01-10 22:19       ` Jonathan Cameron
  2015-01-14 11:30         ` Opensource [Adam Thomson]
  0 siblings, 1 reply; 20+ messages in thread
From: Jonathan Cameron @ 2015-01-10 22:19 UTC (permalink / raw)
  To: Opensource [Adam Thomson], Lee Jones, Samuel Ortiz,
	Hartmut Knaack, linux-iio@vger.kernel.org, Sebastian Reichel,
	Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm@vger.kernel.org, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	devicetree@vger.kernel.org, Andrew Morton, Joe Perches
  Cc: linux-kernel@vger.kernel.org, Support Opensource

On 07/01/15 16:03, Opensource [Adam Thomson] wrote:
> On January 4, 2015 17:22, Jonathan Cameron wrote:
> 
>> On 22/12/14 16:51, Adam Thomson wrote:
>>> This patch adds support for DA9150 Charger & Fuel-Gauge IC GPADC.
>>>
>>> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
>> One last query from me.
>>
>> Using the extended channel names in IIO is only really appropriate when
>> they don't correspond to simple pins on the side of the chip. For those
>> just drop the extname bit.  Some of the channels you have here, definitely
>> need them though.
>>
>> Drop those first 4 or convince me otherwise and add
>> Acked-by: Jonathan Cameron <jic23@kernel.org>
> 
> Have added responses below. If the comments are accepted then I'll respin
> and add you're 'Acked-by'. Is that ok?
> 
Not accepted as yet :)
>>> +#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type, _ext_name)
>> 	\
>>> +	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
>>> +			     BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
>>> +
>>> +/* Supported channels */
>>> +static const struct iio_chan_spec da9150_gpadc_channels[] = {
>>> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOA, GPIOA_6V, IIO_VOLTAGE,
>> "GPIOA"),
>>> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOB, GPIOB_6V, IIO_VOLTAGE,
>> "GPIOB"),
>>> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOC, GPIOC_6V, IIO_VOLTAGE,
>> "GPIOC"),
>>> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOD, GPIOD_6V, IIO_VOLTAGE,
>> "GPIOD"),
>> I'm not sure some of these really deserve extended names.  Those are usually
>> reserved for naming strange internal adc channels etc.  These first 4 are
>> presumably just for input pins?  Those should just be channels 0..3
>> On another note, unless you want really weird sysfs attribute names, the
>> extended names want to be lowercase.
>>
> 
> I'd prefer to keep the names because the input pins are muxed with GPIOs of the
> chip, so thought it sensible to show that this is the case. Am happy to change
> to lower-case to follow convention.
Hmm.  It's a bit of an oddity as the point of the naming
is about the uses, not which pins they are on.  If we exposed the
'datasheet_name' parameter directly rather than just using it internally
I'd suggest relying on that - but clearly you want it to be apparent
in the interface.  Whether that is useful is the question I'd raise
here (and is the reason datasheet_name is not exposed.

The obvious question is does userspace care?  Answer is probably not.

It cares what is being measured but this is about what pins it is
on and doesn't provide any information on what is connected to them.


> 
>>> +	DA9150_GPADC_CHANNEL_PROCESSED(IBUS, IBUS_SENSE, IIO_CURRENT,
>> "IBUS"),
>>> +	DA9150_GPADC_CHANNEL_PROCESSED(VBUS, VBUS_DIV_, IIO_VOLTAGE,
>> "VBUS"),
>>> +	DA9150_GPADC_CHANNEL_RAW(ID, ID, IIO_VOLTAGE, "ID"),
>> You hae an identifier voltage? That's certainly unusual but if so - fair enough
>> and it defintely needs the extname!
> 
> Thanks for pointing that out. Having checked again, this is not needed and can
> be dispensed with.
> 
>>> +	DA9150_GPADC_CHANNEL_PROCESSED(VSYS, VSYS, IIO_VOLTAGE, "VSYS"),
>>> +	DA9150_GPADC_CHANNEL_SCALED(VBAT, VBAT, IIO_VOLTAGE, "VBAT"),
>>> +	DA9150_GPADC_CHANNEL_RAW(TBAT, TBAT, IIO_VOLTAGE, "TBAT"),
>>> +	DA9150_GPADC_CHANNEL_SCALED(TJUNC_CORE, TJUNC_CORE,
>> IIO_TEMP,
>>> +				    "TJUNC_CORE"),
>> tjunc_core is a good use of extname ;)
>>> +	DA9150_GPADC_CHANNEL_SCALED(TJUNC_OVP, 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",
>>> +	},
>>> +	{
>>> +		.consumer_dev_name = "da9150-charger",
>>> +		.consumer_channel = "CHAN_VBUS",
>>> +		.adc_channel_label = "VBUS",
>>> +	},
>>> +	{
>>> +		.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",
>>> +	},
>>> +	{},
>>> +};
>>> +
>>> +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 irq, ret;
>>> +
>>> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*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;
>>> +	mutex_init(&gpadc->lock);
>>> +	init_completion(&gpadc->complete);
>>> +
>>> +	irq = platform_get_irq_byname(pdev, "GPADC");
>>> +	if (irq < 0) {
>>> +		dev_err(dev, "Failed to get IRQ: %d\n", irq);
>>> +		return irq;
>>> +	}
>>> +
>>> +	ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
>>> +					IRQF_ONESHOT, "GPADC", gpadc);
>>> +	if (ret) {
>>> +		dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
>>> +		return ret;
>>> +	}
>>> +
>>> +	ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
>>> +	if (ret) {
>>> +		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
>>> +		return ret;
>>> +	}
>>> +
>>> +	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_map_unreg;
>>> +	}
>>> +
>>> +	return 0;
>>> +
>>> +iio_map_unreg:
>>> +	iio_map_array_unregister(indio_dev);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +static int da9150_gpadc_remove(struct platform_device *pdev)
>>> +{
>>> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>>> +
>>> +	iio_device_unregister(indio_dev);
>>> +	iio_map_array_unregister(indio_dev);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static struct platform_driver da9150_gpadc_driver = {
>>> +	.driver = {
>>> +		.name = "da9150-gpadc",
>>> +	},
>>> +	.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");
>>> --
>>> 1.9.3
>>>


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

* RE: [PATCH v5 3/7] iio: Add support for DA9150 GPADC
  2015-01-10 22:19       ` Jonathan Cameron
@ 2015-01-14 11:30         ` Opensource [Adam Thomson]
  2015-01-20 20:49           ` Jonathan Cameron
  0 siblings, 1 reply; 20+ messages in thread
From: Opensource [Adam Thomson] @ 2015-01-14 11:30 UTC (permalink / raw)
  To: Jonathan Cameron, Opensource [Adam Thomson], Lee Jones,
	Samuel Ortiz, Hartmut Knaack, linux-iio@vger.kernel.org,
	Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm@vger.kernel.org, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	devicetree@vger.kernel.org, Andrew Morton, Joe Perches
  Cc: linux-kernel@vger.kernel.org, Support Opensource

T24gSmFudWFyeSAxMCwgMjAxNSAyMjoxOSwgSm9uYXRoYW4gQ2FtZXJvbiB3cm90ZToNCg0KPiBP
biAwNy8wMS8xNSAxNjowMywgT3BlbnNvdXJjZSBbQWRhbSBUaG9tc29uXSB3cm90ZToNCj4gPiBP
biBKYW51YXJ5IDQsIDIwMTUgMTc6MjIsIEpvbmF0aGFuIENhbWVyb24gd3JvdGU6DQo+ID4NCj4g
Pj4gT24gMjIvMTIvMTQgMTY6NTEsIEFkYW0gVGhvbXNvbiB3cm90ZToNCj4gPj4+IFRoaXMgcGF0
Y2ggYWRkcyBzdXBwb3J0IGZvciBEQTkxNTAgQ2hhcmdlciAmIEZ1ZWwtR2F1Z2UgSUMgR1BBREMu
DQo+ID4+Pg0KPiA+Pj4gU2lnbmVkLW9mZi1ieTogQWRhbSBUaG9tc29uIDxBZGFtLlRob21zb24u
T3BlbnNvdXJjZUBkaWFzZW1pLmNvbT4NCj4gPj4gT25lIGxhc3QgcXVlcnkgZnJvbSBtZS4NCj4g
Pj4NCj4gPj4gVXNpbmcgdGhlIGV4dGVuZGVkIGNoYW5uZWwgbmFtZXMgaW4gSUlPIGlzIG9ubHkg
cmVhbGx5IGFwcHJvcHJpYXRlIHdoZW4NCj4gPj4gdGhleSBkb24ndCBjb3JyZXNwb25kIHRvIHNp
bXBsZSBwaW5zIG9uIHRoZSBzaWRlIG9mIHRoZSBjaGlwLiBGb3IgdGhvc2UNCj4gPj4ganVzdCBk
cm9wIHRoZSBleHRuYW1lIGJpdC4gIFNvbWUgb2YgdGhlIGNoYW5uZWxzIHlvdSBoYXZlIGhlcmUs
IGRlZmluaXRlbHkNCj4gPj4gbmVlZCB0aGVtIHRob3VnaC4NCj4gPj4NCj4gPj4gRHJvcCB0aG9z
ZSBmaXJzdCA0IG9yIGNvbnZpbmNlIG1lIG90aGVyd2lzZSBhbmQgYWRkDQo+ID4+IEFja2VkLWJ5
OiBKb25hdGhhbiBDYW1lcm9uIDxqaWMyM0BrZXJuZWwub3JnPg0KPiA+DQo+ID4gSGF2ZSBhZGRl
ZCByZXNwb25zZXMgYmVsb3cuIElmIHRoZSBjb21tZW50cyBhcmUgYWNjZXB0ZWQgdGhlbiBJJ2xs
IHJlc3Bpbg0KPiA+IGFuZCBhZGQgeW91J3JlICdBY2tlZC1ieScuIElzIHRoYXQgb2s/DQo+ID4N
Cj4gTm90IGFjY2VwdGVkIGFzIHlldCA6KQ0KDQpZZWFoLCB0aGF0J3Mgd2h5IEkgYWRkZWQgdGhl
ICdpZicuIDopDQoNCj4gPj4+ICsjZGVmaW5lIERBOTE1MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NF
RChfaWQsIF9od19pZCwgX3R5cGUsDQo+IF9leHRfbmFtZSkNCj4gPj4gCVwNCj4gPj4+ICsJREE5
MTUwX0dQQURDX0NIQU5ORUwoX2lkLCBfaHdfaWQsIF90eXBlLAkJCVwNCj4gPj4+ICsJCQkgICAg
IEJJVChJSU9fQ0hBTl9JTkZPX1BST0NFU1NFRCksIF9leHRfbmFtZSkNCj4gPj4+ICsNCj4gPj4+
ICsvKiBTdXBwb3J0ZWQgY2hhbm5lbHMgKi8NCj4gPj4+ICtzdGF0aWMgY29uc3Qgc3RydWN0IGlp
b19jaGFuX3NwZWMgZGE5MTUwX2dwYWRjX2NoYW5uZWxzW10gPSB7DQo+ID4+PiArCURBOTE1MF9H
UEFEQ19DSEFOTkVMX1BST0NFU1NFRChHUElPQSwgR1BJT0FfNlYsIElJT19WT0xUQUdFLA0KPiA+
PiAiR1BJT0EiKSwNCj4gPj4+ICsJREE5MTUwX0dQQURDX0NIQU5ORUxfUFJPQ0VTU0VEKEdQSU9C
LCBHUElPQl82ViwgSUlPX1ZPTFRBR0UsDQo+ID4+ICJHUElPQiIpLA0KPiA+Pj4gKwlEQTkxNTBf
R1BBRENfQ0hBTk5FTF9QUk9DRVNTRUQoR1BJT0MsIEdQSU9DXzZWLCBJSU9fVk9MVEFHRSwNCj4g
Pj4gIkdQSU9DIiksDQo+ID4+PiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NFRChHUElP
RCwgR1BJT0RfNlYsIElJT19WT0xUQUdFLA0KPiA+PiAiR1BJT0QiKSwNCj4gPj4gSSdtIG5vdCBz
dXJlIHNvbWUgb2YgdGhlc2UgcmVhbGx5IGRlc2VydmUgZXh0ZW5kZWQgbmFtZXMuICBUaG9zZSBh
cmUgdXN1YWxseQ0KPiA+PiByZXNlcnZlZCBmb3IgbmFtaW5nIHN0cmFuZ2UgaW50ZXJuYWwgYWRj
IGNoYW5uZWxzIGV0Yy4gIFRoZXNlIGZpcnN0IDQgYXJlDQo+ID4+IHByZXN1bWFibHkganVzdCBm
b3IgaW5wdXQgcGlucz8gIFRob3NlIHNob3VsZCBqdXN0IGJlIGNoYW5uZWxzIDAuLjMNCj4gPj4g
T24gYW5vdGhlciBub3RlLCB1bmxlc3MgeW91IHdhbnQgcmVhbGx5IHdlaXJkIHN5c2ZzIGF0dHJp
YnV0ZSBuYW1lcywgdGhlDQo+ID4+IGV4dGVuZGVkIG5hbWVzIHdhbnQgdG8gYmUgbG93ZXJjYXNl
Lg0KPiA+Pg0KPiA+DQo+ID4gSSdkIHByZWZlciB0byBrZWVwIHRoZSBuYW1lcyBiZWNhdXNlIHRo
ZSBpbnB1dCBwaW5zIGFyZSBtdXhlZCB3aXRoIEdQSU9zIG9mIHRoZQ0KPiA+IGNoaXAsIHNvIHRo
b3VnaHQgaXQgc2Vuc2libGUgdG8gc2hvdyB0aGF0IHRoaXMgaXMgdGhlIGNhc2UuIEFtIGhhcHB5
IHRvIGNoYW5nZQ0KPiA+IHRvIGxvd2VyLWNhc2UgdG8gZm9sbG93IGNvbnZlbnRpb24uDQo+IEht
bS4gIEl0J3MgYSBiaXQgb2YgYW4gb2RkaXR5IGFzIHRoZSBwb2ludCBvZiB0aGUgbmFtaW5nDQo+
IGlzIGFib3V0IHRoZSB1c2VzLCBub3Qgd2hpY2ggcGlucyB0aGV5IGFyZSBvbi4gIElmIHdlIGV4
cG9zZWQgdGhlDQo+ICdkYXRhc2hlZXRfbmFtZScgcGFyYW1ldGVyIGRpcmVjdGx5IHJhdGhlciB0
aGFuIGp1c3QgdXNpbmcgaXQgaW50ZXJuYWxseQ0KPiBJJ2Qgc3VnZ2VzdCByZWx5aW5nIG9uIHRo
YXQgLSBidXQgY2xlYXJseSB5b3Ugd2FudCBpdCB0byBiZSBhcHBhcmVudA0KPiBpbiB0aGUgaW50
ZXJmYWNlLiAgV2hldGhlciB0aGF0IGlzIHVzZWZ1bCBpcyB0aGUgcXVlc3Rpb24gSSdkIHJhaXNl
DQo+IGhlcmUgKGFuZCBpcyB0aGUgcmVhc29uIGRhdGFzaGVldF9uYW1lIGlzIG5vdCBleHBvc2Vk
Lg0KPiANCj4gVGhlIG9idmlvdXMgcXVlc3Rpb24gaXMgZG9lcyB1c2Vyc3BhY2UgY2FyZT8gIEFu
c3dlciBpcyBwcm9iYWJseSBub3QuDQo+IA0KPiBJdCBjYXJlcyB3aGF0IGlzIGJlaW5nIG1lYXN1
cmVkIGJ1dCB0aGlzIGlzIGFib3V0IHdoYXQgcGlucyBpdCBpcw0KPiBvbiBhbmQgZG9lc24ndCBw
cm92aWRlIGFueSBpbmZvcm1hdGlvbiBvbiB3aGF0IGlzIGNvbm5lY3RlZCB0byB0aGVtLg0KPiAN
Cg0KU3VyZWx5IGl0IGhlbHBzIHdoZW4gdXNpbmcgc3lzZnMgdG8gYWNjZXNzIHdoYXRldmVyIGlz
IGNvbm5lY3RlZCB0byBvbmUgb2YNCnRob3NlIHBpbnMgaWYgd2UgbGFiZWwgdGhlIHBpbiB3aXRo
IHNvbWV0aGluZyBtZWFuaW5nZnVsPyBJZiBzYXkgeW91IGhhdmUgYQ0KZGV2aWNlIGNvbm5lY3Rl
ZCB0byBHUElDIG9mIHRoZSBjaGFyZ2VyIElDLCBpdCdzIGVhc2llciB0byB3b3JrIG91dCB3aGlj
aCBBREMNCmNoYW5uZWwgeW91IG5lZWQgdG8gYWNjZXNzIHRocm91Z2ggc3lzZnMgaWYgdGhlIG5h
bWluZyBpcyBhcyBJIGhhdmUgbm93LCByYXRoZXINCnRoYW4gc29tZSBhcmJpdHJhcnkgbnVtYmVy
IHdoaWNoIGRvZXNuJ3QgbmVjZXNzYXJpbHkgdGFsbHkgdG8gdGhlIGNoYW5uZWwgaW4gdGhlDQpk
YXRhc2hlZXQuIFlvdSdkIHRoZW4gbmVlZCB0byBsb29rIGF0IHRoZSBjb2RlIGFuZCB3b3JrIG91
dCB3aGljaCBjaGFubmVsIG51bWJlcg0KR1BJT0MgYWN0dWFsbHkgd2FzLiBPciBhbSBJIGp1c3Qg
bWlzc2luZyBzb21ldGhpbmcgaGVyZT8gOikNCg0KPiANCj4gPg0KPiA+Pj4gKwlEQTkxNTBfR1BB
RENfQ0hBTk5FTF9QUk9DRVNTRUQoSUJVUywgSUJVU19TRU5TRSwgSUlPX0NVUlJFTlQsDQo+ID4+
ICJJQlVTIiksDQo+ID4+PiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NFRChWQlVTLCBW
QlVTX0RJVl8sIElJT19WT0xUQUdFLA0KPiA+PiAiVkJVUyIpLA0KPiA+Pj4gKwlEQTkxNTBfR1BB
RENfQ0hBTk5FTF9SQVcoSUQsIElELCBJSU9fVk9MVEFHRSwgIklEIiksDQo+ID4+IFlvdSBoYWUg
YW4gaWRlbnRpZmllciB2b2x0YWdlPyBUaGF0J3MgY2VydGFpbmx5IHVudXN1YWwgYnV0IGlmIHNv
IC0gZmFpciBlbm91Z2gNCj4gPj4gYW5kIGl0IGRlZmludGVseSBuZWVkcyB0aGUgZXh0bmFtZSEN
Cj4gPg0KPiA+IFRoYW5rcyBmb3IgcG9pbnRpbmcgdGhhdCBvdXQuIEhhdmluZyBjaGVja2VkIGFn
YWluLCB0aGlzIGlzIG5vdCBuZWVkZWQgYW5kIGNhbg0KPiA+IGJlIGRpc3BlbnNlZCB3aXRoLg0K
PiA+DQo+ID4+PiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NFRChWU1lTLCBWU1lTLCBJ
SU9fVk9MVEFHRSwgIlZTWVMiKSwNCj4gPj4+ICsJREE5MTUwX0dQQURDX0NIQU5ORUxfU0NBTEVE
KFZCQVQsIFZCQVQsIElJT19WT0xUQUdFLCAiVkJBVCIpLA0KPiA+Pj4gKwlEQTkxNTBfR1BBRENf
Q0hBTk5FTF9SQVcoVEJBVCwgVEJBVCwgSUlPX1ZPTFRBR0UsICJUQkFUIiksDQo+ID4+PiArCURB
OTE1MF9HUEFEQ19DSEFOTkVMX1NDQUxFRChUSlVOQ19DT1JFLCBUSlVOQ19DT1JFLA0KPiA+PiBJ
SU9fVEVNUCwNCj4gPj4+ICsJCQkJICAgICJUSlVOQ19DT1JFIiksDQo+ID4+IHRqdW5jX2NvcmUg
aXMgYSBnb29kIHVzZSBvZiBleHRuYW1lIDspDQo+ID4+PiArCURBOTE1MF9HUEFEQ19DSEFOTkVM
X1NDQUxFRChUSlVOQ19PVlAsIFRKVU5DX09WUCwgSUlPX1RFTVAsDQo+ID4+PiArCQkJCSAgICAi
VEpVTkNfT1ZQIiksDQo+ID4+PiArfTsNCj4gPj4+ICsNCj4gPj4+ICsvKiBEZWZhdWx0IG1hcHMg
dXNlZCBieSBkYTkxNTAtY2hhcmdlciAqLw0KPiA+Pj4gK3N0YXRpYyBzdHJ1Y3QgaWlvX21hcCBk
YTkxNTBfZ3BhZGNfZGVmYXVsdF9tYXBzW10gPSB7DQo+ID4+PiArCXsNCj4gPj4+ICsJCS5jb25z
dW1lcl9kZXZfbmFtZSA9ICJkYTkxNTAtY2hhcmdlciIsDQo+ID4+PiArCQkuY29uc3VtZXJfY2hh
bm5lbCA9ICJDSEFOX0lCVVMiLA0KPiA+Pj4gKwkJLmFkY19jaGFubmVsX2xhYmVsID0gIklCVVMi
LA0KPiA+Pj4gKwl9LA0KPiA+Pj4gKwl7DQo+ID4+PiArCQkuY29uc3VtZXJfZGV2X25hbWUgPSAi
ZGE5MTUwLWNoYXJnZXIiLA0KPiA+Pj4gKwkJLmNvbnN1bWVyX2NoYW5uZWwgPSAiQ0hBTl9WQlVT
IiwNCj4gPj4+ICsJCS5hZGNfY2hhbm5lbF9sYWJlbCA9ICJWQlVTIiwNCj4gPj4+ICsJfSwNCj4g
Pj4+ICsJew0KPiA+Pj4gKwkJLmNvbnN1bWVyX2Rldl9uYW1lID0gImRhOTE1MC1jaGFyZ2VyIiwN
Cj4gPj4+ICsJCS5jb25zdW1lcl9jaGFubmVsID0gIkNIQU5fVEpVTkMiLA0KPiA+Pj4gKwkJLmFk
Y19jaGFubmVsX2xhYmVsID0gIlRKVU5DX0NPUkUiLA0KPiA+Pj4gKwl9LA0KPiA+Pj4gKwl7DQo+
ID4+PiArCQkuY29uc3VtZXJfZGV2X25hbWUgPSAiZGE5MTUwLWNoYXJnZXIiLA0KPiA+Pj4gKwkJ
LmNvbnN1bWVyX2NoYW5uZWwgPSAiQ0hBTl9WQkFUIiwNCj4gPj4+ICsJCS5hZGNfY2hhbm5lbF9s
YWJlbCA9ICJWQkFUIiwNCj4gPj4+ICsJfSwNCj4gPj4+ICsJe30sDQo+ID4+PiArfTsNCj4gPj4+
ICsNCj4gPj4+ICtzdGF0aWMgaW50IGRhOTE1MF9ncGFkY19wcm9iZShzdHJ1Y3QgcGxhdGZvcm1f
ZGV2aWNlICpwZGV2KQ0KPiA+Pj4gK3sNCj4gPj4+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gJnBk
ZXYtPmRldjsNCj4gPj4+ICsJc3RydWN0IGRhOTE1MCAqZGE5MTUwID0gZGV2X2dldF9kcnZkYXRh
KGRldi0+cGFyZW50KTsNCj4gPj4+ICsJc3RydWN0IGRhOTE1MF9ncGFkYyAqZ3BhZGM7DQo+ID4+
PiArCXN0cnVjdCBpaW9fZGV2ICppbmRpb19kZXY7DQo+ID4+PiArCWludCBpcnEsIHJldDsNCj4g
Pj4+ICsNCj4gPj4+ICsJaW5kaW9fZGV2ID0gZGV2bV9paW9fZGV2aWNlX2FsbG9jKCZwZGV2LT5k
ZXYsIHNpemVvZigqZ3BhZGMpKTsNCj4gPj4+ICsJaWYgKCFpbmRpb19kZXYpIHsNCj4gPj4+ICsJ
CWRldl9lcnIoJnBkZXYtPmRldiwgIkZhaWxlZCB0byBhbGxvY2F0ZSBJSU8gZGV2aWNlXG4iKTsN
Cj4gPj4+ICsJCXJldHVybiAtRU5PTUVNOw0KPiA+Pj4gKwl9DQo+ID4+PiArCWdwYWRjID0gaWlv
X3ByaXYoaW5kaW9fZGV2KTsNCj4gPj4+ICsNCj4gPj4+ICsJcGxhdGZvcm1fc2V0X2RydmRhdGEo
cGRldiwgaW5kaW9fZGV2KTsNCj4gPj4+ICsJZ3BhZGMtPmRhOTE1MCA9IGRhOTE1MDsNCj4gPj4+
ICsJZ3BhZGMtPmRldiA9IGRldjsNCj4gPj4+ICsJbXV0ZXhfaW5pdCgmZ3BhZGMtPmxvY2spOw0K
PiA+Pj4gKwlpbml0X2NvbXBsZXRpb24oJmdwYWRjLT5jb21wbGV0ZSk7DQo+ID4+PiArDQo+ID4+
PiArCWlycSA9IHBsYXRmb3JtX2dldF9pcnFfYnluYW1lKHBkZXYsICJHUEFEQyIpOw0KPiA+Pj4g
KwlpZiAoaXJxIDwgMCkgew0KPiA+Pj4gKwkJZGV2X2VycihkZXYsICJGYWlsZWQgdG8gZ2V0IElS
UTogJWRcbiIsIGlycSk7DQo+ID4+PiArCQlyZXR1cm4gaXJxOw0KPiA+Pj4gKwl9DQo+ID4+PiAr
DQo+ID4+PiArCXJldCA9IGRldm1fcmVxdWVzdF90aHJlYWRlZF9pcnEoZGV2LCBpcnEsIE5VTEws
IGRhOTE1MF9ncGFkY19pcnEsDQo+ID4+PiArCQkJCQlJUlFGX09ORVNIT1QsICJHUEFEQyIsIGdw
YWRjKTsNCj4gPj4+ICsJaWYgKHJldCkgew0KPiA+Pj4gKwkJZGV2X2VycihkZXYsICJGYWlsZWQg
dG8gcmVxdWVzdCBJUlEgJWQ6ICVkXG4iLCBpcnEsIHJldCk7DQo+ID4+PiArCQlyZXR1cm4gcmV0
Ow0KPiA+Pj4gKwl9DQo+ID4+PiArDQo+ID4+PiArCXJldCA9IGlpb19tYXBfYXJyYXlfcmVnaXN0
ZXIoaW5kaW9fZGV2LCBkYTkxNTBfZ3BhZGNfZGVmYXVsdF9tYXBzKTsNCj4gPj4+ICsJaWYgKHJl
dCkgew0KPiA+Pj4gKwkJZGV2X2VycihkZXYsICJGYWlsZWQgdG8gcmVnaXN0ZXIgSUlPIG1hcHM6
ICVkXG4iLCByZXQpOw0KPiA+Pj4gKwkJcmV0dXJuIHJldDsNCj4gPj4+ICsJfQ0KPiA+Pj4gKw0K
PiA+Pj4gKwlpbmRpb19kZXYtPm5hbWUgPSBkZXZfbmFtZShkZXYpOw0KPiA+Pj4gKwlpbmRpb19k
ZXYtPmRldi5wYXJlbnQgPSBkZXY7DQo+ID4+PiArCWluZGlvX2Rldi0+ZGV2Lm9mX25vZGUgPSBw
ZGV2LT5kZXYub2Zfbm9kZTsNCj4gPj4+ICsJaW5kaW9fZGV2LT5pbmZvID0gJmRhOTE1MF9ncGFk
Y19pbmZvOw0KPiA+Pj4gKwlpbmRpb19kZXYtPm1vZGVzID0gSU5ESU9fRElSRUNUX01PREU7DQo+
ID4+PiArCWluZGlvX2Rldi0+Y2hhbm5lbHMgPSBkYTkxNTBfZ3BhZGNfY2hhbm5lbHM7DQo+ID4+
PiArCWluZGlvX2Rldi0+bnVtX2NoYW5uZWxzID0gQVJSQVlfU0laRShkYTkxNTBfZ3BhZGNfY2hh
bm5lbHMpOw0KPiA+Pj4gKw0KPiA+Pj4gKwlyZXQgPSBpaW9fZGV2aWNlX3JlZ2lzdGVyKGluZGlv
X2Rldik7DQo+ID4+PiArCWlmIChyZXQpIHsNCj4gPj4+ICsJCWRldl9lcnIoZGV2LCAiRmFpbGVk
IHRvIHJlZ2lzdGVyIElJTyBkZXZpY2U6ICVkXG4iLCByZXQpOw0KPiA+Pj4gKwkJZ290byBpaW9f
bWFwX3VucmVnOw0KPiA+Pj4gKwl9DQo+ID4+PiArDQo+ID4+PiArCXJldHVybiAwOw0KPiA+Pj4g
Kw0KPiA+Pj4gK2lpb19tYXBfdW5yZWc6DQo+ID4+PiArCWlpb19tYXBfYXJyYXlfdW5yZWdpc3Rl
cihpbmRpb19kZXYpOw0KPiA+Pj4gKw0KPiA+Pj4gKwlyZXR1cm4gcmV0Ow0KPiA+Pj4gK30NCj4g
Pj4+ICsNCj4gPj4+ICtzdGF0aWMgaW50IGRhOTE1MF9ncGFkY19yZW1vdmUoc3RydWN0IHBsYXRm
b3JtX2RldmljZSAqcGRldikNCj4gPj4+ICt7DQo+ID4+PiArCXN0cnVjdCBpaW9fZGV2ICppbmRp
b19kZXYgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShwZGV2KTsNCj4gPj4+ICsNCj4gPj4+ICsJaWlv
X2RldmljZV91bnJlZ2lzdGVyKGluZGlvX2Rldik7DQo+ID4+PiArCWlpb19tYXBfYXJyYXlfdW5y
ZWdpc3RlcihpbmRpb19kZXYpOw0KPiA+Pj4gKw0KPiA+Pj4gKwlyZXR1cm4gMDsNCj4gPj4+ICt9
DQo+ID4+PiArDQo+ID4+PiArc3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgZGE5MTUwX2dw
YWRjX2RyaXZlciA9IHsNCj4gPj4+ICsJLmRyaXZlciA9IHsNCj4gPj4+ICsJCS5uYW1lID0gImRh
OTE1MC1ncGFkYyIsDQo+ID4+PiArCX0sDQo+ID4+PiArCS5wcm9iZSA9IGRhOTE1MF9ncGFkY19w
cm9iZSwNCj4gPj4+ICsJLnJlbW92ZSA9IGRhOTE1MF9ncGFkY19yZW1vdmUsDQo+ID4+PiArfTsN
Cj4gPj4+ICsNCj4gPj4+ICttb2R1bGVfcGxhdGZvcm1fZHJpdmVyKGRhOTE1MF9ncGFkY19kcml2
ZXIpOw0KPiA+Pj4gKw0KPiA+Pj4gK01PRFVMRV9ERVNDUklQVElPTigiR1BBREMgRHJpdmVyIGZv
ciBEQTkxNTAiKTsNCj4gPj4+ICtNT0RVTEVfQVVUSE9SKCJBZGFtIFRob21zb24NCj4gPj4gPEFk
YW0uVGhvbXNvbi5PcGVuc291cmNlQGRpYXNlbWkuY29tPiIpOw0KPiA+Pj4gK01PRFVMRV9MSUNF
TlNFKCJHUEwiKTsNCj4gPj4+IC0tDQo+ID4+PiAxLjkuMw0KPiA+Pj4NCg==

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

* Re: [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2014-12-22 16:51 ` [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
@ 2015-01-19 11:33   ` Lee Jones
  2015-01-19 13:23     ` Opensource [Adam Thomson]
  0 siblings, 1 reply; 20+ messages in thread
From: Lee Jones @ 2015-01-19 11:33 UTC (permalink / raw)
  To: Adam Thomson
  Cc: Samuel Ortiz, Jonathan Cameron, Hartmut Knaack, linux-iio,
	Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm, Rob Herring, Pawel Moll, Mark Rutland, Ian Campbell,
	Kumar Gala, Grant Likely, devicetree, Andrew Morton, Joe Perches,
	linux-kernel, support.opensource

On Mon, 22 Dec 2014, Adam Thomson wrote:

> DA9150 is a combined Charger and Fuel-Gauge IC, with additional
> GPIO and GPADC functionality.
> 
> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> ---
>  drivers/mfd/Kconfig                  |   12 +
>  drivers/mfd/Makefile                 |    2 +-
>  drivers/mfd/da9150-core.c            |  413 ++++++++++++
>  include/linux/mfd/da9150/core.h      |   68 ++
>  include/linux/mfd/da9150/registers.h | 1155 ++++++++++++++++++++++++++++++++++
>  5 files changed, 1649 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/mfd/da9150-core.c
>  create mode 100644 include/linux/mfd/da9150/core.h
>  create mode 100644 include/linux/mfd/da9150/registers.h
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 2e6b731..56e80d2 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -195,6 +195,18 @@ config MFD_DA9063
>  	  Additional drivers must be enabled in order to use the functionality
>  	  of the device.
> 
> +config MFD_DA9150
> +	tristate "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_DLN2
>  	tristate "Diolan DLN2 support"
>  	select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 53467e2..f06f4c6 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -113,7 +113,7 @@ 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
>  obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
>  obj-$(CONFIG_MFD_MAX77686)	+= max77686.o
>  obj-$(CONFIG_MFD_MAX77693)	+= max77693.o
> diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c
> new file mode 100644
> index 0000000..4d757b9
> --- /dev/null
> +++ b/drivers/mfd/da9150-core.c
> @@ -0,0 +1,413 @@
> +/*
> + * 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.
> + */

[...]

> +u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
> +{
> +	int val, ret;
> +
> +	ret = regmap_read(da9150->regmap, reg, &val);
> +	if (ret)
> +		dev_err(da9150->dev, "Failed to read from reg 0x%x: %d\n",
> +			reg, ret);
> +
> +	return (u8) val;
> +}
> +EXPORT_SYMBOL_GPL(da9150_reg_read);
> +
> +void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val)
> +{
> +	int ret;
> +
> +	ret = regmap_write(da9150->regmap, reg, val);
> +	if (ret)
> +		dev_err(da9150->dev, "Failed to write to reg 0x%x: %d\n",
> +			reg, ret);
> +}
> +EXPORT_SYMBOL_GPL(da9150_reg_write);
> +
> +void 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)
> +		dev_err(da9150->dev, "Failed to set bits in reg 0x%x: %d\n",
> +			reg, ret);
> +}
> +EXPORT_SYMBOL_GPL(da9150_set_bits);
> +
> +void 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)
> +		dev_err(da9150->dev, "Failed to bulk read from reg 0x%x: %d\n",
> +			reg, ret);
> +}
> +EXPORT_SYMBOL_GPL(da9150_bulk_read);
> +
> +void 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)
> +		dev_err(da9150->dev, "Failed to bulk write to reg 0x%x %d\n",
> +			reg, ret);
> +}
> +EXPORT_SYMBOL_GPL(da9150_bulk_write);

I've never been a fan of this type of aggregation.  Can you explain to
me what the point of them is?

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

* RE: [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2015-01-19 11:33   ` Lee Jones
@ 2015-01-19 13:23     ` Opensource [Adam Thomson]
  2015-01-20 10:50       ` Lee Jones
  0 siblings, 1 reply; 20+ messages in thread
From: Opensource [Adam Thomson] @ 2015-01-19 13:23 UTC (permalink / raw)
  To: Lee Jones, Opensource [Adam Thomson]
  Cc: Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio@vger.kernel.org, Sebastian Reichel,
	Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm@vger.kernel.org, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	devicetree@vger.kernel.org, Andrew Morton, Joe Perches,
	linux-kernel@vger.kernel.org, Support Opensource

T24gSmFudWFyeSAxOSwgMjAxNSAxMTozNCwgTGVlIEpvbmVzIHdyb3RlOg0KDQo+IE9uIE1vbiwg
MjIgRGVjIDIwMTQsIEFkYW0gVGhvbXNvbiB3cm90ZToNCj4gDQo+ID4gREE5MTUwIGlzIGEgY29t
YmluZWQgQ2hhcmdlciBhbmQgRnVlbC1HYXVnZSBJQywgd2l0aCBhZGRpdGlvbmFsDQo+ID4gR1BJ
TyBhbmQgR1BBREMgZnVuY3Rpb25hbGl0eS4NCj4gPg0KPiA+IFNpZ25lZC1vZmYtYnk6IEFkYW0g
VGhvbXNvbiA8QWRhbS5UaG9tc29uLk9wZW5zb3VyY2VAZGlhc2VtaS5jb20+DQo+ID4gLS0tDQo+
ID4gIGRyaXZlcnMvbWZkL0tjb25maWcgICAgICAgICAgICAgICAgICB8ICAgMTIgKw0KPiA+ICBk
cml2ZXJzL21mZC9NYWtlZmlsZSAgICAgICAgICAgICAgICAgfCAgICAyICstDQo+ID4gIGRyaXZl
cnMvbWZkL2RhOTE1MC1jb3JlLmMgICAgICAgICAgICB8ICA0MTMgKysrKysrKysrKysrDQo+ID4g
IGluY2x1ZGUvbGludXgvbWZkL2RhOTE1MC9jb3JlLmggICAgICB8ICAgNjggKysNCj4gPiAgaW5j
bHVkZS9saW51eC9tZmQvZGE5MTUwL3JlZ2lzdGVycy5oIHwgMTE1NQ0KPiArKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKysrDQo+ID4gIDUgZmlsZXMgY2hhbmdlZCwgMTY0OSBpbnNlcnRp
b25zKCspLCAxIGRlbGV0aW9uKC0pDQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBkcml2ZXJzL21m
ZC9kYTkxNTAtY29yZS5jDQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL2xpbnV4L21m
ZC9kYTkxNTAvY29yZS5oDQo+ID4gIGNyZWF0ZSBtb2RlIDEwMDY0NCBpbmNsdWRlL2xpbnV4L21m
ZC9kYTkxNTAvcmVnaXN0ZXJzLmgNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL21mZC9L
Y29uZmlnIGIvZHJpdmVycy9tZmQvS2NvbmZpZw0KPiA+IGluZGV4IDJlNmI3MzEuLjU2ZTgwZDIg
MTAwNjQ0DQo+ID4gLS0tIGEvZHJpdmVycy9tZmQvS2NvbmZpZw0KPiA+ICsrKyBiL2RyaXZlcnMv
bWZkL0tjb25maWcNCj4gPiBAQCAtMTk1LDYgKzE5NSwxOCBAQCBjb25maWcgTUZEX0RBOTA2Mw0K
PiA+ICAJICBBZGRpdGlvbmFsIGRyaXZlcnMgbXVzdCBiZSBlbmFibGVkIGluIG9yZGVyIHRvIHVz
ZSB0aGUgZnVuY3Rpb25hbGl0eQ0KPiA+ICAJICBvZiB0aGUgZGV2aWNlLg0KPiA+DQo+ID4gK2Nv
bmZpZyBNRkRfREE5MTUwDQo+ID4gKwl0cmlzdGF0ZSAiRGlhbG9nIFNlbWljb25kdWN0b3IgREE5
MTUwIENoYXJnZXIgRnVlbC1HYXVnZSBjaGlwIg0KPiA+ICsJZGVwZW5kcyBvbiBJMkM9eQ0KPiA+
ICsJc2VsZWN0IE1GRF9DT1JFDQo+ID4gKwlzZWxlY3QgUkVHTUFQX0kyQw0KPiA+ICsJc2VsZWN0
IFJFR01BUF9JUlENCj4gPiArCWhlbHANCj4gPiArCSAgVGhpcyBhZGRzIHN1cHBvcnQgZm9yIHRo
ZSBEQTkxNTAgaW50ZWdyYXRlZCBjaGFyZ2VyIGFuZCBmdWVsLWdhdWdlDQo+ID4gKwkgIGNoaXAu
IFRoaXMgZHJpdmVyIHByb3ZpZGVzIGNvbW1vbiBzdXBwb3J0IGZvciBhY2Nlc3NpbmcgdGhlIGRl
dmljZS4NCj4gPiArCSAgQWRkaXRpb25hbCBkcml2ZXJzIG11c3QgYmUgZW5hYmxlZCBpbiBvcmRl
ciB0byB1c2UgdGhlIHNwZWNpZmljDQo+ID4gKwkgIGZlYXR1cmVzIG9mIHRoZSBkZXZpY2UuDQo+
ID4gKw0KPiA+ICBjb25maWcgTUZEX0RMTjINCj4gPiAgCXRyaXN0YXRlICJEaW9sYW4gRExOMiBz
dXBwb3J0Ig0KPiA+ICAJc2VsZWN0IE1GRF9DT1JFDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv
bWZkL01ha2VmaWxlIGIvZHJpdmVycy9tZmQvTWFrZWZpbGUNCj4gPiBpbmRleCA1MzQ2N2UyLi5m
MDZmNGM2IDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvbWZkL01ha2VmaWxlDQo+ID4gKysrIGIv
ZHJpdmVycy9tZmQvTWFrZWZpbGUNCj4gPiBAQCAtMTEzLDcgKzExMyw3IEBAIG9iai0kKENPTkZJ
R19NRkRfREE5MDU1KQkrPSBkYTkwNTUubw0KPiA+DQo+ID4gIGRhOTA2My1vYmpzCQkJOj0gZGE5
MDYzLWNvcmUubyBkYTkwNjMtaXJxLm8gZGE5MDYzLWkyYy5vDQo+ID4gIG9iai0kKENPTkZJR19N
RkRfREE5MDYzKQkrPSBkYTkwNjMubw0KPiA+IC0NCj4gPiArb2JqLSQoQ09ORklHX01GRF9EQTkx
NTApCSs9IGRhOTE1MC1jb3JlLm8NCj4gPiAgb2JqLSQoQ09ORklHX01GRF9NQVgxNDU3NykJKz0g
bWF4MTQ1Nzcubw0KPiA+ICBvYmotJChDT05GSUdfTUZEX01BWDc3Njg2KQkrPSBtYXg3NzY4Ni5v
DQo+ID4gIG9iai0kKENPTkZJR19NRkRfTUFYNzc2OTMpCSs9IG1heDc3NjkzLm8NCj4gPiBkaWZm
IC0tZ2l0IGEvZHJpdmVycy9tZmQvZGE5MTUwLWNvcmUuYyBiL2RyaXZlcnMvbWZkL2RhOTE1MC1j
b3JlLmMNCj4gPiBuZXcgZmlsZSBtb2RlIDEwMDY0NA0KPiA+IGluZGV4IDAwMDAwMDAuLjRkNzU3
YjkNCj4gPiAtLS0gL2Rldi9udWxsDQo+ID4gKysrIGIvZHJpdmVycy9tZmQvZGE5MTUwLWNvcmUu
Yw0KPiA+IEBAIC0wLDAgKzEsNDEzIEBADQo+ID4gKy8qDQo+ID4gKyAqIERBOTE1MCBDb3JlIE1G
RCBEcml2ZXINCj4gPiArICoNCj4gPiArICogQ29weXJpZ2h0IChjKSAyMDE0IERpYWxvZyBTZW1p
Y29uZHVjdG9yDQo+ID4gKyAqDQo+ID4gKyAqIEF1dGhvcjogQWRhbSBUaG9tc29uIDxBZGFtLlRo
b21zb24uT3BlbnNvdXJjZUBkaWFzZW1pLmNvbT4NCj4gPiArICoNCj4gPiArICogVGhpcyBwcm9n
cmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlICBpdCBhbmQvb3IgbW9k
aWZ5IGl0DQo+ID4gKyAqIHVuZGVyICB0aGUgdGVybXMgb2YgIHRoZSBHTlUgR2VuZXJhbCAgUHVi
bGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZQ0KPiA+ICsgKiBGcmVlIFNvZnR3YXJlIEZv
dW5kYXRpb247ICBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSAgTGljZW5zZSwgb3IgKGF0IHlvdXIN
Cj4gPiArICogb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4NCj4gPiArICovDQo+IA0KPiBbLi4u
XQ0KPiANCj4gPiArdTggZGE5MTUwX3JlZ19yZWFkKHN0cnVjdCBkYTkxNTAgKmRhOTE1MCwgdTE2
IHJlZykNCj4gPiArew0KPiA+ICsJaW50IHZhbCwgcmV0Ow0KPiA+ICsNCj4gPiArCXJldCA9IHJl
Z21hcF9yZWFkKGRhOTE1MC0+cmVnbWFwLCByZWcsICZ2YWwpOw0KPiA+ICsJaWYgKHJldCkNCj4g
PiArCQlkZXZfZXJyKGRhOTE1MC0+ZGV2LCAiRmFpbGVkIHRvIHJlYWQgZnJvbSByZWcgMHgleDog
JWRcbiIsDQo+ID4gKwkJCXJlZywgcmV0KTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gKHU4KSB2YWw7
DQo+ID4gK30NCj4gPiArRVhQT1JUX1NZTUJPTF9HUEwoZGE5MTUwX3JlZ19yZWFkKTsNCj4gPiAr
DQo+ID4gK3ZvaWQgZGE5MTUwX3JlZ193cml0ZShzdHJ1Y3QgZGE5MTUwICpkYTkxNTAsIHUxNiBy
ZWcsIHU4IHZhbCkNCj4gPiArew0KPiA+ICsJaW50IHJldDsNCj4gPiArDQo+ID4gKwlyZXQgPSBy
ZWdtYXBfd3JpdGUoZGE5MTUwLT5yZWdtYXAsIHJlZywgdmFsKTsNCj4gPiArCWlmIChyZXQpDQo+
ID4gKwkJZGV2X2VycihkYTkxNTAtPmRldiwgIkZhaWxlZCB0byB3cml0ZSB0byByZWcgMHgleDog
JWRcbiIsDQo+ID4gKwkJCXJlZywgcmV0KTsNCj4gPiArfQ0KPiA+ICtFWFBPUlRfU1lNQk9MX0dQ
TChkYTkxNTBfcmVnX3dyaXRlKTsNCj4gPiArDQo+ID4gK3ZvaWQgZGE5MTUwX3NldF9iaXRzKHN0
cnVjdCBkYTkxNTAgKmRhOTE1MCwgdTE2IHJlZywgdTggbWFzaywgdTggdmFsKQ0KPiA+ICt7DQo+
ID4gKwlpbnQgcmV0Ow0KPiA+ICsNCj4gPiArCXJldCA9IHJlZ21hcF91cGRhdGVfYml0cyhkYTkx
NTAtPnJlZ21hcCwgcmVnLCBtYXNrLCB2YWwpOw0KPiA+ICsJaWYgKHJldCkNCj4gPiArCQlkZXZf
ZXJyKGRhOTE1MC0+ZGV2LCAiRmFpbGVkIHRvIHNldCBiaXRzIGluIHJlZyAweCV4OiAlZFxuIiwN
Cj4gPiArCQkJcmVnLCByZXQpOw0KPiA+ICt9DQo+ID4gK0VYUE9SVF9TWU1CT0xfR1BMKGRhOTE1
MF9zZXRfYml0cyk7DQo+ID4gKw0KPiA+ICt2b2lkIGRhOTE1MF9idWxrX3JlYWQoc3RydWN0IGRh
OTE1MCAqZGE5MTUwLCB1MTYgcmVnLCBpbnQgY291bnQsIHU4ICpidWYpDQo+ID4gK3sNCj4gPiAr
CWludCByZXQ7DQo+ID4gKw0KPiA+ICsJcmV0ID0gcmVnbWFwX2J1bGtfcmVhZChkYTkxNTAtPnJl
Z21hcCwgcmVnLCBidWYsIGNvdW50KTsNCj4gPiArCWlmIChyZXQpDQo+ID4gKwkJZGV2X2Vycihk
YTkxNTAtPmRldiwgIkZhaWxlZCB0byBidWxrIHJlYWQgZnJvbSByZWcgMHgleDogJWRcbiIsDQo+
ID4gKwkJCXJlZywgcmV0KTsNCj4gPiArfQ0KPiA+ICtFWFBPUlRfU1lNQk9MX0dQTChkYTkxNTBf
YnVsa19yZWFkKTsNCj4gPiArDQo+ID4gK3ZvaWQgZGE5MTUwX2J1bGtfd3JpdGUoc3RydWN0IGRh
OTE1MCAqZGE5MTUwLCB1MTYgcmVnLCBpbnQgY291bnQsIGNvbnN0IHU4DQo+ICpidWYpDQo+ID4g
K3sNCj4gPiArCWludCByZXQ7DQo+ID4gKw0KPiA+ICsJcmV0ID0gcmVnbWFwX3Jhd193cml0ZShk
YTkxNTAtPnJlZ21hcCwgcmVnLCBidWYsIGNvdW50KTsNCj4gPiArCWlmIChyZXQpDQo+ID4gKwkJ
ZGV2X2VycihkYTkxNTAtPmRldiwgIkZhaWxlZCB0byBidWxrIHdyaXRlIHRvIHJlZyAweCV4ICVk
XG4iLA0KPiA+ICsJCQlyZWcsIHJldCk7DQo+ID4gK30NCj4gPiArRVhQT1JUX1NZTUJPTF9HUEwo
ZGE5MTUwX2J1bGtfd3JpdGUpOw0KPiANCj4gSSd2ZSBuZXZlciBiZWVuIGEgZmFuIG9mIHRoaXMg
dHlwZSBvZiBhZ2dyZWdhdGlvbi4gIENhbiB5b3UgZXhwbGFpbiB0bw0KPiBtZSB3aGF0IHRoZSBw
b2ludCBvZiB0aGVtIGlzPw0KDQpJIHJlZmVyIHlvdSBiYWNrIHRvIG91ciBwcmV2aW91cyBkaXNj
dXNzaW9uIHNvbWUgdGltZSBiYWNrOg0KDQpodHRwczovL2xrbWwub3JnL2xrbWwvMjAxNC85Lzkv
Mjg0DQoNCidUaGUgcmVhc29uIGZvciB0aGVzZSBpcyBiZWNhdXNlIGZ1dHVyZSBwYXRjaGVzIHRv
IGFkZCBhZGRpdGlvbmFsIGZ1bmN0aW9uYWxpdHkNCndpbGwgaW50cm9kdWNlIEkyQyBhY2Nlc3Mg
ZnVuY3Rpb25zIHdoaWNoIGRvIG5vdCB1c2UgcmVnbWFwIGFuZCBhY2Nlc3MgdGhlDQpkZXZpY2Ug
dmlhIGEgc2VwYXJhdGUgSTJDIGFkZHJlc3MgZm9yIHRoaXMgcHVycG9zZS4gSSB3aWxsIG5lZWQg
dG8gcHJvdmlkZQ0KYWNjZXNzIGZ1bmN0aW9ucyBmb3IgdGhhdCwgYW5kIHNvIGhhdmluZyBhIGNv
bW1vbiBzdHlsZSBvZiBJMkMgYWNjZXNzIG1ha2VzDQpzZW5zZSBmb3IgdGhpcyBkcml2ZXIuIE1l
YW5zIGFueSBhY2Nlc3MganVzdCBuZWVkcyB0byBwcm92aWRlIHRoZSBNRkQgcHJpdmF0ZQ0KZGF0
YSwgYW5kIHRoZSByZWxldmFudCBmdW5jdGlvbnMgdGFrZSBjYXJlIG9mIHRoZSByZXN0LiBJIHRo
aW5rIHRoaXMgaXMgY2xlYW5lcg0KaW4gdGhpcyBpbnN0YW5jZS4nDQo=

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

* Re: [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device
  2015-01-19 13:23     ` Opensource [Adam Thomson]
@ 2015-01-20 10:50       ` Lee Jones
  0 siblings, 0 replies; 20+ messages in thread
From: Lee Jones @ 2015-01-20 10:50 UTC (permalink / raw)
  To: Opensource [Adam Thomson]
  Cc: Samuel Ortiz, Jonathan Cameron, Hartmut Knaack,
	linux-iio@vger.kernel.org, Sebastian Reichel,
	Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm@vger.kernel.org, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	devicetree@vger.kernel.org, Andrew Morton, Joe Perches,
	linux-kernel@vger.kernel.org, Support Opensource

On Mon, 19 Jan 2015, Opensource [Adam Thomson] wrote:

> On January 19, 2015 11:34, Lee Jones wrote:
> 
> > On Mon, 22 Dec 2014, Adam Thomson wrote:
> > 
> > > DA9150 is a combined Charger and Fuel-Gauge IC, with additional
> > > GPIO and GPADC functionality.
> > >
> > > Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
> > > ---
> > >  drivers/mfd/Kconfig                  |   12 +
> > >  drivers/mfd/Makefile                 |    2 +-
> > >  drivers/mfd/da9150-core.c            |  413 ++++++++++++
> > >  include/linux/mfd/da9150/core.h      |   68 ++
> > >  include/linux/mfd/da9150/registers.h | 1155
> > ++++++++++++++++++++++++++++++++++
> > >  5 files changed, 1649 insertions(+), 1 deletion(-)
> > >  create mode 100644 drivers/mfd/da9150-core.c
> > >  create mode 100644 include/linux/mfd/da9150/core.h
> > >  create mode 100644 include/linux/mfd/da9150/registers.h
> > >
> > > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> > > index 2e6b731..56e80d2 100644
> > > --- a/drivers/mfd/Kconfig
> > > +++ b/drivers/mfd/Kconfig
> > > @@ -195,6 +195,18 @@ config MFD_DA9063
> > >  	  Additional drivers must be enabled in order to use the functionality
> > >  	  of the device.
> > >
> > > +config MFD_DA9150
> > > +	tristate "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_DLN2
> > >  	tristate "Diolan DLN2 support"
> > >  	select MFD_CORE
> > > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> > > index 53467e2..f06f4c6 100644
> > > --- a/drivers/mfd/Makefile
> > > +++ b/drivers/mfd/Makefile
> > > @@ -113,7 +113,7 @@ 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
> > >  obj-$(CONFIG_MFD_MAX14577)	+= max14577.o
> > >  obj-$(CONFIG_MFD_MAX77686)	+= max77686.o
> > >  obj-$(CONFIG_MFD_MAX77693)	+= max77693.o
> > > diff --git a/drivers/mfd/da9150-core.c b/drivers/mfd/da9150-core.c
> > > new file mode 100644
> > > index 0000000..4d757b9
> > > --- /dev/null
> > > +++ b/drivers/mfd/da9150-core.c
> > > @@ -0,0 +1,413 @@
> > > +/*
> > > + * 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.
> > > + */
> > 
> > [...]
> > 
> > > +u8 da9150_reg_read(struct da9150 *da9150, u16 reg)
> > > +{
> > > +	int val, ret;
> > > +
> > > +	ret = regmap_read(da9150->regmap, reg, &val);
> > > +	if (ret)
> > > +		dev_err(da9150->dev, "Failed to read from reg 0x%x: %d\n",
> > > +			reg, ret);
> > > +
> > > +	return (u8) val;
> > > +}
> > > +EXPORT_SYMBOL_GPL(da9150_reg_read);
> > > +
> > > +void da9150_reg_write(struct da9150 *da9150, u16 reg, u8 val)
> > > +{
> > > +	int ret;
> > > +
> > > +	ret = regmap_write(da9150->regmap, reg, val);
> > > +	if (ret)
> > > +		dev_err(da9150->dev, "Failed to write to reg 0x%x: %d\n",
> > > +			reg, ret);
> > > +}
> > > +EXPORT_SYMBOL_GPL(da9150_reg_write);
> > > +
> > > +void 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)
> > > +		dev_err(da9150->dev, "Failed to set bits in reg 0x%x: %d\n",
> > > +			reg, ret);
> > > +}
> > > +EXPORT_SYMBOL_GPL(da9150_set_bits);
> > > +
> > > +void 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)
> > > +		dev_err(da9150->dev, "Failed to bulk read from reg 0x%x: %d\n",
> > > +			reg, ret);
> > > +}
> > > +EXPORT_SYMBOL_GPL(da9150_bulk_read);
> > > +
> > > +void 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)
> > > +		dev_err(da9150->dev, "Failed to bulk write to reg 0x%x %d\n",
> > > +			reg, ret);
> > > +}
> > > +EXPORT_SYMBOL_GPL(da9150_bulk_write);
> > 
> > I've never been a fan of this type of aggregation.  Can you explain to
> > me what the point of them is?
> 
> I refer you back to our previous discussion some time back:
> 
> https://lkml.org/lkml/2014/9/9/284
> 
> 'The reason for these is because future patches to add additional functionality
> will introduce I2C access functions which do not use regmap and access the
> device via a separate I2C address for this purpose. I will need to provide
> access functions for that, and so having a common style of I2C access makes
> sense for this driver. Means any access just needs to provide the MFD private
> data, and the relevant functions take care of the rest. I think this is cleaner
> in this instance.'

Well at least I'm consistent.

For my own reference:
  Acked-by: Lee Jones <lee.jones@linaro.org>

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

* Re: [PATCH v5 3/7] iio: Add support for DA9150 GPADC
  2015-01-14 11:30         ` Opensource [Adam Thomson]
@ 2015-01-20 20:49           ` Jonathan Cameron
  2015-01-21 11:02             ` Opensource [Adam Thomson]
  0 siblings, 1 reply; 20+ messages in thread
From: Jonathan Cameron @ 2015-01-20 20:49 UTC (permalink / raw)
  To: Opensource [Adam Thomson], Lee Jones, Samuel Ortiz,
	Hartmut Knaack, linux-iio@vger.kernel.org, Sebastian Reichel,
	Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm@vger.kernel.org, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	devicetree@vger.kernel.org, Andrew Morton, Joe Perches
  Cc: linux-kernel@vger.kernel.org, Support Opensource

On 14/01/15 11:30, Opensource [Adam Thomson] wrote:
> On January 10, 2015 22:19, Jonathan Cameron wrote:
> 
>> On 07/01/15 16:03, Opensource [Adam Thomson] wrote:
>>> On January 4, 2015 17:22, Jonathan Cameron wrote:
>>>
>>>> On 22/12/14 16:51, Adam Thomson wrote:
>>>>> This patch adds support for DA9150 Charger & Fuel-Gauge IC GPADC.
>>>>>
>>>>> Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
>>>> One last query from me.
>>>>
>>>> Using the extended channel names in IIO is only really appropriate when
>>>> they don't correspond to simple pins on the side of the chip. For those
>>>> just drop the extname bit.  Some of the channels you have here, definitely
>>>> need them though.
>>>>
>>>> Drop those first 4 or convince me otherwise and add
>>>> Acked-by: Jonathan Cameron <jic23@kernel.org>
>>>
>>> Have added responses below. If the comments are accepted then I'll respin
>>> and add you're 'Acked-by'. Is that ok?
>>>
>> Not accepted as yet :)
> 
> Yeah, that's why I added the 'if'. :)
> 
>>>>> +#define DA9150_GPADC_CHANNEL_PROCESSED(_id, _hw_id, _type,
>> _ext_name)
>>>> 	\
>>>>> +	DA9150_GPADC_CHANNEL(_id, _hw_id, _type,			\
>>>>> +			     BIT(IIO_CHAN_INFO_PROCESSED), _ext_name)
>>>>> +
>>>>> +/* Supported channels */
>>>>> +static const struct iio_chan_spec da9150_gpadc_channels[] = {
>>>>> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOA, GPIOA_6V, IIO_VOLTAGE,
>>>> "GPIOA"),
>>>>> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOB, GPIOB_6V, IIO_VOLTAGE,
>>>> "GPIOB"),
>>>>> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOC, GPIOC_6V, IIO_VOLTAGE,
>>>> "GPIOC"),
>>>>> +	DA9150_GPADC_CHANNEL_PROCESSED(GPIOD, GPIOD_6V, IIO_VOLTAGE,
>>>> "GPIOD"),
>>>> I'm not sure some of these really deserve extended names.  Those are usually
>>>> reserved for naming strange internal adc channels etc.  These first 4 are
>>>> presumably just for input pins?  Those should just be channels 0..3
>>>> On another note, unless you want really weird sysfs attribute names, the
>>>> extended names want to be lowercase.
>>>>
>>>
>>> I'd prefer to keep the names because the input pins are muxed with GPIOs of the
>>> chip, so thought it sensible to show that this is the case. Am happy to change
>>> to lower-case to follow convention.
>> Hmm.  It's a bit of an oddity as the point of the naming
>> is about the uses, not which pins they are on.  If we exposed the
>> 'datasheet_name' parameter directly rather than just using it internally
>> I'd suggest relying on that - but clearly you want it to be apparent
>> in the interface.  Whether that is useful is the question I'd raise
>> here (and is the reason datasheet_name is not exposed.
>>
>> The obvious question is does userspace care?  Answer is probably not.
>>
>> It cares what is being measured but this is about what pins it is
>> on and doesn't provide any information on what is connected to them.
>>
> 
> Surely it helps when using sysfs to access whatever is connected to one of
> those pins if we label the pin with something meaningful? If say you have a
> device connected to GPIC of the charger IC, it's easier to work out which ADC
> channel you need to access through sysfs if the naming is as I have now, rather
> than some arbitrary number which doesn't necessarily tally to the channel in the
> datasheet. You'd then need to look at the code and work out which channel number
> GPIOC actually was. Or am I just missing something here? :)
Not really for the vast majority of users.  They tend not to have a detailed
board layout in front of them.  It's more interesting if you know 'what' they
are measuring (hence we do use these names when that is true - such as
internal voltage measurements).

The numbers almost never tally with the datasheet, but then datasheet numbering
has a habit of being inconsistent as well!
> 
>>
>>>
>>>>> +	DA9150_GPADC_CHANNEL_PROCESSED(IBUS, IBUS_SENSE, IIO_CURRENT,
>>>> "IBUS"),
>>>>> +	DA9150_GPADC_CHANNEL_PROCESSED(VBUS, VBUS_DIV_, IIO_VOLTAGE,
>>>> "VBUS"),
>>>>> +	DA9150_GPADC_CHANNEL_RAW(ID, ID, IIO_VOLTAGE, "ID"),
>>>> You hae an identifier voltage? That's certainly unusual but if so - fair enough
>>>> and it defintely needs the extname!
>>>
>>> Thanks for pointing that out. Having checked again, this is not needed and can
>>> be dispensed with.
>>>
>>>>> +	DA9150_GPADC_CHANNEL_PROCESSED(VSYS, VSYS, IIO_VOLTAGE, "VSYS"),
>>>>> +	DA9150_GPADC_CHANNEL_SCALED(VBAT, VBAT, IIO_VOLTAGE, "VBAT"),
>>>>> +	DA9150_GPADC_CHANNEL_RAW(TBAT, TBAT, IIO_VOLTAGE, "TBAT"),
>>>>> +	DA9150_GPADC_CHANNEL_SCALED(TJUNC_CORE, TJUNC_CORE,
>>>> IIO_TEMP,
>>>>> +				    "TJUNC_CORE"),
>>>> tjunc_core is a good use of extname ;)
>>>>> +	DA9150_GPADC_CHANNEL_SCALED(TJUNC_OVP, 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",
>>>>> +	},
>>>>> +	{
>>>>> +		.consumer_dev_name = "da9150-charger",
>>>>> +		.consumer_channel = "CHAN_VBUS",
>>>>> +		.adc_channel_label = "VBUS",
>>>>> +	},
>>>>> +	{
>>>>> +		.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",
>>>>> +	},
>>>>> +	{},
>>>>> +};
>>>>> +
>>>>> +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 irq, ret;
>>>>> +
>>>>> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*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;
>>>>> +	mutex_init(&gpadc->lock);
>>>>> +	init_completion(&gpadc->complete);
>>>>> +
>>>>> +	irq = platform_get_irq_byname(pdev, "GPADC");
>>>>> +	if (irq < 0) {
>>>>> +		dev_err(dev, "Failed to get IRQ: %d\n", irq);
>>>>> +		return irq;
>>>>> +	}
>>>>> +
>>>>> +	ret = devm_request_threaded_irq(dev, irq, NULL, da9150_gpadc_irq,
>>>>> +					IRQF_ONESHOT, "GPADC", gpadc);
>>>>> +	if (ret) {
>>>>> +		dev_err(dev, "Failed to request IRQ %d: %d\n", irq, ret);
>>>>> +		return ret;
>>>>> +	}
>>>>> +
>>>>> +	ret = iio_map_array_register(indio_dev, da9150_gpadc_default_maps);
>>>>> +	if (ret) {
>>>>> +		dev_err(dev, "Failed to register IIO maps: %d\n", ret);
>>>>> +		return ret;
>>>>> +	}
>>>>> +
>>>>> +	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_map_unreg;
>>>>> +	}
>>>>> +
>>>>> +	return 0;
>>>>> +
>>>>> +iio_map_unreg:
>>>>> +	iio_map_array_unregister(indio_dev);
>>>>> +
>>>>> +	return ret;
>>>>> +}
>>>>> +
>>>>> +static int da9150_gpadc_remove(struct platform_device *pdev)
>>>>> +{
>>>>> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>>>>> +
>>>>> +	iio_device_unregister(indio_dev);
>>>>> +	iio_map_array_unregister(indio_dev);
>>>>> +
>>>>> +	return 0;
>>>>> +}
>>>>> +
>>>>> +static struct platform_driver da9150_gpadc_driver = {
>>>>> +	.driver = {
>>>>> +		.name = "da9150-gpadc",
>>>>> +	},
>>>>> +	.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");
>>>>> --
>>>>> 1.9.3
>>>>>


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

* RE: [PATCH v5 3/7] iio: Add support for DA9150 GPADC
  2015-01-20 20:49           ` Jonathan Cameron
@ 2015-01-21 11:02             ` Opensource [Adam Thomson]
  0 siblings, 0 replies; 20+ messages in thread
From: Opensource [Adam Thomson] @ 2015-01-21 11:02 UTC (permalink / raw)
  To: Jonathan Cameron, Opensource [Adam Thomson], Lee Jones,
	Samuel Ortiz, Hartmut Knaack, linux-iio@vger.kernel.org,
	Sebastian Reichel, Dmitry Eremin-Solenikov, David Woodhouse,
	linux-pm@vger.kernel.org, Rob Herring, Pawel Moll, Mark Rutland,
	Ian Campbell, Kumar Gala, Grant Likely,
	devicetree@vger.kernel.org, Andrew Morton, Joe Perches
  Cc: linux-kernel@vger.kernel.org, Support Opensource

T24gSmFudWFyeSAyMCwgMjAxNSAyMDo0OSwgSm9uYXRoYW4gQ2FtZXJvbiB3cm90ZToNCg0KPiA+
Pj4+PiArI2RlZmluZSBEQTkxNTBfR1BBRENfQ0hBTk5FTF9QUk9DRVNTRUQoX2lkLCBfaHdfaWQs
IF90eXBlLA0KPiA+PiBfZXh0X25hbWUpDQo+ID4+Pj4gCVwNCj4gPj4+Pj4gKwlEQTkxNTBfR1BB
RENfQ0hBTk5FTChfaWQsIF9od19pZCwgX3R5cGUsCQkJXA0KPiA+Pj4+PiArCQkJICAgICBCSVQo
SUlPX0NIQU5fSU5GT19QUk9DRVNTRUQpLCBfZXh0X25hbWUpDQo+ID4+Pj4+ICsNCj4gPj4+Pj4g
Ky8qIFN1cHBvcnRlZCBjaGFubmVscyAqLw0KPiA+Pj4+PiArc3RhdGljIGNvbnN0IHN0cnVjdCBp
aW9fY2hhbl9zcGVjIGRhOTE1MF9ncGFkY19jaGFubmVsc1tdID0gew0KPiA+Pj4+PiArCURBOTE1
MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NFRChHUElPQSwgR1BJT0FfNlYsIElJT19WT0xUQUdFLA0K
PiA+Pj4+ICJHUElPQSIpLA0KPiA+Pj4+PiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NF
RChHUElPQiwgR1BJT0JfNlYsIElJT19WT0xUQUdFLA0KPiA+Pj4+ICJHUElPQiIpLA0KPiA+Pj4+
PiArCURBOTE1MF9HUEFEQ19DSEFOTkVMX1BST0NFU1NFRChHUElPQywgR1BJT0NfNlYsIElJT19W
T0xUQUdFLA0KPiA+Pj4+ICJHUElPQyIpLA0KPiA+Pj4+PiArCURBOTE1MF9HUEFEQ19DSEFOTkVM
X1BST0NFU1NFRChHUElPRCwgR1BJT0RfNlYsIElJT19WT0xUQUdFLA0KPiA+Pj4+ICJHUElPRCIp
LA0KPiA+Pj4+IEknbSBub3Qgc3VyZSBzb21lIG9mIHRoZXNlIHJlYWxseSBkZXNlcnZlIGV4dGVu
ZGVkIG5hbWVzLiAgVGhvc2UgYXJlIHVzdWFsbHkNCj4gPj4+PiByZXNlcnZlZCBmb3IgbmFtaW5n
IHN0cmFuZ2UgaW50ZXJuYWwgYWRjIGNoYW5uZWxzIGV0Yy4gIFRoZXNlIGZpcnN0IDQgYXJlDQo+
ID4+Pj4gcHJlc3VtYWJseSBqdXN0IGZvciBpbnB1dCBwaW5zPyAgVGhvc2Ugc2hvdWxkIGp1c3Qg
YmUgY2hhbm5lbHMgMC4uMw0KPiA+Pj4+IE9uIGFub3RoZXIgbm90ZSwgdW5sZXNzIHlvdSB3YW50
IHJlYWxseSB3ZWlyZCBzeXNmcyBhdHRyaWJ1dGUgbmFtZXMsIHRoZQ0KPiA+Pj4+IGV4dGVuZGVk
IG5hbWVzIHdhbnQgdG8gYmUgbG93ZXJjYXNlLg0KPiA+Pj4+DQo+ID4+Pg0KPiA+Pj4gSSdkIHBy
ZWZlciB0byBrZWVwIHRoZSBuYW1lcyBiZWNhdXNlIHRoZSBpbnB1dCBwaW5zIGFyZSBtdXhlZCB3
aXRoIEdQSU9zIG9mIHRoZQ0KPiA+Pj4gY2hpcCwgc28gdGhvdWdodCBpdCBzZW5zaWJsZSB0byBz
aG93IHRoYXQgdGhpcyBpcyB0aGUgY2FzZS4gQW0gaGFwcHkgdG8gY2hhbmdlDQo+ID4+PiB0byBs
b3dlci1jYXNlIHRvIGZvbGxvdyBjb252ZW50aW9uLg0KPiA+PiBIbW0uICBJdCdzIGEgYml0IG9m
IGFuIG9kZGl0eSBhcyB0aGUgcG9pbnQgb2YgdGhlIG5hbWluZw0KPiA+PiBpcyBhYm91dCB0aGUg
dXNlcywgbm90IHdoaWNoIHBpbnMgdGhleSBhcmUgb24uICBJZiB3ZSBleHBvc2VkIHRoZQ0KPiA+
PiAnZGF0YXNoZWV0X25hbWUnIHBhcmFtZXRlciBkaXJlY3RseSByYXRoZXIgdGhhbiBqdXN0IHVz
aW5nIGl0IGludGVybmFsbHkNCj4gPj4gSSdkIHN1Z2dlc3QgcmVseWluZyBvbiB0aGF0IC0gYnV0
IGNsZWFybHkgeW91IHdhbnQgaXQgdG8gYmUgYXBwYXJlbnQNCj4gPj4gaW4gdGhlIGludGVyZmFj
ZS4gIFdoZXRoZXIgdGhhdCBpcyB1c2VmdWwgaXMgdGhlIHF1ZXN0aW9uIEknZCByYWlzZQ0KPiA+
PiBoZXJlIChhbmQgaXMgdGhlIHJlYXNvbiBkYXRhc2hlZXRfbmFtZSBpcyBub3QgZXhwb3NlZC4N
Cj4gPj4NCj4gPj4gVGhlIG9idmlvdXMgcXVlc3Rpb24gaXMgZG9lcyB1c2Vyc3BhY2UgY2FyZT8g
IEFuc3dlciBpcyBwcm9iYWJseSBub3QuDQo+ID4+DQo+ID4+IEl0IGNhcmVzIHdoYXQgaXMgYmVp
bmcgbWVhc3VyZWQgYnV0IHRoaXMgaXMgYWJvdXQgd2hhdCBwaW5zIGl0IGlzDQo+ID4+IG9uIGFu
ZCBkb2Vzbid0IHByb3ZpZGUgYW55IGluZm9ybWF0aW9uIG9uIHdoYXQgaXMgY29ubmVjdGVkIHRv
IHRoZW0uDQo+ID4+DQo+ID4NCj4gPiBTdXJlbHkgaXQgaGVscHMgd2hlbiB1c2luZyBzeXNmcyB0
byBhY2Nlc3Mgd2hhdGV2ZXIgaXMgY29ubmVjdGVkIHRvIG9uZSBvZg0KPiA+IHRob3NlIHBpbnMg
aWYgd2UgbGFiZWwgdGhlIHBpbiB3aXRoIHNvbWV0aGluZyBtZWFuaW5nZnVsPyBJZiBzYXkgeW91
IGhhdmUgYQ0KPiA+IGRldmljZSBjb25uZWN0ZWQgdG8gR1BJQyBvZiB0aGUgY2hhcmdlciBJQywg
aXQncyBlYXNpZXIgdG8gd29yayBvdXQgd2hpY2ggQURDDQo+ID4gY2hhbm5lbCB5b3UgbmVlZCB0
byBhY2Nlc3MgdGhyb3VnaCBzeXNmcyBpZiB0aGUgbmFtaW5nIGlzIGFzIEkgaGF2ZSBub3csIHJh
dGhlcg0KPiA+IHRoYW4gc29tZSBhcmJpdHJhcnkgbnVtYmVyIHdoaWNoIGRvZXNuJ3QgbmVjZXNz
YXJpbHkgdGFsbHkgdG8gdGhlIGNoYW5uZWwgaW4gdGhlDQo+ID4gZGF0YXNoZWV0LiBZb3UnZCB0
aGVuIG5lZWQgdG8gbG9vayBhdCB0aGUgY29kZSBhbmQgd29yayBvdXQgd2hpY2ggY2hhbm5lbA0K
PiBudW1iZXINCj4gPiBHUElPQyBhY3R1YWxseSB3YXMuIE9yIGFtIEkganVzdCBtaXNzaW5nIHNv
bWV0aGluZyBoZXJlPyA6KQ0KPiBOb3QgcmVhbGx5IGZvciB0aGUgdmFzdCBtYWpvcml0eSBvZiB1
c2Vycy4gIFRoZXkgdGVuZCBub3QgdG8gaGF2ZSBhIGRldGFpbGVkDQo+IGJvYXJkIGxheW91dCBp
biBmcm9udCBvZiB0aGVtLiAgSXQncyBtb3JlIGludGVyZXN0aW5nIGlmIHlvdSBrbm93ICd3aGF0
JyB0aGV5DQo+IGFyZSBtZWFzdXJpbmcgKGhlbmNlIHdlIGRvIHVzZSB0aGVzZSBuYW1lcyB3aGVu
IHRoYXQgaXMgdHJ1ZSAtIHN1Y2ggYXMNCj4gaW50ZXJuYWwgdm9sdGFnZSBtZWFzdXJlbWVudHMp
Lg0KPiANCj4gVGhlIG51bWJlcnMgYWxtb3N0IG5ldmVyIHRhbGx5IHdpdGggdGhlIGRhdGFzaGVl
dCwgYnV0IHRoZW4gZGF0YXNoZWV0IG51bWJlcmluZw0KPiBoYXMgYSBoYWJpdCBvZiBiZWluZyBp
bmNvbnNpc3RlbnQgYXMgd2VsbCENCg0KQ2FuJ3Qgc2F5IEkgYWdyZWUgdGhhdCB0aGlzIHdvbid0
IGJlIHVzZWZ1bC9pbmZvcm1hdGl2ZSB0byBtYW55IHVzZXJzLCBidXQgZG9uJ3QNCndhbnQgdG8g
bWFrZSB0aGlzIGEgc3RpY2tpbmcgcG9pbnQgc28gd2lsbCB1cGRhdGUuDQo=

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

end of thread, other threads:[~2015-01-21 11:02 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-22 16:50 [PATCH v5 0/7] Add initial support for DA9150 Charger & Fuel-Gauge IC Adam Thomson
2014-12-22 16:51 ` [PATCH v5 1/7] mfd: Add support for DA9150 combined charger & fuel-gauge device Adam Thomson
2015-01-19 11:33   ` Lee Jones
2015-01-19 13:23     ` Opensource [Adam Thomson]
2015-01-20 10:50       ` Lee Jones
2014-12-22 16:51 ` [PATCH v5 2/7] mfd: da9150: Add DT binding documentation for core Adam Thomson
2014-12-22 16:51 ` [PATCH v5 3/7] iio: Add support for DA9150 GPADC Adam Thomson
2015-01-01 20:51   ` Hartmut Knaack
2015-01-04 17:22   ` Jonathan Cameron
2015-01-07 16:03     ` Opensource [Adam Thomson]
2015-01-10 22:19       ` Jonathan Cameron
2015-01-14 11:30         ` Opensource [Adam Thomson]
2015-01-20 20:49           ` Jonathan Cameron
2015-01-21 11:02             ` Opensource [Adam Thomson]
2014-12-22 16:51 ` [PATCH v5 4/7] iio: da9150: Add DT binding documentation for GPADC Adam Thomson
2014-12-22 16:51 ` [PATCH v5 5/7] power: Add support for DA9150 Charger Adam Thomson
2015-01-04 17:26   ` Jonathan Cameron
2015-01-07 16:04     ` Opensource [Adam Thomson]
2014-12-22 16:51 ` [PATCH v5 6/7] power: da9150: Add DT binding documentation for charger Adam Thomson
2014-12-22 16:51 ` [PATCH v5 7/7] MAINTAINERS: Include DA9150 files in Dialog Semiconductor support list 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).