Skip to content
Permalink
Browse files
Silicon/Broadcom/BcmGenetDxe: Add GENET driver
Add support for the Broadcom GENET v5 ethernet controller
for the Raspberry Pi 4 (BCM2711)

Co-authored-by: Jared McNeill <jmcneill@invisible.ca>
Co-authored-by: Andrei Warkentin <awarkentin@vmware.com>
Co-authored-by: Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>
Co-authored-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
Reviewed-by: Leif Lindholm <leif@nuviainc.com>
  • Loading branch information
4 people committed May 12, 2020
1 parent cc2e45a commit 8f330caf903963aadae92372b3ef0a98335c0931
Showing 9 changed files with 3,194 additions and 126 deletions.
@@ -0,0 +1,363 @@
/** @file
Copyright (c) 2020 Jared McNeill <jmcneill@invisible.ca>
Copyright (c) 2020, ARM Limited. All rights reserved.
Copyright (c) 2020 Andrey Warkentin <andrey.warkentin@gmail.com>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/

#ifndef BCM_GENET_DXE_H__
#define BCM_GENET_DXE_H__

#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Protocol/BcmGenetPlatformDevice.h>
#include <Protocol/ComponentName.h>
#include <Protocol/ComponentName2.h>
#include <Protocol/SimpleNetwork.h>

#include "GenericPhy.h"

#define LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask))
#define SHIFTOUT(__x, __mask) (((__x) & (__mask)) / LOWEST_SET_BIT (__mask))
#define SHIFTIN(__x, __mask) ((__x) * LOWEST_SET_BIT (__mask))

/*
* Aux control shadow register, bits 0-2 select function (0x00 to
* 0x07).
*/
#define BRGPHY_MII_AUXCTL 0x18 /* AUX control */
#define BRGPHY_AUXCTL_SHADOW_MISC 0x07
#define BRGPHY_AUXCTL_MISC_DATA_MASK 0x7ff8
#define BRGPHY_AUXCTL_MISC_READ_SHIFT 12
#define BRGPHY_AUXCTL_MISC_WRITE_EN 0x8000
#define BRGPHY_AUXCTL_MISC_RGMII_SKEW_EN 0x0200

/*
* Shadow register 0x1C, bit 15 is write enable,
* bits 14-10 select function (0x00 to 0x1F).
*/
#define BRGPHY_MII_SHADOW_1C 0x1C
#define BRGPHY_SHADOW_1C_WRITE_EN 0x8000
#define BRGPHY_SHADOW_1C_SELECT_MASK 0x7C00
#define BRGPHY_SHADOW_1C_DATA_MASK 0x03FF

/* Shadow 0x1C Clock Alignment Control Register (select value 0x03) */
#define BRGPHY_SHADOW_1C_CLK_CTRL (0x03 << 10)
#define BRGPHY_SHADOW_1C_GTXCLK_EN 0x0200

#define MAX_ETHERNET_PKT_SIZE 1500

#define GENET_VERSION 0x0a
#define GENET_MAX_PACKET_SIZE 1536

#define GENET_SYS_REV_CTRL 0x000
#define SYS_REV_MAJOR (BIT27|BIT26|BIT25|BIT24)
#define SYS_REV_MINOR (BIT19|BIT18|BIT17|BIT16)
#define GENET_SYS_PORT_CTRL 0x004
#define GENET_SYS_PORT_MODE_EXT_GPHY 3
#define GENET_SYS_RBUF_FLUSH_CTRL 0x008
#define GENET_SYS_RBUF_FLUSH_RESET BIT1
#define GENET_SYS_TBUF_FLUSH_CTRL 0x00c
#define GENET_EXT_RGMII_OOB_CTRL 0x08c
#define GENET_EXT_RGMII_OOB_ID_MODE_DISABLE BIT16
#define GENET_EXT_RGMII_OOB_RGMII_MODE_EN BIT6
#define GENET_EXT_RGMII_OOB_OOB_DISABLE BIT5
#define GENET_EXT_RGMII_OOB_RGMII_LINK BIT4
#define GENET_INTRL2_CPU_STAT 0x200
#define GENET_INTRL2_CPU_CLEAR 0x208
#define GENET_INTRL2_CPU_STAT_MASK 0x20c
#define GENET_INTRL2_CPU_SET_MASK 0x210
#define GENET_INTRL2_CPU_CLEAR_MASK 0x214
#define GENET_IRQ_MDIO_ERROR BIT24
#define GENET_IRQ_MDIO_DONE BIT23
#define GENET_IRQ_TXDMA_DONE BIT16
#define GENET_IRQ_RXDMA_DONE BIT13
#define GENET_RBUF_CTRL 0x300
#define GENET_RBUF_BAD_DIS BIT2
#define GENET_RBUF_ALIGN_2B BIT1
#define GENET_RBUF_64B_EN BIT0
#define GENET_RBUF_TBUF_SIZE_CTRL 0x3b4
#define GENET_UMAC_CMD 0x808
#define GENET_UMAC_CMD_LCL_LOOP_EN BIT15
#define GENET_UMAC_CMD_SW_RESET BIT13
#define GENET_UMAC_CMD_HD_EN BIT10
#define GENET_UMAC_CMD_PROMISC BIT4
#define GENET_UMAC_CMD_SPEED (BIT3|BIT2)
#define GENET_UMAC_CMD_SPEED_10 0
#define GENET_UMAC_CMD_SPEED_100 1
#define GENET_UMAC_CMD_SPEED_1000 2
#define GENET_UMAC_CMD_RXEN BIT1
#define GENET_UMAC_CMD_TXEN BIT0
#define GENET_UMAC_MAC0 0x80c
#define GENET_UMAC_MAC1 0x810
#define GENET_UMAC_MAX_FRAME_LEN 0x814
#define GENET_UMAC_TX_FLUSH 0xb34
#define GENET_UMAC_MIB_CTRL 0xd80
#define GENET_UMAC_MIB_RESET_TX BIT2
#define GENET_UMAC_MIB_RESET_RUNT BIT1
#define GENET_UMAC_MIB_RESET_RX BIT0
#define GENET_MDIO_CMD 0xe14
#define GENET_MDIO_START_BUSY BIT29
#define GENET_MDIO_READ BIT27
#define GENET_MDIO_WRITE BIT26
#define GENET_MDIO_PMD (BIT25|BIT24|BIT23|BIT22|BIT21)
#define GENET_MDIO_REG (BIT20|BIT19|BIT18|BIT17|BIT16)
#define GENET_UMAC_MDF_CTRL 0xe50
#define GENET_UMAC_MDF_ADDR0(n) (0xe54 + (n) * 0x8)
#define GENET_UMAC_MDF_ADDR1(n) (0xe58 + (n) * 0x8)
#define GENET_MAX_MDF_FILTER 17

#define GENET_DMA_DESC_COUNT 256
#define GENET_DMA_DESC_SIZE 12
#define GENET_DMA_DEFAULT_QUEUE 16

#define GENET_DMA_RING_SIZE 0x40
#define GENET_DMA_RINGS_SIZE (GENET_DMA_RING_SIZE * (GENET_DMA_DEFAULT_QUEUE + 1))

#define GENET_RX_BASE 0x2000
#define GENET_TX_BASE 0x4000

#define GENET_RX_DMA_RINGBASE(qid) (GENET_RX_BASE + 0xc00 + GENET_DMA_RING_SIZE * (qid))
#define GENET_RX_DMA_WRITE_PTR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x00)
#define GENET_RX_DMA_WRITE_PTR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x04)
#define GENET_RX_DMA_PROD_INDEX(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x08)
#define GENET_RX_DMA_CONS_INDEX(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x0c)
#define GENET_RX_DMA_RING_BUF_SIZE(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x10)
#define GENET_RX_DMA_RING_BUF_SIZE_DESC_COUNT 0xffff0000
#define GENET_RX_DMA_RING_BUF_SIZE_BUF_LENGTH 0x0000ffff
#define GENET_RX_DMA_START_ADDR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x14)
#define GENET_RX_DMA_START_ADDR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x18)
#define GENET_RX_DMA_END_ADDR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x1c)
#define GENET_RX_DMA_END_ADDR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x20)
#define GENET_RX_DMA_XON_XOFF_THRES(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x28)
#define GENET_RX_DMA_XON_XOFF_THRES_LO 0xffff0000
#define GENET_RX_DMA_XON_XOFF_THRES_HI 0x0000ffff
#define GENET_RX_DMA_READ_PTR_LO(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x2c)
#define GENET_RX_DMA_READ_PTR_HI(qid) (GENET_RX_DMA_RINGBASE(qid) + 0x30)

#define GENET_TX_DMA_RINGBASE(qid) (GENET_TX_BASE + 0xc00 + GENET_DMA_RING_SIZE * (qid))
#define GENET_TX_DMA_READ_PTR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x00)
#define GENET_TX_DMA_READ_PTR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x04)
#define GENET_TX_DMA_CONS_INDEX(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x08)
#define GENET_TX_DMA_PROD_INDEX(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x0c)
#define GENET_TX_DMA_RING_BUF_SIZE(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x10)
#define GENET_TX_DMA_RING_BUF_SIZE_DESC_COUNT 0xffff0000
#define GENET_TX_DMA_RING_BUF_SIZE_BUF_LENGTH 0x0000ffff
#define GENET_TX_DMA_START_ADDR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x14)
#define GENET_TX_DMA_START_ADDR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x18)
#define GENET_TX_DMA_END_ADDR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x1c)
#define GENET_TX_DMA_END_ADDR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x20)
#define GENET_TX_DMA_MBUF_DONE_THRES(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x24)
#define GENET_TX_DMA_FLOW_PERIOD(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x28)
#define GENET_TX_DMA_WRITE_PTR_LO(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x2c)
#define GENET_TX_DMA_WRITE_PTR_HI(qid) (GENET_TX_DMA_RINGBASE(qid) + 0x30)

#define GENET_RX_DESC_STATUS(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x00)
#define GENET_RX_DESC_STATUS_BUFLEN (BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)
#define GENET_RX_DESC_STATUS_OWN BIT15
#define GENET_RX_DESC_STATUS_EOP BIT14
#define GENET_RX_DESC_STATUS_SOP BIT13
#define GENET_RX_DESC_STATUS_RX_ERROR BIT2
#define GENET_RX_DESC_ADDRESS_LO(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x04)
#define GENET_RX_DESC_ADDRESS_HI(idx) (GENET_RX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x08)

#define GENET_TX_DESC_STATUS(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x00)
#define GENET_TX_DESC_STATUS_BUFLEN (BIT27|BIT26|BIT25|BIT24|BIT23|BIT22|BIT21|BIT20|BIT19|BIT18|BIT17|BIT16)
#define GENET_TX_DESC_STATUS_OWN BIT15
#define GENET_TX_DESC_STATUS_EOP BIT14
#define GENET_TX_DESC_STATUS_SOP BIT13
#define GENET_TX_DESC_STATUS_QTAG (BIT12|BIT11|BIT10|BIT9|BIT8|BIT7)
#define GENET_TX_DESC_STATUS_CRC BIT6
#define GENET_TX_DESC_ADDRESS_LO(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x04)
#define GENET_TX_DESC_ADDRESS_HI(idx) (GENET_TX_BASE + GENET_DMA_DESC_SIZE * (idx) + 0x08)

#define GENET_RX_DMA_RING_CFG (GENET_RX_BASE + 0x1040 + 0x00)
#define GENET_RX_DMA_CTRL (GENET_RX_BASE + 0x1040 + 0x04)
#define GENET_RX_DMA_CTRL_RBUF_EN(qid) (BIT1 << (qid))
#define GENET_RX_DMA_CTRL_EN BIT0
#define GENET_RX_SCB_BURST_SIZE (GENET_RX_BASE + 0x1040 + 0x0c)

#define GENET_TX_DMA_RING_CFG (GENET_TX_BASE + 0x1040 + 0x00)
#define GENET_TX_DMA_CTRL (GENET_TX_BASE + 0x1040 + 0x04)
#define GENET_TX_DMA_CTRL_RBUF_EN(qid) (BIT1 << (qid))
#define GENET_TX_DMA_CTRL_EN BIT0
#define GENET_TX_SCB_BURST_SIZE (GENET_TX_BASE + 0x1040 + 0x0c)

typedef struct {
EFI_PHYSICAL_ADDRESS PhysAddress;
VOID * Mapping;
} GENET_MAP_INFO;

typedef enum {
GENET_PHY_MODE_MII,
GENET_PHY_MODE_RGMII,
GENET_PHY_MODE_RGMII_RXID,
GENET_PHY_MODE_RGMII_TXID,
GENET_PHY_MODE_RGMII_ID,
} GENET_PHY_MODE;

typedef struct {
UINT32 Signature;
EFI_HANDLE ControllerHandle;

EFI_LOCK Lock;
EFI_EVENT ExitBootServicesEvent;

EFI_SIMPLE_NETWORK_PROTOCOL Snp;
EFI_SIMPLE_NETWORK_MODE SnpMode;

BCM_GENET_PLATFORM_DEVICE_PROTOCOL *Dev;

GENERIC_PHY_PRIVATE_DATA Phy;

UINT8 *TxBuffer[GENET_DMA_DESC_COUNT];
VOID *TxBufferMap[GENET_DMA_DESC_COUNT];
UINT8 TxQueued;
UINT16 TxNext;
UINT16 TxConsIndex;
UINT16 TxProdIndex;

EFI_PHYSICAL_ADDRESS RxBuffer;
GENET_MAP_INFO RxBufferMap[GENET_DMA_DESC_COUNT];
UINT16 RxConsIndex;
UINT16 RxProdIndex;

GENET_PHY_MODE PhyMode;

UINTN RegBase;
} GENET_PRIVATE_DATA;

extern EFI_COMPONENT_NAME_PROTOCOL gGenetComponentName;
extern EFI_COMPONENT_NAME2_PROTOCOL gGenetComponentName2;

extern CONST EFI_SIMPLE_NETWORK_PROTOCOL gGenetSimpleNetworkTemplate;

#define GENET_DRIVER_SIGNATURE SIGNATURE_32('G', 'N', 'E', 'T')
#define GENET_PRIVATE_DATA_FROM_SNP_THIS(a) CR(a, GENET_PRIVATE_DATA, Snp, GENET_DRIVER_SIGNATURE)

#define GENET_RX_BUFFER(g, idx) ((UINT8 *)(UINTN)(g)->RxBuffer + GENET_MAX_PACKET_SIZE * (idx))

EFI_STATUS
EFIAPI
GenetPhyRead (
IN VOID *Priv,
IN UINT8 PhyAddr,
IN UINT8 Reg,
OUT UINT16 *Data
);

EFI_STATUS
EFIAPI
GenetPhyWrite (
IN VOID *Priv,
IN UINT8 PhyAddr,
IN UINT8 Reg,
IN UINT16 Data
);

EFI_STATUS
EFIAPI
GenetPhyResetAction (
IN VOID *Priv
);

VOID
EFIAPI
GenetPhyConfigure (
IN VOID *Priv,
IN GENERIC_PHY_SPEED Speed,
IN GENERIC_PHY_DUPLEX Duplex
);

VOID
GenetReset (
IN GENET_PRIVATE_DATA *Genet
);

VOID
EFIAPI
GenetSetMacAddress (
IN GENET_PRIVATE_DATA *Genet,
IN EFI_MAC_ADDRESS *MacAddr
);

VOID
GenetSetPhyMode (
IN GENET_PRIVATE_DATA *Genet,
IN GENET_PHY_MODE PhyMode
);

VOID
GenetEnableTxRx (
IN GENET_PRIVATE_DATA *Genet
);

VOID
GenetDisableTxRx (
IN GENET_PRIVATE_DATA *Genet
);

VOID
GenetSetPromisc (
IN GENET_PRIVATE_DATA *Genet,
IN BOOLEAN Enable
);

VOID
GenetEnableBroadcastFilter (
IN GENET_PRIVATE_DATA *Genet,
IN BOOLEAN Enable
);

VOID
GenetDmaInitRings (
IN GENET_PRIVATE_DATA *Genet
);

EFI_STATUS
GenetDmaAlloc (
IN GENET_PRIVATE_DATA *Genet
);

VOID
GenetDmaFree (
IN GENET_PRIVATE_DATA *Genet
);

VOID
GenetDmaTriggerTx (
IN GENET_PRIVATE_DATA *Genet,
IN UINT8 DescIndex,
IN EFI_PHYSICAL_ADDRESS PhysAddr,
IN UINTN NumberOfBytes
);

EFI_STATUS
GenetDmaMapRxDescriptor (
IN GENET_PRIVATE_DATA *Genet,
IN UINT8 DescIndex
);

VOID
GenetDmaUnmapRxDescriptor (
IN GENET_PRIVATE_DATA *Genet,
IN UINT8 DescIndex
);

VOID
GenetTxIntr (
IN GENET_PRIVATE_DATA *Genet,
OUT VOID **TxBuf
);

EFI_STATUS
GenetRxIntr (
IN GENET_PRIVATE_DATA *Genet,
OUT UINT8 *DescIndex,
OUT UINTN *FrameLength
);

#endif /* GENET_UTIL_H__ */

0 comments on commit 8f330ca

Please sign in to comment.