1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright(c) 2015 EZchip Technologies. |
4 | */ |
5 | |
6 | #include <linux/module.h> |
7 | #include <linux/etherdevice.h> |
8 | #include <linux/interrupt.h> |
9 | #include <linux/mod_devicetable.h> |
10 | #include <linux/of_net.h> |
11 | #include <linux/platform_device.h> |
12 | #include "nps_enet.h" |
13 | |
14 | #define DRV_NAME "nps_mgt_enet" |
15 | |
16 | static inline bool nps_enet_is_tx_pending(struct nps_enet_priv *priv) |
17 | { |
18 | u32 tx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); |
19 | u32 tx_ctrl_ct = (tx_ctrl_value & TX_CTL_CT_MASK) >> TX_CTL_CT_SHIFT; |
20 | |
21 | return (!tx_ctrl_ct && priv->tx_skb); |
22 | } |
23 | |
24 | static void nps_enet_clean_rx_fifo(struct net_device *ndev, u32 frame_len) |
25 | { |
26 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
27 | u32 i, len = DIV_ROUND_UP(frame_len, sizeof(u32)); |
28 | |
29 | /* Empty Rx FIFO buffer by reading all words */ |
30 | for (i = 0; i < len; i++) |
31 | nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF); |
32 | } |
33 | |
34 | static void nps_enet_read_rx_fifo(struct net_device *ndev, |
35 | unsigned char *dst, u32 length) |
36 | { |
37 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
38 | s32 i, last = length & (sizeof(u32) - 1); |
39 | u32 *reg = (u32 *)dst, len = length / sizeof(u32); |
40 | bool dst_is_aligned = IS_ALIGNED((unsigned long)dst, sizeof(u32)); |
41 | |
42 | /* In case dst is not aligned we need an intermediate buffer */ |
43 | if (dst_is_aligned) { |
44 | ioread32_rep(port: priv->regs_base + NPS_ENET_REG_RX_BUF, buf: reg, count: len); |
45 | reg += len; |
46 | } else { /* !dst_is_aligned */ |
47 | for (i = 0; i < len; i++, reg++) { |
48 | u32 buf = nps_enet_reg_get(priv, NPS_ENET_REG_RX_BUF); |
49 | |
50 | put_unaligned_be32(val: buf, p: reg); |
51 | } |
52 | } |
53 | /* copy last bytes (if any) */ |
54 | if (last) { |
55 | u32 buf; |
56 | |
57 | ioread32_rep(port: priv->regs_base + NPS_ENET_REG_RX_BUF, buf: &buf, count: 1); |
58 | memcpy((u8 *)reg, &buf, last); |
59 | } |
60 | } |
61 | |
62 | static u32 nps_enet_rx_handler(struct net_device *ndev) |
63 | { |
64 | u32 frame_len, err = 0; |
65 | u32 work_done = 0; |
66 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
67 | struct sk_buff *skb; |
68 | u32 rx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); |
69 | u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT; |
70 | u32 rx_ctrl_er = (rx_ctrl_value & RX_CTL_ER_MASK) >> RX_CTL_ER_SHIFT; |
71 | u32 rx_ctrl_crc = (rx_ctrl_value & RX_CTL_CRC_MASK) >> RX_CTL_CRC_SHIFT; |
72 | |
73 | frame_len = (rx_ctrl_value & RX_CTL_NR_MASK) >> RX_CTL_NR_SHIFT; |
74 | |
75 | /* Check if we got RX */ |
76 | if (!rx_ctrl_cr) |
77 | return work_done; |
78 | |
79 | /* If we got here there is a work for us */ |
80 | work_done++; |
81 | |
82 | /* Check Rx error */ |
83 | if (rx_ctrl_er) { |
84 | ndev->stats.rx_errors++; |
85 | err = 1; |
86 | } |
87 | |
88 | /* Check Rx CRC error */ |
89 | if (rx_ctrl_crc) { |
90 | ndev->stats.rx_crc_errors++; |
91 | ndev->stats.rx_dropped++; |
92 | err = 1; |
93 | } |
94 | |
95 | /* Check Frame length Min 64b */ |
96 | if (unlikely(frame_len < ETH_ZLEN)) { |
97 | ndev->stats.rx_length_errors++; |
98 | ndev->stats.rx_dropped++; |
99 | err = 1; |
100 | } |
101 | |
102 | if (err) |
103 | goto rx_irq_clean; |
104 | |
105 | /* Skb allocation */ |
106 | skb = netdev_alloc_skb_ip_align(dev: ndev, length: frame_len); |
107 | if (unlikely(!skb)) { |
108 | ndev->stats.rx_errors++; |
109 | ndev->stats.rx_dropped++; |
110 | goto rx_irq_clean; |
111 | } |
112 | |
113 | /* Copy frame from Rx fifo into the skb */ |
114 | nps_enet_read_rx_fifo(ndev, dst: skb->data, length: frame_len); |
115 | |
116 | skb_put(skb, len: frame_len); |
117 | skb->protocol = eth_type_trans(skb, dev: ndev); |
118 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
119 | |
120 | ndev->stats.rx_packets++; |
121 | ndev->stats.rx_bytes += frame_len; |
122 | netif_receive_skb(skb); |
123 | |
124 | goto rx_irq_frame_done; |
125 | |
126 | rx_irq_clean: |
127 | /* Clean Rx fifo */ |
128 | nps_enet_clean_rx_fifo(ndev, frame_len); |
129 | |
130 | rx_irq_frame_done: |
131 | /* Ack Rx ctrl register */ |
132 | nps_enet_reg_set(priv, NPS_ENET_REG_RX_CTL, value: 0); |
133 | |
134 | return work_done; |
135 | } |
136 | |
137 | static void nps_enet_tx_handler(struct net_device *ndev) |
138 | { |
139 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
140 | u32 tx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_TX_CTL); |
141 | u32 tx_ctrl_et = (tx_ctrl_value & TX_CTL_ET_MASK) >> TX_CTL_ET_SHIFT; |
142 | u32 tx_ctrl_nt = (tx_ctrl_value & TX_CTL_NT_MASK) >> TX_CTL_NT_SHIFT; |
143 | |
144 | /* Check if we got TX */ |
145 | if (!nps_enet_is_tx_pending(priv)) |
146 | return; |
147 | |
148 | /* Ack Tx ctrl register */ |
149 | nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, value: 0); |
150 | |
151 | /* Check Tx transmit error */ |
152 | if (unlikely(tx_ctrl_et)) { |
153 | ndev->stats.tx_errors++; |
154 | } else { |
155 | ndev->stats.tx_packets++; |
156 | ndev->stats.tx_bytes += tx_ctrl_nt; |
157 | } |
158 | |
159 | dev_kfree_skb(priv->tx_skb); |
160 | priv->tx_skb = NULL; |
161 | |
162 | if (netif_queue_stopped(dev: ndev)) |
163 | netif_wake_queue(dev: ndev); |
164 | } |
165 | |
166 | /** |
167 | * nps_enet_poll - NAPI poll handler. |
168 | * @napi: Pointer to napi_struct structure. |
169 | * @budget: How many frames to process on one call. |
170 | * |
171 | * returns: Number of processed frames |
172 | */ |
173 | static int nps_enet_poll(struct napi_struct *napi, int budget) |
174 | { |
175 | struct net_device *ndev = napi->dev; |
176 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
177 | u32 work_done; |
178 | |
179 | nps_enet_tx_handler(ndev); |
180 | work_done = nps_enet_rx_handler(ndev); |
181 | if ((work_done < budget) && napi_complete_done(n: napi, work_done)) { |
182 | u32 buf_int_enable_value = 0; |
183 | |
184 | /* set tx_done and rx_rdy bits */ |
185 | buf_int_enable_value |= NPS_ENET_ENABLE << RX_RDY_SHIFT; |
186 | buf_int_enable_value |= NPS_ENET_ENABLE << TX_DONE_SHIFT; |
187 | |
188 | nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, |
189 | value: buf_int_enable_value); |
190 | |
191 | /* in case we will get a tx interrupt while interrupts |
192 | * are masked, we will lose it since the tx is edge interrupt. |
193 | * specifically, while executing the code section above, |
194 | * between nps_enet_tx_handler and the interrupts enable, all |
195 | * tx requests will be stuck until we will get an rx interrupt. |
196 | * the two code lines below will solve this situation by |
197 | * re-adding ourselves to the poll list. |
198 | */ |
199 | if (nps_enet_is_tx_pending(priv)) { |
200 | nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, value: 0); |
201 | napi_schedule(n: napi); |
202 | } |
203 | } |
204 | |
205 | return work_done; |
206 | } |
207 | |
208 | /** |
209 | * nps_enet_irq_handler - Global interrupt handler for ENET. |
210 | * @irq: irq number. |
211 | * @dev_instance: device instance. |
212 | * |
213 | * returns: IRQ_HANDLED for all cases. |
214 | * |
215 | * EZchip ENET has 2 interrupt causes, and depending on bits raised in |
216 | * CTRL registers we may tell what is a reason for interrupt to fire up. |
217 | * We got one for RX and the other for TX (completion). |
218 | */ |
219 | static irqreturn_t nps_enet_irq_handler(s32 irq, void *dev_instance) |
220 | { |
221 | struct net_device *ndev = dev_instance; |
222 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
223 | u32 rx_ctrl_value = nps_enet_reg_get(priv, NPS_ENET_REG_RX_CTL); |
224 | u32 rx_ctrl_cr = (rx_ctrl_value & RX_CTL_CR_MASK) >> RX_CTL_CR_SHIFT; |
225 | |
226 | if (nps_enet_is_tx_pending(priv) || rx_ctrl_cr) |
227 | if (likely(napi_schedule_prep(&priv->napi))) { |
228 | nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, value: 0); |
229 | __napi_schedule(n: &priv->napi); |
230 | } |
231 | |
232 | return IRQ_HANDLED; |
233 | } |
234 | |
235 | static void nps_enet_set_hw_mac_address(struct net_device *ndev) |
236 | { |
237 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
238 | u32 ge_mac_cfg_1_value = 0; |
239 | u32 *ge_mac_cfg_2_value = &priv->ge_mac_cfg_2_value; |
240 | |
241 | /* set MAC address in HW */ |
242 | ge_mac_cfg_1_value |= ndev->dev_addr[0] << CFG_1_OCTET_0_SHIFT; |
243 | ge_mac_cfg_1_value |= ndev->dev_addr[1] << CFG_1_OCTET_1_SHIFT; |
244 | ge_mac_cfg_1_value |= ndev->dev_addr[2] << CFG_1_OCTET_2_SHIFT; |
245 | ge_mac_cfg_1_value |= ndev->dev_addr[3] << CFG_1_OCTET_3_SHIFT; |
246 | *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_OCTET_4_MASK) |
247 | | ndev->dev_addr[4] << CFG_2_OCTET_4_SHIFT; |
248 | *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_OCTET_5_MASK) |
249 | | ndev->dev_addr[5] << CFG_2_OCTET_5_SHIFT; |
250 | |
251 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_1, |
252 | value: ge_mac_cfg_1_value); |
253 | |
254 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, |
255 | value: *ge_mac_cfg_2_value); |
256 | } |
257 | |
258 | /** |
259 | * nps_enet_hw_reset - Reset the network device. |
260 | * @ndev: Pointer to the network device. |
261 | * |
262 | * This function reset the PCS and TX fifo. |
263 | * The programming model is to set the relevant reset bits |
264 | * wait for some time for this to propagate and then unset |
265 | * the reset bits. This way we ensure that reset procedure |
266 | * is done successfully by device. |
267 | */ |
268 | static void nps_enet_hw_reset(struct net_device *ndev) |
269 | { |
270 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
271 | u32 ge_rst_value = 0, phase_fifo_ctl_value = 0; |
272 | |
273 | /* Pcs reset sequence*/ |
274 | ge_rst_value |= NPS_ENET_ENABLE << RST_GMAC_0_SHIFT; |
275 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, value: ge_rst_value); |
276 | usleep_range(min: 10, max: 20); |
277 | ge_rst_value = 0; |
278 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_RST, value: ge_rst_value); |
279 | |
280 | /* Tx fifo reset sequence */ |
281 | phase_fifo_ctl_value |= NPS_ENET_ENABLE << PHASE_FIFO_CTL_RST_SHIFT; |
282 | phase_fifo_ctl_value |= NPS_ENET_ENABLE << PHASE_FIFO_CTL_INIT_SHIFT; |
283 | nps_enet_reg_set(priv, NPS_ENET_REG_PHASE_FIFO_CTL, |
284 | value: phase_fifo_ctl_value); |
285 | usleep_range(min: 10, max: 20); |
286 | phase_fifo_ctl_value = 0; |
287 | nps_enet_reg_set(priv, NPS_ENET_REG_PHASE_FIFO_CTL, |
288 | value: phase_fifo_ctl_value); |
289 | } |
290 | |
291 | static void nps_enet_hw_enable_control(struct net_device *ndev) |
292 | { |
293 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
294 | u32 ge_mac_cfg_0_value = 0, buf_int_enable_value = 0; |
295 | u32 *ge_mac_cfg_2_value = &priv->ge_mac_cfg_2_value; |
296 | u32 *ge_mac_cfg_3_value = &priv->ge_mac_cfg_3_value; |
297 | s32 max_frame_length; |
298 | |
299 | /* Enable Rx and Tx statistics */ |
300 | *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_STAT_EN_MASK) |
301 | | NPS_ENET_GE_MAC_CFG_2_STAT_EN << CFG_2_STAT_EN_SHIFT; |
302 | |
303 | /* Discard packets with different MAC address */ |
304 | *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) |
305 | | NPS_ENET_ENABLE << CFG_2_DISK_DA_SHIFT; |
306 | |
307 | /* Discard multicast packets */ |
308 | *ge_mac_cfg_2_value = (*ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) |
309 | | NPS_ENET_ENABLE << CFG_2_DISK_MC_SHIFT; |
310 | |
311 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, |
312 | value: *ge_mac_cfg_2_value); |
313 | |
314 | /* Discard Packets bigger than max frame length */ |
315 | max_frame_length = ETH_HLEN + ndev->mtu + ETH_FCS_LEN; |
316 | if (max_frame_length <= NPS_ENET_MAX_FRAME_LENGTH) { |
317 | *ge_mac_cfg_3_value = |
318 | (*ge_mac_cfg_3_value & ~CFG_3_MAX_LEN_MASK) |
319 | | max_frame_length << CFG_3_MAX_LEN_SHIFT; |
320 | } |
321 | |
322 | /* Enable interrupts */ |
323 | buf_int_enable_value |= NPS_ENET_ENABLE << RX_RDY_SHIFT; |
324 | buf_int_enable_value |= NPS_ENET_ENABLE << TX_DONE_SHIFT; |
325 | nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, |
326 | value: buf_int_enable_value); |
327 | |
328 | /* Write device MAC address to HW */ |
329 | nps_enet_set_hw_mac_address(ndev); |
330 | |
331 | /* Rx and Tx HW features */ |
332 | ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_PAD_EN_SHIFT; |
333 | ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_CRC_EN_SHIFT; |
334 | ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_CRC_STRIP_SHIFT; |
335 | |
336 | /* IFG configuration */ |
337 | ge_mac_cfg_0_value |= |
338 | NPS_ENET_GE_MAC_CFG_0_RX_IFG << CFG_0_RX_IFG_SHIFT; |
339 | ge_mac_cfg_0_value |= |
340 | NPS_ENET_GE_MAC_CFG_0_TX_IFG << CFG_0_TX_IFG_SHIFT; |
341 | |
342 | /* preamble configuration */ |
343 | ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_PR_CHECK_EN_SHIFT; |
344 | ge_mac_cfg_0_value |= |
345 | NPS_ENET_GE_MAC_CFG_0_TX_PR_LEN << CFG_0_TX_PR_LEN_SHIFT; |
346 | |
347 | /* enable flow control frames */ |
348 | ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_FC_EN_SHIFT; |
349 | ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_FC_EN_SHIFT; |
350 | ge_mac_cfg_0_value |= |
351 | NPS_ENET_GE_MAC_CFG_0_TX_FC_RETR << CFG_0_TX_FC_RETR_SHIFT; |
352 | *ge_mac_cfg_3_value = (*ge_mac_cfg_3_value & ~CFG_3_CF_DROP_MASK) |
353 | | NPS_ENET_ENABLE << CFG_3_CF_DROP_SHIFT; |
354 | |
355 | /* Enable Rx and Tx */ |
356 | ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_RX_EN_SHIFT; |
357 | ge_mac_cfg_0_value |= NPS_ENET_ENABLE << CFG_0_TX_EN_SHIFT; |
358 | |
359 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_3, |
360 | value: *ge_mac_cfg_3_value); |
361 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_0, |
362 | value: ge_mac_cfg_0_value); |
363 | } |
364 | |
365 | static void nps_enet_hw_disable_control(struct net_device *ndev) |
366 | { |
367 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
368 | |
369 | /* Disable interrupts */ |
370 | nps_enet_reg_set(priv, NPS_ENET_REG_BUF_INT_ENABLE, value: 0); |
371 | |
372 | /* Disable Rx and Tx */ |
373 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_0, value: 0); |
374 | } |
375 | |
376 | static void nps_enet_send_frame(struct net_device *ndev, |
377 | struct sk_buff *skb) |
378 | { |
379 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
380 | u32 tx_ctrl_value = 0; |
381 | short length = skb->len; |
382 | u32 i, len = DIV_ROUND_UP(length, sizeof(u32)); |
383 | u32 *src = (void *)skb->data; |
384 | bool src_is_aligned = IS_ALIGNED((unsigned long)src, sizeof(u32)); |
385 | |
386 | /* In case src is not aligned we need an intermediate buffer */ |
387 | if (src_is_aligned) |
388 | iowrite32_rep(port: priv->regs_base + NPS_ENET_REG_TX_BUF, buf: src, count: len); |
389 | else /* !src_is_aligned */ |
390 | for (i = 0; i < len; i++, src++) |
391 | nps_enet_reg_set(priv, NPS_ENET_REG_TX_BUF, |
392 | value: get_unaligned_be32(p: src)); |
393 | |
394 | /* Write the length of the Frame */ |
395 | tx_ctrl_value |= length << TX_CTL_NT_SHIFT; |
396 | |
397 | tx_ctrl_value |= NPS_ENET_ENABLE << TX_CTL_CT_SHIFT; |
398 | /* Send Frame */ |
399 | nps_enet_reg_set(priv, NPS_ENET_REG_TX_CTL, value: tx_ctrl_value); |
400 | } |
401 | |
402 | /** |
403 | * nps_enet_set_mac_address - Set the MAC address for this device. |
404 | * @ndev: Pointer to net_device structure. |
405 | * @p: 6 byte Address to be written as MAC address. |
406 | * |
407 | * This function copies the HW address from the sockaddr structure to the |
408 | * net_device structure and updates the address in HW. |
409 | * |
410 | * returns: -EBUSY if the net device is busy or 0 if the address is set |
411 | * successfully. |
412 | */ |
413 | static s32 nps_enet_set_mac_address(struct net_device *ndev, void *p) |
414 | { |
415 | struct sockaddr *addr = p; |
416 | s32 res; |
417 | |
418 | if (netif_running(dev: ndev)) |
419 | return -EBUSY; |
420 | |
421 | res = eth_mac_addr(dev: ndev, p); |
422 | if (!res) { |
423 | eth_hw_addr_set(dev: ndev, addr: addr->sa_data); |
424 | nps_enet_set_hw_mac_address(ndev); |
425 | } |
426 | |
427 | return res; |
428 | } |
429 | |
430 | /** |
431 | * nps_enet_set_rx_mode - Change the receive filtering mode. |
432 | * @ndev: Pointer to the network device. |
433 | * |
434 | * This function enables/disables promiscuous mode |
435 | */ |
436 | static void nps_enet_set_rx_mode(struct net_device *ndev) |
437 | { |
438 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
439 | u32 ge_mac_cfg_2_value = priv->ge_mac_cfg_2_value; |
440 | |
441 | if (ndev->flags & IFF_PROMISC) { |
442 | ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) |
443 | | NPS_ENET_DISABLE << CFG_2_DISK_DA_SHIFT; |
444 | ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) |
445 | | NPS_ENET_DISABLE << CFG_2_DISK_MC_SHIFT; |
446 | |
447 | } else { |
448 | ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_DA_MASK) |
449 | | NPS_ENET_ENABLE << CFG_2_DISK_DA_SHIFT; |
450 | ge_mac_cfg_2_value = (ge_mac_cfg_2_value & ~CFG_2_DISK_MC_MASK) |
451 | | NPS_ENET_ENABLE << CFG_2_DISK_MC_SHIFT; |
452 | } |
453 | |
454 | nps_enet_reg_set(priv, NPS_ENET_REG_GE_MAC_CFG_2, value: ge_mac_cfg_2_value); |
455 | } |
456 | |
457 | /** |
458 | * nps_enet_open - Open the network device. |
459 | * @ndev: Pointer to the network device. |
460 | * |
461 | * returns: 0, on success or non-zero error value on failure. |
462 | * |
463 | * This function sets the MAC address, requests and enables an IRQ |
464 | * for the ENET device and starts the Tx queue. |
465 | */ |
466 | static s32 nps_enet_open(struct net_device *ndev) |
467 | { |
468 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
469 | s32 err; |
470 | |
471 | /* Reset private variables */ |
472 | priv->tx_skb = NULL; |
473 | priv->ge_mac_cfg_2_value = 0; |
474 | priv->ge_mac_cfg_3_value = 0; |
475 | |
476 | /* ge_mac_cfg_3 default values */ |
477 | priv->ge_mac_cfg_3_value |= |
478 | NPS_ENET_GE_MAC_CFG_3_RX_IFG_TH << CFG_3_RX_IFG_TH_SHIFT; |
479 | |
480 | priv->ge_mac_cfg_3_value |= |
481 | NPS_ENET_GE_MAC_CFG_3_MAX_LEN << CFG_3_MAX_LEN_SHIFT; |
482 | |
483 | /* Disable HW device */ |
484 | nps_enet_hw_disable_control(ndev); |
485 | |
486 | /* irq Rx allocation */ |
487 | err = request_irq(irq: priv->irq, handler: nps_enet_irq_handler, |
488 | flags: 0, name: "enet-rx-tx" , dev: ndev); |
489 | if (err) |
490 | return err; |
491 | |
492 | napi_enable(n: &priv->napi); |
493 | |
494 | /* Enable HW device */ |
495 | nps_enet_hw_reset(ndev); |
496 | nps_enet_hw_enable_control(ndev); |
497 | |
498 | netif_start_queue(dev: ndev); |
499 | |
500 | return 0; |
501 | } |
502 | |
503 | /** |
504 | * nps_enet_stop - Close the network device. |
505 | * @ndev: Pointer to the network device. |
506 | * |
507 | * This function stops the Tx queue, disables interrupts for the ENET device. |
508 | */ |
509 | static s32 nps_enet_stop(struct net_device *ndev) |
510 | { |
511 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
512 | |
513 | napi_disable(n: &priv->napi); |
514 | netif_stop_queue(dev: ndev); |
515 | nps_enet_hw_disable_control(ndev); |
516 | free_irq(priv->irq, ndev); |
517 | |
518 | return 0; |
519 | } |
520 | |
521 | /** |
522 | * nps_enet_start_xmit - Starts the data transmission. |
523 | * @skb: sk_buff pointer that contains data to be Transmitted. |
524 | * @ndev: Pointer to net_device structure. |
525 | * |
526 | * returns: NETDEV_TX_OK, on success |
527 | * NETDEV_TX_BUSY, if any of the descriptors are not free. |
528 | * |
529 | * This function is invoked from upper layers to initiate transmission. |
530 | */ |
531 | static netdev_tx_t nps_enet_start_xmit(struct sk_buff *skb, |
532 | struct net_device *ndev) |
533 | { |
534 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
535 | |
536 | /* This driver handles one frame at a time */ |
537 | netif_stop_queue(dev: ndev); |
538 | |
539 | priv->tx_skb = skb; |
540 | |
541 | /* make sure tx_skb is actually written to the memory |
542 | * before the HW is informed and the IRQ is fired. |
543 | */ |
544 | wmb(); |
545 | |
546 | nps_enet_send_frame(ndev, skb); |
547 | |
548 | return NETDEV_TX_OK; |
549 | } |
550 | |
551 | #ifdef CONFIG_NET_POLL_CONTROLLER |
552 | static void nps_enet_poll_controller(struct net_device *ndev) |
553 | { |
554 | disable_irq(irq: ndev->irq); |
555 | nps_enet_irq_handler(irq: ndev->irq, dev_instance: ndev); |
556 | enable_irq(irq: ndev->irq); |
557 | } |
558 | #endif |
559 | |
560 | static const struct net_device_ops nps_netdev_ops = { |
561 | .ndo_open = nps_enet_open, |
562 | .ndo_stop = nps_enet_stop, |
563 | .ndo_start_xmit = nps_enet_start_xmit, |
564 | .ndo_set_mac_address = nps_enet_set_mac_address, |
565 | .ndo_set_rx_mode = nps_enet_set_rx_mode, |
566 | #ifdef CONFIG_NET_POLL_CONTROLLER |
567 | .ndo_poll_controller = nps_enet_poll_controller, |
568 | #endif |
569 | }; |
570 | |
571 | static s32 nps_enet_probe(struct platform_device *pdev) |
572 | { |
573 | struct device *dev = &pdev->dev; |
574 | struct net_device *ndev; |
575 | struct nps_enet_priv *priv; |
576 | s32 err = 0; |
577 | |
578 | if (!dev->of_node) |
579 | return -ENODEV; |
580 | |
581 | ndev = alloc_etherdev(sizeof(struct nps_enet_priv)); |
582 | if (!ndev) |
583 | return -ENOMEM; |
584 | |
585 | platform_set_drvdata(pdev, data: ndev); |
586 | SET_NETDEV_DEV(ndev, dev); |
587 | priv = netdev_priv(dev: ndev); |
588 | |
589 | /* The EZ NET specific entries in the device structure. */ |
590 | ndev->netdev_ops = &nps_netdev_ops; |
591 | ndev->watchdog_timeo = (400 * HZ / 1000); |
592 | /* FIXME :: no multicast support yet */ |
593 | ndev->flags &= ~IFF_MULTICAST; |
594 | |
595 | priv->regs_base = devm_platform_ioremap_resource(pdev, index: 0); |
596 | if (IS_ERR(ptr: priv->regs_base)) { |
597 | err = PTR_ERR(ptr: priv->regs_base); |
598 | goto out_netdev; |
599 | } |
600 | dev_dbg(dev, "Registers base address is 0x%p\n" , priv->regs_base); |
601 | |
602 | /* set kernel MAC address to dev */ |
603 | err = of_get_ethdev_address(np: dev->of_node, dev: ndev); |
604 | if (err) |
605 | eth_hw_addr_random(dev: ndev); |
606 | |
607 | /* Get IRQ number */ |
608 | priv->irq = platform_get_irq(pdev, 0); |
609 | if (priv->irq < 0) { |
610 | err = -ENODEV; |
611 | goto out_netdev; |
612 | } |
613 | |
614 | netif_napi_add_weight(dev: ndev, napi: &priv->napi, poll: nps_enet_poll, |
615 | NPS_ENET_NAPI_POLL_WEIGHT); |
616 | |
617 | /* Register the driver. Should be the last thing in probe */ |
618 | err = register_netdev(dev: ndev); |
619 | if (err) { |
620 | dev_err(dev, "Failed to register ndev for %s, err = 0x%08x\n" , |
621 | ndev->name, (s32)err); |
622 | goto out_netif_api; |
623 | } |
624 | |
625 | dev_info(dev, "(rx/tx=%d)\n" , priv->irq); |
626 | return 0; |
627 | |
628 | out_netif_api: |
629 | netif_napi_del(napi: &priv->napi); |
630 | out_netdev: |
631 | free_netdev(dev: ndev); |
632 | |
633 | return err; |
634 | } |
635 | |
636 | static s32 nps_enet_remove(struct platform_device *pdev) |
637 | { |
638 | struct net_device *ndev = platform_get_drvdata(pdev); |
639 | struct nps_enet_priv *priv = netdev_priv(dev: ndev); |
640 | |
641 | unregister_netdev(dev: ndev); |
642 | netif_napi_del(napi: &priv->napi); |
643 | free_netdev(dev: ndev); |
644 | |
645 | return 0; |
646 | } |
647 | |
648 | static const struct of_device_id nps_enet_dt_ids[] = { |
649 | { .compatible = "ezchip,nps-mgt-enet" }, |
650 | { /* Sentinel */ } |
651 | }; |
652 | MODULE_DEVICE_TABLE(of, nps_enet_dt_ids); |
653 | |
654 | static struct platform_driver nps_enet_driver = { |
655 | .probe = nps_enet_probe, |
656 | .remove = nps_enet_remove, |
657 | .driver = { |
658 | .name = DRV_NAME, |
659 | .of_match_table = nps_enet_dt_ids, |
660 | }, |
661 | }; |
662 | |
663 | module_platform_driver(nps_enet_driver); |
664 | |
665 | MODULE_AUTHOR("EZchip Semiconductor" ); |
666 | MODULE_LICENSE("GPL v2" ); |
667 | |