blob: 3a060468dd950ae8102567de4c0c278d23a722c6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * MPC8560ADS board specific routines
3 *
Kumar Gala4c8d3d92005-11-13 16:06:30 -08004 * Maintainer: Kumar Gala <galak@kernel.crashing.org>
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070014#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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#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>
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070032#include <linux/fs_enet_pd.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#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
Linus Torvalds1da177e2005-04-16 15:20:36 -070056
57/* ************************************************************************
58 *
59 * Setup the architecture
60 *
61 */
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070062static 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}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127
128static void __init
129mpc8560ads_setup_arch(void)
130{
131 bd_t *binfo = (bd_t *) __res;
132 unsigned int freq;
133 struct gianfar_platform_data *pdata;
Andy Flemingb37665e2005-10-28 17:46:27 -0700134 struct gianfar_mdio_data *mdata;
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -0700135 struct fs_platform_info *fpi;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136
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
Andy Flemingb37665e2005-10-28 17:46:27 -0700154 /* 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;
Andy Fleminga9b14972006-10-19 19:52:26 -0500159 mdata->irq[2] = PHY_POLL;
Andy Flemingb37665e2005-10-28 17:46:27 -0700160 mdata->irq[3] = MPC85xx_IRQ_EXT5;
Andy Fleminga9b14972006-10-19 19:52:26 -0500161 mdata->irq[31] = PHY_POLL;
Andy Flemingb37665e2005-10-28 17:46:27 -0700162
Linus Torvalds1da177e2005-04-16 15:20:36 -0700163 /* setup the board related information for the enet controllers */
164 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC1);
Kumar Gala62aa7512005-06-25 14:54:36 -0700165 if (pdata) {
166 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
Kumar Gala7e78e5e2006-01-12 21:04:23 -0600167 pdata->bus_id = 0;
168 pdata->phy_id = 0;
Kumar Gala62aa7512005-06-25 14:54:36 -0700169 memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
170 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
172 pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC85xx_TSEC2);
Kumar Gala62aa7512005-06-25 14:54:36 -0700173 if (pdata) {
174 pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
Kumar Gala7e78e5e2006-01-12 21:04:23 -0600175 pdata->bus_id = 0;
176 pdata->phy_id = 1;
Kumar Gala62aa7512005-06-25 14:54:36 -0700177 memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
178 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -0700180 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#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
Olaf Hering35a84c22006-10-07 22:08:26 +1000214static irqreturn_t cpm2_cascade(int irq, void *dev_id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700215{
Olaf Hering35a84c22006-10-07 22:08:26 +1000216 while ((irq = cpm2_get_irq()) >= 0)
217 __do_IRQ(irq);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700218 return IRQ_HANDLED;
219}
220
221static struct irqaction cpm2_irqaction = {
222 .handler = cpm2_cascade,
Thomas Gleixnerbc59d282006-07-01 19:29:22 -0700223 .flags = IRQF_DISABLED,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224 .mask = CPU_MASK_NONE,
225 .name = "cpm2_cascade",
226};
227
228static void __init
229mpc8560_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/* ************************************************************************ */
245void __init
246platform_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}