2 * MPC86xx HPCN board specific routines
4 * Recode: ZHANG WEI <wei.zhang@freescale.com>
5 * Initial author: Xianghua Xiao <x.xiao@freescale.com>
7 * Copyright 2006 Freescale Semiconductor Inc.
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
15 #include <linux/stddef.h>
16 #include <linux/kernel.h>
17 #include <linux/pci.h>
18 #include <linux/kdev_t.h>
19 #include <linux/delay.h>
20 #include <linux/seq_file.h>
21 #include <linux/root_dev.h>
23 #include <asm/system.h>
25 #include <asm/machdep.h>
26 #include <asm/pci-bridge.h>
27 #include <asm/mpc86xx.h>
29 #include <mm/mmu_decl.h>
31 #include <asm/i8259.h>
35 #include <sysdev/fsl_soc.h>
40 unsigned long isa_io_base
= 0;
41 unsigned long isa_mem_base
= 0;
42 unsigned long pci_dram_offset
= 0;
47 * Internal interrupts are all Level Sensitive, and Positive Polarity
50 static u_char mpc86xx_hpcn_openpic_initsenses
[] __initdata
= {
51 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 0: Reserved */
52 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 1: MCM */
53 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 2: DDR DRAM */
54 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 3: LBIU */
55 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 4: DMA 0 */
56 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 5: DMA 1 */
57 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 6: DMA 2 */
58 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 7: DMA 3 */
59 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 8: PCIE1 */
60 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 9: PCIE2 */
61 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 10: Reserved */
62 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 11: Reserved */
63 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 12: DUART2 */
64 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 13: TSEC 1 Transmit */
65 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 14: TSEC 1 Receive */
66 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 15: TSEC 3 transmit */
67 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 16: TSEC 3 receive */
68 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 17: TSEC 3 error */
69 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 18: TSEC 1 Receive/Transmit Error */
70 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 19: TSEC 2 Transmit */
71 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 20: TSEC 2 Receive */
72 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 21: TSEC 4 transmit */
73 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 22: TSEC 4 receive */
74 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 23: TSEC 4 error */
75 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 24: TSEC 2 Receive/Transmit Error */
76 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 25: Unused */
77 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 26: DUART1 */
78 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 27: I2C */
79 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 28: Performance Monitor */
80 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 29: Unused */
81 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 30: Unused */
82 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 31: Unused */
83 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 32: SRIO error/write-port unit */
84 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 33: SRIO outbound doorbell */
85 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 34: SRIO inbound doorbell */
86 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 35: Unused */
87 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 36: Unused */
88 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 37: SRIO outbound message unit 1 */
89 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 38: SRIO inbound message unit 1 */
90 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 39: SRIO outbound message unit 2 */
91 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 40: SRIO inbound message unit 2 */
92 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 41: Unused */
93 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 42: Unused */
94 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 43: Unused */
95 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 44: Unused */
96 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 45: Unused */
97 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 46: Unused */
98 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* Internal 47: Unused */
99 0x0, /* External 0: */
100 0x0, /* External 1: */
101 0x0, /* External 2: */
102 0x0, /* External 3: */
103 0x0, /* External 4: */
104 0x0, /* External 5: */
105 0x0, /* External 6: */
106 0x0, /* External 7: */
107 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_NEGATIVE
), /* External 8: Pixis FPGA */
108 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_POSITIVE
), /* External 9: ULI 8259 INTR Cascade */
109 (IRQ_SENSE_LEVEL
| IRQ_POLARITY_NEGATIVE
), /* External 10: Quad ETH PHY */
110 0x0, /* External 11: */
119 mpc86xx_hpcn_init_irq(void)
122 phys_addr_t openpic_paddr
;
124 /* Determine the Physical Address of the OpenPIC regs */
125 openpic_paddr
= get_immrbase() + MPC86xx_OPENPIC_OFFSET
;
127 /* Alloc mpic structure and per isu has 16 INT entries. */
128 mpic1
= mpic_alloc(openpic_paddr
,
129 MPIC_PRIMARY
| MPIC_WANTS_RESET
| MPIC_BIG_ENDIAN
,
130 16, MPC86xx_OPENPIC_IRQ_OFFSET
, 0, 250,
131 mpc86xx_hpcn_openpic_initsenses
,
132 sizeof(mpc86xx_hpcn_openpic_initsenses
),
134 BUG_ON(mpic1
== NULL
);
136 /* 48 Internal Interrupts */
137 mpic_assign_isu(mpic1
, 0, openpic_paddr
+ 0x10200);
138 mpic_assign_isu(mpic1
, 1, openpic_paddr
+ 0x10400);
139 mpic_assign_isu(mpic1
, 2, openpic_paddr
+ 0x10600);
141 /* 16 External interrupts */
142 mpic_assign_isu(mpic1
, 3, openpic_paddr
+ 0x10000);
147 mpic_setup_cascade(MPC86xx_IRQ_EXT9
, i8259_irq_cascade
, NULL
);
148 i8259_init(0, I8259_OFFSET
);
160 mpc86xx_map_irq(struct pci_dev
*dev
, unsigned char idsel
, unsigned char pin
)
162 static char pci_irq_table
[][4] = {
164 * PCI IDSEL/INTPIN->INTLINE
167 {PIRQA
, PIRQB
, PIRQC
, PIRQD
}, /* IDSEL 17 -- PCI Slot 1 */
168 {PIRQB
, PIRQC
, PIRQD
, PIRQA
}, /* IDSEL 18 -- PCI Slot 2 */
169 {0, 0, 0, 0}, /* IDSEL 19 */
170 {0, 0, 0, 0}, /* IDSEL 20 */
171 {0, 0, 0, 0}, /* IDSEL 21 */
172 {0, 0, 0, 0}, /* IDSEL 22 */
173 {0, 0, 0, 0}, /* IDSEL 23 */
174 {0, 0, 0, 0}, /* IDSEL 24 */
175 {0, 0, 0, 0}, /* IDSEL 25 */
176 {PIRQD
, PIRQA
, PIRQB
, PIRQC
}, /* IDSEL 26 -- PCI Bridge*/
177 {PIRQC
, 0, 0, 0}, /* IDSEL 27 -- LAN */
178 {PIRQE
, PIRQF
, PIRQH
, PIRQ7
}, /* IDSEL 28 -- USB 1.1 */
179 {PIRQE
, PIRQF
, PIRQG
, 0}, /* IDSEL 29 -- Audio & Modem */
180 {PIRQH
, 0, 0, 0}, /* IDSEL 30 -- LPC & PMU*/
181 {PIRQD
, 0, 0, 0}, /* IDSEL 31 -- ATA */
184 const long min_idsel
= 17, max_idsel
= 31, irqs_per_slot
= 4;
185 return PCI_IRQ_TABLE_LOOKUP
+ I8259_OFFSET
;
190 mpc86xx_exclude_device(u_char bus
, u_char devfn
)
192 #if !defined(CONFIG_PCI)
193 if (bus
== 0 && PCI_SLOT(devfn
) == 0)
194 return PCIBIOS_DEVICE_NOT_FOUND
;
197 return PCIBIOS_SUCCESSFUL
;
199 #endif /* CONFIG_PCI */
203 mpc86xx_hpcn_setup_arch(void)
205 struct device_node
*np
;
208 ppc_md
.progress("mpc86xx_hpcn_setup_arch()", 0);
210 np
= of_find_node_by_type(NULL
, "cpu");
214 fp
= (int *)get_property(np
, "clock-frequency", NULL
);
216 loops_per_jiffy
= *fp
/ HZ
;
218 loops_per_jiffy
= 50000000 / HZ
;
223 for (np
= NULL
; (np
= of_find_node_by_type(np
, "pci")) != NULL
;)
226 ppc_md
.pci_swizzle
= common_swizzle
;
227 ppc_md
.pci_map_irq
= mpc86xx_map_irq
;
228 ppc_md
.pci_exclude_device
= mpc86xx_exclude_device
;
231 printk("MPC86xx HPCN board from Freescale Semiconductor\n");
233 #ifdef CONFIG_ROOT_NFS
236 ROOT_DEV
= Root_HDA1
;
246 mpc86xx_hpcn_show_cpuinfo(struct seq_file
*m
)
248 struct device_node
*root
;
249 uint memsize
= total_memory
;
250 const char *model
= "";
251 uint svid
= mfspr(SPRN_SVR
);
253 seq_printf(m
, "Vendor\t\t: Freescale Semiconductor\n");
255 root
= of_find_node_by_path("/");
257 model
= get_property(root
, "model", NULL
);
258 seq_printf(m
, "Machine\t\t: %s\n", model
);
261 seq_printf(m
, "SVR\t\t: 0x%x\n", svid
);
262 seq_printf(m
, "Memory\t\t: %d MB\n", memsize
/ (1024 * 1024));
267 * Called very early, device-tree isn't unflattened
269 static int __init
mpc86xx_hpcn_probe(void)
271 unsigned long root
= of_get_flat_dt_root();
273 if (of_flat_dt_is_compatible(root
, "mpc86xx"))
274 return 1; /* Looks good */
281 mpc86xx_restart(char *cmd
)
285 rstcr
= ioremap(get_immrbase() + MPC86XX_RSTCR_OFFSET
, 0x100);
289 /* Assert reset request to Reset Control Register */
290 out_be32(rstcr
, 0x2);
297 mpc86xx_time_init(void)
301 /* Set the time base to zero */
305 temp
= mfspr(SPRN_HID0
);
307 mtspr(SPRN_HID0
, temp
);
308 asm volatile("isync");
314 define_machine(mpc86xx_hpcn
) {
315 .name
= "MPC86xx HPCN",
316 .probe
= mpc86xx_hpcn_probe
,
317 .setup_arch
= mpc86xx_hpcn_setup_arch
,
318 .init_IRQ
= mpc86xx_hpcn_init_irq
,
319 .show_cpuinfo
= mpc86xx_hpcn_show_cpuinfo
,
320 .get_irq
= mpic_get_irq
,
321 .restart
= mpc86xx_restart
,
322 .time_init
= mpc86xx_time_init
,
323 .calibrate_decr
= generic_calibrate_decr
,
324 .progress
= udbg_progress
,