mirror of
https://github.com/cesanta/mongoose.git
synced 2024-11-23 18:49:01 +08:00
TMS570 support
This commit is contained in:
parent
244536ea72
commit
cbbcec0895
237
mongoose.c
237
mongoose.c
@ -18507,6 +18507,243 @@ struct mg_tcpip_driver mg_tcpip_driver_tm4c = {mg_tcpip_driver_tm4c_init,
|
||||
mg_tcpip_driver_tm4c_up};
|
||||
#endif
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/drivers/tms570.c"
|
||||
#endif
|
||||
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TMS570) && MG_ENABLE_DRIVER_TMS570
|
||||
struct tms570_emac_ctrl {
|
||||
volatile uint32_t REVID, SOFTRESET, RESERVED1[1], INTCONTROL, C0RXTHRESHEN,
|
||||
C0RXEN, C0TXEN, C0MISCEN, RESERVED2[8],
|
||||
C0RXTHRESHSTAT, C0RXSTAT, C0TXSTAT, C0MISCSTAT,
|
||||
RESERVED3[8],
|
||||
C0RXIMAX, C0TXIMAX;
|
||||
};
|
||||
struct tms570_emac {
|
||||
volatile uint32_t TXREVID, TXCONTROL, TXTEARDOWN, RESERVED1[1], RXREVID,
|
||||
RXCONTROL, RXTEARDOWN, RESERVED2[25], TXINTSTATRAW,TXINTSTATMASKED,
|
||||
TXINTMASKSET, TXINTMASKCLEAR, MACINVECTOR, MACEOIVECTOR, RESERVED8[2], RXINTSTATRAW,
|
||||
RXINTSTATMASKED, RXINTMASKSET, RXINTMASKCLEAR, MACINTSTATRAW, MACINTSTATMASKED,
|
||||
MACINTMASKSET, MACINTMASKCLEAR, RESERVED3[16], RXMBPENABLE, RXUNICASTSET,
|
||||
RXUNICASTCLEAR, RXMAXLEN, RXBUFFEROFFSET, RXFILTERLOWTHRESH, RESERVED9[2], RXFLOWTHRESH[8],
|
||||
RXFREEBUFFER[8], MACCONTROL, MACSTATUS, EMCONTROL, FIFOCONTROL, MACCONFIG,
|
||||
SOFTRESET, RESERVED4[22], MACSRCADDRLO, MACSRCADDRHI, MACHASH1, MACHASH2,
|
||||
BOFFTEST, TPACETEST, RXPAUSE, TXPAUSE, RESERVED5[4], RXGOODFRAMES, RXBCASTFRAMES,
|
||||
RXMCASTFRAMES, RXPAUSEFRAMES, RXCRCERRORS, RXALIGNCODEERRORS, RXOVERSIZED,
|
||||
RXJABBER, RXUNDERSIZED, RXFRAGMENTS, RXFILTERED, RXQOSFILTERED, RXOCTETS,
|
||||
TXGOODFRAMES, TXBCASTFRAMES, TXMCASTFRAMES, TXPAUSEFRAMES, TXDEFERRED,
|
||||
TXCOLLISION, TXSINGLECOLL, TXMULTICOLL, TXEXCESSIVECOLL, TXLATECOLL,
|
||||
TXUNDERRUN, TXCARRIERSENSE, TXOCTETS, FRAME64, FRAME65T127, FRAME128T255,
|
||||
FRAME256T511, FRAME512T1023, FRAME1024TUP, NETOCTETS, RXSOFOVERRUNS,
|
||||
RXMOFOVERRUNS, RXDMAOVERRUNS, RESERVED6[156], MACADDRLO, MACADDRHI,
|
||||
MACINDEX, RESERVED7[61], TXHDP[8], RXHDP[8], TXCP[8], RXCP[8];
|
||||
};
|
||||
struct tms570_mdio {
|
||||
volatile uint32_t REVID, CONTROL, ALIVE, LINK, LINKINTRAW, LINKINTMASKED,
|
||||
RESERVED1[2], USERINTRAW, USERINTMASKED, USERINTMASKSET, USERINTMASKCLEAR,
|
||||
RESERVED2[20], USERACCESS0, USERPHYSEL0, USERACCESS1, USERPHYSEL1;
|
||||
};
|
||||
#define SWAP32(x) ( (((x) & 0x000000FF) << 24) | \
|
||||
(((x) & 0x0000FF00) << 8) | \
|
||||
(((x) & 0x00FF0000) >> 8) | \
|
||||
(((x) & 0xFF000000) >> 24) )
|
||||
#undef EMAC
|
||||
#undef EMAC_CTRL
|
||||
#undef MDIO
|
||||
#define EMAC ((struct tms570_emac *) (uintptr_t) 0xFCF78000)
|
||||
#define EMAC_CTRL ((struct tms570_emac_ctrl *) (uintptr_t) 0xFCF78800)
|
||||
#define MDIO ((struct tms570_mdio *) (uintptr_t) 0xFCF78900)
|
||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 4 // Descriptor size (words)
|
||||
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]
|
||||
__attribute__((section(".ETH_CPPI"), aligned(4))); // TX descriptors
|
||||
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]
|
||||
__attribute__((section(".ETH_CPPI"), aligned(4))); // RX descriptors
|
||||
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]
|
||||
__attribute__((aligned(4))); // RX ethernet buffers
|
||||
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]
|
||||
__attribute__((aligned(4))); // TX ethernet buffers
|
||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||
static uint16_t emac_read_phy(uint8_t addr, uint8_t reg) {
|
||||
while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
|
||||
MDIO->USERACCESS0 = MG_BIT(31) | ((reg & 0x1f) << 21) |
|
||||
((addr & 0x1f) << 16);
|
||||
while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
|
||||
return MDIO->USERACCESS0 & 0xffff;
|
||||
}
|
||||
static void emac_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
||||
while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
|
||||
MDIO->USERACCESS0 = MG_BIT(31) | MG_BIT(30) | ((reg & 0x1f) << 21) |
|
||||
((addr & 0x1f) << 16) | (val & 0xffff);
|
||||
while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
|
||||
}
|
||||
static bool mg_tcpip_driver_tms570_init(struct mg_tcpip_if *ifp) {
|
||||
struct mg_tcpip_driver_tms570_data *d =
|
||||
(struct mg_tcpip_driver_tms570_data *) ifp->driver_data;
|
||||
s_ifp = ifp;
|
||||
EMAC_CTRL->SOFTRESET = MG_BIT(0); // Reset the EMAC Control Module
|
||||
while(EMAC_CTRL->SOFTRESET & MG_BIT(0)) (void) 0; // wait
|
||||
EMAC->SOFTRESET = MG_BIT(0); // Reset the EMAC Module
|
||||
while(EMAC->SOFTRESET & MG_BIT(0)) (void) 0;
|
||||
EMAC->MACCONTROL = 0;
|
||||
EMAC->RXCONTROL = 0;
|
||||
EMAC->TXCONTROL = 0;
|
||||
// Initialize all the header descriptor pointer registers
|
||||
uint32_t i;
|
||||
for(i = 0; i < ETH_DESC_CNT; i++) {
|
||||
EMAC->RXHDP[i] = 0;
|
||||
EMAC->TXHDP[i] = 0;
|
||||
EMAC->RXCP[i] = 0;
|
||||
EMAC->TXCP[i] = 0;
|
||||
///EMAC->RXFREEBUFFER[i] = 0xff;
|
||||
}
|
||||
// Clear the interrupt enable for all the channels
|
||||
EMAC->TXINTMASKCLEAR = 0xff;
|
||||
EMAC->RXINTMASKCLEAR = 0xff;
|
||||
EMAC->MACHASH1 = 0;
|
||||
EMAC->MACHASH2 = 0;
|
||||
EMAC->RXBUFFEROFFSET = 0;
|
||||
EMAC->RXUNICASTCLEAR = 0xff;
|
||||
EMAC->RXUNICASTSET = 0;
|
||||
EMAC->RXMBPENABLE = 0;
|
||||
// init MDIO
|
||||
// MDIO_CLK frequency = VCLK3/(CLKDIV + 1). (MDIO must be between 1.0 - 2.5Mhz)
|
||||
uint32_t clkdiv = 75; // VCLK is configured to 75Mhz
|
||||
// CLKDIV, ENABLE, PREAMBLE, FAULTENB
|
||||
MDIO->CONTROL = (clkdiv - 1) | MG_BIT(30) | MG_BIT(20) | MG_BIT(18);
|
||||
volatile int delay = 0xfff;
|
||||
while (delay-- != 0) (void) 0;
|
||||
struct mg_phy phy = {emac_read_phy, emac_write_phy};
|
||||
mg_phy_init(&phy, d->phy_addr, MG_PHY_CLOCKS_MAC);
|
||||
// set the mac address
|
||||
EMAC->MACSRCADDRHI = ifp->mac[0] | (ifp->mac[1] << 8) | (ifp->mac[2] << 16) |
|
||||
(ifp->mac[3] << 24);
|
||||
EMAC->MACSRCADDRLO = ifp->mac[4] | (ifp->mac[5] << 8);
|
||||
uint32_t channel;
|
||||
for (channel = 0; channel < 8; channel++) {
|
||||
EMAC->MACINDEX = channel;
|
||||
EMAC->MACADDRHI = ifp->mac[0] | (ifp->mac[1] << 8) | (ifp->mac[2] << 16) |
|
||||
(ifp->mac[3] << 24);
|
||||
EMAC->MACADDRLO = ifp->mac[4] | (ifp->mac[5] << 8) | MG_BIT(20) |
|
||||
MG_BIT(19) | (channel << 16);
|
||||
}
|
||||
EMAC->RXUNICASTSET = 1; // accept unicast frames;
|
||||
EMAC->RXMBPENABLE = MG_BIT(30) | MG_BIT(13); // CRC, broadcast;
|
||||
|
||||
// Initialize the descriptors
|
||||
for (i = 0; i < ETH_DESC_CNT; i++) {
|
||||
if (i < ETH_DESC_CNT - 1) {
|
||||
s_txdesc[i][0] = 0;
|
||||
s_rxdesc[i][0] = SWAP32(((uint32_t) &s_rxdesc[i + 1][0]));
|
||||
}
|
||||
s_txdesc[i][1] = SWAP32(((uint32_t) s_txbuf[i]));
|
||||
s_rxdesc[i][1] = SWAP32(((uint32_t) s_rxbuf[i]));
|
||||
s_txdesc[i][2] = 0;
|
||||
s_rxdesc[i][2] = SWAP32(ETH_PKT_SIZE);
|
||||
s_txdesc[i][3] = 0;
|
||||
s_rxdesc[i][3] = SWAP32(MG_BIT(29)); // OWN
|
||||
}
|
||||
s_txdesc[ETH_DESC_CNT - 1][0] = 0;
|
||||
s_rxdesc[ETH_DESC_CNT - 1][0] = 0;
|
||||
|
||||
EMAC->MACCONTROL = MG_BIT(5) | MG_BIT(0); // Enable MII, Full-duplex
|
||||
//EMAC->TXINTMASKSET = 1; // Enable TX interrupt
|
||||
EMAC->RXINTMASKSET = 1; // Enable RX interrupt
|
||||
//EMAC_CTRL->C0TXEN = 1; // TX completion interrupt
|
||||
EMAC_CTRL->C0RXEN = 1; // RX completion interrupt
|
||||
EMAC->TXCONTROL = 1; // TXEN
|
||||
EMAC->RXCONTROL = 1; // RXEN
|
||||
EMAC->RXHDP[0] = (uint32_t) &s_rxdesc[0][0];
|
||||
return true;
|
||||
}
|
||||
static uint32_t s_txno;
|
||||
static size_t mg_tcpip_driver_tms570_tx(const void *buf, size_t len,
|
||||
struct mg_tcpip_if *ifp) {
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // fail
|
||||
} else if ((s_txdesc[s_txno][3] & SWAP32(MG_BIT(29)))) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No descriptors available"));
|
||||
len = 0; // fail
|
||||
} else {
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
if (len < 128) len = 128;
|
||||
s_txdesc[s_txno][2] = SWAP32((uint32_t) len); // Set data len
|
||||
s_txdesc[s_txno][3] =
|
||||
SWAP32(MG_BIT(31) | MG_BIT(30) | MG_BIT(29) | len); // SOP, EOP, OWN, length
|
||||
|
||||
while(EMAC->TXHDP[0] != 0) (void) 0;
|
||||
EMAC->TXHDP[0] = (uint32_t) &s_txdesc[s_txno][0];
|
||||
if(++s_txno == ETH_DESC_CNT) {
|
||||
s_txno = 0;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
(void) ifp;
|
||||
}
|
||||
static bool mg_tcpip_driver_tms570_up(struct mg_tcpip_if *ifp) {
|
||||
struct mg_tcpip_driver_tms570_data *d =
|
||||
(struct mg_tcpip_driver_tms570_data *) ifp->driver_data;
|
||||
uint8_t speed = MG_PHY_SPEED_10M;
|
||||
bool up = false, full_duplex = false;
|
||||
struct mg_phy phy = {emac_read_phy, emac_write_phy};
|
||||
up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) {
|
||||
// link state just went up
|
||||
MG_DEBUG(("Link is %uM %s-duplex", speed == MG_PHY_SPEED_10M ? 10 : 100,
|
||||
full_duplex ? "full" : "half"));
|
||||
}
|
||||
return up;
|
||||
}
|
||||
#pragma CODE_STATE(EMAC_TX_IRQHandler, 32)
|
||||
#pragma INTERRUPT(EMAC_TX_IRQHandler, IRQ)
|
||||
void EMAC_TX_IRQHandler(void) {
|
||||
uint32_t status = EMAC_CTRL->C0TXSTAT;
|
||||
if (status & 1) { // interrupt caused on channel 0
|
||||
while(s_txdesc[s_txno][3] & SWAP32(MG_BIT(29))) (void) 0;
|
||||
EMAC->TXCP[0] = (uint32_t) &s_txdesc[s_txno][0];
|
||||
}
|
||||
//Write the DMA end of interrupt vector
|
||||
EMAC->MACEOIVECTOR = 2;
|
||||
}
|
||||
static uint32_t s_rxno;
|
||||
#pragma CODE_STATE(EMAC_RX_IRQHandler, 32)
|
||||
#pragma INTERRUPT(EMAC_RX_IRQHandler, IRQ)
|
||||
void EMAC_RX_IRQHandler(void) {
|
||||
uint32_t status = EMAC_CTRL->C0RXSTAT;
|
||||
if (status & 1) { // Frame received, loop
|
||||
uint32_t i;
|
||||
//MG_INFO(("RX interrupt"));
|
||||
for (i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||
if ((s_rxdesc[s_rxno][3] & SWAP32(MG_BIT(29))) == 0) {
|
||||
uint32_t len = SWAP32(s_rxdesc[s_rxno][3]) & 0xffff;
|
||||
//MG_INFO(("recv len: %d", len));
|
||||
//mg_hexdump(s_rxbuf[s_rxno], len);
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
|
||||
uint32_t flags = s_rxdesc[s_rxno][3];
|
||||
s_rxdesc[s_rxno][3] = SWAP32(MG_BIT(29));
|
||||
s_rxdesc[s_rxno][2] = SWAP32(ETH_PKT_SIZE);
|
||||
EMAC->RXCP[0] = (uint32_t) &s_rxdesc[s_rxno][0];
|
||||
if (flags & SWAP32(MG_BIT(28))) {
|
||||
//MG_INFO(("EOQ detected"));
|
||||
EMAC->RXHDP[0] = (uint32_t) &s_rxdesc[0][0];
|
||||
}
|
||||
}
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
//Write the DMA end of interrupt vector
|
||||
EMAC->MACEOIVECTOR = 1;
|
||||
}
|
||||
struct mg_tcpip_driver mg_tcpip_driver_tms570 = {mg_tcpip_driver_tms570_init,
|
||||
mg_tcpip_driver_tms570_tx, NULL,
|
||||
mg_tcpip_driver_tms570_up};
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef MG_ENABLE_LINES
|
||||
#line 1 "src/drivers/w5500.c"
|
||||
#endif
|
||||
|
34
mongoose.h
34
mongoose.h
@ -2786,6 +2786,7 @@ void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_stm32f;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_tm4c;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_tms570;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_stm32h;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_imxrt;
|
||||
extern struct mg_tcpip_driver mg_tcpip_driver_same54;
|
||||
@ -3124,6 +3125,39 @@ struct mg_tcpip_driver_tm4c_data {
|
||||
#endif
|
||||
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TMS570) && MG_ENABLE_DRIVER_TMS570
|
||||
struct mg_tcpip_driver_tms570_data {
|
||||
int mdc_cr;
|
||||
int phy_addr;
|
||||
};
|
||||
|
||||
#ifndef MG_TCPIP_PHY_ADDR
|
||||
#define MG_TCPIP_PHY_ADDR 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_DRIVER_MDC_CR
|
||||
#define MG_DRIVER_MDC_CR 1
|
||||
#endif
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_tcpip_driver_tms570_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
|
||||
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
|
||||
mif_.ip = MG_TCPIP_IP; \
|
||||
mif_.mask = MG_TCPIP_MASK; \
|
||||
mif_.gw = MG_TCPIP_GW; \
|
||||
mif_.driver = &mg_tcpip_driver_tms570; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: tms570, MAC: %M", mg_print_mac, mif_.mac));\
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_XMC) && MG_ENABLE_DRIVER_XMC
|
||||
|
||||
struct mg_tcpip_driver_xmc_data {
|
||||
|
233
src/drivers/tms570.c
Normal file
233
src/drivers/tms570.c
Normal file
@ -0,0 +1,233 @@
|
||||
#include "net_builtin.h"
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TMS570) && MG_ENABLE_DRIVER_TMS570
|
||||
struct tms570_emac_ctrl {
|
||||
volatile uint32_t REVID, SOFTRESET, RESERVED1[1], INTCONTROL, C0RXTHRESHEN,
|
||||
C0RXEN, C0TXEN, C0MISCEN, RESERVED2[8],
|
||||
C0RXTHRESHSTAT, C0RXSTAT, C0TXSTAT, C0MISCSTAT,
|
||||
RESERVED3[8],
|
||||
C0RXIMAX, C0TXIMAX;
|
||||
};
|
||||
struct tms570_emac {
|
||||
volatile uint32_t TXREVID, TXCONTROL, TXTEARDOWN, RESERVED1[1], RXREVID,
|
||||
RXCONTROL, RXTEARDOWN, RESERVED2[25], TXINTSTATRAW,TXINTSTATMASKED,
|
||||
TXINTMASKSET, TXINTMASKCLEAR, MACINVECTOR, MACEOIVECTOR, RESERVED8[2], RXINTSTATRAW,
|
||||
RXINTSTATMASKED, RXINTMASKSET, RXINTMASKCLEAR, MACINTSTATRAW, MACINTSTATMASKED,
|
||||
MACINTMASKSET, MACINTMASKCLEAR, RESERVED3[16], RXMBPENABLE, RXUNICASTSET,
|
||||
RXUNICASTCLEAR, RXMAXLEN, RXBUFFEROFFSET, RXFILTERLOWTHRESH, RESERVED9[2], RXFLOWTHRESH[8],
|
||||
RXFREEBUFFER[8], MACCONTROL, MACSTATUS, EMCONTROL, FIFOCONTROL, MACCONFIG,
|
||||
SOFTRESET, RESERVED4[22], MACSRCADDRLO, MACSRCADDRHI, MACHASH1, MACHASH2,
|
||||
BOFFTEST, TPACETEST, RXPAUSE, TXPAUSE, RESERVED5[4], RXGOODFRAMES, RXBCASTFRAMES,
|
||||
RXMCASTFRAMES, RXPAUSEFRAMES, RXCRCERRORS, RXALIGNCODEERRORS, RXOVERSIZED,
|
||||
RXJABBER, RXUNDERSIZED, RXFRAGMENTS, RXFILTERED, RXQOSFILTERED, RXOCTETS,
|
||||
TXGOODFRAMES, TXBCASTFRAMES, TXMCASTFRAMES, TXPAUSEFRAMES, TXDEFERRED,
|
||||
TXCOLLISION, TXSINGLECOLL, TXMULTICOLL, TXEXCESSIVECOLL, TXLATECOLL,
|
||||
TXUNDERRUN, TXCARRIERSENSE, TXOCTETS, FRAME64, FRAME65T127, FRAME128T255,
|
||||
FRAME256T511, FRAME512T1023, FRAME1024TUP, NETOCTETS, RXSOFOVERRUNS,
|
||||
RXMOFOVERRUNS, RXDMAOVERRUNS, RESERVED6[156], MACADDRLO, MACADDRHI,
|
||||
MACINDEX, RESERVED7[61], TXHDP[8], RXHDP[8], TXCP[8], RXCP[8];
|
||||
};
|
||||
struct tms570_mdio {
|
||||
volatile uint32_t REVID, CONTROL, ALIVE, LINK, LINKINTRAW, LINKINTMASKED,
|
||||
RESERVED1[2], USERINTRAW, USERINTMASKED, USERINTMASKSET, USERINTMASKCLEAR,
|
||||
RESERVED2[20], USERACCESS0, USERPHYSEL0, USERACCESS1, USERPHYSEL1;
|
||||
};
|
||||
#define SWAP32(x) ( (((x) & 0x000000FF) << 24) | \
|
||||
(((x) & 0x0000FF00) << 8) | \
|
||||
(((x) & 0x00FF0000) >> 8) | \
|
||||
(((x) & 0xFF000000) >> 24) )
|
||||
#undef EMAC
|
||||
#undef EMAC_CTRL
|
||||
#undef MDIO
|
||||
#define EMAC ((struct tms570_emac *) (uintptr_t) 0xFCF78000)
|
||||
#define EMAC_CTRL ((struct tms570_emac_ctrl *) (uintptr_t) 0xFCF78800)
|
||||
#define MDIO ((struct tms570_mdio *) (uintptr_t) 0xFCF78900)
|
||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
#define ETH_DS 4 // Descriptor size (words)
|
||||
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]
|
||||
__attribute__((section(".ETH_CPPI"), aligned(4))); // TX descriptors
|
||||
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]
|
||||
__attribute__((section(".ETH_CPPI"), aligned(4))); // RX descriptors
|
||||
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]
|
||||
__attribute__((aligned(4))); // RX ethernet buffers
|
||||
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]
|
||||
__attribute__((aligned(4))); // TX ethernet buffers
|
||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||
static uint16_t emac_read_phy(uint8_t addr, uint8_t reg) {
|
||||
while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
|
||||
MDIO->USERACCESS0 = MG_BIT(31) | ((reg & 0x1f) << 21) |
|
||||
((addr & 0x1f) << 16);
|
||||
while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
|
||||
return MDIO->USERACCESS0 & 0xffff;
|
||||
}
|
||||
static void emac_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
||||
while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
|
||||
MDIO->USERACCESS0 = MG_BIT(31) | MG_BIT(30) | ((reg & 0x1f) << 21) |
|
||||
((addr & 0x1f) << 16) | (val & 0xffff);
|
||||
while(MDIO->USERACCESS0 & MG_BIT(31)) (void) 0;
|
||||
}
|
||||
static bool mg_tcpip_driver_tms570_init(struct mg_tcpip_if *ifp) {
|
||||
struct mg_tcpip_driver_tms570_data *d =
|
||||
(struct mg_tcpip_driver_tms570_data *) ifp->driver_data;
|
||||
s_ifp = ifp;
|
||||
EMAC_CTRL->SOFTRESET = MG_BIT(0); // Reset the EMAC Control Module
|
||||
while(EMAC_CTRL->SOFTRESET & MG_BIT(0)) (void) 0; // wait
|
||||
EMAC->SOFTRESET = MG_BIT(0); // Reset the EMAC Module
|
||||
while(EMAC->SOFTRESET & MG_BIT(0)) (void) 0;
|
||||
EMAC->MACCONTROL = 0;
|
||||
EMAC->RXCONTROL = 0;
|
||||
EMAC->TXCONTROL = 0;
|
||||
// Initialize all the header descriptor pointer registers
|
||||
uint32_t i;
|
||||
for(i = 0; i < ETH_DESC_CNT; i++) {
|
||||
EMAC->RXHDP[i] = 0;
|
||||
EMAC->TXHDP[i] = 0;
|
||||
EMAC->RXCP[i] = 0;
|
||||
EMAC->TXCP[i] = 0;
|
||||
///EMAC->RXFREEBUFFER[i] = 0xff;
|
||||
}
|
||||
// Clear the interrupt enable for all the channels
|
||||
EMAC->TXINTMASKCLEAR = 0xff;
|
||||
EMAC->RXINTMASKCLEAR = 0xff;
|
||||
EMAC->MACHASH1 = 0;
|
||||
EMAC->MACHASH2 = 0;
|
||||
EMAC->RXBUFFEROFFSET = 0;
|
||||
EMAC->RXUNICASTCLEAR = 0xff;
|
||||
EMAC->RXUNICASTSET = 0;
|
||||
EMAC->RXMBPENABLE = 0;
|
||||
// init MDIO
|
||||
// MDIO_CLK frequency = VCLK3/(CLKDIV + 1). (MDIO must be between 1.0 - 2.5Mhz)
|
||||
uint32_t clkdiv = 75; // VCLK is configured to 75Mhz
|
||||
// CLKDIV, ENABLE, PREAMBLE, FAULTENB
|
||||
MDIO->CONTROL = (clkdiv - 1) | MG_BIT(30) | MG_BIT(20) | MG_BIT(18);
|
||||
volatile int delay = 0xfff;
|
||||
while (delay-- != 0) (void) 0;
|
||||
struct mg_phy phy = {emac_read_phy, emac_write_phy};
|
||||
mg_phy_init(&phy, d->phy_addr, MG_PHY_CLOCKS_MAC);
|
||||
// set the mac address
|
||||
EMAC->MACSRCADDRHI = ifp->mac[0] | (ifp->mac[1] << 8) | (ifp->mac[2] << 16) |
|
||||
(ifp->mac[3] << 24);
|
||||
EMAC->MACSRCADDRLO = ifp->mac[4] | (ifp->mac[5] << 8);
|
||||
uint32_t channel;
|
||||
for (channel = 0; channel < 8; channel++) {
|
||||
EMAC->MACINDEX = channel;
|
||||
EMAC->MACADDRHI = ifp->mac[0] | (ifp->mac[1] << 8) | (ifp->mac[2] << 16) |
|
||||
(ifp->mac[3] << 24);
|
||||
EMAC->MACADDRLO = ifp->mac[4] | (ifp->mac[5] << 8) | MG_BIT(20) |
|
||||
MG_BIT(19) | (channel << 16);
|
||||
}
|
||||
EMAC->RXUNICASTSET = 1; // accept unicast frames;
|
||||
EMAC->RXMBPENABLE = MG_BIT(30) | MG_BIT(13); // CRC, broadcast;
|
||||
|
||||
// Initialize the descriptors
|
||||
for (i = 0; i < ETH_DESC_CNT; i++) {
|
||||
if (i < ETH_DESC_CNT - 1) {
|
||||
s_txdesc[i][0] = 0;
|
||||
s_rxdesc[i][0] = SWAP32(((uint32_t) &s_rxdesc[i + 1][0]));
|
||||
}
|
||||
s_txdesc[i][1] = SWAP32(((uint32_t) s_txbuf[i]));
|
||||
s_rxdesc[i][1] = SWAP32(((uint32_t) s_rxbuf[i]));
|
||||
s_txdesc[i][2] = 0;
|
||||
s_rxdesc[i][2] = SWAP32(ETH_PKT_SIZE);
|
||||
s_txdesc[i][3] = 0;
|
||||
s_rxdesc[i][3] = SWAP32(MG_BIT(29)); // OWN
|
||||
}
|
||||
s_txdesc[ETH_DESC_CNT - 1][0] = 0;
|
||||
s_rxdesc[ETH_DESC_CNT - 1][0] = 0;
|
||||
|
||||
EMAC->MACCONTROL = MG_BIT(5) | MG_BIT(0); // Enable MII, Full-duplex
|
||||
//EMAC->TXINTMASKSET = 1; // Enable TX interrupt
|
||||
EMAC->RXINTMASKSET = 1; // Enable RX interrupt
|
||||
//EMAC_CTRL->C0TXEN = 1; // TX completion interrupt
|
||||
EMAC_CTRL->C0RXEN = 1; // RX completion interrupt
|
||||
EMAC->TXCONTROL = 1; // TXEN
|
||||
EMAC->RXCONTROL = 1; // RXEN
|
||||
EMAC->RXHDP[0] = (uint32_t) &s_rxdesc[0][0];
|
||||
return true;
|
||||
}
|
||||
static uint32_t s_txno;
|
||||
static size_t mg_tcpip_driver_tms570_tx(const void *buf, size_t len,
|
||||
struct mg_tcpip_if *ifp) {
|
||||
if (len > sizeof(s_txbuf[s_txno])) {
|
||||
MG_ERROR(("Frame too big, %ld", (long) len));
|
||||
len = 0; // fail
|
||||
} else if ((s_txdesc[s_txno][3] & SWAP32(MG_BIT(29)))) {
|
||||
ifp->nerr++;
|
||||
MG_ERROR(("No descriptors available"));
|
||||
len = 0; // fail
|
||||
} else {
|
||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
||||
if (len < 128) len = 128;
|
||||
s_txdesc[s_txno][2] = SWAP32((uint32_t) len); // Set data len
|
||||
s_txdesc[s_txno][3] =
|
||||
SWAP32(MG_BIT(31) | MG_BIT(30) | MG_BIT(29) | len); // SOP, EOP, OWN, length
|
||||
|
||||
while(EMAC->TXHDP[0] != 0) (void) 0;
|
||||
EMAC->TXHDP[0] = (uint32_t) &s_txdesc[s_txno][0];
|
||||
if(++s_txno == ETH_DESC_CNT) {
|
||||
s_txno = 0;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
(void) ifp;
|
||||
}
|
||||
static bool mg_tcpip_driver_tms570_up(struct mg_tcpip_if *ifp) {
|
||||
struct mg_tcpip_driver_tms570_data *d =
|
||||
(struct mg_tcpip_driver_tms570_data *) ifp->driver_data;
|
||||
uint8_t speed = MG_PHY_SPEED_10M;
|
||||
bool up = false, full_duplex = false;
|
||||
struct mg_phy phy = {emac_read_phy, emac_write_phy};
|
||||
up = mg_phy_up(&phy, d->phy_addr, &full_duplex, &speed);
|
||||
if ((ifp->state == MG_TCPIP_STATE_DOWN) && up) {
|
||||
// link state just went up
|
||||
MG_DEBUG(("Link is %uM %s-duplex", speed == MG_PHY_SPEED_10M ? 10 : 100,
|
||||
full_duplex ? "full" : "half"));
|
||||
}
|
||||
return up;
|
||||
}
|
||||
#pragma CODE_STATE(EMAC_TX_IRQHandler, 32)
|
||||
#pragma INTERRUPT(EMAC_TX_IRQHandler, IRQ)
|
||||
void EMAC_TX_IRQHandler(void) {
|
||||
uint32_t status = EMAC_CTRL->C0TXSTAT;
|
||||
if (status & 1) { // interrupt caused on channel 0
|
||||
while(s_txdesc[s_txno][3] & SWAP32(MG_BIT(29))) (void) 0;
|
||||
EMAC->TXCP[0] = (uint32_t) &s_txdesc[s_txno][0];
|
||||
}
|
||||
//Write the DMA end of interrupt vector
|
||||
EMAC->MACEOIVECTOR = 2;
|
||||
}
|
||||
static uint32_t s_rxno;
|
||||
#pragma CODE_STATE(EMAC_RX_IRQHandler, 32)
|
||||
#pragma INTERRUPT(EMAC_RX_IRQHandler, IRQ)
|
||||
void EMAC_RX_IRQHandler(void) {
|
||||
uint32_t status = EMAC_CTRL->C0RXSTAT;
|
||||
if (status & 1) { // Frame received, loop
|
||||
uint32_t i;
|
||||
//MG_INFO(("RX interrupt"));
|
||||
for (i = 0; i < 10; i++) { // read as they arrive but not forever
|
||||
if ((s_rxdesc[s_rxno][3] & SWAP32(MG_BIT(29))) == 0) {
|
||||
uint32_t len = SWAP32(s_rxdesc[s_rxno][3]) & 0xffff;
|
||||
//MG_INFO(("recv len: %d", len));
|
||||
//mg_hexdump(s_rxbuf[s_rxno], len);
|
||||
mg_tcpip_qwrite(s_rxbuf[s_rxno], len > 4 ? len - 4 : len, s_ifp);
|
||||
uint32_t flags = s_rxdesc[s_rxno][3];
|
||||
s_rxdesc[s_rxno][3] = SWAP32(MG_BIT(29));
|
||||
s_rxdesc[s_rxno][2] = SWAP32(ETH_PKT_SIZE);
|
||||
EMAC->RXCP[0] = (uint32_t) &s_rxdesc[s_rxno][0];
|
||||
if (flags & SWAP32(MG_BIT(28))) {
|
||||
//MG_INFO(("EOQ detected"));
|
||||
EMAC->RXHDP[0] = (uint32_t) &s_rxdesc[0][0];
|
||||
}
|
||||
}
|
||||
if (++s_rxno >= ETH_DESC_CNT) s_rxno = 0;
|
||||
}
|
||||
}
|
||||
//Write the DMA end of interrupt vector
|
||||
EMAC->MACEOIVECTOR = 1;
|
||||
}
|
||||
struct mg_tcpip_driver mg_tcpip_driver_tms570 = {mg_tcpip_driver_tms570_init,
|
||||
mg_tcpip_driver_tms570_tx, NULL,
|
||||
mg_tcpip_driver_tms570_up};
|
||||
#endif
|
||||
|
33
src/drivers/tms570.h
Normal file
33
src/drivers/tms570.h
Normal file
@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_TMS570) && MG_ENABLE_DRIVER_TMS570
|
||||
struct mg_tcpip_driver_tms570_data {
|
||||
int mdc_cr;
|
||||
int phy_addr;
|
||||
};
|
||||
|
||||
#ifndef MG_TCPIP_PHY_ADDR
|
||||
#define MG_TCPIP_PHY_ADDR 0
|
||||
#endif
|
||||
|
||||
#ifndef MG_DRIVER_MDC_CR
|
||||
#define MG_DRIVER_MDC_CR 1
|
||||
#endif
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_tcpip_driver_tms570_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
|
||||
driver_data_.phy_addr = MG_TCPIP_PHY_ADDR; \
|
||||
mif_.ip = MG_TCPIP_IP; \
|
||||
mif_.mask = MG_TCPIP_MASK; \
|
||||
mif_.gw = MG_TCPIP_GW; \
|
||||
mif_.driver = &mg_tcpip_driver_tms570; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: tms570, MAC: %M", mg_print_mac, mif_.mac));\
|
||||
} while (0)
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user