blob: d919dab6134768ae67249071c7ba2577ccb5cf73 [file] [log] [blame]
Vitaly Bordug42dc75c2006-01-20 22:22:36 +03001/*arch/ppc/platforms/mpc885ads-setup.c
2 *
3 * Platform setup for the Freescale mpc885ads board
4 *
5 * Vitaly Bordug <vbordug@ru.mvista.com>
6 *
7 * Copyright 2005 MontaVista Software Inc.
8 *
9 * This file is licensed under the terms of the GNU General Public License
10 * version 2. This program is licensed "as is" without any warranty of any
11 * kind, whether express or implied.
12 */
13
14#include <linux/config.h>
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/param.h>
18#include <linux/string.h>
19#include <linux/ioport.h>
20#include <linux/device.h>
21
22#include <linux/fs_enet_pd.h>
Vitaly Bordug4427d6b2006-04-25 20:26:43 +040023#include <linux/fs_uart_pd.h>
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030024#include <linux/mii.h>
25
26#include <asm/delay.h>
27#include <asm/io.h>
28#include <asm/machdep.h>
29#include <asm/page.h>
30#include <asm/processor.h>
31#include <asm/system.h>
32#include <asm/time.h>
33#include <asm/ppcboot.h>
34#include <asm/8xx_immap.h>
35#include <asm/commproc.h>
36#include <asm/ppc_sys.h>
37#include <asm/mpc8xx.h>
38
39extern unsigned char __res[];
40
Vitaly Bordug4427d6b2006-04-25 20:26:43 +040041static void setup_fec1_ioports(void);
42static void setup_scc1_ioports(void);
43static void setup_smc1_ioports(void);
44static void setup_smc2_ioports(void);
45
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030046static struct fs_mii_bus_info fec_mii_bus_info = {
47 .method = fsmii_fec,
48 .id = 0,
49};
50
51static struct fs_mii_bus_info scc_mii_bus_info = {
52 .method = fsmii_fixed,
53 .id = 0,
54 .i.fixed.speed = 10,
55 .i.fixed.duplex = 0,
56};
57
58static struct fs_platform_info mpc8xx_fec_pdata[] = {
59 {
60 .rx_ring = 128,
61 .tx_ring = 16,
62 .rx_copybreak = 240,
63
64 .use_napi = 1,
65 .napi_weight = 17,
66
67 .phy_addr = 15,
68 .phy_irq = -1,
69
70 .use_rmii = 0,
71
72 .bus_info = &fec_mii_bus_info,
73 }
74};
75
76static struct fs_platform_info mpc8xx_scc_pdata = {
77 .rx_ring = 64,
78 .tx_ring = 8,
79 .rx_copybreak = 240,
80
81 .use_napi = 1,
82 .napi_weight = 17,
83
84 .phy_addr = -1,
85 .phy_irq = -1,
86
87 .bus_info = &scc_mii_bus_info,
Vitaly Bordug4427d6b2006-04-25 20:26:43 +040088
89};
90
91static struct fs_uart_platform_info mpc866_uart_pdata[] = {
92 [fsid_smc1_uart] = {
93 .brg = 1,
94 .fs_no = fsid_smc1_uart,
95 .init_ioports = setup_smc1_ioports,
96 .tx_num_fifo = 4,
97 .tx_buf_size = 32,
98 .rx_num_fifo = 4,
99 .rx_buf_size = 32,
100 },
101 [fsid_smc2_uart] = {
102 .brg = 2,
103 .fs_no = fsid_smc2_uart,
104 .init_ioports = setup_smc2_ioports,
105 .tx_num_fifo = 4,
106 .tx_buf_size = 32,
107 .rx_num_fifo = 4,
108 .rx_buf_size = 32,
109 },
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300110};
111
112void __init board_init(void)
113{
114 volatile cpm8xx_t *cp = cpmp;
115 unsigned *bcsr_io;
116
117 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
118
119 if (bcsr_io == NULL) {
120 printk(KERN_CRIT "Could not remap BCSR1\n");
121 return;
122 }
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400123
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300124#ifdef CONFIG_SERIAL_CPM_SMC1
125 cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
126 clrbits32(bcsr_io,(0x80000000 >> 7));
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400127 cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
128 cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300129#else
130 setbits32(bcsr_io,(0x80000000 >> 7));
131
132 cp->cp_pbpar &= ~(0x000000c0);
133 cp->cp_pbdir |= 0x000000c0;
134 cp->cp_smc[0].smc_smcmr = 0;
135 cp->cp_smc[0].smc_smce = 0;
136#endif
137
138#ifdef CONFIG_SERIAL_CPM_SMC2
139 cp->cp_simode &= ~(0xe0000000 >> 1);
140 cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
141 clrbits32(bcsr_io,(0x80000000 >> 13));
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400142 cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
143 cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300144#else
145 clrbits32(bcsr_io,(0x80000000 >> 13));
146 cp->cp_pbpar &= ~(0x00000c00);
147 cp->cp_pbdir |= 0x00000c00;
148 cp->cp_smc[1].smc_smcmr = 0;
149 cp->cp_smc[1].smc_smce = 0;
150#endif
151 iounmap(bcsr_io);
152}
153
154static void setup_fec1_ioports(void)
155{
156 immap_t *immap = (immap_t *) IMAP_ADDR;
157
158 setbits16(&immap->im_ioport.iop_pdpar, 0x1fff);
159 setbits16(&immap->im_ioport.iop_pddir, 0x1fff);
160}
161
162static void setup_scc1_ioports(void)
163{
164 immap_t *immap = (immap_t *) IMAP_ADDR;
165 unsigned *bcsr_io;
166
167 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
168
169 if (bcsr_io == NULL) {
170 printk(KERN_CRIT "Could not remap BCSR1\n");
171 return;
172 }
173
174 /* Enable the PHY.
175 */
176 clrbits32(bcsr_io,BCSR1_ETHEN);
177
178 /* Configure port A pins for Txd and Rxd.
179 */
180 /* Disable receive and transmit in case EPPC-Bug started it.
181 */
182 setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
183 clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
184 clrbits16(&immap->im_ioport.iop_paodr, PA_ENET_TXD);
185
186 /* Configure port C pins to enable CLSN and RENA.
187 */
188 clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
189 clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
190 setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
191 /* Configure port A for TCLK and RCLK.
192 */
193 setbits16(&immap->im_ioport.iop_papar, PA_ENET_TCLK | PA_ENET_RCLK);
194 clrbits16(&immap->im_ioport.iop_padir, PA_ENET_TCLK | PA_ENET_RCLK);
195 clrbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
196 clrbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);
197
198 /* Configure Serial Interface clock routing.
199 * First, clear all SCC bits to zero, then set the ones we want.
200 */
201 clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
202 setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
203
204 /* In the original SCC enet driver the following code is placed at
205 the end of the initialization */
206 setbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
207 setbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);
208
209}
210
211static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
212{
213 struct fs_platform_info *fpi = pdev->dev.platform_data;
214
215 volatile cpm8xx_t *cp;
216 bd_t *bd = (bd_t *) __res;
217 char *e;
218 int i;
219
220 /* Get pointer to Communication Processor */
221 cp = cpmp;
222 switch (fs_no) {
223 case fsid_fec1:
224 fpi = &mpc8xx_fec_pdata[0];
225 fpi->init_ioports = &setup_fec1_ioports;
226
227 break;
228 case fsid_scc1:
229 fpi = &mpc8xx_scc_pdata;
230 fpi->init_ioports = &setup_scc1_ioports;
231
232 break;
233 default:
234 printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
235 return;
236 }
237
238 pdev->dev.platform_data = fpi;
239 fpi->fs_no = fs_no;
240
241 e = (unsigned char *)&bd->bi_enetaddr;
242 for (i = 0; i < 6; i++)
243 fpi->macaddr[i] = *e++;
244
245 fpi->macaddr[5 - pdev->id]++;
246
247}
248
249static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
250 int idx)
251{
252 /* This is for FEC devices only */
253 if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
254 return;
255 mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
256}
257
258static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
259 int idx)
260{
261 /* This is for SCC devices only */
262 if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
263 return;
264
265 mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
266}
267
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400268static void setup_smc1_ioports(void)
269{
270 immap_t *immap = (immap_t *) IMAP_ADDR;
271 unsigned *bcsr_io;
272 unsigned int iobits = 0x000000c0;
273
274 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
275
276 if (bcsr_io == NULL) {
277 printk(KERN_CRIT "Could not remap BCSR1\n");
278 return;
279 }
280
281 clrbits32(bcsr_io,BCSR1_RS232EN_1);
282 iounmap(bcsr_io);
283
284 setbits32(&immap->im_cpm.cp_pbpar, iobits);
285 clrbits32(&immap->im_cpm.cp_pbdir, iobits);
286 clrbits16(&immap->im_cpm.cp_pbodr, iobits);
287
288}
289
290static void setup_smc2_ioports(void)
291{
292 immap_t *immap = (immap_t *) IMAP_ADDR;
293 unsigned *bcsr_io;
294 unsigned int iobits = 0x00000c00;
295
296 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
297
298 if (bcsr_io == NULL) {
299 printk(KERN_CRIT "Could not remap BCSR1\n");
300 return;
301 }
302
303 clrbits32(bcsr_io,BCSR1_RS232EN_2);
304
305 iounmap(bcsr_io);
306
307#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
308 setbits32(&immap->im_cpm.cp_pbpar, iobits);
309 clrbits32(&immap->im_cpm.cp_pbdir, iobits);
310 clrbits16(&immap->im_cpm.cp_pbodr, iobits);
311#else
312 setbits16(&immap->im_ioport.iop_papar, iobits);
313 clrbits16(&immap->im_ioport.iop_padir, iobits);
314 clrbits16(&immap->im_ioport.iop_paodr, iobits);
315#endif
316
317}
318
319static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
320 int idx)
321{
322 bd_t *bd = (bd_t *) __res;
323 struct fs_uart_platform_info *pinfo;
324 int num = ARRAY_SIZE(mpc866_uart_pdata);
325
326 int id = fs_uart_id_smc2fsid(idx);
327
328 /* no need to alter anything if console */
329 if ((id <= num) && (!pdev->dev.platform_data)) {
330 pinfo = &mpc866_uart_pdata[id];
331 pinfo->uart_clk = bd->bi_intfreq;
332 pdev->dev.platform_data = pinfo;
333 }
334}
335
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300336static int mpc866ads_platform_notify(struct device *dev)
337{
338 static const struct platform_notify_dev_map dev_map[] = {
339 {
340 .bus_id = "fsl-cpm-fec",
341 .rtn = mpc866ads_fixup_fec_enet_pdata,
342 },
343 {
344 .bus_id = "fsl-cpm-scc",
345 .rtn = mpc866ads_fixup_scc_enet_pdata,
346 },
347 {
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400348 .bus_id = "fsl-cpm-smc:uart",
349 .rtn = mpc866ads_fixup_uart_pdata
350 },
351 {
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300352 .bus_id = NULL
353 }
354 };
355
356 platform_notify_map(dev_map,dev);
357
358 return 0;
359}
360
361int __init mpc866ads_init(void)
362{
363 printk(KERN_NOTICE "mpc866ads: Init\n");
364
365 platform_notify = mpc866ads_platform_notify;
366
367 ppc_sys_device_initfunc();
368 ppc_sys_device_disable_all();
369
370#ifdef MPC8xx_SECOND_ETH_SCC1
371 ppc_sys_device_enable(MPC8xx_CPM_SCC1);
372#endif
373 ppc_sys_device_enable(MPC8xx_CPM_FEC1);
374
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400375/* Since either of the uarts could be used as console, they need to ready */
376#ifdef CONFIG_SERIAL_CPM_SMC1
377 ppc_sys_device_enable(MPC8xx_CPM_SMC1);
378 ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
379#endif
380
Vitaly Bordug6e1976962006-04-29 23:06:00 +0400381#ifdef CONFIG_SERIAL_CPM_SMC
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400382 ppc_sys_device_enable(MPC8xx_CPM_SMC2);
383 ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
384#endif
385
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300386 return 0;
387}
388
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400389/*
390 To prevent confusion, console selection is gross:
391 by 0 assumed SMC1 and by 1 assumed SMC2
392 */
393struct platform_device* early_uart_get_pdev(int index)
394{
395 bd_t *bd = (bd_t *) __res;
396 struct fs_uart_platform_info *pinfo;
397
398 struct platform_device* pdev = NULL;
399 if(index) { /*assume SMC2 here*/
400 pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
401 pinfo = &mpc866_uart_pdata[1];
402 } else { /*over SMC1*/
403 pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
404 pinfo = &mpc866_uart_pdata[0];
405 }
406
407 pinfo->uart_clk = bd->bi_intfreq;
408 pdev->dev.platform_data = pinfo;
409 ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
410 return NULL;
411}
412
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300413arch_initcall(mpc866ads_init);