blob: fd289e52b2eccc5a287195994dab9b805d3a146a [file] [log] [blame]
Ben Dooks825a2ff2007-07-03 16:53:09 +01001/* drivers/net/ax88796.c
2 *
3 * Copyright 2005,2007 Simtec Electronics
4 * Ben Dooks <ben@simtec.co.uk>
5 *
6 * Asix AX88796 10/100 Ethernet controller support
7 * Based on ne.c, by Donald Becker, et-al.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010012 */
Ben Dooks825a2ff2007-07-03 16:53:09 +010013
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/errno.h>
17#include <linux/isapnp.h>
18#include <linux/init.h>
19#include <linux/interrupt.h>
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010020#include <linux/io.h>
Ben Dooks825a2ff2007-07-03 16:53:09 +010021#include <linux/platform_device.h>
22#include <linux/delay.h>
23#include <linux/timer.h>
24#include <linux/netdevice.h>
25#include <linux/etherdevice.h>
26#include <linux/ethtool.h>
27#include <linux/mii.h>
Magnus Damm89e536a2007-09-28 22:42:16 -070028#include <linux/eeprom_93cx6.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090029#include <linux/slab.h>
Ben Dooks825a2ff2007-07-03 16:53:09 +010030
31#include <net/ax88796.h>
32
33#include <asm/system.h>
Ben Dooks825a2ff2007-07-03 16:53:09 +010034
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010035static int phy_debug;
Ben Dooks825a2ff2007-07-03 16:53:09 +010036
37/* Rename the lib8390.c functions to show that they are in this driver */
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010038#define __ei_open ax_ei_open
39#define __ei_close ax_ei_close
40#define __ei_poll ax_ei_poll
Magnus Dammd57bc362009-01-14 21:05:55 -080041#define __ei_start_xmit ax_ei_start_xmit
Ben Dooks825a2ff2007-07-03 16:53:09 +010042#define __ei_tx_timeout ax_ei_tx_timeout
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010043#define __ei_get_stats ax_ei_get_stats
Magnus Dammd57bc362009-01-14 21:05:55 -080044#define __ei_set_multicast_list ax_ei_set_multicast_list
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010045#define __ei_interrupt ax_ei_interrupt
Ben Dooks825a2ff2007-07-03 16:53:09 +010046#define ____alloc_ei_netdev ax__alloc_ei_netdev
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010047#define __NS8390_init ax_NS8390_init
Ben Dooks825a2ff2007-07-03 16:53:09 +010048
49/* force unsigned long back to 'void __iomem *' */
50#define ax_convert_addr(_a) ((void __force __iomem *)(_a))
51
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010052#define ei_inb(_a) readb(ax_convert_addr(_a))
Ben Dooks825a2ff2007-07-03 16:53:09 +010053#define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
54
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010055#define ei_inb_p(_a) ei_inb(_a)
Ben Dooks825a2ff2007-07-03 16:53:09 +010056#define ei_outb_p(_v, _a) ei_outb(_v, _a)
57
58/* define EI_SHIFT() to take into account our register offsets */
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010059#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
Ben Dooks825a2ff2007-07-03 16:53:09 +010060
61/* Ensure we have our RCR base value */
62#define AX88796_PLATFORM
63
64static unsigned char version[] = "ax88796.c: Copyright 2005,2007 Simtec Electronics\n";
65
66#include "lib8390.c"
67
68#define DRV_NAME "ax88796"
69#define DRV_VERSION "1.00"
70
71/* from ne.c */
72#define NE_CMD EI_SHIFT(0x00)
73#define NE_RESET EI_SHIFT(0x1f)
74#define NE_DATAPORT EI_SHIFT(0x10)
75
76#define NE1SM_START_PG 0x20 /* First page of TX buffer */
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010077#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */
Ben Dooks825a2ff2007-07-03 16:53:09 +010078#define NESM_START_PG 0x40 /* First page of TX buffer */
79#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */
80
81/* device private data */
82
83struct ax_device {
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010084 struct timer_list mii_timer;
85 spinlock_t mii_lock;
86 struct mii_if_info mii;
Ben Dooks825a2ff2007-07-03 16:53:09 +010087
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010088 u32 msg_enable;
89 void __iomem *map2;
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010090 struct resource *mem;
91 struct resource *mem2;
Marc Kleine-Buddea54dc582011-02-21 10:43:31 +010092 const struct ax_plat_data *plat;
Ben Dooks825a2ff2007-07-03 16:53:09 +010093
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010094 unsigned char running;
95 unsigned char resume_open;
96 unsigned int irqflags;
Ben Dooks825a2ff2007-07-03 16:53:09 +010097
Marc Kleine-Budde9f072422011-02-19 17:07:40 +010098 u32 reg_offsets[0x20];
Ben Dooks825a2ff2007-07-03 16:53:09 +010099};
100
101static inline struct ax_device *to_ax_dev(struct net_device *dev)
102{
103 struct ei_device *ei_local = netdev_priv(dev);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100104 return (struct ax_device *)(ei_local + 1);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100105}
106
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100107/*
108 * ax_initial_check
Ben Dooks825a2ff2007-07-03 16:53:09 +0100109 *
110 * do an initial probe for the card to check wether it exists
111 * and is functional
112 */
Ben Dooks825a2ff2007-07-03 16:53:09 +0100113static int ax_initial_check(struct net_device *dev)
114{
115 struct ei_device *ei_local = netdev_priv(dev);
116 void __iomem *ioaddr = ei_local->mem;
117 int reg0;
118 int regd;
119
120 reg0 = ei_inb(ioaddr);
121 if (reg0 == 0xFF)
122 return -ENODEV;
123
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100124 ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100125 regd = ei_inb(ioaddr + 0x0d);
126 ei_outb(0xff, ioaddr + 0x0d);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100127 ei_outb(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100128 ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
129 if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
130 ei_outb(reg0, ioaddr);
131 ei_outb(regd, ioaddr + 0x0d); /* Restore the old values. */
132 return -ENODEV;
133 }
134
135 return 0;
136}
137
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100138/*
139 * Hard reset the card. This used to pause for the same period that a
140 * 8390 reset command required, but that shouldn't be necessary.
141 */
Ben Dooks825a2ff2007-07-03 16:53:09 +0100142static void ax_reset_8390(struct net_device *dev)
143{
144 struct ei_device *ei_local = netdev_priv(dev);
145 unsigned long reset_start_time = jiffies;
146 void __iomem *addr = (void __iomem *)dev->base_addr;
147
148 if (ei_debug > 1)
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100149 netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100150
151 ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
152
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100153 ei_local->txing = 0;
154 ei_local->dmaing = 0;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100155
156 /* This check _should_not_ be necessary, omit eventually. */
157 while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100158 if (jiffies - reset_start_time > 2 * HZ / 100) {
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100159 netdev_warn(dev, "%s: did not complete.\n", __func__);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100160 break;
161 }
162 }
163
164 ei_outb(ENISR_RESET, addr + EN0_ISR); /* Ack intr. */
165}
166
167
168static void ax_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
169 int ring_page)
170{
171 struct ei_device *ei_local = netdev_priv(dev);
172 void __iomem *nic_base = ei_local->mem;
173
174 /* This *shouldn't* happen. If it does, it's the last thing you'll see */
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100175 if (ei_local->dmaing) {
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100176 netdev_err(dev, "DMAing conflict in %s "
Ben Dooks237c5e82008-01-31 11:25:31 +0000177 "[DMAstat:%d][irqlock:%d].\n",
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100178 __func__,
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100179 ei_local->dmaing, ei_local->irqlock);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100180 return;
181 }
182
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100183 ei_local->dmaing |= 0x01;
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100184 ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100185 ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
186 ei_outb(0, nic_base + EN0_RCNTHI);
187 ei_outb(0, nic_base + EN0_RSARLO); /* On page boundary */
188 ei_outb(ring_page, nic_base + EN0_RSARHI);
189 ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
190
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100191 if (ei_local->word16)
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100192 readsw(nic_base + NE_DATAPORT, hdr,
193 sizeof(struct e8390_pkt_hdr) >> 1);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100194 else
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100195 readsb(nic_base + NE_DATAPORT, hdr,
196 sizeof(struct e8390_pkt_hdr));
Ben Dooks825a2ff2007-07-03 16:53:09 +0100197
198 ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100199 ei_local->dmaing &= ~0x01;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100200
201 le16_to_cpus(&hdr->count);
202}
203
204
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100205/*
206 * Block input and output, similar to the Crynwr packet driver. If
207 * you are porting to a new ethercard, look at the packet driver
208 * source for hints. The NEx000 doesn't share the on-board packet
209 * memory -- you have to put the packet out through the "remote DMA"
210 * dataport using ei_outb.
211 */
Ben Dooks825a2ff2007-07-03 16:53:09 +0100212static void ax_block_input(struct net_device *dev, int count,
213 struct sk_buff *skb, int ring_offset)
214{
215 struct ei_device *ei_local = netdev_priv(dev);
216 void __iomem *nic_base = ei_local->mem;
217 char *buf = skb->data;
218
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100219 if (ei_local->dmaing) {
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100220 netdev_err(dev,
221 "DMAing conflict in %s "
Ben Dooks825a2ff2007-07-03 16:53:09 +0100222 "[DMAstat:%d][irqlock:%d].\n",
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100223 __func__,
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100224 ei_local->dmaing, ei_local->irqlock);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100225 return;
226 }
227
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100228 ei_local->dmaing |= 0x01;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100229
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100230 ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + NE_CMD);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100231 ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
232 ei_outb(count >> 8, nic_base + EN0_RCNTHI);
233 ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
234 ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
235 ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
236
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100237 if (ei_local->word16) {
Ben Dooks825a2ff2007-07-03 16:53:09 +0100238 readsw(nic_base + NE_DATAPORT, buf, count >> 1);
239 if (count & 0x01)
240 buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
241
242 } else {
243 readsb(nic_base + NE_DATAPORT, buf, count);
244 }
245
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100246 ei_local->dmaing &= ~1;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100247}
248
249static void ax_block_output(struct net_device *dev, int count,
250 const unsigned char *buf, const int start_page)
251{
252 struct ei_device *ei_local = netdev_priv(dev);
253 void __iomem *nic_base = ei_local->mem;
254 unsigned long dma_start;
255
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100256 /*
257 * Round the count up for word writes. Do we need to do this?
258 * What effect will an odd byte count have on the 8390? I
259 * should check someday.
260 */
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100261 if (ei_local->word16 && (count & 0x01))
Ben Dooks825a2ff2007-07-03 16:53:09 +0100262 count++;
263
264 /* This *shouldn't* happen. If it does, it's the last thing you'll see */
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100265 if (ei_local->dmaing) {
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100266 netdev_err(dev, "DMAing conflict in %s."
Ben Dooks825a2ff2007-07-03 16:53:09 +0100267 "[DMAstat:%d][irqlock:%d]\n",
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100268 __func__,
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100269 ei_local->dmaing, ei_local->irqlock);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100270 return;
271 }
272
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100273 ei_local->dmaing |= 0x01;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100274 /* We should already be in page 0, but to be safe... */
275 ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
276
277 ei_outb(ENISR_RDC, nic_base + EN0_ISR);
278
279 /* Now the normal output. */
280 ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100281 ei_outb(count >> 8, nic_base + EN0_RCNTHI);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100282 ei_outb(0x00, nic_base + EN0_RSARLO);
283 ei_outb(start_page, nic_base + EN0_RSARHI);
284
285 ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100286 if (ei_local->word16)
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100287 writesw(nic_base + NE_DATAPORT, buf, count >> 1);
288 else
Ben Dooks825a2ff2007-07-03 16:53:09 +0100289 writesb(nic_base + NE_DATAPORT, buf, count);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100290
291 dma_start = jiffies;
292
293 while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100294 if (jiffies - dma_start > 2 * HZ / 100) { /* 20ms */
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100295 netdev_warn(dev, "timeout waiting for Tx RDC.\n");
Ben Dooks825a2ff2007-07-03 16:53:09 +0100296 ax_reset_8390(dev);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100297 ax_NS8390_init(dev, 1);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100298 break;
299 }
300 }
301
302 ei_outb(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100303 ei_local->dmaing &= ~0x01;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100304}
305
306/* definitions for accessing MII/EEPROM interface */
307
308#define AX_MEMR EI_SHIFT(0x14)
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100309#define AX_MEMR_MDC BIT(0)
310#define AX_MEMR_MDIR BIT(1)
311#define AX_MEMR_MDI BIT(2)
312#define AX_MEMR_MDO BIT(3)
313#define AX_MEMR_EECS BIT(4)
314#define AX_MEMR_EEI BIT(5)
315#define AX_MEMR_EEO BIT(6)
316#define AX_MEMR_EECLK BIT(7)
Ben Dooks825a2ff2007-07-03 16:53:09 +0100317
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100318/*
319 * ax_mii_ei_outbits
Ben Dooks825a2ff2007-07-03 16:53:09 +0100320 *
321 * write the specified set of bits to the phy
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100322 */
Ben Dooks825a2ff2007-07-03 16:53:09 +0100323static void
324ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len)
325{
Joe Perchesece49152010-11-15 11:12:31 +0000326 struct ei_device *ei_local = netdev_priv(dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100327 void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
328 unsigned int memr;
329
330 /* clock low, data to output mode */
331 memr = ei_inb(memr_addr);
332 memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR);
333 ei_outb(memr, memr_addr);
334
335 for (len--; len >= 0; len--) {
336 if (bits & (1 << len))
337 memr |= AX_MEMR_MDO;
338 else
339 memr &= ~AX_MEMR_MDO;
340
341 ei_outb(memr, memr_addr);
342
343 /* clock high */
344
345 ei_outb(memr | AX_MEMR_MDC, memr_addr);
346 udelay(1);
347
348 /* clock low */
349 ei_outb(memr, memr_addr);
350 }
351
352 /* leaves the clock line low, mdir input */
353 memr |= AX_MEMR_MDIR;
354 ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR);
355}
356
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100357/*
358 * ax_phy_ei_inbits
Ben Dooks825a2ff2007-07-03 16:53:09 +0100359 *
360 * read a specified number of bits from the phy
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100361 */
Ben Dooks825a2ff2007-07-03 16:53:09 +0100362static unsigned int
363ax_phy_ei_inbits(struct net_device *dev, int no)
364{
Joe Perchesece49152010-11-15 11:12:31 +0000365 struct ei_device *ei_local = netdev_priv(dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100366 void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
367 unsigned int memr;
368 unsigned int result = 0;
369
370 /* clock low, data to input mode */
371 memr = ei_inb(memr_addr);
372 memr &= ~AX_MEMR_MDC;
373 memr |= AX_MEMR_MDIR;
374 ei_outb(memr, memr_addr);
375
376 for (no--; no >= 0; no--) {
377 ei_outb(memr | AX_MEMR_MDC, memr_addr);
378
379 udelay(1);
380
381 if (ei_inb(memr_addr) & AX_MEMR_MDI)
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100382 result |= (1 << no);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100383
384 ei_outb(memr, memr_addr);
385 }
386
387 return result;
388}
389
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100390/*
391 * ax_phy_issueaddr
Ben Dooks825a2ff2007-07-03 16:53:09 +0100392 *
393 * use the low level bit shifting routines to send the address
394 * and command to the specified phy
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100395 */
Ben Dooks825a2ff2007-07-03 16:53:09 +0100396static void
397ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc)
398{
399 if (phy_debug)
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100400 netdev_dbg(dev, "%s: dev %p, %04x, %04x, %d\n",
Harvey Harrisonb39d66a2008-08-20 16:52:04 -0700401 __func__, dev, phy_addr, reg, opc);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100402
403 ax_mii_ei_outbits(dev, 0x3f, 6); /* pre-amble */
404 ax_mii_ei_outbits(dev, 1, 2); /* frame-start */
405 ax_mii_ei_outbits(dev, opc, 2); /* op code */
406 ax_mii_ei_outbits(dev, phy_addr, 5); /* phy address */
407 ax_mii_ei_outbits(dev, reg, 5); /* reg address */
408}
409
410static int
411ax_phy_read(struct net_device *dev, int phy_addr, int reg)
412{
Joe Perchesece49152010-11-15 11:12:31 +0000413 struct ei_device *ei_local = netdev_priv(dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100414 unsigned long flags;
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100415 unsigned int result;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100416
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100417 spin_lock_irqsave(&ei_local->page_lock, flags);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100418
419 ax_phy_issueaddr(dev, phy_addr, reg, 2);
420
421 result = ax_phy_ei_inbits(dev, 17);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100422 result &= ~(3 << 16);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100423
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100424 spin_unlock_irqrestore(&ei_local->page_lock, flags);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100425
426 if (phy_debug)
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100427 netdev_dbg(dev, "%s: %04x.%04x => read %04x\n", __func__,
Ben Dooks825a2ff2007-07-03 16:53:09 +0100428 phy_addr, reg, result);
429
430 return result;
431}
432
433static void
434ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
435{
Joe Perchesece49152010-11-15 11:12:31 +0000436 struct ei_device *ei = netdev_priv(dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100437 unsigned long flags;
438
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100439 netdev_dbg(dev, "%s: %p, %04x, %04x %04x\n",
Harvey Harrisonb39d66a2008-08-20 16:52:04 -0700440 __func__, dev, phy_addr, reg, value);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100441
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100442 spin_lock_irqsave(&ei->page_lock, flags);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100443
444 ax_phy_issueaddr(dev, phy_addr, reg, 1);
445 ax_mii_ei_outbits(dev, 2, 2); /* send TA */
446 ax_mii_ei_outbits(dev, value, 16);
447
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100448 spin_unlock_irqrestore(&ei->page_lock, flags);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100449}
450
451static void ax_mii_expiry(unsigned long data)
452{
453 struct net_device *dev = (struct net_device *)data;
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100454 struct ax_device *ax = to_ax_dev(dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100455 unsigned long flags;
456
457 spin_lock_irqsave(&ax->mii_lock, flags);
458 mii_check_media(&ax->mii, netif_msg_link(ax), 0);
459 spin_unlock_irqrestore(&ax->mii_lock, flags);
460
461 if (ax->running) {
462 ax->mii_timer.expires = jiffies + HZ*2;
463 add_timer(&ax->mii_timer);
464 }
465}
466
467static int ax_open(struct net_device *dev)
468{
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100469 struct ax_device *ax = to_ax_dev(dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100470 struct ei_device *ei_local = netdev_priv(dev);
471 int ret;
472
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100473 netdev_dbg(dev, "open\n");
Ben Dooks825a2ff2007-07-03 16:53:09 +0100474
Daniel Mack47cb0352009-03-24 23:31:22 -0700475 ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
476 dev->name, dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100477 if (ret)
478 return ret;
479
480 ret = ax_ei_open(dev);
Kulikov Vasiliy9f1e7582010-07-08 23:42:40 -0700481 if (ret) {
482 free_irq(dev->irq, dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100483 return ret;
Kulikov Vasiliy9f1e7582010-07-08 23:42:40 -0700484 }
Ben Dooks825a2ff2007-07-03 16:53:09 +0100485
486 /* turn the phy on (if turned off) */
487
488 ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17));
489 ax->running = 1;
490
491 /* start the MII timer */
492
493 init_timer(&ax->mii_timer);
494
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100495 ax->mii_timer.expires = jiffies + 1;
496 ax->mii_timer.data = (unsigned long) dev;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100497 ax->mii_timer.function = ax_mii_expiry;
498
499 add_timer(&ax->mii_timer);
500
501 return 0;
502}
503
504static int ax_close(struct net_device *dev)
505{
506 struct ax_device *ax = to_ax_dev(dev);
507 struct ei_device *ei_local = netdev_priv(dev);
508
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100509 netdev_dbg(dev, "close\n");
Ben Dooks825a2ff2007-07-03 16:53:09 +0100510
511 /* turn the phy off */
512
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100513 ei_outb(ax->plat->gpoc_val | (1 << 6),
Ben Dooks825a2ff2007-07-03 16:53:09 +0100514 ei_local->mem + EI_SHIFT(0x17));
515
516 ax->running = 0;
517 wmb();
518
519 del_timer_sync(&ax->mii_timer);
520 ax_ei_close(dev);
521
522 free_irq(dev->irq, dev);
523 return 0;
524}
525
526static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
527{
528 struct ax_device *ax = to_ax_dev(dev);
529 unsigned long flags;
530 int rc;
531
532 if (!netif_running(dev))
533 return -EINVAL;
534
535 spin_lock_irqsave(&ax->mii_lock, flags);
536 rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL);
537 spin_unlock_irqrestore(&ax->mii_lock, flags);
538
539 return rc;
540}
541
542/* ethtool ops */
543
544static void ax_get_drvinfo(struct net_device *dev,
545 struct ethtool_drvinfo *info)
546{
Marc Kleine-Budde0f442f52011-02-20 19:13:20 +0100547 struct platform_device *pdev = to_platform_device(dev->dev.parent);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100548
549 strcpy(info->driver, DRV_NAME);
550 strcpy(info->version, DRV_VERSION);
Marc Kleine-Budde0f442f52011-02-20 19:13:20 +0100551 strcpy(info->bus_info, pdev->name);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100552}
553
554static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
555{
556 struct ax_device *ax = to_ax_dev(dev);
557 unsigned long flags;
558
559 spin_lock_irqsave(&ax->mii_lock, flags);
560 mii_ethtool_gset(&ax->mii, cmd);
Ben Dooksc0912582008-08-07 17:21:09 +0100561 spin_unlock_irqrestore(&ax->mii_lock, flags);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100562
563 return 0;
564}
565
566static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
567{
568 struct ax_device *ax = to_ax_dev(dev);
569 unsigned long flags;
570 int rc;
571
572 spin_lock_irqsave(&ax->mii_lock, flags);
573 rc = mii_ethtool_sset(&ax->mii, cmd);
Ben Dooksc0912582008-08-07 17:21:09 +0100574 spin_unlock_irqrestore(&ax->mii_lock, flags);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100575
576 return rc;
577}
578
579static int ax_nway_reset(struct net_device *dev)
580{
581 struct ax_device *ax = to_ax_dev(dev);
582 return mii_nway_restart(&ax->mii);
583}
584
585static u32 ax_get_link(struct net_device *dev)
586{
587 struct ax_device *ax = to_ax_dev(dev);
588 return mii_link_ok(&ax->mii);
589}
590
591static const struct ethtool_ops ax_ethtool_ops = {
592 .get_drvinfo = ax_get_drvinfo,
593 .get_settings = ax_get_settings,
594 .set_settings = ax_set_settings,
595 .nway_reset = ax_nway_reset,
596 .get_link = ax_get_link,
Ben Dooks825a2ff2007-07-03 16:53:09 +0100597};
598
Magnus Damm89e536a2007-09-28 22:42:16 -0700599#ifdef CONFIG_AX88796_93CX6
600static void ax_eeprom_register_read(struct eeprom_93cx6 *eeprom)
601{
602 struct ei_device *ei_local = eeprom->data;
603 u8 reg = ei_inb(ei_local->mem + AX_MEMR);
604
605 eeprom->reg_data_in = reg & AX_MEMR_EEI;
606 eeprom->reg_data_out = reg & AX_MEMR_EEO; /* Input pin */
607 eeprom->reg_data_clock = reg & AX_MEMR_EECLK;
608 eeprom->reg_chip_select = reg & AX_MEMR_EECS;
609}
610
611static void ax_eeprom_register_write(struct eeprom_93cx6 *eeprom)
612{
613 struct ei_device *ei_local = eeprom->data;
614 u8 reg = ei_inb(ei_local->mem + AX_MEMR);
615
616 reg &= ~(AX_MEMR_EEI | AX_MEMR_EECLK | AX_MEMR_EECS);
617
618 if (eeprom->reg_data_in)
619 reg |= AX_MEMR_EEI;
620 if (eeprom->reg_data_clock)
621 reg |= AX_MEMR_EECLK;
622 if (eeprom->reg_chip_select)
623 reg |= AX_MEMR_EECS;
624
625 ei_outb(reg, ei_local->mem + AX_MEMR);
626 udelay(10);
627}
628#endif
629
Magnus Dammd57bc362009-01-14 21:05:55 -0800630static const struct net_device_ops ax_netdev_ops = {
631 .ndo_open = ax_open,
632 .ndo_stop = ax_close,
633 .ndo_do_ioctl = ax_ioctl,
634
635 .ndo_start_xmit = ax_ei_start_xmit,
636 .ndo_tx_timeout = ax_ei_tx_timeout,
637 .ndo_get_stats = ax_ei_get_stats,
638 .ndo_set_multicast_list = ax_ei_set_multicast_list,
639 .ndo_validate_addr = eth_validate_addr,
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100640 .ndo_set_mac_address = eth_mac_addr,
Magnus Dammd57bc362009-01-14 21:05:55 -0800641 .ndo_change_mtu = eth_change_mtu,
642#ifdef CONFIG_NET_POLL_CONTROLLER
643 .ndo_poll_controller = ax_ei_poll,
644#endif
645};
646
Ben Dooks825a2ff2007-07-03 16:53:09 +0100647/* setup code */
648
649static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
650{
651 void __iomem *ioaddr = ei_local->mem;
652 struct ax_device *ax = to_ax_dev(dev);
653
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100654 /* Select page 0 */
655 ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_STOP, ioaddr + E8390_CMD);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100656
657 /* set to byte access */
658 ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
659 ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
660}
661
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100662/*
663 * ax_init_dev
Ben Dooks825a2ff2007-07-03 16:53:09 +0100664 *
665 * initialise the specified device, taking care to note the MAC
666 * address it may already have (if configured), ensure
667 * the device is ready to be used by lib8390.c and registerd with
668 * the network layer.
669 */
Marc Kleine-Budde1cbece32011-02-19 23:07:09 +0100670static int ax_init_dev(struct net_device *dev)
Ben Dooks825a2ff2007-07-03 16:53:09 +0100671{
672 struct ei_device *ei_local = netdev_priv(dev);
673 struct ax_device *ax = to_ax_dev(dev);
674 void __iomem *ioaddr = ei_local->mem;
675 unsigned int start_page;
676 unsigned int stop_page;
677 int ret;
678 int i;
679
680 ret = ax_initial_check(dev);
681 if (ret)
682 goto err_out;
683
684 /* setup goes here */
685
686 ax_initial_setup(dev, ei_local);
687
688 /* read the mac from the card prom if we need it */
689
Marc Kleine-Budde1cbece32011-02-19 23:07:09 +0100690 if (ax->plat->flags & AXFLG_HAS_EEPROM) {
Ben Dooks825a2ff2007-07-03 16:53:09 +0100691 unsigned char SA_prom[32];
692
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100693 for (i = 0; i < sizeof(SA_prom); i += 2) {
Ben Dooks825a2ff2007-07-03 16:53:09 +0100694 SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100695 SA_prom[i + 1] = ei_inb(ioaddr + NE_DATAPORT);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100696 }
697
698 if (ax->plat->wordlength == 2)
699 for (i = 0; i < 16; i++)
700 SA_prom[i] = SA_prom[i+i];
701
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100702 memcpy(dev->dev_addr, SA_prom, 6);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100703 }
704
Magnus Damm89e536a2007-09-28 22:42:16 -0700705#ifdef CONFIG_AX88796_93CX6
Marc Kleine-Budde1cbece32011-02-19 23:07:09 +0100706 if (ax->plat->flags & AXFLG_HAS_93CX6) {
Magnus Damm89e536a2007-09-28 22:42:16 -0700707 unsigned char mac_addr[6];
708 struct eeprom_93cx6 eeprom;
709
710 eeprom.data = ei_local;
711 eeprom.register_read = ax_eeprom_register_read;
712 eeprom.register_write = ax_eeprom_register_write;
713 eeprom.width = PCI_EEPROM_WIDTH_93C56;
714
715 eeprom_93cx6_multiread(&eeprom, 0,
716 (__le16 __force *)mac_addr,
717 sizeof(mac_addr) >> 1);
718
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100719 memcpy(dev->dev_addr, mac_addr, 6);
Magnus Damm89e536a2007-09-28 22:42:16 -0700720 }
721#endif
Ben Dooks825a2ff2007-07-03 16:53:09 +0100722 if (ax->plat->wordlength == 2) {
723 /* We must set the 8390 for word mode. */
724 ei_outb(ax->plat->dcr_val, ei_local->mem + EN0_DCFG);
725 start_page = NESM_START_PG;
726 stop_page = NESM_STOP_PG;
727 } else {
728 start_page = NE1SM_START_PG;
729 stop_page = NE1SM_STOP_PG;
730 }
731
Marc Kleine-Budde1cbece32011-02-19 23:07:09 +0100732 /* load the mac-address from the device */
733 if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
734 ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
735 ei_local->mem + E8390_CMD); /* 0x61 */
736 for (i = 0; i < ETHER_ADDR_LEN; i++)
737 dev->dev_addr[i] =
738 ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
Ben Dooks825a2ff2007-07-03 16:53:09 +0100739 }
740
Marc Kleine-Budde1cbece32011-02-19 23:07:09 +0100741 if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
742 ax->plat->mac_addr)
743 memcpy(dev->dev_addr, ax->plat->mac_addr,
744 ETHER_ADDR_LEN);
745
Ben Dooks825a2ff2007-07-03 16:53:09 +0100746 ax_reset_8390(dev);
747
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100748 ei_local->name = "AX88796";
749 ei_local->tx_start_page = start_page;
750 ei_local->stop_page = stop_page;
751 ei_local->word16 = (ax->plat->wordlength == 2);
752 ei_local->rx_start_page = start_page + TX_PAGES;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100753
754#ifdef PACKETBUF_MEMSIZE
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100755 /* Allow the packet buffer size to be overridden by know-it-alls. */
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100756 ei_local->stop_page = ei_local->tx_start_page + PACKETBUF_MEMSIZE;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100757#endif
758
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100759 ei_local->reset_8390 = &ax_reset_8390;
760 ei_local->block_input = &ax_block_input;
761 ei_local->block_output = &ax_block_output;
762 ei_local->get_8390_hdr = &ax_get_8390_hdr;
763 ei_local->priv = 0;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100764
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100765 dev->netdev_ops = &ax_netdev_ops;
766 dev->ethtool_ops = &ax_ethtool_ops;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100767
768 ax->msg_enable = NETIF_MSG_LINK;
769 ax->mii.phy_id_mask = 0x1f;
770 ax->mii.reg_num_mask = 0x1f;
771 ax->mii.phy_id = 0x10; /* onboard phy */
772 ax->mii.force_media = 0;
773 ax->mii.full_duplex = 0;
774 ax->mii.mdio_read = ax_phy_read;
775 ax->mii.mdio_write = ax_phy_write;
776 ax->mii.dev = dev;
777
Ben Dooks825a2ff2007-07-03 16:53:09 +0100778 ax_NS8390_init(dev, 0);
779
Ben Dooks825a2ff2007-07-03 16:53:09 +0100780 ret = register_netdev(dev);
781 if (ret)
782 goto out_irq;
783
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100784 netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",
785 ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr,
786 dev->dev_addr);
787
Ben Dooks825a2ff2007-07-03 16:53:09 +0100788 return 0;
789
790 out_irq:
791 /* cleanup irq */
792 free_irq(dev->irq, dev);
793 err_out:
794 return ret;
795}
796
797static int ax_remove(struct platform_device *_dev)
798{
799 struct net_device *dev = platform_get_drvdata(_dev);
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100800 struct ei_device *ei_local = netdev_priv(dev);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100801 struct ax_device *ax;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100802
803 ax = to_ax_dev(dev);
804
805 unregister_netdev(dev);
806 free_irq(dev->irq, dev);
807
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100808 iounmap(ei_local->mem);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100809 release_resource(ax->mem);
810 kfree(ax->mem);
811
812 if (ax->map2) {
813 iounmap(ax->map2);
814 release_resource(ax->mem2);
815 kfree(ax->mem2);
816 }
817
818 free_netdev(dev);
819
820 return 0;
821}
822
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100823/*
824 * ax_probe
Ben Dooks825a2ff2007-07-03 16:53:09 +0100825 *
826 * This is the entry point when the platform device system uses to
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100827 * notify us of a new device to attach to. Allocate memory, find the
828 * resources and information passed, and map the necessary registers.
829 */
Ben Dooks825a2ff2007-07-03 16:53:09 +0100830static int ax_probe(struct platform_device *pdev)
831{
832 struct net_device *dev;
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100833 struct ei_device *ei_local;
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100834 struct ax_device *ax;
835 struct resource *res;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100836 size_t size;
Daniel Mack47cb0352009-03-24 23:31:22 -0700837 int ret = 0;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100838
839 dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
840 if (dev == NULL)
841 return -ENOMEM;
842
843 /* ok, let's setup our device */
Marc Kleine-Budde85ac6162011-02-20 17:46:18 +0100844 SET_NETDEV_DEV(dev, &pdev->dev);
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100845 ei_local = netdev_priv(dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100846 ax = to_ax_dev(dev);
847
Ben Dooks825a2ff2007-07-03 16:53:09 +0100848 spin_lock_init(&ax->mii_lock);
849
Ben Dooks825a2ff2007-07-03 16:53:09 +0100850 ax->plat = pdev->dev.platform_data;
851 platform_set_drvdata(pdev, dev);
852
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100853 ei_local->rxcr_base = ax->plat->rcr_val;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100854
855 /* find the platform resources */
Daniel Mack47cb0352009-03-24 23:31:22 -0700856 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
857 if (res == NULL) {
Ben Dooks825a2ff2007-07-03 16:53:09 +0100858 dev_err(&pdev->dev, "no IRQ specified\n");
Julia Lawall13eea192010-10-18 04:11:14 +0000859 ret = -ENXIO;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100860 goto exit_mem;
861 }
Daniel Mack47cb0352009-03-24 23:31:22 -0700862
863 dev->irq = res->start;
864 ax->irqflags = res->flags & IRQF_TRIGGER_MASK;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100865
866 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
867 if (res == NULL) {
868 dev_err(&pdev->dev, "no MEM specified\n");
869 ret = -ENXIO;
870 goto exit_mem;
871 }
872
873 size = (res->end - res->start) + 1;
874
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100875 /*
876 * setup the register offsets from either the platform data or
877 * by using the size of the resource provided
878 */
Ben Dooks825a2ff2007-07-03 16:53:09 +0100879 if (ax->plat->reg_offsets)
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100880 ei_local->reg_offset = ax->plat->reg_offsets;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100881 else {
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100882 ei_local->reg_offset = ax->reg_offsets;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100883 for (ret = 0; ret < 0x18; ret++)
884 ax->reg_offsets[ret] = (size / 0x18) * ret;
885 }
886
887 ax->mem = request_mem_region(res->start, size, pdev->name);
888 if (ax->mem == NULL) {
889 dev_err(&pdev->dev, "cannot reserve registers\n");
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100890 ret = -ENXIO;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100891 goto exit_mem;
892 }
893
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100894 ei_local->mem = ioremap(res->start, size);
895 dev->base_addr = (unsigned long)ei_local->mem;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100896
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100897 if (ei_local->mem == NULL) {
Andrew Mortonb4efe222007-08-10 14:05:21 -0700898 dev_err(&pdev->dev, "Cannot ioremap area (%08llx,%08llx)\n",
899 (unsigned long long)res->start,
900 (unsigned long long)res->end);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100901
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100902 ret = -ENXIO;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100903 goto exit_req;
904 }
905
906 /* look for reset area */
907
908 res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
909 if (res == NULL) {
910 if (!ax->plat->reg_offsets) {
911 for (ret = 0; ret < 0x20; ret++)
912 ax->reg_offsets[ret] = (size / 0x20) * ret;
913 }
914
915 ax->map2 = NULL;
916 } else {
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100917 size = (res->end - res->start) + 1;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100918
919 ax->mem2 = request_mem_region(res->start, size, pdev->name);
Julia Lawallbcf4d812010-02-08 22:44:18 -0800920 if (ax->mem2 == NULL) {
Ben Dooks825a2ff2007-07-03 16:53:09 +0100921 dev_err(&pdev->dev, "cannot reserve registers\n");
922 ret = -ENXIO;
923 goto exit_mem1;
924 }
925
926 ax->map2 = ioremap(res->start, size);
927 if (ax->map2 == NULL) {
Joe Perches898eb712007-10-18 03:06:30 -0700928 dev_err(&pdev->dev, "cannot map reset register\n");
Ben Dooks825a2ff2007-07-03 16:53:09 +0100929 ret = -ENXIO;
930 goto exit_mem2;
931 }
932
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100933 ei_local->reg_offset[0x1f] = ax->map2 - ei_local->mem;
Ben Dooks825a2ff2007-07-03 16:53:09 +0100934 }
935
936 /* got resources, now initialise and register device */
937
Marc Kleine-Budde1cbece32011-02-19 23:07:09 +0100938 ret = ax_init_dev(dev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100939 if (!ret)
940 return 0;
941
942 if (ax->map2 == NULL)
943 goto exit_mem1;
944
945 iounmap(ax->map2);
946
947 exit_mem2:
948 release_resource(ax->mem2);
949 kfree(ax->mem2);
950
951 exit_mem1:
Marc Kleine-Buddeea5a43d2011-02-19 22:08:33 +0100952 iounmap(ei_local->mem);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100953
954 exit_req:
955 release_resource(ax->mem);
956 kfree(ax->mem);
957
958 exit_mem:
959 free_netdev(dev);
960
961 return ret;
962}
963
964/* suspend and resume */
965
966#ifdef CONFIG_PM
967static int ax_suspend(struct platform_device *dev, pm_message_t state)
968{
969 struct net_device *ndev = platform_get_drvdata(dev);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100970 struct ax_device *ax = to_ax_dev(ndev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100971
972 ax->resume_open = ax->running;
973
974 netif_device_detach(ndev);
975 ax_close(ndev);
976
977 return 0;
978}
979
980static int ax_resume(struct platform_device *pdev)
981{
982 struct net_device *ndev = platform_get_drvdata(pdev);
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100983 struct ax_device *ax = to_ax_dev(ndev);
Ben Dooks825a2ff2007-07-03 16:53:09 +0100984
985 ax_initial_setup(ndev, netdev_priv(ndev));
986 ax_NS8390_init(ndev, ax->resume_open);
987 netif_device_attach(ndev);
988
989 if (ax->resume_open)
990 ax_open(ndev);
991
992 return 0;
993}
994
995#else
996#define ax_suspend NULL
Marc Kleine-Budde9f072422011-02-19 17:07:40 +0100997#define ax_resume NULL
Ben Dooks825a2ff2007-07-03 16:53:09 +0100998#endif
999
1000static struct platform_driver axdrv = {
1001 .driver = {
1002 .name = "ax88796",
1003 .owner = THIS_MODULE,
1004 },
1005 .probe = ax_probe,
1006 .remove = ax_remove,
1007 .suspend = ax_suspend,
1008 .resume = ax_resume,
1009};
1010
1011static int __init axdrv_init(void)
1012{
1013 return platform_driver_register(&axdrv);
1014}
1015
1016static void __exit axdrv_exit(void)
1017{
1018 platform_driver_unregister(&axdrv);
1019}
1020
1021module_init(axdrv_init);
1022module_exit(axdrv_exit);
1023
1024MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver");
1025MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
1026MODULE_LICENSE("GPL v2");
Kay Sievers72abb462008-04-18 13:50:44 -07001027MODULE_ALIAS("platform:ax88796");