diff --git a/os/io/platforms/AT91SAM7X/mii.h b/os/io/platforms/AT91SAM7X/mii.h index 4ec25667a..990222a11 100644 --- a/os/io/platforms/AT91SAM7X/mii.h +++ b/os/io/platforms/AT91SAM7X/mii.h @@ -151,6 +151,6 @@ #define MII_DM9161_ID 0x0181b8a0 #define MII_AM79C875_ID 0x00225540 -#define MII_MICREL_ID 0x00221610 +#define MII_KS8721_ID 0x00221610 #endif /* _MII_H_ */ diff --git a/os/io/platforms/AT91SAM7X/phy_lld.c b/os/io/platforms/AT91SAM7X/phy_lld.c index 1b965d3e5..220d34a25 100644 --- a/os/io/platforms/AT91SAM7X/phy_lld.c +++ b/os/io/platforms/AT91SAM7X/phy_lld.c @@ -28,6 +28,8 @@ #include #include +#include "mii.h" + /** * @brief Low level PHY initialization. */ @@ -42,6 +44,36 @@ void phy_lld_init(void) { */ void phy_lld_reset(MACDriver *macp) { + /* + * 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 = PHY_LATCHED_PINS; + +#ifdef PIOB_PHY_PD_MASK + /* + * PHY power control. + */ + AT91C_BASE_PIOB->PIO_OER = PIOB_PHY_PD_MASK; // Becomes an output. + AT91C_BASE_PIOB->PIO_PPUDR = PIOB_PHY_PD_MASK; // Default pullup disabled. + AT91C_BASE_PIOB->PIO_SODR = PIOB_PHY_PD_MASK; // Output to high level. +#endif + + /* + * PHY reset by pulsing the NRST pin. + */ + AT91C_BASE_RSTC->RSTC_RMR = 0xA5000100; + AT91C_BASE_RSTC->RSTC_RCR = 0xA5000000 | AT91C_RSTC_EXTRST; + while (!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL)) + ; } /** @@ -53,7 +85,14 @@ void phy_lld_reset(MACDriver *macp) { */ phyreg_t phy_lld_get(MACDriver *macp, phyaddr_t addr) { - return 0; + AT91C_BASE_EMAC->EMAC_MAN = (0b01 << 30) | /* SOF */ + (0b10 << 28) | /* RW */ + (PHY_ADDRESS << 23) | /* PHYA */ + (addr << 18) | /* REGA */ + (0b10 << 16); /* CODE */ + while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE)) + ; + return (phyreg_t)(AT91C_BASE_EMAC->EMAC_MAN & 0xFFFF); } /** @@ -65,6 +104,14 @@ phyreg_t phy_lld_get(MACDriver *macp, phyaddr_t addr) { */ void phy_lld_put(MACDriver *macp, phyaddr_t addr, phyreg_t value) { + AT91C_BASE_EMAC->EMAC_MAN = (0b01 << 30) | /* SOF */ + (0b01 << 28) | /* RW */ + (PHY_ADDRESS << 23) | /* PHYA */ + (addr << 18) | /* REGA */ + (0b10 << 16) | /* CODE */ + value; + while (!( AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE)) + ; } /** @} */ diff --git a/os/io/platforms/AT91SAM7X/phy_lld.h b/os/io/platforms/AT91SAM7X/phy_lld.h index 09f7bbc92..df583426e 100644 --- a/os/io/platforms/AT91SAM7X/phy_lld.h +++ b/os/io/platforms/AT91SAM7X/phy_lld.h @@ -31,6 +31,30 @@ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @brief PHY manufacturer and model. + */ +#if !defined(PHY_HARDWARE) || defined(__DOXYGEN__) +#define PHY_HARDWARE PHY_MICREL_KS8721 +#endif + +/*===========================================================================*/ +/* PHY specific constants. */ +/*===========================================================================*/ + +#define PHY_MICREL_KS8721 0 + +#define PHY_ADDRESS 1 + +/** + * @brief Pins latched by the PHY at reset. + */ +#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 | \ + AT91C_PIO_PB26) + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ diff --git a/os/io/platforms/AT91SAM7X/sam7x_emac.c b/os/io/platforms/AT91SAM7X/sam7x_emac.c index 82d7e8381..d265330d8 100644 --- a/os/io/platforms/AT91SAM7X/sam7x_emac.c +++ b/os/io/platforms/AT91SAM7X/sam7x_emac.c @@ -219,8 +219,8 @@ void emac_init(int prio) { * PHY detection 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))) + if ((phy_get(MII_PHYSID1) != (MII_KS8721_ID >> 16)) || + ((phy_get(MII_PHYSID2) & 0xFFF0) != (MII_KS8721_ID & 0xFFF0))) chSysHalt(); /*