Merge git://git.infradead.org/mtd-2.6
[linux-2.6] / drivers / net / fec_8xx / fec_8xx-netta.c
1 /*
2  * FEC instantatiation file for NETTA
3  */
4
5 #include <linux/kernel.h>
6 #include <linux/types.h>
7 #include <linux/string.h>
8 #include <linux/ptrace.h>
9 #include <linux/errno.h>
10 #include <linux/ioport.h>
11 #include <linux/slab.h>
12 #include <linux/interrupt.h>
13 #include <linux/pci.h>
14 #include <linux/init.h>
15 #include <linux/delay.h>
16 #include <linux/netdevice.h>
17 #include <linux/etherdevice.h>
18 #include <linux/skbuff.h>
19 #include <linux/spinlock.h>
20 #include <linux/mii.h>
21 #include <linux/ethtool.h>
22 #include <linux/bitops.h>
23
24 #include <asm/8xx_immap.h>
25 #include <asm/pgtable.h>
26 #include <asm/mpc8xx.h>
27 #include <asm/irq.h>
28 #include <asm/uaccess.h>
29 #include <asm/commproc.h>
30
31 #include "fec_8xx.h"
32
33 /*************************************************/
34
35 static struct fec_platform_info fec1_info = {
36         .fec_no = 0,
37         .use_mdio = 1,
38         .phy_addr = 8,
39         .fec_irq = SIU_LEVEL1,
40         .phy_irq = CPM_IRQ_OFFSET + CPMVEC_PIO_PC6,
41         .rx_ring = 128,
42         .tx_ring = 16,
43         .rx_copybreak = 240,
44         .use_napi = 1,
45         .napi_weight = 17,
46 };
47
48 static struct fec_platform_info fec2_info = {
49         .fec_no = 1,
50         .use_mdio = 1,
51         .phy_addr = 2,
52         .fec_irq = SIU_LEVEL3,
53         .phy_irq = CPM_IRQ_OFFSET + CPMVEC_PIO_PC7,
54         .rx_ring = 128,
55         .tx_ring = 16,
56         .rx_copybreak = 240,
57         .use_napi = 1,
58         .napi_weight = 17,
59 };
60
61 static struct net_device *fec1_dev;
62 static struct net_device *fec2_dev;
63
64 /* XXX custom u-boot & Linux startup needed */
65 extern const char *__fw_getenv(const char *var);
66
67 /* access ports */
68 #define setbits32(_addr, _v) __fec_out32(&(_addr), __fec_in32(&(_addr)) |  (_v))
69 #define clrbits32(_addr, _v) __fec_out32(&(_addr), __fec_in32(&(_addr)) & ~(_v))
70
71 #define setbits16(_addr, _v) __fec_out16(&(_addr), __fec_in16(&(_addr)) |  (_v))
72 #define clrbits16(_addr, _v) __fec_out16(&(_addr), __fec_in16(&(_addr)) & ~(_v))
73
74 int fec_8xx_platform_init(void)
75 {
76         immap_t *immap = (immap_t *)IMAP_ADDR;
77         bd_t *bd = (bd_t *) __res;
78         const char *s;
79         char *e;
80         int i;
81
82         /* use MDC for MII */
83         setbits16(immap->im_ioport.iop_pdpar, 0x0080);
84         clrbits16(immap->im_ioport.iop_pddir, 0x0080);
85
86         /* configure FEC1 pins */
87         setbits16(immap->im_ioport.iop_papar, 0xe810);
88         setbits16(immap->im_ioport.iop_padir, 0x0810);
89         clrbits16(immap->im_ioport.iop_padir, 0xe000);
90
91         setbits32(immap->im_cpm.cp_pbpar, 0x00000001);
92         clrbits32(immap->im_cpm.cp_pbdir, 0x00000001);
93
94         setbits32(immap->im_cpm.cp_cptr, 0x00000100);
95         clrbits32(immap->im_cpm.cp_cptr, 0x00000050);
96
97         clrbits16(immap->im_ioport.iop_pcpar, 0x0200);
98         clrbits16(immap->im_ioport.iop_pcdir, 0x0200);
99         clrbits16(immap->im_ioport.iop_pcso, 0x0200);
100         setbits16(immap->im_ioport.iop_pcint, 0x0200);
101
102         /* configure FEC2 pins */
103         setbits32(immap->im_cpm.cp_pepar, 0x00039620);
104         setbits32(immap->im_cpm.cp_pedir, 0x00039620);
105         setbits32(immap->im_cpm.cp_peso, 0x00031000);
106         clrbits32(immap->im_cpm.cp_peso, 0x00008620);
107
108         setbits32(immap->im_cpm.cp_cptr, 0x00000080);
109         clrbits32(immap->im_cpm.cp_cptr, 0x00000028);
110
111         clrbits16(immap->im_ioport.iop_pcpar, 0x0200);
112         clrbits16(immap->im_ioport.iop_pcdir, 0x0200);
113         clrbits16(immap->im_ioport.iop_pcso, 0x0200);
114         setbits16(immap->im_ioport.iop_pcint, 0x0200);
115
116         /* fill up */
117         fec1_info.sys_clk = bd->bi_intfreq;
118         fec2_info.sys_clk = bd->bi_intfreq;
119
120         s = __fw_getenv("ethaddr");
121         if (s != NULL) {
122                 for (i = 0; i < 6; i++) {
123                         fec1_info.macaddr[i] = simple_strtoul(s, &e, 16);
124                         if (*e)
125                                 s = e + 1;
126                 }
127         }
128
129         s = __fw_getenv("eth1addr");
130         if (s != NULL) {
131                 for (i = 0; i < 6; i++) {
132                         fec2_info.macaddr[i] = simple_strtoul(s, &e, 16);
133                         if (*e)
134                                 s = e + 1;
135                 }
136         }
137
138         fec_8xx_init_one(&fec1_info, &fec1_dev);
139         fec_8xx_init_one(&fec2_info, &fec2_dev);
140
141         return fec1_dev != NULL && fec2_dev != NULL ? 0 : -1;
142 }
143
144 void fec_8xx_platform_cleanup(void)
145 {
146         if (fec2_dev != NULL)
147                 fec_8xx_cleanup_one(fec2_dev);
148
149         if (fec1_dev != NULL)
150                 fec_8xx_cleanup_one(fec1_dev);
151 }