From d1626cc8b53ab6a787693d0e040171e0201b24b3 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Tue, 6 May 2008 15:04:12 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@281 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- ports/ARM7-AT91SAM7X/sam7x_emac.c | 121 +++++++++++++++++++++++++++++++------- ports/ARM7-AT91SAM7X/sam7x_emac.h | 4 +- 2 files changed, 104 insertions(+), 21 deletions(-) (limited to 'ports') diff --git a/ports/ARM7-AT91SAM7X/sam7x_emac.c b/ports/ARM7-AT91SAM7X/sam7x_emac.c index 0a680860e..61b387820 100644 --- a/ports/ARM7-AT91SAM7X/sam7x_emac.c +++ b/ports/ARM7-AT91SAM7X/sam7x_emac.c @@ -29,14 +29,15 @@ #define EMAC_TRANSMIT_BUFFERS 2 #define EMAC_TRANSMIT_BUFFERS_SIZE 1518 +EventSource EMACFrameTransmitted, EMACFrameReceived; + +static uint8_t default_mac[] = {0xAA, 0x55, 0x13, 0x37, 0x01, 0x10}; static BufDescriptorEntry rent[EMAC_RECEIVE_BUFFERS] __attribute__((aligned(4))); static uint8_t rbuffers[EMAC_RECEIVE_BUFFERS * EMAC_RECEIVE_BUFFERS_SIZE] __attribute__((aligned(4))); static BufDescriptorEntry tent[EMAC_TRANSMIT_BUFFERS] __attribute__((aligned(4))); static uint8_t tbuffers[EMAC_TRANSMIT_BUFFERS * EMAC_TRANSMIT_BUFFERS_SIZE] __attribute__((aligned(4))); -EventSource TransmitDone, ReceiveNotEmpty; - #define PHY_ADDRESS 1 #define AT91C_PB15_ERXDV AT91C_PB15_ERXDV_ECRSDV #define EMAC_PIN_MASK (AT91C_PB1_ETXEN | AT91C_PB2_ETX0 | \ @@ -49,6 +50,10 @@ EventSource TransmitDone, ReceiveNotEmpty; AT91C_PB15_ERXDV | AT91C_PB16_ECOL | \ AT91C_PB17_ERXCK) +#define PHY_LATCHED_PINS (AT91C_PB4_ECRS | AT91C_PB5_ERX0 | AT91C_PB6_ERX1 | \ + AT91C_PB7_ERXER | AT91C_PB13_ERX2 | AT91C_PB14_ERX3 | \ + AT91C_PB15_ERXDV | AT91C_PB16_ECOL | PIOB_PHY_IRQ) + /* * PHY utilities. */ @@ -64,7 +69,7 @@ static uint32_t phy_get(uint8_t regno) { return AT91C_BASE_EMAC->EMAC_MAN & 0xFFFF; } -static void phy_put(uint8_t regno, uint32_t val) { +/*static void phy_put(uint8_t regno, uint32_t val) { AT91C_BASE_EMAC->EMAC_MAN = (1 << 30) | // SOF = 01 (1 << 28) | // RW = 01 @@ -74,6 +79,51 @@ static void phy_put(uint8_t regno, uint32_t val) { val; while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE)) ; +}*/ + +/* + * Returns TRUE if the link is active else FALSE. + * It also setup the link-related EMAC registers. + */ +static bool_t check_link_status(void) { + uint32_t ncfgr, bmsr, bmcr, lpa; + + (void)phy_get(MII_BMSR); + bmsr = phy_get(MII_BMSR); + if (!(bmsr & BMSR_LSTATUS)) + return TRUE; + + ncfgr = AT91C_BASE_EMAC->EMAC_NCFGR & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD); + bmcr = phy_get(MII_BMCR); + if (bmcr & BMCR_ANENABLE) { + lpa = phy_get(MII_LPA); + if (lpa & (LPA_100HALF | LPA_100FULL | LPA_100BASE4)) + ncfgr |= AT91C_EMAC_SPD; + if (lpa & (LPA_10FULL | LPA_100FULL)) + ncfgr |= AT91C_EMAC_FD; + } + else { + if (bmcr & BMCR_SPEED100) + ncfgr |= AT91C_EMAC_SPD; + if (bmcr & BMCR_FULLDPLX) + ncfgr |= AT91C_EMAC_FD; + } + AT91C_BASE_EMAC->EMAC_NCFGR = ncfgr; + return FALSE; +} + +__attribute__((noinline)) +static void ServeInterrupt(void) { +} + +__attribute__((naked, weak)) +void EMACIrqHandler(void) { + + chSysIRQEnterI(); + + ServeInterrupt(); + + chSysIRQExitI(); } /* @@ -98,17 +148,26 @@ void InitEMAC(int prio) { tent[EMAC_TRANSMIT_BUFFERS - 1].w1 |= W2_T_WRAP; /* - * Disables default pullups, the PHY has an internal pulldowns. - * Selects MII mode. + * Disables the pullups on all the pins that are latched on reset by the PHY. + * The status latched into the PHY is: + * PHYADDR = 00001 + * PCS_LPBK = 0 (disabled) + * ISOLATE = 0 (disabled) + * RMIISEL = 0 (MII mode) + * RMIIBTB = 0 (BTB mode disabled) + * SPEED = 1 (100mbps) + * DUPLEX = 1 (full duplex) + * ANEG_EN = 1 (auto negotiation enabled) */ - AT91C_BASE_PIOB->PIO_PPUDR = AT91C_PB15_ERXDV | AT91C_PB16_ECOL; + AT91C_BASE_PIOB->PIO_PPUDR = PHY_LATCHED_PINS; /* - * PHY powerdown. + * PHY power control. */ - AT91C_BASE_PIOB->PIO_OER = PIOB_PHY_PD; // Becomes an output. - AT91C_BASE_PIOB->PIO_PPUDR = PIOB_PHY_PD; // Default pullup disabled. - AT91C_BASE_PIOB->PIO_CODR = PIOB_PHY_PD; // Output to low level. + AT91C_BASE_PIOB->PIO_OER = PIOB_PHY_PD; // Becomes an output. + AT91C_BASE_PIOB->PIO_PPUDR = PIOB_PHY_PD; // Default pullup disabled. +// AT91C_BASE_PIOB->PIO_CODR = PIOB_PHY_PD; // Output to low level. + AT91C_BASE_PIOB->PIO_SODR = PIOB_PHY_PD; // Output to high level. /* * PHY reset by pulsing the NRST pin. @@ -119,7 +178,8 @@ void InitEMAC(int prio) { ; /* - * EMAC pins setup. + * EMAC pins setup. Note, PB18 is not included because it is used as #PD + * control and not as EF100. */ AT91C_BASE_PIOB->PIO_ASR = EMAC_PIN_MASK; AT91C_BASE_PIOB->PIO_PDR = EMAC_PIN_MASK; @@ -128,30 +188,51 @@ void InitEMAC(int prio) { /* * EMAC setup. */ - AT91C_BASE_EMAC->EMAC_NCR = AT91C_EMAC_MPE; // Enable Management Port +// AT91C_BASE_EMAC->EMAC_NCR = AT91C_EMAC_MPE; // Enable Management Port AT91C_BASE_EMAC->EMAC_NCFGR = 2 << 10; // MDC-CLK = MCK / 32 - chThdSleep(5); // It could perform one or more dummy phy_get() instead. - (void)phy_get(MII_BMCR); - phy_put(MII_BMCR, phy_get(MII_BMCR) & ~BMCR_ISOLATE); // Disable ISOLATE +// chThdSleep(5); // It could perform one or more dummy phy_get() instead. +// (void)phy_get(MII_BMCR); +// phy_put(MII_BMCR, phy_get(MII_BMCR) & ~BMCR_ISOLATE); // Disable ISOLATE AT91C_BASE_EMAC->EMAC_NCR = 0; // Disable Management Port AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_CLKEN; // Enable EMAC in MII mode - AT91C_BASE_EMAC->EMAC_RBQP = (AT91_REG)rent; // RX buffers list AT91C_BASE_EMAC->EMAC_TBQP = (AT91_REG)tent; // TX buffers list - AT91C_BASE_EMAC->EMAC_RSR = AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA; // Clears RSR - AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_CAF | AT91C_EMAC_NBC | AT91C_EMAC_DRFCS; // Initial NCFGR settings - AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_CLRSTAT; // Initial NCR settings + EMACSetAddress(default_mac); + + /* + * PHY checks and settings. + */ + AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE; + if ((phy_get(MII_PHYSID1) != (MII_MICREL_ID >> 16)) || + (phy_get(MII_PHYSID2 & 0xFFF0) != (MII_MICREL_ID & 0xFFF0))) + chDbgPanic("Wrong PHY identifier"); + if (check_link_status()) + chDbgPanic("No link"); + AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE; + /* + * Interrupt setup. + */ + AIC_ConfigureIT(AT91C_ID_EMAC, + AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | prio, + EMACIrqHandler); + AIC_EnableIT(AT91C_ID_EMAC); + + /* + * Event sources setup. + */ + chEvtInit(&EMACFrameTransmitted); + chEvtInit(&EMACFrameReceived); } /* @@ -167,7 +248,7 @@ void EMACSetAddress(uint8_t *eaddr) { /* * Transmits an ethernet frame. */ -bool_t EMACTransmit(uint8_t *hdr, size_t hsize, uint8_t *data, size_t dsize) { +bool_t EMACTransmit(uint8_t *hdr, uint8_t *data, size_t size) { return FALSE; } diff --git a/ports/ARM7-AT91SAM7X/sam7x_emac.h b/ports/ARM7-AT91SAM7X/sam7x_emac.h index 7fb5e4517..aff071ff6 100644 --- a/ports/ARM7-AT91SAM7X/sam7x_emac.h +++ b/ports/ARM7-AT91SAM7X/sam7x_emac.h @@ -63,9 +63,11 @@ extern "C" { #endif void InitEMAC(int prio); void EMACSetAddress(uint8_t *eaddr); - bool_t EMACTransmit(uint8_t *hdr, size_t hsize, uint8_t *data, size_t dsize); + bool_t EMACTransmit(uint8_t *hdr, uint8_t *data, size_t size); #ifdef __cplusplus } #endif +extern EventSource EMACFrameTransmitted, EMACFrameReceived; + #endif /* _SAM7X_EMAC_H_ */ -- cgit v1.2.3