diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/platforms/hdpu.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/ppc/platforms/hdpu.c')
-rw-r--r-- | arch/ppc/platforms/hdpu.c | 1062 |
1 files changed, 1062 insertions, 0 deletions
diff --git a/arch/ppc/platforms/hdpu.c b/arch/ppc/platforms/hdpu.c new file mode 100644 index 000000000000..b659d7b3d747 --- /dev/null +++ b/arch/ppc/platforms/hdpu.c | |||
@@ -0,0 +1,1062 @@ | |||
1 | |||
2 | /* | ||
3 | * arch/ppc/platforms/hdpu_setup.c | ||
4 | * | ||
5 | * Board setup routines for the Sky Computers HDPU Compute Blade. | ||
6 | * | ||
7 | * Written by Brian Waite <waite@skycomputers.com> | ||
8 | * | ||
9 | * Based on code done by - Mark A. Greer <mgreer@mvista.com> | ||
10 | * Rabeeh Khoury - rabeeh@galileo.co.il | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/config.h> | ||
19 | |||
20 | #include <linux/pci.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/irq.h> | ||
23 | #include <linux/ide.h> | ||
24 | #include <linux/seq_file.h> | ||
25 | |||
26 | #include <linux/initrd.h> | ||
27 | #include <linux/root_dev.h> | ||
28 | #include <linux/smp.h> | ||
29 | |||
30 | #include <asm/time.h> | ||
31 | #include <asm/machdep.h> | ||
32 | #include <asm/todc.h> | ||
33 | #include <asm/mv64x60.h> | ||
34 | #include <asm/ppcboot.h> | ||
35 | #include <platforms/hdpu.h> | ||
36 | #include <linux/mv643xx.h> | ||
37 | #include <linux/hdpu_features.h> | ||
38 | #include <linux/device.h> | ||
39 | #include <linux/mtd/physmap.h> | ||
40 | |||
41 | #define BOARD_VENDOR "Sky Computers" | ||
42 | #define BOARD_MACHINE "HDPU-CB-A" | ||
43 | |||
44 | bd_t ppcboot_bd; | ||
45 | int ppcboot_bd_valid = 0; | ||
46 | |||
47 | static mv64x60_handle_t bh; | ||
48 | |||
49 | extern char cmd_line[]; | ||
50 | |||
51 | unsigned long hdpu_find_end_of_memory(void); | ||
52 | void hdpu_mpsc_progress(char *s, unsigned short hex); | ||
53 | void hdpu_heartbeat(void); | ||
54 | |||
55 | static void parse_bootinfo(unsigned long r3, | ||
56 | unsigned long r4, unsigned long r5, | ||
57 | unsigned long r6, unsigned long r7); | ||
58 | static void hdpu_set_l1pe(void); | ||
59 | static void hdpu_cpustate_set(unsigned char new_state); | ||
60 | #ifdef CONFIG_SMP | ||
61 | static spinlock_t timebase_lock = SPIN_LOCK_UNLOCKED; | ||
62 | static unsigned int timebase_upper = 0, timebase_lower = 0; | ||
63 | extern int smp_tb_synchronized; | ||
64 | |||
65 | void __devinit hdpu_tben_give(void); | ||
66 | void __devinit hdpu_tben_take(void); | ||
67 | #endif | ||
68 | |||
69 | static int __init | ||
70 | hdpu_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) | ||
71 | { | ||
72 | struct pci_controller *hose = pci_bus_to_hose(dev->bus->number); | ||
73 | |||
74 | if (hose->index == 0) { | ||
75 | static char pci_irq_table[][4] = { | ||
76 | {HDPU_PCI_0_IRQ, 0, 0, 0}, | ||
77 | {HDPU_PCI_0_IRQ, 0, 0, 0}, | ||
78 | }; | ||
79 | |||
80 | const long min_idsel = 1, max_idsel = 2, irqs_per_slot = 4; | ||
81 | return PCI_IRQ_TABLE_LOOKUP; | ||
82 | } else { | ||
83 | static char pci_irq_table[][4] = { | ||
84 | {HDPU_PCI_1_IRQ, 0, 0, 0}, | ||
85 | }; | ||
86 | |||
87 | const long min_idsel = 1, max_idsel = 1, irqs_per_slot = 4; | ||
88 | return PCI_IRQ_TABLE_LOOKUP; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | static void __init hdpu_intr_setup(void) | ||
93 | { | ||
94 | mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, | ||
95 | (1 | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | | ||
96 | (1 << 6) | (1 << 7) | (1 << 12) | (1 << 16) | | ||
97 | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21) | | ||
98 | (1 << 22) | (1 << 23) | (1 << 24) | (1 << 25) | | ||
99 | (1 << 26) | (1 << 27) | (1 << 28) | (1 << 29))); | ||
100 | |||
101 | /* XXXX Erranum FEr PCI-#8 */ | ||
102 | mv64x60_clr_bits(&bh, MV64x60_PCI0_CMD, (1 << 5) | (1 << 9)); | ||
103 | mv64x60_clr_bits(&bh, MV64x60_PCI1_CMD, (1 << 5) | (1 << 9)); | ||
104 | |||
105 | /* | ||
106 | * Dismiss and then enable interrupt on GPP interrupt cause | ||
107 | * for CPU #0 | ||
108 | */ | ||
109 | mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~((1 << 8) | (1 << 13))); | ||
110 | mv64x60_set_bits(&bh, MV64x60_GPP_INTR_MASK, (1 << 8) | (1 << 13)); | ||
111 | |||
112 | /* | ||
113 | * Dismiss and then enable interrupt on CPU #0 high cause reg | ||
114 | * BIT25 summarizes GPP interrupts 8-15 | ||
115 | */ | ||
116 | mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1 << 25)); | ||
117 | } | ||
118 | |||
119 | static void __init hdpu_setup_peripherals(void) | ||
120 | { | ||
121 | unsigned int val; | ||
122 | |||
123 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
124 | HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0); | ||
125 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
126 | |||
127 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, | ||
128 | HDPU_TBEN_BASE, HDPU_TBEN_SIZE, 0); | ||
129 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN); | ||
130 | |||
131 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, | ||
132 | HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE, 0); | ||
133 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN); | ||
134 | |||
135 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
136 | HDPU_INTERNAL_SRAM_BASE, | ||
137 | HDPU_INTERNAL_SRAM_SIZE, 0); | ||
138 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
139 | |||
140 | bh.ci->disable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN); | ||
141 | mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN, 0, 0, 0); | ||
142 | |||
143 | mv64x60_clr_bits(&bh, MV64x60_PCI0_PCI_DECODE_CNTL, (1 << 3)); | ||
144 | mv64x60_clr_bits(&bh, MV64x60_PCI1_PCI_DECODE_CNTL, (1 << 3)); | ||
145 | mv64x60_clr_bits(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, | ||
146 | ((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24))); | ||
147 | |||
148 | /* Enable pipelining */ | ||
149 | mv64x60_set_bits(&bh, MV64x60_CPU_CONFIG, (1 << 13)); | ||
150 | /* Enable Snoop Pipelineing */ | ||
151 | mv64x60_set_bits(&bh, MV64360_D_UNIT_CONTROL_HIGH, (1 << 24)); | ||
152 | |||
153 | /* | ||
154 | * Change DRAM read buffer assignment. | ||
155 | * Assign read buffer 0 dedicated only for CPU, | ||
156 | * and the rest read buffer 1. | ||
157 | */ | ||
158 | val = mv64x60_read(&bh, MV64360_SDRAM_CONFIG); | ||
159 | val = val & 0x03ffffff; | ||
160 | val = val | 0xf8000000; | ||
161 | mv64x60_write(&bh, MV64360_SDRAM_CONFIG, val); | ||
162 | |||
163 | /* | ||
164 | * Configure internal SRAM - | ||
165 | * Cache coherent write back, if CONFIG_MV64360_SRAM_CACHE_COHERENT set | ||
166 | * Parity enabled. | ||
167 | * Parity error propagation | ||
168 | * Arbitration not parked for CPU only | ||
169 | * Other bits are reserved. | ||
170 | */ | ||
171 | #ifdef CONFIG_MV64360_SRAM_CACHE_COHERENT | ||
172 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b2); | ||
173 | #else | ||
174 | mv64x60_write(&bh, MV64360_SRAM_CONFIG, 0x001600b0); | ||
175 | #endif | ||
176 | |||
177 | hdpu_intr_setup(); | ||
178 | } | ||
179 | |||
180 | static void __init hdpu_setup_bridge(void) | ||
181 | { | ||
182 | struct mv64x60_setup_info si; | ||
183 | int i; | ||
184 | |||
185 | memset(&si, 0, sizeof(si)); | ||
186 | |||
187 | si.phys_reg_base = HDPU_BRIDGE_REG_BASE; | ||
188 | si.pci_0.enable_bus = 1; | ||
189 | si.pci_0.pci_io.cpu_base = HDPU_PCI0_IO_START_PROC_ADDR; | ||
190 | si.pci_0.pci_io.pci_base_hi = 0; | ||
191 | si.pci_0.pci_io.pci_base_lo = HDPU_PCI0_IO_START_PCI_ADDR; | ||
192 | si.pci_0.pci_io.size = HDPU_PCI0_IO_SIZE; | ||
193 | si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
194 | si.pci_0.pci_mem[0].cpu_base = HDPU_PCI0_MEM_START_PROC_ADDR; | ||
195 | si.pci_0.pci_mem[0].pci_base_hi = HDPU_PCI0_MEM_START_PCI_HI_ADDR; | ||
196 | si.pci_0.pci_mem[0].pci_base_lo = HDPU_PCI0_MEM_START_PCI_LO_ADDR; | ||
197 | si.pci_0.pci_mem[0].size = HDPU_PCI0_MEM_SIZE; | ||
198 | si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
199 | si.pci_0.pci_cmd_bits = 0; | ||
200 | si.pci_0.latency_timer = 0x80; | ||
201 | |||
202 | si.pci_1.enable_bus = 1; | ||
203 | si.pci_1.pci_io.cpu_base = HDPU_PCI1_IO_START_PROC_ADDR; | ||
204 | si.pci_1.pci_io.pci_base_hi = 0; | ||
205 | si.pci_1.pci_io.pci_base_lo = HDPU_PCI1_IO_START_PCI_ADDR; | ||
206 | si.pci_1.pci_io.size = HDPU_PCI1_IO_SIZE; | ||
207 | si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
208 | si.pci_1.pci_mem[0].cpu_base = HDPU_PCI1_MEM_START_PROC_ADDR; | ||
209 | si.pci_1.pci_mem[0].pci_base_hi = HDPU_PCI1_MEM_START_PCI_HI_ADDR; | ||
210 | si.pci_1.pci_mem[0].pci_base_lo = HDPU_PCI1_MEM_START_PCI_LO_ADDR; | ||
211 | si.pci_1.pci_mem[0].size = HDPU_PCI1_MEM_SIZE; | ||
212 | si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE; | ||
213 | si.pci_1.pci_cmd_bits = 0; | ||
214 | si.pci_1.latency_timer = 0x80; | ||
215 | |||
216 | for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) { | ||
217 | #if defined(CONFIG_NOT_COHERENT_CACHE) | ||
218 | si.cpu_prot_options[i] = 0; | ||
219 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE; | ||
220 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE; | ||
221 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE; | ||
222 | |||
223 | si.pci_1.acc_cntl_options[i] = | ||
224 | MV64360_PCI_ACC_CNTL_SNOOP_NONE | | ||
225 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
226 | MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | ||
227 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
228 | |||
229 | si.pci_0.acc_cntl_options[i] = | ||
230 | MV64360_PCI_ACC_CNTL_SNOOP_NONE | | ||
231 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
232 | MV64360_PCI_ACC_CNTL_MBURST_128_BYTES | | ||
233 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
234 | |||
235 | #else | ||
236 | si.cpu_prot_options[i] = 0; | ||
237 | si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB; /* errata */ | ||
238 | si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB; /* errata */ | ||
239 | si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB; /* errata */ | ||
240 | |||
241 | si.pci_0.acc_cntl_options[i] = | ||
242 | MV64360_PCI_ACC_CNTL_SNOOP_WB | | ||
243 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
244 | MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | ||
245 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
246 | |||
247 | si.pci_1.acc_cntl_options[i] = | ||
248 | MV64360_PCI_ACC_CNTL_SNOOP_WB | | ||
249 | MV64360_PCI_ACC_CNTL_SWAP_NONE | | ||
250 | MV64360_PCI_ACC_CNTL_MBURST_32_BYTES | | ||
251 | MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
252 | #endif | ||
253 | } | ||
254 | |||
255 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_PCI); | ||
256 | |||
257 | /* Lookup PCI host bridges */ | ||
258 | mv64x60_init(&bh, &si); | ||
259 | pci_dram_offset = 0; /* System mem at same addr on PCI & cpu bus */ | ||
260 | ppc_md.pci_swizzle = common_swizzle; | ||
261 | ppc_md.pci_map_irq = hdpu_map_irq; | ||
262 | |||
263 | mv64x60_set_bus(&bh, 0, 0); | ||
264 | bh.hose_a->first_busno = 0; | ||
265 | bh.hose_a->last_busno = 0xff; | ||
266 | bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0); | ||
267 | |||
268 | bh.hose_b->first_busno = bh.hose_a->last_busno + 1; | ||
269 | mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno); | ||
270 | bh.hose_b->last_busno = 0xff; | ||
271 | bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b, | ||
272 | bh.hose_b->first_busno); | ||
273 | |||
274 | ppc_md.pci_exclude_device = mv64x60_pci_exclude_device; | ||
275 | |||
276 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_INIT_REG); | ||
277 | /* | ||
278 | * Enabling of PCI internal-vs-external arbitration | ||
279 | * is a platform- and errata-dependent decision. | ||
280 | */ | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | #if defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
285 | static void __init hdpu_early_serial_map(void) | ||
286 | { | ||
287 | #ifdef CONFIG_KGDB | ||
288 | static char first_time = 1; | ||
289 | |||
290 | #if defined(CONFIG_KGDB_TTYS0) | ||
291 | #define KGDB_PORT 0 | ||
292 | #elif defined(CONFIG_KGDB_TTYS1) | ||
293 | #define KGDB_PORT 1 | ||
294 | #else | ||
295 | #error "Invalid kgdb_tty port" | ||
296 | #endif | ||
297 | |||
298 | if (first_time) { | ||
299 | gt_early_mpsc_init(KGDB_PORT, | ||
300 | B9600 | CS8 | CREAD | HUPCL | CLOCAL); | ||
301 | first_time = 0; | ||
302 | } | ||
303 | |||
304 | return; | ||
305 | #endif | ||
306 | } | ||
307 | #endif | ||
308 | |||
309 | static void hdpu_init2(void) | ||
310 | { | ||
311 | return; | ||
312 | } | ||
313 | |||
314 | #if defined(CONFIG_MV643XX_ETH) | ||
315 | static void __init hdpu_fixup_eth_pdata(struct platform_device *pd) | ||
316 | { | ||
317 | |||
318 | struct mv643xx_eth_platform_data *eth_pd; | ||
319 | eth_pd = pd->dev.platform_data; | ||
320 | |||
321 | eth_pd->port_serial_control = | ||
322 | mv64x60_read(&bh, MV643XX_ETH_PORT_SERIAL_CONTROL_REG(pd->id) & ~1); | ||
323 | |||
324 | eth_pd->force_phy_addr = 1; | ||
325 | eth_pd->phy_addr = pd->id; | ||
326 | eth_pd->tx_queue_size = 400; | ||
327 | eth_pd->rx_queue_size = 800; | ||
328 | } | ||
329 | #endif | ||
330 | |||
331 | static void __init hdpu_fixup_mpsc_pdata(struct platform_device *pd) | ||
332 | { | ||
333 | |||
334 | struct mpsc_pdata *pdata; | ||
335 | |||
336 | pdata = (struct mpsc_pdata *)pd->dev.platform_data; | ||
337 | |||
338 | pdata->max_idle = 40; | ||
339 | if (ppcboot_bd_valid) | ||
340 | pdata->default_baud = ppcboot_bd.bi_baudrate; | ||
341 | else | ||
342 | pdata->default_baud = HDPU_DEFAULT_BAUD; | ||
343 | pdata->brg_clk_src = HDPU_MPSC_CLK_SRC; | ||
344 | pdata->brg_clk_freq = HDPU_MPSC_CLK_FREQ; | ||
345 | } | ||
346 | |||
347 | #if defined(CONFIG_HDPU_FEATURES) | ||
348 | static void __init hdpu_fixup_cpustate_pdata(struct platform_device *pd) | ||
349 | { | ||
350 | struct platform_device *pds[1]; | ||
351 | pds[0] = pd; | ||
352 | mv64x60_pd_fixup(&bh, pds, 1); | ||
353 | } | ||
354 | #endif | ||
355 | |||
356 | static int __init hdpu_platform_notify(struct device *dev) | ||
357 | { | ||
358 | static struct { | ||
359 | char *bus_id; | ||
360 | void ((*rtn) (struct platform_device * pdev)); | ||
361 | } dev_map[] = { | ||
362 | { | ||
363 | MPSC_CTLR_NAME ".0", hdpu_fixup_mpsc_pdata}, | ||
364 | #if defined(CONFIG_MV643XX_ETH) | ||
365 | { | ||
366 | MV643XX_ETH_NAME ".0", hdpu_fixup_eth_pdata}, | ||
367 | #endif | ||
368 | #if defined(CONFIG_HDPU_FEATURES) | ||
369 | { | ||
370 | HDPU_CPUSTATE_NAME ".0", hdpu_fixup_cpustate_pdata}, | ||
371 | #endif | ||
372 | }; | ||
373 | struct platform_device *pdev; | ||
374 | int i; | ||
375 | |||
376 | if (dev && dev->bus_id) | ||
377 | for (i = 0; i < ARRAY_SIZE(dev_map); i++) | ||
378 | if (!strncmp(dev->bus_id, dev_map[i].bus_id, | ||
379 | BUS_ID_SIZE)) { | ||
380 | |||
381 | pdev = container_of(dev, | ||
382 | struct platform_device, | ||
383 | dev); | ||
384 | dev_map[i].rtn(pdev); | ||
385 | } | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static void __init hdpu_setup_arch(void) | ||
391 | { | ||
392 | if (ppc_md.progress) | ||
393 | ppc_md.progress("hdpu_setup_arch: enter", 0); | ||
394 | #ifdef CONFIG_BLK_DEV_INITRD | ||
395 | if (initrd_start) | ||
396 | ROOT_DEV = Root_RAM0; | ||
397 | else | ||
398 | #endif | ||
399 | #ifdef CONFIG_ROOT_NFS | ||
400 | ROOT_DEV = Root_NFS; | ||
401 | #else | ||
402 | ROOT_DEV = Root_SDA2; | ||
403 | #endif | ||
404 | |||
405 | ppc_md.heartbeat = hdpu_heartbeat; | ||
406 | |||
407 | ppc_md.heartbeat_reset = HZ; | ||
408 | ppc_md.heartbeat_count = 1; | ||
409 | |||
410 | if (ppc_md.progress) | ||
411 | ppc_md.progress("hdpu_setup_arch: Enabling L2 cache", 0); | ||
412 | |||
413 | /* Enable L1 Parity Bits */ | ||
414 | hdpu_set_l1pe(); | ||
415 | |||
416 | /* Enable L2 and L3 caches (if 745x) */ | ||
417 | _set_L2CR(0x80080000); | ||
418 | |||
419 | if (ppc_md.progress) | ||
420 | ppc_md.progress("hdpu_setup_arch: enter", 0); | ||
421 | |||
422 | hdpu_setup_bridge(); | ||
423 | |||
424 | hdpu_setup_peripherals(); | ||
425 | |||
426 | #ifdef CONFIG_SERIAL_MPSC_CONSOLE | ||
427 | hdpu_early_serial_map(); | ||
428 | #endif | ||
429 | |||
430 | printk("SKY HDPU Compute Blade \n"); | ||
431 | |||
432 | if (ppc_md.progress) | ||
433 | ppc_md.progress("hdpu_setup_arch: exit", 0); | ||
434 | |||
435 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_OK); | ||
436 | return; | ||
437 | } | ||
438 | static void __init hdpu_init_irq(void) | ||
439 | { | ||
440 | mv64360_init_irq(); | ||
441 | } | ||
442 | |||
443 | static void __init hdpu_set_l1pe() | ||
444 | { | ||
445 | unsigned long ictrl; | ||
446 | asm volatile ("mfspr %0, 1011":"=r" (ictrl):); | ||
447 | ictrl |= ICTRL_EICE | ICTRL_EDC | ICTRL_EICP; | ||
448 | asm volatile ("mtspr 1011, %0"::"r" (ictrl)); | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * Set BAT 1 to map 0xf1000000 to end of physical memory space. | ||
453 | */ | ||
454 | static __inline__ void hdpu_set_bat(void) | ||
455 | { | ||
456 | mb(); | ||
457 | mtspr(SPRN_DBAT1U, 0xf10001fe); | ||
458 | mtspr(SPRN_DBAT1L, 0xf100002a); | ||
459 | mb(); | ||
460 | |||
461 | return; | ||
462 | } | ||
463 | |||
464 | unsigned long __init hdpu_find_end_of_memory(void) | ||
465 | { | ||
466 | return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE, | ||
467 | MV64x60_TYPE_MV64360); | ||
468 | } | ||
469 | |||
470 | static void hdpu_reset_board(void) | ||
471 | { | ||
472 | volatile int infinite = 1; | ||
473 | |||
474 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_RESET); | ||
475 | |||
476 | local_irq_disable(); | ||
477 | |||
478 | /* Clear all the LEDs */ | ||
479 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) | | ||
480 | (1 << 5) | (1 << 6))); | ||
481 | |||
482 | /* disable and invalidate the L2 cache */ | ||
483 | _set_L2CR(0); | ||
484 | _set_L2CR(0x200000); | ||
485 | |||
486 | /* flush and disable L1 I/D cache */ | ||
487 | __asm__ __volatile__ | ||
488 | ("\n" | ||
489 | "mfspr 3,1008\n" | ||
490 | "ori 5,5,0xcc00\n" | ||
491 | "ori 4,3,0xc00\n" | ||
492 | "andc 5,3,5\n" | ||
493 | "sync\n" | ||
494 | "mtspr 1008,4\n" | ||
495 | "isync\n" "sync\n" "mtspr 1008,5\n" "isync\n" "sync\n"); | ||
496 | |||
497 | /* Hit the reset bit */ | ||
498 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 3)); | ||
499 | |||
500 | while (infinite) | ||
501 | infinite = infinite; | ||
502 | |||
503 | return; | ||
504 | } | ||
505 | |||
506 | static void hdpu_restart(char *cmd) | ||
507 | { | ||
508 | volatile ulong i = 10000000; | ||
509 | |||
510 | hdpu_reset_board(); | ||
511 | |||
512 | while (i-- > 0) ; | ||
513 | panic("restart failed\n"); | ||
514 | } | ||
515 | |||
516 | static void hdpu_halt(void) | ||
517 | { | ||
518 | local_irq_disable(); | ||
519 | |||
520 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_HALT); | ||
521 | |||
522 | /* Clear all the LEDs */ | ||
523 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, ((1 << 4) | (1 << 5) | | ||
524 | (1 << 6))); | ||
525 | while (1) ; | ||
526 | /* NOTREACHED */ | ||
527 | } | ||
528 | |||
529 | static void hdpu_power_off(void) | ||
530 | { | ||
531 | hdpu_halt(); | ||
532 | /* NOTREACHED */ | ||
533 | } | ||
534 | |||
535 | static int hdpu_show_cpuinfo(struct seq_file *m) | ||
536 | { | ||
537 | uint pvid; | ||
538 | |||
539 | pvid = mfspr(SPRN_PVR); | ||
540 | seq_printf(m, "vendor\t\t: Sky Computers\n"); | ||
541 | seq_printf(m, "machine\t\t: HDPU Compute Blade\n"); | ||
542 | seq_printf(m, "PVID\t\t: 0x%x, vendor: %s\n", | ||
543 | pvid, (pvid & (1 << 15) ? "IBM" : "Motorola")); | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static void __init hdpu_calibrate_decr(void) | ||
549 | { | ||
550 | ulong freq; | ||
551 | |||
552 | if (ppcboot_bd_valid) | ||
553 | freq = ppcboot_bd.bi_busfreq / 4; | ||
554 | else | ||
555 | freq = 133000000; | ||
556 | |||
557 | printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", | ||
558 | freq / 1000000, freq % 1000000); | ||
559 | |||
560 | tb_ticks_per_jiffy = freq / HZ; | ||
561 | tb_to_us = mulhwu_scale_factor(freq, 1000000); | ||
562 | |||
563 | return; | ||
564 | } | ||
565 | |||
566 | static void parse_bootinfo(unsigned long r3, | ||
567 | unsigned long r4, unsigned long r5, | ||
568 | unsigned long r6, unsigned long r7) | ||
569 | { | ||
570 | bd_t *bd = NULL; | ||
571 | char *cmdline_start = NULL; | ||
572 | int cmdline_len = 0; | ||
573 | |||
574 | if (r3) { | ||
575 | if ((r3 & 0xf0000000) == 0) | ||
576 | r3 += KERNELBASE; | ||
577 | if ((r3 & 0xf0000000) == KERNELBASE) { | ||
578 | bd = (void *)r3; | ||
579 | |||
580 | memcpy(&ppcboot_bd, bd, sizeof(ppcboot_bd)); | ||
581 | ppcboot_bd_valid = 1; | ||
582 | } | ||
583 | } | ||
584 | #ifdef CONFIG_BLK_DEV_INITRD | ||
585 | if (r4 && r5 && r5 > r4) { | ||
586 | if ((r4 & 0xf0000000) == 0) | ||
587 | r4 += KERNELBASE; | ||
588 | if ((r5 & 0xf0000000) == 0) | ||
589 | r5 += KERNELBASE; | ||
590 | if ((r4 & 0xf0000000) == KERNELBASE) { | ||
591 | initrd_start = r4; | ||
592 | initrd_end = r5; | ||
593 | initrd_below_start_ok = 1; | ||
594 | } | ||
595 | } | ||
596 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
597 | |||
598 | if (r6 && r7 && r7 > r6) { | ||
599 | if ((r6 & 0xf0000000) == 0) | ||
600 | r6 += KERNELBASE; | ||
601 | if ((r7 & 0xf0000000) == 0) | ||
602 | r7 += KERNELBASE; | ||
603 | if ((r6 & 0xf0000000) == KERNELBASE) { | ||
604 | cmdline_start = (void *)r6; | ||
605 | cmdline_len = (r7 - r6); | ||
606 | strncpy(cmd_line, cmdline_start, cmdline_len); | ||
607 | } | ||
608 | } | ||
609 | } | ||
610 | |||
611 | #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) | ||
612 | static int hdpu_ide_check_region(ide_ioreg_t from, unsigned int extent) | ||
613 | { | ||
614 | return check_region(from, extent); | ||
615 | } | ||
616 | |||
617 | static void | ||
618 | hdpu_ide_request_region(ide_ioreg_t from, unsigned int extent, const char *name) | ||
619 | { | ||
620 | request_region(from, extent, name); | ||
621 | return; | ||
622 | } | ||
623 | |||
624 | static void hdpu_ide_release_region(ide_ioreg_t from, unsigned int extent) | ||
625 | { | ||
626 | release_region(from, extent); | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | static void __init | ||
631 | hdpu_ide_pci_init_hwif_ports(hw_regs_t * hw, ide_ioreg_t data_port, | ||
632 | ide_ioreg_t ctrl_port, int *irq) | ||
633 | { | ||
634 | struct pci_dev *dev; | ||
635 | |||
636 | pci_for_each_dev(dev) { | ||
637 | if (((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) || | ||
638 | ((dev->class >> 8) == PCI_CLASS_STORAGE_RAID)) { | ||
639 | hw->irq = dev->irq; | ||
640 | |||
641 | if (irq != NULL) { | ||
642 | *irq = dev->irq; | ||
643 | } | ||
644 | } | ||
645 | } | ||
646 | |||
647 | return; | ||
648 | } | ||
649 | #endif | ||
650 | |||
651 | void hdpu_heartbeat(void) | ||
652 | { | ||
653 | if (mv64x60_read(&bh, MV64x60_GPP_VALUE) & (1 << 5)) | ||
654 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (1 << 5)); | ||
655 | else | ||
656 | mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, (1 << 5)); | ||
657 | |||
658 | ppc_md.heartbeat_count = ppc_md.heartbeat_reset; | ||
659 | |||
660 | } | ||
661 | |||
662 | static void __init hdpu_map_io(void) | ||
663 | { | ||
664 | io_block_mapping(0xf1000000, 0xf1000000, 0x20000, _PAGE_IO); | ||
665 | } | ||
666 | |||
667 | #ifdef CONFIG_SMP | ||
668 | char hdpu_smp0[] = "SMP Cpu #0"; | ||
669 | char hdpu_smp1[] = "SMP Cpu #1"; | ||
670 | |||
671 | static irqreturn_t hdpu_smp_cpu0_int_handler(int irq, void *dev_id, | ||
672 | struct pt_regs *regs) | ||
673 | { | ||
674 | volatile unsigned int doorbell; | ||
675 | |||
676 | doorbell = mv64x60_read(&bh, MV64360_CPU0_DOORBELL); | ||
677 | |||
678 | /* Ack the doorbell interrupts */ | ||
679 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, doorbell); | ||
680 | |||
681 | if (doorbell & 1) { | ||
682 | smp_message_recv(0, regs); | ||
683 | } | ||
684 | if (doorbell & 2) { | ||
685 | smp_message_recv(1, regs); | ||
686 | } | ||
687 | if (doorbell & 4) { | ||
688 | smp_message_recv(2, regs); | ||
689 | } | ||
690 | if (doorbell & 8) { | ||
691 | smp_message_recv(3, regs); | ||
692 | } | ||
693 | return IRQ_HANDLED; | ||
694 | } | ||
695 | |||
696 | static irqreturn_t hdpu_smp_cpu1_int_handler(int irq, void *dev_id, | ||
697 | struct pt_regs *regs) | ||
698 | { | ||
699 | volatile unsigned int doorbell; | ||
700 | |||
701 | doorbell = mv64x60_read(&bh, MV64360_CPU1_DOORBELL); | ||
702 | |||
703 | /* Ack the doorbell interrupts */ | ||
704 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, doorbell); | ||
705 | |||
706 | if (doorbell & 1) { | ||
707 | smp_message_recv(0, regs); | ||
708 | } | ||
709 | if (doorbell & 2) { | ||
710 | smp_message_recv(1, regs); | ||
711 | } | ||
712 | if (doorbell & 4) { | ||
713 | smp_message_recv(2, regs); | ||
714 | } | ||
715 | if (doorbell & 8) { | ||
716 | smp_message_recv(3, regs); | ||
717 | } | ||
718 | return IRQ_HANDLED; | ||
719 | } | ||
720 | |||
721 | static void smp_hdpu_CPU_two(void) | ||
722 | { | ||
723 | __asm__ __volatile__ | ||
724 | ("\n" | ||
725 | "lis 3,0x0000\n" | ||
726 | "ori 3,3,0x00c0\n" | ||
727 | "mtspr 26, 3\n" "li 4,0\n" "mtspr 27,4\n" "rfi"); | ||
728 | |||
729 | } | ||
730 | |||
731 | static int smp_hdpu_probe(void) | ||
732 | { | ||
733 | int *cpu_count_reg; | ||
734 | int num_cpus = 0; | ||
735 | |||
736 | cpu_count_reg = ioremap(HDPU_NEXUS_ID_BASE, HDPU_NEXUS_ID_SIZE); | ||
737 | if (cpu_count_reg) { | ||
738 | num_cpus = (*cpu_count_reg >> 20) & 0x3; | ||
739 | iounmap(cpu_count_reg); | ||
740 | } | ||
741 | |||
742 | /* Validate the bits in the CPLD. If we could not map the reg, return 2. | ||
743 | * If the register reported 0 or 3, return 2. | ||
744 | * Older CPLD revisions set these bits to all ones (val = 3). | ||
745 | */ | ||
746 | if ((num_cpus < 1) || (num_cpus > 2)) { | ||
747 | printk | ||
748 | ("Unable to determine the number of processors %d . deafulting to 2.\n", | ||
749 | num_cpus); | ||
750 | num_cpus = 2; | ||
751 | } | ||
752 | return num_cpus; | ||
753 | } | ||
754 | |||
755 | static void | ||
756 | smp_hdpu_message_pass(int target, int msg, unsigned long data, int wait) | ||
757 | { | ||
758 | if (msg > 0x3) { | ||
759 | printk("SMP %d: smp_message_pass: unknown msg %d\n", | ||
760 | smp_processor_id(), msg); | ||
761 | return; | ||
762 | } | ||
763 | switch (target) { | ||
764 | case MSG_ALL: | ||
765 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); | ||
766 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); | ||
767 | break; | ||
768 | case MSG_ALL_BUT_SELF: | ||
769 | if (smp_processor_id()) | ||
770 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); | ||
771 | else | ||
772 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); | ||
773 | break; | ||
774 | default: | ||
775 | if (target == 0) | ||
776 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL, 1 << msg); | ||
777 | else | ||
778 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL, 1 << msg); | ||
779 | break; | ||
780 | } | ||
781 | } | ||
782 | |||
783 | static void smp_hdpu_kick_cpu(int nr) | ||
784 | { | ||
785 | volatile unsigned int *bootaddr; | ||
786 | |||
787 | if (ppc_md.progress) | ||
788 | ppc_md.progress("smp_hdpu_kick_cpu", 0); | ||
789 | |||
790 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | CPUSTATE_KERNEL_CPU1_KICK); | ||
791 | |||
792 | /* Disable BootCS. Must also reduce the windows size to zero. */ | ||
793 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
794 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, 0, 0, 0); | ||
795 | |||
796 | bootaddr = ioremap(HDPU_INTERNAL_SRAM_BASE, HDPU_INTERNAL_SRAM_SIZE); | ||
797 | if (!bootaddr) { | ||
798 | if (ppc_md.progress) | ||
799 | ppc_md.progress("smp_hdpu_kick_cpu: ioremap failed", 0); | ||
800 | return; | ||
801 | } | ||
802 | |||
803 | memcpy((void *)(bootaddr + 0x40), (void *)&smp_hdpu_CPU_two, 0x20); | ||
804 | |||
805 | /* map SRAM to 0xfff00000 */ | ||
806 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
807 | |||
808 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
809 | 0xfff00000, HDPU_INTERNAL_SRAM_SIZE, 0); | ||
810 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
811 | |||
812 | /* Enable CPU1 arbitration */ | ||
813 | mv64x60_clr_bits(&bh, MV64x60_CPU_MASTER_CNTL, (1 << 9)); | ||
814 | |||
815 | /* | ||
816 | * Wait 100mSecond until other CPU has reached __secondary_start. | ||
817 | * When it reaches, it is permittable to rever the SRAM mapping etc... | ||
818 | */ | ||
819 | mdelay(100); | ||
820 | *(unsigned long *)KERNELBASE = nr; | ||
821 | asm volatile ("dcbf 0,%0"::"r" (KERNELBASE):"memory"); | ||
822 | |||
823 | iounmap(bootaddr); | ||
824 | |||
825 | /* Set up window for internal sram (256KByte insize) */ | ||
826 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
827 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN, | ||
828 | HDPU_INTERNAL_SRAM_BASE, | ||
829 | HDPU_INTERNAL_SRAM_SIZE, 0); | ||
830 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN); | ||
831 | /* | ||
832 | * Set up windows for embedded FLASH (using boot CS window). | ||
833 | */ | ||
834 | |||
835 | bh.ci->disable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
836 | mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN, | ||
837 | HDPU_EMB_FLASH_BASE, HDPU_EMB_FLASH_SIZE, 0); | ||
838 | bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN); | ||
839 | } | ||
840 | |||
841 | static void smp_hdpu_setup_cpu(int cpu_nr) | ||
842 | { | ||
843 | if (cpu_nr == 0) { | ||
844 | if (ppc_md.progress) | ||
845 | ppc_md.progress("smp_hdpu_setup_cpu 0", 0); | ||
846 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL_CLR, 0xff); | ||
847 | mv64x60_write(&bh, MV64360_CPU0_DOORBELL_MASK, 0xff); | ||
848 | request_irq(60, hdpu_smp_cpu0_int_handler, | ||
849 | SA_INTERRUPT, hdpu_smp0, 0); | ||
850 | } | ||
851 | |||
852 | if (cpu_nr == 1) { | ||
853 | if (ppc_md.progress) | ||
854 | ppc_md.progress("smp_hdpu_setup_cpu 1", 0); | ||
855 | |||
856 | hdpu_cpustate_set(CPUSTATE_KERNEL_MAJOR | | ||
857 | CPUSTATE_KERNEL_CPU1_OK); | ||
858 | |||
859 | /* Enable L1 Parity Bits */ | ||
860 | hdpu_set_l1pe(); | ||
861 | |||
862 | /* Enable L2 cache */ | ||
863 | _set_L2CR(0); | ||
864 | _set_L2CR(0x80080000); | ||
865 | |||
866 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL_CLR, 0x0); | ||
867 | mv64x60_write(&bh, MV64360_CPU1_DOORBELL_MASK, 0xff); | ||
868 | request_irq(28, hdpu_smp_cpu1_int_handler, | ||
869 | SA_INTERRUPT, hdpu_smp1, 0); | ||
870 | } | ||
871 | |||
872 | } | ||
873 | |||
874 | void __devinit hdpu_tben_give() | ||
875 | { | ||
876 | volatile unsigned long *val = 0; | ||
877 | |||
878 | /* By writing 0 to the TBEN_BASE, the timebases is frozen */ | ||
879 | val = ioremap(HDPU_TBEN_BASE, 4); | ||
880 | *val = 0; | ||
881 | mb(); | ||
882 | |||
883 | spin_lock(&timebase_lock); | ||
884 | timebase_upper = get_tbu(); | ||
885 | timebase_lower = get_tbl(); | ||
886 | spin_unlock(&timebase_lock); | ||
887 | |||
888 | while (timebase_upper || timebase_lower) | ||
889 | barrier(); | ||
890 | |||
891 | /* By writing 1 to the TBEN_BASE, the timebases is thawed */ | ||
892 | *val = 1; | ||
893 | mb(); | ||
894 | |||
895 | iounmap(val); | ||
896 | |||
897 | } | ||
898 | |||
899 | void __devinit hdpu_tben_take() | ||
900 | { | ||
901 | while (!(timebase_upper || timebase_lower)) | ||
902 | barrier(); | ||
903 | |||
904 | spin_lock(&timebase_lock); | ||
905 | set_tb(timebase_upper, timebase_lower); | ||
906 | timebase_upper = 0; | ||
907 | timebase_lower = 0; | ||
908 | spin_unlock(&timebase_lock); | ||
909 | } | ||
910 | |||
911 | static struct smp_ops_t hdpu_smp_ops = { | ||
912 | .message_pass = smp_hdpu_message_pass, | ||
913 | .probe = smp_hdpu_probe, | ||
914 | .kick_cpu = smp_hdpu_kick_cpu, | ||
915 | .setup_cpu = smp_hdpu_setup_cpu, | ||
916 | .give_timebase = hdpu_tben_give, | ||
917 | .take_timebase = hdpu_tben_take, | ||
918 | }; | ||
919 | #endif /* CONFIG_SMP */ | ||
920 | |||
921 | void __init | ||
922 | platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
923 | unsigned long r6, unsigned long r7) | ||
924 | { | ||
925 | parse_bootinfo(r3, r4, r5, r6, r7); | ||
926 | |||
927 | isa_mem_base = 0; | ||
928 | |||
929 | ppc_md.setup_arch = hdpu_setup_arch; | ||
930 | ppc_md.init = hdpu_init2; | ||
931 | ppc_md.show_cpuinfo = hdpu_show_cpuinfo; | ||
932 | ppc_md.init_IRQ = hdpu_init_irq; | ||
933 | ppc_md.get_irq = mv64360_get_irq; | ||
934 | ppc_md.restart = hdpu_restart; | ||
935 | ppc_md.power_off = hdpu_power_off; | ||
936 | ppc_md.halt = hdpu_halt; | ||
937 | ppc_md.find_end_of_memory = hdpu_find_end_of_memory; | ||
938 | ppc_md.calibrate_decr = hdpu_calibrate_decr; | ||
939 | ppc_md.setup_io_mappings = hdpu_map_io; | ||
940 | |||
941 | bh.p_base = CONFIG_MV64X60_NEW_BASE; | ||
942 | bh.v_base = (unsigned long *)bh.p_base; | ||
943 | |||
944 | hdpu_set_bat(); | ||
945 | |||
946 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) | ||
947 | ppc_md.progress = hdpu_mpsc_progress; /* embedded UART */ | ||
948 | mv64x60_progress_init(bh.p_base); | ||
949 | #endif /* CONFIG_SERIAL_TEXT_DEBUG */ | ||
950 | |||
951 | #ifdef CONFIG_SMP | ||
952 | ppc_md.smp_ops = &hdpu_smp_ops; | ||
953 | #endif /* CONFIG_SMP */ | ||
954 | |||
955 | #if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH) | ||
956 | platform_notify = hdpu_platform_notify; | ||
957 | #endif | ||
958 | return; | ||
959 | } | ||
960 | |||
961 | #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) | ||
962 | /* SMP safe version of the serial text debug routine. Uses Semaphore 0 */ | ||
963 | void hdpu_mpsc_progress(char *s, unsigned short hex) | ||
964 | { | ||
965 | while (mv64x60_read(&bh, MV64360_WHO_AM_I) != | ||
966 | mv64x60_read(&bh, MV64360_SEMAPHORE_0)) { | ||
967 | } | ||
968 | mv64x60_mpsc_progress(s, hex); | ||
969 | mv64x60_write(&bh, MV64360_SEMAPHORE_0, 0xff); | ||
970 | } | ||
971 | #endif | ||
972 | |||
973 | static void hdpu_cpustate_set(unsigned char new_state) | ||
974 | { | ||
975 | unsigned int state = (new_state << 21); | ||
976 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, (0xff << 21)); | ||
977 | mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, state); | ||
978 | } | ||
979 | |||
980 | #ifdef CONFIG_MTD_PHYSMAP | ||
981 | static struct mtd_partition hdpu_partitions[] = { | ||
982 | { | ||
983 | .name = "Root FS", | ||
984 | .size = 0x03400000, | ||
985 | .offset = 0, | ||
986 | .mask_flags = 0, | ||
987 | },{ | ||
988 | .name = "User FS", | ||
989 | .size = 0x00800000, | ||
990 | .offset = 0x03400000, | ||
991 | .mask_flags = 0, | ||
992 | },{ | ||
993 | .name = "Kernel Image", | ||
994 | .size = 0x002C0000, | ||
995 | .offset = 0x03C00000, | ||
996 | .mask_flags = 0, | ||
997 | },{ | ||
998 | .name = "bootEnv", | ||
999 | .size = 0x00040000, | ||
1000 | .offset = 0x03EC0000, | ||
1001 | .mask_flags = 0, | ||
1002 | },{ | ||
1003 | .name = "bootROM", | ||
1004 | .size = 0x00100000, | ||
1005 | .offset = 0x03F00000, | ||
1006 | .mask_flags = 0, | ||
1007 | } | ||
1008 | }; | ||
1009 | |||
1010 | static int __init hdpu_setup_mtd(void) | ||
1011 | { | ||
1012 | |||
1013 | physmap_set_partitions(hdpu_partitions, 5); | ||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
1017 | arch_initcall(hdpu_setup_mtd); | ||
1018 | #endif | ||
1019 | |||
1020 | #ifdef CONFIG_HDPU_FEATURES | ||
1021 | |||
1022 | static struct resource hdpu_cpustate_resources[] = { | ||
1023 | [0] = { | ||
1024 | .name = "addr base", | ||
1025 | .start = MV64x60_GPP_VALUE_SET, | ||
1026 | .end = MV64x60_GPP_VALUE_CLR + 1, | ||
1027 | .flags = IORESOURCE_MEM, | ||
1028 | }, | ||
1029 | }; | ||
1030 | |||
1031 | static struct resource hdpu_nexus_resources[] = { | ||
1032 | [0] = { | ||
1033 | .name = "nexus register", | ||
1034 | .start = HDPU_NEXUS_ID_BASE, | ||
1035 | .end = HDPU_NEXUS_ID_BASE + HDPU_NEXUS_ID_SIZE, | ||
1036 | .flags = IORESOURCE_MEM, | ||
1037 | }, | ||
1038 | }; | ||
1039 | |||
1040 | static struct platform_device hdpu_cpustate_device = { | ||
1041 | .name = HDPU_CPUSTATE_NAME, | ||
1042 | .id = 0, | ||
1043 | .num_resources = ARRAY_SIZE(hdpu_cpustate_resources), | ||
1044 | .resource = hdpu_cpustate_resources, | ||
1045 | }; | ||
1046 | |||
1047 | static struct platform_device hdpu_nexus_device = { | ||
1048 | .name = HDPU_NEXUS_NAME, | ||
1049 | .id = 0, | ||
1050 | .num_resources = ARRAY_SIZE(hdpu_nexus_resources), | ||
1051 | .resource = hdpu_nexus_resources, | ||
1052 | }; | ||
1053 | |||
1054 | static int __init hdpu_add_pds(void) | ||
1055 | { | ||
1056 | platform_device_register(&hdpu_cpustate_device); | ||
1057 | platform_device_register(&hdpu_nexus_device); | ||
1058 | return 0; | ||
1059 | } | ||
1060 | |||
1061 | arch_initcall(hdpu_add_pds); | ||
1062 | #endif | ||