blob: 6becc619cb1d8a97e7fdff6b81999dde7acdb550 [file] [log] [blame]
Maheshkumar Sivasubramanian8ccc16e2011-10-25 15:59:57 -06001/* 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
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include "scm-boot.h"
19#include "idle.h"
20#include "pm-boot.h"
21
22static uint32_t *msm_pm_reset_vector;
23static uint32_t saved_vector[2];
24static void (*msm_pm_boot_before_pc)(unsigned int cpu, unsigned long entry);
25static void (*msm_pm_boot_after_pc)(unsigned int cpu);
26
27#ifdef CONFIG_MSM_SCM
28static int __init msm_pm_tz_boot_init(void)
29{
30 int flag = 0;
31 if (num_possible_cpus() == 1)
32 flag = SCM_FLAG_WARMBOOT_CPU0;
33 else if (num_possible_cpus() == 2)
34 flag = SCM_FLAG_WARMBOOT_CPU0 | SCM_FLAG_WARMBOOT_CPU1;
35 else
36 __WARN();
37
38 return scm_set_boot_addr((void *)virt_to_phys(msm_pm_boot_entry), flag);
39}
40
41static void msm_pm_config_tz_before_pc(unsigned int cpu,
42 unsigned long entry)
43{
44 msm_pm_write_boot_vector(cpu, entry);
45}
46#else
47static int __init msm_pm_tz_boot_init(void)
48{
49 return 0;
50};
51
52static inline void msm_pm_config_tz_before_pc(unsigned int cpu,
53 unsigned long entry) {}
54#endif
55
56static int __init msm_pm_boot_reset_vector_init(uint32_t *reset_vector)
57{
58 WARN_ON(!reset_vector);
59 msm_pm_reset_vector = reset_vector;
60 mb();
61
62 return 0;
63}
64
65static void msm_pm_config_rst_vector_before_pc(unsigned int cpu,
66 unsigned long entry)
67{
68 saved_vector[0] = msm_pm_reset_vector[0];
69 saved_vector[1] = msm_pm_reset_vector[1];
70 msm_pm_reset_vector[0] = 0xE51FF004; /* ldr pc, 4 */
71 msm_pm_reset_vector[1] = entry;
72}
73
74static void msm_pm_config_rst_vector_after_pc(unsigned int cpu)
75{
76 msm_pm_reset_vector[0] = saved_vector[0];
77 msm_pm_reset_vector[1] = saved_vector[1];
78}
79
80void msm_pm_boot_config_before_pc(unsigned int cpu, unsigned long entry)
81{
82 if (msm_pm_boot_before_pc)
83 msm_pm_boot_before_pc(cpu, entry);
84}
85
86void msm_pm_boot_config_after_pc(unsigned int cpu)
87{
88 if (msm_pm_boot_after_pc)
89 msm_pm_boot_after_pc(cpu);
90}
91
92int __init msm_pm_boot_init(int tz_available, uint32_t* address)
93{
94 int ret = 0;
95
96 switch (tz_available) {
97 case MSM_PM_BOOT_CONFIG_TZ:
98 ret = msm_pm_tz_boot_init();
99 msm_pm_boot_before_pc = msm_pm_config_tz_before_pc;
100 msm_pm_boot_after_pc = NULL;
101 break;
102 case MSM_PM_BOOT_CONFIG_RESET_VECTOR:
103 ret = msm_pm_boot_reset_vector_init(address);
104 msm_pm_boot_before_pc
105 = msm_pm_config_rst_vector_before_pc;
106 msm_pm_boot_after_pc
107 = msm_pm_config_rst_vector_after_pc;
108 break;
109 default:
110 __WARN();
111 }
112
113 return ret;
114}