Merge branch 'drm-patches' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[pandora-kernel.git] / arch / ppc / platforms / mpc885ads_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
37 extern unsigned char __res[];
38
39 static void __init mpc885ads_scc_phy_init(char);
40
41 static struct fs_mii_bus_info fec_mii_bus_info = {
42         .method = fsmii_fec,
43         .id = 0,
44 };
45
46 static struct fs_mii_bus_info scc_mii_bus_info = {
47 #ifdef CONFIG_SCC_ENET_8xx_FIXED
48         .method = fsmii_fixed,
49 #else
50         .method = fsmii_fec,
51 #endif
52
53         .id = 0,
54 };
55
56 static struct fs_platform_info mpc8xx_fec_pdata[] = {
57         {
58          .rx_ring = 128,
59          .tx_ring = 16,
60          .rx_copybreak = 240,
61
62          .use_napi = 1,
63          .napi_weight = 17,
64
65          .phy_addr = 0,
66          .phy_irq = SIU_IRQ7,
67
68          .bus_info = &fec_mii_bus_info,
69          }, {
70              .rx_ring = 128,
71              .tx_ring = 16,
72              .rx_copybreak = 240,
73
74              .use_napi = 1,
75              .napi_weight = 17,
76
77              .phy_addr = 1,
78              .phy_irq = SIU_IRQ7,
79
80              .bus_info = &fec_mii_bus_info,
81              }
82 };
83
84 static struct fs_platform_info mpc8xx_scc_pdata = {
85         .rx_ring = 64,
86         .tx_ring = 8,
87         .rx_copybreak = 240,
88
89         .use_napi = 1,
90         .napi_weight = 17,
91
92         .phy_addr = 2,
93 #ifdef CONFIG_MPC8xx_SCC_ENET_FIXED
94         .phy_irq = -1,
95 #else
96         .phy_irq = SIU_IRQ7,
97 #endif
98
99         .bus_info = &scc_mii_bus_info,
100 };
101
102 void __init board_init(void)
103 {
104         volatile cpm8xx_t *cp = cpmp;
105         unsigned int *bcsr_io;
106
107 #ifdef CONFIG_FS_ENET
108         immap_t *immap = (immap_t *) IMAP_ADDR;
109 #endif
110         bcsr_io = ioremap(BCSR1, sizeof(unsigned long));
111
112         if (bcsr_io == NULL) {
113                 printk(KERN_CRIT "Could not remap BCSR\n");
114                 return;
115         }
116 #ifdef CONFIG_SERIAL_CPM_SMC1
117         cp->cp_simode &= ~(0xe0000000 >> 17);   /* brg1 */
118         clrbits32(bcsr_io, BCSR1_RS232EN_1);
119 #else
120         setbits32(bcsr_io,BCSR1_RS232EN_1);
121         cp->cp_smc[0].smc_smcmr = 0;
122         cp->cp_smc[0].smc_smce = 0;
123 #endif
124
125 #ifdef CONFIG_SERIAL_CPM_SMC2
126         cp->cp_simode &= ~(0xe0000000 >> 1);
127         cp->cp_simode |= (0x20000000 >> 1);     /* brg2 */
128         clrbits32(bcsr_io,BCSR1_RS232EN_2);
129 #else
130         setbits32(bcsr_io,BCSR1_RS232EN_2);
131         cp->cp_smc[1].smc_smcmr = 0;
132         cp->cp_smc[1].smc_smce = 0;
133 #endif
134         iounmap(bcsr_io);
135
136 #ifdef CONFIG_FS_ENET
137         /* use MDC for MII (common) */
138         setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
139         clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
140 #endif
141 }
142
143 static void setup_fec1_ioports(void)
144 {
145         immap_t *immap = (immap_t *) IMAP_ADDR;
146
147         /* configure FEC1 pins  */
148         setbits16(&immap->im_ioport.iop_papar, 0xf830);
149         setbits16(&immap->im_ioport.iop_padir, 0x0830);
150         clrbits16(&immap->im_ioport.iop_padir, 0xf000);
151         setbits32(&immap->im_cpm.cp_pbpar, 0x00001001);
152
153         clrbits32(&immap->im_cpm.cp_pbdir, 0x00001001);
154         setbits16(&immap->im_ioport.iop_pcpar, 0x000c);
155         clrbits16(&immap->im_ioport.iop_pcdir, 0x000c);
156         setbits32(&immap->im_cpm.cp_pepar, 0x00000003);
157
158         setbits32(&immap->im_cpm.cp_pedir, 0x00000003);
159         clrbits32(&immap->im_cpm.cp_peso, 0x00000003);
160         clrbits32(&immap->im_cpm.cp_cptr, 0x00000100);
161 }
162
163 static void setup_fec2_ioports(void)
164 {
165         immap_t *immap = (immap_t *) IMAP_ADDR;
166
167         /* configure FEC2 pins */
168         setbits32(&immap->im_cpm.cp_pepar, 0x0003fffc);
169         setbits32(&immap->im_cpm.cp_pedir, 0x0003fffc);
170         setbits32(&immap->im_cpm.cp_peso, 0x00037800);
171         clrbits32(&immap->im_cpm.cp_peso, 0x000087fc);
172         clrbits32(&immap->im_cpm.cp_cptr, 0x00000080);
173 }
174
175 static void setup_scc3_ioports(void)
176 {
177         immap_t *immap = (immap_t *) IMAP_ADDR;
178         unsigned *bcsr_io;
179
180         bcsr_io = ioremap(BCSR_ADDR, BCSR_SIZE);
181
182         if (bcsr_io == NULL) {
183                 printk(KERN_CRIT "Could not remap BCSR\n");
184                 return;
185         }
186
187         /* Enable the PHY.
188          */
189         setbits32(bcsr_io+4, BCSR4_ETH10_RST);
190         /* Configure port A pins for Txd and Rxd.
191          */
192         setbits16(&immap->im_ioport.iop_papar, PA_ENET_RXD | PA_ENET_TXD);
193         clrbits16(&immap->im_ioport.iop_padir, PA_ENET_RXD | PA_ENET_TXD);
194
195         /* Configure port C pins to enable CLSN and RENA.
196          */
197         clrbits16(&immap->im_ioport.iop_pcpar, PC_ENET_CLSN | PC_ENET_RENA);
198         clrbits16(&immap->im_ioport.iop_pcdir, PC_ENET_CLSN | PC_ENET_RENA);
199         setbits16(&immap->im_ioport.iop_pcso, PC_ENET_CLSN | PC_ENET_RENA);
200
201         /* Configure port E for TCLK and RCLK.
202          */
203         setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TCLK | PE_ENET_RCLK);
204         clrbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
205         clrbits32(&immap->im_cpm.cp_pedir,
206                   PE_ENET_TCLK | PE_ENET_RCLK | PE_ENET_TENA);
207         clrbits32(&immap->im_cpm.cp_peso, PE_ENET_TCLK | PE_ENET_RCLK);
208         setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
209
210         /* Configure Serial Interface clock routing.
211          * First, clear all SCC bits to zero, then set the ones we want.
212          */
213         clrbits32(&immap->im_cpm.cp_sicr, SICR_ENET_MASK);
214         setbits32(&immap->im_cpm.cp_sicr, SICR_ENET_CLKRT);
215
216         /* Disable Rx and Tx. SMC1 sshould be stopped if SCC3 eternet are used.
217          */
218         immap->im_cpm.cp_smc[0].smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
219         /* On the MPC885ADS SCC ethernet PHY is initialized in the full duplex mode
220          * by H/W setting after reset. SCC ethernet controller support only half duplex.
221          * This discrepancy of modes causes a lot of carrier lost errors.
222          */
223
224         /* In the original SCC enet driver the following code is placed at
225            the end of the initialization */
226         setbits32(&immap->im_cpm.cp_pepar, PE_ENET_TENA);
227         clrbits32(&immap->im_cpm.cp_pedir, PE_ENET_TENA);
228         setbits32(&immap->im_cpm.cp_peso, PE_ENET_TENA);
229
230         setbits32(bcsr_io+1, BCSR1_ETHEN);
231         iounmap(bcsr_io);
232 }
233
234 static void mpc885ads_fixup_enet_pdata(struct platform_device *pdev, int fs_no)
235 {
236         struct fs_platform_info *fpi = pdev->dev.platform_data;
237
238         volatile cpm8xx_t *cp;
239         bd_t *bd = (bd_t *) __res;
240         char *e;
241         int i;
242
243         /* Get pointer to Communication Processor */
244         cp = cpmp;
245         switch (fs_no) {
246         case fsid_fec1:
247                 fpi = &mpc8xx_fec_pdata[0];
248                 fpi->init_ioports = &setup_fec1_ioports;
249                 break;
250         case fsid_fec2:
251                 fpi = &mpc8xx_fec_pdata[1];
252                 fpi->init_ioports = &setup_fec2_ioports;
253                 break;
254         case fsid_scc3:
255                 fpi = &mpc8xx_scc_pdata;
256                 fpi->init_ioports = &setup_scc3_ioports;
257                 mpc885ads_scc_phy_init(fpi->phy_addr);
258                 break;
259         default:
260                 printk(KERN_WARNING"Device %s is not supported!\n", pdev->name);
261                 return;
262         }
263
264         pdev->dev.platform_data = fpi;
265         fpi->fs_no = fs_no;
266
267         e = (unsigned char *)&bd->bi_enetaddr;
268         for (i = 0; i < 6; i++)
269                 fpi->macaddr[i] = *e++;
270
271         fpi->macaddr[5 - pdev->id]++;
272
273 }
274
275 static void mpc885ads_fixup_fec_enet_pdata(struct platform_device *pdev,
276                                            int idx)
277 {
278         /* This is for FEC devices only */
279         if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-fec")))
280                 return;
281         mpc885ads_fixup_enet_pdata(pdev, fsid_fec1 + pdev->id - 1);
282 }
283
284 static void __init mpc885ads_fixup_scc_enet_pdata(struct platform_device *pdev,
285                                                   int idx)
286 {
287         /* This is for SCC devices only */
288         if (!pdev || !pdev->name || (!strstr(pdev->name, "fsl-cpm-scc")))
289                 return;
290
291         mpc885ads_fixup_enet_pdata(pdev, fsid_scc1 + pdev->id - 1);
292 }
293
294 /* SCC ethernet controller does not have MII management channel. FEC1 MII
295  * channel is used to communicate with the 10Mbit PHY.
296  */
297
298 #define MII_ECNTRL_PINMUX        0x4
299 #define FEC_ECNTRL_PINMUX        0x00000004
300 #define FEC_RCNTRL_MII_MODE        0x00000004
301
302 /* Make MII read/write commands.
303  */
304 #define mk_mii_write(REG, VAL, PHY_ADDR)    (0x50020000 | (((REG) & 0x1f) << 18) | \
305                 ((VAL) & 0xffff) | ((PHY_ADDR) << 23))
306
307 static void mpc885ads_scc_phy_init(char phy_addr)
308 {
309         volatile immap_t *immap;
310         volatile fec_t *fecp;
311         bd_t *bd;
312
313         bd = (bd_t *) __res;
314         immap = (immap_t *) IMAP_ADDR;  /* pointer to internal registers */
315         fecp = &(immap->im_cpm.cp_fec);
316
317         /* Enable MII pins of the FEC1
318          */
319         setbits16(&immap->im_ioport.iop_pdpar, 0x0080);
320         clrbits16(&immap->im_ioport.iop_pddir, 0x0080);
321         /* Set MII speed to 2.5 MHz
322          */
323         out_be32(&fecp->fec_mii_speed,
324                  ((((bd->bi_intfreq + 4999999) / 2500000) / 2) & 0x3F) << 1);
325
326         /* Enable FEC pin MUX
327          */
328         setbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
329         setbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
330
331         out_be32(&fecp->fec_mii_data,
332                  mk_mii_write(MII_BMCR, BMCR_ISOLATE, phy_addr));
333         udelay(100);
334         out_be32(&fecp->fec_mii_data,
335                  mk_mii_write(MII_ADVERTISE,
336                               ADVERTISE_10HALF | ADVERTISE_CSMA, phy_addr));
337         udelay(100);
338
339         /* Disable FEC MII settings
340          */
341         clrbits32(&fecp->fec_ecntrl, MII_ECNTRL_PINMUX);
342         clrbits32(&fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
343         out_be32(&fecp->fec_mii_speed, 0);
344 }
345
346 static int mpc885ads_platform_notify(struct device *dev)
347 {
348
349         static const struct platform_notify_dev_map dev_map[] = {
350                 {
351                         .bus_id = "fsl-cpm-fec",
352                         .rtn = mpc885ads_fixup_fec_enet_pdata,
353                 },
354                 {
355                         .bus_id = "fsl-cpm-scc",
356                         .rtn = mpc885ads_fixup_scc_enet_pdata,
357                 },
358                 {
359                         .bus_id = NULL
360                 }
361         };
362
363         platform_notify_map(dev_map,dev);
364
365 }
366
367 int __init mpc885ads_init(void)
368 {
369         printk(KERN_NOTICE "mpc885ads: Init\n");
370
371         platform_notify = mpc885ads_platform_notify;
372
373         ppc_sys_device_initfunc();
374         ppc_sys_device_disable_all();
375
376         ppc_sys_device_enable(MPC8xx_CPM_FEC1);
377
378 #ifdef CONFIG_MPC8xx_SECOND_ETH_SCC3
379         ppc_sys_device_enable(MPC8xx_CPM_SCC1);
380
381 #endif
382 #ifdef CONFIG_MPC8xx_SECOND_ETH_FEC2
383         ppc_sys_device_enable(MPC8xx_CPM_FEC2);
384 #endif
385
386         return 0;
387 }
388
389 arch_initcall(mpc885ads_init);