]>
Commit | Line | Data |
---|---|---|
d4b7780e AV |
1 | /* |
2 | * Ethernet driver for the Atmel AT91RM9200 (Thunder) | |
3 | * | |
4 | * Copyright (C) 2003 SAN People (Pty) Ltd | |
5 | * | |
6 | * Based on an earlier Atmel EMAC macrocell driver by Atmel and Lineo Inc. | |
7 | * Initial version by Rick Bronson 01/11/2003 | |
8 | * | |
d4b7780e AV |
9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | |
11 | * as published by the Free Software Foundation; either version | |
12 | * 2 of the License, or (at your option) any later version. | |
13 | */ | |
14 | ||
15 | #include <linux/module.h> | |
16 | #include <linux/init.h> | |
a6b7a407 | 17 | #include <linux/interrupt.h> |
d4b7780e AV |
18 | #include <linux/netdevice.h> |
19 | #include <linux/etherdevice.h> | |
20 | #include <linux/skbuff.h> | |
21 | #include <linux/dma-mapping.h> | |
22 | #include <linux/ethtool.h> | |
84e0cdb0 | 23 | #include <linux/platform_data/macb.h> |
d4b7780e AV |
24 | #include <linux/platform_device.h> |
25 | #include <linux/clk.h> | |
5a0e3ad6 | 26 | #include <linux/gfp.h> |
c5f0f83c | 27 | #include <linux/phy.h> |
63973461 | 28 | #include <linux/io.h> |
96f6360c JCPV |
29 | #include <linux/of.h> |
30 | #include <linux/of_device.h> | |
31 | #include <linux/of_net.h> | |
d4b7780e | 32 | |
bc3bbef6 | 33 | #include "macb.h" |
d4b7780e | 34 | |
04879e5c JE |
35 | /* 1518 rounded up */ |
36 | #define MAX_RBUFF_SZ 0x600 | |
37 | /* max number of receive buffers */ | |
38 | #define MAX_RX_DESCR 9 | |
39 | ||
50b5ca16 | 40 | /* Initialize and start the Receiver and Transmit subsystems */ |
04879e5c | 41 | static int at91ether_start(struct net_device *dev) |
d4b7780e | 42 | { |
b85008b7 | 43 | struct macb *lp = netdev_priv(dev); |
04879e5c | 44 | dma_addr_t addr; |
50b5ca16 | 45 | u32 ctl; |
04879e5c JE |
46 | int i; |
47 | ||
48 | lp->rx_ring = dma_alloc_coherent(&lp->pdev->dev, | |
d0320f75 JP |
49 | (MAX_RX_DESCR * |
50 | sizeof(struct macb_dma_desc)), | |
51 | &lp->rx_ring_dma, GFP_KERNEL); | |
52 | if (!lp->rx_ring) | |
04879e5c | 53 | return -ENOMEM; |
d4b7780e | 54 | |
04879e5c | 55 | lp->rx_buffers = dma_alloc_coherent(&lp->pdev->dev, |
d0320f75 JP |
56 | MAX_RX_DESCR * MAX_RBUFF_SZ, |
57 | &lp->rx_buffers_dma, GFP_KERNEL); | |
04879e5c | 58 | if (!lp->rx_buffers) { |
04879e5c | 59 | dma_free_coherent(&lp->pdev->dev, |
d0320f75 JP |
60 | MAX_RX_DESCR * sizeof(struct macb_dma_desc), |
61 | lp->rx_ring, lp->rx_ring_dma); | |
04879e5c JE |
62 | lp->rx_ring = NULL; |
63 | return -ENOMEM; | |
64 | } | |
65 | ||
66 | addr = lp->rx_buffers_dma; | |
d4b7780e | 67 | for (i = 0; i < MAX_RX_DESCR; i++) { |
04879e5c JE |
68 | lp->rx_ring[i].addr = addr; |
69 | lp->rx_ring[i].ctrl = 0; | |
70 | addr += MAX_RBUFF_SZ; | |
d4b7780e AV |
71 | } |
72 | ||
73 | /* Set the Wrap bit on the last descriptor */ | |
04879e5c | 74 | lp->rx_ring[MAX_RX_DESCR - 1].addr |= MACB_BIT(RX_WRAP); |
d4b7780e AV |
75 | |
76 | /* Reset buffer index */ | |
04879e5c | 77 | lp->rx_tail = 0; |
d4b7780e AV |
78 | |
79 | /* Program address of descriptor list in Rx Buffer Queue register */ | |
04879e5c | 80 | macb_writel(lp, RBQP, lp->rx_ring_dma); |
d4b7780e AV |
81 | |
82 | /* Enable Receive and Transmit */ | |
f8bded38 JE |
83 | ctl = macb_readl(lp, NCR); |
84 | macb_writel(lp, NCR, ctl | MACB_BIT(RE) | MACB_BIT(TE)); | |
04879e5c JE |
85 | |
86 | return 0; | |
d4b7780e AV |
87 | } |
88 | ||
50b5ca16 | 89 | /* Open the ethernet interface */ |
d4b7780e AV |
90 | static int at91ether_open(struct net_device *dev) |
91 | { | |
b85008b7 | 92 | struct macb *lp = netdev_priv(dev); |
50b5ca16 | 93 | u32 ctl; |
04879e5c | 94 | int ret; |
d4b7780e | 95 | |
d4b7780e | 96 | /* Clear internal statistics */ |
f8bded38 JE |
97 | ctl = macb_readl(lp, NCR); |
98 | macb_writel(lp, NCR, ctl | MACB_BIT(CLRSTAT)); | |
d4b7780e | 99 | |
34232476 | 100 | macb_set_hwaddr(lp); |
d4b7780e | 101 | |
04879e5c JE |
102 | ret = at91ether_start(dev); |
103 | if (ret) | |
104 | return ret; | |
105 | ||
d4b7780e | 106 | /* Enable MAC interrupts */ |
50b5ca16 JE |
107 | macb_writel(lp, IER, MACB_BIT(RCOMP) | |
108 | MACB_BIT(RXUBR) | | |
109 | MACB_BIT(ISR_TUND) | | |
110 | MACB_BIT(ISR_RLE) | | |
111 | MACB_BIT(TCOMP) | | |
112 | MACB_BIT(ISR_ROVR) | | |
113 | MACB_BIT(HRESP)); | |
d4b7780e | 114 | |
5e32353d JE |
115 | /* schedule a link state check */ |
116 | phy_start(lp->phy_dev); | |
117 | ||
d4b7780e | 118 | netif_start_queue(dev); |
5e32353d | 119 | |
d4b7780e AV |
120 | return 0; |
121 | } | |
122 | ||
50b5ca16 | 123 | /* Close the interface */ |
d4b7780e AV |
124 | static int at91ether_close(struct net_device *dev) |
125 | { | |
b85008b7 | 126 | struct macb *lp = netdev_priv(dev); |
50b5ca16 | 127 | u32 ctl; |
d4b7780e AV |
128 | |
129 | /* Disable Receiver and Transmitter */ | |
f8bded38 JE |
130 | ctl = macb_readl(lp, NCR); |
131 | macb_writel(lp, NCR, ctl & ~(MACB_BIT(TE) | MACB_BIT(RE))); | |
d4b7780e | 132 | |
d4b7780e | 133 | /* Disable MAC interrupts */ |
50b5ca16 JE |
134 | macb_writel(lp, IDR, MACB_BIT(RCOMP) | |
135 | MACB_BIT(RXUBR) | | |
136 | MACB_BIT(ISR_TUND) | | |
137 | MACB_BIT(ISR_RLE) | | |
138 | MACB_BIT(TCOMP) | | |
139 | MACB_BIT(ISR_ROVR) | | |
140 | MACB_BIT(HRESP)); | |
d4b7780e AV |
141 | |
142 | netif_stop_queue(dev); | |
143 | ||
04879e5c | 144 | dma_free_coherent(&lp->pdev->dev, |
55054a16 | 145 | MAX_RX_DESCR * sizeof(struct macb_dma_desc), |
04879e5c JE |
146 | lp->rx_ring, lp->rx_ring_dma); |
147 | lp->rx_ring = NULL; | |
148 | ||
149 | dma_free_coherent(&lp->pdev->dev, | |
150 | MAX_RX_DESCR * MAX_RBUFF_SZ, | |
151 | lp->rx_buffers, lp->rx_buffers_dma); | |
152 | lp->rx_buffers = NULL; | |
153 | ||
d4b7780e AV |
154 | return 0; |
155 | } | |
156 | ||
50b5ca16 | 157 | /* Transmit packet */ |
531c6804 | 158 | static int at91ether_start_xmit(struct sk_buff *skb, struct net_device *dev) |
d4b7780e | 159 | { |
b85008b7 | 160 | struct macb *lp = netdev_priv(dev); |
d4b7780e | 161 | |
f8bded38 | 162 | if (macb_readl(lp, TSR) & MACB_BIT(RM9200_BNQ)) { |
d4b7780e AV |
163 | netif_stop_queue(dev); |
164 | ||
165 | /* Store packet information (to free when Tx completed) */ | |
166 | lp->skb = skb; | |
167 | lp->skb_length = skb->len; | |
50b5ca16 JE |
168 | lp->skb_physaddr = dma_map_single(NULL, skb->data, skb->len, |
169 | DMA_TO_DEVICE); | |
d4b7780e AV |
170 | |
171 | /* Set address of the data in the Transmit Address register */ | |
f8bded38 | 172 | macb_writel(lp, TAR, lp->skb_physaddr); |
d4b7780e | 173 | /* Set length of the packet in the Transmit Control register */ |
f8bded38 | 174 | macb_writel(lp, TCR, skb->len); |
d4b7780e | 175 | |
d4b7780e | 176 | } else { |
ed2b97d3 | 177 | netdev_err(dev, "%s called, but device is busy!\n", __func__); |
50b5ca16 | 178 | return NETDEV_TX_BUSY; |
d4b7780e AV |
179 | } |
180 | ||
6ed10654 | 181 | return NETDEV_TX_OK; |
d4b7780e AV |
182 | } |
183 | ||
50b5ca16 | 184 | /* Extract received frame from buffer descriptors and sent to upper layers. |
d4b7780e AV |
185 | * (Called from interrupt context) |
186 | */ | |
187 | static void at91ether_rx(struct net_device *dev) | |
188 | { | |
b85008b7 | 189 | struct macb *lp = netdev_priv(dev); |
d4b7780e AV |
190 | unsigned char *p_recv; |
191 | struct sk_buff *skb; | |
192 | unsigned int pktlen; | |
193 | ||
04879e5c JE |
194 | while (lp->rx_ring[lp->rx_tail].addr & MACB_BIT(RX_USED)) { |
195 | p_recv = lp->rx_buffers + lp->rx_tail * MAX_RBUFF_SZ; | |
196 | pktlen = MACB_BF(RX_FRMLEN, lp->rx_ring[lp->rx_tail].ctrl); | |
1d266430 | 197 | skb = netdev_alloc_skb(dev, pktlen + 2); |
04879e5c | 198 | if (skb) { |
d4b7780e AV |
199 | skb_reserve(skb, 2); |
200 | memcpy(skb_put(skb, pktlen), p_recv, pktlen); | |
201 | ||
d4b7780e | 202 | skb->protocol = eth_type_trans(skb, dev); |
2ea32eed JE |
203 | lp->stats.rx_packets++; |
204 | lp->stats.rx_bytes += pktlen; | |
d4b7780e | 205 | netif_rx(skb); |
04879e5c | 206 | } else { |
2ea32eed | 207 | lp->stats.rx_dropped++; |
d4b7780e AV |
208 | } |
209 | ||
04879e5c | 210 | if (lp->rx_ring[lp->rx_tail].ctrl & MACB_BIT(RX_MHASH_MATCH)) |
2ea32eed | 211 | lp->stats.multicast++; |
d4b7780e | 212 | |
04879e5c JE |
213 | /* reset ownership bit */ |
214 | lp->rx_ring[lp->rx_tail].addr &= ~MACB_BIT(RX_USED); | |
215 | ||
216 | /* wrap after last buffer */ | |
217 | if (lp->rx_tail == MAX_RX_DESCR - 1) | |
218 | lp->rx_tail = 0; | |
d4b7780e | 219 | else |
04879e5c | 220 | lp->rx_tail++; |
d4b7780e AV |
221 | } |
222 | } | |
223 | ||
50b5ca16 | 224 | /* MAC interrupt handler */ |
7d12e780 | 225 | static irqreturn_t at91ether_interrupt(int irq, void *dev_id) |
d4b7780e | 226 | { |
50b5ca16 | 227 | struct net_device *dev = dev_id; |
b85008b7 | 228 | struct macb *lp = netdev_priv(dev); |
50b5ca16 | 229 | u32 intstatus, ctl; |
d4b7780e AV |
230 | |
231 | /* MAC Interrupt Status register indicates what interrupts are pending. | |
50b5ca16 JE |
232 | * It is automatically cleared once read. |
233 | */ | |
f8bded38 | 234 | intstatus = macb_readl(lp, ISR); |
d4b7780e | 235 | |
50b5ca16 JE |
236 | /* Receive complete */ |
237 | if (intstatus & MACB_BIT(RCOMP)) | |
d4b7780e AV |
238 | at91ether_rx(dev); |
239 | ||
50b5ca16 JE |
240 | /* Transmit complete */ |
241 | if (intstatus & MACB_BIT(TCOMP)) { | |
242 | /* The TCOM bit is set even if the transmission failed */ | |
bc3bbef6 | 243 | if (intstatus & (MACB_BIT(ISR_TUND) | MACB_BIT(ISR_RLE))) |
2ea32eed | 244 | lp->stats.tx_errors++; |
d4b7780e AV |
245 | |
246 | if (lp->skb) { | |
247 | dev_kfree_skb_irq(lp->skb); | |
248 | lp->skb = NULL; | |
249 | dma_unmap_single(NULL, lp->skb_physaddr, lp->skb_length, DMA_TO_DEVICE); | |
2ea32eed JE |
250 | lp->stats.tx_packets++; |
251 | lp->stats.tx_bytes += lp->skb_length; | |
d4b7780e AV |
252 | } |
253 | netif_wake_queue(dev); | |
254 | } | |
255 | ||
50b5ca16 | 256 | /* Work-around for EMAC Errata section 41.3.1 */ |
bc3bbef6 | 257 | if (intstatus & MACB_BIT(RXUBR)) { |
f8bded38 JE |
258 | ctl = macb_readl(lp, NCR); |
259 | macb_writel(lp, NCR, ctl & ~MACB_BIT(RE)); | |
260 | macb_writel(lp, NCR, ctl | MACB_BIT(RE)); | |
d4b7780e AV |
261 | } |
262 | ||
bc3bbef6 | 263 | if (intstatus & MACB_BIT(ISR_ROVR)) |
ed2b97d3 | 264 | netdev_err(dev, "ROVR error\n"); |
d4b7780e AV |
265 | |
266 | return IRQ_HANDLED; | |
267 | } | |
268 | ||
51cc2104 AV |
269 | #ifdef CONFIG_NET_POLL_CONTROLLER |
270 | static void at91ether_poll_controller(struct net_device *dev) | |
271 | { | |
272 | unsigned long flags; | |
273 | ||
274 | local_irq_save(flags); | |
275 | at91ether_interrupt(dev->irq, dev); | |
276 | local_irq_restore(flags); | |
277 | } | |
278 | #endif | |
279 | ||
531c6804 AB |
280 | static const struct net_device_ops at91ether_netdev_ops = { |
281 | .ndo_open = at91ether_open, | |
282 | .ndo_stop = at91ether_close, | |
283 | .ndo_start_xmit = at91ether_start_xmit, | |
2ea32eed | 284 | .ndo_get_stats = macb_get_stats, |
e0da1f14 | 285 | .ndo_set_rx_mode = macb_set_rx_mode, |
34232476 | 286 | .ndo_set_mac_address = eth_mac_addr, |
5e32353d | 287 | .ndo_do_ioctl = macb_ioctl, |
531c6804 AB |
288 | .ndo_validate_addr = eth_validate_addr, |
289 | .ndo_change_mtu = eth_change_mtu, | |
290 | #ifdef CONFIG_NET_POLL_CONTROLLER | |
291 | .ndo_poll_controller = at91ether_poll_controller, | |
292 | #endif | |
293 | }; | |
294 | ||
96f6360c JCPV |
295 | #if defined(CONFIG_OF) |
296 | static const struct of_device_id at91ether_dt_ids[] = { | |
297 | { .compatible = "cdns,at91rm9200-emac" }, | |
298 | { .compatible = "cdns,emac" }, | |
299 | { /* sentinel */ } | |
300 | }; | |
96f6360c | 301 | MODULE_DEVICE_TABLE(of, at91ether_dt_ids); |
96f6360c JCPV |
302 | #endif |
303 | ||
50b5ca16 | 304 | /* Detect MAC & PHY and perform ethernet interface initialization */ |
c5f0f83c | 305 | static int __init at91ether_probe(struct platform_device *pdev) |
d4b7780e | 306 | { |
09a27480 | 307 | struct macb_platform_data *board_data = dev_get_platdata(&pdev->dev); |
c5f0f83c | 308 | struct resource *regs; |
d4b7780e | 309 | struct net_device *dev; |
5e32353d | 310 | struct phy_device *phydev; |
b85008b7 | 311 | struct macb *lp; |
d4b7780e | 312 | int res; |
50b5ca16 | 313 | u32 reg; |
f9b12490 | 314 | const char *mac; |
d4b7780e | 315 | |
c5f0f83c AV |
316 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
317 | if (!regs) | |
318 | return -ENOENT; | |
319 | ||
b85008b7 | 320 | dev = alloc_etherdev(sizeof(struct macb)); |
d4b7780e AV |
321 | if (!dev) |
322 | return -ENOMEM; | |
323 | ||
c5f0f83c | 324 | lp = netdev_priv(dev); |
5e32353d JE |
325 | lp->pdev = pdev; |
326 | lp->dev = dev; | |
c5f0f83c AV |
327 | spin_lock_init(&lp->lock); |
328 | ||
50b5ca16 JE |
329 | /* physical base address */ |
330 | dev->base_addr = regs->start; | |
63973461 | 331 | lp->regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); |
f8bded38 | 332 | if (!lp->regs) { |
c5f0f83c AV |
333 | res = -ENOMEM; |
334 | goto err_free_dev; | |
335 | } | |
336 | ||
337 | /* Clock */ | |
63973461 | 338 | lp->pclk = devm_clk_get(&pdev->dev, "ether_clk"); |
54f14e4b JE |
339 | if (IS_ERR(lp->pclk)) { |
340 | res = PTR_ERR(lp->pclk); | |
63973461 | 341 | goto err_free_dev; |
c5f0f83c | 342 | } |
54f14e4b | 343 | clk_enable(lp->pclk); |
d4b7780e | 344 | |
c293fb78 GC |
345 | lp->hclk = ERR_PTR(-ENOENT); |
346 | lp->tx_clk = ERR_PTR(-ENOENT); | |
347 | ||
d4b7780e | 348 | /* Install the interrupt handler */ |
c5f0f83c | 349 | dev->irq = platform_get_irq(pdev, 0); |
63973461 JE |
350 | res = devm_request_irq(&pdev->dev, dev->irq, at91ether_interrupt, 0, dev->name, dev); |
351 | if (res) | |
c5f0f83c | 352 | goto err_disable_clock; |
d4b7780e | 353 | |
531c6804 | 354 | dev->netdev_ops = &at91ether_netdev_ops; |
5e32353d | 355 | dev->ethtool_ops = &macb_ethtool_ops; |
c5f0f83c | 356 | platform_set_drvdata(pdev, dev); |
d4b7780e AV |
357 | SET_NETDEV_DEV(dev, &pdev->dev); |
358 | ||
f9b12490 GR |
359 | mac = of_get_mac_address(pdev->dev.of_node); |
360 | if (mac) | |
361 | memcpy(lp->dev->dev_addr, mac, ETH_ALEN); | |
362 | else | |
34232476 | 363 | macb_get_hwaddr(lp); |
d4b7780e | 364 | |
f9b12490 | 365 | res = of_get_phy_mode(pdev->dev.of_node); |
96f6360c JCPV |
366 | if (res < 0) { |
367 | if (board_data && board_data->is_rmii) | |
368 | lp->phy_interface = PHY_INTERFACE_MODE_RMII; | |
369 | else | |
370 | lp->phy_interface = PHY_INTERFACE_MODE_MII; | |
371 | } else { | |
372 | lp->phy_interface = res; | |
373 | } | |
374 | ||
f8bded38 | 375 | macb_writel(lp, NCR, 0); |
d4b7780e | 376 | |
50b5ca16 | 377 | reg = MACB_BF(CLK, MACB_CLK_DIV32) | MACB_BIT(BIG); |
96f6360c | 378 | if (lp->phy_interface == PHY_INTERFACE_MODE_RMII) |
50b5ca16 JE |
379 | reg |= MACB_BIT(RM9200_RMII); |
380 | ||
381 | macb_writel(lp, NCFGR, reg); | |
2f036ac6 | 382 | |
d4b7780e AV |
383 | /* Register the network interface */ |
384 | res = register_netdev(dev); | |
c5f0f83c | 385 | if (res) |
63973461 | 386 | goto err_disable_clock; |
d4b7780e | 387 | |
bbeae58c WY |
388 | res = macb_mii_init(lp); |
389 | if (res) | |
5e32353d JE |
390 | goto err_out_unregister_netdev; |
391 | ||
50b5ca16 JE |
392 | /* will be enabled in open() */ |
393 | netif_carrier_off(dev); | |
d4b7780e | 394 | |
5e32353d JE |
395 | phydev = lp->phy_dev; |
396 | netdev_info(dev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", | |
50b5ca16 JE |
397 | phydev->drv->name, dev_name(&phydev->dev), |
398 | phydev->irq); | |
775637df | 399 | |
d4b7780e | 400 | /* Display ethernet banner */ |
ed2b97d3 JE |
401 | netdev_info(dev, "AT91 ethernet at 0x%08lx int=%d (%pM)\n", |
402 | dev->base_addr, dev->irq, dev->dev_addr); | |
d4b7780e | 403 | |
c5f0f83c | 404 | return 0; |
d4b7780e | 405 | |
5e32353d JE |
406 | err_out_unregister_netdev: |
407 | unregister_netdev(dev); | |
c5f0f83c | 408 | err_disable_clock: |
54f14e4b | 409 | clk_disable(lp->pclk); |
c5f0f83c AV |
410 | err_free_dev: |
411 | free_netdev(dev); | |
412 | return res; | |
d4b7780e AV |
413 | } |
414 | ||
37a5b3d5 | 415 | static int at91ether_remove(struct platform_device *pdev) |
d4b7780e | 416 | { |
c57ee096 | 417 | struct net_device *dev = platform_get_drvdata(pdev); |
b85008b7 | 418 | struct macb *lp = netdev_priv(dev); |
d4b7780e | 419 | |
5e32353d JE |
420 | if (lp->phy_dev) |
421 | phy_disconnect(lp->phy_dev); | |
71527ef4 | 422 | |
5e32353d JE |
423 | mdiobus_unregister(lp->mii_bus); |
424 | kfree(lp->mii_bus->irq); | |
425 | mdiobus_free(lp->mii_bus); | |
c57ee096 | 426 | unregister_netdev(dev); |
5e32353d | 427 | clk_disable(lp->pclk); |
c57ee096 | 428 | free_netdev(dev); |
5e32353d | 429 | |
d4b7780e AV |
430 | return 0; |
431 | } | |
432 | ||
00e5edcb | 433 | #ifdef CONFIG_PM |
00e5edcb AV |
434 | static int at91ether_suspend(struct platform_device *pdev, pm_message_t mesg) |
435 | { | |
00e5edcb | 436 | struct net_device *net_dev = platform_get_drvdata(pdev); |
b85008b7 | 437 | struct macb *lp = netdev_priv(net_dev); |
00e5edcb AV |
438 | |
439 | if (netif_running(net_dev)) { | |
00e5edcb AV |
440 | netif_stop_queue(net_dev); |
441 | netif_device_detach(net_dev); | |
442 | ||
54f14e4b | 443 | clk_disable(lp->pclk); |
00e5edcb AV |
444 | } |
445 | return 0; | |
446 | } | |
447 | ||
448 | static int at91ether_resume(struct platform_device *pdev) | |
449 | { | |
00e5edcb | 450 | struct net_device *net_dev = platform_get_drvdata(pdev); |
b85008b7 | 451 | struct macb *lp = netdev_priv(net_dev); |
00e5edcb AV |
452 | |
453 | if (netif_running(net_dev)) { | |
54f14e4b | 454 | clk_enable(lp->pclk); |
00e5edcb AV |
455 | |
456 | netif_device_attach(net_dev); | |
457 | netif_start_queue(net_dev); | |
00e5edcb AV |
458 | } |
459 | return 0; | |
460 | } | |
00e5edcb AV |
461 | #else |
462 | #define at91ether_suspend NULL | |
463 | #define at91ether_resume NULL | |
464 | #endif | |
465 | ||
d4b7780e | 466 | static struct platform_driver at91ether_driver = { |
37a5b3d5 | 467 | .remove = at91ether_remove, |
00e5edcb AV |
468 | .suspend = at91ether_suspend, |
469 | .resume = at91ether_resume, | |
d4b7780e | 470 | .driver = { |
50b5ca16 | 471 | .name = "at91_ether", |
d4b7780e | 472 | .owner = THIS_MODULE, |
96f6360c | 473 | .of_match_table = of_match_ptr(at91ether_dt_ids), |
d4b7780e AV |
474 | }, |
475 | }; | |
476 | ||
ecad0a68 | 477 | module_platform_driver_probe(at91ether_driver, at91ether_probe); |
d4b7780e AV |
478 | |
479 | MODULE_LICENSE("GPL"); | |
480 | MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver"); | |
481 | MODULE_AUTHOR("Andrew Victor"); | |
50b5ca16 | 482 | MODULE_ALIAS("platform:at91_ether"); |