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