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
35static 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
48static 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
61static struct net_device *fec1_dev;
62static struct net_device *fec2_dev;
63
64extern const char *__fw_getenv(const char *var);
65
66/* access ports */
67#define setbits32(_addr, _v) __fec_out32(&(_addr), __fec_in32(&(_addr)) |  (_v))
68#define clrbits32(_addr, _v) __fec_out32(&(_addr), __fec_in32(&(_addr)) & ~(_v))
69
70#define setbits16(_addr, _v) __fec_out16(&(_addr), __fec_in16(&(_addr)) |  (_v))
71#define clrbits16(_addr, _v) __fec_out16(&(_addr), __fec_in16(&(_addr)) & ~(_v))
72
73int fec_8xx_platform_init(void)
74{
75	immap_t *immap = (immap_t *)IMAP_ADDR;
76	bd_t *bd = (bd_t *) __res;
77	const char *s;
78	char *e;
79	int i;
80
81	/* use MDC for MII */
82	setbits16(immap->im_ioport.iop_pdpar, 0x0080);
83	clrbits16(immap->im_ioport.iop_pddir, 0x0080);
84
85	/* configure FEC1 pins */
86	setbits16(immap->im_ioport.iop_papar, 0xe810);
87	setbits16(immap->im_ioport.iop_padir, 0x0810);
88	clrbits16(immap->im_ioport.iop_padir, 0xe000);
89
90	setbits32(immap->im_cpm.cp_pbpar, 0x00000001);
91	clrbits32(immap->im_cpm.cp_pbdir, 0x00000001);
92
93	setbits32(immap->im_cpm.cp_cptr, 0x00000100);
94	clrbits32(immap->im_cpm.cp_cptr, 0x00000050);
95
96	clrbits16(immap->im_ioport.iop_pcpar, 0x0200);
97	clrbits16(immap->im_ioport.iop_pcdir, 0x0200);
98	clrbits16(immap->im_ioport.iop_pcso, 0x0200);
99	setbits16(immap->im_ioport.iop_pcint, 0x0200);
100
101	/* configure FEC2 pins */
102	setbits32(immap->im_cpm.cp_pepar, 0x00039620);
103	setbits32(immap->im_cpm.cp_pedir, 0x00039620);
104	setbits32(immap->im_cpm.cp_peso, 0x00031000);
105	clrbits32(immap->im_cpm.cp_peso, 0x00008620);
106
107	setbits32(immap->im_cpm.cp_cptr, 0x00000080);
108	clrbits32(immap->im_cpm.cp_cptr, 0x00000028);
109
110	clrbits16(immap->im_ioport.iop_pcpar, 0x0200);
111	clrbits16(immap->im_ioport.iop_pcdir, 0x0200);
112	clrbits16(immap->im_ioport.iop_pcso, 0x0200);
113	setbits16(immap->im_ioport.iop_pcint, 0x0200);
114
115	/* fill up */
116	fec1_info.sys_clk = bd->bi_intfreq;
117	fec2_info.sys_clk = bd->bi_intfreq;
118
119	s = __fw_getenv("ethaddr");
120	if (s != NULL) {
121		for (i = 0; i < 6; i++) {
122			fec1_info.macaddr[i] = simple_strtoul(s, &e, 16);
123			if (*e)
124				s = e + 1;
125		}
126	}
127
128	s = __fw_getenv("eth1addr");
129	if (s != NULL) {
130		for (i = 0; i < 6; i++) {
131			fec2_info.macaddr[i] = simple_strtoul(s, &e, 16);
132			if (*e)
133				s = e + 1;
134		}
135	}
136
137	fec_8xx_init_one(&fec1_info, &fec1_dev);
138	fec_8xx_init_one(&fec2_info, &fec2_dev);
139
140	return fec1_dev != NULL && fec2_dev != NULL ? 0 : -1;
141}
142
143void fec_8xx_platform_cleanup(void)
144{
145	if (fec2_dev != NULL)
146		fec_8xx_cleanup_one(fec2_dev);
147
148	if (fec1_dev != NULL)
149		fec_8xx_cleanup_one(fec1_dev);
150}
151