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