blob: f3f5388ac260fc382deb382c77ba40583233596c [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/elf.h>
17#include <linux/delay.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/clk.h>
21#include <linux/timer.h>
22#include <linux/jiffies.h>
Stephen Boyd3f4da322011-08-30 01:03:23 -070023#include <linux/platform_device.h>
24
25#include <asm/mach-types.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070026
27#include <mach/scm.h>
28#include <mach/msm_iomap.h>
29#include <mach/msm_xo.h>
30
31#include "peripheral-loader.h"
Stephen Boyde44ec392011-08-29 12:03:24 -070032#include "scm-pas.h"
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070033
34#define PROXY_VOTE_TIMEOUT 10000
35
36#define MSM_MMS_REGS_BASE 0x10200000
37#define MSM_LPASS_QDSP6SS_BASE 0x28800000
38
39#define MARM_RESET (MSM_CLK_CTL_BASE + 0x2BD4)
40#define MARM_BOOT_CONTROL (msm_mms_regs_base + 0x0010)
41#define MAHB0_SFAB_PORT_RESET (MSM_CLK_CTL_BASE + 0x2304)
42#define MARM_CLK_BRANCH_ENA_VOTE (MSM_CLK_CTL_BASE + 0x3000)
43#define MARM_CLK_SRC0_NS (MSM_CLK_CTL_BASE + 0x2BC0)
44#define MARM_CLK_SRC1_NS (MSM_CLK_CTL_BASE + 0x2BC4)
45#define MARM_CLK_SRC_CTL (MSM_CLK_CTL_BASE + 0x2BC8)
46#define MARM_CLK_CTL (MSM_CLK_CTL_BASE + 0x2BCC)
47#define SFAB_MSS_S_HCLK_CTL (MSM_CLK_CTL_BASE + 0x2C00)
48#define MSS_MODEM_CXO_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C44)
49#define MSS_SLP_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C60)
50#define MSS_MARM_SYS_REF_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C64)
51#define MAHB0_CLK_CTL (MSM_CLK_CTL_BASE + 0x2300)
52#define MAHB1_CLK_CTL (MSM_CLK_CTL_BASE + 0x2BE4)
53#define MAHB2_CLK_CTL (MSM_CLK_CTL_BASE + 0x2C20)
54#define MAHB1_NS (MSM_CLK_CTL_BASE + 0x2BE0)
55#define MARM_CLK_FS (MSM_CLK_CTL_BASE + 0x2BD0)
56#define MAHB2_CLK_FS (MSM_CLK_CTL_BASE + 0x2C24)
57#define PLL_ENA_MARM (MSM_CLK_CTL_BASE + 0x3500)
58#define PLL8_STATUS (MSM_CLK_CTL_BASE + 0x3158)
59#define CLK_HALT_MSS_SMPSS_MISC_STATE (MSM_CLK_CTL_BASE + 0x2FDC)
60
61#define LCC_Q6_FUNC (MSM_LPASS_CLK_CTL_BASE + 0x001C)
62#define QDSP6SS_RST_EVB (msm_lpass_qdsp6ss_base + 0x0000)
63#define QDSP6SS_STRAP_TCM (msm_lpass_qdsp6ss_base + 0x001C)
64#define QDSP6SS_STRAP_AHB (msm_lpass_qdsp6ss_base + 0x0020)
65
66#define PPSS_RESET (MSM_CLK_CTL_BASE + 0x2594)
67#define PPSS_PROC_CLK_CTL (MSM_CLK_CTL_BASE + 0x2588)
68#define CLK_HALT_DFAB_STATE (MSM_CLK_CTL_BASE + 0x2FC8)
69
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070070static int modem_start, q6_start, dsps_start;
71static void __iomem *msm_mms_regs_base;
72static void __iomem *msm_lpass_qdsp6ss_base;
73
Stephen Boyd3f4da322011-08-30 01:03:23 -070074static int init_image_modem_trusted(struct pil_desc *pil, const u8 *metadata,
Stephen Boyd5bd999a2011-08-02 18:50:57 -070075 size_t size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070076{
Stephen Boyde44ec392011-08-29 12:03:24 -070077 return pas_init_image(PAS_MODEM, metadata, size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070078}
79
Stephen Boyd3f4da322011-08-30 01:03:23 -070080static int init_image_modem_untrusted(struct pil_desc *pil,
Stephen Boyd5bd999a2011-08-02 18:50:57 -070081 const u8 *metadata, size_t size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070082{
83 struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
84 modem_start = ehdr->e_entry;
85 return 0;
86}
87
Stephen Boyd3f4da322011-08-30 01:03:23 -070088static int init_image_q6_trusted(struct pil_desc *pil,
Stephen Boyd5bd999a2011-08-02 18:50:57 -070089 const u8 *metadata, size_t size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070090{
Stephen Boyde44ec392011-08-29 12:03:24 -070091 return pas_init_image(PAS_Q6, metadata, size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070092}
93
Stephen Boyd3f4da322011-08-30 01:03:23 -070094static int init_image_q6_untrusted(struct pil_desc *pil, const u8 *metadata,
Stephen Boyd5bd999a2011-08-02 18:50:57 -070095 size_t size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070096{
97 struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
98 q6_start = ehdr->e_entry;
99 return 0;
100}
101
Stephen Boyd3f4da322011-08-30 01:03:23 -0700102static int init_image_dsps_trusted(struct pil_desc *pil, const u8 *metadata,
Stephen Boyd5bd999a2011-08-02 18:50:57 -0700103 size_t size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700104{
Stephen Boyde44ec392011-08-29 12:03:24 -0700105 return pas_init_image(PAS_DSPS, metadata, size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700106}
107
Stephen Boyd3f4da322011-08-30 01:03:23 -0700108static int init_image_dsps_untrusted(struct pil_desc *pil, const u8 *metadata,
Stephen Boyd5bd999a2011-08-02 18:50:57 -0700109 size_t size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700110{
111 struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
112 dsps_start = ehdr->e_entry;
113 /* Bring memory and bus interface out of reset */
114 __raw_writel(0x2, PPSS_RESET);
115 mb();
116 return 0;
117}
118
Stephen Boyd3f4da322011-08-30 01:03:23 -0700119static int verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700120{
121 return 0;
122}
123
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124static struct msm_xo_voter *pxo;
125static void remove_modem_proxy_votes(unsigned long data)
126{
127 msm_xo_mode_vote(pxo, MSM_XO_MODE_OFF);
128}
129static DEFINE_TIMER(modem_timer, remove_modem_proxy_votes, 0, 0);
130
131static void make_modem_proxy_votes(void)
132{
133 /* Make proxy votes for modem and set up timer to disable it. */
134 msm_xo_mode_vote(pxo, MSM_XO_MODE_ON);
135 mod_timer(&modem_timer, jiffies + msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
136}
137
138static void remove_modem_proxy_votes_now(void)
139{
140 /*
141 * If the modem proxy vote hasn't been removed yet, them remove the
142 * votes immediately.
143 */
144 if (del_timer(&modem_timer))
145 remove_modem_proxy_votes(0);
146}
147
Stephen Boyd3f4da322011-08-30 01:03:23 -0700148static int reset_modem_untrusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700149{
150 u32 reg;
151
152 make_modem_proxy_votes();
153
154 /* Put modem AHB0,1,2 clocks into reset */
155 __raw_writel(BIT(0) | BIT(1), MAHB0_SFAB_PORT_RESET);
156 __raw_writel(BIT(7), MAHB1_CLK_CTL);
157 __raw_writel(BIT(7), MAHB2_CLK_CTL);
158
159 /* Vote for pll8 on behalf of the modem */
160 reg = __raw_readl(PLL_ENA_MARM);
161 reg |= BIT(8);
162 __raw_writel(reg, PLL_ENA_MARM);
163
164 /* Wait for PLL8 to enable */
165 while (!(__raw_readl(PLL8_STATUS) & BIT(16)))
166 cpu_relax();
167
168 /* Set MAHB1 divider to Div-5 to run MAHB1,2 and sfab at 79.8 Mhz*/
169 __raw_writel(0x4, MAHB1_NS);
170
171 /* Vote for modem AHB1 and 2 clocks to be on on behalf of the modem */
172 reg = __raw_readl(MARM_CLK_BRANCH_ENA_VOTE);
173 reg |= BIT(0) | BIT(1);
174 __raw_writel(reg, MARM_CLK_BRANCH_ENA_VOTE);
175
176 /* Source marm_clk off of PLL8 */
177 reg = __raw_readl(MARM_CLK_SRC_CTL);
178 if ((reg & 0x1) == 0) {
179 __raw_writel(0x3, MARM_CLK_SRC1_NS);
180 reg |= 0x1;
181 } else {
182 __raw_writel(0x3, MARM_CLK_SRC0_NS);
183 reg &= ~0x1;
184 }
185 __raw_writel(reg | 0x2, MARM_CLK_SRC_CTL);
186
187 /*
188 * Force core on and periph on signals to remain active during halt
189 * for marm_clk and mahb2_clk
190 */
191 __raw_writel(0x6F, MARM_CLK_FS);
192 __raw_writel(0x6F, MAHB2_CLK_FS);
193
194 /*
195 * Enable all of the marm_clk branches, cxo sourced marm branches,
196 * and sleep clock branches
197 */
198 __raw_writel(0x10, MARM_CLK_CTL);
199 __raw_writel(0x10, MAHB0_CLK_CTL);
200 __raw_writel(0x10, SFAB_MSS_S_HCLK_CTL);
201 __raw_writel(0x10, MSS_MODEM_CXO_CLK_CTL);
202 __raw_writel(0x10, MSS_SLP_CLK_CTL);
203 __raw_writel(0x10, MSS_MARM_SYS_REF_CLK_CTL);
204
205 /* Wait for above clocks to be turned on */
206 while (__raw_readl(CLK_HALT_MSS_SMPSS_MISC_STATE) & (BIT(7) | BIT(8) |
207 BIT(9) | BIT(10) | BIT(4) | BIT(6)))
208 cpu_relax();
209
210 /* Take MAHB0,1,2 clocks out of reset */
211 __raw_writel(0x0, MAHB2_CLK_CTL);
212 __raw_writel(0x0, MAHB1_CLK_CTL);
213 __raw_writel(0x0, MAHB0_SFAB_PORT_RESET);
214
215 /* Setup exception vector table base address */
216 __raw_writel(modem_start | 0x1, MARM_BOOT_CONTROL);
217
218 /* Wait for vector table to be setup */
219 mb();
220
221 /* Bring modem out of reset */
222 __raw_writel(0x0, MARM_RESET);
223
224 return 0;
225}
226
Stephen Boyd3f4da322011-08-30 01:03:23 -0700227static int reset_modem_trusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700228{
229 int ret;
230
231 make_modem_proxy_votes();
232
Stephen Boyde44ec392011-08-29 12:03:24 -0700233 ret = pas_auth_and_reset(PAS_MODEM);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700234 if (ret)
235 remove_modem_proxy_votes_now();
236
237 return ret;
238}
239
Stephen Boyd3f4da322011-08-30 01:03:23 -0700240static int shutdown_modem_untrusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700241{
242 u32 reg;
243
244 /* Put modem into reset */
245 __raw_writel(0x1, MARM_RESET);
246 mb();
247
248 /* Put modem AHB0,1,2 clocks into reset */
249 __raw_writel(BIT(0) | BIT(1), MAHB0_SFAB_PORT_RESET);
250 __raw_writel(BIT(7), MAHB1_CLK_CTL);
251 __raw_writel(BIT(7), MAHB2_CLK_CTL);
252 mb();
253
254 /*
255 * Disable all of the marm_clk branches, cxo sourced marm branches,
256 * and sleep clock branches
257 */
258 __raw_writel(0x0, MARM_CLK_CTL);
259 __raw_writel(0x0, MAHB0_CLK_CTL);
260 __raw_writel(0x0, SFAB_MSS_S_HCLK_CTL);
261 __raw_writel(0x0, MSS_MODEM_CXO_CLK_CTL);
262 __raw_writel(0x0, MSS_SLP_CLK_CTL);
263 __raw_writel(0x0, MSS_MARM_SYS_REF_CLK_CTL);
264
265 /* Disable marm_clk */
266 reg = __raw_readl(MARM_CLK_SRC_CTL);
267 reg &= ~0x2;
268 __raw_writel(reg, MARM_CLK_SRC_CTL);
269
270 /* Clear modem's votes for ahb clocks */
271 __raw_writel(0x0, MARM_CLK_BRANCH_ENA_VOTE);
272
273 /* Clear modem's votes for PLLs */
274 __raw_writel(0x0, PLL_ENA_MARM);
275
276 remove_modem_proxy_votes_now();
277
278 return 0;
279}
280
Stephen Boyd3f4da322011-08-30 01:03:23 -0700281static int shutdown_modem_trusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700282{
283 int ret;
284
Stephen Boyde44ec392011-08-29 12:03:24 -0700285 ret = pas_shutdown(PAS_MODEM);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700286 if (ret)
287 return ret;
288
289 remove_modem_proxy_votes_now();
290
291 return 0;
292}
293
294#define LV_EN BIT(27)
295#define STOP_CORE BIT(26)
296#define CLAMP_IO BIT(25)
297#define Q6SS_PRIV_ARES BIT(24)
298#define Q6SS_SS_ARES BIT(23)
299#define Q6SS_ISDB_ARES BIT(22)
300#define Q6SS_ETM_ARES BIT(21)
301#define Q6_JTAG_CRC_EN BIT(20)
302#define Q6_JTAG_INV_EN BIT(19)
303#define Q6_JTAG_CXC_EN BIT(18)
304#define Q6_PXO_CRC_EN BIT(17)
305#define Q6_PXO_INV_EN BIT(16)
306#define Q6_PXO_CXC_EN BIT(15)
307#define Q6_PXO_SLEEP_EN BIT(14)
308#define Q6_SLP_CRC_EN BIT(13)
309#define Q6_SLP_INV_EN BIT(12)
310#define Q6_SLP_CXC_EN BIT(11)
311#define CORE_ARES BIT(10)
312#define CORE_L1_MEM_CORE_EN BIT(9)
313#define CORE_TCM_MEM_CORE_EN BIT(8)
314#define CORE_TCM_MEM_PERPH_EN BIT(7)
315#define CORE_GFM4_CLK_EN BIT(2)
316#define CORE_GFM4_RES BIT(1)
317#define RAMP_PLL_SRC_SEL BIT(0)
318
319#define Q6_STRAP_AHB_UPPER (0x290 << 12)
320#define Q6_STRAP_AHB_LOWER 0x280
321#define Q6_STRAP_TCM_BASE (0x28C << 15)
322#define Q6_STRAP_TCM_CONFIG 0x28B
323
324static struct clk *pll4;
325
326static void remove_q6_proxy_votes(unsigned long data)
327{
328 clk_disable(pll4);
329}
330static DEFINE_TIMER(q6_timer, remove_q6_proxy_votes, 0, 0);
331
332static void make_q6_proxy_votes(void)
333{
334 /* Make proxy votes for Q6 and set up timer to disable it. */
335 clk_enable(pll4);
336 mod_timer(&q6_timer, jiffies + msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
337}
338
339static void remove_q6_proxy_votes_now(void)
340{
341 /*
342 * If the Q6 proxy vote hasn't been removed yet, them remove the
343 * votes immediately.
344 */
345 if (del_timer(&q6_timer))
346 remove_q6_proxy_votes(0);
347}
348
Stephen Boyd3f4da322011-08-30 01:03:23 -0700349static int reset_q6_untrusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700350{
351 u32 reg;
352
353 make_q6_proxy_votes();
354
355 /* Put Q6 into reset */
356 reg = __raw_readl(LCC_Q6_FUNC);
357 reg |= Q6SS_SS_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES | STOP_CORE |
358 CORE_ARES;
359 reg &= ~CORE_GFM4_CLK_EN;
360 __raw_writel(reg, LCC_Q6_FUNC);
361
362 /* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
363 usleep_range(20, 30);
364
365 /* Turn on Q6 memory */
366 reg |= CORE_GFM4_CLK_EN | CORE_L1_MEM_CORE_EN | CORE_TCM_MEM_CORE_EN |
367 CORE_TCM_MEM_PERPH_EN;
368 __raw_writel(reg, LCC_Q6_FUNC);
369
370 /* Turn on Q6 core clocks and take core out of reset */
371 reg &= ~(CLAMP_IO | Q6SS_SS_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES |
372 CORE_ARES);
373 __raw_writel(reg, LCC_Q6_FUNC);
374
375 /* Wait for clocks to be enabled */
376 mb();
377 /* Program boot address */
378 __raw_writel((q6_start >> 12) & 0xFFFFF, QDSP6SS_RST_EVB);
379
380 __raw_writel(Q6_STRAP_TCM_CONFIG | Q6_STRAP_TCM_BASE,
381 QDSP6SS_STRAP_TCM);
382 __raw_writel(Q6_STRAP_AHB_UPPER | Q6_STRAP_AHB_LOWER,
383 QDSP6SS_STRAP_AHB);
384
385 /* Wait for addresses to be programmed before starting Q6 */
386 mb();
387
388 /* Start Q6 instruction execution */
389 reg &= ~STOP_CORE;
390 __raw_writel(reg, LCC_Q6_FUNC);
391
392 return 0;
393}
394
Stephen Boyd3f4da322011-08-30 01:03:23 -0700395static int reset_q6_trusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700396{
397 make_q6_proxy_votes();
398
Stephen Boyde44ec392011-08-29 12:03:24 -0700399 return pas_auth_and_reset(PAS_Q6);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700400}
401
Stephen Boyd3f4da322011-08-30 01:03:23 -0700402static int shutdown_q6_untrusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700403{
404 u32 reg;
405
406 /* Put Q6 into reset */
407 reg = __raw_readl(LCC_Q6_FUNC);
408 reg |= Q6SS_SS_ARES | Q6SS_ISDB_ARES | Q6SS_ETM_ARES | STOP_CORE |
409 CORE_ARES;
410 reg &= ~CORE_GFM4_CLK_EN;
411 __raw_writel(reg, LCC_Q6_FUNC);
412
413 /* Wait 8 AHB cycles for Q6 to be fully reset (AHB = 1.5Mhz) */
414 usleep_range(20, 30);
415
416 /* Turn off Q6 memory */
417 reg &= ~(CORE_L1_MEM_CORE_EN | CORE_TCM_MEM_CORE_EN |
418 CORE_TCM_MEM_PERPH_EN);
419 __raw_writel(reg, LCC_Q6_FUNC);
420
421 reg |= CLAMP_IO;
422 __raw_writel(reg, LCC_Q6_FUNC);
423
424 remove_q6_proxy_votes_now();
425
426 return 0;
427}
428
Stephen Boyd3f4da322011-08-30 01:03:23 -0700429static int shutdown_q6_trusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700430{
431 int ret;
432
Stephen Boyde44ec392011-08-29 12:03:24 -0700433 ret = pas_shutdown(PAS_Q6);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700434 if (ret)
435 return ret;
436
437 remove_q6_proxy_votes_now();
438
439 return 0;
440}
441
Stephen Boyd3f4da322011-08-30 01:03:23 -0700442static int reset_dsps_untrusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700443{
444 __raw_writel(0x10, PPSS_PROC_CLK_CTL);
445 while (__raw_readl(CLK_HALT_DFAB_STATE) & BIT(18))
446 cpu_relax();
447
448 /* Bring DSPS out of reset */
449 __raw_writel(0x0, PPSS_RESET);
450 return 0;
451}
452
Stephen Boyd3f4da322011-08-30 01:03:23 -0700453static int reset_dsps_trusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700454{
Stephen Boyde44ec392011-08-29 12:03:24 -0700455 return pas_auth_and_reset(PAS_DSPS);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700456}
457
Stephen Boyd3f4da322011-08-30 01:03:23 -0700458static int shutdown_dsps_trusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700459{
Stephen Boyde44ec392011-08-29 12:03:24 -0700460 return pas_shutdown(PAS_DSPS);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700461}
462
Stephen Boyd3f4da322011-08-30 01:03:23 -0700463static int shutdown_dsps_untrusted(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700464{
465 __raw_writel(0x2, PPSS_RESET);
466 __raw_writel(0x0, PPSS_PROC_CLK_CTL);
467 return 0;
468}
469
Stephen Boyd3f4da322011-08-30 01:03:23 -0700470static int init_image_playready(struct pil_desc *pil, const u8 *metadata,
Stephen Boyd5bd999a2011-08-02 18:50:57 -0700471 size_t size)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700472{
Stephen Boyde44ec392011-08-29 12:03:24 -0700473 return pas_init_image(PAS_PLAYREADY, metadata, size);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700474}
475
Stephen Boyd3f4da322011-08-30 01:03:23 -0700476static int reset_playready(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700477{
Stephen Boyde44ec392011-08-29 12:03:24 -0700478 return pas_auth_and_reset(PAS_PLAYREADY);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700479}
480
Stephen Boyd3f4da322011-08-30 01:03:23 -0700481static int shutdown_playready(struct pil_desc *pil)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700482{
Stephen Boyde44ec392011-08-29 12:03:24 -0700483 return pas_shutdown(PAS_PLAYREADY);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700484}
485
486struct pil_reset_ops pil_modem_ops = {
487 .init_image = init_image_modem_untrusted,
488 .verify_blob = verify_blob,
489 .auth_and_reset = reset_modem_untrusted,
490 .shutdown = shutdown_modem_untrusted,
491};
492
493struct pil_reset_ops pil_q6_ops = {
494 .init_image = init_image_q6_untrusted,
495 .verify_blob = verify_blob,
496 .auth_and_reset = reset_q6_untrusted,
497 .shutdown = shutdown_q6_untrusted,
498};
499
500struct pil_reset_ops pil_dsps_ops = {
501 .init_image = init_image_dsps_untrusted,
502 .verify_blob = verify_blob,
503 .auth_and_reset = reset_dsps_untrusted,
504 .shutdown = shutdown_dsps_untrusted,
505};
506
507struct pil_reset_ops pil_playready_ops = {
508 .init_image = init_image_playready,
509 .verify_blob = verify_blob,
510 .auth_and_reset = reset_playready,
511 .shutdown = shutdown_playready,
512};
513
Stephen Boyd3f4da322011-08-30 01:03:23 -0700514static struct platform_device pil_modem = {
515 .name = "pil_modem",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700516};
517
Stephen Boyd3f4da322011-08-30 01:03:23 -0700518static struct pil_desc pil_modem_desc = {
519 .name = "modem",
520 .depends_on = "q6",
521 .dev = &pil_modem.dev,
522 .ops = &pil_modem_ops,
523};
524
525static struct platform_device pil_q6 = {
526 .name = "pil_q6",
527};
528
529static struct pil_desc pil_q6_desc = {
530 .name = "q6",
531 .dev = &pil_q6.dev,
532 .ops = &pil_q6_ops,
533};
534
535static struct platform_device pil_playready = {
536 .name = "pil_playready",
537};
538
539static struct pil_desc pil_playready_desc = {
540 .name = "tzapps",
541 .dev = &pil_playready.dev,
542 .ops = &pil_playready_ops,
543};
544
545static struct platform_device pil_dsps = {
546 .name = "pil_dsps",
547};
548
549static struct pil_desc pil_dsps_desc = {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 .name = "dsps",
Stephen Boyd3f4da322011-08-30 01:03:23 -0700551 .dev = &pil_dsps.dev,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700552 .ops = &pil_dsps_ops,
553};
554
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700555static int __init msm_peripheral_reset_init(void)
556{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700557 msm_mms_regs_base = ioremap(MSM_MMS_REGS_BASE, SZ_256);
558 if (!msm_mms_regs_base)
559 goto err;
560
561 msm_lpass_qdsp6ss_base = ioremap(MSM_LPASS_QDSP6SS_BASE, SZ_256);
562 if (!msm_lpass_qdsp6ss_base)
563 goto err_lpass;
564
565 pxo = msm_xo_get(MSM_XO_PXO, "pil");
566 if (IS_ERR(pxo))
567 goto err_pxo;
568
569 pll4 = clk_get_sys("peripheral-reset", "pll4");
570 if (IS_ERR(pll4))
571 goto err_clk;
572
Stephen Boyde44ec392011-08-29 12:03:24 -0700573 if (pas_supported(PAS_MODEM) > 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700574 pil_modem_ops.init_image = init_image_modem_trusted;
575 pil_modem_ops.auth_and_reset = reset_modem_trusted;
576 pil_modem_ops.shutdown = shutdown_modem_trusted;
Stephen Boyde44ec392011-08-29 12:03:24 -0700577 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700578
Stephen Boyde44ec392011-08-29 12:03:24 -0700579 if (pas_supported(PAS_Q6) > 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700580 pil_q6_ops.init_image = init_image_q6_trusted;
581 pil_q6_ops.auth_and_reset = reset_q6_trusted;
582 pil_q6_ops.shutdown = shutdown_q6_trusted;
Stephen Boyde44ec392011-08-29 12:03:24 -0700583 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700584
Stephen Boyde44ec392011-08-29 12:03:24 -0700585 if (pas_supported(PAS_DSPS) > 0) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700586 pil_dsps_ops.init_image = init_image_dsps_trusted;
587 pil_dsps_ops.auth_and_reset = reset_dsps_trusted;
588 pil_dsps_ops.shutdown = shutdown_dsps_trusted;
589 }
590
Stephen Boyd3f4da322011-08-30 01:03:23 -0700591 BUG_ON(platform_device_register(&pil_q6));
592 BUG_ON(msm_pil_register(&pil_q6_desc));
593 BUG_ON(platform_device_register(&pil_modem));
594 BUG_ON(msm_pil_register(&pil_modem_desc));
595 BUG_ON(platform_device_register(&pil_playready));
596 BUG_ON(msm_pil_register(&pil_playready_desc));
597
598 if (machine_is_msm8x60_fluid())
599 pil_dsps_desc.name = "dsps_fluid";
600 BUG_ON(platform_device_register(&pil_dsps));
601 BUG_ON(msm_pil_register(&pil_dsps_desc));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700602
603 return 0;
604
605err_clk:
606 msm_xo_put(pxo);
607err_pxo:
608 iounmap(msm_lpass_qdsp6ss_base);
609err_lpass:
610 iounmap(msm_mms_regs_base);
611err:
612 return -ENOMEM;
613}
614
615static void __exit msm_peripheral_reset_exit(void)
616{
617 iounmap(msm_mms_regs_base);
618 iounmap(msm_lpass_qdsp6ss_base);
619}
620
621arch_initcall(msm_peripheral_reset_init);
622module_exit(msm_peripheral_reset_exit);
623
624MODULE_LICENSE("GPL v2");
625MODULE_DESCRIPTION("Validate and bring peripherals out of reset");