[PATCH 10/17] mfd: prcmu: dbx500-prmcu creation

Loic Pallardy loic.pallardy-ext at stericsson.com
Wed Sep 5 05:59:06 EDT 2012


Create a generic drivers/mfd/dbx500-prcmu.c
Allow supporting and managing several PRCMU IP versions
Use dbx500-prcmu new interfaces to abstract prcmu services.

Signed-off-by: Michel JAOUEN <michel.jaouen at stericsson.com>
Signed-off-by: Loic Pallardy <loic.pallardy at stericsson.com>
Acked-by: Linus Walleij <linus.walleij at linaro.org>
---
 drivers/mfd/Kconfig              |  10 +
 drivers/mfd/Makefile             |   1 +
 drivers/mfd/db8500-prcmu.c       | 303 ++++++++++++---
 drivers/mfd/dbx500-prcmu.c       | 813 +++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/db8500-prcmu.h | 250 +-----------
 include/linux/mfd/dbx500-prcmu.h | 547 ++++++++++----------------
 6 files changed, 1288 insertions(+), 636 deletions(-)
 create mode 100644 drivers/mfd/dbx500-prcmu.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index b1a1462..3420844 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -801,10 +801,20 @@ config AB8500_GPADC
 	help
 	  AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage
 
+config DBX500_PRCMU
+	bool "ST-Ericsson DBX500 Power Reset Control Management Unit"
+	depends on UX500_SOC_DB8500
+	help
+	  Select this option to enable support for generic DBX500 Power
+	  Reset and Control Management Unit. you have to select it for
+	  enabling interface with other components like cpufreq,
+	  cpuidle, prcmu-qos-power.
+
 config MFD_DB8500_PRCMU
 	bool "ST-Ericsson DB8500 Power Reset Control Management Unit"
 	depends on UX500_SOC_DB8500
 	select MFD_CORE
+	select DBX500_PRCMU
 	help
 	  Select this option to enable support for the DB8500 Power Reset
 	  and Control Management Unit. This is basically an autonomous
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 79dd22d..42d703a 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -106,6 +106,7 @@ obj-$(CONFIG_AB3100_CORE)	+= ab3100-core.o
 obj-$(CONFIG_AB3100_OTP)	+= ab3100-otp.o
 obj-$(CONFIG_AB8500_DEBUG)	+= ab8500-debugfs.o
 obj-$(CONFIG_AB8500_GPADC)	+= ab8500-gpadc.o
+obj-$(CONFIG_DBX500_PRCMU)      += dbx500-prcmu.o
 obj-$(CONFIG_MFD_DB8500_PRCMU)	+= db8500-prcmu.o
 # ab8500-core need to come after db8500-prcmu (which provides the channel)
 obj-$(CONFIG_AB8500_CORE)	+= ab8500-core.o ab8500-sysctrl.o
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index eb327f3..36f7c1d 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -615,12 +615,12 @@ int db8500_prcmu_set_display_clocks(void)
 	return 0;
 }
 
-u32 db8500_prcmu_read(unsigned int reg)
+static u32 db8500_prcmu_read(unsigned int reg)
 {
 	return readl(_PRCMU_BASE + reg);
 }
 
-void db8500_prcmu_write(unsigned int reg, u32 value)
+static void db8500_prcmu_write(unsigned int reg, u32 value)
 {
 	unsigned long flags;
 
@@ -629,7 +629,7 @@ void db8500_prcmu_write(unsigned int reg, u32 value)
 	spin_unlock_irqrestore(&prcmu_lock, flags);
 }
 
-void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
+static void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
 {
 	u32 val;
 	unsigned long flags;
@@ -641,12 +641,12 @@ void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
 	spin_unlock_irqrestore(&prcmu_lock, flags);
 }
 
-struct prcmu_fw_version *prcmu_get_fw_version(void)
+static struct prcmu_fw_version *db8500_prcmu_get_fw_version(void)
 {
 	return fw_info.valid ? &fw_info.version : NULL;
 }
 
-bool prcmu_has_arm_maxopp(void)
+static bool db8500_prcmu_has_arm_maxopp(void)
 {
 	return (readb(tcdm_base + PRCM_AVS_VARM_MAX_OPP) &
 		PRCM_AVS_ISMODEENABLE_MASK) == PRCM_AVS_ISMODEENABLE_MASK;
@@ -700,7 +700,7 @@ enum ap_pwrst prcmu_get_xp70_current_state(void)
 }
 
 /**
- * prcmu_config_clkout - Configure one of the programmable clock outputs.
+ * db8500_prcmu_config_clkout - Configure one of the programmable clock outputs.
  * @clkout:	The CLKOUT number (0 or 1).
  * @source:	The clock to be used (one of the PRCMU_CLKSRC_*).
  * @div:	The divider to be applied.
@@ -709,7 +709,7 @@ enum ap_pwrst prcmu_get_xp70_current_state(void)
  * @div should be in the range [1,63] to request a configuration, or 0 to
  * inform that the configuration is no longer requested.
  */
-int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
+static int db8500_prcmu_config_clkout(u8 clkout, u8 source, u8 div)
 {
 	static int requests[2];
 	int r = 0;
@@ -794,7 +794,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 	return 0;
 }
 
-u8 db8500_prcmu_get_power_state_result(void)
+static u8 db8500_prcmu_get_power_state_result(void)
 {
 	return readb(tcdm_legacy_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
 }
@@ -945,7 +945,7 @@ static void config_wakeups(void)
 	last_abb_events = abb_events;
 }
 
-void db8500_prcmu_enable_wakeups(u32 wakeups)
+static void db8500_prcmu_enable_wakeups(u32 wakeups)
 {
 	unsigned long flags;
 	u32 bits;
@@ -966,7 +966,7 @@ void db8500_prcmu_enable_wakeups(u32 wakeups)
 	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 }
 
-void db8500_prcmu_config_abb_event_readout(u32 abb_events)
+static void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 {
 	unsigned long flags;
 
@@ -978,7 +978,7 @@ void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
 }
 
-void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
+static void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
 {
 	if (readb(tcdm_legacy_base + PRCM_ACK_MB0_READ_POINTER) & 1)
 		*buf = (tcdm_legacy_base + PRCM_ACK_MB0_WAKEUP_1_4500);
@@ -993,7 +993,7 @@ void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
  *
  * This function sets the the operating point of the ARM.
  */
-int db8500_prcmu_set_arm_opp(u8 opp)
+static int db8500_prcmu_set_arm_opp(u8 opp)
 {
 	int r;
 
@@ -1028,7 +1028,7 @@ int db8500_prcmu_set_arm_opp(u8 opp)
  *
  * Returns: the current ARM OPP
  */
-int db8500_prcmu_get_arm_opp(void)
+static int db8500_prcmu_get_arm_opp(void)
 {
 	return readb(tcdm_legacy_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
 }
@@ -1038,7 +1038,7 @@ int db8500_prcmu_get_arm_opp(void)
  *
  * Returns: the current DDR OPP
  */
-int db8500_prcmu_get_ddr_opp(void)
+static int db8500_prcmu_get_ddr_opp(void)
 {
 	return readb(PRCM_DDR_SUBSYS_APE_MINBW);
 }
@@ -1050,7 +1050,7 @@ int db8500_prcmu_get_ddr_opp(void)
  *
  * This function sets the operating point of the DDR.
  */
-int db8500_prcmu_set_ddr_opp(u8 opp)
+static int db8500_prcmu_set_ddr_opp(u8 opp)
 {
 	if (opp < DDR_100_OPP || opp > DDR_25_OPP)
 		return -EINVAL;
@@ -1114,7 +1114,7 @@ unlock_and_return:
  *
  * This function sets the operating point of the APE.
  */
-int db8500_prcmu_set_ape_opp(u8 opp)
+static int db8500_prcmu_set_ape_opp(u8 opp)
 {
 	int r = 0;
 
@@ -1161,18 +1161,18 @@ skip_message:
  *
  * Returns: the current APE OPP
  */
-int db8500_prcmu_get_ape_opp(void)
+static int db8500_prcmu_get_ape_opp(void)
 {
 	return readb(tcdm_legacy_base + PRCM_ACK_MB1_CURRENT_APE_OPP);
 }
 
 /**
- * prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
+ * db8500_prcmu_request_ape_opp_100_voltage - Request APE OPP 100% voltage
  * @enable: true to request the higher voltage, false to drop a request.
  *
  * Calls to this function to enable and disable requests must be balanced.
  */
-int prcmu_request_ape_opp_100_voltage(bool enable)
+static int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 {
 	int r = 0;
 	u8 header;
@@ -1279,7 +1279,7 @@ static int request_pll(u8 clock, bool enable)
  * This function sets the state of a EPOD (power domain). It may not be called
  * from interrupt context.
  */
-int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
+static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 {
 	int r = 0;
 	bool ram_retention = false;
@@ -1341,11 +1341,11 @@ unlock_and_return:
 }
 
 /**
- * prcmu_configure_auto_pm - Configure autonomous power management.
+ * db8500_prcmu_configure_auto_pm - Configure autonomous power management.
  * @sleep: Configuration for ApSleep.
  * @idle:  Configuration for ApIdle.
  */
-void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
+static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	struct prcmu_auto_pm_config *idle)
 {
 	u32 sleep_cfg;
@@ -1386,7 +1386,6 @@ void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 
 	spin_unlock_irqrestore(&mb2_transfer.auto_pm_lock, flags);
 }
-EXPORT_SYMBOL(prcmu_configure_auto_pm);
 
 bool prcmu_is_auto_pm_enabled(void)
 {
@@ -1701,7 +1700,7 @@ static unsigned long dsiescclk_rate(u8 n)
 	return clock_rate(PRCMU_TVCLK) / max((u32)1, div);
 }
 
-unsigned long prcmu_clock_rate(u8 clock)
+static unsigned long db8500_prcmu_clock_rate(u8 clock)
 {
 	if (clock < PRCMU_NUM_REG_CLOCKS)
 		return clock_rate(clock);
@@ -1850,7 +1849,7 @@ static long round_dsiescclk_rate(unsigned long rate)
 	return rounded_rate;
 }
 
-long prcmu_round_clock_rate(u8 clock, unsigned long rate)
+static long db8500_prcmu_round_clock_rate(u8 clock, unsigned long rate)
 {
 	if (clock < PRCMU_NUM_REG_CLOCKS)
 		return round_clock_rate(clock, rate);
@@ -1861,7 +1860,7 @@ long prcmu_round_clock_rate(u8 clock, unsigned long rate)
 	else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
 		return round_dsiescclk_rate(rate);
 	else
-		return (long)prcmu_clock_rate(clock);
+		return (long)db8500_prcmu_clock_rate(clock);
 }
 
 static void set_clock_rate(u8 clock, unsigned long rate)
@@ -1989,7 +1988,7 @@ static void set_dsiescclk_rate(u8 n, unsigned long rate)
 	writel(val, PRCM_DSITVCLK_DIV);
 }
 
-int prcmu_set_clock_rate(u8 clock, unsigned long rate)
+static int db8500_prcmu_set_clock_rate(u8 clock, unsigned long rate)
 {
 	if (clock < PRCMU_NUM_REG_CLOCKS)
 		set_clock_rate(clock, rate);
@@ -2002,7 +2001,7 @@ int prcmu_set_clock_rate(u8 clock, unsigned long rate)
 	return 0;
 }
 
-int db8500_prcmu_config_esram0_deep_sleep(u8 state)
+static int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 {
 	if ((state > ESRAM0_DEEP_SLEEP_STATE_RET) ||
 	    (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
@@ -2122,7 +2121,7 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 
 }
 
-int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+static int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 {
 	BUG_ON(num == 0 || num > 0xf);
 	return prcmu_a9wdog(MB4H_A9WDOG_CONF, num, 0, 0,
@@ -2130,17 +2129,17 @@ int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 			    A9WDOG_AUTO_OFF_DIS);
 }
 
-int db8500_prcmu_enable_a9wdog(u8 id)
+static int db8500_prcmu_enable_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0);
 }
 
-int db8500_prcmu_disable_a9wdog(u8 id)
+static int db8500_prcmu_disable_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0);
 }
 
-int db8500_prcmu_kick_a9wdog(u8 id)
+static int db8500_prcmu_kick_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0);
 }
@@ -2148,7 +2147,7 @@ int db8500_prcmu_kick_a9wdog(u8 id)
 /*
  * timeout is 28 bit, in ms.
  */
-int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
+static int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_LOAD,
 			    (id & A9WDOG_ID_MASK) |
@@ -2163,7 +2162,7 @@ int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
 }
 
 /**
- * prcmu_abb_read() - Read register value(s) from the ABB.
+ * db8500_prcmu_abb_read() - Read register value(s) from the ABB.
  * @slave:	The I2C slave address.
  * @reg:	The (start) register address.
  * @value:	The read out value(s).
@@ -2172,7 +2171,7 @@ int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
  * Reads register value(s) from the ABB.
  * @size has to be 1 for the current firmware version.
  */
-int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 {
 	int r;
 
@@ -2211,7 +2210,7 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 }
 
 /**
- * prcmu_abb_write_masked() - Write masked register value(s) to the ABB.
+ * db8500_prcmu_abb_write_masked() - Write masked register value(s) to the ABB.
  * @slave:	The I2C slave address.
  * @reg:	The (start) register address.
  * @value:	The value(s) to write.
@@ -2223,7 +2222,8 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
  * will be written. The other bits are not changed.
  * @size has to be 1 for the current firmware version.
  */
-int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size)
+static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
+		u8 size)
 {
 	int r;
 
@@ -2259,7 +2259,7 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size)
 }
 
 /**
- * prcmu_abb_write() - Write register value(s) to the ABB.
+ * db8500_prcmu_abb_write() - Write register value(s) to the ABB.
  * @slave:	The I2C slave address.
  * @reg:	The (start) register address.
  * @value:	The value(s) to write.
@@ -2268,7 +2268,7 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size)
  * Writes register value(s) to the ABB.
  * @size has to be 1 for the current firmware version.
  */
-int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+static int db8500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
 {
 	u8 mask = ~0;
 
@@ -2347,7 +2347,7 @@ unlock_and_return:
 	mutex_unlock(&mb0_transfer.ac_wake_lock);
 }
 
-bool db8500_prcmu_is_ac_wake_requested(void)
+static bool db8500_prcmu_is_ac_wake_requested(void)
 {
 	return (atomic_read(&ac_wake_req_state) != 0);
 }
@@ -2358,7 +2358,7 @@ bool db8500_prcmu_is_ac_wake_requested(void)
  * Saves the reset reason code and then sets the APE_SOFTRST register which
  * fires interrupt to fw
  */
-void db8500_prcmu_system_reset(u16 reset_code)
+static void db8500_prcmu_system_reset(u16 reset_code)
 {
 	writew(reset_code, (tcdm_legacy_base + PRCM_SW_RST_REASON));
 	writel(1, PRCM_APE_SOFTRST);
@@ -2370,7 +2370,7 @@ void db8500_prcmu_system_reset(u16 reset_code)
  * Retrieves the reset reason code stored by prcmu_system_reset() before
  * last restart.
  */
-u16 db8500_prcmu_get_reset_code(void)
+static u16 db8500_prcmu_get_reset_code(void)
 {
 	return readw(tcdm_legacy_base + PRCM_SW_RST_REASON);
 }
@@ -2378,7 +2378,7 @@ u16 db8500_prcmu_get_reset_code(void)
 /**
  * db8500_prcmu_reset_modem - ask the PRCMU to reset modem
  */
-void db8500_prcmu_modem_reset(void)
+static void db8500_prcmu_modem_reset(void)
 {
 	mutex_lock(&mb1_transfer.lock);
 
@@ -2651,6 +2651,202 @@ static char *fw_project_name(u8 project)
 	}
 }
 
+static inline void db8500_prcmu_set(unsigned int reg, u32 bits)
+{
+	db8500_prcmu_write_masked(reg, bits, bits);
+}
+
+static inline void db8500_prcmu_clear(unsigned int reg, u32 bits)
+{
+	db8500_prcmu_write_masked(reg, bits, 0);
+}
+
+
+static int db8500_prcmu_enable_spi2(void)
+{
+	db8500_prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
+	return 0;
+}
+
+/**
+ * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
+ */
+static int db8500_prcmu_disable_spi2(void)
+{
+	db8500_prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
+	return 0;
+}
+
+/**
+ * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD
+ * and UARTMOD on OtherAlternateC3.
+ */
+static int db8500_prcmu_enable_stm_mod_uart(void)
+{
+	db8500_prcmu_set(DB8500_PRCM_GPIOCR,
+			(DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
+			 DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0));
+	return 0;
+}
+
+/**
+ * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD
+ * and UARTMOD on OtherAlternateC3.
+ */
+static int db8500_prcmu_disable_stm_mod_uart(void)
+{
+	db8500_prcmu_clear(DB8500_PRCM_GPIOCR,
+			(DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
+			 DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0));
+	return 0;
+}
+
+/**
+ * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1.
+ */
+static int db8500_prcmu_enable_stm_ape(void)
+{
+	db8500_prcmu_set(DB8500_PRCM_GPIOCR,
+			DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
+	return 0;
+}
+
+/**
+ * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1.
+ */
+static int db8500_prcmu_disable_stm_ape(void)
+{
+	db8500_prcmu_clear(DB8500_PRCM_GPIOCR,
+			DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
+	return 0;
+}
+
+static  struct prcmu_val_data db8500_val_tab[] = {
+	{
+		.val = APE_OPP,
+		.set_val = db8500_prcmu_set_ape_opp,
+		.get_val = db8500_prcmu_get_ape_opp,
+	},
+	{
+		.val = DDR_OPP,
+		.set_val = db8500_prcmu_set_ddr_opp,
+		.get_val = db8500_prcmu_get_ddr_opp,
+	},
+	{
+		.val = ARM_OPP,
+		.set_val = db8500_prcmu_set_arm_opp,
+		.get_val = db8500_prcmu_get_arm_opp,
+	}
+};
+static struct prcmu_out_data db8500_out_tab[] = {
+	{
+		.out = SPI2_MUX,
+		.enable =  db8500_prcmu_enable_spi2,
+		.disable = db8500_prcmu_disable_spi2,
+	},
+	{
+		.out = STM_APE_MUX,
+		.enable = db8500_prcmu_enable_stm_ape,
+		.disable = db8500_prcmu_disable_stm_ape,
+	},
+	{
+		.out = STM_MOD_UART_MUX,
+		.enable = db8500_prcmu_enable_stm_mod_uart,
+		.disable = db8500_prcmu_disable_stm_mod_uart,
+	}
+};
+
+static struct prcmu_early_data db8500_early_fops = {
+	/*  system reset  */
+	.system_reset = db8500_prcmu_system_reset,
+
+	/*  clock service */
+	.config_clkout = db8500_prcmu_config_clkout,
+	.request_clock = db8500_prcmu_request_clock,
+
+	/*  direct register access */
+	.read = db8500_prcmu_read,
+	.write =  db8500_prcmu_write,
+	.write_masked = db8500_prcmu_write_masked,
+	/* others */
+	.round_clock_rate = db8500_prcmu_round_clock_rate,
+	.set_clock_rate = db8500_prcmu_set_clock_rate,
+	.clock_rate = db8500_prcmu_clock_rate,
+	.get_fw_version = db8500_prcmu_get_fw_version,
+	.has_arm_maxopp = db8500_prcmu_has_arm_maxopp,
+};
+
+static struct prcmu_fops_register db8500_early_tab[] = {
+	{
+		.fops = PRCMU_EARLY,
+		.data.pearly = &db8500_early_fops
+	},
+	{
+		.fops = PRCMU_VAL,
+		.size = ARRAY_SIZE(db8500_val_tab),
+		.data.pval = db8500_val_tab
+	},
+	{
+		.fops = PRCMU_OUT,
+		.size = ARRAY_SIZE(db8500_out_tab),
+		.data.pout = db8500_out_tab
+	}
+};
+
+static struct prcmu_fops_register_data db8500_early_data = {
+	.size = ARRAY_SIZE(db8500_early_tab),
+	.tab = db8500_early_tab
+};
+
+struct prcmu_probe_data db8500_probe_fops = {
+	/* sysfs soc inf */
+	.get_reset_code = db8500_prcmu_get_reset_code,
+
+	/* pm/suspend.c/cpu freq */
+	.config_esram0_deep_sleep = db8500_prcmu_config_esram0_deep_sleep,
+	.set_power_state = db8500_prcmu_set_power_state,
+	.get_power_state_result = db8500_prcmu_get_power_state_result,
+	.enable_wakeups = db8500_prcmu_enable_wakeups,
+	.is_ac_wake_requested = db8500_prcmu_is_ac_wake_requested,
+
+	/* modem */
+	.modem_reset = db8500_prcmu_modem_reset,
+
+	/* no used at all */
+	.config_abb_event_readout = db8500_prcmu_config_abb_event_readout,
+	.get_abb_event_buffer = db8500_prcmu_get_abb_event_buffer,
+
+	/* abb access */
+	.abb_read = db8500_prcmu_abb_read,
+	.abb_write = db8500_prcmu_abb_write,
+	/*  other u8500 specific */
+	.request_ape_opp_100_voltage = db8500_prcmu_request_ape_opp_100_voltage,
+	.configure_auto_pm = db8500_prcmu_configure_auto_pm,
+	.set_epod = db8500_prcmu_set_epod,
+
+	/* abb specific access */
+	.abb_write_masked = db8500_prcmu_abb_write_masked,
+
+	/* watchdog */
+	.config_a9wdog = db8500_prcmu_config_a9wdog,
+	.enable_a9wdog = db8500_prcmu_enable_a9wdog,
+	.disable_a9wdog = db8500_prcmu_disable_a9wdog,
+	.kick_a9wdog = db8500_prcmu_kick_a9wdog,
+	.load_a9wdog = db8500_prcmu_load_a9wdog,
+};
+
+static struct prcmu_fops_register db8500_probe_tab[] = {
+	{
+		.fops = PRCMU_PROBE,
+		.data.pprobe = &db8500_probe_fops,
+	},
+};
+
+struct prcmu_fops_register_data db8500_probe_data = {
+	.size = ARRAY_SIZE(db8500_probe_tab),
+	.tab = db8500_probe_tab,
+};
+
 static int db8500_irq_map(struct irq_domain *d, unsigned int virq,
 				irq_hw_number_t hwirq)
 {
@@ -2680,7 +2876,8 @@ static int db8500_irq_init(struct device_node *np)
 	return 0;
 }
 
-void __init db8500_prcmu_early_init(struct prcmu_tcdm_map *map)
+struct prcmu_fops_register_data *__init
+			db8500_prcmu_early_init(struct prcmu_tcdm_map *map)
 {
 		void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
 
@@ -2720,6 +2917,9 @@ void __init db8500_prcmu_early_init(struct prcmu_tcdm_map *map)
 	init_completion(&mb5_transfer.work);
 
 	INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
+
+	/*  early init of dbx500-prcmu */
+	return &db8500_early_data;
 }
 
 static void __init init_prcm_registers(void)
@@ -2976,6 +3176,11 @@ static struct resource ab8500_resources[] = {
 
 static struct mfd_cell db8500_prcmu_devs[] = {
 	{
+		.name = "dbx500-prcmu",
+		.platform_data = &db8500_probe_data,
+		.pdata_size = sizeof(db8500_probe_data),
+	},
+	{
 		.name = "db8500-prcmu-regulators",
 		.of_compatible = "stericsson,db8500-prcmu-regulator",
 		.platform_data = &db8500_regulators,
@@ -2996,6 +3201,11 @@ static struct mfd_cell db8500_prcmu_devs[] = {
 
 static struct mfd_cell db9540_prcmu_devs[] = {
 	{
+		.name = "dbx500-prcmu",
+		.platform_data = &db8500_probe_data,
+		.pdata_size = sizeof(db8500_probe_data),
+	},
+	{
 		.name = "db8500-prcmu-regulators",
 		.of_compatible = "stericsson,db8500-prcmu-regulator",
 		.platform_data = &db8500_regulators,
@@ -3048,12 +3258,13 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
 	for (i = 0; i < ARRAY_SIZE(db8500_prcmu_devs); i++) {
 		if (!strcmp(db8500_prcmu_devs[i].name, "ab8500-core")) {
 			db8500_prcmu_devs[i].platform_data = ab8500_platdata;
-			db8500_prcmu_devs[i].pdata_size = sizeof(struct ab8500_platform_data);
+			db8500_prcmu_devs[i].pdata_size =
+				sizeof(struct ab8500_platform_data);
 		}
 	}
 
 	if (cpu_is_u8500v20_or_later() && !cpu_is_u9540())
-		prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
+		db8500_prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
 
 	if (cpu_is_u9540())
 			err = mfd_add_devices(&pdev->dev, 0, db9540_prcmu_devs,
diff --git a/drivers/mfd/dbx500-prcmu.c b/drivers/mfd/dbx500-prcmu.c
new file mode 100644
index 0000000..1823ab7
--- /dev/null
+++ b/drivers/mfd/dbx500-prcmu.c
@@ -0,0 +1,813 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010. All rights reserved.
+ * This code is ST-Ericsson proprietary and confidential.
+ * Any use of the code for whatever purpose is subject to
+ * specific written permission of ST-Ericsson SA.
+ *
+ * Author: Michel Jaouen <michel.jaouen at stericsson.com> for
+ * ST-Ericsson.
+ * License terms: GNU Gereral Public License (GPL) version 2
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/hwmon.h>
+#include <linux/sysfs.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+
+#define dbx500_prcmu_warn(a)					\
+	pr_warn("%s : dbx500-prcmu driver %s",			\
+	__func__, a);
+
+#define dbx500_prcmu_error(a)					\
+	pr_err("%s : dbx500-prcmu driver %s",			\
+	__func__, a);
+
+#define dbx500_prcmu_early_trap_void				\
+	pr_err("%s called :dbx500-prcmu driver not initialized",\
+		__func__);					\
+
+#define dbx500_prcmu_early_trap(a) do {				\
+	pr_err("%s called :dbx500-prcmu driver not initialized",\
+		__func__);					\
+	return a;						\
+	} while (0)
+
+#define dbx500_prcmu_trap(a) do {				\
+	pr_err("%s called : dbx500-prcmu driver not probed",	\
+	__func__);						\
+	return a;						\
+	} while (0)
+
+#define dbx500_prcmu_trap_void					\
+	pr_err("%s called : dbx500-prcmu driver not probed",	\
+	__func__);
+
+/* dummy handler */
+
+static int dummy_set_power_state(u8 state, bool keep_ulp_clk,
+		bool keep_ap_pll) {
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static u8  dummy_get_power_state_result(void)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static int dummy_config_clkout(u8 clkout, u8 source, u8 div)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static int dummy_request_clock(u8 clock, bool enable)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static long dummy_round_clock_rate(u8 clock, unsigned long rate)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static int dummy_set_clock_rate(u8 clock, unsigned long rate)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static	unsigned long dummy_clock_rate(u8 clock)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static	int dummy_set_val(enum prcmu_val type, u8 value)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static	int dummy_get_val(enum prcmu_val type)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static	void dummy_system_reset(u16 reset_code)
+{
+	dbx500_prcmu_early_trap_void;
+}
+static	u16 dummy_get_reset_code(void)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+static	u32 dummy_get_reset_status(void)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static	void dummy_enable_wakeups(u32 wakeups)
+{
+	dbx500_prcmu_trap_void;
+}
+
+static	bool dummy_is_ac_wake_requested(void)
+{
+	dbx500_prcmu_trap(false);
+}
+
+static	int  dummy_disable(enum prcmu_out out)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static	int  dummy_enable(enum prcmu_out out)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static	u32  dummy_read(unsigned int reg)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static	void  dummy_write(unsigned int reg, u32 value)
+{
+	dbx500_prcmu_early_trap_void;
+}
+
+static	void  default_write_masked(unsigned int reg, u32 mask, u32 value)
+{
+	u32 val;
+	val = readl(_PRCMU_BASE + reg);
+	val = ((val & ~mask) | (value & mask));
+	writel(val, (_PRCMU_BASE + reg));
+}
+
+static	int  dummy_config_esram0_deep_sleep(u8 state)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static	void  dummy_config_abb_event_readout(u32 abb_events)
+{
+	dbx500_prcmu_trap_void;
+}
+
+static	void  dummy_get_abb_event_buffer(void __iomem **buf)
+{
+	dbx500_prcmu_trap_void;
+}
+
+static int  dummy_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static	int  dummy_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static	int  dummy_abb_write_masked(u8 slave, u8 reg, u8 *value,
+		u8 *mask, u8 size)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static	void  dummy_modem_reset(void)
+{
+	dbx500_prcmu_trap_void;
+}
+
+static bool dummy_has_arm_maxopp(void)
+{
+	dbx500_prcmu_early_trap(-EINVAL);
+}
+
+static	struct prcmu_fw_version *dummy_get_fw_version(void)
+{
+	dbx500_prcmu_early_trap(NULL);
+}
+
+static int dummy_request_ape_opp_100_voltage(bool enable)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static void dummy_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
+	struct prcmu_auto_pm_config *idle)
+{
+	dbx500_prcmu_trap_void;
+}
+
+static int dummy_config_a9wdog(u8 num, bool sleep_auto_off)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static int dummy_enable_a9wdog(u8 id)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static int dummy_disable_a9wdog(u8 id)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static int dummy_kick_a9wdog(u8 id)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+static int dummy_load_a9wdog(u8 id, u32 timeout)
+{
+	dbx500_prcmu_trap(-EINVAL);
+}
+
+struct prcmu_probe_data dummy_fops = {
+	/* sysfs soc inf */
+	.get_reset_code = dummy_get_reset_code,
+
+	/* pm/suspend.c/cpu freq */
+	.config_esram0_deep_sleep = dummy_config_esram0_deep_sleep,
+	.set_power_state = dummy_set_power_state,
+	.get_power_state_result = dummy_get_power_state_result,
+	.enable_wakeups = dummy_enable_wakeups,
+	.is_ac_wake_requested = dummy_is_ac_wake_requested,
+
+	/* modem */
+	.modem_reset = dummy_modem_reset,
+
+	/* no used at all */
+	.config_abb_event_readout = dummy_config_abb_event_readout,
+	.get_abb_event_buffer = dummy_get_abb_event_buffer,
+
+	/* abb access */
+	.abb_read = dummy_abb_read,
+	.abb_write = dummy_abb_write,
+	.get_reset_status = dummy_get_reset_status,
+	/*  other u8500 specific */
+	.request_ape_opp_100_voltage = dummy_request_ape_opp_100_voltage,
+	.configure_auto_pm = dummy_configure_auto_pm,
+
+	/* abb specific access */
+	.abb_write_masked = dummy_abb_write_masked,
+
+	/* watchdog */
+	.config_a9wdog = dummy_config_a9wdog,
+	.enable_a9wdog = dummy_enable_a9wdog,
+	.disable_a9wdog = dummy_disable_a9wdog,
+	.kick_a9wdog = dummy_kick_a9wdog,
+	.load_a9wdog = dummy_load_a9wdog,
+};
+
+static struct prcmu_early_data default_early_fops = {
+	/*  system reset  */
+	.system_reset = dummy_system_reset,
+
+	/*  clock service */
+	.config_clkout = dummy_config_clkout,
+	.request_clock = dummy_request_clock,
+
+	/*  direct register access */
+	.read = dummy_read,
+	.write =  dummy_write,
+	.write_masked = default_write_masked,
+	/* others */
+	.round_clock_rate = dummy_round_clock_rate,
+	.set_clock_rate = dummy_set_clock_rate,
+	.clock_rate = dummy_clock_rate,
+	.get_fw_version = dummy_get_fw_version,
+	.has_arm_maxopp = dummy_has_arm_maxopp,
+};
+
+static struct {
+	struct prcmu_early_data *pearly;
+	struct prcmu_probe_data *pprobe;
+	struct prcmu_probe_cpuhp_data *pprobe_cpuhp;
+	struct prcmu_val_data tab_val[PRCMU_VAL_MAX];
+	int (*set_val)(enum prcmu_val type, u8 val);
+	int (*get_val) (enum prcmu_val type);
+	struct prcmu_out_data tab_out[PRCMU_OUT_MAX];
+	int (*disable) (enum prcmu_out out);
+	int (*enable) (enum prcmu_out out);
+	bool (*check_ape_age)(void);
+} dbx500_prcmu_context = {
+	.pearly = &default_early_fops,
+	.pprobe = &dummy_fops,
+	.set_val = dummy_set_val,
+	.get_val = dummy_get_val,
+	.disable = dummy_disable,
+	.enable = dummy_enable,
+};
+
+/* early service */
+
+struct prcmu_fw_version *prcmu_get_fw_version(void)
+{
+	return dbx500_prcmu_context.pearly->get_fw_version();
+}
+
+bool prcmu_has_arm_maxopp(void)
+{
+	return dbx500_prcmu_context.pearly->has_arm_maxopp();
+}
+
+void prcmu_system_reset(u16 reset_code)
+{
+	dbx500_prcmu_context.pearly->system_reset(reset_code);
+}
+
+u32 prcmu_read(unsigned int reg)
+{
+	return	dbx500_prcmu_context.pearly->read(reg);
+}
+
+void prcmu_write(unsigned int reg, u32 value)
+{
+	return	dbx500_prcmu_context.pearly->write(reg, value);
+}
+
+void prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
+{
+	 dbx500_prcmu_context.pearly->write_masked(reg, mask, value);
+}
+
+int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
+{
+	return dbx500_prcmu_context.pearly->config_clkout(clkout, source, div);
+}
+
+int prcmu_request_clock(u8 clock, bool enable)
+{
+	return  dbx500_prcmu_context.pearly->request_clock(clock, enable);
+}
+
+unsigned long prcmu_clock_rate(u8 clock)
+{
+	return   dbx500_prcmu_context.pearly->clock_rate(clock);
+}
+
+long prcmu_round_clock_rate(u8 clock, unsigned long rate)
+{
+	return  dbx500_prcmu_context.pearly->round_clock_rate(clock, rate);
+}
+
+int prcmu_set_clock_rate(u8 clock, unsigned long rate)
+{
+	return  dbx500_prcmu_context.pearly->set_clock_rate(clock, rate);
+}
+
+int prcmu_set_val(enum prcmu_val type, u32 value)
+{
+	return dbx500_prcmu_context.set_val(type, value);
+}
+
+int prcmu_get_val(enum prcmu_val type)
+{
+	return dbx500_prcmu_context.get_val(type);
+}
+
+int prcmu_enable_out(enum prcmu_out out)
+{
+	return dbx500_prcmu_context.enable(out);
+}
+
+int prcmu_disable_out(enum prcmu_out out)
+{
+	return dbx500_prcmu_context.disable(out);
+}
+
+int prcmu_set_ddr_opp(u8 opp)
+{
+	return dbx500_prcmu_context.set_val(DDR_OPP, opp);
+}
+
+int prcmu_get_ddr_opp(void)
+{
+	return dbx500_prcmu_context.get_val(DDR_OPP);
+}
+
+int prcmu_set_arm_opp(u8 opp)
+{
+	return dbx500_prcmu_context.set_val(ARM_OPP, opp);
+}
+
+int prcmu_get_arm_opp(void)
+{
+	return dbx500_prcmu_context.get_val(ARM_OPP);
+}
+
+int prcmu_set_ape_opp(u8 opp)
+{
+	return dbx500_prcmu_context.set_val(APE_OPP, opp);
+}
+
+int prcmu_get_ape_opp(void)
+{
+	return dbx500_prcmu_context.get_val(APE_OPP);
+}
+
+int prcmu_gic_decouple(void)
+{
+	return db8500_prcmu_gic_decouple();
+}
+int prcmu_gic_recouple(void)
+{
+	return db8500_prcmu_gic_recouple();
+}
+bool prcmu_gic_pending_irq(void)
+{
+	return db8500_prcmu_gic_pending_irq();
+}
+
+bool prcmu_is_cpu_in_wfi(int cpu)
+{
+	return db8500_prcmu_is_cpu_in_wfi(cpu);
+}
+
+int prcmu_copy_gic_settings(void)
+{
+	return db8500_prcmu_copy_gic_settings();
+}
+
+bool prcmu_pending_irq(void)
+{
+	return db8500_prcmu_pending_irq();
+}
+
+/*  other service available after the probe */
+
+int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
+		bool keep_ap_pll)
+{
+	return	 dbx500_prcmu_context.pprobe->set_power_state(state,
+			keep_ulp_clk,
+			keep_ap_pll);
+}
+
+u8 prcmu_get_power_state_result(void)
+{
+	return	dbx500_prcmu_context.pprobe->get_power_state_result();
+}
+
+void prcmu_enable_wakeups(u32 wakeups)
+{
+	dbx500_prcmu_context.pprobe->enable_wakeups(wakeups);
+}
+
+void prcmu_disable_wakeups(void)
+{
+	dbx500_prcmu_context.pprobe->enable_wakeups(0);
+}
+
+void prcmu_config_abb_event_readout(u32 abb_events)
+{
+	dbx500_prcmu_context.pprobe->config_abb_event_readout(abb_events);
+}
+
+void prcmu_get_abb_event_buffer(void __iomem **buf)
+{
+	dbx500_prcmu_context.pprobe->get_abb_event_buffer(buf);
+}
+
+u16 prcmu_get_reset_code(void)
+{
+	return dbx500_prcmu_context.pprobe->get_reset_code();
+}
+
+void prcmu_modem_reset(void)
+{
+	dbx500_prcmu_context.pprobe->modem_reset();
+}
+
+int  prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+{
+	return dbx500_prcmu_context.pprobe->abb_read(slave, reg, value, size);
+}
+
+int  prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+{
+	return dbx500_prcmu_context.pprobe->abb_write(slave, reg, value, size);
+}
+
+int  prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value,
+		u8 *mask, u8 size)
+{
+	return dbx500_prcmu_context.pprobe->abb_write_masked(
+			slave, reg, value, mask, size);
+}
+
+u32  prcmu_get_reset_status(void)
+{
+	return dbx500_prcmu_context.pprobe->get_reset_status();
+}
+
+bool prcmu_is_ac_wake_requested(void)
+{
+	return dbx500_prcmu_context.pprobe->is_ac_wake_requested();
+}
+
+int prcmu_config_esram0_deep_sleep(u8 state)
+{
+	 return dbx500_prcmu_context.pprobe->config_esram0_deep_sleep(state);
+}
+
+int prcmu_set_epod(u16 epod_id, u8 epod_state)
+{
+	return dbx500_prcmu_context.pprobe->set_epod(epod_id, epod_state);
+}
+
+/**
+ * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1.
+ */
+void prcmu_enable_spi2(void)
+{
+	 dbx500_prcmu_context.enable(SPI2_MUX);
+}
+
+/**
+ * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
+ */
+void prcmu_disable_spi2(void)
+{
+	dbx500_prcmu_context.disable(SPI2_MUX);
+}
+
+/**
+ * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD
+ * and UARTMOD on OtherAlternateC3.
+ */
+void prcmu_enable_stm_mod_uart(void)
+{
+	dbx500_prcmu_context.enable(STM_MOD_UART_MUX);
+}
+
+/**
+ * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD
+ * and UARTMOD on OtherAlternateC3.
+ */
+void prcmu_disable_stm_mod_uart(void)
+{
+	dbx500_prcmu_context.disable(STM_MOD_UART_MUX);
+}
+
+/**
+ * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1.
+ */
+void prcmu_enable_stm_ape(void)
+{
+	dbx500_prcmu_context.enable(STM_APE_MUX);
+}
+
+/**
+ * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1.
+ */
+void prcmu_disable_stm_ape(void)
+{
+	dbx500_prcmu_context.disable(STM_APE_MUX);
+}
+
+void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
+	struct prcmu_auto_pm_config *idle)
+{
+	dbx500_prcmu_context.pprobe->configure_auto_pm(sleep, idle);
+}
+EXPORT_SYMBOL(prcmu_configure_auto_pm);
+
+int prcmu_request_ape_opp_100_voltage(bool enable)
+{
+	return	dbx500_prcmu_context.
+		pprobe->request_ape_opp_100_voltage(enable);
+}
+
+static int dbx500_prcmu_set_val(enum prcmu_val type, u8 value)
+{
+	if (type < PRCMU_VAL_MAX)
+		return dbx500_prcmu_context.tab_val[type].set_val(value);
+	dbx500_prcmu_error("request out of range");
+		return -EIO;
+
+}
+
+static int dbx500_prcmu_get_val(enum prcmu_val type)
+{
+	if (type < PRCMU_VAL_MAX)
+		return dbx500_prcmu_context.tab_val[type].get_val();
+	dbx500_prcmu_error("request out of range");
+		return -EIO;
+
+}
+
+static int dbx500_prcmu_enable_out(enum prcmu_out out)
+{
+	if (out < PRCMU_OUT_MAX)
+		return dbx500_prcmu_context.tab_out[out].enable();
+	dbx500_prcmu_error("request out of range");
+		return -EIO;
+}
+
+static int dbx500_prcmu_disable_out(enum prcmu_out out)
+{
+	if (out < PRCMU_OUT_MAX)
+		return	dbx500_prcmu_context.tab_out[out].disable();
+	dbx500_prcmu_error("request out of range");
+		return -EIO;
+}
+
+/*  used for enable , disable and get */
+static int dbx500_default_handler(void)
+{
+	return 0;
+}
+static int dbx500_default_set(u8 val)
+{
+	return 0;
+}
+static int default_get_ape_opp(void)
+{
+	return APE_100_OPP;
+}
+
+
+static int default_get_ddr_opp(void)
+{
+	return DDR_100_OPP;
+}
+
+static struct prcmu_val_data default_ape = {
+	.set_val = dbx500_default_set,
+	.get_val = default_get_ape_opp,
+};
+
+
+static struct prcmu_val_data default_ddr = {
+	.set_val = dbx500_default_set,
+	.get_val = default_get_ddr_opp,
+};
+
+static struct prcmu_out_data default_out = {
+	.enable = dbx500_default_handler,
+	.disable = dbx500_default_handler,
+};
+
+static struct prcmu_val_data default_val = {
+	.set_val = dbx500_default_set,
+	.get_val = dbx500_default_handler,
+};
+
+static void dbx500_prcmu_init_ctx(void)
+{
+	int i;
+	struct prcmu_val_data *pdefault;
+	for (i = 0; i < PRCMU_VAL_MAX; i++) {
+		switch (i) {
+		case DDR_OPP:
+			pdefault = &default_ddr;
+			break;
+		case APE_OPP:
+			pdefault = &default_ape;
+			break;
+		default:
+			pdefault = &default_val;
+		}
+
+		memcpy(&dbx500_prcmu_context.tab_val[i], pdefault,
+				sizeof(struct prcmu_val_data));
+	}
+
+	for (i = 0; i < PRCMU_OUT_MAX; i++)
+		memcpy(&dbx500_prcmu_context.tab_out[i], &default_out,
+				sizeof(struct prcmu_out_data));
+	dbx500_prcmu_context.enable = dbx500_prcmu_enable_out;
+	dbx500_prcmu_context.disable = dbx500_prcmu_disable_out;
+	dbx500_prcmu_context.set_val = dbx500_prcmu_set_val;
+	dbx500_prcmu_context.get_val = dbx500_prcmu_get_val;
+}
+
+static void dbx500_prcmu_register_pout(struct prcmu_out_data *data, int size)
+{
+	int i;
+	for (i = 0; i < size; i++)
+		if (data[i].out < PRCMU_OUT_MAX)
+			memcpy(&dbx500_prcmu_context.tab_out[data[i].out],
+				&data[i], sizeof(struct prcmu_out_data));
+		else
+			dbx500_prcmu_error("ops out of range");
+}
+
+static void dbx500_prcmu_register_pval(struct prcmu_val_data *data, int size)
+{
+	int i;
+	for (i = 0; i < size; i++)
+		if (data[i].val < PRCMU_VAL_MAX)
+			memcpy(&dbx500_prcmu_context.tab_val[data[i].val],
+				&data[i], sizeof(struct prcmu_val_data));
+		else
+			dbx500_prcmu_error("registering ops out of range");
+}
+
+/**
+ * @brief register prcmu handler
+ *
+ * @param fops
+ */
+void __init prcmu_early_init(struct prcmu_tcdm_map *map)
+{
+	int i, ret = 0;
+	struct prcmu_fops_register_data *data;
+
+	data = db8500_prcmu_early_init(map);
+
+	if (data == NULL)
+		return;
+
+	dbx500_prcmu_init_ctx();
+
+	for (i = 0; i < data->size; i++) {
+		switch (data->tab[i].fops) {
+		case PRCMU_EARLY:
+			dbx500_prcmu_context.pearly = data->tab[i].data.pearly;
+			break;
+		case PRCMU_VAL:
+			dbx500_prcmu_register_pval(data->tab[i].data.pval,
+					data->tab[i].size);
+			break;
+		case PRCMU_OUT:
+			dbx500_prcmu_register_pout(data->tab[i].data.pout,
+					data->tab[i].size);
+			break;
+		default:
+			dbx500_prcmu_error("ops out of range");
+			ret = -EIO;
+		}
+	}
+	return;
+}
+
+/**
+ * @brief dbx500-prcmu probe function
+ *
+ * @param pdev
+ *
+ * @return
+ */
+static int __devinit dbx500_prcmu_probe(struct platform_device *pdev)
+{
+	struct prcmu_fops_register_data *data = dev_get_platdata(&pdev->dev);
+	int i, ret = 0;
+	for (i = 0; i < data->size; i++) {
+		switch (data->tab[i].fops) {
+		case PRCMU_VAL:
+			dbx500_prcmu_register_pval(data->tab[i].data.pval,
+					data->tab[i].size);
+			break;
+		case PRCMU_OUT:
+			dbx500_prcmu_register_pout(data->tab[i].data.pout,
+					data->tab[i].size);
+			break;
+		case PRCMU_PROBE:
+			dbx500_prcmu_context.pprobe =
+				data->tab[i].data.pprobe;
+			break;
+		case PRCMU_PROBE_CPU_HP:
+			dbx500_prcmu_context.pprobe_cpuhp =
+				data->tab[i].data.pprobe_cpuhp;
+			break;
+		default:
+			dbx500_prcmu_error("ops out of range");
+			ret = -EIO;
+		}
+	}
+	return ret;
+}
+
+/* No action required in suspend/resume, thus the lack of functions */
+static struct platform_driver dbx500_prcmu_driver = {
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "dbx500-prcmu",
+	},
+	.probe = dbx500_prcmu_probe,
+};
+
+static int __init dbx500_prcmu_init(void)
+{
+	return platform_driver_register(&dbx500_prcmu_driver);
+}
+
+MODULE_AUTHOR("Michel JAOUEN <michel.jaouen at stericsson.com>");
+MODULE_DESCRIPTION("DBX500 PRCMU DRIVER");
+MODULE_LICENSE("GPL");
+
+core_initcall(dbx500_prcmu_init);
+
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index f932a56..a6d7298 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -140,29 +140,6 @@ enum ap_pwrst {
 };
 
 /**
- * enum ap_pwrst_trans - Transition states defined in PRCMU firmware
- * @NO_TRANSITION: No power state transition
- * @APEXECUTE_TO_APSLEEP: Power state transition from ApExecute to ApSleep
- * @APIDLE_TO_APSLEEP: Power state transition from ApIdle to ApSleep
- * @APBOOT_TO_APEXECUTE: Power state transition from ApBoot to ApExecute
- * @APEXECUTE_TO_APDEEPSLEEP: Power state transition from ApExecute to
- *                          ApDeepSleep
- * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle
- */
-enum ap_pwrst_trans {
-	PRCMU_AP_NO_CHANGE		= 0x00,
-	APEXECUTE_TO_APSLEEP		= 0x01,
-	APIDLE_TO_APSLEEP		= 0x02, /* To be removed */
-	PRCMU_AP_SLEEP			= 0x01,
-	APBOOT_TO_APEXECUTE		= 0x03,
-	APEXECUTE_TO_APDEEPSLEEP	= 0x04, /* To be removed */
-	PRCMU_AP_DEEP_SLEEP		= 0x04,
-	APEXECUTE_TO_APIDLE		= 0x05, /* To be removed */
-	PRCMU_AP_IDLE			= 0x05,
-	PRCMU_AP_DEEP_IDLE		= 0x07,
-};
-
-/**
  * enum hw_acc_state - State definition for hardware accelerator
  * @HW_NO_CHANGE: The hardware accelerator state must remain unchanged
  * @HW_OFF: The hardware accelerator must be switched off
@@ -509,71 +486,41 @@ struct prcmu_fw_version {
 
 #ifdef CONFIG_MFD_DB8500_PRCMU
 
-void db8500_prcmu_early_init(struct prcmu_tcdm_map *map);
+struct prcmu_fops_register_data *db8500_prcmu_early_init(
+		struct prcmu_tcdm_map *map);
 int prcmu_set_rc_a2p(enum romcode_write);
 enum romcode_read prcmu_get_rc_p2a(void);
 enum ap_pwrst prcmu_get_xp70_current_state(void);
-bool prcmu_has_arm_maxopp(void);
-struct prcmu_fw_version *prcmu_get_fw_version(void);
-int prcmu_request_ape_opp_100_voltage(bool enable);
+
 int prcmu_release_usb_wakeup_state(void);
-void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
-	struct prcmu_auto_pm_config *idle);
-bool prcmu_is_auto_pm_enabled(void);
 
-int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
-int prcmu_set_clock_divider(u8 clock, u8 divider);
 int db8500_prcmu_config_hotdog(u8 threshold);
 int db8500_prcmu_config_hotmon(u8 low, u8 high);
 int db8500_prcmu_start_temp_sense(u16 cycles32k);
 int db8500_prcmu_stop_temp_sense(void);
-int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
-int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+
 
 int prcmu_ac_wake_req(void);
 void prcmu_ac_sleep_req(void);
-void db8500_prcmu_modem_reset(void);
-
-int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off);
-int db8500_prcmu_enable_a9wdog(u8 id);
-int db8500_prcmu_disable_a9wdog(u8 id);
-int db8500_prcmu_kick_a9wdog(u8 id);
-int db8500_prcmu_load_a9wdog(u8 id, u32 val);
 
-void db8500_prcmu_system_reset(u16 reset_code);
-int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
-u8 db8500_prcmu_get_power_state_result(void);
 int db8500_prcmu_gic_decouple(void);
 int db8500_prcmu_gic_recouple(void);
 int db8500_prcmu_copy_gic_settings(void);
 bool db8500_prcmu_gic_pending_irq(void);
 bool db8500_prcmu_pending_irq(void);
 bool db8500_prcmu_is_cpu_in_wfi(int cpu);
-void db8500_prcmu_enable_wakeups(u32 wakeups);
-int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state);
-int db8500_prcmu_request_clock(u8 clock, bool enable);
+
 int db8500_prcmu_set_display_clocks(void);
 int db8500_prcmu_disable_dsipll(void);
 int db8500_prcmu_enable_dsipll(void);
-void db8500_prcmu_config_abb_event_readout(u32 abb_events);
-void db8500_prcmu_get_abb_event_buffer(void __iomem **buf);
-int db8500_prcmu_config_esram0_deep_sleep(u8 state);
-u16 db8500_prcmu_get_reset_code(void);
-bool db8500_prcmu_is_ac_wake_requested(void);
-int db8500_prcmu_set_arm_opp(u8 opp);
-int db8500_prcmu_get_arm_opp(void);
-int db8500_prcmu_set_ape_opp(u8 opp);
-int db8500_prcmu_get_ape_opp(void);
-int db8500_prcmu_set_ddr_opp(u8 opp);
-int db8500_prcmu_get_ddr_opp(void);
-
-u32 db8500_prcmu_read(unsigned int reg);
-void db8500_prcmu_write(unsigned int reg, u32 value);
-void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value);
 
 #else /* !CONFIG_MFD_DB8500_PRCMU */
 
-static inline void db8500_prcmu_early_init(struct prcmu_tcdm_map *map) {}
+static struct prcmu_fops_register_data *db8500_prcmu_early_init(
+		struct prcmu_tcdm_map *map)
+{
+	return NULL;
+}
 
 static inline int prcmu_set_rc_a2p(enum romcode_write code)
 {
@@ -590,66 +537,12 @@ static inline enum ap_pwrst prcmu_get_xp70_current_state(void)
 	return AP_EXECUTE;
 }
 
-static inline bool prcmu_has_arm_maxopp(void)
-{
-	return false;
-}
-
-static inline struct prcmu_fw_version *prcmu_get_fw_version(void)
-{
-	return NULL;
-}
-
-static inline int db8500_prcmu_set_ape_opp(u8 opp)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_get_ape_opp(void)
-{
-	return APE_100_OPP;
-}
-
-static inline int prcmu_request_ape_opp_100_voltage(bool enable)
-{
-	return 0;
-}
-
-static inline int prcmu_release_usb_wakeup_state(void)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_set_ddr_opp(u8 opp)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_get_ddr_opp(void)
-{
-	return DDR_100_OPP;
-}
-
-static inline void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
-	struct prcmu_auto_pm_config *idle)
-{
-}
 
 static inline bool prcmu_is_auto_pm_enabled(void)
 {
 	return false;
 }
 
-static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
-{
-	return 0;
-}
-
-static inline int prcmu_set_clock_divider(u8 clock, u8 divider)
-{
-	return 0;
-}
-
 static inline int db8500_prcmu_config_hotdog(u8 threshold)
 {
 	return 0;
@@ -670,129 +563,6 @@ static inline int db8500_prcmu_stop_temp_sense(void)
 	return 0;
 }
 
-static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
-{
-	return -ENOSYS;
-}
-
-static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
-{
-	return -ENOSYS;
-}
-
-static inline int prcmu_ac_wake_req(void)
-{
-	return 0;
-}
-
-static inline void prcmu_ac_sleep_req(void) {}
-
-static inline void db8500_prcmu_modem_reset(void) {}
-
-static inline void db8500_prcmu_system_reset(u16 reset_code) {}
-
-static inline int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-	bool keep_ap_pll)
-{
-	return 0;
-}
-
-static inline u8 db8500_prcmu_get_power_state_result(void)
-{
-	return 0;
-}
-
-static inline void db8500_prcmu_enable_wakeups(u32 wakeups) {}
-
-static inline int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_request_clock(u8 clock, bool enable)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_set_display_clocks(void)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_disable_dsipll(void)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_enable_dsipll(void)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_config_esram0_deep_sleep(u8 state)
-{
-	return 0;
-}
-
-static inline void db8500_prcmu_config_abb_event_readout(u32 abb_events) {}
-
-static inline void db8500_prcmu_get_abb_event_buffer(void __iomem **buf) {}
-
-static inline u16 db8500_prcmu_get_reset_code(void)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_enable_a9wdog(u8 id)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_disable_a9wdog(u8 id)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_kick_a9wdog(u8 id)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_load_a9wdog(u8 id, u32 val)
-{
-	return 0;
-}
-
-static inline bool db8500_prcmu_is_ac_wake_requested(void)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_set_arm_opp(u8 opp)
-{
-	return 0;
-}
-
-static inline int db8500_prcmu_get_arm_opp(void)
-{
-	return 0;
-}
-
-static inline u32 db8500_prcmu_read(unsigned int reg)
-{
-	return 0;
-}
-
-static inline void db8500_prcmu_write(unsigned int reg, u32 value) {}
-
-static inline void db8500_prcmu_write_masked(unsigned int reg, u32 mask,
-	u32 value) {}
-
 #endif /* !CONFIG_MFD_DB8500_PRCMU */
 
 #endif /* __MFD_DB8500_PRCMU_H */
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index aab183d..d76114e 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -213,6 +213,23 @@ enum ddr_pwrst {
 	DDR_PWR_STATE_OFFHIGHLAT    = 0x03
 };
 
+/**
+ * enum ap_pwrst_trans - Transition states defined in PRCMU firmware
+ * @NO_TRANSITION: No power state transition
+ * @APEXECUTE_TO_APSLEEP: Power state transition from ApExecute to ApSleep
+ * @APIDLE_TO_APSLEEP: Power state transition from ApIdle to ApSleep
+ * @APEXECUTE_TO_APDEEPSLEEP: Power state transition from ApExecute to
+ *                          ApDeepSleep
+ * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle
+ */
+enum ap_pwrst_trans {
+	PRCMU_AP_NO_CHANGE		= 0x00,
+	PRCMU_AP_SLEEP,
+	PRCMU_AP_DEEP_SLEEP,
+	PRCMU_AP_IDLE,
+	PRCMU_AP_DEEP_IDLE,
+};
+
 struct prcmu_tcdm_map {
 	u32 tcdm_size;
 	u32 legacy_offset;
@@ -224,77 +241,25 @@ struct prcmu_tcdm_map {
 
 #include <mach/id.h>
 
-static inline void __init prcmu_early_init(struct prcmu_tcdm_map *map)
-{
-	return db8500_prcmu_early_init(map);
-}
-
-static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-		bool keep_ap_pll)
-{
-	return db8500_prcmu_set_power_state(state, keep_ulp_clk,
-		keep_ap_pll);
-}
-
-static inline u8 prcmu_get_power_state_result(void)
-{
-	return db8500_prcmu_get_power_state_result();
-}
-
-static inline int prcmu_gic_decouple(void)
-{
-	return db8500_prcmu_gic_decouple();
-}
-
-static inline int prcmu_gic_recouple(void)
-{
-	return db8500_prcmu_gic_recouple();
-}
-
-static inline bool prcmu_gic_pending_irq(void)
-{
-	return db8500_prcmu_gic_pending_irq();
-}
-
-static inline bool prcmu_is_cpu_in_wfi(int cpu)
-{
-	return db8500_prcmu_is_cpu_in_wfi(cpu);
-}
-
-static inline int prcmu_copy_gic_settings(void)
-{
-	return db8500_prcmu_copy_gic_settings();
-}
-
-static inline bool prcmu_pending_irq(void)
-{
-	return db8500_prcmu_pending_irq();
-}
+void prcmu_early_init(struct prcmu_tcdm_map *map);
 
-static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
-{
-	return db8500_prcmu_set_epod(epod_id, epod_state);
-}
+int prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
+u8 prcmu_get_power_state_result(void);
 
-static inline void prcmu_enable_wakeups(u32 wakeups)
-{
-	db8500_prcmu_enable_wakeups(wakeups);
-}
+int prcmu_gic_decouple(void);
+int prcmu_gic_recouple(void);
+bool prcmu_gic_pending_irq(void);
+bool prcmu_is_cpu_in_wfi(int cpu);
+int prcmu_copy_gic_settings(void);
+bool prcmu_pending_irq(void);
 
-static inline void prcmu_disable_wakeups(void)
-{
-	prcmu_enable_wakeups(0);
-}
+int prcmu_set_epod(u16 epod_id, u8 epod_state);
 
-static inline void prcmu_config_abb_event_readout(u32 abb_events)
-{
-	db8500_prcmu_config_abb_event_readout(abb_events);
-}
+void prcmu_enable_wakeups(u32 wakeups);
+void prcmu_disable_wakeups(void);
 
-static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
-{
-	db8500_prcmu_get_abb_event_buffer(buf);
-}
+void prcmu_config_abb_event_readout(u32 abb_events);
+void prcmu_get_abb_event_buffer(void __iomem **buf);
 
 int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
 int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
@@ -302,65 +267,35 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size);
 
 int prcmu_config_clkout(u8 clkout, u8 source, u8 div);
 
-static inline int prcmu_request_clock(u8 clock, bool enable)
-{
-	return db8500_prcmu_request_clock(clock, enable);
-}
+int prcmu_request_clock(u8 clock, bool enable);
 
 unsigned long prcmu_clock_rate(u8 clock);
 long prcmu_round_clock_rate(u8 clock, unsigned long rate);
 int prcmu_set_clock_rate(u8 clock, unsigned long rate);
 
-static inline int prcmu_set_ddr_opp(u8 opp)
-{
-	return db8500_prcmu_set_ddr_opp(opp);
-}
-static inline int prcmu_get_ddr_opp(void)
-{
-	return db8500_prcmu_get_ddr_opp();
-}
+int prcmu_set_ddr_opp(u8 opp);
+int prcmu_get_ddr_opp(void);
 
-static inline int prcmu_set_arm_opp(u8 opp)
-{
-	return db8500_prcmu_set_arm_opp(opp);
-}
+int prcmu_set_arm_opp(u8 opp);
 
-static inline int prcmu_get_arm_opp(void)
-{
-	return db8500_prcmu_get_arm_opp();
-}
+int prcmu_get_arm_opp(void);
 
-static inline int prcmu_set_ape_opp(u8 opp)
-{
-	return db8500_prcmu_set_ape_opp(opp);
-}
+int prcmu_set_ape_opp(u8 opp);
 
-static inline int prcmu_get_ape_opp(void)
-{
-	return db8500_prcmu_get_ape_opp();
-}
+int prcmu_get_ape_opp(void);
 
-static inline void prcmu_system_reset(u16 reset_code)
-{
-	return db8500_prcmu_system_reset(reset_code);
-}
+void prcmu_system_reset(u16 reset_code);
 
-static inline u16 prcmu_get_reset_code(void)
-{
-	return db8500_prcmu_get_reset_code();
-}
+u16 prcmu_get_reset_code(void);
 
 int prcmu_ac_wake_req(void);
 void prcmu_ac_sleep_req(void);
-static inline void prcmu_modem_reset(void)
-{
-	return db8500_prcmu_modem_reset();
-}
 
-static inline bool prcmu_is_ac_wake_requested(void)
-{
-	return db8500_prcmu_is_ac_wake_requested();
-}
+void prcmu_modem_reset(void);
+
+bool prcmu_is_ac_wake_requested(void);
+
+bool prcmu_has_arm_maxopp(void);
 
 static inline int prcmu_set_display_clocks(void)
 {
@@ -377,10 +312,7 @@ static inline int prcmu_enable_dsipll(void)
 	return db8500_prcmu_enable_dsipll();
 }
 
-static inline int prcmu_config_esram0_deep_sleep(u8 state)
-{
-	return db8500_prcmu_config_esram0_deep_sleep(state);
-}
+int prcmu_config_esram0_deep_sleep(u8 state);
 
 static inline int prcmu_config_hotdog(u8 threshold)
 {
@@ -402,300 +334,215 @@ static inline int prcmu_stop_temp_sense(void)
 	return  db8500_prcmu_stop_temp_sense();
 }
 
-static inline u32 prcmu_read(unsigned int reg)
-{
-	return db8500_prcmu_read(reg);
-}
-
-static inline void prcmu_write(unsigned int reg, u32 value)
-{
-	db8500_prcmu_write(reg, value);
-}
-
-static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
-{
-	db8500_prcmu_write_masked(reg, mask, value);
-}
-
-static inline int prcmu_enable_a9wdog(u8 id)
-{
-	return db8500_prcmu_enable_a9wdog(id);
-}
-
-static inline int prcmu_disable_a9wdog(u8 id)
-{
-	return db8500_prcmu_disable_a9wdog(id);
-}
-
-static inline int prcmu_kick_a9wdog(u8 id)
-{
-	return db8500_prcmu_kick_a9wdog(id);
-}
-
-static inline int prcmu_load_a9wdog(u8 id, u32 timeout)
-{
-	return db8500_prcmu_load_a9wdog(id, timeout);
-}
-
-static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
-{
-	return db8500_prcmu_config_a9wdog(num, sleep_auto_off);
-}
-#else
-
-static inline void __init prcmu_early_init(struct prcmu_tcdm_map *map) {}
-
-static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-	bool keep_ap_pll)
-{
-	return 0;
-}
-
-static inline int prcmu_set_epod(u16 epod_id, u8 epod_state)
-{
-	return 0;
-}
-
-static inline void prcmu_enable_wakeups(u32 wakeups) {}
-
-static inline void prcmu_disable_wakeups(void) {}
-
-static inline int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
-{
-	return -ENOSYS;
-}
-
-static inline int prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
-{
-	return -ENOSYS;
-}
-
-static inline int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
-	u8 size)
-{
-	return -ENOSYS;
-}
-
-static inline int prcmu_config_clkout(u8 clkout, u8 source, u8 div)
-{
-	return 0;
-}
-
-static inline int prcmu_request_clock(u8 clock, bool enable)
-{
-	return 0;
-}
+u32 prcmu_read(unsigned int reg);
+void prcmu_write(unsigned int reg, u32 value);
+void prcmu_write_masked(unsigned int reg, u32 mask, u32 value);
 
-static inline long prcmu_round_clock_rate(u8 clock, unsigned long rate)
-{
-	return 0;
-}
+int prcmu_enable_a9wdog(u8 id);
+int prcmu_disable_a9wdog(u8 id);
+int prcmu_kick_a9wdog(u8 id);
+int prcmu_load_a9wdog(u8 id, u32 timeout);
+int prcmu_config_a9wdog(u8 num, bool sleep_auto_off);
 
-static inline int prcmu_set_clock_rate(u8 clock, unsigned long rate)
-{
-	return 0;
-}
 
-static inline unsigned long prcmu_clock_rate(u8 clock)
-{
-	return 0;
-}
+/* prcmu_get_val /prcmu_set_val */
+enum prcmu_val {
+	DDR_OPP,
+	ARM_OPP,
+	APE_OPP,
 
-static inline int prcmu_set_ape_opp(u8 opp)
-{
-	return 0;
-}
+	PRCMU_VAL_MAX /*  used for dimensioning */
+};
 
-static inline int prcmu_get_ape_opp(void)
-{
-	return APE_100_OPP;
-}
+int prcmu_set_val(enum prcmu_val type, u32 value);
+int prcmu_get_val(enum prcmu_val type);
 
-static inline int prcmu_set_arm_opp(u8 opp)
-{
-	return 0;
-}
+/*  prcmu_enable/prcmu_disable */
+enum prcmu_out {
+	SPI2_MUX,
+	STM_MOD_UART_MUX,
+	STM_APE_MUX,
 
-static inline int prcmu_get_arm_opp(void)
-{
-	return ARM_100_OPP;
-}
+	PRCMU_OUT_MAX /* used for dimensioning  */
+};
 
-static inline int prcmu_set_ddr_opp(u8 opp)
-{
-	return 0;
-}
+int prcmu_enable(enum prcmu_out out);
+int prcmu_disable(enum prcmu_out out);
 
-static inline int prcmu_get_ddr_opp(void)
-{
-	return DDR_100_OPP;
-}
 
-static inline void prcmu_system_reset(u16 reset_code) {}
+struct prcmu_out_data {
+	enum prcmu_out out;
+	int (*enable)(void);
+	int (*disable)(void);
+};
 
-static inline u16 prcmu_get_reset_code(void)
-{
-	return 0;
-}
+struct prcmu_val_data {
+	enum prcmu_val val;
+	int (*get_val)(void);
+	int (*set_val)(u8 value);
+};
 
-static inline int prcmu_ac_wake_req(void)
-{
-	return 0;
-}
 
-static inline void prcmu_ac_sleep_req(void) {}
+/**
+ * @brief mfd device dbx500-prmcu early fops
+ */
+struct prcmu_early_data {
+	/* reset */
+	void (*system_reset) (u16 reset_code);
 
-static inline void prcmu_modem_reset(void) {}
+	/*  clock api  */
+	int (*config_clkout) (u8 clkout, u8 source, u8 div);
+	int (*request_clock) (u8 clock, bool enable);
 
-static inline bool prcmu_is_ac_wake_requested(void)
-{
-	return false;
-}
+	/* direct access to prcmu reg */
+	u32 (*read) (unsigned int reg);
+	void (*write) (unsigned int reg, u32 value);
+	void (*write_masked) (unsigned int reg, u32 mask, u32 value);
 
-static inline int prcmu_set_display_clocks(void)
-{
-	return 0;
-}
 
-static inline int prcmu_disable_dsipll(void)
-{
-	return 0;
-}
+	/*  other specific 8500 */
+	long (*round_clock_rate) (u8 clock, unsigned long rate);
+	int (*set_clock_rate) (u8 clock, unsigned long rate);
+	unsigned long (*clock_rate) (u8 clock);
+	/*  clock specific */
+	struct prcmu_fw_version *(*get_fw_version) (void);
+	bool (*has_arm_maxopp)(void);
 
-static inline int prcmu_enable_dsipll(void)
-{
-	return 0;
-}
+};
 
-static inline int prcmu_config_esram0_deep_sleep(u8 state)
-{
-	return 0;
-}
+/**
+ * @brief mfd device dbx500-prmcu platform data
+ */
+struct prcmu_probe_data {
+	/* ux500 soc sysfs */
+	u16 (*get_reset_code) (void);
+
+	/* pm/suspend.c  */
+	int (*config_esram0_deep_sleep) (u8 state);
+	void (*enable_wakeups)(u32 wakeups);
+	bool (*is_ac_wake_requested) (void);
+	int (*set_power_state) (u8 state, bool keep_ulp_clk,
+			bool keep_ap_pll);
+	u8  (*get_power_state_result) (void);
+
+	/* modem */
+	void (*modem_reset)(void);
+
+	/* no used at all */
+	void (*config_abb_event_readout) (u32 abb_events);
+	void (*get_abb_event_buffer) (void __iomem **buf);
+
+	/* abb access */
+	int (*abb_read) (u8 slave, u8 reg, u8 *value, u8 size);
+	int (*abb_write) (u8 slave, u8 reg, u8 *value, u8 size);
+
+	u32 (*get_reset_status)(void);
+	/*  other u8500 specific */
+	int (*request_ape_opp_100_voltage) (bool enable);
+	void (*configure_auto_pm) (struct prcmu_auto_pm_config *sleep,
+	struct prcmu_auto_pm_config *idle);
+	int (*set_epod) (u16 epod_id, u8 epod_state);
+
+	/* abb specific */
+	int (*abb_write_masked) (u8 slave, u8 reg, u8 *value,
+		u8 *mask, u8 size);
+
+	/* watchdog */
+	int (*config_a9wdog) (u8 num, bool sleep_auto_off);
+	int (*enable_a9wdog) (u8 id);
+	int (*disable_a9wdog) (u8 id);
+	int (*kick_a9wdog) (u8 id);
+	int (*load_a9wdog) (u8 id, u32 val);
+};
 
-static inline void prcmu_config_abb_event_readout(u32 abb_events) {}
+/* on u8500 default behaviour return 0 */
+struct prcmu_probe_cpuhp_data {
+	int (*stay_in_wfi_check)(void);
+	int (*replug_cpu1) (void);
+	int (*unplug_cpu1) (void);
+};
 
-static inline void prcmu_get_abb_event_buffer(void __iomem **buf)
-{
-	*buf = NULL;
-}
 
-static inline int prcmu_config_hotdog(u8 threshold)
-{
-	return 0;
-}
+enum prcmu_fops_type {
+	PRCMU_VAL,
+	PRCMU_OUT,
+	PRCMU_EARLY,
+	PRCMU_PROBE,
+	PRCMU_PROBE_CPU_HP,
+	PRCMU_APE_AGE,
+};
 
-static inline int prcmu_config_hotmon(u8 low, u8 high)
-{
-	return 0;
-}
+struct prcmu_fops_register {
+	enum prcmu_fops_type fops;
+	int size;
+	union {
+		struct prcmu_val_data *pval;
+		struct prcmu_out_data *pout;
+		struct prcmu_early_data *pearly;
+		struct prcmu_probe_data *pprobe;
+		struct prcmu_probe_cpuhp_data *pprobe_cpuhp;
+		bool (*check_ape_age)(void);
+	} data;
+};
 
-static inline int prcmu_start_temp_sense(u16 cycles32k)
-{
-	return 0;
-}
+/**
+ * @brief mfd device dbx500-prcmu platform data
+ */
+struct prcmu_fops_register_data {
+	int size;
+	struct prcmu_fops_register *tab;
+};
 
-static inline int prcmu_stop_temp_sense(void)
-{
-	return 0;
-}
+/**
+ * struct dbx500_regulator_init_data - mfd device prcmu-regulators data
+ *
+ */
+struct dbx500_regulator_init_data {
+	int (*set_epod) (u16 epod_id, u8 epod_state);
+	void *regulators;
+	int reg_num;
+};
 
-static inline u32 prcmu_read(unsigned int reg)
-{
-	return 0;
-}
+#else
 
-static inline void prcmu_write(unsigned int reg, u32 value) {}
+static inline void __init prcmu_early_init(struct prcmu_tcdm_map *map) {}
 
-static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {}
 
 #endif
 
-static inline void prcmu_set(unsigned int reg, u32 bits)
-{
-	prcmu_write_masked(reg, bits, bits);
-}
-
-static inline void prcmu_clear(unsigned int reg, u32 bits)
-{
-	prcmu_write_masked(reg, bits, 0);
-}
 
 #if defined(CONFIG_UX500_SOC_DB8500)
 
 /**
  * prcmu_enable_spi2 - Enables pin muxing for SPI2 on OtherAlternateC1.
  */
-static inline void prcmu_enable_spi2(void)
-{
-	if (cpu_is_u8500())
-		prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
-}
+void prcmu_enable_spi2(void);
 
 /**
  * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
  */
-static inline void prcmu_disable_spi2(void)
-{
-	if (cpu_is_u8500())
-		prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
-}
-
+void prcmu_disable_spi2(void);
 /**
  * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD
  * and UARTMOD on OtherAlternateC3.
  */
-static inline void prcmu_enable_stm_mod_uart(void)
-{
-	if (cpu_is_u8500()) {
-		prcmu_set(DB8500_PRCM_GPIOCR,
-			(DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
-			 DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0));
-	}
-}
+void prcmu_enable_stm_mod_uart(void);
 
 /**
  * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD
  * and UARTMOD on OtherAlternateC3.
  */
-static inline void prcmu_disable_stm_mod_uart(void)
-{
-	if (cpu_is_u8500()) {
-		prcmu_clear(DB8500_PRCM_GPIOCR,
-			(DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
-			 DB8500_PRCM_GPIOCR_DBG_UARTMOD_CMD0));
-	}
-}
+void prcmu_disable_stm_mod_uart(void);
 
 /**
  * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1.
  */
-static inline void prcmu_enable_stm_ape(void)
-{
-	if (cpu_is_u8500()) {
-		prcmu_set(DB8500_PRCM_GPIOCR,
-			DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
-	}
-}
+void prcmu_enable_stm_ape(void);
 
 /**
  * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1.
  */
-static inline void prcmu_disable_stm_ape(void)
-{
-	if (cpu_is_u8500()) {
-		prcmu_clear(DB8500_PRCM_GPIOCR,
-			DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
-	}
-}
-
-#else
-
-static inline void prcmu_enable_spi2(void) {}
-static inline void prcmu_disable_spi2(void) {}
-static inline void prcmu_enable_stm_mod_uart(void) {}
-static inline void prcmu_disable_stm_mod_uart(void) {}
-static inline void prcmu_enable_stm_ape(void) {}
-static inline void prcmu_disable_stm_ape(void) {}
+void prcmu_disable_stm_ape(void);
 
 #endif
 
-- 
1.7.11.1




More information about the linux-arm-kernel mailing list