Commit | Line | Data |
---|---|---|
63dafe57 BB |
1 | /* |
2 | * MPC85xx setup and early boot code plus other random bits. | |
3 | * | |
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | |
5 | * | |
6 | * Copyright 2005 Freescale Semiconductor Inc. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify it | |
9 | * under the terms of the GNU General Public License as published by the | |
10 | * Free Software Foundation; either version 2 of the License, or (at your | |
11 | * option) any later version. | |
12 | */ | |
13 | ||
63dafe57 BB |
14 | #include <linux/stddef.h> |
15 | #include <linux/kernel.h> | |
63dafe57 BB |
16 | #include <linux/pci.h> |
17 | #include <linux/kdev_t.h> | |
63dafe57 | 18 | #include <linux/delay.h> |
63dafe57 | 19 | #include <linux/seq_file.h> |
63dafe57 BB |
20 | |
21 | #include <asm/system.h> | |
63dafe57 | 22 | #include <asm/time.h> |
63dafe57 | 23 | #include <asm/machdep.h> |
63dafe57 BB |
24 | #include <asm/pci-bridge.h> |
25 | #include <asm/mpc85xx.h> | |
63dafe57 BB |
26 | #include <asm/prom.h> |
27 | #include <asm/mpic.h> | |
28 | #include <mm/mmu_decl.h> | |
29 | #include <asm/udbg.h> | |
30 | ||
31 | #include <sysdev/fsl_soc.h> | |
32 | #include "mpc85xx.h" | |
33 | ||
902f392d | 34 | #ifdef CONFIG_CPM2 |
d3465c92 | 35 | #include <linux/fs_enet_pd.h> |
902f392d VB |
36 | #include <asm/cpm2.h> |
37 | #include <sysdev/cpm2_pic.h> | |
38 | #include <asm/fs_pd.h> | |
39 | #endif | |
40 | ||
8080d549 | 41 | #ifdef CONFIG_PCI |
7d52c7b0 KG |
42 | static int mpc85xx_exclude_device(struct pci_controller *hose, |
43 | u_char bus, u_char devfn) | |
8080d549 AF |
44 | { |
45 | if (bus == 0 && PCI_SLOT(devfn) == 0) | |
46 | return PCIBIOS_DEVICE_NOT_FOUND; | |
47 | else | |
48 | return PCIBIOS_SUCCESSFUL; | |
49 | } | |
8080d549 AF |
50 | #endif /* CONFIG_PCI */ |
51 | ||
902f392d VB |
52 | #ifdef CONFIG_CPM2 |
53 | ||
35a84c2f | 54 | static void cpm2_cascade(unsigned int irq, struct irq_desc *desc) |
902f392d VB |
55 | { |
56 | int cascade_irq; | |
57 | ||
35a84c2f | 58 | while ((cascade_irq = cpm2_get_irq()) >= 0) { |
49f19ce4 | 59 | generic_handle_irq(cascade_irq); |
902f392d VB |
60 | } |
61 | desc->chip->eoi(irq); | |
62 | } | |
63 | ||
64 | #endif /* CONFIG_CPM2 */ | |
8080d549 | 65 | |
27630bec | 66 | static void __init mpc85xx_ads_pic_init(void) |
63dafe57 | 67 | { |
4c86cd9c AF |
68 | struct mpic *mpic; |
69 | struct resource r; | |
70 | struct device_node *np = NULL; | |
902f392d VB |
71 | #ifdef CONFIG_CPM2 |
72 | int irq; | |
73 | #endif | |
4c86cd9c AF |
74 | |
75 | np = of_find_node_by_type(np, "open-pic"); | |
76 | ||
77 | if (np == NULL) { | |
78 | printk(KERN_ERR "Could not find open-pic node\n"); | |
79 | return; | |
80 | } | |
81 | ||
82 | if(of_address_to_resource(np, 0, &r)) { | |
83 | printk(KERN_ERR "Could not map mpic register space\n"); | |
84 | of_node_put(np); | |
85 | return; | |
86 | } | |
87 | ||
88 | mpic = mpic_alloc(np, r.start, | |
89 | MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN, | |
b533f8ae | 90 | 0, 256, " OpenPIC "); |
4c86cd9c AF |
91 | BUG_ON(mpic == NULL); |
92 | of_node_put(np); | |
93 | ||
4c86cd9c | 94 | mpic_init(mpic); |
902f392d VB |
95 | |
96 | #ifdef CONFIG_CPM2 | |
97 | /* Setup CPM2 PIC */ | |
98 | np = of_find_node_by_type(NULL, "cpm-pic"); | |
99 | if (np == NULL) { | |
100 | printk(KERN_ERR "PIC init: can not find cpm-pic node\n"); | |
101 | return; | |
102 | } | |
103 | irq = irq_of_parse_and_map(np, 0); | |
104 | ||
105 | cpm2_pic_init(np); | |
106 | set_irq_chained_handler(irq, cpm2_cascade); | |
107 | #endif | |
63dafe57 BB |
108 | } |
109 | ||
63dafe57 BB |
110 | /* |
111 | * Setup the architecture | |
112 | */ | |
902f392d | 113 | #ifdef CONFIG_CPM2 |
d3465c92 | 114 | void init_fcc_ioports(struct fs_platform_info *fpi) |
902f392d | 115 | { |
d3465c92 VB |
116 | struct io_port *io = cpm2_map(im_ioport); |
117 | int fcc_no = fs_get_fcc_index(fpi->fs_no); | |
118 | int target; | |
902f392d VB |
119 | u32 tempval; |
120 | ||
d3465c92 VB |
121 | switch(fcc_no) { |
122 | case 1: | |
123 | tempval = in_be32(&io->iop_pdirb); | |
124 | tempval &= ~PB2_DIRB0; | |
125 | tempval |= PB2_DIRB1; | |
126 | out_be32(&io->iop_pdirb, tempval); | |
127 | ||
128 | tempval = in_be32(&io->iop_psorb); | |
129 | tempval &= ~PB2_PSORB0; | |
130 | tempval |= PB2_PSORB1; | |
131 | out_be32(&io->iop_psorb, tempval); | |
132 | ||
133 | tempval = in_be32(&io->iop_pparb); | |
134 | tempval |= (PB2_DIRB0 | PB2_DIRB1); | |
135 | out_be32(&io->iop_pparb, tempval); | |
136 | ||
137 | target = CPM_CLK_FCC2; | |
138 | break; | |
139 | case 2: | |
140 | tempval = in_be32(&io->iop_pdirb); | |
141 | tempval &= ~PB3_DIRB0; | |
142 | tempval |= PB3_DIRB1; | |
143 | out_be32(&io->iop_pdirb, tempval); | |
144 | ||
145 | tempval = in_be32(&io->iop_psorb); | |
146 | tempval &= ~PB3_PSORB0; | |
147 | tempval |= PB3_PSORB1; | |
148 | out_be32(&io->iop_psorb, tempval); | |
149 | ||
150 | tempval = in_be32(&io->iop_pparb); | |
151 | tempval |= (PB3_DIRB0 | PB3_DIRB1); | |
152 | out_be32(&io->iop_pparb, tempval); | |
153 | ||
154 | tempval = in_be32(&io->iop_pdirc); | |
155 | tempval |= PC3_DIRC1; | |
156 | out_be32(&io->iop_pdirc, tempval); | |
157 | ||
158 | tempval = in_be32(&io->iop_pparc); | |
159 | tempval |= PC3_DIRC1; | |
160 | out_be32(&io->iop_pparc, tempval); | |
161 | ||
162 | target = CPM_CLK_FCC3; | |
163 | break; | |
164 | default: | |
165 | printk(KERN_ERR "init_fcc_ioports: invalid FCC number\n"); | |
166 | return; | |
167 | } | |
902f392d VB |
168 | |
169 | /* Port C has clocks...... */ | |
170 | tempval = in_be32(&io->iop_psorc); | |
d3465c92 | 171 | tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8)); |
902f392d VB |
172 | out_be32(&io->iop_psorc, tempval); |
173 | ||
174 | tempval = in_be32(&io->iop_pdirc); | |
d3465c92 | 175 | tempval &= ~(PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8)); |
902f392d VB |
176 | out_be32(&io->iop_pdirc, tempval); |
177 | tempval = in_be32(&io->iop_pparc); | |
d3465c92 | 178 | tempval |= (PC_CLK(fpi->clk_rx - 8) | PC_CLK(fpi->clk_tx - 8)); |
902f392d VB |
179 | out_be32(&io->iop_pparc, tempval); |
180 | ||
d3465c92 VB |
181 | cpm2_unmap(io); |
182 | ||
902f392d | 183 | /* Configure Serial Interface clock routing. |
d3465c92 | 184 | * First, clear FCC bits to zero, |
902f392d VB |
185 | * then set the ones we want. |
186 | */ | |
d3465c92 VB |
187 | cpm2_clk_setup(target, fpi->clk_rx, CPM_CLK_RX); |
188 | cpm2_clk_setup(target, fpi->clk_tx, CPM_CLK_TX); | |
902f392d VB |
189 | } |
190 | #endif | |
191 | ||
fbc94e7c | 192 | static void __init mpc85xx_ads_setup_arch(void) |
63dafe57 BB |
193 | { |
194 | struct device_node *cpu; | |
4c86cd9c | 195 | #ifdef CONFIG_PCI |
8080d549 | 196 | struct device_node *np; |
4c86cd9c | 197 | #endif |
63dafe57 BB |
198 | |
199 | if (ppc_md.progress) | |
200 | ppc_md.progress("mpc85xx_ads_setup_arch()", 0); | |
201 | ||
202 | cpu = of_find_node_by_type(NULL, "cpu"); | |
203 | if (cpu != 0) { | |
8efca493 | 204 | const unsigned int *fp; |
63dafe57 | 205 | |
e2eb6392 | 206 | fp = of_get_property(cpu, "clock-frequency", NULL); |
63dafe57 BB |
207 | if (fp != 0) |
208 | loops_per_jiffy = *fp / HZ; | |
209 | else | |
210 | loops_per_jiffy = 50000000 / HZ; | |
211 | of_node_put(cpu); | |
212 | } | |
8080d549 | 213 | |
902f392d VB |
214 | #ifdef CONFIG_CPM2 |
215 | cpm2_reset(); | |
902f392d VB |
216 | #endif |
217 | ||
8080d549 AF |
218 | #ifdef CONFIG_PCI |
219 | for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;) | |
09b55f76 | 220 | mpc85xx_add_bridge(np); |
8080d549 AF |
221 | ppc_md.pci_exclude_device = mpc85xx_exclude_device; |
222 | #endif | |
63dafe57 BB |
223 | } |
224 | ||
27630bec | 225 | static void mpc85xx_ads_show_cpuinfo(struct seq_file *m) |
63dafe57 BB |
226 | { |
227 | uint pvid, svid, phid1; | |
228 | uint memsize = total_memory; | |
229 | ||
230 | pvid = mfspr(SPRN_PVR); | |
231 | svid = mfspr(SPRN_SVR); | |
232 | ||
233 | seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n"); | |
234 | seq_printf(m, "Machine\t\t: mpc85xx\n"); | |
235 | seq_printf(m, "PVR\t\t: 0x%x\n", pvid); | |
236 | seq_printf(m, "SVR\t\t: 0x%x\n", svid); | |
237 | ||
238 | /* Display cpu Pll setting */ | |
239 | phid1 = mfspr(SPRN_HID1); | |
240 | seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f)); | |
241 | ||
242 | /* Display the amount of memory */ | |
243 | seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024)); | |
244 | } | |
245 | ||
72d2c3e0 KG |
246 | /* |
247 | * Called very early, device-tree isn't unflattened | |
248 | */ | |
249 | static int __init mpc85xx_ads_probe(void) | |
63dafe57 | 250 | { |
6936c625 KG |
251 | unsigned long root = of_get_flat_dt_root(); |
252 | ||
253 | return of_flat_dt_is_compatible(root, "MPC85xxADS"); | |
63dafe57 | 254 | } |
72d2c3e0 KG |
255 | |
256 | define_machine(mpc85xx_ads) { | |
257 | .name = "MPC85xx ADS", | |
258 | .probe = mpc85xx_ads_probe, | |
259 | .setup_arch = mpc85xx_ads_setup_arch, | |
260 | .init_IRQ = mpc85xx_ads_pic_init, | |
261 | .show_cpuinfo = mpc85xx_ads_show_cpuinfo, | |
262 | .get_irq = mpic_get_irq, | |
263 | .restart = mpc85xx_restart, | |
264 | .calibrate_decr = generic_calibrate_decr, | |
265 | .progress = udbg_progress, | |
266 | }; |