diff mbox

[PATCHv7,19/21] ARM: OMAP3+: PM: introduce a central pmic control

Message ID 1348590833-12335-20-git-send-email-t-kristo@ti.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tero Kristo Sept. 25, 2012, 4:33 p.m. UTC
From: Nishanth Menon <nm@ti.com>

Since we are starting to use multiple PMICs in various combinations,
use the existing .omap_chip = OMAP_CHIP_INIT() to mark the
structures we are interested in using per OMAP device we
are currently running on. This mapping is based on the default
device recommendations from TI. Boards using custom PMICs now
have an opportunity to register their own custom mapping.

With this we no longer need omap4_twl_init and omap3_twl_int
instead we introduce a registration mechanism which is PMIC
generic and move twl implementation to use the same. This allows
for future OMAP4460 support where there is a mixture of
PMIC combinations used.

Signed-off-by: Nishanth Menon <nm@ti.com>
[t-kristo@ti.com: moved code under twl-common, other minor cleanups]
Signed-off-by: Tero Kristo <t-kristo@ti.com>
---
 arch/arm/mach-omap2/omap_twl.c   |   81 ++++++++++++++++++++++----------------
 arch/arm/mach-omap2/pm.h         |    9 +---
 arch/arm/mach-omap2/twl-common.c |   58 +++++++++++++++++++++++++--
 arch/arm/mach-omap2/twl-common.h |   27 +++++++++++++
 4 files changed, 129 insertions(+), 46 deletions(-)
diff mbox

Patch

diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 7ff9667..f6ee038 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -19,8 +19,8 @@ 
 #include <linux/i2c/twl.h>
 
 #include "voltage.h"
-
 #include "pm.h"
+#include "twl-common.h"
 
 #define OMAP3_SRI2C_SLAVE_ADDR		0x12
 #define OMAP3_VDD_MPU_SR_CONTROL_REG	0x00
@@ -170,7 +170,7 @@  static struct omap_voltdm_pmic omap3_core_pmic = {
 	.uv_to_vsel		= twl4030_uv_to_vsel,
 };
 
-static struct omap_voltdm_pmic omap4_mpu_pmic = {
+static struct omap_voltdm_pmic twl6030_vcore1_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12660,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
@@ -188,7 +188,7 @@  static struct omap_voltdm_pmic omap4_mpu_pmic = {
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-static struct omap_voltdm_pmic omap4_iva_pmic = {
+static struct omap_voltdm_pmic twl6030_vcore2_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12660,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
@@ -206,7 +206,7 @@  static struct omap_voltdm_pmic omap4_iva_pmic = {
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-static struct omap_voltdm_pmic omap4_core_pmic = {
+static struct omap_voltdm_pmic twl6030_vcore3_pmic = {
 	.slew_rate		= 4000,
 	.step_size		= 12660,
 	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
@@ -224,31 +224,9 @@  static struct omap_voltdm_pmic omap4_core_pmic = {
 	.uv_to_vsel		= twl6030_uv_to_vsel,
 };
 
-int __init omap4_twl_init(void)
+static int __init twl_set_sr(struct voltagedomain *voltdm)
 {
-	struct voltagedomain *voltdm;
-
-	if (!cpu_is_omap44xx())
-		return -ENODEV;
-
-	voltdm = voltdm_lookup("mpu");
-	omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);
-
-	voltdm = voltdm_lookup("iva");
-	omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);
-
-	voltdm = voltdm_lookup("core");
-	omap_voltage_register_pmic(voltdm, &omap4_core_pmic);
-
-	return 0;
-}
-
-int __init omap3_twl_init(void)
-{
-	struct voltagedomain *voltdm;
-
-	if (!cpu_is_omap34xx())
-		return -ENODEV;
+	int r = 0;
 
 	/*
 	 * The smartreflex bit on twl4030 specifies if the setting of voltage
@@ -260,15 +238,50 @@  int __init omap3_twl_init(void)
 	 * voltage scaling will not function on TWL over I2C_SR.
 	 */
 	if (!twl_sr_enable_autoinit)
-		omap3_twl_set_sr_bit(true);
+		r = omap3_twl_set_sr_bit(true);
 
-	voltdm = voltdm_lookup("mpu_iva");
-	omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
+	return r;
+}
 
-	voltdm = voltdm_lookup("core");
-	omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
+static __initdata struct omap_pmic_map omap_twl_map[] = {
+	{
+		.name = "mpu_iva",
+		.cpu = PMIC_CPU_OMAP3,
+		.pmic_data = &omap3_mpu_pmic,
+		.special_action = twl_set_sr,
+	},
+	{
+		.name = "core",
+		.cpu = PMIC_CPU_OMAP3,
+		.pmic_data = &omap3_core_pmic,
+	},
+	{
+		.name = "mpu",
+		.cpu = PMIC_CPU_OMAP4430,
+		.pmic_data = &twl6030_vcore1_pmic,
+	},
+	{
+		.name = "core",
+		.cpu = PMIC_CPU_OMAP4430,
+		.pmic_data = &twl6030_vcore3_pmic,
+	},
+	{
+		.name = "core",
+		.cpu = PMIC_CPU_OMAP4460,
+		.pmic_data = &twl6030_vcore1_pmic,
+	},
+	{
+		.name = "iva",
+		.cpu = PMIC_CPU_OMAP44XX,
+		.pmic_data = &twl6030_vcore2_pmic,
+	},
+	/* Terminator */
+	{ .name = NULL, .pmic_data = NULL},
+};
 
-	return 0;
+int __init omap_twl_init(void)
+{
+	return omap_pmic_register_data(omap_twl_map);
 }
 
 /**
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index d070ac6..26ac43c 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -122,15 +122,10 @@  static inline void omap_enable_smartreflex_on_init(void) {}
 #endif
 
 #ifdef CONFIG_TWL4030_CORE
-extern int omap3_twl_init(void);
-extern int omap4_twl_init(void);
+extern int omap_twl_init(void);
 extern int omap3_twl_set_sr_bit(bool enable);
 #else
-static inline int omap3_twl_init(void)
-{
-	return -EINVAL;
-}
-static inline int omap4_twl_init(void)
+static inline int omap_twl_init(void)
 {
 	return -EINVAL;
 }
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c
index db5ff66..4a9ca89 100644
--- a/arch/arm/mach-omap2/twl-common.c
+++ b/arch/arm/mach-omap2/twl-common.c
@@ -97,11 +97,7 @@  void __init omap4_pmic_init(const char *pmic_type,
 
 void __init omap_pmic_late_init(void)
 {
-	/* Init the OMAP TWL parameters (if PMIC has been registered) */
-	if (pmic_i2c_board_info.irq)
-		omap3_twl_init();
-	if (omap4_i2c1_board_info[0].irq)
-		omap4_twl_init();
+	omap_twl_init();
 }
 
 #if defined(CONFIG_ARCH_OMAP3)
@@ -538,3 +534,55 @@  void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
 		pmic_data->v2v1 = &omap4_v2v1_idata;
 }
 #endif /* CONFIG_ARCH_OMAP4 */
+
+/**
+ * omap_pmic_register_data() - Register the PMIC information to OMAP mapping
+ * @omap_pmic_maps:    array ending with a empty element representing the maps
+ */
+int __init omap_pmic_register_data(struct omap_pmic_map *map)
+{
+	struct voltagedomain *voltdm;
+	int r;
+
+	if (!map)
+		return 0;
+
+	while (map->name) {
+		if (cpu_is_omap34xx() && !(map->cpu & PMIC_CPU_OMAP3))
+			goto next;
+
+		if (cpu_is_omap443x() && !(map->cpu & PMIC_CPU_OMAP4430))
+			goto next;
+
+		if (cpu_is_omap446x() && !(map->cpu & PMIC_CPU_OMAP4460))
+			goto next;
+
+		voltdm = voltdm_lookup(map->name);
+		if (IS_ERR_OR_NULL(voltdm)) {
+			pr_err("%s: unable to find map %s\n", __func__,
+				map->name);
+			goto next;
+		}
+		if (IS_ERR_OR_NULL(map->pmic_data)) {
+			pr_warn("%s: domain[%s] has no pmic data\n",
+					__func__, map->name);
+			goto next;
+		}
+
+		r = omap_voltage_register_pmic(voltdm, map->pmic_data);
+		if (r) {
+			pr_warn("%s: domain[%s] register returned %d\n",
+					__func__, map->name, r);
+			goto next;
+		}
+		if (map->special_action) {
+			r = map->special_action(voltdm);
+			WARN(r, "%s: domain[%s] action returned %d\n", __func__,
+				map->name, r);
+		}
+next:
+		map++;
+	}
+
+	return 0;
+}
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h
index 8fe71cf..c501b55 100644
--- a/arch/arm/mach-omap2/twl-common.h
+++ b/arch/arm/mach-omap2/twl-common.h
@@ -2,6 +2,7 @@ 
 #define __OMAP_PMIC_COMMON__
 
 #include <plat/irqs.h>
+#include "voltage.h"
 
 #define TWL_COMMON_PDATA_USB		(1 << 0)
 #define TWL_COMMON_PDATA_BCI		(1 << 1)
@@ -59,4 +60,30 @@  void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
 void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
 			   u32 pdata_flags, u32 regulators_flags);
 
+/**
+ * struct omap_pmic_map - Describe the OMAP PMIC data for OMAP
+ * @name:		name of the voltage domain
+ * @pmic_data:		pmic data associated with it
+ * @cpu:		CPUs this PMIC data is valid for
+ * @special_action:	callback for any specific action to take for that map
+ *
+ * Since we support multiple PMICs each potentially functioning on multiple
+ * OMAP devices, we describe the parameters in a map allowing us to reuse the
+ * data as necessary.
+ */
+struct omap_pmic_map {
+	char			*name;
+	struct omap_voltdm_pmic	*pmic_data;
+	u32			cpu;
+	int			(*special_action)(struct voltagedomain *);
+};
+
+#define PMIC_CPU_OMAP3		(1 << 0)
+#define PMIC_CPU_OMAP4430	(1 << 1)
+#define PMIC_CPU_OMAP4460	(1 << 2)
+#define PMIC_CPU_OMAP44XX	(PMIC_CPU_OMAP4430 | PMIC_CPU_OMAP4460)
+
+extern int omap_pmic_register_data(struct omap_pmic_map *map);
+extern void omap_pmic_data_init(void);
+
 #endif /* __OMAP_PMIC_COMMON__ */