blob: dbb440857e2978064bdcc1f1110d7e2e2e4dffcc [file] [log] [blame]
Stephen Boyd12332572011-12-06 16:00:51 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Stephen Boyd322a9922011-09-20 01:05:54 -07002 *
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/platform_device.h>
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -080021#include <linux/regulator/consumer.h>
Stephen Boyd86f2e652012-01-11 18:25:44 -080022#include <linux/clk.h>
Stephen Boydfdec00d2012-05-10 17:04:49 -070023#include <linux/interrupt.h>
24#include <linux/wcnss_wlan.h>
Stephen Boyd322a9922011-09-20 01:05:54 -070025
26#include <mach/msm_iomap.h>
Stephen Boydfdec00d2012-05-10 17:04:49 -070027#include <mach/subsystem_restart.h>
28#include <mach/peripheral-loader.h>
Stephen Boyd322a9922011-09-20 01:05:54 -070029
30#include "peripheral-loader.h"
31#include "scm-pas.h"
Stephen Boydfdec00d2012-05-10 17:04:49 -070032#include "ramdump.h"
33#include "smd_private.h"
Stephen Boyd322a9922011-09-20 01:05:54 -070034
35#define RIVA_PMU_A2XB_CFG 0xB8
36#define RIVA_PMU_A2XB_CFG_EN BIT(0)
37
38#define RIVA_PMU_CFG 0x28
39#define RIVA_PMU_CFG_WARM_BOOT BIT(0)
40#define RIVA_PMU_CFG_IRIS_XO_MODE 0x6
41#define RIVA_PMU_CFG_IRIS_XO_MODE_48 (3 << 1)
42
Stephen Boyd12332572011-12-06 16:00:51 -080043#define RIVA_PMU_OVRD_EN 0x2C
44#define RIVA_PMU_OVRD_EN_CCPU_RESET BIT(0)
45#define RIVA_PMU_OVRD_EN_CCPU_CLK BIT(1)
46
Stephen Boyd322a9922011-09-20 01:05:54 -070047#define RIVA_PMU_OVRD_VAL 0x30
48#define RIVA_PMU_OVRD_VAL_CCPU_RESET BIT(0)
49#define RIVA_PMU_OVRD_VAL_CCPU_CLK BIT(1)
50
51#define RIVA_PMU_CCPU_CTL 0x9C
52#define RIVA_PMU_CCPU_CTL_HIGH_IVT BIT(0)
53#define RIVA_PMU_CCPU_CTL_REMAP_EN BIT(2)
54
55#define RIVA_PMU_CCPU_BOOT_REMAP_ADDR 0xA0
56
57#define RIVA_PLL_MODE (MSM_CLK_CTL_BASE + 0x31A0)
58#define PLL_MODE_OUTCTRL BIT(0)
59#define PLL_MODE_BYPASSNL BIT(1)
60#define PLL_MODE_RESET_N BIT(2)
61#define PLL_MODE_REF_XO_SEL 0x30
62#define PLL_MODE_REF_XO_SEL_CXO (2 << 4)
63#define PLL_MODE_REF_XO_SEL_RF (3 << 4)
64#define RIVA_PLL_L_VAL (MSM_CLK_CTL_BASE + 0x31A4)
65#define RIVA_PLL_M_VAL (MSM_CLK_CTL_BASE + 0x31A8)
66#define RIVA_PLL_N_VAL (MSM_CLK_CTL_BASE + 0x31Ac)
67#define RIVA_PLL_CONFIG (MSM_CLK_CTL_BASE + 0x31B4)
68#define RIVA_PLL_STATUS (MSM_CLK_CTL_BASE + 0x31B8)
Stephen Boyd12332572011-12-06 16:00:51 -080069#define RIVA_RESET (MSM_CLK_CTL_BASE + 0x35E0)
Stephen Boyd322a9922011-09-20 01:05:54 -070070
71#define RIVA_PMU_ROOT_CLK_SEL 0xC8
72#define RIVA_PMU_ROOT_CLK_SEL_3 BIT(2)
73
74#define RIVA_PMU_CLK_ROOT3 0x78
75#define RIVA_PMU_CLK_ROOT3_ENA BIT(0)
76#define RIVA_PMU_CLK_ROOT3_SRC0_DIV 0x3C
77#define RIVA_PMU_CLK_ROOT3_SRC0_DIV_2 (1 << 2)
78#define RIVA_PMU_CLK_ROOT3_SRC0_SEL 0x1C0
79#define RIVA_PMU_CLK_ROOT3_SRC0_SEL_RIVA (1 << 6)
80#define RIVA_PMU_CLK_ROOT3_SRC1_DIV 0x1E00
81#define RIVA_PMU_CLK_ROOT3_SRC1_DIV_2 (1 << 9)
82#define RIVA_PMU_CLK_ROOT3_SRC1_SEL 0xE000
83#define RIVA_PMU_CLK_ROOT3_SRC1_SEL_RIVA (1 << 13)
84
85struct riva_data {
86 void __iomem *base;
87 unsigned long start_addr;
Stephen Boyd86f2e652012-01-11 18:25:44 -080088 struct clk *xo;
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -080089 struct regulator *pll_supply;
Stephen Boyd6d67d252011-09-27 11:50:05 -070090 struct pil_device *pil;
Stephen Boydfdec00d2012-05-10 17:04:49 -070091 int irq;
92 int crash;
93 int rst_in_progress;
94 struct subsys_device *subsys;
95 struct subsys_desc subsys_desc;
96 struct delayed_work cancel_work;
97 struct ramdump_device *ramdump_dev;
Stephen Boyd322a9922011-09-20 01:05:54 -070098};
99
Stephen Boyd86f4a092012-03-22 10:59:22 -0700100static bool cxo_is_needed(struct riva_data *drv)
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800101{
Stephen Boyd86f4a092012-03-22 10:59:22 -0700102 u32 reg = readl_relaxed(drv->base + RIVA_PMU_CFG);
103 return (reg & RIVA_PMU_CFG_IRIS_XO_MODE)
104 != RIVA_PMU_CFG_IRIS_XO_MODE_48;
105}
106
107static int pil_riva_make_proxy_vote(struct pil_desc *pil)
108{
109 struct riva_data *drv = dev_get_drvdata(pil->dev);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800110 int ret;
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800111
Stephen Boydd0b993a2012-01-30 11:59:31 -0800112 ret = regulator_enable(drv->pll_supply);
113 if (ret) {
Stephen Boyd86f4a092012-03-22 10:59:22 -0700114 dev_err(pil->dev, "failed to enable pll supply\n");
Stephen Boydd0b993a2012-01-30 11:59:31 -0800115 goto err;
116 }
Stephen Boyda74acd62012-04-03 17:41:33 -0700117 ret = clk_prepare_enable(drv->xo);
118 if (ret) {
119 dev_err(pil->dev, "failed to enable xo\n");
120 goto err_clk;
Stephen Boyd86f2e652012-01-11 18:25:44 -0800121 }
Stephen Boydd0b993a2012-01-30 11:59:31 -0800122 return 0;
123err_clk:
124 regulator_disable(drv->pll_supply);
125err:
126 return ret;
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800127}
128
Stephen Boyd86f4a092012-03-22 10:59:22 -0700129static void pil_riva_remove_proxy_vote(struct pil_desc *pil)
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800130{
Stephen Boyd86f4a092012-03-22 10:59:22 -0700131 struct riva_data *drv = dev_get_drvdata(pil->dev);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800132 regulator_disable(drv->pll_supply);
Stephen Boyda74acd62012-04-03 17:41:33 -0700133 clk_disable_unprepare(drv->xo);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800134}
135
Stephen Boyd322a9922011-09-20 01:05:54 -0700136static int pil_riva_init_image(struct pil_desc *pil, const u8 *metadata,
137 size_t size)
138{
139 const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
140 struct riva_data *drv = dev_get_drvdata(pil->dev);
141 drv->start_addr = ehdr->e_entry;
142 return 0;
143}
144
145static int pil_riva_reset(struct pil_desc *pil)
146{
147 u32 reg, sel;
Stephen Boyd322a9922011-09-20 01:05:54 -0700148 struct riva_data *drv = dev_get_drvdata(pil->dev);
149 void __iomem *base = drv->base;
150 unsigned long start_addr = drv->start_addr;
Stephen Boyda74acd62012-04-03 17:41:33 -0700151 bool use_cxo = cxo_is_needed(drv);
Stephen Boyd322a9922011-09-20 01:05:54 -0700152
153 /* Enable A2XB bridge */
154 reg = readl_relaxed(base + RIVA_PMU_A2XB_CFG);
155 reg |= RIVA_PMU_A2XB_CFG_EN;
156 writel_relaxed(reg, base + RIVA_PMU_A2XB_CFG);
157
Stephen Boyd322a9922011-09-20 01:05:54 -0700158 /* Program PLL 13 to 960 MHz */
159 reg = readl_relaxed(RIVA_PLL_MODE);
160 reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N);
161 writel_relaxed(reg, RIVA_PLL_MODE);
162
Stephen Boyda74acd62012-04-03 17:41:33 -0700163 if (use_cxo)
Stephen Boyd322a9922011-09-20 01:05:54 -0700164 writel_relaxed(0x40000C00 | 50, RIVA_PLL_L_VAL);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800165 else
166 writel_relaxed(0x40000C00 | 40, RIVA_PLL_L_VAL);
Stephen Boyd322a9922011-09-20 01:05:54 -0700167 writel_relaxed(0, RIVA_PLL_M_VAL);
168 writel_relaxed(1, RIVA_PLL_N_VAL);
169 writel_relaxed(0x01495227, RIVA_PLL_CONFIG);
170
171 reg = readl_relaxed(RIVA_PLL_MODE);
172 reg &= ~(PLL_MODE_REF_XO_SEL);
Stephen Boyda74acd62012-04-03 17:41:33 -0700173 reg |= use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
Stephen Boyd322a9922011-09-20 01:05:54 -0700174 writel_relaxed(reg, RIVA_PLL_MODE);
175
176 /* Enable PLL 13 */
177 reg |= PLL_MODE_BYPASSNL;
178 writel_relaxed(reg, RIVA_PLL_MODE);
179
180 /*
181 * H/W requires a 5us delay between disabling the bypass and
182 * de-asserting the reset. Delay 10us just to be safe.
183 */
184 mb();
185 usleep_range(10, 20);
186
187 reg |= PLL_MODE_RESET_N;
188 writel_relaxed(reg, RIVA_PLL_MODE);
189 reg |= PLL_MODE_OUTCTRL;
190 writel_relaxed(reg, RIVA_PLL_MODE);
191
192 /* Wait for PLL to settle */
193 mb();
194 usleep_range(50, 100);
195
196 /* Configure cCPU for 240 MHz */
197 sel = readl_relaxed(base + RIVA_PMU_ROOT_CLK_SEL);
198 reg = readl_relaxed(base + RIVA_PMU_CLK_ROOT3);
199 if (sel & RIVA_PMU_ROOT_CLK_SEL_3) {
200 reg &= ~(RIVA_PMU_CLK_ROOT3_SRC0_SEL |
201 RIVA_PMU_CLK_ROOT3_SRC0_DIV);
202 reg |= RIVA_PMU_CLK_ROOT3_SRC0_SEL_RIVA |
203 RIVA_PMU_CLK_ROOT3_SRC0_DIV_2;
204 } else {
205 reg &= ~(RIVA_PMU_CLK_ROOT3_SRC1_SEL |
206 RIVA_PMU_CLK_ROOT3_SRC1_DIV);
207 reg |= RIVA_PMU_CLK_ROOT3_SRC1_SEL_RIVA |
208 RIVA_PMU_CLK_ROOT3_SRC1_DIV_2;
209 }
210 writel_relaxed(reg, base + RIVA_PMU_CLK_ROOT3);
211 reg |= RIVA_PMU_CLK_ROOT3_ENA;
212 writel_relaxed(reg, base + RIVA_PMU_CLK_ROOT3);
213 reg = readl_relaxed(base + RIVA_PMU_ROOT_CLK_SEL);
214 reg ^= RIVA_PMU_ROOT_CLK_SEL_3;
215 writel_relaxed(reg, base + RIVA_PMU_ROOT_CLK_SEL);
216
217 /* Use the high vector table */
218 reg = readl_relaxed(base + RIVA_PMU_CCPU_CTL);
219 reg |= RIVA_PMU_CCPU_CTL_HIGH_IVT | RIVA_PMU_CCPU_CTL_REMAP_EN;
220 writel_relaxed(reg, base + RIVA_PMU_CCPU_CTL);
221
222 /* Set base memory address */
223 writel_relaxed(start_addr >> 16, base + RIVA_PMU_CCPU_BOOT_REMAP_ADDR);
224
225 /* Clear warmboot bit indicating this is a cold boot */
226 reg = readl_relaxed(base + RIVA_PMU_CFG);
227 reg &= ~(RIVA_PMU_CFG_WARM_BOOT);
228 writel_relaxed(reg, base + RIVA_PMU_CFG);
229
230 /* Enable the cCPU clock */
231 reg = readl_relaxed(base + RIVA_PMU_OVRD_VAL);
232 reg |= RIVA_PMU_OVRD_VAL_CCPU_CLK;
233 writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL);
234
235 /* Take cCPU out of reset */
236 reg |= RIVA_PMU_OVRD_VAL_CCPU_RESET;
237 writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL);
238
239 return 0;
240}
241
242static int pil_riva_shutdown(struct pil_desc *pil)
243{
Stephen Boyd12332572011-12-06 16:00:51 -0800244 /* Assert reset to Riva */
245 writel_relaxed(1, RIVA_RESET);
246 mb();
247 usleep_range(1000, 2000);
248
249 /* Deassert reset to Riva */
250 writel_relaxed(0, RIVA_RESET);
251 mb();
Stephen Boyd322a9922011-09-20 01:05:54 -0700252
253 return 0;
254}
255
256static struct pil_reset_ops pil_riva_ops = {
257 .init_image = pil_riva_init_image,
Stephen Boyd322a9922011-09-20 01:05:54 -0700258 .auth_and_reset = pil_riva_reset,
259 .shutdown = pil_riva_shutdown,
Stephen Boyd86f4a092012-03-22 10:59:22 -0700260 .proxy_vote = pil_riva_make_proxy_vote,
261 .proxy_unvote = pil_riva_remove_proxy_vote,
Stephen Boyd322a9922011-09-20 01:05:54 -0700262};
263
264static int pil_riva_init_image_trusted(struct pil_desc *pil,
265 const u8 *metadata, size_t size)
266{
Tianyi Gouca0aaac2012-07-27 14:13:29 -0700267 return pas_init_image(PAS_WCNSS, metadata, size);
Stephen Boyd322a9922011-09-20 01:05:54 -0700268}
269
270static int pil_riva_reset_trusted(struct pil_desc *pil)
271{
Tianyi Gouca0aaac2012-07-27 14:13:29 -0700272 return pas_auth_and_reset(PAS_WCNSS);
Stephen Boyd322a9922011-09-20 01:05:54 -0700273}
274
275static int pil_riva_shutdown_trusted(struct pil_desc *pil)
276{
Tianyi Gouca0aaac2012-07-27 14:13:29 -0700277 return pas_shutdown(PAS_WCNSS);
Stephen Boyd322a9922011-09-20 01:05:54 -0700278}
279
280static struct pil_reset_ops pil_riva_ops_trusted = {
281 .init_image = pil_riva_init_image_trusted,
Stephen Boyd322a9922011-09-20 01:05:54 -0700282 .auth_and_reset = pil_riva_reset_trusted,
283 .shutdown = pil_riva_shutdown_trusted,
Stephen Boyd86f4a092012-03-22 10:59:22 -0700284 .proxy_vote = pil_riva_make_proxy_vote,
285 .proxy_unvote = pil_riva_remove_proxy_vote,
Stephen Boyd322a9922011-09-20 01:05:54 -0700286};
287
Stephen Boydfdec00d2012-05-10 17:04:49 -0700288static int enable_riva_ssr;
289
290static int enable_riva_ssr_set(const char *val, struct kernel_param *kp)
291{
292 int ret;
293
294 ret = param_set_int(val, kp);
295 if (ret)
296 return ret;
297
298 if (enable_riva_ssr)
299 pr_info("Subsystem restart activated for riva.\n");
300
301 return 0;
302}
303module_param_call(enable_riva_ssr, enable_riva_ssr_set, param_get_int,
304 &enable_riva_ssr, S_IRUGO | S_IWUSR);
305
306static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
307 uint32_t new_state)
308{
309 struct riva_data *drv = data;
310 char *smem_reset_reason;
311 char buffer[81];
312 unsigned smem_reset_size;
313 unsigned size;
314
315 drv->crash = true;
316 if (!(new_state & SMSM_RESET))
317 return;
318
319 if (drv->rst_in_progress) {
320 pr_err("riva: Ignoring smsm reset req, restart in progress\n");
321 return;
322 }
323
324 pr_err("riva: smsm state changed to smsm reset\n");
325
326 smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
327 &smem_reset_size);
328
329 if (!smem_reset_reason || !smem_reset_size) {
330 pr_err("wcnss subsystem failure reason:\n"
331 "(unknown, smem_get_entry failed)");
332 } else if (!smem_reset_reason[0]) {
333 pr_err("wcnss subsystem failure reason:\n"
334 "(unknown, init string found)");
335 } else {
336 size = smem_reset_size < sizeof(buffer) ? smem_reset_size :
337 (sizeof(buffer) - 1);
338 memcpy(buffer, smem_reset_reason, size);
339 buffer[size] = '\0';
340 pr_err("wcnss subsystem failure reason: %s\n", buffer);
341 memset(smem_reset_reason, 0, smem_reset_size);
342 wmb();
343 }
344
345 drv->rst_in_progress = 1;
346 subsystem_restart_dev(drv->subsys);
347}
348
349static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
350{
351 struct riva_data *drv = dev_id;
352
353 drv->crash = true;
354 if (drv->rst_in_progress) {
355 pr_err("Ignoring riva bite irq, restart in progress\n");
356 return IRQ_HANDLED;
357 }
358 if (!enable_riva_ssr)
359 panic("Watchdog bite received from Riva");
360
361 drv->rst_in_progress = 1;
362 subsystem_restart_dev(drv->subsys);
363
364 return IRQ_HANDLED;
365}
366
367static void riva_post_bootup(struct work_struct *work)
368{
369 struct platform_device *pdev = wcnss_get_platform_device();
370 struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
371
372 wcnss_wlan_power(&pdev->dev, pwlanconfig, WCNSS_WLAN_SWITCH_OFF);
373}
374
375static int riva_shutdown(const struct subsys_desc *desc)
376{
377 struct riva_data *drv;
378
379 drv = container_of(desc, struct riva_data, subsys_desc);
380 pil_force_shutdown("wcnss");
381 flush_delayed_work(&drv->cancel_work);
382 wcnss_flush_delayed_boot_votes();
383 disable_irq_nosync(drv->irq);
384
385 return 0;
386}
387
388static int riva_powerup(const struct subsys_desc *desc)
389{
390 struct riva_data *drv;
391 struct platform_device *pdev = wcnss_get_platform_device();
392 struct wcnss_wlan_config *pwlanconfig = wcnss_get_wlan_config();
393 int ret = 0;
394
395 drv = container_of(desc, struct riva_data, subsys_desc);
396 if (pdev && pwlanconfig) {
397 ret = wcnss_wlan_power(&pdev->dev, pwlanconfig,
398 WCNSS_WLAN_SWITCH_ON);
399 if (!ret)
400 pil_force_boot("wcnss");
401 }
402 drv->rst_in_progress = 0;
403 enable_irq(drv->irq);
404 schedule_delayed_work(&drv->cancel_work, msecs_to_jiffies(5000));
405
406 return ret;
407}
408
409/*
410 * 7MB RAM segments for Riva SS;
411 * Riva 1.1 0x8f000000 - 0x8f700000
412 * Riva 1.0 0x8f200000 - 0x8f700000
413 */
414static struct ramdump_segment riva_segments[] = {
415 {0x8f000000, 0x8f700000 - 0x8f000000}
416};
417
418static int riva_ramdump(int enable, const struct subsys_desc *desc)
419{
420 struct riva_data *drv;
421
422 drv = container_of(desc, struct riva_data, subsys_desc);
423
424 if (enable)
425 return do_ramdump(drv->ramdump_dev, riva_segments,
426 ARRAY_SIZE(riva_segments));
427 else
428 return 0;
429}
430
431/* Riva crash handler */
432static void riva_crash_shutdown(const struct subsys_desc *desc)
433{
434 struct riva_data *drv;
435
436 drv = container_of(desc, struct riva_data, subsys_desc);
437 pr_err("riva crash shutdown %d\n", drv->crash);
438 if (drv->crash != true)
439 smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
440}
441
Stephen Boyd322a9922011-09-20 01:05:54 -0700442static int __devinit pil_riva_probe(struct platform_device *pdev)
443{
444 struct riva_data *drv;
445 struct resource *res;
446 struct pil_desc *desc;
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800447 int ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700448
449 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
450 if (!res)
451 return -EINVAL;
452
453 drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
454 if (!drv)
455 return -ENOMEM;
456 platform_set_drvdata(pdev, drv);
457
458 drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
459 if (!drv->base)
460 return -ENOMEM;
461
462 desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
463 if (!desc)
464 return -ENOMEM;
465
Stephen Boyd83e5eae2012-03-23 15:04:46 -0700466 drv->pll_supply = devm_regulator_get(&pdev->dev, "pll_vdd");
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800467 if (IS_ERR(drv->pll_supply)) {
468 dev_err(&pdev->dev, "failed to get pll supply\n");
469 return PTR_ERR(drv->pll_supply);
470 }
Matt Wagantall52dd0622012-02-02 18:26:16 -0800471 if (regulator_count_voltages(drv->pll_supply) > 0) {
472 ret = regulator_set_voltage(drv->pll_supply, 1800000, 1800000);
473 if (ret) {
474 dev_err(&pdev->dev,
475 "failed to set pll supply voltage\n");
Stephen Boyd93528ea2012-03-23 15:23:10 -0700476 return ret;
Matt Wagantall52dd0622012-02-02 18:26:16 -0800477 }
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800478
Matt Wagantall52dd0622012-02-02 18:26:16 -0800479 ret = regulator_set_optimum_mode(drv->pll_supply, 100000);
480 if (ret < 0) {
481 dev_err(&pdev->dev,
482 "failed to set pll supply optimum mode\n");
Stephen Boyd93528ea2012-03-23 15:23:10 -0700483 return ret;
Matt Wagantall52dd0622012-02-02 18:26:16 -0800484 }
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800485 }
486
Stephen Boydfdec00d2012-05-10 17:04:49 -0700487 drv->irq = platform_get_irq(pdev, 0);
488 if (drv->irq < 0)
489 return drv->irq;
490
Stephen Boyd322a9922011-09-20 01:05:54 -0700491 desc->name = "wcnss";
492 desc->dev = &pdev->dev;
Stephen Boyd6d67d252011-09-27 11:50:05 -0700493 desc->owner = THIS_MODULE;
Stephen Boyd86f4a092012-03-22 10:59:22 -0700494 desc->proxy_timeout = 10000;
Stephen Boyd322a9922011-09-20 01:05:54 -0700495
Tianyi Gouca0aaac2012-07-27 14:13:29 -0700496 if (pas_supported(PAS_WCNSS) > 0) {
Stephen Boyd322a9922011-09-20 01:05:54 -0700497 desc->ops = &pil_riva_ops_trusted;
498 dev_info(&pdev->dev, "using secure boot\n");
499 } else {
500 desc->ops = &pil_riva_ops;
501 dev_info(&pdev->dev, "using non-secure boot\n");
502 }
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800503
Stephen Boyd93528ea2012-03-23 15:23:10 -0700504 drv->xo = devm_clk_get(&pdev->dev, "cxo");
505 if (IS_ERR(drv->xo))
506 return PTR_ERR(drv->xo);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800507
Stephen Boyd6d67d252011-09-27 11:50:05 -0700508 drv->pil = msm_pil_register(desc);
Stephen Boyd93528ea2012-03-23 15:23:10 -0700509 if (IS_ERR(drv->pil))
510 return PTR_ERR(drv->pil);
Stephen Boydfdec00d2012-05-10 17:04:49 -0700511
512 ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
513 smsm_state_cb_hdlr, drv);
514 if (ret < 0)
515 goto err_smsm;
516
517 drv->subsys_desc.name = "wcnss";
518 drv->subsys_desc.shutdown = riva_shutdown;
519 drv->subsys_desc.powerup = riva_powerup;
520 drv->subsys_desc.ramdump = riva_ramdump;
521 drv->subsys_desc.crash_shutdown = riva_crash_shutdown;
522
523 INIT_DELAYED_WORK(&drv->cancel_work, riva_post_bootup);
524
525 drv->ramdump_dev = create_ramdump_device("riva");
526 if (!drv->ramdump_dev) {
527 ret = -ENOMEM;
528 goto err_ramdump;
529 }
530
531 drv->subsys = subsys_register(&drv->subsys_desc);
532 if (IS_ERR(drv->subsys)) {
533 ret = PTR_ERR(drv->subsys);
534 goto err_subsys;
535 }
536
537 ret = devm_request_irq(&pdev->dev, drv->irq, riva_wdog_bite_irq_hdlr,
538 IRQF_TRIGGER_HIGH, "riva_wdog", drv);
539 if (ret < 0)
540 goto err;
541
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800542 return 0;
Stephen Boydfdec00d2012-05-10 17:04:49 -0700543err:
544 subsys_unregister(drv->subsys);
545err_subsys:
546 destroy_ramdump_device(drv->ramdump_dev);
547err_ramdump:
548 smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
549 smsm_state_cb_hdlr, drv);
550err_smsm:
551 msm_pil_unregister(drv->pil);
552 return ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700553}
554
555static int __devexit pil_riva_remove(struct platform_device *pdev)
556{
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800557 struct riva_data *drv = platform_get_drvdata(pdev);
Stephen Boydfdec00d2012-05-10 17:04:49 -0700558
559 subsys_unregister(drv->subsys);
560 destroy_ramdump_device(drv->ramdump_dev);
561 smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
562 smsm_state_cb_hdlr, drv);
Stephen Boyd6d67d252011-09-27 11:50:05 -0700563 msm_pil_unregister(drv->pil);
Stephen Boydfdec00d2012-05-10 17:04:49 -0700564
Stephen Boyd322a9922011-09-20 01:05:54 -0700565 return 0;
566}
567
568static struct platform_driver pil_riva_driver = {
569 .probe = pil_riva_probe,
570 .remove = __devexit_p(pil_riva_remove),
571 .driver = {
572 .name = "pil_riva",
573 .owner = THIS_MODULE,
574 },
575};
576
577static int __init pil_riva_init(void)
578{
579 return platform_driver_register(&pil_riva_driver);
580}
581module_init(pil_riva_init);
582
583static void __exit pil_riva_exit(void)
584{
Stephen Boyd322a9922011-09-20 01:05:54 -0700585 platform_driver_unregister(&pil_riva_driver);
586}
587module_exit(pil_riva_exit);
588
589MODULE_DESCRIPTION("Support for booting RIVA (WCNSS) processors");
590MODULE_LICENSE("GPL v2");