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