public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] added support for ams AS3722 PMIC in mfd
@ 2013-08-14 14:54 Florian Lobmaier
  2013-08-14 14:54 ` [PATCH 2/4] added regmap of AS3722 Florian Lobmaier
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Florian Lobmaier @ 2013-08-14 14:54 UTC (permalink / raw)
  To: linux-kernel; +Cc: sameo, lee.jones, Florian Lobmaier

now using git send-email and splitted mfd patch into multiple patches (4).
Suggestions from 23.05.2013 added.

Signed-off-by: Florian Lobmaier <florian.lobmaier@ams.com>
---
 drivers/mfd/Kconfig       |   15 +
 drivers/mfd/Makefile      |    1 +
 drivers/mfd/as3722-core.c |  747 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 763 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/as3722-core.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index aecd6dd..a02777c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -27,6 +27,21 @@ config MFD_AS3711
 	help
 	  Support for the AS3711 PMIC from AMS
 
+config MFD_AS3722
+        tristate "Support for ams AS3722 PMIC"
+        select MFD_CORE
+        select REGMAP_I2C
+        select REGMAP_IRQ
+        depends on I2C=y
+        help
+          Core support for the ams AS3722 PMIC. Additional
+          drivers must be enabled in order to use the functionality of the
+          device.
+          Related drivers are:
+                * ams AS3722 PMIC regulators
+                * ams AS3722 GPIO
+                * ams AS3722 RTC
+
 config PMIC_ADP5520
 	bool "Analog Devices ADP5520/01 MFD PMIC Core Support"
 	depends on I2C=y
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 3c90051..358e46e 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -159,3 +159,4 @@ obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
 obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o vexpress-sysreg.o
 obj-$(CONFIG_MFD_RETU)		+= retu-mfd.o
 obj-$(CONFIG_MFD_AS3711)	+= as3711.o
+obj-$(CONFIG_MFD_AS3722)        += as3722-core.o as3722-regmap.o
diff --git a/drivers/mfd/as3722-core.c b/drivers/mfd/as3722-core.c
new file mode 100644
index 0000000..ddb39c7
--- /dev/null
+++ b/drivers/mfd/as3722-core.c
@@ -0,0 +1,747 @@
+/*
+ * as3722-core.c - core driver for AS3722 PMICs
+ *
+ * Copyright (C) 2013 ams AG
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/mfd/core.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/as3722-reg.h>
+#include <linux/mfd/as3722-plat.h>
+
+enum as3722_ids {
+	AS3722_GPIO_ID,
+	AS3722_REGULATOR_ID,
+	AS3722_RTC_ID,
+	AS3722_WATCHDOG_ID,
+	AS3722_PWM_ID,
+};
+
+static const struct resource as3722_rtc_resource[] = {
+	{
+		.name = "as3722-rtc-alarm",
+		.start = AS3722_IRQ_RTC_ALARM,
+		.end = AS3722_IRQ_RTC_ALARM,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static const struct resource as3722_wdt_resource[] = {
+	{
+		.name = "as3722-watchdog-ping",
+		.start = AS3722_IRQ_WATCHDOG,
+		.end = AS3722_IRQ_WATCHDOG,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct mfd_cell as3722_devs[] = {
+	{
+		.name = "as3722-gpio",
+		.id = AS3722_GPIO_ID,
+	},
+	{
+		.name = "as3722-regulator",
+		.id = AS3722_REGULATOR_ID,
+	},
+	{
+		.name = "as3722-rtc",
+		.num_resources = ARRAY_SIZE(as3722_rtc_resource),
+		.resources = as3722_rtc_resource,
+		.id = AS3722_RTC_ID,
+	},
+	{
+		.name = "as3722-wdt",
+		.num_resources = ARRAY_SIZE(as3722_wdt_resource),
+		.resources = as3722_wdt_resource,
+		.id = AS3722_WATCHDOG_ID,
+	},
+	{
+		.name = "as3722-pwm",
+		.id = AS3722_PWM_ID,
+	},
+};
+
+static const struct regmap_irq as3722_irqs[] = {
+	/* INT1 IRQs */
+	[AS3722_IRQ_LID] = {
+		.mask = AS3722_IRQ_MASK_LID,
+	},
+	[AS3722_IRQ_ACOK] = {
+		.mask = AS3722_IRQ_MASK_ACOK,
+	},
+	[AS3722_IRQ_ENABLE1] = {
+		.mask = AS3722_IRQ_MASK_ENABLE1,
+	},
+	[AS3722_IRQ_SD0] = {
+		.mask = AS3722_IRQ_MASK_SD0,
+	},
+	[AS3722_IRQ_ONKEY_LONG] = {
+		.mask = AS3722_IRQ_MASK_ONKEY_LONG,
+	},
+	[AS3722_IRQ_ONKEY] = {
+		.mask = AS3722_IRQ_MASK_ONKEY,
+	},
+	[AS3722_IRQ_OVTMP] = {
+		.mask = AS3722_IRQ_MASK_OVTMP,
+	},
+	[AS3722_IRQ_LOWBAT] = {
+		.mask = AS3722_IRQ_MASK_LOWBAT,
+	},
+	[AS3722_IRQ_RTC_REP] = {
+		.mask = AS3722_IRQ_MASK_RTC_REP,
+		.reg_offset = 1,
+	},
+	[AS3722_IRQ_RTC_ALARM] = {
+		.mask = AS3722_IRQ_MASK_RTC_ALARM,
+		.reg_offset = 2,
+	},
+	[AS3722_IRQ_WATCHDOG] = {
+		.mask = AS3722_IRQ_MASK_WATCHDOG,
+		.reg_offset = 2,
+	},
+	[AS3722_IRQ_ADC] = {
+		.mask = AS3722_IRQ_MASK_ADC,
+		.reg_offset = 3,
+	},
+	[AS3722_IRQ_GPIO1] = {
+		.mask = AS3722_IRQ_MASK_GPIO1,
+		.reg_offset = 2,
+	},
+	[AS3722_IRQ_GPIO2] = {
+		.mask = AS3722_IRQ_MASK_GPIO2,
+		.reg_offset = 2,
+	},
+	[AS3722_IRQ_GPIO3] = {
+		.mask = AS3722_IRQ_MASK_GPIO3,
+		.reg_offset = 2,
+	},
+	[AS3722_IRQ_GPIO4] = {
+		.mask = AS3722_IRQ_MASK_GPIO4,
+		.reg_offset = 2,
+	},
+	[AS3722_IRQ_GPIO5] = {
+		.mask = AS3722_IRQ_MASK_GPIO5,
+		.reg_offset = 2,
+	},
+	[AS3722_IRQ_TEMP_SD0_SHUTDOWN] = {
+		.mask = AS3722_IRQ_MASK_TEMP_SD0_SHUTDOWN,
+		.reg_offset = 3,
+	},
+	[AS3722_IRQ_TEMP_SD1_SHUTDOWN] = {
+		.mask = AS3722_IRQ_MASK_TEMP_SD1_SHUTDOWN,
+		.reg_offset = 3,
+	},
+	[AS3722_IRQ_TEMP_SD6_SHUTDOWN] = {
+		.mask = AS3722_IRQ_MASK_TEMP_SD6_SHUTDOWN,
+		.reg_offset = 3,
+	},
+	[AS3722_IRQ_TEMP_SD0_ALARM] = {
+		.mask = AS3722_IRQ_MASK_TEMP_SD0_ALARM,
+		.reg_offset = 3,
+	},
+	[AS3722_IRQ_TEMP_SD1_ALARM] = {
+		.mask = AS3722_IRQ_MASK_TEMP_SD1_ALARM,
+		.reg_offset = 3,
+	},
+	[AS3722_IRQ_TEMP_SD6_ALARM] = {
+		.mask = AS3722_IRQ_MASK_TEMP_SD6_ALARM,
+		.reg_offset = 3,
+	},
+};
+
+static struct regmap_irq_chip as3722_irq_chip = {
+	.name = "as3722",
+	.irqs = as3722_irqs,
+	.num_irqs = ARRAY_SIZE(as3722_irqs),
+	.num_regs = 4,
+	.status_base = AS3722_INTERRUPTSTATUS1_REG,
+	.mask_base = AS3722_INTERRUPTMASK1_REG,
+	.wake_base = 1,
+};
+
+static void as3722_reg_init(struct as3722 *as3722,
+		struct as3722_reg_init *reg_data)
+{
+	int ret;
+
+	while (reg_data->reg != AS3722_REG_INIT_TERMINATE) {
+		ret = as3722_reg_write(as3722, reg_data->reg, reg_data->val);
+		if (ret) {
+			dev_err(as3722->dev,
+					"reg setup failed: %d\n", ret);
+			return;
+		}
+		reg_data++;
+	}
+}
+
+int as3722_read_adc(struct as3722 *as3722,
+		enum as3722_adc_channel channel,
+		enum as3722_adc_source source,
+		enum as3722_adc_voltange_range voltage_range)
+{
+	int result = 0;
+	unsigned int try_counter = 0;
+	u32 val;
+
+	mutex_lock(&as3722->adc_mutex);
+	/* select source */
+	as3722_set_bits(as3722,
+			AS3722_ADC0_CONTROL_REG + channel,
+			AS3722_ADC_MASK_SOURCE_SELECT,
+			source);
+	/* select voltage range */
+	as3722_set_bits(as3722,
+			AS3722_ADC0_CONTROL_REG + channel,
+			AS3722_ADC_MASK_VOLTAGE_RANGE,
+			voltage_range << AS3722_ADC_SHIFT_VOLTAGE_RANGE);
+	/* start conversion */
+	as3722_set_bits(as3722,
+			AS3722_ADC0_CONTROL_REG + channel,
+			AS3722_ADC_MASK_CONV_START,
+			AS3722_ADC_BIT_CONV_START);
+
+	/*
+	 * check if result ready
+	 * as no HW interrupt is available we have to poll
+	 * the status bit. The result is available on the next I2C read
+	 * at 400kHz I2C speed, so no threaded polling required.
+	 */
+	try_counter = 0;
+	do {
+		/* 2*channel for correct channel nr.1 read offset */
+		as3722_reg_read(as3722,
+				AS3722_ADC0_MSB_RESULT_REG + 2*channel,
+				&val);
+		/* check if conversion is ready */
+		if ((val & AS3722_ADC_MASK_CONV_NOTREADY)
+		     != AS3722_ADC_BIT_CONV_NOTREADY
+		   )
+			break;	/* conversion ready */
+		/*
+		 * if not, we try  max. 10 times which ensures
+		 * that it works up to 4MHz I2C speed and that
+		 * we stop if something goes wrong
+		 */
+		try_counter++;
+	} while (try_counter < 10);
+
+	/* read result, MSB byte already available from last read */
+	result = ((val & AS3722_ADC_MASK_MSB_VAL) << 8);
+	as3722_reg_read(as3722,
+			AS3722_ADC0_LSB_RESULT_REG + 2*channel,
+			&val);
+	result += (val & AS3722_ADC_MASK_LSB_VAL);
+
+	mutex_unlock(&as3722->adc_mutex);
+
+	return result;
+}
+EXPORT_SYMBOL_GPL(as3722_read_adc);
+
+static irqreturn_t as3722_onkey_press_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 ONKEY pressed\n");
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as3722_onkey_lpress_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 ONKEY long pressed\n");
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as3722_temp_sd0_shutdown_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 temp SD0 shutdown triggered\n");
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as3722_temp_sd1_shutdown_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 temp SD1 shutdown triggered\n");
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as3722_temp_sd6_shutdown_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 temp SD6 shutdown triggered\n");
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as3722_temp_sd0_alarm_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 temp SD0 alarm triggered\n");
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as3722_temp_sd1_alarm_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 temp SD1 alarm triggered\n");
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as3722_temp_sd6_alarm_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 temp SD6 alarm triggered\n");
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t as3722_ovtmp_alarm_irq(int irq, void *irq_data)
+{
+	struct as3722 *as3722 = irq_data;
+
+	dev_dbg(as3722->dev, "AS3722 ovtmp alarm triggered\n");
+	return IRQ_HANDLED;
+}
+
+static int as3722_init(struct as3722 *as3722,
+		struct as3722_platform_data *pdata, int irq)
+{
+	u32 reg;
+	int ret;
+	int irq_onkey, irq_onkeylong;
+	int irq_temp_sd0_shutdown, irq_temp_sd1_shutdown, irq_temp_sd6_shutdown;
+	int irq_temp_sd0_alarm, irq_temp_sd1_alarm, irq_temp_sd6_alarm;
+	int irq_ovtmp_alarm;
+
+	/* Check that this is actually a AS3722 */
+	ret = regmap_read(as3722->regmap, AS3722_ADDR_ASIC_ID1, &reg);
+	if (ret != 0) {
+		dev_err(as3722->dev,
+			"Chip ID register read failed\n");
+		return ret;
+	}
+	if (reg != AS3722_DEVICE_ID) {
+		dev_err(as3722->dev,
+			"Device is not an AS3722, ID is 0x%x\n",
+			reg);
+		return -ENODEV;
+	}
+
+	ret = regmap_read(as3722->regmap, AS3722_ADDR_ASIC_ID2, &reg);
+	if (ret != 0) {
+		dev_err(as3722->dev,
+			"ID2 register read failed: %d\n",
+			ret);
+		return ret;
+	}
+	dev_info(as3722->dev, "AS3722 with revision %x found\n", reg);
+
+	/* init adc mutex */
+	mutex_init(&as3722->adc_mutex);
+
+	/* request irqs for onkey and over temperature */
+	if (as3722->irq_data) {
+		irq_onkey = regmap_irq_get_virq(as3722->irq_data,
+						AS3722_IRQ_ONKEY);
+		ret = request_threaded_irq(irq_onkey,
+					   NULL,
+					   as3722_onkey_press_irq,
+					   pdata->irq_type,
+					   "onkey-press",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request ONKEY IRQ: %d\n",
+				 ret);
+
+		irq_onkeylong = regmap_irq_get_virq(as3722->irq_data,
+						    AS3722_IRQ_ONKEY_LONG);
+		ret = request_threaded_irq(irq_onkeylong,
+					   NULL,
+					   as3722_onkey_lpress_irq,
+					   pdata->irq_type,
+					   "onkey-lpress",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request ONKEY_LONG IRQ: %d\n",
+				 ret);
+
+		irq_temp_sd0_shutdown =
+			regmap_irq_get_virq(as3722->irq_data,
+					    AS3722_IRQ_TEMP_SD0_SHUTDOWN);
+		ret = request_threaded_irq(irq_temp_sd0_shutdown,
+					   NULL,
+					   as3722_temp_sd0_shutdown_irq,
+					   pdata->irq_type,
+					   "temp sd0 shutdown",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request temp sd0 shutdown IRQ:"
+				 " %d\n",
+				 ret);
+		irq_temp_sd1_shutdown =
+			regmap_irq_get_virq(as3722->irq_data,
+					    AS3722_IRQ_TEMP_SD1_SHUTDOWN);
+		ret = request_threaded_irq(irq_temp_sd1_shutdown,
+					   NULL,
+					   as3722_temp_sd1_shutdown_irq,
+					   pdata->irq_type,
+					   "temp sd1 shutdown",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request temp sd1 shutdown IRQ:"
+				 " %d\n",
+				 ret);
+		irq_temp_sd6_shutdown =
+			regmap_irq_get_virq(as3722->irq_data,
+					    AS3722_IRQ_TEMP_SD6_SHUTDOWN);
+		ret = request_threaded_irq(irq_temp_sd6_shutdown,
+					   NULL,
+					   as3722_temp_sd6_shutdown_irq,
+					   pdata->irq_type,
+					   "temp sd6 shutdown",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request temp sd6 shutdown IRQ:"
+				 " %d\n",
+				 ret);
+		irq_temp_sd0_alarm =
+			regmap_irq_get_virq(as3722->irq_data,
+					    AS3722_IRQ_TEMP_SD0_ALARM);
+		ret = request_threaded_irq(irq_temp_sd0_alarm,
+					   NULL,
+					   as3722_temp_sd0_alarm_irq,
+					   pdata->irq_type,
+					   "temp sd0 alarm",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request temp sd0 alarm IRQ:"
+				 " %d\n",
+				 ret);
+
+		irq_temp_sd1_alarm =
+			regmap_irq_get_virq(as3722->irq_data,
+					    AS3722_IRQ_TEMP_SD1_ALARM);
+		ret = request_threaded_irq(irq_temp_sd1_alarm,
+					   NULL,
+					   as3722_temp_sd1_alarm_irq,
+					   pdata->irq_type,
+					   "temp sd1 alarm",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request temp sd1 alarm IRQ:"
+				 " %d\n",
+				 ret);
+		irq_temp_sd6_alarm =
+			regmap_irq_get_virq(as3722->irq_data,
+					    AS3722_IRQ_TEMP_SD6_ALARM);
+		ret = request_threaded_irq(irq_temp_sd6_alarm,
+					   NULL,
+					   as3722_temp_sd6_alarm_irq,
+					   pdata->irq_type,
+					   "temp sd6 alarm",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request temp sd6 alarm IRQ:"
+				 " %d\n",
+				 ret);
+
+		irq_ovtmp_alarm =
+			regmap_irq_get_virq(as3722->irq_data,
+					    AS3722_IRQ_OVTMP);
+		ret = request_threaded_irq(irq_ovtmp_alarm,
+					   NULL,
+					   as3722_ovtmp_alarm_irq,
+					   pdata->irq_type,
+					   "ovtmp alarm",
+					   as3722);
+		if (ret < 0)
+			dev_warn(as3722->dev,
+				 "Failed to request ovtmp alarm IRQ:"
+				 " %d\n",
+				 ret);
+	}
+
+	/* do some initial platform register setup */
+	if (pdata->core_init_data)
+		as3722_reg_init(as3722, pdata->core_init_data);
+
+	/* initialise stby reg count variable, used in regulator */
+	as3722->reg_stby_counter = 0;
+
+	/* enable pullups if required */
+	if (pdata->use_internal_int_pullup == 1)
+		as3722_set_bits(as3722, AS3722_IOVOLTAGE_REG,
+				AS3722_INT_PULLUP_MASK,
+				AS3722_INT_PULLUP_ON);
+	else
+		as3722_set_bits(as3722, AS3722_IOVOLTAGE_REG,
+				AS3722_INT_PULLUP_MASK,
+				AS3722_INT_PULLUP_OFF);
+
+	if (pdata->use_internal_i2c_pullup)
+		as3722_set_bits(as3722, AS3722_IOVOLTAGE_REG,
+				AS3722_I2C_PULLUP_MASK,
+				AS3722_I2C_PULLUP_ON);
+	else
+		as3722_set_bits(as3722, AS3722_IOVOLTAGE_REG,
+				AS3722_I2C_PULLUP_MASK,
+				AS3722_I2C_PULLUP_OFF);
+
+	/* enable1 pin standby configuration */
+	if (pdata->enable1_deepsleep)
+		as3722_set_bits(as3722, AS3722_CTRL1_REG,
+				AS3722_ENABLE1_DEEPSLEEP_MASK,
+				AS3722_ENABLE1_DEEPSLEEP_ON);
+	else
+		as3722_set_bits(as3722, AS3722_CTRL1_REG,
+				AS3722_ENABLE1_DEEPSLEEP_MASK,
+				AS3722_ENABLE1_DEEPSLEEP_OFF);
+
+	if (pdata->enable1_invert)
+		as3722_set_bits(as3722, AS3722_CTRL1_REG,
+				AS3722_ENABLE1_INVERT_MASK,
+				AS3722_ENABLE1_INVERT_ON);
+	else
+		as3722_set_bits(as3722, AS3722_CTRL1_REG,
+				AS3722_ENABLE1_INVERT_MASK,
+				AS3722_ENABLE1_INVERT_OFF);
+
+	as3722_set_bits(as3722, AS3722_RESETTIMER_REG,
+			AS3722_OFF_DELAY_MASK,
+			pdata->off_delay << AS3722_OFF_DELAY_SHIFT);
+
+	/* thermal shutdown control */
+	as3722_set_bits(as3722, AS3722_OVERTEMPERATURE_CONTROL_REG,
+			AS3722_OVTMP_MASK,
+			pdata->mask_ovtemp << AS3722_OVTMP_SHIFT);
+
+	/* overcurrent/powergood configuration */
+	reg = (pdata->pg_sd6_vmask_time << AS3722_PG_SD6_VMASK_TIME_SHIFT)
+			& AS3722_PG_SD6_VMASK_TIME_MASK;
+	reg |= (pdata->sd6_lv_deb_time << AS3722_SD6_LV_DEB_SHIFT)
+			& AS3722_SD6_LV_DEB_MASK;
+	reg |= (pdata->sd1_lv_deb_time << AS3722_SD1_LV_DEB_SHIFT)
+			& AS3722_SD1_LV_DEB_MASK;
+	reg |= (pdata->sd0_lv_deb_time << AS3722_SD0_LV_DEB_SHIFT)
+			& AS3722_SD0_LV_DEB_MASK;
+	as3722_reg_write(as3722, AS3722_SD_LV_DEB_REG, reg);
+
+	reg = (pdata->pg_vresfall_mask << 7)
+			& AS3722_PG_VRESFALL_MASK_MASK;
+	reg |= (pdata->pg_ovcurr_sd0_mask << 6)
+			& AS3722_PG_OVCURR_SD0_MASK_MASK;
+	reg |= (pdata->pg_pwrgood_sd0_mask << 5)
+			& AS3722_PG_PWRGOOD_SD0_MASK_MASK;
+	reg |= (pdata->pg_gpio5_mask << 4)
+			& AS3722_PG_GPIO5_MASK_MASK;
+	reg |= (pdata->pg_gpio4_mask << 3)
+			& AS3722_PG_GPIO4_MASK_MASK;
+	reg |= (pdata->pg_gpio3_mask << 2)
+			& AS3722_PG_GPIO3_MASK_MASK;
+	reg |= (pdata->pg_ac_ok_mask << 1)
+			& AS3722_PG_AC_OK_MASK_MASK;
+	reg |= (pdata->pg_ac_ok_inv)
+			& AS3722_PG_AC_OK_INV_MASK;
+	as3722_reg_write(as3722, AS3722_OC_PG_CONTROL_REG, reg);
+
+	reg = (pdata->pg_ovcurr_sd6_mask << 7)
+			& AS3722_PG_OVCURR_SD6_MASK_MASK;
+	reg |= (pdata->pg_pwrgood_sd6_mask << 6)
+			& AS3722_PG_PWRGOOD_SD6_MASK_MASK;
+	reg |= (pdata->pg_sd6_ovc_alarm << 3)
+			& AS3722_PG_SD6_OVC_ALARM_MASK;
+	reg |= (pdata->pg_sd0_vmask_time << 1)
+			& AS3722_PG_SD0_VMASK_TIME_MASK;
+	reg |= (pdata->oc_pg_inv)
+			& AS3722_OC_PG_INV_MASK;
+	as3722_reg_write(as3722, AS3722_OC_PG_CONTROL2_REG, reg);
+
+	/* enable 32kHz clock output if required */
+	if (pdata->enable_clk32out_pin)
+		as3722_set_bits(as3722, AS3722_RTC_CONTROL_REG,
+				AS3722_CLK32OUT_ENABLE_MASK,
+				AS3722_CLK32OUT_ENABLE_ON);
+	else
+		as3722_set_bits(as3722, AS3722_RTC_CONTROL_REG,
+				AS3722_CLK32OUT_ENABLE_MASK,
+				AS3722_CLK32OUT_ENABLE_OFF);
+	return 0;
+}
+
+static int as3722_i2c_probe(struct i2c_client *i2c,
+		const struct i2c_device_id *id)
+{
+	struct as3722 *as3722;
+	struct as3722_platform_data *pdata;
+	int irq_flags;
+	int ret;
+
+	pdata = dev_get_platdata(&i2c->dev);
+	if (!pdata) {
+		dev_err(&i2c->dev, "as3722 requires platform data\n");
+		return -EINVAL;
+	}
+
+	as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL);
+	if (!as3722)
+		return -ENOMEM;
+
+	as3722->dev = &i2c->dev;
+	as3722->chip_irq = i2c->irq;
+	i2c_set_clientdata(i2c, as3722);
+
+	as3722->regmap = devm_regmap_init_i2c(i2c, &as3722_regmap_config);
+	if (IS_ERR(as3722->regmap)) {
+		ret = PTR_ERR(as3722->regmap);
+		dev_err(&i2c->dev, "regmap_init failed with err: %d\n", ret);
+		return ret;
+	}
+
+	irq_flags = pdata->irq_type;
+	irq_flags |= IRQF_ONESHOT;
+	ret = regmap_add_irq_chip(as3722->regmap, as3722->chip_irq,
+			irq_flags, pdata->irq_base, &as3722_irq_chip,
+			&as3722->irq_data);
+	if (ret < 0) {
+		dev_err(as3722->dev,
+			"irq allocation failed for as3722 failed\n");
+		return ret;
+	}
+
+	ret = as3722_init(as3722, pdata, i2c->irq);
+	if (ret < 0)
+		return ret;
+
+	ret = mfd_add_devices(&i2c->dev,
+			      -1,
+			      as3722_devs,
+			      ARRAY_SIZE(as3722_devs),
+			      NULL,
+			      pdata->irq_base,
+			      regmap_irq_get_domain(as3722->irq_data));
+	if (ret) {
+		dev_err(as3722->dev,
+			"add mfd devices failed with err: %d\n",
+			ret);
+		return ret;
+	}
+
+	dev_info(as3722->dev,
+		 "AS3722 core driver initialized successfully\n");
+
+	return 0;
+}
+
+static int as3722_i2c_remove(struct i2c_client *i2c)
+{
+	struct as3722 *as3722 = i2c_get_clientdata(i2c);
+	int irq_onkeylong, irq_onkey;
+	int irq_temp_sd0_shutdown, irq_temp_sd1_shutdown, irq_temp_sd6_shutdown;
+	int irq_temp_sd0_alarm, irq_temp_sd1_alarm, irq_temp_sd6_alarm;
+	int irq_ovtmp_alarm;
+
+	irq_onkeylong = regmap_irq_get_virq(as3722->irq_data,
+					    AS3722_IRQ_ONKEY_LONG);
+	irq_onkey = regmap_irq_get_virq(as3722->irq_data, AS3722_IRQ_ONKEY);
+	irq_temp_sd0_shutdown =
+		regmap_irq_get_virq(as3722->irq_data,
+				    AS3722_IRQ_TEMP_SD0_SHUTDOWN);
+	irq_temp_sd1_shutdown =
+		regmap_irq_get_virq(as3722->irq_data,
+				    AS3722_IRQ_TEMP_SD1_SHUTDOWN);
+	irq_temp_sd6_shutdown =
+		regmap_irq_get_virq(as3722->irq_data,
+				    AS3722_IRQ_TEMP_SD6_SHUTDOWN);
+	irq_temp_sd0_alarm =
+		regmap_irq_get_virq(as3722->irq_data,
+				    AS3722_IRQ_TEMP_SD0_ALARM);
+	irq_temp_sd1_alarm =
+		regmap_irq_get_virq(as3722->irq_data,
+				    AS3722_IRQ_TEMP_SD1_ALARM);
+	irq_temp_sd6_alarm =
+		regmap_irq_get_virq(as3722->irq_data,
+				    AS3722_IRQ_TEMP_SD6_ALARM);
+	irq_ovtmp_alarm =
+		regmap_irq_get_virq(as3722->irq_data,
+				    AS3722_IRQ_OVTMP);
+
+	free_irq(irq_onkeylong, as3722);
+	free_irq(irq_onkey, as3722);
+	free_irq(irq_temp_sd0_shutdown, as3722);
+	free_irq(irq_temp_sd1_shutdown, as3722);
+	free_irq(irq_temp_sd6_shutdown, as3722);
+	free_irq(irq_temp_sd0_alarm, as3722);
+	free_irq(irq_temp_sd1_alarm, as3722);
+	free_irq(irq_temp_sd6_alarm, as3722);
+	free_irq(irq_ovtmp_alarm, as3722);
+	mfd_remove_devices(as3722->dev);
+	regmap_del_irq_chip(as3722->chip_irq, as3722->irq_data);
+
+	return 0;
+}
+
+static const struct i2c_device_id as3722_i2c_id[] = {
+	{ "as3722", 0 },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, as3722_i2c_id);
+
+static struct i2c_driver as3722_i2c_driver = {
+	.driver = {
+		.name = "as3722",
+		.owner = THIS_MODULE,
+	},
+	.probe = as3722_i2c_probe,
+	.remove = as3722_i2c_remove,
+	.id_table = as3722_i2c_id,
+};
+
+module_i2c_driver(as3722_i2c_driver);
+
+MODULE_DESCRIPTION("I2C, IRQ and ADC support for AS3722 PMICs");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
-- 
1.7.2.5


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

* [PATCH 2/4] added regmap of AS3722
  2013-08-14 14:54 [PATCH 1/4] added support for ams AS3722 PMIC in mfd Florian Lobmaier
@ 2013-08-14 14:54 ` Florian Lobmaier
  2013-08-14 15:29   ` Mark Brown
  2013-08-14 14:54 ` [PATCH 3/4] added AS3722 platform include file Florian Lobmaier
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Florian Lobmaier @ 2013-08-14 14:54 UTC (permalink / raw)
  To: linux-kernel; +Cc: sameo, lee.jones, Florian Lobmaier


Signed-off-by: Florian Lobmaier <florian.lobmaier@ams.com>
---
 drivers/mfd/as3722-regmap.c |  417 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 417 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mfd/as3722-regmap.c

diff --git a/drivers/mfd/as3722-regmap.c b/drivers/mfd/as3722-regmap.c
new file mode 100644
index 0000000..725722e
--- /dev/null
+++ b/drivers/mfd/as3722-regmap.c
@@ -0,0 +1,417 @@
+/*
+ * as3722-regmap.c - regmap for AS3722 PMICs
+ *
+ * Copyright (C) 2013 ams AG
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/mfd/as3722-reg.h>
+
+/* Default Register Values (for caching)
+ * Please make sure to update (or update cache at startup)
+ * after device is OTP programmed! */
+static struct reg_default as3722_defaults[] = {
+	{ 0x0000, 0x0000 }, /* SD0 Voltage */
+	{ 0x0001, 0x0000 }, /* SD1 Voltage */
+	{ 0x0002, 0x0000 }, /* SD2 Voltage */
+	{ 0x0003, 0x0000 }, /* SD3 Voltage */
+	{ 0x0004, 0x0000 }, /* SD4 Voltage */
+	{ 0x0005, 0x0000 }, /* SD5 Voltage */
+	{ 0x0006, 0x0000 }, /* SD6 Voltage */
+	{ 0x0008, 0x0003 }, /* GPIO0 Control */
+	{ 0x0009, 0x0003 }, /* GPIO1 Control */
+	{ 0x000a, 0x0003 }, /* GPIO2 Control */
+	{ 0x000b, 0x0003 }, /* GPIO3 Control */
+	{ 0x000c, 0x0003 }, /* GPIO4 Control */
+	{ 0x000d, 0x0003 }, /* GPIO5 Control */
+	{ 0x000e, 0x0003 }, /* GPIO6 Control */
+	{ 0x000f, 0x0003 }, /* GPIO7 Control */
+	{ 0x0010, 0x0000 }, /* LDO0 Voltage */
+	{ 0x0011, 0x0000 }, /* LDO1 Voltage */
+	{ 0x0012, 0x0000 }, /* LDO2 Voltage */
+	{ 0x0013, 0x0000 }, /* LDO3 Voltage */
+	{ 0x0014, 0x0000 }, /* LDO4 Voltage */
+	{ 0x0015, 0x0000 }, /* LDO5 Voltage */
+	{ 0x0016, 0x0000 }, /* LDO6 Voltage */
+	{ 0x0017, 0x0000 }, /* LDO7 Voltage */
+	{ 0x0019, 0x0000 }, /* LDO9 Voltage */
+	{ 0x001a, 0x0000 }, /* LDO10 Voltage */
+	{ 0x001b, 0x0000 }, /* LDO11 Voltage */
+	{ 0x001d, 0x0000 }, /* LDO3 Settings */
+	{ 0x001e, 0x0000 }, /* GPIO deb1 */
+	{ 0x001f, 0x0000 }, /* GPIO deb2 */
+	{ 0x0020, 0x0000 }, /* GPIO Signal Out */
+	{ 0x0021, 0x0000 }, /* GPIO Signal In */
+	{ 0x0022, 0x0000 }, /* Reg_sequ_mod1 */
+	{ 0x0023, 0x0000 }, /* Reg_sequ_mod2 */
+	{ 0x0024, 0x0000 }, /* Reg_sequ_mod3 */
+	{ 0x0027, 0x0000 }, /* SD_phsw_ctrl */
+	{ 0x0028, 0x0000 }, /* SD_phsw_status */
+	{ 0x0029, 0x0000 }, /* SD0 Control */
+	{ 0x002a, 0x0001 }, /* SD1 Control */
+	{ 0x002b, 0x0000 }, /* SDmph Control */
+	{ 0x002c, 0x0000 }, /* SD23 Control */
+	{ 0x002d, 0x0000 }, /* SD4 Control */
+	{ 0x002e, 0x0000 }, /* SD5 Control */
+	{ 0x002f, 0x0001 }, /* SD6 Control */
+	{ 0x0030, 0x0000 }, /* SD_dvm */
+	{ 0x0031, 0x0000 }, /* Resetreason */
+	{ 0x0032, 0x0000 }, /* Battery Voltage Monitor */
+	{ 0x0033, 0x0000 }, /* Startup Control */
+	{ 0x0034, 0x0008 }, /* RestTimer */
+	{ 0x0035, 0x0000 }, /* ReferenceControl */
+	{ 0x0036, 0x0000 }, /* ResetControl */
+	{ 0x0037, 0x0001 }, /* OvertemperatureControl */
+	{ 0x0038, 0x0000 }, /* WatchdogControl */
+	{ 0x0039, 0x0000 }, /* Reg_standby_mod1 */
+	{ 0x003a, 0x0000 }, /* Reg_standby_mod2 */
+	{ 0x003b, 0x0000 }, /* Reg_standby_mod3 */
+	{ 0x003c, 0x0000 }, /* Enable Control 1 */
+	{ 0x003d, 0x0000 }, /* Enable Control 2 */
+	{ 0x003e, 0x0000 }, /* Enable Control 3 */
+	{ 0x003f, 0x0000 }, /* Enable Control 4 */
+	{ 0x0040, 0x0000 }, /* Enable Control 5 */
+	{ 0x0041, 0x0000 }, /* PWM Control low */
+	{ 0x0042, 0x0000 }, /* PWM Control high */
+	{ 0x0046, 0x0000 }, /* Watchdog Timer */
+	{ 0x0048, 0x0000 }, /* Watchdog Software Signal */
+	{ 0x0049, 0x0000 }, /* IO Voltage */
+	{ 0x004a, 0x0000 }, /* Battery_voltage_monitor2 */
+	{ 0x004d, 0x007f }, /* SDcontrol */
+	{ 0x004e, 0x00ff }, /* LDOcontrol0 */
+	{ 0x004f, 0x000e }, /* LDOcontrol1 */
+	{ 0x0050, 0x0000 }, /* SD0_protect */
+	{ 0x0051, 0x0000 }, /* SD6_protect */
+	{ 0x0052, 0x0000 }, /* PWM_vcontrol1 */
+	{ 0x0053, 0x0000 }, /* PWM_vcontrol2 */
+	{ 0x0054, 0x0000 }, /* PWM_vcontrol3 */
+	{ 0x0055, 0x0000 }, /* PWM_vcontrol4 */
+	{ 0x0057, 0x0040 }, /* BBcharger */
+	{ 0x0058, 0x0000 }, /* CTRLsequ1 */
+	{ 0x0059, 0x0000 }, /* CTRLsequ2 */
+	{ 0x005a, 0x0000 }, /* OVcurrent */
+	{ 0x005b, 0x0000 }, /* OVcurrent_deb */
+	{ 0x005c, 0x0000 }, /* SDlv_deb */
+	{ 0x005d, 0x0000 }, /* OC_pg_ctrl */
+	{ 0x005e, 0x0000 }, /* OC_pg_ctrl2 */
+	{ 0x005f, 0x0000 }, /* CTRLstatus */
+	{ 0x0060, 0x0020 }, /* RTC Control */
+	{ 0x0061, 0x0000 }, /* RTCsecond */
+	{ 0x0062, 0x0000 }, /* RTCminute */
+	{ 0x0063, 0x0000 }, /* RTChour */
+	{ 0x0064, 0x0001 }, /* RTCday */
+	{ 0x0065, 0x0001 }, /* RTCmonth */
+	{ 0x0066, 0x0000 }, /* RTCyear */
+	{ 0x0067, 0x0000 }, /* RTCAlarmsecond */
+	{ 0x0068, 0x0000 }, /* RTCAlarmminute */
+	{ 0x0069, 0x0000 }, /* RTCAlarmhour */
+	{ 0x006a, 0x003f }, /* RTCAlarmday */
+	{ 0x006b, 0x001f }, /* RTCAlarmmonth */
+	{ 0x006c, 0x007f }, /* RTCAlarmyear */
+	{ 0x006d, 0x0000 }, /* SRAM */
+	{ 0x006f, 0x0000 }, /* RTC_Access */
+	{ 0x0073, 0x0000 }, /* RegStatus */
+	{ 0x0074, 0x00ff }, /* InterruptMask1 */
+	{ 0x0075, 0x00ff }, /* InterruptMask2 */
+	{ 0x0076, 0x00ff }, /* InterruptMask3 */
+	{ 0x0077, 0x00ff }, /* InterruptMask4 */
+	{ 0x0080, 0x0000 }, /* ADC0 Control */
+	{ 0x0081, 0x0000 }, /* ADC1 Control */
+	{ 0x0086, 0x007f }, /* ADC1 threshold hi MSB */
+	{ 0x0087, 0x0007 }, /* ADC1 threshold hi LSB */
+	{ 0x0088, 0x0000 }, /* ADC1 threshold lo MSB */
+	{ 0x0089, 0x0000 }, /* ADC1 threshold lo LSB */
+	{ 0x008a, 0x0000 }, /* ADC Configuration */
+};
+
+/*
+ * Access masks.
+ */
+static bool as3722_readable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AS3722_SD0_VOLTAGE_REG:
+	case AS3722_SD1_VOLTAGE_REG:
+	case AS3722_SD2_VOLTAGE_REG:
+	case AS3722_SD3_VOLTAGE_REG:
+	case AS3722_SD4_VOLTAGE_REG:
+	case AS3722_SD5_VOLTAGE_REG:
+	case AS3722_SD6_VOLTAGE_REG:
+	case AS3722_GPIO0_CONTROL_REG:
+	case AS3722_GPIO1_CONTROL_REG:
+	case AS3722_GPIO2_CONTROL_REG:
+	case AS3722_GPIO3_CONTROL_REG:
+	case AS3722_GPIO4_CONTROL_REG:
+	case AS3722_GPIO5_CONTROL_REG:
+	case AS3722_GPIO6_CONTROL_REG:
+	case AS3722_GPIO7_CONTROL_REG:
+	case AS3722_LDO0_VOLTAGE_REG:
+	case AS3722_LDO1_VOLTAGE_REG:
+	case AS3722_LDO2_VOLTAGE_REG:
+	case AS3722_LDO3_VOLTAGE_REG:
+	case AS3722_LDO4_VOLTAGE_REG:
+	case AS3722_LDO5_VOLTAGE_REG:
+	case AS3722_LDO6_VOLTAGE_REG:
+	case AS3722_LDO7_VOLTAGE_REG:
+	case AS3722_LDO9_VOLTAGE_REG:
+	case AS3722_LDO10_VOLTAGE_REG:
+	case AS3722_LDO11_VOLTAGE_REG:
+	case 0x1d:
+	case 0x1e:
+	case 0x1f:
+	case AS3722_GPIO_SIGNAL_OUT_REG:
+	case AS3722_GPIO_SIGNAL_IN_REG:
+	case 0x22:
+	case 0x23:
+	case 0x24:
+	case 0x27:
+	case 0x28:
+	case AS3722_SD0_CONTROL_REG:
+	case AS3722_SD1_CONTROL_REG:
+	case AS3722_SDmph_CONTROL_REG:
+	case AS3722_SD23_CONTROL_REG:
+	case AS3722_SD4_CONTROL_REG:
+	case AS3722_SD5_CONTROL_REG:
+	case AS3722_SD6_CONTROL_REG:
+	case 0x30:
+	case 0x31:
+	case 0x32:
+	case 0x33:
+	case 0x34:
+	case 0x35:
+	case 0x36:
+	case 0x37:
+	case AS3722_WATCHDOG_CONTROL_REG:
+	case 0x39:
+	case 0x3a:
+	case 0x3b:
+	case 0x3c:
+	case 0x3d:
+	case 0x3e:
+	case 0x3f:
+	case 0x40:
+	case 0x41:
+	case 0x42:
+	case AS3722_WATCHDOG_TIMER_REG:
+	case AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG:
+	case AS3722_IOVOLTAGE_REG:
+	case 0x4a:
+	case AS3722_SD_CONTROL_REG:
+	case AS3722_LDOCONTROL0_REG:
+	case AS3722_LDOCONTROL1_REG:
+	case 0x50:
+	case 0x51:
+	case 0x52:
+	case 0x53:
+	case 0x54:
+	case 0x55:
+	case 0x57:
+	case AS3722_CTRL1_REG:
+	case AS3722_CTRL2_REG:
+	case 0x5a:
+	case 0x5b:
+	case 0x5c:
+	case 0x5d:
+	case 0x5e:
+	case 0x5f:
+	case AS3722_RTC_CONTROL_REG:
+	case AS3722_RTC_SECOND_REG:
+	case AS3722_RTC_MINUTE_REG:
+	case AS3722_RTC_HOUR_REG:
+	case AS3722_RTC_DAY_REG:
+	case AS3722_RTC_MONTH_REG:
+	case AS3722_RTC_YEAR_REG:
+	case AS3722_RTC_ALARM_SECOND_REG:
+	case AS3722_RTC_ALARM_MINUTE_REG:
+	case AS3722_RTC_ALARM_HOUR_REG:
+	case AS3722_RTC_ALARM_DAY_REG:
+	case AS3722_RTC_ALARM_MONTH_REG:
+	case AS3722_RTC_ALARM_YEAR_REG:
+	case 0x6d:
+	case 0x6f:
+	case 0x73:
+	case AS3722_INTERRUPTMASK1_REG:
+	case AS3722_INTERRUPTMASK2_REG:
+	case AS3722_INTERRUPTMASK3_REG:
+	case AS3722_INTERRUPTMASK4_REG:
+	case AS3722_INTERRUPTSTATUS1_REG:
+	case AS3722_INTERRUPTSTATUS2_REG:
+	case AS3722_INTERRUPTSTATUS3_REG:
+	case AS3722_INTERRUPTSTATUS4_REG:
+	case 0x7d:
+	case AS3722_ADC0_CONTROL_REG:
+	case AS3722_ADC1_CONTROL_REG:
+	case AS3722_ADC0_MSB_RESULT_REG:
+	case AS3722_ADC0_LSB_RESULT_REG:
+	case AS3722_ADC1_MSB_RESULT_REG:
+	case AS3722_ADC1_LSB_RESULT_REG:
+	case AS3722_ADC1_THRESHOLD_HI_MSB_REG:
+	case AS3722_ADC1_THRESHOLD_HI_LSB_REG:
+	case AS3722_ADC1_THRESHOLD_LO_MSB_REG:
+	case AS3722_ADC1_THRESHOLD_LO_LSB_REG:
+	case AS3722_ADC_CONFIG_REG:
+	case AS3722_ADDR_ASIC_ID1:
+	case AS3722_ADDR_ASIC_ID2:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool as3722_writeable(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case AS3722_SD0_VOLTAGE_REG:
+	case AS3722_SD1_VOLTAGE_REG:
+	case AS3722_SD2_VOLTAGE_REG:
+	case AS3722_SD3_VOLTAGE_REG:
+	case AS3722_SD4_VOLTAGE_REG:
+	case AS3722_SD5_VOLTAGE_REG:
+	case AS3722_SD6_VOLTAGE_REG:
+	case AS3722_GPIO0_CONTROL_REG:
+	case AS3722_GPIO1_CONTROL_REG:
+	case AS3722_GPIO2_CONTROL_REG:
+	case AS3722_GPIO3_CONTROL_REG:
+	case AS3722_GPIO4_CONTROL_REG:
+	case AS3722_GPIO5_CONTROL_REG:
+	case AS3722_GPIO6_CONTROL_REG:
+	case AS3722_GPIO7_CONTROL_REG:
+	case AS3722_LDO0_VOLTAGE_REG:
+	case AS3722_LDO1_VOLTAGE_REG:
+	case AS3722_LDO2_VOLTAGE_REG:
+	case AS3722_LDO3_VOLTAGE_REG:
+	case AS3722_LDO4_VOLTAGE_REG:
+	case AS3722_LDO5_VOLTAGE_REG:
+	case AS3722_LDO6_VOLTAGE_REG:
+	case AS3722_LDO7_VOLTAGE_REG:
+	case AS3722_LDO9_VOLTAGE_REG:
+	case AS3722_LDO10_VOLTAGE_REG:
+	case AS3722_LDO11_VOLTAGE_REG:
+	case 0x1d:
+	case 0x1e:
+	case 0x1f:
+	case AS3722_GPIO_SIGNAL_OUT_REG:
+	case 0x22:
+	case 0x23:
+	case 0x24:
+	case 0x27:
+	case 0x28:
+	case AS3722_SD0_CONTROL_REG:
+	case AS3722_SD1_CONTROL_REG:
+	case AS3722_SDmph_CONTROL_REG:
+	case AS3722_SD23_CONTROL_REG:
+	case AS3722_SD4_CONTROL_REG:
+	case AS3722_SD5_CONTROL_REG:
+	case AS3722_SD6_CONTROL_REG:
+	case 0x30:
+	case 0x31:
+	case 0x32:
+	case 0x33:
+	case 0x34:
+	case 0x35:
+	case 0x36:
+	case 0x37:
+	case AS3722_WATCHDOG_CONTROL_REG:
+	case 0x39:
+	case 0x3a:
+	case 0x3b:
+	case 0x3c:
+	case 0x3d:
+	case 0x3e:
+	case 0x3f:
+	case 0x40:
+	case 0x41:
+	case 0x42:
+	case AS3722_WATCHDOG_TIMER_REG:
+	case AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG:
+	case AS3722_IOVOLTAGE_REG:
+	case 0x4a:
+	case AS3722_SD_CONTROL_REG:
+	case AS3722_LDOCONTROL0_REG:
+	case AS3722_LDOCONTROL1_REG:
+	case 0x50:
+	case 0x51:
+	case 0x52:
+	case 0x53:
+	case 0x54:
+	case 0x55:
+	case 0x57:
+	case AS3722_CTRL1_REG:
+	case AS3722_CTRL2_REG:
+	case 0x5a:
+	case 0x5b:
+	case 0x5c:
+	case 0x5d:
+	case 0x5e:
+	case AS3722_RTC_CONTROL_REG:
+	case AS3722_RTC_SECOND_REG:
+	case AS3722_RTC_MINUTE_REG:
+	case AS3722_RTC_HOUR_REG:
+	case AS3722_RTC_DAY_REG:
+	case AS3722_RTC_MONTH_REG:
+	case AS3722_RTC_YEAR_REG:
+	case AS3722_RTC_ALARM_SECOND_REG:
+	case AS3722_RTC_ALARM_MINUTE_REG:
+	case AS3722_RTC_ALARM_HOUR_REG:
+	case AS3722_RTC_ALARM_DAY_REG:
+	case AS3722_RTC_ALARM_MONTH_REG:
+	case AS3722_RTC_ALARM_YEAR_REG:
+	case 0x6d:
+	case 0x6f:
+	case AS3722_INTERRUPTMASK1_REG:
+	case AS3722_INTERRUPTMASK2_REG:
+	case AS3722_INTERRUPTMASK3_REG:
+	case AS3722_INTERRUPTMASK4_REG:
+	case AS3722_INTERRUPTSTATUS1_REG:
+	case AS3722_INTERRUPTSTATUS2_REG:
+	case AS3722_INTERRUPTSTATUS3_REG:
+	case AS3722_INTERRUPTSTATUS4_REG:
+	case 0x7d:
+	case AS3722_ADC0_CONTROL_REG:
+	case AS3722_ADC1_CONTROL_REG:
+	case AS3722_ADC1_THRESHOLD_HI_MSB_REG:
+	case AS3722_ADC1_THRESHOLD_HI_LSB_REG:
+	case AS3722_ADC1_THRESHOLD_LO_MSB_REG:
+	case AS3722_ADC1_THRESHOLD_LO_LSB_REG:
+	case AS3722_ADC_CONFIG_REG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool as3722_volatile(struct device *dev, unsigned int reg)
+{
+	return false;
+}
+
+const struct regmap_config as3722_regmap_config = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.cache_type = REGCACHE_RBTREE,
+
+	.max_register = AS3722_REGISTER_COUNT,
+	.readable_reg = as3722_readable,
+	.writeable_reg = as3722_writeable,
+	.volatile_reg = as3722_volatile,
+
+	.reg_defaults = as3722_defaults,
+	.num_reg_defaults = ARRAY_SIZE(as3722_defaults),
+};
-- 
1.7.2.5


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

* [PATCH 3/4] added AS3722 platform include file
  2013-08-14 14:54 [PATCH 1/4] added support for ams AS3722 PMIC in mfd Florian Lobmaier
  2013-08-14 14:54 ` [PATCH 2/4] added regmap of AS3722 Florian Lobmaier
@ 2013-08-14 14:54 ` Florian Lobmaier
  2013-08-14 14:54 ` [PATCH 4/4] added ams AS3722 register " Florian Lobmaier
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Florian Lobmaier @ 2013-08-14 14:54 UTC (permalink / raw)
  To: linux-kernel; +Cc: sameo, lee.jones, Florian Lobmaier


Signed-off-by: Florian Lobmaier <florian.lobmaier@ams.com>
---
 include/linux/mfd/as3722-plat.h |  238 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 238 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/mfd/as3722-plat.h

diff --git a/include/linux/mfd/as3722-plat.h b/include/linux/mfd/as3722-plat.h
new file mode 100644
index 0000000..0fc3fb7
--- /dev/null
+++ b/include/linux/mfd/as3722-plat.h
@@ -0,0 +1,238 @@
+/*
+ * as3722.h definitions
+ *
+ * Copyright (C) 2013 ams
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __LINUX_MFD_AS3722_PLAT_H
+#define __LINUX_MFD_AS3722_PLAT_H
+
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/power_supply.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/machine.h>
+#include <linux/pwm.h>
+#include <linux/mfd/as3722-reg.h>
+
+struct as3722_reg_init {
+	u32 reg;
+	u32 val;
+};
+
+extern const struct regmap_config as3722_regmap_config;
+
+struct as3722_rtc {
+	struct rtc_device *rtc;
+	int alarm_enabled;      /* used for suspend/resume */
+};
+
+struct as3722 {
+	struct device *dev;
+	struct regmap *regmap;
+	struct regmap_irq_chip_data *irq_data;
+	struct regulator_dev *rdevs[AS3722_NUM_REGULATORS];
+	struct as3722_rtc rtc;
+	struct pwm_chip as3722_pwm;
+
+	struct mutex adc_mutex;
+
+	int chip_irq;
+	int reg_stby_counter;
+};
+
+enum {
+	AS3722_GPIO_CFG_NO_INVERT = 0,
+	AS3722_GPIO_CFG_INVERT = 1,
+};
+
+enum {
+	AS3722_GPIO_CFG_OUTPUT_DISABLED = 0,
+	AS3722_GPIO_CFG_OUTPUT_ENABLED = 1,
+};
+
+struct as3722_gpio_config {
+	int gpio;
+	int mode;
+	int invert;
+	int iosf;
+	int output_state;
+};
+
+enum as3722_off_delay {
+	AS3722_OFF_DELAY_NONE = 0,
+	AS3722_OFF_DELAY_8ms = 1,
+	AS3722_OFF_DELAY_16ms = 2,
+	AS3722_OFF_DELAY_32ms = 3,
+};
+
+enum as3722_bit {
+	AS3722_BIT_OFF = 0,
+	AS3722_BIT_ON = 1,
+};
+
+enum as3722_vmask_time {
+	AS3722_NO_MASKING = 0,
+	AS3722_VMASK_4us = 1,
+	AS3722_VMASK_8us = 2,
+};
+
+enum as3722_lv_deb_time {
+	AS3722_NO_DEBOUNCING = 0,
+	AS3722_DEB_1us = 1,
+	AS3722_DEB_4us = 2,
+	AS3722_DEB_20us = 3,
+};
+
+enum as3722_ovc_alarm {
+	AS3722_OVC_ALARM_DISABLED = 0,
+	AS3722_OVC_ALARM_1_6A = 1,
+	AS3722_OVC_ALARM_1_8A = 2,
+	AS3722_OVC_ALARM_2_0A = 3,
+	AS3722_OVC_ALARM_2_2A = 4,
+	AS3722_OVC_ALARM_2_4A = 5,
+	AS3722_OVC_ALARM_2_6A = 6,
+	AS3722_OVC_ALARM_2_8A = 7,
+};
+
+struct as3722_platform_data {
+	struct regulator_init_data *reg_init[AS3722_NUM_REGULATORS];
+
+	/* register initialisation */
+	struct as3722_reg_init *core_init_data;
+	int gpio_base;
+	int irq_base;
+	int irq_type;
+
+	int use_internal_int_pullup;
+	int use_internal_i2c_pullup;
+	int enable_clk32out_pin;
+
+	int num_gpio_cfgs;
+	struct as3722_gpio_config *gpio_cfgs;
+
+	/* enable1 pin standby control */
+	enum as3722_off_delay off_delay;
+	int enable1_deepsleep;
+	int enable1_invert;
+
+	/* thermal shutdown control */
+	enum as3722_bit mask_ovtemp;
+
+	/* overcurrent / powergood settings */
+	enum as3722_vmask_time pg_sd6_vmask_time;
+	enum as3722_lv_deb_time sd6_lv_deb_time;
+	enum as3722_lv_deb_time sd1_lv_deb_time;
+	enum as3722_lv_deb_time sd0_lv_deb_time;
+	enum as3722_bit pg_vresfall_mask;
+	enum as3722_bit pg_ovcurr_sd0_mask;
+	enum as3722_bit pg_pwrgood_sd0_mask;
+	enum as3722_bit pg_gpio5_mask;
+	enum as3722_bit pg_gpio4_mask;
+	enum as3722_bit pg_gpio3_mask;
+	enum as3722_bit pg_ac_ok_mask;
+	enum as3722_bit pg_ac_ok_inv;
+	enum as3722_bit pg_ovcurr_sd6_mask;
+	enum as3722_bit pg_pwrgood_sd6_mask;
+	enum as3722_ovc_alarm pg_sd6_ovc_alarm;
+	enum as3722_vmask_time pg_sd0_vmask_time;
+	enum as3722_bit oc_pg_inv;
+};
+
+static inline int as3722_reg_read(struct as3722 *as3722, u32 reg, u32 *dest)
+{
+	return regmap_read(as3722->regmap, reg, dest);
+}
+
+static inline int as3722_reg_write(struct as3722 *as3722, u32 reg, u32 value)
+{
+	return regmap_write(as3722->regmap, reg, value);
+}
+
+static inline int as3722_block_read(struct as3722 *as3722, u32 reg,
+		int count, u8 *buf)
+{
+	return regmap_bulk_read(as3722->regmap, reg, buf, count);
+}
+
+static inline int as3722_block_write(struct as3722 *as3722, u32 reg,
+		int count, u8 *data)
+{
+	return regmap_bulk_write(as3722->regmap, reg, data, count);
+}
+
+static inline int as3722_set_bits(struct as3722 *as3722, u32 reg,
+		u32 mask, u8 val)
+{
+	return regmap_update_bits(as3722->regmap, reg, mask, val);
+}
+
+/* ADC */
+enum as3722_adc_source {
+	AS3722_ADC_SD0 = 0,
+	AS3722_ADC_SD1 = 1,
+	AS3722_ADC_SD6 = 2,
+	AS3722_ADC_TEMP_SENSOR = 3,
+	AS3722_ADC_VSUP = 4,
+	AS3722_ADC_GPIO1 = 5,
+	AS3722_ADC_GPIO2 = 6,
+	AS3722_ADC_GPIO3 = 7,
+	AS3722_ADC_GPIO4 = 8,
+	AS3722_ADC_GPIO6 = 9,
+	AS3722_ADC_GPIO7 = 10,
+	AS3722_ADC_VBAT = 11,
+	AS3722_ADC_PWM_CLK2 = 12,
+	AS3722_ADC_PWM_DAT2 = 13,
+	AS3722_ADC_TEMP1_SD0 = 16,
+	AS3722_ADC_TEMP2_SD0 = 17,
+	AS3722_ADC_TEMP3_SD0 = 18,
+	AS3722_ADC_TEMP4_SD0 = 19,
+	AS3722_ADC_TEMP_SD1 = 20,
+	AS3722_ADC_TEMP1_SD6 = 21,
+	AS3722_ADC_TEMP2_SD6 = 22,
+};
+
+enum as3722_adc_channel {
+	AS3722_ADC0 = 0,
+	AS3722_ADC1 = 1,
+};
+
+enum as3722_adc_voltange_range {
+	AS3722_ADC_HIGH_VOLTAGE_RANGE = 0,
+	AS3722_ADC_LOW_VOLTAGE_RANGE = 1,
+};
+
+int as3722_adc_read(struct as3722 *as3722,
+			enum as3722_adc_channel channel,
+			enum as3722_adc_source source,
+			enum as3722_adc_voltange_range voltage_range);
+
+#endif
+
+
+
+
+
+
-- 
1.7.2.5


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

* [PATCH 4/4] added ams AS3722 register include file
  2013-08-14 14:54 [PATCH 1/4] added support for ams AS3722 PMIC in mfd Florian Lobmaier
  2013-08-14 14:54 ` [PATCH 2/4] added regmap of AS3722 Florian Lobmaier
  2013-08-14 14:54 ` [PATCH 3/4] added AS3722 platform include file Florian Lobmaier
@ 2013-08-14 14:54 ` Florian Lobmaier
  2013-08-14 15:33   ` Lee Jones
  2013-08-14 15:27 ` [PATCH 1/4] added support for ams AS3722 PMIC in mfd Lee Jones
  2013-08-14 15:27 ` Mark Brown
  4 siblings, 1 reply; 8+ messages in thread
From: Florian Lobmaier @ 2013-08-14 14:54 UTC (permalink / raw)
  To: linux-kernel; +Cc: sameo, lee.jones, Florian Lobmaier


Signed-off-by: Florian Lobmaier <florian.lobmaier@ams.com>
---
 include/linux/mfd/as3722-reg.h |  495 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 495 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/mfd/as3722-reg.h

diff --git a/include/linux/mfd/as3722-reg.h b/include/linux/mfd/as3722-reg.h
new file mode 100644
index 0000000..cc77584
--- /dev/null
+++ b/include/linux/mfd/as3722-reg.h
@@ -0,0 +1,495 @@
+/*
+ * as3722.h definitions
+ *
+ * Copyright (C) 2013 ams
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#ifndef __LINUX_MFD_AS3722_REG_H
+#define __LINUX_MFD_AS3722_REG_H
+
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/power_supply.h>
+#include <linux/irq.h>
+#include <linux/regmap.h>
+#include <linux/regulator/machine.h>
+
+#define AS3722_DEVICE_ID		       0x0C
+#define AS3722_REGISTER_COUNT                  0x92
+#define AS3722_NUM_REGULATORS                  18
+#define AS3722_NUM_STEPDOWN_REGULATORS         7
+#define AS3722_MAX_REG_STBY_COUNT	       10
+
+/* defines for register init */
+#define AS3722_REG_INIT(reg_offset, reg_value)  \
+{                                              \
+	.reg     = (reg_offset),                \
+	.val     = (reg_value),                 \
+}
+
+#define AS3722_REG_INIT_TERMINATE              0xFF
+
+/* regulator IDs */
+#define AS3722_LDO0                            0
+#define AS3722_LDO1                            1
+#define AS3722_LDO2                            2
+#define AS3722_LDO3                            3
+#define AS3722_LDO4                            4
+#define AS3722_LDO5                            5
+#define AS3722_LDO6                            6
+#define AS3722_LDO7                            7
+#define AS3722_LDO9                            8
+#define AS3722_LDO10                           9
+#define AS3722_LDO11                           10
+#define AS3722_SD0                             11
+#define AS3722_SD1                             12
+#define AS3722_SD2                             13
+#define AS3722_SD3                             14
+#define AS3722_SD4                             15
+#define AS3722_SD5                             16
+#define AS3722_SD6                             17
+
+/* AS3722 ASIC ID */
+#define AS3722_ADDR_ASIC_ID1                   0x90
+#define AS3722_ADDR_ASIC_ID2                   0x91
+
+/* GPIO IDs */
+#define AS3722_GPIO0                           0
+#define AS3722_GPIO1                           1
+#define AS3722_GPIO2                           2
+#define AS3722_GPIO3                           3
+#define AS3722_GPIO4                           4
+#define AS3722_GPIO5                           5
+#define AS3722_GPIO6                           6
+#define AS3722_GPIO7                           7
+
+#define AS3722_NUM_GPIO                        8
+#define AS3722_GPIO_IRQ_BASE                   0
+
+/* GPIO modes */
+#define AS3722_GPIO_MODE_MASK                  0x07
+#define AS3722_GPIO_MODE_INPUT                 0
+#define AS3722_GPIO_MODE_OUTPUT_VDDH           1
+#define AS3722_GPIO_MODE_IO_OPEN_DRAIN         2
+#define AS3722_GPIO_MODE_ADC_IN                3
+#define AS3722_GPIO_MODE_INPUT_W_PULLUP        4
+#define AS3722_GPIO_MODE_INPUT_W_PULLDOWN      5
+#define AS3722_GPIO_MODE_IO_OPEN_DRAIN_PULLUP  6
+#define AS3722_GPIO_MODE_OUTPUT_VDDL           7
+
+/* Interrupt IDs */
+#define AS3722_IRQ_MAX_HANDLER                 18
+#define AS3722_IRQ_LID                         0
+#define AS3722_IRQ_ACOK                        1
+#define AS3722_IRQ_ENABLE1		       2
+#define AS3722_IRQ_OCURR_ACOK                  3
+#define AS3722_IRQ_ONKEY_LONG                  4
+#define AS3722_IRQ_ONKEY                       5
+#define AS3722_IRQ_OVTMP                       6
+#define AS3722_IRQ_LOWBAT                      7
+#define AS3722_IRQ_RTC_REP                     8
+#define AS3722_IRQ_RTC_ALARM                   9
+#define AS3722_IRQ_SD0                         10
+#define AS3722_IRQ_WATCHDOG                    11
+#define AS3722_IRQ_ADC                         12
+#define AS3722_IRQ_GPIO1                       13
+#define AS3722_IRQ_GPIO2                       14
+#define AS3722_IRQ_GPIO3                       15
+#define AS3722_IRQ_GPIO4                       16
+#define AS3722_IRQ_GPIO5                       17
+#define AS3722_IRQ_TEMP_SD0_SHUTDOWN	       18
+#define AS3722_IRQ_TEMP_SD1_SHUTDOWN	       19
+#define AS3722_IRQ_TEMP_SD6_SHUTDOWN	       20
+#define AS3722_IRQ_TEMP_SD0_ALARM	       21
+#define AS3722_IRQ_TEMP_SD1_ALARM	       22
+#define AS3722_IRQ_TEMP_SD6_ALARM	       23
+
+/* AS3722 registers */
+#define AS3722_SD0_VOLTAGE_REG                 0x00
+#define AS3722_SD1_VOLTAGE_REG                 0x01
+#define AS3722_SD2_VOLTAGE_REG                 0x02
+#define AS3722_SD3_VOLTAGE_REG                 0x03
+#define AS3722_SD4_VOLTAGE_REG                 0x04
+#define AS3722_SD5_VOLTAGE_REG                 0x05
+#define AS3722_SD6_VOLTAGE_REG                 0x06
+#define AS3722_GPIO0_CONTROL_REG               0x08
+#define AS3722_GPIO1_CONTROL_REG               0x09
+#define AS3722_GPIO2_CONTROL_REG               0x0A
+#define AS3722_GPIO3_CONTROL_REG               0x0B
+#define AS3722_GPIO4_CONTROL_REG               0x0C
+#define AS3722_GPIO5_CONTROL_REG               0x0D
+#define AS3722_GPIO6_CONTROL_REG               0x0E
+#define AS3722_GPIO7_CONTROL_REG               0x0F
+#define AS3722_LDO0_VOLTAGE_REG                0x10
+#define AS3722_LDO1_VOLTAGE_REG                0x11
+#define AS3722_LDO2_VOLTAGE_REG                0x12
+#define AS3722_LDO3_VOLTAGE_REG                0x13
+#define AS3722_LDO4_VOLTAGE_REG                0x14
+#define AS3722_LDO5_VOLTAGE_REG                0x15
+#define AS3722_LDO6_VOLTAGE_REG                0x16
+#define AS3722_LDO7_VOLTAGE_REG                0x17
+#define AS3722_LDO9_VOLTAGE_REG                0x19
+#define AS3722_LDO10_VOLTAGE_REG               0x1A
+#define AS3722_LDO11_VOLTAGE_REG               0x1B
+
+#define AS3722_GPIO_SIGNAL_OUT_REG             0x20
+#define AS3722_GPIO_SIGNAL_IN_REG              0x21
+
+#define AS3722_SD0_CONTROL_REG                 0x29
+#define AS3722_SD1_CONTROL_REG                 0x2A
+#define AS3722_SDmph_CONTROL_REG               0x2B
+#define AS3722_SD23_CONTROL_REG                0x2C
+#define AS3722_SD4_CONTROL_REG                 0x2D
+#define AS3722_SD5_CONTROL_REG                 0x2E
+#define AS3722_SD6_CONTROL_REG                 0x2F
+
+#define AS3722_RESETTIMER_REG		       0x34
+#define AS3722_OVERTEMPERATURE_CONTROL_REG     0x37
+#define AS3722_WATCHDOG_CONTROL_REG            0x38
+#define AS3722_REG_STANDBY_MOD1_REG	       0x39
+#define AS3722_REG_STANDBY_MOD2_REG	       0x3A
+#define AS3722_REG_STANDBY_MOD3_REG	       0x3B
+#define AS3722_PWM_CONTROL_L_REG	       0x41
+#define AS3722_PWM_CONTROL_H_REG	       0x42
+#define AS3722_WATCHDOG_TIMER_REG              0x46
+#define AS3722_WATCHDOG_SOFTWARE_SIGNAL_REG    0x48
+#define AS3722_IOVOLTAGE_REG                   0x49
+#define AS3722_SD_CONTROL_REG                  0x4D
+#define AS3722_LDOCONTROL0_REG                 0x4E
+#define AS3722_LDOCONTROL1_REG                 0x4F
+
+#define AS3722_CTRL1_REG                       0x58
+#define AS3722_CTRL2_REG                       0x59
+#define AS3722_SD_LV_DEB_REG		       0x5C
+#define AS3722_OC_PG_CONTROL_REG	       0x5D
+#define AS3722_OC_PG_CONTROL2_REG	       0x5E
+#define AS3722_RTC_CONTROL_REG                 0x60
+#define AS3722_RTC_SECOND_REG                  0x61
+#define AS3722_RTC_MINUTE_REG                  0x62
+#define AS3722_RTC_HOUR_REG                    0x63
+#define AS3722_RTC_DAY_REG                     0x64
+#define AS3722_RTC_MONTH_REG                   0x65
+#define AS3722_RTC_YEAR_REG                    0x66
+#define AS3722_RTC_ALARM_SECOND_REG            0x67
+#define AS3722_RTC_ALARM_MINUTE_REG            0x68
+#define AS3722_RTC_ALARM_HOUR_REG              0x69
+#define AS3722_RTC_ALARM_DAY_REG               0x6A
+#define AS3722_RTC_ALARM_MONTH_REG             0x6B
+#define AS3722_RTC_ALARM_YEAR_REG              0x6C
+
+#define AS3722_INTERRUPTMASK1_REG              0x74
+#define AS3722_INTERRUPTMASK2_REG              0x75
+#define AS3722_INTERRUPTMASK3_REG              0x76
+#define AS3722_INTERRUPTMASK4_REG              0x77
+#define AS3722_INTERRUPTSTATUS1_REG            0x78
+#define AS3722_INTERRUPTSTATUS2_REG            0x79
+#define AS3722_INTERRUPTSTATUS3_REG            0x7A
+#define AS3722_INTERRUPTSTATUS4_REG            0x7B
+#define AS3722_TEMP_STATUS_REG		       0x7D
+
+#define AS3722_ADC0_CONTROL_REG                0x80
+#define AS3722_ADC1_CONTROL_REG                0x81
+#define AS3722_ADC0_MSB_RESULT_REG             0x82
+#define AS3722_ADC0_LSB_RESULT_REG             0x83
+#define AS3722_ADC1_MSB_RESULT_REG             0x84
+#define AS3722_ADC1_LSB_RESULT_REG             0x85
+#define AS3722_ADC1_THRESHOLD_HI_MSB_REG       0x86
+#define AS3722_ADC1_THRESHOLD_HI_LSB_REG       0x87
+#define AS3722_ADC1_THRESHOLD_LO_MSB_REG       0x88
+#define AS3722_ADC1_THRESHOLD_LO_LSB_REG       0x89
+#define AS3722_ADC_CONFIG_REG                  0x8A
+
+#define AS3722_REG0_CONTROL_REG		       0xE0
+#define AS3722_REG1_CONTROL_REG		       0xE1
+#define AS3722_REG2_CONTROL_REG		       0xE2
+#define AS3722_REG3_CONTROL_REG		       0xE3
+#define AS3722_REG4_CONTROL_REG		       0xE4
+#define AS3722_REG5_CONTROL_REG		       0xE5
+#define AS3722_REG6_CONTROL_REG		       0xE6
+#define AS3722_REG7_CONTROL_REG		       0xE7
+#define AS3722_REG8_CONTROL_REG		       0xE8
+#define AS3722_REG9_CONTROL_REG		       0xE9
+#define AS3722_REG0_VOLTAGE_REG		       0xEA
+#define AS3722_REG1_VOLTAGE_REG		       0xEB
+#define AS3722_REG2_VOLTAGE_REG		       0xEC
+#define AS3722_REG3_VOLTAGE_REG		       0xED
+#define AS3722_REG4_VOLTAGE_REG		       0xEE
+#define AS3722_REG5_VOLTAGE_REG		       0xEF
+#define AS3722_REG6_VOLTAGE_REG		       0xF0
+#define AS3722_REG7_VOLTAGE_REG		       0xF1
+#define AS3722_REG8_VOLTAGE_REG		       0xF2
+#define AS3722_REG9_VOLTAGE_REG		       0xF3
+
+/* AS3722 register bits and bit masks */
+#define AS3722_LDO_ILIMIT_MASK                 (1 << 7)
+#define AS3722_LDO_ILIMIT_BIT                  (1 << 7)
+#define AS3722_LDO0_VSEL_MASK                  0x1F
+#define AS3722_LDO0_VSEL_MIN                   0x01
+#define AS3722_LDO0_VSEL_MAX                   0x12
+#define AS3722_LDO3_VSEL_MASK                  0x3F
+#define AS3722_LDO3_VSEL_MIN                   0x01
+#define AS3722_LDO3_VSEL_MAX                   0x45
+#define AS3722_LDO_VSEL_MASK                   0x7F
+#define AS3722_LDO_VSEL_MIN                    0x01
+#define AS3722_LDO_VSEL_MAX                    0x7F
+#define AS3722_LDO_VSEL_DNU_MIN                0x25
+#define AS3722_LDO_VSEL_DNU_MAX                0x3F
+#define AS3722_LDO_NUM_VOLT                    100
+
+#define AS3722_LDO0_ON                         (1 << 0)
+#define AS3722_LDO0_OFF                        (0 << 0)
+#define AS3722_LDO0_CTRL_MASK                  (1 << 0)
+#define AS3722_LDO1_ON                         (1 << 1)
+#define AS3722_LDO1_OFF                        (0 << 1)
+#define AS3722_LDO1_CTRL_MASK                  (1 << 1)
+#define AS3722_LDO2_ON                         (1 << 2)
+#define AS3722_LDO2_OFF                        (0 << 2)
+#define AS3722_LDO2_CTRL_MASK                  (1 << 2)
+#define AS3722_LDO3_ON                         (1 << 3)
+#define AS3722_LDO3_OFF                        (0 << 3)
+#define AS3722_LDO3_CTRL_MASK                  (1 << 3)
+#define AS3722_LDO4_ON                         (1 << 4)
+#define AS3722_LDO4_OFF                        (0 << 4)
+#define AS3722_LDO4_CTRL_MASK                  (1 << 4)
+#define AS3722_LDO5_ON                         (1 << 5)
+#define AS3722_LDO5_OFF                        (0 << 5)
+#define AS3722_LDO5_CTRL_MASK                  (1 << 5)
+#define AS3722_LDO6_ON                         (1 << 6)
+#define AS3722_LDO6_OFF                        (0 << 6)
+#define AS3722_LDO6_CTRL_MASK                  (1 << 6)
+#define AS3722_LDO7_ON                         (1 << 7)
+#define AS3722_LDO7_OFF                        (0 << 7)
+#define AS3722_LDO7_CTRL_MASK                  (1 << 7)
+#define AS3722_LDO9_ON                         (1 << 1)
+#define AS3722_LDO9_OFF                        (0 << 1)
+#define AS3722_LDO9_CTRL_MASK                  (1 << 1)
+#define AS3722_LDO10_ON                        (1 << 2)
+#define AS3722_LDO10_OFF                       (0 << 2)
+#define AS3722_LDO10_CTRL_MASK                 (1 << 2)
+#define AS3722_LDO11_ON                        (1 << 3)
+#define AS3722_LDO11_OFF                       (0 << 3)
+#define AS3722_LDO11_CTRL_MASK                 (1 << 3)
+
+#define AS3722_SD_VSEL_MASK                    0x7F
+#define AS3722_SD0_VSEL_MIN                    0x01
+#define AS3722_SD0_VSEL_MAX                    0x5A
+#define AS3722_SD2_VSEL_MIN                    0x01
+#define AS3722_SD2_VSEL_MAX                    0x7F
+#define AS3722_SD0_ON                          (1 << 0)
+#define AS3722_SD0_OFF                         (0 << 0)
+#define AS3722_SD0_CTRL_MASK                   (1 << 0)
+#define AS3722_SD1_ON                          (1 << 1)
+#define AS3722_SD1_OFF                         (0 << 1)
+#define AS3722_SD1_CTRL_MASK                   (1 << 1)
+#define AS3722_SD2_ON                          (1 << 2)
+#define AS3722_SD2_OFF                         (0 << 2)
+#define AS3722_SD2_CTRL_MASK                   (1 << 2)
+#define AS3722_SD3_ON                          (1 << 3)
+#define AS3722_SD3_OFF                         (0 << 3)
+#define AS3722_SD3_CTRL_MASK                   (1 << 3)
+#define AS3722_SD4_ON                          (1 << 4)
+#define AS3722_SD4_OFF                         (0 << 4)
+#define AS3722_SD4_CTRL_MASK                   (1 << 4)
+#define AS3722_SD5_ON                          (1 << 5)
+#define AS3722_SD5_OFF                         (0 << 5)
+#define AS3722_SD5_CTRL_MASK                   (1 << 5)
+#define AS3722_SD6_ON                          (1 << 6)
+#define AS3722_SD6_OFF                         (0 << 6)
+#define AS3722_SD6_CTRL_MASK                   (1 << 6)
+
+#define AS3722_SD0_MODE_FAST                   (1 << 4)
+#define AS3722_SD0_MODE_NORMAL                 (0 << 4)
+#define AS3722_SD0_MODE_MASK                   (1 << 4)
+#define AS3722_SD1_MODE_FAST                   (1 << 4)
+#define AS3722_SD1_MODE_NORMAL                 (0 << 4)
+#define AS3722_SD1_MODE_MASK                   (1 << 4)
+#define AS3722_SD2_MODE_FAST                   (1 << 2)
+#define AS3722_SD2_MODE_NORMAL                 (0 << 2)
+#define AS3722_SD2_MODE_MASK                   (1 << 2)
+#define AS3722_SD3_MODE_FAST                   (1 << 6)
+#define AS3722_SD3_MODE_NORMAL                 (0 << 6)
+#define AS3722_SD3_MODE_MASK                   (1 << 6)
+#define AS3722_SD4_MODE_FAST                   (1 << 2)
+#define AS3722_SD4_MODE_NORMAL                 (0 << 2)
+#define AS3722_SD4_MODE_MASK                   (1 << 2)
+#define AS3722_SD5_MODE_FAST                   (1 << 2)
+#define AS3722_SD5_MODE_NORMAL                 (0 << 2)
+#define AS3722_SD5_MODE_MASK                   (1 << 2)
+#define AS3722_SD6_MODE_FAST                   (1 << 4)
+#define AS3722_SD6_MODE_NORMAL                 (0 << 4)
+#define AS3722_SD6_MODE_MASK                   (1 << 4)
+
+#define AS3722_DELAY_TIME_STBY_MASK	       (1 << 6)
+#define AS3722_REG_DELAY_STBY_MASK	       (1 << 5)
+#define AS3722_REG_SELECT_STBY_MASK	       (0x1F)
+#define AS3722_REG_VOLTAGE_STBY_MASK	       (0xFF)
+
+#define AS3722_SD0_LV_DEB_MASK		       (0x03)
+#define AS3722_SD1_LV_DEB_MASK		       (0x0C)
+#define AS3722_SD6_LV_DEB_MASK		       (0x30)
+#define AS3722_PG_SD6_VMASK_TIME_MASK	       (0xC0)
+#define AS3722_SD0_LV_DEB_SHIFT		       (0)
+#define AS3722_SD1_LV_DEB_SHIFT		       (2)
+#define AS3722_SD6_LV_DEB_SHIFT		       (4)
+#define AS3722_PG_SD6_VMASK_TIME_SHIFT	       (6)
+
+#define AS3722_PG_AC_OK_INV_MASK	       (1 << 0)
+#define AS3722_PG_AC_OK_MASK_MASK	       (1 << 1)
+#define AS3722_PG_GPIO3_MASK_MASK	       (1 << 2)
+#define AS3722_PG_GPIO4_MASK_MASK	       (1 << 3)
+#define AS3722_PG_GPIO5_MASK_MASK	       (1 << 4)
+#define AS3722_PG_PWRGOOD_SD0_MASK_MASK	       (1 << 5)
+#define AS3722_PG_OVCURR_SD0_MASK_MASK	       (1 << 6)
+#define AS3722_PG_VRESFALL_MASK_MASK	       (1 << 7)
+
+#define AS3722_OC_PG_INV_MASK		       (1 << 0)
+#define AS3722_PG_SD0_VMASK_TIME_MASK	       (0x06)
+#define AS3722_PG_SD6_OVC_ALARM_MASK	       (0x38)
+#define AS3722_PG_PWRGOOD_SD6_MASK_MASK	       (1 << 6)
+#define AS3722_PG_OVCURR_SD6_MASK_MASK	       (1 << 7)
+
+#define AS3722_IRQ_MASK_LID                    (1 << 0)
+#define AS3722_IRQ_MASK_ACOK                   (1 << 1)
+#define AS3722_IRQ_MASK_ENABLE1                (1 << 2)
+#define AS3722_IRQ_MASK_OCURR_ACOK             (1 << 3)
+#define AS3722_IRQ_MASK_ONKEY_LONG             (1 << 4)
+#define AS3722_IRQ_MASK_ONKEY                  (1 << 5)
+#define AS3722_IRQ_MASK_OVTMP                  (1 << 6)
+#define AS3722_IRQ_MASK_LOWBAT                 (1 << 7)
+#define AS3722_IRQ_MASK_SD0                    (1 << 0)
+#define AS3722_IRQ_MASK_RTC_REP                (1 << 7)
+#define AS3722_IRQ_MASK_RTC_ALARM              (1 << 0)
+#define AS3722_IRQ_MASK_WATCHDOG               (1 << 6)
+#define AS3722_IRQ_MASK_ADC                    (1 << 7)
+#define AS3722_IRQ_MASK_GPIO1		       (1 << 1)
+#define AS3722_IRQ_MASK_GPIO2		       (1 << 2)
+#define AS3722_IRQ_MASK_GPIO3		       (1 << 3)
+#define AS3722_IRQ_MASK_GPIO4		       (1 << 4)
+#define AS3722_IRQ_MASK_GPIO5		       (1 << 5)
+#define AS3722_IRQ_MASK_TEMP_SD0_SHUTDOWN      (1 << 0)
+#define AS3722_IRQ_MASK_TEMP_SD1_SHUTDOWN      (1 << 1)
+#define AS3722_IRQ_MASK_TEMP_SD6_SHUTDOWN      (1 << 2)
+#define AS3722_IRQ_MASK_TEMP_SD0_ALARM	       (1 << 3)
+#define AS3722_IRQ_MASK_TEMP_SD1_ALARM	       (1 << 4)
+#define AS3722_IRQ_MASK_TEMP_SD6_ALARM	       (1 << 5)
+
+#define AS3722_IRQ_BIT_LID                     (1 << 0)
+#define AS3722_IRQ_BIT_ACOK                    (1 << 1)
+#define AS3722_IRQ_BIT_ENABLE1		       (1 << 2)
+#define AS3722_IRQ_BIT_SD0                     (1 << 3)
+#define AS3722_IRQ_BIT_ONKEY_LONG              (1 << 4)
+#define AS3722_IRQ_BIT_ONKEY                   (1 << 5)
+#define AS3722_IRQ_BIT_OVTMP                   (1 << 6)
+#define AS3722_IRQ_BIT_LOWBAT                  (1 << 7)
+#define AS3722_IRQ_BIT_RTC_REP                 (1 << 7)
+#define AS3722_IRQ_BIT_RTC_ALARM               (1 << 0)
+#define AS3722_IRQ_BIT_WATCHDOG                (1 << 6)
+#define AS3722_IRQ_BIT_ADC                     (1 << 7)
+
+#define AS3722_OVTMP_MASK		       (1 << 3)
+#define AS3722_OVTMP_SHIFT		       3
+
+/* ADC bit masks */
+#define AS3722_ADC_MASK_BUF_ON                 (1 << 2)
+#define AS3722_ADC_BIT_BUF_ON                  (1 << 2)
+#define AS3722_ADC1_MASK_INT_MODE_ON           (1 << 1)
+#define AS3722_ADC1_BIT_INT_MODE_ON            (1 << 1)
+#define AS3722_ADC1_MASK_INTERVAL_TIME         (1 << 0)
+#define AS3722_ADC1_BIT_INTERVAL_TIME          (1 << 0)
+
+#define AS3722_ADC_MASK_MSB_VAL                0x3F
+#define AS3722_ADC_MASK_LSB_VAL                0x07
+
+#define AS3722_ADC_MASK_CONV_START            (1 << 7)
+#define AS3722_ADC_BIT_CONV_START             (1 << 7)
+#define AS3722_ADC_MASK_CONV_NOTREADY         (1 << 7)
+#define AS3722_ADC_BIT_CONV_NOTREADY          (1 << 7)
+#define AS3722_ADC_MASK_SOURCE_SELECT         0x1F
+#define AS3722_ADC_MASK_VOLTAGE_RANGE	      (1 << 5)
+#define AS3722_ADC_SHIFT_VOLTAGE_RANGE	      5
+
+#define AS3722_GPIO_INV_MASK                   0x80
+#define AS3722_GPIO_INV                        0x80
+#define AS3722_GPIO_IOSF_MASK                  0x78
+#define AS3722_GPIO_IOSF_NORMAL                0
+#define AS3722_GPIO_IOSF_INTERRUPT_OUT         (1 << 3)
+#define AS3722_GPIO_IOSF_VSUP_LOW_OUT          (2 << 3)
+#define AS3722_GPIO_IOSF_GPIO_INTERRUPT_IN     (3 << 3)
+#define AS3722_GPIO_IOSF_ISINK_PWM_IN          (4 << 3)
+#define AS3722_GPIO_IOSF_VOLTAGE_STBY          (5 << 3)
+#define AS3722_GPIO_IOSF_PWR_GOOD_OUT          (7 << 3)
+#define AS3722_GPIO_IOSF_Q32K_OUT              (8 << 3)
+#define AS3722_GPIO_IOSF_WATCHDOG_IN           (9 << 3)
+#define AS3722_GPIO_IOSF_SOFT_RESET_IN         (11 << 3)
+#define AS3722_GPIO_IOSF_PWM_OUT               (12 << 3)
+#define AS3722_GPIO_IOSF_VSUP_LOW_DEB_OUT      (13 << 3)
+#define AS3722_GPIO_IOSF_SD6_LOW_VOLT_LOW      (14 << 3)
+
+#define AS3722_GPIO0_SIGNAL_MASK               (1 << 0)
+#define AS3722_GPIO1_SIGNAL_MASK               (1 << 1)
+#define AS3722_GPIO2_SIGNAL_MASK               (1 << 2)
+#define AS3722_GPIO3_SIGNAL_MASK               (1 << 3)
+#define AS3722_GPIO4_SIGNAL_MASK               (1 << 4)
+#define AS3722_GPIO5_SIGNAL_MASK               (1 << 5)
+#define AS3722_GPIO6_SIGNAL_MASK               (1 << 6)
+#define AS3722_GPIO7_SIGNAL_MASK               (1 << 7)
+
+#define AS3722_INT_PULLUP_MASK                 (1 << 5)
+#define AS3722_INT_PULLUP_ON                   (1 << 5)
+#define AS3722_INT_PULLUP_OFF                  (0 << 5)
+#define AS3722_I2C_PULLUP_MASK                 (1 << 4)
+#define AS3722_I2C_PULLUP_ON                   (1 << 4)
+#define AS3722_I2C_PULLUP_OFF                  (0 << 4)
+
+#define AS3722_RTC_REP_WAKEUP_EN_MASK          (1 << 0)
+#define AS3722_RTC_ALARM_WAKEUP_EN_MASK        (1 << 1)
+#define AS3722_RTC_ON_MASK                     (1 << 2)
+#define AS3722_RTC_IRQMODE_MASK                (3 << 3)
+#define AS3722_CLK32OUT_ENABLE_MASK	       (1 << 5)
+
+#define AS3722_CLK32OUT_ENABLE_ON	       (1 << 5)
+#define AS3722_CLK32OUT_ENABLE_OFF	       (0 << 5)
+
+#define AS3722_OFF_DELAY_MASK		       (0x18)
+#define AS3722_OFF_DELAY_SHIFT		       (3)
+
+#define AS3722_ENABLE1_INVERT_MASK	       (1 << 4)
+#define AS3722_ENABLE1_INVERT_ON	       (1 << 4)
+#define AS3722_ENABLE1_INVERT_OFF	       (0 << 4)
+#define AS3722_ENABLE1_DEEPSLEEP_MASK	       (1 << 5)
+#define AS3722_ENABLE1_DEEPSLEEP_ON	       (1 << 5)
+#define AS3722_ENABLE1_DEEPSLEEP_OFF	       (0 << 5)
+
+#define AS3722_PWM_DIV_MASK		       0xC0
+#define AS3722_PWM_DIV_SHIFT		       (6)
+#define AS3722_PWM_DIV_DIVIDE_BY_1	       0x00
+#define AS3722_PWM_DIV_DIVIDE_BY_16	       0x40
+#define AS3722_PWM_DIV_DIVIDE_BY_256	       0x80
+#define AS3722_PWM_DIV_DIVIDE_BY_16384	       0xC0
+
+#define AS3722_WATCHDOG_TIMER_MAX              127
+#define AS3722_WATCHDOG_ON_MASK                (1 << 0)
+#define AS3722_WATCHDOG_ON                     (1 << 0)
+#define AS3722_WATCHDOG_SW_SIG_MASK            (1 << 0)
+#define AS3722_WATCHDOG_SW_SIG                 (1 << 0)
+
+#endif
-- 
1.7.2.5


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

* Re: [PATCH 1/4] added support for ams AS3722 PMIC in mfd
  2013-08-14 14:54 [PATCH 1/4] added support for ams AS3722 PMIC in mfd Florian Lobmaier
                   ` (2 preceding siblings ...)
  2013-08-14 14:54 ` [PATCH 4/4] added ams AS3722 register " Florian Lobmaier
@ 2013-08-14 15:27 ` Lee Jones
  2013-08-14 15:27 ` Mark Brown
  4 siblings, 0 replies; 8+ messages in thread
From: Lee Jones @ 2013-08-14 15:27 UTC (permalink / raw)
  To: Florian Lobmaier; +Cc: linux-kernel, sameo

I'm going to comment on the format of the patches before I do the code
review.

The $SUBJECT line needs to use the same formatting as previous patches
accepted by the subsystem. In the case of MFD they're formatted like this:

  mfd: <driver_name>: <what you're doing>

This information can be obtained by issuing something like:

  git log --oneline -- drivers/mfd

> now using git send-email and splitted mfd patch into multiple patches (4).
> Suggestions from 23.05.2013 added.

Anything mentioned here will end up in the Mainline kernel `git log`,
so it needs to only contain what the patch is trying to achieve. The
information you've mentioned above 'could, perhaps' be useful, but it
lives in the cover letter i.e. [PATCH 0/x] instead of in a patch's
commit log.

You are lacking proper commit logs on all 4 patches here. You are also
missing a cover letter.

Once this is all in order, I'll commence the code review.

> Signed-off-by: Florian Lobmaier <florian.lobmaier@ams.com>
> ---
>  drivers/mfd/Kconfig       |   15 +
>  drivers/mfd/Makefile      |    1 +
>  drivers/mfd/as3722-core.c |  747 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 763 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mfd/as3722-core.c
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index aecd6dd..a02777c 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -27,6 +27,21 @@ config MFD_AS3711
>  	help
>  	  Support for the AS3711 PMIC from AMS
>  
> +config MFD_AS3722
> +        tristate "Support for ams AS3722 PMIC"
> +        select MFD_CORE
> +        select REGMAP_I2C
> +        select REGMAP_IRQ
> +        depends on I2C=y
> +        help
> +          Core support for the ams AS3722 PMIC. Additional
> +          drivers must be enabled in order to use the functionality of the
> +          device.
> +          Related drivers are:
> +                * ams AS3722 PMIC regulators
> +                * ams AS3722 GPIO
> +                * ams AS3722 RTC
> +
>  config PMIC_ADP5520
>  	bool "Analog Devices ADP5520/01 MFD PMIC Core Support"
>  	depends on I2C=y
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 3c90051..358e46e 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -159,3 +159,4 @@ obj-$(CONFIG_MFD_LM3533)	+= lm3533-core.o lm3533-ctrlbank.o
>  obj-$(CONFIG_VEXPRESS_CONFIG)	+= vexpress-config.o vexpress-sysreg.o
>  obj-$(CONFIG_MFD_RETU)		+= retu-mfd.o
>  obj-$(CONFIG_MFD_AS3711)	+= as3711.o
> +obj-$(CONFIG_MFD_AS3722)        += as3722-core.o as3722-regmap.o
> diff --git a/drivers/mfd/as3722-core.c b/drivers/mfd/as3722-core.c
> new file mode 100644
> index 0000000..ddb39c7
> --- /dev/null
> +++ b/drivers/mfd/as3722-core.c
> @@ -0,0 +1,747 @@
> +/*
> + * as3722-core.c - core driver for AS3722 PMICs
> + *
> + * Copyright (C) 2013 ams AG
> + *
> + * Author: Florian Lobmaier <florian.lobmaier@ams.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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/i2c.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <linux/regmap.h>
> +#include <linux/err.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/core.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/as3722-reg.h>
> +#include <linux/mfd/as3722-plat.h>
> +
> +enum as3722_ids {
> +	AS3722_GPIO_ID,
> +	AS3722_REGULATOR_ID,
> +	AS3722_RTC_ID,
> +	AS3722_WATCHDOG_ID,
> +	AS3722_PWM_ID,
> +};
> +
> +static const struct resource as3722_rtc_resource[] = {
> +	{
> +		.name = "as3722-rtc-alarm",
> +		.start = AS3722_IRQ_RTC_ALARM,
> +		.end = AS3722_IRQ_RTC_ALARM,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
> +static const struct resource as3722_wdt_resource[] = {
> +	{
> +		.name = "as3722-watchdog-ping",
> +		.start = AS3722_IRQ_WATCHDOG,
> +		.end = AS3722_IRQ_WATCHDOG,
> +		.flags = IORESOURCE_IRQ,
> +	},
> +};
> +
> +static struct mfd_cell as3722_devs[] = {
> +	{
> +		.name = "as3722-gpio",
> +		.id = AS3722_GPIO_ID,
> +	},
> +	{
> +		.name = "as3722-regulator",
> +		.id = AS3722_REGULATOR_ID,
> +	},
> +	{
> +		.name = "as3722-rtc",
> +		.num_resources = ARRAY_SIZE(as3722_rtc_resource),
> +		.resources = as3722_rtc_resource,
> +		.id = AS3722_RTC_ID,
> +	},
> +	{
> +		.name = "as3722-wdt",
> +		.num_resources = ARRAY_SIZE(as3722_wdt_resource),
> +		.resources = as3722_wdt_resource,
> +		.id = AS3722_WATCHDOG_ID,
> +	},
> +	{
> +		.name = "as3722-pwm",
> +		.id = AS3722_PWM_ID,
> +	},
> +};
> +
> +static const struct regmap_irq as3722_irqs[] = {
> +	/* INT1 IRQs */
> +	[AS3722_IRQ_LID] = {
> +		.mask = AS3722_IRQ_MASK_LID,
> +	},
> +	[AS3722_IRQ_ACOK] = {
> +		.mask = AS3722_IRQ_MASK_ACOK,
> +	},
> +	[AS3722_IRQ_ENABLE1] = {
> +		.mask = AS3722_IRQ_MASK_ENABLE1,
> +	},
> +	[AS3722_IRQ_SD0] = {
> +		.mask = AS3722_IRQ_MASK_SD0,
> +	},
> +	[AS3722_IRQ_ONKEY_LONG] = {
> +		.mask = AS3722_IRQ_MASK_ONKEY_LONG,
> +	},
> +	[AS3722_IRQ_ONKEY] = {
> +		.mask = AS3722_IRQ_MASK_ONKEY,
> +	},
> +	[AS3722_IRQ_OVTMP] = {
> +		.mask = AS3722_IRQ_MASK_OVTMP,
> +	},
> +	[AS3722_IRQ_LOWBAT] = {
> +		.mask = AS3722_IRQ_MASK_LOWBAT,
> +	},
> +	[AS3722_IRQ_RTC_REP] = {
> +		.mask = AS3722_IRQ_MASK_RTC_REP,
> +		.reg_offset = 1,
> +	},
> +	[AS3722_IRQ_RTC_ALARM] = {
> +		.mask = AS3722_IRQ_MASK_RTC_ALARM,
> +		.reg_offset = 2,
> +	},
> +	[AS3722_IRQ_WATCHDOG] = {
> +		.mask = AS3722_IRQ_MASK_WATCHDOG,
> +		.reg_offset = 2,
> +	},
> +	[AS3722_IRQ_ADC] = {
> +		.mask = AS3722_IRQ_MASK_ADC,
> +		.reg_offset = 3,
> +	},
> +	[AS3722_IRQ_GPIO1] = {
> +		.mask = AS3722_IRQ_MASK_GPIO1,
> +		.reg_offset = 2,
> +	},
> +	[AS3722_IRQ_GPIO2] = {
> +		.mask = AS3722_IRQ_MASK_GPIO2,
> +		.reg_offset = 2,
> +	},
> +	[AS3722_IRQ_GPIO3] = {
> +		.mask = AS3722_IRQ_MASK_GPIO3,
> +		.reg_offset = 2,
> +	},
> +	[AS3722_IRQ_GPIO4] = {
> +		.mask = AS3722_IRQ_MASK_GPIO4,
> +		.reg_offset = 2,
> +	},
> +	[AS3722_IRQ_GPIO5] = {
> +		.mask = AS3722_IRQ_MASK_GPIO5,
> +		.reg_offset = 2,
> +	},
> +	[AS3722_IRQ_TEMP_SD0_SHUTDOWN] = {
> +		.mask = AS3722_IRQ_MASK_TEMP_SD0_SHUTDOWN,
> +		.reg_offset = 3,
> +	},
> +	[AS3722_IRQ_TEMP_SD1_SHUTDOWN] = {
> +		.mask = AS3722_IRQ_MASK_TEMP_SD1_SHUTDOWN,
> +		.reg_offset = 3,
> +	},
> +	[AS3722_IRQ_TEMP_SD6_SHUTDOWN] = {
> +		.mask = AS3722_IRQ_MASK_TEMP_SD6_SHUTDOWN,
> +		.reg_offset = 3,
> +	},
> +	[AS3722_IRQ_TEMP_SD0_ALARM] = {
> +		.mask = AS3722_IRQ_MASK_TEMP_SD0_ALARM,
> +		.reg_offset = 3,
> +	},
> +	[AS3722_IRQ_TEMP_SD1_ALARM] = {
> +		.mask = AS3722_IRQ_MASK_TEMP_SD1_ALARM,
> +		.reg_offset = 3,
> +	},
> +	[AS3722_IRQ_TEMP_SD6_ALARM] = {
> +		.mask = AS3722_IRQ_MASK_TEMP_SD6_ALARM,
> +		.reg_offset = 3,
> +	},
> +};
> +
> +static struct regmap_irq_chip as3722_irq_chip = {
> +	.name = "as3722",
> +	.irqs = as3722_irqs,
> +	.num_irqs = ARRAY_SIZE(as3722_irqs),
> +	.num_regs = 4,
> +	.status_base = AS3722_INTERRUPTSTATUS1_REG,
> +	.mask_base = AS3722_INTERRUPTMASK1_REG,
> +	.wake_base = 1,
> +};
> +
> +static void as3722_reg_init(struct as3722 *as3722,
> +		struct as3722_reg_init *reg_data)
> +{
> +	int ret;
> +
> +	while (reg_data->reg != AS3722_REG_INIT_TERMINATE) {
> +		ret = as3722_reg_write(as3722, reg_data->reg, reg_data->val);
> +		if (ret) {
> +			dev_err(as3722->dev,
> +					"reg setup failed: %d\n", ret);
> +			return;
> +		}
> +		reg_data++;
> +	}
> +}
> +
> +int as3722_read_adc(struct as3722 *as3722,
> +		enum as3722_adc_channel channel,
> +		enum as3722_adc_source source,
> +		enum as3722_adc_voltange_range voltage_range)
> +{
> +	int result = 0;
> +	unsigned int try_counter = 0;
> +	u32 val;
> +
> +	mutex_lock(&as3722->adc_mutex);
> +	/* select source */
> +	as3722_set_bits(as3722,
> +			AS3722_ADC0_CONTROL_REG + channel,
> +			AS3722_ADC_MASK_SOURCE_SELECT,
> +			source);
> +	/* select voltage range */
> +	as3722_set_bits(as3722,
> +			AS3722_ADC0_CONTROL_REG + channel,
> +			AS3722_ADC_MASK_VOLTAGE_RANGE,
> +			voltage_range << AS3722_ADC_SHIFT_VOLTAGE_RANGE);
> +	/* start conversion */
> +	as3722_set_bits(as3722,
> +			AS3722_ADC0_CONTROL_REG + channel,
> +			AS3722_ADC_MASK_CONV_START,
> +			AS3722_ADC_BIT_CONV_START);
> +
> +	/*
> +	 * check if result ready
> +	 * as no HW interrupt is available we have to poll
> +	 * the status bit. The result is available on the next I2C read
> +	 * at 400kHz I2C speed, so no threaded polling required.
> +	 */
> +	try_counter = 0;
> +	do {
> +		/* 2*channel for correct channel nr.1 read offset */
> +		as3722_reg_read(as3722,
> +				AS3722_ADC0_MSB_RESULT_REG + 2*channel,
> +				&val);
> +		/* check if conversion is ready */
> +		if ((val & AS3722_ADC_MASK_CONV_NOTREADY)
> +		     != AS3722_ADC_BIT_CONV_NOTREADY
> +		   )
> +			break;	/* conversion ready */
> +		/*
> +		 * if not, we try  max. 10 times which ensures
> +		 * that it works up to 4MHz I2C speed and that
> +		 * we stop if something goes wrong
> +		 */
> +		try_counter++;
> +	} while (try_counter < 10);
> +
> +	/* read result, MSB byte already available from last read */
> +	result = ((val & AS3722_ADC_MASK_MSB_VAL) << 8);
> +	as3722_reg_read(as3722,
> +			AS3722_ADC0_LSB_RESULT_REG + 2*channel,
> +			&val);
> +	result += (val & AS3722_ADC_MASK_LSB_VAL);
> +
> +	mutex_unlock(&as3722->adc_mutex);
> +
> +	return result;
> +}
> +EXPORT_SYMBOL_GPL(as3722_read_adc);
> +
> +static irqreturn_t as3722_onkey_press_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 ONKEY pressed\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t as3722_onkey_lpress_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 ONKEY long pressed\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t as3722_temp_sd0_shutdown_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 temp SD0 shutdown triggered\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t as3722_temp_sd1_shutdown_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 temp SD1 shutdown triggered\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t as3722_temp_sd6_shutdown_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 temp SD6 shutdown triggered\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t as3722_temp_sd0_alarm_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 temp SD0 alarm triggered\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t as3722_temp_sd1_alarm_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 temp SD1 alarm triggered\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t as3722_temp_sd6_alarm_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 temp SD6 alarm triggered\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t as3722_ovtmp_alarm_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 ovtmp alarm triggered\n");
> +	return IRQ_HANDLED;
> +}
> +
> +static int as3722_init(struct as3722 *as3722,
> +		struct as3722_platform_data *pdata, int irq)
> +{
> +	u32 reg;
> +	int ret;
> +	int irq_onkey, irq_onkeylong;
> +	int irq_temp_sd0_shutdown, irq_temp_sd1_shutdown, irq_temp_sd6_shutdown;
> +	int irq_temp_sd0_alarm, irq_temp_sd1_alarm, irq_temp_sd6_alarm;
> +	int irq_ovtmp_alarm;
> +
> +	/* Check that this is actually a AS3722 */
> +	ret = regmap_read(as3722->regmap, AS3722_ADDR_ASIC_ID1, &reg);
> +	if (ret != 0) {
> +		dev_err(as3722->dev,
> +			"Chip ID register read failed\n");
> +		return ret;
> +	}
> +	if (reg != AS3722_DEVICE_ID) {
> +		dev_err(as3722->dev,
> +			"Device is not an AS3722, ID is 0x%x\n",
> +			reg);
> +		return -ENODEV;
> +	}
> +
> +	ret = regmap_read(as3722->regmap, AS3722_ADDR_ASIC_ID2, &reg);
> +	if (ret != 0) {
> +		dev_err(as3722->dev,
> +			"ID2 register read failed: %d\n",
> +			ret);
> +		return ret;
> +	}
> +	dev_info(as3722->dev, "AS3722 with revision %x found\n", reg);
> +
> +	/* init adc mutex */
> +	mutex_init(&as3722->adc_mutex);
> +
> +	/* request irqs for onkey and over temperature */
> +	if (as3722->irq_data) {
> +		irq_onkey = regmap_irq_get_virq(as3722->irq_data,
> +						AS3722_IRQ_ONKEY);
> +		ret = request_threaded_irq(irq_onkey,
> +					   NULL,
> +					   as3722_onkey_press_irq,
> +					   pdata->irq_type,
> +					   "onkey-press",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request ONKEY IRQ: %d\n",
> +				 ret);
> +
> +		irq_onkeylong = regmap_irq_get_virq(as3722->irq_data,
> +						    AS3722_IRQ_ONKEY_LONG);
> +		ret = request_threaded_irq(irq_onkeylong,
> +					   NULL,
> +					   as3722_onkey_lpress_irq,
> +					   pdata->irq_type,
> +					   "onkey-lpress",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request ONKEY_LONG IRQ: %d\n",
> +				 ret);
> +
> +		irq_temp_sd0_shutdown =
> +			regmap_irq_get_virq(as3722->irq_data,
> +					    AS3722_IRQ_TEMP_SD0_SHUTDOWN);
> +		ret = request_threaded_irq(irq_temp_sd0_shutdown,
> +					   NULL,
> +					   as3722_temp_sd0_shutdown_irq,
> +					   pdata->irq_type,
> +					   "temp sd0 shutdown",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request temp sd0 shutdown IRQ:"
> +				 " %d\n",
> +				 ret);
> +		irq_temp_sd1_shutdown =
> +			regmap_irq_get_virq(as3722->irq_data,
> +					    AS3722_IRQ_TEMP_SD1_SHUTDOWN);
> +		ret = request_threaded_irq(irq_temp_sd1_shutdown,
> +					   NULL,
> +					   as3722_temp_sd1_shutdown_irq,
> +					   pdata->irq_type,
> +					   "temp sd1 shutdown",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request temp sd1 shutdown IRQ:"
> +				 " %d\n",
> +				 ret);
> +		irq_temp_sd6_shutdown =
> +			regmap_irq_get_virq(as3722->irq_data,
> +					    AS3722_IRQ_TEMP_SD6_SHUTDOWN);
> +		ret = request_threaded_irq(irq_temp_sd6_shutdown,
> +					   NULL,
> +					   as3722_temp_sd6_shutdown_irq,
> +					   pdata->irq_type,
> +					   "temp sd6 shutdown",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request temp sd6 shutdown IRQ:"
> +				 " %d\n",
> +				 ret);
> +		irq_temp_sd0_alarm =
> +			regmap_irq_get_virq(as3722->irq_data,
> +					    AS3722_IRQ_TEMP_SD0_ALARM);
> +		ret = request_threaded_irq(irq_temp_sd0_alarm,
> +					   NULL,
> +					   as3722_temp_sd0_alarm_irq,
> +					   pdata->irq_type,
> +					   "temp sd0 alarm",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request temp sd0 alarm IRQ:"
> +				 " %d\n",
> +				 ret);
> +
> +		irq_temp_sd1_alarm =
> +			regmap_irq_get_virq(as3722->irq_data,
> +					    AS3722_IRQ_TEMP_SD1_ALARM);
> +		ret = request_threaded_irq(irq_temp_sd1_alarm,
> +					   NULL,
> +					   as3722_temp_sd1_alarm_irq,
> +					   pdata->irq_type,
> +					   "temp sd1 alarm",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request temp sd1 alarm IRQ:"
> +				 " %d\n",
> +				 ret);
> +		irq_temp_sd6_alarm =
> +			regmap_irq_get_virq(as3722->irq_data,
> +					    AS3722_IRQ_TEMP_SD6_ALARM);
> +		ret = request_threaded_irq(irq_temp_sd6_alarm,
> +					   NULL,
> +					   as3722_temp_sd6_alarm_irq,
> +					   pdata->irq_type,
> +					   "temp sd6 alarm",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request temp sd6 alarm IRQ:"
> +				 " %d\n",
> +				 ret);
> +
> +		irq_ovtmp_alarm =
> +			regmap_irq_get_virq(as3722->irq_data,
> +					    AS3722_IRQ_OVTMP);
> +		ret = request_threaded_irq(irq_ovtmp_alarm,
> +					   NULL,
> +					   as3722_ovtmp_alarm_irq,
> +					   pdata->irq_type,
> +					   "ovtmp alarm",
> +					   as3722);
> +		if (ret < 0)
> +			dev_warn(as3722->dev,
> +				 "Failed to request ovtmp alarm IRQ:"
> +				 " %d\n",
> +				 ret);
> +	}
> +
> +	/* do some initial platform register setup */
> +	if (pdata->core_init_data)
> +		as3722_reg_init(as3722, pdata->core_init_data);
> +
> +	/* initialise stby reg count variable, used in regulator */
> +	as3722->reg_stby_counter = 0;
> +
> +	/* enable pullups if required */
> +	if (pdata->use_internal_int_pullup == 1)
> +		as3722_set_bits(as3722, AS3722_IOVOLTAGE_REG,
> +				AS3722_INT_PULLUP_MASK,
> +				AS3722_INT_PULLUP_ON);
> +	else
> +		as3722_set_bits(as3722, AS3722_IOVOLTAGE_REG,
> +				AS3722_INT_PULLUP_MASK,
> +				AS3722_INT_PULLUP_OFF);
> +
> +	if (pdata->use_internal_i2c_pullup)
> +		as3722_set_bits(as3722, AS3722_IOVOLTAGE_REG,
> +				AS3722_I2C_PULLUP_MASK,
> +				AS3722_I2C_PULLUP_ON);
> +	else
> +		as3722_set_bits(as3722, AS3722_IOVOLTAGE_REG,
> +				AS3722_I2C_PULLUP_MASK,
> +				AS3722_I2C_PULLUP_OFF);
> +
> +	/* enable1 pin standby configuration */
> +	if (pdata->enable1_deepsleep)
> +		as3722_set_bits(as3722, AS3722_CTRL1_REG,
> +				AS3722_ENABLE1_DEEPSLEEP_MASK,
> +				AS3722_ENABLE1_DEEPSLEEP_ON);
> +	else
> +		as3722_set_bits(as3722, AS3722_CTRL1_REG,
> +				AS3722_ENABLE1_DEEPSLEEP_MASK,
> +				AS3722_ENABLE1_DEEPSLEEP_OFF);
> +
> +	if (pdata->enable1_invert)
> +		as3722_set_bits(as3722, AS3722_CTRL1_REG,
> +				AS3722_ENABLE1_INVERT_MASK,
> +				AS3722_ENABLE1_INVERT_ON);
> +	else
> +		as3722_set_bits(as3722, AS3722_CTRL1_REG,
> +				AS3722_ENABLE1_INVERT_MASK,
> +				AS3722_ENABLE1_INVERT_OFF);
> +
> +	as3722_set_bits(as3722, AS3722_RESETTIMER_REG,
> +			AS3722_OFF_DELAY_MASK,
> +			pdata->off_delay << AS3722_OFF_DELAY_SHIFT);
> +
> +	/* thermal shutdown control */
> +	as3722_set_bits(as3722, AS3722_OVERTEMPERATURE_CONTROL_REG,
> +			AS3722_OVTMP_MASK,
> +			pdata->mask_ovtemp << AS3722_OVTMP_SHIFT);
> +
> +	/* overcurrent/powergood configuration */
> +	reg = (pdata->pg_sd6_vmask_time << AS3722_PG_SD6_VMASK_TIME_SHIFT)
> +			& AS3722_PG_SD6_VMASK_TIME_MASK;
> +	reg |= (pdata->sd6_lv_deb_time << AS3722_SD6_LV_DEB_SHIFT)
> +			& AS3722_SD6_LV_DEB_MASK;
> +	reg |= (pdata->sd1_lv_deb_time << AS3722_SD1_LV_DEB_SHIFT)
> +			& AS3722_SD1_LV_DEB_MASK;
> +	reg |= (pdata->sd0_lv_deb_time << AS3722_SD0_LV_DEB_SHIFT)
> +			& AS3722_SD0_LV_DEB_MASK;
> +	as3722_reg_write(as3722, AS3722_SD_LV_DEB_REG, reg);
> +
> +	reg = (pdata->pg_vresfall_mask << 7)
> +			& AS3722_PG_VRESFALL_MASK_MASK;
> +	reg |= (pdata->pg_ovcurr_sd0_mask << 6)
> +			& AS3722_PG_OVCURR_SD0_MASK_MASK;
> +	reg |= (pdata->pg_pwrgood_sd0_mask << 5)
> +			& AS3722_PG_PWRGOOD_SD0_MASK_MASK;
> +	reg |= (pdata->pg_gpio5_mask << 4)
> +			& AS3722_PG_GPIO5_MASK_MASK;
> +	reg |= (pdata->pg_gpio4_mask << 3)
> +			& AS3722_PG_GPIO4_MASK_MASK;
> +	reg |= (pdata->pg_gpio3_mask << 2)
> +			& AS3722_PG_GPIO3_MASK_MASK;
> +	reg |= (pdata->pg_ac_ok_mask << 1)
> +			& AS3722_PG_AC_OK_MASK_MASK;
> +	reg |= (pdata->pg_ac_ok_inv)
> +			& AS3722_PG_AC_OK_INV_MASK;
> +	as3722_reg_write(as3722, AS3722_OC_PG_CONTROL_REG, reg);
> +
> +	reg = (pdata->pg_ovcurr_sd6_mask << 7)
> +			& AS3722_PG_OVCURR_SD6_MASK_MASK;
> +	reg |= (pdata->pg_pwrgood_sd6_mask << 6)
> +			& AS3722_PG_PWRGOOD_SD6_MASK_MASK;
> +	reg |= (pdata->pg_sd6_ovc_alarm << 3)
> +			& AS3722_PG_SD6_OVC_ALARM_MASK;
> +	reg |= (pdata->pg_sd0_vmask_time << 1)
> +			& AS3722_PG_SD0_VMASK_TIME_MASK;
> +	reg |= (pdata->oc_pg_inv)
> +			& AS3722_OC_PG_INV_MASK;
> +	as3722_reg_write(as3722, AS3722_OC_PG_CONTROL2_REG, reg);
> +
> +	/* enable 32kHz clock output if required */
> +	if (pdata->enable_clk32out_pin)
> +		as3722_set_bits(as3722, AS3722_RTC_CONTROL_REG,
> +				AS3722_CLK32OUT_ENABLE_MASK,
> +				AS3722_CLK32OUT_ENABLE_ON);
> +	else
> +		as3722_set_bits(as3722, AS3722_RTC_CONTROL_REG,
> +				AS3722_CLK32OUT_ENABLE_MASK,
> +				AS3722_CLK32OUT_ENABLE_OFF);
> +	return 0;
> +}
> +
> +static int as3722_i2c_probe(struct i2c_client *i2c,
> +		const struct i2c_device_id *id)
> +{
> +	struct as3722 *as3722;
> +	struct as3722_platform_data *pdata;
> +	int irq_flags;
> +	int ret;
> +
> +	pdata = dev_get_platdata(&i2c->dev);
> +	if (!pdata) {
> +		dev_err(&i2c->dev, "as3722 requires platform data\n");
> +		return -EINVAL;
> +	}
> +
> +	as3722 = devm_kzalloc(&i2c->dev, sizeof(struct as3722), GFP_KERNEL);
> +	if (!as3722)
> +		return -ENOMEM;
> +
> +	as3722->dev = &i2c->dev;
> +	as3722->chip_irq = i2c->irq;
> +	i2c_set_clientdata(i2c, as3722);
> +
> +	as3722->regmap = devm_regmap_init_i2c(i2c, &as3722_regmap_config);
> +	if (IS_ERR(as3722->regmap)) {
> +		ret = PTR_ERR(as3722->regmap);
> +		dev_err(&i2c->dev, "regmap_init failed with err: %d\n", ret);
> +		return ret;
> +	}
> +
> +	irq_flags = pdata->irq_type;
> +	irq_flags |= IRQF_ONESHOT;
> +	ret = regmap_add_irq_chip(as3722->regmap, as3722->chip_irq,
> +			irq_flags, pdata->irq_base, &as3722_irq_chip,
> +			&as3722->irq_data);
> +	if (ret < 0) {
> +		dev_err(as3722->dev,
> +			"irq allocation failed for as3722 failed\n");
> +		return ret;
> +	}
> +
> +	ret = as3722_init(as3722, pdata, i2c->irq);
> +	if (ret < 0)
> +		return ret;
> +
> +	ret = mfd_add_devices(&i2c->dev,
> +			      -1,
> +			      as3722_devs,
> +			      ARRAY_SIZE(as3722_devs),
> +			      NULL,
> +			      pdata->irq_base,
> +			      regmap_irq_get_domain(as3722->irq_data));
> +	if (ret) {
> +		dev_err(as3722->dev,
> +			"add mfd devices failed with err: %d\n",
> +			ret);
> +		return ret;
> +	}
> +
> +	dev_info(as3722->dev,
> +		 "AS3722 core driver initialized successfully\n");
> +
> +	return 0;
> +}
> +
> +static int as3722_i2c_remove(struct i2c_client *i2c)
> +{
> +	struct as3722 *as3722 = i2c_get_clientdata(i2c);
> +	int irq_onkeylong, irq_onkey;
> +	int irq_temp_sd0_shutdown, irq_temp_sd1_shutdown, irq_temp_sd6_shutdown;
> +	int irq_temp_sd0_alarm, irq_temp_sd1_alarm, irq_temp_sd6_alarm;
> +	int irq_ovtmp_alarm;
> +
> +	irq_onkeylong = regmap_irq_get_virq(as3722->irq_data,
> +					    AS3722_IRQ_ONKEY_LONG);
> +	irq_onkey = regmap_irq_get_virq(as3722->irq_data, AS3722_IRQ_ONKEY);
> +	irq_temp_sd0_shutdown =
> +		regmap_irq_get_virq(as3722->irq_data,
> +				    AS3722_IRQ_TEMP_SD0_SHUTDOWN);
> +	irq_temp_sd1_shutdown =
> +		regmap_irq_get_virq(as3722->irq_data,
> +				    AS3722_IRQ_TEMP_SD1_SHUTDOWN);
> +	irq_temp_sd6_shutdown =
> +		regmap_irq_get_virq(as3722->irq_data,
> +				    AS3722_IRQ_TEMP_SD6_SHUTDOWN);
> +	irq_temp_sd0_alarm =
> +		regmap_irq_get_virq(as3722->irq_data,
> +				    AS3722_IRQ_TEMP_SD0_ALARM);
> +	irq_temp_sd1_alarm =
> +		regmap_irq_get_virq(as3722->irq_data,
> +				    AS3722_IRQ_TEMP_SD1_ALARM);
> +	irq_temp_sd6_alarm =
> +		regmap_irq_get_virq(as3722->irq_data,
> +				    AS3722_IRQ_TEMP_SD6_ALARM);
> +	irq_ovtmp_alarm =
> +		regmap_irq_get_virq(as3722->irq_data,
> +				    AS3722_IRQ_OVTMP);
> +
> +	free_irq(irq_onkeylong, as3722);
> +	free_irq(irq_onkey, as3722);
> +	free_irq(irq_temp_sd0_shutdown, as3722);
> +	free_irq(irq_temp_sd1_shutdown, as3722);
> +	free_irq(irq_temp_sd6_shutdown, as3722);
> +	free_irq(irq_temp_sd0_alarm, as3722);
> +	free_irq(irq_temp_sd1_alarm, as3722);
> +	free_irq(irq_temp_sd6_alarm, as3722);
> +	free_irq(irq_ovtmp_alarm, as3722);
> +	mfd_remove_devices(as3722->dev);
> +	regmap_del_irq_chip(as3722->chip_irq, as3722->irq_data);
> +
> +	return 0;
> +}
> +
> +static const struct i2c_device_id as3722_i2c_id[] = {
> +	{ "as3722", 0 },
> +	{ }
> +};
> +
> +MODULE_DEVICE_TABLE(i2c, as3722_i2c_id);
> +
> +static struct i2c_driver as3722_i2c_driver = {
> +	.driver = {
> +		.name = "as3722",
> +		.owner = THIS_MODULE,
> +	},
> +	.probe = as3722_i2c_probe,
> +	.remove = as3722_i2c_remove,
> +	.id_table = as3722_i2c_id,
> +};
> +
> +module_i2c_driver(as3722_i2c_driver);
> +
> +MODULE_DESCRIPTION("I2C, IRQ and ADC support for AS3722 PMICs");
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");

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

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

* Re: [PATCH 1/4] added support for ams AS3722 PMIC in mfd
  2013-08-14 14:54 [PATCH 1/4] added support for ams AS3722 PMIC in mfd Florian Lobmaier
                   ` (3 preceding siblings ...)
  2013-08-14 15:27 ` [PATCH 1/4] added support for ams AS3722 PMIC in mfd Lee Jones
@ 2013-08-14 15:27 ` Mark Brown
  4 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2013-08-14 15:27 UTC (permalink / raw)
  To: Florian Lobmaier; +Cc: linux-kernel, sameo, lee.jones

[-- Attachment #1: Type: text/plain, Size: 2030 bytes --]

On Wed, Aug 14, 2013 at 04:54:55PM +0200, Florian Lobmaier wrote:

> +static struct regmap_irq_chip as3722_irq_chip = {
> +	.name = "as3722",
> +	.irqs = as3722_irqs,
> +	.num_irqs = ARRAY_SIZE(as3722_irqs),
> +	.num_regs = 4,
> +	.status_base = AS3722_INTERRUPTSTATUS1_REG,
> +	.mask_base = AS3722_INTERRUPTMASK1_REG,
> +	.wake_base = 1,
> +};

wake_base looks wrong - that should be either absent or a register name.

> +static void as3722_reg_init(struct as3722 *as3722,
> +		struct as3722_reg_init *reg_data)
> +{
> +	int ret;
> +
> +	while (reg_data->reg != AS3722_REG_INIT_TERMINATE) {
> +		ret = as3722_reg_write(as3722, reg_data->reg, reg_data->val);
> +		if (ret) {
> +			dev_err(as3722->dev,
> +					"reg setup failed: %d\n", ret);
> +			return;
> +		}
> +		reg_data++;
> +	}
> +}

This looks like it might be supposed to be a register patch?

> +int as3722_read_adc(struct as3722 *as3722,
> +		enum as3722_adc_channel channel,
> +		enum as3722_adc_source source,
> +		enum as3722_adc_voltange_range voltage_range)

This should be moved over to IIO - the ADC code in MFDs predates IIO
being available.

> +static irqreturn_t as3722_onkey_press_irq(int irq, void *irq_data)

> +static irqreturn_t as3722_onkey_lpress_irq(int irq, void *irq_data)

These should be handled by an input driver.

> +static irqreturn_t as3722_temp_sd0_shutdown_irq(int irq, void *irq_data)
> +{
> +	struct as3722 *as3722 = irq_data;
> +
> +	dev_dbg(as3722->dev, "AS3722 temp SD0 shutdown triggered\n");
> +	return IRQ_HANDLED;
> +}

You probably want these to complain loudly rather than as dev_dbg(), I'm
not sure what the status of the thermal framework is.

> +	/* enable 32kHz clock output if required */
> +	if (pdata->enable_clk32out_pin)
> +		as3722_set_bits(as3722, AS3722_RTC_CONTROL_REG,
> +				AS3722_CLK32OUT_ENABLE_MASK,
> +				AS3722_CLK32OUT_ENABLE_ON);
> +	else
> +		as3722_set_bits(as3722, AS3722_RTC_CONTROL_REG,
> +				AS3722_CLK32OUT_ENABLE_MASK,
> +				AS3722_CLK32OUT_ENABLE_OFF);

This looks like a job for the clk API.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH 2/4] added regmap of AS3722
  2013-08-14 14:54 ` [PATCH 2/4] added regmap of AS3722 Florian Lobmaier
@ 2013-08-14 15:29   ` Mark Brown
  0 siblings, 0 replies; 8+ messages in thread
From: Mark Brown @ 2013-08-14 15:29 UTC (permalink / raw)
  To: Florian Lobmaier; +Cc: linux-kernel, sameo, lee.jones

[-- Attachment #1: Type: text/plain, Size: 696 bytes --]

On Wed, Aug 14, 2013 at 04:54:56PM +0200, Florian Lobmaier wrote:

> +static bool as3722_readable(struct device *dev, unsigned int reg)
> +{
> +	switch (reg) {
> +	case AS3722_SD0_VOLTAGE_REG:

Are there any gaps in this register map?  If not just checking the range
would be easier (it looks like this is the case here).

> +	case AS3722_INTERRUPTSTATUS1_REG:
> +	case AS3722_INTERRUPTSTATUS2_REG:
> +	case AS3722_INTERRUPTSTATUS3_REG:
> +	case AS3722_INTERRUPTSTATUS4_REG:

> +static bool as3722_volatile(struct device *dev, unsigned int reg)
> +{
> +	return false;
> +}

At least the interrupt status register above should be volatile
otherwise you'll never be able to read the actual stauts.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH 4/4] added ams AS3722 register include file
  2013-08-14 14:54 ` [PATCH 4/4] added ams AS3722 register " Florian Lobmaier
@ 2013-08-14 15:33   ` Lee Jones
  0 siblings, 0 replies; 8+ messages in thread
From: Lee Jones @ 2013-08-14 15:33 UTC (permalink / raw)
  To: Florian Lobmaier; +Cc: linux-kernel, sameo

> ---
>  include/linux/mfd/as3722-reg.h |  495 ++++++++++++++++++++++++++++++++++++++++

So the way you've split up the patch isn't quite right. It shouldn't
be split by files, rather by functionality.

Quoting from Documentation/SubmittingPatches:

"If your changes produce a lot of deltas, you may want to look into
 splitting them into individual patches which modify things in
 logical stages.  This will facilitate easier reviewing by other
 kernel developers, very important if you want your patch accepted."

Note "logical stages".

So things like:

- Driver introduction including Kconfig and Makefile entries
- Resource allocation; memory and irqs
- Everything else, bit by bit

Within reason, the simpler the patches, they more likely they are to
be reviewed and accepted.

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

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

end of thread, other threads:[~2013-08-14 15:33 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-14 14:54 [PATCH 1/4] added support for ams AS3722 PMIC in mfd Florian Lobmaier
2013-08-14 14:54 ` [PATCH 2/4] added regmap of AS3722 Florian Lobmaier
2013-08-14 15:29   ` Mark Brown
2013-08-14 14:54 ` [PATCH 3/4] added AS3722 platform include file Florian Lobmaier
2013-08-14 14:54 ` [PATCH 4/4] added ams AS3722 register " Florian Lobmaier
2013-08-14 15:33   ` Lee Jones
2013-08-14 15:27 ` [PATCH 1/4] added support for ams AS3722 PMIC in mfd Lee Jones
2013-08-14 15:27 ` Mark Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox