msm: pil-q6v4: Split out modem and lpass drivers

Separate the pil-q6v4 driver into subsystem specific drivers for
lpass and modem respectively. This is necessary so that we can
move the subsystem restart code for the lpass and modem
subsystems into their respective pil drivers in a later patch.

Change-Id: Id5e899b5c9cc7d1a3529d1a5f0ff24798f213f00
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 45d52e4..6a6bfda 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -71,7 +71,8 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_AVS_HW=y
 # CONFIG_MSM_HW3D is not set
-CONFIG_MSM_PIL_QDSP6V4=y
+CONFIG_MSM_PIL_LPASS_QDSP6V4=y
+CONFIG_MSM_PIL_MODEM_QDSP6V4=y
 CONFIG_MSM_PIL_RIVA=y
 CONFIG_MSM_PIL_TZAPPS=y
 CONFIG_MSM_PIL_DSPS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 465598f..cf2dd23 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -70,7 +70,8 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_AVS_HW=y
 # CONFIG_MSM_HW3D is not set
-CONFIG_MSM_PIL_QDSP6V4=y
+CONFIG_MSM_PIL_LPASS_QDSP6V4=y
+CONFIG_MSM_PIL_MODEM_QDSP6V4=y
 CONFIG_MSM_PIL_RIVA=y
 CONFIG_MSM_PIL_TZAPPS=y
 CONFIG_MSM_PIL_DSPS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 2020422..bda885a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1914,13 +1914,25 @@
 	  Support for booting and shutting down QDSP6v3 processors (hexagon).
 	  The QDSP6 is a low power DSP used in audio software applications.
 
-config MSM_PIL_QDSP6V4
-	tristate "QDSP6v4 (Hexagon) Boot Support"
+config MSM_PIL_LPASS_QDSP6V4
+	tristate "LPASS QDSP6v4 (Hexagon) Boot Support"
 	depends on MSM_PIL
 	help
-	  Support for booting and shutting down QDSP6v4 processors (hexagon).
-	  The QDSP6 is a low power DSP used in audio, modem firmware, and modem
-	  software applications.
+	  Support for booting and shutting down QDSP6v4 processors (hexagon)
+	  in low power audio subsystems. If you would like to record or
+	  play audio then say Y here.
+
+	  If unsure, say N.
+
+config MSM_PIL_MODEM_QDSP6V4
+	tristate "Modem QDSP6v4 (Hexagon) Boot Support"
+	depends on MSM_PIL
+	help
+	  Support for booting and shutting down QDSP6v4 processors (hexagon)
+	  in modem subsystems. If you would like to make or receive phone
+	  calls then say Y here.
+
+	  If unsure, say N.
 
 config MSM_PIL_LPASS_QDSP6V5
        tristate "LPASS QDSP6v5 (Hexagon) Boot Support"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 8f35d9a..d60fc6c 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -72,7 +72,8 @@
 obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
 obj-$(CONFIG_MSM_PIL) += scm-pas.o
 obj-$(CONFIG_MSM_PIL_QDSP6V3) += pil-q6v3.o
-obj-$(CONFIG_MSM_PIL_QDSP6V4) += pil-q6v4.o
+obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V4) += pil-q6v4.o pil-q6v4-lpass.o
+obj-$(CONFIG_MSM_PIL_MODEM_QDSP6V4) += pil-q6v4.o pil-q6v4-mss.o
 obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
 obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-q6v5-mss.o
 obj-$(CONFIG_MSM_PIL_MBA) += pil-mba.o
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index ef3c81d..2bef087 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -121,8 +121,6 @@
 };
 VREG_CONSUMERS(L23) = {
 	REGULATOR_SUPPLY("8921_l23",		NULL),
-	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.1"),
-	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.2"),
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.0"),
 	REGULATOR_SUPPLY("HSUSB_1p8",		"msm_ehci_host.1"),
 };
@@ -141,15 +139,13 @@
 };
 VREG_CONSUMERS(L26) = {
 	REGULATOR_SUPPLY("8921_l26",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.0"),
+	REGULATOR_SUPPLY("core_vdd",		"pil-q6v4-lpass"),
 };
 VREG_CONSUMERS(L27) = {
 	REGULATOR_SUPPLY("8921_l27",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.2"),
 };
 VREG_CONSUMERS(L28) = {
 	REGULATOR_SUPPLY("8921_l28",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.1"),
 };
 VREG_CONSUMERS(L29) = {
 	REGULATOR_SUPPLY("8921_l29",		NULL),
diff --git a/arch/arm/mach-msm/board-8930-regulator-pm8038.c b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
index 208f15b..16a82b4 100644
--- a/arch/arm/mach-msm/board-8930-regulator-pm8038.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
@@ -117,7 +117,7 @@
 };
 VREG_CONSUMERS(L16) = {
 	REGULATOR_SUPPLY("8038_l16",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.2"),
+	REGULATOR_SUPPLY("sw_core_vdd",		"pil-q6v4-modem"),
 };
 VREG_CONSUMERS(L17) = {
 	REGULATOR_SUPPLY("8038_l17",		NULL),
@@ -127,7 +127,7 @@
 };
 VREG_CONSUMERS(L19) = {
 	REGULATOR_SUPPLY("8038_l19",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.1"),
+	REGULATOR_SUPPLY("fw_core_vdd",		"pil-q6v4-modem"),
 };
 VREG_CONSUMERS(L20) = {
 	REGULATOR_SUPPLY("8038_l20",		NULL),
@@ -151,8 +151,7 @@
 	REGULATOR_SUPPLY("hdmi_avdd",		"hdmi_msm.0"),
 	REGULATOR_SUPPLY("hdmi_vcc",		"hdmi_msm.0"),
 	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
-	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.1"),
-	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.2"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil-q6v4-modem"),
 };
 VREG_CONSUMERS(L24) = {
 	REGULATOR_SUPPLY("8038_l24",		NULL),
@@ -166,7 +165,7 @@
 };
 VREG_CONSUMERS(L27) = {
 	REGULATOR_SUPPLY("8038_l27",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.0"),
+	REGULATOR_SUPPLY("core_vdd",		"pil-q6v4-lpass"),
 };
 VREG_CONSUMERS(S1) = {
 	REGULATOR_SUPPLY("8038_s1",		NULL),
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index ed876c0..47292ac 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -2347,8 +2347,7 @@
 
 static struct platform_device *common_devices[] __initdata = {
 	&msm_8960_q6_lpass,
-	&msm_8960_q6_mss_fw,
-	&msm_8960_q6_mss_sw,
+	&msm_8960_q6_mss,
 	&msm_8960_riva,
 	&msm_pil_tzapps,
 	&msm_pil_vidc,
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 2fa98b6..a6c0bc7 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -120,8 +120,7 @@
 	REGULATOR_SUPPLY("dsi_pll_vddio",	"mdp.0"),
 	REGULATOR_SUPPLY("hdmi_avdd",		"hdmi_msm.0"),
 	REGULATOR_SUPPLY("pll_vdd",		"pil_riva"),
-	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.1"),
-	REGULATOR_SUPPLY("pll_vdd",		"pil_qdsp6v4.2"),
+	REGULATOR_SUPPLY("pll_vdd",		"pil-q6v4-modem"),
 };
 VREG_CONSUMERS(L24) = {
 	REGULATOR_SUPPLY("8921_l24",		NULL),
@@ -136,15 +135,15 @@
 };
 VREG_CONSUMERS(L26) = {
 	REGULATOR_SUPPLY("8921_l26",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.0"),
+	REGULATOR_SUPPLY("core_vdd",		"pil-q6v4-lpass"),
 };
 VREG_CONSUMERS(L27) = {
 	REGULATOR_SUPPLY("8921_l27",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.2"),
+	REGULATOR_SUPPLY("sw_core_vdd",		"pil-q6v4-modem"),
 };
 VREG_CONSUMERS(L28) = {
 	REGULATOR_SUPPLY("8921_l28",		NULL),
-	REGULATOR_SUPPLY("core_vdd",		"pil_qdsp6v4.1"),
+	REGULATOR_SUPPLY("fw_core_vdd",		"pil-q6v4-modem"),
 };
 VREG_CONSUMERS(L29) = {
 	REGULATOR_SUPPLY("8921_l29",		NULL),
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 947b53f..2653d41 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -3282,10 +3282,8 @@
 
 	msm8960_pm8921_gpio_mpp_init();
 	/* Don't add modem devices on APQ targets */
-	if (socinfo_get_id() != 124) {
-		platform_device_register(&msm_8960_q6_mss_fw);
-		platform_device_register(&msm_8960_q6_mss_sw);
-	}
+	if (socinfo_get_id() != 124)
+		platform_device_register(&msm_8960_q6_mss);
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
 	msm8960_init_smsc_hub();
 	msm8960_init_hsic();
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 2cd2cd4..3a72be3 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5216,9 +5216,7 @@
 	CLK_LOOKUP("pwm_clk",		cxo_clk.c,	"0-0048"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"wcnss_wlan.0"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"pil_riva"),
-	CLK_LOOKUP("xo",		pxo_clk.c,	"pil_qdsp6v4.0"),
-	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.1"),
-	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.2"),
+	CLK_LOOKUP("xo",		pxo_clk.c,	"pil-q6v4-lpass"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_gss"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"msm_xo"),
@@ -5562,9 +5560,8 @@
 	CLK_LOOKUP("xo",		pxo_a_clk.c,	""),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"wcnss_wlan.0"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"pil_riva"),
-	CLK_LOOKUP("xo",		pxo_clk.c,	"pil_qdsp6v4.0"),
-	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.1"),
-	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.2"),
+	CLK_LOOKUP("xo",		pxo_clk.c,	"pil-q6v4-lpass"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"pil-q6v4-modem"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"msm_xo"),
 	CLK_LOOKUP("vref_buff",		cxo_clk.c,	"rpm-regulator"),
@@ -5915,9 +5912,8 @@
 	CLK_LOOKUP("xo",		cxo_clk.c,	"msm_xo"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"wcnss_wlan.0"),
 	CLK_LOOKUP("cxo",		cxo_clk.c,	"pil_riva"),
-	CLK_LOOKUP("xo",		pxo_clk.c,	"pil_qdsp6v4.0"),
-	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.1"),
-	CLK_LOOKUP("xo",		cxo_clk.c,	"pil_qdsp6v4.2"),
+	CLK_LOOKUP("xo",		pxo_clk.c,	"pil-q6v4-lpass"),
+	CLK_LOOKUP("xo",		cxo_clk.c,	"pil-q6v4-modem"),
 	CLK_LOOKUP("xo",		cxo_clk.c,	"BAM_RMNT"),
 	CLK_LOOKUP("vref_buff",		cxo_clk.c,	"rpm-regulator"),
 	CLK_LOOKUP("pll2",		pll2_clk.c,	NULL),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 2a641ba..0b7d6ab 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1334,13 +1334,10 @@
 	},
 };
 
-#define MSM_LPASS_QDSP6SS_PHYS	0x28800000
-#define SFAB_LPASS_Q6_ACLK_CTL	(MSM_CLK_CTL_BASE + 0x23A0)
-
 static struct resource msm_8960_q6_lpass_resources[] = {
 	{
-		.start  = MSM_LPASS_QDSP6SS_PHYS,
-		.end    = MSM_LPASS_QDSP6SS_PHYS + SZ_256 - 1,
+		.start  = 0x28800000,
+		.end    = 0x28800000 + SZ_256 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 };
@@ -1349,93 +1346,69 @@
 	.strap_tcm_base  = 0x01460000,
 	.strap_ahb_upper = 0x00290000,
 	.strap_ahb_lower = 0x00000280,
-	.aclk_reg = SFAB_LPASS_Q6_ACLK_CTL,
+	.aclk_reg = MSM_CLK_CTL_BASE + 0x23A0,
 	.name = "q6",
 	.pas_id = PAS_Q6,
 	.bus_port = MSM_BUS_MASTER_LPASS_PROC,
 };
 
 struct platform_device msm_8960_q6_lpass = {
-	.name = "pil_qdsp6v4",
-	.id = 0,
+	.name = "pil-q6v4-lpass",
+	.id = -1,
 	.num_resources  = ARRAY_SIZE(msm_8960_q6_lpass_resources),
 	.resource       = msm_8960_q6_lpass_resources,
 	.dev.platform_data = &msm_8960_q6_lpass_data,
 };
 
-#define MSM_MSS_ENABLE_PHYS	0x08B00000
-#define MSM_FW_QDSP6SS_PHYS	0x08800000
-#define MSS_Q6FW_JTAG_CLK_CTL	(MSM_CLK_CTL_BASE + 0x2C6C)
-#define SFAB_MSS_Q6_FW_ACLK_CTL (MSM_CLK_CTL_BASE + 0x2044)
-
-static struct resource msm_8960_q6_mss_fw_resources[] = {
+static struct resource msm_8960_q6_mss_resources[] = {
 	{
-		.start  = MSM_FW_QDSP6SS_PHYS,
-		.end    = MSM_FW_QDSP6SS_PHYS + SZ_256 - 1,
+		.start  = 0x08800000,
+		.end    = 0x08800000 + SZ_256 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 	{
-		.start  = MSM_MSS_ENABLE_PHYS,
-		.end    = MSM_MSS_ENABLE_PHYS + 4 - 1,
+		.start  = 0x08B00000,
+		.end    = 0x08B00000 + SZ_256 - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+	{
+		.start  = 0x08900000,
+		.end    = 0x08900000 + SZ_256 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
 };
 
-static struct pil_q6v4_pdata msm_8960_q6_mss_fw_data = {
-	.strap_tcm_base  = 0x00400000,
-	.strap_ahb_upper = 0x00090000,
-	.strap_ahb_lower = 0x00000080,
-	.aclk_reg = SFAB_MSS_Q6_FW_ACLK_CTL,
-	.jtag_clk_reg = MSS_Q6FW_JTAG_CLK_CTL,
-	.name = "modem_fw",
-	.depends = "q6",
-	.pas_id = PAS_MODEM_FW,
-	.bus_port = MSM_BUS_MASTER_MSS_FW_PROC,
-};
-
-struct platform_device msm_8960_q6_mss_fw = {
-	.name = "pil_qdsp6v4",
-	.id = 1,
-	.num_resources  = ARRAY_SIZE(msm_8960_q6_mss_fw_resources),
-	.resource       = msm_8960_q6_mss_fw_resources,
-	.dev.platform_data = &msm_8960_q6_mss_fw_data,
-};
-
-#define MSM_SW_QDSP6SS_PHYS	0x08900000
-#define SFAB_MSS_Q6_SW_ACLK_CTL	(MSM_CLK_CTL_BASE + 0x2040)
-#define MSS_Q6SW_JTAG_CLK_CTL	(MSM_CLK_CTL_BASE + 0x2C68)
-
-static struct resource msm_8960_q6_mss_sw_resources[] = {
+static struct pil_q6v4_pdata msm_8960_q6_mss_data[2] = {
 	{
-		.start  = MSM_SW_QDSP6SS_PHYS,
-		.end    = MSM_SW_QDSP6SS_PHYS + SZ_256 - 1,
-		.flags  = IORESOURCE_MEM,
+		.strap_tcm_base  = 0x00400000,
+		.strap_ahb_upper = 0x00090000,
+		.strap_ahb_lower = 0x00000080,
+		.aclk_reg = MSM_CLK_CTL_BASE + 0x2C6C,
+		.jtag_clk_reg = MSM_CLK_CTL_BASE + 0x2044,
+		.name = "modem_fw",
+		.depends = "q6",
+		.pas_id = PAS_MODEM_FW,
+		.bus_port = MSM_BUS_MASTER_MSS_FW_PROC,
 	},
 	{
-		.start  = MSM_MSS_ENABLE_PHYS,
-		.end    = MSM_MSS_ENABLE_PHYS + 4 - 1,
-		.flags  = IORESOURCE_MEM,
-	},
+		.strap_tcm_base  = 0x00420000,
+		.strap_ahb_upper = 0x00090000,
+		.strap_ahb_lower = 0x00000080,
+		.aclk_reg = MSM_CLK_CTL_BASE + 0x2040,
+		.jtag_clk_reg = MSM_CLK_CTL_BASE + 0x2C68,
+		.name = "modem",
+		.depends = "modem_fw",
+		.pas_id = PAS_MODEM_SW,
+		.bus_port = MSM_BUS_MASTER_MSS_SW_PROC,
+	}
 };
 
-static struct pil_q6v4_pdata msm_8960_q6_mss_sw_data = {
-	.strap_tcm_base  = 0x00420000,
-	.strap_ahb_upper = 0x00090000,
-	.strap_ahb_lower = 0x00000080,
-	.aclk_reg = SFAB_MSS_Q6_SW_ACLK_CTL,
-	.jtag_clk_reg = MSS_Q6SW_JTAG_CLK_CTL,
-	.name = "modem",
-	.depends = "modem_fw",
-	.pas_id = PAS_MODEM_SW,
-	.bus_port = MSM_BUS_MASTER_MSS_SW_PROC,
-};
-
-struct platform_device msm_8960_q6_mss_sw = {
-	.name = "pil_qdsp6v4",
-	.id = 2,
-	.num_resources  = ARRAY_SIZE(msm_8960_q6_mss_sw_resources),
-	.resource       = msm_8960_q6_mss_sw_resources,
-	.dev.platform_data = &msm_8960_q6_mss_sw_data,
+struct platform_device msm_8960_q6_mss = {
+	.name = "pil-q6v4-modem",
+	.id = -1,
+	.num_resources  = ARRAY_SIZE(msm_8960_q6_mss_resources),
+	.resource       = msm_8960_q6_mss_resources,
+	.dev.platform_data = msm_8960_q6_mss_data,
 };
 
 static struct resource msm_8960_riva_resources[] = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 0506217..cb89cd31 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -251,8 +251,7 @@
 extern struct platform_device msm_pil_dsps;
 extern struct platform_device msm_pil_vidc;
 extern struct platform_device msm_8960_q6_lpass;
-extern struct platform_device msm_8960_q6_mss_fw;
-extern struct platform_device msm_8960_q6_mss_sw;
+extern struct platform_device msm_8960_q6_mss;
 extern struct platform_device msm_8960_riva;
 extern struct platform_device msm_gss;
 
diff --git a/arch/arm/mach-msm/pil-q6v4-lpass.c b/arch/arm/mach-msm/pil-q6v4-lpass.c
new file mode 100644
index 0000000..222bd10
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v4-lpass.c
@@ -0,0 +1,143 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v4.h"
+#include "scm-pas.h"
+
+static int pil_q6v4_lpass_boot(struct pil_desc *pil)
+{
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
+	int err;
+
+	err = pil_q6v4_power_up(drv);
+	if (err)
+		return err;
+
+	return pil_q6v4_boot(pil);
+}
+
+static int pil_q6v4_lpass_shutdown(struct pil_desc *pil)
+{
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
+	int ret;
+
+	ret = pil_q6v4_shutdown(pil);
+	if (ret)
+		return ret;
+	pil_q6v4_power_down(drv);
+	return 0;
+}
+
+static struct pil_reset_ops pil_q6v4_lpass_ops = {
+	.init_image = pil_q6v4_init_image,
+	.auth_and_reset = pil_q6v4_lpass_boot,
+	.shutdown = pil_q6v4_lpass_shutdown,
+	.proxy_vote = pil_q6v4_make_proxy_votes,
+	.proxy_unvote = pil_q6v4_remove_proxy_votes,
+};
+
+static struct pil_reset_ops pil_q6v4_lpass_ops_trusted = {
+	.init_image = pil_q6v4_init_image_trusted,
+	.auth_and_reset = pil_q6v4_boot_trusted,
+	.shutdown = pil_q6v4_shutdown_trusted,
+	.proxy_vote = pil_q6v4_make_proxy_votes,
+	.proxy_unvote = pil_q6v4_remove_proxy_votes,
+};
+
+static int __devinit pil_q6v4_lpass_driver_probe(struct platform_device *pdev)
+{
+	const struct pil_q6v4_pdata *pdata = pdev->dev.platform_data;
+	struct q6v4_data *drv;
+	struct pil_desc *desc;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, drv);
+
+	drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!drv->base)
+		return -ENOMEM;
+
+	drv->vreg = devm_regulator_get(&pdev->dev, "core_vdd");
+	if (IS_ERR(drv->vreg))
+		return PTR_ERR(drv->vreg);
+
+	drv->xo = devm_clk_get(&pdev->dev, "xo");
+	if (IS_ERR(drv->xo))
+		return PTR_ERR(drv->xo);
+
+	desc = &drv->desc;
+	desc->name = pdata->name;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	desc->proxy_timeout = 10000;
+	pil_q6v4_init(drv, pdata);
+
+	if (pas_supported(pdata->pas_id) > 0) {
+		desc->ops = &pil_q6v4_lpass_ops_trusted;
+		dev_info(&pdev->dev, "using secure boot\n");
+	} else {
+		desc->ops = &pil_q6v4_lpass_ops;
+		dev_info(&pdev->dev, "using non-secure boot\n");
+	}
+
+	drv->pil = msm_pil_register(desc);
+	if (IS_ERR(drv->pil))
+		return PTR_ERR(drv->pil);
+	return 0;
+}
+
+static int __devexit pil_q6v4_lpass_driver_exit(struct platform_device *pdev)
+{
+	struct q6v4_data *drv = platform_get_drvdata(pdev);
+	msm_pil_unregister(drv->pil);
+	return 0;
+}
+
+static struct platform_driver pil_q6v4_lpass_driver = {
+	.probe = pil_q6v4_lpass_driver_probe,
+	.remove = __devexit_p(pil_q6v4_lpass_driver_exit),
+	.driver = {
+		.name = "pil-q6v4-lpass",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pil_q6v4_lpass_init(void)
+{
+	return platform_driver_register(&pil_q6v4_lpass_driver);
+}
+module_init(pil_q6v4_lpass_init);
+
+static void __exit pil_q6v4_lpass_exit(void)
+{
+	platform_driver_unregister(&pil_q6v4_lpass_driver);
+}
+module_exit(pil_q6v4_lpass_exit);
+
+MODULE_DESCRIPTION("Support for booting QDSP6v4 (Hexagon) processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v4-mss.c b/arch/arm/mach-msm/pil-q6v4-mss.c
new file mode 100644
index 0000000..65b56d3
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v4-mss.c
@@ -0,0 +1,264 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include <mach/msm_iomap.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v4.h"
+#include "scm-pas.h"
+
+#define MSS_S_HCLK_CTL		(MSM_CLK_CTL_BASE + 0x2C70)
+#define MSS_SLP_CLK_CTL		(MSM_CLK_CTL_BASE + 0x2C60)
+#define SFAB_MSS_M_ACLK_CTL	(MSM_CLK_CTL_BASE + 0x2340)
+#define SFAB_MSS_S_HCLK_CTL	(MSM_CLK_CTL_BASE + 0x2C00)
+#define MSS_RESET		(MSM_CLK_CTL_BASE + 0x2C64)
+
+struct q6v4_modem {
+	struct q6v4_data q6_fw;
+	struct q6v4_data q6_sw;
+	void __iomem *modem_base;
+};
+
+static DEFINE_MUTEX(pil_q6v4_modem_lock);
+static unsigned pil_q6v4_modem_count;
+
+/* Bring modem subsystem out of reset */
+static void pil_q6v4_init_modem(void __iomem *base, void __iomem *jtag_clk)
+{
+	mutex_lock(&pil_q6v4_modem_lock);
+	if (!pil_q6v4_modem_count) {
+		/* Enable MSS clocks */
+		writel_relaxed(0x10, SFAB_MSS_M_ACLK_CTL);
+		writel_relaxed(0x10, SFAB_MSS_S_HCLK_CTL);
+		writel_relaxed(0x10, MSS_S_HCLK_CTL);
+		writel_relaxed(0x10, MSS_SLP_CLK_CTL);
+		/* Wait for clocks to enable */
+		mb();
+		udelay(10);
+
+		/* De-assert MSS reset */
+		writel_relaxed(0x0, MSS_RESET);
+		mb();
+		udelay(10);
+		/* Enable MSS */
+		writel_relaxed(0x7, base);
+	}
+
+	/* Enable JTAG clocks */
+	/* TODO: Remove if/when Q6 software enables them? */
+	writel_relaxed(0x10, jtag_clk);
+
+	pil_q6v4_modem_count++;
+	mutex_unlock(&pil_q6v4_modem_lock);
+}
+
+/* Put modem subsystem back into reset */
+static void pil_q6v4_shutdown_modem(void)
+{
+	mutex_lock(&pil_q6v4_modem_lock);
+	if (pil_q6v4_modem_count)
+		pil_q6v4_modem_count--;
+	if (pil_q6v4_modem_count == 0)
+		writel_relaxed(0x1, MSS_RESET);
+	mutex_unlock(&pil_q6v4_modem_lock);
+}
+
+static int pil_q6v4_modem_boot(struct pil_desc *pil)
+{
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
+	struct q6v4_modem *mdm = dev_get_drvdata(pil->dev);
+	int err;
+
+	err = pil_q6v4_power_up(drv);
+	if (err)
+		return err;
+
+	pil_q6v4_init_modem(mdm->modem_base, drv->jtag_clk_reg);
+	return pil_q6v4_boot(pil);
+}
+
+static int pil_q6v4_modem_shutdown(struct pil_desc *pil)
+{
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
+	int ret;
+
+	ret = pil_q6v4_shutdown(pil);
+	if (ret)
+		return ret;
+	pil_q6v4_shutdown_modem();
+	pil_q6v4_power_down(drv);
+	return 0;
+}
+
+static struct pil_reset_ops pil_q6v4_modem_ops = {
+	.init_image = pil_q6v4_init_image,
+	.auth_and_reset = pil_q6v4_modem_boot,
+	.shutdown = pil_q6v4_modem_shutdown,
+	.proxy_vote = pil_q6v4_make_proxy_votes,
+	.proxy_unvote = pil_q6v4_remove_proxy_votes,
+};
+
+static struct pil_reset_ops pil_q6v4_modem_ops_trusted = {
+	.init_image = pil_q6v4_init_image_trusted,
+	.auth_and_reset = pil_q6v4_boot_trusted,
+	.shutdown = pil_q6v4_shutdown_trusted,
+	.proxy_vote = pil_q6v4_make_proxy_votes,
+	.proxy_unvote = pil_q6v4_remove_proxy_votes,
+};
+
+static int __devinit
+pil_q6v4_proc_init(struct q6v4_data *drv, struct platform_device *pdev, int i)
+{
+	static const char *name[2] = { "fw", "sw" };
+	const struct pil_q6v4_pdata *pdata_p = pdev->dev.platform_data;
+	const struct pil_q6v4_pdata *pdata = pdata_p + i;
+	char reg_name[12];
+	struct pil_desc *desc;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1 + i);
+	if (!res)
+		return -EINVAL;
+
+	drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!drv->base)
+		return -ENOMEM;
+
+	snprintf(reg_name, sizeof(reg_name), "%s_core_vdd", name[i]);
+	drv->vreg = devm_regulator_get(&pdev->dev, reg_name);
+	if (IS_ERR(drv->vreg))
+		return PTR_ERR(drv->vreg);
+
+	drv->xo = devm_clk_get(&pdev->dev, "xo");
+	if (IS_ERR(drv->xo))
+		return PTR_ERR(drv->xo);
+
+	desc = &drv->desc;
+	desc->name = pdata->name;
+	desc->depends_on = pdata->depends;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	desc->proxy_timeout = 10000;
+	pil_q6v4_init(drv, pdata);
+
+	if (pas_supported(pdata->pas_id) > 0) {
+		desc->ops = &pil_q6v4_modem_ops_trusted;
+		dev_info(&pdev->dev, "using secure boot for %s\n", name[i]);
+	} else {
+		desc->ops = &pil_q6v4_modem_ops;
+		dev_info(&pdev->dev, "using non-secure boot for %s\n", name[i]);
+	}
+	return 0;
+}
+
+static int __devinit pil_q6v4_modem_driver_probe(struct platform_device *pdev)
+{
+	struct q6v4_data *drv_fw, *drv_sw;
+	struct q6v4_modem *drv;
+	struct resource *res;
+	struct regulator *pll_supply;
+	int ret;
+
+	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+	if (!drv)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, drv);
+
+	drv_fw = &drv->q6_fw;
+	drv_sw = &drv->q6_sw;
+
+	ret = pil_q6v4_proc_init(drv_fw, pdev, 0);
+	if (ret)
+		return ret;
+
+	ret = pil_q6v4_proc_init(drv_sw, pdev, 1);
+	if (ret)
+		return ret;
+
+	pll_supply = devm_regulator_get(&pdev->dev, "pll_vdd");
+	drv_fw->pll_supply = drv_sw->pll_supply = pll_supply;
+	if (IS_ERR(pll_supply))
+		return PTR_ERR(pll_supply);
+
+	ret = regulator_set_voltage(pll_supply, 1800000, 1800000);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to set pll voltage\n");
+		return ret;
+	}
+
+	ret = regulator_set_optimum_mode(pll_supply, 100000);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to set pll optimum mode\n");
+		return ret;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	drv->modem_base = devm_ioremap(&pdev->dev, res->start,
+			resource_size(res));
+	if (!drv->modem_base)
+		return -ENOMEM;
+
+	drv_fw->pil = msm_pil_register(&drv_fw->desc);
+	if (IS_ERR(drv_fw->pil))
+		return PTR_ERR(drv_fw->pil);
+
+	drv_sw->pil = msm_pil_register(&drv_sw->desc);
+	if (IS_ERR(drv_sw->pil)) {
+		msm_pil_unregister(drv_fw->pil);
+		return PTR_ERR(drv_sw->pil);
+	}
+	return 0;
+}
+
+static int __devexit pil_q6v4_modem_driver_exit(struct platform_device *pdev)
+{
+	struct q6v4_modem *drv = platform_get_drvdata(pdev);
+	msm_pil_unregister(drv->q6_sw.pil);
+	msm_pil_unregister(drv->q6_fw.pil);
+	return 0;
+}
+
+static struct platform_driver pil_q6v4_modem_driver = {
+	.probe = pil_q6v4_modem_driver_probe,
+	.remove = __devexit_p(pil_q6v4_modem_driver_exit),
+	.driver = {
+		.name = "pil-q6v4-modem",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pil_q6v4_modem_init(void)
+{
+	return platform_driver_register(&pil_q6v4_modem_driver);
+}
+module_init(pil_q6v4_modem_init);
+
+static void __exit pil_q6v4_modem_exit(void)
+{
+	platform_driver_unregister(&pil_q6v4_modem_driver);
+}
+module_exit(pil_q6v4_modem_exit);
+
+MODULE_DESCRIPTION("Support for booting QDSP6v4 (Hexagon) processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v4.c b/arch/arm/mach-msm/pil-q6v4.c
index 32cce1d..47033fc 100644
--- a/arch/arm/mach-msm/pil-q6v4.c
+++ b/arch/arm/mach-msm/pil-q6v4.c
@@ -22,7 +22,6 @@
 #include <linux/clk.h>
 
 #include <mach/msm_bus.h>
-#include <mach/msm_iomap.h>
 
 #include "peripheral-loader.h"
 #include "pil-q6v4.h"
@@ -35,12 +34,6 @@
 #define QDSP6SS_GFMUX_CTL	0x30
 #define QDSP6SS_PWR_CTL		0x38
 
-#define MSS_S_HCLK_CTL		(MSM_CLK_CTL_BASE + 0x2C70)
-#define MSS_SLP_CLK_CTL		(MSM_CLK_CTL_BASE + 0x2C60)
-#define SFAB_MSS_M_ACLK_CTL	(MSM_CLK_CTL_BASE + 0x2340)
-#define SFAB_MSS_S_HCLK_CTL	(MSM_CLK_CTL_BASE + 0x2C00)
-#define MSS_RESET		(MSM_CLK_CTL_BASE + 0x2C64)
-
 #define Q6SS_SS_ARES		BIT(0)
 #define Q6SS_CORE_ARES		BIT(1)
 #define Q6SS_ISDB_ARES		BIT(2)
@@ -59,29 +52,19 @@
 #define Q6SS_CLK_ENA		BIT(1)
 #define Q6SS_SRC_SWITCH_CLK_OVR	BIT(8)
 
-struct q6v4_data {
-	void __iomem *base;
-	void __iomem *modem_base;
-	unsigned long start_addr;
-	struct regulator *vreg;
-	struct regulator *pll_supply;
-	bool vreg_enabled;
-	struct clk *xo;
-	struct pil_device *pil;
-};
-
-static int pil_q6v4_init_image(struct pil_desc *pil, const u8 *metadata,
+int pil_q6v4_init_image(struct pil_desc *pil, const u8 *metadata,
 		size_t size)
 {
 	const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
-	struct q6v4_data *drv = dev_get_drvdata(pil->dev);
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
 	drv->start_addr = ehdr->e_entry;
 	return 0;
 }
+EXPORT_SYMBOL(pil_q6v4_init_image);
 
-static int pil_q6v4_make_proxy_votes(struct pil_desc *pil)
+int pil_q6v4_make_proxy_votes(struct pil_desc *pil)
 {
-	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
+	const struct q6v4_data *drv = pil_to_q6v4_data(pil);
 	int ret;
 
 	ret = clk_prepare_enable(drv->xo);
@@ -102,19 +85,21 @@
 err:
 	return ret;
 }
+EXPORT_SYMBOL(pil_q6v4_make_proxy_votes);
 
-static void pil_q6v4_remove_proxy_votes(struct pil_desc *pil)
+void pil_q6v4_remove_proxy_votes(struct pil_desc *pil)
 {
-	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
+	const struct q6v4_data *drv = pil_to_q6v4_data(pil);
 	if (drv->pll_supply)
 		regulator_disable(drv->pll_supply);
 	clk_disable_unprepare(drv->xo);
 }
+EXPORT_SYMBOL(pil_q6v4_remove_proxy_votes);
 
-static int pil_q6v4_power_up(struct device *dev)
+int pil_q6v4_power_up(struct q6v4_data *drv)
 {
 	int err;
-	struct q6v4_data *drv = dev_get_drvdata(dev);
+	struct device *dev = drv->desc.dev;
 
 	err = regulator_set_voltage(drv->vreg, 743750, 743750);
 	if (err) {
@@ -141,68 +126,27 @@
 	drv->vreg_enabled = true;
 	return 0;
 }
+EXPORT_SYMBOL(pil_q6v4_power_up);
 
-static DEFINE_MUTEX(pil_q6v4_modem_lock);
-static unsigned pil_q6v4_modem_count;
-
-/* Bring modem subsystem out of reset */
-static void pil_q6v4_init_modem(void __iomem *base, void __iomem *jtag_clk)
+void pil_q6v4_power_down(struct q6v4_data *drv)
 {
-	mutex_lock(&pil_q6v4_modem_lock);
-	if (!pil_q6v4_modem_count) {
-		/* Enable MSS clocks */
-		writel_relaxed(0x10, SFAB_MSS_M_ACLK_CTL);
-		writel_relaxed(0x10, SFAB_MSS_S_HCLK_CTL);
-		writel_relaxed(0x10, MSS_S_HCLK_CTL);
-		writel_relaxed(0x10, MSS_SLP_CLK_CTL);
-		/* Wait for clocks to enable */
-		mb();
-		udelay(10);
-
-		/* De-assert MSS reset */
-		writel_relaxed(0x0, MSS_RESET);
-		mb();
-		udelay(10);
-		/* Enable MSS */
-		writel_relaxed(0x7, base);
+	if (drv->vreg_enabled) {
+		regulator_disable(drv->vreg);
+		drv->vreg_enabled = false;
 	}
-
-	/* Enable JTAG clocks */
-	/* TODO: Remove if/when Q6 software enables them? */
-	writel_relaxed(0x10, jtag_clk);
-
-	pil_q6v4_modem_count++;
-	mutex_unlock(&pil_q6v4_modem_lock);
 }
+EXPORT_SYMBOL(pil_q6v4_power_down);
 
-/* Put modem subsystem back into reset */
-static void pil_q6v4_shutdown_modem(void)
-{
-	mutex_lock(&pil_q6v4_modem_lock);
-	if (pil_q6v4_modem_count)
-		pil_q6v4_modem_count--;
-	if (pil_q6v4_modem_count == 0)
-		writel_relaxed(0x1, MSS_RESET);
-	mutex_unlock(&pil_q6v4_modem_lock);
-}
-
-static int pil_q6v4_reset(struct pil_desc *pil)
+int pil_q6v4_boot(struct pil_desc *pil)
 {
 	u32 reg, err;
-	const struct q6v4_data *drv = dev_get_drvdata(pil->dev);
-	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+	const struct q6v4_data *drv = pil_to_q6v4_data(pil);
 
-	err = pil_q6v4_power_up(pil->dev);
-	if (err)
-		return err;
 	/* Enable Q6 ACLK */
-	writel_relaxed(0x10, pdata->aclk_reg);
-
-	if (drv->modem_base)
-		pil_q6v4_init_modem(drv->modem_base, pdata->jtag_clk_reg);
+	writel_relaxed(0x10, drv->aclk_reg);
 
 	/* Unhalt bus port */
-	err = msm_bus_axi_portunhalt(pdata->bus_port);
+	err = msm_bus_axi_portunhalt(drv->bus_port);
 	if (err)
 		dev_err(pil->dev, "Failed to unhalt bus port\n");
 
@@ -216,8 +160,8 @@
 			drv->base + QDSP6SS_RST_EVB);
 
 	/* Program TCM and AHB address ranges */
-	writel_relaxed(pdata->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
-	writel_relaxed(pdata->strap_ahb_upper | pdata->strap_ahb_lower,
+	writel_relaxed(drv->strap_tcm_base, drv->base + QDSP6SS_STRAP_TCM);
+	writel_relaxed(drv->strap_ahb_upper | drv->strap_ahb_lower,
 		       drv->base + QDSP6SS_STRAP_AHB);
 
 	/* Turn off Q6 core clock */
@@ -257,15 +201,15 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(pil_q6v4_boot);
 
-static int pil_q6v4_shutdown(struct pil_desc *pil)
+int pil_q6v4_shutdown(struct pil_desc *pil)
 {
 	u32 reg;
-	struct q6v4_data *drv = dev_get_drvdata(pil->dev);
-	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
 
 	/* Make sure bus port is halted */
-	msm_bus_axi_porthalt(pdata->bus_port);
+	msm_bus_axi_porthalt(drv->bus_port);
 
 	/* Turn off Q6 core clock */
 	writel_relaxed(Q6SS_SRC_SWITCH_CLK_OVR,
@@ -279,188 +223,67 @@
 	/* Turn off Q6 memories */
 	writel_relaxed(Q6SS_CLAMP_IO, drv->base + QDSP6SS_PWR_CTL);
 
-	if (drv->modem_base)
-		pil_q6v4_shutdown_modem();
-
-	if (drv->vreg_enabled) {
-		regulator_disable(drv->vreg);
-		drv->vreg_enabled = false;
-	}
-
 	return 0;
 }
+EXPORT_SYMBOL(pil_q6v4_shutdown);
 
-static struct pil_reset_ops pil_q6v4_ops = {
-	.init_image = pil_q6v4_init_image,
-	.auth_and_reset = pil_q6v4_reset,
-	.shutdown = pil_q6v4_shutdown,
-	.proxy_vote = pil_q6v4_make_proxy_votes,
-	.proxy_unvote = pil_q6v4_remove_proxy_votes,
-};
-
-static int pil_q6v4_init_image_trusted(struct pil_desc *pil,
+int pil_q6v4_init_image_trusted(struct pil_desc *pil,
 		const u8 *metadata, size_t size)
 {
-	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
-	return pas_init_image(pdata->pas_id, metadata, size);
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
+	return pas_init_image(drv->pas_id, metadata, size);
 }
+EXPORT_SYMBOL(pil_q6v4_init_image_trusted);
 
-static int pil_q6v4_reset_trusted(struct pil_desc *pil)
+int pil_q6v4_boot_trusted(struct pil_desc *pil)
 {
-	const struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
 	int err;
 
-	err = pil_q6v4_power_up(pil->dev);
+	err = pil_q6v4_power_up(drv);
 	if (err)
 		return err;
 
 	/* Unhalt bus port */
-	err = msm_bus_axi_portunhalt(pdata->bus_port);
+	err = msm_bus_axi_portunhalt(drv->bus_port);
 	if (err)
 		dev_err(pil->dev, "Failed to unhalt bus port\n");
-	return pas_auth_and_reset(pdata->pas_id);
+	return pas_auth_and_reset(drv->pas_id);
 }
+EXPORT_SYMBOL(pil_q6v4_boot_trusted);
 
-static int pil_q6v4_shutdown_trusted(struct pil_desc *pil)
+int pil_q6v4_shutdown_trusted(struct pil_desc *pil)
 {
 	int ret;
-	struct q6v4_data *drv = dev_get_drvdata(pil->dev);
-	struct pil_q6v4_pdata *pdata = pil->dev->platform_data;
+	struct q6v4_data *drv = pil_to_q6v4_data(pil);
 
 	/* Make sure bus port is halted */
-	msm_bus_axi_porthalt(pdata->bus_port);
+	msm_bus_axi_porthalt(drv->bus_port);
 
-	ret = pas_shutdown(pdata->pas_id);
+	ret = pas_shutdown(drv->pas_id);
 	if (ret)
 		return ret;
 
-	if (drv->vreg_enabled) {
-		regulator_disable(drv->vreg);
-		drv->vreg_enabled = false;
-	}
+	pil_q6v4_power_down(drv);
 
 	return ret;
 }
+EXPORT_SYMBOL(pil_q6v4_shutdown_trusted);
 
-static struct pil_reset_ops pil_q6v4_ops_trusted = {
-	.init_image = pil_q6v4_init_image_trusted,
-	.auth_and_reset = pil_q6v4_reset_trusted,
-	.shutdown = pil_q6v4_shutdown_trusted,
-	.proxy_vote = pil_q6v4_make_proxy_votes,
-	.proxy_unvote = pil_q6v4_remove_proxy_votes,
-};
-
-static int __devinit pil_q6v4_driver_probe(struct platform_device *pdev)
+void __devinit
+pil_q6v4_init(struct q6v4_data *drv, const struct pil_q6v4_pdata *pdata)
 {
-	const struct pil_q6v4_pdata *pdata = pdev->dev.platform_data;
-	struct q6v4_data *drv;
-	struct resource *res;
-	struct pil_desc *desc;
-	int ret;
+	drv->strap_tcm_base	= pdata->strap_tcm_base;
+	drv->strap_ahb_upper	= pdata->strap_ahb_upper;
+	drv->strap_ahb_lower	= pdata->strap_ahb_lower;
+	drv->aclk_reg		= pdata->aclk_reg;
+	drv->jtag_clk_reg	= pdata->jtag_clk_reg;
+	drv->pas_id		= pdata->pas_id;
+	drv->bus_port		= pdata->bus_port;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -EINVAL;
-
-	drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
-	if (!drv)
-		return -ENOMEM;
-	platform_set_drvdata(pdev, drv);
-
-	drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
-	if (!drv->base)
-		return -ENOMEM;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (res) {
-		drv->modem_base = devm_ioremap(&pdev->dev, res->start,
-				resource_size(res));
-		if (!drv->modem_base)
-			return -ENOMEM;
-	}
-
-	desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
-	if (!desc)
-		return -ENOMEM;
-
-	drv->pll_supply = devm_regulator_get(&pdev->dev, "pll_vdd");
-	if (IS_ERR(drv->pll_supply)) {
-		drv->pll_supply = NULL;
-	} else {
-		ret = regulator_set_voltage(drv->pll_supply, 1800000, 1800000);
-		if (ret) {
-			dev_err(&pdev->dev, "failed to set pll voltage\n");
-			return ret;
-		}
-
-		ret = regulator_set_optimum_mode(drv->pll_supply, 100000);
-		if (ret < 0) {
-			dev_err(&pdev->dev, "failed to set pll optimum mode\n");
-			return ret;
-		}
-	}
-
-	desc->name = pdata->name;
-	desc->depends_on = pdata->depends;
-	desc->dev = &pdev->dev;
-	desc->owner = THIS_MODULE;
-	desc->proxy_timeout = 10000;
-
-	if (pas_supported(pdata->pas_id) > 0) {
-		desc->ops = &pil_q6v4_ops_trusted;
-		dev_info(&pdev->dev, "using secure boot\n");
-	} else {
-		desc->ops = &pil_q6v4_ops;
-		dev_info(&pdev->dev, "using non-secure boot\n");
-	}
-
-	drv->vreg = devm_regulator_get(&pdev->dev, "core_vdd");
-	if (IS_ERR(drv->vreg))
-		return PTR_ERR(drv->vreg);
-
-	ret = regulator_set_optimum_mode(drv->vreg, 100000);
-	if (ret < 0) {
-		dev_err(&pdev->dev, "Failed to set regulator's mode.\n");
-		return ret;
-	}
-
-	drv->xo = devm_clk_get(&pdev->dev, "xo");
-	if (IS_ERR(drv->xo))
-		return PTR_ERR(drv->xo);
-
-	drv->pil = msm_pil_register(desc);
-	if (IS_ERR(drv->pil))
-		return PTR_ERR(drv->pil);
-	return 0;
+	regulator_set_optimum_mode(drv->vreg, 100000);
 }
-
-static int __devexit pil_q6v4_driver_exit(struct platform_device *pdev)
-{
-	struct q6v4_data *drv = platform_get_drvdata(pdev);
-	msm_pil_unregister(drv->pil);
-	return 0;
-}
-
-static struct platform_driver pil_q6v4_driver = {
-	.probe = pil_q6v4_driver_probe,
-	.remove = __devexit_p(pil_q6v4_driver_exit),
-	.driver = {
-		.name = "pil_qdsp6v4",
-		.owner = THIS_MODULE,
-	},
-};
-
-static int __init pil_q6v4_init(void)
-{
-	return platform_driver_register(&pil_q6v4_driver);
-}
-module_init(pil_q6v4_init);
-
-static void __exit pil_q6v4_exit(void)
-{
-	platform_driver_unregister(&pil_q6v4_driver);
-}
-module_exit(pil_q6v4_exit);
+EXPORT_SYMBOL(pil_q6v4_init);
 
 MODULE_DESCRIPTION("Support for booting QDSP6v4 (Hexagon) processors");
 MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v4.h b/arch/arm/mach-msm/pil-q6v4.h
index b0b97d0..d280d84 100644
--- a/arch/arm/mach-msm/pil-q6v4.h
+++ b/arch/arm/mach-msm/pil-q6v4.h
@@ -12,6 +12,8 @@
 #ifndef __MSM_PIL_Q6V4_H
 #define __MSM_PIL_Q6V4_H
 
+#include "peripheral-loader.h"
+
 struct pil_q6v4_pdata {
 	const unsigned long strap_tcm_base;
 	const unsigned long strap_ahb_upper;
@@ -23,4 +25,50 @@
 	const unsigned pas_id;
 	int bus_port;
 };
+
+struct clk;
+struct pil_device;
+struct regulator;
+
+/**
+ * struct q6v4_data - Q6 processor
+ */
+struct q6v4_data {
+	void __iomem *base;
+	unsigned long start_addr;
+	unsigned long strap_tcm_base;
+	unsigned long strap_ahb_upper;
+	unsigned long strap_ahb_lower;
+	void __iomem *aclk_reg;
+	void __iomem *jtag_clk_reg;
+	unsigned pas_id;
+	int bus_port;
+
+	struct regulator *vreg;
+	struct regulator *pll_supply;
+	bool vreg_enabled;
+	struct clk *xo;
+
+	struct pil_device *pil;
+	struct pil_desc desc;
+};
+
+#define pil_to_q6v4_data(p) container_of(p, struct q6v4_data, desc)
+
+extern int pil_q6v4_init_image(struct pil_desc *pil, const u8 *metadata,
+		size_t size);
+extern int pil_q6v4_make_proxy_votes(struct pil_desc *pil);
+extern void pil_q6v4_remove_proxy_votes(struct pil_desc *pil);
+extern int pil_q6v4_power_up(struct q6v4_data *drv);
+extern void pil_q6v4_power_down(struct q6v4_data *drv);
+extern int pil_q6v4_boot(struct pil_desc *pil);
+extern int pil_q6v4_shutdown(struct pil_desc *pil);
+
+extern int pil_q6v4_init_image_trusted(struct pil_desc *pil,
+		const u8 *metadata, size_t size);
+extern int pil_q6v4_boot_trusted(struct pil_desc *pil);
+extern int pil_q6v4_shutdown_trusted(struct pil_desc *pil);
+extern void __devinit
+pil_q6v4_init(struct q6v4_data *drv, const struct pil_q6v4_pdata *p);
+
 #endif