blob: 7e78a15c8ad309af34454e46041a52244f4c8fbc [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>
22#include <linux/workqueue.h>
Stephen Boyd86f2e652012-01-11 18:25:44 -080023#include <linux/clk.h>
Stephen Boyd322a9922011-09-20 01:05:54 -070024
25#include <mach/msm_iomap.h>
26
27#include "peripheral-loader.h"
28#include "scm-pas.h"
29
Matt Wagantall04b7cc72011-12-09 18:52:26 -080030#define PROXY_VOTE_TIMEOUT 10000
31
Stephen Boyd322a9922011-09-20 01:05:54 -070032#define RIVA_PMU_A2XB_CFG 0xB8
33#define RIVA_PMU_A2XB_CFG_EN BIT(0)
34
35#define RIVA_PMU_CFG 0x28
36#define RIVA_PMU_CFG_WARM_BOOT BIT(0)
37#define RIVA_PMU_CFG_IRIS_XO_MODE 0x6
38#define RIVA_PMU_CFG_IRIS_XO_MODE_48 (3 << 1)
39
Stephen Boyd12332572011-12-06 16:00:51 -080040#define RIVA_PMU_OVRD_EN 0x2C
41#define RIVA_PMU_OVRD_EN_CCPU_RESET BIT(0)
42#define RIVA_PMU_OVRD_EN_CCPU_CLK BIT(1)
43
Stephen Boyd322a9922011-09-20 01:05:54 -070044#define RIVA_PMU_OVRD_VAL 0x30
45#define RIVA_PMU_OVRD_VAL_CCPU_RESET BIT(0)
46#define RIVA_PMU_OVRD_VAL_CCPU_CLK BIT(1)
47
48#define RIVA_PMU_CCPU_CTL 0x9C
49#define RIVA_PMU_CCPU_CTL_HIGH_IVT BIT(0)
50#define RIVA_PMU_CCPU_CTL_REMAP_EN BIT(2)
51
52#define RIVA_PMU_CCPU_BOOT_REMAP_ADDR 0xA0
53
54#define RIVA_PLL_MODE (MSM_CLK_CTL_BASE + 0x31A0)
55#define PLL_MODE_OUTCTRL BIT(0)
56#define PLL_MODE_BYPASSNL BIT(1)
57#define PLL_MODE_RESET_N BIT(2)
58#define PLL_MODE_REF_XO_SEL 0x30
59#define PLL_MODE_REF_XO_SEL_CXO (2 << 4)
60#define PLL_MODE_REF_XO_SEL_RF (3 << 4)
61#define RIVA_PLL_L_VAL (MSM_CLK_CTL_BASE + 0x31A4)
62#define RIVA_PLL_M_VAL (MSM_CLK_CTL_BASE + 0x31A8)
63#define RIVA_PLL_N_VAL (MSM_CLK_CTL_BASE + 0x31Ac)
64#define RIVA_PLL_CONFIG (MSM_CLK_CTL_BASE + 0x31B4)
65#define RIVA_PLL_STATUS (MSM_CLK_CTL_BASE + 0x31B8)
Stephen Boyd12332572011-12-06 16:00:51 -080066#define RIVA_RESET (MSM_CLK_CTL_BASE + 0x35E0)
Stephen Boyd322a9922011-09-20 01:05:54 -070067
68#define RIVA_PMU_ROOT_CLK_SEL 0xC8
69#define RIVA_PMU_ROOT_CLK_SEL_3 BIT(2)
70
71#define RIVA_PMU_CLK_ROOT3 0x78
72#define RIVA_PMU_CLK_ROOT3_ENA BIT(0)
73#define RIVA_PMU_CLK_ROOT3_SRC0_DIV 0x3C
74#define RIVA_PMU_CLK_ROOT3_SRC0_DIV_2 (1 << 2)
75#define RIVA_PMU_CLK_ROOT3_SRC0_SEL 0x1C0
76#define RIVA_PMU_CLK_ROOT3_SRC0_SEL_RIVA (1 << 6)
77#define RIVA_PMU_CLK_ROOT3_SRC1_DIV 0x1E00
78#define RIVA_PMU_CLK_ROOT3_SRC1_DIV_2 (1 << 9)
79#define RIVA_PMU_CLK_ROOT3_SRC1_SEL 0xE000
80#define RIVA_PMU_CLK_ROOT3_SRC1_SEL_RIVA (1 << 13)
81
82struct riva_data {
83 void __iomem *base;
84 unsigned long start_addr;
Stephen Boyd86f2e652012-01-11 18:25:44 -080085 struct clk *xo;
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -080086 bool use_cxo;
87 struct delayed_work work;
88 struct regulator *pll_supply;
Stephen Boyd322a9922011-09-20 01:05:54 -070089};
90
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -080091static void pil_riva_make_proxy_votes(struct device *dev)
Matt Wagantall04b7cc72011-12-09 18:52:26 -080092{
93 struct riva_data *drv = dev_get_drvdata(dev);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -080094 int ret;
Matt Wagantall04b7cc72011-12-09 18:52:26 -080095
Stephen Boyd86f2e652012-01-11 18:25:44 -080096 if (drv->use_cxo) {
97 ret = clk_prepare_enable(drv->xo);
98 if (ret)
99 dev_err(dev, "failed to enable xo\n");
100 }
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800101 ret = regulator_enable(drv->pll_supply);
102 if (ret)
103 dev_err(dev, "failed to enable pll supply\n");
104 schedule_delayed_work(&drv->work, msecs_to_jiffies(PROXY_VOTE_TIMEOUT));
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800105}
106
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800107static void pil_riva_remove_proxy_votes(struct work_struct *work)
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800108{
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800109 struct riva_data *drv = container_of(work, struct riva_data, work.work);
110 regulator_disable(drv->pll_supply);
111 if (drv->use_cxo)
Stephen Boyd86f2e652012-01-11 18:25:44 -0800112 clk_disable_unprepare(drv->xo);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800113}
114
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800115static void pil_riva_remove_proxy_votes_now(struct device *dev)
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800116{
117 struct riva_data *drv = dev_get_drvdata(dev);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800118 flush_delayed_work(&drv->work);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800119}
120
Stephen Boyd322a9922011-09-20 01:05:54 -0700121static int nop_verify_blob(struct pil_desc *pil, u32 phy_addr, size_t size)
122{
123 return 0;
124}
125
126static int pil_riva_init_image(struct pil_desc *pil, const u8 *metadata,
127 size_t size)
128{
129 const struct elf32_hdr *ehdr = (struct elf32_hdr *)metadata;
130 struct riva_data *drv = dev_get_drvdata(pil->dev);
131 drv->start_addr = ehdr->e_entry;
132 return 0;
133}
134
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800135static bool cxo_is_needed(struct riva_data *drv)
136{
137 u32 reg = readl_relaxed(drv->base + RIVA_PMU_CFG);
138 return (reg & RIVA_PMU_CFG_IRIS_XO_MODE)
139 != RIVA_PMU_CFG_IRIS_XO_MODE_48;
140}
141
Stephen Boyd322a9922011-09-20 01:05:54 -0700142static int pil_riva_reset(struct pil_desc *pil)
143{
144 u32 reg, sel;
Stephen Boyd322a9922011-09-20 01:05:54 -0700145 struct riva_data *drv = dev_get_drvdata(pil->dev);
146 void __iomem *base = drv->base;
147 unsigned long start_addr = drv->start_addr;
Stephen Boyd86f2e652012-01-11 18:25:44 -0800148 int ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700149
Stephen Boyd86f2e652012-01-11 18:25:44 -0800150 ret = clk_prepare_enable(drv->xo);
151 if (ret)
152 return ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700153 /* 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 Boyd3bbdf6c2011-12-21 16:02:26 -0800158 drv->use_cxo = cxo_is_needed(drv);
159 pil_riva_make_proxy_votes(pil->dev);
Stephen Boyd322a9922011-09-20 01:05:54 -0700160
161 /* Program PLL 13 to 960 MHz */
162 reg = readl_relaxed(RIVA_PLL_MODE);
163 reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N);
164 writel_relaxed(reg, RIVA_PLL_MODE);
165
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800166 if (drv->use_cxo)
Stephen Boyd322a9922011-09-20 01:05:54 -0700167 writel_relaxed(0x40000C00 | 50, RIVA_PLL_L_VAL);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800168 else
169 writel_relaxed(0x40000C00 | 40, RIVA_PLL_L_VAL);
Stephen Boyd322a9922011-09-20 01:05:54 -0700170 writel_relaxed(0, RIVA_PLL_M_VAL);
171 writel_relaxed(1, RIVA_PLL_N_VAL);
172 writel_relaxed(0x01495227, RIVA_PLL_CONFIG);
173
174 reg = readl_relaxed(RIVA_PLL_MODE);
175 reg &= ~(PLL_MODE_REF_XO_SEL);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800176 reg |= drv->use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
Stephen Boyd322a9922011-09-20 01:05:54 -0700177 writel_relaxed(reg, RIVA_PLL_MODE);
178
179 /* Enable PLL 13 */
180 reg |= PLL_MODE_BYPASSNL;
181 writel_relaxed(reg, RIVA_PLL_MODE);
182
183 /*
184 * H/W requires a 5us delay between disabling the bypass and
185 * de-asserting the reset. Delay 10us just to be safe.
186 */
187 mb();
188 usleep_range(10, 20);
189
190 reg |= PLL_MODE_RESET_N;
191 writel_relaxed(reg, RIVA_PLL_MODE);
192 reg |= PLL_MODE_OUTCTRL;
193 writel_relaxed(reg, RIVA_PLL_MODE);
194
195 /* Wait for PLL to settle */
196 mb();
197 usleep_range(50, 100);
198
199 /* Configure cCPU for 240 MHz */
200 sel = readl_relaxed(base + RIVA_PMU_ROOT_CLK_SEL);
201 reg = readl_relaxed(base + RIVA_PMU_CLK_ROOT3);
202 if (sel & RIVA_PMU_ROOT_CLK_SEL_3) {
203 reg &= ~(RIVA_PMU_CLK_ROOT3_SRC0_SEL |
204 RIVA_PMU_CLK_ROOT3_SRC0_DIV);
205 reg |= RIVA_PMU_CLK_ROOT3_SRC0_SEL_RIVA |
206 RIVA_PMU_CLK_ROOT3_SRC0_DIV_2;
207 } else {
208 reg &= ~(RIVA_PMU_CLK_ROOT3_SRC1_SEL |
209 RIVA_PMU_CLK_ROOT3_SRC1_DIV);
210 reg |= RIVA_PMU_CLK_ROOT3_SRC1_SEL_RIVA |
211 RIVA_PMU_CLK_ROOT3_SRC1_DIV_2;
212 }
213 writel_relaxed(reg, base + RIVA_PMU_CLK_ROOT3);
214 reg |= RIVA_PMU_CLK_ROOT3_ENA;
215 writel_relaxed(reg, base + RIVA_PMU_CLK_ROOT3);
216 reg = readl_relaxed(base + RIVA_PMU_ROOT_CLK_SEL);
217 reg ^= RIVA_PMU_ROOT_CLK_SEL_3;
218 writel_relaxed(reg, base + RIVA_PMU_ROOT_CLK_SEL);
219
220 /* Use the high vector table */
221 reg = readl_relaxed(base + RIVA_PMU_CCPU_CTL);
222 reg |= RIVA_PMU_CCPU_CTL_HIGH_IVT | RIVA_PMU_CCPU_CTL_REMAP_EN;
223 writel_relaxed(reg, base + RIVA_PMU_CCPU_CTL);
224
225 /* Set base memory address */
226 writel_relaxed(start_addr >> 16, base + RIVA_PMU_CCPU_BOOT_REMAP_ADDR);
227
228 /* Clear warmboot bit indicating this is a cold boot */
229 reg = readl_relaxed(base + RIVA_PMU_CFG);
230 reg &= ~(RIVA_PMU_CFG_WARM_BOOT);
231 writel_relaxed(reg, base + RIVA_PMU_CFG);
232
233 /* Enable the cCPU clock */
234 reg = readl_relaxed(base + RIVA_PMU_OVRD_VAL);
235 reg |= RIVA_PMU_OVRD_VAL_CCPU_CLK;
236 writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL);
237
238 /* Take cCPU out of reset */
239 reg |= RIVA_PMU_OVRD_VAL_CCPU_RESET;
240 writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL);
Stephen Boyd86f2e652012-01-11 18:25:44 -0800241 clk_disable_unprepare(drv->xo);
Stephen Boyd322a9922011-09-20 01:05:54 -0700242
243 return 0;
244}
245
246static int pil_riva_shutdown(struct pil_desc *pil)
247{
248 struct riva_data *drv = dev_get_drvdata(pil->dev);
249 u32 reg;
Stephen Boyd86f2e652012-01-11 18:25:44 -0800250 int ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700251
Stephen Boyd86f2e652012-01-11 18:25:44 -0800252 ret = clk_prepare_enable(drv->xo);
253 if (ret)
254 return ret;
Stephen Boyd12332572011-12-06 16:00:51 -0800255 /* Put cCPU and cCPU clock into reset */
Stephen Boyd322a9922011-09-20 01:05:54 -0700256 reg = readl_relaxed(drv->base + RIVA_PMU_OVRD_VAL);
257 reg &= ~(RIVA_PMU_OVRD_VAL_CCPU_RESET | RIVA_PMU_OVRD_VAL_CCPU_CLK);
258 writel_relaxed(reg, drv->base + RIVA_PMU_OVRD_VAL);
Stephen Boyd12332572011-12-06 16:00:51 -0800259 reg = readl_relaxed(drv->base + RIVA_PMU_OVRD_EN);
260 reg |= RIVA_PMU_OVRD_EN_CCPU_RESET | RIVA_PMU_OVRD_EN_CCPU_CLK;
261 writel_relaxed(reg, drv->base + RIVA_PMU_OVRD_EN);
262 mb();
263
264 /* Assert reset to Riva */
265 writel_relaxed(1, RIVA_RESET);
266 mb();
267 usleep_range(1000, 2000);
268
269 /* Deassert reset to Riva */
270 writel_relaxed(0, RIVA_RESET);
271 mb();
Stephen Boyd322a9922011-09-20 01:05:54 -0700272
Stephen Boyd86f2e652012-01-11 18:25:44 -0800273 clk_disable_unprepare(drv->xo);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800274 pil_riva_remove_proxy_votes_now(pil->dev);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800275
Stephen Boyd322a9922011-09-20 01:05:54 -0700276 return 0;
277}
278
279static struct pil_reset_ops pil_riva_ops = {
280 .init_image = pil_riva_init_image,
281 .verify_blob = nop_verify_blob,
282 .auth_and_reset = pil_riva_reset,
283 .shutdown = pil_riva_shutdown,
284};
285
286static int pil_riva_init_image_trusted(struct pil_desc *pil,
287 const u8 *metadata, size_t size)
288{
289 return pas_init_image(PAS_RIVA, metadata, size);
290}
291
292static int pil_riva_reset_trusted(struct pil_desc *pil)
293{
Stephen Boyd86f2e652012-01-11 18:25:44 -0800294 struct riva_data *drv = dev_get_drvdata(pil->dev);
295 int ret;
296
297 ret = clk_prepare_enable(drv->xo);
298 if (ret)
299 return ret;
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800300 /* Proxy-vote for resources RIVA needs */
301 pil_riva_make_proxy_votes(pil->dev);
Stephen Boyd86f2e652012-01-11 18:25:44 -0800302 ret = pas_auth_and_reset(PAS_RIVA);
303 clk_disable_unprepare(drv->xo);
304 return ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700305}
306
307static int pil_riva_shutdown_trusted(struct pil_desc *pil)
308{
Stephen Boyd86f2e652012-01-11 18:25:44 -0800309 int ret;
310 struct riva_data *drv = dev_get_drvdata(pil->dev);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800311
Stephen Boyd86f2e652012-01-11 18:25:44 -0800312 ret = clk_prepare_enable(drv->xo);
313 if (ret)
314 return ret;
315 ret = pas_shutdown(PAS_RIVA);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800316 pil_riva_remove_proxy_votes_now(pil->dev);
Stephen Boyd86f2e652012-01-11 18:25:44 -0800317 clk_disable_unprepare(drv->xo);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800318
319 return ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700320}
321
322static struct pil_reset_ops pil_riva_ops_trusted = {
323 .init_image = pil_riva_init_image_trusted,
324 .verify_blob = nop_verify_blob,
325 .auth_and_reset = pil_riva_reset_trusted,
326 .shutdown = pil_riva_shutdown_trusted,
327};
328
329static int __devinit pil_riva_probe(struct platform_device *pdev)
330{
331 struct riva_data *drv;
332 struct resource *res;
333 struct pil_desc *desc;
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800334 int ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700335
336 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
337 if (!res)
338 return -EINVAL;
339
340 drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
341 if (!drv)
342 return -ENOMEM;
343 platform_set_drvdata(pdev, drv);
344
345 drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
346 if (!drv->base)
347 return -ENOMEM;
348
349 desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
350 if (!desc)
351 return -ENOMEM;
352
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800353 drv->pll_supply = regulator_get(&pdev->dev, "pll_vdd");
354 if (IS_ERR(drv->pll_supply)) {
355 dev_err(&pdev->dev, "failed to get pll supply\n");
356 return PTR_ERR(drv->pll_supply);
357 }
358 ret = regulator_set_voltage(drv->pll_supply, 1800000, 1800000);
359 if (ret) {
360 dev_err(&pdev->dev, "failed to set pll supply voltage\n");
361 goto err;
362 }
363
364 ret = regulator_set_optimum_mode(drv->pll_supply, 100000);
365 if (ret < 0) {
366 dev_err(&pdev->dev, "failed to set pll supply optimum mode\n");
367 goto err;
368 }
369
Stephen Boyd322a9922011-09-20 01:05:54 -0700370 desc->name = "wcnss";
371 desc->dev = &pdev->dev;
372
373 if (pas_supported(PAS_RIVA) > 0) {
374 desc->ops = &pil_riva_ops_trusted;
375 dev_info(&pdev->dev, "using secure boot\n");
376 } else {
377 desc->ops = &pil_riva_ops;
378 dev_info(&pdev->dev, "using non-secure boot\n");
379 }
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800380
Stephen Boyd86f2e652012-01-11 18:25:44 -0800381 drv->xo = clk_get(&pdev->dev, "cxo");
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800382 if (IS_ERR(drv->xo)) {
383 ret = PTR_ERR(drv->xo);
384 goto err;
385 }
386 INIT_DELAYED_WORK(&drv->work, pil_riva_remove_proxy_votes);
Matt Wagantall04b7cc72011-12-09 18:52:26 -0800387
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800388 ret = msm_pil_register(desc);
389 if (ret)
390 goto err_register;
391 return 0;
392err_register:
393 cancel_delayed_work_sync(&drv->work);
Stephen Boyd86f2e652012-01-11 18:25:44 -0800394 clk_put(drv->xo);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800395err:
396 regulator_put(drv->pll_supply);
397 return ret;
Stephen Boyd322a9922011-09-20 01:05:54 -0700398}
399
400static int __devexit pil_riva_remove(struct platform_device *pdev)
401{
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800402 struct riva_data *drv = platform_get_drvdata(pdev);
403 cancel_delayed_work_sync(&drv->work);
Stephen Boyd86f2e652012-01-11 18:25:44 -0800404 clk_put(drv->xo);
Stephen Boyd3bbdf6c2011-12-21 16:02:26 -0800405 regulator_put(drv->pll_supply);
Stephen Boyd322a9922011-09-20 01:05:54 -0700406 return 0;
407}
408
409static struct platform_driver pil_riva_driver = {
410 .probe = pil_riva_probe,
411 .remove = __devexit_p(pil_riva_remove),
412 .driver = {
413 .name = "pil_riva",
414 .owner = THIS_MODULE,
415 },
416};
417
418static int __init pil_riva_init(void)
419{
420 return platform_driver_register(&pil_riva_driver);
421}
422module_init(pil_riva_init);
423
424static void __exit pil_riva_exit(void)
425{
426 platform_driver_unregister(&pil_riva_driver);
427}
428module_exit(pil_riva_exit);
429
430MODULE_DESCRIPTION("Support for booting RIVA (WCNSS) processors");
431MODULE_LICENSE("GPL v2");