diff options
author | Roy Zang <tie-fei.zang@freescale.com> | 2007-07-13 06:05:08 -0400 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2007-07-23 23:30:02 -0400 |
commit | f16dab981aa9d423bdfe096e3422acd33d905c1e (patch) | |
tree | aafb0d944784f4a3dd53058d0d111eaa34b48893 /arch/powerpc/platforms | |
parent | 2e56ff206b7c6c28b847ccdbe46ad69b3263ac32 (diff) |
[POWERPC] Add basic PCI/PCI Express support for 8544DS board
Add basic support for the PCIe PHB and enable the ULI bridge.
Signed-off-by: York Sun <yorksun@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/85xx/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/85xx/mpc8544_ds.c | 241 |
2 files changed, 241 insertions, 1 deletions
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index 4661fccdaa5a..99bb74da0760 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
@@ -30,6 +30,7 @@ config MPC85xx_MDS | |||
30 | 30 | ||
31 | config MPC8544_DS | 31 | config MPC8544_DS |
32 | bool "Freescale MPC8544 DS" | 32 | bool "Freescale MPC8544 DS" |
33 | select PPC_I8259 | ||
33 | select DEFAULT_UIMAGE | 34 | select DEFAULT_UIMAGE |
34 | help | 35 | help |
35 | This option enables support for the MPC8544 DS board | 36 | This option enables support for the MPC8544 DS board |
diff --git a/arch/powerpc/platforms/85xx/mpc8544_ds.c b/arch/powerpc/platforms/85xx/mpc8544_ds.c index 6fb90aab879f..4905f6f8903b 100644 --- a/arch/powerpc/platforms/85xx/mpc8544_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8544_ds.c | |||
@@ -2,6 +2,8 @@ | |||
2 | * MPC8544 DS Board Setup | 2 | * MPC8544 DS Board Setup |
3 | * | 3 | * |
4 | * Author Xianghua Xiao (x.xiao@freescale.com) | 4 | * Author Xianghua Xiao (x.xiao@freescale.com) |
5 | * Roy Zang <tie-fei.zang@freescale.com> | ||
6 | * - Add PCI/PCI Exprees support | ||
5 | * Copyright 2007 Freescale Semiconductor Inc. | 7 | * Copyright 2007 Freescale Semiconductor Inc. |
6 | * | 8 | * |
7 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
@@ -12,13 +14,16 @@ | |||
12 | 14 | ||
13 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
14 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/pci.h> | ||
15 | #include <linux/kdev_t.h> | 18 | #include <linux/kdev_t.h> |
16 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
17 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
21 | #include <linux/interrupt.h> | ||
18 | 22 | ||
19 | #include <asm/system.h> | 23 | #include <asm/system.h> |
20 | #include <asm/time.h> | 24 | #include <asm/time.h> |
21 | #include <asm/machdep.h> | 25 | #include <asm/machdep.h> |
26 | #include <asm/pci-bridge.h> | ||
22 | #include <asm/mpc85xx.h> | 27 | #include <asm/mpc85xx.h> |
23 | #include <mm/mmu_decl.h> | 28 | #include <mm/mmu_decl.h> |
24 | #include <asm/prom.h> | 29 | #include <asm/prom.h> |
@@ -27,6 +32,7 @@ | |||
27 | #include <asm/i8259.h> | 32 | #include <asm/i8259.h> |
28 | 33 | ||
29 | #include <sysdev/fsl_soc.h> | 34 | #include <sysdev/fsl_soc.h> |
35 | #include <sysdev/fsl_pci.h> | ||
30 | #include "mpc85xx.h" | 36 | #include "mpc85xx.h" |
31 | 37 | ||
32 | #undef DEBUG | 38 | #undef DEBUG |
@@ -37,6 +43,17 @@ | |||
37 | #define DBG(fmt, args...) | 43 | #define DBG(fmt, args...) |
38 | #endif | 44 | #endif |
39 | 45 | ||
46 | #ifdef CONFIG_PPC_I8259 | ||
47 | static void mpc8544_8259_cascade(unsigned int irq, struct irq_desc *desc) | ||
48 | { | ||
49 | unsigned int cascade_irq = i8259_irq(); | ||
50 | |||
51 | if (cascade_irq != NO_IRQ) { | ||
52 | generic_handle_irq(cascade_irq); | ||
53 | } | ||
54 | desc->chip->eoi(irq); | ||
55 | } | ||
56 | #endif /* CONFIG_PPC_I8259 */ | ||
40 | 57 | ||
41 | void __init mpc8544_ds_pic_init(void) | 58 | void __init mpc8544_ds_pic_init(void) |
42 | { | 59 | { |
@@ -96,19 +113,240 @@ void __init mpc8544_ds_pic_init(void) | |||
96 | #endif /* CONFIG_PPC_I8259 */ | 113 | #endif /* CONFIG_PPC_I8259 */ |
97 | } | 114 | } |
98 | 115 | ||
116 | #ifdef CONFIG_PCI | ||
117 | enum pirq { PIRQA = 8, PIRQB, PIRQC, PIRQD, PIRQE, PIRQF, PIRQG, PIRQH }; | ||
118 | |||
119 | /* | ||
120 | * Value in table -- IRQ number | ||
121 | */ | ||
122 | const unsigned char uli1575_irq_route_table[16] = { | ||
123 | 0, /* 0: Reserved */ | ||
124 | 0x8, | ||
125 | 0, /* 2: Reserved */ | ||
126 | 0x2, | ||
127 | 0x4, | ||
128 | 0x5, | ||
129 | 0x7, | ||
130 | 0x6, | ||
131 | 0, /* 8: Reserved */ | ||
132 | 0x1, | ||
133 | 0x3, | ||
134 | 0x9, | ||
135 | 0xb, | ||
136 | 0, /* 13: Reserved */ | ||
137 | 0xd, | ||
138 | 0xf, | ||
139 | }; | ||
140 | |||
141 | static int __devinit | ||
142 | get_pci_irq_from_of(struct pci_controller *hose, int slot, int pin) | ||
143 | { | ||
144 | struct of_irq oirq; | ||
145 | u32 laddr[3]; | ||
146 | struct device_node *hosenode = hose ? hose->arch_data : NULL; | ||
147 | |||
148 | if (!hosenode) | ||
149 | return -EINVAL; | ||
150 | |||
151 | laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(slot, 0) << 8); | ||
152 | laddr[1] = laddr[2] = 0; | ||
153 | of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq); | ||
154 | DBG("mpc8544_ds: pci irq addr %x, slot %d, pin %d, irq %d\n", | ||
155 | laddr[0], slot, pin, oirq.specifier[0]); | ||
156 | return oirq.specifier[0]; | ||
157 | } | ||
158 | |||
159 | /*8259*/ | ||
160 | static void __devinit quirk_uli1575(struct pci_dev *dev) | ||
161 | { | ||
162 | unsigned short temp; | ||
163 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | ||
164 | unsigned char irq2pin[16]; | ||
165 | unsigned long pirq_map_word = 0; | ||
166 | u32 irq; | ||
167 | int i; | ||
168 | |||
169 | /* | ||
170 | * ULI1575 interrupts route setup | ||
171 | */ | ||
172 | memset(irq2pin, 0, 16); /* Initialize default value 0 */ | ||
173 | |||
174 | irq2pin[6]=PIRQA+3; /* enabled mapping for IRQ6 to PIRQD, used by SATA */ | ||
175 | |||
176 | /* | ||
177 | * PIRQE -> PIRQF mapping set manually | ||
178 | * | ||
179 | * IRQ pin IRQ# | ||
180 | * PIRQE ---- 9 | ||
181 | * PIRQF ---- 10 | ||
182 | * PIRQG ---- 11 | ||
183 | * PIRQH ---- 12 | ||
184 | */ | ||
185 | for (i = 0; i < 4; i++) | ||
186 | irq2pin[i + 9] = PIRQE + i; | ||
187 | |||
188 | /* Set IRQ-PIRQ Mapping to ULI1575 */ | ||
189 | for (i = 0; i < 16; i++) | ||
190 | if (irq2pin[i]) | ||
191 | pirq_map_word |= (uli1575_irq_route_table[i] & 0xf) | ||
192 | << ((irq2pin[i] - PIRQA) * 4); | ||
193 | |||
194 | pirq_map_word |= 1<<26; /* disable INTx in EP mode*/ | ||
195 | |||
196 | /* ULI1575 IRQ mapping conf register default value is 0xb9317542 */ | ||
197 | DBG("Setup ULI1575 IRQ mapping configuration register value = 0x%x\n", | ||
198 | (int)pirq_map_word); | ||
199 | pci_write_config_dword(dev, 0x48, pirq_map_word); | ||
200 | |||
201 | #define ULI1575_SET_DEV_IRQ(slot, pin, reg) \ | ||
202 | do { \ | ||
203 | int irq; \ | ||
204 | irq = get_pci_irq_from_of(hose, slot, pin); \ | ||
205 | if (irq > 0 && irq < 16) \ | ||
206 | pci_write_config_byte(dev, reg, irq2pin[irq]); \ | ||
207 | else \ | ||
208 | printk(KERN_WARNING "ULI1575 device" \ | ||
209 | "(slot %d, pin %d) irq %d is invalid.\n", \ | ||
210 | slot, pin, irq); \ | ||
211 | } while(0) | ||
212 | |||
213 | /* USB 1.1 OHCI controller 1, slot 28, pin 1 */ | ||
214 | ULI1575_SET_DEV_IRQ(28, 1, 0x86); | ||
215 | |||
216 | /* USB 1.1 OHCI controller 2, slot 28, pin 2 */ | ||
217 | ULI1575_SET_DEV_IRQ(28, 2, 0x87); | ||
218 | |||
219 | /* USB 1.1 OHCI controller 3, slot 28, pin 3 */ | ||
220 | ULI1575_SET_DEV_IRQ(28, 3, 0x88); | ||
221 | |||
222 | /* USB 2.0 controller, slot 28, pin 4 */ | ||
223 | irq = get_pci_irq_from_of(hose, 28, 4); | ||
224 | if (irq >= 0 && irq <= 15) | ||
225 | pci_write_config_dword(dev, 0x74, uli1575_irq_route_table[irq]); | ||
226 | |||
227 | /* Audio controller, slot 29, pin 1 */ | ||
228 | ULI1575_SET_DEV_IRQ(29, 1, 0x8a); | ||
229 | |||
230 | /* Modem controller, slot 29, pin 2 */ | ||
231 | ULI1575_SET_DEV_IRQ(29, 2, 0x8b); | ||
232 | |||
233 | /* HD audio controller, slot 29, pin 3 */ | ||
234 | ULI1575_SET_DEV_IRQ(29, 3, 0x8c); | ||
235 | |||
236 | /* SMB interrupt: slot 30, pin 1 */ | ||
237 | ULI1575_SET_DEV_IRQ(30, 1, 0x8e); | ||
238 | |||
239 | /* PMU ACPI SCI interrupt: slot 30, pin 2 */ | ||
240 | ULI1575_SET_DEV_IRQ(30, 2, 0x8f); | ||
241 | |||
242 | /* Serial ATA interrupt: slot 31, pin 1 */ | ||
243 | ULI1575_SET_DEV_IRQ(31, 1, 0x8d); | ||
244 | |||
245 | /* Primary PATA IDE IRQ: 14 | ||
246 | * Secondary PATA IDE IRQ: 15 | ||
247 | */ | ||
248 | pci_write_config_byte(dev, 0x44, 0x30 | uli1575_irq_route_table[14]); | ||
249 | pci_write_config_byte(dev, 0x75, uli1575_irq_route_table[15]); | ||
250 | |||
251 | /* Set IRQ14 and IRQ15 to legacy IRQs */ | ||
252 | pci_read_config_word(dev, 0x46, &temp); | ||
253 | temp |= 0xc000; | ||
254 | pci_write_config_word(dev, 0x46, temp); | ||
255 | |||
256 | /* Set i8259 interrupt trigger | ||
257 | * IRQ 3: Level | ||
258 | * IRQ 4: Level | ||
259 | * IRQ 5: Level | ||
260 | * IRQ 6: Level | ||
261 | * IRQ 7: Level | ||
262 | * IRQ 9: Level | ||
263 | * IRQ 10: Level | ||
264 | * IRQ 11: Level | ||
265 | * IRQ 12: Level | ||
266 | * IRQ 14: Edge | ||
267 | * IRQ 15: Edge | ||
268 | */ | ||
269 | outb(0xfa, 0x4d0); | ||
270 | outb(0x1e, 0x4d1); | ||
271 | |||
272 | #undef ULI1575_SET_DEV_IRQ | ||
273 | } | ||
274 | |||
275 | /* SATA */ | ||
276 | static void __devinit quirk_uli5288(struct pci_dev *dev) | ||
277 | { | ||
278 | unsigned char c; | ||
279 | |||
280 | pci_read_config_byte(dev, 0x83, &c); | ||
281 | c |= 0x80; /* read/write lock */ | ||
282 | pci_write_config_byte(dev, 0x83, c); | ||
283 | |||
284 | pci_write_config_byte(dev, 0x09, 0x01); /* Base class code: storage */ | ||
285 | pci_write_config_byte(dev, 0x0a, 0x06); /* IDE disk */ | ||
286 | |||
287 | pci_read_config_byte(dev, 0x83, &c); | ||
288 | c &= 0x7f; | ||
289 | pci_write_config_byte(dev, 0x83, c); | ||
290 | |||
291 | pci_read_config_byte(dev, 0x84, &c); | ||
292 | c |= 0x01; /* emulated PATA mode enabled */ | ||
293 | pci_write_config_byte(dev, 0x84, c); | ||
294 | } | ||
295 | |||
296 | /* PATA */ | ||
297 | static void __devinit quirk_uli5229(struct pci_dev *dev) | ||
298 | { | ||
299 | unsigned short temp; | ||
300 | pci_write_config_word(dev, 0x04, 0x0405); /* MEM IO MSI */ | ||
301 | pci_read_config_word(dev, 0x4a, &temp); | ||
302 | temp |= 0x1000; /* Enable Native IRQ 14/15 */ | ||
303 | pci_write_config_word(dev, 0x4a, temp); | ||
304 | } | ||
305 | |||
306 | /*Bridge*/ | ||
307 | static void __devinit early_uli5249(struct pci_dev *dev) | ||
308 | { | ||
309 | unsigned char temp; | ||
310 | pci_write_config_word(dev, 0x04, 0x0007); /* mem access */ | ||
311 | pci_read_config_byte(dev, 0x7c, &temp); | ||
312 | pci_write_config_byte(dev, 0x7c, 0x80); /* R/W lock control */ | ||
313 | pci_write_config_byte(dev, 0x09, 0x01); /* set as pci-pci bridge */ | ||
314 | pci_write_config_byte(dev, 0x7c, temp); /* restore pci bus debug control */ | ||
315 | dev->class |= 0x1; | ||
316 | } | ||
317 | |||
318 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, quirk_uli1575); | ||
319 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5288, quirk_uli5288); | ||
320 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x5229, quirk_uli5229); | ||
321 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_AL, 0x5249, early_uli5249); | ||
322 | #endif /* CONFIG_PCI */ | ||
99 | 323 | ||
100 | /* | 324 | /* |
101 | * Setup the architecture | 325 | * Setup the architecture |
102 | */ | 326 | */ |
103 | static void __init mpc8544_ds_setup_arch(void) | 327 | static void __init mpc8544_ds_setup_arch(void) |
104 | { | 328 | { |
329 | #ifdef CONFIG_PCI | ||
330 | struct device_node *np; | ||
331 | #endif | ||
332 | |||
105 | if (ppc_md.progress) | 333 | if (ppc_md.progress) |
106 | ppc_md.progress("mpc8544_ds_setup_arch()", 0); | 334 | ppc_md.progress("mpc8544_ds_setup_arch()", 0); |
107 | 335 | ||
336 | #ifdef CONFIG_PCI | ||
337 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) { | ||
338 | struct resource rsrc; | ||
339 | of_address_to_resource(np, 0, &rsrc); | ||
340 | if ((rsrc.start & 0xfffff) == 0xb000) | ||
341 | fsl_add_bridge(np, 1); | ||
342 | else | ||
343 | fsl_add_bridge(np, 0); | ||
344 | } | ||
345 | #endif | ||
346 | |||
108 | printk("MPC8544 DS board from Freescale Semiconductor\n"); | 347 | printk("MPC8544 DS board from Freescale Semiconductor\n"); |
109 | } | 348 | } |
110 | 349 | ||
111 | |||
112 | /* | 350 | /* |
113 | * Called very early, device-tree isn't unflattened | 351 | * Called very early, device-tree isn't unflattened |
114 | */ | 352 | */ |
@@ -124,6 +362,7 @@ define_machine(mpc8544_ds) { | |||
124 | .probe = mpc8544_ds_probe, | 362 | .probe = mpc8544_ds_probe, |
125 | .setup_arch = mpc8544_ds_setup_arch, | 363 | .setup_arch = mpc8544_ds_setup_arch, |
126 | .init_IRQ = mpc8544_ds_pic_init, | 364 | .init_IRQ = mpc8544_ds_pic_init, |
365 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
127 | .get_irq = mpic_get_irq, | 366 | .get_irq = mpic_get_irq, |
128 | .restart = mpc85xx_restart, | 367 | .restart = mpc85xx_restart, |
129 | .calibrate_decr = generic_calibrate_decr, | 368 | .calibrate_decr = generic_calibrate_decr, |