aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Zankel <czankel@Athlon.(none)>2008-05-06 02:36:35 -0400
committerChris Zankel <chris@zankel.net>2008-10-21 10:58:06 -0400
commit74f2a5f0ef643b7b277f7a270f85573f88d930d1 (patch)
treeeec23ab745ff6b346333e092611fe6a4c3152ed7
parent1b532c6ced5417ef18d5c10e5bc5e0ae21eb81c4 (diff)
xtensa: Add support for the Sonic Ethernet device for the XT2000 board.
Add support for the on-board Sonic Ethernet device for the XT2000 evaluation board. Signed-off-by: Chris Zankel <chris@zankel.net>
-rw-r--r--drivers/net/Kconfig6
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/xtsonic.c319
3 files changed, 327 insertions, 0 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 1d8af3348331..d15ab76964eb 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -464,6 +464,12 @@ config MIPS_JAZZ_SONIC
464 This is the driver for the onboard card of MIPS Magnum 4000, 464 This is the driver for the onboard card of MIPS Magnum 4000,
465 Acer PICA, Olivetti M700-10 and a few other identical OEM systems. 465 Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
466 466
467config XTENSA_XT2000_SONIC
468 tristate "Xtensa XT2000 onboard SONIC Ethernet support"
469 depends on XTENSA_PLATFORM_XT2000
470 help
471 This is the driver for the onboard card of the Xtensa XT2000 board.
472
467config MIPS_AU1X00_ENET 473config MIPS_AU1X00_ENET
468 bool "MIPS AU1000 Ethernet support" 474 bool "MIPS AU1000 Ethernet support"
469 depends on SOC_AU1X00 475 depends on SOC_AU1X00
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index fa2510b2e609..f19acf8b9220 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -227,6 +227,8 @@ pasemi_mac_driver-objs := pasemi_mac.o pasemi_mac_ethtool.o
227obj-$(CONFIG_MLX4_CORE) += mlx4/ 227obj-$(CONFIG_MLX4_CORE) += mlx4/
228obj-$(CONFIG_ENC28J60) += enc28j60.o 228obj-$(CONFIG_ENC28J60) += enc28j60.o
229 229
230obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
231
230obj-$(CONFIG_MACB) += macb.o 232obj-$(CONFIG_MACB) += macb.o
231 233
232obj-$(CONFIG_ARM) += arm/ 234obj-$(CONFIG_ARM) += arm/
diff --git a/drivers/net/xtsonic.c b/drivers/net/xtsonic.c
new file mode 100644
index 000000000000..da42aa06a3ba
--- /dev/null
+++ b/drivers/net/xtsonic.c
@@ -0,0 +1,319 @@
1/*
2 * xtsonic.c
3 *
4 * (C) 2001 - 2007 Tensilica Inc.
5 * Kevin Chea <kchea@yahoo.com>
6 * Marc Gauthier <marc@linux-xtensa.org>
7 * Chris Zankel <chris@zankel.net>
8 *
9 * (C) 1996,1998 by Thomas Bogendoerfer (tsbogend@alpha.franken.de)
10 *
11 * This driver is based on work from Andreas Busse, but most of
12 * the code is rewritten.
13 *
14 * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
15 *
16 * A driver for the onboard Sonic ethernet controller on the XT2000.
17 */
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/types.h>
22#include <linux/fcntl.h>
23#include <linux/interrupt.h>
24#include <linux/init.h>
25#include <linux/ioport.h>
26#include <linux/in.h>
27#include <linux/slab.h>
28#include <linux/string.h>
29#include <linux/delay.h>
30#include <linux/errno.h>
31#include <linux/netdevice.h>
32#include <linux/etherdevice.h>
33#include <linux/skbuff.h>
34#include <linux/platform_device.h>
35#include <linux/dma-mapping.h>
36
37#include <asm/io.h>
38#include <asm/pgtable.h>
39#include <asm/dma.h>
40
41static char xtsonic_string[] = "xtsonic";
42
43extern unsigned xtboard_nvram_valid(void);
44extern void xtboard_get_ether_addr(unsigned char *buf);
45
46#include "sonic.h"
47
48/*
49 * According to the documentation for the Sonic ethernet controller,
50 * EOBC should be 760 words (1520 bytes) for 32-bit applications, and,
51 * as such, 2 words less than the buffer size. The value for RBSIZE
52 * defined in sonic.h, however is only 1520.
53 *
54 * (Note that in 16-bit configurations, EOBC is 759 words (1518 bytes) and
55 * RBSIZE 1520 bytes)
56 */
57#undef SONIC_RBSIZE
58#define SONIC_RBSIZE 1524
59
60/*
61 * The chip provides 256 byte register space.
62 */
63#define SONIC_MEM_SIZE 0x100
64
65/*
66 * Macros to access SONIC registers
67 */
68#define SONIC_READ(reg) \
69 (0xffff & *((volatile unsigned int *)dev->base_addr+reg))
70
71#define SONIC_WRITE(reg,val) \
72 *((volatile unsigned int *)dev->base_addr+reg) = val
73
74
75/* Use 0 for production, 1 for verification, and >2 for debug */
76#ifdef SONIC_DEBUG
77static unsigned int sonic_debug = SONIC_DEBUG;
78#else
79static unsigned int sonic_debug = 1;
80#endif
81
82/*
83 * We cannot use station (ethernet) address prefixes to detect the
84 * sonic controller since these are board manufacturer depended.
85 * So we check for known Silicon Revision IDs instead.
86 */
87static unsigned short known_revisions[] =
88{
89 0x101, /* SONIC 83934 */
90 0xffff /* end of list */
91};
92
93static int xtsonic_open(struct net_device *dev)
94{
95 if (request_irq(dev->irq,&sonic_interrupt,IRQF_DISABLED,"sonic",dev)) {
96 printk(KERN_ERR "%s: unable to get IRQ %d.\n",
97 dev->name, dev->irq);
98 return -EAGAIN;
99 }
100 return sonic_open(dev);
101}
102
103static int xtsonic_close(struct net_device *dev)
104{
105 int err;
106 err = sonic_close(dev);
107 free_irq(dev->irq, dev);
108 return err;
109}
110
111static int __init sonic_probe1(struct net_device *dev)
112{
113 static unsigned version_printed = 0;
114 unsigned int silicon_revision;
115 struct sonic_local *lp = netdev_priv(dev);
116 unsigned int base_addr = dev->base_addr;
117 int i;
118 int err = 0;
119
120 if (!request_mem_region(base_addr, 0x100, xtsonic_string))
121 return -EBUSY;
122
123 /*
124 * get the Silicon Revision ID. If this is one of the known
125 * one assume that we found a SONIC ethernet controller at
126 * the expected location.
127 */
128 silicon_revision = SONIC_READ(SONIC_SR);
129 if (sonic_debug > 1)
130 printk("SONIC Silicon Revision = 0x%04x\n",silicon_revision);
131
132 i = 0;
133 while ((known_revisions[i] != 0xffff) &&
134 (known_revisions[i] != silicon_revision))
135 i++;
136
137 if (known_revisions[i] == 0xffff) {
138 printk("SONIC ethernet controller not found (0x%4x)\n",
139 silicon_revision);
140 return -ENODEV;
141 }
142
143 if (sonic_debug && version_printed++ == 0)
144 printk(version);
145
146 /*
147 * Put the sonic into software reset, then retrieve ethernet address.
148 * Note: we are assuming that the boot-loader has initialized the cam.
149 */
150 SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
151 SONIC_WRITE(SONIC_DCR,
152 SONIC_DCR_WC0|SONIC_DCR_DW|SONIC_DCR_LBR|SONIC_DCR_SBUS);
153 SONIC_WRITE(SONIC_CEP,0);
154 SONIC_WRITE(SONIC_IMR,0);
155
156 SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
157 SONIC_WRITE(SONIC_CEP,0);
158
159 for (i=0; i<3; i++) {
160 unsigned int val = SONIC_READ(SONIC_CAP0-i);
161 dev->dev_addr[i*2] = val;
162 dev->dev_addr[i*2+1] = val >> 8;
163 }
164
165 /* Initialize the device structure. */
166
167 lp->dma_bitmode = SONIC_BITMODE32;
168
169 /*
170 * Allocate local private descriptor areas in uncached space.
171 * The entire structure must be located within the same 64kb segment.
172 * A simple way to ensure this is to allocate twice the
173 * size of the structure -- given that the structure is
174 * much less than 64 kB, at least one of the halves of
175 * the allocated area will be contained entirely in 64 kB.
176 * We also allocate extra space for a pointer to allow freeing
177 * this structure later on (in xtsonic_cleanup_module()).
178 */
179 lp->descriptors =
180 dma_alloc_coherent(lp->device,
181 SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
182 &lp->descriptors_laddr, GFP_KERNEL);
183
184 if (lp->descriptors == NULL) {
185 printk(KERN_ERR "%s: couldn't alloc DMA memory for "
186 " descriptors.\n", lp->device->bus_id);
187 goto out;
188 }
189
190 lp->cda = lp->descriptors;
191 lp->tda = lp->cda + (SIZEOF_SONIC_CDA
192 * SONIC_BUS_SCALE(lp->dma_bitmode));
193 lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
194 * SONIC_BUS_SCALE(lp->dma_bitmode));
195 lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
196 * SONIC_BUS_SCALE(lp->dma_bitmode));
197
198 /* get the virtual dma address */
199
200 lp->cda_laddr = lp->descriptors_laddr;
201 lp->tda_laddr = lp->cda_laddr + (SIZEOF_SONIC_CDA
202 * SONIC_BUS_SCALE(lp->dma_bitmode));
203 lp->rda_laddr = lp->tda_laddr + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
204 * SONIC_BUS_SCALE(lp->dma_bitmode));
205 lp->rra_laddr = lp->rda_laddr + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
206 * SONIC_BUS_SCALE(lp->dma_bitmode));
207
208 dev->open = xtsonic_open;
209 dev->stop = xtsonic_close;
210 dev->hard_start_xmit = sonic_send_packet;
211 dev->get_stats = sonic_get_stats;
212 dev->set_multicast_list = &sonic_multicast_list;
213 dev->tx_timeout = sonic_tx_timeout;
214 dev->watchdog_timeo = TX_TIMEOUT;
215
216 /*
217 * clear tally counter
218 */
219 SONIC_WRITE(SONIC_CRCT,0xffff);
220 SONIC_WRITE(SONIC_FAET,0xffff);
221 SONIC_WRITE(SONIC_MPT,0xffff);
222
223 return 0;
224out:
225 release_region(dev->base_addr, SONIC_MEM_SIZE);
226 return err;
227}
228
229
230/*
231 * Probe for a SONIC ethernet controller on an XT2000 board.
232 * Actually probing is superfluous but we're paranoid.
233 */
234
235int __init xtsonic_probe(struct platform_device *pdev)
236{
237 struct net_device *dev;
238 struct sonic_local *lp;
239 struct resource *resmem, *resirq;
240 int err = 0;
241
242 DECLARE_MAC_BUF(mac);
243
244 if ((resmem = platform_get_resource(pdev, IORESOURCE_MEM, 0)) == NULL)
245 return -ENODEV;
246
247 if ((resirq = platform_get_resource(pdev, IORESOURCE_IRQ, 0)) == NULL)
248 return -ENODEV;
249
250 if ((dev = alloc_etherdev(sizeof(struct sonic_local))) == NULL)
251 return -ENOMEM;
252
253 lp = netdev_priv(dev);
254 lp->device = &pdev->dev;
255 SET_NETDEV_DEV(dev, &pdev->dev);
256 netdev_boot_setup_check(dev);
257
258 dev->base_addr = resmem->start;
259 dev->irq = resirq->start;
260
261 if ((err = sonic_probe1(dev)))
262 goto out;
263 if ((err = register_netdev(dev)))
264 goto out1;
265
266 printk("%s: SONIC ethernet @%08lx, MAC %s, IRQ %d\n", dev->name,
267 dev->base_addr, print_mac(mac, dev->dev_addr), dev->irq);
268
269 return 0;
270
271out1:
272 release_region(dev->base_addr, SONIC_MEM_SIZE);
273out:
274 free_netdev(dev);
275
276 return err;
277}
278
279MODULE_DESCRIPTION("Xtensa XT2000 SONIC ethernet driver");
280module_param(sonic_debug, int, 0);
281MODULE_PARM_DESC(sonic_debug, "xtsonic debug level (1-4)");
282
283#include "sonic.c"
284
285static int __devexit xtsonic_device_remove (struct platform_device *pdev)
286{
287 struct net_device *dev = platform_get_drvdata(pdev);
288 struct sonic_local *lp = netdev_priv(dev);
289
290 unregister_netdev(dev);
291 dma_free_coherent(lp->device,
292 SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
293 lp->descriptors, lp->descriptors_laddr);
294 release_region (dev->base_addr, SONIC_MEM_SIZE);
295 free_netdev(dev);
296
297 return 0;
298}
299
300static struct platform_driver xtsonic_driver = {
301 .probe = xtsonic_probe,
302 .remove = __devexit_p(xtsonic_device_remove),
303 .driver = {
304 .name = xtsonic_string,
305 },
306};
307
308static int __init xtsonic_init(void)
309{
310 return platform_driver_register(&xtsonic_driver);
311}
312
313static void __exit xtsonic_cleanup(void)
314{
315 platform_driver_unregister(&xtsonic_driver);
316}
317
318module_init(xtsonic_init);
319module_exit(xtsonic_cleanup);