*
* \return Contents of the specified register.
*/
-static uint16_t phy_hw_read(reg8_t reg)
+static uint16_t phy_hw_read(uint8_t phy_addr, reg8_t reg)
{
// PHY read command.
- EMAC_MAN = EMAC_SOF | EMAC_RW_READ | (NIC_PHY_ADDR << EMAC_PHYA_SHIFT)
- | ((reg << EMAC_REGA_SHIFT) & EMAC_REGA) | EMAC_CODE;
+ EMAC_MAN = EMAC_SOF | EMAC_RW_READ
+ | ((phy_addr << EMAC_PHYA_SHIFT) & EMAC_PHYA)
+ | ((reg << EMAC_REGA_SHIFT) & EMAC_REGA)
+ | EMAC_CODE;
// Wait until PHY logic completed.
while (!(EMAC_NSR & BV(EMAC_IDLE)))
* \param reg PHY register number.
* \param val Value to write.
*/
-static void phy_hw_write(reg8_t reg, uint16_t val)
+static void phy_hw_write(uint8_t phy_addr, reg8_t reg, uint16_t val)
{
// PHY write command.
- EMAC_MAN = EMAC_SOF | EMAC_RW_WRITE | (NIC_PHY_ADDR << EMAC_PHYA_SHIFT)
- | ((reg << EMAC_REGA_SHIFT) & EMAC_REGA) | EMAC_CODE | val;
+ EMAC_MAN = EMAC_SOF | EMAC_RW_WRITE
+ | ((phy_addr << EMAC_PHYA_SHIFT) & EMAC_PHYA)
+ | ((reg << EMAC_REGA_SHIFT) & EMAC_REGA)
+ | EMAC_CODE | val;
// Wait until PHY logic completed.
while (!(EMAC_NSR & BV(EMAC_IDLE)))
static int emac_reset(void)
{
uint16_t phy_cr;
+ unsigned i;
+#if CPU_ARM_AT91
// Enable devices
- //PMC_PCER = BV(PIOA_ID);
- //PMC_PCER = BV(PIOB_ID);
- //PMC_PCER = BV(EMAC_ID);
- // TOOD: Implement in sam7x
- pmc_periphEnable(PIOA_ID);
- pmc_periphEnable(PIOB_ID);
- pmc_periphEnable(EMAC_ID);
+ PMC_PCER = BV(PIOA_ID);
+ PMC_PCER = BV(PIOB_ID);
+ PMC_PCER = BV(EMAC_ID);
- // Disable TESTMODE
+ // Disable TESTMODE and RMII
PIOB_PUDR = BV(PHY_RXDV_TESTMODE_BIT);
-#if CPU_ARM_AT91
- // Disable RMII
PIOB_PUDR = BV(PHY_COL_RMII_BIT);
// Disable PHY power down.
PIOB_PER = BV(PHY_PWRDN_BIT);
PIOB_OER = BV(PHY_PWRDN_BIT);
PIOB_CODR = BV(PHY_PWRDN_BIT);
+#else
+ pmc_periphEnable(PIOA_ID);
+ pmc_periphEnable(PIOB_ID);
+ pmc_periphEnable(PIOC_ID);
+ pmc_periphEnable(PIOD_ID);
+ pmc_periphEnable(EMAC_ID);
+
+ // Disable TESTMODE and RMII
+ PIOC_PUDR = BV(PHY_RXDV_TESTMODE_BIT);
+
+ // Disable PHY power down.
+ PIOD_PER = BV(PHY_PWRDN_BIT);
+ PIOD_OER = BV(PHY_PWRDN_BIT);
+ PIOD_CODR = BV(PHY_PWRDN_BIT);
#endif
// Toggle external hardware reset pin.
PIOB_ASR = PHY_MII_PINS;
PIOB_BSR = 0;
PIOB_PDR = PHY_MII_PINS;
+
// Enable receive and transmit clocks.
EMAC_USRIO = BV(EMAC_CLKEN);
#else
- PIO_PERIPH_SEL(PIOB_BASE, PHY_MII_PINS, PIO_PERIPH_A);
- PIOB_PDR = PHY_MII_PINS;
+ PIO_PERIPH_SEL(PIOB_BASE, PHY_MII_PINS_PORTB, PIO_PERIPH_A);
+ PIOB_PDR = PHY_MII_PINS_PORTB;
+
+ PIO_PERIPH_SEL(PIOC_BASE, PHY_MII_PINS_PORTC, PIO_PERIPH_A);
+ PIOC_PDR = PHY_MII_PINS_PORTC;
+
// Enable receive, transmit clocks and RMII mode.
EMAC_USRIO = BV(EMAC_CLKEN) | BV(EMAC_RMII);
#endif
// Enable management port.
EMAC_NCR |= BV(EMAC_MPE);
- EMAC_NCFGR |= EMAC_CLK_HCLK_32;
+ EMAC_NCFGR |= EMAC_CLK_HCLK_64;
// Set local MAC address.
EMAC_SA1L = (mac_addr[3] << 24) | (mac_addr[2] << 16) |
EMAC_SA1H = (mac_addr[5] << 8) | mac_addr[4];
// Wait for PHY ready
- timer_delay(255);
+ timer_delay(500);
+
+#if 0 // debug test
+ for (;;)
+ {
+ for (i = 0; i < 32; i++)
+ {
+ // Clear MII isolate.
+ phy_hw_read(i, NIC_PHY_BMCR);
+ phy_cr = phy_hw_read(i, NIC_PHY_BMCR);
+
+ phy_cr &= ~NIC_PHY_BMCR_ISOLATE;
+ phy_hw_write(i, NIC_PHY_BMCR, phy_cr);
+
+ phy_cr = phy_hw_read(i, NIC_PHY_BMCR);
+
+ LOG_INFO("%s: PHY ID %d %#04x %#04x\n",
+ __func__, i,
+ phy_hw_read(i, NIC_PHY_ID1), phy_hw_read(i, NIC_PHY_ID2));
+ }
+ timer_delay(1000);
+ }
+#endif
// Clear MII isolate.
- phy_hw_read(NIC_PHY_BMCR);
- phy_cr = phy_hw_read(NIC_PHY_BMCR);
+ //phy_hw_read(NIC_PHY_ADDR, NIC_PHY_BMCR);
+ phy_cr = phy_hw_read(NIC_PHY_ADDR, NIC_PHY_BMCR);
phy_cr &= ~NIC_PHY_BMCR_ISOLATE;
- phy_hw_write(NIC_PHY_BMCR, phy_cr);
+ phy_hw_write(NIC_PHY_ADDR, NIC_PHY_BMCR, phy_cr);
- phy_cr = phy_hw_read(NIC_PHY_BMCR);
+ //phy_cr = phy_hw_read(NIC_PHY_ADDR, NIC_PHY_BMCR);
LOG_INFO("%s: PHY ID %#04x %#04x\n",
__func__,
- phy_hw_read(NIC_PHY_ID1), phy_hw_read(NIC_PHY_ID2));
-
- // Wait for auto negotiation completed.
- phy_hw_read(NIC_PHY_BMSR);
- for (;;)
- {
- if (phy_hw_read(NIC_PHY_BMSR) & NIC_PHY_BMSR_ANCOMPL)
- break;
- cpu_relax();
- }
+ phy_hw_read(NIC_PHY_ADDR, NIC_PHY_ID1), phy_hw_read(NIC_PHY_ADDR, NIC_PHY_ID2));
// Disable management port.
EMAC_NCR &= ~BV(EMAC_MPE);