blob: e12cece4c9fd056e1a2586d2feabc996d986ef7d [file] [log] [blame]
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -07001/*arch/ppc/platforms/mpc866ads-setup.c
Vitaly Bordug42dc75c2006-01-20 22:22:36 +03002 *
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -07003 * Platform setup for the Freescale mpc866ads board
Vitaly Bordug42dc75c2006-01-20 22:22:36 +03004 *
5 * Vitaly Bordug <vbordug@ru.mvista.com>
6 *
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -07007 * Copyright 2005-2006 MontaVista Software Inc.
Vitaly Bordug42dc75c2006-01-20 22:22:36 +03008 *
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
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030014#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/param.h>
17#include <linux/string.h>
18#include <linux/ioport.h>
19#include <linux/device.h>
20
21#include <linux/fs_enet_pd.h>
Vitaly Bordug4427d6b2006-04-25 20:26:43 +040022#include <linux/fs_uart_pd.h>
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030023#include <linux/mii.h>
24
25#include <asm/delay.h>
26#include <asm/io.h>
27#include <asm/machdep.h>
28#include <asm/page.h>
29#include <asm/processor.h>
30#include <asm/system.h>
31#include <asm/time.h>
32#include <asm/ppcboot.h>
33#include <asm/8xx_immap.h>
34#include <asm/commproc.h>
35#include <asm/ppc_sys.h>
36#include <asm/mpc8xx.h>
37
38extern unsigned char __res[];
39
Vitaly Bordug4427d6b2006-04-25 20:26:43 +040040static void setup_fec1_ioports(void);
41static void setup_scc1_ioports(void);
42static void setup_smc1_ioports(void);
43static void setup_smc2_ioports(void);
44
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070045static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030046
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070047static struct fs_mii_fec_platform_info mpc8xx_mdio_fec_pdata;
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030048
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070049static struct fs_platform_info mpc8xx_enet_pdata[] = {
50 [fsid_fec1] = {
51 .rx_ring = 128,
52 .tx_ring = 16,
53 .rx_copybreak = 240,
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030054
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070055 .use_napi = 1,
56 .napi_weight = 17,
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030057
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070058 .init_ioports = setup_fec1_ioports,
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030059
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070060 .bus_id = "0:0f",
61 .has_phy = 1,
62 },
63 [fsid_scc1] = {
64 .rx_ring = 64,
65 .tx_ring = 8,
66 .rx_copybreak = 240,
67 .use_napi = 1,
68 .napi_weight = 17,
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030069
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030070
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070071 .init_ioports = setup_scc1_ioports,
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030072
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -070073 .bus_id = "fixed@100:1",
74 },
Vitaly Bordug4427d6b2006-04-25 20:26:43 +040075};
76
77static struct fs_uart_platform_info mpc866_uart_pdata[] = {
78 [fsid_smc1_uart] = {
79 .brg = 1,
80 .fs_no = fsid_smc1_uart,
81 .init_ioports = setup_smc1_ioports,
82 .tx_num_fifo = 4,
83 .tx_buf_size = 32,
84 .rx_num_fifo = 4,
85 .rx_buf_size = 32,
86 },
87 [fsid_smc2_uart] = {
88 .brg = 2,
89 .fs_no = fsid_smc2_uart,
90 .init_ioports = setup_smc2_ioports,
91 .tx_num_fifo = 4,
92 .tx_buf_size = 32,
93 .rx_num_fifo = 4,
94 .rx_buf_size = 32,
95 },
Vitaly Bordug42dc75c2006-01-20 22:22:36 +030096};
97
98void __init board_init(void)
99{
100 volatile cpm8xx_t *cp = cpmp;
101 unsigned *bcsr_io;
102
103 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
104
105 if (bcsr_io == NULL) {
106 printk(KERN_CRIT "Could not remap BCSR1\n");
107 return;
108 }
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400109
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300110#ifdef CONFIG_SERIAL_CPM_SMC1
111 cp->cp_simode &= ~(0xe0000000 >> 17); /* brg1 */
112 clrbits32(bcsr_io,(0x80000000 >> 7));
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400113 cp->cp_smc[0].smc_smcm |= (SMCM_RX | SMCM_TX);
114 cp->cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300115#else
116 setbits32(bcsr_io,(0x80000000 >> 7));
117
118 cp->cp_pbpar &= ~(0x000000c0);
119 cp->cp_pbdir |= 0x000000c0;
120 cp->cp_smc[0].smc_smcmr = 0;
121 cp->cp_smc[0].smc_smce = 0;
122#endif
123
124#ifdef CONFIG_SERIAL_CPM_SMC2
125 cp->cp_simode &= ~(0xe0000000 >> 1);
126 cp->cp_simode |= (0x20000000 >> 1); /* brg2 */
127 clrbits32(bcsr_io,(0x80000000 >> 13));
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400128 cp->cp_smc[1].smc_smcm |= (SMCM_RX | SMCM_TX);
129 cp->cp_smc[1].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300130#else
131 clrbits32(bcsr_io,(0x80000000 >> 13));
132 cp->cp_pbpar &= ~(0x00000c00);
133 cp->cp_pbdir |= 0x00000c00;
134 cp->cp_smc[1].smc_smcmr = 0;
135 cp->cp_smc[1].smc_smce = 0;
136#endif
137 iounmap(bcsr_io);
138}
139
140static void setup_fec1_ioports(void)
141{
142 immap_t *immap = (immap_t *) IMAP_ADDR;
143
144 setbits16(&immap->im_ioport.iop_pdpar, 0x1fff);
145 setbits16(&immap->im_ioport.iop_pddir, 0x1fff);
146}
147
148static void setup_scc1_ioports(void)
149{
150 immap_t *immap = (immap_t *) IMAP_ADDR;
151 unsigned *bcsr_io;
152
153 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
154
155 if (bcsr_io == NULL) {
156 printk(KERN_CRIT "Could not remap BCSR1\n");
157 return;
158 }
159
160 /* Enable the PHY.
161 */
162 clrbits32(bcsr_io,BCSR1_ETHEN);
163
164 /* Configure port A pins for Txd and Rxd.
165 */
166 /* Disable receive and transmit in case EPPC-Bug started it.
167 */
168 setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
169 clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
170 clrbits16(&immap->im_ioport.iop_paodr, PA_ENET_TXD);
171
172 /* Configure port C pins to enable CLSN and RENA.
173 */
174 clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
175 clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
176 setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
177 /* Configure port A for TCLK and RCLK.
178 */
179 setbits16(&immap->im_ioport.iop_papar, PA_ENET_TCLK | PA_ENET_RCLK);
180 clrbits16(&immap->im_ioport.iop_padir, PA_ENET_TCLK | PA_ENET_RCLK);
181 clrbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
182 clrbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);
183
184 /* Configure Serial Interface clock routing.
185 * First, clear all SCC bits to zero, then set the ones we want.
186 */
187 clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
188 setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
189
190 /* In the original SCC enet driver the following code is placed at
191 the end of the initialization */
192 setbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
193 setbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);
194
195}
196
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400197static void setup_smc1_ioports(void)
198{
199 immap_t *immap = (immap_t *) IMAP_ADDR;
200 unsigned *bcsr_io;
201 unsigned int iobits = 0x000000c0;
202
203 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
204
205 if (bcsr_io == NULL) {
206 printk(KERN_CRIT "Could not remap BCSR1\n");
207 return;
208 }
209
210 clrbits32(bcsr_io,BCSR1_RS232EN_1);
211 iounmap(bcsr_io);
212
213 setbits32(&immap->im_cpm.cp_pbpar, iobits);
214 clrbits32(&immap->im_cpm.cp_pbdir, iobits);
215 clrbits16(&immap->im_cpm.cp_pbodr, iobits);
216
217}
218
219static void setup_smc2_ioports(void)
220{
221 immap_t *immap = (immap_t *) IMAP_ADDR;
222 unsigned *bcsr_io;
223 unsigned int iobits = 0x00000c00;
224
225 bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
226
227 if (bcsr_io == NULL) {
228 printk(KERN_CRIT "Could not remap BCSR1\n");
229 return;
230 }
231
232 clrbits32(bcsr_io,BCSR1_RS232EN_2);
233
234 iounmap(bcsr_io);
235
236#ifndef CONFIG_SERIAL_CPM_ALT_SMC2
237 setbits32(&immap->im_cpm.cp_pbpar, iobits);
238 clrbits32(&immap->im_cpm.cp_pbdir, iobits);
239 clrbits16(&immap->im_cpm.cp_pbodr, iobits);
240#else
241 setbits16(&immap->im_ioport.iop_papar, iobits);
242 clrbits16(&immap->im_ioport.iop_padir, iobits);
243 clrbits16(&immap->im_ioport.iop_paodr, iobits);
244#endif
245
246}
247
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -0700248static int ma_count = 0;
249
250static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
251{
252 struct fs_platform_info *fpi;
253
254 volatile cpm8xx_t *cp;
255 bd_t *bd = (bd_t *) __res;
256 char *e;
257 int i;
258
259 /* Get pointer to Communication Processor */
260 cp = cpmp;
261
262 if(fs_no > ARRAY_SIZE(mpc8xx_enet_pdata)) {
263 printk(KERN_ERR"No network-suitable #%d device on bus", fs_no);
264 return;
265 }
266
267
268 fpi = &mpc8xx_enet_pdata[fs_no];
269 fpi->fs_no = fs_no;
270 pdev->dev.platform_data = fpi;
271
272 e = (unsigned char *)&bd->bi_enetaddr;
273 for (i = 0; i < 6; i++)
274 fpi->macaddr[i] = *e++;
275
276 fpi->macaddr[5] += ma_count++;
277}
278
279static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
280 int idx)
281{
282 /* This is for FEC devices only */
283 if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
284 return;
285 mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
286}
287
288static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
289 int idx)
290{
291 /* This is for SCC devices only */
292 if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
293 return;
294
295 mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
296}
297
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400298static void __init mpc866ads_fixup_uart_pdata(struct platform_device *pdev,
299 int idx)
300{
301 bd_t *bd = (bd_t *) __res;
302 struct fs_uart_platform_info *pinfo;
303 int num = ARRAY_SIZE(mpc866_uart_pdata);
304
305 int id = fs_uart_id_smc2fsid(idx);
306
307 /* no need to alter anything if console */
308 if ((id <= num) && (!pdev->dev.platform_data)) {
309 pinfo = &mpc866_uart_pdata[id];
310 pinfo->uart_clk = bd->bi_intfreq;
311 pdev->dev.platform_data = pinfo;
312 }
313}
314
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300315static int mpc866ads_platform_notify(struct device *dev)
316{
317 static const struct platform_notify_dev_map dev_map[] = {
318 {
319 .bus_id = "fsl-cpm-fec",
320 .rtn = mpc866ads_fixup_fec_enet_pdata,
321 },
322 {
323 .bus_id = "fsl-cpm-scc",
324 .rtn = mpc866ads_fixup_scc_enet_pdata,
325 },
326 {
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400327 .bus_id = "fsl-cpm-smc:uart",
328 .rtn = mpc866ads_fixup_uart_pdata
329 },
330 {
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300331 .bus_id = NULL
332 }
333 };
334
335 platform_notify_map(dev_map,dev);
336
337 return 0;
338}
339
340int __init mpc866ads_init(void)
341{
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -0700342 bd_t *bd = (bd_t *) __res;
343 struct fs_mii_fec_platform_info* fmpi;
344
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300345 printk(KERN_NOTICE "mpc866ads: Init\n");
346
347 platform_notify = mpc866ads_platform_notify;
348
349 ppc_sys_device_initfunc();
350 ppc_sys_device_disable_all();
351
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -0700352#ifdef CONFIG_MPC8xx_SECOND_ETH_SCC1
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300353 ppc_sys_device_enable(MPC8xx_CPM_SCC1);
354#endif
355 ppc_sys_device_enable(MPC8xx_CPM_FEC1);
356
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -0700357 ppc_sys_device_enable(MPC8xx_MDIO_FEC);
358
359 fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
360 &mpc8xx_mdio_fec_pdata;
361
362 fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
363 /* No PHY interrupt line here */
364 fmpi->irq[0xf] = -1;
365
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400366/* Since either of the uarts could be used as console, they need to ready */
367#ifdef CONFIG_SERIAL_CPM_SMC1
368 ppc_sys_device_enable(MPC8xx_CPM_SMC1);
369 ppc_sys_device_setfunc(MPC8xx_CPM_SMC1, PPC_SYS_FUNC_UART);
370#endif
371
Vitaly Bordug6e1976962006-04-29 23:06:00 +0400372#ifdef CONFIG_SERIAL_CPM_SMC
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400373 ppc_sys_device_enable(MPC8xx_CPM_SMC2);
374 ppc_sys_device_setfunc(MPC8xx_CPM_SMC2, PPC_SYS_FUNC_UART);
375#endif
Vitaly Bordug2ca2d5e2006-08-14 23:00:31 -0700376 ppc_sys_device_enable(MPC8xx_MDIO_FEC);
377
378 fmpi = ppc_sys_platform_devices[MPC8xx_MDIO_FEC].dev.platform_data =
379 &mpc8xx_mdio_fec_pdata;
380
381 fmpi->mii_speed = ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1;
382 /* No PHY interrupt line here */
383 fmpi->irq[0xf] = -1;
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400384
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300385 return 0;
386}
387
Vitaly Bordug4427d6b2006-04-25 20:26:43 +0400388/*
389 To prevent confusion, console selection is gross:
390 by 0 assumed SMC1 and by 1 assumed SMC2
391 */
392struct platform_device* early_uart_get_pdev(int index)
393{
394 bd_t *bd = (bd_t *) __res;
395 struct fs_uart_platform_info *pinfo;
396
397 struct platform_device* pdev = NULL;
398 if(index) { /*assume SMC2 here*/
399 pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC2];
400 pinfo = &mpc866_uart_pdata[1];
401 } else { /*over SMC1*/
402 pdev = &ppc_sys_platform_devices[MPC8xx_CPM_SMC1];
403 pinfo = &mpc866_uart_pdata[0];
404 }
405
406 pinfo->uart_clk = bd->bi_intfreq;
407 pdev->dev.platform_data = pinfo;
408 ppc_sys_fixup_mem_resource(pdev, IMAP_ADDR);
409 return NULL;
410}
411
Vitaly Bordug42dc75c2006-01-20 22:22:36 +0300412arch_initcall(mpc866ads_init);