Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[sfrench/cifs-2.6.git] / arch / ppc / platforms / mpc866ads_setup.c
1 /*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>
23 #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
38 extern unsigned char __res[];
39
40 static struct fs_mii_bus_info fec_mii_bus_info = {
41         .method = fsmii_fec,
42         .id = 0,
43 };
44
45 static struct fs_mii_bus_info scc_mii_bus_info = {
46         .method = fsmii_fixed,
47         .id = 0,
48         .i.fixed.speed = 10,
49         .i.fixed.duplex = 0,
50 };
51
52 static struct fs_platform_info mpc8xx_fec_pdata[] = {
53         {
54          .rx_ring = 128,
55          .tx_ring = 16,
56          .rx_copybreak = 240,
57
58          .use_napi = 1,
59          .napi_weight = 17,
60
61          .phy_addr = 15,
62          .phy_irq = -1,
63
64          .use_rmii = 0,
65
66          .bus_info = &fec_mii_bus_info,
67          }
68 };
69
70 static struct fs_platform_info mpc8xx_scc_pdata = {
71         .rx_ring = 64,
72         .tx_ring = 8,
73         .rx_copybreak = 240,
74
75         .use_napi = 1,
76         .napi_weight = 17,
77
78         .phy_addr = -1,
79         .phy_irq = -1,
80
81         .bus_info = &scc_mii_bus_info,
82 };
83
84 void __init board_init(void)
85 {
86         volatile cpm8xx_t *cp = cpmp;
87         unsigned *bcsr_io;
88
89         bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
90
91         if (bcsr_io == NULL) {
92                 printk(KERN_CRIT "Could not remap BCSR1\n");
93                 return;
94         }
95 #ifdef CONFIG_SERIAL_CPM_SMC1
96         cp->cp_simode &= ~(0xe0000000 >> 17);   /* brg1 */
97         clrbits32(bcsr_io,(0x80000000 >> 7));
98 #else
99         setbits32(bcsr_io,(0x80000000 >> 7));
100
101         cp->cp_pbpar &= ~(0x000000c0);
102         cp->cp_pbdir |= 0x000000c0;
103         cp->cp_smc[0].smc_smcmr = 0;
104         cp->cp_smc[0].smc_smce = 0;
105 #endif
106
107 #ifdef CONFIG_SERIAL_CPM_SMC2
108         cp->cp_simode &= ~(0xe0000000 >> 1);
109         cp->cp_simode |= (0x20000000 >> 1);     /* brg2 */
110         clrbits32(bcsr_io,(0x80000000 >> 13));
111 #else
112         clrbits32(bcsr_io,(0x80000000 >> 13));
113         cp->cp_pbpar &= ~(0x00000c00);
114         cp->cp_pbdir |= 0x00000c00;
115         cp->cp_smc[1].smc_smcmr = 0;
116         cp->cp_smc[1].smc_smce = 0;
117 #endif
118         iounmap(bcsr_io);
119 }
120
121 static void setup_fec1_ioports(void)
122 {
123         immap_t *immap = (immap_t *) IMAP_ADDR;
124
125         setbits16(&immap->im_ioport.iop_pdpar, 0x1fff);
126         setbits16(&immap->im_ioport.iop_pddir, 0x1fff);
127 }
128
129 static void setup_scc1_ioports(void)
130 {
131         immap_t *immap = (immap_t *) IMAP_ADDR;
132         unsigned *bcsr_io;
133
134         bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
135
136         if (bcsr_io == NULL) {
137                 printk(KERN_CRIT "Could not remap BCSR1\n");
138                 return;
139         }
140
141         /* Enable the PHY.
142          */
143         clrbits32(bcsr_io,BCSR1_ETHEN);
144
145         /* Configure port A pins for Txd and Rxd.
146          */
147         /* Disable receive and transmit in case EPPC-Bug started it.
148          */
149         setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
150         clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
151         clrbits16(&immap->im_ioport.iop_paodr, PA_ENET_TXD);
152
153         /* Configure port C pins to enable CLSN and RENA.
154          */
155         clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
156         clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
157         setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
158         /* Configure port A for TCLK and RCLK.
159          */
160         setbits16(&immap->im_ioport.iop_papar, PA_ENET_TCLK | PA_ENET_RCLK);
161         clrbits16(&immap->im_ioport.iop_padir, PA_ENET_TCLK | PA_ENET_RCLK);
162         clrbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
163         clrbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);
164
165         /* Configure Serial Interface clock routing.
166          * First, clear all SCC bits to zero, then set the ones we want.
167          */
168         clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
169         setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
170
171         /* In the original SCC enet driver the following code is placed at
172         the end of the initialization */
173         setbits32(&immap->im_cpm.cp_pbpar, PB_ENET_TENA);
174         setbits32(&immap->im_cpm.cp_pbdir, PB_ENET_TENA);
175
176 }
177
178 static void mpc866ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
179 {
180         struct fs_platform_info *fpi = pdev->dev.platform_data;
181
182         volatile cpm8xx_t *cp;
183         bd_t *bd = (bd_t *) __res;
184         char *e;
185         int i;
186
187         /* Get pointer to Communication Processor */
188         cp = cpmp;
189         switch (fs_no) {
190         case fsid_fec1:
191                 fpi = &mpc8xx_fec_pdata[0];
192                 fpi->init_ioports = &setup_fec1_ioports;
193
194                 break;
195         case fsid_scc1:
196                 fpi = &mpc8xx_scc_pdata;
197                 fpi->init_ioports = &setup_scc1_ioports;
198
199                 break;
200         default:
201                 printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
202                 return;
203         }
204
205         pdev->dev.platform_data = fpi;
206         fpi->fs_no = fs_no;
207
208         e = (unsigned char *)&bd->bi_enetaddr;
209         for (i = 0; i < 6; i++)
210                 fpi->macaddr[i] = *e++;
211
212         fpi->macaddr[5 - pdev->id]++;
213
214 }
215
216 static void mpc866ads_fixup_fec_enet_pdata(struct platform_device *pdev,
217                                            int idx)
218 {
219         /* This is for FEC devices only */
220         if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
221                 return;
222         mpc866ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
223 }
224
225 static void mpc866ads_fixup_scc_enet_pdata(struct platform_device *pdev,
226                                            int idx)
227 {
228         /* This is for SCC devices only */
229         if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
230                 return;
231
232         mpc866ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
233 }
234
235 static int mpc866ads_platform_notify(struct device *dev)
236 {
237         static const struct platform_notify_dev_map dev_map[] = {
238                 {
239                         .bus_id = "fsl-cpm-fec",
240                         .rtn = mpc866ads_fixup_fec_enet_pdata,
241                 },
242                 {
243                         .bus_id = "fsl-cpm-scc",
244                         .rtn = mpc866ads_fixup_scc_enet_pdata,
245                 },
246                 {
247                         .bus_id = NULL
248                 }
249         };
250
251         platform_notify_map(dev_map,dev);
252
253         return 0;
254 }
255
256 int __init mpc866ads_init(void)
257 {
258         printk(KERN_NOTICE "mpc866ads: Init\n");
259
260         platform_notify = mpc866ads_platform_notify;
261
262         ppc_sys_device_initfunc();
263         ppc_sys_device_disable_all();
264
265 #ifdef MPC8xx_SECOND_ETH_SCC1
266         ppc_sys_device_enable(MPC8xx_CPM_SCC1);
267 #endif
268         ppc_sys_device_enable(MPC8xx_CPM_FEC1);
269
270         return 0;
271 }
272
273 arch_initcall(mpc866ads_init);