Merge branch 'upstream-greg' of gregkh@master.kernel.org:/pub/scm/linux/kernel/git...
[pandora-kernel.git] / arch / ppc / platforms / 85xx / mpc8560_ads.c
1 /*
2  * MPC8560ADS board specific routines
3  *
4  * Maintainer: Kumar Gala <galak@kernel.crashing.org>
5  *
6  * Copyright 2004 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/init.h>
17 #include <linux/errno.h>
18 #include <linux/reboot.h>
19 #include <linux/pci.h>
20 #include <linux/kdev_t.h>
21 #include <linux/major.h>
22 #include <linux/console.h>
23 #include <linux/delay.h>
24 #include <linux/seq_file.h>
25 #include <linux/root_dev.h>
26 #include <linux/serial.h>
27 #include <linux/tty.h>  /* for linux/serial_core.h */
28 #include <linux/serial_core.h>
29 #include <linux/initrd.h>
30 #include <linux/module.h>
31 #include <linux/fsl_devices.h>
32 #include <linux/fs_enet_pd.h>
33
34 #include <asm/system.h>
35 #include <asm/pgtable.h>
36 #include <asm/page.h>
37 #include <asm/atomic.h>
38 #include <asm/time.h>
39 #include <asm/io.h>
40 #include <asm/machdep.h>
41 #include <asm/open_pic.h>
42 #include <asm/bootinfo.h>
43 #include <asm/pci-bridge.h>
44 #include <asm/mpc85xx.h>
45 #include <asm/irq.h>
46 #include <asm/immap_85xx.h>
47 #include <asm/kgdb.h>
48 #include <asm/ppc_sys.h>
49 #include <asm/cpm2.h>
50 #include <mm/mmu_decl.h>
51
52 #include <syslib/cpm2_pic.h>
53 #include <syslib/ppc85xx_common.h>
54 #include <syslib/ppc85xx_setup.h>
55
56
57 /* ************************************************************************
58  *
59  * Setup the architecture
60  *
61  */
62 static void init_fcc_ioports(void)
63 {
64         struct immap *immap;
65         struct io_port *io;
66         u32 tempval;
67
68         immap = cpm2_immr;
69
70         io = &immap->im_ioport;
71         /* FCC2/3 are on the ports B/C. */
72         tempval = in_be32(&io->iop_pdirb);
73         tempval &= ~PB2_DIRB0;
74         tempval |= PB2_DIRB1;
75         out_be32(&io->iop_pdirb, tempval);
76
77         tempval = in_be32(&io->iop_psorb);
78         tempval &= ~PB2_PSORB0;
79         tempval |= PB2_PSORB1;
80         out_be32(&io->iop_psorb, tempval);
81
82         tempval = in_be32(&io->iop_pparb);
83         tempval |= (PB2_DIRB0 | PB2_DIRB1);
84         out_be32(&io->iop_pparb, tempval);
85
86         tempval = in_be32(&io->iop_pdirb);
87         tempval &= ~PB3_DIRB0;
88         tempval |= PB3_DIRB1;
89         out_be32(&io->iop_pdirb, tempval);
90
91         tempval = in_be32(&io->iop_psorb);
92         tempval &= ~PB3_PSORB0;
93         tempval |= PB3_PSORB1;
94         out_be32(&io->iop_psorb, tempval);
95
96         tempval = in_be32(&io->iop_pparb);
97         tempval |= (PB3_DIRB0 | PB3_DIRB1);
98         out_be32(&io->iop_pparb, tempval);
99
100         tempval = in_be32(&io->iop_pdirc);
101         tempval |= PC3_DIRC1;
102         out_be32(&io->iop_pdirc, tempval);
103
104         tempval = in_be32(&io->iop_pparc);
105         tempval |= PC3_DIRC1;
106         out_be32(&io->iop_pparc, tempval);
107
108         /* Port C has clocks......  */
109         tempval = in_be32(&io->iop_psorc);
110         tempval &= ~(CLK_TRX);
111         out_be32(&io->iop_psorc, tempval);
112
113         tempval = in_be32(&io->iop_pdirc);
114         tempval &= ~(CLK_TRX);
115         out_be32(&io->iop_pdirc, tempval);
116         tempval = in_be32(&io->iop_pparc);
117         tempval |= (CLK_TRX);
118         out_be32(&io->iop_pparc, tempval);
119
120         /* Configure Serial Interface clock routing.
121          * First,  clear all FCC bits to zero,
122          * then set the ones we want.
123          */
124         immap->im_cpmux.cmx_fcr &= ~(CPMUX_CLK_MASK);
125         immap->im_cpmux.cmx_fcr |= CPMUX_CLK_ROUTE;
126 }
127
128 static void __init
129 mpc8560ads_setup_arch(void)
130 {
131         bd_t *binfo = (bd_t *) __res;
132         unsigned int freq;
133         struct gianfar_platform_data *pdata;
134         struct gianfar_mdio_data *mdata;
135         struct fs_platform_info *fpi;
136
137         cpm2_reset();
138
139         /* get the core frequency */
140         freq = binfo->bi_intfreq;
141
142         if (ppc_md.progress)
143                 ppc_md.progress("mpc8560ads_setup_arch()", 0);
144
145         /* Set loops_per_jiffy to a half-way reasonable value,
146            for use until calibrate_delay gets called. */
147         loops_per_jiffy = freq / HZ;
148
149 #ifdef CONFIG_PCI
150         /* setup PCI host bridges */
151         mpc85xx_setup_hose();
152 #endif
153
154         /* setup the board related info for the MDIO bus */
155         mdata = (struct gianfar_mdio_data *) ppc_sys_get_pdata(MPC85xx_MDIO);
156
157         mdata->irq[0] = MPC85xx_IRQ_EXT5;
158         mdata->irq[1] = MPC85xx_IRQ_EXT5;
159         mdata->irq[2] = -1;
160         mdata->irq[3] = MPC85xx_IRQ_EXT5;
161         mdata->irq[31] = -1;
162
163         /* setup the board related information for the enet controllers */
164         pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
165         if (pdata) {
166                 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
167                 pdata->bus_id = 0;
168                 pdata->phy_id = 0;
169                 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
170         }
171
172         pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
173         if (pdata) {
174                 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
175                 pdata->bus_id = 0;
176                 pdata->phy_id = 1;
177                 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
178         }
179
180         init_fcc_ioports();
181         ppc_sys_device_remove(MPC85xx_CPM_FCC1);
182
183         fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC2);
184         if (fpi) {
185                 memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
186                 fpi->bus_id = "0:02";
187                 fpi->phy_addr = 2;
188                 fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
189                 fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[1];
190         }
191
192         fpi = (struct fs_platform_info *) ppc_sys_get_pdata(MPC85xx_CPM_FCC3);
193         if (fpi) {
194                 memcpy(fpi->macaddr, binfo->bi_enet2addr, 6);
195                 fpi->macaddr[5] += 1;
196                 fpi->bus_id = "0:03";
197                 fpi->phy_addr = 3;
198                 fpi->dpram_offset = (u32)cpm2_immr->im_dprambase;
199                 fpi->fcc_regs_c = (u32)&cpm2_immr->im_fcc_c[2];
200         }
201
202 #ifdef CONFIG_BLK_DEV_INITRD
203         if (initrd_start)
204                 ROOT_DEV = Root_RAM0;
205         else
206 #endif
207 #ifdef  CONFIG_ROOT_NFS
208                 ROOT_DEV = Root_NFS;
209 #else
210                 ROOT_DEV = Root_HDA1;
211 #endif
212 }
213
214 static irqreturn_t cpm2_cascade(int irq, void *dev_id, struct pt_regs *regs)
215 {
216         while ((irq = cpm2_get_irq(regs)) >= 0)
217                 __do_IRQ(irq, regs);
218         return IRQ_HANDLED;
219 }
220
221 static struct irqaction cpm2_irqaction = {
222         .handler = cpm2_cascade,
223         .flags = IRQF_DISABLED,
224         .mask = CPU_MASK_NONE,
225         .name = "cpm2_cascade",
226 };
227
228 static void __init
229 mpc8560_ads_init_IRQ(void)
230 {
231         /* Setup OpenPIC */
232         mpc85xx_ads_init_IRQ();
233
234         /* Setup CPM2 PIC */
235         cpm2_init_IRQ();
236
237         setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
238
239         return;
240 }
241
242
243
244 /* ************************************************************************ */
245 void __init
246 platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
247               unsigned long r6, unsigned long r7)
248 {
249         /* parse_bootinfo must always be called first */
250         parse_bootinfo(find_bootinfo());
251
252         /*
253          * If we were passed in a board information, copy it into the
254          * residual data area.
255          */
256         if (r3) {
257                 memcpy((void *) __res, (void *) (r3 + KERNELBASE),
258                        sizeof (bd_t));
259
260         }
261 #if defined(CONFIG_BLK_DEV_INITRD)
262         /*
263          * If the init RAM disk has been configured in, and there's a valid
264          * starting address for it, set it up.
265          */
266         if (r4) {
267                 initrd_start = r4 + KERNELBASE;
268                 initrd_end = r5 + KERNELBASE;
269         }
270 #endif                          /* CONFIG_BLK_DEV_INITRD */
271
272         /* Copy the kernel command line arguments to a safe place. */
273
274         if (r6) {
275                 *(char *) (r7 + KERNELBASE) = 0;
276                 strcpy(cmd_line, (char *) (r6 + KERNELBASE));
277         }
278
279         identify_ppc_sys_by_id(mfspr(SPRN_SVR));
280
281         /* setup the PowerPC module struct */
282         ppc_md.setup_arch = mpc8560ads_setup_arch;
283         ppc_md.show_cpuinfo = mpc85xx_ads_show_cpuinfo;
284
285         ppc_md.init_IRQ = mpc8560_ads_init_IRQ;
286         ppc_md.get_irq = openpic_get_irq;
287
288         ppc_md.restart = mpc85xx_restart;
289         ppc_md.power_off = mpc85xx_power_off;
290         ppc_md.halt = mpc85xx_halt;
291
292         ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
293
294         ppc_md.time_init = NULL;
295         ppc_md.set_rtc_time = NULL;
296         ppc_md.get_rtc_time = NULL;
297         ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
298
299         if (ppc_md.progress)
300                 ppc_md.progress("mpc8560ads_init(): exit", 0);
301
302         return;
303 }