增加bootload程序
This commit is contained in:
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* dp83848.c
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: eth phy dp83848 drv
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "debug.h"
|
||||
#include "CLI.h"
|
||||
#include "phy.h"
|
||||
|
||||
#define MII_BMCR 0x00 /* Basic mode control register */
|
||||
#define MII_BMSR 0x01 /* Basic mode status register */
|
||||
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
|
||||
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
|
||||
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
|
||||
#define MII_LPA 0x05 /* Link partner ability reg */
|
||||
#define MII_EXPANSION 0x06 /* Expansion register */
|
||||
|
||||
#define MII_PHYSTS 0x10
|
||||
#define MII_PHYCR 0x19
|
||||
|
||||
/* 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 */
|
||||
|
||||
/* Basic mode status register */
|
||||
#define BMSR_LINK_STATUS 0x4
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_SLCT 0x001f /* Selector bits */
|
||||
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
|
||||
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
||||
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
|
||||
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
|
||||
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
|
||||
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
|
||||
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
|
||||
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
|
||||
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
|
||||
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
|
||||
#define ADVERTISE_RESV 0x1000 /* Unused... */
|
||||
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
|
||||
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
|
||||
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
|
||||
|
||||
/* PHY status register */
|
||||
#define PHYSTS_DUPLEX 0x40
|
||||
#define PHYSTS_SPEED 0x20
|
||||
|
||||
/* PHY control register */
|
||||
#define PHYCR_MDIX_EN 0x8000
|
||||
|
||||
#define PHY_CLI_EN 1
|
||||
|
||||
#if PHY_CLI_EN
|
||||
static phy_dev_t *g_dp83848_dev;
|
||||
#endif
|
||||
|
||||
static int dp83848_read(phy_dev_t *dev, uint32_t regaddr)
|
||||
{
|
||||
phy_bus_t *bus = dev->bus;
|
||||
int ret = bus->ops->mdio_read(bus, dev->phy_addr, 0xFF, regaddr);
|
||||
if (ret < 0)
|
||||
ssdk_printf(SSDK_ERR, "dp83848_read err!\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dp83848_write(phy_dev_t *dev, uint32_t regaddr, uint16_t val)
|
||||
{
|
||||
phy_bus_t *bus = dev->bus;
|
||||
if (bus->ops->mdio_write(bus, dev->phy_addr, 0xFF, regaddr, val)) {
|
||||
ssdk_printf(SSDK_ERR, "dp83848_write err!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp83848_reset(phy_dev_t *dev)
|
||||
{
|
||||
int timeout = 500;
|
||||
int reg_val;
|
||||
|
||||
if (dp83848_write(dev, MII_BMCR, BMCR_RESET)) {
|
||||
ssdk_printf(SSDK_ERR, "PHY reset failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (timeout--) {
|
||||
reg_val = dp83848_read(dev, MII_BMCR);
|
||||
if (reg_val < 0) {
|
||||
ssdk_printf(SSDK_ERR, "BMCR read failed\n");
|
||||
return -2;
|
||||
}
|
||||
if (!(reg_val & BMCR_RESET))
|
||||
break;
|
||||
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
if (reg_val & BMCR_RESET) {
|
||||
ssdk_printf(SSDK_ERR, "PHY reset timeout\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint32_t dp83848_get_phy_id(phy_dev_t *dev)
|
||||
{
|
||||
int reg_val;
|
||||
|
||||
reg_val = dp83848_read(dev, MII_PHYSID1);
|
||||
if (reg_val < 0) {
|
||||
ssdk_printf(SSDK_ERR, "Read phy id1 error\n");
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
reg_val <<= 16;
|
||||
int temp = dp83848_read(dev, MII_PHYSID2);
|
||||
if (temp < 0) {
|
||||
ssdk_printf(SSDK_ERR, "Read phy id2 error\n");
|
||||
return temp;
|
||||
}
|
||||
reg_val |= temp;
|
||||
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
static int dp83848_config_aneg(phy_dev_t *dev)
|
||||
{
|
||||
int reg_val, ret, timeout = 1000;
|
||||
|
||||
if (dev->auto_negotiation) {
|
||||
reg_val = dp83848_read(dev, MII_ADVERTISE);
|
||||
if (reg_val < 0) {
|
||||
ssdk_printf(SSDK_ERR, "Read advertise error\n");
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
reg_val |= ADVERTISE_100FULL | ADVERTISE_100HALF |
|
||||
ADVERTISE_10FULL | ADVERTISE_10HALF;
|
||||
ret = dp83848_write(dev, MII_ADVERTISE, reg_val);
|
||||
if (ret) {
|
||||
ssdk_printf(SSDK_ERR, "Config advertisement register failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
reg_val = dp83848_read(dev, MII_BMCR);
|
||||
if (reg_val < 0) {
|
||||
ssdk_printf(SSDK_ERR, "Read BMCR failed\n");
|
||||
return reg_val;
|
||||
}
|
||||
reg_val |= BMCR_ANENABLE;
|
||||
ret = dp83848_write(dev, MII_BMCR, reg_val);
|
||||
if (ret)
|
||||
ssdk_printf(SSDK_ERR, "Write BMCR failed\n");
|
||||
}
|
||||
else {
|
||||
reg_val = dp83848_read(dev, MII_BMCR);
|
||||
if (reg_val < 0) {
|
||||
ssdk_printf(SSDK_ERR, "Read BMCR failed\n");
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
reg_val &= ~BMCR_ANENABLE;
|
||||
|
||||
if (dev->speed == PHY_SPEED_10)
|
||||
reg_val &= ~BMCR_SPEED100;
|
||||
else
|
||||
reg_val |= BMCR_SPEED100;
|
||||
|
||||
if (dev->duplex_mode == ETH_PHY_DUPLEX_MODE_HALF)
|
||||
reg_val &= ~BMCR_FULLDPLX;
|
||||
else
|
||||
reg_val |= BMCR_FULLDPLX;
|
||||
|
||||
ret = dp83848_write(dev, MII_BMCR, reg_val);
|
||||
if (ret)
|
||||
ssdk_printf(SSDK_ERR, "Write BMCR failed\n");
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (dev->auto_negotiation) {
|
||||
ssdk_printf(SSDK_EMERG, "Wait for dp83848 link ...\n");
|
||||
while (timeout--) {
|
||||
reg_val = dp83848_read(dev, MII_BMSR);
|
||||
if ((reg_val >= 0) && (reg_val & BMSR_LINK_STATUS))
|
||||
break;
|
||||
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if ((reg_val < 0) || !(reg_val & BMSR_LINK_STATUS)) {
|
||||
ssdk_printf(SSDK_EMERG, "Link failed\n");
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
ssdk_printf(SSDK_EMERG, "Link successfully\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dp83848_startup(phy_dev_t *dev)
|
||||
{
|
||||
int reg_val, ret;
|
||||
|
||||
reg_val = dp83848_read(dev, MII_PHYSTS);
|
||||
if (reg_val < 0) {
|
||||
ssdk_printf(SSDK_ERR, "Read PHYSTS failed\n");
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_INFO, "PHYSTS value 0x%x\n", reg_val);
|
||||
if (reg_val & PHYSTS_SPEED)
|
||||
dev->speed = PHY_SPEED_10;
|
||||
else
|
||||
dev->speed = PHY_SPEED_100;
|
||||
if (reg_val & PHYSTS_DUPLEX)
|
||||
dev->duplex_mode = ETH_PHY_DUPLEX_MODE_FULL;
|
||||
else
|
||||
dev->duplex_mode = ETH_PHY_DUPLEX_MODE_HALF;
|
||||
|
||||
reg_val = dp83848_read(dev, MII_BMCR);
|
||||
if (reg_val < 0) {
|
||||
ssdk_printf(SSDK_ERR, "Read BMCR failed\n");
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
reg_val &= ~(BMCR_ISOLATE | BMCR_PDOWN);
|
||||
ret = dp83848_write(dev, MII_BMCR, reg_val);
|
||||
if (ret) {
|
||||
ssdk_printf(SSDK_ERR, "Config BMCR failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = dp83848_write(dev, MII_PHYCR, PHYCR_MDIX_EN | dev->phy_addr);
|
||||
if (ret) {
|
||||
ssdk_printf(SSDK_ERR, "Config PHYCR failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_INFO, "PHY status 0x%x\n", dp83848_read(dev, MII_BMSR));
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dp83848_init(phy_dev_t *dev)
|
||||
{
|
||||
#if PHY_CLI_EN
|
||||
g_dp83848_dev = dev;
|
||||
#endif
|
||||
|
||||
if (dp83848_reset(dev))
|
||||
return -1;
|
||||
|
||||
ssdk_printf(SSDK_INFO, "PHY ID 0x%x\n",
|
||||
dp83848_get_phy_id(dev));
|
||||
|
||||
if (dp83848_config_aneg(dev))
|
||||
return -2;
|
||||
|
||||
return dp83848_startup(dev);
|
||||
}
|
||||
|
||||
#if PHY_CLI_EN
|
||||
static int phy_dump(int argc, char *argv[])
|
||||
{
|
||||
if (!g_dp83848_dev) {
|
||||
printf("dp83848 is not availiable\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
printf("phy <reg_num> [val]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reg_num = strtoul(argv[0], NULL, 0);
|
||||
if (argc == 1)
|
||||
printf("read reg %d: 0x%x\n", reg_num, dp83848_read(g_dp83848_dev, reg_num));
|
||||
else {
|
||||
int val = strtoul(argv[1], NULL, 0);
|
||||
printf("write reg %d val 0x%x result %d\n", reg_num, val,
|
||||
dp83848_write(g_dp83848_dev, reg_num, val));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CLI_CMD("phy", "\r\nphy:\r\n phy reg dump\r\n", phy_dump);
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* phy.c
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: eth phy driver
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include "armv7-r/irq.h"
|
||||
#include "phy.h"
|
||||
|
||||
void phy_dev_register(phy_bus_t *bus, phy_dev_t *dev)
|
||||
{
|
||||
irq_state_t state;
|
||||
|
||||
state = arch_irq_save();
|
||||
list_add_tail(&bus->phy_dev_list, &dev->node);
|
||||
bus->ref_cnt++;
|
||||
dev->bus = bus;
|
||||
arch_irq_restore(state);
|
||||
}
|
||||
|
||||
void phy_init(phy_bus_t *bus)
|
||||
{
|
||||
phy_dev_t *phy;
|
||||
|
||||
list_for_every_entry(&bus->phy_dev_list, phy, phy_dev_t, node) {
|
||||
if (phy->init)
|
||||
phy->init(phy);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* phy.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: eth phy driver header file
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef _PHY_H_
|
||||
#define _PHY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "lib/list.h"
|
||||
#include "../sdrv_mac_lld.h"
|
||||
|
||||
typedef enum {
|
||||
/* Automatic Negotiation */
|
||||
ETH_PHY_CONN_NEG_AUTO = 0,
|
||||
/* Master */
|
||||
ETH_PHY_CONN_NEG_MASTER,
|
||||
/* Slave */
|
||||
ETH_PHY_CONN_NEG_SLAVE
|
||||
} eth_phy_conn_neg_mode_type;
|
||||
|
||||
typedef enum {
|
||||
/* Half duplex Ethernet connection */
|
||||
ETH_PHY_DUPLEX_MODE_HALF = 0,
|
||||
/* 0x01 Full duplex Ethernet connection */
|
||||
ETH_PHY_DUPLEX_MODE_FULL
|
||||
} eth_duplex_mode_type;
|
||||
|
||||
typedef enum phy_speed{
|
||||
PHY_SPEED_10 = 0x0,
|
||||
PHY_SPEED_100,
|
||||
PHY_SPEED_1000,
|
||||
} phy_speed_t;
|
||||
|
||||
typedef struct phy_bus phy_bus_t;
|
||||
|
||||
typedef struct phy_bus_ops {
|
||||
int (*mdio_read)(phy_bus_t *bus, uint32_t phyaddr, uint32_t devaddr,
|
||||
uint32_t regaddr);
|
||||
int (*mdio_write)(phy_bus_t *bus , uint32_t phyaddr, uint32_t devaddr,
|
||||
uint32_t regaddr, uint32_t data);
|
||||
} phy_bus_ops_t;
|
||||
|
||||
struct phy_bus {
|
||||
phy_bus_ops_t *ops;
|
||||
|
||||
uint32_t ref_cnt;
|
||||
struct list_node phy_dev_list;
|
||||
};
|
||||
|
||||
typedef struct phy_dev phy_dev_t;
|
||||
|
||||
struct phy_dev {
|
||||
struct list_node node;
|
||||
phy_bus_t *bus;
|
||||
|
||||
uint32_t phy_addr;
|
||||
eth_phy_conn_neg_mode_type conn_neg_mode;
|
||||
eth_duplex_mode_type duplex_mode;
|
||||
phy_speed_t speed;
|
||||
bool auto_negotiation;
|
||||
int (*init)(phy_dev_t *dev);
|
||||
};
|
||||
|
||||
void phy_dev_register(phy_bus_t *bus, phy_dev_t *dev);
|
||||
void phy_init(phy_bus_t *bus);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* rtl9010.c
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: eth phy rtl9010 drv
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "debug.h"
|
||||
#include "CLI.h"
|
||||
#include "phy.h"
|
||||
|
||||
#define LINK_UP 0
|
||||
#define LINK_DOWN -100
|
||||
|
||||
#define PHY_CLI_EN 1
|
||||
|
||||
#if PHY_CLI_EN
|
||||
static phy_dev_t *g_rtl9010_dev;
|
||||
#endif
|
||||
|
||||
static int rtl9010_read(phy_dev_t *dev, uint32_t regaddr)
|
||||
{
|
||||
phy_bus_t *bus = dev->bus;
|
||||
int ret = bus->ops->mdio_read(bus, dev->phy_addr, 0xFF, regaddr);
|
||||
if (ret < 0)
|
||||
ssdk_printf(SSDK_ERR, "rtl9010_read err!\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rtl9010_write(phy_dev_t *dev, uint32_t regaddr, uint16_t val)
|
||||
{
|
||||
phy_bus_t *bus = dev->bus;
|
||||
if (bus->ops->mdio_write(bus, dev->phy_addr, 0xFF, regaddr, val)) {
|
||||
ssdk_printf(SSDK_ERR, "rtl9010_write err!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9010_initial_config(phy_dev_t *dev)
|
||||
{
|
||||
int mdio_data = 0;
|
||||
int timer = 2000; // set a 2ms timer
|
||||
|
||||
// PHY Parameter Start //
|
||||
rtl9010_write(dev, 31, 0x0BC4);
|
||||
rtl9010_write(dev, 21, 0x16FE);
|
||||
|
||||
rtl9010_write(dev, 27, 0xB820);
|
||||
rtl9010_write(dev, 28, 0x0010);
|
||||
rtl9010_write(dev, 27, 0xB830);
|
||||
rtl9010_write(dev, 28, 0x8000);
|
||||
rtl9010_write(dev, 27, 0xB800);
|
||||
|
||||
mdio_data = (rtl9010_read(dev, 28) & 0x0040);
|
||||
while (mdio_data != 0x0040) {
|
||||
rtl9010_write(dev, 27, 0xB800);
|
||||
mdio_data = (rtl9010_read(dev, 28) & 0x0040);
|
||||
timer--;
|
||||
if (timer == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rtl9010_write(dev, 27, 0x8020);
|
||||
rtl9010_write(dev, 28, 0x9100);
|
||||
rtl9010_write(dev, 27, 0xB82E);
|
||||
rtl9010_write(dev, 28, 0x0001);
|
||||
|
||||
rtl9010_write(dev, 27, 0xB820);
|
||||
rtl9010_write(dev, 28, 0x0290);
|
||||
rtl9010_write(dev, 27, 0xA012);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
rtl9010_write(dev, 27, 0xA014);
|
||||
rtl9010_write(dev, 28, 0xD700);
|
||||
rtl9010_write(dev, 28, 0x880F);
|
||||
rtl9010_write(dev, 28, 0x262D);
|
||||
rtl9010_write(dev, 27, 0xA01A);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
rtl9010_write(dev, 27, 0xA000);
|
||||
rtl9010_write(dev, 28, 0x162C);
|
||||
rtl9010_write(dev, 27, 0xB820);
|
||||
rtl9010_write(dev, 28, 0x0210);
|
||||
rtl9010_write(dev, 27, 0xB82E);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
rtl9010_write(dev, 27, 0x8020);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
rtl9010_write(dev, 27, 0xB820);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
|
||||
rtl9010_write(dev, 27, 0xB800);
|
||||
mdio_data = rtl9010_read(dev, 28) & 0x0040;
|
||||
timer = 2000; // set a 2ms timer
|
||||
while (mdio_data != 0x0000) {
|
||||
rtl9010_write(dev, 27, 0xB800);
|
||||
mdio_data = (rtl9010_read(dev, 28) & 0x0040);
|
||||
timer--;
|
||||
if (timer == 0) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
// End //
|
||||
|
||||
/* Set rx delay to 2ns. */
|
||||
rtl9010_write(dev, 27, 0xD04A);
|
||||
rtl9010_write(dev, 28, 7);
|
||||
|
||||
/* Set tx delay to 2ns. */
|
||||
rtl9010_write(dev, 27, 0xD084);
|
||||
rtl9010_write(dev, 28, 0x4007);
|
||||
|
||||
rtl9010_write(dev, 0, 0x8000); // PHY soft-reset
|
||||
mdio_data = 0;
|
||||
while (mdio_data != 0x0140) { // Check soft-reset complete
|
||||
mdio_data = rtl9010_read(dev, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9010_initial_with_nway_config(phy_dev_t *dev)
|
||||
{
|
||||
int mdio_data = 0;
|
||||
int timer = 2000; // set a 2ms timer
|
||||
|
||||
// PHY Parameter Start //
|
||||
rtl9010_write(dev, 31,0x0A54);
|
||||
rtl9010_write(dev, 21,0xFA06);
|
||||
rtl9010_write(dev, 31,0x0BC4);
|
||||
rtl9010_write(dev, 21,0x16FE);
|
||||
|
||||
rtl9010_write(dev, 27, 0xB820);
|
||||
rtl9010_write(dev, 28, 0x0010);
|
||||
rtl9010_write(dev, 27, 0xB830);
|
||||
rtl9010_write(dev, 28, 0x8000);
|
||||
rtl9010_write(dev, 27, 0xB800);
|
||||
mdio_data = (rtl9010_read(dev, 28) & 0x0040);
|
||||
while (mdio_data != 0x0040) {
|
||||
rtl9010_write(dev, 27, 0xB800);
|
||||
mdio_data = (rtl9010_read(dev, 28) & 0x0040);
|
||||
timer--;
|
||||
if (timer == 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
rtl9010_write(dev, 27, 0x8020);
|
||||
rtl9010_write(dev, 28, 0x9100);
|
||||
rtl9010_write(dev, 27, 0xB82E);
|
||||
rtl9010_write(dev, 28, 0x0001);
|
||||
|
||||
rtl9010_write(dev, 27, 0xB820);
|
||||
rtl9010_write(dev, 28, 0x0290);
|
||||
rtl9010_write(dev, 27, 0xA012);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
rtl9010_write(dev, 27, 0xA014);
|
||||
rtl9010_write(dev, 28, 0x2C03);
|
||||
rtl9010_write(dev, 28, 0x2C07);
|
||||
rtl9010_write(dev, 28, 0x2C0B);
|
||||
rtl9010_write(dev, 28, 0x6054);
|
||||
rtl9010_write(dev, 28, 0xA701);
|
||||
rtl9010_write(dev, 28, 0xD500);
|
||||
rtl9010_write(dev, 28, 0x2108);
|
||||
rtl9010_write(dev, 28, 0x4054);
|
||||
rtl9010_write(dev, 28, 0x8701);
|
||||
rtl9010_write(dev, 28, 0xA74A);
|
||||
rtl9010_write(dev, 28, 0x20DE);
|
||||
rtl9010_write(dev, 28, 0xD700);
|
||||
rtl9010_write(dev, 28, 0x880F);
|
||||
rtl9010_write(dev, 28, 0x262D);
|
||||
rtl9010_write(dev, 27, 0xA01A);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
rtl9010_write(dev, 27, 0xA004);
|
||||
rtl9010_write(dev, 28, 0x062C);
|
||||
rtl9010_write(dev, 27, 0xA002);
|
||||
rtl9010_write(dev, 28, 0x00DD);
|
||||
rtl9010_write(dev, 27, 0xA000);
|
||||
rtl9010_write(dev, 28, 0x7107);
|
||||
rtl9010_write(dev, 27, 0xB820);
|
||||
rtl9010_write(dev, 28, 0x0210);
|
||||
|
||||
rtl9010_write(dev, 27, 0xB82E);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
rtl9010_write(dev, 27, 0x8020);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
rtl9010_write(dev, 27, 0xB820);
|
||||
rtl9010_write(dev, 28, 0x0000);
|
||||
|
||||
rtl9010_write(dev, 27, 0xB800);
|
||||
mdio_data = (rtl9010_read(dev, 28) & 0x0040);
|
||||
timer = 2000; // set a 2ms timer
|
||||
while (mdio_data != 0x0000) {
|
||||
rtl9010_write(dev, 27, 0xB800);
|
||||
mdio_data = (rtl9010_read(dev, 28) & 0x0040);
|
||||
timer--;
|
||||
if (timer == 0) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
// End //
|
||||
|
||||
/* Set rx delay to 2ns. */
|
||||
rtl9010_write(dev, 27, 0xD04A);
|
||||
rtl9010_write(dev, 28, 7);
|
||||
|
||||
/* Set tx delay to 2ns. */
|
||||
rtl9010_write(dev, 27, 0xD084);
|
||||
rtl9010_write(dev, 28, 0x4007);
|
||||
|
||||
rtl9010_write(dev, 0, 0x8000); // PHY soft-reset
|
||||
mdio_data = 0;
|
||||
while (mdio_data != 0x0140) { // Check soft-reset complete
|
||||
mdio_data = rtl9010_read(dev, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtl9010_get_link_status(phy_dev_t *dev)
|
||||
{
|
||||
int mdio_data = 0;
|
||||
int locok = 0;
|
||||
int remok = 0;
|
||||
int link_status = 0;
|
||||
int pcs_status;
|
||||
int pcs_status_checkOK=0;
|
||||
|
||||
mdio_data = rtl9010_read(dev, 1);
|
||||
mdio_data = rtl9010_read(dev, 1);//Read twice for current link status.
|
||||
link_status = (mdio_data & 0x0004);
|
||||
|
||||
rtl9010_write(dev, 31, 0x0A60);
|
||||
mdio_data = rtl9010_read(dev, 16);
|
||||
pcs_status = (mdio_data & 0x00FF);
|
||||
|
||||
if (dev->speed == PHY_SPEED_1000){
|
||||
mdio_data = rtl9010_read(dev, 10);
|
||||
locok = ((mdio_data & 0x2000) == 0x2000);
|
||||
remok = ((mdio_data & 0x1000) == 0x1000);
|
||||
if (pcs_status == 0x0037)
|
||||
pcs_status_checkOK = 1;
|
||||
}
|
||||
else {
|
||||
rtl9010_write(dev, 31, 0x0A64);
|
||||
mdio_data = rtl9010_read(dev, 23);
|
||||
locok = ((mdio_data & 0x0004) == 0x0004);
|
||||
remok = ((mdio_data & 0x0400) == 0x0400);
|
||||
if (pcs_status == 0x0044)
|
||||
pcs_status_checkOK = 1;
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_INFO, "link_status = 0x%04X\r\n",link_status);
|
||||
ssdk_printf(SSDK_INFO, "locok = 0x%04X\r\n",locok);
|
||||
ssdk_printf(SSDK_INFO, "remok = 0x%04X\r\n",remok);
|
||||
ssdk_printf(SSDK_INFO, "pcs_status = 0x%04X\r\n",pcs_status);
|
||||
|
||||
if ((link_status == 0x0004) & (locok) & (remok) &
|
||||
pcs_status_checkOK)
|
||||
return LINK_UP;
|
||||
else
|
||||
return LINK_DOWN;
|
||||
}
|
||||
|
||||
int rtl9010_init(phy_dev_t *dev)
|
||||
{
|
||||
int ret = 0, timeout = 1000;
|
||||
|
||||
#if PHY_CLI_EN
|
||||
g_rtl9010_dev = dev;
|
||||
#endif
|
||||
|
||||
if (dev->auto_negotiation)
|
||||
ret = rtl9010_initial_with_nway_config(dev);
|
||||
else
|
||||
ret = rtl9010_initial_config(dev);
|
||||
|
||||
if (!ret && dev->auto_negotiation) {
|
||||
ssdk_printf(SSDK_EMERG, "Wait for rtl9010 link ...\n");
|
||||
while (timeout--) {
|
||||
ret = rtl9010_get_link_status(dev);
|
||||
if (ret == LINK_UP) {
|
||||
ssdk_printf(SSDK_EMERG, "Link successfully\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
ssdk_printf(SSDK_EMERG, "Link failed\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if PHY_CLI_EN
|
||||
static int rtl9010_dump(int argc, char *argv[])
|
||||
{
|
||||
if (!g_rtl9010_dev) {
|
||||
printf("rtl9010 is not availiable\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 0) {
|
||||
printf("phy <reg_num> [val]\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int reg_num = strtoul(argv[0], NULL, 0);
|
||||
if (argc == 1)
|
||||
printf("read reg %d: 0x%x\n", reg_num, rtl9010_read(g_rtl9010_dev, reg_num));
|
||||
else {
|
||||
int val = strtoul(argv[1], NULL, 0);
|
||||
printf("write reg %d val 0x%x result %d\n", reg_num, val,
|
||||
rtl9010_write(g_rtl9010_dev, reg_num, val));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CLI_CMD("rtl", "\r\nrtl:\r\n rtl reg dump\r\n", rtl9010_dump);
|
||||
#endif
|
||||
@@ -0,0 +1,786 @@
|
||||
/**
|
||||
* dwc_eth.c
|
||||
*
|
||||
* Copyright (c) 2021 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: dw eth mac drv
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "debug.h"
|
||||
#include "param.h"
|
||||
#include "armv7-r/barriers.h"
|
||||
#include "armv7-r/cache.h"
|
||||
#include "irq_num.h"
|
||||
#include "irq.h"
|
||||
#include "sdrv_mac_lld.h"
|
||||
#include "sdrv_eth.h"
|
||||
#include "phy/phy.h"
|
||||
|
||||
#include <wdt_refresh.h>
|
||||
|
||||
/* Eth frame header and crc length. */
|
||||
#define ETH_FRAME_HEADER_LEN (6 + 6 + 2)
|
||||
#define ETH_FRAME_OVERHEAD_LEN (ETH_FRAME_HEADER_LEN + 4)
|
||||
|
||||
#if !CONFIG_ETH_USE_HEAP
|
||||
#define MAX_ETH_CNT 2
|
||||
|
||||
#ifndef CONFIG_ARCH_CACHE_LINE
|
||||
#define CONFIG_ARCH_CACHE_LINE 32
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
struct eqos_desc desc;
|
||||
} __ALIGNED(EQOS_DESCRIPTOR_ALIGN) eqos_desc_t;
|
||||
|
||||
struct eqos_data {
|
||||
bool used;
|
||||
dwc_eth_dev_t dev;
|
||||
struct eqos_priv eqos;
|
||||
eqos_desc_t descs[EQOS_DESCRIPTORS_NUM];
|
||||
uint8_t rx_dma_buf[EQOS_RX_BUFFER_SIZE] __ALIGNED(CONFIG_ARCH_CACHE_LINE);
|
||||
uint8_t tx_dma_buf[EQOS_TX_BUFFER_SIZE] __ALIGNED(CONFIG_ARCH_CACHE_LINE);
|
||||
};
|
||||
|
||||
static struct eqos_data g_eqos_data[MAX_ETH_CNT];
|
||||
#endif
|
||||
|
||||
static void *eqos_alloc_descs(struct eqos_priv *eqos, unsigned int num)
|
||||
{
|
||||
/* Align dma descriptors base address & size to cache line to avoid
|
||||
* descriptors corrupted by cacahe line invalidation needed by other
|
||||
* address, if descriptors has not been wrote to ram.
|
||||
*/
|
||||
eqos->desc_size = ALIGN(sizeof(struct eqos_desc),
|
||||
(unsigned int)EQOS_DESCRIPTOR_ALIGN);
|
||||
|
||||
#if !CONFIG_ETH_USE_HEAP
|
||||
return containerof(eqos, struct eqos_data, eqos)->descs;
|
||||
#else
|
||||
#if __GNUC__
|
||||
return (void *)memalign(eqos->desc_size, num * eqos->desc_size);
|
||||
#else
|
||||
return aligned_alloc(eqos->desc_size, num * eqos->desc_size);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_ETH_USE_HEAP
|
||||
static void eqos_free_descs(void *descs)
|
||||
{
|
||||
free(descs);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct eqos_desc *eqos_get_desc(struct eqos_priv *eqos, unsigned int num,
|
||||
bool rx)
|
||||
{
|
||||
void *desc = (uint8_t *)eqos->descs +
|
||||
((rx ? EQOS_DESCRIPTORS_TX : 0) + num) * eqos->desc_size;
|
||||
return desc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Init the Controller DMA Block
|
||||
*/
|
||||
static inline void mac_init_dma(uint32_t regbase, struct eqos_priv *eqos)
|
||||
{
|
||||
uint8_t ch_cnt = 0U;
|
||||
|
||||
dwmac_dma_bus_init(regbase, DMA_AXI_MAX_OSR_LIMIT | DMA_SYS_BUS_AAL |
|
||||
DMA_AXI_BLEN16 | DMA_AXI_BLEN8 | DMA_AXI_BLEN4);
|
||||
|
||||
for (ch_cnt = 0; ch_cnt < ETH_MAX_DMA_CHANNEL; ch_cnt++) {
|
||||
// DMA Control
|
||||
dwmac_dma_init_channel(regbase, 0, ch_cnt, eqos->dsl);
|
||||
// rx ring length
|
||||
dwmac_set_rx_ring_len(regbase, EQOS_DESCRIPTORS_RX - 1, ch_cnt);
|
||||
// init_rx_chan
|
||||
dwmac_dma_init_rx_chan(regbase, (paddr_t)eqos_get_desc(eqos, 0, true),
|
||||
EQOS_MAX_PACKET_SIZE, ch_cnt);
|
||||
// rx bufsize
|
||||
dwmac_set_bfsize(regbase, 2048, ch_cnt);//2048 20250112<31><EFBFBD>Ϊ 4096
|
||||
// tx ring length
|
||||
dwmac_set_tx_ring_len(regbase, EQOS_DESCRIPTORS_TX - 1, ch_cnt);
|
||||
// init_tx_chan
|
||||
dwmac_dma_init_tx_chan(regbase, (paddr_t)eqos_get_desc(eqos, 0, false),
|
||||
ch_cnt);
|
||||
// set tx tail ptr to next address after the last tx descriptor, so that
|
||||
// dma will never suspend.
|
||||
dwmac_set_tx_tail_ptr(regbase, (uint32_t)eqos_get_desc(eqos, EQOS_DESCRIPTORS_TX, false),
|
||||
ch_cnt);
|
||||
// set rx tail ptr to next address after the last tx descriptor, so that
|
||||
// dma will never suspend.
|
||||
dwmac_set_rx_tail_ptr(regbase,
|
||||
(paddr_t)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX, true),
|
||||
ch_cnt);
|
||||
|
||||
dwmac_enable_dma_irq(regbase, ch_cnt, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Init the Controller MTL Block
|
||||
*/
|
||||
static inline void mac_init_mtl(uint32_t regbase)
|
||||
{
|
||||
uint8_t ch_cnt = 0U;
|
||||
|
||||
dwmac_prog_mtl_rx_algorithms(regbase, MTL_RX_ALGORITHM_SP);
|
||||
|
||||
dwmac_prog_mtl_tx_algorithms(regbase, MTL_OPERATION_SCHALG_WRR);
|
||||
|
||||
for (ch_cnt = 0; ch_cnt < ETH_MAX_DMA_CHANNEL; ch_cnt++) {
|
||||
// rx mtl map with dma
|
||||
dwmac_map_mtl_dma(regbase, ch_cnt, ch_cnt);
|
||||
dwmac_rx_queue_enable(regbase, MTL_QUEUE_MODE_DCB, ch_cnt);
|
||||
dwmac_dma_tx_chan_op_mode(regbase, ch_cnt, SF_MODE, 10240, MTL_QUEUE_MODE_DCB);
|
||||
dwmac_dma_rx_chan_op_mode(regbase, ch_cnt, SF_MODE, 10240, MTL_QUEUE_MODE_DCB);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void mac_start(uint32_t regbase, bool start)
|
||||
{
|
||||
uint8_t ch_cnt = 0U;
|
||||
|
||||
for (ch_cnt = 0; ch_cnt < ETH_MAX_DMA_CHANNEL; ch_cnt++) {
|
||||
if (start) {
|
||||
// start rx
|
||||
dwmac_dma_start_rx(regbase, ch_cnt);
|
||||
// start tx
|
||||
dwmac_dma_start_tx(regbase, ch_cnt);
|
||||
}
|
||||
else {
|
||||
// stop rx
|
||||
dwmac_dma_stop_rx(regbase, ch_cnt);
|
||||
// stop tx
|
||||
dwmac_dma_stop_tx(regbase, ch_cnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void eth_mac_init(dwc_eth_config_t *cfg, struct eqos_priv *eqos)
|
||||
{
|
||||
//DMA core sw reset
|
||||
dwmac_dma_reset(cfg->base);
|
||||
|
||||
uint32_t skip_len = eqos->desc_size - sizeof(struct eqos_desc);
|
||||
uint8_t bus_width = cfg->dma_bus_width ? cfg->dma_bus_width : 64;
|
||||
eqos->dsl = skip_len * 8 / bus_width;
|
||||
|
||||
//DMA init
|
||||
mac_init_dma(cfg->base, eqos);
|
||||
|
||||
//MTL init
|
||||
mac_init_mtl(cfg->base);
|
||||
|
||||
//core init
|
||||
phy_speed_t speed = (cfg->phy[0].phy_addr == ~0) ?
|
||||
PHY_SPEED_1000 : cfg->phy[0].speed;
|
||||
dwmac_core_init(cfg->base, cfg->mtu, speed, cfg->mac_addr);
|
||||
dwmac_mac_rx_queue_mcbc_routing(cfg->base, 0);
|
||||
}
|
||||
|
||||
static inline void set_phyif_mode(dwc_eth_config_t *cfg)
|
||||
{
|
||||
if (cfg->set_phy_intf)
|
||||
cfg->set_phy_intf(cfg->base, cfg->phy_intf_mode);
|
||||
}
|
||||
|
||||
static inline void config_eth_clk(dwc_eth_config_t *cfg)
|
||||
{
|
||||
if (cfg->timer_sec_clk)
|
||||
sdrv_ckgen_set_rate(cfg->timer_sec_clk, 125000000);
|
||||
if (cfg->phy_ref_clk)
|
||||
sdrv_ckgen_set_rate(cfg->phy_ref_clk, 125000000);
|
||||
if (cfg->rmii_clk)
|
||||
sdrv_ckgen_set_rate(cfg->rmii_clk, 50000000);
|
||||
if (cfg->tx_clk)
|
||||
sdrv_ckgen_set_rate(cfg->tx_clk, 250000000);
|
||||
}
|
||||
|
||||
static inline void reset_eth(dwc_eth_config_t *cfg)
|
||||
{
|
||||
if (cfg->rst)
|
||||
sdrv_rstgen_reset(cfg->rst);
|
||||
}
|
||||
|
||||
static err_t dwc_eth_init(struct net_driver_s *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
int i;
|
||||
dwc_eth_dev_t *eth_dev = (dwc_eth_dev_t *)dev->d_private;
|
||||
dwc_eth_config_t *cfg = eth_dev->config;
|
||||
struct eqos_priv *eqos;
|
||||
|
||||
if (eth_dev->init)
|
||||
return 0;
|
||||
else
|
||||
eth_dev->init = true;
|
||||
|
||||
//set SCR ethernet operating mode, e.g. RGMII, SGMII, etc.
|
||||
set_phyif_mode(cfg);
|
||||
|
||||
//set ethernet Clk
|
||||
config_eth_clk(cfg);
|
||||
|
||||
//ethernet reset
|
||||
reset_eth(cfg);
|
||||
|
||||
#if !CONFIG_ETH_USE_HEAP
|
||||
struct eqos_data *eqosd = containerof(eth_dev, struct eqos_data, dev);
|
||||
eqos = &eqosd->eqos;
|
||||
#else
|
||||
eqos = (struct eqos_priv *)malloc(sizeof(struct eqos_priv));
|
||||
ASSERT(eqos);
|
||||
memset(eqos, 0, sizeof(struct eqos_priv));
|
||||
#endif
|
||||
|
||||
eqos->descs = eqos_alloc_descs(eqos, EQOS_DESCRIPTORS_NUM);
|
||||
|
||||
if (!eqos->descs) {
|
||||
ssdk_printf(SSDK_INFO, "%s: eqos_alloc_descs() failed\n", __func__);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
eqos->tx_desc_idx = 0;
|
||||
eqos->rx_desc_idx = 0;
|
||||
|
||||
#if !CONFIG_ETH_USE_HEAP
|
||||
eqos->tx_dma_buf = eqosd->tx_dma_buf;
|
||||
eqos->rx_dma_buf = eqosd->rx_dma_buf;
|
||||
#else
|
||||
/* Align tx dma buf base address & size to cache line to avoid tx
|
||||
* dma buf corrupted by cacahe line invalidation needed by other
|
||||
* address, if tx dma buf data has not been wrote to ram.
|
||||
*/
|
||||
#if __GNUC__
|
||||
eqos->tx_dma_buf = (void *)memalign(CONFIG_ARCH_CACHE_LINE,
|
||||
EQOS_TX_BUFFER_SIZE);
|
||||
#else
|
||||
eqos->tx_dma_buf = (void *)aligned_alloc(CONFIG_ARCH_CACHE_LINE,
|
||||
EQOS_TX_BUFFER_SIZE);
|
||||
#endif
|
||||
ASSERT(eqos->tx_dma_buf);
|
||||
memset(eqos->tx_dma_buf, 0, EQOS_TX_BUFFER_SIZE);
|
||||
|
||||
/* rx dma buf base address & size should be cache line aligned.
|
||||
* Otherwise data before or after rx dma buf may locate in same
|
||||
* cache line with rx dma buf, when invalidate rx dma buf cache,
|
||||
* heap data before or after rx dma buf may be corrupted.
|
||||
*/
|
||||
#if __GNUC__
|
||||
eqos->rx_dma_buf = (void *)memalign(CONFIG_ARCH_CACHE_LINE,
|
||||
EQOS_RX_BUFFER_SIZE);
|
||||
#else
|
||||
eqos->rx_dma_buf = (void *)aligned_alloc(CONFIG_ARCH_CACHE_LINE,
|
||||
EQOS_RX_BUFFER_SIZE);
|
||||
#endif
|
||||
ASSERT(eqos->rx_dma_buf);
|
||||
memset(eqos->rx_dma_buf, 0, EQOS_RX_BUFFER_SIZE);
|
||||
#endif
|
||||
|
||||
//init phy
|
||||
phy_init(ð_dev->phy_bus);
|
||||
|
||||
//init mac
|
||||
eth_mac_init(cfg, eqos);
|
||||
|
||||
// set up dma tx/rx descriptors
|
||||
memset(eqos->descs, 0, eqos->desc_size * EQOS_DESCRIPTORS_NUM);
|
||||
|
||||
for (i = 0; i < EQOS_DESCRIPTORS_TX; i++) {
|
||||
struct eqos_desc *tx_desc = eqos_get_desc(eqos, i, false);
|
||||
arch_clean_cache_range((addr_t)tx_desc, sizeof(struct eqos_desc));
|
||||
}
|
||||
|
||||
for (i = 0; i < EQOS_DESCRIPTORS_RX; i++) {
|
||||
struct eqos_desc *rx_desc = eqos_get_desc(eqos, i, true);
|
||||
rx_desc->des0 = (paddr_t)eqos->rx_dma_buf +
|
||||
(i * EQOS_MAX_PACKET_SIZE);
|
||||
DMB;
|
||||
rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_IOC | EQOS_DESC3_BUF1V;
|
||||
arch_clean_cache_range((addr_t)rx_desc, sizeof(struct eqos_desc));
|
||||
arch_invalidate_cache_range((addr_t)((char *)eqos->rx_dma_buf +
|
||||
(i * EQOS_MAX_PACKET_SIZE)), EQOS_MAX_PACKET_SIZE);
|
||||
}
|
||||
|
||||
//enable rx/tx
|
||||
mac_start(cfg->base, true);
|
||||
|
||||
eqos->started = true;
|
||||
|
||||
eth_dev->eqos = eqos;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void eqos_rx_lock(struct eqos_priv *eqos)
|
||||
{
|
||||
EQOS_RX_LOCK(eqos);
|
||||
}
|
||||
|
||||
static inline void eqos_rx_unlock(struct eqos_priv *eqos)
|
||||
{
|
||||
EQOS_RX_UNLOCK(eqos);
|
||||
}
|
||||
|
||||
static inline void eqos_tx_lock(struct eqos_priv *eqos)
|
||||
{
|
||||
EQOS_TX_LOCK(eqos);
|
||||
}
|
||||
|
||||
static inline void eqos_tx_unlock(struct eqos_priv *eqos)
|
||||
{
|
||||
EQOS_TX_UNLOCK(eqos);
|
||||
}
|
||||
|
||||
static err_t dwc_eth_txavail(struct net_driver_s *dev, struct pbuf *p)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct eqos_desc *tx_desc;
|
||||
uint8_t *tx_buf;
|
||||
uint32_t offset = 0;
|
||||
struct pbuf *q = NULL;
|
||||
dwc_eth_dev_t *eth_dev = (dwc_eth_dev_t *)dev->d_private;
|
||||
dwc_eth_config_t *cfg = eth_dev->config;
|
||||
struct eqos_priv *eqos = eth_dev->eqos;
|
||||
|
||||
if (p->tot_len > (cfg->mtu + ETH_FRAME_HEADER_LEN)) {
|
||||
ssdk_printf(SSDK_INFO, "eth tx len > MTU, %d\n", p->tot_len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
eqos_tx_lock(eqos);
|
||||
|
||||
tx_desc = eqos_get_desc(eqos, eqos->tx_desc_idx, false);
|
||||
|
||||
for (i = 0; i < 100000; i++) {
|
||||
arch_invalidate_cache_range((addr_t)tx_desc, sizeof(struct eqos_desc));
|
||||
|
||||
if ((tx_desc->des3 & EQOS_DESC3_OWN) == 0) {
|
||||
goto start_tx;
|
||||
}
|
||||
}
|
||||
|
||||
ssdk_printf(SSDK_INFO, "%s: Previous tX on desc %d timeout\n", __func__,
|
||||
eqos->tx_desc_idx);
|
||||
ret = -1;
|
||||
goto tx_out;
|
||||
|
||||
start_tx:
|
||||
tx_buf = (uint8_t *)eqos->tx_dma_buf +
|
||||
eqos->tx_desc_idx * EQOS_MAX_PACKET_SIZE;
|
||||
//copy data to pbuf
|
||||
for (q = p; q != NULL; q = q->next) {
|
||||
memcpy((uint8_t *)(tx_buf + offset),
|
||||
(uint8_t *)((uint8_t *)q->payload), q->len);
|
||||
offset += q->len;
|
||||
}
|
||||
|
||||
arch_clean_cache_range((addr_t)tx_buf, p->tot_len);
|
||||
|
||||
eqos->tx_desc_idx ++;
|
||||
eqos->tx_desc_idx %= EQOS_DESCRIPTORS_TX;
|
||||
tx_desc->des0 = (paddr_t)tx_buf;
|
||||
tx_desc->des1 = 0;
|
||||
tx_desc->des2 = p->tot_len;
|
||||
|
||||
/*
|
||||
* Make sure that if HW sees the _OWN write below, it will see all the
|
||||
* writes to the rest of the descriptor too.
|
||||
*/
|
||||
DMB;
|
||||
tx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_FD | EQOS_DESC3_LD | (p->tot_len);
|
||||
|
||||
arch_clean_cache_range((addr_t)tx_desc, sizeof(struct eqos_desc));
|
||||
|
||||
dwmac_set_tx_tail_ptr(cfg->base,
|
||||
(uint32_t)eqos_get_desc(eqos, EQOS_DESCRIPTORS_TX, false),
|
||||
0);
|
||||
|
||||
tx_out:
|
||||
eqos_tx_unlock(eqos);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t dwc_eth_getmac(struct net_driver_s *dev, void *buf, uint32_t max_len)
|
||||
{
|
||||
dwc_eth_dev_t *eth_dev = (dwc_eth_dev_t *)dev->d_private;
|
||||
uint8_t *mac_addr = eth_dev->config->mac_addr;
|
||||
|
||||
if (mac_addr == NULL) {
|
||||
mac_addr = dwmac_get_default_mac_addr();
|
||||
}
|
||||
|
||||
memcpy(buf, (void *)mac_addr, max_len);
|
||||
|
||||
return max_len;
|
||||
}
|
||||
|
||||
static uint32_t dwc_eth_getmtu(struct net_driver_s *dev)
|
||||
{
|
||||
dwc_eth_dev_t *eth_dev = (dwc_eth_dev_t *)dev->d_private;
|
||||
|
||||
return eth_dev->config->mtu;
|
||||
}
|
||||
|
||||
static int dwc_eth_rx_poll(struct net_driver_s *dev)
|
||||
{
|
||||
struct eqos_desc *rx_desc;
|
||||
uint32_t length = 0;
|
||||
uint8_t *recbuf;
|
||||
struct pbuf *rx_pbuf = NULL;
|
||||
dwc_eth_dev_t *eth_dev = (dwc_eth_dev_t *)dev->d_private;
|
||||
dwc_eth_config_t *cfg = eth_dev->config;
|
||||
struct eqos_priv *eqos = eth_dev->eqos;
|
||||
|
||||
eqos_rx_lock(eqos);
|
||||
|
||||
rx_desc = eqos_get_desc(eqos, eqos->rx_desc_idx, true);
|
||||
|
||||
arch_invalidate_cache_range((addr_t)rx_desc, sizeof(struct eqos_desc));
|
||||
|
||||
if (rx_desc->des3 & EQOS_DESC3_OWN) {
|
||||
eqos_rx_unlock(eqos);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure reading des3 before dma buffer.
|
||||
* Avoid speculative reading of buffer before des3 own bit cleared.
|
||||
*/
|
||||
DMB;
|
||||
|
||||
recbuf = (uint8_t *)eqos->rx_dma_buf + (eqos->rx_desc_idx *
|
||||
EQOS_MAX_PACKET_SIZE);
|
||||
length = rx_desc->des3 & 0x7FFF;
|
||||
|
||||
arch_invalidate_cache_range((addr_t)((char *)recbuf), length);
|
||||
|
||||
if (length <= (cfg->mtu + ETH_FRAME_OVERHEAD_LEN)) {
|
||||
rx_pbuf = pbuf_alloc(PBUF_RAW, length, PBUF_POOL);
|
||||
|
||||
if (rx_pbuf) {
|
||||
uint32_t offset = 0;
|
||||
struct pbuf *q = NULL;
|
||||
|
||||
for (q = rx_pbuf; q != NULL; q = q->next) {
|
||||
memcpy( (uint8_t *)((uint8_t *)q->payload ), ((uint8_t *)recbuf + offset),
|
||||
q->len);
|
||||
offset += q->len;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ssdk_printf(SSDK_INFO, "len > 1500! desc3 = 0x%x\n", rx_desc->des3);
|
||||
}
|
||||
|
||||
//free packet
|
||||
rx_desc->des0 = (paddr_t)recbuf;
|
||||
rx_desc->des1 = 0;
|
||||
rx_desc->des2 = 0;
|
||||
/*
|
||||
* Make sure DMA observes new des3 value after observing
|
||||
* new des0 & des1 & des2 value under any condition, especially
|
||||
* when des3 located in a different cache line and the cache line
|
||||
* is automatically evicted due to corresponding cache set full.
|
||||
*/
|
||||
DMB;
|
||||
rx_desc->des3 = EQOS_DESC3_OWN | EQOS_DESC3_IOC | EQOS_DESC3_BUF1V;
|
||||
arch_clean_cache_range((addr_t)rx_desc, sizeof(struct eqos_desc));
|
||||
|
||||
dwmac_set_rx_tail_ptr(cfg->base,
|
||||
(uint32_t)eqos_get_desc(eqos, EQOS_DESCRIPTORS_RX, true),
|
||||
0);
|
||||
eqos->rx_desc_idx++;
|
||||
eqos->rx_desc_idx %= EQOS_DESCRIPTORS_RX;
|
||||
|
||||
eqos_rx_unlock(eqos);
|
||||
|
||||
if (rx_pbuf)
|
||||
netdev_input(dev, rx_pbuf);
|
||||
|
||||
|
||||
|
||||
// if(0x40 == length)
|
||||
// {
|
||||
// udp_length ++;
|
||||
// }
|
||||
|
||||
// if(50 == length) //20250113 <20><><EFBFBD><EFBFBD>
|
||||
// {
|
||||
// udp_length = udp_length + length;
|
||||
// }
|
||||
|
||||
// if(50 == length) //20250113 <20><><EFBFBD><EFBFBD>
|
||||
// {
|
||||
// udp_length = length;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// else
|
||||
// {
|
||||
// }
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static inline void __dwc_eth_enable_dma_rx_int(dwc_eth_dev_t *dwc_eth)
|
||||
{
|
||||
for (int chn = 0; chn < ETH_MAX_DMA_CHANNEL; chn++) {
|
||||
dwmac_enable_dma_rx_int(dwc_eth->config->base, chn, true);
|
||||
}
|
||||
}
|
||||
|
||||
__UNUSED static inline void __dwc_eth_disable_dma_rx_int(dwc_eth_dev_t *dwc_eth)
|
||||
{
|
||||
for (int chn = 0; chn < ETH_MAX_DMA_CHANNEL; chn++) {
|
||||
dwmac_enable_dma_rx_int(dwc_eth->config->base, chn, false);
|
||||
}
|
||||
}
|
||||
|
||||
void dwc_eth_enable_dma_rx_int(struct net_driver_s *dev, dma_rx_int_cb_t callback)
|
||||
{
|
||||
ASSERT(dev);
|
||||
dwc_eth_dev_t *dwc_eth = dev->d_private;
|
||||
|
||||
dwc_eth->rx_cb = callback;
|
||||
__dwc_eth_enable_dma_rx_int(dwc_eth);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief try to read rx packet and send the packet to lwip stack.
|
||||
* Should be called in thread context.
|
||||
* If enable DMA rx interrupt, i.e. poll is false, this function
|
||||
* should be called after DMA rx interrupt triggered. DMA rx
|
||||
* interrupt will be disabled in ISR, and re-enabled in this
|
||||
* function after reading out all rx packets, this is helpful to
|
||||
* avoid too much rx interrupt.
|
||||
*
|
||||
* @param [in] dev eth device
|
||||
* @param [in] poll true for polling read, false for interrupt read
|
||||
* @return int total length of rx packets or -1 if rx nothing
|
||||
*/
|
||||
int dwc_eth_rx(struct net_driver_s *dev, bool poll)
|
||||
{
|
||||
ASSERT(dev);
|
||||
|
||||
int rx_pkt_len = 0;
|
||||
int len;
|
||||
|
||||
do {
|
||||
len = dwc_eth_rx_poll(dev);
|
||||
if (len != -1)
|
||||
rx_pkt_len += len;
|
||||
}
|
||||
while (len != -1);
|
||||
|
||||
if (!poll) {
|
||||
dwc_eth_dev_t *dwc_eth = dev->d_private;
|
||||
/* After reading all packets out, re-enable eth dma rx
|
||||
* interrupt which had been disabled in rx int service
|
||||
* routine. This strategy can avoid too much eth interrupt.
|
||||
*/
|
||||
__dwc_eth_enable_dma_rx_int(dwc_eth);
|
||||
}
|
||||
|
||||
return rx_pkt_len ? rx_pkt_len : -1;
|
||||
}
|
||||
|
||||
static int dwc_eth_irq_handler(uint32_t irq, void *arg)
|
||||
{
|
||||
struct net_driver_s *dev = arg;
|
||||
dwc_eth_dev_t *dwc_eth = dev->d_private;
|
||||
uint32_t reg_base = dwc_eth->config->base;
|
||||
uint32_t status = dwmac_get_dma_int_status(reg_base);
|
||||
uint32_t sub_sts, detail;
|
||||
uint8_t chn = (irq == ENET1_SBD_INTR_NUM) ? 1 : 2;
|
||||
|
||||
// ssdk_printf(SSDK_DEBUG, "%s int status 0x%x\n", __func__, status);
|
||||
if (!status) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (status & (1 << 17)) {
|
||||
/* MAC interrupt */
|
||||
sub_sts = dwmac_get_mac_int_status(reg_base);
|
||||
ssdk_printf(SSDK_EMERG, "%s %d mac int status 0x%x\n", __func__, irq, sub_sts);
|
||||
if (sub_sts & (1 << 0)) {
|
||||
/* RGMII/SMII PHY link status changed. Read of MAC_PHYIF_Control_Status
|
||||
* register will clear the interrupt status.
|
||||
*/
|
||||
detail = dwmac_get_mac_phyif_control_status(reg_base);
|
||||
if (detail & (1 << 19))
|
||||
ssdk_printf(SSDK_EMERG, "ETH%d phy link up\n", chn);
|
||||
else
|
||||
ssdk_printf(SSDK_EMERG, "ETH%d phy link down\n", chn);
|
||||
}
|
||||
if (sub_sts & (3 << 1)) {
|
||||
/* TBI/RTBI/SGMII PHY link status changed, or TBI/RTBI/SGMII PHY
|
||||
* auto-negotiation is completed. Read of MAC_AN_Status register
|
||||
* will clear the interrupt status.
|
||||
*/
|
||||
detail = dwmac_get_mac_an_status(reg_base);
|
||||
ssdk_printf(SSDK_EMERG, "ETH%d mac an status 0x%x\n",
|
||||
chn, detail);
|
||||
}
|
||||
if (sub_sts & (1 << 4)) {
|
||||
/* A magic packet or Wake-on-LAN packet is received.
|
||||
* Read of MAC_PMT_Control_Status register will clear
|
||||
* the interrupt status.
|
||||
*/
|
||||
detail = dwmac_get_mac_pmt_control_status(reg_base);
|
||||
ssdk_printf(SSDK_EMERG, "ETH%d mac pmt ctrl status 0x%x\n",
|
||||
chn, detail);
|
||||
}
|
||||
if (sub_sts & (1 << 5)) {
|
||||
/* LPI state entry or exit in the MAC Transmitter or Receiver.
|
||||
* Read of MAC_LPI_Control_Status register will clear the
|
||||
* interrupt status.
|
||||
*/
|
||||
detail = dwmac_get_mac_lpi_control_status(reg_base);
|
||||
ssdk_printf(SSDK_EMERG, "ETH%d mac lpi ctrl status 0x%x\n",
|
||||
chn, detail);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & (1 << 16)) {
|
||||
/* MTL interrupt */
|
||||
sub_sts = dwmac_get_mtl_int_status(reg_base);
|
||||
if (sub_sts & 0xFFFFFF00) {
|
||||
ssdk_printf(SSDK_EMERG, "ETH%d mtl int status 0x%x\n",
|
||||
chn, sub_sts);
|
||||
ASSERT(0);
|
||||
}
|
||||
for (int i = 0; i < ETH_MAX_DMA_CHANNEL; i++) {
|
||||
if (sub_sts & (1 << i)) {
|
||||
detail = dwmac_get_mtl_q_int_status(reg_base, i);
|
||||
dwmac_clr_mtl_q_int_status(reg_base, i, detail);
|
||||
if (detail & (1 << 16))
|
||||
ssdk_printf(SSDK_WARNING, "ETH%d mtl queue %d rx overflow\n",
|
||||
chn, i);
|
||||
if (detail & (1 << 1))
|
||||
ssdk_printf(SSDK_WARNING, "ETH%d mtl queue %d ABS updated\n",
|
||||
chn, i);
|
||||
if (detail & (1 << 1))
|
||||
ssdk_printf(SSDK_WARNING, "ETH%d mtl queue %d tx underflow\n",
|
||||
chn, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (status & 0x7F) {
|
||||
/* DMA interrupt */
|
||||
for (int chn = 0; chn < ETH_MAX_DMA_CHANNEL; chn++) {
|
||||
sub_sts = dwmac_get_dma_chn_status(reg_base, chn);
|
||||
dwmac_clear_dma_chn_int_status(reg_base, chn);
|
||||
if (sub_sts & BIT(6)) {
|
||||
/* DMA rx interrupt */
|
||||
// ssdk_printf(SSDK_DEBUG, "%s: chn %d rx int\n", __func__, chn);
|
||||
dwmac_enable_dma_rx_int(reg_base, chn, false);
|
||||
if (dwc_eth->rx_cb)
|
||||
dwc_eth->rx_cb(dev);
|
||||
}
|
||||
if (sub_sts & BIT(0)) {
|
||||
/* DMA tx interrupt */
|
||||
// ssdk_printf(SSDK_DEBUG, "%s: chn %d tx int\n", __func__, chn);
|
||||
/* Nothing to do for now. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dwc_eqos_mdio_read(phy_bus_t *bus, uint32_t phyaddr,
|
||||
uint32_t devaddr, uint32_t reg)
|
||||
{
|
||||
dwc_eth_dev_t *dwc_eth_dev = containerof(bus, dwc_eth_dev_t, phy_bus);
|
||||
uint32_t reg_base = dwc_eth_dev->config->base;
|
||||
|
||||
return mac_mdio_read(reg_base, phyaddr, devaddr, reg);
|
||||
}
|
||||
|
||||
static int dwc_eqos_mdio_write(phy_bus_t *bus, uint32_t phyaddr,
|
||||
uint32_t devaddr, uint32_t reg, uint32_t data)
|
||||
{
|
||||
dwc_eth_dev_t *dwc_eth_dev = containerof(bus, dwc_eth_dev_t, phy_bus);
|
||||
uint32_t reg_base = dwc_eth_dev->config->base;
|
||||
|
||||
return mac_mdio_write(reg_base, phyaddr, devaddr, reg, data);
|
||||
}
|
||||
|
||||
static phy_bus_ops_t g_dwc_eqos_mdio_ops = {
|
||||
.mdio_read = dwc_eqos_mdio_read,
|
||||
.mdio_write = dwc_eqos_mdio_write
|
||||
};
|
||||
|
||||
static void dwc_eth_phy_bus_init(phy_bus_t *bus)
|
||||
{
|
||||
list_initialize(&bus->phy_dev_list);
|
||||
bus->ref_cnt = 0;
|
||||
bus->ops = &g_dwc_eqos_mdio_ops;
|
||||
}
|
||||
|
||||
static dwc_eth_dev_t *alloc_dwc_eth_device(void)
|
||||
{
|
||||
#if !CONFIG_ETH_USE_HEAP
|
||||
for (int i = 0; i < MAX_ETH_CNT; i++) {
|
||||
if (!g_eqos_data[i].used)
|
||||
{
|
||||
g_eqos_data[i].used = true;
|
||||
return &g_eqos_data[i].dev;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
return (dwc_eth_dev_t *)malloc(sizeof(dwc_eth_dev_t));
|
||||
#endif
|
||||
}
|
||||
|
||||
int dwc_eth_probe(struct net_driver_s *dev, dwc_eth_config_t *cfg)
|
||||
{
|
||||
ASSERT(dev && cfg);
|
||||
|
||||
dev->d_init = dwc_eth_init;
|
||||
dev->d_txavail = dwc_eth_txavail;
|
||||
dev->d_getmac = dwc_eth_getmac;
|
||||
dev->d_getmtu = dwc_eth_getmtu;
|
||||
|
||||
dwc_eth_dev_t *dw_eth_dev = alloc_dwc_eth_device();
|
||||
ASSERT(dw_eth_dev);
|
||||
dw_eth_dev->init = false;
|
||||
dw_eth_dev->config = cfg;
|
||||
dev->d_private = dw_eth_dev;
|
||||
|
||||
dev->d_ipaddr.addr = (cfg->ip[3] << 24) | (cfg->ip[2] << 16) |
|
||||
(cfg->ip[1] << 8) | cfg->ip[0];
|
||||
dev->d_netmask.addr = (cfg->mask[3] << 24) | (cfg->mask[2] << 16) |
|
||||
(cfg->mask[1] << 8) | cfg->mask[0];
|
||||
dev->d_gateway.addr = (1 << 24) | (cfg->ip[2] << 16) |
|
||||
(cfg->ip[1] << 8) | cfg->ip[0];
|
||||
|
||||
dwc_eth_phy_bus_init(&dw_eth_dev->phy_bus);
|
||||
|
||||
for (int i = 0; cfg->phy[i].phy_addr != ~0; i++) {
|
||||
phy_dev_register(&dw_eth_dev->phy_bus, &cfg->phy[i]);
|
||||
}
|
||||
|
||||
External_wdt_refresh();
|
||||
int ret = netdev_register(dev, NET_LL_ETHERNET);
|
||||
External_wdt_refresh();
|
||||
irq_attach(cfg->irq_num, dwc_eth_irq_handler, dev);
|
||||
irq_enable(cfg->irq_num);
|
||||
|
||||
return ret;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,638 @@
|
||||
/**
|
||||
* dw_mac_lld.h
|
||||
*
|
||||
* Copyright (c) 2021 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description: dw eth mac lld header file
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#ifndef _DW_MAC_LLD_H_
|
||||
#define _DW_MAC_LLD_H_
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(n) (1U << (n))
|
||||
#endif
|
||||
|
||||
#ifndef GENMASK
|
||||
#define GENMASK(h, l) \
|
||||
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (32 - 1 - (h))))
|
||||
#endif
|
||||
|
||||
/* MAC reg */
|
||||
#define MAC_CONFIG 0x00000000
|
||||
#define MAC_PACKET_FILTER 0x00000008
|
||||
#define MAC_HASH_TAB_0_31 0x00000010
|
||||
#define MAC_HASH_TAB_32_63 0x00000014
|
||||
#define MAC_HASH_TAB_64_95 0x00000018
|
||||
#define MAC_HASH_TAB_96_127 0x0000001c
|
||||
#define MAC_RX_FLOW_CTRL 0x00000090
|
||||
#define MAC_QX_TX_FLOW_CTRL(x) (0x70 + x * 4)
|
||||
#define MAC_TXQ_PRTY_MAP0 0x98
|
||||
#define MAC_TXQ_PRTY_MAP1 0x9C
|
||||
#define MAC_RXQ_CTRL0 0x000000a0
|
||||
#define MAC_RXQ_CTRL1 0x000000a4
|
||||
#define MAC_RXQ_CTRL2 0x000000a8
|
||||
#define MAC_RXQ_CTRL3 0x000000ac
|
||||
#define MAC_INT_STATUS 0x000000b0
|
||||
#define MAC_INT_EN 0x000000b4
|
||||
#define MAC_RX_TX_STATUS 0x000000b8
|
||||
#define MAC_PMT_CONTROL_STATUS 0x000000c0
|
||||
#define MAC_LPI_CONTROL_STATUS 0x000000d0
|
||||
#define MAC_1US_TIC_COUNTER 0x000000dc
|
||||
#define MAC_PCS_BASE 0x000000e0
|
||||
#define MAC_AN_STATUS 0x000000e4
|
||||
#define MAC_PHYIF_CONTROL_STATUS 0x000000f8
|
||||
#define MAC_PMT 0x000000c0
|
||||
#define MAC_VERSION 0x00000110
|
||||
#define MAC_DEBUG 0x00000114
|
||||
#define MAC_HW_FEATURE0 0x0000011c
|
||||
#define MAC_HW_FEATURE1 0x00000120
|
||||
#define MAC_HW_FEATURE2 0x00000124
|
||||
#define MAC_HW_FEATURE3 0x00000128
|
||||
#define MAC_MDIO_ADDR 0x00000200
|
||||
#define MAC_MDIO_DATA 0x00000204
|
||||
#define MAC_ADDR_HIGH(reg) (0x300 + reg * 8)
|
||||
#define MAC_ADDR_LOW(reg) (0x304 + reg * 8)
|
||||
/* Rx Stats */
|
||||
#define MAC_PACKETS_RX_CONUT_64 0x000007ac
|
||||
#define MAC_PACKETS_RX_CONUT_65_127 0x000007b0
|
||||
#define MAC_PACKETS_RX_CONUT_128_255 0x000007b4
|
||||
#define MAC_PACKETS_RX_CONUT_256_511 0x000007b8
|
||||
#define MAC_PACKETS_RX_CONUT_512_1023 0x000007bc
|
||||
#define MAC_PACKETS_RX_CONUT_1024_MAX 0x000007c0
|
||||
#define MAC_PACKETS_RX_CONUT_UNICAST 0x000007c4
|
||||
#define MAC_PACKETS_RX_CONUT_MULTICAST 0x00000790
|
||||
#define MAC_PACKETS_RX_CONUT_BROADCAST 0x0000078c
|
||||
#define MAC_PACKETS_RX_CONUT_ALL_BYTES 0x00000784
|
||||
#define MAC_PACKETS_RX_CONUT_ALL_PKT 0x00000780
|
||||
#define MAC_PACKETS_RX_CONUT_BAD_PKT 0x000007e0
|
||||
#define MAC_PACKETS_RX_CONUT_CRC_ERR 0x00000794
|
||||
#define MAC_PACKETS_RX_CONUT_FRAG_ERR 0x0000079C
|
||||
#define MAC_PACKETS_RX_CONUT_ALIGN_ERR 0x00000798
|
||||
#define MAC_PACKETS_RX_CONUT_JABBER_ERR 0x000007a0
|
||||
#define MAC_PACKETS_RX_CONUT_UNDER_PKT 0x000007a4
|
||||
#define MAC_PACKETS_RX_CONUT_OVER_PKT 0x000007a8
|
||||
#define MAC_PACKETS_RX_CONUT_DROP_PKT 0x000007d4
|
||||
#define MAC_PACKETS_RX_CONUT_MIIDROP_PKT 0x000007e0
|
||||
/* Tx Stats */
|
||||
#define MAC_PACKETS_TX_CONUT_ALL_BYTES 0x00000714
|
||||
#define MAC_PACKETS_TX_CONUT_UNICAST 0x0000073C
|
||||
#define MAC_PACKETS_TX_CONUT_BROADCAST 0x00000744
|
||||
#define MAC_PACKETS_TX_CONUT_MULTICAST 0x00000740
|
||||
#define MAC_PACKETS_TX_CONUT_SINGL_COLL 0x0000074C
|
||||
#define MAC_PACKETS_TX_CONUT_MULT_COLL 0x00000750
|
||||
#define MAC_PACKETS_TX_CONUT_DFRD_COLL 0x00000754
|
||||
#define MAC_PACKETS_TX_CONUT_LATE_COLL 0x00000758
|
||||
#define MAC_PACKETS_TX_CONUT_OVER_PKT 0x00000778
|
||||
#define MAC_PACKETS_TX_CONUT_ALL_PKT 0x00000718
|
||||
#define MAC_PACKETS_TX_CONUT_GOOD_PKT 0x00000768
|
||||
|
||||
#define MAC_PACKETS_TX_CONUT_DROP_PKT_COLL 0x0000075c
|
||||
#define MAC_PACKETS_TX_CONUT_DROP_PKT_CARR 0x00000760
|
||||
#define MAC_PACKETS_TX_CONUT_ERR_PKT 0x0000076c
|
||||
|
||||
#define MMC_RX_INTERRUPT_MASK 0x70C
|
||||
#define MMC_TX_INTERRUPT_MASK 0x710
|
||||
#define MMC_IPC_RX_INTERRUPT_MASK 0x800
|
||||
|
||||
/* RX Queues Routing */
|
||||
#define MAC_RXQCTRL_AVCPQ_MASK GENMASK(2, 0)
|
||||
#define MAC_RXQCTRL_AVCPQ_SHIFT 0
|
||||
#define MAC_RXQCTRL_PTPQ_MASK GENMASK(6, 4)
|
||||
#define MAC_RXQCTRL_PTPQ_SHIFT 4
|
||||
#define MAC_RXQCTRL_DCBCPQ_MASK GENMASK(10, 8)
|
||||
#define MAC_RXQCTRL_DCBCPQ_SHIFT 8
|
||||
#define MAC_RXQCTRL_UPQ_MASK GENMASK(14, 12)
|
||||
#define MAC_RXQCTRL_UPQ_SHIFT 12
|
||||
#define MAC_RXQCTRL_MCBCQ_MASK GENMASK(18, 16)
|
||||
#define MAC_RXQCTRL_MCBCQ_SHIFT 16
|
||||
#define MAC_RXQCTRL_MCBCQEN BIT(20)
|
||||
#define MAC_RXQCTRL_MCBCQEN_SHIFT 20
|
||||
#define MAC_RXQCTRL_TACPQE BIT(21)
|
||||
#define MAC_RXQCTRL_TACPQE_SHIFT 21
|
||||
|
||||
/* MAC Packet Filtering */
|
||||
#define MAC_PACKET_FILTER_PR BIT(0)
|
||||
#define MAC_PACKET_FILTER_HUC BIT(1)
|
||||
#define MAC_PACKET_FILTER_HMC BIT(2)
|
||||
#define MAC_PACKET_FILTER_DAIF BIT(3)
|
||||
#define MAC_PACKET_FILTER_PM BIT(4)
|
||||
#define MAC_PACKET_FILTER_DBF BIT(5)
|
||||
#define MAC_PACKET_FILTER_MASK GENMASK(7, 6)
|
||||
#define MAC_PACKET_FILTER_SHIFT (6)
|
||||
#define MAC_PACKET_FILTER_HPF BIT(10)
|
||||
#define MAC_PACKET_FILTER_PA BIT(31)
|
||||
|
||||
#define MAC_MAX_PERFECT_ADDRESSES 128
|
||||
|
||||
/* MAC RX Queue Enable */
|
||||
#define MAC_RX_QUEUE_CLEAR(queue) ~(GENMASK(1, 0) << ((queue) * 2))
|
||||
#define MAC_RX_AV_QUEUE_ENABLE(queue) BIT((queue) * 2)
|
||||
#define MAC_RX_DCB_QUEUE_ENABLE(queue) BIT(((queue) * 2) + 1)
|
||||
|
||||
/* MAC Flow Control RX */
|
||||
#define MAC_RX_FLOW_CTRL_RFE BIT(0)
|
||||
|
||||
/* RX Queues Priorities */
|
||||
#define MAC_RXQCTRL_PSRQX_MASK(x) GENMASK(7 + ((x) * 8), 0 + ((x) * 8))
|
||||
#define MAC_RXQCTRL_PSRQX_SHIFT(x) ((x) * 8)
|
||||
|
||||
/* TX Queues Priorities */
|
||||
#define MAC_TXQCTRL_PSTQX_MASK(x) GENMASK(7 + ((x) * 8), 0 + ((x) * 8))
|
||||
#define MAC_TXQCTRL_PSTQX_SHIFT(x) ((x) * 8)
|
||||
|
||||
/* MAC Flow Control TX */
|
||||
#define MAC_TX_FLOW_CTRL_TFE BIT(1)
|
||||
#define MAC_TX_FLOW_CTRL_PT_SHIFT 16
|
||||
|
||||
/* MAC Interrupt bitmap*/
|
||||
#define MAC_INT_RGSMIIS BIT(0)
|
||||
#define MAC_INT_PCS_LINK BIT(1)
|
||||
#define MAC_INT_PCS_ANE BIT(2)
|
||||
#define MAC_INT_PCS_PHYIS BIT(3)
|
||||
#define MAC_INT_PMT_EN BIT(4)
|
||||
#define MAC_INT_LPI_EN BIT(5)
|
||||
|
||||
#define MAC_PCS_IRQ_DEFAULT (MAC_INT_RGSMIIS | MAC_INT_PCS_LINK | MAC_INT_PCS_ANE)
|
||||
|
||||
#define MAC_INT_DEFAULT_ENABLE (MAC_INT_PMT_EN | MAC_INT_LPI_EN)
|
||||
|
||||
/* MAC config */
|
||||
#define MAC_CONFIG_IPC BIT(27)
|
||||
#define MAC_CONFIG_2K BIT(22)
|
||||
#define MAC_CONFIG_ACS BIT(20)
|
||||
#define MAC_CONFIG_WD BIT(19)
|
||||
#define MAC_CONFIG_BE BIT(18)
|
||||
#define MAC_CONFIG_JD BIT(17)
|
||||
#define MAC_CONFIG_JE BIT(16)
|
||||
#define MAC_CONFIG_PS BIT(15)
|
||||
#define MAC_CONFIG_FES BIT(14)
|
||||
#define MAC_CONFIG_DM BIT(13)
|
||||
#define MAC_CONFIG_DCRS BIT(9)
|
||||
#define MAC_CONFIG_TE BIT(1)
|
||||
#define MAC_CONFIG_RE BIT(0)
|
||||
|
||||
/* MAC HW ADDR regs */
|
||||
#define MAC_HI_DCS GENMASK(18, 16)
|
||||
#define MAC_HI_DCS_SHIFT 16
|
||||
#define MAC_HI_REG_AE BIT(31)
|
||||
|
||||
/* MTL registers */
|
||||
#define MTL_OPERATION_MODE 0x00000c00
|
||||
#define MTL_OPERATION_SCHALG_MASK GENMASK(6, 5)
|
||||
#define MTL_OPERATION_SCHALG_WRR (0x0 << 5)
|
||||
#define MTL_OPERATION_SCHALG_WFQ (0x1 << 5)
|
||||
#define MTL_OPERATION_SCHALG_DWRR (0x2 << 5)
|
||||
#define MTL_OPERATION_SCHALG_SP (0x3 << 5)
|
||||
#define MTL_OPERATION_RAA BIT(2)
|
||||
#define MTL_OPERATION_RAA_SP (0x0 << 2)
|
||||
#define MTL_OPERATION_RAA_WSP (0x1 << 2)
|
||||
|
||||
#define MTL_TX_OPERATION_TSF BIT(2)
|
||||
#define MTL_TX_OPERATION_TQ GENMASK(3, 2)
|
||||
#define MTL_TX_OPERATION_TQ_EN (0x2 << 2)
|
||||
#define MTL_TX_OPERATION_TQ_DIS (0x0 << 2)
|
||||
|
||||
#define MTL_TX_CONFIG_FLAGS_TQ BIT(3)
|
||||
|
||||
#define MTL_INT_STATUS 0x00000c20
|
||||
#define MTL_INT_QX(x) BIT(x)
|
||||
|
||||
#define MTL_RXQ_DMA_MAP0 0x00000c30 /* queue 0 to 3 */
|
||||
#define MTL_RXQ_DMA_MAP1 0x00000c34 /* queue 4 to 7 */
|
||||
#define MTL_RXQ_DMA_Q04MDMACH_MASK GENMASK(3, 0)
|
||||
#define MTL_RXQ_DMA_Q04MDMACH(x) ((x) << 0)
|
||||
#define MTL_RXQ_DMA_QXMDMACH_MASK(x) GENMASK(11 + (8 * ((x) - 1)), 8 * (x))
|
||||
#define MTL_RXQ_DMA_QXMDMACH(channel, q) ((channel) << (8 * (q)))
|
||||
|
||||
#define MTL_ECC_CTRL 0xcc0
|
||||
#define MTL_ECC_DEFAULT_ENABLE 0xf
|
||||
|
||||
#define MTL_DPP_CTRL 0x00000ce0
|
||||
#define MTL_DPP_CTRL_DATA_PARITY BIT(0)
|
||||
#define MTL_DPP_CTRL_SLAVE_PARITY BIT(2)
|
||||
|
||||
#define MTL_CHAN_BASE_ADDR 0x00000d00
|
||||
#define MTL_CHAN_BASE_OFFSET 0x40
|
||||
#define MTL_CHANX_BASE_ADDR(x) (MTL_CHAN_BASE_ADDR + \
|
||||
(x * MTL_CHAN_BASE_OFFSET))
|
||||
|
||||
#define MTL_CHAN_TX_OP_MODE(x) MTL_CHANX_BASE_ADDR(x)
|
||||
#define MTL_CHAN_TX_DEBUG(x) (MTL_CHANX_BASE_ADDR(x) + 0x8)
|
||||
#define MTL_CHAN_INT_CTRL(x) (MTL_CHANX_BASE_ADDR(x) + 0x2c)
|
||||
#define MTL_CHAN_RX_OP_MODE(x) (MTL_CHANX_BASE_ADDR(x) + 0x30)
|
||||
#define MTL_CHAN_RX_DEBUG(x) (MTL_CHANX_BASE_ADDR(x) + 0x38)
|
||||
|
||||
#define MTL_OP_MODE_RSF BIT(5)
|
||||
#define MTL_OP_MODE_TXQEN_MASK GENMASK(3, 2)
|
||||
#define MTL_OP_MODE_TXQEN_AV BIT(2)
|
||||
#define MTL_OP_MODE_TXQEN BIT(3)
|
||||
#define MTL_OP_MODE_TSF BIT(1)
|
||||
|
||||
#define MTL_OP_MODE_TQS_MASK GENMASK(24, 16)
|
||||
#define MTL_OP_MODE_TQS_SHIFT 16
|
||||
|
||||
#define MTL_OP_MODE_TTC_MASK 0x70
|
||||
#define MTL_OP_MODE_TTC_SHIFT 4
|
||||
|
||||
#define MTL_OP_MODE_TTC_32 0
|
||||
#define MTL_OP_MODE_TTC_64 (1 << MTL_OP_MODE_TTC_SHIFT)
|
||||
#define MTL_OP_MODE_TTC_96 (2 << MTL_OP_MODE_TTC_SHIFT)
|
||||
#define MTL_OP_MODE_TTC_128 (3 << MTL_OP_MODE_TTC_SHIFT)
|
||||
#define MTL_OP_MODE_TTC_192 (4 << MTL_OP_MODE_TTC_SHIFT)
|
||||
#define MTL_OP_MODE_TTC_256 (5 << MTL_OP_MODE_TTC_SHIFT)
|
||||
#define MTL_OP_MODE_TTC_384 (6 << MTL_OP_MODE_TTC_SHIFT)
|
||||
#define MTL_OP_MODE_TTC_512 (7 << MTL_OP_MODE_TTC_SHIFT)
|
||||
|
||||
#define MTL_OP_MODE_RQS_MASK GENMASK(29, 20)
|
||||
#define MTL_OP_MODE_RQS_SHIFT 20
|
||||
|
||||
#define MTL_OP_MODE_RFD_MASK GENMASK(19, 14)
|
||||
#define MTL_OP_MODE_RFD_SHIFT 14
|
||||
|
||||
#define MTL_OP_MODE_RFA_MASK GENMASK(13, 8)
|
||||
#define MTL_OP_MODE_RFA_SHIFT 8
|
||||
#define MTL_OP_MODE_FEP BIT(4)
|
||||
#define MTL_OP_MODE_FUP BIT(3)
|
||||
#define MTL_OP_MODE_EHFC BIT(7)
|
||||
|
||||
#define MTL_OP_MODE_RTC_MASK 0x18
|
||||
#define MTL_OP_MODE_RTC_SHIFT 3
|
||||
|
||||
#define MTL_OP_MODE_RTC_32 (1 << MTL_OP_MODE_RTC_SHIFT)
|
||||
#define MTL_OP_MODE_RTC_64 0
|
||||
#define MTL_OP_MODE_RTC_96 (2 << MTL_OP_MODE_RTC_SHIFT)
|
||||
#define MTL_OP_MODE_RTC_128 (3 << MTL_OP_MODE_RTC_SHIFT)
|
||||
|
||||
/* MTL ETS Control register */
|
||||
#define MTL_ETS_CTRL_BASE_ADDR 0x00000d10
|
||||
#define MTL_ETS_CTRL_BASE_OFFSET 0x40
|
||||
#define MTL_ETSX_CTRL_BASE_ADDR(x) (MTL_ETS_CTRL_BASE_ADDR + \
|
||||
((x) * MTL_ETS_CTRL_BASE_OFFSET))
|
||||
|
||||
#define MTL_ETS_CTRL_CC BIT(3)
|
||||
#define MTL_ETS_CTRL_AVALG BIT(2)
|
||||
|
||||
/* MTL Queue Quantum Weight */
|
||||
#define MTL_TXQ_WEIGHT_BASE_ADDR 0x00000d18
|
||||
#define MTL_TXQ_WEIGHT_BASE_OFFSET 0x40
|
||||
#define MTL_TXQX_WEIGHT_BASE_ADDR(x) (MTL_TXQ_WEIGHT_BASE_ADDR + \
|
||||
((x) * MTL_TXQ_WEIGHT_BASE_OFFSET))
|
||||
#define MTL_TXQ_WEIGHT_ISCQW_MASK GENMASK(20, 0)
|
||||
|
||||
/* MTL sendSlopeCredit register */
|
||||
#define MTL_SEND_SLP_CRED_BASE_ADDR 0x00000d1c
|
||||
#define MTL_SEND_SLP_CRED_OFFSET 0x40
|
||||
#define MTL_SEND_SLP_CREDX_BASE_ADDR(x) (MTL_SEND_SLP_CRED_BASE_ADDR + \
|
||||
((x) * MTL_SEND_SLP_CRED_OFFSET))
|
||||
|
||||
#define MTL_SEND_SLP_CRED_SSC_MASK GENMASK(13, 0)
|
||||
|
||||
/* MTL hiCredit register */
|
||||
#define MTL_HIGH_CRED_BASE_ADDR 0x00000d20
|
||||
#define MTL_HIGH_CRED_OFFSET 0x40
|
||||
#define MTL_HIGH_CREDX_BASE_ADDR(x) (MTL_HIGH_CRED_BASE_ADDR + \
|
||||
((x) * MTL_HIGH_CRED_OFFSET))
|
||||
|
||||
#define MTL_HIGH_CRED_HC_MASK GENMASK(28, 0)
|
||||
|
||||
/* MTL loCredit register */
|
||||
#define MTL_LOW_CRED_BASE_ADDR 0x00000d24
|
||||
#define MTL_LOW_CRED_OFFSET 0x40
|
||||
#define MTL_LOW_CREDX_BASE_ADDR(x) (MTL_LOW_CRED_BASE_ADDR + \
|
||||
((x) * MTL_LOW_CRED_OFFSET))
|
||||
|
||||
#define MTL_HIGH_CRED_LC_MASK GENMASK(28, 0)
|
||||
|
||||
/* MTL interrupt */
|
||||
#define MTL_RX_OVERFLOW_INT_EN BIT(24)
|
||||
#define MTL_RX_OVERFLOW_INT BIT(16)
|
||||
#define MTL_TX_UNDEROVERFLOW_INT BIT(0)
|
||||
|
||||
/* Default operating mode of the MAC */
|
||||
#define MAC_CORE_INIT (MAC_CONFIG_JD | MAC_CONFIG_PS | \
|
||||
MAC_CONFIG_BE | MAC_CONFIG_DCRS | MAC_CONFIG_DM)
|
||||
|
||||
/* To dump the core regs excluding the Address Registers */
|
||||
#define MAC_REG_NUM 0x300
|
||||
|
||||
/* MTL algorithms identifiers */
|
||||
#define MTL_TX_ALGORITHM_WRR 0x0
|
||||
#define MTL_TX_ALGORITHM_WFQ 0x1
|
||||
#define MTL_TX_ALGORITHM_DWRR 0x2
|
||||
#define MTL_TX_ALGORITHM_SP 0x3
|
||||
#define MTL_RX_ALGORITHM_SP 0x4
|
||||
#define MTL_RX_ALGORITHM_WSP 0x5
|
||||
|
||||
/* RX/TX Queue Mode */
|
||||
#define MTL_QUEUE_MODE_AVB 0x1
|
||||
#define MTL_QUEUE_MODE_DCB 0x2
|
||||
|
||||
#define SF_MODE 1
|
||||
|
||||
#define MAC_FITER_PASS_ALL 0
|
||||
#define MAC_FITER_PASS_MULTICAST 1
|
||||
#define MAC_FITER_PASS_HASH_MULTICAST 2
|
||||
#define MAC_FITER_PASS_UNICAST 3
|
||||
|
||||
#define ERDES4_MSG_TYPE_MASK GENMASK(11, 8)
|
||||
|
||||
/* Extended RDES4 message type definitions */
|
||||
#define RDES_EXT_NO_PTP 0x0
|
||||
#define RDES_EXT_SYNC 0x1
|
||||
#define RDES_EXT_FOLLOW_UP 0x2
|
||||
#define RDES_EXT_DELAY_REQ 0x3
|
||||
#define RDES_EXT_DELAY_RESP 0x4
|
||||
#define RDES_EXT_PDELAY_REQ 0x5
|
||||
#define RDES_EXT_PDELAY_RESP 0x6
|
||||
#define RDES_EXT_PDELAY_FOLLOW_UP 0x7
|
||||
#define RDES_PTP_ANNOUNCE 0x8
|
||||
#define RDES_PTP_MANAGEMENT 0x9
|
||||
#define RDES_PTP_SIGNALING 0xa
|
||||
#define RDES_PTP_PKT_RESERVED_TYPE 0xf
|
||||
|
||||
/* Rx IPC status */
|
||||
enum rx_frame_status {
|
||||
RX_GOOD = 0x0,
|
||||
RX_BAD = 0x1,
|
||||
RX_DMA_PROCESS = 0x8,
|
||||
csum_none = 0x2,
|
||||
llc_snap = 0x4,
|
||||
rx_not_ls = 0x10,
|
||||
};
|
||||
|
||||
enum tx_frame_status {
|
||||
TX_GOOD = 0x0,
|
||||
TX_ERROR = 0x1,
|
||||
TX_DMA_PROCESS = 0x2,
|
||||
TX_NOT_LS = 0x3,
|
||||
};
|
||||
|
||||
/* DMA config */
|
||||
#define ETH_MAX_DMA_CHANNEL 1
|
||||
|
||||
#define DMA_BUS_MODE 0x00001000
|
||||
#define DMA_STATUS 0x00001008
|
||||
#define DMA_SYS_BUS_MODE 0x00001004
|
||||
#define DMA_DEBUG_STATUS_0 0x0000100c
|
||||
#define DMA_DEBUG_STATUS_1 0x00001010
|
||||
#define DMA_DEBUG_STATUS_2 0x00001014
|
||||
#define DMA_AXI_BUS_MODE 0x00001028
|
||||
|
||||
enum dma_rx_status {
|
||||
DMX_RX_STOP = 0,
|
||||
DMX_RX_RUN_FRTD,
|
||||
DMX_RX_RSVD,
|
||||
DMX_RX_WRP,
|
||||
DMX_RX_SUSPND,
|
||||
DMX_RX_RUN_CRD,
|
||||
DMX_RX_TSTMP,
|
||||
DMX_RX_TRP
|
||||
};
|
||||
|
||||
/* DMA Bus Mode bitmap */
|
||||
#define DMA_BUS_MODE_SFT_RESET BIT(0)
|
||||
|
||||
/* DMA SYS Bus Mode bitmap */
|
||||
#define DMA_BUS_MODE_SPH BIT(24)
|
||||
#define DMA_BUS_MODE_PBL BIT(16)
|
||||
#define DMA_BUS_MODE_PBL_SHIFT 16
|
||||
#define DMA_BUS_MODE_RPBL_SHIFT 16
|
||||
#define DMA_BUS_MODE_MB BIT(14)
|
||||
#define DMA_BUS_MODE_FB BIT(0)
|
||||
|
||||
/* DMA Interrupt top status */
|
||||
#define DMA_STATUS_MAC BIT(17)
|
||||
#define DMA_STATUS_MTL BIT(16)
|
||||
#define DMA_STATUS_CHAN7 BIT(7)
|
||||
#define DMA_STATUS_CHAN6 BIT(6)
|
||||
#define DMA_STATUS_CHAN5 BIT(5)
|
||||
#define DMA_STATUS_CHAN4 BIT(4)
|
||||
#define DMA_STATUS_CHAN3 BIT(3)
|
||||
#define DMA_STATUS_CHAN2 BIT(2)
|
||||
#define DMA_STATUS_CHAN1 BIT(1)
|
||||
#define DMA_STATUS_CHAN0 BIT(0)
|
||||
#define DMA_STATUS_CHAN0_5 GENMASK(4,0)
|
||||
|
||||
/* DMA debug status bitmap */
|
||||
#define DMA_DEBUG_STATUS_TS_MASK 0xf
|
||||
#define DMA_DEBUG_STATUS_RS_MASK 0xf
|
||||
|
||||
/* DMA AXI bitmap */
|
||||
#define DMA_AXI_EN_LPI BIT(31)
|
||||
#define DMA_AXI_LPI_XIT_FRM BIT(30)
|
||||
#define DMA_AXI_WR_OSR_LMT GENMASK(27, 24)
|
||||
#define DMA_AXI_WR_OSR_LMT_SHIFT 24
|
||||
#define DMA_AXI_RD_OSR_LMT GENMASK(19, 16)
|
||||
#define DMA_AXI_RD_OSR_LMT_SHIFT 16
|
||||
|
||||
#define DMA_AXI_OSR_MAX 0xf
|
||||
#define DMA_AXI_MAX_OSR_LIMIT ((DMA_AXI_OSR_MAX << DMA_AXI_WR_OSR_LMT_SHIFT) | \
|
||||
(DMA_AXI_OSR_MAX << DMA_AXI_RD_OSR_LMT_SHIFT))
|
||||
|
||||
#define DMA_SYS_BUS_MB BIT(14)
|
||||
#define DMA_AXI_1KBBE BIT(13)
|
||||
#define DMA_SYS_BUS_AAL BIT(12)
|
||||
#define DMA_SYS_BUS_EAME BIT(11)
|
||||
#define DMA_AXI_BLEN256 BIT(7)
|
||||
#define DMA_AXI_BLEN128 BIT(6)
|
||||
#define DMA_AXI_BLEN64 BIT(5)
|
||||
#define DMA_AXI_BLEN32 BIT(4)
|
||||
#define DMA_AXI_BLEN16 BIT(3)
|
||||
#define DMA_AXI_BLEN8 BIT(2)
|
||||
#define DMA_AXI_BLEN4 BIT(1)
|
||||
#define DMA_SYS_BUS_FB BIT(0)
|
||||
|
||||
#define DMA_BURST_LEN_DEFAULT (DMA_AXI_BLEN256 | DMA_AXI_BLEN128 | \
|
||||
DMA_AXI_BLEN64 | DMA_AXI_BLEN32 | \
|
||||
DMA_AXI_BLEN16 | DMA_AXI_BLEN8 | \
|
||||
DMA_AXI_BLEN4)
|
||||
|
||||
#define DMA_AXI_BURST_LEN_MASK 0x000000FE
|
||||
|
||||
/* Following DMA defines are chanels oriented */
|
||||
#define DMA_CHAN_BASE_ADDR 0x00001100
|
||||
#define DMA_CHAN_BASE_OFFSET 0x80
|
||||
#define DMA_CHANX_BASE_ADDR(x) (DMA_CHAN_BASE_ADDR + (x * DMA_CHAN_BASE_OFFSET))
|
||||
#define DMA_CHAN_REG_NUMBER 17
|
||||
|
||||
#define DMA_CHAN_CONTROL(x) DMA_CHANX_BASE_ADDR(x)
|
||||
#define DMA_CHAN_TX_CONTROL(x) (DMA_CHANX_BASE_ADDR(x) + 0x4)
|
||||
#define DMA_CHAN_RX_CONTROL(x) (DMA_CHANX_BASE_ADDR(x) + 0x8)
|
||||
#define DMA_CHAN_TX_BASE_ADDR_HI(x) (DMA_CHANX_BASE_ADDR(x) + 0x10)
|
||||
#define DMA_CHAN_TX_BASE_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x14)
|
||||
#define DMA_CHAN_RX_BASE_ADDR_HI(x) (DMA_CHANX_BASE_ADDR(x) + 0x18)
|
||||
#define DMA_CHAN_RX_BASE_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x1c)
|
||||
#define DMA_CHAN_TX_END_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x20)
|
||||
#define DMA_CHAN_RX_END_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x28)
|
||||
#define DMA_CHAN_TX_RING_LEN(x) (DMA_CHANX_BASE_ADDR(x) + 0x2c)
|
||||
#define DMA_CHAN_RX_RING_LEN(x) (DMA_CHANX_BASE_ADDR(x) + 0x30)
|
||||
#define DMA_CHAN_INTR_ENA(x) (DMA_CHANX_BASE_ADDR(x) + 0x34)
|
||||
#define DMA_CHAN_RX_WATCHDOG(x) (DMA_CHANX_BASE_ADDR(x) + 0x38)
|
||||
#define DMA_CHAN_SLOT_CTRL_STATUS(x) (DMA_CHANX_BASE_ADDR(x) + 0x3c)
|
||||
#define DMA_CHAN_CUR_TX_DESC(x) (DMA_CHANX_BASE_ADDR(x) + 0x44)
|
||||
#define DMA_CHAN_CUR_RX_DESC(x) (DMA_CHANX_BASE_ADDR(x) + 0x4c)
|
||||
#define DMA_CHAN_CUR_TX_BUF_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x54)
|
||||
#define DMA_CHAN_CUR_RX_BUF_ADDR(x) (DMA_CHANX_BASE_ADDR(x) + 0x5c)
|
||||
#define DMA_CHAN_STATUS(x) (DMA_CHANX_BASE_ADDR(x) + 0x60)
|
||||
|
||||
/* DMA Control X */
|
||||
#define DMA_CONTROL_MSS_MASK GENMASK(13, 0)
|
||||
|
||||
/* DMA Tx channel X Control register defines */
|
||||
#define DMA_CONTROL_DSL_MASK GENMASK(20, 18)
|
||||
#define DMA_CONTROL_DSL_SHIFT 18
|
||||
#define DMA_CONTROL_TSE BIT(12)
|
||||
#define DMA_CONTROL_OSP BIT(4)
|
||||
#define DMA_CONTROL_ST BIT(0)
|
||||
#define DMA_CONTROL_TXPBL(x) (((x) << 16) & GENMASK(21, 16))
|
||||
|
||||
/* DMA Rx channel X Control register defines */
|
||||
#define DMA_CONTROL_SR BIT(0)
|
||||
#define DMA_RBSZ_MASK GENMASK(14, 1)
|
||||
#define DMA_RBSZ_SHIFT 1
|
||||
#define DMA_CONTROL_RXPBL(x) (((x) << 16) & GENMASK(21, 16))
|
||||
|
||||
/* Interrupt status per channel */
|
||||
#define DMA_CHAN_STATUS_REB GENMASK(21, 19)
|
||||
#define DMA_CHAN_STATUS_REB_SHIFT 19
|
||||
#define DMA_CHAN_STATUS_TEB GENMASK(18, 16)
|
||||
#define DMA_CHAN_STATUS_TEB_SHIFT 16
|
||||
#define DMA_CHAN_STATUS_NIS BIT(15)
|
||||
#define DMA_CHAN_STATUS_AIS BIT(14)
|
||||
#define DMA_CHAN_STATUS_CDE BIT(13)
|
||||
#define DMA_CHAN_STATUS_FBE BIT(12)
|
||||
#define DMA_CHAN_STATUS_ERI BIT(11)
|
||||
#define DMA_CHAN_STATUS_ETI BIT(10)
|
||||
#define DMA_CHAN_STATUS_RWT BIT(9)
|
||||
#define DMA_CHAN_STATUS_RPS BIT(8)
|
||||
#define DMA_CHAN_STATUS_RBU BIT(7)
|
||||
#define DMA_CHAN_STATUS_RI BIT(6)
|
||||
#define DMA_CHAN_STATUS_TBU BIT(2)
|
||||
#define DMA_CHAN_STATUS_TPS BIT(1)
|
||||
#define DMA_CHAN_STATUS_TI BIT(0)
|
||||
|
||||
/* Interrupt enable bits per channel */
|
||||
#define DMA_CHAN_INTR_ENA_NIE BIT(15)
|
||||
#define DMA_CHAN_INTR_ENA_AIE BIT(14)
|
||||
#define DMA_CHAN_INTR_ENA_CDE BIT(13)
|
||||
#define DMA_CHAN_INTR_ENA_FBE BIT(12)
|
||||
#define DMA_CHAN_INTR_ENA_ERE BIT(11)
|
||||
#define DMA_CHAN_INTR_ENA_ETE BIT(10)
|
||||
#define DMA_CHAN_INTR_ENA_RWE BIT(9)
|
||||
#define DMA_CHAN_INTR_ENA_RSE BIT(8)
|
||||
#define DMA_CHAN_INTR_ENA_RBUE BIT(7)
|
||||
#define DMA_CHAN_INTR_ENA_RIE BIT(6)
|
||||
#define DMA_CHAN_INTR_ENA_TBUE BIT(2)
|
||||
#define DMA_CHAN_INTR_ENA_TSE BIT(1)
|
||||
#define DMA_CHAN_INTR_ENA_TIE BIT(0)
|
||||
|
||||
#define DMA_CHAN_INTR_NORMAL (DMA_CHAN_INTR_ENA_NIE | \
|
||||
DMA_CHAN_INTR_ENA_RIE | \
|
||||
DMA_CHAN_INTR_ENA_TIE )
|
||||
|
||||
#define DMA_CHAN_INTR_ABNORMAL (DMA_CHAN_INTR_ENA_AIE | \
|
||||
DMA_CHAN_INTR_ENA_FBE)
|
||||
/* DMA default interrupt mask for 4.00 */
|
||||
#define DMA_CHAN_INTR_DEFAULT_MASK (DMA_CHAN_INTR_NORMAL | \
|
||||
DMA_CHAN_INTR_ABNORMAL)
|
||||
|
||||
#define PHY_CLAUSE_22 0xFF
|
||||
|
||||
static inline void udelay(uint32_t usecs)
|
||||
{
|
||||
volatile uint64_t count = usecs * 300;
|
||||
|
||||
while (count > 0)
|
||||
count--;
|
||||
}
|
||||
|
||||
/*
|
||||
mode transmit store and forward enable or not
|
||||
qmode transmit queue enable or not
|
||||
fifo transmit queue size
|
||||
*/
|
||||
#if defined(DEBUG_ENABLE)
|
||||
void dwmac_dump_mac(uint32_t addr);
|
||||
void dwmac_dump_mtl(uint32_t regbase, uint32_t queue);
|
||||
#endif
|
||||
void dwmac_prog_mtl_rx_algorithms(uint32_t regbase, uint32_t rx_alg);
|
||||
void dwmac_prog_mtl_tx_algorithms(uint32_t regbase, uint32_t tx_alg);
|
||||
void dwmac_map_mtl_dma(uint32_t addr, uint32_t queue, uint32_t channel);
|
||||
int32_t dwmac_set_filter(uint32_t regbase, uint32_t mode,
|
||||
const uint8_t *mac_addr);
|
||||
void dwmac_flow_ctrl(uint32_t regbase, uint32_t duplex, uint32_t fc,
|
||||
uint32_t pause_time, uint32_t tx_cnt);
|
||||
void dwmac_core_init(uint32_t regbase, uint32_t mtu, uint32_t speed,
|
||||
uint8_t *macaddr);
|
||||
void dwmac_clr_umac_addr(uint32_t regbase, uint32_t Reg_n);
|
||||
void dwmac_set_umac_addr(uint32_t regbase, const uint8_t *addr,
|
||||
uint32_t reg_n);
|
||||
void dwmac_get_umac_addr(uint32_t regbase, uint8_t *addr, uint32_t reg_n);
|
||||
void dwmac_rx_queue_enable(uint32_t addr, uint8_t mode, uint32_t queue);
|
||||
int dwmac_irq_mtl_status(uint32_t regbase, uint32_t channel);
|
||||
int32_t dwmac_dma_reset(uint32_t regbase);
|
||||
bool dwmac_access_test(uint32_t regbase);
|
||||
void dwmac_enable_dma_irq(uint32_t regbase, uint32_t channel, bool rx,
|
||||
bool tx);
|
||||
void dwmac_disable_dma_irq(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_dump_dma_regs(uint32_t regbase, int channel);
|
||||
void dwmac_dma_start_tx(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_dma_stop_tx(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_dma_start_rx(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_dma_stop_rx(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_dma_rx_chan_op_mode(uint32_t regbase, uint32_t channel, int mode,
|
||||
int fifosz, uint8_t qmode);
|
||||
/*
|
||||
mode transmit store and forward enable or not
|
||||
qmode transmit queue enable or not
|
||||
fifo transmit queue size
|
||||
*/
|
||||
void dwmac_dma_tx_chan_op_mode(uint32_t regbase, uint32_t channel, int mode,
|
||||
int fifosz, uint8_t qmode);
|
||||
|
||||
void dwmac_set_rx_ring_len(uint32_t regbase, uint32_t len, uint32_t channel);
|
||||
void dwmac_set_tx_ring_len(uint32_t regbase, uint32_t len, uint32_t channel);
|
||||
void dwmac_set_rx_list_ptr(uint32_t regbase, uint32_t list_ptr,
|
||||
uint32_t channel);
|
||||
void dwmac_set_tx_list_ptr(uint32_t regbase, uint32_t list_ptr,
|
||||
uint32_t channel);
|
||||
void dwmac_set_rx_tail_ptr(uint32_t regbase, uint32_t tail_ptr,
|
||||
uint32_t channel);
|
||||
void dwmac_set_tx_tail_ptr(uint32_t regbase, uint32_t tail_ptr,
|
||||
uint32_t channel);
|
||||
void dwmac_dma_init_rx_chan(uint32_t regbase, uint32_t base_ptr,
|
||||
uint32_t rbsz, uint32_t channel);
|
||||
void dwmac_dma_init_tx_chan(uint32_t regbase, uint32_t base_ptr,
|
||||
uint32_t channel);
|
||||
void dwmac_dma_bus_init(uint32_t regbase, uint32_t flags);
|
||||
uint32_t dwmac_dma_rx_state_get(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_dma_init_channel(uint32_t regbase, uint32_t flags, \
|
||||
uint32_t channel, uint32_t skip);
|
||||
|
||||
void dwmac_set_bfsize(uint32_t regbase, int bfsize, uint32_t channel);
|
||||
int32_t mac_mdio_write(uint32_t regbase, uint8_t phyaddr, uint8_t device,
|
||||
uint16_t phyreg, uint16_t phydata);
|
||||
int32_t mac_mdio_read(uint32_t regbase, uint8_t phyaddr, uint8_t device,
|
||||
uint16_t phyreg);
|
||||
void dwmac_rx_trigger(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_mac_rx_queue_mcbc_routing(uint32_t regbase, uint8_t channel);
|
||||
uint8_t *dwmac_get_default_mac_addr(void);
|
||||
void dwmac_enable_dma_rx_int(uint32_t regbase, uint32_t channel, bool enable);
|
||||
void dwmac_enable_dma_tx_int(uint32_t regbase, uint32_t channel, bool enable);
|
||||
uint32_t dwmac_get_dma_int_status(uint32_t regbase);
|
||||
uint32_t dwmac_get_mac_int_status(uint32_t regbase);
|
||||
uint32_t dwmac_get_mac_phyif_control_status(uint32_t regbase);
|
||||
uint32_t dwmac_get_mac_an_status(uint32_t regbase);
|
||||
uint32_t dwmac_get_mac_pmt_control_status(uint32_t regbase);
|
||||
uint32_t dwmac_get_mac_lpi_control_status(uint32_t regbase);
|
||||
uint32_t dwmac_get_mtl_int_status(uint32_t regbase);
|
||||
uint32_t dwmac_get_mtl_q_int_status(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_clr_mtl_q_int_status(uint32_t regbase, uint32_t channel, uint32_t val);
|
||||
uint32_t dwmac_get_dma_chn_status(uint32_t regbase, uint32_t channel);
|
||||
void dwmac_clear_dma_chn_int_status(uint32_t regbase, uint32_t channel);
|
||||
#endif
|
||||
Reference in New Issue
Block a user