Commit c5d56332fd6c2f0c7cf9d1f65416076f2711ea28
Committed by
Paul Mackerras
1 parent
1729dc7833
[POWERPC] Add general support for mpc7448hpc2 (Taiga) platform
Add support for Freescale mpc7448 (Taiga) board support Signed-off-by: Roy Zang <tie-fei.zang@freescale.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Showing 7 changed files with 397 additions and 3 deletions Side-by-side Diff
arch/powerpc/Kconfig
... | ... | @@ -336,7 +336,7 @@ |
336 | 336 | |
337 | 337 | config EMBEDDED6xx |
338 | 338 | bool "Embedded 6xx/7xx/7xxx-based board" |
339 | - depends on PPC32 && BROKEN | |
339 | + depends on PPC32 && (BROKEN||BROKEN_ON_SMP) | |
340 | 340 | |
341 | 341 | config APUS |
342 | 342 | bool "Amiga-APUS" |
... | ... | @@ -436,7 +436,8 @@ |
436 | 436 | default n |
437 | 437 | |
438 | 438 | config MPIC |
439 | - depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP | |
439 | + depends on PPC_PSERIES || PPC_PMAC || PPC_MAPLE || PPC_CHRP \ | |
440 | + || MPC7448HPC2 | |
440 | 441 | bool |
441 | 442 | default y |
442 | 443 | |
... | ... | @@ -821,7 +822,8 @@ |
821 | 822 | bool |
822 | 823 | |
823 | 824 | config PCI |
824 | - bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_86xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) | |
825 | + bool "PCI support" if 40x || CPM2 || PPC_83xx || PPC_85xx || PPC_MPC52xx || (EMBEDDED && PPC_ISERIES) \ | |
826 | + || MPC7448HPC2 | |
825 | 827 | default y if !40x && !CPM2 && !8xx && !APUS && !PPC_83xx && !PPC_85xx && !PPC_86xx |
826 | 828 | default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS |
827 | 829 | default PCI_QSPAN if !4xx && !CPM2 && 8xx |
arch/powerpc/kernel/legacy_serial.c
... | ... | @@ -302,6 +302,17 @@ |
302 | 302 | of_node_put(isa); |
303 | 303 | } |
304 | 304 | |
305 | + /* First fill our array with tsi-bridge ports */ | |
306 | + for (np = NULL; (np = of_find_compatible_node(np, "serial", "ns16550")) != NULL;) { | |
307 | + struct device_node *tsi = of_get_parent(np); | |
308 | + if (tsi && !strcmp(tsi->type, "tsi-bridge")) { | |
309 | + index = add_legacy_soc_port(np, np); | |
310 | + if (index >= 0 && np == stdout) | |
311 | + legacy_serial_console = index; | |
312 | + } | |
313 | + of_node_put(tsi); | |
314 | + } | |
315 | + | |
305 | 316 | #ifdef CONFIG_PCI |
306 | 317 | /* Next, try to locate PCI ports */ |
307 | 318 | for (np = NULL; (np = of_find_all_nodes(np));) { |
arch/powerpc/platforms/Makefile
arch/powerpc/platforms/embedded6xx/Kconfig
... | ... | @@ -74,6 +74,16 @@ |
74 | 74 | Select SANDPOINT if configuring for a Motorola Sandpoint X3 |
75 | 75 | (any flavor). |
76 | 76 | |
77 | +config MPC7448HPC2 | |
78 | + bool "Freescale MPC7448HPC2(Taiga)" | |
79 | + select TSI108_BRIDGE | |
80 | + select DEFAULT_UIMAGE | |
81 | + select PPC_UDBG_16550 | |
82 | + select MPIC | |
83 | + help | |
84 | + Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga) | |
85 | + platform | |
86 | + | |
77 | 87 | config RADSTONE_PPC7D |
78 | 88 | bool "Radstone Technology PPC7D board" |
79 | 89 | select PPC_I8259 |
... | ... | @@ -219,6 +229,11 @@ |
219 | 229 | bool |
220 | 230 | depends on (GT64260 || MV64360) |
221 | 231 | select PPC_INDIRECT_PCI |
232 | + default y | |
233 | + | |
234 | +config TSI108_BRIDGE | |
235 | + bool | |
236 | + depends on MPC7448HPC2 | |
222 | 237 | default y |
223 | 238 | |
224 | 239 | menu "Set bridge options" |
arch/powerpc/platforms/embedded6xx/Makefile
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
1 | +/* | |
2 | + * mpc7448_hpc2.c | |
3 | + * | |
4 | + * Board setup routines for the Freescale Taiga platform | |
5 | + * | |
6 | + * Author: Jacob Pan | |
7 | + * jacob.pan@freescale.com | |
8 | + * Author: Xianghua Xiao | |
9 | + * x.xiao@freescale.com | |
10 | + * Maintainer: Roy Zang <tie-fei.zang@freescale.com> | |
11 | + * Add Flat Device Tree support fot mpc7448hpc2 board | |
12 | + * | |
13 | + * Copyright 2004-2006 Freescale Semiconductor, Inc. | |
14 | + * | |
15 | + * This file is licensed under | |
16 | + * the terms of the GNU General Public License version 2. This program | |
17 | + * is licensed "as is" without any warranty of any kind, whether express | |
18 | + * or implied. | |
19 | + */ | |
20 | + | |
21 | +#include <linux/config.h> | |
22 | +#include <linux/stddef.h> | |
23 | +#include <linux/kernel.h> | |
24 | +#include <linux/pci.h> | |
25 | +#include <linux/kdev_t.h> | |
26 | +#include <linux/console.h> | |
27 | +#include <linux/delay.h> | |
28 | +#include <linux/irq.h> | |
29 | +#include <linux/ide.h> | |
30 | +#include <linux/seq_file.h> | |
31 | +#include <linux/root_dev.h> | |
32 | +#include <linux/serial.h> | |
33 | +#include <linux/tty.h> | |
34 | +#include <linux/serial_core.h> | |
35 | + | |
36 | +#include <asm/system.h> | |
37 | +#include <asm/time.h> | |
38 | +#include <asm/machdep.h> | |
39 | +#include <asm/prom.h> | |
40 | +#include <asm/udbg.h> | |
41 | +#include <asm/tsi108.h> | |
42 | +#include <asm/pci-bridge.h> | |
43 | +#include <asm/reg.h> | |
44 | +#include <mm/mmu_decl.h> | |
45 | +#include "mpc7448_hpc2.h" | |
46 | +#include <asm/tsi108_irq.h> | |
47 | +#include <asm/mpic.h> | |
48 | + | |
49 | +#undef DEBUG | |
50 | +#ifdef DEBUG | |
51 | +#define DBG(fmt...) do { printk(fmt); } while(0) | |
52 | +#else | |
53 | +#define DBG(fmt...) do { } while(0) | |
54 | +#endif | |
55 | + | |
56 | +#ifndef CONFIG_PCI | |
57 | +isa_io_base = MPC7448_HPC2_ISA_IO_BASE; | |
58 | +isa_mem_base = MPC7448_HPC2_ISA_MEM_BASE; | |
59 | +pci_dram_offset = MPC7448_HPC2_PCI_MEM_OFFSET; | |
60 | +#endif | |
61 | + | |
62 | +extern int tsi108_setup_pci(struct device_node *dev); | |
63 | +extern void _nmask_and_or_msr(unsigned long nmask, unsigned long or_val); | |
64 | +extern void tsi108_pci_int_init(void); | |
65 | +extern int tsi108_irq_cascade(struct pt_regs *regs, void *unused); | |
66 | + | |
67 | +/* | |
68 | + * Define all of the IRQ senses and polarities. Taken from the | |
69 | + * mpc7448hpc manual. | |
70 | + * Note: Likely, this table and the following function should be | |
71 | + * obtained and derived from the OF Device Tree. | |
72 | + */ | |
73 | + | |
74 | +static u_char mpc7448_hpc2_pic_initsenses[] __initdata = { | |
75 | + /* External on-board sources */ | |
76 | + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[0] XINT0 from FPGA */ | |
77 | + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[1] XINT1 from FPGA */ | |
78 | + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[2] PHY_INT from both GIGE */ | |
79 | + (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE), /* INT[3] RESERVED */ | |
80 | + /* Internal Tsi108/109 interrupt sources */ | |
81 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */ | |
82 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */ | |
83 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */ | |
84 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */ | |
85 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA0 */ | |
86 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA1 */ | |
87 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA2 */ | |
88 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* DMA3 */ | |
89 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* UART0 */ | |
90 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* UART1 */ | |
91 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* I2C */ | |
92 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* GPIO */ | |
93 | + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* GIGE0 */ | |
94 | + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* GIGE1 */ | |
95 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */ | |
96 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* HLP */ | |
97 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* SDC */ | |
98 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Processor IF */ | |
99 | + (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE), /* Reserved IRQ */ | |
100 | + (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE), /* PCI/X block */ | |
101 | +}; | |
102 | + | |
103 | +int mpc7448_hpc2_exclude_device(u_char bus, u_char devfn) | |
104 | +{ | |
105 | + if (bus == 0 && PCI_SLOT(devfn) == 0) | |
106 | + return PCIBIOS_DEVICE_NOT_FOUND; | |
107 | + else | |
108 | + return PCIBIOS_SUCCESSFUL; | |
109 | +} | |
110 | + | |
111 | +/* | |
112 | + * find pci slot by devfn in interrupt map of OF tree | |
113 | + */ | |
114 | +u8 find_slot_by_devfn(unsigned int *interrupt_map, unsigned int devfn) | |
115 | +{ | |
116 | + int i; | |
117 | + unsigned int tmp; | |
118 | + for (i = 0; i < 4; i++){ | |
119 | + tmp = interrupt_map[i*4*7]; | |
120 | + if ((tmp >> 11) == (devfn >> 3)) | |
121 | + return i; | |
122 | + } | |
123 | + return i; | |
124 | +} | |
125 | + | |
126 | +/* | |
127 | + * Scans the interrupt map for pci device | |
128 | + */ | |
129 | +void mpc7448_hpc2_fixup_irq(struct pci_dev *dev) | |
130 | +{ | |
131 | + struct pci_controller *hose; | |
132 | + struct device_node *node; | |
133 | + unsigned int *interrupt; | |
134 | + int busnr; | |
135 | + int len; | |
136 | + u8 slot; | |
137 | + u8 pin; | |
138 | + | |
139 | + /* Lookup the hose */ | |
140 | + busnr = dev->bus->number; | |
141 | + hose = pci_bus_to_hose(busnr); | |
142 | + if (!hose) | |
143 | + printk(KERN_ERR "No pci hose found\n"); | |
144 | + | |
145 | + /* Check it has an OF node associated */ | |
146 | + node = (struct device_node *) hose->arch_data; | |
147 | + if (!node) | |
148 | + printk(KERN_ERR "No pci node found\n"); | |
149 | + | |
150 | + interrupt = (unsigned int *) get_property(node, "interrupt-map", &len); | |
151 | + slot = find_slot_by_devfn(interrupt, dev->devfn); | |
152 | + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); | |
153 | + if (pin == 0 || pin > 4) | |
154 | + pin = 1; | |
155 | + pin--; | |
156 | + dev->irq = interrupt[slot*4*7 + pin*7 + 5]; | |
157 | + DBG("TSI_PCI: dev->irq = 0x%x\n", dev->irq); | |
158 | +} | |
159 | +/* temporary pci irq map fixup*/ | |
160 | + | |
161 | +void __init mpc7448_hpc2_pcibios_fixup(void) | |
162 | +{ | |
163 | + struct pci_dev *dev = NULL; | |
164 | + for_each_pci_dev(dev) { | |
165 | + mpc7448_hpc2_fixup_irq(dev); | |
166 | + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); | |
167 | + } | |
168 | +} | |
169 | + | |
170 | +static void __init mpc7448_hpc2_setup_arch(void) | |
171 | +{ | |
172 | + struct device_node *cpu; | |
173 | + struct device_node *np; | |
174 | + if (ppc_md.progress) | |
175 | + ppc_md.progress("mpc7448_hpc2_setup_arch():set_bridge", 0); | |
176 | + | |
177 | + cpu = of_find_node_by_type(NULL, "cpu"); | |
178 | + if (cpu != 0) { | |
179 | + unsigned int *fp; | |
180 | + | |
181 | + fp = (int *)get_property(cpu, "clock-frequency", NULL); | |
182 | + if (fp != 0) | |
183 | + loops_per_jiffy = *fp / HZ; | |
184 | + else | |
185 | + loops_per_jiffy = 50000000 / HZ; | |
186 | + of_node_put(cpu); | |
187 | + } | |
188 | + tsi108_csr_vir_base = get_vir_csrbase(); | |
189 | + | |
190 | +#ifdef CONFIG_ROOT_NFS | |
191 | + ROOT_DEV = Root_NFS; | |
192 | +#else | |
193 | + ROOT_DEV = Root_HDA1; | |
194 | +#endif | |
195 | + | |
196 | +#ifdef CONFIG_BLK_DEV_INITRD | |
197 | + ROOT_DEV = Root_RAM0; | |
198 | +#endif | |
199 | + | |
200 | + /* setup PCI host bridge */ | |
201 | +#ifdef CONFIG_PCI | |
202 | + for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | |
203 | + tsi108_setup_pci(np); | |
204 | + | |
205 | + ppc_md.pci_exclude_device = mpc7448_hpc2_exclude_device; | |
206 | + if (ppc_md.progress) | |
207 | + ppc_md.progress("tsi108: resources set", 0x100); | |
208 | +#endif | |
209 | + | |
210 | + printk(KERN_INFO "MPC7448HPC2 (TAIGA) Platform\n"); | |
211 | + printk(KERN_INFO | |
212 | + "Jointly ported by Freescale and Tundra Semiconductor\n"); | |
213 | + printk(KERN_INFO | |
214 | + "Enabling L2 cache then enabling the HID0 prefetch engine.\n"); | |
215 | +} | |
216 | + | |
217 | +/* | |
218 | + * Interrupt setup and service. Interrrupts on the mpc7448_hpc2 come | |
219 | + * from the four external INT pins, PCI interrupts are routed via | |
220 | + * PCI interrupt control registers, it generates internal IRQ23 | |
221 | + * | |
222 | + * Interrupt routing on the Taiga Board: | |
223 | + * TSI108:PB_INT[0] -> CPU0:INT# | |
224 | + * TSI108:PB_INT[1] -> CPU0:MCP# | |
225 | + * TSI108:PB_INT[2] -> N/C | |
226 | + * TSI108:PB_INT[3] -> N/C | |
227 | + */ | |
228 | +static void __init mpc7448_hpc2_init_IRQ(void) | |
229 | +{ | |
230 | + struct mpic *mpic; | |
231 | + phys_addr_t mpic_paddr = 0; | |
232 | + struct device_node *tsi_pic; | |
233 | + | |
234 | + tsi_pic = of_find_node_by_type(NULL, "open-pic"); | |
235 | + if (tsi_pic) { | |
236 | + unsigned int size; | |
237 | + void *prop = get_property(tsi_pic, "reg", &size); | |
238 | + mpic_paddr = of_translate_address(tsi_pic, prop); | |
239 | + } | |
240 | + | |
241 | + if (mpic_paddr == 0) { | |
242 | + printk("%s: No tsi108 PIC found !\n", __FUNCTION__); | |
243 | + return; | |
244 | + } | |
245 | + | |
246 | + DBG("%s: tsi108pic phys_addr = 0x%x\n", __FUNCTION__, | |
247 | + (u32) mpic_paddr); | |
248 | + | |
249 | + mpic = mpic_alloc(mpic_paddr, | |
250 | + MPIC_PRIMARY | MPIC_BIG_ENDIAN | MPIC_WANTS_RESET | | |
251 | + MPIC_SPV_EOI | MPIC_MOD_ID(MPIC_ID_TSI108), | |
252 | + 0, /* num_sources used */ | |
253 | + TSI108_IRQ_BASE, | |
254 | + 0, /* num_sources used */ | |
255 | + NR_IRQS - 4 /* XXXX */, | |
256 | + mpc7448_hpc2_pic_initsenses, | |
257 | + sizeof(mpc7448_hpc2_pic_initsenses), "Tsi108_PIC"); | |
258 | + | |
259 | + BUG_ON(mpic == NULL); /* XXXX */ | |
260 | + | |
261 | + mpic_init(mpic); | |
262 | + mpic_setup_cascade(IRQ_TSI108_PCI, tsi108_irq_cascade, mpic); | |
263 | + tsi108_pci_int_init(); | |
264 | + | |
265 | + /* Configure MPIC outputs to CPU0 */ | |
266 | + tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0); | |
267 | +} | |
268 | + | |
269 | +void mpc7448_hpc2_show_cpuinfo(struct seq_file *m) | |
270 | +{ | |
271 | + seq_printf(m, "vendor\t\t: Freescale Semiconductor\n"); | |
272 | + seq_printf(m, "machine\t\t: MPC7448hpc2\n"); | |
273 | +} | |
274 | + | |
275 | +void mpc7448_hpc2_restart(char *cmd) | |
276 | +{ | |
277 | + local_irq_disable(); | |
278 | + | |
279 | + /* Set exception prefix high - to the firmware */ | |
280 | + _nmask_and_or_msr(0, MSR_IP); | |
281 | + | |
282 | + for (;;) ; /* Spin until reset happens */ | |
283 | +} | |
284 | + | |
285 | +void mpc7448_hpc2_power_off(void) | |
286 | +{ | |
287 | + local_irq_disable(); | |
288 | + for (;;) ; /* No way to shut power off with software */ | |
289 | +} | |
290 | + | |
291 | +void mpc7448_hpc2_halt(void) | |
292 | +{ | |
293 | + mpc7448_hpc2_power_off(); | |
294 | +} | |
295 | + | |
296 | +/* | |
297 | + * Called very early, device-tree isn't unflattened | |
298 | + */ | |
299 | +static int __init mpc7448_hpc2_probe(void) | |
300 | +{ | |
301 | + unsigned long root = of_get_flat_dt_root(); | |
302 | + | |
303 | + if (!of_flat_dt_is_compatible(root, "mpc74xx")) | |
304 | + return 0; | |
305 | + return 1; | |
306 | +} | |
307 | + | |
308 | +static int mpc7448_machine_check_exception(struct pt_regs *regs) | |
309 | +{ | |
310 | + extern void tsi108_clear_pci_cfg_error(void); | |
311 | + const struct exception_table_entry *entry; | |
312 | + | |
313 | + /* Are we prepared to handle this fault */ | |
314 | + if ((entry = search_exception_tables(regs->nip)) != NULL) { | |
315 | + tsi108_clear_pci_cfg_error(); | |
316 | + regs->msr |= MSR_RI; | |
317 | + regs->nip = entry->fixup; | |
318 | + return 1; | |
319 | + } | |
320 | + return 0; | |
321 | + | |
322 | +} | |
323 | +define_machine(mpc7448_hpc2){ | |
324 | + .name = "MPC7448 HPC2", | |
325 | + .probe = mpc7448_hpc2_probe, | |
326 | + .setup_arch = mpc7448_hpc2_setup_arch, | |
327 | + .init_IRQ = mpc7448_hpc2_init_IRQ, | |
328 | + .show_cpuinfo = mpc7448_hpc2_show_cpuinfo, | |
329 | + .get_irq = mpic_get_irq, | |
330 | + .pcibios_fixup = mpc7448_hpc2_pcibios_fixup, | |
331 | + .restart = mpc7448_hpc2_restart, | |
332 | + .calibrate_decr = generic_calibrate_decr, | |
333 | + .machine_check_exception= mpc7448_machine_check_exception, | |
334 | + .progress = udbg_progress, | |
335 | +}; |
arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.h
1 | +/* | |
2 | + * mpc7448_hpc2.h | |
3 | + * | |
4 | + * Definitions for Freescale MPC7448_HPC2 platform | |
5 | + * | |
6 | + * Author: Jacob Pan | |
7 | + * jacob.pan@freescale.com | |
8 | + * Maintainer: Roy Zang <roy.zang@freescale.com> | |
9 | + * | |
10 | + * 2006 (c) Freescale Semiconductor, Inc. This file is licensed under | |
11 | + * the terms of the GNU General Public License version 2. This program | |
12 | + * is licensed "as is" without any warranty of any kind, whether express | |
13 | + * or implied. | |
14 | + */ | |
15 | + | |
16 | +#ifndef __PPC_PLATFORMS_MPC7448_HPC2_H | |
17 | +#define __PPC_PLATFORMS_MPC7448_HPC2_H | |
18 | + | |
19 | +#include <asm/ppcboot.h> | |
20 | + | |
21 | +/* Base Addresses for the PCI bus | |
22 | + */ | |
23 | +#define MPC7448_HPC2_PCI_MEM_OFFSET (0x00000000) | |
24 | +#define MPC7448_HPC2_ISA_IO_BASE (0x00000000) | |
25 | +#define MPC7448_HPC2_ISA_MEM_BASE (0x00000000) | |
26 | +#endif /* __PPC_PLATFORMS_MPC7448_HPC2_H */ |