Commit | Line | Data |
---|---|---|
35832e26 MSJ |
1 | /* |
2 | * The generic setup file for PMC-Sierra MSP processors | |
3 | * | |
4 | * Copyright 2005-2007 PMC-Sierra, Inc, | |
5 | * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify it | |
8 | * under the terms of the GNU General Public License as published by the | |
9 | * Free Software Foundation; either version 2 of the License, or (at your | |
10 | * option) any later version. | |
11 | */ | |
12 | ||
13 | #include <asm/bootinfo.h> | |
14 | #include <asm/cacheflush.h> | |
15 | #include <asm/r4kcache.h> | |
16 | #include <asm/reboot.h> | |
17 | #include <asm/time.h> | |
18 | ||
19 | #include <msp_prom.h> | |
20 | #include <msp_regs.h> | |
21 | ||
22 | #if defined(CONFIG_PMC_MSP7120_GW) | |
23 | #include <msp_regops.h> | |
24 | #include <msp_gpio.h> | |
25 | #define MSP_BOARD_RESET_GPIO 9 | |
26 | #endif | |
27 | ||
28 | extern void msp_timer_init(void); | |
29 | extern void msp_serial_setup(void); | |
30 | extern void pmctwiled_setup(void); | |
31 | ||
32 | #if defined(CONFIG_PMC_MSP7120_EVAL) || \ | |
33 | defined(CONFIG_PMC_MSP7120_GW) || \ | |
34 | defined(CONFIG_PMC_MSP7120_FPGA) | |
35 | /* | |
36 | * Performs the reset for MSP7120-based boards | |
37 | */ | |
38 | void msp7120_reset(void) | |
39 | { | |
40 | void *start, *end, *iptr; | |
41 | register int i; | |
42 | ||
43 | /* Diasble all interrupts */ | |
44 | local_irq_disable(); | |
45 | #ifdef CONFIG_SYS_SUPPORTS_MULTITHREADING | |
46 | dvpe(); | |
47 | #endif | |
48 | ||
49 | /* Cache the reset code of this function */ | |
50 | __asm__ __volatile__ ( | |
51 | " .set push \n" | |
52 | " .set mips3 \n" | |
53 | " la %0,startpoint \n" | |
54 | " la %1,endpoint \n" | |
55 | " .set pop \n" | |
56 | : "=r" (start), "=r" (end) | |
57 | : | |
58 | ); | |
59 | ||
60 | for (iptr = (void *)((unsigned int)start & ~(L1_CACHE_BYTES - 1)); | |
61 | iptr < end; iptr += L1_CACHE_BYTES) | |
62 | cache_op(Fill, iptr); | |
63 | ||
64 | __asm__ __volatile__ ( | |
65 | "startpoint: \n" | |
66 | ); | |
67 | ||
68 | /* Put the DDRC into self-refresh mode */ | |
69 | DDRC_INDIRECT_WRITE(DDRC_CTL(10), 0xb, 1 << 16); | |
70 | ||
71 | /* | |
72 | * IMPORTANT! | |
73 | * DO NOT do anything from here on out that might even | |
74 | * think about fetching from RAM - i.e., don't call any | |
75 | * non-inlined functions, and be VERY sure that any inline | |
76 | * functions you do call do NOT access any sort of RAM | |
77 | * anywhere! | |
78 | */ | |
79 | ||
80 | /* Wait a bit for the DDRC to settle */ | |
81 | for (i = 0; i < 100000000; i++); | |
82 | ||
83 | #if defined(CONFIG_PMC_MSP7120_GW) | |
84 | /* | |
85 | * Set GPIO 9 HI, (tied to board reset logic) | |
86 | * GPIO 9 is the 4th GPIO of register 3 | |
87 | * | |
88 | * NOTE: We cannot use the higher-level msp_gpio_mode()/out() | |
89 | * as GPIO char driver may not be enabled and it would look up | |
90 | * data inRAM! | |
91 | */ | |
92 | set_value_reg32(GPIO_CFG3_REG, | |
93 | basic_mode_mask(MSP_BOARD_RESET_GPIO), | |
94 | basic_mode(MSP_GPIO_OUTPUT, MSP_BOARD_RESET_GPIO)); | |
95 | set_reg32(GPIO_DATA3_REG, | |
96 | basic_data_mask(MSP_BOARD_RESET_GPIO)); | |
97 | ||
98 | /* | |
99 | * In case GPIO9 doesn't reset the board (jumper configurable!) | |
100 | * fallback to device reset below. | |
101 | */ | |
102 | #endif | |
103 | /* Set bit 1 of the MSP7120 reset register */ | |
104 | *RST_SET_REG = 0x00000001; | |
105 | ||
106 | __asm__ __volatile__ ( | |
107 | "endpoint: \n" | |
108 | ); | |
109 | } | |
110 | #endif | |
111 | ||
112 | void msp_restart(char *command) | |
113 | { | |
114 | printk(KERN_WARNING "Now rebooting .......\n"); | |
115 | ||
116 | #if defined(CONFIG_PMC_MSP7120_EVAL) || \ | |
117 | defined(CONFIG_PMC_MSP7120_GW) || \ | |
118 | defined(CONFIG_PMC_MSP7120_FPGA) | |
119 | msp7120_reset(); | |
120 | #else | |
121 | /* No chip-specific reset code, just jump to the ROM reset vector */ | |
122 | set_c0_status(ST0_BEV | ST0_ERL); | |
123 | change_c0_config(CONF_CM_CMASK, CONF_CM_UNCACHED); | |
124 | flush_cache_all(); | |
125 | write_c0_wired(0); | |
126 | ||
127 | __asm__ __volatile__("jr\t%0"::"r"(0xbfc00000)); | |
128 | #endif | |
129 | } | |
130 | ||
131 | void msp_halt(void) | |
132 | { | |
133 | printk(KERN_WARNING "\n** You can safely turn off the power\n"); | |
134 | while (1) | |
135 | /* If possible call official function to get CPU WARs */ | |
136 | if (cpu_wait) | |
137 | (*cpu_wait)(); | |
138 | else | |
139 | __asm__(".set\tmips3\n\t" "wait\n\t" ".set\tmips0"); | |
140 | } | |
141 | ||
142 | void msp_power_off(void) | |
143 | { | |
144 | msp_halt(); | |
145 | } | |
146 | ||
147 | void __init plat_mem_setup(void) | |
148 | { | |
149 | _machine_restart = msp_restart; | |
150 | _machine_halt = msp_halt; | |
151 | pm_power_off = msp_power_off; | |
152 | ||
153 | board_time_init = msp_timer_init; | |
154 | } | |
155 | ||
156 | void __init prom_init(void) | |
157 | { | |
158 | unsigned long family; | |
159 | unsigned long revision; | |
160 | ||
161 | prom_argc = fw_arg0; | |
162 | prom_argv = (char **)fw_arg1; | |
163 | prom_envp = (char **)fw_arg2; | |
164 | ||
165 | /* | |
166 | * Someday we can use this with PMON2000 to get a | |
167 | * platform call prom routines for output etc. without | |
168 | * having to use grody hacks. For now it's unused. | |
169 | * | |
170 | * struct callvectors *cv = (struct callvectors *) fw_arg3; | |
171 | */ | |
172 | family = identify_family(); | |
173 | revision = identify_revision(); | |
174 | ||
175 | switch (family) { | |
176 | case FAMILY_FPGA: | |
177 | if (FPGA_IS_MSP4200(revision)) { | |
178 | /* Old-style revision ID */ | |
179 | mips_machgroup = MACH_GROUP_MSP; | |
180 | mips_machtype = MACH_MSP4200_FPGA; | |
181 | } else { | |
182 | mips_machgroup = MACH_GROUP_MSP; | |
183 | mips_machtype = MACH_MSP_OTHER; | |
184 | } | |
185 | break; | |
186 | ||
187 | case FAMILY_MSP4200: | |
188 | mips_machgroup = MACH_GROUP_MSP; | |
189 | #if defined(CONFIG_PMC_MSP4200_EVAL) | |
190 | mips_machtype = MACH_MSP4200_EVAL; | |
191 | #elif defined(CONFIG_PMC_MSP4200_GW) | |
192 | mips_machtype = MACH_MSP4200_GW; | |
193 | #else | |
194 | mips_machtype = MACH_MSP_OTHER; | |
195 | #endif | |
196 | break; | |
197 | ||
198 | case FAMILY_MSP4200_FPGA: | |
199 | mips_machgroup = MACH_GROUP_MSP; | |
200 | mips_machtype = MACH_MSP4200_FPGA; | |
201 | break; | |
202 | ||
203 | case FAMILY_MSP7100: | |
204 | mips_machgroup = MACH_GROUP_MSP; | |
205 | #if defined(CONFIG_PMC_MSP7120_EVAL) | |
206 | mips_machtype = MACH_MSP7120_EVAL; | |
207 | #elif defined(CONFIG_PMC_MSP7120_GW) | |
208 | mips_machtype = MACH_MSP7120_GW; | |
209 | #else | |
210 | mips_machtype = MACH_MSP_OTHER; | |
211 | #endif | |
212 | break; | |
213 | ||
214 | case FAMILY_MSP7100_FPGA: | |
215 | mips_machgroup = MACH_GROUP_MSP; | |
216 | mips_machtype = MACH_MSP7120_FPGA; | |
217 | break; | |
218 | ||
219 | default: | |
220 | /* we don't recognize the machine */ | |
221 | mips_machgroup = MACH_GROUP_UNKNOWN; | |
222 | mips_machtype = MACH_UNKNOWN; | |
223 | break; | |
224 | } | |
225 | ||
226 | /* make sure we have the right initialization routine - sanity */ | |
227 | if (mips_machgroup != MACH_GROUP_MSP) { | |
228 | ppfinit("Unknown machine group in a " | |
229 | "MSP initialization routine\n"); | |
230 | panic("***Bogosity factor five***, exiting\n"); | |
231 | } | |
232 | ||
233 | prom_init_cmdline(); | |
234 | ||
235 | prom_meminit(); | |
236 | ||
237 | /* | |
238 | * Sub-system setup follows. | |
239 | * Setup functions can either be called here or using the | |
240 | * subsys_initcall mechanism (i.e. see msp_pci_setup). The | |
241 | * order in which they are called can be changed by using the | |
242 | * link order in arch/mips/pmc-sierra/msp71xx/Makefile. | |
243 | * | |
244 | * NOTE: Please keep sub-system specific initialization code | |
245 | * in separate specific files. | |
246 | */ | |
247 | msp_serial_setup(); | |
248 | ||
249 | #ifdef CONFIG_PMCTWILED | |
250 | /* | |
251 | * Setup LED states before the subsys_initcall loads other | |
252 | * dependant drivers/modules. | |
253 | */ | |
254 | pmctwiled_setup(); | |
255 | #endif | |
256 | } |