linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/17] Add ST-Ericsson U9540 support
@ 2012-09-05  9:58 Loic Pallardy
  2012-09-05  9:58 ` [PATCH 01/17] arm: ux500: add u9540 pin configuration Loic Pallardy
                   ` (16 more replies)
  0 siblings, 17 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:58 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy

Hi,

The following patch series contains board files and prcmu driver modifications
to support ST-Ericsson U9540 chipset and CCU9540 board configuration.
It includes:
 - mfd db8500-prmcu: adaptation to support new chipset
 - mfd dbx540-prmcu: creation for u9540 platform
 - arm ux500: add u9540 chipset definition

Best regards,
Loic

Loic Pallardy (17):
  arm: ux500: add u9540 pin configuration
  arm: ux500: add ccu9540 board support
  arm: ux500: Create board-specific IRQ init callback
  mfd: dbx500-prcmu: Introduce TCDM mapping struct
  mfd: dbx500-prcmu: Handle TCDM mapping
  arm: ux500: Add u9540 PRCMU TCDM configuration
  mfd: prcmu: configurable tcdm base address
  arm: ux500: update DB internal irq nb
  mfd: prcmu: add db9540 support
  mfd: prcmu: dbx500-prmcu creation
  mfd: pcrmu: create common header file for legacy mailbox
  mfd: prcmu: make fw_project_name generic
  mfd: prcmu: make legacy mailbox services configurable
  mfd: db8500-prcmu: use db8500 legacy services
  mfd: dbx540-prcmu creation
  arm: ux500: add dbx540 prcmu platform data
  mfd: db8500-prcmu: activate dbx540-prcmu driver

 arch/arm/mach-ux500/board-mop500-pins.c    |  200 ++
 arch/arm/mach-ux500/board-mop500-sdi.c     |   12 +
 arch/arm/mach-ux500/board-mop500.c         |   67 +-
 arch/arm/mach-ux500/board-mop500.h         |    2 +
 arch/arm/mach-ux500/cpu-db8500.c           |   18 +-
 arch/arm/mach-ux500/cpu.c                  |    4 +-
 arch/arm/mach-ux500/include/mach/devices.h |    6 +
 arch/arm/mach-ux500/include/mach/irqs.h    |    2 +-
 drivers/mfd/Kconfig                        |   21 +
 drivers/mfd/Makefile                       |    2 +
 drivers/mfd/db8500-prcmu.c                 | 1161 ++++++------
 drivers/mfd/dbx500-prcmu-regs.h            |    1 +
 drivers/mfd/dbx500-prcmu.c                 |  815 ++++++++
 drivers/mfd/dbx500-prcmu.h                 |  465 +++++
 drivers/mfd/dbx540-prcmu-regs.h            |  106 ++
 drivers/mfd/dbx540-prcmu.c                 | 2807 ++++++++++++++++++++++++++++
 include/linux/mfd/db8500-prcmu.h           |  274 +--
 include/linux/mfd/dbx500-prcmu.h           |  593 +++---
 include/linux/mfd/dbx540-prcmu.h           |   96 +
 19 files changed, 5455 insertions(+), 1197 deletions(-)
 create mode 100644 drivers/mfd/dbx500-prcmu.c
 create mode 100644 drivers/mfd/dbx500-prcmu.h
 create mode 100644 drivers/mfd/dbx540-prcmu-regs.h
 create mode 100644 drivers/mfd/dbx540-prcmu.c
 create mode 100644 include/linux/mfd/dbx540-prcmu.h

-- 
1.7.11.1


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

* [PATCH 01/17] arm: ux500: add u9540 pin configuration
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
@ 2012-09-05  9:58 ` Loic Pallardy
  2012-09-05  9:58 ` [PATCH 02/17] arm: ux500: add ccu9540 board support Loic Pallardy
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:58 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

Add dedicated pin configuration for u9540 platform

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/board-mop500-pins.c | 200 ++++++++++++++++++++++++++++++++
 arch/arm/mach-ux500/board-mop500.h      |   1 +
 2 files changed, 201 insertions(+)

diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c
index 32fd992..cc0949d 100644
--- a/arch/arm/mach-ux500/board-mop500-pins.c
+++ b/arch/arm/mach-ux500/board-mop500-pins.c
@@ -40,11 +40,15 @@ BIAS(in_pu_slpm_out_lo, PIN_INPUT_PULLUP|PIN_SLPM_OUTPUT_LOW);
 BIAS(out_hi, PIN_OUTPUT_HIGH);
 BIAS(out_lo, PIN_OUTPUT_LOW);
 BIAS(out_lo_sleep_nowkup, PIN_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE);
+BIAS(in_pu_slpm_in_pu, PIN_INPUT_PULLUP|PIN_SLPM_INPUT_PULLUP);
+BIAS(out_lo_slpm_out_lo, PIN_OUTPUT_LOW|PIN_SLPM_OUTPUT_LOW);
 /* These also force them into GPIO mode */
 BIAS(gpio_in_pu, PIN_INPUT_PULLUP|PIN_GPIOMODE_ENABLED);
 BIAS(gpio_in_pd, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED);
+BIAS(gpio_in_nopull, PIN_INPUT_NOPULL|PIN_GPIOMODE_ENABLED);
 BIAS(gpio_in_pu_slpm_gpio_nopull, PIN_INPUT_PULLUP|PIN_GPIOMODE_ENABLED|PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
 BIAS(gpio_in_pd_slpm_gpio_nopull, PIN_INPUT_PULLDOWN|PIN_GPIOMODE_ENABLED|PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
+BIAS(gpio_in_nopull_slpm_gpio_nopull, PIN_INPUT_NOPULL|PIN_GPIOMODE_ENABLED|PIN_SLPM_GPIO|PIN_SLPM_INPUT_NOPULL);
 BIAS(gpio_out_hi, PIN_OUTPUT_HIGH|PIN_GPIOMODE_ENABLED);
 BIAS(gpio_out_lo, PIN_OUTPUT_LOW|PIN_GPIOMODE_ENABLED);
 /* Sleep modes */
@@ -447,6 +451,192 @@ static struct pinctrl_map __initdata snowball_pinmap[] = {
 	DB8500_PIN_HOG("GPIO216_AG12", gpio_in_pu), /* WLAN_IRQ */
 };
 
+/* Pin control settings */
+static struct pinctrl_map __initdata ccu9540_common_pinmap[] = {
+	/*
+	 * uMSP0, mux in 4 pins, regular placement of RX/TX
+	 * explicitly set the pins to no pull
+	 */
+	DB8500_MUX_HOG("msp0txrx_a_1", "msp0"),
+	DB8500_MUX_HOG("msp0tfstck_a_1", "msp0"),
+	DB8500_PIN_HOG("GPIO12_AC4", in_nopull), /* TXD */
+	DB8500_PIN_HOG("GPIO13_AF3", in_nopull), /* TFS */
+	DB8500_PIN_HOG("GPIO14_AE3", in_nopull), /* TCK */
+	DB8500_PIN_HOG("GPIO15_AC3", in_nopull), /* RXD */
+
+	/* MSP2 for HDMI, pull down TXD, TCK, TFS  */
+	DB8500_MUX_HOG("msp2_a_1", "msp2"),
+	DB8500_PIN_HOG("GPIO193_AH27", in_pd), /* TXD */
+	DB8500_PIN_HOG("GPIO194_AF27", in_pd), /* TCK */
+	DB8500_PIN_HOG("GPIO195_AG28", in_pd), /* TFS */
+	DB8500_PIN_HOG("GPIO196_AG26", out_lo), /* RXD */
+	/*
+	 * LCD, set TE0 (using LCD VSI0) and D14 (touch screen interrupt) to
+	 * pull-up
+	 * TODO: is this really correct? Snowball doesn't have a LCD.
+	 */
+	DB8500_MUX_HOG("lcdvsi0_a_1", "lcd"),
+	DB8500_PIN_HOG("GPIO68_E1", in_pu),
+	/*
+	 * UART0, we do not mux in u0 here.
+	 * uart-0 pins gpio configuration should be kept intact to prevent
+	 * a glitch in tx line when the tty dev is opened. Later these pins
+	 * are configured to uart mop500_pins_uart0
+	*/
+	DB8500_PIN_HOG("GPIO0_AJ5", in_pu), /* CTS */
+	DB8500_PIN_HOG("GPIO1_AJ3", out_hi), /* RTS */
+	DB8500_PIN_HOG("GPIO2_AH4", in_pu), /* RXD */
+	DB8500_PIN_HOG("GPIO3_AH3", out_hi), /* TXD */
+	/*
+	 * Mux in UART2 on altfunction C and set pull-ups.
+	 * TODO: is this used on U8500 variants and Snowball really?
+	 * The setting on GPIO31 conflicts with magnetometer use on hrefv60
+	 */
+	DB8500_MUX_HOG("u2rxtx_c_1", "u2"),
+	DB8500_MUX_HOG("u2ctsrts_c_1", "u2"),
+	DB8500_PIN_HOG("GPIO29_W2", in_pu), /* RXD */
+	DB8500_PIN_HOG("GPIO30_W3", out_hi), /* TXD */
+	DB8500_PIN_HOG("GPIO31_V3", in_pu), /* CTS */
+	DB8500_PIN_HOG("GPIO32_V2", out_hi), /* RTS */
+};
+
+static struct pinctrl_map __initdata ccu9540_pinmap[] = {
+	/* MSP : HDTV INTERFACE */
+	DB8500_PIN_HOG("GPIO192_AJ27", gpio_in_pd),
+
+	/* ACCELEROMETER_INTERFACE */
+	DB8500_PIN_HOG("GPIO82_C1", gpio_in_pu), /* ACC_INT1 */
+	DB8500_PIN_HOG("GPIO83_D3", gpio_in_pu), /* ACC_INT2 */
+
+	/* PM2301 interrupt dedicated GPIO */
+	DB8500_PIN_HOG("GPIO171_D23", gpio_in_pu),
+
+	DB8500_MUX_HOG("u1rxtx_a_1", "u1"),
+	DB8500_PIN_HOG("GPIO4_AH6", in_pu), /* RXD */
+	DB8500_PIN_HOG("GPIO5_AG6", out_hi), /*TXD */
+
+	DB8500_PIN_HOG("GPIO6_AF6", gpio_in_nopull), /* LAN PME */
+	DB8500_PIN_HOG("GPIO7_AG5", gpio_in_nopull), /* LAN IRQ */
+
+	/* Display Interface */
+	DB8500_PIN_HOG("GPIO143_D12", gpio_out_hi), /* DISP1 NO RST */
+
+	/* Touch screen INTERFACE */
+	DB8500_PIN_HOG("GPIO145_C13", gpio_out_lo), /* TOUCH_RST1 */
+	DB8500_PIN_HOG("GPIO146_D13", gpio_in_pu), /* TOUCH_INT1 */
+
+	/* LAN SMSC9221i */
+	DB8500_MUX_HOG("sm_b_1", "sm"),
+	DB8500_PIN_HOG("GPIO86_C6", out_lo),
+	DB8500_PIN_HOG("GPIO87_B3", out_lo),
+	DB8500_PIN_HOG("GPIO88_C4", out_lo),
+	DB8500_PIN_HOG("GPIO89_E6", out_lo),
+	DB8500_PIN_HOG("GPIO90_A3", out_lo),
+	DB8500_PIN_HOG("GPIO91_B6", out_lo),
+	DB8500_PIN_HOG("GPIO92_D6", out_lo),
+	DB8500_PIN_HOG("GPIO93_B7", out_lo),
+	DB8500_PIN_HOG("GPIO94_D7", out_lo),
+	DB8500_PIN_HOG("GPIO96_D8", out_hi),
+	DB8500_PIN_HOG("GPIO97_D9", out_hi),
+	DB8500_PIN_HOG("GPIO128_A5", out_lo),
+	DB8500_PIN_HOG("GPIO129_B4", out_lo),
+	DB8500_PIN_HOG("GPIO130_C8", out_lo),
+	DB8500_PIN_HOG("GPIO131_A12", out_lo),
+	DB8500_PIN_HOG("GPIO132_C10", out_lo),
+	DB8500_PIN_HOG("GPIO133_B10", out_lo),
+	DB8500_PIN_HOG("GPIO134_B9", out_lo),
+	DB8500_PIN_HOG("GPIO135_A9", out_lo),
+	DB8500_PIN_HOG("GPIO136_C7", out_lo),
+	DB8500_PIN_HOG("GPIO137_A7", out_lo),
+	DB8500_PIN_HOG("GPIO138_C5", out_lo),
+	DB8500_PIN_HOG("GPIO139_C9", out_lo),
+	DB8500_MUX_HOG("smcs0_b_1", "sm"),
+	DB8500_PIN_HOG("GPIO95_E8", out_hi),
+
+	/* RESOUT */
+	DB8500_PIN_HOG("GPIO84_C2", gpio_in_nopull), /* RESOUT0 */
+	DB8500_PIN_HOG("GPIO85_D5", gpio_in_nopull), /* RESOUT2 */
+
+	/* SD card detect */
+	DB8500_PIN_HOG("GPIO230_AF7", gpio_in_pu),
+
+	/*
+	 * The following pin sets were known as "runtime pins" before being
+	 * converted to the pinctrl model. Here we model them as "default"
+	 * states.
+	 */
+	/* Mux in I2C blocks, put pins into GPIO in sleepmode no pull-up */
+	DB8500_MUX("i2c0_a_1", "i2c0", "nmk-i2c.0"),
+	DB8500_PIN("GPIO147_C15", slpm_gpio_nopull, "nmk-i2c.0"),
+	DB8500_PIN("GPIO148_B16", slpm_gpio_nopull, "nmk-i2c.0"),
+
+	/* Mux in I2C1 blocks, put pins into GPIO in sleepmode no pull-up */
+	DB8500_MUX("i2c1_b_2", "i2c1", "nmk-i2c.1"),
+	DB8500_PIN("GPIO16_AD3", slpm_gpio_nopull, "nmk-i2c.1"),
+	DB8500_PIN("GPIO17_AD4", slpm_gpio_nopull, "nmk-i2c.1"),
+
+	/* Mux in I2C2 blocks, put pins into GPIO in sleepmode no pull-up */
+	DB8500_MUX("i2c2_b_2", "i2c2", "nmk-i2c.2"),
+	DB8500_PIN("GPIO10_AF5", slpm_gpio_nopull, "nmk-i2c.2"),
+	DB8500_PIN("GPIO11_AG4", slpm_gpio_nopull, "nmk-i2c.2"),
+
+	/* Mux in LCD VSI1 and pull it up for MCDE HDMI output */
+	DB8500_MUX("lcdvsi1_a_1", "lcd", "0-0070"),
+	DB8500_PIN("GPIO69_E2", in_pu, "0-0070"),
+
+	DB8500_MUX("kp_b_1", "kp", "nmk-ske-keypad"),
+	DB8500_PIN("GPIO79_E3", in_pu_slpm_in_pu, "nmk-ske-keypad"), /* I6 */
+	DB8500_PIN("GPIO66_G3", in_pu_slpm_in_pu, "nmk-ske-keypad"), /* I1 */
+	DB8500_PIN("GPIO67_G2", in_pu_slpm_in_pu, "nmk-ske-keypad"), /* I0 */
+	DB8500_PIN("GPIO78_F4", out_lo_slpm_out_lo, "nmk-ske-keypad"), /* O6 */
+	DB8500_PIN("GPIO64_F3", out_lo_slpm_out_lo, "nmk-ske-keypad"), /* O1 */
+	DB8500_PIN("GPIO65_F1", out_lo_slpm_out_lo, "nmk-ske-keypad"), /* O0 */
+
+	/* Mux in SDI0 (here called MC0) used for removable MMC/SD/SDIO cards */
+	DB8500_MUX("mc0_a_1", "mc0", "sdi0"),
+	DB8500_PIN("GPIO18_AC2", out_hi, "sdi0"), /* CMDDIR */
+	DB8500_PIN("GPIO19_AC1", out_hi, "sdi0"), /* DAT0DIR */
+	DB8500_PIN("GPIO20_AB4", out_hi, "sdi0"), /* DAT2DIR */
+	DB8500_PIN("GPIO22_AA3", in_nopull, "sdi0"), /* FBCLK */
+	DB8500_PIN("GPIO23_AA4", out_lo, "sdi0"), /* CLK */
+	DB8500_PIN("GPIO24_AB2", in_pu, "sdi0"), /* CMD */
+	DB8500_PIN("GPIO25_Y4", in_pu, "sdi0"), /* DAT0 */
+	DB8500_PIN("GPIO26_Y2", in_pu, "sdi0"), /* DAT1 */
+	DB8500_PIN("GPIO27_AA2", in_pu, "sdi0"), /* DAT2 */
+	DB8500_PIN("GPIO28_AA1", in_pu, "sdi0"), /* DAT3 */
+
+	/* Mux in SDI1 (here called MC1) used for SDIO for CW1200 WLAN */
+	DB8500_MUX("mc1_a_1", "mc1", "sdi1"),
+	DB8500_PIN("GPIO208_AH16", out_lo, "sdi1"), /* CLK */
+	DB8500_PIN("GPIO209_AG15", in_nopull, "sdi1"), /* FBCLK */
+	DB8500_PIN("GPIO210_AJ15", in_pu, "sdi1"), /* CMD */
+	DB8500_PIN("GPIO211_AG14", in_pu, "sdi1"), /* DAT0 */
+	DB8500_PIN("GPIO212_AF13", in_pu, "sdi1"), /* DAT1 */
+	DB8500_PIN("GPIO213_AG13", in_pu, "sdi1"), /* DAT2 */
+	DB8500_PIN("GPIO214_AH15", in_pu, "sdi1"), /* DAT3 */
+
+	/* Mux in SDI4 (here called MC4) used for for PCB-mounted eMMC */
+	DB8500_MUX("mc4_a_1", "mc4", "sdi4"),
+	DB8500_PIN("GPIO197_AH24", in_pu, "sdi4"), /* DAT3 */
+	DB8500_PIN("GPIO198_AG25", in_pu, "sdi4"), /* DAT2 */
+	DB8500_PIN("GPIO199_AH23", in_pu, "sdi4"), /* DAT1 */
+	DB8500_PIN("GPIO200_AH26", in_pu, "sdi4"), /* DAT0 */
+	DB8500_PIN("GPIO201_AF24", in_pu, "sdi4"), /* CMD */
+	DB8500_PIN("GPIO202_AF25", in_nopull, "sdi4"), /* FBCLK */
+	DB8500_PIN("GPIO203_AE23", out_lo, "sdi4"), /* CLK */
+	DB8500_PIN("GPIO204_AF23", in_pu, "sdi4"), /* DAT7 */
+	DB8500_PIN("GPIO205_AG23", in_pu, "sdi4"), /* DAT6 */
+	DB8500_PIN("GPIO206_AG24", in_pu, "sdi4"), /* DAT5 */
+	DB8500_PIN("GPIO207_AJ23", in_pu, "sdi4"), /* DAT4 */
+
+	/* Mux in USB pins, drive STP high */
+	DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"),
+	DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */
+
+	/* Sensor1p */
+	DB8500_PIN("GPIO229_AG7", gpio_in_nopull_slpm_gpio_nopull, "gpio-keys.0"),
+};
+
 /*
  * passing "pinsfor=" in kernel cmdline allows for custom
  * configuration of GPIOs on u8500 derived boards.
@@ -512,3 +702,13 @@ void __init hrefv60_pinmaps_init(void)
 				  ARRAY_SIZE(hrefv60_pinmap));
 	mop500_href_family_pinmaps_init();
 }
+
+void __init ccu9540_pins_init(void)
+{
+
+	pinctrl_register_mappings(ccu9540_common_pinmap,
+				  ARRAY_SIZE(ccu9540_common_pinmap));
+	pinctrl_register_mappings(ccu9540_pinmap,
+				  ARRAY_SIZE(ccu9540_pinmap));
+}
+
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index d04a8e6..b696ab0 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -92,6 +92,7 @@ void __init mop500_stuib_init(void);
 void __init mop500_pinmaps_init(void);
 void __init snowball_pinmaps_init(void);
 void __init hrefv60_pinmaps_init(void);
+void __init ccu9540_pins_init(void);
 
 int __init mop500_uib_init(void);
 void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
-- 
1.7.11.1


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

* [PATCH 02/17] arm: ux500: add ccu9540 board support
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
  2012-09-05  9:58 ` [PATCH 01/17] arm: ux500: add u9540 pin configuration Loic Pallardy
@ 2012-09-05  9:58 ` Loic Pallardy
  2012-09-05 10:42   ` Arnd Bergmann
  2012-09-05  9:58 ` [PATCH 03/17] arm: ux500: Create board-specific IRQ init callback Loic Pallardy
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:58 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

Upgrade existing mop500 definition to support new ccu9540
board.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/board-mop500-sdi.c | 12 ++++++++++++
 arch/arm/mach-ux500/board-mop500.c     | 35 ++++++++++++++++++++++++++++++++++
 arch/arm/mach-ux500/board-mop500.h     |  1 +
 3 files changed, 48 insertions(+)

diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 18ff781..4fd21fe 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -255,6 +255,18 @@ void __init mop500_sdi_init(struct device *parent)
 	 */
 }
 
+void __init ccu9540_sdi_init(struct device *parent)
+{
+	/* On-board eMMC */
+	db8500_add_sdi4(parent, &mop500_sdi4_data, U8500_SDI_V2_PERIPHID);
+
+	/*
+	 * On boards with the TC35892 GPIO expander, sdi0 will finally
+	 * be added when the TC35892 initializes and calls
+	 * mop500_sdi_tc35892_init() above.
+	 */
+}
+
 void __init snowball_sdi_init(struct device *parent)
 {
 	/* On Snowball MMC_CAP_SD_HIGHSPEED isn't supported (Hardware issue?) */
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index fe1ff85..fa75f95 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -691,6 +691,30 @@ static void __init hrefv60_init_machine(void)
 	mop500_uib_init();
 }
 
+
+static void __init u9540_init_machine(void)
+{
+	struct device *parent;
+	int i;
+
+	ccu9540_pins_init();
+
+	parent = u8500_init_devices(&ab8500_platdata);
+
+	for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
+		mop500_platform_devs[i]->dev.parent = parent;
+
+	platform_add_devices(mop500_platform_devs,
+				ARRAY_SIZE(mop500_platform_devs));
+	mop500_i2c_init(parent);
+	ccu9540_sdi_init(parent);
+	mop500_msp_init(parent);
+	mop500_uart_init(parent);
+
+	/* This board has full regulator constraints */
+	regulator_has_full_constraints();
+}
+
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
 	.atag_offset	= 0x100,
@@ -727,6 +751,17 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
 	.init_late	= ux500_init_late,
 MACHINE_END
 
+MACHINE_START(U9540, "ST-Ericsson 9540 platform")
+	.atag_offset	= 0x100,
+	.map_io		= u8500_map_io,
+	.nr_irqs	= UX500_NR_IRQS,
+	.init_irq	= ux500_init_irq,
+	.timer		= &ux500_timer,
+	.handle_irq	= gic_handle_irq,
+	.init_machine	= u9540_init_machine,
+	.init_late	= ux500_init_late,
+MACHINE_END
+
 #ifdef CONFIG_MACH_UX500_DT
 
 struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index b696ab0..e5b2d3c 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -84,6 +84,7 @@ extern struct mmci_platform_data mop500_sdi4_data;
 extern struct arm_pmu_platdata db8500_pmu_platdata;
 
 extern void mop500_sdi_init(struct device *parent);
+extern void ccu9540_sdi_init(struct device *parent);
 extern void snowball_sdi_init(struct device *parent);
 extern void hrefv60_sdi_init(struct device *parent);
 extern void mop500_sdi_tc35892_init(struct device *parent);
-- 
1.7.11.1


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

* [PATCH 03/17] arm: ux500: Create board-specific IRQ init callback
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
  2012-09-05  9:58 ` [PATCH 01/17] arm: ux500: add u9540 pin configuration Loic Pallardy
  2012-09-05  9:58 ` [PATCH 02/17] arm: ux500: add ccu9540 board support Loic Pallardy
@ 2012-09-05  9:58 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 04/17] mfd: dbx500-prcmu: Introduce TCDM mapping struct Loic Pallardy
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:58 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy,
	Maxime Coquelin

First step to have a cpu-specific prcmu early init.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/board-mop500.c | 15 +++++++++++----
 arch/arm/mach-ux500/cpu.c          |  2 --
 2 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index fa75f95..057dfdb 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -21,6 +21,7 @@
 #include <linux/amba/pl022.h>
 #include <linux/amba/serial.h>
 #include <linux/spi/spi.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/regulator/ab8500.h>
 #include <linux/mfd/tc3589x.h>
@@ -715,12 +716,18 @@ static void __init u9540_init_machine(void)
 	regulator_has_full_constraints();
 }
 
+static void __init mop500_init_irq(void)
+{
+	prcmu_early_init();
+	ux500_init_irq();
+}
+
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
 	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.nr_irqs	= UX500_NR_IRQS,
-	.init_irq	= ux500_init_irq,
+	.init_irq	= mop500_init_irq,
 	/* we re-use nomadik timer here */
 	.timer		= &ux500_timer,
 	.handle_irq	= gic_handle_irq,
@@ -732,7 +739,7 @@ MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
 	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.nr_irqs	= UX500_NR_IRQS,
-	.init_irq	= ux500_init_irq,
+	.init_irq	= mop500_init_irq,
 	.timer		= &ux500_timer,
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= hrefv60_init_machine,
@@ -743,7 +750,7 @@ MACHINE_START(SNOWBALL, "Calao Systems Snowball platform")
 	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.nr_irqs	= UX500_NR_IRQS,
-	.init_irq	= ux500_init_irq,
+	.init_irq	= mop500_init_irq,
 	/* we re-use nomadik timer here */
 	.timer		= &ux500_timer,
 	.handle_irq	= gic_handle_irq,
@@ -755,7 +762,7 @@ MACHINE_START(U9540, "ST-Ericsson 9540 platform")
 	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.nr_irqs	= UX500_NR_IRQS,
-	.init_irq	= ux500_init_irq,
+	.init_irq	= mop500_init_irq,
 	.timer		= &ux500_timer,
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= u9540_init_machine,
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 4b0a9b3..4a5177b 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -68,8 +68,6 @@ void __init ux500_init_irq(void)
 	 * Init clocks here so that they are available for system timer
 	 * initialization.
 	 */
-	if (cpu_is_u8500_family())
-		db8500_prcmu_early_init();
 	clk_init();
 }
 
-- 
1.7.11.1


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

* [PATCH 04/17] mfd: dbx500-prcmu: Introduce TCDM mapping struct
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (2 preceding siblings ...)
  2012-09-05  9:58 ` [PATCH 03/17] arm: ux500: Create board-specific IRQ init callback Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 05/17] mfd: dbx500-prcmu: Handle TCDM mapping Loic Pallardy
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy,
	Maxime Coquelin

TCDM size varies between DBs models.
This patch introduces a new structure aimed to handle the TCDM
dynamically.

Each SoC from ux500 family declares its mapping and pass it to
prcmu early init.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/board-mop500.c         |  3 ++-
 arch/arm/mach-ux500/cpu-db8500.c           | 11 +++++++++++
 arch/arm/mach-ux500/include/mach/devices.h |  3 +++
 include/linux/mfd/dbx500-prcmu.h           |  9 +++++++--
 4 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 057dfdb..a38493b 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -28,6 +28,7 @@
 #include <linux/mfd/tps6105x.h>
 #include <linux/mfd/abx500/ab8500-gpio.h>
 #include <linux/mfd/abx500/ab8500-codec.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <linux/leds-lp5521.h>
 #include <linux/input.h>
 #include <linux/smsc911x.h>
@@ -718,7 +719,7 @@ static void __init u9540_init_machine(void)
 
 static void __init mop500_init_irq(void)
 {
-	prcmu_early_init();
+	prcmu_early_init(&db8500_tcdm_map);
 	ux500_init_irq();
 }
 
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index f3ed787..59dcf82 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/dbx500-prcmu.h>
 
 #include <asm/mach/map.h>
 #include <asm/pmu.h>
@@ -133,6 +134,16 @@ static struct platform_device db8500_prcmu_device = {
 	.name			= "db8500-prcmu",
 };
 
+struct prcmu_tcdm_map db8500_tcdm_map = {
+	.tcdm_size = SZ_4K,
+	.legacy_offset = 0,
+};
+
+struct prcmu_tcdm_map db9540_tcdm_map = {
+	.tcdm_size = SZ_4K + SZ_8K,
+	.legacy_offset = SZ_8K,
+};
+
 static struct platform_device *platform_devs[] __initdata = {
 	&u8500_dma40_device,
 	&db8500_pmu_device,
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index cbc6f1e..1caa76e 100644
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -20,4 +20,7 @@ extern struct platform_device ux500_cryp1_device;
 extern struct platform_device u8500_dma40_device;
 extern struct platform_device ux500_ske_keypad_device;
 
+extern struct prcmu_tcdm_map db8500_tcdm_map;
+extern struct prcmu_tcdm_map db9540_tcdm_map;
+
 #endif
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index 5b90e94..55025ba 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -213,13 +213,18 @@ enum ddr_pwrst {
 	DDR_PWR_STATE_OFFHIGHLAT    = 0x03
 };
 
+struct prcmu_tcdm_map {
+	u32 tcdm_size;
+	u32 legacy_offset;
+};
+
 #include <linux/mfd/db8500-prcmu.h>
 
 #if defined(CONFIG_UX500_SOC_DB8500)
 
 #include <mach/id.h>
 
-static inline void __init prcmu_early_init(void)
+static inline void __init prcmu_early_init(struct prcmu_tcdm_map *map)
 {
 	return db8500_prcmu_early_init();
 }
@@ -438,7 +443,7 @@ static inline int prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 }
 #else
 
-static inline void __init prcmu_early_init(void) {}
+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)
-- 
1.7.11.1


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

* [PATCH 05/17] mfd: dbx500-prcmu: Handle TCDM mapping
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (3 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 04/17] mfd: dbx500-prcmu: Introduce TCDM mapping struct Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 06/17] arm: ux500: Add u9540 PRCMU TCDM configuration Loic Pallardy
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy,
	Maxime Coquelin

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/cpu.c        | 2 +-
 drivers/mfd/db8500-prcmu.c       | 2 +-
 include/linux/mfd/db8500-prcmu.h | 4 ++--
 include/linux/mfd/dbx500-prcmu.h | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 4a5177b..08672be 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -9,7 +9,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx500-prcmu.h>
 #include <linux/clksrc-dbx500-prcmu.h>
 #include <linux/sys_soc.h>
 #include <linux/err.h>
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index de09113..1d2fb45 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2668,7 +2668,7 @@ static int db8500_irq_init(struct device_node *np)
 	return 0;
 }
 
-void __init db8500_prcmu_early_init(void)
+void __init db8500_prcmu_early_init(struct prcmu_tcdm_map *map)
 {
 	if (cpu_is_u8500v2()) {
 		void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index b82f6ee..f932a56 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -509,7 +509,7 @@ struct prcmu_fw_version {
 
 #ifdef CONFIG_MFD_DB8500_PRCMU
 
-void db8500_prcmu_early_init(void);
+void 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);
@@ -573,7 +573,7 @@ void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value);
 
 #else /* !CONFIG_MFD_DB8500_PRCMU */
 
-static inline void db8500_prcmu_early_init(void) {}
+static inline void db8500_prcmu_early_init(struct prcmu_tcdm_map *map) {}
 
 static inline int prcmu_set_rc_a2p(enum romcode_write code)
 {
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index 55025ba..aab183d 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -226,7 +226,7 @@ struct prcmu_tcdm_map {
 
 static inline void __init prcmu_early_init(struct prcmu_tcdm_map *map)
 {
-	return db8500_prcmu_early_init();
+	return db8500_prcmu_early_init(map);
 }
 
 static inline int prcmu_set_power_state(u8 state, bool keep_ulp_clk,
-- 
1.7.11.1


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

* [PATCH 06/17] arm: ux500: Add u9540 PRCMU TCDM configuration
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (4 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 05/17] mfd: dbx500-prcmu: Handle TCDM mapping Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 07/17] mfd: prcmu: configurable tcdm base address Loic Pallardy
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

u9540 dedicated prcmu configuration to use legacy driver

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/board-mop500.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index a38493b..0869c58 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -723,6 +723,12 @@ static void __init mop500_init_irq(void)
 	ux500_init_irq();
 }
 
+static void __init ccu9540_init_irq(void)
+{
+	prcmu_early_init(&db9540_tcdm_map);
+	ux500_init_irq();
+}
+
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
 	/* Maintainer: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> */
 	.atag_offset	= 0x100,
@@ -763,7 +769,7 @@ MACHINE_START(U9540, "ST-Ericsson 9540 platform")
 	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.nr_irqs	= UX500_NR_IRQS,
-	.init_irq	= mop500_init_irq,
+	.init_irq	= ccu9540_init_irq,
 	.timer		= &ux500_timer,
 	.handle_irq	= gic_handle_irq,
 	.init_machine	= u9540_init_machine,
-- 
1.7.11.1


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

* [PATCH 07/17] mfd: prcmu: configurable tcdm base address
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (5 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 06/17] arm: ux500: Add u9540 PRCMU TCDM configuration Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 08/17] arm: ux500: update DB internal irq nb Loic Pallardy
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

This patch allows using same services on different hardware
having different configuration.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/db8500-prcmu.c | 195 +++++++++++++++++++++++----------------------
 1 file changed, 101 insertions(+), 94 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 1d2fb45..3df427f 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -425,6 +425,7 @@ static DEFINE_SPINLOCK(prcmu_lock);
 static DEFINE_SPINLOCK(clkout_lock);
 
 /* Global var to runtime determine TCDM base for v2 or v1 */
+static __iomem void *tcdm_legacy_base;
 static __iomem void *tcdm_base;
 
 struct clk_mgt {
@@ -778,12 +779,14 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
 
-	writeb(MB0H_POWER_STATE_TRANS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
-	writeb(state, (tcdm_base + PRCM_REQ_MB0_AP_POWER_STATE));
-	writeb((keep_ap_pll ? 1 : 0), (tcdm_base + PRCM_REQ_MB0_AP_PLL_STATE));
+	writeb(MB0H_POWER_STATE_TRANS,
+			tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB0);
+	writeb(state, (tcdm_legacy_base + PRCM_REQ_MB0_AP_POWER_STATE));
+	writeb((keep_ap_pll ? 1 : 0),
+			tcdm_legacy_base + PRCM_REQ_MB0_AP_PLL_STATE);
 	writeb((keep_ulp_clk ? 1 : 0),
-		(tcdm_base + PRCM_REQ_MB0_ULP_CLOCK_STATE));
-	writeb(0, (tcdm_base + PRCM_REQ_MB0_DO_NOT_WFI));
+		(tcdm_legacy_base + PRCM_REQ_MB0_ULP_CLOCK_STATE));
+	writeb(0, (tcdm_legacy_base + PRCM_REQ_MB0_DO_NOT_WFI));
 	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
 	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
@@ -793,7 +796,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 
 u8 db8500_prcmu_get_power_state_result(void)
 {
-	return readb(tcdm_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
+	return readb(tcdm_legacy_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
 }
 
 /* This function decouple the gic from the prcmu */
@@ -933,9 +936,9 @@ static void config_wakeups(void)
 	for (i = 0; i < 2; i++) {
 		while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 			cpu_relax();
-		writel(dbb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_8500));
-		writel(abb_events, (tcdm_base + PRCM_REQ_MB0_WAKEUP_4500));
-		writeb(header[i], (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
+		writel(dbb_events, tcdm_legacy_base + PRCM_REQ_MB0_WAKEUP_8500);
+		writel(abb_events, tcdm_legacy_base + PRCM_REQ_MB0_WAKEUP_4500);
+		writeb(header[i], tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB0);
 		writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 	}
 	last_dbb_events = dbb_events;
@@ -977,10 +980,10 @@ void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 
 void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
 {
-	if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
-		*buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_1_4500);
+	if (readb(tcdm_legacy_base + PRCM_ACK_MB0_READ_POINTER) & 1)
+		*buf = (tcdm_legacy_base + PRCM_ACK_MB0_WAKEUP_1_4500);
 	else
-		*buf = (tcdm_base + PRCM_ACK_MB0_WAKEUP_0_4500);
+		*buf = (tcdm_legacy_base + PRCM_ACK_MB0_WAKEUP_0_4500);
 }
 
 /**
@@ -1004,9 +1007,9 @@ int db8500_prcmu_set_arm_opp(u8 opp)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
-	writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
-	writeb(opp, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
-	writeb(APE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_APE_OPP));
+	writeb(MB1H_ARM_APE_OPP, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
+	writeb(opp, (tcdm_legacy_base + PRCM_REQ_MB1_ARM_OPP));
+	writeb(APE_NO_CHANGE, (tcdm_legacy_base + PRCM_REQ_MB1_APE_OPP));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
@@ -1027,7 +1030,7 @@ int db8500_prcmu_set_arm_opp(u8 opp)
  */
 int db8500_prcmu_get_arm_opp(void)
 {
-	return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
+	return readb(tcdm_legacy_base + PRCM_ACK_MB1_CURRENT_ARM_OPP);
 }
 
 /**
@@ -1129,10 +1132,10 @@ int db8500_prcmu_set_ape_opp(u8 opp)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
-	writeb(MB1H_ARM_APE_OPP, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
-	writeb(ARM_NO_CHANGE, (tcdm_base + PRCM_REQ_MB1_ARM_OPP));
+	writeb(MB1H_ARM_APE_OPP, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
+	writeb(ARM_NO_CHANGE, (tcdm_legacy_base + PRCM_REQ_MB1_ARM_OPP));
 	writeb(((opp == APE_50_PARTLY_25_OPP) ? APE_50_OPP : opp),
-		(tcdm_base + PRCM_REQ_MB1_APE_OPP));
+		(tcdm_legacy_base + PRCM_REQ_MB1_APE_OPP));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
@@ -1160,7 +1163,7 @@ skip_message:
  */
 int db8500_prcmu_get_ape_opp(void)
 {
-	return readb(tcdm_base + PRCM_ACK_MB1_CURRENT_APE_OPP);
+	return readb(tcdm_legacy_base + PRCM_ACK_MB1_CURRENT_APE_OPP);
 }
 
 /**
@@ -1194,7 +1197,7 @@ int prcmu_request_ape_opp_100_voltage(bool enable)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
-	writeb(header, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+	writeb(header, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
@@ -1224,7 +1227,7 @@ int prcmu_release_usb_wakeup_state(void)
 		cpu_relax();
 
 	writeb(MB1H_RELEASE_USB_WAKEUP,
-		(tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+		(tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
@@ -1254,8 +1257,8 @@ static int request_pll(u8 clock, bool enable)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
-	writeb(MB1H_PLL_ON_OFF, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
-	writeb(clock, (tcdm_base + PRCM_REQ_MB1_PLL_ON_OFF));
+	writeb(MB1H_PLL_ON_OFF, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
+	writeb(clock, (tcdm_legacy_base + PRCM_REQ_MB1_PLL_ON_OFF));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
@@ -1308,10 +1311,11 @@ int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 
 	/* fill in mailbox */
 	for (i = 0; i < NUM_EPOD_ID; i++)
-		writeb(EPOD_STATE_NO_CHANGE, (tcdm_base + PRCM_REQ_MB2 + i));
-	writeb(epod_state, (tcdm_base + PRCM_REQ_MB2 + epod_id));
+		writeb(EPOD_STATE_NO_CHANGE,
+				tcdm_legacy_base + PRCM_REQ_MB2 + i);
+	writeb(epod_state, (tcdm_legacy_base + PRCM_REQ_MB2 + epod_id));
 
-	writeb(MB2H_DPS, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB2));
+	writeb(MB2H_DPS, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB2));
 
 	writel(MBOX_BIT(2), PRCM_MBOX_CPU_SET);
 
@@ -1371,8 +1375,8 @@ void prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	 * fields in mailbox 2, but these fields are only used as shared
 	 * variables - i.e. there is no need to send a message.
 	 */
-	writel(sleep_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_SLEEP));
-	writel(idle_cfg, (tcdm_base + PRCM_REQ_MB2_AUTO_PM_IDLE));
+	writel(sleep_cfg, (tcdm_legacy_base + PRCM_REQ_MB2_AUTO_PM_SLEEP));
+	writel(idle_cfg, (tcdm_legacy_base + PRCM_REQ_MB2_AUTO_PM_IDLE));
 
 	mb2_transfer.auto_pm_enabled =
 		((sleep->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
@@ -1403,9 +1407,9 @@ static int request_sysclk(bool enable)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
 		cpu_relax();
 
-	writeb((enable ? ON : OFF), (tcdm_base + PRCM_REQ_MB3_SYSCLK_MGT));
+	writeb((enable ? ON : OFF), tcdm_legacy_base + PRCM_REQ_MB3_SYSCLK_MGT);
 
-	writeb(MB3H_SYSCLK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB3));
+	writeb(MB3H_SYSCLK, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB3));
 	writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
 
 	spin_unlock_irqrestore(&mb3_transfer.lock, flags);
@@ -2009,12 +2013,12 @@ int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
-	writeb(MB4H_MEM_ST, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+	writeb(MB4H_MEM_ST, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 	writeb(((DDR_PWR_STATE_OFFHIGHLAT << 4) | DDR_PWR_STATE_ON),
-	       (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE));
+	       (tcdm_legacy_base + PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE));
 	writeb(DDR_PWR_STATE_ON,
-	       (tcdm_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE));
-	writeb(state, (tcdm_base + PRCM_REQ_MB4_ESRAM0_ST));
+	       (tcdm_legacy_base + PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE));
+	writeb(state, (tcdm_legacy_base + PRCM_REQ_MB4_ESRAM0_ST));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
@@ -2031,8 +2035,8 @@ int db8500_prcmu_config_hotdog(u8 threshold)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
-	writeb(threshold, (tcdm_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD));
-	writeb(MB4H_HOTDOG, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+	writeb(threshold, (tcdm_legacy_base + PRCM_REQ_MB4_HOTDOG_THRESHOLD));
+	writeb(MB4H_HOTDOG, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
@@ -2049,11 +2053,11 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
-	writeb(low, (tcdm_base + PRCM_REQ_MB4_HOTMON_LOW));
-	writeb(high, (tcdm_base + PRCM_REQ_MB4_HOTMON_HIGH));
+	writeb(low, (tcdm_legacy_base + PRCM_REQ_MB4_HOTMON_LOW));
+	writeb(high, (tcdm_legacy_base + PRCM_REQ_MB4_HOTMON_HIGH));
 	writeb((HOTMON_CONFIG_LOW | HOTMON_CONFIG_HIGH),
-		(tcdm_base + PRCM_REQ_MB4_HOTMON_CONFIG));
-	writeb(MB4H_HOTMON, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+		(tcdm_legacy_base + PRCM_REQ_MB4_HOTMON_CONFIG));
+	writeb(MB4H_HOTMON, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
@@ -2070,8 +2074,8 @@ static int config_hot_period(u16 val)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
-	writew(val, (tcdm_base + PRCM_REQ_MB4_HOT_PERIOD));
-	writeb(MB4H_HOT_PERIOD, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+	writew(val, (tcdm_legacy_base + PRCM_REQ_MB4_HOT_PERIOD));
+	writeb(MB4H_HOT_PERIOD, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
@@ -2102,12 +2106,12 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
 
-	writeb(d0, (tcdm_base + PRCM_REQ_MB4_A9WDOG_0));
-	writeb(d1, (tcdm_base + PRCM_REQ_MB4_A9WDOG_1));
-	writeb(d2, (tcdm_base + PRCM_REQ_MB4_A9WDOG_2));
-	writeb(d3, (tcdm_base + PRCM_REQ_MB4_A9WDOG_3));
+	writeb(d0, (tcdm_legacy_base + PRCM_REQ_MB4_A9WDOG_0));
+	writeb(d1, (tcdm_legacy_base + PRCM_REQ_MB4_A9WDOG_1));
+	writeb(d2, (tcdm_legacy_base + PRCM_REQ_MB4_A9WDOG_2));
+	writeb(d3, (tcdm_legacy_base + PRCM_REQ_MB4_A9WDOG_3));
 
-	writeb(cmd, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB4));
+	writeb(cmd, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb4_transfer.work);
@@ -2180,11 +2184,12 @@ int prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
 
-	writeb(0, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5));
-	writeb(PRCMU_I2C_READ(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
-	writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
-	writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
-	writeb(0, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
+	writeb(0, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB5));
+	writeb(PRCMU_I2C_READ(slave),
+			tcdm_legacy_base + PRCM_REQ_MB5_I2C_SLAVE_OP);
+	writeb(PRCMU_I2C_STOP_EN, tcdm_legacy_base + PRCM_REQ_MB5_I2C_HW_BITS);
+	writeb(reg, (tcdm_legacy_base + PRCM_REQ_MB5_I2C_REG));
+	writeb(0, (tcdm_legacy_base + PRCM_REQ_MB5_I2C_VAL));
 
 	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
@@ -2230,11 +2235,12 @@ int prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
 
-	writeb(~*mask, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB5));
-	writeb(PRCMU_I2C_WRITE(slave), (tcdm_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
-	writeb(PRCMU_I2C_STOP_EN, (tcdm_base + PRCM_REQ_MB5_I2C_HW_BITS));
-	writeb(reg, (tcdm_base + PRCM_REQ_MB5_I2C_REG));
-	writeb(*value, (tcdm_base + PRCM_REQ_MB5_I2C_VAL));
+	writeb(~*mask, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB5));
+	writeb(PRCMU_I2C_WRITE(slave),
+			(tcdm_legacy_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
+	writeb(PRCMU_I2C_STOP_EN, tcdm_legacy_base + PRCM_REQ_MB5_I2C_HW_BITS);
+	writeb(reg, (tcdm_legacy_base + PRCM_REQ_MB5_I2C_REG));
+	writeb(*value, (tcdm_legacy_base + PRCM_REQ_MB5_I2C_VAL));
 
 	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
@@ -2354,7 +2360,7 @@ bool db8500_prcmu_is_ac_wake_requested(void)
  */
 void db8500_prcmu_system_reset(u16 reset_code)
 {
-	writew(reset_code, (tcdm_base + PRCM_SW_RST_REASON));
+	writew(reset_code, (tcdm_legacy_base + PRCM_SW_RST_REASON));
 	writel(1, PRCM_APE_SOFTRST);
 }
 
@@ -2366,7 +2372,7 @@ void db8500_prcmu_system_reset(u16 reset_code)
  */
 u16 db8500_prcmu_get_reset_code(void)
 {
-	return readw(tcdm_base + PRCM_SW_RST_REASON);
+	return readw(tcdm_legacy_base + PRCM_SW_RST_REASON);
 }
 
 /**
@@ -2379,7 +2385,7 @@ void db8500_prcmu_modem_reset(void)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
-	writeb(MB1H_RESET_MODEM, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB1));
+	writeb(MB1H_RESET_MODEM, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
 	wait_for_completion(&mb1_transfer.work);
 
@@ -2400,7 +2406,8 @@ static void ack_dbb_wakeup(void)
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
 
-	writeb(MB0H_READ_WAKEUP_ACK, (tcdm_base + PRCM_MBOX_HEADER_REQ_MB0));
+	writeb(MB0H_READ_WAKEUP_ACK,
+			tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB0);
 	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
 	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
@@ -2419,14 +2426,16 @@ static bool read_mailbox_0(void)
 	unsigned int n;
 	u8 header;
 
-	header = readb(tcdm_base + PRCM_MBOX_HEADER_ACK_MB0);
+	header = readb(tcdm_legacy_base + PRCM_MBOX_HEADER_ACK_MB0);
 	switch (header) {
 	case MB0H_WAKEUP_EXE:
 	case MB0H_WAKEUP_SLEEP:
-		if (readb(tcdm_base + PRCM_ACK_MB0_READ_POINTER) & 1)
-			ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_1_8500);
+		if (readb(tcdm_legacy_base + PRCM_ACK_MB0_READ_POINTER) & 1)
+			ev = readl(tcdm_legacy_base +
+					PRCM_ACK_MB0_WAKEUP_1_8500);
 		else
-			ev = readl(tcdm_base + PRCM_ACK_MB0_WAKEUP_0_8500);
+			ev = readl(tcdm_legacy_base +
+					PRCM_ACK_MB0_WAKEUP_0_8500);
 
 		if (ev & (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK))
 			complete(&mb0_transfer.ac_wake_work);
@@ -2452,12 +2461,13 @@ static bool read_mailbox_0(void)
 
 static bool read_mailbox_1(void)
 {
-	mb1_transfer.ack.header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB1);
-	mb1_transfer.ack.arm_opp = readb(tcdm_base +
+	mb1_transfer.ack.header = readb(tcdm_legacy_base +
+			PRCM_MBOX_HEADER_REQ_MB1);
+	mb1_transfer.ack.arm_opp = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_CURRENT_ARM_OPP);
-	mb1_transfer.ack.ape_opp = readb(tcdm_base +
+	mb1_transfer.ack.ape_opp = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_CURRENT_APE_OPP);
-	mb1_transfer.ack.ape_voltage_status = readb(tcdm_base +
+	mb1_transfer.ack.ape_voltage_status = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_APE_VOLTAGE_STATUS);
 	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
 	complete(&mb1_transfer.work);
@@ -2466,7 +2476,8 @@ static bool read_mailbox_1(void)
 
 static bool read_mailbox_2(void)
 {
-	mb2_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB2_DPS_STATUS);
+	mb2_transfer.ack.status = readb(tcdm_legacy_base
+			+ PRCM_ACK_MB2_DPS_STATUS);
 	writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
 	complete(&mb2_transfer.work);
 	return false;
@@ -2483,7 +2494,7 @@ static bool read_mailbox_4(void)
 	u8 header;
 	bool do_complete = true;
 
-	header = readb(tcdm_base + PRCM_MBOX_HEADER_REQ_MB4);
+	header = readb(tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4);
 	switch (header) {
 	case MB4H_MEM_ST:
 	case MB4H_HOTDOG:
@@ -2511,8 +2522,9 @@ static bool read_mailbox_4(void)
 
 static bool read_mailbox_5(void)
 {
-	mb5_transfer.ack.status = readb(tcdm_base + PRCM_ACK_MB5_I2C_STATUS);
-	mb5_transfer.ack.value = readb(tcdm_base + PRCM_ACK_MB5_I2C_VAL);
+	mb5_transfer.ack.status = readb(tcdm_legacy_base
+			+ PRCM_ACK_MB5_I2C_STATUS);
+	mb5_transfer.ack.value = readb(tcdm_legacy_base + PRCM_ACK_MB5_I2C_VAL);
 	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
 	complete(&mb5_transfer.work);
 	return false;
@@ -2670,29 +2682,24 @@ static int db8500_irq_init(struct device_node *np)
 
 void __init db8500_prcmu_early_init(struct prcmu_tcdm_map *map)
 {
-	if (cpu_is_u8500v2()) {
 		void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
 
-		if (tcpm_base != NULL) {
-			u32 version;
-			version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET);
-			fw_info.version.project = version & 0xFF;
-			fw_info.version.api_version = (version >> 8) & 0xFF;
-			fw_info.version.func_version = (version >> 16) & 0xFF;
-			fw_info.version.errata = (version >> 24) & 0xFF;
-			fw_info.valid = true;
-			pr_info("PRCMU firmware: %s, version %d.%d.%d\n",
-				fw_project_name(fw_info.version.project),
-				(version >> 8) & 0xFF, (version >> 16) & 0xFF,
-				(version >> 24) & 0xFF);
-			iounmap(tcpm_base);
-		}
-
-		tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE);
-	} else {
-		pr_err("prcmu: Unsupported chip version\n");
-		BUG();
+	if (tcpm_base != NULL) {
+		u32 version;
+		version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET);
+		fw_info.version.project = version & 0xFF;
+		fw_info.version.api_version = (version >> 8) & 0xFF;
+		fw_info.version.func_version = (version >> 16) & 0xFF;
+		fw_info.version.errata = (version >> 24) & 0xFF;
+		fw_info.valid = true;
+		pr_info("PRCMU firmware: %s, version %d.%d.%d\n",
+			fw_project_name(fw_info.version.project),
+			(version >> 8) & 0xFF, (version >> 16) & 0xFF,
+			(version >> 24) & 0xFF);
+		iounmap(tcpm_base);
 	}
+	tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE, map->tcdm_size);
+	tcdm_legacy_base = tcdm_base + map->legacy_offset;
 
 	spin_lock_init(&mb0_transfer.lock);
 	spin_lock_init(&mb0_transfer.dbb_irqs_lock);
-- 
1.7.11.1


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

* [PATCH 08/17] arm: ux500: update DB internal irq nb
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (6 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 07/17] mfd: prcmu: configurable tcdm base address Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 09/17] mfd: prcmu: add db9540 support Loic Pallardy
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

To support DB9540 chipset, nb internal irq must be updated.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/include/mach/irqs.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mach-ux500/include/mach/irqs.h b/arch/arm/mach-ux500/include/mach/irqs.h
index fc77b42..c1a6908 100644
--- a/arch/arm/mach-ux500/include/mach/irqs.h
+++ b/arch/arm/mach-ux500/include/mach/irqs.h
@@ -24,7 +24,7 @@
  */
 #define IRQ_MTU0		(IRQ_SHPI_START + 4)
 
-#define DBX500_NR_INTERNAL_IRQS		166
+#define DBX500_NR_INTERNAL_IRQS		(IRQ_SHPI_START + 224)
 
 /* After chip-specific IRQ numbers we have the GPIO ones */
 #define NOMADIK_NR_GPIO			288
-- 
1.7.11.1


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

* [PATCH 09/17] mfd: prcmu: add db9540 support
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (7 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 08/17] arm: ux500: update DB internal irq nb Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 10/17] mfd: prcmu: dbx500-prmcu creation Loic Pallardy
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

Light modifications to add db9540 support
and ab9540 detection.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/db8500-prcmu.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 3df427f..eb327f3 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2994,6 +2994,23 @@ static struct mfd_cell db8500_prcmu_devs[] = {
 	},
 };
 
+static struct mfd_cell db9540_prcmu_devs[] = {
+	{
+		.name = "db8500-prcmu-regulators",
+		.of_compatible = "stericsson,db8500-prcmu-regulator",
+		.platform_data = &db8500_regulators,
+		.pdata_size = sizeof(db8500_regulators),
+	},
+	{
+		.name = "ab9540-i2c",
+		.of_compatible = "stericsson,ab8500",
+		.num_resources = ARRAY_SIZE(ab8500_resources),
+		.resources = ab8500_resources,
+		.id = AB8500_VERSION_AB9540,
+	},
+};
+
+
 /**
  * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
  *
@@ -3035,11 +3052,16 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (cpu_is_u8500v20_or_later())
+	if (cpu_is_u8500v20_or_later() && !cpu_is_u9540())
 		prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
 
-	err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
+	if (cpu_is_u9540())
+			err = mfd_add_devices(&pdev->dev, 0, db9540_prcmu_devs,
+			ARRAY_SIZE(db9540_prcmu_devs), NULL, 0);
+	else
+		err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
 			ARRAY_SIZE(db8500_prcmu_devs), NULL, 0);
+
 	if (err) {
 		pr_err("prcmu: Failed to add subdevices\n");
 		return err;
-- 
1.7.11.1


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

* [PATCH 10/17] mfd: prcmu: dbx500-prmcu creation
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (8 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 09/17] mfd: prcmu: add db9540 support Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 11/17] mfd: pcrmu: create common header file for legacy mailbox Loic Pallardy
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Michel JAOUEN,
	Loic Pallardy

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@stericsson.com>
Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@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@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@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


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

* [PATCH 11/17] mfd: pcrmu: create common header file for legacy mailbox
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (9 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 10/17] mfd: prcmu: dbx500-prmcu creation Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 12/17] mfd: prcmu: make fw_project_name generic Loic Pallardy
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

Legacy mailbox are used by both 8500 and x540 projects.
Structure and definition should be shared to avoid misalignment.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/db8500-prcmu.c | 576 +++++++++++----------------------------------
 drivers/mfd/dbx500-prcmu.h | 378 +++++++++++++++++++++++++++++
 2 files changed, 518 insertions(+), 436 deletions(-)
 create mode 100644 drivers/mfd/dbx500-prcmu.h

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 36f7c1d..96487a0 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -36,6 +36,7 @@
 #include <mach/irqs.h>
 #include <mach/db8500-regs.h>
 #include <mach/id.h>
+#include "dbx500-prcmu.h"
 #include "dbx500-prcmu-regs.h"
 
 /* Offset for the firmware version within the TCPM */
@@ -69,202 +70,6 @@
 #define PRCM_ROMCODE_P2A	0xFFD
 #define PRCM_XP70_CUR_PWR_STATE 0xFFC      /* 4 BYTES */
 
-#define PRCM_SW_RST_REASON 0xFF8 /* 2 bytes */
-
-#define _PRCM_MBOX_HEADER		0xFE8 /* 16 bytes */
-#define PRCM_MBOX_HEADER_REQ_MB0	(_PRCM_MBOX_HEADER + 0x0)
-#define PRCM_MBOX_HEADER_REQ_MB1	(_PRCM_MBOX_HEADER + 0x1)
-#define PRCM_MBOX_HEADER_REQ_MB2	(_PRCM_MBOX_HEADER + 0x2)
-#define PRCM_MBOX_HEADER_REQ_MB3	(_PRCM_MBOX_HEADER + 0x3)
-#define PRCM_MBOX_HEADER_REQ_MB4	(_PRCM_MBOX_HEADER + 0x4)
-#define PRCM_MBOX_HEADER_REQ_MB5	(_PRCM_MBOX_HEADER + 0x5)
-#define PRCM_MBOX_HEADER_ACK_MB0	(_PRCM_MBOX_HEADER + 0x8)
-
-/* Req Mailboxes */
-#define PRCM_REQ_MB0 0xFDC /* 12 bytes  */
-#define PRCM_REQ_MB1 0xFD0 /* 12 bytes  */
-#define PRCM_REQ_MB2 0xFC0 /* 16 bytes  */
-#define PRCM_REQ_MB3 0xE4C /* 372 bytes  */
-#define PRCM_REQ_MB4 0xE48 /* 4 bytes  */
-#define PRCM_REQ_MB5 0xE44 /* 4 bytes  */
-
-/* Ack Mailboxes */
-#define PRCM_ACK_MB0 0xE08 /* 52 bytes  */
-#define PRCM_ACK_MB1 0xE04 /* 4 bytes */
-#define PRCM_ACK_MB2 0xE00 /* 4 bytes */
-#define PRCM_ACK_MB3 0xDFC /* 4 bytes */
-#define PRCM_ACK_MB4 0xDF8 /* 4 bytes */
-#define PRCM_ACK_MB5 0xDF4 /* 4 bytes */
-
-/* Mailbox 0 headers */
-#define MB0H_POWER_STATE_TRANS		0
-#define MB0H_CONFIG_WAKEUPS_EXE		1
-#define MB0H_READ_WAKEUP_ACK		3
-#define MB0H_CONFIG_WAKEUPS_SLEEP	4
-
-#define MB0H_WAKEUP_EXE 2
-#define MB0H_WAKEUP_SLEEP 5
-
-/* Mailbox 0 REQs */
-#define PRCM_REQ_MB0_AP_POWER_STATE	(PRCM_REQ_MB0 + 0x0)
-#define PRCM_REQ_MB0_AP_PLL_STATE	(PRCM_REQ_MB0 + 0x1)
-#define PRCM_REQ_MB0_ULP_CLOCK_STATE	(PRCM_REQ_MB0 + 0x2)
-#define PRCM_REQ_MB0_DO_NOT_WFI		(PRCM_REQ_MB0 + 0x3)
-#define PRCM_REQ_MB0_WAKEUP_8500	(PRCM_REQ_MB0 + 0x4)
-#define PRCM_REQ_MB0_WAKEUP_4500	(PRCM_REQ_MB0 + 0x8)
-
-/* Mailbox 0 ACKs */
-#define PRCM_ACK_MB0_AP_PWRSTTR_STATUS	(PRCM_ACK_MB0 + 0x0)
-#define PRCM_ACK_MB0_READ_POINTER	(PRCM_ACK_MB0 + 0x1)
-#define PRCM_ACK_MB0_WAKEUP_0_8500	(PRCM_ACK_MB0 + 0x4)
-#define PRCM_ACK_MB0_WAKEUP_0_4500	(PRCM_ACK_MB0 + 0x8)
-#define PRCM_ACK_MB0_WAKEUP_1_8500	(PRCM_ACK_MB0 + 0x1C)
-#define PRCM_ACK_MB0_WAKEUP_1_4500	(PRCM_ACK_MB0 + 0x20)
-#define PRCM_ACK_MB0_EVENT_4500_NUMBERS	20
-
-/* Mailbox 1 headers */
-#define MB1H_ARM_APE_OPP 0x0
-#define MB1H_RESET_MODEM 0x2
-#define MB1H_REQUEST_APE_OPP_100_VOLT 0x3
-#define MB1H_RELEASE_APE_OPP_100_VOLT 0x4
-#define MB1H_RELEASE_USB_WAKEUP 0x5
-#define MB1H_PLL_ON_OFF 0x6
-
-/* Mailbox 1 Requests */
-#define PRCM_REQ_MB1_ARM_OPP			(PRCM_REQ_MB1 + 0x0)
-#define PRCM_REQ_MB1_APE_OPP			(PRCM_REQ_MB1 + 0x1)
-#define PRCM_REQ_MB1_PLL_ON_OFF			(PRCM_REQ_MB1 + 0x4)
-#define PLL_SOC0_OFF	0x1
-#define PLL_SOC0_ON	0x2
-#define PLL_SOC1_OFF	0x4
-#define PLL_SOC1_ON	0x8
-
-/* Mailbox 1 ACKs */
-#define PRCM_ACK_MB1_CURRENT_ARM_OPP	(PRCM_ACK_MB1 + 0x0)
-#define PRCM_ACK_MB1_CURRENT_APE_OPP	(PRCM_ACK_MB1 + 0x1)
-#define PRCM_ACK_MB1_APE_VOLTAGE_STATUS	(PRCM_ACK_MB1 + 0x2)
-#define PRCM_ACK_MB1_DVFS_STATUS	(PRCM_ACK_MB1 + 0x3)
-
-/* Mailbox 2 headers */
-#define MB2H_DPS	0x0
-#define MB2H_AUTO_PWR	0x1
-
-/* Mailbox 2 REQs */
-#define PRCM_REQ_MB2_SVA_MMDSP		(PRCM_REQ_MB2 + 0x0)
-#define PRCM_REQ_MB2_SVA_PIPE		(PRCM_REQ_MB2 + 0x1)
-#define PRCM_REQ_MB2_SIA_MMDSP		(PRCM_REQ_MB2 + 0x2)
-#define PRCM_REQ_MB2_SIA_PIPE		(PRCM_REQ_MB2 + 0x3)
-#define PRCM_REQ_MB2_SGA		(PRCM_REQ_MB2 + 0x4)
-#define PRCM_REQ_MB2_B2R2_MCDE		(PRCM_REQ_MB2 + 0x5)
-#define PRCM_REQ_MB2_ESRAM12		(PRCM_REQ_MB2 + 0x6)
-#define PRCM_REQ_MB2_ESRAM34		(PRCM_REQ_MB2 + 0x7)
-#define PRCM_REQ_MB2_AUTO_PM_SLEEP	(PRCM_REQ_MB2 + 0x8)
-#define PRCM_REQ_MB2_AUTO_PM_IDLE	(PRCM_REQ_MB2 + 0xC)
-
-/* Mailbox 2 ACKs */
-#define PRCM_ACK_MB2_DPS_STATUS (PRCM_ACK_MB2 + 0x0)
-#define HWACC_PWR_ST_OK 0xFE
-
-/* Mailbox 3 headers */
-#define MB3H_ANC	0x0
-#define MB3H_SIDETONE	0x1
-#define MB3H_SYSCLK	0xE
-
-/* Mailbox 3 Requests */
-#define PRCM_REQ_MB3_ANC_FIR_COEFF	(PRCM_REQ_MB3 + 0x0)
-#define PRCM_REQ_MB3_ANC_IIR_COEFF	(PRCM_REQ_MB3 + 0x20)
-#define PRCM_REQ_MB3_ANC_SHIFTER	(PRCM_REQ_MB3 + 0x60)
-#define PRCM_REQ_MB3_ANC_WARP		(PRCM_REQ_MB3 + 0x64)
-#define PRCM_REQ_MB3_SIDETONE_FIR_GAIN	(PRCM_REQ_MB3 + 0x68)
-#define PRCM_REQ_MB3_SIDETONE_FIR_COEFF	(PRCM_REQ_MB3 + 0x6C)
-#define PRCM_REQ_MB3_SYSCLK_MGT		(PRCM_REQ_MB3 + 0x16C)
-
-/* Mailbox 4 headers */
-#define MB4H_DDR_INIT	0x0
-#define MB4H_MEM_ST	0x1
-#define MB4H_HOTDOG	0x12
-#define MB4H_HOTMON	0x13
-#define MB4H_HOT_PERIOD	0x14
-#define MB4H_A9WDOG_CONF 0x16
-#define MB4H_A9WDOG_EN   0x17
-#define MB4H_A9WDOG_DIS  0x18
-#define MB4H_A9WDOG_LOAD 0x19
-#define MB4H_A9WDOG_KICK 0x20
-
-/* Mailbox 4 Requests */
-#define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE	(PRCM_REQ_MB4 + 0x0)
-#define PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE	(PRCM_REQ_MB4 + 0x1)
-#define PRCM_REQ_MB4_ESRAM0_ST			(PRCM_REQ_MB4 + 0x3)
-#define PRCM_REQ_MB4_HOTDOG_THRESHOLD		(PRCM_REQ_MB4 + 0x0)
-#define PRCM_REQ_MB4_HOTMON_LOW			(PRCM_REQ_MB4 + 0x0)
-#define PRCM_REQ_MB4_HOTMON_HIGH		(PRCM_REQ_MB4 + 0x1)
-#define PRCM_REQ_MB4_HOTMON_CONFIG		(PRCM_REQ_MB4 + 0x2)
-#define PRCM_REQ_MB4_HOT_PERIOD			(PRCM_REQ_MB4 + 0x0)
-#define HOTMON_CONFIG_LOW			BIT(0)
-#define HOTMON_CONFIG_HIGH			BIT(1)
-#define PRCM_REQ_MB4_A9WDOG_0			(PRCM_REQ_MB4 + 0x0)
-#define PRCM_REQ_MB4_A9WDOG_1			(PRCM_REQ_MB4 + 0x1)
-#define PRCM_REQ_MB4_A9WDOG_2			(PRCM_REQ_MB4 + 0x2)
-#define PRCM_REQ_MB4_A9WDOG_3			(PRCM_REQ_MB4 + 0x3)
-#define A9WDOG_AUTO_OFF_EN			BIT(7)
-#define A9WDOG_AUTO_OFF_DIS			0
-#define A9WDOG_ID_MASK				0xf
-
-/* Mailbox 5 Requests */
-#define PRCM_REQ_MB5_I2C_SLAVE_OP	(PRCM_REQ_MB5 + 0x0)
-#define PRCM_REQ_MB5_I2C_HW_BITS	(PRCM_REQ_MB5 + 0x1)
-#define PRCM_REQ_MB5_I2C_REG		(PRCM_REQ_MB5 + 0x2)
-#define PRCM_REQ_MB5_I2C_VAL		(PRCM_REQ_MB5 + 0x3)
-#define PRCMU_I2C_WRITE(slave) \
-	(((slave) << 1) | (cpu_is_u8500v2() ? BIT(6) : 0))
-#define PRCMU_I2C_READ(slave) \
-	(((slave) << 1) | BIT(0) | (cpu_is_u8500v2() ? BIT(6) : 0))
-#define PRCMU_I2C_STOP_EN		BIT(3)
-
-/* Mailbox 5 ACKs */
-#define PRCM_ACK_MB5_I2C_STATUS	(PRCM_ACK_MB5 + 0x1)
-#define PRCM_ACK_MB5_I2C_VAL	(PRCM_ACK_MB5 + 0x3)
-#define I2C_WR_OK 0x1
-#define I2C_RD_OK 0x2
-
-#define NUM_MB 8
-#define MBOX_BIT BIT
-#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
-
-/*
- * Wakeups/IRQs
- */
-
-#define WAKEUP_BIT_RTC BIT(0)
-#define WAKEUP_BIT_RTT0 BIT(1)
-#define WAKEUP_BIT_RTT1 BIT(2)
-#define WAKEUP_BIT_HSI0 BIT(3)
-#define WAKEUP_BIT_HSI1 BIT(4)
-#define WAKEUP_BIT_CA_WAKE BIT(5)
-#define WAKEUP_BIT_USB BIT(6)
-#define WAKEUP_BIT_ABB BIT(7)
-#define WAKEUP_BIT_ABB_FIFO BIT(8)
-#define WAKEUP_BIT_SYSCLK_OK BIT(9)
-#define WAKEUP_BIT_CA_SLEEP BIT(10)
-#define WAKEUP_BIT_AC_WAKE_ACK BIT(11)
-#define WAKEUP_BIT_SIDE_TONE_OK BIT(12)
-#define WAKEUP_BIT_ANC_OK BIT(13)
-#define WAKEUP_BIT_SW_ERROR BIT(14)
-#define WAKEUP_BIT_AC_SLEEP_ACK BIT(15)
-#define WAKEUP_BIT_ARM BIT(17)
-#define WAKEUP_BIT_HOTMON_LOW BIT(18)
-#define WAKEUP_BIT_HOTMON_HIGH BIT(19)
-#define WAKEUP_BIT_MODEM_SW_RESET_REQ BIT(20)
-#define WAKEUP_BIT_GPIO0 BIT(23)
-#define WAKEUP_BIT_GPIO1 BIT(24)
-#define WAKEUP_BIT_GPIO2 BIT(25)
-#define WAKEUP_BIT_GPIO3 BIT(26)
-#define WAKEUP_BIT_GPIO4 BIT(27)
-#define WAKEUP_BIT_GPIO5 BIT(28)
-#define WAKEUP_BIT_GPIO6 BIT(29)
-#define WAKEUP_BIT_GPIO7 BIT(30)
-#define WAKEUP_BIT_GPIO8 BIT(31)
-
 static struct {
 	bool valid;
 	struct prcmu_fw_version version;
@@ -322,102 +127,6 @@ static u32 prcmu_wakeup_bit[NUM_PRCMU_WAKEUP_INDICES] = {
 	WAKEUP_ENTRY(ARM)
 };
 
-/*
- * mb0_transfer - state needed for mailbox 0 communication.
- * @lock:		The transaction lock.
- * @dbb_events_lock:	A lock used to handle concurrent access to (parts of)
- *			the request data.
- * @mask_work:		Work structure used for (un)masking wakeup interrupts.
- * @req:		Request data that need to persist between requests.
- */
-static struct {
-	spinlock_t lock;
-	spinlock_t dbb_irqs_lock;
-	struct work_struct mask_work;
-	struct mutex ac_wake_lock;
-	struct completion ac_wake_work;
-	struct {
-		u32 dbb_irqs;
-		u32 dbb_wakeups;
-		u32 abb_events;
-	} req;
-} mb0_transfer;
-
-/*
- * mb1_transfer - state needed for mailbox 1 communication.
- * @lock:	The transaction lock.
- * @work:	The transaction completion structure.
- * @ape_opp:	The current APE OPP.
- * @ack:	Reply ("acknowledge") data.
- */
-static struct {
-	struct mutex lock;
-	struct completion work;
-	u8 ape_opp;
-	struct {
-		u8 header;
-		u8 arm_opp;
-		u8 ape_opp;
-		u8 ape_voltage_status;
-	} ack;
-} mb1_transfer;
-
-/*
- * mb2_transfer - state needed for mailbox 2 communication.
- * @lock:            The transaction lock.
- * @work:            The transaction completion structure.
- * @auto_pm_lock:    The autonomous power management configuration lock.
- * @auto_pm_enabled: A flag indicating whether autonomous PM is enabled.
- * @req:             Request data that need to persist between requests.
- * @ack:             Reply ("acknowledge") data.
- */
-static struct {
-	struct mutex lock;
-	struct completion work;
-	spinlock_t auto_pm_lock;
-	bool auto_pm_enabled;
-	struct {
-		u8 status;
-	} ack;
-} mb2_transfer;
-
-/*
- * mb3_transfer - state needed for mailbox 3 communication.
- * @lock:		The request lock.
- * @sysclk_lock:	A lock used to handle concurrent sysclk requests.
- * @sysclk_work:	Work structure used for sysclk requests.
- */
-static struct {
-	spinlock_t lock;
-	struct mutex sysclk_lock;
-	struct completion sysclk_work;
-} mb3_transfer;
-
-/*
- * mb4_transfer - state needed for mailbox 4 communication.
- * @lock:	The transaction lock.
- * @work:	The transaction completion structure.
- */
-static struct {
-	struct mutex lock;
-	struct completion work;
-} mb4_transfer;
-
-/*
- * mb5_transfer - state needed for mailbox 5 communication.
- * @lock:	The transaction lock.
- * @work:	The transaction completion structure.
- * @ack:	Reply ("acknowledge") data.
- */
-static struct {
-	struct mutex lock;
-	struct completion work;
-	struct {
-		u8 status;
-		u8 value;
-	} ack;
-} mb5_transfer;
-
 static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
 
 /* Spinlocks */
@@ -428,18 +137,13 @@ static DEFINE_SPINLOCK(clkout_lock);
 static __iomem void *tcdm_legacy_base;
 static __iomem void *tcdm_base;
 
-struct clk_mgt {
-	void __iomem *reg;
-	u32 pllsw;
-	int branch;
-	bool clk38div;
-};
-
-enum {
-	PLL_RAW,
-	PLL_FIX,
-	PLL_DIV
-};
+/* mailbox definition */
+static struct mb0_transfer mb0;
+static struct mb1_transfer mb1;
+static struct mb2_transfer mb2;
+static struct mb3_transfer mb3;
+static struct mb4_transfer mb4;
+static struct mb5_transfer mb5;
 
 static DEFINE_SPINLOCK(clk_mgt_lock);
 
@@ -774,7 +478,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 
 	BUG_ON((state < PRCMU_AP_SLEEP) || (PRCMU_AP_DEEP_IDLE < state));
 
-	spin_lock_irqsave(&mb0_transfer.lock, flags);
+	spin_lock_irqsave(&mb0.lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
@@ -789,7 +493,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 	writeb(0, (tcdm_legacy_base + PRCM_REQ_MB0_DO_NOT_WFI));
 	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+	spin_unlock_irqrestore(&mb0.lock, flags);
 
 	return 0;
 }
@@ -912,7 +616,7 @@ int db8500_prcmu_copy_gic_settings(void)
 	return 0;
 }
 
-/* This function should only be called while mb0_transfer.lock is held. */
+/* This function should only be called while mb0.lock is held. */
 static void config_wakeups(void)
 {
 	const u8 header[2] = {
@@ -925,10 +629,10 @@ static void config_wakeups(void)
 	u32 abb_events;
 	unsigned int i;
 
-	dbb_events = mb0_transfer.req.dbb_irqs | mb0_transfer.req.dbb_wakeups;
+	dbb_events = mb0.req.dbb_irqs | mb0.req.dbb_wakeups;
 	dbb_events |= (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK);
 
-	abb_events = mb0_transfer.req.abb_events;
+	abb_events = mb0.req.abb_events;
 
 	if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events))
 		return;
@@ -958,24 +662,24 @@ static void db8500_prcmu_enable_wakeups(u32 wakeups)
 			bits |= prcmu_wakeup_bit[i];
 	}
 
-	spin_lock_irqsave(&mb0_transfer.lock, flags);
+	spin_lock_irqsave(&mb0.lock, flags);
 
-	mb0_transfer.req.dbb_wakeups = bits;
+	mb0.req.dbb_wakeups = bits;
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+	spin_unlock_irqrestore(&mb0.lock, flags);
 }
 
 static void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0_transfer.lock, flags);
+	spin_lock_irqsave(&mb0.lock, flags);
 
-	mb0_transfer.req.abb_events = abb_events;
+	mb0.req.abb_events = abb_events;
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+	spin_unlock_irqrestore(&mb0.lock, flags);
 }
 
 static void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
@@ -1002,7 +706,7 @@ static int db8500_prcmu_set_arm_opp(u8 opp)
 
 	r = 0;
 
-	mutex_lock(&mb1_transfer.lock);
+	mutex_lock(&mb1.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -1012,13 +716,13 @@ static int db8500_prcmu_set_arm_opp(u8 opp)
 	writeb(APE_NO_CHANGE, (tcdm_legacy_base + PRCM_REQ_MB1_APE_OPP));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1_transfer.work);
+	wait_for_completion(&mb1.work);
 
-	if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
-		(mb1_transfer.ack.arm_opp != opp))
+	if ((mb1.ack.header != MB1H_ARM_APE_OPP) ||
+		(mb1.ack.arm_opp != opp))
 		r = -EIO;
 
-	mutex_unlock(&mb1_transfer.lock);
+	mutex_unlock(&mb1.lock);
 
 	return r;
 }
@@ -1118,15 +822,15 @@ static int db8500_prcmu_set_ape_opp(u8 opp)
 {
 	int r = 0;
 
-	if (opp == mb1_transfer.ape_opp)
+	if (opp == mb1.ape_opp)
 		return 0;
 
-	mutex_lock(&mb1_transfer.lock);
+	mutex_lock(&mb1.lock);
 
-	if (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)
+	if (mb1.ape_opp == APE_50_PARTLY_25_OPP)
 		request_even_slower_clocks(false);
 
-	if ((opp != APE_100_OPP) && (mb1_transfer.ape_opp != APE_100_OPP))
+	if ((opp != APE_100_OPP) && (mb1.ape_opp != APE_100_OPP))
 		goto skip_message;
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
@@ -1138,20 +842,20 @@ static int db8500_prcmu_set_ape_opp(u8 opp)
 		(tcdm_legacy_base + PRCM_REQ_MB1_APE_OPP));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1_transfer.work);
+	wait_for_completion(&mb1.work);
 
-	if ((mb1_transfer.ack.header != MB1H_ARM_APE_OPP) ||
-		(mb1_transfer.ack.ape_opp != opp))
+	if ((mb1.ack.header != MB1H_ARM_APE_OPP) ||
+		(mb1.ack.ape_opp != opp))
 		r = -EIO;
 
 skip_message:
 	if ((!r && (opp == APE_50_PARTLY_25_OPP)) ||
-		(r && (mb1_transfer.ape_opp == APE_50_PARTLY_25_OPP)))
+		(r && (mb1.ape_opp == APE_50_PARTLY_25_OPP)))
 		request_even_slower_clocks(true);
 	if (!r)
-		mb1_transfer.ape_opp = opp;
+		mb1.ape_opp = opp;
 
-	mutex_unlock(&mb1_transfer.lock);
+	mutex_unlock(&mb1.lock);
 
 	return r;
 }
@@ -1178,7 +882,7 @@ static int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 	u8 header;
 	static unsigned int requests;
 
-	mutex_lock(&mb1_transfer.lock);
+	mutex_lock(&mb1.lock);
 
 	if (enable) {
 		if (0 != requests++)
@@ -1200,14 +904,14 @@ static int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 	writeb(header, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1_transfer.work);
+	wait_for_completion(&mb1.work);
 
-	if ((mb1_transfer.ack.header != header) ||
-		((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0))
+	if ((mb1.ack.header != header) ||
+		((mb1.ack.ape_voltage_status & BIT(0)) != 0))
 		r = -EIO;
 
 unlock_and_return:
-	mutex_unlock(&mb1_transfer.lock);
+	mutex_unlock(&mb1.lock);
 
 	return r;
 }
@@ -1221,7 +925,7 @@ int prcmu_release_usb_wakeup_state(void)
 {
 	int r = 0;
 
-	mutex_lock(&mb1_transfer.lock);
+	mutex_lock(&mb1.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -1230,13 +934,13 @@ int prcmu_release_usb_wakeup_state(void)
 		(tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1_transfer.work);
+	wait_for_completion(&mb1.work);
 
-	if ((mb1_transfer.ack.header != MB1H_RELEASE_USB_WAKEUP) ||
-		((mb1_transfer.ack.ape_voltage_status & BIT(0)) != 0))
+	if ((mb1.ack.header != MB1H_RELEASE_USB_WAKEUP) ||
+		((mb1.ack.ape_voltage_status & BIT(0)) != 0))
 		r = -EIO;
 
-	mutex_unlock(&mb1_transfer.lock);
+	mutex_unlock(&mb1.lock);
 
 	return r;
 }
@@ -1252,7 +956,7 @@ static int request_pll(u8 clock, bool enable)
 	else
 		return -EINVAL;
 
-	mutex_lock(&mb1_transfer.lock);
+	mutex_lock(&mb1.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -1261,12 +965,12 @@ static int request_pll(u8 clock, bool enable)
 	writeb(clock, (tcdm_legacy_base + PRCM_REQ_MB1_PLL_ON_OFF));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1_transfer.work);
+	wait_for_completion(&mb1.work);
 
-	if (mb1_transfer.ack.header != MB1H_PLL_ON_OFF)
+	if (mb1.ack.header != MB1H_PLL_ON_OFF)
 		r = -EIO;
 
-	mutex_unlock(&mb1_transfer.lock);
+	mutex_unlock(&mb1.lock);
 
 	return r;
 }
@@ -1303,7 +1007,7 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 	BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention);
 
 	/* get lock */
-	mutex_lock(&mb2_transfer.lock);
+	mutex_lock(&mb2.lock);
 
 	/* wait for mailbox */
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
@@ -1324,7 +1028,7 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 	 * and we cannot recover if there is an error.
 	 * This is expected to change when the firmware is updated.
 	 */
-	if (!wait_for_completion_timeout(&mb2_transfer.work,
+	if (!wait_for_completion_timeout(&mb2.work,
 			msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
@@ -1332,11 +1036,11 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 		goto unlock_and_return;
 	}
 
-	if (mb2_transfer.ack.status != HWACC_PWR_ST_OK)
+	if (mb2.ack.status != HWACC_PWR_ST_OK)
 		r = -EIO;
 
 unlock_and_return:
-	mutex_unlock(&mb2_transfer.lock);
+	mutex_unlock(&mb2.lock);
 	return r;
 }
 
@@ -1368,7 +1072,7 @@ static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	idle_cfg = ((idle_cfg << 4) | (idle->sva_policy & 0xF));
 	idle_cfg = ((idle_cfg << 4) | (idle->sia_policy & 0xF));
 
-	spin_lock_irqsave(&mb2_transfer.auto_pm_lock, flags);
+	spin_lock_irqsave(&mb2.auto_pm_lock, flags);
 
 	/*
 	 * The autonomous power management configuration is done through
@@ -1378,18 +1082,18 @@ static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	writel(sleep_cfg, (tcdm_legacy_base + PRCM_REQ_MB2_AUTO_PM_SLEEP));
 	writel(idle_cfg, (tcdm_legacy_base + PRCM_REQ_MB2_AUTO_PM_IDLE));
 
-	mb2_transfer.auto_pm_enabled =
+	mb2.auto_pm_enabled =
 		((sleep->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (sleep->sia_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (idle->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (idle->sia_auto_pm_enable == PRCMU_AUTO_PM_ON));
 
-	spin_unlock_irqrestore(&mb2_transfer.auto_pm_lock, flags);
+	spin_unlock_irqrestore(&mb2.auto_pm_lock, flags);
 }
 
 bool prcmu_is_auto_pm_enabled(void)
 {
-	return mb2_transfer.auto_pm_enabled;
+	return mb2.auto_pm_enabled;
 }
 
 static int request_sysclk(bool enable)
@@ -1399,9 +1103,9 @@ static int request_sysclk(bool enable)
 
 	r = 0;
 
-	mutex_lock(&mb3_transfer.sysclk_lock);
+	mutex_lock(&mb3.sysclk_lock);
 
-	spin_lock_irqsave(&mb3_transfer.lock, flags);
+	spin_lock_irqsave(&mb3.lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
 		cpu_relax();
@@ -1411,20 +1115,20 @@ static int request_sysclk(bool enable)
 	writeb(MB3H_SYSCLK, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB3));
 	writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb3_transfer.lock, flags);
+	spin_unlock_irqrestore(&mb3.lock, flags);
 
 	/*
 	 * The firmware only sends an ACK if we want to enable the
 	 * SysClk, and it succeeds.
 	 */
-	if (enable && !wait_for_completion_timeout(&mb3_transfer.sysclk_work,
+	if (enable && !wait_for_completion_timeout(&mb3.sysclk_work,
 			msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	}
 
-	mutex_unlock(&mb3_transfer.sysclk_lock);
+	mutex_unlock(&mb3.sysclk_lock);
 
 	return r;
 }
@@ -2007,7 +1711,7 @@ static int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 	    (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
 		return -EINVAL;
 
-	mutex_lock(&mb4_transfer.lock);
+	mutex_lock(&mb4.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -2020,16 +1724,16 @@ static int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 	writeb(state, (tcdm_legacy_base + PRCM_REQ_MB4_ESRAM0_ST));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4_transfer.work);
+	wait_for_completion(&mb4.work);
 
-	mutex_unlock(&mb4_transfer.lock);
+	mutex_unlock(&mb4.lock);
 
 	return 0;
 }
 
 int db8500_prcmu_config_hotdog(u8 threshold)
 {
-	mutex_lock(&mb4_transfer.lock);
+	mutex_lock(&mb4.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -2038,16 +1742,16 @@ int db8500_prcmu_config_hotdog(u8 threshold)
 	writeb(MB4H_HOTDOG, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4_transfer.work);
+	wait_for_completion(&mb4.work);
 
-	mutex_unlock(&mb4_transfer.lock);
+	mutex_unlock(&mb4.lock);
 
 	return 0;
 }
 
 int db8500_prcmu_config_hotmon(u8 low, u8 high)
 {
-	mutex_lock(&mb4_transfer.lock);
+	mutex_lock(&mb4.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -2059,16 +1763,16 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high)
 	writeb(MB4H_HOTMON, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4_transfer.work);
+	wait_for_completion(&mb4.work);
 
-	mutex_unlock(&mb4_transfer.lock);
+	mutex_unlock(&mb4.lock);
 
 	return 0;
 }
 
 static int config_hot_period(u16 val)
 {
-	mutex_lock(&mb4_transfer.lock);
+	mutex_lock(&mb4.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -2077,9 +1781,9 @@ static int config_hot_period(u16 val)
 	writeb(MB4H_HOT_PERIOD, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4_transfer.work);
+	wait_for_completion(&mb4.work);
 
-	mutex_unlock(&mb4_transfer.lock);
+	mutex_unlock(&mb4.lock);
 
 	return 0;
 }
@@ -2100,7 +1804,7 @@ int db8500_prcmu_stop_temp_sense(void)
 static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 {
 
-	mutex_lock(&mb4_transfer.lock);
+	mutex_lock(&mb4.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -2113,9 +1817,9 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 	writeb(cmd, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4_transfer.work);
+	wait_for_completion(&mb4.work);
 
-	mutex_unlock(&mb4_transfer.lock);
+	mutex_unlock(&mb4.lock);
 
 	return 0;
 
@@ -2178,7 +1882,7 @@ static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 	if (size != 1)
 		return -EINVAL;
 
-	mutex_lock(&mb5_transfer.lock);
+	mutex_lock(&mb5.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
@@ -2192,19 +1896,19 @@ static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 
 	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
-	if (!wait_for_completion_timeout(&mb5_transfer.work,
+	if (!wait_for_completion_timeout(&mb5.work,
 				msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	} else {
-		r = ((mb5_transfer.ack.status == I2C_RD_OK) ? 0 : -EIO);
+		r = ((mb5.ack.status == I2C_RD_OK) ? 0 : -EIO);
 	}
 
 	if (!r)
-		*value = mb5_transfer.ack.value;
+		*value = mb5.ack.value;
 
-	mutex_unlock(&mb5_transfer.lock);
+	mutex_unlock(&mb5.lock);
 
 	return r;
 }
@@ -2230,30 +1934,30 @@ static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
 	if (size != 1)
 		return -EINVAL;
 
-	mutex_lock(&mb5_transfer.lock);
+	mutex_lock(&mb5.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
 
 	writeb(~*mask, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB5));
 	writeb(PRCMU_I2C_WRITE(slave),
-			(tcdm_legacy_base + PRCM_REQ_MB5_I2C_SLAVE_OP));
+			tcdm_legacy_base + PRCM_REQ_MB5_I2C_SLAVE_OP);
 	writeb(PRCMU_I2C_STOP_EN, tcdm_legacy_base + PRCM_REQ_MB5_I2C_HW_BITS);
 	writeb(reg, (tcdm_legacy_base + PRCM_REQ_MB5_I2C_REG));
 	writeb(*value, (tcdm_legacy_base + PRCM_REQ_MB5_I2C_VAL));
 
 	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
-	if (!wait_for_completion_timeout(&mb5_transfer.work,
+	if (!wait_for_completion_timeout(&mb5.work,
 				msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	} else {
-		r = ((mb5_transfer.ack.status == I2C_WR_OK) ? 0 : -EIO);
+		r = ((mb5.ack.status == I2C_WR_OK) ? 0 : -EIO);
 	}
 
-	mutex_unlock(&mb5_transfer.lock);
+	mutex_unlock(&mb5.lock);
 
 	return r;
 }
@@ -2283,7 +1987,7 @@ int prcmu_ac_wake_req(void)
 	u32 val;
 	int ret = 0;
 
-	mutex_lock(&mb0_transfer.ac_wake_lock);
+	mutex_lock(&mb0.ac_wake_lock);
 
 	val = readl(PRCM_HOSTACCESS_REQ);
 	if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)
@@ -2304,7 +2008,7 @@ int prcmu_ac_wake_req(void)
 	val |= PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ;
 	writel(val, PRCM_HOSTACCESS_REQ);
 
-	if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
+	if (!wait_for_completion_timeout(&mb0.ac_wake_work,
 			msecs_to_jiffies(5000))) {
 #if defined(CONFIG_DBX500_PRCMU_DEBUG)
 		db8500_prcmu_debug_dump(__func__, true, true);
@@ -2315,7 +2019,7 @@ int prcmu_ac_wake_req(void)
 	}
 
 unlock_and_return:
-	mutex_unlock(&mb0_transfer.ac_wake_lock);
+	mutex_unlock(&mb0.ac_wake_lock);
 	return ret;
 }
 
@@ -2326,7 +2030,7 @@ void prcmu_ac_sleep_req()
 {
 	u32 val;
 
-	mutex_lock(&mb0_transfer.ac_wake_lock);
+	mutex_lock(&mb0.ac_wake_lock);
 
 	val = readl(PRCM_HOSTACCESS_REQ);
 	if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ))
@@ -2335,7 +2039,7 @@ void prcmu_ac_sleep_req()
 	writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
 		PRCM_HOSTACCESS_REQ);
 
-	if (!wait_for_completion_timeout(&mb0_transfer.ac_wake_work,
+	if (!wait_for_completion_timeout(&mb0.ac_wake_work,
 			msecs_to_jiffies(5000))) {
 		pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
 			__func__);
@@ -2344,7 +2048,7 @@ void prcmu_ac_sleep_req()
 	atomic_set(&ac_wake_req_state, 0);
 
 unlock_and_return:
-	mutex_unlock(&mb0_transfer.ac_wake_lock);
+	mutex_unlock(&mb0.ac_wake_lock);
 }
 
 static bool db8500_prcmu_is_ac_wake_requested(void)
@@ -2380,28 +2084,28 @@ static u16 db8500_prcmu_get_reset_code(void)
  */
 static void db8500_prcmu_modem_reset(void)
 {
-	mutex_lock(&mb1_transfer.lock);
+	mutex_lock(&mb1.lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
 	writeb(MB1H_RESET_MODEM, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1_transfer.work);
+	wait_for_completion(&mb1.work);
 
 	/*
 	 * No need to check return from PRCMU as modem should go in reset state
 	 * This state is already managed by upper layer
 	 */
 
-	mutex_unlock(&mb1_transfer.lock);
+	mutex_unlock(&mb1.lock);
 }
 
 static void ack_dbb_wakeup(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0_transfer.lock, flags);
+	spin_lock_irqsave(&mb0.lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
@@ -2410,7 +2114,7 @@ static void ack_dbb_wakeup(void)
 			tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB0);
 	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+	spin_unlock_irqrestore(&mb0.lock, flags);
 }
 
 static inline void print_unknown_header_warning(u8 n, u8 header)
@@ -2438,11 +2142,11 @@ static bool read_mailbox_0(void)
 					PRCM_ACK_MB0_WAKEUP_0_8500);
 
 		if (ev & (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK))
-			complete(&mb0_transfer.ac_wake_work);
+			complete(&mb0.ac_wake_work);
 		if (ev & WAKEUP_BIT_SYSCLK_OK)
-			complete(&mb3_transfer.sysclk_work);
+			complete(&mb3.sysclk_work);
 
-		ev &= mb0_transfer.req.dbb_irqs;
+		ev &= mb0.req.dbb_irqs;
 
 		for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
 			if (ev & prcmu_irq_bit[n])
@@ -2461,25 +2165,25 @@ static bool read_mailbox_0(void)
 
 static bool read_mailbox_1(void)
 {
-	mb1_transfer.ack.header = readb(tcdm_legacy_base +
+	mb1.ack.header = readb(tcdm_legacy_base +
 			PRCM_MBOX_HEADER_REQ_MB1);
-	mb1_transfer.ack.arm_opp = readb(tcdm_legacy_base +
+	mb1.ack.arm_opp = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_CURRENT_ARM_OPP);
-	mb1_transfer.ack.ape_opp = readb(tcdm_legacy_base +
+	mb1.ack.ape_opp = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_CURRENT_APE_OPP);
-	mb1_transfer.ack.ape_voltage_status = readb(tcdm_legacy_base +
+	mb1.ack.ape_voltage_status = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_APE_VOLTAGE_STATUS);
 	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
-	complete(&mb1_transfer.work);
+	complete(&mb1.work);
 	return false;
 }
 
 static bool read_mailbox_2(void)
 {
-	mb2_transfer.ack.status = readb(tcdm_legacy_base
+	mb2.ack.status = readb(tcdm_legacy_base
 			+ PRCM_ACK_MB2_DPS_STATUS);
 	writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
-	complete(&mb2_transfer.work);
+	complete(&mb2.work);
 	return false;
 }
 
@@ -2515,18 +2219,18 @@ static bool read_mailbox_4(void)
 	writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
 
 	if (do_complete)
-		complete(&mb4_transfer.work);
+		complete(&mb4.work);
 
 	return false;
 }
 
 static bool read_mailbox_5(void)
 {
-	mb5_transfer.ack.status = readb(tcdm_legacy_base
+	mb5.ack.status = readb(tcdm_legacy_base
 			+ PRCM_ACK_MB5_I2C_STATUS);
-	mb5_transfer.ack.value = readb(tcdm_legacy_base + PRCM_ACK_MB5_I2C_VAL);
+	mb5.ack.value = readb(tcdm_legacy_base + PRCM_ACK_MB5_I2C_VAL);
 	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
-	complete(&mb5_transfer.work);
+	complete(&mb5.work);
 	return false;
 }
 
@@ -2584,39 +2288,39 @@ static void prcmu_mask_work(struct work_struct *work)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0_transfer.lock, flags);
+	spin_lock_irqsave(&mb0.lock, flags);
 
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0_transfer.lock, flags);
+	spin_unlock_irqrestore(&mb0.lock, flags);
 }
 
 static void prcmu_irq_mask(struct irq_data *d)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
+	spin_lock_irqsave(&mb0.dbb_irqs_lock, flags);
 
-	mb0_transfer.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
+	mb0.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
 
-	spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
+	spin_unlock_irqrestore(&mb0.dbb_irqs_lock, flags);
 
 	if (d->irq != IRQ_PRCMU_CA_SLEEP)
-		schedule_work(&mb0_transfer.mask_work);
+		schedule_work(&mb0.mask_work);
 }
 
 static void prcmu_irq_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0_transfer.dbb_irqs_lock, flags);
+	spin_lock_irqsave(&mb0.dbb_irqs_lock, flags);
 
-	mb0_transfer.req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
+	mb0.req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
 
-	spin_unlock_irqrestore(&mb0_transfer.dbb_irqs_lock, flags);
+	spin_unlock_irqrestore(&mb0.dbb_irqs_lock, flags);
 
 	if (d->irq != IRQ_PRCMU_CA_SLEEP)
-		schedule_work(&mb0_transfer.mask_work);
+		schedule_work(&mb0.mask_work);
 }
 
 static void noop(struct irq_data *d)
@@ -2898,25 +2602,25 @@ struct prcmu_fops_register_data *__init
 	tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE, map->tcdm_size);
 	tcdm_legacy_base = tcdm_base + map->legacy_offset;
 
-	spin_lock_init(&mb0_transfer.lock);
-	spin_lock_init(&mb0_transfer.dbb_irqs_lock);
-	mutex_init(&mb0_transfer.ac_wake_lock);
-	init_completion(&mb0_transfer.ac_wake_work);
-	mutex_init(&mb1_transfer.lock);
-	init_completion(&mb1_transfer.work);
-	mb1_transfer.ape_opp = APE_NO_CHANGE;
-	mutex_init(&mb2_transfer.lock);
-	init_completion(&mb2_transfer.work);
-	spin_lock_init(&mb2_transfer.auto_pm_lock);
-	spin_lock_init(&mb3_transfer.lock);
-	mutex_init(&mb3_transfer.sysclk_lock);
-	init_completion(&mb3_transfer.sysclk_work);
-	mutex_init(&mb4_transfer.lock);
-	init_completion(&mb4_transfer.work);
-	mutex_init(&mb5_transfer.lock);
-	init_completion(&mb5_transfer.work);
-
-	INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
+	spin_lock_init(&mb0.lock);
+	spin_lock_init(&mb0.dbb_irqs_lock);
+	mutex_init(&mb0.ac_wake_lock);
+	init_completion(&mb0.ac_wake_work);
+	mutex_init(&mb1.lock);
+	init_completion(&mb1.work);
+	mb1.ape_opp = APE_NO_CHANGE;
+	mutex_init(&mb2.lock);
+	init_completion(&mb2.work);
+	spin_lock_init(&mb2.auto_pm_lock);
+	spin_lock_init(&mb3.lock);
+	mutex_init(&mb3.sysclk_lock);
+	init_completion(&mb3.sysclk_work);
+	mutex_init(&mb4.lock);
+	init_completion(&mb4.work);
+	mutex_init(&mb5.lock);
+	init_completion(&mb5.work);
+
+	INIT_WORK(&mb0.mask_work, prcmu_mask_work);
 
 	/*  early init of dbx500-prcmu */
 	return &db8500_early_data;
diff --git a/drivers/mfd/dbx500-prcmu.h b/drivers/mfd/dbx500-prcmu.h
new file mode 100644
index 0000000..79cba24
--- /dev/null
+++ b/drivers/mfd/dbx500-prcmu.h
@@ -0,0 +1,378 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: Loic Pallardy <loic.pallardy@stericsson.com>
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCMU legacy mailbox definition
+ */
+
+#define KHZ_TO_HZ(A) (A*1000)
+#define HZ_TO_KHZ(A) (A/1000)
+
+/* Offset for the firmware version within the TCPM */
+#define PRCMU_FW_VERSION_OFFSET 0xA4
+
+#define PRCM_BOOT_STATUS	0xFFF
+
+#define PRCM_SW_RST_REASON 0xFF8 /* 2 bytes */
+
+#define PRCM_TCDM_VOICE_CALL_FLAG 0xDD4 /* 4 bytes */
+
+#define _PRCM_MBOX_HEADER		0xFE8 /* 16 bytes */
+#define PRCM_MBOX_HEADER_REQ_MB0	(_PRCM_MBOX_HEADER + 0x0)
+#define PRCM_MBOX_HEADER_REQ_MB1	(_PRCM_MBOX_HEADER + 0x1)
+#define PRCM_MBOX_HEADER_REQ_MB2	(_PRCM_MBOX_HEADER + 0x2)
+#define PRCM_MBOX_HEADER_REQ_MB3	(_PRCM_MBOX_HEADER + 0x3)
+#define PRCM_MBOX_HEADER_REQ_MB4	(_PRCM_MBOX_HEADER + 0x4)
+#define PRCM_MBOX_HEADER_REQ_MB5	(_PRCM_MBOX_HEADER + 0x5)
+#define PRCM_MBOX_HEADER_ACK_MB0	(_PRCM_MBOX_HEADER + 0x8)
+
+/* Req Mailboxes */
+#define PRCM_REQ_MB0 0xFDC /* 12 bytes  */
+#define PRCM_REQ_MB1 0xFD0 /* 12 bytes  */
+#define PRCM_REQ_MB2 0xFC0 /* 16 bytes  */
+#define PRCM_REQ_MB3 0xE4C /* 372 bytes  */
+#define PRCM_REQ_MB4 0xE48 /* 4 bytes  */
+#define PRCM_REQ_MB5 0xE44 /* 4 bytes  */
+#define PRCM_REQ_PASR		0xE04 /* 4 bytes */
+
+/* Ack Mailboxes */
+#define PRCM_ACK_MB0 0xE08 /* 52 bytes  */
+#define PRCM_ACK_MB1 0xE04 /* 4 bytes */
+#define PRCM_ACK_MB2 0xE00 /* 4 bytes */
+#define PRCM_ACK_MB3 0xDFC /* 4 bytes */
+#define PRCM_ACK_MB4 0xDF8 /* 4 bytes */
+#define PRCM_ACK_MB5 0xDF4 /* 4 bytes */
+
+/* Mailbox 0 headers */
+#define MB0H_POWER_STATE_TRANS		0
+#define MB0H_CONFIG_WAKEUPS_EXE		1
+#define MB0H_READ_WAKEUP_ACK		3
+#define MB0H_CONFIG_WAKEUPS_SLEEP	4
+#define MB0H_CONFIG_PASR_DDR0_CS0	6
+#define MB0H_CONFIG_PASR_DDR0_CS1	7
+#define MB0H_CONFIG_PASR_DDR1_CS0	8
+#define MB0H_CONFIG_PASR_DDR1_CS1	9
+
+#define MB0H_WAKEUP_EXE 2
+#define MB0H_WAKEUP_SLEEP 5
+
+/* Mailbox 0 REQs */
+#define PRCM_REQ_MB0_AP_POWER_STATE	(PRCM_REQ_MB0 + 0x0)
+#define PRCM_REQ_MB0_AP_PLL_STATE	(PRCM_REQ_MB0 + 0x1)
+#define PRCM_REQ_MB0_ULP_CLOCK_STATE	(PRCM_REQ_MB0 + 0x2)
+#define PRCM_REQ_MB0_DO_NOT_WFI		(PRCM_REQ_MB0 + 0x3)
+#define PRCM_REQ_MB0_WAKEUP_8500	(PRCM_REQ_MB0 + 0x4)
+#define PRCM_REQ_MB0_WAKEUP_4500	(PRCM_REQ_MB0 + 0x8)
+
+/* Mailbox 0 PASR REQs */
+#define PRCM_REQ_MB0_PASR_MR16		(PRCM_REQ_PASR + 0x0)
+#define PRCM_REQ_MB0_PASR_MR17		(PRCM_REQ_PASR + 0x2)
+
+/* Mailbox 0 ACKs */
+#define PRCM_ACK_MB0_AP_PWRSTTR_STATUS	(PRCM_ACK_MB0 + 0x0)
+#define PRCM_ACK_MB0_READ_POINTER	(PRCM_ACK_MB0 + 0x1)
+#define PRCM_ACK_MB0_WAKEUP_0_8500	(PRCM_ACK_MB0 + 0x4)
+#define PRCM_ACK_MB0_WAKEUP_0_4500	(PRCM_ACK_MB0 + 0x8)
+#define PRCM_ACK_MB0_WAKEUP_1_8500	(PRCM_ACK_MB0 + 0x1C)
+#define PRCM_ACK_MB0_WAKEUP_1_4500	(PRCM_ACK_MB0 + 0x20)
+#define PRCM_ACK_MB0_EVENT_4500_NUMBERS	20
+
+/* Mailbox 1 headers */
+#define MB1H_ARM_APE_OPP 0x0
+#define MB1H_RESET_MODEM 0x2
+#define MB1H_REQUEST_APE_OPP_100_VOLT 0x3
+#define MB1H_RELEASE_APE_OPP_100_VOLT 0x4
+#define MB1H_RELEASE_USB_WAKEUP 0x5
+#define MB1H_PLL_ON_OFF 0x6
+
+/* Mailbox 1 Requests */
+#define PRCM_REQ_MB1_ARM_OPP			(PRCM_REQ_MB1 + 0x0)
+#define PRCM_REQ_MB1_APE_OPP			(PRCM_REQ_MB1 + 0x1)
+#define PRCM_REQ_MB1_PLL_ON_OFF			(PRCM_REQ_MB1 + 0x4)
+#define PLL_SOC0_OFF	0x1
+#define PLL_SOC0_ON	0x2
+#define PLL_SOC1_OFF	0x4
+#define PLL_SOC1_ON	0x8
+
+/* Mailbox 1 ACKs */
+#define PRCM_ACK_MB1_CURRENT_ARM_OPP	(PRCM_ACK_MB1 + 0x0)
+#define PRCM_ACK_MB1_CURRENT_APE_OPP	(PRCM_ACK_MB1 + 0x1)
+#define PRCM_ACK_MB1_APE_VOLTAGE_STATUS	(PRCM_ACK_MB1 + 0x2)
+#define PRCM_ACK_MB1_DVFS_STATUS	(PRCM_ACK_MB1 + 0x3)
+
+/* Mailbox 2 headers */
+#define MB2H_DPS	0x0
+#define MB2H_AUTO_PWR	0x1
+
+/* Mailbox 2 REQs */
+#define PRCM_REQ_MB2_SVA_MMDSP		(PRCM_REQ_MB2 + 0x0)
+#define PRCM_REQ_MB2_SVA_PIPE		(PRCM_REQ_MB2 + 0x1)
+#define PRCM_REQ_MB2_SIA_MMDSP		(PRCM_REQ_MB2 + 0x2)
+#define PRCM_REQ_MB2_SIA_PIPE		(PRCM_REQ_MB2 + 0x3)
+#define PRCM_REQ_MB2_SGA		(PRCM_REQ_MB2 + 0x4)
+#define PRCM_REQ_MB2_B2R2_MCDE		(PRCM_REQ_MB2 + 0x5)
+#define PRCM_REQ_MB2_ESRAM12		(PRCM_REQ_MB2 + 0x6)
+#define PRCM_REQ_MB2_ESRAM34		(PRCM_REQ_MB2 + 0x7)
+#define PRCM_REQ_MB2_AUTO_PM_SLEEP	(PRCM_REQ_MB2 + 0x8)
+#define PRCM_REQ_MB2_AUTO_PM_IDLE	(PRCM_REQ_MB2 + 0xC)
+
+/* Mailbox 2 ACKs */
+#define PRCM_ACK_MB2_DPS_STATUS (PRCM_ACK_MB2 + 0x0)
+#define HWACC_PWR_ST_OK 0xFE
+
+/* Mailbox 3 headers */
+#define MB3H_ANC	0x0
+#define MB3H_SIDETONE	0x1
+#define MB3H_SYSCLK	0xE
+
+/* Mailbox 3 Requests */
+#define PRCM_REQ_MB3_ANC_FIR_COEFF	(PRCM_REQ_MB3 + 0x0)
+#define PRCM_REQ_MB3_ANC_IIR_COEFF	(PRCM_REQ_MB3 + 0x20)
+#define PRCM_REQ_MB3_ANC_SHIFTER	(PRCM_REQ_MB3 + 0x60)
+#define PRCM_REQ_MB3_ANC_WARP		(PRCM_REQ_MB3 + 0x64)
+#define PRCM_REQ_MB3_SIDETONE_FIR_GAIN	(PRCM_REQ_MB3 + 0x68)
+#define PRCM_REQ_MB3_SIDETONE_FIR_COEFF	(PRCM_REQ_MB3 + 0x6C)
+#define PRCM_REQ_MB3_SYSCLK_MGT		(PRCM_REQ_MB3 + 0x16C)
+
+/* Mailbox 3 ACKs */
+#define PRCM_ACK_MB3_TRACE_MSG	(PRCM_ACK_MB3 + 0x00)
+#define PRCM_ACK_MB3_LOG_REQ	(PRCM_ACK_MB3 + 0x01)
+#define MB3_LOG_REQ_PRCMU_REGS	(1 << 0)
+#define MB3_LOG_REQ_TCDM	(1 << 1)
+#define MB3_LOG_REQ_AB_REGS	(1 << 2)
+
+/* Mailbox 4 headers */
+#define MB4H_DDR_INIT	0x0
+#define MB4H_MEM_ST	0x1
+#define MB4H_HOTDOG	0x12
+#define MB4H_HOTMON	0x13
+#define MB4H_HOT_PERIOD	0x14
+#define MB4H_A9WDOG_CONF 0x16
+#define MB4H_A9WDOG_EN   0x17
+#define MB4H_A9WDOG_DIS  0x18
+#define MB4H_A9WDOG_LOAD 0x19
+#define MB4H_A9WDOG_KICK 0x20
+
+/* Mailbox 4 Requests */
+#define PRCM_REQ_MB4_DDR_ST_AP_SLEEP_IDLE	(PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_DDR_ST_AP_DEEP_IDLE	(PRCM_REQ_MB4 + 0x1)
+#define PRCM_REQ_MB4_ESRAM0_ST			(PRCM_REQ_MB4 + 0x3)
+#define PRCM_REQ_MB4_HOTDOG_THRESHOLD		(PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_HOTMON_LOW			(PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_HOTMON_HIGH		(PRCM_REQ_MB4 + 0x1)
+#define PRCM_REQ_MB4_HOTMON_CONFIG		(PRCM_REQ_MB4 + 0x2)
+#define PRCM_REQ_MB4_HOT_PERIOD			(PRCM_REQ_MB4 + 0x0)
+#define HOTMON_CONFIG_LOW			BIT(0)
+#define HOTMON_CONFIG_HIGH			BIT(1)
+#define PRCM_REQ_MB4_A9WDOG_0			(PRCM_REQ_MB4 + 0x0)
+#define PRCM_REQ_MB4_A9WDOG_1			(PRCM_REQ_MB4 + 0x1)
+#define PRCM_REQ_MB4_A9WDOG_2			(PRCM_REQ_MB4 + 0x2)
+#define PRCM_REQ_MB4_A9WDOG_3			(PRCM_REQ_MB4 + 0x3)
+#define A9WDOG_AUTO_OFF_EN			BIT(7)
+#define A9WDOG_AUTO_OFF_DIS			0
+#define A9WDOG_ID_MASK				0xf
+
+#define MB4TIM (HZ/10)
+
+/* Mailbox 5 Requests */
+#define PRCM_REQ_MB5_I2C_SLAVE_OP	(PRCM_REQ_MB5 + 0x0)
+#define PRCM_REQ_MB5_I2C_HW_BITS	(PRCM_REQ_MB5 + 0x1)
+#define PRCM_REQ_MB5_I2C_REG		(PRCM_REQ_MB5 + 0x2)
+#define PRCM_REQ_MB5_I2C_VAL		(PRCM_REQ_MB5 + 0x3)
+#define PRCMU_I2C_WRITE(slave) (((slave) << 1) | BIT(6))
+#define PRCMU_I2C_READ(slave) (((slave) << 1) | BIT(0) | BIT(6))
+#define PRCMU_I2C_STOP_EN		BIT(3)
+
+/* Mailbox 5 ACKs */
+#define PRCM_ACK_MB5_I2C_STATUS	(PRCM_ACK_MB5 + 0x1)
+#define PRCM_ACK_MB5_I2C_VAL	(PRCM_ACK_MB5 + 0x3)
+#define I2C_WR_OK 0x1
+#define I2C_RD_OK 0x2
+
+#define NUM_MB 8
+#define MBOX_BIT BIT
+#define ALL_MBOX_BITS (MBOX_BIT(NUM_MB) - 1)
+
+/*
+ * Wakeups/IRQs
+ */
+
+#define WAKEUP_BIT_RTC BIT(0)
+#define WAKEUP_BIT_RTT0 BIT(1)
+#define WAKEUP_BIT_RTT1 BIT(2)
+#define WAKEUP_BIT_HSI0 BIT(3)
+#define WAKEUP_BIT_HSI1 BIT(4)
+#define WAKEUP_BIT_CA_WAKE BIT(5)
+#define WAKEUP_BIT_USB BIT(6)
+#define WAKEUP_BIT_ABB BIT(7)
+#define WAKEUP_BIT_ABB_FIFO BIT(8)
+#define WAKEUP_BIT_SYSCLK_OK BIT(9)
+#define WAKEUP_BIT_CA_SLEEP BIT(10)
+#define WAKEUP_BIT_AC_WAKE_ACK BIT(11)
+#define WAKEUP_BIT_SIDE_TONE_OK BIT(12)
+#define WAKEUP_BIT_ANC_OK BIT(13)
+#define WAKEUP_BIT_SW_ERROR BIT(14)
+#define WAKEUP_BIT_AC_SLEEP_ACK BIT(15)
+#define WAKEUP_BIT_ARM BIT(17)
+#define WAKEUP_BIT_HOTMON_LOW BIT(18)
+#define WAKEUP_BIT_HOTMON_HIGH BIT(19)
+#define WAKEUP_BIT_MODEM_SW_RESET_REQ BIT(20)
+#define WAKEUP_BIT_GPIO0 BIT(23)
+#define WAKEUP_BIT_GPIO1 BIT(24)
+#define WAKEUP_BIT_GPIO2 BIT(25)
+#define WAKEUP_BIT_GPIO3 BIT(26)
+#define WAKEUP_BIT_GPIO4 BIT(27)
+#define WAKEUP_BIT_GPIO5 BIT(28)
+#define WAKEUP_BIT_GPIO6 BIT(29)
+#define WAKEUP_BIT_GPIO7 BIT(30)
+#define WAKEUP_BIT_GPIO8 BIT(31)
+
+/*
+* Used by MCDE to setup all necessary PRCMU registers
+*/
+#define PRCMU_RESET_DSIPLL		0x00004000
+#define PRCMU_UNCLAMP_DSIPLL		0x00400800
+
+#define PRCMU_CLK_PLL_DIV_SHIFT		0
+#define PRCMU_CLK_PLL_SW_SHIFT		5
+#define PRCMU_CLK_38			(1 << 9)
+#define PRCMU_CLK_38_SRC		(1 << 10)
+#define PRCMU_CLK_38_DIV		(1 << 11)
+
+/* PLLDIV=12, PLLSW=4 (PLLDDR) */
+#define PRCMU_DSI_CLOCK_SETTING		0x0000008C
+
+/* DPI 50000000 Hz */
+#define PRCMU_DPI_CLOCK_SETTING		((1 << PRCMU_CLK_PLL_SW_SHIFT) | \
+					  (16 << PRCMU_CLK_PLL_DIV_SHIFT))
+#define PRCMU_DSI_LP_CLOCK_SETTING	0x00000E00
+
+/* D=101, N=1, R=4, SELDIV2=0 */
+#define PRCMU_PLLDSI_FREQ_SETTING	0x00040165
+
+#define PRCMU_ENABLE_PLLDSI		0x00000001
+#define PRCMU_DISABLE_PLLDSI		0x00000000
+#define PRCMU_RELEASE_RESET_DSS		0x0000400C
+#define PRCMU_DSI_PLLOUT_SEL_SETTING	0x00000202
+/* ESC clk, div0=1, div1=1, div2=3 */
+#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV	0x07030101
+#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV	0x00030101
+#define PRCMU_DSI_RESET_SW		0x00000007
+
+#define PRCMU_PLLDSI_LOCKP_LOCKED	0x3
+
+struct clk_mgt {
+	void __iomem *reg;
+	u32 pllsw;
+	int branch;
+	bool clk38div;
+};
+
+enum {
+	PLL_RAW,
+	PLL_FIX,
+	PLL_DIV
+};
+
+/*
+ * mb0_transfer - state needed for mailbox 0 communication.
+ * @lock:		The transaction lock.
+ * @dbb_events_lock:	A lock used to handle concurrent access to (parts of)
+ *			the request data.
+ * @mask_work:		Work structure used for (un)masking wakeup interrupts.
+ * @req:		Request data that need to persist between requests.
+ */
+struct mb0_transfer {
+	spinlock_t lock;
+	spinlock_t dbb_irqs_lock;
+	struct work_struct mask_work;
+	struct mutex ac_wake_lock;
+	struct completion ac_wake_work;
+	struct {
+		u32 dbb_irqs;
+		u32 dbb_wakeups;
+		u32 abb_events;
+	} req;
+};
+
+/*
+ * mb1_transfer - state needed for mailbox 1 communication.
+ * @lock:	The transaction lock.
+ * @work:	The transaction completion structure.
+ * @ape_opp:	The current APE OPP.
+ * @ack:	Reply ("acknowledge") data.
+ */
+struct mb1_transfer {
+	struct mutex lock;
+	struct completion work;
+	u8 ape_opp;
+	struct {
+		u8 header;
+		u8 arm_opp;
+		u8 ape_opp;
+		u8 ape_voltage_status;
+	} ack;
+};
+
+/*
+ * mb2_transfer - state needed for mailbox 2 communication.
+ * @lock:            The transaction lock.
+ * @work:            The transaction completion structure.
+ * @auto_pm_lock:    The autonomous power management configuration lock.
+ * @auto_pm_enabled: A flag indicating whether autonomous PM is enabled.
+ * @req:             Request data that need to persist between requests.
+ * @ack:             Reply ("acknowledge") data.
+ */
+struct mb2_transfer {
+	struct mutex lock;
+	struct completion work;
+	spinlock_t auto_pm_lock;
+	bool auto_pm_enabled;
+	struct {
+		u8 status;
+	} ack;
+};
+
+/*
+ * mb3_transfer - state needed for mailbox 3 communication.
+ * @lock:		The request lock.
+ * @sysclk_lock:	A lock used to handle concurrent sysclk requests.
+ * @sysclk_work:	Work structure used for sysclk requests.
+ */
+struct mb3_transfer {
+	spinlock_t lock;
+	struct mutex sysclk_lock;
+	struct completion sysclk_work;
+	spinlock_t fw_log_lock;
+	struct work_struct fw_log_work;
+	u8 fw_log_req;
+};
+
+/*
+ * mb4_transfer - state needed for mailbox 4 communication.
+ * @lock:	The transaction lock.
+ * @work:	The transaction completion structure.
+ */
+struct mb4_transfer {
+	struct mutex lock;
+	struct completion work;
+};
+
+/*
+ * mb5_transfer - state needed for mailbox 5 communication.
+ * @lock:	The transaction lock.
+ * @work:	The transaction completion structure.
+ * @ack:	Reply ("acknowledge") data.
+ */
+struct mb5_transfer {
+	struct mutex lock;
+	struct completion work;
+	struct {
+		u8 status;
+		u8 value;
+	} ack;
+};
+
-- 
1.7.11.1


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

* [PATCH 12/17] mfd: prcmu: make fw_project_name generic
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (10 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 11/17] mfd: pcrmu: create common header file for legacy mailbox Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 13/17] mfd: prcmu: make legacy mailbox services configurable Loic Pallardy
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

Project_name_id must be increased to support 8500 and x540 project.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/db8500-prcmu.c       |  4 +++-
 include/linux/mfd/db8500-prcmu.h | 14 --------------
 include/linux/mfd/dbx500-prcmu.h | 17 +++++++++++++++++
 3 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 96487a0..327e9f6 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2335,7 +2335,7 @@ static struct irq_chip prcmu_irq_chip = {
 	.irq_unmask	= prcmu_irq_unmask,
 };
 
-static char *fw_project_name(u8 project)
+char *fw_project_name(u32 project)
 {
 	switch (project) {
 	case PRCMU_FW_PROJECT_U8500:
@@ -2350,6 +2350,8 @@ static char *fw_project_name(u8 project)
 		return "U8520";
 	case PRCMU_FW_PROJECT_U8420:
 		return "U8420";
+	case PRCMU_FW_PROJECT_U9540:
+		return "U9540";
 	default:
 		return "Unknown";
 	}
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index a6d7298..f3b8b60 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -470,20 +470,6 @@ struct prcmu_auto_pm_config {
 	u8 sva_policy;
 };
 
-#define PRCMU_FW_PROJECT_U8500		2
-#define PRCMU_FW_PROJECT_U9500		4
-#define PRCMU_FW_PROJECT_U8500_C2	7
-#define PRCMU_FW_PROJECT_U9500_C2	11
-#define PRCMU_FW_PROJECT_U8520		13
-#define PRCMU_FW_PROJECT_U8420		14
-
-struct prcmu_fw_version {
-	u8 project;
-	u8 api_version;
-	u8 func_version;
-	u8 errata;
-};
-
 #ifdef CONFIG_MFD_DB8500_PRCMU
 
 struct prcmu_fops_register_data *db8500_prcmu_early_init(
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index d76114e..49e71a7 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -235,6 +235,23 @@ struct prcmu_tcdm_map {
 	u32 legacy_offset;
 };
 
+#define PRCMU_FW_PROJECT_U8500		2
+#define PRCMU_FW_PROJECT_U9500		4 /* Customer specific */
+#define PRCMU_FW_PROJECT_U8500_C2	7
+#define PRCMU_FW_PROJECT_U9500_C2	11 /* Customer specific */
+#define PRCMU_FW_PROJECT_U8520		13
+#define PRCMU_FW_PROJECT_U8420		14
+#define PRCMU_FW_PROJECT_U9540		(6<<8)
+
+#define PRCMU_FW_PROJECT_NAME_LEN	20
+struct prcmu_fw_version {
+	u8 project;
+	u8 api_version;
+	u8 func_version;
+	u8 errata;
+	char project_name[PRCMU_FW_PROJECT_NAME_LEN];
+};
+
 #include <linux/mfd/db8500-prcmu.h>
 
 #if defined(CONFIG_UX500_SOC_DB8500)
-- 
1.7.11.1


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

* [PATCH 13/17] mfd: prcmu: make legacy mailbox services configurable
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (11 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 12/17] mfd: prcmu: make fw_project_name generic Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 14/17] mfd: db8500-prcmu: use db8500 legacy services Loic Pallardy
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

8500 and x540 are using same services based on prcmu legacy
mailbox but with different base address and different arguments.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/db8500-prcmu.c | 371 +++++++++++++++++++++++++++------------------
 drivers/mfd/dbx500-prcmu.h |  16 ++
 2 files changed, 243 insertions(+), 144 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 327e9f6..73c98e5 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -137,13 +137,21 @@ static DEFINE_SPINLOCK(clkout_lock);
 static __iomem void *tcdm_legacy_base;
 static __iomem void *tcdm_base;
 
+/* mailbox pointers */
+static struct mb0_transfer *mb0;
+static struct mb1_transfer *mb1;
+static struct mb2_transfer *mb2;
+static struct mb3_transfer *mb3;
+static struct mb4_transfer *mb4;
+static struct mb5_transfer *mb5;
+
 /* mailbox definition */
-static struct mb0_transfer mb0;
-static struct mb1_transfer mb1;
-static struct mb2_transfer mb2;
-static struct mb3_transfer mb3;
-static struct mb4_transfer mb4;
-static struct mb5_transfer mb5;
+static struct mb0_transfer db8500_mb0;
+static struct mb1_transfer db8500_mb1;
+static struct mb2_transfer db8500_mb2;
+static struct mb3_transfer db8500_mb3;
+static struct mb4_transfer db8500_mb4;
+static struct mb5_transfer db8500_mb5;
 
 static DEFINE_SPINLOCK(clk_mgt_lock);
 
@@ -472,20 +480,31 @@ unlock_and_return:
 	return r;
 }
 
+static u8 db8500_fw_trans[] = {
+	0x00,/* PRCMU_AP_NO_CHANGE */
+	0x01,/* PRCMU_AP_SLEEP */
+	0x04,/*	PRCMU_AP_DEEP_SLEEP */
+	0x05,/*	PRCMU_AP_IDLE */
+	0x07,/*	PRCMU_AP_DEEP_IDLE*/
+};
+
+static u8 *fw_trans;
+static u32 fw_trans_nb;
+
 int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 {
 	unsigned long flags;
 
-	BUG_ON((state < PRCMU_AP_SLEEP) || (PRCMU_AP_DEEP_IDLE < state));
-
-	spin_lock_irqsave(&mb0.lock, flags);
+	BUG_ON((state == PRCMU_AP_NO_CHANGE) ||
+			(state >= fw_trans_nb));
+	spin_lock_irqsave(&mb0->lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
 
 	writeb(MB0H_POWER_STATE_TRANS,
 			tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB0);
-	writeb(state, (tcdm_legacy_base + PRCM_REQ_MB0_AP_POWER_STATE));
+	writeb(fw_trans[state], tcdm_legacy_base + PRCM_REQ_MB0_AP_POWER_STATE);
 	writeb((keep_ap_pll ? 1 : 0),
 			tcdm_legacy_base + PRCM_REQ_MB0_AP_PLL_STATE);
 	writeb((keep_ulp_clk ? 1 : 0),
@@ -493,7 +512,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 	writeb(0, (tcdm_legacy_base + PRCM_REQ_MB0_DO_NOT_WFI));
 	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 
 	return 0;
 }
@@ -616,7 +635,7 @@ int db8500_prcmu_copy_gic_settings(void)
 	return 0;
 }
 
-/* This function should only be called while mb0.lock is held. */
+/* This function should only be called while mb0->lock is held. */
 static void config_wakeups(void)
 {
 	const u8 header[2] = {
@@ -629,10 +648,10 @@ static void config_wakeups(void)
 	u32 abb_events;
 	unsigned int i;
 
-	dbb_events = mb0.req.dbb_irqs | mb0.req.dbb_wakeups;
+	dbb_events = mb0->req.dbb_irqs | mb0->req.dbb_wakeups;
 	dbb_events |= (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK);
 
-	abb_events = mb0.req.abb_events;
+	abb_events = mb0->req.abb_events;
 
 	if ((dbb_events == last_dbb_events) && (abb_events == last_abb_events))
 		return;
@@ -662,24 +681,24 @@ static void db8500_prcmu_enable_wakeups(u32 wakeups)
 			bits |= prcmu_wakeup_bit[i];
 	}
 
-	spin_lock_irqsave(&mb0.lock, flags);
+	spin_lock_irqsave(&mb0->lock, flags);
 
-	mb0.req.dbb_wakeups = bits;
+	mb0->req.dbb_wakeups = bits;
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
 static void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.lock, flags);
+	spin_lock_irqsave(&mb0->lock, flags);
 
-	mb0.req.abb_events = abb_events;
+	mb0->req.abb_events = abb_events;
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
 static void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
@@ -706,7 +725,7 @@ static int db8500_prcmu_set_arm_opp(u8 opp)
 
 	r = 0;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -716,13 +735,13 @@ static int db8500_prcmu_set_arm_opp(u8 opp)
 	writeb(APE_NO_CHANGE, (tcdm_legacy_base + PRCM_REQ_MB1_APE_OPP));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if ((mb1.ack.header != MB1H_ARM_APE_OPP) ||
-		(mb1.ack.arm_opp != opp))
+	if ((mb1->ack.header != MB1H_ARM_APE_OPP) ||
+		(mb1->ack.arm_opp != opp))
 		r = -EIO;
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -822,15 +841,15 @@ static int db8500_prcmu_set_ape_opp(u8 opp)
 {
 	int r = 0;
 
-	if (opp == mb1.ape_opp)
+	if (opp == mb1->ape_opp)
 		return 0;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
-	if (mb1.ape_opp == APE_50_PARTLY_25_OPP)
+	if (mb1->ape_opp == APE_50_PARTLY_25_OPP)
 		request_even_slower_clocks(false);
 
-	if ((opp != APE_100_OPP) && (mb1.ape_opp != APE_100_OPP))
+	if ((opp != APE_100_OPP) && (mb1->ape_opp != APE_100_OPP))
 		goto skip_message;
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
@@ -842,20 +861,20 @@ static int db8500_prcmu_set_ape_opp(u8 opp)
 		(tcdm_legacy_base + PRCM_REQ_MB1_APE_OPP));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if ((mb1.ack.header != MB1H_ARM_APE_OPP) ||
-		(mb1.ack.ape_opp != opp))
+	if ((mb1->ack.header != MB1H_ARM_APE_OPP) ||
+		(mb1->ack.ape_opp != opp))
 		r = -EIO;
 
 skip_message:
 	if ((!r && (opp == APE_50_PARTLY_25_OPP)) ||
-		(r && (mb1.ape_opp == APE_50_PARTLY_25_OPP)))
+		(r && (mb1->ape_opp == APE_50_PARTLY_25_OPP)))
 		request_even_slower_clocks(true);
 	if (!r)
-		mb1.ape_opp = opp;
+		mb1->ape_opp = opp;
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -882,7 +901,7 @@ static int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 	u8 header;
 	static unsigned int requests;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	if (enable) {
 		if (0 != requests++)
@@ -904,14 +923,14 @@ static int db8500_prcmu_request_ape_opp_100_voltage(bool enable)
 	writeb(header, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if ((mb1.ack.header != header) ||
-		((mb1.ack.ape_voltage_status & BIT(0)) != 0))
+	if ((mb1->ack.header != header) ||
+		((mb1->ack.ape_voltage_status & BIT(0)) != 0))
 		r = -EIO;
 
 unlock_and_return:
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -925,7 +944,7 @@ int prcmu_release_usb_wakeup_state(void)
 {
 	int r = 0;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -934,13 +953,13 @@ int prcmu_release_usb_wakeup_state(void)
 		(tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if ((mb1.ack.header != MB1H_RELEASE_USB_WAKEUP) ||
-		((mb1.ack.ape_voltage_status & BIT(0)) != 0))
+	if ((mb1->ack.header != MB1H_RELEASE_USB_WAKEUP) ||
+		((mb1->ack.ape_voltage_status & BIT(0)) != 0))
 		r = -EIO;
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -956,7 +975,7 @@ static int request_pll(u8 clock, bool enable)
 	else
 		return -EINVAL;
 
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
@@ -965,12 +984,12 @@ static int request_pll(u8 clock, bool enable)
 	writeb(clock, (tcdm_legacy_base + PRCM_REQ_MB1_PLL_ON_OFF));
 
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
-	if (mb1.ack.header != MB1H_PLL_ON_OFF)
+	if (mb1->ack.header != MB1H_PLL_ON_OFF)
 		r = -EIO;
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 
 	return r;
 }
@@ -1007,7 +1026,7 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 	BUG_ON(epod_state == EPOD_STATE_RAMRET && !ram_retention);
 
 	/* get lock */
-	mutex_lock(&mb2.lock);
+	mutex_lock(&mb2->lock);
 
 	/* wait for mailbox */
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(2))
@@ -1028,7 +1047,7 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 	 * and we cannot recover if there is an error.
 	 * This is expected to change when the firmware is updated.
 	 */
-	if (!wait_for_completion_timeout(&mb2.work,
+	if (!wait_for_completion_timeout(&mb2->work,
 			msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
@@ -1036,11 +1055,11 @@ static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 		goto unlock_and_return;
 	}
 
-	if (mb2.ack.status != HWACC_PWR_ST_OK)
+	if (mb2->ack.status != HWACC_PWR_ST_OK)
 		r = -EIO;
 
 unlock_and_return:
-	mutex_unlock(&mb2.lock);
+	mutex_unlock(&mb2->lock);
 	return r;
 }
 
@@ -1072,7 +1091,7 @@ static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	idle_cfg = ((idle_cfg << 4) | (idle->sva_policy & 0xF));
 	idle_cfg = ((idle_cfg << 4) | (idle->sia_policy & 0xF));
 
-	spin_lock_irqsave(&mb2.auto_pm_lock, flags);
+	spin_lock_irqsave(&mb2->auto_pm_lock, flags);
 
 	/*
 	 * The autonomous power management configuration is done through
@@ -1082,18 +1101,18 @@ static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	writel(sleep_cfg, (tcdm_legacy_base + PRCM_REQ_MB2_AUTO_PM_SLEEP));
 	writel(idle_cfg, (tcdm_legacy_base + PRCM_REQ_MB2_AUTO_PM_IDLE));
 
-	mb2.auto_pm_enabled =
+	mb2->auto_pm_enabled =
 		((sleep->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (sleep->sia_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (idle->sva_auto_pm_enable == PRCMU_AUTO_PM_ON) ||
 		 (idle->sia_auto_pm_enable == PRCMU_AUTO_PM_ON));
 
-	spin_unlock_irqrestore(&mb2.auto_pm_lock, flags);
+	spin_unlock_irqrestore(&mb2->auto_pm_lock, flags);
 }
 
 bool prcmu_is_auto_pm_enabled(void)
 {
-	return mb2.auto_pm_enabled;
+	return mb2->auto_pm_enabled;
 }
 
 static int request_sysclk(bool enable)
@@ -1103,9 +1122,9 @@ static int request_sysclk(bool enable)
 
 	r = 0;
 
-	mutex_lock(&mb3.sysclk_lock);
+	mutex_lock(&mb3->sysclk_lock);
 
-	spin_lock_irqsave(&mb3.lock, flags);
+	spin_lock_irqsave(&mb3->lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
 		cpu_relax();
@@ -1115,20 +1134,20 @@ static int request_sysclk(bool enable)
 	writeb(MB3H_SYSCLK, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB3));
 	writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb3.lock, flags);
+	spin_unlock_irqrestore(&mb3->lock, flags);
 
 	/*
 	 * The firmware only sends an ACK if we want to enable the
 	 * SysClk, and it succeeds.
 	 */
-	if (enable && !wait_for_completion_timeout(&mb3.sysclk_work,
+	if (enable && !wait_for_completion_timeout(&mb3->sysclk_work,
 			msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	}
 
-	mutex_unlock(&mb3.sysclk_lock);
+	mutex_unlock(&mb3->sysclk_lock);
 
 	return r;
 }
@@ -1711,7 +1730,7 @@ static int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 	    (state < ESRAM0_DEEP_SLEEP_STATE_OFF))
 		return -EINVAL;
 
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1724,16 +1743,16 @@ static int db8500_prcmu_config_esram0_deep_sleep(u8 state)
 	writeb(state, (tcdm_legacy_base + PRCM_REQ_MB4_ESRAM0_ST));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 }
 
 int db8500_prcmu_config_hotdog(u8 threshold)
 {
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1742,16 +1761,16 @@ int db8500_prcmu_config_hotdog(u8 threshold)
 	writeb(MB4H_HOTDOG, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 }
 
 int db8500_prcmu_config_hotmon(u8 low, u8 high)
 {
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1763,16 +1782,16 @@ int db8500_prcmu_config_hotmon(u8 low, u8 high)
 	writeb(MB4H_HOTMON, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 }
 
 static int config_hot_period(u16 val)
 {
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1781,9 +1800,9 @@ static int config_hot_period(u16 val)
 	writeb(MB4H_HOT_PERIOD, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 }
@@ -1804,7 +1823,7 @@ int db8500_prcmu_stop_temp_sense(void)
 static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 {
 
-	mutex_lock(&mb4.lock);
+	mutex_lock(&mb4->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(4))
 		cpu_relax();
@@ -1817,9 +1836,9 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 	writeb(cmd, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB4));
 
 	writel(MBOX_BIT(4), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb4.work);
+	wait_for_completion(&mb4->work);
 
-	mutex_unlock(&mb4.lock);
+	mutex_unlock(&mb4->lock);
 
 	return 0;
 
@@ -1882,7 +1901,7 @@ static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 	if (size != 1)
 		return -EINVAL;
 
-	mutex_lock(&mb5.lock);
+	mutex_lock(&mb5->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
@@ -1896,19 +1915,19 @@ static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 
 	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
-	if (!wait_for_completion_timeout(&mb5.work,
+	if (!wait_for_completion_timeout(&mb5->work,
 				msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	} else {
-		r = ((mb5.ack.status == I2C_RD_OK) ? 0 : -EIO);
+		r = ((mb5->ack.status == I2C_RD_OK) ? 0 : -EIO);
 	}
 
 	if (!r)
-		*value = mb5.ack.value;
+		*value = mb5->ack.value;
 
-	mutex_unlock(&mb5.lock);
+	mutex_unlock(&mb5->lock);
 
 	return r;
 }
@@ -1934,7 +1953,7 @@ static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
 	if (size != 1)
 		return -EINVAL;
 
-	mutex_lock(&mb5.lock);
+	mutex_lock(&mb5->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(5))
 		cpu_relax();
@@ -1948,16 +1967,16 @@ static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
 
 	writel(MBOX_BIT(5), PRCM_MBOX_CPU_SET);
 
-	if (!wait_for_completion_timeout(&mb5.work,
+	if (!wait_for_completion_timeout(&mb5->work,
 				msecs_to_jiffies(20000))) {
 		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
 			__func__);
 		r = -EIO;
 	} else {
-		r = ((mb5.ack.status == I2C_WR_OK) ? 0 : -EIO);
+		r = ((mb5->ack.status == I2C_WR_OK) ? 0 : -EIO);
 	}
 
-	mutex_unlock(&mb5.lock);
+	mutex_unlock(&mb5->lock);
 
 	return r;
 }
@@ -1987,7 +2006,7 @@ int prcmu_ac_wake_req(void)
 	u32 val;
 	int ret = 0;
 
-	mutex_lock(&mb0.ac_wake_lock);
+	mutex_lock(&mb0->ac_wake_lock);
 
 	val = readl(PRCM_HOSTACCESS_REQ);
 	if (val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ)
@@ -2008,7 +2027,7 @@ int prcmu_ac_wake_req(void)
 	val |= PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ;
 	writel(val, PRCM_HOSTACCESS_REQ);
 
-	if (!wait_for_completion_timeout(&mb0.ac_wake_work,
+	if (!wait_for_completion_timeout(&mb0->ac_wake_work,
 			msecs_to_jiffies(5000))) {
 #if defined(CONFIG_DBX500_PRCMU_DEBUG)
 		db8500_prcmu_debug_dump(__func__, true, true);
@@ -2019,7 +2038,7 @@ int prcmu_ac_wake_req(void)
 	}
 
 unlock_and_return:
-	mutex_unlock(&mb0.ac_wake_lock);
+	mutex_unlock(&mb0->ac_wake_lock);
 	return ret;
 }
 
@@ -2030,7 +2049,7 @@ void prcmu_ac_sleep_req()
 {
 	u32 val;
 
-	mutex_lock(&mb0.ac_wake_lock);
+	mutex_lock(&mb0->ac_wake_lock);
 
 	val = readl(PRCM_HOSTACCESS_REQ);
 	if (!(val & PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ))
@@ -2039,7 +2058,7 @@ void prcmu_ac_sleep_req()
 	writel((val & ~PRCM_HOSTACCESS_REQ_HOSTACCESS_REQ),
 		PRCM_HOSTACCESS_REQ);
 
-	if (!wait_for_completion_timeout(&mb0.ac_wake_work,
+	if (!wait_for_completion_timeout(&mb0->ac_wake_work,
 			msecs_to_jiffies(5000))) {
 		pr_crit("prcmu: %s timed out (5 s) waiting for a reply.\n",
 			__func__);
@@ -2048,7 +2067,7 @@ void prcmu_ac_sleep_req()
 	atomic_set(&ac_wake_req_state, 0);
 
 unlock_and_return:
-	mutex_unlock(&mb0.ac_wake_lock);
+	mutex_unlock(&mb0->ac_wake_lock);
 }
 
 static bool db8500_prcmu_is_ac_wake_requested(void)
@@ -2084,28 +2103,28 @@ static u16 db8500_prcmu_get_reset_code(void)
  */
 static void db8500_prcmu_modem_reset(void)
 {
-	mutex_lock(&mb1.lock);
+	mutex_lock(&mb1->lock);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(1))
 		cpu_relax();
 
 	writeb(MB1H_RESET_MODEM, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB1));
 	writel(MBOX_BIT(1), PRCM_MBOX_CPU_SET);
-	wait_for_completion(&mb1.work);
+	wait_for_completion(&mb1->work);
 
 	/*
 	 * No need to check return from PRCMU as modem should go in reset state
 	 * This state is already managed by upper layer
 	 */
 
-	mutex_unlock(&mb1.lock);
+	mutex_unlock(&mb1->lock);
 }
 
 static void ack_dbb_wakeup(void)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.lock, flags);
+	spin_lock_irqsave(&mb0->lock, flags);
 
 	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(0))
 		cpu_relax();
@@ -2114,7 +2133,7 @@ static void ack_dbb_wakeup(void)
 			tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB0);
 	writel(MBOX_BIT(0), PRCM_MBOX_CPU_SET);
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
 static inline void print_unknown_header_warning(u8 n, u8 header)
@@ -2142,11 +2161,11 @@ static bool read_mailbox_0(void)
 					PRCM_ACK_MB0_WAKEUP_0_8500);
 
 		if (ev & (WAKEUP_BIT_AC_WAKE_ACK | WAKEUP_BIT_AC_SLEEP_ACK))
-			complete(&mb0.ac_wake_work);
+			complete(&mb0->ac_wake_work);
 		if (ev & WAKEUP_BIT_SYSCLK_OK)
-			complete(&mb3.sysclk_work);
+			complete(&mb3->sysclk_work);
 
-		ev &= mb0.req.dbb_irqs;
+		ev &= mb0->req.dbb_irqs;
 
 		for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
 			if (ev & prcmu_irq_bit[n])
@@ -2165,25 +2184,25 @@ static bool read_mailbox_0(void)
 
 static bool read_mailbox_1(void)
 {
-	mb1.ack.header = readb(tcdm_legacy_base +
+	mb1->ack.header = readb(tcdm_legacy_base +
 			PRCM_MBOX_HEADER_REQ_MB1);
-	mb1.ack.arm_opp = readb(tcdm_legacy_base +
+	mb1->ack.arm_opp = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_CURRENT_ARM_OPP);
-	mb1.ack.ape_opp = readb(tcdm_legacy_base +
+	mb1->ack.ape_opp = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_CURRENT_APE_OPP);
-	mb1.ack.ape_voltage_status = readb(tcdm_legacy_base +
+	mb1->ack.ape_voltage_status = readb(tcdm_legacy_base +
 		PRCM_ACK_MB1_APE_VOLTAGE_STATUS);
 	writel(MBOX_BIT(1), PRCM_ARM_IT1_CLR);
-	complete(&mb1.work);
+	complete(&mb1->work);
 	return false;
 }
 
 static bool read_mailbox_2(void)
 {
-	mb2.ack.status = readb(tcdm_legacy_base
+	mb2->ack.status = readb(tcdm_legacy_base
 			+ PRCM_ACK_MB2_DPS_STATUS);
 	writel(MBOX_BIT(2), PRCM_ARM_IT1_CLR);
-	complete(&mb2.work);
+	complete(&mb2->work);
 	return false;
 }
 
@@ -2219,18 +2238,18 @@ static bool read_mailbox_4(void)
 	writel(MBOX_BIT(4), PRCM_ARM_IT1_CLR);
 
 	if (do_complete)
-		complete(&mb4.work);
+		complete(&mb4->work);
 
 	return false;
 }
 
 static bool read_mailbox_5(void)
 {
-	mb5.ack.status = readb(tcdm_legacy_base
+	mb5->ack.status = readb(tcdm_legacy_base
 			+ PRCM_ACK_MB5_I2C_STATUS);
-	mb5.ack.value = readb(tcdm_legacy_base + PRCM_ACK_MB5_I2C_VAL);
+	mb5->ack.value = readb(tcdm_legacy_base + PRCM_ACK_MB5_I2C_VAL);
 	writel(MBOX_BIT(5), PRCM_ARM_IT1_CLR);
-	complete(&mb5.work);
+	complete(&mb5->work);
 	return false;
 }
 
@@ -2246,7 +2265,7 @@ static bool read_mailbox_7(void)
 	return false;
 }
 
-static bool (* const read_mailbox[NUM_MB])(void) = {
+static bool (*db8500_read_mailbox[NUM_MB])(void) = {
 	read_mailbox_0,
 	read_mailbox_1,
 	read_mailbox_2,
@@ -2257,6 +2276,8 @@ static bool (* const read_mailbox[NUM_MB])(void) = {
 	read_mailbox_7
 };
 
+static bool (**read_mailbox)(void);
+
 static irqreturn_t prcmu_irq_handler(int irq, void *data)
 {
 	u32 bits;
@@ -2288,39 +2309,39 @@ static void prcmu_mask_work(struct work_struct *work)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.lock, flags);
+	spin_lock_irqsave(&mb0->lock, flags);
 
 	config_wakeups();
 
-	spin_unlock_irqrestore(&mb0.lock, flags);
+	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
 static void prcmu_irq_mask(struct irq_data *d)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.dbb_irqs_lock, flags);
+	spin_lock_irqsave(&mb0->dbb_irqs_lock, flags);
 
-	mb0.req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
+	mb0->req.dbb_irqs &= ~prcmu_irq_bit[d->hwirq];
 
-	spin_unlock_irqrestore(&mb0.dbb_irqs_lock, flags);
+	spin_unlock_irqrestore(&mb0->dbb_irqs_lock, flags);
 
 	if (d->irq != IRQ_PRCMU_CA_SLEEP)
-		schedule_work(&mb0.mask_work);
+		schedule_work(&mb0->mask_work);
 }
 
 static void prcmu_irq_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 
-	spin_lock_irqsave(&mb0.dbb_irqs_lock, flags);
+	spin_lock_irqsave(&mb0->dbb_irqs_lock, flags);
 
-	mb0.req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
+	mb0->req.dbb_irqs |= prcmu_irq_bit[d->hwirq];
 
-	spin_unlock_irqrestore(&mb0.dbb_irqs_lock, flags);
+	spin_unlock_irqrestore(&mb0->dbb_irqs_lock, flags);
 
 	if (d->irq != IRQ_PRCMU_CA_SLEEP)
-		schedule_work(&mb0.mask_work);
+		schedule_work(&mb0->mask_work);
 }
 
 static void noop(struct irq_data *d)
@@ -2553,6 +2574,62 @@ struct prcmu_fops_register_data db8500_probe_data = {
 	.tab = db8500_probe_tab,
 };
 
+int __init db8500_prcmu_init_mb0(struct mb0_transfer *mb)
+{
+	mb0 = mb;
+	spin_lock_init(&mb0->lock);
+	spin_lock_init(&mb0->dbb_irqs_lock);
+	mutex_init(&mb0->ac_wake_lock);
+	init_completion(&mb0->ac_wake_work);
+	INIT_WORK(&mb0->mask_work, prcmu_mask_work);
+
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb1(struct mb1_transfer *mb)
+{
+	mb1 = mb;
+	mutex_init(&mb1->lock);
+	init_completion(&mb1->work);
+	mb1->ape_opp = APE_NO_CHANGE;
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb2(struct mb2_transfer *mb)
+{
+	mb2 = mb;
+	mutex_init(&mb2->lock);
+	init_completion(&mb2->work);
+	spin_lock_init(&mb2->auto_pm_lock);
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb3(struct mb3_transfer *mb)
+{
+	mb3 = mb;
+	spin_lock_init(&mb3->lock);
+	mutex_init(&mb3->sysclk_lock);
+	init_completion(&mb3->sysclk_work);
+	spin_lock_init(&mb3->fw_log_lock);
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb4(struct mb4_transfer *mb)
+{
+	mb4 = mb;
+	mutex_init(&mb4->lock);
+	init_completion(&mb4->work);
+	return 0;
+}
+
+int __init db8500_prcmu_init_mb5(struct mb5_transfer *mb)
+{
+	mb5 = mb;
+	mutex_init(&mb5->lock);
+	init_completion(&mb5->work);
+	return 0;
+}
+
 static int db8500_irq_map(struct irq_domain *d, unsigned int virq,
 				irq_hw_number_t hwirq)
 {
@@ -2582,10 +2659,23 @@ static int db8500_irq_init(struct device_node *np)
 	return 0;
 }
 
+int __init db8500_prcmu_context_init(struct prcmu_context *context)
+{
+	/* initialize PRCMU driver context */
+	tcdm_base = context->tcdm_base;
+	tcdm_legacy_base = context->tcdm_legacy_base;
+	fw_trans = context->fw_trans;
+	fw_trans_nb = context->fw_trans_nb;
+	read_mailbox = context->read_mbox;
+
+	return 0;
+}
+
 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);
+	struct prcmu_context context;
 
 	if (tcpm_base != NULL) {
 		u32 version;
@@ -2601,28 +2691,21 @@ struct prcmu_fops_register_data *__init
 			(version >> 24) & 0xFF);
 		iounmap(tcpm_base);
 	}
-	tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE, map->tcdm_size);
-	tcdm_legacy_base = tcdm_base + map->legacy_offset;
-
-	spin_lock_init(&mb0.lock);
-	spin_lock_init(&mb0.dbb_irqs_lock);
-	mutex_init(&mb0.ac_wake_lock);
-	init_completion(&mb0.ac_wake_work);
-	mutex_init(&mb1.lock);
-	init_completion(&mb1.work);
-	mb1.ape_opp = APE_NO_CHANGE;
-	mutex_init(&mb2.lock);
-	init_completion(&mb2.work);
-	spin_lock_init(&mb2.auto_pm_lock);
-	spin_lock_init(&mb3.lock);
-	mutex_init(&mb3.sysclk_lock);
-	init_completion(&mb3.sysclk_work);
-	mutex_init(&mb4.lock);
-	init_completion(&mb4.work);
-	mutex_init(&mb5.lock);
-	init_completion(&mb5.work);
-
-	INIT_WORK(&mb0.mask_work, prcmu_mask_work);
+
+	context.tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE,
+			map->tcdm_size);
+	context.tcdm_legacy_base = context.tcdm_base + map->legacy_offset;
+	context.fw_trans = db8500_fw_trans;
+	context.fw_trans_nb = ARRAY_SIZE(db8500_fw_trans);
+	context.read_mbox = db8500_read_mailbox;
+	db8500_prcmu_context_init(&context);
+
+	db8500_prcmu_init_mb0(&db8500_mb0);
+	db8500_prcmu_init_mb1(&db8500_mb1);
+	db8500_prcmu_init_mb2(&db8500_mb2);
+	db8500_prcmu_init_mb3(&db8500_mb3);
+	db8500_prcmu_init_mb4(&db8500_mb4);
+	db8500_prcmu_init_mb5(&db8500_mb5);
 
 	/*  early init of dbx500-prcmu */
 	return &db8500_early_data;
diff --git a/drivers/mfd/dbx500-prcmu.h b/drivers/mfd/dbx500-prcmu.h
index 79cba24..ce0e519 100644
--- a/drivers/mfd/dbx500-prcmu.h
+++ b/drivers/mfd/dbx500-prcmu.h
@@ -376,3 +376,19 @@ struct mb5_transfer {
 	} ack;
 };
 
+/*
+ * prcmu_context - PRCMU common layer need to be configured
+ * @tcdm_base:	PRCMU TCDM base address
+ * @tcdm_legacy_base:	Base address for legacy mailbox
+ * @fw_trans:  Firmware power transition list
+ * @fw_trans_nb: Nb of firmware power transitions
+ * @read_mbox: Pointer on mailbox interrupt management
+ */
+struct prcmu_context {
+	void *tcdm_base;
+	void *tcdm_legacy_base;
+	u8 *fw_trans;
+	u32 fw_trans_nb;
+	bool (**read_mbox)(void);
+};
+
-- 
1.7.11.1


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

* [PATCH 14/17] mfd: db8500-prcmu: use db8500 legacy services
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (12 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 13/17] mfd: prcmu: make legacy mailbox services configurable Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05 11:01   ` Arnd Bergmann
  2012-09-05  9:59 ` [PATCH 15/17] mfd: dbx540-prcmu creation Loic Pallardy
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

This patch exposes db8500 legacy services which are
now available to support new baseband.
If different are needed, then services are overloaded.
This allows to reduce duplicate code between projects.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/db8500-prcmu.c | 90 +++++++++++++++++++++++-----------------------
 drivers/mfd/dbx500-prcmu.h | 71 ++++++++++++++++++++++++++++++++++++
 2 files changed, 116 insertions(+), 45 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index 73c98e5..b39441f 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -327,12 +327,12 @@ int db8500_prcmu_set_display_clocks(void)
 	return 0;
 }
 
-static u32 db8500_prcmu_read(unsigned int reg)
+u32 db8500_prcmu_read(unsigned int reg)
 {
 	return readl(_PRCMU_BASE + reg);
 }
 
-static void db8500_prcmu_write(unsigned int reg, u32 value)
+void db8500_prcmu_write(unsigned int reg, u32 value)
 {
 	unsigned long flags;
 
@@ -341,7 +341,7 @@ static void db8500_prcmu_write(unsigned int reg, u32 value)
 	spin_unlock_irqrestore(&prcmu_lock, flags);
 }
 
-static void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
+void db8500_prcmu_write_masked(unsigned int reg, u32 mask, u32 value)
 {
 	u32 val;
 	unsigned long flags;
@@ -517,7 +517,7 @@ int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll)
 	return 0;
 }
 
-static u8 db8500_prcmu_get_power_state_result(void)
+u8 db8500_prcmu_get_power_state_result(void)
 {
 	return readb(tcdm_legacy_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
 }
@@ -668,7 +668,7 @@ static void config_wakeups(void)
 	last_abb_events = abb_events;
 }
 
-static void db8500_prcmu_enable_wakeups(u32 wakeups)
+void db8500_prcmu_enable_wakeups(u32 wakeups)
 {
 	unsigned long flags;
 	u32 bits;
@@ -689,7 +689,7 @@ static void db8500_prcmu_enable_wakeups(u32 wakeups)
 	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
-static void db8500_prcmu_config_abb_event_readout(u32 abb_events)
+void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 {
 	unsigned long flags;
 
@@ -701,7 +701,7 @@ static void db8500_prcmu_config_abb_event_readout(u32 abb_events)
 	spin_unlock_irqrestore(&mb0->lock, flags);
 }
 
-static void db8500_prcmu_get_abb_event_buffer(void __iomem **buf)
+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);
@@ -1002,7 +1002,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.
  */
-static int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
+int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state)
 {
 	int r = 0;
 	bool ram_retention = false;
@@ -1068,7 +1068,7 @@ unlock_and_return:
  * @sleep: Configuration for ApSleep.
  * @idle:  Configuration for ApIdle.
  */
-static void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
+void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
 	struct prcmu_auto_pm_config *idle)
 {
 	u32 sleep_cfg;
@@ -1844,7 +1844,7 @@ static int prcmu_a9wdog(u8 cmd, u8 d0, u8 d1, u8 d2, u8 d3)
 
 }
 
-static int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
+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,
@@ -1852,17 +1852,17 @@ static int db8500_prcmu_config_a9wdog(u8 num, bool sleep_auto_off)
 			    A9WDOG_AUTO_OFF_DIS);
 }
 
-static int db8500_prcmu_enable_a9wdog(u8 id)
+int db8500_prcmu_enable_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_EN, id, 0, 0, 0);
 }
 
-static int db8500_prcmu_disable_a9wdog(u8 id)
+int db8500_prcmu_disable_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_DIS, id, 0, 0, 0);
 }
 
-static int db8500_prcmu_kick_a9wdog(u8 id)
+int db8500_prcmu_kick_a9wdog(u8 id)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_KICK, id, 0, 0, 0);
 }
@@ -1870,7 +1870,7 @@ static int db8500_prcmu_kick_a9wdog(u8 id)
 /*
  * timeout is 28 bit, in ms.
  */
-static int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
+int db8500_prcmu_load_a9wdog(u8 id, u32 timeout)
 {
 	return prcmu_a9wdog(MB4H_A9WDOG_LOAD,
 			    (id & A9WDOG_ID_MASK) |
@@ -1894,7 +1894,7 @@ static 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.
  */
-static int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
+int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size)
 {
 	int r;
 
@@ -1945,7 +1945,7 @@ static int db8500_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.
  */
-static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
+int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
 		u8 size)
 {
 	int r;
@@ -1991,7 +1991,7 @@ static int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask,
  * Writes register value(s) to the ABB.
  * @size has to be 1 for the current firmware version.
  */
-static int db8500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
+int db8500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size)
 {
 	u8 mask = ~0;
 
@@ -2081,7 +2081,7 @@ static 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
  */
-static void db8500_prcmu_system_reset(u16 reset_code)
+void db8500_prcmu_system_reset(u16 reset_code)
 {
 	writew(reset_code, (tcdm_legacy_base + PRCM_SW_RST_REASON));
 	writel(1, PRCM_APE_SOFTRST);
@@ -2142,7 +2142,7 @@ static inline void print_unknown_header_warning(u8 n, u8 header)
 		header, n);
 }
 
-static bool read_mailbox_0(void)
+bool db8500_prcmu_read_mailbox_0(void)
 {
 	bool r;
 	u32 ev;
@@ -2182,7 +2182,7 @@ static bool read_mailbox_0(void)
 	return r;
 }
 
-static bool read_mailbox_1(void)
+bool db8500_prcmu_read_mailbox_1(void)
 {
 	mb1->ack.header = readb(tcdm_legacy_base +
 			PRCM_MBOX_HEADER_REQ_MB1);
@@ -2197,7 +2197,7 @@ static bool read_mailbox_1(void)
 	return false;
 }
 
-static bool read_mailbox_2(void)
+bool db8500_prcmu_read_mailbox_2(void)
 {
 	mb2->ack.status = readb(tcdm_legacy_base
 			+ PRCM_ACK_MB2_DPS_STATUS);
@@ -2206,13 +2206,13 @@ static bool read_mailbox_2(void)
 	return false;
 }
 
-static bool read_mailbox_3(void)
+bool db8500_prcmu_read_mailbox_3(void)
 {
 	writel(MBOX_BIT(3), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
-static bool read_mailbox_4(void)
+bool db8500_prcmu_read_mailbox_4(void)
 {
 	u8 header;
 	bool do_complete = true;
@@ -2243,7 +2243,7 @@ static bool read_mailbox_4(void)
 	return false;
 }
 
-static bool read_mailbox_5(void)
+bool db8500_prcmu_read_mailbox_5(void)
 {
 	mb5->ack.status = readb(tcdm_legacy_base
 			+ PRCM_ACK_MB5_I2C_STATUS);
@@ -2253,32 +2253,32 @@ static bool read_mailbox_5(void)
 	return false;
 }
 
-static bool read_mailbox_6(void)
+bool db8500_prcmu_read_mailbox_6(void)
 {
 	writel(MBOX_BIT(6), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
-static bool read_mailbox_7(void)
+bool db8500_prcmu_read_mailbox_7(void)
 {
 	writel(MBOX_BIT(7), PRCM_ARM_IT1_CLR);
 	return false;
 }
 
 static bool (*db8500_read_mailbox[NUM_MB])(void) = {
-	read_mailbox_0,
-	read_mailbox_1,
-	read_mailbox_2,
-	read_mailbox_3,
-	read_mailbox_4,
-	read_mailbox_5,
-	read_mailbox_6,
-	read_mailbox_7
+	db8500_prcmu_read_mailbox_0,
+	db8500_prcmu_read_mailbox_1,
+	db8500_prcmu_read_mailbox_2,
+	db8500_prcmu_read_mailbox_3,
+	db8500_prcmu_read_mailbox_4,
+	db8500_prcmu_read_mailbox_5,
+	db8500_prcmu_read_mailbox_6,
+	db8500_prcmu_read_mailbox_7
 };
 
 static bool (**read_mailbox)(void);
 
-static irqreturn_t prcmu_irq_handler(int irq, void *data)
+irqreturn_t db8500_prcmu_irq_handler(int irq, void *data)
 {
 	u32 bits;
 	u8 n;
@@ -2299,7 +2299,7 @@ static irqreturn_t prcmu_irq_handler(int irq, void *data)
 	return r;
 }
 
-static irqreturn_t prcmu_irq_thread_fn(int irq, void *data)
+irqreturn_t db8500_prcmu_irq_thread_fn(int irq, void *data)
 {
 	ack_dbb_wakeup();
 	return IRQ_HANDLED;
@@ -2389,7 +2389,7 @@ static inline void db8500_prcmu_clear(unsigned int reg, u32 bits)
 }
 
 
-static int db8500_prcmu_enable_spi2(void)
+int db8500_prcmu_enable_spi2(void)
 {
 	db8500_prcmu_set(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
 	return 0;
@@ -2398,7 +2398,7 @@ static int db8500_prcmu_enable_spi2(void)
 /**
  * prcmu_disable_spi2 - Disables pin muxing for SPI2 on OtherAlternateC1.
  */
-static int db8500_prcmu_disable_spi2(void)
+int db8500_prcmu_disable_spi2(void)
 {
 	db8500_prcmu_clear(DB8500_PRCM_GPIOCR, DB8500_PRCM_GPIOCR_SPI2_SELECT);
 	return 0;
@@ -2408,7 +2408,7 @@ static int db8500_prcmu_disable_spi2(void)
  * prcmu_enable_stm_mod_uart - Enables pin muxing for STMMOD
  * and UARTMOD on OtherAlternateC3.
  */
-static int db8500_prcmu_enable_stm_mod_uart(void)
+int db8500_prcmu_enable_stm_mod_uart(void)
 {
 	db8500_prcmu_set(DB8500_PRCM_GPIOCR,
 			(DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
@@ -2420,7 +2420,7 @@ static int db8500_prcmu_enable_stm_mod_uart(void)
  * prcmu_disable_stm_mod_uart - Disables pin muxing for STMMOD
  * and UARTMOD on OtherAlternateC3.
  */
-static int db8500_prcmu_disable_stm_mod_uart(void)
+int db8500_prcmu_disable_stm_mod_uart(void)
 {
 	db8500_prcmu_clear(DB8500_PRCM_GPIOCR,
 			(DB8500_PRCM_GPIOCR_DBG_STM_MOD_CMD1 |
@@ -2431,7 +2431,7 @@ static int db8500_prcmu_disable_stm_mod_uart(void)
 /**
  * prcmu_enable_stm_ape - Enables pin muxing for STM APE on OtherAlternateC1.
  */
-static int db8500_prcmu_enable_stm_ape(void)
+int db8500_prcmu_enable_stm_ape(void)
 {
 	db8500_prcmu_set(DB8500_PRCM_GPIOCR,
 			DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
@@ -2441,7 +2441,7 @@ static int db8500_prcmu_enable_stm_ape(void)
 /**
  * prcmu_disable_stm_ape - Disables pin muxing for STM APE on OtherAlternateC1.
  */
-static int db8500_prcmu_disable_stm_ape(void)
+int db8500_prcmu_disable_stm_ape(void)
 {
 	db8500_prcmu_clear(DB8500_PRCM_GPIOCR,
 			DB8500_PRCM_GPIOCR_DBG_STM_APE_CMD);
@@ -2645,7 +2645,7 @@ static struct irq_domain_ops db8500_irq_ops = {
         .xlate  = irq_domain_xlate_twocell,
 };
 
-static int db8500_irq_init(struct device_node *np)
+int db8500_irq_init(struct device_node *np)
 {
 	db8500_irq_domain = irq_domain_add_legacy(
 		np, NUM_PRCMU_WAKEUPS, IRQ_PRCMU_BASE,
@@ -3034,8 +3034,8 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
 	if (!np || irq <= 0)
 		irq = IRQ_DB8500_PRCMU1;
 
-	err = request_threaded_irq(irq, prcmu_irq_handler,
-	        prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
+	err = request_threaded_irq(irq, db8500_prcmu_irq_handler,
+		db8500_prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
 	if (err < 0) {
 		pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n");
 		err = -EBUSY;
diff --git a/drivers/mfd/dbx500-prcmu.h b/drivers/mfd/dbx500-prcmu.h
index ce0e519..037695d 100644
--- a/drivers/mfd/dbx500-prcmu.h
+++ b/drivers/mfd/dbx500-prcmu.h
@@ -392,3 +392,74 @@ struct prcmu_context {
 	bool (**read_mbox)(void);
 };
 
+/* initialization */
+int db8500_prcmu_context_init(struct prcmu_context *context);
+int db8500_irq_init(struct device_node *np);
+int db8500_prcmu_clean_mailbox_irq(void);
+char *fw_project_name(u32 project);
+
+/* interrupt management */
+irqreturn_t db8500_prcmu_irq_handler(int irq, void *data);
+irqreturn_t db8500_prcmu_irq_thread_fn(int irq, void *data);
+
+/*  debug */
+void db8500_prcmu_debug_dump(const char *func,
+				bool dump_prcmu, bool dump_abb);
+
+/* mailbox services */
+int db8500_prcmu_init_mb0(struct mb0_transfer *mb);
+int db8500_prcmu_init_mb1(struct mb1_transfer *mb);
+int db8500_prcmu_init_mb2(struct mb2_transfer *mb);
+int db8500_prcmu_init_mb3(struct mb3_transfer *mb);
+int db8500_prcmu_init_mb4(struct mb4_transfer *mb);
+int db8500_prcmu_init_mb5(struct mb5_transfer *mb);
+
+bool db8500_prcmu_read_mailbox_0(void);
+bool db8500_prcmu_read_mailbox_1(void);
+bool db8500_prcmu_read_mailbox_2(void);
+bool db8500_prcmu_read_mailbox_3(void);
+bool db8500_prcmu_read_mailbox_4(void);
+bool db8500_prcmu_read_mailbox_5(void);
+bool db8500_prcmu_read_mailbox_6(void);
+bool db8500_prcmu_read_mailbox_7(void);
+
+/* PRCMU services */
+void db8500_prcmu_system_reset(u16 reset_code);
+
+/* direct access */
+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);
+
+void db8500_prcmu_vc(bool enable);
+int db8500_prcmu_set_epod(u16 epod_id, u8 epod_state);
+
+int db8500_prcmu_set_power_state(u8 state, bool keep_ulp_clk, bool keep_ap_pll);
+u8 db8500_prcmu_get_power_state_result(void);
+void db8500_prcmu_enable_wakeups(u32 wakeups);
+void db8500_prcmu_configure_auto_pm(struct prcmu_auto_pm_config *sleep,
+	struct prcmu_auto_pm_config *idle);
+
+/* ABB access */
+void db8500_prcmu_config_abb_event_readout(u32 abb_events);
+void db8500_prcmu_get_abb_event_buffer(void __iomem **buf);
+
+int db8500_prcmu_abb_read(u8 slave, u8 reg, u8 *value, u8 size);
+int db8500_prcmu_abb_read_no_irq(u8 slave, u8 reg, u8 *value, u8 size);
+int db8500_prcmu_abb_write(u8 slave, u8 reg, u8 *value, u8 size);
+int db8500_prcmu_abb_write_masked(u8 slave, u8 reg, u8 *value, u8 *mask, u8 size);
+
+/* a9 watchdog */
+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 timeout);
+
+/* peripheral management */
+int db8500_prcmu_enable_spi2(void);
+int db8500_prcmu_disable_spi2(void);
+int db8500_prcmu_enable_stm_mod_uart(void);
+int db8500_prcmu_disable_stm_mod_uart(void);
+int db8500_prcmu_enable_stm_ape(void);
+int db8500_prcmu_disable_stm_ape(void);
-- 
1.7.11.1


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

* [PATCH 15/17] mfd: dbx540-prcmu creation
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (13 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 14/17] mfd: db8500-prcmu: use db8500 legacy services Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05 12:10   ` Arnd Bergmann
  2012-09-05  9:59 ` [PATCH 16/17] arm: ux500: add dbx540 prcmu platform data Loic Pallardy
  2012-09-05  9:59 ` [PATCH 17/17] mfd: db8500-prcmu: activate dbx540-prcmu driver Loic Pallardy
  16 siblings, 1 reply; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

This driver offers support for ST-Ericsson DB9540 and
DB8540 PRCMU.
- add new communication interface named UniqPAP
- add support for x540 HW

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/Kconfig              |   11 +
 drivers/mfd/Makefile             |    1 +
 drivers/mfd/dbx500-prcmu-regs.h  |    1 +
 drivers/mfd/dbx540-prcmu-regs.h  |  106 ++
 drivers/mfd/dbx540-prcmu.c       | 2807 ++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/db8500-prcmu.h |    6 +-
 include/linux/mfd/dbx500-prcmu.h |   24 +
 include/linux/mfd/dbx540-prcmu.h |   96 ++
 8 files changed, 3049 insertions(+), 3 deletions(-)
 create mode 100644 drivers/mfd/dbx540-prcmu-regs.h
 create mode 100644 drivers/mfd/dbx540-prcmu.c
 create mode 100644 include/linux/mfd/dbx540-prcmu.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3420844..bb8444c 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -821,6 +821,17 @@ config MFD_DB8500_PRCMU
 	  system controller running an XP70 microprocessor, which is accessed
 	  through a register map.
 
+config MFD_DBX540_PRCMU
+	bool "ST-Ericsson DB9540/DB8540 Power Reset Control Management Unit"
+	depends on UX500_SOC_DB8500
+	select MFD_CORE
+	select MFD_DB8500_PRCMU
+	help
+	  Select this option to enable support for the DB9540/DB8540 Power Reset
+	  and Control Management Unit. This is basically an autonomous
+	  system controller running an XP70 microprocessor, which is accessed
+	  through a register map.
+
 config MFD_CS5535
 	tristate "Support for CS5535 and CS5536 southbridge core functions"
 	select MFD_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 42d703a..8715743 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -108,6 +108,7 @@ 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
+obj-$(CONFIG_MFD_DBX540_PRCMU)  += dbx540-prcmu.o
 # ab8500-core need to come after db8500-prcmu (which provides the channel)
 obj-$(CONFIG_AB8500_CORE)	+= ab8500-core.o ab8500-sysctrl.o
 obj-$(CONFIG_MFD_TIMBERDALE)    += timberdale.o
diff --git a/drivers/mfd/dbx500-prcmu-regs.h b/drivers/mfd/dbx500-prcmu-regs.h
index 23108a6..888baf6 100644
--- a/drivers/mfd/dbx500-prcmu-regs.h
+++ b/drivers/mfd/dbx500-prcmu-regs.h
@@ -83,6 +83,7 @@
 #define PRCM_ARM_WFI_STANDBY_WFI1               0x10
 #define PRCM_IOCR		(_PRCMU_BASE + 0x310)
 #define PRCM_IOCR_IOFORCE			0x1
+#define PRCM_IOCR_TDO_PULLUP_ENABLE		0x2
 
 /* CPU mailbox registers */
 #define PRCM_MBOX_CPU_VAL	(_PRCMU_BASE + 0x0fc)
diff --git a/drivers/mfd/dbx540-prcmu-regs.h b/drivers/mfd/dbx540-prcmu-regs.h
new file mode 100644
index 0000000..a15810d
--- /dev/null
+++ b/drivers/mfd/dbx540-prcmu-regs.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) STMicroelectronics 2012
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * Author: michel jaouen <michel.jaouen@stericsson.com>
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * PRCM Unit registers
+ */
+
+#ifndef __DBX540_PRCMU_REGS_H
+#define __DBX540_PRCMU_REGS_H
+
+#include "dbx500-prcmu-regs.h"
+
+#define PRCM_SPARE1CLK_MGT	PRCM_CLK_MGT(0x048)
+#define	PRCM_C2CCLK_MGT		PRCM_CLK_MGT(0x108)
+#define PRCM_G1CLK_MGT		PRCM_CLK_MGT(0x548)
+#define PRCM_HVACLK_MGT		PRCM_CLK_MGT(0x54C)
+
+
+#define PRCM_POWER_STATE_VAL_VAPE_STATE_OPP_MASK	BITS(1, 3)
+#define PRCM_POWER_STATE_VAL_VAPE_STATE_OPP_SHIFT	1
+#define PRCM_POWER_STATE_VAL_VARM_STATE_OPP_MASK	BITS(28, 30)
+#define PRCM_POWER_STATE_VAL_VARM_STATE_OPP_SHIFT	28
+
+#define PRCM_PLLDSITV_FREQ         (_PRCMU_BASE + 0x500)
+#define PRCM_PLLDSITV_ENABLE       (_PRCMU_BASE + 0x504)
+#define PRCM_PLLDSITV_LOCKP        (_PRCMU_BASE + 0x508)
+#define PRCM_PLLDSILCD_FREQ        (_PRCMU_BASE + 0x290)
+#define PRCM_PLLDSILCD_ENABLE      (_PRCMU_BASE + 0x294)
+#define PRCM_PLLDSILCD_LOCKP       (_PRCMU_BASE + 0x298)
+
+#define PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT		0
+#define U8500_PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK	BITS(0, 2)
+#define U9540_PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK	BITS(0, 3)
+#define PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT		8
+#define U8500_PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK	BITS(8, 10)
+#define U9540_PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK	BITS(8, 11)
+
+
+#define PRCM_APE_RESETN_DSIPLL_TV_RESETN		BIT(14)
+#define PRCM_APE_RESETN_DSIPLL_LCD_RESETN		BIT(15)
+
+
+#define PRCM_EPOD_C_CLR            (_PRCMU_BASE + 0x414)
+#define PRCM_EPOD_C_VAL            (_PRCMU_BASE + 0x418)
+#define PRCM_EPOD_VOK              (_PRCMU_BASE + 0x41C)
+
+#define PRCM_DDR1_SUBSYS_APE_MINBW	(_PRCMU_BASE + 0x2438)
+
+
+/* C2C related PRCM register */
+#define	PRCM_C2C_RESETN_SET     (_PRCMU_BASE + 0x2B0)
+#define	PRCM_C2C_RESETN_CLR     (_PRCMU_BASE + 0x2B4)
+#define	PRCM_C2C_RESETN_VAL     (_PRCMU_BASE + 0x2B8)
+
+#define PRCM_C2C_RESETN_C2C_WRAPPER_PER		BIT(0)
+#define PRCM_C2C_RESETN_C2C_CORE		BIT(1)
+#define PRCM_C2C_RESETN_HVA_LOGIC		BIT(2)
+#define PRCM_C2C_RESETN_HVA_MEM			BIT(3)
+#define PRCM_C2C_RESETN_G1_LOGIC		BIT(4)
+#define PRCM_C2C_RESETN_G1_MEM			BIT(5)
+
+#define	PRCM_C2C_CTL_SET        (_PRCMU_BASE + 0x4F4)
+#define	PRCM_C2C_CTL_CLR        (_PRCMU_BASE + 0x4F8)
+#define	PRCM_C2C_CTL_VAL        (_PRCMU_BASE + 0x4FC)
+
+#define	PRCM_C2CSUBSYS_STATUS   (_PRCMU_BASE + 0x2024)
+#define	PRCM_C2CSUBSYS_CONTROL_SET (_PRCMU_BASE + 0x2048)
+#define	PRCM_C2CSUBSYS_CONTROL_CLR (_PRCMU_BASE + 0x204C)
+#define	PRCM_C2CSUBSYS_CONTROL_VAL (_PRCMU_BASE + 0x2050)
+#define	PRCM_C2C_SSCM_GENI_SET  (_PRCMU_BASE + 0x2054)
+#define	PRCM_C2C_SSCM_GENI_CLR  (_PRCMU_BASE + 0x2058)
+#define	PRCM_C2C_SSCM_GENI_VAL  (_PRCMU_BASE + 0x205C)
+#define	PRCM_C2C_SSCM_GENO      (_PRCMU_BASE + 0x2060)
+#define	PRCM_C2C_COMPCR         (_PRCMU_BASE + 0x2064)
+#define	PRCM_C2C_COMPSTA        (_PRCMU_BASE + 0x2068)
+#define	PRCM_C2C_IO_CTL_SET     (_PRCMU_BASE + 0x202C)
+#define	PRCM_C2C_IO_CTL_CLR     (_PRCMU_BASE + 0x2030)
+#define	PRCM_C2C_IO_CTL_VAL     (_PRCMU_BASE + 0x2034)
+#define	PRCM_A9_C2C_GENO_MASK_SET (_PRCMU_BASE + 0x2078)
+#define	PRCM_A9_C2C_GENO_MASK_CLR (_PRCMU_BASE + 0x207C)
+#define	PRCM_A9_C2C_GENO_MASK_VAL (_PRCMU_BASE + 0x2080)
+#define	PRCM_C2C_MEM_REQ        (_PRCMU_BASE + 0x2038)
+#define	PRCM_C2C_MEM_ACK        (_PRCMU_BASE + 0x203C)
+#define	PRCM_C2C_MEM_LAT        (_PRCMU_BASE + 0x2040)
+#define	PRCM_C2C_MEM_MIN_BW     (_PRCMU_BASE + 0x2044)
+#define	PRCM_ITSTATUS7          (_PRCMU_BASE + 0x24B8)
+#define	PRCM_ITCLR7             (_PRCMU_BASE + 0x24BC)
+#define	PRCM_LINE_VALUE7        (_PRCMU_BASE + 0x24C0)
+#define	PRCM_HOLD_EVT7          (_PRCMU_BASE + 0x24C4)
+#define	PRCM_EDGE_SENS_L7       (_PRCMU_BASE + 0x24C8)
+#define	PRCM_EDGE_SENS_H7       (_PRCMU_BASE + 0x24CC)
+#define	PRCM_ITSTATUS8          (_PRCMU_BASE + 0x24D0)
+#define	PRCM_ITCLR8             (_PRCMU_BASE + 0x24D4)
+#define	PRCM_LINE_VALUE8        (_PRCMU_BASE + 0x24D8)
+#define	PRCM_HOLD_EVT8          (_PRCMU_BASE + 0x24DC)
+#define	PRCM_EDGE_SENS_L8       (_PRCMU_BASE + 0x24E0)
+#define	PRCM_EDGE_SENS_H8       (_PRCMU_BASE + 0x24E4)
+
+#define	PRCM_SPARE_OUT          (_PRCMU_BASE + 0x2070)
+#define	PRCM_SPARE_OUT_PSW_SDMMC BIT(1)
+
+#endif /* __DBX540_PRCMU_REGS_H */
diff --git a/drivers/mfd/dbx540-prcmu.c b/drivers/mfd/dbx540-prcmu.c
new file mode 100644
index 0000000..374ba6c
--- /dev/null
+++ b/drivers/mfd/dbx540-prcmu.c
@@ -0,0 +1,2807 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2012
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Michel Jaouen <michel.jaouen@stericsson.com>
+ * Author: Alexandre Torgue <alexandre.torgues@stericsson.com>
+ * Author: David Paris <david.paris@stericsson.com>
+ * Author: Etienne Carriere <etienne.carriere@stericsson.com>
+ * Author: Guillaume KOUADIO CARRY <guillaume.kouadio-carry@stericsson.com>
+ * DBX540 PRCM Unit interface driver
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/bitops.h>
+#include <linux/fs.h>
+#include <linux/cpufreq.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/of.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/dbx500-prcmu.h>
+#include <linux/regulator/db8500-prcmu.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/abx500.h>
+#include <linux/time.h>
+#include <linux/sched.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/db8500-regs.h>
+#include <mach/hardware.h>
+
+#include "dbx500-prcmu.h"
+#include "dbx500-prcmu-regs.h"
+#include "dbx540-prcmu-regs.h"
+
+/* Global var to runtime determine TCDM base for v2 or v1 */
+static __iomem void *tcdm_legacy_base;
+static __iomem void *tcdm_base;
+
+/* mailbox definition */
+static struct mb0_transfer mb0;
+static struct mb2_transfer mb2;
+static struct mb3_transfer mb3;
+static struct mb4_transfer mb4;
+static struct mb5_transfer mb5;
+
+/* Offset for the firmware version within the TCPM */
+#define PRCMU_FW_VERSION_OFFSET 0xA4
+
+#define PRCM_BOOT_STATUS	0xFFF
+
+#define PRCM_SW_RST_REASON 0xFF8 /* 2 bytes */
+
+#define PRCM_TCDM_VOICE_CALL_FLAG 0xDD4 /* 4 bytes */
+
+#define U9540_PRCM_UPAP_OFFSET		0x0A00
+
+/*
+ * UniqPAP (Request/Response/Notify) - U9540
+ */
+struct upap_arm_opp_req_data {
+	u32 freq;
+	u16 volt;
+	u16 bias;
+	u16 vbbp;
+	u16 vbbn;
+};
+
+struct upap_req {
+	u32 req_state;
+	u32 service_id;
+	u32 command_id;
+	u32 status;
+	union {
+		u32 data; /*  default: single 32bit data */
+		struct upap_arm_opp_req_data arm_opp;
+		u8 full_data_buf[4*6];	 /*  TODO: check size from xp70 API */
+	} data;
+};
+
+struct upap_nfy {
+	u32 nfy_state;
+	u32 service_id;
+	u32 command_id;
+	union {
+		u32 data; /*  default: single 32bit data */
+		u8 full_data_buf[4];	 /*  TODO: check size from xp70 API */
+	} data;
+};
+
+/*  UniqPAP timeout */
+#define UPAP_TIM (HZ/10)
+
+/* UniqPAP Configuration */
+static struct upap_configuration {
+	struct upap_req *req;
+	struct upap_nfy *nfy;
+	u8 mbox_nb;
+} upap_conf;
+
+enum upap_req_state {
+	U9540_PRCM_UPAP_REQ_STATE_REQ_IDLE = 0,
+	U9540_PRCM_UPAP_REQ_STATE_REQ_SENT,
+	U9540_PRCM_UPAP_REQ_STATE_REQ_EXECUTING,
+	U9540_PRCM_UPAP_REQ_STATE_ACK_SENT,
+};
+
+enum upap_nfy_state {
+	U9540_PRCM_UPAP_NFY_STATE_IDLE = 0,
+	U9540_PRCM_UPAP_NFY_STATE_ONGOING,
+	U9540_PRCM_UPAP_NFY_STATE_SENT,
+};
+
+enum upap_service {
+	U9540_PRCM_UPAP_SERVICE_DDR = 0,
+	U9540_PRCM_UPAP_SERVICE_DVFS,
+	U9540_PRCM_UPAP_SERVICE_MODEM,
+	U9540_PRCM_UPAP_SERVICE_USB,
+	U9540_PRCM_UPAP_SERVICE_CLOCK,
+	U9540_PRCM_UPAP_SERVICE_C2C,
+	U9540_PRCM_UPAP_SERVICE_CPUHOTPLUG,
+	U9540_PRCM_UPAP_SERVICE_THSENSOR,
+	UPAP_SERVICES_NB,
+};
+
+enum upap_command {
+	/* req/resp commands */
+	U9540_PRCM_UPAP_COMMAND_SET_ARM_OPP = 0x1002,
+	U9540_PRCM_UPAP_COMMAND_SET_APE_OPP = 0x1003,
+	U9540_PRCM_UPAP_COMMAND_SET_SAFE_OPP = 0x1004,
+	U9540_PRCM_UPAP_COMMAND_DDR_SLEEP_STRAT = 0x2005,
+	U9540_PRCM_UPAP_COMMAND_RESET_MODEM = 0x3001,
+	U9540_PRCM_UPAP_COMMAND_USB_WAKEUP_REL = 0x4001,
+	U9540_PRCM_UPAP_COMMAND_PLL_ON_OFF = 0x5001,
+	U9540_PRCM_UPAP_COMMAND_C2CINIT = 0x6001,
+	U9540_PRCM_UPAP_COMMAND_C2CNOTIFYME = 0x6002,
+	U9540_PRCM_UPAP_COMMAND_C2CTESTWAKEUP = 0x6003,
+	U9540_PRCM_UPAP_COMMAND_C2CTESTSLEEP = 0x6004,
+	U9540_PRCM_UPAP_COMMAND_C2CRESET = 0x6005,
+	U9540_PRCM_UPAP_COMMAND_CPU1_UNPLUG = 0x7001,
+	U9540_PRCM_UPAP_COMMAND_CPU1_REPLUG = 0x7002,
+	/* nfy commands */
+	U9540_PRCM_UPAP_COMMAND_C2CNOTIFICATION = 0x601,
+	U9540_PRCM_UPAP_COMMAND_THSENSOR_GET_TEMP = 0x8001,
+};
+
+enum upap_status {
+	U9540_PRCM_UPAP_STATUS_OK = 0,
+	/* all non-0 IDs below report an error */
+	U9540_PRCM_UPAP_STATUS_UNKNOWN_CMD_ID,
+	U9540_PRCM_UPAP_STATUS_BAD_PARAM,
+	U9540_PRCM_UPAP_STATUS_PARTIAL_SELF_REFRESH_DDR_EXEC,
+	U9540_PRCM_UPAP_STATUS_QOS_DDR_EXEC,
+	U9540_PRCM_UPAP_STATUS_SET_ARM_OPP_EXEC,
+	U9540_PRCM_UPAP_STATUS_SET_ARM_OPP_INVAL,
+	U9540_PRCM_UPAP_STATUS_SET_APE_OPP_EXEC,
+	U9540_PRCM_UPAP_STATUS_SET_APE_OPP_INVAL,
+	U9540_PRCM_UPAP_STATUS_SET_SAFE_OPP_EXEC,
+	U9540_PRCM_UPAP_STATUS_SET_SAFE_OPP_INVAL,
+	U9540_PRCM_UPAP_STATUS_DVFS_PLL_NOT_LOCKED,
+	U9540_PRCM_UPAP_STATUS_C2C_UNKNOWN_ERR,
+	U9540_PRCM_UPAP_STATUS_BAD_STATE,
+	U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_ALRDY_UNPLUGED,
+	U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_NOT_UNPLUGED,
+	U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_SECURE_ROM_ERR,
+	U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_UNKNOWN_ERR,
+	U9540_PRCM_UPAP_STATUS_INVALID_STATE,
+	U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_ARMVOK_TIMEOUT,
+	U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_ROMCODESAVEOWNCTX_ERR,
+	U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_WAKEUPNORESP_ROM_ERR,
+	U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_RESPLSNOTDSTOREADY,
+	U9540_PRCM_UPAP_STATUS_OVERFLOW,
+	U9540_PRCM_UPAP_STATUS_BUSY,
+	U9540_PRCM_UPAP_STATUS_SET_ARM_OPP_FREQ_ERR,
+	U9540_PRCM_UPAP_STATUS_THSENSOR_ALL_READY,
+};
+
+enum upap_ape_opp_ids {
+	U9540_PRCM_REQ_UPAP_APE_OPP_1 = 0,
+	U9540_PRCM_REQ_UPAP_APE_OPP_2,
+};
+
+enum upap_pll_on_off_ids {
+	U9540_PRCM_REQ_UPAP_PLL_SOC0_OFF = 1,
+	U9540_PRCM_REQ_UPAP_PLL_SOC0_ON	= 2,
+	U9540_PRCM_REQ_UPAP_PLL_SOC1_OFF = 4,
+	U9540_PRCM_REQ_UPAP_PLL_SOC1_ON	= 8,
+};
+
+enum upap_vsafe_opp_ids {
+	U9540_PRCM_REQ_UPAP_VSAFE_OPP0 = 0,
+	U9540_PRCM_REQ_UPAP_VSAFE_OPP1,
+	U9540_PRCM_REQ_UPAP_VSAFE_OPP2,
+};
+
+enum uupap_c2c_ids {
+	U9540_PRCM_UPAP_NFYDAT_C2CNOTIF_OK = 0x601,
+	U9540_PRCM_REQ_DATA_C2C_NOTIFYME = 0x601,
+};
+
+/* UniqPAP Acknowledgement data: data copied from upap buffer */
+struct upap_ack {
+	u32 service_id;
+	u32 command_id;
+	u32 status;
+	u32 arm_freq;
+	u32 sensor_read;
+};
+
+/*
+ * upap_transfer - state needed for UniqPAP communication.
+ * @lock:	The transaction lock.
+ * @work:	The transaction completion structure.
+ * @ape_opp:	The current APE OPP.
+ * @arm_freq:	The current ARM Freq (U9540 only)
+ * @ack:	Reply ("acknowledge") data. Structure used selected at run-
+ *		time based on chip-set detected.
+ */
+static struct {
+	struct mutex lock;
+	struct completion work;
+	struct upap_ack *ack;
+} upap_transfer;
+
+/*
+ * dvfs_transfer - PRCMU need to save some dvfs context
+ * @ape_opp:	The current APE OPP.
+ * @arm_freq:	The current ARM Freq (U9540 only)
+ * @vsafe_opp:  The current Vsafe state (U9540 only)
+ */
+struct {
+	u8 ape_opp;
+	u32 arm_freq;
+	u8 vsafe_opp;
+} dvfs_context;
+
+static void (*upap_read_services[UPAP_SERVICES_NB])(struct upap_req *req,
+		struct upap_ack *ack);
+
+static int cpu1_unplug_ongoing;
+static int prcmu_driver_initialised;
+static int set_arm_freq(u32 freq);
+static int get_arm_freq(void);
+
+static struct {
+	bool valid;
+	struct prcmu_fw_version version;
+} fw_info;
+
+static unsigned long latest_armss_rate;
+
+/*The timer time-base is in nano-seconde*/
+#define TIME_NS 1000000000ULL
+/* profiling cycle time (in second)*/
+#define PROFILING_CYCLE_TIME 4ULL
+/* STORE_CYCLE = TIME_NS*PROFILING_CYCLE_TIME in NS*/
+#define STORE_CYCLE (TIME_NS * PROFILING_CYCLE_TIME)
+/* 9540 aging in second (8 years by default)*/
+#define	DB9540_AGING 252288000ULL
+/* 9540 aging in nano-second*/
+#define	DB9540_AGING_TRADE (DB9540_AGING * TIME_NS)
+
+/* SecMap is at 0x300 from tcdm_legacy_base adress*/
+#define PRCMU_SECMAP 0x0300
+/* InitOppData is at 0x598 from SecMap */
+#define PRCM_INIT_OPP_DATA (PRCMU_SECMAP + 0x0598)
+/* OPP0 table is at 0x48 from InitOppData */
+#define PRCMU_OPP0_TABLE (PRCM_INIT_OPP_DATA + 0x0048)
+/* OPP0 enable/disable is at 0x6 from OPP0 table*/
+#define PRCMU_OPP0_IS_ENABLE (PRCMU_OPP0_TABLE + 0x0006)
+
+struct max_opp_profile {
+	u32 last_arm_opp;
+	u64 max_opp_cnt;
+	u64 secure_memory;
+	u64 cumul;
+	u64 start;
+};
+
+static struct max_opp_profile arm_max_opp_profile = {
+	.last_arm_opp = 0,
+	.max_opp_cnt = 0,
+	.secure_memory = 0,
+	.cumul = 0,
+	.start = 0,
+};
+
+static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
+
+/* Spinlocks */
+static DEFINE_SPINLOCK(prcmu_lock);
+static DEFINE_SPINLOCK(clkout_lock);
+static DEFINE_SPINLOCK(spare_out_lock);
+
+/*
+ * Copies of the startup values of the reset status register and the SW reset
+ * code.
+ */
+static u32 reset_status_copy;
+static u16 reset_code_copy;
+
+static DEFINE_SPINLOCK(clk_mgt_lock);
+
+#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
+	{ (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
+static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
+	CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
+	CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(MSP02CLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(MSP1CLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(I2CCLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(SDMMCCLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(SLIMCLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(PER1CLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(PER2CLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(PER3CLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(PER5CLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(HDMICLK, PLL_FIX, false),
+	CLK_MGT_ENTRY(APEATCLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(APETRACECLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(MCDECLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(IPI2CCLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(DSIALTCLK, PLL_FIX, false),
+	CLK_MGT_ENTRY(DMACLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(ACLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(B2R2CLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(TVCLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(SSPCLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(RNGCLK, PLL_FIX, true),
+	CLK_MGT_ENTRY(UICCCLK, PLL_FIX, false),
+	CLK_MGT_ENTRY(HVACLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(G1CLK, PLL_DIV, true),
+	CLK_MGT_ENTRY(SPARE1CLK, PLL_FIX, true),
+};
+
+struct dsiclk {
+	u32 divsel_mask;
+	u32 divsel_shift;
+	u32 divsel;
+	u32 divsel_lcd_mask; /* For LCD DSI PLL supported by U9540 */
+};
+
+static struct dsiclk u9540_dsiclk[2] = {
+	{
+		.divsel_mask =
+			U9540_PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_MASK,
+		.divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI0_PLLOUT_DIVSEL_SHIFT,
+		.divsel = PRCM_DSI_PLLOUT_SEL_PHI,
+		.divsel_lcd_mask = BIT(3),
+	},
+	{
+		.divsel_mask =
+			U9540_PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_MASK,
+		.divsel_shift = PRCM_DSI_PLLOUT_SEL_DSI1_PLLOUT_DIVSEL_SHIFT,
+		.divsel = PRCM_DSI_PLLOUT_SEL_PHI,
+		.divsel_lcd_mask = BIT(11),
+	}
+};
+
+struct dsiescclk {
+	u32 en;
+	u32 div_mask;
+	u32 div_shift;
+};
+
+static struct dsiescclk dsiescclk[3] = {
+	{
+		.en = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_EN,
+		.div_mask = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_MASK,
+		.div_shift = PRCM_DSITVCLK_DIV_DSI0_ESC_CLK_DIV_SHIFT,
+	},
+	{
+		.en = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_EN,
+		.div_mask = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_MASK,
+		.div_shift = PRCM_DSITVCLK_DIV_DSI1_ESC_CLK_DIV_SHIFT,
+	},
+	{
+		.en = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_EN,
+		.div_mask = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_MASK,
+		.div_shift = PRCM_DSITVCLK_DIV_DSI2_ESC_CLK_DIV_SHIFT,
+	}
+};
+
+static u32 ddr_sleep_strat_policy[PRCMU_DDR_SLEEP_STRAT_LP_MODE_NB]
+					[PRCMU_DDR_SLEEP_STRAT_DDRCTRL_NB] =
+{
+	{
+		DDRCTRLSTATE_ON, /* Ctrl0ApIdle */
+		DDRCTRLSTATE_ON  /* Ctrl1ApIdle */
+	},
+	{
+		DDRCTRLSTATE_ON, /* Ctrl0ApDeepIdle */
+		DDRCTRLSTATE_ON  /* Ctrl1ApDeepIdle */
+	},
+	{
+		DDRCTRLSTATE_OFFHIGHLAT, /* Ctrl0ApSleep */
+		DDRCTRLSTATE_OFFHIGHLAT  /* Ctrl1ApSleep */
+	}
+};
+
+/*
+* Used by MCDE to setup all necessary PRCMU registers
+*/
+#define PRCMU_RESET_DSIPLLTV		0x00004000
+#define PRCMU_RESET_DSIPLLLCD		0x00008000
+#define PRCMU_UNCLAMP_DSIPLL		0x00400800
+
+#define PRCMU_CLK_PLL_DIV_SHIFT		0
+#define PRCMU_CLK_PLL_SW_SHIFT		5
+#define PRCMU_CLK_38			(1 << 9)
+#define PRCMU_CLK_38_SRC		(1 << 10)
+#define PRCMU_CLK_38_DIV		(1 << 11)
+
+/* PLLDIV=12, PLLSW=4 (PLLDDR) */
+#define PRCMU_DSI_CLOCK_SETTING		0x0000008C
+/* PLLDIV = 12, PLLSW=1 (PLLSOC0) */
+#define U9540_PRCMU_DSI_CLOCK_SETTING	0x0000002C
+
+/* DPI 50000000 Hz */
+#define PRCMU_DPI_CLOCK_SETTING		((1 << PRCMU_CLK_PLL_SW_SHIFT) | \
+					  (16 << PRCMU_CLK_PLL_DIV_SHIFT))
+#define PRCMU_DSI_LP_CLOCK_SETTING	0x00000E00
+
+/* D=101, N=1, R=4, SELDIV2=0 */
+#define PRCMU_PLLDSI_FREQ_SETTING	0x00040165
+
+#define PRCMU_ENABLE_PLLDSI		0x00000001
+#define PRCMU_DISABLE_PLLDSI		0x00000000
+#define PRCMU_RELEASE_RESET_DSS		0x0000400C
+#define PRCMU_TV_DSI_PLLOUT_SEL_SETTING	0x00000202
+#define PRCMU_LCD_DSI_PLLOUT_SEL_SETTING	0x00000A0A
+/* ESC clk, div0=1, div1=1, div2=3 */
+#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV	0x07030101
+#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV	0x00030101
+#define PRCMU_DSI_RESET_SW		0x00000007
+
+#define PRCMU_PLLDSI_LOCKP_LOCKED	0x3
+
+/**
+ * upap_init
+ * initialization UniqPAP link
+ */
+static void upap_init(void)
+{
+	upap_conf.req = (struct upap_req *)(tcdm_base + U9540_PRCM_UPAP_OFFSET);
+	upap_conf.nfy = (struct upap_nfy *)(tcdm_base + U9540_PRCM_UPAP_OFFSET +
+			sizeof(struct upap_req));
+	upap_conf.mbox_nb = 1;
+
+	mutex_init(&upap_transfer.lock);
+	init_completion(&upap_transfer.work);
+}
+
+/**
+ * db9540_prcmu_upap_wait_released
+ * Utility function which blocks until Mailbox is released.
+ */
+static inline void db9540_prcmu_upap_wait_released(void)
+{
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(upap_conf.mbox_nb))
+		cpu_relax();
+}
+
+/**
+ * db9540_prcmu_upap_wait_for_idle
+ * Utility function which blocks until uniqPAP is in its Idle state.
+ */
+static inline void db9540_prcmu_upap_wait_for_idle(void)
+{
+	while (upap_conf.req->req_state != U9540_PRCM_UPAP_REQ_STATE_REQ_IDLE)
+		cpu_relax();
+}
+
+/**
+ * upap_send_request
+ * Generic to send UniqPAP request to PRCMU
+ */
+static void upap_send_request(struct upap_req *req, struct upap_ack *ack,
+		int data_size)
+{
+	mutex_lock(&upap_transfer.lock);
+
+	/* save ack structure */
+	upap_transfer.ack = ack;
+
+	/* Wait for MBOX to become idle */
+	db9540_prcmu_upap_wait_released();
+	/* Ensure MB1 is in Idle state */
+	db9540_prcmu_upap_wait_for_idle();
+
+	/* Write to TCDM (header and data, then req_state) */
+	upap_conf.req->service_id = req->service_id;
+	upap_conf.req->command_id = req->command_id;
+	upap_conf.req->req_state = req->req_state;
+	if (data_size)
+		memcpy(&upap_conf.req->data.data, &req->data.data, data_size);
+
+	/* Set interrupt ARM -> PRCMU */
+	writel(MBOX_BIT(upap_conf.mbox_nb), PRCM_MBOX_CPU_SET);
+	WARN_ON(wait_for_completion_timeout(&upap_transfer.work, UPAP_TIM)== 0);
+
+	mutex_unlock(&upap_transfer.lock);
+}
+
+/**
+ * upap_register_ack_service
+ * dynamic service acknoledge registering
+ */
+static int upap_register_ack_service(u32 service_id, void (*service_ack)(struct upap_req *req,
+		struct upap_ack *ack))
+{
+	if(service_id >= UPAP_SERVICES_NB)
+		return -EINVAL;
+
+	if(upap_read_services[service_id] == NULL)
+		upap_read_services[service_id] = service_ack;
+	else
+		return -EBUSY;
+	return 0;
+}
+
+/**
+ * unplug_cpu1 - Power gate OFF CPU1 for U9540
+ * * void:
+ * Returns:
+ */
+static int unplug_cpu1(void)
+{
+	int r = 0;
+#ifdef CONFIG_UX500_ROMCODE_SHARED_MUTEX
+	struct upap_req req;
+	struct upap_ack ack;
+
+	/* Set flag start Hotplug sequence */
+	cpu1_unplug_ongoing = 1;
+
+	/* Fill request (header and data, then req_state) */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_CPUHOTPLUG;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_CPU1_UNPLUG;
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, 0);
+
+	/* Check response from PRCMU */
+	if ((ack.service_id == U9540_PRCM_UPAP_SERVICE_CPUHOTPLUG) &&
+		(ack.command_id == U9540_PRCM_UPAP_COMMAND_CPU1_UNPLUG)) {
+		switch (ack.status) {
+		case U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_UNKNOWN_ERR:
+			pr_err("PRCMU: %s, unknown error\n", __func__);
+			WARN_ON(1);
+			break;
+		case U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_ROMCODESAVEOWNCTX_ERR:
+			pr_err("PRCMU: %s, CPU1 ROM code err: save own context error\n"
+			, __func__);
+			break;
+	}
+	} else {
+		r = -EIO;
+		pr_err("PRCMU - bad ack in %s. %u %u %u\n", __func__,
+		ack.service_id, ack.command_id, ack.status);
+	}
+	/* set flag HotPlug sequence end */
+	cpu1_unplug_ongoing = 0;
+#endif
+	return r;
+}
+
+/**
+ * replug_cpu1 - Power gate ON CPU1 for U9540
+ * * void
+ * * Returns:
+ */
+static int replug_cpu1(void)
+{
+	int r = 0;
+#ifdef CONFIG_UX500_ROMCODE_SHARED_MUTEX
+	struct upap_req req;
+	struct upap_ack ack;
+
+	if (prcmu_driver_initialised == 0) {
+		pr_info("PRCMU: %s, PRCMU DRIVER NOT INITIALISED\n", __func__);
+		return 0;
+	}
+
+	/* Fill request (header and data, then req_state) */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_CPUHOTPLUG;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_CPU1_REPLUG;
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, 0);
+
+	/* Check response from PRCMU */
+	if ((ack.service_id == U9540_PRCM_UPAP_SERVICE_CPUHOTPLUG) &&
+		(ack.command_id == U9540_PRCM_UPAP_COMMAND_CPU1_REPLUG)) {
+		switch (ack.status) {
+		case U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_UNKNOWN_ERR:
+			pr_err("PRCMU: %s, unknown error\n", __func__);
+			WARN_ON(1);
+			break;
+		case U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_WAKEUPNORESP_ROM_ERR:
+			pr_err("PRCMU: %s, CPU1 Rom code err: no resp at wake up\n"
+					, __func__);
+			WARN_ON(1);
+			break;
+		case U9540_PRCM_UPAP_STATUS_CPUHOTPLUG_RESPLSNOTDSTOREADY:
+			pr_err("PRCMU: %s, CPU1 Rom code err: no Ds to Rdy\n"
+					, __func__);
+			WARN_ON(1);
+			break;
+	}
+	} else {
+		r = -EIO;
+		pr_err("PRCMU - bad ack in %s. %u %u %u\n", __func__,
+		ack.service_id, ack.command_id, ack.status);
+	}
+#endif
+	return r;
+}
+
+static struct cpufreq_frequency_table *freq_table;
+
+static struct prcmu_fw_version *get_fw_version(void)
+{
+	return fw_info.valid ? &fw_info.version : NULL;
+}
+
+
+bool has_arm_maxopp(void)
+{
+	if(readw(tcdm_base+PRCMU_OPP0_IS_ENABLE) != 1)
+		return false;
+	else
+		return true;
+}
+
+static void update_freq_table(struct cpufreq_frequency_table *table)
+{
+	if (has_arm_maxopp())
+		table[5].frequency = 1850000;
+#ifdef CONFIG_MFD_DBX540_FREQ_LIMITATION
+	{
+		int i;
+		/*  remove 266 MHz frequency that creates re-entering condition */
+		for (i = 0; i < 5; i++)
+			table[i].frequency = table[i+1].frequency;
+		table[5].frequency = CPUFREQ_TABLE_END;
+	}
+#endif
+}
+
+/**
+ * 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.
+ *
+ * Configures one of the programmable clock outputs (CLKOUTs).
+ * @div should be in the range [1,63] to request a configuration, or 0 to
+ * inform that the configuration is no longer requested.
+ */
+static int config_clkout(u8 clkout, u8 source, u8 div)
+{
+	static int requests[2];
+	int r = 0;
+	unsigned long flags;
+	u32 val;
+	u32 bits;
+	u32 mask;
+	u32 div_mask;
+
+	BUG_ON(clkout > 1);
+	BUG_ON(div > 63);
+	BUG_ON((clkout == 0) && (source > PRCMU_CLKSRC_CLK009));
+
+	if (!div && !requests[clkout])
+		return -EINVAL;
+
+	switch (clkout) {
+	case 0:
+		div_mask = PRCM_CLKOCR_CLKODIV0_MASK;
+		mask = (PRCM_CLKOCR_CLKODIV0_MASK | PRCM_CLKOCR_CLKOSEL0_MASK);
+		bits = ((source << PRCM_CLKOCR_CLKOSEL0_SHIFT) |
+			(div << PRCM_CLKOCR_CLKODIV0_SHIFT));
+		break;
+	case 1:
+		div_mask = PRCM_CLKOCR_CLKODIV1_MASK;
+		mask = (PRCM_CLKOCR_CLKODIV1_MASK | PRCM_CLKOCR_CLKOSEL1_MASK |
+			PRCM_CLKOCR_CLK1TYPE);
+		bits = ((source << PRCM_CLKOCR_CLKOSEL1_SHIFT) |
+			(div << PRCM_CLKOCR_CLKODIV1_SHIFT));
+		break;
+	}
+	bits &= mask;
+
+	spin_lock_irqsave(&clkout_lock, flags);
+
+	val = readl(PRCM_CLKOCR);
+	if (val & div_mask) {
+		if (div) {
+			if ((val & mask) != bits) {
+				r = -EBUSY;
+				goto unlock_and_return;
+			}
+		} else {
+			if ((val & mask & ~div_mask) != bits) {
+				r = -EINVAL;
+				goto unlock_and_return;
+			}
+		}
+	}
+	writel((bits | (val & ~mask)), PRCM_CLKOCR);
+	requests[clkout] += (div ? 1 : -1);
+
+unlock_and_return:
+	spin_unlock_irqrestore(&clkout_lock, flags);
+
+	return r;
+}
+
+/*  transition translation table to FW magic number */
+static u8 dbx540_fw_trans[] = {
+	0x00,/* PRCMU_AP_NO_CHANGE */
+	0x10,/* PRCMU_AP_SLEEP */
+	0x43,/* PRCMU_AP_DEEP_SLEEP */
+	0x50,/* PRCMU_AP_IDLE */
+	0x73,/*	PRCMU_AP_DEEP_IDLE */
+};
+
+static int stay_in_wfi_check(void)
+{
+	int stay_in_wfi = 0;
+	u8 status;
+
+	status = readb(tcdm_legacy_base + PRCM_ACK_MB0_AP_PWRSTTR_STATUS);
+
+	if ((status == EXECUTETODEEPSLEEP)
+			|| (status == EXECUTETODEEPIDLE)) {
+		stay_in_wfi = 1;
+	}
+	if (cpu1_unplug_ongoing == 1)
+		stay_in_wfi = 1;
+
+	return stay_in_wfi;
+}
+
+/*
+ * set_arm_freq - set the appropriate ARM frequency for U9540
+ * @freq: The new ARM frequency to which transition is to be made (kHz)
+ * Returns: 0 on success, non-zero on failure
+ */
+static int set_arm_freq(u32 freq)
+{
+	struct upap_req req;
+	struct upap_ack ack;
+	int r = 0;
+
+	if (dvfs_context.arm_freq == freq)
+		return 0;
+
+	/* Prepare request (header and data, then req_state) */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_DVFS;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_SET_ARM_OPP;
+	req.data.arm_opp.freq = freq;
+	req.data.arm_opp.volt = 0;
+	req.data.arm_opp.bias = 0;
+	req.data.arm_opp.vbbp = 0;
+	req.data.arm_opp.vbbn = 0;
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, sizeof(struct upap_arm_opp_req_data));
+
+	/* Check response from PRCMU */
+	if ((ack.service_id == U9540_PRCM_UPAP_SERVICE_DVFS) &&
+		(ack.command_id == U9540_PRCM_UPAP_COMMAND_SET_ARM_OPP) &&
+		(ack.status == U9540_PRCM_UPAP_STATUS_OK)) {
+		dvfs_context.arm_freq = freq;
+		latest_armss_rate = freq;
+	} else {
+		r = -EIO;
+		pr_info("PRCMU - bad ack in %s. %u %u %u %u %u\n", __func__,
+		ack.service_id, ack.command_id, ack.status, ack.arm_freq,
+		freq);
+	}
+
+	return r;
+}
+
+/**
+ * get_arm_freq - get the current ARM freq
+ *
+ * Returns: the current ARM freq (kHz).
+ * Not supported by U8500
+ */
+static int get_arm_freq(void)
+{
+	u32 val;
+	/*
+	 * U9540 is not able to read ARM OPP value from TCDM. Therefore
+	 * determine if the ARM OPP has been set, or not.
+	 */
+	if (dvfs_context.arm_freq != 0)
+		return dvfs_context.arm_freq;
+
+	/* ARM OPP value not yet initialised. Read value from register. */
+	val = readl(PRCM_POWER_STATE_VAL);
+	val &= PRCM_POWER_STATE_VAL_VARM_STATE_OPP_MASK;
+	val >>= PRCM_POWER_STATE_VAL_VARM_STATE_OPP_SHIFT;
+
+	switch (val) {
+	case 0x00:
+		return 1850000;
+	case 0x01:
+		return 1500000;
+	case 0x02:
+		return 1200000;
+	case 0x03:
+		return 800000;
+	case 0x04:
+		return 400000;
+	case 0x05:
+		return 266000;
+	default:
+		pr_warn("prcmu: %s Unknown ARM OPP val %d\n", __func__, val);
+		/* Return fastest non-"speed-binned" frequency */
+		return 1500000;
+	}
+}
+
+/**
+ * prcmu_get_vsafe_opp - get the current VSAFE OPP
+ *
+ * Returns: the current VSAFE OPP
+ */
+int prcmu_get_vsafe_opp(void)
+{
+	/*
+	 * U9540 is not able to read VSAFE OPP value from TCDM. Therefore
+	 * determine if the VSAFE OPP has been set, or not.
+	 */
+	if (dvfs_context.vsafe_opp != 0) {
+		return dvfs_context.vsafe_opp;
+	} else {
+		/*
+		 * VSAFE OPP value not yet initialised.
+		 * Return default (reset) value.
+		 */
+		return VSAFE_100_OPP;
+	}
+}
+
+/**
+ * prcmu_set_vsafe_opp - set the appropriate VSAFE OPP
+ * @opp: The new VSAFE operating point to which transition is to be made
+ * Returns: 0 on success, non-zero on failure
+ *
+ * This function sets the operating point of the VSAFE.
+ */
+int prcmu_set_vsafe_opp(u8 opp)
+{
+	struct upap_req req;
+	struct upap_ack ack;
+	int r = 0;
+	u32 prcmu_opp;
+
+	switch (opp) {
+	case VSAFE_50_OPP:
+	case VSAFE_100_OPP:
+		prcmu_opp = U9540_PRCM_REQ_UPAP_VSAFE_OPP2;
+		break;
+	default:
+		/* Do nothing */
+		return 0;
+	}
+
+	/* Prepare request */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_DVFS;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_SET_SAFE_OPP;
+	req.data.data = prcmu_opp;
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, sizeof(u32));
+
+	/*
+	 * Check response from PRCMU. U9540 TCDM does not contain current OPP
+	 * so we cannot check its value.
+	 */
+	if ((ack.service_id == U9540_PRCM_UPAP_SERVICE_DVFS) &&
+		(ack.command_id == U9540_PRCM_UPAP_COMMAND_SET_SAFE_OPP) &&
+		(ack.status == U9540_PRCM_UPAP_STATUS_OK)) {
+		dvfs_context.vsafe_opp = prcmu_opp;
+	} else {
+		r = -EIO;
+		pr_info("PRCMU - bad ack in %s. %u %u %u %u\n", __func__,
+		ack.service_id, ack.command_id, ack.status, opp);
+	}
+
+	return r;
+}
+
+/**
+ * get_ddr_opp - get the current DDR OPP
+ *
+ * Returns: the current DDR OPP
+ */
+int get_ddr_opp(void)
+{
+	return readb(PRCM_DDR_SUBSYS_APE_MINBW);
+}
+
+/**
+ * get_ddr1_opp - get the current DDR1 OPP
+ *
+ * Returns: the current DDR1 OPP
+ */
+int get_ddr1_opp(void)
+{
+	return readb(PRCM_DDR1_SUBSYS_APE_MINBW);
+}
+
+/**
+ * set_ddr_opp - set the appropriate DDR OPP
+ * @opp: The new DDR operating point to which transition is to be made
+ * Returns: 0 on success, non-zero on failure
+ *
+ * This function sets the operating point of the DDR.
+ */
+int set_ddr_opp(u8 opp)
+{
+	if (opp < DDR_100_OPP || opp > DDR_25_OPP)
+		return -EINVAL;
+	/* Changing the DDR OPP can hang the hardware pre-v21 */
+	writeb(opp, PRCM_DDR_SUBSYS_APE_MINBW);
+	writeb(opp, PRCM_DDR1_SUBSYS_APE_MINBW);
+
+	return 0;
+}
+
+/* Divide the frequency of certain clocks by 2 for APE_50_PARTLY_25_OPP. */
+static void request_even_slower_clocks(bool enable)
+{
+	void __iomem *clock_reg[] = {
+		PRCM_ACLK_MGT,
+		PRCM_DMACLK_MGT
+	};
+	unsigned long flags;
+	unsigned int i;
+
+	spin_lock_irqsave(&clk_mgt_lock, flags);
+
+	/* Grab the HW semaphore. */
+	while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+		cpu_relax();
+
+	for (i = 0; i < ARRAY_SIZE(clock_reg); i++) {
+		u32 val;
+		u32 div;
+
+		val = readl(clock_reg[i]);
+		div = (val & PRCM_CLK_MGT_CLKPLLDIV_MASK);
+		if (enable) {
+			if ((div <= 1) || (div > 15)) {
+				pr_err("prcmu: Bad clock divider %d in %s\n",
+					div, __func__);
+				goto unlock_and_return;
+			}
+			div <<= 1;
+		} else {
+			if (div <= 2)
+				goto unlock_and_return;
+			div >>= 1;
+		}
+		val = ((val & ~PRCM_CLK_MGT_CLKPLLDIV_MASK) |
+			(div & PRCM_CLK_MGT_CLKPLLDIV_MASK));
+		writel(val, clock_reg[i]);
+	}
+
+unlock_and_return:
+	/* Release the HW semaphore. */
+	writel(0, PRCM_SEM);
+
+	spin_unlock_irqrestore(&clk_mgt_lock, flags);
+}
+
+static int db9540_prcmu_write_ape_opp(u8 opp)
+{
+	struct upap_req req;
+	struct upap_ack ack;
+	int r = 0;
+	u32 prcmu_opp;
+
+	switch (opp) {
+	case APE_50_OPP:
+	case APE_50_PARTLY_25_OPP:
+		prcmu_opp = U9540_PRCM_REQ_UPAP_APE_OPP_1;
+		break;
+	case APE_100_OPP:
+		prcmu_opp = U9540_PRCM_REQ_UPAP_APE_OPP_2;
+		break;
+	case APE_OPP_INIT:
+	case APE_NO_CHANGE:
+	default:
+		/* Do nothing */
+		return 0;
+	}
+
+	/* Prepare request */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_DVFS;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_SET_APE_OPP;
+	req.data.data = prcmu_opp;
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, sizeof(u32));
+
+	/*
+	 * Check response from PRCMU. U9540 TCDM does not contain current OPP
+	 * so we cannot check its value.
+	 */
+	if ((ack.service_id == U9540_PRCM_UPAP_SERVICE_DVFS) &&
+		(ack.command_id == U9540_PRCM_UPAP_COMMAND_SET_APE_OPP) &&
+		(ack.status == U9540_PRCM_UPAP_STATUS_OK)) {
+		r = 0;
+	} else {
+		r = -EIO;
+		pr_info("PRCMU - bad ack in %s. %u %u %u %u\n", __func__,
+		ack.service_id, ack.command_id, ack.status, prcmu_opp);
+	}
+
+	return r;
+}
+
+/**
+ * set_ape_opp - set the appropriate APE OPP
+ * @opp: The new APE operating point to which transition is to be made
+ * Returns: 0 on success, non-zero on failure
+ *
+ * This function sets the operating point of the APE.
+ */
+static int set_ape_opp(u8 opp)
+{
+	int r = 0;
+
+	if (opp == dvfs_context.ape_opp)
+		return 0;
+
+	/* Exit APE_50_PARTLY_25_OPP */
+	if (dvfs_context.ape_opp == APE_50_PARTLY_25_OPP)
+		request_even_slower_clocks(false);
+
+	if ((opp != APE_100_OPP) && (dvfs_context.ape_opp != APE_100_OPP))
+		goto skip_message;
+
+	r = db9540_prcmu_write_ape_opp(opp);
+skip_message:
+	if ((!r && (opp == APE_50_PARTLY_25_OPP)) ||
+			/* Set APE_50_PARTLY_25_OPP back in case new opp failed */
+			(r && (dvfs_context.ape_opp == APE_50_PARTLY_25_OPP)))
+		request_even_slower_clocks(true);
+	if (!r)
+		dvfs_context.ape_opp = opp;
+
+	return r;
+}
+
+/**
+ * get_ape_opp - get the current APE OPP
+ *
+ * Returns: the current APE OPP
+ */
+static int get_ape_opp(void)
+{
+	u32 val;
+	/*
+	 * U9540 is not able to read APE OPP value from TCDM. Therefore
+	 * determine if the APE OPP has been set, or not.
+	 */
+	if (dvfs_context.ape_opp != APE_OPP_INIT)
+		return dvfs_context.ape_opp;
+
+	/*
+	 * APE OPP value not yet initialised. Read value from
+	 * register.
+	 */
+	val = readl(PRCM_POWER_STATE_VAL);
+	val &= PRCM_POWER_STATE_VAL_VAPE_STATE_OPP_MASK;
+	val >>= PRCM_POWER_STATE_VAL_VAPE_STATE_OPP_SHIFT;
+	switch (val) {
+	case 0x00:
+		return APE_100_OPP;
+	case 0x01:
+		return APE_50_OPP;
+	default:
+		pr_warn("prcmu: %s Unknown APE OPP val %d\n", __func__, val);
+		return APE_OPP_INIT;
+	}
+}
+
+/**
+ * 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.
+ * Not supported by U9540
+ */
+static int request_ape_opp_100_voltage(bool enable)
+{
+	pr_debug("prcmu: %s not supported\n", __func__);
+	return 0;
+}
+
+static int db9540_prcmu_release_usb_wakeup_state(void)
+{
+	struct upap_req req;
+	struct upap_ack ack;
+	int r = 0;
+
+	/* Write to TCDM */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_USB;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_USB_WAKEUP_REL;
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, 0);
+
+	/* Check response from PRCMU */
+	if ((ack.service_id == U9540_PRCM_UPAP_SERVICE_USB) &&
+			(ack.command_id ==
+			 U9540_PRCM_UPAP_COMMAND_USB_WAKEUP_REL) &&
+			(ack.status == U9540_PRCM_UPAP_STATUS_OK)) {
+		r = 0;
+	} else {
+		r = -EIO;
+		pr_info("PRCMU - bad ack in %s. %u %u %u\n", __func__,
+				ack.service_id, ack.command_id, ack.status);
+	}
+
+	return r;
+}
+
+/**
+ * dbx540_prcmu_release_usb_wakeup_state - release the state required by a USB wakeup
+ *
+ * This function releases the power state requirements of a USB wakeup.
+ */
+int dbx540_prcmu_release_usb_wakeup_state(void)
+{
+	return (db9540_prcmu_release_usb_wakeup_state());
+}
+
+static int db9540_request_pll(u8 clock, bool enable)
+{
+	int r;
+	u32 prcmu_clock;
+	struct upap_req req;
+	struct upap_ack ack;
+
+	if (clock == PRCMU_PLLSOC0)
+		prcmu_clock = (enable ? U9540_PRCM_REQ_UPAP_PLL_SOC0_ON :
+				U9540_PRCM_REQ_UPAP_PLL_SOC0_OFF);
+	else if (clock == PRCMU_PLLSOC1)
+		prcmu_clock = (enable ? U9540_PRCM_REQ_UPAP_PLL_SOC1_ON :
+				U9540_PRCM_REQ_UPAP_PLL_SOC1_OFF);
+
+	/* Prepare request */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_CLOCK;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_PLL_ON_OFF;
+	req.data.data = prcmu_clock;
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, sizeof(u32));
+
+	/* Check response from PRCMU */
+	if ((ack.service_id == U9540_PRCM_UPAP_SERVICE_CLOCK) &&
+			(ack.command_id == U9540_PRCM_UPAP_COMMAND_PLL_ON_OFF)
+			&& (ack.status == U9540_PRCM_UPAP_STATUS_OK))
+		r = 0;
+	else {
+		r = -EIO;
+		pr_info("PRCMU - bad ack in %s. %u %u %u\n", __func__,
+				ack.service_id, ack.command_id, ack.status);
+	}
+
+	return r;
+}
+
+static int request_pll(u8 clock, bool enable)
+{
+	if (clock != PRCMU_PLLSOC1)
+		return -EINVAL;
+
+	 return db9540_request_pll(clock, enable);
+}
+
+static int request_sysclk(bool enable)
+{
+	int r = 0;
+	unsigned long flags;
+
+	mutex_lock(&mb3.sysclk_lock);
+
+	spin_lock_irqsave(&mb3.lock, flags);
+
+	while (readl(PRCM_MBOX_CPU_VAL) & MBOX_BIT(3))
+		cpu_relax();
+
+	writeb((enable ? ON : OFF), tcdm_legacy_base + PRCM_REQ_MB3_SYSCLK_MGT);
+
+	writeb(MB3H_SYSCLK, (tcdm_legacy_base + PRCM_MBOX_HEADER_REQ_MB3));
+	writel(MBOX_BIT(3), PRCM_MBOX_CPU_SET);
+
+	spin_unlock_irqrestore(&mb3.lock, flags);
+
+	/*
+	 * The firmware only sends an ACK if we want to enable the
+	 * SysClk, and it succeeds.
+	 */
+	if (enable && !wait_for_completion_timeout(&mb3.sysclk_work,
+			msecs_to_jiffies(20000))) {
+		pr_err("prcmu: %s timed out (20 s) waiting for a reply.\n",
+			__func__);
+		r = -EIO;
+	}
+
+	mutex_unlock(&mb3.sysclk_lock);
+
+	return r;
+}
+
+static int request_timclk(bool enable)
+{
+	u32 val = (PRCM_TCR_DOZE_MODE | PRCM_TCR_TENSEL_MASK);
+
+	if (!enable)
+		val |= PRCM_TCR_STOP_TIMERS;
+	writel(val, PRCM_TCR);
+
+	return 0;
+}
+
+static int request_clock(u8 clock, bool enable)
+{
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk_mgt_lock, flags);
+
+	/* Grab the HW semaphore. */
+	while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+		cpu_relax();
+
+	val = readl(clk_mgt[clock].reg);
+	if (enable) {
+		val |= (PRCM_CLK_MGT_CLKEN | clk_mgt[clock].pllsw);
+	} else {
+		clk_mgt[clock].pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
+		val &= ~(PRCM_CLK_MGT_CLKEN | PRCM_CLK_MGT_CLKPLLSW_MASK);
+	}
+	writel(val, clk_mgt[clock].reg);
+
+	/* Release the HW semaphore. */
+	writel(0, PRCM_SEM);
+
+	spin_unlock_irqrestore(&clk_mgt_lock, flags);
+
+	return 0;
+}
+
+static int request_sga_clock(u8 clock, bool enable)
+{
+	u32 val;
+	int ret;
+
+	if (enable) {
+		val = readl(PRCM_CGATING_BYPASS);
+		writel(val | PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
+	}
+
+	ret = request_clock(clock, enable);
+
+	if (!ret && !enable) {
+		val = readl(PRCM_CGATING_BYPASS);
+		writel(val & ~PRCM_CGATING_BYPASS_ICN2, PRCM_CGATING_BYPASS);
+	}
+
+	return ret;
+}
+
+static inline bool plldsi_tv_locked(void)
+{
+	return (readl(PRCM_PLLDSITV_LOCKP) &
+		(PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
+		 PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) ==
+		(PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
+		 PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3);
+}
+
+static inline bool plldsi_lcd_locked(void)
+{
+	return (readl(PRCM_PLLDSILCD_LOCKP) &
+		(PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
+		 PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3)) ==
+		(PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP10 |
+		 PRCM_PLLDSI_LOCKP_PRCM_PLLDSI_LOCKP3);
+}
+
+static int request_plldsi(bool enable, bool lcd)
+{
+	int r = 0;
+	u32 val;
+	void __iomem *pll_dsi_enable_reg;
+	u32 pll_dsi_resetn_bit;
+	bool (*plldsi_locked)(void);
+
+	if (lcd) {
+		pll_dsi_enable_reg = PRCM_PLLDSILCD_ENABLE;
+		pll_dsi_resetn_bit = PRCM_APE_RESETN_DSIPLL_LCD_RESETN;
+		plldsi_locked = plldsi_lcd_locked;
+	} else {
+		pll_dsi_enable_reg = PRCM_PLLDSITV_ENABLE;
+		pll_dsi_resetn_bit = PRCM_APE_RESETN_DSIPLL_TV_RESETN;
+		plldsi_locked = plldsi_tv_locked;
+	}
+
+	if (enable) {
+		/* Only clamp for enable if both are unlocked */
+		if (!plldsi_lcd_locked() && !plldsi_tv_locked())
+			writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
+				PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI),
+							PRCM_MMIP_LS_CLAMP_CLR);
+	} else {
+		/* Only clamp for disable if one are locked */
+		bool tv_locked = plldsi_tv_locked();
+		bool lcd_locked = plldsi_lcd_locked();
+		if ((!lcd_locked && tv_locked) || (lcd_locked && !tv_locked))
+			writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
+				PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI),
+							PRCM_MMIP_LS_CLAMP_SET);
+	}
+
+	val = readl(pll_dsi_enable_reg);
+	if (enable)
+		val |= PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+	else
+		val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+	writel(val, pll_dsi_enable_reg);
+
+	if (enable) {
+		unsigned int i;
+		bool locked = plldsi_locked();
+
+		for (i = 10; !locked && (i > 0); --i) {
+			udelay(100);
+			locked = plldsi_locked();
+		}
+		if (locked) {
+			writel(pll_dsi_resetn_bit,
+				PRCM_APE_RESETN_SET);
+		} else {
+			writel((PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMP |
+				PRCM_MMIP_LS_CLAMP_DSIPLL_CLAMPI),
+				PRCM_MMIP_LS_CLAMP_SET);
+			val &= ~PRCM_PLLDSI_ENABLE_PRCM_PLLDSI_ENABLE;
+			writel(val, pll_dsi_enable_reg);
+			r = -EAGAIN;
+		}
+	} else {
+		writel(pll_dsi_resetn_bit, PRCM_APE_RESETN_CLR);
+	}
+
+	return r;
+}
+
+#define NO_LCD false
+#define LCD true
+
+static int request_dsiclk(u8 n, bool enable, bool lcd)
+{
+	u32 val;
+	struct dsiclk *dsiclk;
+
+	dsiclk = u9540_dsiclk;
+
+	val = readl(PRCM_DSI_PLLOUT_SEL);
+	val &= ~dsiclk[n].divsel_mask;
+	val |= ((enable ? dsiclk[n].divsel : PRCM_DSI_PLLOUT_SEL_OFF) <<
+			dsiclk[n].divsel_shift);
+	if (lcd)
+		val |= dsiclk[n].divsel_lcd_mask;
+	writel(val, PRCM_DSI_PLLOUT_SEL);
+	return 0;
+}
+
+static int request_dsiescclk(u8 n, bool enable)
+{
+	u32 val;
+
+	val = readl(PRCM_DSITVCLK_DIV);
+	enable ? (val |= dsiescclk[n].en) : (val &= ~dsiescclk[n].en);
+	writel(val, PRCM_DSITVCLK_DIV);
+	return 0;
+}
+
+/**
+ * dbx540_request_clock() - Request for a clock to be enabled or disabled.
+ * @clock:      The clock for which the request is made.
+ * @enable:     Whether the clock should be enabled (true) or disabled (false).
+ *
+ * This function should only be used by the clock implementation.
+ * Do not use it from any other place!
+ */
+static int dbx540_prcmu_request_clock(u8 clock, bool enable)
+{
+	if (clock == PRCMU_SGACLK)
+		return request_sga_clock(clock, enable);
+	else if (clock < PRCMU_NUM_REG_CLOCKS)
+		return request_clock(clock, enable);
+	else if (clock == PRCMU_TIMCLK)
+		return request_timclk(enable);
+	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+		return request_dsiclk((clock - PRCMU_DSI0CLK), enable, NO_LCD);
+	else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+		return request_dsiescclk((clock - PRCMU_DSI0ESCCLK), enable);
+	else if (clock == PRCMU_PLLDSI)
+		return request_plldsi(enable, false);
+	else if ((clock == PRCMU_DSI0CLK_LCD) || (clock == PRCMU_DSI1CLK_LCD))
+		return request_dsiclk((clock - PRCMU_DSI0CLK_LCD),
+			enable, LCD);
+	else if (clock == PRCMU_PLLDSI_LCD)
+		return request_plldsi(enable, true);
+	else if (clock == PRCMU_SYSCLK)
+		return request_sysclk(enable);
+	else if ((clock == PRCMU_PLLSOC0) || (clock == PRCMU_PLLSOC1))
+		return request_pll(clock, enable);
+	else
+		return -EINVAL;
+}
+
+static unsigned long pll_rate(void __iomem *reg, unsigned long src_rate,
+	int branch)
+{
+	u64 rate;
+	u32 val;
+	u32 d;
+	u32 div = 1;
+
+	val = readl(reg);
+
+	rate = src_rate;
+	rate *= ((val & PRCM_PLL_FREQ_D_MASK) >> PRCM_PLL_FREQ_D_SHIFT);
+
+	d = ((val & PRCM_PLL_FREQ_N_MASK) >> PRCM_PLL_FREQ_N_SHIFT);
+	if (d > 1)
+		div *= d;
+
+	d = ((val & PRCM_PLL_FREQ_R_MASK) >> PRCM_PLL_FREQ_R_SHIFT);
+	if (d > 1)
+		div *= d;
+
+	if (val & PRCM_PLL_FREQ_SELDIV2)
+		div *= 2;
+
+	if ((branch == PLL_FIX) || ((branch == PLL_DIV) &&
+		(val & PRCM_PLL_FREQ_DIV2EN) &&
+		((reg == PRCM_PLLSOC0_FREQ) ||
+		 (reg == PRCM_PLLDDR_FREQ))))
+		div *= 2;
+
+	(void)do_div(rate, div);
+
+	return (unsigned long)rate;
+}
+
+#define ROOT_CLOCK_RATE 38400000
+
+static unsigned long clock_rate(u8 clock)
+{
+	u32 val;
+	u32 pllsw;
+	unsigned long rate = ROOT_CLOCK_RATE;
+
+	val = readl(clk_mgt[clock].reg);
+
+	if (val & PRCM_CLK_MGT_CLK38) {
+		if (clk_mgt[clock].clk38div && (val & PRCM_CLK_MGT_CLK38DIV))
+			rate /= 2;
+		return rate;
+	}
+
+	val |= clk_mgt[clock].pllsw;
+	pllsw = (val & PRCM_CLK_MGT_CLKPLLSW_MASK);
+
+	if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC0)
+		rate = pll_rate(PRCM_PLLSOC0_FREQ, rate, clk_mgt[clock].branch);
+	else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_SOC1)
+		rate = pll_rate(PRCM_PLLSOC1_FREQ, rate, clk_mgt[clock].branch);
+	else if (pllsw == PRCM_CLK_MGT_CLKPLLSW_DDR)
+		rate = pll_rate(PRCM_PLLDDR_FREQ, rate, clk_mgt[clock].branch);
+	else
+		return 0;
+
+	if ((clock == PRCMU_SGACLK) &&
+		(val & PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN)) {
+		u64 r = (rate * 10);
+
+		(void)do_div(r, 25);
+		return (unsigned long)r;
+	}
+	val &= PRCM_CLK_MGT_CLKPLLDIV_MASK;
+	if (val)
+		return rate / val;
+	else
+		return 0;
+}
+
+static unsigned long armss_rate(void)
+{
+	return latest_armss_rate;
+}
+
+static unsigned long dsiclk_rate(u8 n, bool lcd)
+{
+	u32 divsel;
+	u32 div = 1;
+	struct dsiclk *dsiclk;
+
+	dsiclk = u9540_dsiclk;
+
+	divsel = readl(PRCM_DSI_PLLOUT_SEL);
+	divsel = ((divsel & dsiclk[n].divsel_mask) >> dsiclk[n].divsel_shift);
+
+	if (divsel == PRCM_DSI_PLLOUT_SEL_OFF)
+		divsel = dsiclk[n].divsel;
+
+	switch (divsel) {
+	case PRCM_DSI_PLLOUT_SEL_PHI_4:
+		div *= 2;
+	case PRCM_DSI_PLLOUT_SEL_PHI_2:
+		div *= 2;
+	case PRCM_DSI_PLLOUT_SEL_PHI:
+		if (lcd)
+			return pll_rate(PRCM_PLLDSILCD_FREQ,
+					clock_rate(PRCMU_SPARE1CLK), PLL_RAW) / div;
+		else
+			return pll_rate(PRCM_PLLDSITV_FREQ,
+					clock_rate(PRCMU_HDMICLK), PLL_RAW) / div;
+	default:
+		return 0;
+	}
+}
+
+static unsigned long dsiescclk_rate(u8 n)
+{
+	u32 div;
+
+	div = readl(PRCM_DSITVCLK_DIV);
+	div = ((div & dsiescclk[n].div_mask) >> (dsiescclk[n].div_shift));
+	return clock_rate(PRCMU_TVCLK) / max((u32)1, div);
+}
+
+static unsigned long dbx540_prcmu_clock_rate(u8 clock)
+{
+	if (clock < PRCMU_NUM_REG_CLOCKS)
+		return clock_rate(clock);
+	else if (clock == PRCMU_TIMCLK)
+		return ROOT_CLOCK_RATE / 16;
+	else if (clock == PRCMU_SYSCLK)
+		return ROOT_CLOCK_RATE;
+	else if (clock == PRCMU_PLLSOC0)
+		return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+	else if (clock == PRCMU_PLLSOC1)
+		return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+	else if (clock == PRCMU_PLLDDR)
+		return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
+	else if (clock == PRCMU_PLLDSI)
+		return pll_rate(PRCM_PLLDSITV_FREQ, clock_rate(PRCMU_HDMICLK),
+			PLL_RAW);
+	else if (clock == PRCMU_ARMSS)
+		return KHZ_TO_HZ(armss_rate());
+	else if (clock == PRCMU_ARMCLK)
+		return KHZ_TO_HZ(get_arm_freq());
+	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+		return dsiclk_rate(clock - PRCMU_DSI0CLK, false);
+	else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+		return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK);
+	else if (clock == PRCMU_PLLDSI_LCD)
+		return pll_rate(PRCM_PLLDSILCD_FREQ,
+					clock_rate(PRCMU_SPARE1CLK), PLL_RAW);
+	else if ((clock == PRCMU_DSI0CLK_LCD) || (clock == PRCMU_DSI1CLK_LCD))
+		return dsiclk_rate(clock - PRCMU_DSI0CLK_LCD, true);
+	else
+		return 0;
+}
+
+static unsigned long clock_source_rate(u32 clk_mgt_val, int branch)
+{
+	if (clk_mgt_val & PRCM_CLK_MGT_CLK38)
+		return ROOT_CLOCK_RATE;
+	clk_mgt_val &= PRCM_CLK_MGT_CLKPLLSW_MASK;
+	if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC0)
+		return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, branch);
+	else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_SOC1)
+		return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, branch);
+	else if (clk_mgt_val == PRCM_CLK_MGT_CLKPLLSW_DDR)
+		return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, branch);
+	else
+		return 0;
+}
+
+static u32 clock_divider(unsigned long src_rate, unsigned long rate)
+{
+	u32 div;
+
+	div = (src_rate / rate);
+	if (div == 0)
+		return 1;
+	if (rate < (src_rate / div))
+		div++;
+	return div;
+}
+
+static long round_clock_rate(u8 clock, unsigned long rate)
+{
+	u32 val;
+	u32 div;
+	unsigned long src_rate;
+	long rounded_rate;
+
+	val = readl(clk_mgt[clock].reg);
+	src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
+		clk_mgt[clock].branch);
+	div = clock_divider(src_rate, rate);
+	if (val & PRCM_CLK_MGT_CLK38) {
+		if (clk_mgt[clock].clk38div) {
+			if (div > 2)
+				div = 2;
+		} else {
+			div = 1;
+		}
+	} else if ((clock == PRCMU_SGACLK) && (div == 3)) {
+		u64 r = (src_rate * 10);
+
+		(void)do_div(r, 25);
+		if (r <= rate)
+			return (unsigned long)r;
+	}
+	rounded_rate = (src_rate / min(div, (u32)31));
+
+	return rounded_rate;
+}
+
+#define MIN_PLL_VCO_RATE 600000000ULL
+#define MAX_PLL_VCO_RATE 2000000000ULL
+
+static long round_plldsi_rate(unsigned long rate)
+{
+	long rounded_rate = 0;
+	unsigned long src_rate;
+	unsigned long rem;
+	u32 r;
+
+	src_rate = clock_rate(PRCMU_HDMICLK);
+	rem = rate;
+
+	for (r = 7; (rem > 0) && (r > 0); r--) {
+		u64 d;
+
+		d = (r * rate);
+		(void)do_div(d, src_rate);
+		if (d < 6)
+			d = 6;
+		else if (d > 255)
+			d = 255;
+		d *= src_rate;
+		if (((2 * d) < (r * MIN_PLL_VCO_RATE)) ||
+			((r * MAX_PLL_VCO_RATE) < (2 * d)))
+			continue;
+		(void)do_div(d, r);
+		if (rate < d) {
+			if (rounded_rate == 0)
+				rounded_rate = (long)d;
+			break;
+		}
+		if ((rate - d) < rem) {
+			rem = (rate - d);
+			rounded_rate = (long)d;
+		}
+	}
+	return rounded_rate;
+}
+
+static long round_dsiclk_rate(unsigned long rate, bool lcd)
+{
+	u32 div;
+	unsigned long src_rate;
+	long rounded_rate;
+
+	if (lcd)
+		src_rate = pll_rate(PRCM_PLLDSILCD_FREQ,
+			clock_rate(PRCMU_SPARE1CLK), PLL_RAW);
+	else
+		src_rate = pll_rate(PRCM_PLLDSITV_FREQ,
+			clock_rate(PRCMU_HDMICLK), PLL_RAW);
+	div = clock_divider(src_rate, rate);
+	rounded_rate = (src_rate / ((div > 2) ? 4 : div));
+
+	return rounded_rate;
+}
+
+static long round_dsiescclk_rate(unsigned long rate)
+{
+	u32 div;
+	unsigned long src_rate;
+	long rounded_rate;
+
+	src_rate = clock_rate(PRCMU_TVCLK);
+	div = clock_divider(src_rate, rate);
+	rounded_rate = (src_rate / min(div, (u32)255));
+
+	return rounded_rate;
+}
+
+static long dbx540_prcmu_round_clock_rate(u8 clock, unsigned long rate)
+{
+	if (clock < PRCMU_NUM_REG_CLOCKS)
+		return round_clock_rate(clock, rate);
+	else if (clock == PRCMU_PLLDSI)
+		return round_plldsi_rate(rate);
+	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+		return round_dsiclk_rate(rate, false);
+	else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+		return round_dsiescclk_rate(rate);
+	else if (clock == PRCMU_PLLDSI_LCD)
+		return round_plldsi_rate(rate);
+	else if ((clock == PRCMU_DSI0CLK_LCD) || (clock == PRCMU_DSI1CLK_LCD))
+		return round_dsiclk_rate(rate, true);
+	else
+		return (long)prcmu_clock_rate(clock);
+}
+
+static void set_clock_rate(u8 clock, unsigned long rate)
+{
+	u32 val;
+	u32 div;
+	unsigned long src_rate;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clk_mgt_lock, flags);
+
+	/* Grab the HW semaphore. */
+	while ((readl(PRCM_SEM) & PRCM_SEM_PRCM_SEM) != 0)
+		cpu_relax();
+
+	val = readl(clk_mgt[clock].reg);
+	src_rate = clock_source_rate((val | clk_mgt[clock].pllsw),
+		clk_mgt[clock].branch);
+	div = clock_divider(src_rate, rate);
+	if (val & PRCM_CLK_MGT_CLK38) {
+		if (clk_mgt[clock].clk38div) {
+			if (div > 1)
+				val |= PRCM_CLK_MGT_CLK38DIV;
+			else
+				val &= ~PRCM_CLK_MGT_CLK38DIV;
+		}
+	} else if (clock == PRCMU_SGACLK) {
+		val &= ~(PRCM_CLK_MGT_CLKPLLDIV_MASK |
+			PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN);
+		if (div == 3) {
+			u64 r = (src_rate * 10);
+
+			(void)do_div(r, 25);
+			if (r <= rate) {
+				val |= PRCM_SGACLK_MGT_SGACLKDIV_BY_2_5_EN;
+				div = 0;
+			}
+		}
+		val |= min(div, (u32)31);
+	} else {
+		val &= ~PRCM_CLK_MGT_CLKPLLDIV_MASK;
+		val |= min(div, (u32)31);
+	}
+
+	writel(val, clk_mgt[clock].reg);
+
+	/* Release the HW semaphore. */
+	writel(0, PRCM_SEM);
+
+	spin_unlock_irqrestore(&clk_mgt_lock, flags);
+}
+
+static int set_plldsi_rate(unsigned long rate, bool lcd)
+{
+	unsigned long src_rate;
+	unsigned long rem;
+	u32 pll_freq = 0;
+	u32 r;
+
+	if (lcd)
+		src_rate = clock_rate(PRCMU_SPARE1CLK);
+	else
+		src_rate = clock_rate(PRCMU_HDMICLK);
+
+	rem = rate;
+
+	for (r = 7; (rem > 0) && (r > 0); r--) {
+		u64 d;
+		u64 hwrate;
+
+		d = (r * rate);
+		(void)do_div(d, src_rate);
+		if (d < 6)
+			d = 6;
+		else if (d > 255)
+			d = 255;
+		hwrate = (d * src_rate);
+		if (((2 * hwrate) < (r * MIN_PLL_VCO_RATE)) ||
+			((r * MAX_PLL_VCO_RATE) < (2 * hwrate)))
+			continue;
+		(void)do_div(hwrate, r);
+		if (rate < hwrate) {
+			if (pll_freq == 0)
+				pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
+					(r << PRCM_PLL_FREQ_R_SHIFT));
+			break;
+		}
+		if ((rate - hwrate) < rem) {
+			rem = (rate - hwrate);
+			pll_freq = (((u32)d << PRCM_PLL_FREQ_D_SHIFT) |
+				(r << PRCM_PLL_FREQ_R_SHIFT));
+		}
+	}
+	if (pll_freq == 0)
+		return -EINVAL;
+
+	pll_freq |= (1 << PRCM_PLL_FREQ_N_SHIFT);
+	writel(pll_freq, lcd ? PRCM_PLLDSILCD_FREQ : PRCM_PLLDSITV_FREQ);
+
+	return 0;
+}
+
+static void set_dsiclk_rate(u8 n, unsigned long rate, bool lcd)
+{
+	unsigned long src_rate;
+	u32 val;
+	u32 div;
+	struct dsiclk *dsiclk;
+
+	dsiclk = u9540_dsiclk;
+
+	if (lcd)
+		src_rate = clock_rate(PRCMU_SPARE1CLK);
+	else
+		src_rate = clock_rate(PRCMU_HDMICLK);
+
+	div = clock_divider(pll_rate(
+				lcd ? PRCM_PLLDSILCD_FREQ : PRCM_PLLDSITV_FREQ,
+				src_rate, PLL_RAW), rate);
+
+	dsiclk[n].divsel = (div == 1) ? PRCM_DSI_PLLOUT_SEL_PHI :
+		(div == 2) ? PRCM_DSI_PLLOUT_SEL_PHI_2 :
+		/* else */	PRCM_DSI_PLLOUT_SEL_PHI_4;
+
+	val = readl(PRCM_DSI_PLLOUT_SEL);
+	val &= ~dsiclk[n].divsel_mask;
+	val |= (dsiclk[n].divsel << dsiclk[n].divsel_shift);
+	if (lcd)
+		val |= dsiclk[n].divsel_lcd_mask;
+	writel(val, PRCM_DSI_PLLOUT_SEL);
+}
+
+static void set_dsiescclk_rate(u8 n, unsigned long rate)
+{
+	u32 val;
+	u32 div;
+
+	div = clock_divider(clock_rate(PRCMU_TVCLK), rate);
+	val = readl(PRCM_DSITVCLK_DIV);
+	val &= ~dsiescclk[n].div_mask;
+	val |= (min(div, (u32)255) << dsiescclk[n].div_shift);
+	writel(val, PRCM_DSITVCLK_DIV);
+}
+
+static int dbx540_prcmu_set_clock_rate(u8 clock, unsigned long rate)
+{
+	if (clock < PRCMU_NUM_REG_CLOCKS)
+		set_clock_rate(clock, rate);
+	else if (clock == PRCMU_PLLDSI)
+		return set_plldsi_rate(rate, false);
+	else if (clock == PRCMU_ARMCLK)
+		return set_arm_freq(HZ_TO_KHZ(rate));
+	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
+		set_dsiclk_rate((clock - PRCMU_DSI0CLK), rate, false);
+	else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
+		set_dsiescclk_rate((clock - PRCMU_DSI0ESCCLK), rate);
+	else if (clock == PRCMU_PLLDSI_LCD)
+		return set_plldsi_rate(rate, true);
+	else if ((clock == PRCMU_DSI0CLK_LCD) || (clock == PRCMU_DSI1CLK_LCD))
+		set_dsiclk_rate((clock - PRCMU_DSI0CLK_LCD), rate, true);
+
+	return 0;
+}
+
+static int config_esram0_deep_sleep(u8 state)
+{
+	return 0;
+}
+
+int prcmu_set_ddr_sleep_strat_policy(u8 ddr_ctrl_nb, u8 lp_mode,
+		u8 ddr_ctrl_mode)
+{
+	struct upap_req req;
+	struct upap_ack ack;
+	int r = 0;
+
+	if ((ddr_ctrl_nb > DDR_SLEEP_STRAT_DDRCTRL1) ||
+			(ddr_ctrl_nb < DDR_SLEEP_STRAT_DDRCTRL0))
+		goto error;
+	if ((lp_mode > DDR_SLEEP_STRAT_AP_SLEEP_INDEX) ||
+			(ddr_ctrl_nb < DDR_SLEEP_STRAT_AP_IDLE_INDEX))
+		goto error;
+	if ((ddr_ctrl_mode > DDRCTRLSTATE_ON) ||
+			(ddr_ctrl_mode < DDRCTRLSTATE_OFFHIGHLAT))
+		goto error;
+
+	/* Set policy for DDRCtrlNb[cs0] */
+	ddr_sleep_strat_policy[lp_mode][ddr_ctrl_nb] = ddr_ctrl_mode;
+
+	/* Write to TCDM (header and data, then req_state) */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_DDR;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_DDR_SLEEP_STRAT;
+	memcpy(req.data.full_data_buf, ddr_sleep_strat_policy,
+					sizeof(ddr_sleep_strat_policy));
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, sizeof(ddr_sleep_strat_policy));
+
+	return r;
+
+error:
+	return -EINVAL;
+}
+
+static bool is_ac_wake_requested(void)
+{
+	return (atomic_read(&ac_wake_req_state) != 0);
+}
+
+void prcmu_reset_hva(void)
+{
+	writel(PRCM_C2C_RESETN_HVA_MEM | PRCM_C2C_RESETN_HVA_LOGIC,
+			PRCM_C2C_RESETN_CLR);
+	writel(PRCM_C2C_RESETN_HVA_MEM | PRCM_C2C_RESETN_HVA_LOGIC,
+			PRCM_C2C_RESETN_SET);
+}
+EXPORT_SYMBOL(prcmu_reset_hva);
+
+void prcmu_reset_hx170(void)
+{
+	writel(PRCM_C2C_RESETN_G1_MEM | PRCM_C2C_RESETN_G1_LOGIC,
+			PRCM_C2C_RESETN_CLR);
+	writel(PRCM_C2C_RESETN_G1_MEM | PRCM_C2C_RESETN_G1_LOGIC,
+			PRCM_C2C_RESETN_SET);
+}
+EXPORT_SYMBOL(prcmu_reset_hx170);
+
+/**
+ * get_reset_code - Retrieve SW reset reason code
+ *
+ * Retrieves the reset reason code stored by prcmu_system_reset() before
+ * last restart.
+ */
+static u16 get_reset_code(void)
+{
+	return reset_code_copy;
+}
+
+/**
+ * get_reset_status - Retrieve reset status
+ *
+ * Retrieves the value of the reset status register as read at startup.
+ */
+u32 get_reset_status(void)
+{
+	return reset_status_copy;
+}
+
+static void prcmu_modem_reset_db9540(void)
+{
+	struct upap_req req;
+	struct upap_ack ack;
+
+	/* prepare request */
+	req.service_id = U9540_PRCM_UPAP_SERVICE_MODEM;
+	req.command_id = U9540_PRCM_UPAP_COMMAND_RESET_MODEM;
+	req.req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_SENT;
+
+	upap_send_request(&req, &ack, 0);
+
+	/*
+	 * No need to check return from PRCMU as modem should go in reset state
+	 * This state is already managed by upper layer
+	 */
+}
+
+/**
+ * prcmu_reset_modem - ask the PRCMU to reset modem
+ */
+void modem_reset(void)
+{
+	prcmu_modem_reset_db9540();
+}
+
+static inline void print_unknown_header_warning(u8 n, u8 header)
+{
+	pr_warning("prcmu: Unknown message header (%d) in mailbox %d.\n",
+		header, n);
+}
+
+static void upap_print_unknown_header_warning(
+	u32 service, u32 command, u32 status)
+{
+	pr_warning("prcmu: Unknown service (%u) and command (%u) in UniqPAP."
+			"Returned status (%u)\n",
+		service, command, status);
+}
+
+static void upap_read_service_dvfs(struct upap_req *req,
+		struct upap_ack *ack)
+{
+	switch (ack->command_id) {
+	case U9540_PRCM_UPAP_COMMAND_SET_ARM_OPP:
+		ack->arm_freq = req->data.data;
+		break;
+
+	case U9540_PRCM_UPAP_COMMAND_SET_APE_OPP:
+		/* No response data for this service ID and command ID. */
+		break;
+
+	case U9540_PRCM_UPAP_COMMAND_SET_SAFE_OPP:
+		/* No response data for this service ID and command ID. */
+		break;
+
+	default:
+		upap_print_unknown_header_warning(ack->service_id,
+			ack->command_id, ack->status);
+		break;
+	}
+}
+
+static void upap_read_service_usb(struct upap_req *req,
+		struct upap_ack *ack)
+{
+	/* No response data for this service ID. Just check command ID is OK */
+	if (unlikely(ack->command_id != U9540_PRCM_UPAP_COMMAND_USB_WAKEUP_REL))
+		upap_print_unknown_header_warning(ack->service_id,
+			ack->command_id, ack->status);
+}
+
+static void upap_read_service_clock(struct upap_req *req,
+		struct upap_ack *ack)
+{
+	/* No response data for this service ID. Just check command ID is OK */
+	if (unlikely(ack->command_id != U9540_PRCM_UPAP_COMMAND_PLL_ON_OFF))
+		upap_print_unknown_header_warning(ack->service_id,
+			ack->command_id, ack->status);
+}
+
+static void upap_read_service_modem(struct upap_req *req,
+		struct upap_ack *ack)
+{
+	/* No response data for this service ID. Just check command ID is OK */
+	if (unlikely(ack->command_id != U9540_PRCM_UPAP_COMMAND_RESET_MODEM))
+		upap_print_unknown_header_warning(ack->service_id,
+			ack->command_id, ack->status);
+}
+
+static void upap_read_service_cpuhotplug(struct upap_req *req,
+		struct upap_ack *ack)
+{
+	/* No response data for this service ID. Just check command ID is OK */
+	if (unlikely((ack->command_id != U9540_PRCM_UPAP_COMMAND_CPU1_UNPLUG) &&
+			(ack->command_id != U9540_PRCM_UPAP_COMMAND_CPU1_REPLUG)
+			))
+	  upap_print_unknown_header_warning(ack->service_id,
+	  ack->command_id, ack->status);
+}
+
+static void upap_read_service_ddr(struct upap_req *req,
+		struct upap_ack *ack)
+{
+	/* No response data for this service ID. Just check command ID is OK */
+	if (unlikely(ack->command_id !=
+				U9540_PRCM_UPAP_COMMAND_DDR_SLEEP_STRAT))
+		upap_print_unknown_header_warning(ack->service_id,
+				ack->command_id, ack->status);
+}
+
+static void upap_read_service_thsensor(struct upap_req *req,
+		struct upap_ack *ack)
+{
+	switch (ack->command_id) {
+	case U9540_PRCM_UPAP_COMMAND_THSENSOR_GET_TEMP:
+		ack->sensor_read = req->data.data;
+		break;
+
+	default:
+		upap_print_unknown_header_warning(ack->service_id,
+			ack->command_id, ack->status);
+		break;
+	}
+}
+
+static void upap_read_ack(struct upap_req *req)
+{
+	struct upap_ack *ack = upap_transfer.ack;
+
+	ack->service_id = req->service_id;
+	ack->command_id = req->command_id;
+	ack->status = req->status;
+
+	if ((ack->service_id < UPAP_SERVICES_NB) &&
+		(upap_read_services[ack->service_id] != NULL))
+		upap_read_services[ack->service_id](req, ack);
+	else
+		upap_print_unknown_header_warning(ack->service_id,
+				ack->command_id, ack->status);
+
+	/* Update mailbox state */
+	req->req_state = U9540_PRCM_UPAP_REQ_STATE_REQ_IDLE;
+
+	complete(&upap_transfer.work);
+}
+
+static void upap_read_nfy(struct upap_nfy *nfy)
+{
+	switch (nfy->service_id) {
+#ifdef CONFIG_C2C
+	case U9540_PRCM_UPAP_SERVICE_C2C:
+		upap_read_nfy_service_c2c(nfy);
+		break;
+#endif
+	default:
+		pr_warning("prcmu: Unknown notif service %u / cmd %u in MB1\n",
+			nfy->service_id, nfy->command_id);
+	}
+	/* Update mailbox state */
+	nfy->nfy_state = U9540_PRCM_UPAP_NFY_STATE_IDLE;
+}
+
+static bool upap_handler(void)
+{
+	/* ack interuption */
+	writel(MBOX_BIT(upap_conf.mbox_nb), PRCM_ARM_IT1_CLR);
+
+	if (upap_conf.req->req_state == U9540_PRCM_UPAP_REQ_STATE_ACK_SENT)
+		upap_read_ack(upap_conf.req);
+
+	if (upap_conf.nfy->nfy_state == U9540_PRCM_UPAP_NFY_STATE_SENT)
+		upap_read_nfy(upap_conf.nfy);
+
+	return false;
+}
+
+static bool (*dbx540_read_mailbox[NUM_MB])(void) = {
+	db8500_prcmu_read_mailbox_0,
+	upap_handler,
+	db8500_prcmu_read_mailbox_2,
+	db8500_prcmu_read_mailbox_3,
+	db8500_prcmu_read_mailbox_4,
+	db8500_prcmu_read_mailbox_5,
+	db8500_prcmu_read_mailbox_6,
+	db8500_prcmu_read_mailbox_7
+};
+
+static  struct prcmu_val_data val_tab[] = {
+	{
+		.val = APE_OPP,
+		.set_val = set_ape_opp,
+		.get_val = get_ape_opp,
+	},
+	{
+		.val = DDR_OPP,
+		.set_val = set_ddr_opp,
+		.get_val = get_ddr_opp,
+	},
+};
+
+static struct prcmu_out_data 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 early_fops = {
+	/*  system reset  */
+	.system_reset = db8500_prcmu_system_reset,
+
+	/*  clock service */
+	.config_clkout = config_clkout,
+	.request_clock = dbx540_prcmu_request_clock,
+
+	/*  direct register access */
+	.read = db8500_prcmu_read,
+	.write =  db8500_prcmu_write,
+	.write_masked = db8500_prcmu_write_masked,
+	/* others */
+	.round_clock_rate = dbx540_prcmu_round_clock_rate,
+	.set_clock_rate = dbx540_prcmu_set_clock_rate,
+	.clock_rate = dbx540_prcmu_clock_rate,
+	.get_fw_version = get_fw_version,
+	.has_arm_maxopp = has_arm_maxopp,
+};
+
+static struct prcmu_fops_register early_tab[] = {
+	{
+		.fops = PRCMU_EARLY,
+		.data.pearly = &early_fops
+	},
+	{
+		.fops = PRCMU_VAL,
+		.size = ARRAY_SIZE(val_tab),
+		.data.pval = val_tab
+	},
+	{
+		.fops = PRCMU_OUT,
+		.size = ARRAY_SIZE(out_tab),
+		.data.pout = out_tab
+	}
+};
+
+static struct prcmu_fops_register_data early_data = {
+	.size = ARRAY_SIZE(early_tab),
+	.tab = early_tab
+};
+
+struct prcmu_probe_data probe_fops = {
+	/* sysfs soc inf */
+	.get_reset_code = get_reset_code,
+
+	/* pm/suspend.c/cpu freq */
+	.config_esram0_deep_sleep = 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 = is_ac_wake_requested,
+
+	/* modem */
+	.modem_reset = 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,
+	.get_reset_status = get_reset_status,
+	/*  other u8500 specific */
+	.request_ape_opp_100_voltage = 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,
+};
+
+struct prcmu_probe_cpuhp_data probe_cpuhp_fops = {
+
+	.stay_in_wfi_check = stay_in_wfi_check,
+	.replug_cpu1 = replug_cpu1,
+	.unplug_cpu1 = unplug_cpu1,
+};
+
+static struct prcmu_fops_register probe_tab[] = {
+	{
+		.fops = PRCMU_PROBE,
+		.data.pprobe = &probe_fops,
+	},
+	{
+		.fops = PRCMU_PROBE_CPU_HP,
+		.data.pprobe_cpuhp =&probe_cpuhp_fops,
+	},
+};
+
+struct prcmu_fops_register_data probe_data = {
+	.size = ARRAY_SIZE(probe_tab),
+	.tab = probe_tab,
+};
+
+struct prcmu_fops_register_data *__init
+			dbx540_prcmu_early_init(struct prcmu_tcdm_map *map)
+{
+	void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);
+	struct prcmu_context context;
+
+	if (tcpm_base != NULL) {
+		u32 version;
+		version = readl(tcpm_base + PRCMU_FW_VERSION_OFFSET + 4);
+		fw_info.version.project = version & 0xFF;
+		fw_info.version.api_version = (version >> 8) & 0xFF;
+		fw_info.version.func_version = (version >> 16) & 0xFF;
+		fw_info.version.errata = (version >> 24) & 0xFF;
+		fw_info.valid = true;
+		pr_info("PRCMU firmware: %s(%d), version %d.%d.%d\n",
+				fw_project_name(fw_info.version.project<<8),
+				fw_info.version.project,
+				fw_info.version.api_version,
+				fw_info.version.func_version,
+				fw_info.version.errata);
+		iounmap(tcpm_base);
+	}
+
+	tcdm_base = ioremap_nocache(U8500_PRCMU_TCDM_BASE, map->tcdm_size);
+	context.tcdm_base = tcdm_base;
+	tcdm_legacy_base = context.tcdm_base + map->legacy_offset;
+	context.tcdm_legacy_base = tcdm_legacy_base;
+
+	/* read curent max opp counter */
+	arm_max_opp_profile.max_opp_cnt =
+		arm_max_opp_profile.secure_memory;
+	/*
+	 * Copy the value of the reset status register and if needed also
+	 * the software reset code.
+	 */
+	reset_code_copy = readw(context.tcdm_legacy_base + PRCM_SW_RST_REASON);
+
+	context.fw_trans = dbx540_fw_trans;
+	context.fw_trans_nb = ARRAY_SIZE(dbx540_fw_trans);
+	context.read_mbox = dbx540_read_mailbox;
+	db8500_prcmu_context_init(&context);
+
+	db8500_prcmu_init_mb0(&mb0);
+	/*  mailbox 1 used by UniqPAP */
+	db8500_prcmu_init_mb2(&mb2);
+	db8500_prcmu_init_mb3(&mb3);
+	db8500_prcmu_init_mb4(&mb4);
+	db8500_prcmu_init_mb5(&mb5);
+
+	/* initialize UniqPAP */
+	upap_init();
+	/* register UniqPAP services */
+	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_DVFS,
+			upap_read_service_dvfs);
+	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_USB,
+			upap_read_service_usb);
+	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_CLOCK,
+			upap_read_service_clock);
+	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_MODEM,
+			upap_read_service_modem);
+	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_CPUHOTPLUG,
+			upap_read_service_cpuhotplug);
+	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_THSENSOR,
+			upap_read_service_thsensor);
+	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_DDR,
+			upap_read_service_ddr);
+
+	dvfs_context.ape_opp = APE_OPP_INIT;
+
+	/*  fixed it according to soc settings knowledge */
+	latest_armss_rate = 1500000;
+	return &early_data;
+}
+
+static void __init init_prcm_registers(void)
+{
+	u32 val;
+
+	val = readl(PRCM_A9PL_FORCE_CLKEN);
+	val &= ~(PRCM_A9PL_FORCE_CLKEN_PRCM_A9PL_FORCE_CLKEN |
+		PRCM_A9PL_FORCE_CLKEN_PRCM_A9AXI_FORCE_CLKEN);
+	writel(val, (PRCM_A9PL_FORCE_CLKEN));
+}
+
+void prcmu_set_sdmmc_psw(bool status)
+{
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&spare_out_lock, flags);
+	val = readl(PRCM_SPARE_OUT);
+	if (status)
+		val |= PRCM_SPARE_OUT_PSW_SDMMC;
+	else
+		val &= ~PRCM_SPARE_OUT_PSW_SDMMC;
+	writel(val, PRCM_SPARE_OUT);
+	spin_unlock_irqrestore(&spare_out_lock, flags);
+}
+
+void prcmu_pullup_tdo(bool enable)
+{
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&prcmu_lock, flags);
+	val = readl(PRCM_IOCR);
+	if (enable)
+		val &= ~PRCM_IOCR_TDO_PULLUP_ENABLE;
+	else
+		val |= PRCM_IOCR_TDO_PULLUP_ENABLE;
+	writel(val, PRCM_IOCR);
+	spin_unlock_irqrestore(&prcmu_lock, flags);
+}
+
+/*
+ * Power domain switches (ePODs) modeled as regulators for the DB8500 SoC
+ */
+static struct regulator_consumer_supply db8500_vape_consumers[] = {
+	REGULATOR_SUPPLY("v-ape", NULL),
+	REGULATOR_SUPPLY("v-i2c", "nmk-i2c.0"),
+	REGULATOR_SUPPLY("v-i2c", "nmk-i2c.1"),
+	REGULATOR_SUPPLY("v-i2c", "nmk-i2c.2"),
+	REGULATOR_SUPPLY("v-i2c", "nmk-i2c.3"),
+	/* "v-mmc" changed to "vcore" in the mainline kernel */
+	REGULATOR_SUPPLY("vcore", "sdi0"),
+	REGULATOR_SUPPLY("vcore", "sdi1"),
+	REGULATOR_SUPPLY("vcore", "sdi2"),
+	REGULATOR_SUPPLY("vcore", "sdi3"),
+	REGULATOR_SUPPLY("vcore", "sdi4"),
+	REGULATOR_SUPPLY("v-dma", "dma40.0"),
+	REGULATOR_SUPPLY("v-ape", "ab8500-usb.0"),
+	REGULATOR_SUPPLY("v-uart", "uart0"),
+	REGULATOR_SUPPLY("v-uart", "uart1"),
+	REGULATOR_SUPPLY("v-uart", "uart2"),
+	REGULATOR_SUPPLY("v-ape", "nmk-ske-keypad.0"),
+	REGULATOR_SUPPLY("v-hsi", "ste_hsi.0"),
+};
+
+static struct regulator_consumer_supply db8500_vsmps2_consumers[] = {
+	REGULATOR_SUPPLY("musb_1v8", "ab9540-usb.0"),
+	REGULATOR_SUPPLY("musb_1v8", "ab8500-usb.0"),
+	/* AV8100 regulator */
+	REGULATOR_SUPPLY("hdmi_1v8", "0-0070"),
+};
+
+static struct regulator_consumer_supply db8500_b2r2_mcde_consumers[] = {
+	REGULATOR_SUPPLY("vsupply", "b2r2_core"),
+	REGULATOR_SUPPLY("vsupply", "b2r2_1_core"),
+	REGULATOR_SUPPLY("vsupply", "mcde"),
+	REGULATOR_SUPPLY("vsupply", "dsilink.0"),
+	REGULATOR_SUPPLY("vsupply", "dsilink.1"),
+	REGULATOR_SUPPLY("vsupply", "dsilink.2"),
+};
+
+/* SVA MMDSP regulator switch */
+static struct regulator_consumer_supply db8500_svammdsp_consumers[] = {
+	REGULATOR_SUPPLY("sva-mmdsp", "cm_control"),
+};
+
+/* SVA pipe regulator switch */
+static struct regulator_consumer_supply db8500_svapipe_consumers[] = {
+	REGULATOR_SUPPLY("sva-pipe", "cm_control"),
+	REGULATOR_SUPPLY("v-hva", NULL),
+	REGULATOR_SUPPLY("v-g1", NULL),
+};
+
+/* SIA MMDSP regulator switch */
+static struct regulator_consumer_supply db8500_siammdsp_consumers[] = {
+	REGULATOR_SUPPLY("sia-mmdsp", "cm_control"),
+};
+
+/* SIA pipe regulator switch */
+static struct regulator_consumer_supply db8500_siapipe_consumers[] = {
+	REGULATOR_SUPPLY("sia-pipe", "cm_control"),
+};
+
+static struct regulator_consumer_supply db8500_sga_consumers[] = {
+	REGULATOR_SUPPLY("v-mali", NULL),
+};
+
+static struct regulator_consumer_supply db8500_vpll_consumers[] = {
+	REGULATOR_SUPPLY("v-vpll", NULL),
+};
+
+/* ESRAM1 and 2 regulator switch */
+static struct regulator_consumer_supply db8500_esram12_consumers[] = {
+	REGULATOR_SUPPLY("esram12", "cm_control"),
+};
+
+/* ESRAM3 and 4 regulator switch */
+static struct regulator_consumer_supply db8500_esram34_consumers[] = {
+	REGULATOR_SUPPLY("v-esram34", "mcde"),
+	REGULATOR_SUPPLY("esram34", "cm_control"),
+	REGULATOR_SUPPLY("lcla_esram", "dma40.0"),
+};
+
+static struct regulator_init_data dbx540_regulators[DB8500_NUM_REGULATORS] = {
+	[DB8500_REGULATOR_VAPE] = {
+		.constraints = {
+			.name = "db8500-vape",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_vape_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers),
+	},
+	[DB8500_REGULATOR_VARM] = {
+		.constraints = {
+			.name = "db8500-varm",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+	[DB8500_REGULATOR_VMODEM] = {
+		.constraints = {
+			.name = "db8500-vmodem",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+	[DB8500_REGULATOR_VPLL] = {
+		.constraints = {
+			.name = "db8500-vpll",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_vpll_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_vpll_consumers),
+	},
+	[DB8500_REGULATOR_VSMPS1] = {
+		.constraints = {
+			.name = "db8500-vsmps1",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+	[DB8500_REGULATOR_VSMPS2] = {
+		.constraints = {
+			.name = "db8500-vsmps2",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_vsmps2_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_vsmps2_consumers),
+	},
+	[DB8500_REGULATOR_VSMPS3] = {
+		.constraints = {
+			.name = "db8500-vsmps3",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+	[DB8500_REGULATOR_VRF1] = {
+		.constraints = {
+			.name = "db8500-vrf1",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+	[DB8500_REGULATOR_SWITCH_SVAMMDSP] = {
+		/* dependency to u8500-vape is handled outside regulator framework */
+		.constraints = {
+			.name = "db8500-sva-mmdsp",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_svammdsp_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_svammdsp_consumers),
+	},
+	[DB8500_REGULATOR_SWITCH_SVAMMDSPRET] = {
+		.constraints = {
+			/* "ret" means "retention" */
+			.name = "db8500-sva-mmdsp-ret",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+	[DB8500_REGULATOR_SWITCH_SVAPIPE] = {
+		/* dependency to u8500-vape is handled outside regulator framework */
+		.constraints = {
+			.name = "db8500-sva-pipe",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_svapipe_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_svapipe_consumers),
+	},
+	[DB8500_REGULATOR_SWITCH_SIAMMDSP] = {
+		/* dependency to u8500-vape is handled outside regulator framework */
+		.constraints = {
+			.name = "db8500-sia-mmdsp",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_siammdsp_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_siammdsp_consumers),
+	},
+	[DB8500_REGULATOR_SWITCH_SIAMMDSPRET] = {
+		.constraints = {
+			.name = "db8500-sia-mmdsp-ret",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+	[DB8500_REGULATOR_SWITCH_SIAPIPE] = {
+		/* dependency to u8500-vape is handled outside regulator framework */
+		.constraints = {
+			.name = "db8500-sia-pipe",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_siapipe_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_siapipe_consumers),
+	},
+	[DB8500_REGULATOR_SWITCH_SGA] = {
+		.supply_regulator = "db8500-vape",
+		.constraints = {
+			.name = "db8500-sga",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_sga_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_sga_consumers),
+
+	},
+	[DB8500_REGULATOR_SWITCH_B2R2_MCDE] = {
+		.supply_regulator = "db8500-vape",
+		.constraints = {
+			.name = "db8500-b2r2-mcde",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_b2r2_mcde_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_b2r2_mcde_consumers),
+	},
+	[DB8500_REGULATOR_SWITCH_ESRAM12] = {
+		/*
+		 * esram12 is set in retention and supplied by Vsafe when Vape is off,
+		 * no need to hold Vape
+		 */
+		.constraints = {
+			.name = "db8500-esram12",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_esram12_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_esram12_consumers),
+	},
+	[DB8500_REGULATOR_SWITCH_ESRAM12RET] = {
+		.constraints = {
+			.name = "db8500-esram12-ret",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+	[DB8500_REGULATOR_SWITCH_ESRAM34] = {
+		/*
+		 * esram34 is set in retention and supplied by Vsafe when Vape is off,
+		 * no need to hold Vape
+		 */
+		.constraints = {
+			.name = "db8500-esram34",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+		.consumer_supplies = db8500_esram34_consumers,
+		.num_consumer_supplies = ARRAY_SIZE(db8500_esram34_consumers),
+	},
+	[DB8500_REGULATOR_SWITCH_ESRAM34RET] = {
+		.constraints = {
+			.name = "db8500-esram34-ret",
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		},
+	},
+};
+
+static struct resource abx540_resources[] = {
+	[0] = {
+		.start	= IRQ_DB8500_AB8500,
+		.end	= IRQ_DB8500_AB8500,
+		.flags	= IORESOURCE_IRQ
+	}
+};
+
+static struct mfd_cell db9540_prcmu_devs[] = {
+	{
+		.name = "dbx500-prcmu",
+		.platform_data = &probe_data,
+		.pdata_size = sizeof(probe_data),
+	},
+	{
+		.name = "cpufreq-ux500",
+		.id = -1,
+	},
+	{
+		.name = "db8500-prcmu-regulators",
+		.of_compatible = "stericsson,db8500-prcmu-regulator",
+		.platform_data = &dbx540_regulators,
+		.pdata_size = sizeof(dbx540_regulators),
+	},
+	{
+		.name = "ab9540-i2c",
+		.of_compatible = "stericsson,ab8500",
+		.num_resources = ARRAY_SIZE(abx540_resources),
+		.resources = abx540_resources,
+		.id = AB8500_VERSION_AB9540,
+	},
+};
+
+/**
+ * prcmu_fw_init - core init call for the Linux PRCMU fw init logic
+ *
+ */
+static int __init dbx540_prcmu_probe(struct platform_device *pdev)
+{
+	int irq = 0, err = 0;
+	struct device_node *np = pdev->dev.of_node;
+
+	init_prcm_registers();
+
+	writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
+
+	if (np)
+		irq = platform_get_irq(pdev, 0);
+
+	if (!np || irq <= 0)
+		irq = IRQ_DB8500_PRCMU1;
+
+	err = request_threaded_irq(irq, db8500_prcmu_irq_handler,
+	        db8500_prcmu_irq_thread_fn, IRQF_NO_SUSPEND, "prcmu", NULL);
+	if (err < 0) {
+		pr_err("prcmu: Failed to allocate IRQ_DB8500_PRCMU1.\n");
+		err = -EBUSY;
+		goto no_irq_return;
+	}
+
+	db8500_irq_init(np);
+
+	if(np) {
+		if (of_property_read_u32_array(np,
+				"stericsson,db8500-frequency-tab ",
+				(u32 *)freq_table, 7) < 0)
+                         dev_err(&pdev->dev, "frequency tab\n");
+	} else
+		freq_table =
+			(struct cpufreq_frequency_table *)dev_get_platdata(&pdev->dev);
+
+	update_freq_table(freq_table);
+
+	err = mfd_add_devices(&pdev->dev, 0, db9540_prcmu_devs,
+			ARRAY_SIZE(db9540_prcmu_devs), NULL,
+			0);
+
+	if (err)
+		pr_err("prcmu: Failed to add subdevices\n");
+	else
+		pr_info("DBX540 PRCMU initialized\n");
+
+	/*
+	 * Temporary U9540 bringup code - Enable all clock gates.
+	 * Write 1 to all bits of PRCM_YYCLKEN0_MGT_SET and
+	 * PRCM_YYCLKEN1_MGT_SET registers.
+	 */
+	writel(~0, _PRCMU_BASE + 0x510); /* PRCM_YYCLKEN0_MGT_SET */
+	writel(~0, _PRCMU_BASE + 0x514); /* PRCM_YYCLKEN1_MGT_SET */
+
+	/*
+	 * set a flag to indicate that prcmu drv is well initialised and that
+	 * prcmu driver services can be called
+	 */
+	prcmu_driver_initialised = 1;
+	cpu1_unplug_ongoing = 0;
+
+no_irq_return:
+	return err;
+}
+
+static const struct of_device_id db8500_prcmu_match[] = {
+	{ .compatible = "stericsson,dbx540-prcmu"},
+	{ },
+};
+
+static struct platform_driver dbx540_prcmu_driver = {
+	.driver = {
+		.name = "dbx540-prcmu",
+		.owner = THIS_MODULE,
+		.of_match_table = db8500_prcmu_match,
+	},
+	.probe = dbx540_prcmu_probe,
+};
+
+static int __init dbx540_prcmu_init(void)
+{
+	return platform_driver_register(&dbx540_prcmu_driver);
+}
+
+core_initcall(dbx540_prcmu_init);
+
+MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com>");
+MODULE_AUTHOR("Michel Jaouen <michel.jaouen@stericsson.com>");
+MODULE_AUTHOR("Loic Pallardy <loic.pallardy@stericsson.com>");
+MODULE_DESCRIPTION("DBX540 PRCMU Unit driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/mfd/db8500-prcmu.h b/include/linux/mfd/db8500-prcmu.h
index f3b8b60..68c35b0 100644
--- a/include/linux/mfd/db8500-prcmu.h
+++ b/include/linux/mfd/db8500-prcmu.h
@@ -470,7 +470,7 @@ struct prcmu_auto_pm_config {
 	u8 sva_policy;
 };
 
-#ifdef CONFIG_MFD_DB8500_PRCMU
+#if defined(CONFIG_MFD_DB8500_PRCMU) || defined(CONFIG_MFD_DBX540_PRCMU)
 
 struct prcmu_fops_register_data *db8500_prcmu_early_init(
 		struct prcmu_tcdm_map *map);
@@ -500,7 +500,7 @@ int db8500_prcmu_set_display_clocks(void);
 int db8500_prcmu_disable_dsipll(void);
 int db8500_prcmu_enable_dsipll(void);
 
-#else /* !CONFIG_MFD_DB8500_PRCMU */
+#else /* !(CONFIG_MFD_DB8500_PRCMU || CONFIG_MFD_DBX540_PRCMU) */
 
 static struct prcmu_fops_register_data *db8500_prcmu_early_init(
 		struct prcmu_tcdm_map *map)
@@ -549,6 +549,6 @@ static inline int db8500_prcmu_stop_temp_sense(void)
 	return 0;
 }
 
-#endif /* !CONFIG_MFD_DB8500_PRCMU */
+#endif /* !(CONFIG_MFD_DB8500_PRCMU || CONFIG_MFD_DBX540_PRCMU) */
 
 #endif /* __MFD_DB8500_PRCMU_H */
diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h
index 49e71a7..4123f81 100644
--- a/include/linux/mfd/dbx500-prcmu.h
+++ b/include/linux/mfd/dbx500-prcmu.h
@@ -130,12 +130,17 @@ enum prcmu_clock {
 	PRCMU_SIACLK,
 	PRCMU_SVACLK,
 	PRCMU_ACLK,
+	/* HVA & G1 - U9540 only */
+	PRCMU_HVACLK,
+	PRCMU_G1CLK,
 	PRCMU_NUM_REG_CLOCKS,
 	PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
 	PRCMU_CDCLK,
 	PRCMU_TIMCLK,
 	PRCMU_PLLSOC0,
 	PRCMU_PLLSOC1,
+	PRCMU_ARMSS,
+	PRCMU_ARMCLK,
 	PRCMU_PLLDDR,
 	PRCMU_PLLDSI,
 	PRCMU_DSI0CLK,
@@ -143,6 +148,13 @@ enum prcmu_clock {
 	PRCMU_DSI0ESCCLK,
 	PRCMU_DSI1ESCCLK,
 	PRCMU_DSI2ESCCLK,
+	/* LCD DSI PLL - U9540 only */
+	PRCMU_PLLDSI_LCD,
+	PRCMU_DSI0CLK_LCD,
+	PRCMU_DSI1CLK_LCD,
+	PRCMU_DSI0ESCCLK_LCD,
+	PRCMU_DSI1ESCCLK_LCD,
+	PRCMU_DSI2ESCCLK_LCD,
 };
 
 /**
@@ -193,6 +205,17 @@ enum ddr_opp {
 	DDR_25_OPP = 0x02,
 };
 
+/**
+ * enum vsafe_opp - VSAFE OPP states definition
+ * @VSAFE_100_OPP: The new VSAFE operating point is vsafe100opp
+ * @VSAFE_50_OPP: The new DDR operating point is vsafe50opp
+ */
+enum vsafe_opp {
+	VSAFE_OPP_INIT = 0x00,
+	VSAFE_50_OPP = 0x01,
+	VSAFE_100_OPP = 0x02,
+};
+
 /*
  * Definitions for controlling ESRAM0 in deep sleep.
  */
@@ -253,6 +276,7 @@ struct prcmu_fw_version {
 };
 
 #include <linux/mfd/db8500-prcmu.h>
+#include <linux/mfd/dbx540-prcmu.h>
 
 #if defined(CONFIG_UX500_SOC_DB8500)
 
diff --git a/include/linux/mfd/dbx540-prcmu.h b/include/linux/mfd/dbx540-prcmu.h
new file mode 100644
index 0000000..b85769e
--- /dev/null
+++ b/include/linux/mfd/dbx540-prcmu.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) STMicroelectronics 2009
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Michel Jaouen <michel.jaouen@stericsson.com>
+ *
+ * PRCMU f/w APIs
+ */
+#ifndef __MFD_DBX540_PRCMU_H
+#define __MFD_DBX540_PRCMU_H
+
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
+
+
+
+enum ap_pwrst_trans_status_9540 {
+	EXECUTETODEEPIDLE	= 0xE8,
+	EXECUTETODEEPSLEEP	= 0xF8
+};
+
+#define PRCMU_DDR_SLEEP_STRAT_DDRCTRL_NB 2
+#define PRCMU_DDR_SLEEP_STRAT_LP_MODE_NB 3
+
+enum ddr_sleep_strat_ap_pwrst {
+	DDR_SLEEP_STRAT_AP_IDLE_INDEX,
+	DDR_SLEEP_STRAT_AP_DEEPIDLE_INDEX,
+	DDR_SLEEP_STRAT_AP_SLEEP_INDEX,
+};
+
+enum ddr_ctrl_lp_mode {
+	DDRCTRLSTATE_OFFHIGHLAT = 0,
+	DDRCTRLSTATE_OFFLOWLAT,
+	DDRCTRLSTATE_ON,
+};
+
+enum ddr_ctrl_nb {
+	DDR_SLEEP_STRAT_DDRCTRL0,
+	DDR_SLEEP_STRAT_DDRCTRL1
+};
+
+#ifdef CONFIG_MFD_DBX540_PRCMU
+struct prcmu_fops_register_data *dbx540_prcmu_early_init(
+		struct prcmu_tcdm_map *map);
+int prcmu_set_vsafe_opp(u8 opp);
+int prcmu_get_vsafe_opp(void);
+int prcmu_set_ddr_sleep_strat_policy(u8 ddr_ctrl_nb, u8 lp_mode,
+						u8 ddr_ctrl_mode);
+void prcmu_set_sdmmc_psw(bool status);
+#ifdef CONFIG_C2C
+void prcmu_c2c_request_notif_up(void);
+void prcmu_c2c_request_reset(void);
+#endif
+
+void prcmu_reset_hva(void);
+void prcmu_reset_hx170(void);
+void prcmu_pullup_tdo(bool enable);
+
+#else /* !CONFIG_MFD_DBX540_PRCMU */
+static inline struct prcmu_fops_register_data *dbx540_prcmu_early_init(
+		struct prcmu_tcdm_map *map)
+{
+	return NULL;
+}
+
+static inline int prcmu_set_vsafe_opp(u8 opp)
+{
+	return -EINVAL;
+}
+
+static inline int prcmu_get_vsafe_opp(void)
+{
+	return -EINVAL;
+}
+
+static inline int prcmu_set_ddr_sleep_strat_policy(u8 ddr_ctrl_nb, u8 lp_mode,
+						u8 ddr_ctrl_mode)
+{
+	return -EINVAL;
+}
+
+static inline void db8540_prcmu_set_sdmmc_psw(bool status) {}
+
+#ifdef CONFIG_C2C
+static inline void prcmu_c2c_request_notif_up(void) {}
+static inline void prcmu_c2c_request_reset(void) {}
+#endif
+
+static inline void prcmu_reset_hva(void) {}
+static inline void prcmu_reset_hx170(void) {}
+static inline void prcmu_pullup_tdo(bool enable) {}
+
+#endif /* !CONFIG_MFD_DBX540_PRCMU */
+
+#endif /* __MFD_DBX540_PRCMU_H */
-- 
1.7.11.1


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

* [PATCH 16/17] arm: ux500: add dbx540 prcmu platform data
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (14 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 15/17] mfd: dbx540-prcmu creation Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  2012-09-05  9:59 ` [PATCH 17/17] mfd: db8500-prcmu: activate dbx540-prcmu driver Loic Pallardy
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

Add support for new dbx540-prcmu driver.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 arch/arm/mach-ux500/board-mop500.c         | 12 ++++++++++++
 arch/arm/mach-ux500/cpu-db8500.c           |  7 +++++--
 arch/arm/mach-ux500/include/mach/devices.h |  3 +++
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index 0869c58..ed1507a 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -600,6 +600,9 @@ static void __init mop500_init_machine(void)
 
 	mop500_pinmaps_init();
 	parent = u8500_init_devices(&ab8500_platdata);
+	db8500_prcmu_device.dev.parent = parent;
+	db8500_prcmu_device.dev.platform_data = &ab8500_platdata;
+	platform_device_register(&db8500_prcmu_device);
 
 	for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
 		mop500_platform_devs[i]->dev.parent = parent;
@@ -634,6 +637,9 @@ static void __init snowball_init_machine(void)
 
 	snowball_pinmaps_init();
 	parent = u8500_init_devices(&ab8500_platdata);
+	db8500_prcmu_device.dev.parent = parent;
+	db8500_prcmu_device.dev.platform_data = &ab8500_platdata;
+	platform_device_register(&db8500_prcmu_device);
 
 	for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
 		snowball_platform_devs[i]->dev.parent = parent;
@@ -666,6 +672,9 @@ static void __init hrefv60_init_machine(void)
 
 	hrefv60_pinmaps_init();
 	parent = u8500_init_devices(&ab8500_platdata);
+	db8500_prcmu_device.dev.parent = parent;
+	db8500_prcmu_device.dev.platform_data = &ab8500_platdata;
+	platform_device_register(&db8500_prcmu_device);
 
 	for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
 		mop500_platform_devs[i]->dev.parent = parent;
@@ -702,6 +711,9 @@ static void __init u9540_init_machine(void)
 	ccu9540_pins_init();
 
 	parent = u8500_init_devices(&ab8500_platdata);
+	dbx540_prcmu_device.dev.parent = parent;
+	dbx540_prcmu_device.dev.platform_data = &ab8500_platdata;
+	platform_device_register(&dbx540_prcmu_device);
 
 	for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
 		mop500_platform_devs[i]->dev.parent = parent;
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 59dcf82..8f74c31 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -130,7 +130,7 @@ static struct platform_device db8500_pmu_device = {
 	.dev.platform_data	= &db8500_pmu_platdata,
 };
 
-static struct platform_device db8500_prcmu_device = {
+struct platform_device db8500_prcmu_device = {
 	.name			= "db8500-prcmu",
 };
 
@@ -139,6 +139,10 @@ struct prcmu_tcdm_map db8500_tcdm_map = {
 	.legacy_offset = 0,
 };
 
+struct platform_device dbx540_prcmu_device = {
+	.name			= "dbx540-prcmu",
+};
+
 struct prcmu_tcdm_map db9540_tcdm_map = {
 	.tcdm_size = SZ_4K + SZ_8K,
 	.legacy_offset = SZ_8K,
@@ -147,7 +151,6 @@ struct prcmu_tcdm_map db9540_tcdm_map = {
 static struct platform_device *platform_devs[] __initdata = {
 	&u8500_dma40_device,
 	&db8500_pmu_device,
-	&db8500_prcmu_device,
 };
 
 static resource_size_t __initdata db8500_gpio_base[] = {
diff --git a/arch/arm/mach-ux500/include/mach/devices.h b/arch/arm/mach-ux500/include/mach/devices.h
index 1caa76e..5c4f92e 100644
--- a/arch/arm/mach-ux500/include/mach/devices.h
+++ b/arch/arm/mach-ux500/include/mach/devices.h
@@ -20,6 +20,9 @@ extern struct platform_device ux500_cryp1_device;
 extern struct platform_device u8500_dma40_device;
 extern struct platform_device ux500_ske_keypad_device;
 
+extern struct platform_device db8500_prcmu_device;
+extern struct platform_device dbx540_prcmu_device;
+
 extern struct prcmu_tcdm_map db8500_tcdm_map;
 extern struct prcmu_tcdm_map db9540_tcdm_map;
 
-- 
1.7.11.1


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

* [PATCH 17/17] mfd: db8500-prcmu: activate dbx540-prcmu driver
  2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
                   ` (15 preceding siblings ...)
  2012-09-05  9:59 ` [PATCH 16/17] arm: ux500: add dbx540 prcmu platform data Loic Pallardy
@ 2012-09-05  9:59 ` Loic Pallardy
  16 siblings, 0 replies; 27+ messages in thread
From: Loic Pallardy @ 2012-09-05  9:59 UTC (permalink / raw)
  To: Samuel Ortiz, linux-kernel, linux-arm-kernel, Linus Walleij
  Cc: Lee Jones, Loic Pallardy, LT ST-Ericsson,
	STEricsson_nomadik_linux, Loic Pallardy, Loic Pallardy

db8500-prcmu clean up, removing dbx540 definition from
db8500-prcmu file.

Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
---
 drivers/mfd/db8500-prcmu.c | 30 ++----------------------------
 drivers/mfd/dbx500-prcmu.c |  6 ++++--
 2 files changed, 6 insertions(+), 30 deletions(-)

diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index b39441f..164c9d5 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -2988,28 +2988,6 @@ 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,
-		.pdata_size = sizeof(db8500_regulators),
-	},
-	{
-		.name = "ab9540-i2c",
-		.of_compatible = "stericsson,ab8500",
-		.num_resources = ARRAY_SIZE(ab8500_resources),
-		.resources = ab8500_resources,
-		.id = AB8500_VERSION_AB9540,
-	},
-};
-
-
 /**
  * prcmu_fw_init - arch init call for the Linux PRCMU fw init logic
  *
@@ -3052,14 +3030,10 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (cpu_is_u8500v20_or_later() && !cpu_is_u9540())
+	if (cpu_is_u8500v20_or_later())
 		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,
-			ARRAY_SIZE(db9540_prcmu_devs), NULL, 0);
-	else
-		err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
+	err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
 			ARRAY_SIZE(db8500_prcmu_devs), NULL, 0);
 
 	if (err) {
diff --git a/drivers/mfd/dbx500-prcmu.c b/drivers/mfd/dbx500-prcmu.c
index 1823ab7..964804e 100644
--- a/drivers/mfd/dbx500-prcmu.c
+++ b/drivers/mfd/dbx500-prcmu.c
@@ -725,8 +725,10 @@ 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 (cpu_is_ux540_family())
+		data =  dbx540_prcmu_early_init(map);
+	else
+		data = db8500_prcmu_early_init(map);
 
 	if (data == NULL)
 		return;
-- 
1.7.11.1


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

* Re: [PATCH 02/17] arm: ux500: add ccu9540 board support
  2012-09-05  9:58 ` [PATCH 02/17] arm: ux500: add ccu9540 board support Loic Pallardy
@ 2012-09-05 10:42   ` Arnd Bergmann
  2012-09-05 11:38     ` Loic PALLARDY
  0 siblings, 1 reply; 27+ messages in thread
From: Arnd Bergmann @ 2012-09-05 10:42 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Loic Pallardy, Samuel Ortiz, linux-kernel, Linus Walleij,
	Loic Pallardy, STEricsson_nomadik_linux, Loic Pallardy,
	Lee Jones, LT ST-Ericsson

On Wednesday 05 September 2012, Loic Pallardy wrote:
> +MACHINE_START(U9540, "ST-Ericsson 9540 platform")
> +       .atag_offset    = 0x100,
> +       .map_io         = u8500_map_io,
> +       .nr_irqs        = UX500_NR_IRQS,
> +       .init_irq       = ux500_init_irq,
> +       .timer          = &ux500_timer,
> +       .handle_irq     = gic_handle_irq,
> +       .init_machine   = u9540_init_machine,
> +       .init_late      = ux500_init_late,
> +MACHINE_END
> +

Please don't add another ATAG based board definition to ux500. We're closing in
on having full support for DT booting with this platform, so your patch is just
making it harder for us to complete this. 

	Arnd

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

* Re: [PATCH 14/17] mfd: db8500-prcmu: use db8500 legacy services
  2012-09-05  9:59 ` [PATCH 14/17] mfd: db8500-prcmu: use db8500 legacy services Loic Pallardy
@ 2012-09-05 11:01   ` Arnd Bergmann
  0 siblings, 0 replies; 27+ messages in thread
From: Arnd Bergmann @ 2012-09-05 11:01 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Loic Pallardy, Samuel Ortiz, linux-kernel, Linus Walleij,
	Loic Pallardy, STEricsson_nomadik_linux, Loic Pallardy,
	Lee Jones, LT ST-Ericsson

On Wednesday 05 September 2012, Loic Pallardy wrote:
> This patch exposes db8500 legacy services which are
> now available to support new baseband.
> If different are needed, then services are overloaded.
> This allows to reduce duplicate code between projects.
> 
> Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> ---
>  drivers/mfd/db8500-prcmu.c | 90 +++++++++++++++++++++++-----------------------
>  drivers/mfd/dbx500-prcmu.h | 71 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 116 insertions(+), 45 deletions(-)
> 
> diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
> index 73c98e5..b39441f 100644
> --- a/drivers/mfd/db8500-prcmu.c
> +++ b/drivers/mfd/db8500-prcmu.c
> @@ -327,12 +327,12 @@ int db8500_prcmu_set_display_clocks(void)
>         return 0;
>  }
>  
> -static u32 db8500_prcmu_read(unsigned int reg)
> +u32 db8500_prcmu_read(unsigned int reg)
>  {
>         return readl(_PRCMU_BASE + reg);
>  }

If these are common to both db8500 and dbx540, why not put the definitions
into the common dbx500.c file, rather than making dbx540 depend on the
db8500?

	Arnd

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

* Re: [PATCH 02/17] arm: ux500: add ccu9540 board support
  2012-09-05 10:42   ` Arnd Bergmann
@ 2012-09-05 11:38     ` Loic PALLARDY
  2012-09-05 12:08       ` Linus Walleij
  2012-09-05 12:11       ` Arnd Bergmann
  0 siblings, 2 replies; 27+ messages in thread
From: Loic PALLARDY @ 2012-09-05 11:38 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Loic PALLARDY STE, Samuel Ortiz, linux-kernel,
	Linus Walleij, STEricsson_nomadik_linux, Loic Pallardy,
	Lee Jones, LT ST-Ericsson


On 09/05/2012 12:42 PM, Arnd Bergmann wrote:
> On Wednesday 05 September 2012, Loic Pallardy wrote:
>> +MACHINE_START(U9540, "ST-Ericsson 9540 platform")
>> +       .atag_offset    = 0x100,
>> +       .map_io         = u8500_map_io,
>> +       .nr_irqs        = UX500_NR_IRQS,
>> +       .init_irq       = ux500_init_irq,
>> +       .timer          =&ux500_timer,
>> +       .handle_irq     = gic_handle_irq,
>> +       .init_machine   = u9540_init_machine,
>> +       .init_late      = ux500_init_late,
>> +MACHINE_END
>> +
>
> Please don't add another ATAG based board definition to ux500. We're closing in
> on having full support for DT booting with this platform, so your patch is just
> making it harder for us to complete this.
>
> 	Arnd
Yes I know and agree.
Please consider this patch as a temporary one waiting for 9540 support 
from Lee.

Regards,
Loic

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

* Re: [PATCH 02/17] arm: ux500: add ccu9540 board support
  2012-09-05 11:38     ` Loic PALLARDY
@ 2012-09-05 12:08       ` Linus Walleij
  2012-09-05 12:11       ` Arnd Bergmann
  1 sibling, 0 replies; 27+ messages in thread
From: Linus Walleij @ 2012-09-05 12:08 UTC (permalink / raw)
  To: Loic PALLARDY
  Cc: Arnd Bergmann, linux-arm-kernel, Loic PALLARDY STE, Samuel Ortiz,
	linux-kernel, Linus Walleij, STEricsson_nomadik_linux,
	Loic Pallardy, Lee Jones, LT ST-Ericsson

On Wed, Sep 5, 2012 at 1:38 PM, Loic PALLARDY <loic.pallardy@st.com> wrote:
> On 09/05/2012 12:42 PM, Arnd Bergmann wrote:
>> On Wednesday 05 September 2012, Loic Pallardy wrote:
>>> +MACHINE_START(U9540, "ST-Ericsson 9540 platform")
>>> +       .atag_offset    = 0x100,
>>> +       .map_io         = u8500_map_io,
>>> +       .nr_irqs        = UX500_NR_IRQS,
>>> +       .init_irq       = ux500_init_irq,
>>> +       .timer          =&ux500_timer,
>>> +       .handle_irq     = gic_handle_irq,
>>> +       .init_machine   = u9540_init_machine,
>>> +       .init_late      = ux500_init_late,
>>> +MACHINE_END
>>
>> Please don't add another ATAG based board definition to ux500. We're closing in
>> on having full support for DT booting with this platform, so your patch is just
>> making it harder for us to complete this.
>>
>>       Arnd
> Yes I know and agree.
> Please consider this patch as a temporary one waiting for 9540 support
> from Lee.

It seems it would still be possible to create a patch series containing
just the PRCMU refactorings (which are really nice) and necessary
modifications to the MOP500 series so we could get this ground work
into the 3.7 merge window (if Sam is happy with it).

Actually it'd be nice to have a patch series containing that *and*
Lee's recent patches for e.g. IRQ domain on the PRCMU in one
big series, that would prepare the ground very nicely, then only
the DT board stuff would be missing for a successful U9540 DT
boot.

Is this possible?

Yours,
Linus Walleij

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

* Re: [PATCH 15/17] mfd: dbx540-prcmu creation
  2012-09-05  9:59 ` [PATCH 15/17] mfd: dbx540-prcmu creation Loic Pallardy
@ 2012-09-05 12:10   ` Arnd Bergmann
  2012-09-05 12:39     ` [st-ericsson] " Linus Walleij
  0 siblings, 1 reply; 27+ messages in thread
From: Arnd Bergmann @ 2012-09-05 12:10 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Loic Pallardy, Samuel Ortiz, linux-kernel, Linus Walleij,
	Loic Pallardy, STEricsson_nomadik_linux, Loic Pallardy,
	Lee Jones, LT ST-Ericsson

On Wednesday 05 September 2012, Loic Pallardy wrote:
 
> This driver offers support for ST-Ericsson DB9540 and
> DB8540 PRCMU.
> - add new communication interface named UniqPAP
> - add support for x540 HW
> 
> Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
> Acked-by: Linus Walleij <linus.walleij@linaro.org>

This makes me doubt the quality of Linus' Ack on other patches...

> diff --git a/drivers/mfd/dbx540-prcmu-regs.h b/drivers/mfd/dbx540-prcmu-regs.h
> new file mode 100644
> index 0000000..a15810d
> --- /dev/null
> +++ b/drivers/mfd/dbx540-prcmu-regs.h

This header file looks like it really should only be included in a
single .c file, so better put all the definitions in there.

> +#define PRCM_PLLDSITV_FREQ         (_PRCMU_BASE + 0x500)
> +#define PRCM_PLLDSITV_ENABLE       (_PRCMU_BASE + 0x504)
> +#define PRCM_PLLDSITV_LOCKP        (_PRCMU_BASE + 0x508)
> +#define PRCM_PLLDSILCD_FREQ        (_PRCMU_BASE + 0x290)
> +#define PRCM_PLLDSILCD_ENABLE      (_PRCMU_BASE + 0x294)
> +#define PRCM_PLLDSILCD_LOCKP       (_PRCMU_BASE + 0x298)

Please get rid of the global _PRCMU_BASE variable, at least for new
code. Instead, please use ioremap() of the resources passed in the
device tree, like we do for all other drivers.

> +#include <mach/hardware.h>
> +#include <mach/irqs.h>
> +#include <mach/db8500-regs.h>
> +#include <mach/hardware.h>

None of these should be needed in this driver, especially not twice.

> +/* mailbox definition */
> +static struct mb0_transfer mb0;
> +static struct mb2_transfer mb2;
> +static struct mb3_transfer mb3;
> +static struct mb4_transfer mb4;
> +static struct mb5_transfer mb5;

The entire mailbox system seems to be complicated by having a different
structure for each one, and no shared code between them. 

> +static void (*upap_read_services[UPAP_SERVICES_NB])(struct upap_req *req,
> +		struct upap_ack *ack);
> +
> +static int cpu1_unplug_ongoing;
> +static int prcmu_driver_initialised;
> +
> +static struct {
> +	bool valid;
> +	struct prcmu_fw_version version;
> +} fw_info;
> +
> +static unsigned long latest_armss_rate;
>
> +static atomic_t ac_wake_req_state = ATOMIC_INIT(0);
> +
> +/* Spinlocks */
> +static DEFINE_SPINLOCK(prcmu_lock);
> +static DEFINE_SPINLOCK(clkout_lock);
> +static DEFINE_SPINLOCK(spare_out_lock);
> +
> +/*
> + * Copies of the startup values of the reset status register and the SW reset
> + * code.
> + */
> +static u32 reset_status_copy;
> +static u16 reset_code_copy;
> +
> +static DEFINE_SPINLOCK(clk_mgt_lock);
> +

You have *way* too many static variables in this driver.

> +static int set_arm_freq(u32 freq);
> +static int get_arm_freq(void);

You should also just remove all forward declarations by reordering the
functions in the order they are called in.

> +#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
> +	{ (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
> +static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
> +	CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
> +	CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),

Never use string concatenation in macros to generate identifier names
like this. It makes it impossible to grep for where the symbols are used.
Better avoid those macros entirely and just open-code the array.

Another option would be to put the table into the device tree so you
can abstract the differences between the two prmu versions more easily.

> +
> +/*
> +* Used by MCDE to setup all necessary PRCMU registers
> +*/
> +#define PRCMU_RESET_DSIPLLTV		0x00004000
> +#define PRCMU_RESET_DSIPLLLCD		0x00008000
> +#define PRCMU_UNCLAMP_DSIPLL		0x00400800
> +
> +#define PRCMU_CLK_PLL_DIV_SHIFT		0
> +#define PRCMU_CLK_PLL_SW_SHIFT		5
> +#define PRCMU_CLK_38			(1 << 9)
> +#define PRCMU_CLK_38_SRC		(1 << 10)
> +#define PRCMU_CLK_38_DIV		(1 << 11)
> +
> +/* PLLDIV=12, PLLSW=4 (PLLDDR) */
> +#define PRCMU_DSI_CLOCK_SETTING		0x0000008C
> +/* PLLDIV = 12, PLLSW=1 (PLLSOC0) */
> +#define U9540_PRCMU_DSI_CLOCK_SETTING	0x0000002C
> +
> +/* DPI 50000000 Hz */
> +#define PRCMU_DPI_CLOCK_SETTING		((1 << PRCMU_CLK_PLL_SW_SHIFT) | \
> +					  (16 << PRCMU_CLK_PLL_DIV_SHIFT))
> +#define PRCMU_DSI_LP_CLOCK_SETTING	0x00000E00
> +
> +/* D=101, N=1, R=4, SELDIV2=0 */
> +#define PRCMU_PLLDSI_FREQ_SETTING	0x00040165
> +
> +#define PRCMU_ENABLE_PLLDSI		0x00000001
> +#define PRCMU_DISABLE_PLLDSI		0x00000000
> +#define PRCMU_RELEASE_RESET_DSS		0x0000400C
> +#define PRCMU_TV_DSI_PLLOUT_SEL_SETTING	0x00000202
> +#define PRCMU_LCD_DSI_PLLOUT_SEL_SETTING	0x00000A0A
> +/* ESC clk, div0=1, div1=1, div2=3 */
> +#define PRCMU_ENABLE_ESCAPE_CLOCK_DIV	0x07030101
> +#define PRCMU_DISABLE_ESCAPE_CLOCK_DIV	0x00030101
> +#define PRCMU_DSI_RESET_SW		0x00000007
> +
> +#define PRCMU_PLLDSI_LOCKP_LOCKED	0x3

A lot of this looks identical to the db8500 version, so maybe it's better to
have it in the generic dbx500-prcmu.c file?

> +/**
> +/**
> + * unplug_cpu1 - Power gate OFF CPU1 for U9540
> + * * void:
> + * Returns:
> + */
> +static int unplug_cpu1(void)
> +{
> +	int r = 0;
> +#ifdef CONFIG_UX500_ROMCODE_SHARED_MUTEX
> +	struct upap_req req;
> +	struct upap_ack ack;
> +
> +	/* Set flag start Hotplug sequence */
> +	cpu1_unplug_ongoing = 1;

> +
> +/**
> + * replug_cpu1 - Power gate ON CPU1 for U9540
> + * * void
> + * * Returns:
> + */
> +static int replug_cpu1(void)
> +{
> +	int r = 0;
> +#ifdef CONFIG_UX500_ROMCODE_SHARED_MUTEX
> +	struct upap_req req;
> +	struct upap_ack ack;
> +

Can you move these to a separate cpu-hotplug file?

> +/**
> + * 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.
> + *
> + * Configures one of the programmable clock outputs (CLKOUTs).
> + * @div should be in the range [1,63] to request a configuration, or 0 to
> + * inform that the configuration is no longer requested.
> + */
> +static int config_clkout(u8 clkout, u8 source, u8 div)
> +{

This again looks identical to the db8500 version.

> +/*
> + * set_arm_freq - set the appropriate ARM frequency for U9540
> + * @freq: The new ARM frequency to which transition is to be made (kHz)
> + * Returns: 0 on success, non-zero on failure
> + */
> +static int set_arm_freq(u32 freq)
> +{
> +	struct upap_req req;
> +	struct upap_ack ack;
> +	int r = 0;
> +
> +	if (dvfs_context.arm_freq == freq)
> +		return 0;
> +
> +
> +/**
> + * get_arm_freq - get the current ARM freq
> + *
> + * Returns: the current ARM freq (kHz).
> + * Not supported by U8500
> + */
> +static int get_arm_freq(void)
> +{
> +	u32 val;
> +	/*
> +	 * U9540 is not able to read ARM OPP value from TCDM. Therefore
> +	 * determine if the ARM OPP has been set, or not.
> +	 */
> +	if (dvfs_context.arm_freq != 0)
> +		return dvfs_context.arm_freq;
> +

These look like they belong into the cpufreq driver.

> +static unsigned long dbx540_prcmu_clock_rate(u8 clock)
> +{
> +	if (clock < PRCMU_NUM_REG_CLOCKS)
> +		return clock_rate(clock);
> +	else if (clock == PRCMU_TIMCLK)
> +		return ROOT_CLOCK_RATE / 16;
> +	else if (clock == PRCMU_SYSCLK)
> +		return ROOT_CLOCK_RATE;
> +	else if (clock == PRCMU_PLLSOC0)
> +		return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
> +	else if (clock == PRCMU_PLLSOC1)
> +		return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
> +	else if (clock == PRCMU_PLLDDR)
> +		return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
> +	else if (clock == PRCMU_PLLDSI)
> +		return pll_rate(PRCM_PLLDSITV_FREQ, clock_rate(PRCMU_HDMICLK),
> +			PLL_RAW);
> +	else if (clock == PRCMU_ARMSS)
> +		return KHZ_TO_HZ(armss_rate());
> +	else if (clock == PRCMU_ARMCLK)
> +		return KHZ_TO_HZ(get_arm_freq());
> +	else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
> +		return dsiclk_rate(clock - PRCMU_DSI0CLK, false);
> +	else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
> +		return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK);
> +	else if (clock == PRCMU_PLLDSI_LCD)
> +		return pll_rate(PRCM_PLLDSILCD_FREQ,
> +					clock_rate(PRCMU_SPARE1CLK), PLL_RAW);
> +	else if ((clock == PRCMU_DSI0CLK_LCD) || (clock == PRCMU_DSI1CLK_LCD))
> +		return dsiclk_rate(clock - PRCMU_DSI0CLK_LCD, true);
> +	else
> +		return 0;
> +}

Please use the common clock code for managing these.
No more private clock implementations.

> +void prcmu_reset_hva(void)
> +{
> +	writel(PRCM_C2C_RESETN_HVA_MEM | PRCM_C2C_RESETN_HVA_LOGIC,
> +			PRCM_C2C_RESETN_CLR);
> +	writel(PRCM_C2C_RESETN_HVA_MEM | PRCM_C2C_RESETN_HVA_LOGIC,
> +			PRCM_C2C_RESETN_SET);
> +}
> +EXPORT_SYMBOL(prcmu_reset_hva);
> +
> +void prcmu_reset_hx170(void)
> +{
> +	writel(PRCM_C2C_RESETN_G1_MEM | PRCM_C2C_RESETN_G1_LOGIC,
> +			PRCM_C2C_RESETN_CLR);
> +	writel(PRCM_C2C_RESETN_G1_MEM | PRCM_C2C_RESETN_G1_LOGIC,
> +			PRCM_C2C_RESETN_SET);
> +}
> +EXPORT_SYMBOL(prcmu_reset_hx170);

Why is the dbx540 driver exporting symbols for non-GPL drivers?
Shouldn't this be handled through the common dbx500 code, if at all?

> +/**
> + * get_reset_status - Retrieve reset status
> + *
> + * Retrieves the value of the reset status register as read at startup.
> + */
> +u32 get_reset_status(void)
> +{
> +	return reset_status_copy;
> +}
> +
> +/**
> + * prcmu_reset_modem - ask the PRCMU to reset modem
> + */
> +void modem_reset(void)
> +{
> +	prcmu_modem_reset_db9540();
> +}

Moreover, why do you have any global functions in this driver that
are not in a well-defined namespace?

> +static struct prcmu_early_data early_fops = {
> +	/*  system reset  */
> +	.system_reset = db8500_prcmu_system_reset,
> +
> +	/*  clock service */
> +	.config_clkout = config_clkout,
> +	.request_clock = dbx540_prcmu_request_clock,
> +
> +	/*  direct register access */
> +	.read = db8500_prcmu_read,
> +	.write =  db8500_prcmu_write,
> +	.write_masked = db8500_prcmu_write_masked,
> +	/* others */
> +	.round_clock_rate = dbx540_prcmu_round_clock_rate,
> +	.set_clock_rate = dbx540_prcmu_set_clock_rate,
> +	.clock_rate = dbx540_prcmu_clock_rate,
> +	.get_fw_version = get_fw_version,
> +	.has_arm_maxopp = has_arm_maxopp,
> +};

What does the "f" in fops stand for?

Why are these all early?

Why do you have an abstract interface for functions that are the same
between db8500 and dbx540, rather than just the different ones?

> +struct prcmu_probe_data probe_fops = {
> +	/* sysfs soc inf */
> +	.get_reset_code = get_reset_code,
> +
> +	/* pm/suspend.c/cpu freq */
> +	.config_esram0_deep_sleep = 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 = is_ac_wake_requested,
> +
> +	/* modem */
> +	.modem_reset = 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,
> +	.get_reset_status = get_reset_status,
> +	/*  other u8500 specific */
> +	.request_ape_opp_100_voltage = 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,
> +};

Same comment about these

> +struct prcmu_probe_cpuhp_data probe_cpuhp_fops = {
> +
> +	.stay_in_wfi_check = stay_in_wfi_check,
> +	.replug_cpu1 = replug_cpu1,
> +	.unplug_cpu1 = unplug_cpu1,
> +};
> +
> +static struct prcmu_fops_register probe_tab[] = {
> +	{
> +		.fops = PRCMU_PROBE,
> +		.data.pprobe = &probe_fops,
> +	},
> +	{
> +		.fops = PRCMU_PROBE_CPU_HP,
> +		.data.pprobe_cpuhp =&probe_cpuhp_fops,
> +	},
> +};
> +
> +struct prcmu_fops_register_data probe_data = {
> +	.size = ARRAY_SIZE(probe_tab),
> +	.tab = probe_tab,
> +};

I'm lost in the number of abstraction layers here.

> +struct prcmu_fops_register_data *__init
> +			dbx540_prcmu_early_init(struct prcmu_tcdm_map *map)
> +{
> +	void *tcpm_base = ioremap_nocache(U8500_PRCMU_TCPM_BASE, SZ_4K);

Please use the resources rather than hardcoding a physical address.

> +	db8500_prcmu_init_mb0(&mb0);
> +	/*  mailbox 1 used by UniqPAP */
> +	db8500_prcmu_init_mb2(&mb2);
> +	db8500_prcmu_init_mb3(&mb3);
> +	db8500_prcmu_init_mb4(&mb4);
> +	db8500_prcmu_init_mb5(&mb5);

I think it would be good to split out all the mailbox handling into a
separate file, and provide a proper abstraction for it, based on a
data structure that can hold pointers to the init/read/write/... functions
as well as the common data for all mailboxes, such as

struct prcmu_mailbox {
	struct mutex lock;
	struct completion complete;
	bool (*read)(struct prcmu_mailbox *);
	void (*init)(struct prcmu_mailbox *):
}

> +	/* initialize UniqPAP */
> +	upap_init();
> +	/* register UniqPAP services */
> +	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_DVFS,
> +			upap_read_service_dvfs);
> +	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_USB,
> +			upap_read_service_usb);
> +	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_CLOCK,
> +			upap_read_service_clock);
> +	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_MODEM,
> +			upap_read_service_modem);
> +	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_CPUHOTPLUG,
> +			upap_read_service_cpuhotplug);
> +	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_THSENSOR,
> +			upap_read_service_thsensor);
> +	upap_register_ack_service(U9540_PRCM_UPAP_SERVICE_DDR,
> +			upap_read_service_ddr);

And then a separate file for the new upap stuff, with a similar
structure.

> +
> +static struct regulator_init_data dbx540_regulators[DB8500_NUM_REGULATORS] = {
> +	[DB8500_REGULATOR_VAPE] = {
> +		.constraints = {
> +			.name = "db8500-vape",
> +			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
> +		},
> +		.consumer_supplies = db8500_vape_consumers,
> +		.num_consumer_supplies = ARRAY_SIZE(db8500_vape_consumers),
> +	},


The array again looks a lot like the db8500 one. Please find a way to share more
of the code.

> +/**
> + * prcmu_fw_init - core init call for the Linux PRCMU fw init logic
> + *
> + */
> +static int __init dbx540_prcmu_probe(struct platform_device *pdev)
> +{
> +	int irq = 0, err = 0;
> +	struct device_node *np = pdev->dev.of_node;
> +
> +	init_prcm_registers();
> +
> +	writel(ALL_MBOX_BITS, PRCM_ARM_IT1_CLR);
> +

Please move the common parts of this function into dbx500-prcmu.c

> +	if(np) {
> +		if (of_property_read_u32_array(np,
> +				"stericsson,db8500-frequency-tab ",
> +				(u32 *)freq_table, 7) < 0)
> +                         dev_err(&pdev->dev, "frequency tab\n");
> +	} else
> +		freq_table =
> +			(struct cpufreq_frequency_table *)dev_get_platdata(&pdev->dev);

I haven't seen a binding for this property yet. Please make sure you post the
binding along with the patch.

> +#ifdef CONFIG_C2C
> +void prcmu_c2c_request_notif_up(void);
> +void prcmu_c2c_request_reset(void);
> +#endif

No need to enclose declarations in #ifdef, unless you provide an empty
stub in the #else path.


	Arnd

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

* Re: [PATCH 02/17] arm: ux500: add ccu9540 board support
  2012-09-05 11:38     ` Loic PALLARDY
  2012-09-05 12:08       ` Linus Walleij
@ 2012-09-05 12:11       ` Arnd Bergmann
  2012-09-05 12:41         ` [st-ericsson] " Linus Walleij
  1 sibling, 1 reply; 27+ messages in thread
From: Arnd Bergmann @ 2012-09-05 12:11 UTC (permalink / raw)
  To: linux-arm-kernel
  Cc: Loic PALLARDY, Loic PALLARDY STE, Samuel Ortiz, linux-kernel,
	STEricsson_nomadik_linux, Loic Pallardy, Lee Jones,
	LT ST-Ericsson, Linus Walleij

On Wednesday 05 September 2012, Loic PALLARDY wrote:
> 
> On 09/05/2012 12:42 PM, Arnd Bergmann wrote:
> > On Wednesday 05 September 2012, Loic Pallardy wrote:
> >> +MACHINE_START(U9540, "ST-Ericsson 9540 platform")
> >> +       .atag_offset    = 0x100,
> >> +       .map_io         = u8500_map_io,
> >> +       .nr_irqs        = UX500_NR_IRQS,
> >> +       .init_irq       = ux500_init_irq,
> >> +       .timer          =&ux500_timer,
> >> +       .handle_irq     = gic_handle_irq,
> >> +       .init_machine   = u9540_init_machine,
> >> +       .init_late      = ux500_init_late,
> >> +MACHINE_END
> >> +
> >
> > Please don't add another ATAG based board definition to ux500. We're closing in
> > on having full support for DT booting with this platform, so your patch is just
> > making it harder for us to complete this.
> >
> >       Arnd
> Yes I know and agree.
> Please consider this patch as a temporary one waiting for 9540 support 
> from Lee.

Why are you even posting the patches that you know won't make it then?

	Arnd

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

* Re: [st-ericsson] [PATCH 15/17] mfd: dbx540-prcmu creation
  2012-09-05 12:10   ` Arnd Bergmann
@ 2012-09-05 12:39     ` Linus Walleij
  2012-09-05 12:52       ` Arnd Bergmann
  0 siblings, 1 reply; 27+ messages in thread
From: Linus Walleij @ 2012-09-05 12:39 UTC (permalink / raw)
  To: Arnd Bergmann, Ulf Hansson, Loic Pallardy
  Cc: linux-arm-kernel, Samuel Ortiz, Loic Pallardy, linux-kernel,
	STEricsson_nomadik_linux, Loic Pallardy, LT ST-Ericsson,
	Linus Walleij

On Wed, Sep 5, 2012 at 2:10 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 05 September 2012, Loic Pallardy wrote:
>>
>> Signed-off-by: Loic Pallardy <loic.pallardy@stericsson.com>
>> Acked-by: Linus Walleij <linus.walleij@linaro.org>
>
> This makes me doubt the quality of Linus' Ack on other patches...

Basically the rationale is that to me the driver looks better after these
patches than before. But the basic problem is that I've read
the driver so much internally that I am already unable to see
some of it's shortcomings. (And a fair share of these comments
would apply to the already in-tree driver as well.) And we really
need help to figure out how to handle this beast. So fresh reviews
like this are much, much appreciated....

>> +#define PRCM_PLLDSITV_FREQ         (_PRCMU_BASE + 0x500)
>> +#define PRCM_PLLDSITV_ENABLE       (_PRCMU_BASE + 0x504)
>> +#define PRCM_PLLDSITV_LOCKP        (_PRCMU_BASE + 0x508)
>> +#define PRCM_PLLDSILCD_FREQ        (_PRCMU_BASE + 0x290)
>> +#define PRCM_PLLDSILCD_ENABLE      (_PRCMU_BASE + 0x294)
>> +#define PRCM_PLLDSILCD_LOCKP       (_PRCMU_BASE + 0x298)
>
> Please get rid of the global _PRCMU_BASE variable, at least for new
> code. Instead, please use ioremap() of the resources passed in the
> device tree, like we do for all other drivers.

Sounds reasonable, but historically we needed to write and control the
PRCMU before ioremap() is available. (Like at irq_init() time.)

If I'm not mistaken this has been fixed now, so what you say is true.

>> +#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
>> +     { (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
>> +static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
>> +     CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
>> +     CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),
>(...)
> Another option would be to put the table into the device tree so you
> can abstract the differences between the two prmu versions more easily.

This falls back to the debate of whether SoC properties shall be
heavily encoded into the device tree, a point of contention. Doing
that may make the driver even harder to read than these macros,
like you need the driver, the device tree and the data sheet and
read all three simultaneously to understand what is going on.

>> +/**
>> + * replug_cpu1 - Power gate ON CPU1 for U9540
>> + * * void
>> + * * Returns:
>> + */
>> +static int replug_cpu1(void)
>> +{
>> +     int r = 0;
>> +#ifdef CONFIG_UX500_ROMCODE_SHARED_MUTEX
>> +     struct upap_req req;
>> +     struct upap_ack ack;
>
> Can you move these to a separate cpu-hotplug file?

Isn't this a more general comment such as that we should distribute
out the code in the PRCMU out into the device drivers? I think you or
someone else said that at some point, and that would then go for
all of them I think, then the PRCMU driver would just be a MFD
hub and mailbox/regmap provider in the end.

How to get there is another question...

>> +static unsigned long dbx540_prcmu_clock_rate(u8 clock)
>> +{
>> +     if (clock < PRCMU_NUM_REG_CLOCKS)
>> +             return clock_rate(clock);
>> +     else if (clock == PRCMU_TIMCLK)
>> +             return ROOT_CLOCK_RATE / 16;
>> +     else if (clock == PRCMU_SYSCLK)
>> +             return ROOT_CLOCK_RATE;
>> +     else if (clock == PRCMU_PLLSOC0)
>> +             return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
>> +     else if (clock == PRCMU_PLLSOC1)
>> +             return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
>> +     else if (clock == PRCMU_PLLDDR)
>> +             return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
>> +     else if (clock == PRCMU_PLLDSI)
>> +             return pll_rate(PRCM_PLLDSITV_FREQ, clock_rate(PRCMU_HDMICLK),
>> +                     PLL_RAW);
>> +     else if (clock == PRCMU_ARMSS)
>> +             return KHZ_TO_HZ(armss_rate());
>> +     else if (clock == PRCMU_ARMCLK)
>> +             return KHZ_TO_HZ(get_arm_freq());
>> +     else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
>> +             return dsiclk_rate(clock - PRCMU_DSI0CLK, false);
>> +     else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
>> +             return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK);
>> +     else if (clock == PRCMU_PLLDSI_LCD)
>> +             return pll_rate(PRCM_PLLDSILCD_FREQ,
>> +                                     clock_rate(PRCMU_SPARE1CLK), PLL_RAW);
>> +     else if ((clock == PRCMU_DSI0CLK_LCD) || (clock == PRCMU_DSI1CLK_LCD))
>> +             return dsiclk_rate(clock - PRCMU_DSI0CLK_LCD, true);
>> +     else
>> +             return 0;
>> +}
>
> Please use the common clock code for managing these.
> No more private clock implementations.

So here again there is a driver split issue. I think Ulf's current clock
implementation just use these implementations, so this would be a matter
of pushing that code down into the clock driver and decentralize this
PRCMU driver a bit more.

>> +     db8500_prcmu_init_mb0(&mb0);
>> +     /*  mailbox 1 used by UniqPAP */
>> +     db8500_prcmu_init_mb2(&mb2);
>> +     db8500_prcmu_init_mb3(&mb3);
>> +     db8500_prcmu_init_mb4(&mb4);
>> +     db8500_prcmu_init_mb5(&mb5);
>
> I think it would be good to split out all the mailbox handling into a
> separate file, and provide a proper abstraction for it,

This is what is happening in patch 11/17, elbeit it's just a separate
header. Thinking of it, I think it's possible to create a separate file
for the code too.

> based on a
> data structure that can hold pointers to the init/read/write/... functions
> as well as the common data for all mailboxes, such as
>
> struct prcmu_mailbox {
>         struct mutex lock;
>         struct completion complete;
>         bool (*read)(struct prcmu_mailbox *);
>         void (*init)(struct prcmu_mailbox *):
> }

This looks like a good idea.

Yours,
Linus Walleij

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

* Re: [st-ericsson] [PATCH 02/17] arm: ux500: add ccu9540 board support
  2012-09-05 12:11       ` Arnd Bergmann
@ 2012-09-05 12:41         ` Linus Walleij
  0 siblings, 0 replies; 27+ messages in thread
From: Linus Walleij @ 2012-09-05 12:41 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: linux-arm-kernel, Loic PALLARDY STE, Samuel Ortiz, linux-kernel,
	STEricsson_nomadik_linux, Loic Pallardy, LT ST-Ericsson,
	Linus Walleij

On Wed, Sep 5, 2012 at 2:11 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Wednesday 05 September 2012, Loic PALLARDY wrote:
>>
>> On 09/05/2012 12:42 PM, Arnd Bergmann wrote:
>> > On Wednesday 05 September 2012, Loic Pallardy wrote:
>> >> +MACHINE_START(U9540, "ST-Ericsson 9540 platform")
>> >> +       .atag_offset    = 0x100,
>> >> +       .map_io         = u8500_map_io,
>> >> +       .nr_irqs        = UX500_NR_IRQS,
>> >> +       .init_irq       = ux500_init_irq,
>> >> +       .timer          =&ux500_timer,
>> >> +       .handle_irq     = gic_handle_irq,
>> >> +       .init_machine   = u9540_init_machine,
>> >> +       .init_late      = ux500_init_late,
>> >> +MACHINE_END
>> >> +
>> >
>> > Please don't add another ATAG based board definition to ux500. We're closing in
>> > on having full support for DT booting with this platform, so your patch is just
>> > making it harder for us to complete this.
>> >
>> >       Arnd
>> Yes I know and agree.
>> Please consider this patch as a temporary one waiting for 9540 support
>> from Lee.
>
> Why are you even posting the patches that you know won't make it then?

My fault! I wanted an outside look at them before we take them
too far.

I should've requested to have the "RFC" prefix attached to them.

Sorry if it annoyed you too much...

Yours,
Linus Walleij

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

* Re: [st-ericsson] [PATCH 15/17] mfd: dbx540-prcmu creation
  2012-09-05 12:39     ` [st-ericsson] " Linus Walleij
@ 2012-09-05 12:52       ` Arnd Bergmann
  0 siblings, 0 replies; 27+ messages in thread
From: Arnd Bergmann @ 2012-09-05 12:52 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Ulf Hansson, Loic Pallardy, linux-arm-kernel, Samuel Ortiz,
	Loic Pallardy, linux-kernel, STEricsson_nomadik_linux,
	Loic Pallardy, LT ST-Ericsson, Linus Walleij

On Wednesday 05 September 2012, Linus Walleij wrote:
> On Wed, Sep 5, 2012 at 2:10 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Wednesday 05 September 2012, Loic Pallardy wrote:

> >> +#define PRCM_PLLDSITV_FREQ         (_PRCMU_BASE + 0x500)
> >> +#define PRCM_PLLDSITV_ENABLE       (_PRCMU_BASE + 0x504)
> >> +#define PRCM_PLLDSITV_LOCKP        (_PRCMU_BASE + 0x508)
> >> +#define PRCM_PLLDSILCD_FREQ        (_PRCMU_BASE + 0x290)
> >> +#define PRCM_PLLDSILCD_ENABLE      (_PRCMU_BASE + 0x294)
> >> +#define PRCM_PLLDSILCD_LOCKP       (_PRCMU_BASE + 0x298)
> >
> > Please get rid of the global _PRCMU_BASE variable, at least for new
> > code. Instead, please use ioremap() of the resources passed in the
> > device tree, like we do for all other drivers.
> 
> Sounds reasonable, but historically we needed to write and control the
> PRCMU before ioremap() is available. (Like at irq_init() time.)
> 
> If I'm not mistaken this has been fixed now, so what you say is true.

Ok, very good.

> >> +#define CLK_MGT_ENTRY(_name, _branch, _clk38div)[PRCMU_##_name] = \
> >> +     { (PRCM_##_name##_MGT), 0 , _branch, _clk38div}
> >> +static struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
> >> +     CLK_MGT_ENTRY(SGACLK, PLL_DIV, false),
> >> +     CLK_MGT_ENTRY(UARTCLK, PLL_FIX, true),
> >(...)
> > Another option would be to put the table into the device tree so you
> > can abstract the differences between the two prmu versions more easily.
> 
> This falls back to the debate of whether SoC properties shall be
> heavily encoded into the device tree, a point of contention. Doing
> that may make the driver even harder to read than these macros,
> like you need the driver, the device tree and the data sheet and
> read all three simultaneously to understand what is going on.

Yes, and I'll gladly leave the choice of how far to move stuff into the
device tree in your hands as the platform maintainer, as you can best
tell how many other prcmu variants we are going to see in the future.
Generally, I think there is a stronger reason for putting stuff into
DT when you have a lot of chips that only differ in this data.

> >> +/**
> >> + * replug_cpu1 - Power gate ON CPU1 for U9540
> >> + * * void
> >> + * * Returns:
> >> + */
> >> +static int replug_cpu1(void)
> >> +{
> >> +     int r = 0;
> >> +#ifdef CONFIG_UX500_ROMCODE_SHARED_MUTEX
> >> +     struct upap_req req;
> >> +     struct upap_ack ack;
> >
> > Can you move these to a separate cpu-hotplug file?
> 
> Isn't this a more general comment such as that we should distribute
> out the code in the PRCMU out into the device drivers? I think you or
> someone else said that at some point, and that would then go for
> all of them I think, then the PRCMU driver would just be a MFD
> hub and mailbox/regmap provider in the end.
> 
> How to get there is another question...

Right. Splitting out the mailboxes and the clock handling would probably
a good step in that direction, then we can see what is left in the
MFD driver.

> >> +static unsigned long dbx540_prcmu_clock_rate(u8 clock)
> >> +{
> >> +     if (clock < PRCMU_NUM_REG_CLOCKS)
> >> +             return clock_rate(clock);
> >> +     else if (clock == PRCMU_TIMCLK)
> >> +             return ROOT_CLOCK_RATE / 16;
> >> +     else if (clock == PRCMU_SYSCLK)
> >> +             return ROOT_CLOCK_RATE;
> >> +     else if (clock == PRCMU_PLLSOC0)
> >> +             return pll_rate(PRCM_PLLSOC0_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
> >> +     else if (clock == PRCMU_PLLSOC1)
> >> +             return pll_rate(PRCM_PLLSOC1_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
> >> +     else if (clock == PRCMU_PLLDDR)
> >> +             return pll_rate(PRCM_PLLDDR_FREQ, ROOT_CLOCK_RATE, PLL_RAW);
> >> +     else if (clock == PRCMU_PLLDSI)
> >> +             return pll_rate(PRCM_PLLDSITV_FREQ, clock_rate(PRCMU_HDMICLK),
> >> +                     PLL_RAW);
> >> +     else if (clock == PRCMU_ARMSS)
> >> +             return KHZ_TO_HZ(armss_rate());
> >> +     else if (clock == PRCMU_ARMCLK)
> >> +             return KHZ_TO_HZ(get_arm_freq());
> >> +     else if ((clock == PRCMU_DSI0CLK) || (clock == PRCMU_DSI1CLK))
> >> +             return dsiclk_rate(clock - PRCMU_DSI0CLK, false);
> >> +     else if ((PRCMU_DSI0ESCCLK <= clock) && (clock <= PRCMU_DSI2ESCCLK))
> >> +             return dsiescclk_rate(clock - PRCMU_DSI0ESCCLK);
> >> +     else if (clock == PRCMU_PLLDSI_LCD)
> >> +             return pll_rate(PRCM_PLLDSILCD_FREQ,
> >> +                                     clock_rate(PRCMU_SPARE1CLK), PLL_RAW);
> >> +     else if ((clock == PRCMU_DSI0CLK_LCD) || (clock == PRCMU_DSI1CLK_LCD))
> >> +             return dsiclk_rate(clock - PRCMU_DSI0CLK_LCD, true);
> >> +     else
> >> +             return 0;
> >> +}
> >
> > Please use the common clock code for managing these.
> > No more private clock implementations.
> 
> So here again there is a driver split issue. I think Ulf's current clock
> implementation just use these implementations, so this would be a matter
> of pushing that code down into the clock driver and decentralize this
> PRCMU driver a bit more.

Right, I think the clock driver should really be the place that knows about
the different kinds of clocks, rather than just calling into a different
driver that handles all the details.

	Arnd

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

end of thread, other threads:[~2012-09-05 12:52 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-05  9:58 [PATCH 00/17] Add ST-Ericsson U9540 support Loic Pallardy
2012-09-05  9:58 ` [PATCH 01/17] arm: ux500: add u9540 pin configuration Loic Pallardy
2012-09-05  9:58 ` [PATCH 02/17] arm: ux500: add ccu9540 board support Loic Pallardy
2012-09-05 10:42   ` Arnd Bergmann
2012-09-05 11:38     ` Loic PALLARDY
2012-09-05 12:08       ` Linus Walleij
2012-09-05 12:11       ` Arnd Bergmann
2012-09-05 12:41         ` [st-ericsson] " Linus Walleij
2012-09-05  9:58 ` [PATCH 03/17] arm: ux500: Create board-specific IRQ init callback Loic Pallardy
2012-09-05  9:59 ` [PATCH 04/17] mfd: dbx500-prcmu: Introduce TCDM mapping struct Loic Pallardy
2012-09-05  9:59 ` [PATCH 05/17] mfd: dbx500-prcmu: Handle TCDM mapping Loic Pallardy
2012-09-05  9:59 ` [PATCH 06/17] arm: ux500: Add u9540 PRCMU TCDM configuration Loic Pallardy
2012-09-05  9:59 ` [PATCH 07/17] mfd: prcmu: configurable tcdm base address Loic Pallardy
2012-09-05  9:59 ` [PATCH 08/17] arm: ux500: update DB internal irq nb Loic Pallardy
2012-09-05  9:59 ` [PATCH 09/17] mfd: prcmu: add db9540 support Loic Pallardy
2012-09-05  9:59 ` [PATCH 10/17] mfd: prcmu: dbx500-prmcu creation Loic Pallardy
2012-09-05  9:59 ` [PATCH 11/17] mfd: pcrmu: create common header file for legacy mailbox Loic Pallardy
2012-09-05  9:59 ` [PATCH 12/17] mfd: prcmu: make fw_project_name generic Loic Pallardy
2012-09-05  9:59 ` [PATCH 13/17] mfd: prcmu: make legacy mailbox services configurable Loic Pallardy
2012-09-05  9:59 ` [PATCH 14/17] mfd: db8500-prcmu: use db8500 legacy services Loic Pallardy
2012-09-05 11:01   ` Arnd Bergmann
2012-09-05  9:59 ` [PATCH 15/17] mfd: dbx540-prcmu creation Loic Pallardy
2012-09-05 12:10   ` Arnd Bergmann
2012-09-05 12:39     ` [st-ericsson] " Linus Walleij
2012-09-05 12:52       ` Arnd Bergmann
2012-09-05  9:59 ` [PATCH 16/17] arm: ux500: add dbx540 prcmu platform data Loic Pallardy
2012-09-05  9:59 ` [PATCH 17/17] mfd: db8500-prcmu: activate dbx540-prcmu driver Loic Pallardy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).