Commit | Line | Data |
---|---|---|
9952f691 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
bbd2190c VB |
2 | /* Altera Triple-Speed Ethernet MAC driver |
3 | * Copyright (C) 2008-2014 Altera Corporation. All rights reserved | |
4 | * | |
5 | * Contributors: | |
6 | * Dalon Westergreen | |
7 | * Thomas Chou | |
8 | * Ian Abbott | |
9 | * Yuriy Kozlov | |
10 | * Tobias Klauser | |
11 | * Andriy Smolskyy | |
12 | * Roman Bulgakov | |
13 | * Dmytro Mytarchuk | |
14 | * Matthew Gerlach | |
15 | * | |
16 | * Original driver contributed by SLS. | |
17 | * Major updates contributed by GlobalLogic | |
bbd2190c VB |
18 | */ |
19 | ||
20 | #include <linux/atomic.h> | |
21 | #include <linux/delay.h> | |
22 | #include <linux/etherdevice.h> | |
23 | #include <linux/if_vlan.h> | |
24 | #include <linux/init.h> | |
25 | #include <linux/interrupt.h> | |
26 | #include <linux/io.h> | |
27 | #include <linux/kernel.h> | |
28 | #include <linux/module.h> | |
3b804564 | 29 | #include <linux/mii.h> |
db48abba | 30 | #include <linux/mdio/mdio-regmap.h> |
bbd2190c | 31 | #include <linux/netdevice.h> |
b0377116 | 32 | #include <linux/of.h> |
bbd2190c VB |
33 | #include <linux/of_mdio.h> |
34 | #include <linux/of_net.h> | |
db48abba | 35 | #include <linux/pcs-lynx.h> |
bbd2190c VB |
36 | #include <linux/phy.h> |
37 | #include <linux/platform_device.h> | |
b0377116 | 38 | #include <linux/property.h> |
db48abba | 39 | #include <linux/regmap.h> |
bbd2190c VB |
40 | #include <linux/skbuff.h> |
41 | #include <asm/cacheflush.h> | |
42 | ||
43 | #include "altera_utils.h" | |
44 | #include "altera_tse.h" | |
45 | #include "altera_sgdma.h" | |
46 | #include "altera_msgdma.h" | |
47 | ||
48 | static atomic_t instance_count = ATOMIC_INIT(~0); | |
49 | /* Module parameters */ | |
50 | static int debug = -1; | |
d3757ba4 | 51 | module_param(debug, int, 0644); |
bbd2190c VB |
52 | MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)"); |
53 | ||
54 | static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | | |
55 | NETIF_MSG_LINK | NETIF_MSG_IFUP | | |
56 | NETIF_MSG_IFDOWN); | |
57 | ||
58 | #define RX_DESCRIPTORS 64 | |
59 | static int dma_rx_num = RX_DESCRIPTORS; | |
d3757ba4 | 60 | module_param(dma_rx_num, int, 0644); |
bbd2190c VB |
61 | MODULE_PARM_DESC(dma_rx_num, "Number of descriptors in the RX list"); |
62 | ||
63 | #define TX_DESCRIPTORS 64 | |
64 | static int dma_tx_num = TX_DESCRIPTORS; | |
d3757ba4 | 65 | module_param(dma_tx_num, int, 0644); |
bbd2190c VB |
66 | MODULE_PARM_DESC(dma_tx_num, "Number of descriptors in the TX list"); |
67 | ||
68 | ||
69 | #define POLL_PHY (-1) | |
70 | ||
71 | /* Make sure DMA buffer size is larger than the max frame size | |
72 | * plus some alignment offset and a VLAN header. If the max frame size is | |
73 | * 1518, a VLAN header would be additional 4 bytes and additional | |
74 | * headroom for alignment is 2 bytes, 2048 is just fine. | |
75 | */ | |
76 | #define ALTERA_RXDMABUFFER_SIZE 2048 | |
77 | ||
a5e516d0 | 78 | /* Allow network stack to resume queuing packets after we've |
bbd2190c VB |
79 | * finished transmitting at least 1/4 of the packets in the queue. |
80 | */ | |
81 | #define TSE_TX_THRESH(x) (x->tx_ring_size / 4) | |
82 | ||
83 | #define TXQUEUESTOP_THRESHHOLD 2 | |
84 | ||
bbd2190c VB |
85 | static inline u32 tse_tx_avail(struct altera_tse_private *priv) |
86 | { | |
87 | return priv->tx_cons + priv->tx_ring_size - priv->tx_prod - 1; | |
88 | } | |
89 | ||
90 | /* MDIO specific functions | |
91 | */ | |
92 | static int altera_tse_mdio_read(struct mii_bus *bus, int mii_id, int regnum) | |
93 | { | |
89830580 VB |
94 | struct net_device *ndev = bus->priv; |
95 | struct altera_tse_private *priv = netdev_priv(ndev); | |
bbd2190c VB |
96 | |
97 | /* set MDIO address */ | |
89830580 | 98 | csrwr32((mii_id & 0x1f), priv->mac_dev, |
a923fc73 | 99 | tse_csroffs(mdio_phy1_addr)); |
bbd2190c VB |
100 | |
101 | /* get the data */ | |
89830580 | 102 | return csrrd32(priv->mac_dev, |
a923fc73 | 103 | tse_csroffs(mdio_phy1) + regnum * 4) & 0xffff; |
bbd2190c VB |
104 | } |
105 | ||
106 | static int altera_tse_mdio_write(struct mii_bus *bus, int mii_id, int regnum, | |
107 | u16 value) | |
108 | { | |
89830580 VB |
109 | struct net_device *ndev = bus->priv; |
110 | struct altera_tse_private *priv = netdev_priv(ndev); | |
bbd2190c VB |
111 | |
112 | /* set MDIO address */ | |
89830580 | 113 | csrwr32((mii_id & 0x1f), priv->mac_dev, |
a923fc73 | 114 | tse_csroffs(mdio_phy1_addr)); |
bbd2190c VB |
115 | |
116 | /* write the data */ | |
a923fc73 | 117 | csrwr32(value, priv->mac_dev, tse_csroffs(mdio_phy1) + regnum * 4); |
bbd2190c VB |
118 | return 0; |
119 | } | |
120 | ||
121 | static int altera_tse_mdio_create(struct net_device *dev, unsigned int id) | |
122 | { | |
123 | struct altera_tse_private *priv = netdev_priv(dev); | |
bbd2190c | 124 | struct device_node *mdio_node = NULL; |
bbd2190c | 125 | struct device_node *child_node = NULL; |
5adb0ed0 MC |
126 | struct mii_bus *mdio = NULL; |
127 | int ret; | |
bbd2190c VB |
128 | |
129 | for_each_child_of_node(priv->device->of_node, child_node) { | |
130 | if (of_device_is_compatible(child_node, "altr,tse-mdio")) { | |
131 | mdio_node = child_node; | |
132 | break; | |
133 | } | |
134 | } | |
135 | ||
136 | if (mdio_node) { | |
137 | netdev_dbg(dev, "FOUND MDIO subnode\n"); | |
138 | } else { | |
139 | netdev_dbg(dev, "NO MDIO subnode\n"); | |
140 | return 0; | |
141 | } | |
142 | ||
143 | mdio = mdiobus_alloc(); | |
144 | if (mdio == NULL) { | |
145 | netdev_err(dev, "Error allocating MDIO bus\n"); | |
11ec18b1 ML |
146 | ret = -ENOMEM; |
147 | goto put_node; | |
bbd2190c VB |
148 | } |
149 | ||
150 | mdio->name = ALTERA_TSE_RESOURCE_NAME; | |
151 | mdio->read = &altera_tse_mdio_read; | |
152 | mdio->write = &altera_tse_mdio_write; | |
153 | snprintf(mdio->id, MII_BUS_ID_SIZE, "%s-%u", mdio->name, id); | |
154 | ||
89830580 | 155 | mdio->priv = dev; |
bbd2190c VB |
156 | mdio->parent = priv->device; |
157 | ||
158 | ret = of_mdiobus_register(mdio, mdio_node); | |
159 | if (ret != 0) { | |
160 | netdev_err(dev, "Cannot register MDIO bus %s\n", | |
161 | mdio->id); | |
e7f4dc35 | 162 | goto out_free_mdio; |
bbd2190c | 163 | } |
11ec18b1 | 164 | of_node_put(mdio_node); |
bbd2190c VB |
165 | |
166 | if (netif_msg_drv(priv)) | |
167 | netdev_info(dev, "MDIO bus %s: created\n", mdio->id); | |
168 | ||
169 | priv->mdio = mdio; | |
170 | return 0; | |
bbd2190c VB |
171 | out_free_mdio: |
172 | mdiobus_free(mdio); | |
173 | mdio = NULL; | |
11ec18b1 ML |
174 | put_node: |
175 | of_node_put(mdio_node); | |
bbd2190c VB |
176 | return ret; |
177 | } | |
178 | ||
179 | static void altera_tse_mdio_destroy(struct net_device *dev) | |
180 | { | |
181 | struct altera_tse_private *priv = netdev_priv(dev); | |
182 | ||
183 | if (priv->mdio == NULL) | |
184 | return; | |
185 | ||
186 | if (netif_msg_drv(priv)) | |
187 | netdev_info(dev, "MDIO bus %s: removed\n", | |
188 | priv->mdio->id); | |
189 | ||
190 | mdiobus_unregister(priv->mdio); | |
bbd2190c VB |
191 | mdiobus_free(priv->mdio); |
192 | priv->mdio = NULL; | |
193 | } | |
194 | ||
195 | static int tse_init_rx_buffer(struct altera_tse_private *priv, | |
196 | struct tse_buffer *rxbuffer, int len) | |
197 | { | |
198 | rxbuffer->skb = netdev_alloc_skb_ip_align(priv->dev, len); | |
199 | if (!rxbuffer->skb) | |
200 | return -ENOMEM; | |
201 | ||
202 | rxbuffer->dma_addr = dma_map_single(priv->device, rxbuffer->skb->data, | |
203 | len, | |
204 | DMA_FROM_DEVICE); | |
205 | ||
206 | if (dma_mapping_error(priv->device, rxbuffer->dma_addr)) { | |
207 | netdev_err(priv->dev, "%s: DMA mapping error\n", __func__); | |
208 | dev_kfree_skb_any(rxbuffer->skb); | |
209 | return -EINVAL; | |
210 | } | |
37c0ffaa | 211 | rxbuffer->dma_addr &= (dma_addr_t)~3; |
bbd2190c VB |
212 | rxbuffer->len = len; |
213 | return 0; | |
214 | } | |
215 | ||
216 | static void tse_free_rx_buffer(struct altera_tse_private *priv, | |
217 | struct tse_buffer *rxbuffer) | |
218 | { | |
bbd2190c | 219 | dma_addr_t dma_addr = rxbuffer->dma_addr; |
5adb0ed0 | 220 | struct sk_buff *skb = rxbuffer->skb; |
bbd2190c VB |
221 | |
222 | if (skb != NULL) { | |
223 | if (dma_addr) | |
224 | dma_unmap_single(priv->device, dma_addr, | |
225 | rxbuffer->len, | |
226 | DMA_FROM_DEVICE); | |
227 | dev_kfree_skb_any(skb); | |
228 | rxbuffer->skb = NULL; | |
229 | rxbuffer->dma_addr = 0; | |
230 | } | |
231 | } | |
232 | ||
233 | /* Unmap and free Tx buffer resources | |
234 | */ | |
235 | static void tse_free_tx_buffer(struct altera_tse_private *priv, | |
236 | struct tse_buffer *buffer) | |
237 | { | |
238 | if (buffer->dma_addr) { | |
239 | if (buffer->mapped_as_page) | |
240 | dma_unmap_page(priv->device, buffer->dma_addr, | |
241 | buffer->len, DMA_TO_DEVICE); | |
242 | else | |
243 | dma_unmap_single(priv->device, buffer->dma_addr, | |
244 | buffer->len, DMA_TO_DEVICE); | |
245 | buffer->dma_addr = 0; | |
246 | } | |
247 | if (buffer->skb) { | |
248 | dev_kfree_skb_any(buffer->skb); | |
249 | buffer->skb = NULL; | |
250 | } | |
251 | } | |
252 | ||
253 | static int alloc_init_skbufs(struct altera_tse_private *priv) | |
254 | { | |
255 | unsigned int rx_descs = priv->rx_ring_size; | |
256 | unsigned int tx_descs = priv->tx_ring_size; | |
257 | int ret = -ENOMEM; | |
258 | int i; | |
259 | ||
260 | /* Create Rx ring buffer */ | |
261 | priv->rx_ring = kcalloc(rx_descs, sizeof(struct tse_buffer), | |
262 | GFP_KERNEL); | |
263 | if (!priv->rx_ring) | |
264 | goto err_rx_ring; | |
265 | ||
266 | /* Create Tx ring buffer */ | |
267 | priv->tx_ring = kcalloc(tx_descs, sizeof(struct tse_buffer), | |
268 | GFP_KERNEL); | |
269 | if (!priv->tx_ring) | |
270 | goto err_tx_ring; | |
271 | ||
272 | priv->tx_cons = 0; | |
273 | priv->tx_prod = 0; | |
274 | ||
275 | /* Init Rx ring */ | |
276 | for (i = 0; i < rx_descs; i++) { | |
277 | ret = tse_init_rx_buffer(priv, &priv->rx_ring[i], | |
278 | priv->rx_dma_buf_sz); | |
279 | if (ret) | |
280 | goto err_init_rx_buffers; | |
281 | } | |
282 | ||
283 | priv->rx_cons = 0; | |
284 | priv->rx_prod = 0; | |
285 | ||
286 | return 0; | |
287 | err_init_rx_buffers: | |
288 | while (--i >= 0) | |
289 | tse_free_rx_buffer(priv, &priv->rx_ring[i]); | |
290 | kfree(priv->tx_ring); | |
291 | err_tx_ring: | |
292 | kfree(priv->rx_ring); | |
293 | err_rx_ring: | |
294 | return ret; | |
295 | } | |
296 | ||
297 | static void free_skbufs(struct net_device *dev) | |
298 | { | |
299 | struct altera_tse_private *priv = netdev_priv(dev); | |
300 | unsigned int rx_descs = priv->rx_ring_size; | |
301 | unsigned int tx_descs = priv->tx_ring_size; | |
302 | int i; | |
303 | ||
304 | /* Release the DMA TX/RX socket buffers */ | |
305 | for (i = 0; i < rx_descs; i++) | |
306 | tse_free_rx_buffer(priv, &priv->rx_ring[i]); | |
307 | for (i = 0; i < tx_descs; i++) | |
308 | tse_free_tx_buffer(priv, &priv->tx_ring[i]); | |
309 | ||
310 | ||
311 | kfree(priv->tx_ring); | |
312 | } | |
313 | ||
314 | /* Reallocate the skb for the reception process | |
315 | */ | |
316 | static inline void tse_rx_refill(struct altera_tse_private *priv) | |
317 | { | |
318 | unsigned int rxsize = priv->rx_ring_size; | |
319 | unsigned int entry; | |
320 | int ret; | |
321 | ||
322 | for (; priv->rx_cons - priv->rx_prod > 0; | |
323 | priv->rx_prod++) { | |
324 | entry = priv->rx_prod % rxsize; | |
325 | if (likely(priv->rx_ring[entry].skb == NULL)) { | |
326 | ret = tse_init_rx_buffer(priv, &priv->rx_ring[entry], | |
327 | priv->rx_dma_buf_sz); | |
328 | if (unlikely(ret != 0)) | |
329 | break; | |
330 | priv->dmaops->add_rx_desc(priv, &priv->rx_ring[entry]); | |
331 | } | |
332 | } | |
333 | } | |
334 | ||
335 | /* Pull out the VLAN tag and fix up the packet | |
336 | */ | |
337 | static inline void tse_rx_vlan(struct net_device *dev, struct sk_buff *skb) | |
338 | { | |
339 | struct ethhdr *eth_hdr; | |
340 | u16 vid; | |
5adb0ed0 | 341 | |
bbd2190c VB |
342 | if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) && |
343 | !__vlan_get_tag(skb, &vid)) { | |
344 | eth_hdr = (struct ethhdr *)skb->data; | |
345 | memmove(skb->data + VLAN_HLEN, eth_hdr, ETH_ALEN * 2); | |
346 | skb_pull(skb, VLAN_HLEN); | |
347 | __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); | |
348 | } | |
349 | } | |
350 | ||
351 | /* Receive a packet: retrieve and pass over to upper levels | |
352 | */ | |
353 | static int tse_rx(struct altera_tse_private *priv, int limit) | |
354 | { | |
5adb0ed0 | 355 | unsigned int entry = priv->rx_cons % priv->rx_ring_size; |
bbd2190c | 356 | unsigned int next_entry; |
5adb0ed0 | 357 | unsigned int count = 0; |
bbd2190c | 358 | struct sk_buff *skb; |
bbd2190c VB |
359 | u32 rxstatus; |
360 | u16 pktlength; | |
361 | u16 pktstatus; | |
362 | ||
93ea3378 AO |
363 | /* Check for count < limit first as get_rx_status is changing |
364 | * the response-fifo so we must process the next packet | |
365 | * after calling get_rx_status if a response is pending. | |
366 | * (reading the last byte of the response pops the value from the fifo.) | |
367 | */ | |
368 | while ((count < limit) && | |
369 | ((rxstatus = priv->dmaops->get_rx_status(priv)) != 0)) { | |
bbd2190c VB |
370 | pktstatus = rxstatus >> 16; |
371 | pktlength = rxstatus & 0xffff; | |
372 | ||
373 | if ((pktstatus & 0xFF) || (pktlength == 0)) | |
374 | netdev_err(priv->dev, | |
375 | "RCV pktstatus %08X pktlength %08X\n", | |
376 | pktstatus, pktlength); | |
377 | ||
a5e516d0 | 378 | /* DMA transfer from TSE starts with 2 additional bytes for |
48734994 VS |
379 | * IP payload alignment. Status returned by get_rx_status() |
380 | * contains DMA transfer length. Packet is 2 bytes shorter. | |
381 | */ | |
382 | pktlength -= 2; | |
383 | ||
bbd2190c VB |
384 | count++; |
385 | next_entry = (++priv->rx_cons) % priv->rx_ring_size; | |
386 | ||
387 | skb = priv->rx_ring[entry].skb; | |
388 | if (unlikely(!skb)) { | |
389 | netdev_err(priv->dev, | |
390 | "%s: Inconsistent Rx descriptor chain\n", | |
391 | __func__); | |
392 | priv->dev->stats.rx_dropped++; | |
393 | break; | |
394 | } | |
395 | priv->rx_ring[entry].skb = NULL; | |
396 | ||
397 | skb_put(skb, pktlength); | |
398 | ||
bbd2190c VB |
399 | dma_unmap_single(priv->device, priv->rx_ring[entry].dma_addr, |
400 | priv->rx_ring[entry].len, DMA_FROM_DEVICE); | |
401 | ||
402 | if (netif_msg_pktdata(priv)) { | |
403 | netdev_info(priv->dev, "frame received %d bytes\n", | |
404 | pktlength); | |
405 | print_hex_dump(KERN_ERR, "data: ", DUMP_PREFIX_OFFSET, | |
406 | 16, 1, skb->data, pktlength, true); | |
407 | } | |
408 | ||
409 | tse_rx_vlan(priv->dev, skb); | |
410 | ||
411 | skb->protocol = eth_type_trans(skb, priv->dev); | |
412 | skb_checksum_none_assert(skb); | |
413 | ||
414 | napi_gro_receive(&priv->napi, skb); | |
415 | ||
416 | priv->dev->stats.rx_packets++; | |
417 | priv->dev->stats.rx_bytes += pktlength; | |
418 | ||
419 | entry = next_entry; | |
37c0ffaa VB |
420 | |
421 | tse_rx_refill(priv); | |
bbd2190c VB |
422 | } |
423 | ||
bbd2190c VB |
424 | return count; |
425 | } | |
426 | ||
427 | /* Reclaim resources after transmission completes | |
428 | */ | |
429 | static int tse_tx_complete(struct altera_tse_private *priv) | |
430 | { | |
431 | unsigned int txsize = priv->tx_ring_size; | |
bbd2190c | 432 | struct tse_buffer *tx_buff; |
5adb0ed0 | 433 | unsigned int entry; |
bbd2190c | 434 | int txcomplete = 0; |
5adb0ed0 | 435 | u32 ready; |
bbd2190c VB |
436 | |
437 | spin_lock(&priv->tx_lock); | |
438 | ||
439 | ready = priv->dmaops->tx_completions(priv); | |
440 | ||
441 | /* Free sent buffers */ | |
442 | while (ready && (priv->tx_cons != priv->tx_prod)) { | |
443 | entry = priv->tx_cons % txsize; | |
444 | tx_buff = &priv->tx_ring[entry]; | |
445 | ||
446 | if (netif_msg_tx_done(priv)) | |
447 | netdev_dbg(priv->dev, "%s: curr %d, dirty %d\n", | |
448 | __func__, priv->tx_prod, priv->tx_cons); | |
449 | ||
450 | if (likely(tx_buff->skb)) | |
451 | priv->dev->stats.tx_packets++; | |
452 | ||
453 | tse_free_tx_buffer(priv, tx_buff); | |
454 | priv->tx_cons++; | |
455 | ||
456 | txcomplete++; | |
457 | ready--; | |
458 | } | |
459 | ||
460 | if (unlikely(netif_queue_stopped(priv->dev) && | |
461 | tse_tx_avail(priv) > TSE_TX_THRESH(priv))) { | |
bbd2190c VB |
462 | if (netif_queue_stopped(priv->dev) && |
463 | tse_tx_avail(priv) > TSE_TX_THRESH(priv)) { | |
464 | if (netif_msg_tx_done(priv)) | |
465 | netdev_dbg(priv->dev, "%s: restart transmit\n", | |
466 | __func__); | |
467 | netif_wake_queue(priv->dev); | |
468 | } | |
bbd2190c VB |
469 | } |
470 | ||
471 | spin_unlock(&priv->tx_lock); | |
472 | return txcomplete; | |
473 | } | |
474 | ||
475 | /* NAPI polling function | |
476 | */ | |
477 | static int tse_poll(struct napi_struct *napi, int budget) | |
478 | { | |
479 | struct altera_tse_private *priv = | |
480 | container_of(napi, struct altera_tse_private, napi); | |
bbd2190c | 481 | unsigned long int flags; |
5adb0ed0 | 482 | int rxcomplete = 0; |
bbd2190c | 483 | |
8d4ac39d | 484 | tse_tx_complete(priv); |
bbd2190c VB |
485 | |
486 | rxcomplete = tse_rx(priv, budget); | |
487 | ||
8d4ac39d | 488 | if (rxcomplete < budget) { |
bbd2190c | 489 | |
6ad20165 | 490 | napi_complete_done(napi, rxcomplete); |
bbd2190c | 491 | |
8d4ac39d VS |
492 | netdev_dbg(priv->dev, |
493 | "NAPI Complete, did %d packets with budget %d\n", | |
494 | rxcomplete, budget); | |
bbd2190c | 495 | |
8d4ac39d VS |
496 | spin_lock_irqsave(&priv->rxdma_irq_lock, flags); |
497 | priv->dmaops->enable_rxirq(priv); | |
498 | priv->dmaops->enable_txirq(priv); | |
499 | spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags); | |
500 | } | |
501 | return rxcomplete; | |
bbd2190c VB |
502 | } |
503 | ||
504 | /* DMA TX & RX FIFO interrupt routing | |
505 | */ | |
506 | static irqreturn_t altera_isr(int irq, void *dev_id) | |
507 | { | |
508 | struct net_device *dev = dev_id; | |
509 | struct altera_tse_private *priv; | |
bbd2190c | 510 | |
bbd2190c VB |
511 | if (unlikely(!dev)) { |
512 | pr_err("%s: invalid dev pointer\n", __func__); | |
513 | return IRQ_NONE; | |
514 | } | |
515 | priv = netdev_priv(dev); | |
516 | ||
8d4ac39d VS |
517 | spin_lock(&priv->rxdma_irq_lock); |
518 | /* reset IRQs */ | |
519 | priv->dmaops->clear_rxirq(priv); | |
520 | priv->dmaops->clear_txirq(priv); | |
521 | spin_unlock(&priv->rxdma_irq_lock); | |
bbd2190c VB |
522 | |
523 | if (likely(napi_schedule_prep(&priv->napi))) { | |
8d4ac39d | 524 | spin_lock(&priv->rxdma_irq_lock); |
bbd2190c VB |
525 | priv->dmaops->disable_rxirq(priv); |
526 | priv->dmaops->disable_txirq(priv); | |
8d4ac39d | 527 | spin_unlock(&priv->rxdma_irq_lock); |
bbd2190c VB |
528 | __napi_schedule(&priv->napi); |
529 | } | |
530 | ||
bbd2190c VB |
531 | |
532 | return IRQ_HANDLED; | |
533 | } | |
534 | ||
535 | /* Transmit a packet (called by the kernel). Dispatches | |
536 | * either the SGDMA method for transmitting or the | |
537 | * MSGDMA method, assumes no scatter/gather support, | |
538 | * implying an assumption that there's only one | |
539 | * physically contiguous fragment starting at | |
540 | * skb->data, for length of skb_headlen(skb). | |
541 | */ | |
ab99b7d2 | 542 | static netdev_tx_t tse_start_xmit(struct sk_buff *skb, struct net_device *dev) |
bbd2190c VB |
543 | { |
544 | struct altera_tse_private *priv = netdev_priv(dev); | |
5adb0ed0 | 545 | unsigned int nopaged_len = skb_headlen(skb); |
bbd2190c | 546 | unsigned int txsize = priv->tx_ring_size; |
bbd2190c | 547 | int nfrags = skb_shinfo(skb)->nr_frags; |
5adb0ed0 | 548 | struct tse_buffer *buffer = NULL; |
ab99b7d2 | 549 | netdev_tx_t ret = NETDEV_TX_OK; |
bbd2190c | 550 | dma_addr_t dma_addr; |
5adb0ed0 | 551 | unsigned int entry; |
bbd2190c VB |
552 | |
553 | spin_lock_bh(&priv->tx_lock); | |
554 | ||
555 | if (unlikely(tse_tx_avail(priv) < nfrags + 1)) { | |
556 | if (!netif_queue_stopped(dev)) { | |
557 | netif_stop_queue(dev); | |
558 | /* This is a hard error, log it. */ | |
559 | netdev_err(priv->dev, | |
560 | "%s: Tx list full when queue awake\n", | |
561 | __func__); | |
562 | } | |
563 | ret = NETDEV_TX_BUSY; | |
564 | goto out; | |
565 | } | |
566 | ||
567 | /* Map the first skb fragment */ | |
568 | entry = priv->tx_prod % txsize; | |
569 | buffer = &priv->tx_ring[entry]; | |
570 | ||
571 | dma_addr = dma_map_single(priv->device, skb->data, nopaged_len, | |
572 | DMA_TO_DEVICE); | |
573 | if (dma_mapping_error(priv->device, dma_addr)) { | |
574 | netdev_err(priv->dev, "%s: DMA mapping error\n", __func__); | |
575 | ret = NETDEV_TX_OK; | |
576 | goto out; | |
577 | } | |
578 | ||
579 | buffer->skb = skb; | |
580 | buffer->dma_addr = dma_addr; | |
581 | buffer->len = nopaged_len; | |
582 | ||
89830580 | 583 | priv->dmaops->tx_buffer(priv, buffer); |
bbd2190c VB |
584 | |
585 | skb_tx_timestamp(skb); | |
586 | ||
587 | priv->tx_prod++; | |
588 | dev->stats.tx_bytes += skb->len; | |
589 | ||
590 | if (unlikely(tse_tx_avail(priv) <= TXQUEUESTOP_THRESHHOLD)) { | |
591 | if (netif_msg_hw(priv)) | |
592 | netdev_dbg(priv->dev, "%s: stop transmitted packets\n", | |
593 | __func__); | |
594 | netif_stop_queue(dev); | |
595 | } | |
596 | ||
597 | out: | |
598 | spin_unlock_bh(&priv->tx_lock); | |
599 | ||
600 | return ret; | |
601 | } | |
602 | ||
004fa118 WL |
603 | static int altera_tse_phy_get_addr_mdio_create(struct net_device *dev) |
604 | { | |
605 | struct altera_tse_private *priv = netdev_priv(dev); | |
606 | struct device_node *np = priv->device->of_node; | |
0c65b2b9 | 607 | int ret; |
004fa118 | 608 | |
0c65b2b9 | 609 | ret = of_get_phy_mode(np, &priv->phy_iface); |
004fa118 | 610 | |
3354313e | 611 | /* Avoid get phy addr and create mdio if no phy is present */ |
0c65b2b9 | 612 | if (ret) |
3354313e WL |
613 | return 0; |
614 | ||
004fa118 WL |
615 | /* try to get PHY address from device tree, use PHY autodetection if |
616 | * no valid address is given | |
617 | */ | |
618 | ||
619 | if (of_property_read_u32(priv->device->of_node, "phy-addr", | |
620 | &priv->phy_addr)) { | |
621 | priv->phy_addr = POLL_PHY; | |
622 | } | |
623 | ||
624 | if (!((priv->phy_addr == POLL_PHY) || | |
625 | ((priv->phy_addr >= 0) && (priv->phy_addr < PHY_MAX_ADDR)))) { | |
626 | netdev_err(dev, "invalid phy-addr specified %d\n", | |
627 | priv->phy_addr); | |
628 | return -ENODEV; | |
629 | } | |
630 | ||
631 | /* Create/attach to MDIO bus */ | |
632 | ret = altera_tse_mdio_create(dev, | |
633 | atomic_add_return(1, &instance_count)); | |
634 | ||
635 | if (ret) | |
636 | return -ENODEV; | |
637 | ||
638 | return 0; | |
639 | } | |
640 | ||
76660757 | 641 | static void tse_update_mac_addr(struct altera_tse_private *priv, const u8 *addr) |
bbd2190c | 642 | { |
bbd2190c VB |
643 | u32 msb; |
644 | u32 lsb; | |
645 | ||
646 | msb = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0]; | |
647 | lsb = ((addr[5] << 8) | addr[4]) & 0xffff; | |
648 | ||
649 | /* Set primary MAC address */ | |
89830580 VB |
650 | csrwr32(msb, priv->mac_dev, tse_csroffs(mac_addr_0)); |
651 | csrwr32(lsb, priv->mac_dev, tse_csroffs(mac_addr_1)); | |
bbd2190c VB |
652 | } |
653 | ||
654 | /* MAC software reset. | |
655 | * When reset is triggered, the MAC function completes the current | |
656 | * transmission or reception, and subsequently disables the transmit and | |
657 | * receive logic, flushes the receive FIFO buffer, and resets the statistics | |
658 | * counters. | |
659 | */ | |
660 | static int reset_mac(struct altera_tse_private *priv) | |
661 | { | |
bbd2190c VB |
662 | int counter; |
663 | u32 dat; | |
664 | ||
89830580 | 665 | dat = csrrd32(priv->mac_dev, tse_csroffs(command_config)); |
bbd2190c VB |
666 | dat &= ~(MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA); |
667 | dat |= MAC_CMDCFG_SW_RESET | MAC_CMDCFG_CNT_RESET; | |
89830580 | 668 | csrwr32(dat, priv->mac_dev, tse_csroffs(command_config)); |
bbd2190c VB |
669 | |
670 | counter = 0; | |
671 | while (counter++ < ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) { | |
89830580 VB |
672 | if (tse_bit_is_clear(priv->mac_dev, tse_csroffs(command_config), |
673 | MAC_CMDCFG_SW_RESET)) | |
bbd2190c VB |
674 | break; |
675 | udelay(1); | |
676 | } | |
677 | ||
678 | if (counter >= ALTERA_TSE_SW_RESET_WATCHDOG_CNTR) { | |
89830580 | 679 | dat = csrrd32(priv->mac_dev, tse_csroffs(command_config)); |
bbd2190c | 680 | dat &= ~MAC_CMDCFG_SW_RESET; |
89830580 | 681 | csrwr32(dat, priv->mac_dev, tse_csroffs(command_config)); |
bbd2190c VB |
682 | return -1; |
683 | } | |
684 | return 0; | |
685 | } | |
686 | ||
687 | /* Initialize MAC core registers | |
688 | */ | |
689 | static int init_mac(struct altera_tse_private *priv) | |
690 | { | |
bbd2190c VB |
691 | unsigned int cmd = 0; |
692 | u32 frm_length; | |
693 | ||
694 | /* Setup Rx FIFO */ | |
89830580 VB |
695 | csrwr32(priv->rx_fifo_depth - ALTERA_TSE_RX_SECTION_EMPTY, |
696 | priv->mac_dev, tse_csroffs(rx_section_empty)); | |
697 | ||
698 | csrwr32(ALTERA_TSE_RX_SECTION_FULL, priv->mac_dev, | |
699 | tse_csroffs(rx_section_full)); | |
700 | ||
701 | csrwr32(ALTERA_TSE_RX_ALMOST_EMPTY, priv->mac_dev, | |
702 | tse_csroffs(rx_almost_empty)); | |
703 | ||
704 | csrwr32(ALTERA_TSE_RX_ALMOST_FULL, priv->mac_dev, | |
705 | tse_csroffs(rx_almost_full)); | |
bbd2190c VB |
706 | |
707 | /* Setup Tx FIFO */ | |
89830580 VB |
708 | csrwr32(priv->tx_fifo_depth - ALTERA_TSE_TX_SECTION_EMPTY, |
709 | priv->mac_dev, tse_csroffs(tx_section_empty)); | |
710 | ||
711 | csrwr32(ALTERA_TSE_TX_SECTION_FULL, priv->mac_dev, | |
712 | tse_csroffs(tx_section_full)); | |
713 | ||
714 | csrwr32(ALTERA_TSE_TX_ALMOST_EMPTY, priv->mac_dev, | |
715 | tse_csroffs(tx_almost_empty)); | |
716 | ||
717 | csrwr32(ALTERA_TSE_TX_ALMOST_FULL, priv->mac_dev, | |
718 | tse_csroffs(tx_almost_full)); | |
bbd2190c VB |
719 | |
720 | /* MAC Address Configuration */ | |
721 | tse_update_mac_addr(priv, priv->dev->dev_addr); | |
722 | ||
723 | /* MAC Function Configuration */ | |
724 | frm_length = ETH_HLEN + priv->dev->mtu + ETH_FCS_LEN; | |
89830580 VB |
725 | csrwr32(frm_length, priv->mac_dev, tse_csroffs(frm_length)); |
726 | ||
727 | csrwr32(ALTERA_TSE_TX_IPG_LENGTH, priv->mac_dev, | |
728 | tse_csroffs(tx_ipg_length)); | |
bbd2190c VB |
729 | |
730 | /* Disable RX/TX shift 16 for alignment of all received frames on 16-bit | |
731 | * start address | |
732 | */ | |
89830580 VB |
733 | tse_set_bit(priv->mac_dev, tse_csroffs(rx_cmd_stat), |
734 | ALTERA_TSE_RX_CMD_STAT_RX_SHIFT16); | |
735 | ||
736 | tse_clear_bit(priv->mac_dev, tse_csroffs(tx_cmd_stat), | |
737 | ALTERA_TSE_TX_CMD_STAT_TX_SHIFT16 | | |
738 | ALTERA_TSE_TX_CMD_STAT_OMIT_CRC); | |
bbd2190c VB |
739 | |
740 | /* Set the MAC options */ | |
89830580 | 741 | cmd = csrrd32(priv->mac_dev, tse_csroffs(command_config)); |
37c0ffaa | 742 | cmd &= ~MAC_CMDCFG_PAD_EN; /* No padding Removal on Receive */ |
bbd2190c VB |
743 | cmd &= ~MAC_CMDCFG_CRC_FWD; /* CRC Removal */ |
744 | cmd |= MAC_CMDCFG_RX_ERR_DISC; /* Automatically discard frames | |
745 | * with CRC errors | |
746 | */ | |
747 | cmd |= MAC_CMDCFG_CNTL_FRM_ENA; | |
748 | cmd &= ~MAC_CMDCFG_TX_ENA; | |
749 | cmd &= ~MAC_CMDCFG_RX_ENA; | |
37c0ffaa VB |
750 | |
751 | /* Default speed and duplex setting, full/100 */ | |
752 | cmd &= ~MAC_CMDCFG_HD_ENA; | |
753 | cmd &= ~MAC_CMDCFG_ETH_SPEED; | |
754 | cmd &= ~MAC_CMDCFG_ENA_10; | |
755 | ||
89830580 | 756 | csrwr32(cmd, priv->mac_dev, tse_csroffs(command_config)); |
bbd2190c | 757 | |
89830580 VB |
758 | csrwr32(ALTERA_TSE_PAUSE_QUANTA, priv->mac_dev, |
759 | tse_csroffs(pause_quanta)); | |
5aec4ee3 | 760 | |
bbd2190c VB |
761 | if (netif_msg_hw(priv)) |
762 | dev_dbg(priv->device, | |
763 | "MAC post-initialization: CMD_CONFIG = 0x%08x\n", cmd); | |
764 | ||
765 | return 0; | |
766 | } | |
767 | ||
768 | /* Start/stop MAC transmission logic | |
769 | */ | |
770 | static void tse_set_mac(struct altera_tse_private *priv, bool enable) | |
771 | { | |
89830580 | 772 | u32 value = csrrd32(priv->mac_dev, tse_csroffs(command_config)); |
bbd2190c VB |
773 | |
774 | if (enable) | |
775 | value |= MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA; | |
776 | else | |
777 | value &= ~(MAC_CMDCFG_TX_ENA | MAC_CMDCFG_RX_ENA); | |
778 | ||
89830580 | 779 | csrwr32(value, priv->mac_dev, tse_csroffs(command_config)); |
bbd2190c VB |
780 | } |
781 | ||
782 | /* Change the MTU | |
783 | */ | |
784 | static int tse_change_mtu(struct net_device *dev, int new_mtu) | |
785 | { | |
bbd2190c VB |
786 | if (netif_running(dev)) { |
787 | netdev_err(dev, "must be stopped to change its MTU\n"); | |
788 | return -EBUSY; | |
789 | } | |
790 | ||
1eb2cded | 791 | WRITE_ONCE(dev->mtu, new_mtu); |
bbd2190c VB |
792 | netdev_update_features(dev); |
793 | ||
794 | return 0; | |
795 | } | |
796 | ||
797 | static void altera_tse_set_mcfilter(struct net_device *dev) | |
798 | { | |
799 | struct altera_tse_private *priv = netdev_priv(dev); | |
bbd2190c | 800 | struct netdev_hw_addr *ha; |
5adb0ed0 | 801 | int i; |
bbd2190c VB |
802 | |
803 | /* clear the hash filter */ | |
804 | for (i = 0; i < 64; i++) | |
89830580 | 805 | csrwr32(0, priv->mac_dev, tse_csroffs(hash_table) + i * 4); |
bbd2190c VB |
806 | |
807 | netdev_for_each_mc_addr(ha, dev) { | |
808 | unsigned int hash = 0; | |
809 | int mac_octet; | |
810 | ||
811 | for (mac_octet = 5; mac_octet >= 0; mac_octet--) { | |
812 | unsigned char xor_bit = 0; | |
813 | unsigned char octet = ha->addr[mac_octet]; | |
814 | unsigned int bitshift; | |
815 | ||
816 | for (bitshift = 0; bitshift < 8; bitshift++) | |
817 | xor_bit ^= ((octet >> bitshift) & 0x01); | |
818 | ||
819 | hash = (hash << 1) | xor_bit; | |
820 | } | |
89830580 | 821 | csrwr32(1, priv->mac_dev, tse_csroffs(hash_table) + hash * 4); |
bbd2190c VB |
822 | } |
823 | } | |
824 | ||
825 | ||
826 | static void altera_tse_set_mcfilterall(struct net_device *dev) | |
827 | { | |
828 | struct altera_tse_private *priv = netdev_priv(dev); | |
bbd2190c VB |
829 | int i; |
830 | ||
831 | /* set the hash filter */ | |
832 | for (i = 0; i < 64; i++) | |
89830580 | 833 | csrwr32(1, priv->mac_dev, tse_csroffs(hash_table) + i * 4); |
bbd2190c VB |
834 | } |
835 | ||
a5e516d0 | 836 | /* Set or clear the multicast filter for this adapter |
bbd2190c VB |
837 | */ |
838 | static void tse_set_rx_mode_hashfilter(struct net_device *dev) | |
839 | { | |
840 | struct altera_tse_private *priv = netdev_priv(dev); | |
bbd2190c VB |
841 | |
842 | spin_lock(&priv->mac_cfg_lock); | |
843 | ||
844 | if (dev->flags & IFF_PROMISC) | |
89830580 VB |
845 | tse_set_bit(priv->mac_dev, tse_csroffs(command_config), |
846 | MAC_CMDCFG_PROMIS_EN); | |
bbd2190c VB |
847 | |
848 | if (dev->flags & IFF_ALLMULTI) | |
849 | altera_tse_set_mcfilterall(dev); | |
850 | else | |
851 | altera_tse_set_mcfilter(dev); | |
852 | ||
853 | spin_unlock(&priv->mac_cfg_lock); | |
854 | } | |
855 | ||
a5e516d0 | 856 | /* Set or clear the multicast filter for this adapter |
bbd2190c VB |
857 | */ |
858 | static void tse_set_rx_mode(struct net_device *dev) | |
859 | { | |
860 | struct altera_tse_private *priv = netdev_priv(dev); | |
bbd2190c VB |
861 | |
862 | spin_lock(&priv->mac_cfg_lock); | |
863 | ||
864 | if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || | |
865 | !netdev_mc_empty(dev) || !netdev_uc_empty(dev)) | |
89830580 VB |
866 | tse_set_bit(priv->mac_dev, tse_csroffs(command_config), |
867 | MAC_CMDCFG_PROMIS_EN); | |
bbd2190c | 868 | else |
89830580 VB |
869 | tse_clear_bit(priv->mac_dev, tse_csroffs(command_config), |
870 | MAC_CMDCFG_PROMIS_EN); | |
bbd2190c VB |
871 | |
872 | spin_unlock(&priv->mac_cfg_lock); | |
873 | } | |
874 | ||
875 | /* Open and initialize the interface | |
876 | */ | |
877 | static int tse_open(struct net_device *dev) | |
878 | { | |
879 | struct altera_tse_private *priv = netdev_priv(dev); | |
5adb0ed0 | 880 | unsigned long flags; |
bbd2190c VB |
881 | int ret = 0; |
882 | int i; | |
bbd2190c VB |
883 | |
884 | /* Reset and configure TSE MAC and probe associated PHY */ | |
885 | ret = priv->dmaops->init_dma(priv); | |
886 | if (ret != 0) { | |
887 | netdev_err(dev, "Cannot initialize DMA\n"); | |
888 | goto phy_error; | |
889 | } | |
890 | ||
891 | if (netif_msg_ifup(priv)) | |
892 | netdev_warn(dev, "device MAC address %pM\n", | |
893 | dev->dev_addr); | |
894 | ||
895 | if ((priv->revision < 0xd00) || (priv->revision > 0xe00)) | |
896 | netdev_warn(dev, "TSE revision %x\n", priv->revision); | |
897 | ||
898 | spin_lock(&priv->mac_cfg_lock); | |
3b804564 | 899 | |
bbd2190c | 900 | ret = reset_mac(priv); |
ea8860eb VB |
901 | /* Note that reset_mac will fail if the clocks are gated by the PHY |
902 | * due to the PHY being put into isolation or power down mode. | |
903 | * This is not an error if reset fails due to no clock. | |
904 | */ | |
bbd2190c | 905 | if (ret) |
ea8860eb | 906 | netdev_dbg(dev, "Cannot reset MAC core (error: %d)\n", ret); |
bbd2190c VB |
907 | |
908 | ret = init_mac(priv); | |
909 | spin_unlock(&priv->mac_cfg_lock); | |
910 | if (ret) { | |
911 | netdev_err(dev, "Cannot init MAC core (error: %d)\n", ret); | |
912 | goto alloc_skbuf_error; | |
913 | } | |
914 | ||
915 | priv->dmaops->reset_dma(priv); | |
916 | ||
917 | /* Create and initialize the TX/RX descriptors chains. */ | |
918 | priv->rx_ring_size = dma_rx_num; | |
919 | priv->tx_ring_size = dma_tx_num; | |
920 | ret = alloc_init_skbufs(priv); | |
921 | if (ret) { | |
922 | netdev_err(dev, "DMA descriptors initialization failed\n"); | |
923 | goto alloc_skbuf_error; | |
924 | } | |
925 | ||
926 | ||
927 | /* Register RX interrupt */ | |
928 | ret = request_irq(priv->rx_irq, altera_isr, IRQF_SHARED, | |
929 | dev->name, dev); | |
930 | if (ret) { | |
931 | netdev_err(dev, "Unable to register RX interrupt %d\n", | |
932 | priv->rx_irq); | |
933 | goto init_error; | |
934 | } | |
935 | ||
936 | /* Register TX interrupt */ | |
937 | ret = request_irq(priv->tx_irq, altera_isr, IRQF_SHARED, | |
938 | dev->name, dev); | |
939 | if (ret) { | |
940 | netdev_err(dev, "Unable to register TX interrupt %d\n", | |
941 | priv->tx_irq); | |
942 | goto tx_request_irq_error; | |
943 | } | |
944 | ||
945 | /* Enable DMA interrupts */ | |
946 | spin_lock_irqsave(&priv->rxdma_irq_lock, flags); | |
947 | priv->dmaops->enable_rxirq(priv); | |
948 | priv->dmaops->enable_txirq(priv); | |
949 | ||
950 | /* Setup RX descriptor chain */ | |
951 | for (i = 0; i < priv->rx_ring_size; i++) | |
952 | priv->dmaops->add_rx_desc(priv, &priv->rx_ring[i]); | |
953 | ||
954 | spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags); | |
955 | ||
fef29982 MC |
956 | ret = phylink_of_phy_connect(priv->phylink, priv->device->of_node, 0); |
957 | if (ret) { | |
958 | netdev_err(dev, "could not connect phylink (%d)\n", ret); | |
959 | goto tx_request_irq_error; | |
960 | } | |
961 | phylink_start(priv->phylink); | |
bbd2190c VB |
962 | |
963 | napi_enable(&priv->napi); | |
964 | netif_start_queue(dev); | |
965 | ||
37c0ffaa VB |
966 | priv->dmaops->start_rxdma(priv); |
967 | ||
968 | /* Start MAC Rx/Tx */ | |
969 | spin_lock(&priv->mac_cfg_lock); | |
970 | tse_set_mac(priv, true); | |
971 | spin_unlock(&priv->mac_cfg_lock); | |
972 | ||
bbd2190c VB |
973 | return 0; |
974 | ||
975 | tx_request_irq_error: | |
976 | free_irq(priv->rx_irq, dev); | |
977 | init_error: | |
978 | free_skbufs(dev); | |
979 | alloc_skbuf_error: | |
bbd2190c VB |
980 | phy_error: |
981 | return ret; | |
982 | } | |
983 | ||
984 | /* Stop TSE MAC interface and put the device in an inactive state | |
985 | */ | |
986 | static int tse_shutdown(struct net_device *dev) | |
987 | { | |
988 | struct altera_tse_private *priv = netdev_priv(dev); | |
bbd2190c | 989 | unsigned long int flags; |
5adb0ed0 | 990 | int ret; |
bbd2190c | 991 | |
fef29982 | 992 | phylink_stop(priv->phylink); |
6aae1bcb | 993 | phylink_disconnect_phy(priv->phylink); |
bbd2190c VB |
994 | netif_stop_queue(dev); |
995 | napi_disable(&priv->napi); | |
996 | ||
997 | /* Disable DMA interrupts */ | |
998 | spin_lock_irqsave(&priv->rxdma_irq_lock, flags); | |
999 | priv->dmaops->disable_rxirq(priv); | |
1000 | priv->dmaops->disable_txirq(priv); | |
1001 | spin_unlock_irqrestore(&priv->rxdma_irq_lock, flags); | |
1002 | ||
1003 | /* Free the IRQ lines */ | |
1004 | free_irq(priv->rx_irq, dev); | |
1005 | free_irq(priv->tx_irq, dev); | |
1006 | ||
1007 | /* disable and reset the MAC, empties fifo */ | |
1008 | spin_lock(&priv->mac_cfg_lock); | |
1009 | spin_lock(&priv->tx_lock); | |
1010 | ||
1011 | ret = reset_mac(priv); | |
ea8860eb VB |
1012 | /* Note that reset_mac will fail if the clocks are gated by the PHY |
1013 | * due to the PHY being put into isolation or power down mode. | |
1014 | * This is not an error if reset fails due to no clock. | |
1015 | */ | |
bbd2190c | 1016 | if (ret) |
ea8860eb | 1017 | netdev_dbg(dev, "Cannot reset MAC core (error: %d)\n", ret); |
bbd2190c VB |
1018 | priv->dmaops->reset_dma(priv); |
1019 | free_skbufs(dev); | |
1020 | ||
1021 | spin_unlock(&priv->tx_lock); | |
1022 | spin_unlock(&priv->mac_cfg_lock); | |
1023 | ||
1024 | priv->dmaops->uninit_dma(priv); | |
1025 | ||
1026 | return 0; | |
1027 | } | |
1028 | ||
1029 | static struct net_device_ops altera_tse_netdev_ops = { | |
1030 | .ndo_open = tse_open, | |
1031 | .ndo_stop = tse_shutdown, | |
1032 | .ndo_start_xmit = tse_start_xmit, | |
1033 | .ndo_set_mac_address = eth_mac_addr, | |
1034 | .ndo_set_rx_mode = tse_set_rx_mode, | |
1035 | .ndo_change_mtu = tse_change_mtu, | |
1036 | .ndo_validate_addr = eth_validate_addr, | |
1037 | }; | |
1038 | ||
fef29982 MC |
1039 | static void alt_tse_mac_config(struct phylink_config *config, unsigned int mode, |
1040 | const struct phylink_link_state *state) | |
1041 | { | |
1042 | struct net_device *ndev = to_net_dev(config->dev); | |
1043 | struct altera_tse_private *priv = netdev_priv(ndev); | |
1044 | ||
1045 | spin_lock(&priv->mac_cfg_lock); | |
1046 | reset_mac(priv); | |
1047 | tse_set_mac(priv, true); | |
1048 | spin_unlock(&priv->mac_cfg_lock); | |
1049 | } | |
1050 | ||
1051 | static void alt_tse_mac_link_down(struct phylink_config *config, | |
1052 | unsigned int mode, phy_interface_t interface) | |
1053 | { | |
1054 | } | |
1055 | ||
1056 | static void alt_tse_mac_link_up(struct phylink_config *config, | |
1057 | struct phy_device *phy, unsigned int mode, | |
1058 | phy_interface_t interface, int speed, | |
1059 | int duplex, bool tx_pause, bool rx_pause) | |
1060 | { | |
1061 | struct net_device *ndev = to_net_dev(config->dev); | |
1062 | struct altera_tse_private *priv = netdev_priv(ndev); | |
1063 | u32 ctrl; | |
1064 | ||
1065 | ctrl = csrrd32(priv->mac_dev, tse_csroffs(command_config)); | |
1066 | ctrl &= ~(MAC_CMDCFG_ENA_10 | MAC_CMDCFG_ETH_SPEED | MAC_CMDCFG_HD_ENA); | |
1067 | ||
1068 | if (duplex == DUPLEX_HALF) | |
1069 | ctrl |= MAC_CMDCFG_HD_ENA; | |
1070 | ||
1071 | if (speed == SPEED_1000) | |
1072 | ctrl |= MAC_CMDCFG_ETH_SPEED; | |
1073 | else if (speed == SPEED_10) | |
1074 | ctrl |= MAC_CMDCFG_ENA_10; | |
1075 | ||
1076 | spin_lock(&priv->mac_cfg_lock); | |
1077 | csrwr32(ctrl, priv->mac_dev, tse_csroffs(command_config)); | |
1078 | spin_unlock(&priv->mac_cfg_lock); | |
1079 | } | |
1080 | ||
1081 | static struct phylink_pcs *alt_tse_select_pcs(struct phylink_config *config, | |
1082 | phy_interface_t interface) | |
1083 | { | |
1084 | struct net_device *ndev = to_net_dev(config->dev); | |
1085 | struct altera_tse_private *priv = netdev_priv(ndev); | |
1086 | ||
1087 | if (interface == PHY_INTERFACE_MODE_SGMII || | |
1088 | interface == PHY_INTERFACE_MODE_1000BASEX) | |
1089 | return priv->pcs; | |
1090 | else | |
1091 | return NULL; | |
1092 | } | |
1093 | ||
1094 | static const struct phylink_mac_ops alt_tse_phylink_ops = { | |
fef29982 MC |
1095 | .mac_config = alt_tse_mac_config, |
1096 | .mac_link_down = alt_tse_mac_link_down, | |
1097 | .mac_link_up = alt_tse_mac_link_up, | |
1098 | .mac_select_pcs = alt_tse_select_pcs, | |
1099 | }; | |
1100 | ||
bbd2190c VB |
1101 | static int request_and_map(struct platform_device *pdev, const char *name, |
1102 | struct resource **res, void __iomem **ptr) | |
1103 | { | |
bbd2190c | 1104 | struct device *device = &pdev->dev; |
5adb0ed0 | 1105 | struct resource *region; |
bbd2190c VB |
1106 | |
1107 | *res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name); | |
1108 | if (*res == NULL) { | |
1109 | dev_err(device, "resource %s not defined\n", name); | |
1110 | return -ENODEV; | |
1111 | } | |
1112 | ||
1113 | region = devm_request_mem_region(device, (*res)->start, | |
1114 | resource_size(*res), dev_name(device)); | |
1115 | if (region == NULL) { | |
1116 | dev_err(device, "unable to request %s\n", name); | |
1117 | return -EBUSY; | |
1118 | } | |
1119 | ||
4bdc0d67 | 1120 | *ptr = devm_ioremap(device, region->start, |
bbd2190c VB |
1121 | resource_size(region)); |
1122 | if (*ptr == NULL) { | |
4bdc0d67 | 1123 | dev_err(device, "ioremap of %s failed!", name); |
bbd2190c VB |
1124 | return -ENOMEM; |
1125 | } | |
1126 | ||
1127 | return 0; | |
1128 | } | |
1129 | ||
1130 | /* Probe Altera TSE MAC device | |
1131 | */ | |
1132 | static int altera_tse_probe(struct platform_device *pdev) | |
1133 | { | |
db48abba | 1134 | struct regmap_config pcs_regmap_cfg; |
5adb0ed0 | 1135 | struct altera_tse_private *priv; |
db48abba | 1136 | struct mdio_regmap_config mrc; |
bbd2190c | 1137 | struct resource *control_port; |
db48abba | 1138 | struct regmap *pcs_regmap; |
bbd2190c | 1139 | struct resource *dma_res; |
fef29982 | 1140 | struct resource *pcs_res; |
db48abba | 1141 | struct mii_bus *pcs_bus; |
5adb0ed0 | 1142 | struct net_device *ndev; |
bbd2190c | 1143 | void __iomem *descmap; |
5adb0ed0 | 1144 | int ret = -ENODEV; |
bbd2190c VB |
1145 | |
1146 | ndev = alloc_etherdev(sizeof(struct altera_tse_private)); | |
1147 | if (!ndev) { | |
1148 | dev_err(&pdev->dev, "Could not allocate network device\n"); | |
1149 | return -ENODEV; | |
1150 | } | |
1151 | ||
1152 | SET_NETDEV_DEV(ndev, &pdev->dev); | |
1153 | ||
1154 | priv = netdev_priv(ndev); | |
1155 | priv->device = &pdev->dev; | |
1156 | priv->dev = ndev; | |
1157 | priv->msg_enable = netif_msg_init(debug, default_msg_level); | |
1158 | ||
b0377116 | 1159 | priv->dmaops = device_get_match_data(&pdev->dev); |
bbd2190c VB |
1160 | |
1161 | if (priv->dmaops && | |
1162 | priv->dmaops->altera_dtype == ALTERA_DTYPE_SGDMA) { | |
1163 | /* Get the mapped address to the SGDMA descriptor memory */ | |
1164 | ret = request_and_map(pdev, "s1", &dma_res, &descmap); | |
1165 | if (ret) | |
a7642009 | 1166 | goto err_free_netdev; |
bbd2190c VB |
1167 | |
1168 | /* Start of that memory is for transmit descriptors */ | |
1169 | priv->tx_dma_desc = descmap; | |
1170 | ||
1171 | /* First half is for tx descriptors, other half for tx */ | |
1172 | priv->txdescmem = resource_size(dma_res)/2; | |
1173 | ||
1174 | priv->txdescmem_busaddr = (dma_addr_t)dma_res->start; | |
1175 | ||
1176 | priv->rx_dma_desc = (void __iomem *)((uintptr_t)(descmap + | |
1177 | priv->txdescmem)); | |
1178 | priv->rxdescmem = resource_size(dma_res)/2; | |
1179 | priv->rxdescmem_busaddr = dma_res->start; | |
1180 | priv->rxdescmem_busaddr += priv->txdescmem; | |
1181 | ||
1182 | if (upper_32_bits(priv->rxdescmem_busaddr)) { | |
1183 | dev_dbg(priv->device, | |
1184 | "SGDMA bus addresses greater than 32-bits\n"); | |
a24a9d7a | 1185 | ret = -EINVAL; |
a7642009 | 1186 | goto err_free_netdev; |
bbd2190c VB |
1187 | } |
1188 | if (upper_32_bits(priv->txdescmem_busaddr)) { | |
1189 | dev_dbg(priv->device, | |
1190 | "SGDMA bus addresses greater than 32-bits\n"); | |
a24a9d7a | 1191 | ret = -EINVAL; |
a7642009 | 1192 | goto err_free_netdev; |
bbd2190c VB |
1193 | } |
1194 | } else if (priv->dmaops && | |
1195 | priv->dmaops->altera_dtype == ALTERA_DTYPE_MSGDMA) { | |
1196 | ret = request_and_map(pdev, "rx_resp", &dma_res, | |
1197 | &priv->rx_dma_resp); | |
1198 | if (ret) | |
a7642009 | 1199 | goto err_free_netdev; |
bbd2190c VB |
1200 | |
1201 | ret = request_and_map(pdev, "tx_desc", &dma_res, | |
1202 | &priv->tx_dma_desc); | |
1203 | if (ret) | |
a7642009 | 1204 | goto err_free_netdev; |
bbd2190c VB |
1205 | |
1206 | priv->txdescmem = resource_size(dma_res); | |
1207 | priv->txdescmem_busaddr = dma_res->start; | |
1208 | ||
1209 | ret = request_and_map(pdev, "rx_desc", &dma_res, | |
1210 | &priv->rx_dma_desc); | |
1211 | if (ret) | |
a7642009 | 1212 | goto err_free_netdev; |
bbd2190c VB |
1213 | |
1214 | priv->rxdescmem = resource_size(dma_res); | |
1215 | priv->rxdescmem_busaddr = dma_res->start; | |
1216 | ||
1217 | } else { | |
badd7857 | 1218 | ret = -ENODEV; |
a7642009 | 1219 | goto err_free_netdev; |
bbd2190c VB |
1220 | } |
1221 | ||
badd7857 | 1222 | if (!dma_set_mask(priv->device, DMA_BIT_MASK(priv->dmaops->dmamask))) { |
bbd2190c VB |
1223 | dma_set_coherent_mask(priv->device, |
1224 | DMA_BIT_MASK(priv->dmaops->dmamask)); | |
badd7857 | 1225 | } else if (!dma_set_mask(priv->device, DMA_BIT_MASK(32))) { |
bbd2190c | 1226 | dma_set_coherent_mask(priv->device, DMA_BIT_MASK(32)); |
badd7857 DC |
1227 | } else { |
1228 | ret = -EIO; | |
a7642009 | 1229 | goto err_free_netdev; |
badd7857 | 1230 | } |
bbd2190c VB |
1231 | |
1232 | /* MAC address space */ | |
1233 | ret = request_and_map(pdev, "control_port", &control_port, | |
1234 | (void __iomem **)&priv->mac_dev); | |
1235 | if (ret) | |
a7642009 | 1236 | goto err_free_netdev; |
bbd2190c VB |
1237 | |
1238 | /* xSGDMA Rx Dispatcher address space */ | |
1239 | ret = request_and_map(pdev, "rx_csr", &dma_res, | |
1240 | &priv->rx_dma_csr); | |
1241 | if (ret) | |
a7642009 | 1242 | goto err_free_netdev; |
bbd2190c VB |
1243 | |
1244 | ||
1245 | /* xSGDMA Tx Dispatcher address space */ | |
1246 | ret = request_and_map(pdev, "tx_csr", &dma_res, | |
1247 | &priv->tx_dma_csr); | |
1248 | if (ret) | |
a7642009 | 1249 | goto err_free_netdev; |
bbd2190c | 1250 | |
2d830f7a MC |
1251 | memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg)); |
1252 | memset(&mrc, 0, sizeof(mrc)); | |
fef29982 MC |
1253 | /* SGMII PCS address space. The location can vary depending on how the |
1254 | * IP is integrated. We can have a resource dedicated to it at a specific | |
1255 | * address space, but if it's not the case, we fallback to the mdiophy0 | |
1256 | * from the MAC's address space | |
1257 | */ | |
db48abba | 1258 | ret = request_and_map(pdev, "pcs", &pcs_res, &priv->pcs_base); |
fef29982 | 1259 | if (ret) { |
db48abba MC |
1260 | /* If we can't find a dedicated resource for the PCS, fallback |
1261 | * to the internal PCS, that has a different address stride | |
1262 | */ | |
fef29982 | 1263 | priv->pcs_base = priv->mac_dev + tse_csroffs(mdio_phy0); |
db48abba MC |
1264 | pcs_regmap_cfg.reg_bits = 32; |
1265 | /* Values are MDIO-like values, on 16 bits */ | |
1266 | pcs_regmap_cfg.val_bits = 16; | |
1267 | pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(2); | |
1268 | } else { | |
1269 | pcs_regmap_cfg.reg_bits = 16; | |
1270 | pcs_regmap_cfg.val_bits = 16; | |
1271 | pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1); | |
1272 | } | |
1273 | ||
1274 | /* Create a regmap for the PCS so that it can be used by the PCS driver */ | |
1275 | pcs_regmap = devm_regmap_init_mmio(&pdev->dev, priv->pcs_base, | |
1276 | &pcs_regmap_cfg); | |
1277 | if (IS_ERR(pcs_regmap)) { | |
1278 | ret = PTR_ERR(pcs_regmap); | |
1279 | goto err_free_netdev; | |
fef29982 | 1280 | } |
db48abba MC |
1281 | mrc.regmap = pcs_regmap; |
1282 | mrc.parent = &pdev->dev; | |
1283 | mrc.valid_addr = 0x0; | |
fa19a5d9 | 1284 | mrc.autoscan = false; |
bbd2190c VB |
1285 | |
1286 | /* Rx IRQ */ | |
1287 | priv->rx_irq = platform_get_irq_byname(pdev, "rx_irq"); | |
1288 | if (priv->rx_irq == -ENXIO) { | |
1289 | dev_err(&pdev->dev, "cannot obtain Rx IRQ\n"); | |
1290 | ret = -ENXIO; | |
a7642009 | 1291 | goto err_free_netdev; |
bbd2190c VB |
1292 | } |
1293 | ||
1294 | /* Tx IRQ */ | |
1295 | priv->tx_irq = platform_get_irq_byname(pdev, "tx_irq"); | |
1296 | if (priv->tx_irq == -ENXIO) { | |
1297 | dev_err(&pdev->dev, "cannot obtain Tx IRQ\n"); | |
1298 | ret = -ENXIO; | |
a7642009 | 1299 | goto err_free_netdev; |
bbd2190c VB |
1300 | } |
1301 | ||
1302 | /* get FIFO depths from device tree */ | |
1303 | if (of_property_read_u32(pdev->dev.of_node, "rx-fifo-depth", | |
1304 | &priv->rx_fifo_depth)) { | |
1305 | dev_err(&pdev->dev, "cannot obtain rx-fifo-depth\n"); | |
1306 | ret = -ENXIO; | |
a7642009 | 1307 | goto err_free_netdev; |
bbd2190c VB |
1308 | } |
1309 | ||
1310 | if (of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", | |
fe6e4081 | 1311 | &priv->tx_fifo_depth)) { |
bbd2190c VB |
1312 | dev_err(&pdev->dev, "cannot obtain tx-fifo-depth\n"); |
1313 | ret = -ENXIO; | |
a7642009 | 1314 | goto err_free_netdev; |
bbd2190c VB |
1315 | } |
1316 | ||
1317 | /* get hash filter settings for this instance */ | |
1318 | priv->hash_filter = | |
1319 | of_property_read_bool(pdev->dev.of_node, | |
1320 | "altr,has-hash-multicast-filter"); | |
1321 | ||
d91e5c02 VB |
1322 | /* Set hash filter to not set for now until the |
1323 | * multicast filter receive issue is debugged | |
1324 | */ | |
1325 | priv->hash_filter = 0; | |
1326 | ||
bbd2190c VB |
1327 | /* get supplemental address settings for this instance */ |
1328 | priv->added_unicast = | |
1329 | of_property_read_bool(pdev->dev.of_node, | |
1330 | "altr,has-supplementary-unicast"); | |
1331 | ||
44770e11 | 1332 | priv->dev->min_mtu = ETH_ZLEN + ETH_FCS_LEN; |
bbd2190c | 1333 | /* Max MTU is 1500, ETH_DATA_LEN */ |
44770e11 | 1334 | priv->dev->max_mtu = ETH_DATA_LEN; |
bbd2190c VB |
1335 | |
1336 | /* Get the max mtu from the device tree. Note that the | |
1337 | * "max-frame-size" parameter is actually max mtu. Definition | |
1338 | * in the ePAPR v1.1 spec and usage differ, so go with usage. | |
1339 | */ | |
1340 | of_property_read_u32(pdev->dev.of_node, "max-frame-size", | |
44770e11 | 1341 | &priv->dev->max_mtu); |
bbd2190c VB |
1342 | |
1343 | /* The DMA buffer size already accounts for an alignment bias | |
1344 | * to avoid unaligned access exceptions for the NIOS processor, | |
1345 | */ | |
1346 | priv->rx_dma_buf_sz = ALTERA_RXDMABUFFER_SIZE; | |
1347 | ||
1348 | /* get default MAC address from device tree */ | |
9ca01b25 | 1349 | ret = of_get_ethdev_address(pdev->dev.of_node, ndev); |
83216e39 | 1350 | if (ret) |
bbd2190c VB |
1351 | eth_hw_addr_random(ndev); |
1352 | ||
004fa118 WL |
1353 | /* get phy addr and create mdio */ |
1354 | ret = altera_tse_phy_get_addr_mdio_create(ndev); | |
bbd2190c VB |
1355 | |
1356 | if (ret) | |
a7642009 | 1357 | goto err_free_netdev; |
bbd2190c VB |
1358 | |
1359 | /* initialize netdev */ | |
bbd2190c VB |
1360 | ndev->mem_start = control_port->start; |
1361 | ndev->mem_end = control_port->end; | |
1362 | ndev->netdev_ops = &altera_tse_netdev_ops; | |
1363 | altera_tse_set_ethtool_ops(ndev); | |
1364 | ||
1365 | altera_tse_netdev_ops.ndo_set_rx_mode = tse_set_rx_mode; | |
1366 | ||
1367 | if (priv->hash_filter) | |
1368 | altera_tse_netdev_ops.ndo_set_rx_mode = | |
1369 | tse_set_rx_mode_hashfilter; | |
1370 | ||
1371 | /* Scatter/gather IO is not supported, | |
1372 | * so it is turned off | |
1373 | */ | |
1374 | ndev->hw_features &= ~NETIF_F_SG; | |
1375 | ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; | |
1376 | ||
1377 | /* VLAN offloading of tagging, stripping and filtering is not | |
1378 | * supported by hardware, but driver will accommodate the | |
1379 | * extra 4-byte VLAN tag for processing by upper layers | |
1380 | */ | |
1381 | ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; | |
1382 | ||
1383 | /* setup NAPI interface */ | |
b48b89f9 | 1384 | netif_napi_add(ndev, &priv->napi, tse_poll); |
bbd2190c VB |
1385 | |
1386 | spin_lock_init(&priv->mac_cfg_lock); | |
1387 | spin_lock_init(&priv->tx_lock); | |
1388 | spin_lock_init(&priv->rxdma_irq_lock); | |
1389 | ||
d43cefcd | 1390 | netif_carrier_off(ndev); |
bbd2190c VB |
1391 | ret = register_netdev(ndev); |
1392 | if (ret) { | |
1393 | dev_err(&pdev->dev, "failed to register TSE net device\n"); | |
a7642009 | 1394 | goto err_register_netdev; |
bbd2190c VB |
1395 | } |
1396 | ||
1397 | platform_set_drvdata(pdev, ndev); | |
1398 | ||
1399 | priv->revision = ioread32(&priv->mac_dev->megacore_revision); | |
1400 | ||
1401 | if (netif_msg_probe(priv)) | |
1402 | dev_info(&pdev->dev, "Altera TSE MAC version %d.%d at 0x%08lx irq %d/%d\n", | |
1403 | (priv->revision >> 8) & 0xff, | |
1404 | priv->revision & 0xff, | |
1405 | (unsigned long) control_port->start, priv->rx_irq, | |
1406 | priv->tx_irq); | |
1407 | ||
db48abba MC |
1408 | snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name); |
1409 | pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc); | |
1410 | if (IS_ERR(pcs_bus)) { | |
1411 | ret = PTR_ERR(pcs_bus); | |
1412 | goto err_init_pcs; | |
1413 | } | |
1414 | ||
1415 | priv->pcs = lynx_pcs_create_mdiodev(pcs_bus, 0); | |
1416 | if (IS_ERR(priv->pcs)) { | |
1417 | ret = PTR_ERR(priv->pcs); | |
1418 | goto err_init_pcs; | |
1419 | } | |
fef29982 MC |
1420 | |
1421 | priv->phylink_config.dev = &ndev->dev; | |
1422 | priv->phylink_config.type = PHYLINK_NETDEV; | |
1423 | priv->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | | |
1424 | MAC_100 | MAC_1000FD; | |
1425 | ||
1426 | phy_interface_set_rgmii(priv->phylink_config.supported_interfaces); | |
1427 | __set_bit(PHY_INTERFACE_MODE_MII, | |
1428 | priv->phylink_config.supported_interfaces); | |
1429 | __set_bit(PHY_INTERFACE_MODE_GMII, | |
1430 | priv->phylink_config.supported_interfaces); | |
1431 | __set_bit(PHY_INTERFACE_MODE_SGMII, | |
1432 | priv->phylink_config.supported_interfaces); | |
1433 | __set_bit(PHY_INTERFACE_MODE_1000BASEX, | |
1434 | priv->phylink_config.supported_interfaces); | |
1435 | ||
1436 | priv->phylink = phylink_create(&priv->phylink_config, | |
1437 | of_fwnode_handle(priv->device->of_node), | |
1438 | priv->phy_iface, &alt_tse_phylink_ops); | |
1439 | if (IS_ERR(priv->phylink)) { | |
1440 | dev_err(&pdev->dev, "failed to create phylink\n"); | |
9b17dbd9 | 1441 | ret = PTR_ERR(priv->phylink); |
db48abba | 1442 | goto err_init_phylink; |
bbd2190c | 1443 | } |
fef29982 | 1444 | |
bbd2190c | 1445 | return 0; |
db48abba MC |
1446 | err_init_phylink: |
1447 | lynx_pcs_destroy(priv->pcs); | |
1448 | err_init_pcs: | |
a7642009 VB |
1449 | unregister_netdev(ndev); |
1450 | err_register_netdev: | |
1451 | netif_napi_del(&priv->napi); | |
bbd2190c | 1452 | altera_tse_mdio_destroy(ndev); |
a7642009 | 1453 | err_free_netdev: |
bbd2190c VB |
1454 | free_netdev(ndev); |
1455 | return ret; | |
1456 | } | |
1457 | ||
1458 | /* Remove Altera TSE MAC device | |
1459 | */ | |
d0b0245b | 1460 | static void altera_tse_remove(struct platform_device *pdev) |
bbd2190c VB |
1461 | { |
1462 | struct net_device *ndev = platform_get_drvdata(pdev); | |
5a89394a | 1463 | struct altera_tse_private *priv = netdev_priv(ndev); |
c484994e | 1464 | |
bbd2190c VB |
1465 | platform_set_drvdata(pdev, NULL); |
1466 | altera_tse_mdio_destroy(ndev); | |
1467 | unregister_netdev(ndev); | |
fef29982 | 1468 | phylink_destroy(priv->phylink); |
db48abba MC |
1469 | lynx_pcs_destroy(priv->pcs); |
1470 | ||
bbd2190c | 1471 | free_netdev(ndev); |
bbd2190c VB |
1472 | } |
1473 | ||
89830580 | 1474 | static const struct altera_dmaops altera_dtype_sgdma = { |
bbd2190c VB |
1475 | .altera_dtype = ALTERA_DTYPE_SGDMA, |
1476 | .dmamask = 32, | |
1477 | .reset_dma = sgdma_reset, | |
1478 | .enable_txirq = sgdma_enable_txirq, | |
1479 | .enable_rxirq = sgdma_enable_rxirq, | |
1480 | .disable_txirq = sgdma_disable_txirq, | |
1481 | .disable_rxirq = sgdma_disable_rxirq, | |
1482 | .clear_txirq = sgdma_clear_txirq, | |
1483 | .clear_rxirq = sgdma_clear_rxirq, | |
1484 | .tx_buffer = sgdma_tx_buffer, | |
1485 | .tx_completions = sgdma_tx_completions, | |
1486 | .add_rx_desc = sgdma_add_rx_desc, | |
1487 | .get_rx_status = sgdma_rx_status, | |
1488 | .init_dma = sgdma_initialize, | |
1489 | .uninit_dma = sgdma_uninitialize, | |
37c0ffaa | 1490 | .start_rxdma = sgdma_start_rxdma, |
bbd2190c VB |
1491 | }; |
1492 | ||
89830580 | 1493 | static const struct altera_dmaops altera_dtype_msgdma = { |
bbd2190c VB |
1494 | .altera_dtype = ALTERA_DTYPE_MSGDMA, |
1495 | .dmamask = 64, | |
1496 | .reset_dma = msgdma_reset, | |
1497 | .enable_txirq = msgdma_enable_txirq, | |
1498 | .enable_rxirq = msgdma_enable_rxirq, | |
1499 | .disable_txirq = msgdma_disable_txirq, | |
1500 | .disable_rxirq = msgdma_disable_rxirq, | |
1501 | .clear_txirq = msgdma_clear_txirq, | |
1502 | .clear_rxirq = msgdma_clear_rxirq, | |
1503 | .tx_buffer = msgdma_tx_buffer, | |
1504 | .tx_completions = msgdma_tx_completions, | |
1505 | .add_rx_desc = msgdma_add_rx_desc, | |
1506 | .get_rx_status = msgdma_rx_status, | |
1507 | .init_dma = msgdma_initialize, | |
1508 | .uninit_dma = msgdma_uninitialize, | |
37c0ffaa | 1509 | .start_rxdma = msgdma_start_rxdma, |
bbd2190c VB |
1510 | }; |
1511 | ||
27260530 | 1512 | static const struct of_device_id altera_tse_ids[] = { |
bbd2190c VB |
1513 | { .compatible = "altr,tse-msgdma-1.0", .data = &altera_dtype_msgdma, }, |
1514 | { .compatible = "altr,tse-1.0", .data = &altera_dtype_sgdma, }, | |
1515 | { .compatible = "ALTR,tse-1.0", .data = &altera_dtype_sgdma, }, | |
1516 | {}, | |
1517 | }; | |
1518 | MODULE_DEVICE_TABLE(of, altera_tse_ids); | |
1519 | ||
1520 | static struct platform_driver altera_tse_driver = { | |
1521 | .probe = altera_tse_probe, | |
d0b0245b | 1522 | .remove_new = altera_tse_remove, |
bbd2190c VB |
1523 | .suspend = NULL, |
1524 | .resume = NULL, | |
1525 | .driver = { | |
1526 | .name = ALTERA_TSE_RESOURCE_NAME, | |
bbd2190c VB |
1527 | .of_match_table = altera_tse_ids, |
1528 | }, | |
1529 | }; | |
1530 | ||
1531 | module_platform_driver(altera_tse_driver); | |
1532 | ||
1533 | MODULE_AUTHOR("Altera Corporation"); | |
1534 | MODULE_DESCRIPTION("Altera Triple Speed Ethernet MAC driver"); | |
1535 | MODULE_LICENSE("GPL v2"); |