blob: 6625012d734e7e1e4e7dc657028943d1890e877f [file] [log] [blame]
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001/*
2 * Faraday FTGMAC100 Gigabit Ethernet
3 *
4 * (C) Copyright 2009-2011 Faraday Technology
5 * Po-Yu Chuang <ratbert@faraday-tech.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24#include <linux/dma-mapping.h>
25#include <linux/etherdevice.h>
26#include <linux/ethtool.h>
Thomas Faber17f1bbc2012-01-18 13:45:44 +000027#include <linux/interrupt.h>
Po-Yu Chuang69785b72011-06-08 23:32:48 +000028#include <linux/io.h>
29#include <linux/module.h>
30#include <linux/netdevice.h>
Mark Brown3af887c2017-03-30 17:00:12 +010031#include <linux/of.h>
Po-Yu Chuang69785b72011-06-08 23:32:48 +000032#include <linux/phy.h>
33#include <linux/platform_device.h>
Mark Brown3af887c2017-03-30 17:00:12 +010034#include <linux/property.h>
Po-Yu Chuang69785b72011-06-08 23:32:48 +000035#include <net/ip.h>
Gavin Shanbd466c32016-07-19 11:54:23 +100036#include <net/ncsi.h>
Po-Yu Chuang69785b72011-06-08 23:32:48 +000037
38#include "ftgmac100.h"
39
40#define DRV_NAME "ftgmac100"
41#define DRV_VERSION "0.7"
42
43#define RX_QUEUE_ENTRIES 256 /* must be power of 2 */
44#define TX_QUEUE_ENTRIES 512 /* must be power of 2 */
45
46#define MAX_PKT_SIZE 1518
47#define RX_BUF_SIZE PAGE_SIZE /* must be smaller than 0x3fff */
48
Po-Yu Chuang69785b72011-06-08 23:32:48 +000049struct ftgmac100_descs {
50 struct ftgmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
51 struct ftgmac100_txdes txdes[TX_QUEUE_ENTRIES];
52};
53
54struct ftgmac100 {
Benjamin Herrenschmidt831fb332017-04-05 12:28:43 +100055 /* Registers */
Po-Yu Chuang69785b72011-06-08 23:32:48 +000056 struct resource *res;
57 void __iomem *base;
Po-Yu Chuang69785b72011-06-08 23:32:48 +000058
59 struct ftgmac100_descs *descs;
60 dma_addr_t descs_dma_addr;
61
Benjamin Herrenschmidt831fb332017-04-05 12:28:43 +100062 /* Rx ring */
Andrew Jefferyada66b52016-09-22 08:34:58 +093063 struct page *rx_pages[RX_QUEUE_ENTRIES];
Po-Yu Chuang69785b72011-06-08 23:32:48 +000064 unsigned int rx_pointer;
Benjamin Herrenschmidt831fb332017-04-05 12:28:43 +100065 u32 rxdes0_edorr_mask;
66
67 /* Tx ring */
Po-Yu Chuang69785b72011-06-08 23:32:48 +000068 unsigned int tx_clean_pointer;
69 unsigned int tx_pointer;
70 unsigned int tx_pending;
Benjamin Herrenschmidt831fb332017-04-05 12:28:43 +100071 u32 txdes0_edotr_mask;
Po-Yu Chuang69785b72011-06-08 23:32:48 +000072 spinlock_t tx_lock;
73
Benjamin Herrenschmidt831fb332017-04-05 12:28:43 +100074 /* Component structures */
Po-Yu Chuang69785b72011-06-08 23:32:48 +000075 struct net_device *netdev;
76 struct device *dev;
Gavin Shanbd466c32016-07-19 11:54:23 +100077 struct ncsi_dev *ndev;
Po-Yu Chuang69785b72011-06-08 23:32:48 +000078 struct napi_struct napi;
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +100079 struct work_struct reset_task;
Po-Yu Chuang69785b72011-06-08 23:32:48 +000080 struct mii_bus *mii_bus;
Andrew Jeffery7906a4d2016-09-22 08:34:59 +093081
Benjamin Herrenschmidt831fb332017-04-05 12:28:43 +100082 /* Link management */
Benjamin Herrenschmidt51764772017-04-05 12:28:45 +100083 int cur_speed;
84 int cur_duplex;
Benjamin Herrenschmidt831fb332017-04-05 12:28:43 +100085 bool use_ncsi;
86
87 /* Misc */
88 int int_mask_all;
Po-Yu Chuang69785b72011-06-08 23:32:48 +000089};
90
91static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv,
92 struct ftgmac100_rxdes *rxdes, gfp_t gfp);
93
Po-Yu Chuang69785b72011-06-08 23:32:48 +000094static void ftgmac100_set_rx_ring_base(struct ftgmac100 *priv, dma_addr_t addr)
95{
96 iowrite32(addr, priv->base + FTGMAC100_OFFSET_RXR_BADR);
97}
98
99static void ftgmac100_set_rx_buffer_size(struct ftgmac100 *priv,
100 unsigned int size)
101{
102 size = FTGMAC100_RBSR_SIZE(size);
103 iowrite32(size, priv->base + FTGMAC100_OFFSET_RBSR);
104}
105
106static void ftgmac100_set_normal_prio_tx_ring_base(struct ftgmac100 *priv,
107 dma_addr_t addr)
108{
109 iowrite32(addr, priv->base + FTGMAC100_OFFSET_NPTXR_BADR);
110}
111
112static void ftgmac100_txdma_normal_prio_start_polling(struct ftgmac100 *priv)
113{
114 iowrite32(1, priv->base + FTGMAC100_OFFSET_NPTXPD);
115}
116
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000117static int ftgmac100_reset_mac(struct ftgmac100 *priv, u32 maccr)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000118{
119 struct net_device *netdev = priv->netdev;
120 int i;
121
122 /* NOTE: reset clears all registers */
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000123 iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR);
124 iowrite32(maccr | FTGMAC100_MACCR_SW_RST,
125 priv->base + FTGMAC100_OFFSET_MACCR);
126 for (i = 0; i < 50; i++) {
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000127 unsigned int maccr;
128
129 maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR);
130 if (!(maccr & FTGMAC100_MACCR_SW_RST))
131 return 0;
132
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000133 udelay(1);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000134 }
135
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000136 netdev_err(netdev, "Hardware reset failed\n");
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000137 return -EIO;
138}
139
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000140static int ftgmac100_reset_and_config_mac(struct ftgmac100 *priv)
141{
142 u32 maccr = 0;
143
144 switch (priv->cur_speed) {
145 case SPEED_10:
146 case 0: /* no link */
147 break;
148
149 case SPEED_100:
150 maccr |= FTGMAC100_MACCR_FAST_MODE;
151 break;
152
153 case SPEED_1000:
154 maccr |= FTGMAC100_MACCR_GIGA_MODE;
155 break;
156 default:
157 netdev_err(priv->netdev, "Unknown speed %d !\n",
158 priv->cur_speed);
159 break;
160 }
161
162 /* (Re)initialize the queue pointers */
163 priv->rx_pointer = 0;
164 priv->tx_clean_pointer = 0;
165 priv->tx_pointer = 0;
166 priv->tx_pending = 0;
167
168 /* The doc says reset twice with 10us interval */
169 if (ftgmac100_reset_mac(priv, maccr))
170 return -EIO;
171 usleep_range(10, 1000);
172 return ftgmac100_reset_mac(priv, maccr);
173}
174
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000175static void ftgmac100_set_mac(struct ftgmac100 *priv, const unsigned char *mac)
176{
177 unsigned int maddr = mac[0] << 8 | mac[1];
178 unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
179
180 iowrite32(maddr, priv->base + FTGMAC100_OFFSET_MAC_MADR);
181 iowrite32(laddr, priv->base + FTGMAC100_OFFSET_MAC_LADR);
182}
183
Gavin Shan113ce102016-07-19 11:54:22 +1000184static void ftgmac100_setup_mac(struct ftgmac100 *priv)
185{
186 u8 mac[ETH_ALEN];
187 unsigned int m;
188 unsigned int l;
189 void *addr;
190
191 addr = device_get_mac_address(priv->dev, mac, ETH_ALEN);
192 if (addr) {
193 ether_addr_copy(priv->netdev->dev_addr, mac);
194 dev_info(priv->dev, "Read MAC address %pM from device tree\n",
195 mac);
196 return;
197 }
198
199 m = ioread32(priv->base + FTGMAC100_OFFSET_MAC_MADR);
200 l = ioread32(priv->base + FTGMAC100_OFFSET_MAC_LADR);
201
202 mac[0] = (m >> 8) & 0xff;
203 mac[1] = m & 0xff;
204 mac[2] = (l >> 24) & 0xff;
205 mac[3] = (l >> 16) & 0xff;
206 mac[4] = (l >> 8) & 0xff;
207 mac[5] = l & 0xff;
208
Gavin Shan113ce102016-07-19 11:54:22 +1000209 if (is_valid_ether_addr(mac)) {
210 ether_addr_copy(priv->netdev->dev_addr, mac);
211 dev_info(priv->dev, "Read MAC address %pM from chip\n", mac);
212 } else {
213 eth_hw_addr_random(priv->netdev);
214 dev_info(priv->dev, "Generated random MAC address %pM\n",
215 priv->netdev->dev_addr);
216 }
217}
218
219static int ftgmac100_set_mac_addr(struct net_device *dev, void *p)
220{
221 int ret;
222
223 ret = eth_prepare_mac_addr_change(dev, p);
224 if (ret < 0)
225 return ret;
226
227 eth_commit_mac_addr_change(dev, p);
228 ftgmac100_set_mac(netdev_priv(dev), dev->dev_addr);
229
230 return 0;
231}
232
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000233static void ftgmac100_init_hw(struct ftgmac100 *priv)
234{
235 /* setup ring buffer base registers */
236 ftgmac100_set_rx_ring_base(priv,
237 priv->descs_dma_addr +
238 offsetof(struct ftgmac100_descs, rxdes));
239 ftgmac100_set_normal_prio_tx_ring_base(priv,
240 priv->descs_dma_addr +
241 offsetof(struct ftgmac100_descs, txdes));
242
243 ftgmac100_set_rx_buffer_size(priv, RX_BUF_SIZE);
244
245 iowrite32(FTGMAC100_APTC_RXPOLL_CNT(1), priv->base + FTGMAC100_OFFSET_APTC);
246
247 ftgmac100_set_mac(priv, priv->netdev->dev_addr);
248}
249
Benjamin Herrenschmidt51764772017-04-05 12:28:45 +1000250static void ftgmac100_start_hw(struct ftgmac100 *priv)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000251{
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000252 u32 maccr = ioread32(priv->base + FTGMAC100_OFFSET_MACCR);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000253
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000254 /* Keep the original GMAC and FAST bits */
255 maccr &= (FTGMAC100_MACCR_FAST_MODE | FTGMAC100_MACCR_GIGA_MODE);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000256
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000257 /* Add all the main enable bits */
258 maccr |= FTGMAC100_MACCR_TXDMA_EN |
259 FTGMAC100_MACCR_RXDMA_EN |
260 FTGMAC100_MACCR_TXMAC_EN |
261 FTGMAC100_MACCR_RXMAC_EN |
262 FTGMAC100_MACCR_CRC_APD |
263 FTGMAC100_MACCR_PHY_LINK_LEVEL |
264 FTGMAC100_MACCR_RX_RUNT |
265 FTGMAC100_MACCR_RX_BROADPKT;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000266
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000267 /* Add other bits as needed */
Benjamin Herrenschmidt51764772017-04-05 12:28:45 +1000268 if (priv->cur_duplex == DUPLEX_FULL)
269 maccr |= FTGMAC100_MACCR_FULLDUP;
270
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +1000271 /* Hit the HW */
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000272 iowrite32(maccr, priv->base + FTGMAC100_OFFSET_MACCR);
273}
274
275static void ftgmac100_stop_hw(struct ftgmac100 *priv)
276{
277 iowrite32(0, priv->base + FTGMAC100_OFFSET_MACCR);
278}
279
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000280static bool ftgmac100_rxdes_first_segment(struct ftgmac100_rxdes *rxdes)
281{
282 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_FRS);
283}
284
285static bool ftgmac100_rxdes_last_segment(struct ftgmac100_rxdes *rxdes)
286{
287 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_LRS);
288}
289
290static bool ftgmac100_rxdes_packet_ready(struct ftgmac100_rxdes *rxdes)
291{
292 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RXPKT_RDY);
293}
294
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930295static void ftgmac100_rxdes_set_dma_own(const struct ftgmac100 *priv,
296 struct ftgmac100_rxdes *rxdes)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000297{
298 /* clear status bits */
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930299 rxdes->rxdes0 &= cpu_to_le32(priv->rxdes0_edorr_mask);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000300}
301
302static bool ftgmac100_rxdes_rx_error(struct ftgmac100_rxdes *rxdes)
303{
304 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RX_ERR);
305}
306
307static bool ftgmac100_rxdes_crc_error(struct ftgmac100_rxdes *rxdes)
308{
309 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_CRC_ERR);
310}
311
312static bool ftgmac100_rxdes_frame_too_long(struct ftgmac100_rxdes *rxdes)
313{
314 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_FTL);
315}
316
317static bool ftgmac100_rxdes_runt(struct ftgmac100_rxdes *rxdes)
318{
319 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RUNT);
320}
321
322static bool ftgmac100_rxdes_odd_nibble(struct ftgmac100_rxdes *rxdes)
323{
324 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_RX_ODD_NB);
325}
326
327static unsigned int ftgmac100_rxdes_data_length(struct ftgmac100_rxdes *rxdes)
328{
329 return le32_to_cpu(rxdes->rxdes0) & FTGMAC100_RXDES0_VDBC;
330}
331
332static bool ftgmac100_rxdes_multicast(struct ftgmac100_rxdes *rxdes)
333{
334 return rxdes->rxdes0 & cpu_to_le32(FTGMAC100_RXDES0_MULTICAST);
335}
336
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930337static void ftgmac100_rxdes_set_end_of_ring(const struct ftgmac100 *priv,
338 struct ftgmac100_rxdes *rxdes)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000339{
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930340 rxdes->rxdes0 |= cpu_to_le32(priv->rxdes0_edorr_mask);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000341}
342
343static void ftgmac100_rxdes_set_dma_addr(struct ftgmac100_rxdes *rxdes,
344 dma_addr_t addr)
345{
346 rxdes->rxdes3 = cpu_to_le32(addr);
347}
348
349static dma_addr_t ftgmac100_rxdes_get_dma_addr(struct ftgmac100_rxdes *rxdes)
350{
351 return le32_to_cpu(rxdes->rxdes3);
352}
353
354static bool ftgmac100_rxdes_is_tcp(struct ftgmac100_rxdes *rxdes)
355{
356 return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) ==
357 cpu_to_le32(FTGMAC100_RXDES1_PROT_TCPIP);
358}
359
360static bool ftgmac100_rxdes_is_udp(struct ftgmac100_rxdes *rxdes)
361{
362 return (rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_PROT_MASK)) ==
363 cpu_to_le32(FTGMAC100_RXDES1_PROT_UDPIP);
364}
365
366static bool ftgmac100_rxdes_tcpcs_err(struct ftgmac100_rxdes *rxdes)
367{
368 return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_TCP_CHKSUM_ERR);
369}
370
371static bool ftgmac100_rxdes_udpcs_err(struct ftgmac100_rxdes *rxdes)
372{
373 return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_UDP_CHKSUM_ERR);
374}
375
376static bool ftgmac100_rxdes_ipcs_err(struct ftgmac100_rxdes *rxdes)
377{
378 return rxdes->rxdes1 & cpu_to_le32(FTGMAC100_RXDES1_IP_CHKSUM_ERR);
379}
380
Andrew Jefferyada66b52016-09-22 08:34:58 +0930381static inline struct page **ftgmac100_rxdes_page_slot(struct ftgmac100 *priv,
382 struct ftgmac100_rxdes *rxdes)
383{
384 return &priv->rx_pages[rxdes - priv->descs->rxdes];
385}
386
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000387/*
388 * rxdes2 is not used by hardware. We use it to keep track of page.
389 * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
390 */
Andrew Jefferyada66b52016-09-22 08:34:58 +0930391static void ftgmac100_rxdes_set_page(struct ftgmac100 *priv,
392 struct ftgmac100_rxdes *rxdes,
393 struct page *page)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000394{
Andrew Jefferyada66b52016-09-22 08:34:58 +0930395 *ftgmac100_rxdes_page_slot(priv, rxdes) = page;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000396}
397
Andrew Jefferyada66b52016-09-22 08:34:58 +0930398static struct page *ftgmac100_rxdes_get_page(struct ftgmac100 *priv,
399 struct ftgmac100_rxdes *rxdes)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000400{
Andrew Jefferyada66b52016-09-22 08:34:58 +0930401 return *ftgmac100_rxdes_page_slot(priv, rxdes);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000402}
403
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000404static int ftgmac100_next_rx_pointer(int pointer)
405{
406 return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
407}
408
409static void ftgmac100_rx_pointer_advance(struct ftgmac100 *priv)
410{
411 priv->rx_pointer = ftgmac100_next_rx_pointer(priv->rx_pointer);
412}
413
414static struct ftgmac100_rxdes *ftgmac100_current_rxdes(struct ftgmac100 *priv)
415{
416 return &priv->descs->rxdes[priv->rx_pointer];
417}
418
419static struct ftgmac100_rxdes *
420ftgmac100_rx_locate_first_segment(struct ftgmac100 *priv)
421{
422 struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
423
424 while (ftgmac100_rxdes_packet_ready(rxdes)) {
425 if (ftgmac100_rxdes_first_segment(rxdes))
426 return rxdes;
427
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930428 ftgmac100_rxdes_set_dma_own(priv, rxdes);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000429 ftgmac100_rx_pointer_advance(priv);
430 rxdes = ftgmac100_current_rxdes(priv);
431 }
432
433 return NULL;
434}
435
436static bool ftgmac100_rx_packet_error(struct ftgmac100 *priv,
437 struct ftgmac100_rxdes *rxdes)
438{
439 struct net_device *netdev = priv->netdev;
440 bool error = false;
441
442 if (unlikely(ftgmac100_rxdes_rx_error(rxdes))) {
443 if (net_ratelimit())
444 netdev_info(netdev, "rx err\n");
445
446 netdev->stats.rx_errors++;
447 error = true;
448 }
449
450 if (unlikely(ftgmac100_rxdes_crc_error(rxdes))) {
451 if (net_ratelimit())
452 netdev_info(netdev, "rx crc err\n");
453
454 netdev->stats.rx_crc_errors++;
455 error = true;
456 } else if (unlikely(ftgmac100_rxdes_ipcs_err(rxdes))) {
457 if (net_ratelimit())
458 netdev_info(netdev, "rx IP checksum err\n");
459
460 error = true;
461 }
462
463 if (unlikely(ftgmac100_rxdes_frame_too_long(rxdes))) {
464 if (net_ratelimit())
465 netdev_info(netdev, "rx frame too long\n");
466
467 netdev->stats.rx_length_errors++;
468 error = true;
469 } else if (unlikely(ftgmac100_rxdes_runt(rxdes))) {
470 if (net_ratelimit())
471 netdev_info(netdev, "rx runt\n");
472
473 netdev->stats.rx_length_errors++;
474 error = true;
475 } else if (unlikely(ftgmac100_rxdes_odd_nibble(rxdes))) {
476 if (net_ratelimit())
477 netdev_info(netdev, "rx odd nibble\n");
478
479 netdev->stats.rx_length_errors++;
480 error = true;
481 }
482
483 return error;
484}
485
486static void ftgmac100_rx_drop_packet(struct ftgmac100 *priv)
487{
488 struct net_device *netdev = priv->netdev;
489 struct ftgmac100_rxdes *rxdes = ftgmac100_current_rxdes(priv);
490 bool done = false;
491
492 if (net_ratelimit())
493 netdev_dbg(netdev, "drop packet %p\n", rxdes);
494
495 do {
496 if (ftgmac100_rxdes_last_segment(rxdes))
497 done = true;
498
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930499 ftgmac100_rxdes_set_dma_own(priv, rxdes);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000500 ftgmac100_rx_pointer_advance(priv);
501 rxdes = ftgmac100_current_rxdes(priv);
502 } while (!done && ftgmac100_rxdes_packet_ready(rxdes));
503
504 netdev->stats.rx_dropped++;
505}
506
507static bool ftgmac100_rx_packet(struct ftgmac100 *priv, int *processed)
508{
509 struct net_device *netdev = priv->netdev;
510 struct ftgmac100_rxdes *rxdes;
511 struct sk_buff *skb;
512 bool done = false;
513
514 rxdes = ftgmac100_rx_locate_first_segment(priv);
515 if (!rxdes)
516 return false;
517
518 if (unlikely(ftgmac100_rx_packet_error(priv, rxdes))) {
519 ftgmac100_rx_drop_packet(priv);
520 return true;
521 }
522
523 /* start processing */
524 skb = netdev_alloc_skb_ip_align(netdev, 128);
525 if (unlikely(!skb)) {
526 if (net_ratelimit())
527 netdev_err(netdev, "rx skb alloc failed\n");
528
529 ftgmac100_rx_drop_packet(priv);
530 return true;
531 }
532
533 if (unlikely(ftgmac100_rxdes_multicast(rxdes)))
534 netdev->stats.multicast++;
535
536 /*
537 * It seems that HW does checksum incorrectly with fragmented packets,
538 * so we are conservative here - if HW checksum error, let software do
539 * the checksum again.
540 */
541 if ((ftgmac100_rxdes_is_tcp(rxdes) && !ftgmac100_rxdes_tcpcs_err(rxdes)) ||
542 (ftgmac100_rxdes_is_udp(rxdes) && !ftgmac100_rxdes_udpcs_err(rxdes)))
543 skb->ip_summed = CHECKSUM_UNNECESSARY;
544
545 do {
546 dma_addr_t map = ftgmac100_rxdes_get_dma_addr(rxdes);
Andrew Jefferyada66b52016-09-22 08:34:58 +0930547 struct page *page = ftgmac100_rxdes_get_page(priv, rxdes);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000548 unsigned int size;
549
550 dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
551
552 size = ftgmac100_rxdes_data_length(rxdes);
553 skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page, 0, size);
554
555 skb->len += size;
556 skb->data_len += size;
Eric Dumazet5935f812011-10-13 11:30:52 +0000557 skb->truesize += PAGE_SIZE;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000558
559 if (ftgmac100_rxdes_last_segment(rxdes))
560 done = true;
561
562 ftgmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
563
564 ftgmac100_rx_pointer_advance(priv);
565 rxdes = ftgmac100_current_rxdes(priv);
566 } while (!done);
567
Eric Dumazet6ecd09d2012-07-12 04:19:38 +0000568 /* Small frames are copied into linear part of skb to free one page */
569 if (skb->len <= 128) {
Eric Dumazet5935f812011-10-13 11:30:52 +0000570 skb->truesize -= PAGE_SIZE;
Eric Dumazet6ecd09d2012-07-12 04:19:38 +0000571 __pskb_pull_tail(skb, skb->len);
572 } else {
573 /* We pull the minimum amount into linear part */
574 __pskb_pull_tail(skb, ETH_HLEN);
575 }
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000576 skb->protocol = eth_type_trans(skb, netdev);
577
578 netdev->stats.rx_packets++;
579 netdev->stats.rx_bytes += skb->len;
580
581 /* push packet to protocol stack */
582 napi_gro_receive(&priv->napi, skb);
583
584 (*processed)++;
585 return true;
586}
587
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930588static void ftgmac100_txdes_reset(const struct ftgmac100 *priv,
589 struct ftgmac100_txdes *txdes)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000590{
591 /* clear all except end of ring bit */
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930592 txdes->txdes0 &= cpu_to_le32(priv->txdes0_edotr_mask);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000593 txdes->txdes1 = 0;
594 txdes->txdes2 = 0;
595 txdes->txdes3 = 0;
596}
597
598static bool ftgmac100_txdes_owned_by_dma(struct ftgmac100_txdes *txdes)
599{
600 return txdes->txdes0 & cpu_to_le32(FTGMAC100_TXDES0_TXDMA_OWN);
601}
602
603static void ftgmac100_txdes_set_dma_own(struct ftgmac100_txdes *txdes)
604{
605 /*
606 * Make sure dma own bit will not be set before any other
607 * descriptor fields.
608 */
609 wmb();
610 txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXDMA_OWN);
611}
612
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930613static void ftgmac100_txdes_set_end_of_ring(const struct ftgmac100 *priv,
614 struct ftgmac100_txdes *txdes)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000615{
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930616 txdes->txdes0 |= cpu_to_le32(priv->txdes0_edotr_mask);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000617}
618
619static void ftgmac100_txdes_set_first_segment(struct ftgmac100_txdes *txdes)
620{
621 txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_FTS);
622}
623
624static void ftgmac100_txdes_set_last_segment(struct ftgmac100_txdes *txdes)
625{
626 txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_LTS);
627}
628
629static void ftgmac100_txdes_set_buffer_size(struct ftgmac100_txdes *txdes,
630 unsigned int len)
631{
632 txdes->txdes0 |= cpu_to_le32(FTGMAC100_TXDES0_TXBUF_SIZE(len));
633}
634
635static void ftgmac100_txdes_set_txint(struct ftgmac100_txdes *txdes)
636{
637 txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TXIC);
638}
639
640static void ftgmac100_txdes_set_tcpcs(struct ftgmac100_txdes *txdes)
641{
642 txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_TCP_CHKSUM);
643}
644
645static void ftgmac100_txdes_set_udpcs(struct ftgmac100_txdes *txdes)
646{
647 txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_UDP_CHKSUM);
648}
649
650static void ftgmac100_txdes_set_ipcs(struct ftgmac100_txdes *txdes)
651{
652 txdes->txdes1 |= cpu_to_le32(FTGMAC100_TXDES1_IP_CHKSUM);
653}
654
655static void ftgmac100_txdes_set_dma_addr(struct ftgmac100_txdes *txdes,
656 dma_addr_t addr)
657{
658 txdes->txdes3 = cpu_to_le32(addr);
659}
660
661static dma_addr_t ftgmac100_txdes_get_dma_addr(struct ftgmac100_txdes *txdes)
662{
663 return le32_to_cpu(txdes->txdes3);
664}
665
666/*
667 * txdes2 is not used by hardware. We use it to keep track of socket buffer.
668 * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
669 */
670static void ftgmac100_txdes_set_skb(struct ftgmac100_txdes *txdes,
671 struct sk_buff *skb)
672{
673 txdes->txdes2 = (unsigned int)skb;
674}
675
676static struct sk_buff *ftgmac100_txdes_get_skb(struct ftgmac100_txdes *txdes)
677{
678 return (struct sk_buff *)txdes->txdes2;
679}
680
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000681static int ftgmac100_next_tx_pointer(int pointer)
682{
683 return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
684}
685
686static void ftgmac100_tx_pointer_advance(struct ftgmac100 *priv)
687{
688 priv->tx_pointer = ftgmac100_next_tx_pointer(priv->tx_pointer);
689}
690
691static void ftgmac100_tx_clean_pointer_advance(struct ftgmac100 *priv)
692{
693 priv->tx_clean_pointer = ftgmac100_next_tx_pointer(priv->tx_clean_pointer);
694}
695
696static struct ftgmac100_txdes *ftgmac100_current_txdes(struct ftgmac100 *priv)
697{
698 return &priv->descs->txdes[priv->tx_pointer];
699}
700
701static struct ftgmac100_txdes *
702ftgmac100_current_clean_txdes(struct ftgmac100 *priv)
703{
704 return &priv->descs->txdes[priv->tx_clean_pointer];
705}
706
707static bool ftgmac100_tx_complete_packet(struct ftgmac100 *priv)
708{
709 struct net_device *netdev = priv->netdev;
710 struct ftgmac100_txdes *txdes;
711 struct sk_buff *skb;
712 dma_addr_t map;
713
714 if (priv->tx_pending == 0)
715 return false;
716
717 txdes = ftgmac100_current_clean_txdes(priv);
718
719 if (ftgmac100_txdes_owned_by_dma(txdes))
720 return false;
721
722 skb = ftgmac100_txdes_get_skb(txdes);
723 map = ftgmac100_txdes_get_dma_addr(txdes);
724
725 netdev->stats.tx_packets++;
726 netdev->stats.tx_bytes += skb->len;
727
728 dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
729
730 dev_kfree_skb(skb);
731
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930732 ftgmac100_txdes_reset(priv, txdes);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000733
734 ftgmac100_tx_clean_pointer_advance(priv);
735
736 spin_lock(&priv->tx_lock);
737 priv->tx_pending--;
738 spin_unlock(&priv->tx_lock);
739 netif_wake_queue(netdev);
740
741 return true;
742}
743
744static void ftgmac100_tx_complete(struct ftgmac100 *priv)
745{
746 while (ftgmac100_tx_complete_packet(priv))
747 ;
748}
749
750static int ftgmac100_xmit(struct ftgmac100 *priv, struct sk_buff *skb,
751 dma_addr_t map)
752{
753 struct net_device *netdev = priv->netdev;
754 struct ftgmac100_txdes *txdes;
755 unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
756
757 txdes = ftgmac100_current_txdes(priv);
758 ftgmac100_tx_pointer_advance(priv);
759
760 /* setup TX descriptor */
761 ftgmac100_txdes_set_skb(txdes, skb);
762 ftgmac100_txdes_set_dma_addr(txdes, map);
763 ftgmac100_txdes_set_buffer_size(txdes, len);
764
765 ftgmac100_txdes_set_first_segment(txdes);
766 ftgmac100_txdes_set_last_segment(txdes);
767 ftgmac100_txdes_set_txint(txdes);
768 if (skb->ip_summed == CHECKSUM_PARTIAL) {
769 __be16 protocol = skb->protocol;
770
771 if (protocol == cpu_to_be16(ETH_P_IP)) {
772 u8 ip_proto = ip_hdr(skb)->protocol;
773
774 ftgmac100_txdes_set_ipcs(txdes);
775 if (ip_proto == IPPROTO_TCP)
776 ftgmac100_txdes_set_tcpcs(txdes);
777 else if (ip_proto == IPPROTO_UDP)
778 ftgmac100_txdes_set_udpcs(txdes);
779 }
780 }
781
782 spin_lock(&priv->tx_lock);
783 priv->tx_pending++;
784 if (priv->tx_pending == TX_QUEUE_ENTRIES)
785 netif_stop_queue(netdev);
786
787 /* start transmit */
788 ftgmac100_txdes_set_dma_own(txdes);
789 spin_unlock(&priv->tx_lock);
790
791 ftgmac100_txdma_normal_prio_start_polling(priv);
792
793 return NETDEV_TX_OK;
794}
795
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000796static int ftgmac100_alloc_rx_page(struct ftgmac100 *priv,
797 struct ftgmac100_rxdes *rxdes, gfp_t gfp)
798{
799 struct net_device *netdev = priv->netdev;
800 struct page *page;
801 dma_addr_t map;
802
803 page = alloc_page(gfp);
804 if (!page) {
805 if (net_ratelimit())
806 netdev_err(netdev, "failed to allocate rx page\n");
807 return -ENOMEM;
808 }
809
810 map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
811 if (unlikely(dma_mapping_error(priv->dev, map))) {
812 if (net_ratelimit())
813 netdev_err(netdev, "failed to map rx page\n");
814 __free_page(page);
815 return -ENOMEM;
816 }
817
Andrew Jefferyada66b52016-09-22 08:34:58 +0930818 ftgmac100_rxdes_set_page(priv, rxdes, page);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000819 ftgmac100_rxdes_set_dma_addr(rxdes, map);
Andrew Jeffery7906a4d2016-09-22 08:34:59 +0930820 ftgmac100_rxdes_set_dma_own(priv, rxdes);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000821 return 0;
822}
823
824static void ftgmac100_free_buffers(struct ftgmac100 *priv)
825{
826 int i;
827
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +1000828 /* Free all RX buffers */
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000829 for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
830 struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
Andrew Jefferyada66b52016-09-22 08:34:58 +0930831 struct page *page = ftgmac100_rxdes_get_page(priv, rxdes);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000832 dma_addr_t map = ftgmac100_rxdes_get_dma_addr(rxdes);
833
834 if (!page)
835 continue;
836
837 dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
838 __free_page(page);
839 }
840
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +1000841 /* Free all TX buffers */
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000842 for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
843 struct ftgmac100_txdes *txdes = &priv->descs->txdes[i];
844 struct sk_buff *skb = ftgmac100_txdes_get_skb(txdes);
845 dma_addr_t map = ftgmac100_txdes_get_dma_addr(txdes);
846
847 if (!skb)
848 continue;
849
850 dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
Eric Dumazet0113e342014-01-16 23:38:24 -0800851 kfree_skb(skb);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000852 }
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000853}
854
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +1000855static void ftgmac100_free_rings(struct ftgmac100 *priv)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000856{
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +1000857 /* Free descriptors */
858 if (priv->descs)
859 dma_free_coherent(priv->dev, sizeof(struct ftgmac100_descs),
860 priv->descs, priv->descs_dma_addr);
861}
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000862
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +1000863static int ftgmac100_alloc_rings(struct ftgmac100 *priv)
864{
865 /* Allocate descriptors */
Joe Perchesede23fa82013-08-26 22:45:23 -0700866 priv->descs = dma_zalloc_coherent(priv->dev,
867 sizeof(struct ftgmac100_descs),
868 &priv->descs_dma_addr, GFP_KERNEL);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000869 if (!priv->descs)
870 return -ENOMEM;
871
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +1000872 return 0;
873}
874
875static void ftgmac100_init_rings(struct ftgmac100 *priv)
876{
877 int i;
878
879 /* Initialize RX ring */
880 for (i = 0; i < RX_QUEUE_ENTRIES; i++)
881 priv->descs->rxdes[i].rxdes0 = 0;
882 ftgmac100_rxdes_set_end_of_ring(priv, &priv->descs->rxdes[i - 1]);
883
884 /* Initialize TX ring */
885 for (i = 0; i < TX_QUEUE_ENTRIES; i++)
886 priv->descs->txdes[i].txdes0 = 0;
887 ftgmac100_txdes_set_end_of_ring(priv, &priv->descs->txdes[i -1]);
888}
889
890static int ftgmac100_alloc_rx_buffers(struct ftgmac100 *priv)
891{
892 int i;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000893
894 for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
895 struct ftgmac100_rxdes *rxdes = &priv->descs->rxdes[i];
896
897 if (ftgmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +1000898 return -ENOMEM;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000899 }
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000900 return 0;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000901}
902
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000903static void ftgmac100_adjust_link(struct net_device *netdev)
904{
905 struct ftgmac100 *priv = netdev_priv(netdev);
Philippe Reynesb3c40ad2016-05-16 01:35:13 +0200906 struct phy_device *phydev = netdev->phydev;
Benjamin Herrenschmidt51764772017-04-05 12:28:45 +1000907 int new_speed;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000908
Benjamin Herrenschmidt51764772017-04-05 12:28:45 +1000909 /* We store "no link" as speed 0 */
910 if (!phydev->link)
911 new_speed = 0;
912 else
913 new_speed = phydev->speed;
914
915 if (phydev->speed == priv->cur_speed &&
916 phydev->duplex == priv->cur_duplex)
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000917 return;
918
Benjamin Herrenschmidt51764772017-04-05 12:28:45 +1000919 /* Print status if we have a link or we had one and just lost it,
920 * don't print otherwise.
921 */
922 if (new_speed || priv->cur_speed)
923 phy_print_status(phydev);
924
925 priv->cur_speed = new_speed;
926 priv->cur_duplex = phydev->duplex;
927
928 /* Link is down, do nothing else */
929 if (!new_speed)
930 return;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000931
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +1000932 /* Disable all interrupts */
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000933 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
934
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +1000935 /* Reset the adapter asynchronously */
936 schedule_work(&priv->reset_task);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000937}
938
939static int ftgmac100_mii_probe(struct ftgmac100 *priv)
940{
941 struct net_device *netdev = priv->netdev;
Guenter Roecke574f392016-01-10 12:04:32 -0800942 struct phy_device *phydev;
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000943
Guenter Roecke574f392016-01-10 12:04:32 -0800944 phydev = phy_find_first(priv->mii_bus);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000945 if (!phydev) {
946 netdev_info(netdev, "%s: no PHY found\n", netdev->name);
947 return -ENODEV;
948 }
949
Andrew Lunn84eff6d2016-01-06 20:11:10 +0100950 phydev = phy_connect(netdev, phydev_name(phydev),
Florian Fainellif9a8f832013-01-14 00:52:52 +0000951 &ftgmac100_adjust_link, PHY_INTERFACE_MODE_GMII);
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000952
953 if (IS_ERR(phydev)) {
954 netdev_err(netdev, "%s: Could not attach to PHY\n", netdev->name);
955 return PTR_ERR(phydev);
956 }
957
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000958 return 0;
959}
960
Po-Yu Chuang69785b72011-06-08 23:32:48 +0000961static int ftgmac100_mdiobus_read(struct mii_bus *bus, int phy_addr, int regnum)
962{
963 struct net_device *netdev = bus->priv;
964 struct ftgmac100 *priv = netdev_priv(netdev);
965 unsigned int phycr;
966 int i;
967
968 phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
969
970 /* preserve MDC cycle threshold */
971 phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
972
973 phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) |
974 FTGMAC100_PHYCR_REGAD(regnum) |
975 FTGMAC100_PHYCR_MIIRD;
976
977 iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR);
978
979 for (i = 0; i < 10; i++) {
980 phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
981
982 if ((phycr & FTGMAC100_PHYCR_MIIRD) == 0) {
983 int data;
984
985 data = ioread32(priv->base + FTGMAC100_OFFSET_PHYDATA);
986 return FTGMAC100_PHYDATA_MIIRDATA(data);
987 }
988
989 udelay(100);
990 }
991
992 netdev_err(netdev, "mdio read timed out\n");
993 return -EIO;
994}
995
996static int ftgmac100_mdiobus_write(struct mii_bus *bus, int phy_addr,
997 int regnum, u16 value)
998{
999 struct net_device *netdev = bus->priv;
1000 struct ftgmac100 *priv = netdev_priv(netdev);
1001 unsigned int phycr;
1002 int data;
1003 int i;
1004
1005 phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
1006
1007 /* preserve MDC cycle threshold */
1008 phycr &= FTGMAC100_PHYCR_MDC_CYCTHR_MASK;
1009
1010 phycr |= FTGMAC100_PHYCR_PHYAD(phy_addr) |
1011 FTGMAC100_PHYCR_REGAD(regnum) |
1012 FTGMAC100_PHYCR_MIIWR;
1013
1014 data = FTGMAC100_PHYDATA_MIIWDATA(value);
1015
1016 iowrite32(data, priv->base + FTGMAC100_OFFSET_PHYDATA);
1017 iowrite32(phycr, priv->base + FTGMAC100_OFFSET_PHYCR);
1018
1019 for (i = 0; i < 10; i++) {
1020 phycr = ioread32(priv->base + FTGMAC100_OFFSET_PHYCR);
1021
1022 if ((phycr & FTGMAC100_PHYCR_MIIWR) == 0)
1023 return 0;
1024
1025 udelay(100);
1026 }
1027
1028 netdev_err(netdev, "mdio write timed out\n");
1029 return -EIO;
1030}
1031
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001032static void ftgmac100_get_drvinfo(struct net_device *netdev,
1033 struct ethtool_drvinfo *info)
1034{
Jiri Pirko7826d432013-01-06 00:44:26 +00001035 strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
1036 strlcpy(info->version, DRV_VERSION, sizeof(info->version));
1037 strlcpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info));
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001038}
1039
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001040static const struct ethtool_ops ftgmac100_ethtool_ops = {
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001041 .get_drvinfo = ftgmac100_get_drvinfo,
1042 .get_link = ethtool_op_get_link,
Philippe Reynesfd24d722016-05-16 01:35:14 +02001043 .get_link_ksettings = phy_ethtool_get_link_ksettings,
1044 .set_link_ksettings = phy_ethtool_set_link_ksettings,
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001045};
1046
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001047static irqreturn_t ftgmac100_interrupt(int irq, void *dev_id)
1048{
1049 struct net_device *netdev = dev_id;
1050 struct ftgmac100 *priv = netdev_priv(netdev);
1051
Benjamin Herrenschmidt9b86785d2017-04-05 12:28:52 +10001052 /* Disable interrupts for polling */
1053 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
1054 napi_schedule(&priv->napi);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001055
1056 return IRQ_HANDLED;
1057}
1058
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001059static int ftgmac100_poll(struct napi_struct *napi, int budget)
1060{
1061 struct ftgmac100 *priv = container_of(napi, struct ftgmac100, napi);
1062 struct net_device *netdev = priv->netdev;
1063 unsigned int status;
1064 bool completed = true;
1065 int rx = 0;
1066
1067 status = ioread32(priv->base + FTGMAC100_OFFSET_ISR);
1068 iowrite32(status, priv->base + FTGMAC100_OFFSET_ISR);
1069
1070 if (status & (FTGMAC100_INT_RPKT_BUF | FTGMAC100_INT_NO_RXBUF)) {
1071 /*
1072 * FTGMAC100_INT_RPKT_BUF:
1073 * RX DMA has received packets into RX buffer successfully
1074 *
1075 * FTGMAC100_INT_NO_RXBUF:
1076 * RX buffer unavailable
1077 */
1078 bool retry;
1079
1080 do {
1081 retry = ftgmac100_rx_packet(priv, &rx);
1082 } while (retry && rx < budget);
1083
1084 if (retry && rx == budget)
1085 completed = false;
1086 }
1087
1088 if (status & (FTGMAC100_INT_XPKT_ETH | FTGMAC100_INT_XPKT_LOST)) {
1089 /*
1090 * FTGMAC100_INT_XPKT_ETH:
1091 * packet transmitted to ethernet successfully
1092 *
1093 * FTGMAC100_INT_XPKT_LOST:
1094 * packet transmitted to ethernet lost due to late
1095 * collision or excessive collision
1096 */
1097 ftgmac100_tx_complete(priv);
1098 }
1099
Gavin Shanfc6061c2016-07-19 11:54:25 +10001100 if (status & priv->int_mask_all & (FTGMAC100_INT_NO_RXBUF |
Joel Stanleyedcd6922016-09-22 08:35:03 +09301101 FTGMAC100_INT_RPKT_LOST | FTGMAC100_INT_AHB_ERR)) {
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001102 if (net_ratelimit())
Joel Stanleyedcd6922016-09-22 08:35:03 +09301103 netdev_info(netdev, "[ISR] = 0x%x: %s%s%s\n", status,
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001104 status & FTGMAC100_INT_NO_RXBUF ? "NO_RXBUF " : "",
1105 status & FTGMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
Joel Stanleyedcd6922016-09-22 08:35:03 +09301106 status & FTGMAC100_INT_AHB_ERR ? "AHB_ERR " : "");
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001107
1108 if (status & FTGMAC100_INT_NO_RXBUF) {
1109 /* RX buffer unavailable */
1110 netdev->stats.rx_over_errors++;
1111 }
1112
1113 if (status & FTGMAC100_INT_RPKT_LOST) {
1114 /* received packet lost due to RX FIFO full */
1115 netdev->stats.rx_fifo_errors++;
1116 }
1117 }
1118
1119 if (completed) {
1120 napi_complete(napi);
1121
1122 /* enable all interrupts */
Gavin Shanfc6061c2016-07-19 11:54:25 +10001123 iowrite32(priv->int_mask_all,
1124 priv->base + FTGMAC100_OFFSET_IER);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001125 }
1126
1127 return rx;
1128}
1129
Benjamin Herrenschmidtda40d9d2017-04-05 12:28:49 +10001130static int ftgmac100_init_all(struct ftgmac100 *priv, bool ignore_alloc_err)
1131{
1132 int err = 0;
1133
1134 /* Re-init descriptors (adjust queue sizes) */
1135 ftgmac100_init_rings(priv);
1136
1137 /* Realloc rx descriptors */
1138 err = ftgmac100_alloc_rx_buffers(priv);
1139 if (err && !ignore_alloc_err)
1140 return err;
1141
1142 /* Reinit and restart HW */
1143 ftgmac100_init_hw(priv);
1144 ftgmac100_start_hw(priv);
1145
1146 /* Re-enable the device */
1147 napi_enable(&priv->napi);
1148 netif_start_queue(priv->netdev);
1149
1150 /* Enable all interrupts */
1151 iowrite32(priv->int_mask_all, priv->base + FTGMAC100_OFFSET_IER);
1152
1153 return err;
1154}
1155
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +10001156static void ftgmac100_reset_task(struct work_struct *work)
1157{
1158 struct ftgmac100 *priv = container_of(work, struct ftgmac100,
1159 reset_task);
1160 struct net_device *netdev = priv->netdev;
1161 int err;
1162
1163 netdev_dbg(netdev, "Resetting NIC...\n");
1164
1165 /* Lock the world */
1166 rtnl_lock();
1167 if (netdev->phydev)
1168 mutex_lock(&netdev->phydev->lock);
1169 if (priv->mii_bus)
1170 mutex_lock(&priv->mii_bus->mdio_lock);
1171
1172
1173 /* Check if the interface is still up */
1174 if (!netif_running(netdev))
1175 goto bail;
1176
1177 /* Stop the network stack */
1178 netif_trans_update(netdev);
1179 napi_disable(&priv->napi);
1180 netif_tx_disable(netdev);
1181
1182 /* Stop and reset the MAC */
1183 ftgmac100_stop_hw(priv);
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +10001184 err = ftgmac100_reset_and_config_mac(priv);
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +10001185 if (err) {
1186 /* Not much we can do ... it might come back... */
1187 netdev_err(netdev, "attempting to continue...\n");
1188 }
1189
1190 /* Free all rx and tx buffers */
1191 ftgmac100_free_buffers(priv);
1192
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +10001193 /* Setup everything again and restart chip */
1194 ftgmac100_init_all(priv, true);
1195
1196 netdev_dbg(netdev, "Reset done !\n");
1197 bail:
1198 if (priv->mii_bus)
1199 mutex_unlock(&priv->mii_bus->mdio_lock);
1200 if (netdev->phydev)
1201 mutex_unlock(&netdev->phydev->lock);
1202 rtnl_unlock();
1203}
1204
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001205static int ftgmac100_open(struct net_device *netdev)
1206{
1207 struct ftgmac100 *priv = netdev_priv(netdev);
1208 int err;
1209
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +10001210 /* Allocate ring buffers */
1211 err = ftgmac100_alloc_rings(priv);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001212 if (err) {
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +10001213 netdev_err(netdev, "Failed to allocate descriptors\n");
1214 return err;
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001215 }
1216
Benjamin Herrenschmidt51764772017-04-05 12:28:45 +10001217 /* When using NC-SI we force the speed to 100Mbit/s full duplex,
1218 *
1219 * Otherwise we leave it set to 0 (no link), the link
1220 * message from the PHY layer will handle setting it up to
1221 * something else if needed.
1222 */
1223 if (priv->use_ncsi) {
1224 priv->cur_duplex = DUPLEX_FULL;
1225 priv->cur_speed = SPEED_100;
1226 } else {
1227 priv->cur_duplex = 0;
1228 priv->cur_speed = 0;
1229 }
1230
Benjamin Herrenschmidt874b55b2017-04-05 12:28:51 +10001231 /* Reset the hardware */
1232 err = ftgmac100_reset_and_config_mac(priv);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001233 if (err)
1234 goto err_hw;
1235
Benjamin Herrenschmidtb8dbecf2017-04-05 12:28:47 +10001236 /* Initialize NAPI */
1237 netif_napi_add(netdev, &priv->napi, ftgmac100_poll, 64);
1238
Benjamin Herrenschmidt81f1eca2017-04-05 12:28:48 +10001239 /* Grab our interrupt */
1240 err = request_irq(netdev->irq, ftgmac100_interrupt, 0, netdev->name, netdev);
1241 if (err) {
1242 netdev_err(netdev, "failed to request irq %d\n", netdev->irq);
1243 goto err_irq;
1244 }
1245
Benjamin Herrenschmidtda40d9d2017-04-05 12:28:49 +10001246 /* Start things up */
1247 err = ftgmac100_init_all(priv, false);
1248 if (err) {
1249 netdev_err(netdev, "Failed to allocate packet buffers\n");
1250 goto err_alloc;
1251 }
Gavin Shan08c9c122016-09-22 08:35:01 +09301252
Benjamin Herrenschmidtda40d9d2017-04-05 12:28:49 +10001253 if (netdev->phydev) {
1254 /* If we have a PHY, start polling */
Gavin Shanbd466c32016-07-19 11:54:23 +10001255 phy_start(netdev->phydev);
Benjamin Herrenschmidtda40d9d2017-04-05 12:28:49 +10001256 } else if (priv->use_ncsi) {
1257 /* If using NC-SI, set our carrier on and start the stack */
Gavin Shanbd466c32016-07-19 11:54:23 +10001258 netif_carrier_on(netdev);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001259
Benjamin Herrenschmidtda40d9d2017-04-05 12:28:49 +10001260 /* Start the NCSI device */
Gavin Shanbd466c32016-07-19 11:54:23 +10001261 err = ncsi_start_dev(priv->ndev);
1262 if (err)
1263 goto err_ncsi;
1264 }
1265
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001266 return 0;
1267
Benjamin Herrenschmidtda40d9d2017-04-05 12:28:49 +10001268 err_ncsi:
Gavin Shanbd466c32016-07-19 11:54:23 +10001269 napi_disable(&priv->napi);
1270 netif_stop_queue(netdev);
Benjamin Herrenschmidtda40d9d2017-04-05 12:28:49 +10001271 err_alloc:
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +10001272 ftgmac100_free_buffers(priv);
Benjamin Herrenschmidtda40d9d2017-04-05 12:28:49 +10001273 free_irq(netdev->irq, netdev);
1274 err_irq:
1275 netif_napi_del(&priv->napi);
1276 err_hw:
1277 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +10001278 ftgmac100_free_rings(priv);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001279 return err;
1280}
1281
1282static int ftgmac100_stop(struct net_device *netdev)
1283{
1284 struct ftgmac100 *priv = netdev_priv(netdev);
1285
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +10001286 /* Note about the reset task: We are called with the rtnl lock
1287 * held, so we are synchronized against the core of the reset
1288 * task. We must not try to synchronously cancel it otherwise
1289 * we can deadlock. But since it will test for netif_running()
1290 * which has already been cleared by the net core, we don't
1291 * anything special to do.
1292 */
1293
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001294 /* disable all interrupts */
1295 iowrite32(0, priv->base + FTGMAC100_OFFSET_IER);
1296
1297 netif_stop_queue(netdev);
1298 napi_disable(&priv->napi);
Benjamin Herrenschmidtb8dbecf2017-04-05 12:28:47 +10001299 netif_napi_del(&priv->napi);
Gavin Shanbd466c32016-07-19 11:54:23 +10001300 if (netdev->phydev)
1301 phy_stop(netdev->phydev);
Gavin Shan2c15f252016-10-04 11:25:54 +11001302 else if (priv->use_ncsi)
1303 ncsi_stop_dev(priv->ndev);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001304
1305 ftgmac100_stop_hw(priv);
Benjamin Herrenschmidt60b28a12017-04-05 12:28:41 +10001306 free_irq(netdev->irq, netdev);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001307 ftgmac100_free_buffers(priv);
Benjamin Herrenschmidt87d18752017-04-05 12:28:46 +10001308 ftgmac100_free_rings(priv);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001309
1310 return 0;
1311}
1312
1313static int ftgmac100_hard_start_xmit(struct sk_buff *skb,
1314 struct net_device *netdev)
1315{
1316 struct ftgmac100 *priv = netdev_priv(netdev);
1317 dma_addr_t map;
1318
1319 if (unlikely(skb->len > MAX_PKT_SIZE)) {
1320 if (net_ratelimit())
1321 netdev_dbg(netdev, "tx packet too big\n");
1322
1323 netdev->stats.tx_dropped++;
Eric Dumazet0113e342014-01-16 23:38:24 -08001324 kfree_skb(skb);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001325 return NETDEV_TX_OK;
1326 }
1327
1328 map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
1329 if (unlikely(dma_mapping_error(priv->dev, map))) {
1330 /* drop packet */
1331 if (net_ratelimit())
1332 netdev_err(netdev, "map socket buffer failed\n");
1333
1334 netdev->stats.tx_dropped++;
Eric Dumazet0113e342014-01-16 23:38:24 -08001335 kfree_skb(skb);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001336 return NETDEV_TX_OK;
1337 }
1338
1339 return ftgmac100_xmit(priv, skb, map);
1340}
1341
1342/* optional */
1343static int ftgmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
1344{
Gavin Shanbd466c32016-07-19 11:54:23 +10001345 if (!netdev->phydev)
1346 return -ENXIO;
1347
Philippe Reynesb3c40ad2016-05-16 01:35:13 +02001348 return phy_mii_ioctl(netdev->phydev, ifr, cmd);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001349}
1350
1351static const struct net_device_ops ftgmac100_netdev_ops = {
1352 .ndo_open = ftgmac100_open,
1353 .ndo_stop = ftgmac100_stop,
1354 .ndo_start_xmit = ftgmac100_hard_start_xmit,
Gavin Shan113ce102016-07-19 11:54:22 +10001355 .ndo_set_mac_address = ftgmac100_set_mac_addr,
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001356 .ndo_validate_addr = eth_validate_addr,
1357 .ndo_do_ioctl = ftgmac100_do_ioctl,
1358};
1359
Gavin Shaneb418182016-07-19 11:54:21 +10001360static int ftgmac100_setup_mdio(struct net_device *netdev)
1361{
1362 struct ftgmac100 *priv = netdev_priv(netdev);
1363 struct platform_device *pdev = to_platform_device(priv->dev);
1364 int i, err = 0;
Joel Stanleye07dc632016-09-22 08:35:02 +09301365 u32 reg;
Gavin Shaneb418182016-07-19 11:54:21 +10001366
1367 /* initialize mdio bus */
1368 priv->mii_bus = mdiobus_alloc();
1369 if (!priv->mii_bus)
1370 return -EIO;
1371
Joel Stanleye07dc632016-09-22 08:35:02 +09301372 if (of_machine_is_compatible("aspeed,ast2400") ||
1373 of_machine_is_compatible("aspeed,ast2500")) {
1374 /* This driver supports the old MDIO interface */
1375 reg = ioread32(priv->base + FTGMAC100_OFFSET_REVR);
1376 reg &= ~FTGMAC100_REVR_NEW_MDIO_INTERFACE;
1377 iowrite32(reg, priv->base + FTGMAC100_OFFSET_REVR);
1378 };
1379
Gavin Shaneb418182016-07-19 11:54:21 +10001380 priv->mii_bus->name = "ftgmac100_mdio";
1381 snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%d",
1382 pdev->name, pdev->id);
1383 priv->mii_bus->priv = priv->netdev;
1384 priv->mii_bus->read = ftgmac100_mdiobus_read;
1385 priv->mii_bus->write = ftgmac100_mdiobus_write;
1386
1387 for (i = 0; i < PHY_MAX_ADDR; i++)
1388 priv->mii_bus->irq[i] = PHY_POLL;
1389
1390 err = mdiobus_register(priv->mii_bus);
1391 if (err) {
1392 dev_err(priv->dev, "Cannot register MDIO bus!\n");
1393 goto err_register_mdiobus;
1394 }
1395
1396 err = ftgmac100_mii_probe(priv);
1397 if (err) {
1398 dev_err(priv->dev, "MII Probe failed!\n");
1399 goto err_mii_probe;
1400 }
1401
1402 return 0;
1403
1404err_mii_probe:
1405 mdiobus_unregister(priv->mii_bus);
1406err_register_mdiobus:
1407 mdiobus_free(priv->mii_bus);
1408 return err;
1409}
1410
1411static void ftgmac100_destroy_mdio(struct net_device *netdev)
1412{
1413 struct ftgmac100 *priv = netdev_priv(netdev);
1414
1415 if (!netdev->phydev)
1416 return;
1417
1418 phy_disconnect(netdev->phydev);
1419 mdiobus_unregister(priv->mii_bus);
1420 mdiobus_free(priv->mii_bus);
1421}
1422
Gavin Shanbd466c32016-07-19 11:54:23 +10001423static void ftgmac100_ncsi_handler(struct ncsi_dev *nd)
1424{
1425 if (unlikely(nd->state != ncsi_dev_state_functional))
1426 return;
1427
1428 netdev_info(nd->dev, "NCSI interface %s\n",
1429 nd->link_up ? "up" : "down");
1430}
1431
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001432static int ftgmac100_probe(struct platform_device *pdev)
1433{
1434 struct resource *res;
1435 int irq;
1436 struct net_device *netdev;
1437 struct ftgmac100 *priv;
Gavin Shanbd466c32016-07-19 11:54:23 +10001438 int err = 0;
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001439
1440 if (!pdev)
1441 return -ENODEV;
1442
1443 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1444 if (!res)
1445 return -ENXIO;
1446
1447 irq = platform_get_irq(pdev, 0);
1448 if (irq < 0)
1449 return irq;
1450
1451 /* setup net_device */
1452 netdev = alloc_etherdev(sizeof(*priv));
1453 if (!netdev) {
1454 err = -ENOMEM;
1455 goto err_alloc_etherdev;
1456 }
1457
1458 SET_NETDEV_DEV(netdev, &pdev->dev);
1459
Wilfried Klaebe7ad24ea2014-05-11 00:12:32 +00001460 netdev->ethtool_ops = &ftgmac100_ethtool_ops;
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001461 netdev->netdev_ops = &ftgmac100_netdev_ops;
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001462
1463 platform_set_drvdata(pdev, netdev);
1464
1465 /* setup private data */
1466 priv = netdev_priv(netdev);
1467 priv->netdev = netdev;
1468 priv->dev = &pdev->dev;
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +10001469 INIT_WORK(&priv->reset_task, ftgmac100_reset_task);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001470
1471 spin_lock_init(&priv->tx_lock);
1472
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001473 /* map io memory */
1474 priv->res = request_mem_region(res->start, resource_size(res),
1475 dev_name(&pdev->dev));
1476 if (!priv->res) {
1477 dev_err(&pdev->dev, "Could not reserve memory region\n");
1478 err = -ENOMEM;
1479 goto err_req_mem;
1480 }
1481
1482 priv->base = ioremap(res->start, resource_size(res));
1483 if (!priv->base) {
1484 dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
1485 err = -EIO;
1486 goto err_ioremap;
1487 }
1488
Benjamin Herrenschmidt60b28a12017-04-05 12:28:41 +10001489 netdev->irq = irq;
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001490
Gavin Shan113ce102016-07-19 11:54:22 +10001491 /* MAC address from chip or random one */
1492 ftgmac100_setup_mac(priv);
1493
Gavin Shanfc6061c2016-07-19 11:54:25 +10001494 priv->int_mask_all = (FTGMAC100_INT_RPKT_LOST |
1495 FTGMAC100_INT_XPKT_ETH |
1496 FTGMAC100_INT_XPKT_LOST |
1497 FTGMAC100_INT_AHB_ERR |
Gavin Shanfc6061c2016-07-19 11:54:25 +10001498 FTGMAC100_INT_RPKT_BUF |
1499 FTGMAC100_INT_NO_RXBUF);
Joel Stanley2a0ab8eb2016-09-22 08:35:00 +09301500
1501 if (of_machine_is_compatible("aspeed,ast2400") ||
1502 of_machine_is_compatible("aspeed,ast2500")) {
1503 priv->rxdes0_edorr_mask = BIT(30);
1504 priv->txdes0_edotr_mask = BIT(30);
1505 } else {
1506 priv->rxdes0_edorr_mask = BIT(15);
1507 priv->txdes0_edotr_mask = BIT(15);
1508 }
1509
Gavin Shanbd466c32016-07-19 11:54:23 +10001510 if (pdev->dev.of_node &&
1511 of_get_property(pdev->dev.of_node, "use-ncsi", NULL)) {
1512 if (!IS_ENABLED(CONFIG_NET_NCSI)) {
1513 dev_err(&pdev->dev, "NCSI stack not enabled\n");
1514 goto err_ncsi_dev;
1515 }
1516
1517 dev_info(&pdev->dev, "Using NCSI interface\n");
1518 priv->use_ncsi = true;
1519 priv->ndev = ncsi_register_dev(netdev, ftgmac100_ncsi_handler);
1520 if (!priv->ndev)
1521 goto err_ncsi_dev;
1522 } else {
1523 priv->use_ncsi = false;
1524 err = ftgmac100_setup_mdio(netdev);
1525 if (err)
1526 goto err_setup_mdio;
1527 }
1528
1529 /* We have to disable on-chip IP checksum functionality
1530 * when NCSI is enabled on the interface. It doesn't work
1531 * in that case.
1532 */
1533 netdev->features = NETIF_F_IP_CSUM | NETIF_F_GRO;
1534 if (priv->use_ncsi &&
1535 of_get_property(pdev->dev.of_node, "no-hw-checksum", NULL))
1536 netdev->features &= ~NETIF_F_IP_CSUM;
1537
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001538
1539 /* register network device */
1540 err = register_netdev(netdev);
1541 if (err) {
1542 dev_err(&pdev->dev, "Failed to register netdev\n");
1543 goto err_register_netdev;
1544 }
1545
Benjamin Herrenschmidt60b28a12017-04-05 12:28:41 +10001546 netdev_info(netdev, "irq %d, mapped at %p\n", netdev->irq, priv->base);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001547
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001548 return 0;
1549
Gavin Shanbd466c32016-07-19 11:54:23 +10001550err_ncsi_dev:
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001551err_register_netdev:
Gavin Shaneb418182016-07-19 11:54:21 +10001552 ftgmac100_destroy_mdio(netdev);
1553err_setup_mdio:
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001554 iounmap(priv->base);
1555err_ioremap:
1556 release_resource(priv->res);
1557err_req_mem:
1558 netif_napi_del(&priv->napi);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001559 free_netdev(netdev);
1560err_alloc_etherdev:
1561 return err;
1562}
1563
Dmitry Torokhovbe125022017-03-01 17:24:47 -08001564static int ftgmac100_remove(struct platform_device *pdev)
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001565{
1566 struct net_device *netdev;
1567 struct ftgmac100 *priv;
1568
1569 netdev = platform_get_drvdata(pdev);
1570 priv = netdev_priv(netdev);
1571
1572 unregister_netdev(netdev);
Benjamin Herrenschmidt855944c2017-04-05 12:28:50 +10001573
1574 /* There's a small chance the reset task will have been re-queued,
1575 * during stop, make sure it's gone before we free the structure.
1576 */
1577 cancel_work_sync(&priv->reset_task);
1578
Gavin Shaneb418182016-07-19 11:54:21 +10001579 ftgmac100_destroy_mdio(netdev);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001580
1581 iounmap(priv->base);
1582 release_resource(priv->res);
1583
1584 netif_napi_del(&priv->napi);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001585 free_netdev(netdev);
1586 return 0;
1587}
1588
Gavin Shanbb168e22016-07-19 11:54:24 +10001589static const struct of_device_id ftgmac100_of_match[] = {
1590 { .compatible = "faraday,ftgmac100" },
1591 { }
1592};
1593MODULE_DEVICE_TABLE(of, ftgmac100_of_match);
1594
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001595static struct platform_driver ftgmac100_driver = {
Gavin Shanbb168e22016-07-19 11:54:24 +10001596 .probe = ftgmac100_probe,
Dmitry Torokhovbe125022017-03-01 17:24:47 -08001597 .remove = ftgmac100_remove,
Gavin Shanbb168e22016-07-19 11:54:24 +10001598 .driver = {
1599 .name = DRV_NAME,
1600 .of_match_table = ftgmac100_of_match,
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001601 },
1602};
Sachin Kamat14f645d2013-03-18 01:50:48 +00001603module_platform_driver(ftgmac100_driver);
Po-Yu Chuang69785b72011-06-08 23:32:48 +00001604
1605MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
1606MODULE_DESCRIPTION("FTGMAC100 driver");
1607MODULE_LICENSE("GPL");