blob: f4536f769df4479af88e411f96557bdaf44edcb5 [file] [log] [blame]
Sravan Kumar Ambapuramb22cf4d2012-01-02 21:45:04 +05301/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -06002 *
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
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/io.h>
Maheshkumar Sivasubramanianc6c55032011-10-25 16:01:32 -060018#include <mach/msm_iomap.h>
19#include <mach/socinfo.h>
20#include <asm/mach-types.h>
21#include <asm/sizes.h>
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -060022#include "scm-boot.h"
23#include "idle.h"
24#include "pm-boot.h"
25
26static uint32_t *msm_pm_reset_vector;
27static uint32_t saved_vector[2];
28static void (*msm_pm_boot_before_pc)(unsigned int cpu, unsigned long entry);
29static void (*msm_pm_boot_after_pc)(unsigned int cpu);
30
31#ifdef CONFIG_MSM_SCM
32static int __init msm_pm_tz_boot_init(void)
33{
34 int flag = 0;
35 if (num_possible_cpus() == 1)
36 flag = SCM_FLAG_WARMBOOT_CPU0;
37 else if (num_possible_cpus() == 2)
38 flag = SCM_FLAG_WARMBOOT_CPU0 | SCM_FLAG_WARMBOOT_CPU1;
Joel King274621c2011-12-05 06:18:20 -080039 else if (num_possible_cpus() == 4)
40 flag = SCM_FLAG_WARMBOOT_CPU0 | SCM_FLAG_WARMBOOT_CPU1 |
41 SCM_FLAG_WARMBOOT_CPU2 | SCM_FLAG_WARMBOOT_CPU3;
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -060042 else
43 __WARN();
44
45 return scm_set_boot_addr((void *)virt_to_phys(msm_pm_boot_entry), flag);
46}
47
48static void msm_pm_config_tz_before_pc(unsigned int cpu,
49 unsigned long entry)
50{
51 msm_pm_write_boot_vector(cpu, entry);
52}
53#else
54static int __init msm_pm_tz_boot_init(void)
55{
56 return 0;
57};
58
59static inline void msm_pm_config_tz_before_pc(unsigned int cpu,
60 unsigned long entry) {}
61#endif
62
63static int __init msm_pm_boot_reset_vector_init(uint32_t *reset_vector)
64{
Maheshkumar Sivasubramanianc6c55032011-10-25 16:01:32 -060065 if (!reset_vector)
66 return -ENODEV;
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -060067 msm_pm_reset_vector = reset_vector;
68 mb();
69
70 return 0;
71}
72
73static void msm_pm_config_rst_vector_before_pc(unsigned int cpu,
74 unsigned long entry)
75{
76 saved_vector[0] = msm_pm_reset_vector[0];
77 saved_vector[1] = msm_pm_reset_vector[1];
78 msm_pm_reset_vector[0] = 0xE51FF004; /* ldr pc, 4 */
79 msm_pm_reset_vector[1] = entry;
80}
81
82static void msm_pm_config_rst_vector_after_pc(unsigned int cpu)
83{
84 msm_pm_reset_vector[0] = saved_vector[0];
85 msm_pm_reset_vector[1] = saved_vector[1];
86}
87
88void msm_pm_boot_config_before_pc(unsigned int cpu, unsigned long entry)
89{
90 if (msm_pm_boot_before_pc)
91 msm_pm_boot_before_pc(cpu, entry);
92}
93
94void msm_pm_boot_config_after_pc(unsigned int cpu)
95{
96 if (msm_pm_boot_after_pc)
97 msm_pm_boot_after_pc(cpu);
98}
Maheshkumar Sivasubramanianc6c55032011-10-25 16:01:32 -060099#define BOOT_REMAP_ENABLE BIT(0)
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -0600100
Maheshkumar Sivasubramanianc6c55032011-10-25 16:01:32 -0600101int __init msm_pm_boot_init(struct msm_pm_boot_platform_data *pdata)
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -0600102{
103 int ret = 0;
Murali Nalajala41786ab2012-03-06 10:47:32 +0530104 unsigned long entry;
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -0600105
Maheshkumar Sivasubramanianc6c55032011-10-25 16:01:32 -0600106 switch (pdata->mode) {
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -0600107 case MSM_PM_BOOT_CONFIG_TZ:
108 ret = msm_pm_tz_boot_init();
109 msm_pm_boot_before_pc = msm_pm_config_tz_before_pc;
110 msm_pm_boot_after_pc = NULL;
111 break;
Maheshkumar Sivasubramanianc6c55032011-10-25 16:01:32 -0600112 case MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS:
Maheshkumar Sivasubramanianc6c55032011-10-25 16:01:32 -0600113 pdata->v_addr = ioremap(pdata->p_addr, PAGE_SIZE);
114 /* Fall through */
115 case MSM_PM_BOOT_CONFIG_RESET_VECTOR_VIRT:
116
117 if (!pdata->v_addr)
118 return -ENODEV;
119
120 ret = msm_pm_boot_reset_vector_init(pdata->v_addr);
121 msm_pm_boot_before_pc
122 = msm_pm_config_rst_vector_before_pc;
123 msm_pm_boot_after_pc
124 = msm_pm_config_rst_vector_after_pc;
125 break;
126 case MSM_PM_BOOT_CONFIG_REMAP_BOOT_ADDR:
127 /*
128 * Set the boot remap address and enable remapping of
129 * reset vector
130 */
131 if (!pdata->p_addr || !pdata->v_addr)
132 return -ENODEV;
133
Maheshkumar Sivasubramanianc6c55032011-10-25 16:01:32 -0600134 ret = msm_pm_boot_reset_vector_init(__va(pdata->p_addr));
135
Murali Nalajala41786ab2012-03-06 10:47:32 +0530136 if (!cpu_is_msm8625()) {
137 __raw_writel((pdata->p_addr | BOOT_REMAP_ENABLE),
138 pdata->v_addr);
139
140 msm_pm_boot_before_pc
141 = msm_pm_config_rst_vector_before_pc;
142 msm_pm_boot_after_pc
143 = msm_pm_config_rst_vector_after_pc;
144 } else {
145 entry = virt_to_phys(msm_pm_boot_entry);
146
147 msm_pm_reset_vector[0] = 0xE51FF004; /* ldr pc, 4 */
148 msm_pm_reset_vector[1] = entry;
149
150 /* Here upper 16bits[16:31] used by CORE1
151 * lower 16bits[0:15] used by CORE0
152 */
153 entry = (pdata->p_addr) |
154 ((pdata->p_addr & 0xFFFF0000) >> 16);
155
156 /* write 'entry' to boot remapper register */
157 __raw_writel(entry, (pdata->v_addr +
158 MPA5_BOOT_REMAP_ADDR));
159
160 /* Enable boot remapper for C0 [bit:25th] */
161 __raw_writel(readl_relaxed(pdata->v_addr +
162 MPA5_CFG_CTL_REG) | BIT(25),
163 pdata->v_addr + MPA5_CFG_CTL_REG);
164
165 /* Enable boot remapper for C1 [bit:26th] */
166 __raw_writel(readl_relaxed(pdata->v_addr +
167 MPA5_CFG_CTL_REG) | BIT(26),
168 pdata->v_addr + MPA5_CFG_CTL_REG);
169
170 msm_pm_boot_before_pc = msm_pm_write_boot_vector;
171 }
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -0600172 break;
173 default:
174 __WARN();
175 }
176
177 return ret;
178}