1 /** @file
2 
3   Copyright (c) 2020 Jared McNeill. All rights reserved.
4   Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
5 
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 **/
8 
9 #include <Uefi.h>
10 #include <Library/DebugLib.h>
11 #include <Library/DmaLib.h>
12 #include <Library/IoLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 
15 #include "BcmGenetDxe.h"
16 
17 #define GENET_PHY_RETRY     1000
18 
19 STATIC CONST
20 EFI_PHYSICAL_ADDRESS   mDmaAddressLimit = FixedPcdGet64 (PcdDmaDeviceLimit) -
21                                           FixedPcdGet64 (PcdDmaDeviceOffset);
22 
23 /**
24   Read a memory-mapped device CSR.
25 
26   @param  Genet[in]   Pointer to GENERIC_PHY_PRIVATE_DATA instance.
27   @param  Offset[in]  Register offset.
28 
29   @retval Value
30 
31 **/
32 STATIC
33 UINT32
GenetMmioRead(IN GENET_PRIVATE_DATA * Genet,IN UINT32 Offset)34 GenetMmioRead (
35   IN GENET_PRIVATE_DATA *Genet,
36   IN UINT32             Offset
37   )
38 {
39   ASSERT ((Offset & 3) == 0);
40 
41   return MmioRead32 (Genet->RegBase + Offset);
42 }
43 
44 /**
45   Write a memory-mapped device CSR.
46 
47   @param  Genet[in]   Pointer to GENERIC_PHY_PRIVATE_DATA instance.
48   @param  Offset[in]  Register offset.
49   @param  Data[in]    Data to write.
50 
51   @retval Value
52 
53 **/
54 STATIC
55 VOID
GenetMmioWrite(IN GENET_PRIVATE_DATA * Genet,IN UINT32 Offset,IN UINT32 Data)56 GenetMmioWrite (
57   IN GENET_PRIVATE_DATA *Genet,
58   IN UINT32             Offset,
59   IN UINT32             Data
60   )
61 {
62   ASSERT ((Offset & 3) == 0);
63 
64   MemoryFence ();
65   MmioWrite32 (Genet->RegBase + Offset, Data);
66 }
67 
68 /**
69   Perform a GENET PHY register read.
70 
71   @param  Priv[in]     Pointer to GENET_PRIVATE_DATA.
72   @param  PhyAddr[in]  PHY address.
73   @param  Reg[in]      PHY register.
74   @param  Data[out]    Pointer to register data read.
75 
76   @retval EFI_SUCCESS       Data read successfully.
77   @retval EFI_DEVICE_ERROR  Failed to read data.
78 
79 **/
80 EFI_STATUS
81 EFIAPI
GenetPhyRead(IN VOID * Priv,IN UINT8 PhyAddr,IN UINT8 Reg,OUT UINT16 * Data)82 GenetPhyRead (
83   IN  VOID   *Priv,
84   IN  UINT8  PhyAddr,
85   IN  UINT8  Reg,
86   OUT UINT16 *Data
87   )
88 {
89   GENET_PRIVATE_DATA   *Genet;
90   UINTN                Retry;
91   UINT32               Value;
92 
93   Genet = Priv;
94   Value = GENET_MDIO_READ |
95           GENET_MDIO_START_BUSY |
96           SHIFTIN (PhyAddr, GENET_MDIO_PMD) |
97           SHIFTIN (Reg, GENET_MDIO_REG);
98   GenetMmioWrite (Genet, GENET_MDIO_CMD, Value);
99 
100   for (Retry = GENET_PHY_RETRY; Retry > 0; Retry--) {
101     Value = GenetMmioRead (Genet, GENET_MDIO_CMD);
102     if ((Value & GENET_MDIO_START_BUSY) == 0) {
103       *Data = Value & 0xffff;
104       break;
105     }
106     gBS->Stall (10);
107   }
108 
109   if (Retry == 0) {
110     DEBUG ((DEBUG_ERROR,
111       "%a: Timeout reading PhyAddr %d, Reg %d\n", __FUNCTION__, PhyAddr, Reg));
112     return EFI_DEVICE_ERROR;
113   }
114 
115   return EFI_SUCCESS;
116 }
117 
118 /**
119   Perform a GENET PHY register write.
120 
121   @param  Priv[in]     Pointer to GENET_PRIVATE_DATA.
122   @param  PhyAddr[in]  PHY address.
123   @param  Reg[in]      PHY register.
124   @param  Data[in]     Pointer to register data to write.
125 
126   @retval EFI_SUCCESS       Data written successfully.
127   @retval EFI_DEVICE_ERROR  Failed to write data.
128 
129 **/
130 EFI_STATUS
131 EFIAPI
GenetPhyWrite(IN VOID * Priv,IN UINT8 PhyAddr,IN UINT8 Reg,IN UINT16 Data)132 GenetPhyWrite (
133   IN VOID   *Priv,
134   IN UINT8  PhyAddr,
135   IN UINT8  Reg,
136   IN UINT16 Data
137   )
138 {
139   GENET_PRIVATE_DATA    *Genet;
140   UINTN                 Retry;
141   UINT32                Value;
142 
143   Genet = Priv;
144   Value = GENET_MDIO_WRITE |
145           GENET_MDIO_START_BUSY |
146           SHIFTIN (PhyAddr, GENET_MDIO_PMD) |
147           SHIFTIN (Reg, GENET_MDIO_REG);
148   GenetMmioWrite (Genet, GENET_MDIO_CMD, Value | Data);
149 
150   for (Retry = GENET_PHY_RETRY; Retry > 0; Retry--) {
151     Value = GenetMmioRead (Genet, GENET_MDIO_CMD);
152     if ((Value & GENET_MDIO_START_BUSY) == 0) {
153       break;
154     }
155     gBS->Stall (10);
156   }
157 
158   if (Retry == 0) {
159     DEBUG ((DEBUG_ERROR,
160       "%a: Timeout writing PhyAddr %d, Reg %d\n", __FUNCTION__, PhyAddr, Reg));
161     return EFI_DEVICE_ERROR;
162   }
163 
164   return EFI_SUCCESS;
165 }
166 
167 /**
168   Process a PHY link speed change (e.g. with MAC layer).
169 
170   @param  Priv[in]    Pointer to GENET_PRIVATE_DATA.
171   @param  Speed[in]   Speed setting.
172   @param  Duplex[in]  Duplex setting.
173 
174 **/
175 VOID
176 EFIAPI
GenetPhyConfigure(IN VOID * Priv,IN GENERIC_PHY_SPEED Speed,IN GENERIC_PHY_DUPLEX Duplex)177 GenetPhyConfigure (
178   IN VOID               *Priv,
179   IN GENERIC_PHY_SPEED  Speed,
180   IN GENERIC_PHY_DUPLEX Duplex
181   )
182 {
183   GENET_PRIVATE_DATA  *Genet;
184   UINT32              Value;
185 
186   Genet = Priv;
187   Value = GenetMmioRead (Genet, GENET_EXT_RGMII_OOB_CTRL);
188   Value &= ~GENET_EXT_RGMII_OOB_OOB_DISABLE;
189   Value |= GENET_EXT_RGMII_OOB_RGMII_LINK;
190   Value |= GENET_EXT_RGMII_OOB_RGMII_MODE_EN;
191   if (Genet->PhyMode == GENET_PHY_MODE_RGMII) {
192     Value |= GENET_EXT_RGMII_OOB_ID_MODE_DISABLE;
193   } else {
194     Value &= ~GENET_EXT_RGMII_OOB_ID_MODE_DISABLE;
195   }
196   GenetMmioWrite (Genet, GENET_EXT_RGMII_OOB_CTRL, Value);
197 
198   Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
199   Value &= ~GENET_UMAC_CMD_SPEED;
200   switch (Speed) {
201     case PHY_SPEED_1000:
202       Value |= SHIFTIN (GENET_UMAC_CMD_SPEED_1000, GENET_UMAC_CMD_SPEED);
203       break;
204     case PHY_SPEED_100:
205       Value |= SHIFTIN (GENET_UMAC_CMD_SPEED_100, GENET_UMAC_CMD_SPEED);
206       break;
207     default:
208       Value |= SHIFTIN (GENET_UMAC_CMD_SPEED_10, GENET_UMAC_CMD_SPEED);
209       break;
210   }
211   if (Duplex == PHY_DUPLEX_FULL) {
212     Value &= ~GENET_UMAC_CMD_HD_EN;
213   } else {
214     Value |= GENET_UMAC_CMD_HD_EN;
215   }
216   GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
217 }
218 
219 /**
220   Extra action to run after a PHY reset. This adds the appropriate clock
221   delay based on the PHY mode.
222 
223   @param  Priv[in]  Pointer to GENET_PRIVATE_DATA.
224 
225 **/
226 EFI_STATUS
227 EFIAPI
GenetPhyResetAction(IN VOID * Priv)228 GenetPhyResetAction (
229   IN VOID             *Priv
230   )
231 {
232   GENET_PRIVATE_DATA  *Genet;
233   UINT16              Value;
234   EFI_STATUS          Status;
235 
236   Genet = Priv;
237   Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL,
238              BRGPHY_AUXCTL_SHADOW_MISC |
239              (BRGPHY_AUXCTL_SHADOW_MISC << BRGPHY_AUXCTL_MISC_READ_SHIFT));
240   if (EFI_ERROR (Status)) {
241     return Status;
242   }
243 
244   Status = GenetPhyRead (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL, &Value);
245   if (EFI_ERROR (Status)) {
246     return Status;
247   }
248 
249   Value &= BRGPHY_AUXCTL_MISC_DATA_MASK;
250 
251   if (Genet->PhyMode == GENET_PHY_MODE_RGMII_RXID ||
252       Genet->PhyMode == GENET_PHY_MODE_RGMII_ID) {
253     Value |= BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN;
254   } else {
255     Value &= ~BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN;
256   }
257 
258   Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_AUXCTL,
259              BRGPHY_AUXCTL_MISC_WRITE_EN | BRGPHY_AUXCTL_SHADOW_MISC | Value);
260   if (EFI_ERROR (Status)) {
261     return Status;
262   }
263 
264   Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C,
265                           BRGPHY_SHADOW_1C_CLK_CTRL);
266   if (EFI_ERROR (Status)) {
267     return Status;
268   }
269 
270   Status = GenetPhyRead (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C, &Value);
271   if (EFI_ERROR (Status)) {
272     return Status;
273   }
274 
275   Value &= BRGPHY_SHADOW_1C_DATA_MASK;
276 
277   if (Genet->PhyMode == GENET_PHY_MODE_RGMII_TXID ||
278       Genet->PhyMode == GENET_PHY_MODE_RGMII_ID) {
279     Value |= BRGPHY_SHADOW_1C_GTXCLK_EN;
280   } else {
281     Value &= ~BRGPHY_SHADOW_1C_GTXCLK_EN;
282   }
283 
284   Status = GenetPhyWrite (Priv, Genet->Phy.PhyAddr, BRGPHY_MII_SHADOW_1C,
285              BRGPHY_SHADOW_1C_WRITE_EN | BRGPHY_SHADOW_1C_CLK_CTRL | Value);
286   if (EFI_ERROR (Status)) {
287     return Status;
288   }
289 
290   return EFI_SUCCESS;
291 }
292 
293 /**
294   Reset GENET.
295 
296   @param  Genet[in]  Pointer to GENET_PRIVATE_DATA.
297 
298 **/
299 VOID
GenetReset(IN GENET_PRIVATE_DATA * Genet)300 GenetReset (
301   IN GENET_PRIVATE_DATA   *Genet
302   )
303 {
304   UINT32  Value;
305 
306   Value = GenetMmioRead (Genet, GENET_SYS_RBUF_FLUSH_CTRL);
307   Value |= GENET_SYS_RBUF_FLUSH_RESET;
308   GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, Value);
309   gBS->Stall (10);
310 
311   Value &= ~GENET_SYS_RBUF_FLUSH_RESET;
312   GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, Value);
313   gBS->Stall (10);
314 
315   GenetMmioWrite (Genet, GENET_SYS_RBUF_FLUSH_CTRL, 0);
316   gBS->Stall (10);
317 
318   GenetMmioWrite (Genet, GENET_UMAC_CMD, 0);
319   GenetMmioWrite (Genet, GENET_UMAC_CMD,
320     GENET_UMAC_CMD_LCL_LOOP_EN | GENET_UMAC_CMD_SW_RESET);
321   gBS->Stall (10);
322   GenetMmioWrite (Genet, GENET_UMAC_CMD, 0);
323 
324   GenetMmioWrite (Genet, GENET_UMAC_MIB_CTRL,
325     GENET_UMAC_MIB_RESET_RUNT | GENET_UMAC_MIB_RESET_RX | GENET_UMAC_MIB_RESET_TX);
326   GenetMmioWrite (Genet, GENET_UMAC_MIB_CTRL, 0);
327 
328   GenetMmioWrite (Genet, GENET_UMAC_MAX_FRAME_LEN, GENET_MAX_PACKET_SIZE);
329 
330   Value = GenetMmioRead (Genet, GENET_RBUF_CTRL);
331   Value |= GENET_RBUF_ALIGN_2B;
332   GenetMmioWrite (Genet, GENET_RBUF_CTRL, Value);
333 
334   GenetMmioWrite (Genet, GENET_RBUF_TBUF_SIZE_CTRL, 1);
335 }
336 
337 /**
338   Set the station address.
339 
340   @param  Genet[in]    Pointer to GENET_PRIVATE_DATA.
341   @param  MacAddr[in]  MAC address to set.
342 
343 **/
344 VOID
345 EFIAPI
GenetSetMacAddress(IN GENET_PRIVATE_DATA * Genet,IN EFI_MAC_ADDRESS * MacAddr)346 GenetSetMacAddress (
347   IN GENET_PRIVATE_DATA   *Genet,
348   IN EFI_MAC_ADDRESS      *MacAddr
349   )
350 {
351   UINT32  Value;
352 
353   Value = MacAddr->Addr[3] |
354           MacAddr->Addr[2] << 8 |
355           MacAddr->Addr[1] << 16 |
356           MacAddr->Addr[0] << 24;
357   GenetMmioWrite (Genet, GENET_UMAC_MAC0, Value);
358   Value = MacAddr->Addr[5] |
359           MacAddr->Addr[4] << 8;
360   GenetMmioWrite (Genet, GENET_UMAC_MAC1, Value);
361 }
362 
363 /**
364   Set a PHY mode.
365 
366   @param  Genet[in]    Pointer to GENET_PRIVATE_DATA.
367   @param  PhyMode[in]  Mode to set.
368 
369 **/
370 VOID
GenetSetPhyMode(IN GENET_PRIVATE_DATA * Genet,IN GENET_PHY_MODE PhyMode)371 GenetSetPhyMode (
372   IN GENET_PRIVATE_DATA   *Genet,
373   IN GENET_PHY_MODE       PhyMode
374   )
375 {
376   UINT32  Value;
377 
378   switch (PhyMode) {
379     case GENET_PHY_MODE_RGMII:
380     case GENET_PHY_MODE_RGMII_RXID:
381     case GENET_PHY_MODE_RGMII_TXID:
382     case GENET_PHY_MODE_RGMII_ID:
383       Value = GENET_SYS_PORT_MODE_EXT_GPHY;
384       break;
385     default:
386       Value = 0;
387       break;
388   }
389   GenetMmioWrite (Genet, GENET_SYS_PORT_CTRL, Value);
390 }
391 
392 /**
393   Enable TX/RX.
394 
395   @param  Genet[in]  Pointer to GENET_PRIVATE_DATA.
396 
397 **/
398 VOID
GenetEnableTxRx(IN GENET_PRIVATE_DATA * Genet)399 GenetEnableTxRx (
400   IN GENET_PRIVATE_DATA   *Genet
401   )
402 {
403   UINT32 Value;
404 
405   // Start TX DMA on default queue
406   Value = GenetMmioRead (Genet, GENET_TX_DMA_CTRL);
407   Value |= GENET_TX_DMA_CTRL_EN |
408            GENET_TX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
409   GenetMmioWrite (Genet, GENET_TX_DMA_CTRL, Value);
410 
411   // Start RX DMA on default queue
412   Value = GenetMmioRead (Genet, GENET_RX_DMA_CTRL);
413   Value |= GENET_RX_DMA_CTRL_EN |
414            GENET_RX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
415   GenetMmioWrite (Genet, GENET_RX_DMA_CTRL, Value);
416 
417   // Enable transmitter and receiver
418   Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
419   Value |= GENET_UMAC_CMD_TXEN | GENET_UMAC_CMD_RXEN;
420   GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
421 
422   // Enable interrupts
423   GenetMmioWrite (Genet, GENET_INTRL2_CPU_CLEAR_MASK,
424     GENET_IRQ_TXDMA_DONE | GENET_IRQ_RXDMA_DONE);
425 }
426 
427 /**
428   Disable TX/RX.
429 
430   @param  Genet[in]  Pointer to GENET_PRIVATE_DATA.
431 
432 **/
433 VOID
GenetDisableTxRx(IN GENET_PRIVATE_DATA * Genet)434 GenetDisableTxRx (
435   IN GENET_PRIVATE_DATA   *Genet
436   )
437 {
438   UINT32  Value;
439 
440   // Disable interrupts
441   GenetMmioWrite (Genet, GENET_INTRL2_CPU_SET_MASK, 0xFFFFFFFF);
442   GenetMmioWrite (Genet, GENET_INTRL2_CPU_CLEAR, 0xFFFFFFFF);
443 
444   // Disable receiver
445   Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
446   Value &= ~GENET_UMAC_CMD_RXEN;
447   GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
448 
449   // Stop RX DMA
450   Value = GenetMmioRead (Genet, GENET_RX_DMA_CTRL);
451   Value &= ~GENET_RX_DMA_CTRL_EN;
452   Value &= ~GENET_RX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
453   GenetMmioWrite (Genet, GENET_RX_DMA_CTRL, Value);
454 
455   // Stop TX DMA
456   Value = GenetMmioRead (Genet, GENET_TX_DMA_CTRL);
457   Value &= ~GENET_TX_DMA_CTRL_EN;
458   Value &= ~GENET_TX_DMA_CTRL_RBUF_EN (GENET_DMA_DEFAULT_QUEUE);
459   GenetMmioWrite (Genet, GENET_TX_DMA_CTRL, Value);
460 
461   // Flush data in the TX FIFO
462   GenetMmioWrite (Genet, GENET_UMAC_TX_FLUSH, 1);
463   gBS->Stall (10);
464   GenetMmioWrite (Genet, GENET_UMAC_TX_FLUSH, 0);
465 
466   // Disable transmitter
467   Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
468   Value &= ~GENET_UMAC_CMD_TXEN;
469   GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
470 }
471 
472 /**
473   Change promiscuous mode state.
474 
475   @param  Genet[in]   Pointer to GENET_PRIVATE_DATA.
476   @param  Enable[in]  Promiscuous mode state.
477 
478 **/
479 VOID
GenetSetPromisc(IN GENET_PRIVATE_DATA * Genet,IN BOOLEAN Enable)480 GenetSetPromisc (
481   IN GENET_PRIVATE_DATA   *Genet,
482   IN BOOLEAN              Enable
483   )
484 {
485   UINT32 Value;
486 
487   Value = GenetMmioRead (Genet, GENET_UMAC_CMD);
488   if (Enable) {
489     Value |= GENET_UMAC_CMD_PROMISC;
490   } else {
491     Value &= ~GENET_UMAC_CMD_PROMISC;
492   }
493   GenetMmioWrite (Genet, GENET_UMAC_CMD, Value);
494 }
495 
496 /**
497   Enable the MAC filter for the Ethernet broadcast address
498 
499   @param  Genet[in]   Pointer to GENET_PRIVATE_DATA.
500   @param  Enable[in]  Promiscuous mode state.
501 
502 **/
503 VOID
GenetEnableBroadcastFilter(IN GENET_PRIVATE_DATA * Genet,IN BOOLEAN Enable)504 GenetEnableBroadcastFilter (
505   IN GENET_PRIVATE_DATA   *Genet,
506   IN BOOLEAN              Enable
507   )
508 {
509   CONST EFI_MAC_ADDRESS   *MacAddr;
510   UINT32                  Value;
511 
512   if (Enable) {
513     MacAddr = &Genet->SnpMode.CurrentAddress;
514 
515     GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR0 (0),
516       MacAddr->Addr[1] | MacAddr->Addr[0] << 8);
517     GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR1 (0),
518       MacAddr->Addr[5] | MacAddr->Addr[4] << 8 |
519       MacAddr->Addr[3] << 16 | MacAddr->Addr[2] << 24);
520 
521     GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR0 (1), 0xffff);
522     GenetMmioWrite (Genet, GENET_UMAC_MDF_ADDR1 (1), 0xffffffff);
523 
524     Value = BIT16 | BIT15; // enable filters 0 and 1
525   } else {
526     Value = 0;
527   }
528   GenetMmioWrite (Genet, GENET_UMAC_MDF_CTRL, Value);
529 }
530 
531 /**
532   Configure DMA TX and RX queues, enabling them.
533 
534   @param  Genet[in]  Pointer to GENET_PRIVATE_DATA.
535 
536 **/
537 VOID
GenetDmaInitRings(IN GENET_PRIVATE_DATA * Genet)538 GenetDmaInitRings (
539   IN GENET_PRIVATE_DATA *Genet
540   )
541 {
542   UINT8 Qid;
543 
544   Qid = GENET_DMA_DEFAULT_QUEUE;
545 
546   Genet->TxQueued = 0;
547   Genet->TxNext = 0;
548   Genet->TxConsIndex = 0;
549   Genet->TxProdIndex = 0;
550 
551   Genet->RxConsIndex = 0;
552   Genet->RxProdIndex = 0;
553 
554   // Configure TX queue
555   GenetMmioWrite (Genet, GENET_TX_SCB_BURST_SIZE, 0x08);
556   GenetMmioWrite (Genet, GENET_TX_DMA_READ_PTR_LO (Qid), 0);
557   GenetMmioWrite (Genet, GENET_TX_DMA_READ_PTR_HI (Qid), 0);
558   GenetMmioWrite (Genet, GENET_TX_DMA_CONS_INDEX (Qid), 0);
559   GenetMmioWrite (Genet, GENET_TX_DMA_PROD_INDEX (Qid), 0);
560   GenetMmioWrite (Genet, GENET_TX_DMA_RING_BUF_SIZE (Qid),
561     SHIFTIN (GENET_DMA_DESC_COUNT, GENET_TX_DMA_RING_BUF_SIZE_DESC_COUNT) |
562     SHIFTIN (GENET_MAX_PACKET_SIZE, GENET_TX_DMA_RING_BUF_SIZE_BUF_LENGTH));
563   GenetMmioWrite (Genet, GENET_TX_DMA_START_ADDR_LO (Qid), 0);
564   GenetMmioWrite (Genet, GENET_TX_DMA_START_ADDR_HI (Qid), 0);
565   GenetMmioWrite (Genet, GENET_TX_DMA_END_ADDR_LO (Qid),
566     GENET_DMA_DESC_COUNT * GENET_DMA_DESC_SIZE / 4 - 1);
567   GenetMmioWrite (Genet, GENET_TX_DMA_END_ADDR_HI (Qid), 0);
568   GenetMmioWrite (Genet, GENET_TX_DMA_MBUF_DONE_THRES (Qid), 1);
569   GenetMmioWrite (Genet, GENET_TX_DMA_FLOW_PERIOD (Qid), 0);
570   GenetMmioWrite (Genet, GENET_TX_DMA_WRITE_PTR_LO (Qid), 0);
571   GenetMmioWrite (Genet, GENET_TX_DMA_WRITE_PTR_HI (Qid), 0);
572 
573   // Enable TX queue
574   GenetMmioWrite (Genet, GENET_TX_DMA_RING_CFG, (1U << Qid));
575 
576   // Configure RX queue
577   GenetMmioWrite (Genet, GENET_RX_SCB_BURST_SIZE, 0x08);
578   GenetMmioWrite (Genet, GENET_RX_DMA_WRITE_PTR_LO (Qid), 0);
579   GenetMmioWrite (Genet, GENET_RX_DMA_WRITE_PTR_HI (Qid), 0);
580   GenetMmioWrite (Genet, GENET_RX_DMA_PROD_INDEX (Qid), 0);
581   GenetMmioWrite (Genet, GENET_RX_DMA_CONS_INDEX (Qid), 0);
582   GenetMmioWrite (Genet, GENET_RX_DMA_RING_BUF_SIZE (Qid),
583     SHIFTIN (GENET_DMA_DESC_COUNT, GENET_RX_DMA_RING_BUF_SIZE_DESC_COUNT) |
584     SHIFTIN (GENET_MAX_PACKET_SIZE, GENET_RX_DMA_RING_BUF_SIZE_BUF_LENGTH));
585   GenetMmioWrite (Genet, GENET_RX_DMA_START_ADDR_LO (Qid), 0);
586   GenetMmioWrite (Genet, GENET_RX_DMA_START_ADDR_HI (Qid), 0);
587   GenetMmioWrite (Genet, GENET_RX_DMA_END_ADDR_LO (Qid),
588     GENET_DMA_DESC_COUNT * GENET_DMA_DESC_SIZE / 4 - 1);
589   GenetMmioWrite (Genet, GENET_RX_DMA_END_ADDR_HI (Qid), 0);
590   GenetMmioWrite (Genet, GENET_RX_DMA_XON_XOFF_THRES (Qid),
591     SHIFTIN (5, GENET_RX_DMA_XON_XOFF_THRES_LO) |
592     SHIFTIN (GENET_DMA_DESC_COUNT >> 4, GENET_RX_DMA_XON_XOFF_THRES_HI));
593   GenetMmioWrite (Genet, GENET_RX_DMA_READ_PTR_LO (Qid), 0);
594   GenetMmioWrite (Genet, GENET_RX_DMA_READ_PTR_HI (Qid), 0);
595 
596   // Enable RX queue
597   GenetMmioWrite (Genet, GENET_RX_DMA_RING_CFG, (1U << Qid));
598 }
599 
600 /**
601   Allocate DMA buffers for RX.
602 
603   @param  Genet[in]  Pointer to GENET_PRIVATE_DATA.
604 
605   @retval EFI_SUCCESS           DMA buffers allocated.
606   @retval EFI_OUT_OF_RESOURCES  DMA buffers could not be allocated.
607 **/
608 EFI_STATUS
GenetDmaAlloc(IN GENET_PRIVATE_DATA * Genet)609 GenetDmaAlloc (
610   IN GENET_PRIVATE_DATA   *Genet
611   )
612 {
613   EFI_STATUS              Status;
614 
615   Genet->RxBuffer = mDmaAddressLimit;
616   Status = gBS->AllocatePages (AllocateMaxAddress, EfiBootServicesData,
617                   EFI_SIZE_TO_PAGES (GENET_MAX_PACKET_SIZE * GENET_DMA_DESC_COUNT),
618                   &Genet->RxBuffer);
619   if (EFI_ERROR (Status)) {
620     DEBUG ((DEBUG_ERROR,
621       "%a: Failed to allocate RX buffer: %r\n", __FUNCTION__, Status));
622   }
623   return Status;
624 }
625 
626 /**
627   Given an RX buffer descriptor index, program the IO address of the buffer into the hardware.
628 
629   @param  Genet[in]      Pointer to GENET_PRIVATE_DATA.
630   @param  DescIndex[in]  Index of RX buffer descriptor.
631 
632   @retval EFI_SUCCESS  DMA buffers allocated.
633   @retval Others       Programmatic errors, as buffers come from DmaAllocateBuffer, and thus
634                        cannot fail DmaMap (for the expected NonCoherentDmaLib).
635 **/
636 EFI_STATUS
GenetDmaMapRxDescriptor(IN GENET_PRIVATE_DATA * Genet,IN UINT8 DescIndex)637 GenetDmaMapRxDescriptor (
638   IN GENET_PRIVATE_DATA * Genet,
639   IN UINT8                DescIndex
640   )
641 {
642   EFI_STATUS    Status;
643   UINTN         DmaNumberOfBytes;
644 
645   ASSERT (Genet->RxBufferMap[DescIndex].Mapping == NULL);
646   ASSERT (Genet->RxBuffer != 0);
647 
648   DmaNumberOfBytes = GENET_MAX_PACKET_SIZE;
649   Status = DmaMap (MapOperationBusMasterWrite,
650              GENET_RX_BUFFER (Genet, DescIndex),
651              &DmaNumberOfBytes,
652              &Genet->RxBufferMap[DescIndex].PhysAddress,
653              &Genet->RxBufferMap[DescIndex].Mapping);
654   if (EFI_ERROR (Status)) {
655     DEBUG ((DEBUG_ERROR, "%a: Failed to map RX buffer: %r\n",
656       __FUNCTION__, Status));
657     return Status;
658   }
659 
660   GenetMmioWrite (Genet, GENET_RX_DESC_ADDRESS_LO (DescIndex),
661     Genet->RxBufferMap[DescIndex].PhysAddress & 0xFFFFFFFF);
662   GenetMmioWrite (Genet, GENET_RX_DESC_ADDRESS_HI (DescIndex),
663     (Genet->RxBufferMap[DescIndex].PhysAddress >> 32) & 0xFFFFFFFF);
664   GenetMmioWrite (Genet, GENET_RX_DESC_STATUS (DescIndex), 0);
665 
666   return EFI_SUCCESS;
667 }
668 
669 /**
670   Given an RX buffer descriptor index, undo the DmaMap operation on the buffer.
671 
672   @param  Genet[in]      Pointer to GENET_PRIVATE_DATA.
673   @param  DescIndex[in]  Index of RX buffer descriptor.
674 
675 **/
676 VOID
GenetDmaUnmapRxDescriptor(IN GENET_PRIVATE_DATA * Genet,IN UINT8 DescIndex)677 GenetDmaUnmapRxDescriptor (
678   IN GENET_PRIVATE_DATA * Genet,
679   IN UINT8                DescIndex
680   )
681 {
682   if (Genet->RxBufferMap[DescIndex].Mapping != NULL) {
683     DmaUnmap (Genet->RxBufferMap[DescIndex].Mapping);
684     Genet->RxBufferMap[DescIndex].Mapping = NULL;
685   }
686 }
687 
688 /**
689   Free DMA buffers for RX, undoing GenetDmaAlloc.
690 
691   @param  Genet[in]      Pointer to GENET_PRIVATE_DATA.
692   @param  DescIndex[in]  Index of RX buffer descriptor.
693 
694 **/
695 VOID
GenetDmaFree(IN GENET_PRIVATE_DATA * Genet)696 GenetDmaFree (
697   IN GENET_PRIVATE_DATA *Genet
698   )
699 {
700   UINTN Idx;
701 
702   for (Idx = 0; Idx < GENET_DMA_DESC_COUNT; Idx++) {
703     GenetDmaUnmapRxDescriptor (Genet, Idx);
704   }
705   gBS->FreePages (Genet->RxBuffer,
706          EFI_SIZE_TO_PAGES (GENET_MAX_PACKET_SIZE * GENET_DMA_DESC_COUNT));
707 }
708 
709 /**
710   Queue TX transmission, given a buffer to transmit and a TX descriptor index.
711 
712   @param  Genet[in]          Pointer to GENET_PRIVATE_DATA.
713   @param  DescIndex[in]      TX descriptor index.
714   @param  PhysAddr[in]       Buffer to transmit.
715   @param  NumberOfBytes[in]  Buffer length.
716 
717 **/
718 VOID
GenetDmaTriggerTx(IN GENET_PRIVATE_DATA * Genet,IN UINT8 DescIndex,IN EFI_PHYSICAL_ADDRESS PhysAddr,IN UINTN NumberOfBytes)719 GenetDmaTriggerTx (
720   IN GENET_PRIVATE_DATA * Genet,
721   IN UINT8                DescIndex,
722   IN EFI_PHYSICAL_ADDRESS PhysAddr,
723   IN UINTN                NumberOfBytes
724   )
725 {
726   UINT32    DescStatus;
727 
728   DescStatus = GENET_TX_DESC_STATUS_SOP |
729                GENET_TX_DESC_STATUS_EOP |
730                GENET_TX_DESC_STATUS_CRC |
731                GENET_TX_DESC_STATUS_QTAG |
732                SHIFTIN (NumberOfBytes, GENET_TX_DESC_STATUS_BUFLEN);
733 
734   GenetMmioWrite (Genet, GENET_TX_DESC_ADDRESS_LO (DescIndex),
735     PhysAddr & 0xFFFFFFFF);
736   GenetMmioWrite (Genet, GENET_TX_DESC_ADDRESS_HI (DescIndex),
737     (PhysAddr >> 32) & 0xFFFFFFFF);
738   GenetMmioWrite (Genet, GENET_TX_DESC_STATUS (DescIndex), DescStatus);
739 
740   GenetMmioWrite (Genet, GENET_TX_DMA_PROD_INDEX (GENET_DMA_DEFAULT_QUEUE),
741     Genet->TxProdIndex);
742 }
743 
744 /**
745   Simulate a "TX interrupt", return the next (completed) TX buffer to recycle.
746 
747   @param  Genet[in]   Pointer to GENET_PRIVATE_DATA.
748   @param  TxBuf[out]  Location to store pointer to next TX buffer to recycle.
749 
750 **/
751 VOID
GenetTxIntr(IN GENET_PRIVATE_DATA * Genet,OUT VOID ** TxBuf)752 GenetTxIntr (
753   IN  GENET_PRIVATE_DATA *Genet,
754   OUT VOID               **TxBuf
755   )
756 {
757   UINT32 Total;
758 
759   Total = GenetTxPending (Genet);
760   if (Genet->TxQueued > 0 && Total > 0) {
761     DmaUnmap (Genet->TxBufferMap[Genet->TxNext]);
762     *TxBuf = Genet->TxBuffer[Genet->TxNext];
763     Genet->TxQueued--;
764     Genet->TxNext = (Genet->TxNext + 1) % GENET_DMA_DESC_COUNT;
765     Genet->TxConsIndex = (Genet->TxConsIndex + 1) & 0xFFFF;
766   } else {
767     *TxBuf = NULL;
768   }
769 }
770 
771 UINT32
GenetRxPending(IN GENET_PRIVATE_DATA * Genet)772 GenetRxPending (
773   IN  GENET_PRIVATE_DATA *Genet
774   )
775 {
776   UINT32 ProdIndex;
777   UINT32 ConsIndex;
778 
779   ConsIndex = GenetMmioRead (Genet,
780                 GENET_RX_DMA_CONS_INDEX (GENET_DMA_DEFAULT_QUEUE)) & 0xFFFF;
781   ASSERT (ConsIndex == Genet->RxConsIndex);
782 
783   ProdIndex = GenetMmioRead (Genet,
784                 GENET_RX_DMA_PROD_INDEX (GENET_DMA_DEFAULT_QUEUE)) & 0xFFFF;
785   return (ProdIndex - Genet->RxConsIndex) & 0xFFFF;
786 }
787 
788 UINT32
GenetTxPending(IN GENET_PRIVATE_DATA * Genet)789 GenetTxPending (
790   IN  GENET_PRIVATE_DATA *Genet
791   )
792 {
793   UINT32 ConsIndex;
794 
795   ConsIndex = GenetMmioRead (Genet,
796                 GENET_TX_DMA_CONS_INDEX (GENET_DMA_DEFAULT_QUEUE)) & 0xFFFF;
797 
798   return (ConsIndex - Genet->TxConsIndex) & 0xFFFF;
799 }
800 
801 VOID
GenetRxComplete(IN GENET_PRIVATE_DATA * Genet)802 GenetRxComplete (
803   IN GENET_PRIVATE_DATA *Genet
804   )
805 {
806   Genet->RxConsIndex = (Genet->RxConsIndex + 1) & 0xFFFF;
807   GenetMmioWrite (Genet, GENET_RX_DMA_CONS_INDEX (GENET_DMA_DEFAULT_QUEUE),
808                   Genet->RxConsIndex);
809 }
810 
811 /**
812   Simulate an "RX interrupt", returning the index of a completed RX buffer and
813   corresponding frame length.
814 
815   @param  Genet[in]         Pointer to GENET_PRIVATE_DATA.
816   @param  DescIndex[out]    Location to store completed RX buffer index.
817   @param  FrameLength[out]  Location to store frame length.
818 
819   @retval EFI_SUCCESS    Data received.
820   @retval EFI_NOT_READY  No RX buffers ready as no data received.
821 
822 **/
823 EFI_STATUS
GenetRxIntr(IN GENET_PRIVATE_DATA * Genet,OUT UINT8 * DescIndex,OUT UINTN * FrameLength)824 GenetRxIntr (
825   IN  GENET_PRIVATE_DATA *Genet,
826   OUT UINT8              *DescIndex,
827   OUT UINTN              *FrameLength
828   )
829 {
830   EFI_STATUS    Status;
831   UINT32        Total;
832   UINT32        DescStatus;
833 
834   Total = GenetRxPending (Genet);
835   if (Total > 0) {
836     *DescIndex = Genet->RxConsIndex % GENET_DMA_DESC_COUNT;
837     DescStatus = GenetMmioRead (Genet, GENET_RX_DESC_STATUS (*DescIndex));
838     *FrameLength = SHIFTOUT (DescStatus, GENET_RX_DESC_STATUS_BUFLEN);
839     Status = EFI_SUCCESS;
840   } else {
841     Status = EFI_NOT_READY;
842   }
843 
844   return Status;
845 }
846