forked from xuos/xiuos
801 lines
22 KiB
C
801 lines
22 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause */
|
|
/*
|
|
* Copyright (c) 2021 Rockchip Electronics Co., Ltd.
|
|
*/
|
|
|
|
#include "hal_bsp.h"
|
|
#include "hal_base.h"
|
|
#include "hal_gmac.h"
|
|
#include "hal_pinctrl.h"
|
|
#include "hal_debug.h"
|
|
#include "hal_timer.h"
|
|
#include "hal_cache.h"
|
|
#include "hal_gpio.h"
|
|
#include "hal_cru.h"
|
|
#include "libserial.h"
|
|
#include "stdlib.h"
|
|
|
|
|
|
/*************************** GMAC DRIVER ****************************/
|
|
|
|
/***************************** MACRO Definition ******************************/
|
|
#define __is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
|
|
|
|
#define CONFIG_SYS_NONCACHED_MEMORY (4 << 20) /* 4M */
|
|
|
|
/* 1MB granularity */
|
|
#define MMU_SECTION_SIZE (1 << 20)
|
|
|
|
/***************************** Structure Definition **************************/
|
|
|
|
/***************************** Function Declare ******************************/
|
|
|
|
/********************* Private MACRO Definition ******************************/
|
|
#define GMAC_BUS_MAX 2
|
|
|
|
#define ARCH_DMA_MINALIGN 64
|
|
|
|
#define GMAC_DESCRIPTOR_SIZE 16
|
|
#define GMAC_DESCRIPTORS_TX 8
|
|
#define GMAC_DESCRIPTORS_RX 8
|
|
#define GMAC_DESC_TX_SIZE HAL_GMAC_ALIGN(GMAC_DESCRIPTORS_TX * GMAC_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN)
|
|
#define GMAC_DESC_RX_SIZE HAL_GMAC_ALIGN(GMAC_DESCRIPTORS_RX * GMAC_DESCRIPTOR_SIZE, ARCH_DMA_MINALIGN)
|
|
|
|
#define GMAC_RX_BUFFER_SIZE (GMAC_DESCRIPTORS_RX * HAL_GMAC_MAX_PACKET_SIZE)
|
|
#define GMAC_TX_BUFFER_SIZE (GMAC_DESCRIPTORS_TX * HAL_GMAC_MAX_PACKET_SIZE)
|
|
|
|
/* Basic mode control register. */
|
|
#define BMCR_RESV 0x003f /* Unused... */
|
|
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
|
|
#define BMCR_CTST 0x0080 /* Collision test */
|
|
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
|
|
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
|
|
#define BMCR_ISOLATE 0x0400 /* Isolate data paths from MII */
|
|
#define BMCR_PDOWN 0x0800 /* Enable low power state */
|
|
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
|
|
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
|
|
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
|
|
#define BMCR_RESET 0x8000 /* Reset to default state */
|
|
#define BMCR_SPEED10 0x0000 /* Select 10Mbps */
|
|
|
|
#define GMAC_TEST_TIMES 1600
|
|
|
|
/********************* Private Structure Definition **************************/
|
|
/* GMAC consumer config data. */
|
|
struct GMAC_ETH_CONFIG {
|
|
struct GMAC_HANDLE instance;
|
|
const struct HAL_GMAC_DEV *halDev;
|
|
eGMAC_PHY_Interface mode;
|
|
uint32_t speed;
|
|
uint32_t maxSpeed;
|
|
uint16_t phyAddr;
|
|
|
|
bool extClk;
|
|
|
|
/* phy reset gpio */
|
|
struct GPIO_REG *resetGpioBank;
|
|
ePINCTRL_GPIO_PINS resetGpioNum;
|
|
uint32_t resetDelayMs[3];
|
|
|
|
int32_t txDelay;
|
|
int32_t rxDelay;
|
|
|
|
struct GMAC_Desc *txDescs;
|
|
struct GMAC_Desc *rxDescs;
|
|
|
|
uint8_t *txBuff;
|
|
uint8_t *rxBuff;
|
|
|
|
/* MAC address info, hw address */
|
|
uint8_t macAddr[6];
|
|
};
|
|
|
|
/********************* Private Variable Definition ***************************/
|
|
#ifdef NC_MEM_BASE
|
|
static const unsigned long os_no_cache_start = (unsigned long)NC_MEM_BASE;
|
|
#else
|
|
static const unsigned long os_no_cache_start = 0;
|
|
#endif
|
|
|
|
/*
|
|
* Reserve one MMU section worth of address space below the malloc() area that
|
|
* will be mapped uncached.
|
|
*/
|
|
static unsigned long noncached_start;
|
|
static unsigned long noncached_end;
|
|
static unsigned long noncached_next;
|
|
|
|
static unsigned int m_nocachemem_inited = 0;
|
|
|
|
static uint8_t dstAddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
|
|
static struct GMAC_ETH_CONFIG ethConfigTable[] =
|
|
{
|
|
|
|
{
|
|
.halDev = &g_gmac0Dev,
|
|
.mode = PHY_INTERFACE_MODE_RGMII,
|
|
.maxSpeed = 1000,
|
|
.phyAddr = 1,
|
|
|
|
.extClk = false,
|
|
|
|
.resetGpioBank = GPIO2,
|
|
.resetGpioNum = GPIO_PIN_D3,
|
|
.resetDelayMs = { 0, 20, 100 },
|
|
|
|
.txDelay = 0x3C,
|
|
.rxDelay = 0x2f,
|
|
},
|
|
|
|
// {
|
|
// .halDev = &g_gmac1Dev,
|
|
// .mode = PHY_INTERFACE_MODE_RGMII,
|
|
// .maxSpeed = 1000,
|
|
// .phyAddr = 1,
|
|
|
|
// .extClk = false,
|
|
|
|
// .resetGpioBank = GPIO2,
|
|
// .resetGpioNum = GPIO_PIN_D1,
|
|
// .resetDelayMs = { 0, 20, 100 },
|
|
|
|
// .txDelay = 0x4f,
|
|
// .rxDelay = 0x26,
|
|
// },
|
|
};
|
|
|
|
|
|
|
|
/********************* Private Function Definition ***************************/
|
|
|
|
static void Dump_Hex(char *message, uint8_t *ptr, uint16_t buflen)
|
|
{
|
|
unsigned char *buf = (unsigned char *)ptr;
|
|
int i, j;
|
|
|
|
printf("%s package at %p, len: %d: \n", message, ptr, buflen);
|
|
for (i = 0; i < buflen; i += 16) {
|
|
printf("%08X: ", i);
|
|
|
|
for (j = 0; j < 16; j++) {
|
|
if (i + j < buflen) {
|
|
printf("%02X ", buf[i + j]);
|
|
} else {
|
|
printf(" ");
|
|
}
|
|
}
|
|
printf(" ");
|
|
|
|
for (j = 0; j < 16; j++) {
|
|
if (i + j < buflen) {
|
|
printf("%c", __is_print(buf[i + j]) ? buf[i + j] : '.');
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
static void print_desc(struct GMAC_HANDLE *pGMAC)
|
|
{
|
|
struct GMAC_Desc *desc;
|
|
int nIndex;
|
|
|
|
printf("\n");
|
|
|
|
if (pGMAC->rxDescs) {
|
|
desc = pGMAC->rxDescs;
|
|
for (nIndex = 0; nIndex < pGMAC->rxSize; nIndex++) {
|
|
desc = pGMAC->rxDescs + nIndex;
|
|
printf("rx_desc[%d]@0x%08lx={0x%lx, 0x%lx, 0x%lx, 0x%lx};\n",
|
|
nIndex, (uint32_t)desc, desc->des0, desc->des1, desc->des2, desc->des3);
|
|
}
|
|
}
|
|
|
|
if (pGMAC->txDescs) {
|
|
desc = pGMAC->txDescs;
|
|
for (nIndex = 0; nIndex < pGMAC->txSize; nIndex++) {
|
|
desc = pGMAC->txDescs + nIndex;
|
|
printf("tx_desc[%d]@0x%08lx={0x%lx, 0x%lx, 0x%lx, 0x%lx};\n",
|
|
nIndex, (uint32_t)desc, desc->des0, desc->des1, desc->des2, desc->des3);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void Dump_Regs(struct GMAC_HANDLE *pGMAC)
|
|
{
|
|
uint32_t *reg = (uint32_t *)pGMAC->pReg;
|
|
int i;
|
|
|
|
printf("\n");
|
|
|
|
for (i = 0; i < (0x200 / 0x4); i++) {
|
|
printf("offset_0x%08x: %08lx %08lx %08lx %08lx\n", i * 0x10,
|
|
*((volatile const uint32_t *)(reg + 0x4 * i)), *(volatile const uint32_t *)((reg + 0x4 * i + 1)),
|
|
*((volatile const uint32_t *)(reg + 0x4 * i + 2)), *((volatile const uint32_t *)(reg + 0x4 * i + 3)));
|
|
}
|
|
|
|
reg = reg + 0x1000 / 4;
|
|
|
|
for (i = 0; i < (0x100 / 0x4); i++) {
|
|
printf("offset_0x%08x: %08lx %08lx %08lx %08lx\n", i * 0x10 + 0x1000,
|
|
*((volatile const uint32_t *)(reg + 0x4 * i)), *((volatile const uint32_t *)(reg + 0x4 * i + 1)),
|
|
*((volatile const uint32_t *)(reg + 0x4 * i + 2)), *((volatile const uint32_t *)(reg + 0x4 * i + 3)));
|
|
}
|
|
}
|
|
|
|
static void PHY_Read(struct GMAC_HANDLE *pGMAC, uint32_t phyReg)
|
|
{
|
|
int data;
|
|
|
|
data = HAL_GMAC_MDIORead(pGMAC, pGMAC->phyConfig.phyAddress, phyReg);
|
|
if (data >= 0) {
|
|
printf("PHY_Read: %02lX --> %08X\n", phyReg, data);
|
|
} else {
|
|
printf("PHY_Read: %02lX --> faild\n", phyReg);
|
|
}
|
|
}
|
|
|
|
static void PHY_Write(uint32_t phyReg, uint32_t data)
|
|
{
|
|
struct GMAC_HANDLE *pGMAC;
|
|
int status;
|
|
|
|
status = HAL_GMAC_MDIOWrite(pGMAC, pGMAC->phyConfig.phyAddress, phyReg, data);
|
|
if (!status) {
|
|
printf("PHY_Write: %02lX --> %08lX\n", phyReg, data);
|
|
} else {
|
|
printf("PHY_Write: %02lX --> faild\n", phyReg);
|
|
}
|
|
}
|
|
|
|
static void PHY_Dump(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC)
|
|
{
|
|
int data, i;
|
|
|
|
for (i = 0; i < 32; i++) {
|
|
data = HAL_GMAC_MDIORead(pGMAC, eth->phyAddr, i);
|
|
if (data < 0) {
|
|
printf("phy_dump: %d --> faild\n", i);
|
|
break;
|
|
}
|
|
|
|
if (i % 8 == 7) {
|
|
printf("%d --> %08X\n ", i, data);
|
|
} else {
|
|
printf("%d --> %08X\n\n", i, data);
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
static void GMAC_PHY_Reset(struct GMAC_ETH_CONFIG *config)
|
|
{
|
|
if (config->resetGpioBank) {
|
|
HAL_GPIO_SetPinDirection(config->resetGpioBank,
|
|
config->resetGpioNum,
|
|
GPIO_OUT);
|
|
HAL_GPIO_SetPinLevel(config->resetGpioBank,
|
|
config->resetGpioNum,
|
|
GPIO_HIGH);
|
|
|
|
HAL_DelayMs(config->resetDelayMs[0]);
|
|
|
|
HAL_GPIO_SetPinLevel(config->resetGpioBank,
|
|
config->resetGpioNum,
|
|
GPIO_LOW);
|
|
HAL_DelayMs(config->resetDelayMs[1]);
|
|
|
|
HAL_GPIO_SetPinLevel(config->resetGpioBank,
|
|
config->resetGpioNum,
|
|
GPIO_HIGH);
|
|
HAL_DelayMs(config->resetDelayMs[2]);
|
|
}
|
|
}
|
|
|
|
static inline void NET_Random_ETHAddr(uint8_t *addr)
|
|
{
|
|
unsigned int seed = HAL_TIMER_GetCount(SYS_TIMER) | 0xffffffff;
|
|
uint8_t i;
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
addr[i] = 0xae;
|
|
}
|
|
|
|
addr[0] &= 0xfe; /* clear multicast bit */
|
|
addr[0] |= 0x02; /* set local assignment bit (IEEE802) */
|
|
}
|
|
|
|
static inline void NET_Random_Package(uint8_t *addr, uint16_t len)
|
|
{
|
|
unsigned int seed = HAL_TIMER_GetCount(SYS_TIMER) | 0xffffffff;
|
|
uint16_t i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
addr[i] = 0xae;
|
|
}
|
|
}
|
|
|
|
static void PHY_Update_Links(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC,
|
|
uint8_t id)
|
|
{
|
|
HAL_Status status;
|
|
|
|
status = HAL_GMAC_PHYStartup(pGMAC);
|
|
if (status) {
|
|
printf("HAL_PHY_Startup() failed: %d\n", status);
|
|
|
|
return;
|
|
}
|
|
HAL_DelayMs(7000);
|
|
|
|
status = HAL_GMAC_PHYUpdateLink(pGMAC);
|
|
if (status == HAL_OK) {
|
|
if (pGMAC->phyStatus.link) {
|
|
status = HAL_GMAC_PHYParseLink(pGMAC);
|
|
if (PHY_SPEED_1000M == pGMAC->phyStatus.speed) {
|
|
printf("Phy%d: 1000M link speed\n", id);
|
|
} else if (PHY_SPEED_100M == pGMAC->phyStatus.speed) {
|
|
printf("Phy%d: 100M link speed\n", id);
|
|
} else {
|
|
printf("Phy%d: 10M link speed\n", id);
|
|
}
|
|
|
|
if (PHY_DUPLEX_HALF == pGMAC->phyStatus.duplex) {
|
|
printf("Phy%d: half dumplex\n", id);
|
|
} else {
|
|
printf("Phy%d: full dumplex\n", id);
|
|
}
|
|
|
|
if (pGMAC->phyStatus.pause) {
|
|
printf("Phy%d: flow control rx/tx\n", id);
|
|
} else {
|
|
printf("Phy%d: flow control off\n", id);
|
|
}
|
|
|
|
status = HAL_GMAC_AdjustLink(pGMAC, eth->txDelay, eth->rxDelay);
|
|
if (status != HAL_OK) {
|
|
printf("HAL_GMAC_AdjustLink() failed: %d\n", status);
|
|
}
|
|
|
|
printf("Phy%d: link up.\n", id);
|
|
} else {
|
|
printf("Phy%d: link down.\n", id);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* interrupt service routine polling */
|
|
static HAL_Status GMAC_ETH_IRQ(struct GMAC_HANDLE *pGMAC)
|
|
{
|
|
HAL_Status status;
|
|
|
|
/* enter interrupt */
|
|
/* rt_interrupt_enter(); */
|
|
status = HAL_GMAC_IRQHandler(pGMAC);
|
|
|
|
if (status & DMA_HANLE_RX) {
|
|
/* a frame has been received */
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
/* leave interrupt */
|
|
/* rt_interrupt_leave(); */
|
|
}
|
|
|
|
static HAL_Status noncached_init(void)
|
|
{
|
|
unsigned long start, end;
|
|
size_t size;
|
|
|
|
if (os_no_cache_start <= 0) {
|
|
printf("Noncached_init failed, plase defined no cached memort\n");
|
|
return -1;
|
|
}
|
|
|
|
start = HAL_GMAC_ALIGN(os_no_cache_start, 64);
|
|
size = HAL_GMAC_ALIGN(CONFIG_SYS_NONCACHED_MEMORY, MMU_SECTION_SIZE);
|
|
end = start + size;
|
|
|
|
noncached_start = start;
|
|
noncached_end = end;
|
|
noncached_next = start;
|
|
m_nocachemem_inited = 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static unsigned long noncached_alloc(size_t size, size_t align)
|
|
{
|
|
if (!m_nocachemem_inited) {
|
|
if (noncached_init())
|
|
return (unsigned long)NULL;
|
|
}
|
|
|
|
unsigned long next = HAL_GMAC_ALIGN(noncached_next, align);
|
|
|
|
if (next >= noncached_end || (noncached_end - next) < size) {
|
|
return 0;
|
|
}
|
|
|
|
noncached_next = next + size;
|
|
|
|
return next;
|
|
}
|
|
|
|
static void *malloc_align(size_t size, size_t align)
|
|
{
|
|
void *align_ptr;
|
|
void *ptr;
|
|
size_t align_size;
|
|
|
|
/* align the alignment size to 4 byte */
|
|
align = ((align + 0x03) & ~0x03);
|
|
|
|
/* get total aligned size */
|
|
align_size = ((size + 0x03) & ~0x03) + align;
|
|
/* allocate memory block from heap */
|
|
ptr = malloc(align_size);
|
|
if (ptr != NULL) {
|
|
/* the allocated memory block is aligned */
|
|
if (((uint32_t)ptr & (align - 1)) == 0) {
|
|
align_ptr = (void *)((uint32_t)ptr + align);
|
|
} else {
|
|
align_ptr = (void *)(((uint32_t)ptr + (align - 1)) & ~(align - 1));
|
|
}
|
|
|
|
/* set the pointer before alignment pointer to the real pointer */
|
|
*((uint32_t *)((uint32_t)align_ptr - sizeof(void *))) = (uint32_t)ptr;
|
|
|
|
ptr = align_ptr;
|
|
}
|
|
|
|
return ptr;
|
|
}
|
|
|
|
static void free_align(void *ptr)
|
|
{
|
|
void *real_ptr;
|
|
|
|
real_ptr = (void *)*(uint32_t *)((uint32_t)ptr - sizeof(void *));
|
|
free(real_ptr);
|
|
}
|
|
|
|
/********************* Public Function Definition ****************************/
|
|
|
|
static HAL_Status GMAC_Send_Test(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC,
|
|
uint16_t len)
|
|
{
|
|
uint8_t *ptr = NULL;
|
|
HAL_Status status;
|
|
|
|
if (!pGMAC->phyStatus.link) {
|
|
return -1;
|
|
}
|
|
|
|
/* Check the frame length. */
|
|
if (len > HAL_GMAC_MAX_FRAME_SIZE) {
|
|
return -1;
|
|
}
|
|
|
|
ptr = (uint8_t *)HAL_GMAC_GetTXBuffer(pGMAC);
|
|
memcpy(ptr, dstAddr, 6);
|
|
memcpy(ptr + 6, eth->macAddr, 6);
|
|
ptr[12] = 0x40;
|
|
ptr[13] = 0x06;
|
|
ptr[14] = 0x00;
|
|
ptr[15] = 0x01;
|
|
NET_Random_Package(ptr + 16, len - 16);
|
|
|
|
if (len > 60) {
|
|
/* index */
|
|
ptr[50] = pGMAC->txDescIdx;
|
|
}
|
|
|
|
/* dump packages */
|
|
Dump_Hex("Tx", ptr, len);
|
|
|
|
HAL_DCACHE_CleanByRange((uint32_t)ptr, len);
|
|
status = HAL_GMAC_Send(pGMAC, ptr, len);
|
|
if (status) {
|
|
printf("GMAC send failed: %d\n", status);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
static uint16_t GMAC_Recv_Test(struct GMAC_HANDLE *pGMAC)
|
|
{
|
|
uint8_t *ptr = NULL;
|
|
HAL_Status status;
|
|
int32_t size;
|
|
|
|
if (!pGMAC->phyStatus.link) {
|
|
return -1;
|
|
}
|
|
|
|
status = GMAC_ETH_IRQ(pGMAC);
|
|
ptr = HAL_GMAC_Recv(pGMAC, &size);
|
|
while (status && ptr) {
|
|
if (size > 0 && ptr) {
|
|
/* dump packages */
|
|
Dump_Hex("Rx", ptr, size);
|
|
HAL_DCACHE_InvalidateByRange((uint32_t)ptr, size);
|
|
HAL_GMAC_CleanRX(pGMAC);
|
|
} else {
|
|
printf("GMAC recv failed: %ld\n", size);
|
|
|
|
return -1;
|
|
}
|
|
ptr = HAL_GMAC_Recv(pGMAC, &size);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static HAL_Status GMAC_Memory_Init(struct GMAC_ETH_CONFIG *eth, struct GMAC_HANDLE *pGMAC)
|
|
{
|
|
eth->rxDescs = (struct GMAC_Desc *)noncached_alloc(GMAC_DESC_RX_SIZE, ARCH_DMA_MINALIGN);
|
|
eth->txDescs = (struct GMAC_Desc *)noncached_alloc(GMAC_DESC_TX_SIZE, ARCH_DMA_MINALIGN);
|
|
|
|
if (!eth->rxDescs || !eth->txDescs)
|
|
return -1;
|
|
|
|
eth->rxBuff = malloc_align(GMAC_RX_BUFFER_SIZE, ARCH_DMA_MINALIGN);
|
|
eth->txBuff = malloc_align(GMAC_TX_BUFFER_SIZE, ARCH_DMA_MINALIGN);
|
|
|
|
if (!eth->rxBuff || !eth->txBuff)
|
|
return -1;
|
|
|
|
memset(eth->rxDescs, 0, GMAC_DESC_RX_SIZE);
|
|
memset(eth->txDescs, 0, GMAC_DESC_TX_SIZE);
|
|
|
|
memset(eth->rxBuff, 0, GMAC_RX_BUFFER_SIZE);
|
|
HAL_DCACHE_InvalidateByRange((uint32_t)eth->rxBuff, GMAC_RX_BUFFER_SIZE);
|
|
|
|
memset(eth->txBuff, 0, GMAC_TX_BUFFER_SIZE);
|
|
HAL_DCACHE_CleanByRange((uint32_t)eth->txBuff, GMAC_TX_BUFFER_SIZE);
|
|
|
|
HAL_GMAC_DMARxDescInit(pGMAC, eth->rxDescs, eth->rxBuff, GMAC_DESCRIPTORS_RX);
|
|
HAL_GMAC_DMATxDescInit(pGMAC, eth->txDescs, eth->txBuff, GMAC_DESCRIPTORS_TX);
|
|
|
|
print_desc(pGMAC);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static HAL_Status GMAC_Init(uint8_t id)
|
|
{
|
|
struct GMAC_ETH_CONFIG *eth;
|
|
struct GMAC_HANDLE *pGMAC;
|
|
const struct HAL_GMAC_DEV *gmacDev;
|
|
struct GMAC_PHY_Config config;
|
|
eGMAC_PHY_Interface interface;
|
|
HAL_Status status;
|
|
uint32_t freq;
|
|
|
|
HAL_ASSERT(id < GMAC_BUS_MAX);
|
|
|
|
eth = ðConfigTable[id];
|
|
if (!eth) {
|
|
return HAL_ERROR;
|
|
}
|
|
|
|
pGMAC = ð->instance;
|
|
gmacDev = eth->halDev;
|
|
|
|
/* MAC init */
|
|
interface = eth->mode;
|
|
|
|
if (interface == PHY_INTERFACE_MODE_RGMII) {
|
|
HAL_CRU_ClkSetFreq(gmacDev->clkID, 125000000);
|
|
} else {
|
|
HAL_CRU_ClkSetFreq(gmacDev->clkID, 50000000);
|
|
}
|
|
|
|
freq = HAL_CRU_ClkGetFreq(gmacDev->pclkID);
|
|
HAL_GMAC_Init(pGMAC, gmacDev->pReg, freq, interface, eth->extClk);
|
|
|
|
/* PHY Init */
|
|
config.speed = eth->speed;
|
|
config.maxSpeed = eth->maxSpeed;
|
|
config.duplexMode = PHY_DUPLEX_FULL;
|
|
config.neg = PHY_AUTONEG_ENABLE;
|
|
config.interface = interface;
|
|
config.phyAddress = eth->phyAddr;
|
|
config.features = 0;
|
|
status = HAL_GMAC_PHYInit(pGMAC, &config);
|
|
if (status) {
|
|
printf("HAL_PHY_Init() failed: %d\n", status);
|
|
|
|
return status;
|
|
}
|
|
|
|
/* MAC Address */
|
|
NET_Random_ETHAddr(eth->macAddr);
|
|
HAL_GMAC_WriteHWAddr(ð->instance, eth->macAddr);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*************************** GMAC TEST ****************************/
|
|
#define GMAC_MAX_DEVICES 2
|
|
|
|
|
|
|
|
/**
|
|
* @brief Config iomux for GMAC0
|
|
*/
|
|
static void GMAC0_Iomux_Config(void)
|
|
{
|
|
/* GMAC0 iomux */
|
|
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
|
GPIO_PIN_B6, /* gmac0_rxd0 */
|
|
PIN_CONFIG_MUX_FUNC1);
|
|
|
|
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
|
GPIO_PIN_C3 | /* gmac0_mdc */
|
|
GPIO_PIN_C4 | /* gmac0_mdio */
|
|
GPIO_PIN_C0 | /* gmac0_rxdvcrs */
|
|
GPIO_PIN_B7 | /* gmac0_rxd1 */
|
|
GPIO_PIN_A3 | /* gmac0_rxd2 */
|
|
GPIO_PIN_A4 | /* gmac0_rxd3 */
|
|
GPIO_PIN_A6 | /* gmac0_txd2 */
|
|
GPIO_PIN_A7 | /* gmac0_txd3 */
|
|
GPIO_PIN_A5, /* gmac0_rxclk */
|
|
PIN_CONFIG_MUX_FUNC2);
|
|
|
|
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
|
GPIO_PIN_B3 | /* gmac0_txd0 */
|
|
GPIO_PIN_B4 | /* gmac0_txd1 */
|
|
GPIO_PIN_B5, /* gmac0_txen */
|
|
PIN_CONFIG_MUX_FUNC1 | PIN_CONFIG_DRV_LEVEL2);
|
|
|
|
HAL_PINCTRL_SetIOMUX(GPIO_BANK2,
|
|
GPIO_PIN_A7 | /* gmac0_txd3 */
|
|
GPIO_PIN_A6, /* gmac0_txd2 */
|
|
PIN_CONFIG_MUX_FUNC2 | PIN_CONFIG_DRV_LEVEL2);
|
|
HAL_PINCTRL_SetIOMUX(GPIO_BANK2, /* gmac0_txclk */
|
|
GPIO_PIN_B0,
|
|
PIN_CONFIG_MUX_FUNC2 | PIN_CONFIG_DRV_LEVEL1);
|
|
|
|
#if 0
|
|
/* io-domian: 1.8v or 3.3v for vccio4 */
|
|
WRITE_REG_MASK_WE(GRF->IO_VSEL0,
|
|
GRF_IO_VSEL0_POC_VCCIO4_SEL18_MASK,
|
|
(1 << GRF_IO_VSEL0_POC_VCCIO4_SEL18_SHIFT));
|
|
|
|
WRITE_REG_MASK_WE(GRF->IO_VSEL1,
|
|
GRF_IO_VSEL1_POC_VCCIO4_SEL33_MASK,
|
|
(0 << GRF_IO_VSEL1_POC_VCCIO4_SEL33_SHIFT));
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* @brief Config iomux for GMAC1
|
|
*/
|
|
// static void GMAC1_M1_Iomux_Config(void)
|
|
// {
|
|
// /* GMAC1 M1 iomux */
|
|
// HAL_PINCTRL_SetIOMUX(GPIO_BANK4,
|
|
// GPIO_PIN_B6 | /* gmac1_mdcm1 */
|
|
// GPIO_PIN_B7 | /* gmac1_mdiom1 */
|
|
// GPIO_PIN_B1 | /* gmac1_rxdvcrsm1 */
|
|
// GPIO_PIN_A7 | /* gmac1_rxd0m1 */
|
|
// GPIO_PIN_B0 | /* gmac1_rxd1m1 */
|
|
// GPIO_PIN_A1 | /* gmac1_rxd2m1 */
|
|
// GPIO_PIN_A2 | /* gmac1_rxd3m1 */
|
|
// GPIO_PIN_A6 | /* gmac1_txenm1 */
|
|
// GPIO_PIN_A3, /* gmac1_rxclkm1 */
|
|
// PIN_CONFIG_MUX_FUNC3);
|
|
|
|
// HAL_PINCTRL_SetIOMUX(GPIO_BANK4,
|
|
// GPIO_PIN_A0, /* gmac1_txd1m1 */
|
|
// PIN_CONFIG_MUX_FUNC3 | PIN_CONFIG_DRV_LEVEL3);
|
|
|
|
// HAL_PINCTRL_SetIOMUX(GPIO_BANK4,
|
|
// GPIO_PIN_A4 | /* gmac1_txd0m1 */
|
|
// GPIO_PIN_A5, /* gmac1_txd1m1 */
|
|
// PIN_CONFIG_MUX_FUNC3 | PIN_CONFIG_DRV_LEVEL2);
|
|
|
|
// /* GMAC1 M1 iomux */
|
|
// HAL_PINCTRL_SetIOMUX(GPIO_BANK3,
|
|
// GPIO_PIN_D6 | /* gmac1_txd2m1 */
|
|
// GPIO_PIN_D7, /* gmac1_txd3m1 */
|
|
// PIN_CONFIG_MUX_FUNC3 | PIN_CONFIG_DRV_LEVEL2);
|
|
|
|
// HAL_PINCTRL_IOFuncSelForGMAC1(IOFUNC_SEL_M1);
|
|
|
|
// #if 0
|
|
// /* io-domian: 1.8v or 3.3v for vccio6 */
|
|
// WRITE_REG_MASK_WE(GRF->IO_VSEL0,
|
|
// GRF_IO_VSEL0_POC_VCCIO6_SEL18_MASK,
|
|
// (1 << GRF_IO_VSEL0_POC_VCCIO6_SEL18_SHIFT));
|
|
|
|
// WRITE_REG_MASK_WE(GRF->IO_VSEL1,
|
|
// GRF_IO_VSEL1_POC_VCCIO6_SEL33_MASK,
|
|
// (0 << GRF_IO_VSEL1_POC_VCCIO6_SEL33_SHIFT));
|
|
// #endif
|
|
// }
|
|
|
|
|
|
static void GMAC_Iomux_Config(uint8_t id)
|
|
{
|
|
// if (id == 1) {
|
|
// GMAC1_M1_Iomux_Config();
|
|
// } else if (id == 0) {
|
|
GMAC0_Iomux_Config();
|
|
// }
|
|
}
|
|
|
|
|
|
/*************************** GMAC TEST MAIN ****************************/
|
|
|
|
void main(){
|
|
struct GMAC_ETH_CONFIG *eth;
|
|
struct GMAC_HANDLE *pGMAC;
|
|
int32_t bus, num = 0, i;
|
|
|
|
HAL_DBG("\n");
|
|
HAL_DBG("%s\n", __func__);
|
|
HAL_DBG(" GMAC Test:\n");
|
|
|
|
num = sizeof(ethConfigTable) / sizeof(struct GMAC_ETH_CONFIG);
|
|
HAL_DBG(" GMAC Num: %ld\n", num);
|
|
for (bus = 0; bus < num; bus++) {
|
|
eth = ðConfigTable[bus];
|
|
if (eth) {
|
|
pGMAC = ð->instance;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
/* ionmux */
|
|
GMAC_Iomux_Config(bus);
|
|
|
|
HAL_CRU_ClkEnable(eth->halDev->pclkGateID);
|
|
HAL_CRU_ClkEnable(eth->halDev->clkGateID);
|
|
|
|
/* Register irq */
|
|
|
|
/* PHY reset */
|
|
GMAC_PHY_Reset(eth);
|
|
|
|
/* GMAC Init */
|
|
GMAC_Init(bus);
|
|
|
|
GMAC_Memory_Init(eth, pGMAC);
|
|
|
|
/* Enable GMAC and DMA transmission and reception */
|
|
HAL_GMAC_Start(pGMAC, eth->macAddr);
|
|
|
|
/* Update links information */
|
|
PHY_Update_Links(eth, pGMAC, bus);
|
|
|
|
/* Dump MAC Regs */
|
|
Dump_Regs(pGMAC);
|
|
/* Dump PHY Regs */
|
|
PHY_Dump(eth, pGMAC);
|
|
|
|
for (i = 0; i < GMAC_TEST_TIMES; i++) {
|
|
/* GMAC Send 64 bytes */
|
|
GMAC_Send_Test(eth, pGMAC, 64);
|
|
/* GMAC Send 1500 bytes */
|
|
GMAC_Send_Test(eth, pGMAC, 1500);
|
|
HAL_DelayMs(1000);
|
|
|
|
/* GMAC Recv */
|
|
GMAC_Recv_Test(pGMAC);
|
|
}
|
|
|
|
HAL_CRU_ClkDisable(eth->halDev->pclkGateID);
|
|
HAL_CRU_ClkDisable(eth->halDev->clkGateID);
|
|
|
|
free_align(eth->txBuff);
|
|
free_align(eth->rxBuff);
|
|
}
|
|
}
|