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