mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-12 10:13:29 +00:00
Merge pull request #3218 from cesanta/same54-driver-update
Update same54 driver
This commit is contained in:
+103
-77
@@ -23192,7 +23192,45 @@ struct mg_tcpip_driver mg_tcpip_driver_rw612 = {mg_tcpip_driver_rw612_init,
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
|
||||
MG_ENABLE_DRIVER_SAME54
|
||||
|
||||
#include <sam.h>
|
||||
struct GMAC_REGS_ {
|
||||
uint32_t GMAC_NCR, GMAC_NCFGR, GMAC_NSR, GMAC_UR, GMAC_DCFGR, GMAC_TSR, GMAC_RBQB, GMAC_TBQB,
|
||||
GMAC_RSR, GMAC_ISR, GMAC_IER, GMAC_IDR, GMAC_IMR, GMAC_MAN, GMAC_RPQ, GMAC_TPQ,
|
||||
GMAC_TPSF, GMAC_RPSF, GMAC_RJFML,
|
||||
Reserved1[13],
|
||||
GMAC_HRB, GMAC_HRT,
|
||||
GMAC_SAB0, GMAC_SAT0, GMAC_SAB1, GMAC_SAT1, GMAC_SAB2, GMAC_SAT2, GMAC_SAB3, GMAC_SAT3,
|
||||
GMAC_TIDM[4],
|
||||
GMAC_WOL, GMAC_IPGS, GMAC_SVLAN, GMAC_TPFCP,
|
||||
GMAC_SAMB1, GMAC_SAMT1,
|
||||
Reserved2[3],
|
||||
GMAC_NSC, GMAC_SCL, GMAC_SCH,
|
||||
GMAC_EFTSH, GMAC_EFRSH, GMAC_PEFTSH, GMAC_PEFRSH,
|
||||
Reserved3[2],
|
||||
GMAC_OTLO, GMAC_OTHI, GMAC_FT, GMAC_BCFT, GMAC_MFT, GMAC_PFT, GMAC_BFT64, GMAC_TBFT127,
|
||||
GMAC_TBFT255, GMAC_TBFT511, GMAC_TBFT1023, GMAC_TBFT1518, GMAC_GTBFT1518,
|
||||
GMAC_TUR, GMAC_SCF, GMAC_MCF, GMAC_EC, GMAC_LC, GMAC_DTF, GMAC_CSE,
|
||||
GMAC_ORLO, GMAC_ORHI, GMAC_FR, GMAC_BCFR, GMAC_MFR, GMAC_PFR, GMAC_BFR64, GMAC_TBFR127,
|
||||
GMAC_TBFR255, GMAC_TBFR511, GMAC_TBFR1023, GMAC_TBFR1518, GMAC_TMXBFR,
|
||||
GMAC_UFR, GMAC_OFR, GMAC_JR, GMAC_FCSE, GMAC_LFFE, GMAC_RSE, GMAC_AE, GMAC_RRE,
|
||||
GMAC_ROE, GMAC_IHCE, GMAC_TCE, GMAC_UCE,
|
||||
Reserved4[2],
|
||||
GMAC_TISUBN, GMAC_TSH,
|
||||
Reserved5,
|
||||
GMAC_TSSSL, GMAC_TSSN, GMAC_TSL, GMAC_TN, GMAC_TA, GMAC_TI,
|
||||
GMAC_EFTSL, GMAC_EFTN, GMAC_EFRSL, GMAC_EFRN,
|
||||
GMAC_PEFTSL, GMAC_PEFTN, GMAC_PEFRSL, GMAC_PEFRN,
|
||||
Reserved6[28],
|
||||
GMAC_RLPITR, GMAC_RLPITI, GMAC_TLPITR, GMAC_TLPITI;
|
||||
};
|
||||
|
||||
struct GCLK_REGS_ {
|
||||
uint32_t GCLK_CTRLA_RESERVED, GCLK_SYNCBUSY, Reserved2[6],
|
||||
GCLK_GENCTRL[12], Reserved3[12], GCLK_PCHCTRL[48];
|
||||
};
|
||||
|
||||
|
||||
#define GMAC_REGS ((struct GMAC_REGS_ *) 0x42000800)
|
||||
#define GCLK_REGS ((struct GCLK_REGS_ *) 0x40001c00)
|
||||
|
||||
#define ETH_PKT_SIZE 1536 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
@@ -23206,72 +23244,65 @@ static uint8_t s_txno; // Current TX descriptor
|
||||
static uint8_t s_rxno; // Current RX descriptor
|
||||
|
||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
|
||||
|
||||
#define MG_PHYREGBIT_BCR_DUPLEX_MODE MG_BIT(8)
|
||||
#define MG_PHYREGBIT_BCR_SPEED MG_BIT(13)
|
||||
#define MG_PHYREGBIT_BSR_LINK_STATUS MG_BIT(2)
|
||||
|
||||
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk |
|
||||
GMAC_MAN_OP(2) | // Setting the read operation
|
||||
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
|
||||
GMAC_MAN_REGA(reg); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)) (void) 0;
|
||||
return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value
|
||||
GMAC_REGS->GMAC_MAN = MG_BIT(30) | // Clause 22
|
||||
MG_BIT(29) | // Setting the read operation
|
||||
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
|
||||
((reg & 0x1f) << 18); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2))) (void) 0;
|
||||
return GMAC_REGS->GMAC_MAN & 0xffff; // Getting the read value
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation
|
||||
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
|
||||
GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete
|
||||
GMAC_REGS->GMAC_MAN = MG_BIT(30) | MG_BIT(28) | // Setting the write operation
|
||||
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
|
||||
((reg & 0x1f) << 18) | val; // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2))); // Waiting until the write op is complete
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
|
||||
uint32_t get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
|
||||
if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) {
|
||||
return d->mdc_cr;
|
||||
} else {
|
||||
// get MCLK from GCLK_GENERATOR 0
|
||||
uint32_t div = 512;
|
||||
uint32_t mclk;
|
||||
if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) {
|
||||
if (!(GCLK_REGS->GCLK_GENCTRL[0] & MG_BIT(12))) {
|
||||
div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16);
|
||||
if (div == 0) div = 1;
|
||||
}
|
||||
switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) {
|
||||
case GCLK_GENCTRL_SRC_XOSC0_Val:
|
||||
mclk = 32000000UL; /* 32MHz */
|
||||
switch (GCLK_REGS->GCLK_GENCTRL[0] & 0xF) {
|
||||
case 0: // GCLK_GENCTRL_SRC_XOSC0_Val
|
||||
mclk = 32000000UL; // 32MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_XOSC1_Val:
|
||||
mclk = 32000000UL; /* 32MHz */
|
||||
case 1: // GCLK_GENCTRL_SRC_XOSC1_Val
|
||||
mclk = 32000000UL; // 32MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_OSCULP32K_Val:
|
||||
mclk = 32000UL;
|
||||
case 4: // GCLK_GENCTRL_SRC_OSCULP32K_Val
|
||||
mclk = 32000UL; // 32Khz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_XOSC32K_Val:
|
||||
mclk = 32000UL;
|
||||
case 5: // GCLK_GENCTRL_SRC_XOSC32K_Val
|
||||
mclk = 32000UL; // 32Khz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DFLL_Val:
|
||||
mclk = 48000000UL; /* 48MHz */
|
||||
case 6: // GCLK_GENCTRL_SRC_DFLL_Val
|
||||
mclk = 48000000UL; // 48MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DPLL0_Val:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
case 7: // GCLK_GENCTRL_SRC_DPLL0_Val:
|
||||
mclk = 200000000UL; // 200MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DPLL1_Val:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
case 8: // GCLK_GENCTRL_SRC_DPLL1_Val
|
||||
mclk = 200000000UL; // 200MHz
|
||||
break;
|
||||
default:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
mclk = 200000000UL; // 200MHz
|
||||
}
|
||||
|
||||
mclk /= div;
|
||||
uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values
|
||||
uint8_t dividers[] = {8, 16, 32, 48, 64, 96}; // Respective CLK dividers
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) {
|
||||
if (mclk / dividers[i] <= 2375000UL) { // 2.5MHz - 5%
|
||||
return crs[i];
|
||||
}
|
||||
}
|
||||
@@ -23285,11 +23316,12 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
(struct mg_tcpip_driver_same54_data *) ifp->driver_data;
|
||||
s_ifp = ifp;
|
||||
|
||||
MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk;
|
||||
MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk;
|
||||
GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider
|
||||
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO
|
||||
GMAC_REGS->GMAC_NCFGR = get_clock_rate(d) << 18; // Set MDC divider
|
||||
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(4); // Enable MDC & MDIO
|
||||
|
||||
struct mg_phy phy = {eth_read_phy, eth_write_phy};
|
||||
mg_phy_init(&phy, d->phy_addr, 0);
|
||||
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
|
||||
s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
|
||||
@@ -23297,9 +23329,9 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
}
|
||||
s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
|
||||
|
||||
GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18) // DMA recv buf 1536
|
||||
| GMAC_DCFGR_RXBMS(GMAC_DCFGR_RXBMS_FULL_Val) |
|
||||
GMAC_DCFGR_TXPBMS(1); // See #2487
|
||||
GMAC_REGS->GMAC_DCFGR = (0x18 << 16) | // DMA recv buf 1536
|
||||
(3 << 8) | // RXBMS
|
||||
MG_BIT(10); // See #2487
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
|
||||
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
|
||||
s_rxdesc[i][1] = 0; // Clear status
|
||||
@@ -23309,26 +23341,21 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
|
||||
GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
|
||||
|
||||
GMAC_REGS->SA[0].GMAC_SAB =
|
||||
GMAC_REGS->GMAC_SAB0 =
|
||||
MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
|
||||
GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
|
||||
GMAC_REGS->GMAC_SAT0 = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
|
||||
|
||||
GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII
|
||||
GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk |
|
||||
GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk;
|
||||
GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk |
|
||||
GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk |
|
||||
GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk;
|
||||
GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk |
|
||||
GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk;
|
||||
GMAC_REGS->GMAC_UR &= ~MG_BIT(0); // Disable MII, use RMII
|
||||
GMAC_REGS->GMAC_NCFGR |= MG_BIT(8) | MG_BIT(6) | // MAXFX, MTIHEN
|
||||
MG_BIT(25) | MG_BIT(4); // EFRHD, CAF
|
||||
GMAC_REGS->GMAC_TSR = 0x17f; // all transmit statuses
|
||||
GMAC_REGS->GMAC_RSR = 0xf; // all recv statuses
|
||||
GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required
|
||||
GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk |
|
||||
GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk |
|
||||
GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk |
|
||||
GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk;
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk;
|
||||
NVIC_EnableIRQ(GMAC_IRQn);
|
||||
GMAC_REGS->GMAC_IER = MG_BIT(11) | MG_BIT(10) | // HRESP, ROVR
|
||||
MG_BIT(7) | MG_BIT(6) | // TCOMP, TFC
|
||||
MG_BIT(5) | MG_BIT(4) | // RLEX, TUR
|
||||
MG_BIT(2) | MG_BIT(1); // RXUBR, RCOMP
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(3) | MG_BIT(2); // TXEN, RXEN
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -23349,8 +23376,8 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
|
||||
s_txdesc[s_txno][1] = status;
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
__DSB(); // Ensure descriptors have been written
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission
|
||||
MG_DSB(); // Ensure descriptors have been written
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(9); // Enable transmission
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -23370,21 +23397,22 @@ static bool mg_tcpip_driver_same54_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
mg_tcpip_driver_same54_update_hash_table(ifp);
|
||||
ifp->update_mac_hash_table = false;
|
||||
}
|
||||
|
||||
bool up = false;
|
||||
if (s1) {
|
||||
uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR);
|
||||
bool up = bsr & MG_PHYREGBIT_BSR_LINK_STATUS ? 1 : 0;
|
||||
uint8_t speed = MG_PHY_SPEED_10M;
|
||||
bool full_duplex = false;
|
||||
struct mg_phy phy = {eth_read_phy, eth_write_phy};
|
||||
up = mg_phy_up(&phy, 0, &full_duplex, &speed);
|
||||
|
||||
// If PHY is ready, update NCFGR accordingly
|
||||
if (ifp->state == MG_TCPIP_STATE_DOWN && up) {
|
||||
uint16_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR);
|
||||
bool fd = bcr & MG_PHYREGBIT_BCR_DUPLEX_MODE ? 1 : 0;
|
||||
bool spd = bcr & MG_PHYREGBIT_BCR_SPEED ? 1 : 0;
|
||||
GMAC_REGS->GMAC_NCFGR = (GMAC_REGS->GMAC_NCFGR &
|
||||
~(GMAC_NCFGR_SPD_Msk | MG_PHYREGBIT_BCR_SPEED)) |
|
||||
GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd);
|
||||
~(MG_BIT(0) | MG_BIT(1))) |
|
||||
(speed & 1) | (full_duplex << 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return up;
|
||||
}
|
||||
|
||||
void GMAC_Handler(void);
|
||||
@@ -23392,8 +23420,8 @@ void GMAC_Handler(void) {
|
||||
uint32_t isr = GMAC_REGS->GMAC_ISR;
|
||||
uint32_t rsr = GMAC_REGS->GMAC_RSR;
|
||||
uint32_t tsr = GMAC_REGS->GMAC_TSR;
|
||||
if (isr & GMAC_ISR_RCOMP_Msk) {
|
||||
if (rsr & GMAC_ISR_RCOMP_Msk) {
|
||||
if (isr & MG_BIT(1)) {
|
||||
if (rsr & MG_BIT(1)) {
|
||||
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
|
||||
if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
|
||||
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
|
||||
@@ -23404,9 +23432,7 @@ void GMAC_Handler(void) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk |
|
||||
GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) {
|
||||
if (tsr != 0) {
|
||||
// MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
|
||||
if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
|
||||
}
|
||||
|
||||
+25
-4
@@ -3414,14 +3414,35 @@ struct mg_tcpip_driver_rw612_data {
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54
|
||||
|
||||
struct mg_tcpip_driver_same54_data {
|
||||
int mdc_cr;
|
||||
};
|
||||
|
||||
#ifndef MG_DRIVER_MDC_CR
|
||||
#define MG_DRIVER_MDC_CR 5
|
||||
#endif
|
||||
|
||||
#ifndef MG_DRIVER_PHY_ADDR
|
||||
#define MG_DRIVER_PHY_ADDR 0
|
||||
#endif
|
||||
|
||||
struct mg_tcpip_driver_same54_data {
|
||||
int mdc_cr;
|
||||
uint8_t phy_addr;
|
||||
};
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_tcpip_driver_same54_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
|
||||
driver_data_.phy_addr = MG_DRIVER_PHY_ADDR; \
|
||||
mif_.ip = MG_TCPIP_IP; \
|
||||
mif_.mask = MG_TCPIP_MASK; \
|
||||
mif_.gw = MG_TCPIP_GW; \
|
||||
mif_.driver = &mg_tcpip_driver_same54; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: same54, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+103
-77
@@ -3,7 +3,45 @@
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && \
|
||||
MG_ENABLE_DRIVER_SAME54
|
||||
|
||||
#include <sam.h>
|
||||
struct GMAC_REGS_ {
|
||||
uint32_t GMAC_NCR, GMAC_NCFGR, GMAC_NSR, GMAC_UR, GMAC_DCFGR, GMAC_TSR, GMAC_RBQB, GMAC_TBQB,
|
||||
GMAC_RSR, GMAC_ISR, GMAC_IER, GMAC_IDR, GMAC_IMR, GMAC_MAN, GMAC_RPQ, GMAC_TPQ,
|
||||
GMAC_TPSF, GMAC_RPSF, GMAC_RJFML,
|
||||
Reserved1[13],
|
||||
GMAC_HRB, GMAC_HRT,
|
||||
GMAC_SAB0, GMAC_SAT0, GMAC_SAB1, GMAC_SAT1, GMAC_SAB2, GMAC_SAT2, GMAC_SAB3, GMAC_SAT3,
|
||||
GMAC_TIDM[4],
|
||||
GMAC_WOL, GMAC_IPGS, GMAC_SVLAN, GMAC_TPFCP,
|
||||
GMAC_SAMB1, GMAC_SAMT1,
|
||||
Reserved2[3],
|
||||
GMAC_NSC, GMAC_SCL, GMAC_SCH,
|
||||
GMAC_EFTSH, GMAC_EFRSH, GMAC_PEFTSH, GMAC_PEFRSH,
|
||||
Reserved3[2],
|
||||
GMAC_OTLO, GMAC_OTHI, GMAC_FT, GMAC_BCFT, GMAC_MFT, GMAC_PFT, GMAC_BFT64, GMAC_TBFT127,
|
||||
GMAC_TBFT255, GMAC_TBFT511, GMAC_TBFT1023, GMAC_TBFT1518, GMAC_GTBFT1518,
|
||||
GMAC_TUR, GMAC_SCF, GMAC_MCF, GMAC_EC, GMAC_LC, GMAC_DTF, GMAC_CSE,
|
||||
GMAC_ORLO, GMAC_ORHI, GMAC_FR, GMAC_BCFR, GMAC_MFR, GMAC_PFR, GMAC_BFR64, GMAC_TBFR127,
|
||||
GMAC_TBFR255, GMAC_TBFR511, GMAC_TBFR1023, GMAC_TBFR1518, GMAC_TMXBFR,
|
||||
GMAC_UFR, GMAC_OFR, GMAC_JR, GMAC_FCSE, GMAC_LFFE, GMAC_RSE, GMAC_AE, GMAC_RRE,
|
||||
GMAC_ROE, GMAC_IHCE, GMAC_TCE, GMAC_UCE,
|
||||
Reserved4[2],
|
||||
GMAC_TISUBN, GMAC_TSH,
|
||||
Reserved5,
|
||||
GMAC_TSSSL, GMAC_TSSN, GMAC_TSL, GMAC_TN, GMAC_TA, GMAC_TI,
|
||||
GMAC_EFTSL, GMAC_EFTN, GMAC_EFRSL, GMAC_EFRN,
|
||||
GMAC_PEFTSL, GMAC_PEFTN, GMAC_PEFRSL, GMAC_PEFRN,
|
||||
Reserved6[28],
|
||||
GMAC_RLPITR, GMAC_RLPITI, GMAC_TLPITR, GMAC_TLPITI;
|
||||
};
|
||||
|
||||
struct GCLK_REGS_ {
|
||||
uint32_t GCLK_CTRLA_RESERVED, GCLK_SYNCBUSY, Reserved2[6],
|
||||
GCLK_GENCTRL[12], Reserved3[12], GCLK_PCHCTRL[48];
|
||||
};
|
||||
|
||||
|
||||
#define GMAC_REGS ((struct GMAC_REGS_ *) 0x42000800)
|
||||
#define GCLK_REGS ((struct GCLK_REGS_ *) 0x40001c00)
|
||||
|
||||
#define ETH_PKT_SIZE 1536 // Max frame size
|
||||
#define ETH_DESC_CNT 4 // Descriptors count
|
||||
@@ -17,72 +55,65 @@ static uint8_t s_txno; // Current TX descriptor
|
||||
static uint8_t s_rxno; // Current RX descriptor
|
||||
|
||||
static struct mg_tcpip_if *s_ifp; // MIP interface
|
||||
enum { MG_PHY_ADDR = 0, MG_PHYREG_BCR = 0, MG_PHYREG_BSR = 1 };
|
||||
|
||||
#define MG_PHYREGBIT_BCR_DUPLEX_MODE MG_BIT(8)
|
||||
#define MG_PHYREGBIT_BCR_SPEED MG_BIT(13)
|
||||
#define MG_PHYREGBIT_BSR_LINK_STATUS MG_BIT(2)
|
||||
|
||||
static uint16_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk |
|
||||
GMAC_MAN_OP(2) | // Setting the read operation
|
||||
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
|
||||
GMAC_MAN_REGA(reg); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)) (void) 0;
|
||||
return GMAC_REGS->GMAC_MAN & GMAC_MAN_DATA_Msk; // Getting the read value
|
||||
GMAC_REGS->GMAC_MAN = MG_BIT(30) | // Clause 22
|
||||
MG_BIT(29) | // Setting the read operation
|
||||
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
|
||||
((reg & 0x1f) << 18); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2))) (void) 0;
|
||||
return GMAC_REGS->GMAC_MAN & 0xffff; // Getting the read value
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void eth_write_phy(uint8_t addr, uint8_t reg, uint16_t val) {
|
||||
GMAC_REGS->GMAC_MAN = GMAC_MAN_CLTTO_Msk | GMAC_MAN_OP(1) | // Setting the write operation
|
||||
GMAC_MAN_WTN(2) | GMAC_MAN_PHYA(addr) | // PHY address
|
||||
GMAC_MAN_REGA(reg) | GMAC_MAN_DATA(val); // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & GMAC_NSR_IDLE_Msk)); // Waiting until the write op is complete
|
||||
GMAC_REGS->GMAC_MAN = MG_BIT(30) | MG_BIT(28) | // Setting the write operation
|
||||
MG_BIT(17) | ((addr & 0x1f) << 23) | // PHY address
|
||||
((reg & 0x1f) << 18) | val; // Setting the register
|
||||
while (!(GMAC_REGS->GMAC_NSR & MG_BIT(2))); // Waiting until the write op is complete
|
||||
}
|
||||
#endif
|
||||
|
||||
int get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
|
||||
uint32_t get_clock_rate(struct mg_tcpip_driver_same54_data *d) {
|
||||
if (d && d->mdc_cr >= 0 && d->mdc_cr <= 5) {
|
||||
return d->mdc_cr;
|
||||
} else {
|
||||
// get MCLK from GCLK_GENERATOR 0
|
||||
uint32_t div = 512;
|
||||
uint32_t mclk;
|
||||
if (!(GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_DIVSEL_Msk)) {
|
||||
if (!(GCLK_REGS->GCLK_GENCTRL[0] & MG_BIT(12))) {
|
||||
div = ((GCLK_REGS->GCLK_GENCTRL[0] & 0x00FF0000) >> 16);
|
||||
if (div == 0) div = 1;
|
||||
}
|
||||
switch (GCLK_REGS->GCLK_GENCTRL[0] & GCLK_GENCTRL_SRC_Msk) {
|
||||
case GCLK_GENCTRL_SRC_XOSC0_Val:
|
||||
mclk = 32000000UL; /* 32MHz */
|
||||
switch (GCLK_REGS->GCLK_GENCTRL[0] & 0xF) {
|
||||
case 0: // GCLK_GENCTRL_SRC_XOSC0_Val
|
||||
mclk = 32000000UL; // 32MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_XOSC1_Val:
|
||||
mclk = 32000000UL; /* 32MHz */
|
||||
case 1: // GCLK_GENCTRL_SRC_XOSC1_Val
|
||||
mclk = 32000000UL; // 32MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_OSCULP32K_Val:
|
||||
mclk = 32000UL;
|
||||
case 4: // GCLK_GENCTRL_SRC_OSCULP32K_Val
|
||||
mclk = 32000UL; // 32Khz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_XOSC32K_Val:
|
||||
mclk = 32000UL;
|
||||
case 5: // GCLK_GENCTRL_SRC_XOSC32K_Val
|
||||
mclk = 32000UL; // 32Khz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DFLL_Val:
|
||||
mclk = 48000000UL; /* 48MHz */
|
||||
case 6: // GCLK_GENCTRL_SRC_DFLL_Val
|
||||
mclk = 48000000UL; // 48MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DPLL0_Val:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
case 7: // GCLK_GENCTRL_SRC_DPLL0_Val:
|
||||
mclk = 200000000UL; // 200MHz
|
||||
break;
|
||||
case GCLK_GENCTRL_SRC_DPLL1_Val:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
case 8: // GCLK_GENCTRL_SRC_DPLL1_Val
|
||||
mclk = 200000000UL; // 200MHz
|
||||
break;
|
||||
default:
|
||||
mclk = 200000000UL; /* 200MHz */
|
||||
mclk = 200000000UL; // 200MHz
|
||||
}
|
||||
|
||||
mclk /= div;
|
||||
uint8_t crs[] = {0, 1, 2, 3, 4, 5}; // GMAC->NCFGR::CLK values
|
||||
uint8_t dividers[] = {8, 16, 32, 48, 64, 96}; // Respective CLK dividers
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (mclk / dividers[i] <= 2375000UL /* 2.5MHz - 5% */) {
|
||||
if (mclk / dividers[i] <= 2375000UL) { // 2.5MHz - 5%
|
||||
return crs[i];
|
||||
}
|
||||
}
|
||||
@@ -96,11 +127,12 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
(struct mg_tcpip_driver_same54_data *) ifp->driver_data;
|
||||
s_ifp = ifp;
|
||||
|
||||
MCLK_REGS->MCLK_APBCMASK |= MCLK_APBCMASK_GMAC_Msk;
|
||||
MCLK_REGS->MCLK_AHBMASK |= MCLK_AHBMASK_GMAC_Msk;
|
||||
GMAC_REGS->GMAC_NCFGR = GMAC_NCFGR_CLK(get_clock_rate(d)); // Set MDC divider
|
||||
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_MPE_Msk; // Enable MDC & MDIO
|
||||
GMAC_REGS->GMAC_NCFGR = get_clock_rate(d) << 18; // Set MDC divider
|
||||
GMAC_REGS->GMAC_NCR = 0; // Disable RX & TX
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(4); // Enable MDC & MDIO
|
||||
|
||||
struct mg_phy phy = {eth_read_phy, eth_write_phy};
|
||||
mg_phy_init(&phy, d->phy_addr, 0);
|
||||
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init TX descriptors
|
||||
s_txdesc[i][0] = (uint32_t) s_txbuf[i]; // Point to data buffer
|
||||
@@ -108,9 +140,9 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
}
|
||||
s_txdesc[ETH_DESC_CNT - 1][1] |= MG_BIT(30); // Last tx descriptor - wrap
|
||||
|
||||
GMAC_REGS->GMAC_DCFGR = GMAC_DCFGR_DRBS(0x18) // DMA recv buf 1536
|
||||
| GMAC_DCFGR_RXBMS(GMAC_DCFGR_RXBMS_FULL_Val) |
|
||||
GMAC_DCFGR_TXPBMS(1); // See #2487
|
||||
GMAC_REGS->GMAC_DCFGR = (0x18 << 16) | // DMA recv buf 1536
|
||||
(3 << 8) | // RXBMS
|
||||
MG_BIT(10); // See #2487
|
||||
for (int i = 0; i < ETH_DESC_CNT; i++) { // Init RX descriptors
|
||||
s_rxdesc[i][0] = (uint32_t) s_rxbuf[i]; // Address of the data buffer
|
||||
s_rxdesc[i][1] = 0; // Clear status
|
||||
@@ -120,26 +152,21 @@ static bool mg_tcpip_driver_same54_init(struct mg_tcpip_if *ifp) {
|
||||
GMAC_REGS->GMAC_TBQB = (uint32_t) s_txdesc; // about the descriptor addresses
|
||||
GMAC_REGS->GMAC_RBQB = (uint32_t) s_rxdesc; // Let the controller know
|
||||
|
||||
GMAC_REGS->SA[0].GMAC_SAB =
|
||||
GMAC_REGS->GMAC_SAB0 =
|
||||
MG_U32(ifp->mac[3], ifp->mac[2], ifp->mac[1], ifp->mac[0]);
|
||||
GMAC_REGS->SA[0].GMAC_SAT = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
|
||||
GMAC_REGS->GMAC_SAT0 = MG_U32(0, 0, ifp->mac[5], ifp->mac[4]);
|
||||
|
||||
GMAC_REGS->GMAC_UR &= ~GMAC_UR_MII_Msk; // Disable MII, use RMII
|
||||
GMAC_REGS->GMAC_NCFGR |= GMAC_NCFGR_MAXFS_Msk | GMAC_NCFGR_MTIHEN_Msk |
|
||||
GMAC_NCFGR_EFRHD_Msk | GMAC_NCFGR_CAF_Msk;
|
||||
GMAC_REGS->GMAC_TSR = GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk |
|
||||
GMAC_TSR_TXCOMP_Msk | GMAC_TSR_TFC_Msk |
|
||||
GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk;
|
||||
GMAC_REGS->GMAC_RSR = GMAC_RSR_HNO_Msk | GMAC_RSR_RXOVR_Msk |
|
||||
GMAC_RSR_REC_Msk | GMAC_RSR_BNA_Msk;
|
||||
GMAC_REGS->GMAC_UR &= ~MG_BIT(0); // Disable MII, use RMII
|
||||
GMAC_REGS->GMAC_NCFGR |= MG_BIT(8) | MG_BIT(6) | // MAXFX, MTIHEN
|
||||
MG_BIT(25) | MG_BIT(4); // EFRHD, CAF
|
||||
GMAC_REGS->GMAC_TSR = 0x17f; // all transmit statuses
|
||||
GMAC_REGS->GMAC_RSR = 0xf; // all recv statuses
|
||||
GMAC_REGS->GMAC_IDR = ~0U; // Disable interrupts, then enable required
|
||||
GMAC_REGS->GMAC_IER = GMAC_IER_HRESP_Msk | GMAC_IER_ROVR_Msk |
|
||||
GMAC_IER_TCOMP_Msk | GMAC_IER_TFC_Msk |
|
||||
GMAC_IER_RLEX_Msk | GMAC_IER_TUR_Msk |
|
||||
GMAC_IER_RXUBR_Msk | GMAC_IER_RCOMP_Msk;
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TXEN_Msk | GMAC_NCR_RXEN_Msk;
|
||||
NVIC_EnableIRQ(GMAC_IRQn);
|
||||
GMAC_REGS->GMAC_IER = MG_BIT(11) | MG_BIT(10) | // HRESP, ROVR
|
||||
MG_BIT(7) | MG_BIT(6) | // TCOMP, TFC
|
||||
MG_BIT(5) | MG_BIT(4) | // RLEX, TUR
|
||||
MG_BIT(2) | MG_BIT(1); // RXUBR, RCOMP
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(3) | MG_BIT(2); // TXEN, RXEN
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -160,8 +187,8 @@ static size_t mg_tcpip_driver_same54_tx(const void *buf, size_t len,
|
||||
s_txdesc[s_txno][1] = status;
|
||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
||||
}
|
||||
__DSB(); // Ensure descriptors have been written
|
||||
GMAC_REGS->GMAC_NCR |= GMAC_NCR_TSTART_Msk; // Enable transmission
|
||||
MG_DSB(); // Ensure descriptors have been written
|
||||
GMAC_REGS->GMAC_NCR |= MG_BIT(9); // Enable transmission
|
||||
return len;
|
||||
}
|
||||
|
||||
@@ -181,21 +208,22 @@ static bool mg_tcpip_driver_same54_poll(struct mg_tcpip_if *ifp, bool s1) {
|
||||
mg_tcpip_driver_same54_update_hash_table(ifp);
|
||||
ifp->update_mac_hash_table = false;
|
||||
}
|
||||
|
||||
bool up = false;
|
||||
if (s1) {
|
||||
uint16_t bsr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BSR);
|
||||
bool up = bsr & MG_PHYREGBIT_BSR_LINK_STATUS ? 1 : 0;
|
||||
uint8_t speed = MG_PHY_SPEED_10M;
|
||||
bool full_duplex = false;
|
||||
struct mg_phy phy = {eth_read_phy, eth_write_phy};
|
||||
up = mg_phy_up(&phy, 0, &full_duplex, &speed);
|
||||
|
||||
// If PHY is ready, update NCFGR accordingly
|
||||
if (ifp->state == MG_TCPIP_STATE_DOWN && up) {
|
||||
uint16_t bcr = eth_read_phy(MG_PHY_ADDR, MG_PHYREG_BCR);
|
||||
bool fd = bcr & MG_PHYREGBIT_BCR_DUPLEX_MODE ? 1 : 0;
|
||||
bool spd = bcr & MG_PHYREGBIT_BCR_SPEED ? 1 : 0;
|
||||
GMAC_REGS->GMAC_NCFGR = (GMAC_REGS->GMAC_NCFGR &
|
||||
~(GMAC_NCFGR_SPD_Msk | MG_PHYREGBIT_BCR_SPEED)) |
|
||||
GMAC_NCFGR_SPD(spd) | GMAC_NCFGR_FD(fd);
|
||||
~(MG_BIT(0) | MG_BIT(1))) |
|
||||
(speed & 1) | (full_duplex << 1);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return up;
|
||||
}
|
||||
|
||||
void GMAC_Handler(void);
|
||||
@@ -203,8 +231,8 @@ void GMAC_Handler(void) {
|
||||
uint32_t isr = GMAC_REGS->GMAC_ISR;
|
||||
uint32_t rsr = GMAC_REGS->GMAC_RSR;
|
||||
uint32_t tsr = GMAC_REGS->GMAC_TSR;
|
||||
if (isr & GMAC_ISR_RCOMP_Msk) {
|
||||
if (rsr & GMAC_ISR_RCOMP_Msk) {
|
||||
if (isr & MG_BIT(1)) {
|
||||
if (rsr & MG_BIT(1)) {
|
||||
for (uint8_t i = 0; i < ETH_DESC_CNT; i++) {
|
||||
if ((s_rxdesc[s_rxno][0] & MG_BIT(0)) == 0) break;
|
||||
size_t len = s_rxdesc[s_rxno][1] & (MG_BIT(13) - 1);
|
||||
@@ -215,9 +243,7 @@ void GMAC_Handler(void) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((tsr & (GMAC_TSR_HRESP_Msk | GMAC_TSR_UND_Msk | GMAC_TSR_TXCOMP_Msk |
|
||||
GMAC_TSR_TFC_Msk | GMAC_TSR_TXGO_Msk | GMAC_TSR_RLE_Msk |
|
||||
GMAC_TSR_COL_Msk | GMAC_TSR_UBR_Msk)) != 0) {
|
||||
if (tsr != 0) {
|
||||
// MG_INFO((" --> %#x %#x", s_txdesc[s_txno][1], tsr));
|
||||
if (!(s_txdesc[s_txno][1] & MG_BIT(31))) s_txdesc[s_txno][1] |= MG_BIT(31);
|
||||
}
|
||||
|
||||
+25
-4
@@ -2,12 +2,33 @@
|
||||
|
||||
#if MG_ENABLE_TCPIP && defined(MG_ENABLE_DRIVER_SAME54) && MG_ENABLE_DRIVER_SAME54
|
||||
|
||||
struct mg_tcpip_driver_same54_data {
|
||||
int mdc_cr;
|
||||
};
|
||||
|
||||
#ifndef MG_DRIVER_MDC_CR
|
||||
#define MG_DRIVER_MDC_CR 5
|
||||
#endif
|
||||
|
||||
#ifndef MG_DRIVER_PHY_ADDR
|
||||
#define MG_DRIVER_PHY_ADDR 0
|
||||
#endif
|
||||
|
||||
struct mg_tcpip_driver_same54_data {
|
||||
int mdc_cr;
|
||||
uint8_t phy_addr;
|
||||
};
|
||||
|
||||
#define MG_TCPIP_DRIVER_INIT(mgr) \
|
||||
do { \
|
||||
static struct mg_tcpip_driver_same54_data driver_data_; \
|
||||
static struct mg_tcpip_if mif_; \
|
||||
driver_data_.mdc_cr = MG_DRIVER_MDC_CR; \
|
||||
driver_data_.phy_addr = MG_DRIVER_PHY_ADDR; \
|
||||
mif_.ip = MG_TCPIP_IP; \
|
||||
mif_.mask = MG_TCPIP_MASK; \
|
||||
mif_.gw = MG_TCPIP_GW; \
|
||||
mif_.driver = &mg_tcpip_driver_same54; \
|
||||
mif_.driver_data = &driver_data_; \
|
||||
MG_SET_MAC_ADDRESS(mif_.mac); \
|
||||
mg_tcpip_init(mgr, &mif_); \
|
||||
MG_INFO(("Driver: same54, MAC: %M", mg_print_mac, mif_.mac)); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user