diff options
author | Marc St-Jean <stjeanma@pmc-sierra.com> | 2007-06-14 17:54:47 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-07-10 12:33:02 -0400 |
commit | 35832e26f95ba14a6b6f0519441c5cb64cca6bf9 (patch) | |
tree | db3c05782a2140b19917344fb640070a655d75fd /arch/mips/pmc-sierra/msp71xx/msp_setup.c | |
parent | a4b156d47d204904fa104c3e585b4c67b89195f3 (diff) |
[MIPS] PMC MSP71xx core platform
Patch to add core platform support for the PMC-Sierra MSP71xx devices.
Signed-off-by: Marc St-Jean <Marc_St-Jean@pmc-sierra.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/pmc-sierra/msp71xx/msp_setup.c')
-rw-r--r-- | arch/mips/pmc-sierra/msp71xx/msp_setup.c | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/arch/mips/pmc-sierra/msp71xx/msp_setup.c b/arch/mips/pmc-sierra/msp71xx/msp_setup.c new file mode 100644 index 00000000000..8f69b789be9 --- /dev/null +++ b/arch/mips/pmc-sierra/msp71xx/msp_setup.c | |||
@@ -0,0 +1,256 @@ | |||
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 | } | ||