]>
Commit | Line | Data |
---|---|---|
9899b81e MS |
1 | /* |
2 | * Ethernet driver for the WIZnet W5300 chip. | |
3 | * | |
4 | * Copyright (C) 2008-2009 WIZnet Co.,Ltd. | |
5 | * Copyright (C) 2011 Taehun Kim <kth3321 <at> gmail.com> | |
6 | * Copyright (C) 2012 Mike Sinkovsky <msink@permonline.ru> | |
7 | * | |
8 | * Licensed under the GPL-2 or later. | |
9 | */ | |
10 | ||
11 | #include <linux/kernel.h> | |
12 | #include <linux/module.h> | |
13 | #include <linux/kconfig.h> | |
14 | #include <linux/netdevice.h> | |
15 | #include <linux/etherdevice.h> | |
16 | #include <linux/platform_device.h> | |
17 | #include <linux/platform_data/wiznet.h> | |
18 | #include <linux/ethtool.h> | |
19 | #include <linux/skbuff.h> | |
20 | #include <linux/types.h> | |
21 | #include <linux/errno.h> | |
22 | #include <linux/delay.h> | |
23 | #include <linux/slab.h> | |
24 | #include <linux/spinlock.h> | |
25 | #include <linux/io.h> | |
26 | #include <linux/ioport.h> | |
27 | #include <linux/interrupt.h> | |
64d176fc | 28 | #include <linux/irq.h> |
9899b81e MS |
29 | #include <linux/gpio.h> |
30 | ||
31 | #define DRV_NAME "w5300" | |
32 | #define DRV_VERSION "2012-04-04" | |
33 | ||
34 | MODULE_DESCRIPTION("WIZnet W5300 Ethernet driver v"DRV_VERSION); | |
35 | MODULE_AUTHOR("Mike Sinkovsky <msink@permonline.ru>"); | |
36 | MODULE_ALIAS("platform:"DRV_NAME); | |
37 | MODULE_LICENSE("GPL"); | |
38 | ||
39 | /* | |
40 | * Registers | |
41 | */ | |
42 | #define W5300_MR 0x0000 /* Mode Register */ | |
43 | #define MR_DBW (1 << 15) /* Data bus width */ | |
44 | #define MR_MPF (1 << 14) /* Mac layer pause frame */ | |
45 | #define MR_WDF(n) (((n)&7)<<11) /* Write data fetch time */ | |
46 | #define MR_RDH (1 << 10) /* Read data hold time */ | |
47 | #define MR_FS (1 << 8) /* FIFO swap */ | |
48 | #define MR_RST (1 << 7) /* S/W reset */ | |
49 | #define MR_PB (1 << 4) /* Ping block */ | |
50 | #define MR_DBS (1 << 2) /* Data bus swap */ | |
51 | #define MR_IND (1 << 0) /* Indirect mode */ | |
52 | #define W5300_IR 0x0002 /* Interrupt Register */ | |
53 | #define W5300_IMR 0x0004 /* Interrupt Mask Register */ | |
54 | #define IR_S0 0x0001 /* S0 interrupt */ | |
55 | #define W5300_SHARL 0x0008 /* Source MAC address (0123) */ | |
56 | #define W5300_SHARH 0x000c /* Source MAC address (45) */ | |
57 | #define W5300_TMSRL 0x0020 /* Transmit Memory Size (0123) */ | |
58 | #define W5300_TMSRH 0x0024 /* Transmit Memory Size (4567) */ | |
59 | #define W5300_RMSRL 0x0028 /* Receive Memory Size (0123) */ | |
60 | #define W5300_RMSRH 0x002c /* Receive Memory Size (4567) */ | |
61 | #define W5300_MTYPE 0x0030 /* Memory Type */ | |
62 | #define W5300_IDR 0x00fe /* Chip ID register */ | |
63 | #define IDR_W5300 0x5300 /* =0x5300 for WIZnet W5300 */ | |
64 | #define W5300_S0_MR 0x0200 /* S0 Mode Register */ | |
65 | #define S0_MR_CLOSED 0x0000 /* Close mode */ | |
66 | #define S0_MR_MACRAW 0x0004 /* MAC RAW mode (promiscous) */ | |
67 | #define S0_MR_MACRAW_MF 0x0044 /* MAC RAW mode (filtered) */ | |
68 | #define W5300_S0_CR 0x0202 /* S0 Command Register */ | |
69 | #define S0_CR_OPEN 0x0001 /* OPEN command */ | |
70 | #define S0_CR_CLOSE 0x0010 /* CLOSE command */ | |
71 | #define S0_CR_SEND 0x0020 /* SEND command */ | |
72 | #define S0_CR_RECV 0x0040 /* RECV command */ | |
73 | #define W5300_S0_IMR 0x0204 /* S0 Interrupt Mask Register */ | |
74 | #define W5300_S0_IR 0x0206 /* S0 Interrupt Register */ | |
75 | #define S0_IR_RECV 0x0004 /* Receive interrupt */ | |
76 | #define S0_IR_SENDOK 0x0010 /* Send OK interrupt */ | |
77 | #define W5300_S0_SSR 0x0208 /* S0 Socket Status Register */ | |
78 | #define W5300_S0_TX_WRSR 0x0220 /* S0 TX Write Size Register */ | |
79 | #define W5300_S0_TX_FSR 0x0224 /* S0 TX Free Size Register */ | |
80 | #define W5300_S0_RX_RSR 0x0228 /* S0 Received data Size */ | |
81 | #define W5300_S0_TX_FIFO 0x022e /* S0 Transmit FIFO */ | |
82 | #define W5300_S0_RX_FIFO 0x0230 /* S0 Receive FIFO */ | |
83 | #define W5300_REGS_LEN 0x0400 | |
84 | ||
85 | /* | |
86 | * Device driver private data structure | |
87 | */ | |
88 | struct w5300_priv { | |
89 | void __iomem *base; | |
90 | spinlock_t reg_lock; | |
91 | bool indirect; | |
92 | u16 (*read) (struct w5300_priv *priv, u16 addr); | |
93 | void (*write)(struct w5300_priv *priv, u16 addr, u16 data); | |
94 | int irq; | |
95 | int link_irq; | |
96 | int link_gpio; | |
97 | ||
98 | struct napi_struct napi; | |
99 | struct net_device *ndev; | |
100 | bool promisc; | |
101 | u32 msg_enable; | |
102 | }; | |
103 | ||
104 | /************************************************************************ | |
105 | * | |
106 | * Lowlevel I/O functions | |
107 | * | |
108 | ***********************************************************************/ | |
109 | ||
110 | /* | |
111 | * In direct address mode host system can directly access W5300 registers | |
112 | * after mapping to Memory-Mapped I/O space. | |
113 | * | |
114 | * 0x400 bytes are required for memory space. | |
115 | */ | |
116 | static inline u16 w5300_read_direct(struct w5300_priv *priv, u16 addr) | |
117 | { | |
118 | return ioread16(priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT)); | |
119 | } | |
120 | ||
121 | static inline void w5300_write_direct(struct w5300_priv *priv, | |
122 | u16 addr, u16 data) | |
123 | { | |
124 | iowrite16(data, priv->base + (addr << CONFIG_WIZNET_BUS_SHIFT)); | |
125 | } | |
126 | ||
127 | /* | |
128 | * In indirect address mode host system indirectly accesses registers by | |
129 | * using Indirect Mode Address Register (IDM_AR) and Indirect Mode Data | |
130 | * Register (IDM_DR), which are directly mapped to Memory-Mapped I/O space. | |
131 | * Mode Register (MR) is directly accessible. | |
132 | * | |
133 | * Only 0x06 bytes are required for memory space. | |
134 | */ | |
135 | #define W5300_IDM_AR 0x0002 /* Indirect Mode Address */ | |
136 | #define W5300_IDM_DR 0x0004 /* Indirect Mode Data */ | |
137 | ||
138 | static u16 w5300_read_indirect(struct w5300_priv *priv, u16 addr) | |
139 | { | |
140 | unsigned long flags; | |
141 | u16 data; | |
142 | ||
143 | spin_lock_irqsave(&priv->reg_lock, flags); | |
144 | w5300_write_direct(priv, W5300_IDM_AR, addr); | |
145 | mmiowb(); | |
146 | data = w5300_read_direct(priv, W5300_IDM_DR); | |
147 | spin_unlock_irqrestore(&priv->reg_lock, flags); | |
148 | ||
149 | return data; | |
150 | } | |
151 | ||
152 | static void w5300_write_indirect(struct w5300_priv *priv, u16 addr, u16 data) | |
153 | { | |
154 | unsigned long flags; | |
155 | ||
156 | spin_lock_irqsave(&priv->reg_lock, flags); | |
157 | w5300_write_direct(priv, W5300_IDM_AR, addr); | |
158 | mmiowb(); | |
159 | w5300_write_direct(priv, W5300_IDM_DR, data); | |
160 | mmiowb(); | |
161 | spin_unlock_irqrestore(&priv->reg_lock, flags); | |
162 | } | |
163 | ||
164 | #if defined(CONFIG_WIZNET_BUS_DIRECT) | |
165 | #define w5300_read w5300_read_direct | |
166 | #define w5300_write w5300_write_direct | |
167 | ||
168 | #elif defined(CONFIG_WIZNET_BUS_INDIRECT) | |
169 | #define w5300_read w5300_read_indirect | |
170 | #define w5300_write w5300_write_indirect | |
171 | ||
172 | #else /* CONFIG_WIZNET_BUS_ANY */ | |
173 | #define w5300_read priv->read | |
174 | #define w5300_write priv->write | |
175 | #endif | |
176 | ||
177 | static u32 w5300_read32(struct w5300_priv *priv, u16 addr) | |
178 | { | |
179 | u32 data; | |
180 | data = w5300_read(priv, addr) << 16; | |
181 | data |= w5300_read(priv, addr + 2); | |
182 | return data; | |
183 | } | |
184 | ||
185 | static void w5300_write32(struct w5300_priv *priv, u16 addr, u32 data) | |
186 | { | |
187 | w5300_write(priv, addr, data >> 16); | |
188 | w5300_write(priv, addr + 2, data); | |
189 | } | |
190 | ||
191 | static int w5300_command(struct w5300_priv *priv, u16 cmd) | |
192 | { | |
193 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | |
194 | ||
195 | w5300_write(priv, W5300_S0_CR, cmd); | |
196 | mmiowb(); | |
197 | ||
198 | while (w5300_read(priv, W5300_S0_CR) != 0) { | |
199 | if (time_after(jiffies, timeout)) | |
200 | return -EIO; | |
201 | cpu_relax(); | |
202 | } | |
203 | ||
204 | return 0; | |
205 | } | |
206 | ||
207 | static void w5300_read_frame(struct w5300_priv *priv, u8 *buf, int len) | |
208 | { | |
209 | u16 fifo; | |
210 | int i; | |
211 | ||
212 | for (i = 0; i < len; i += 2) { | |
213 | fifo = w5300_read(priv, W5300_S0_RX_FIFO); | |
214 | *buf++ = fifo >> 8; | |
215 | *buf++ = fifo; | |
216 | } | |
217 | fifo = w5300_read(priv, W5300_S0_RX_FIFO); | |
218 | fifo = w5300_read(priv, W5300_S0_RX_FIFO); | |
219 | } | |
220 | ||
221 | static void w5300_write_frame(struct w5300_priv *priv, u8 *buf, int len) | |
222 | { | |
223 | u16 fifo; | |
224 | int i; | |
225 | ||
226 | for (i = 0; i < len; i += 2) { | |
227 | fifo = *buf++ << 8; | |
228 | fifo |= *buf++; | |
229 | w5300_write(priv, W5300_S0_TX_FIFO, fifo); | |
230 | } | |
231 | w5300_write32(priv, W5300_S0_TX_WRSR, len); | |
232 | } | |
233 | ||
234 | static void w5300_write_macaddr(struct w5300_priv *priv) | |
235 | { | |
236 | struct net_device *ndev = priv->ndev; | |
237 | w5300_write32(priv, W5300_SHARL, | |
238 | ndev->dev_addr[0] << 24 | | |
239 | ndev->dev_addr[1] << 16 | | |
240 | ndev->dev_addr[2] << 8 | | |
241 | ndev->dev_addr[3]); | |
242 | w5300_write(priv, W5300_SHARH, | |
243 | ndev->dev_addr[4] << 8 | | |
244 | ndev->dev_addr[5]); | |
245 | mmiowb(); | |
246 | } | |
247 | ||
248 | static void w5300_hw_reset(struct w5300_priv *priv) | |
249 | { | |
250 | w5300_write_direct(priv, W5300_MR, MR_RST); | |
251 | mmiowb(); | |
252 | mdelay(5); | |
253 | w5300_write_direct(priv, W5300_MR, priv->indirect ? | |
254 | MR_WDF(7) | MR_PB | MR_IND : | |
255 | MR_WDF(7) | MR_PB); | |
256 | mmiowb(); | |
257 | w5300_write(priv, W5300_IMR, 0); | |
258 | w5300_write_macaddr(priv); | |
259 | ||
260 | /* Configure 128K of internal memory | |
261 | * as 64K RX fifo and 64K TX fifo | |
262 | */ | |
263 | w5300_write32(priv, W5300_RMSRL, 64 << 24); | |
264 | w5300_write32(priv, W5300_RMSRH, 0); | |
265 | w5300_write32(priv, W5300_TMSRL, 64 << 24); | |
266 | w5300_write32(priv, W5300_TMSRH, 0); | |
267 | w5300_write(priv, W5300_MTYPE, 0x00ff); | |
268 | mmiowb(); | |
269 | } | |
270 | ||
271 | static void w5300_hw_start(struct w5300_priv *priv) | |
272 | { | |
273 | w5300_write(priv, W5300_S0_MR, priv->promisc ? | |
274 | S0_MR_MACRAW : S0_MR_MACRAW_MF); | |
275 | mmiowb(); | |
276 | w5300_command(priv, S0_CR_OPEN); | |
376b16f4 | 277 | w5300_write(priv, W5300_S0_IMR, S0_IR_RECV | S0_IR_SENDOK); |
9899b81e MS |
278 | w5300_write(priv, W5300_IMR, IR_S0); |
279 | mmiowb(); | |
280 | } | |
281 | ||
282 | static void w5300_hw_close(struct w5300_priv *priv) | |
283 | { | |
284 | w5300_write(priv, W5300_IMR, 0); | |
285 | mmiowb(); | |
286 | w5300_command(priv, S0_CR_CLOSE); | |
287 | } | |
288 | ||
289 | /*********************************************************************** | |
290 | * | |
291 | * Device driver functions / callbacks | |
292 | * | |
293 | ***********************************************************************/ | |
294 | ||
295 | static void w5300_get_drvinfo(struct net_device *ndev, | |
296 | struct ethtool_drvinfo *info) | |
297 | { | |
298 | strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); | |
299 | strlcpy(info->version, DRV_VERSION, sizeof(info->version)); | |
300 | strlcpy(info->bus_info, dev_name(ndev->dev.parent), | |
301 | sizeof(info->bus_info)); | |
302 | } | |
303 | ||
304 | static u32 w5300_get_link(struct net_device *ndev) | |
305 | { | |
306 | struct w5300_priv *priv = netdev_priv(ndev); | |
307 | ||
308 | if (gpio_is_valid(priv->link_gpio)) | |
309 | return !!gpio_get_value(priv->link_gpio); | |
310 | ||
311 | return 1; | |
312 | } | |
313 | ||
314 | static u32 w5300_get_msglevel(struct net_device *ndev) | |
315 | { | |
316 | struct w5300_priv *priv = netdev_priv(ndev); | |
317 | ||
318 | return priv->msg_enable; | |
319 | } | |
320 | ||
321 | static void w5300_set_msglevel(struct net_device *ndev, u32 value) | |
322 | { | |
323 | struct w5300_priv *priv = netdev_priv(ndev); | |
324 | ||
325 | priv->msg_enable = value; | |
326 | } | |
327 | ||
328 | static int w5300_get_regs_len(struct net_device *ndev) | |
329 | { | |
330 | return W5300_REGS_LEN; | |
331 | } | |
332 | ||
333 | static void w5300_get_regs(struct net_device *ndev, | |
334 | struct ethtool_regs *regs, void *_buf) | |
335 | { | |
336 | struct w5300_priv *priv = netdev_priv(ndev); | |
337 | u8 *buf = _buf; | |
338 | u16 addr; | |
339 | u16 data; | |
340 | ||
341 | regs->version = 1; | |
342 | for (addr = 0; addr < W5300_REGS_LEN; addr += 2) { | |
343 | switch (addr & 0x23f) { | |
344 | case W5300_S0_TX_FIFO: /* cannot read TX_FIFO */ | |
345 | case W5300_S0_RX_FIFO: /* cannot read RX_FIFO */ | |
346 | data = 0xffff; | |
347 | break; | |
348 | default: | |
349 | data = w5300_read(priv, addr); | |
350 | break; | |
351 | } | |
352 | *buf++ = data >> 8; | |
353 | *buf++ = data; | |
354 | } | |
355 | } | |
356 | ||
357 | static void w5300_tx_timeout(struct net_device *ndev) | |
358 | { | |
359 | struct w5300_priv *priv = netdev_priv(ndev); | |
360 | ||
361 | netif_stop_queue(ndev); | |
362 | w5300_hw_reset(priv); | |
363 | w5300_hw_start(priv); | |
364 | ndev->stats.tx_errors++; | |
365 | ndev->trans_start = jiffies; | |
366 | netif_wake_queue(ndev); | |
367 | } | |
368 | ||
369 | static int w5300_start_tx(struct sk_buff *skb, struct net_device *ndev) | |
370 | { | |
371 | struct w5300_priv *priv = netdev_priv(ndev); | |
372 | ||
376b16f4 | 373 | netif_stop_queue(ndev); |
9899b81e MS |
374 | |
375 | w5300_write_frame(priv, skb->data, skb->len); | |
376 | mmiowb(); | |
377 | ndev->stats.tx_packets++; | |
378 | ndev->stats.tx_bytes += skb->len; | |
379 | dev_kfree_skb(skb); | |
380 | netif_dbg(priv, tx_queued, ndev, "tx queued\n"); | |
381 | ||
382 | w5300_command(priv, S0_CR_SEND); | |
383 | ||
384 | return NETDEV_TX_OK; | |
385 | } | |
386 | ||
387 | static int w5300_napi_poll(struct napi_struct *napi, int budget) | |
388 | { | |
389 | struct w5300_priv *priv = container_of(napi, struct w5300_priv, napi); | |
390 | struct net_device *ndev = priv->ndev; | |
391 | struct sk_buff *skb; | |
392 | int rx_count; | |
393 | u16 rx_len; | |
394 | ||
395 | for (rx_count = 0; rx_count < budget; rx_count++) { | |
396 | u32 rx_fifo_len = w5300_read32(priv, W5300_S0_RX_RSR); | |
397 | if (rx_fifo_len == 0) | |
398 | break; | |
399 | ||
400 | rx_len = w5300_read(priv, W5300_S0_RX_FIFO); | |
401 | ||
402 | skb = netdev_alloc_skb_ip_align(ndev, roundup(rx_len, 2)); | |
403 | if (unlikely(!skb)) { | |
404 | u32 i; | |
405 | for (i = 0; i < rx_fifo_len; i += 2) | |
406 | w5300_read(priv, W5300_S0_RX_FIFO); | |
407 | ndev->stats.rx_dropped++; | |
408 | return -ENOMEM; | |
409 | } | |
410 | ||
411 | skb_put(skb, rx_len); | |
412 | w5300_read_frame(priv, skb->data, rx_len); | |
413 | skb->protocol = eth_type_trans(skb, ndev); | |
414 | ||
415 | netif_receive_skb(skb); | |
416 | ndev->stats.rx_packets++; | |
417 | ndev->stats.rx_bytes += rx_len; | |
418 | } | |
419 | ||
420 | if (rx_count < budget) { | |
421 | w5300_write(priv, W5300_IMR, IR_S0); | |
422 | mmiowb(); | |
423 | napi_complete(napi); | |
424 | } | |
425 | ||
426 | return rx_count; | |
427 | } | |
428 | ||
429 | static irqreturn_t w5300_interrupt(int irq, void *ndev_instance) | |
430 | { | |
431 | struct net_device *ndev = ndev_instance; | |
432 | struct w5300_priv *priv = netdev_priv(ndev); | |
433 | ||
434 | int ir = w5300_read(priv, W5300_S0_IR); | |
435 | if (!ir) | |
436 | return IRQ_NONE; | |
437 | w5300_write(priv, W5300_S0_IR, ir); | |
438 | mmiowb(); | |
439 | ||
376b16f4 | 440 | if (ir & S0_IR_SENDOK) { |
9899b81e MS |
441 | netif_dbg(priv, tx_done, ndev, "tx done\n"); |
442 | netif_wake_queue(ndev); | |
443 | } | |
444 | ||
445 | if (ir & S0_IR_RECV) { | |
446 | if (napi_schedule_prep(&priv->napi)) { | |
447 | w5300_write(priv, W5300_IMR, 0); | |
448 | mmiowb(); | |
449 | __napi_schedule(&priv->napi); | |
450 | } | |
451 | } | |
452 | ||
453 | return IRQ_HANDLED; | |
454 | } | |
455 | ||
456 | static irqreturn_t w5300_detect_link(int irq, void *ndev_instance) | |
457 | { | |
458 | struct net_device *ndev = ndev_instance; | |
459 | struct w5300_priv *priv = netdev_priv(ndev); | |
460 | ||
461 | if (netif_running(ndev)) { | |
462 | if (gpio_get_value(priv->link_gpio) != 0) { | |
463 | netif_info(priv, link, ndev, "link is up\n"); | |
464 | netif_carrier_on(ndev); | |
465 | } else { | |
466 | netif_info(priv, link, ndev, "link is down\n"); | |
467 | netif_carrier_off(ndev); | |
468 | } | |
469 | } | |
470 | ||
471 | return IRQ_HANDLED; | |
472 | } | |
473 | ||
474 | static void w5300_set_rx_mode(struct net_device *ndev) | |
475 | { | |
476 | struct w5300_priv *priv = netdev_priv(ndev); | |
477 | bool set_promisc = (ndev->flags & IFF_PROMISC) != 0; | |
478 | ||
479 | if (priv->promisc != set_promisc) { | |
480 | priv->promisc = set_promisc; | |
481 | w5300_hw_start(priv); | |
482 | } | |
483 | } | |
484 | ||
485 | static int w5300_set_macaddr(struct net_device *ndev, void *addr) | |
486 | { | |
487 | struct w5300_priv *priv = netdev_priv(ndev); | |
488 | struct sockaddr *sock_addr = addr; | |
489 | ||
490 | if (!is_valid_ether_addr(sock_addr->sa_data)) | |
491 | return -EADDRNOTAVAIL; | |
492 | memcpy(ndev->dev_addr, sock_addr->sa_data, ETH_ALEN); | |
493 | ndev->addr_assign_type &= ~NET_ADDR_RANDOM; | |
494 | w5300_write_macaddr(priv); | |
495 | return 0; | |
496 | } | |
497 | ||
498 | static int w5300_open(struct net_device *ndev) | |
499 | { | |
500 | struct w5300_priv *priv = netdev_priv(ndev); | |
501 | ||
502 | netif_info(priv, ifup, ndev, "enabling\n"); | |
503 | if (!is_valid_ether_addr(ndev->dev_addr)) | |
504 | return -EINVAL; | |
505 | w5300_hw_start(priv); | |
506 | napi_enable(&priv->napi); | |
507 | netif_start_queue(ndev); | |
508 | if (!gpio_is_valid(priv->link_gpio) || | |
509 | gpio_get_value(priv->link_gpio) != 0) | |
510 | netif_carrier_on(ndev); | |
511 | return 0; | |
512 | } | |
513 | ||
514 | static int w5300_stop(struct net_device *ndev) | |
515 | { | |
516 | struct w5300_priv *priv = netdev_priv(ndev); | |
517 | ||
518 | netif_info(priv, ifdown, ndev, "shutting down\n"); | |
519 | w5300_hw_close(priv); | |
520 | netif_carrier_off(ndev); | |
521 | netif_stop_queue(ndev); | |
522 | napi_disable(&priv->napi); | |
523 | return 0; | |
524 | } | |
525 | ||
526 | static const struct ethtool_ops w5300_ethtool_ops = { | |
527 | .get_drvinfo = w5300_get_drvinfo, | |
528 | .get_msglevel = w5300_get_msglevel, | |
529 | .set_msglevel = w5300_set_msglevel, | |
530 | .get_link = w5300_get_link, | |
531 | .get_regs_len = w5300_get_regs_len, | |
532 | .get_regs = w5300_get_regs, | |
533 | }; | |
534 | ||
535 | static const struct net_device_ops w5300_netdev_ops = { | |
536 | .ndo_open = w5300_open, | |
537 | .ndo_stop = w5300_stop, | |
538 | .ndo_start_xmit = w5300_start_tx, | |
539 | .ndo_tx_timeout = w5300_tx_timeout, | |
540 | .ndo_set_rx_mode = w5300_set_rx_mode, | |
541 | .ndo_set_mac_address = w5300_set_macaddr, | |
542 | .ndo_validate_addr = eth_validate_addr, | |
543 | .ndo_change_mtu = eth_change_mtu, | |
544 | }; | |
545 | ||
546 | static int __devinit w5300_hw_probe(struct platform_device *pdev) | |
547 | { | |
548 | struct wiznet_platform_data *data = pdev->dev.platform_data; | |
549 | struct net_device *ndev = platform_get_drvdata(pdev); | |
550 | struct w5300_priv *priv = netdev_priv(ndev); | |
551 | const char *name = netdev_name(ndev); | |
552 | struct resource *mem; | |
553 | int mem_size; | |
554 | int irq; | |
555 | int ret; | |
556 | ||
557 | if (data && is_valid_ether_addr(data->mac_addr)) { | |
558 | memcpy(ndev->dev_addr, data->mac_addr, ETH_ALEN); | |
559 | } else { | |
560 | random_ether_addr(ndev->dev_addr); | |
561 | ndev->addr_assign_type |= NET_ADDR_RANDOM; | |
562 | } | |
563 | ||
564 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
565 | if (!mem) | |
566 | return -ENXIO; | |
567 | mem_size = resource_size(mem); | |
568 | if (!devm_request_mem_region(&pdev->dev, mem->start, mem_size, name)) | |
569 | return -EBUSY; | |
570 | priv->base = devm_ioremap(&pdev->dev, mem->start, mem_size); | |
571 | if (!priv->base) | |
572 | return -EBUSY; | |
573 | ||
574 | spin_lock_init(&priv->reg_lock); | |
575 | priv->indirect = mem_size < W5300_BUS_DIRECT_SIZE; | |
576 | if (priv->indirect) { | |
577 | priv->read = w5300_read_indirect; | |
578 | priv->write = w5300_write_indirect; | |
579 | } else { | |
580 | priv->read = w5300_read_direct; | |
581 | priv->write = w5300_write_direct; | |
582 | } | |
583 | ||
584 | w5300_hw_reset(priv); | |
585 | if (w5300_read(priv, W5300_IDR) != IDR_W5300) | |
586 | return -ENODEV; | |
587 | ||
588 | irq = platform_get_irq(pdev, 0); | |
589 | if (irq < 0) | |
590 | return irq; | |
591 | ret = request_irq(irq, w5300_interrupt, | |
592 | IRQ_TYPE_LEVEL_LOW, name, ndev); | |
593 | if (ret < 0) | |
594 | return ret; | |
595 | priv->irq = irq; | |
596 | ||
597 | priv->link_gpio = data->link_gpio; | |
598 | if (gpio_is_valid(priv->link_gpio)) { | |
599 | char *link_name = devm_kzalloc(&pdev->dev, 16, GFP_KERNEL); | |
600 | if (!link_name) | |
601 | return -ENOMEM; | |
602 | snprintf(link_name, 16, "%s-link", name); | |
603 | priv->link_irq = gpio_to_irq(priv->link_gpio); | |
604 | if (request_any_context_irq(priv->link_irq, w5300_detect_link, | |
605 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | |
606 | link_name, priv->ndev) < 0) | |
607 | priv->link_gpio = -EINVAL; | |
608 | } | |
609 | ||
610 | netdev_info(ndev, "at 0x%llx irq %d\n", (u64)mem->start, irq); | |
611 | return 0; | |
612 | } | |
613 | ||
614 | static int __devinit w5300_probe(struct platform_device *pdev) | |
615 | { | |
616 | struct w5300_priv *priv; | |
617 | struct net_device *ndev; | |
618 | int err; | |
619 | ||
620 | ndev = alloc_etherdev(sizeof(*priv)); | |
621 | if (!ndev) | |
622 | return -ENOMEM; | |
623 | SET_NETDEV_DEV(ndev, &pdev->dev); | |
624 | platform_set_drvdata(pdev, ndev); | |
625 | priv = netdev_priv(ndev); | |
626 | priv->ndev = ndev; | |
627 | ||
628 | ether_setup(ndev); | |
629 | ndev->netdev_ops = &w5300_netdev_ops; | |
630 | ndev->ethtool_ops = &w5300_ethtool_ops; | |
631 | ndev->watchdog_timeo = HZ; | |
632 | netif_napi_add(ndev, &priv->napi, w5300_napi_poll, 16); | |
633 | ||
634 | /* This chip doesn't support VLAN packets with normal MTU, | |
635 | * so disable VLAN for this device. | |
636 | */ | |
637 | ndev->features |= NETIF_F_VLAN_CHALLENGED; | |
638 | ||
639 | err = register_netdev(ndev); | |
640 | if (err < 0) | |
641 | goto err_register; | |
642 | ||
643 | err = w5300_hw_probe(pdev); | |
644 | if (err < 0) | |
645 | goto err_hw_probe; | |
646 | ||
647 | return 0; | |
648 | ||
649 | err_hw_probe: | |
650 | unregister_netdev(ndev); | |
651 | err_register: | |
652 | free_netdev(ndev); | |
653 | platform_set_drvdata(pdev, NULL); | |
654 | return err; | |
655 | } | |
656 | ||
657 | static int __devexit w5300_remove(struct platform_device *pdev) | |
658 | { | |
659 | struct net_device *ndev = platform_get_drvdata(pdev); | |
660 | struct w5300_priv *priv = netdev_priv(ndev); | |
661 | ||
662 | w5300_hw_reset(priv); | |
663 | free_irq(priv->irq, ndev); | |
664 | if (gpio_is_valid(priv->link_gpio)) | |
665 | free_irq(priv->link_irq, ndev); | |
666 | ||
667 | unregister_netdev(ndev); | |
668 | free_netdev(ndev); | |
669 | platform_set_drvdata(pdev, NULL); | |
670 | return 0; | |
671 | } | |
672 | ||
673 | #ifdef CONFIG_PM | |
674 | static int w5300_suspend(struct device *dev) | |
675 | { | |
676 | struct platform_device *pdev = to_platform_device(dev); | |
677 | struct net_device *ndev = platform_get_drvdata(pdev); | |
678 | struct w5300_priv *priv = netdev_priv(ndev); | |
679 | ||
680 | if (netif_running(ndev)) { | |
681 | netif_carrier_off(ndev); | |
682 | netif_device_detach(ndev); | |
683 | ||
684 | w5300_hw_close(priv); | |
685 | } | |
686 | return 0; | |
687 | } | |
688 | ||
689 | static int w5300_resume(struct device *dev) | |
690 | { | |
691 | struct platform_device *pdev = to_platform_device(dev); | |
692 | struct net_device *ndev = platform_get_drvdata(pdev); | |
693 | struct w5300_priv *priv = netdev_priv(ndev); | |
694 | ||
695 | if (!netif_running(ndev)) { | |
696 | w5300_hw_reset(priv); | |
697 | w5300_hw_start(priv); | |
698 | ||
699 | netif_device_attach(ndev); | |
700 | if (!gpio_is_valid(priv->link_gpio) || | |
701 | gpio_get_value(priv->link_gpio) != 0) | |
702 | netif_carrier_on(ndev); | |
703 | } | |
704 | return 0; | |
705 | } | |
706 | #endif /* CONFIG_PM */ | |
707 | ||
708 | static SIMPLE_DEV_PM_OPS(w5300_pm_ops, w5300_suspend, w5300_resume); | |
709 | ||
710 | static struct platform_driver w5300_driver = { | |
711 | .driver = { | |
712 | .name = DRV_NAME, | |
713 | .owner = THIS_MODULE, | |
714 | .pm = &w5300_pm_ops, | |
715 | }, | |
716 | .probe = w5300_probe, | |
717 | .remove = __devexit_p(w5300_remove), | |
718 | }; | |
719 | ||
720 | module_platform_driver(w5300_driver); |