I cannot get the PHY link-change interrupt to assert. I have the driver running, and I can see that the bits change in the MII_INTR register, and the MDINTR bit in the register gets set, but there doesn't appear to be anything happening on the PB26 pin (according to PIO_PDSR).
Anyone gotten this to work? Here is my init code, distilled to the important parts...
Code:
#define MII_INTR 21 /// interrupt register on PHY
#define MII_INTR_ENABLE_ALL 0 /// Set all the bits to 0
#define MII_INTERRUPT_PIN AT91C_PIO_PB26
static void phy_install_interrupt(void) {
// Enable the interrupts in the MII register
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
phy_write(MII_INTR,MII_INTR_ENABLE_ALL);
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
// Configure the pin to be an input source
AT91C_BASE_PIOB->PIO_ODR = MII_INTERRUPT_PIN; // Make it an input
AT91C_BASE_PIOB->PIO_IFDR = MII_INTERRUPT_PIN; // Disable the input glitch filter (could enable it, but we'll try this for now)
AT91C_BASE_PIOB->PIO_PER = MII_INTERRUPT_PIN; // Make it a GPIO pin
/* ...Set up the interrupt vector... */
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOB] = (AT91_REG) &sam7xek_piob_handler;
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOB] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | (AT91C_AIC_PRIOR && (3<<0));
AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_PIOB);
AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_PIOB);
/* Enable an interrupt based on that pin */
AT91C_BASE_PIOB->PIO_IER = MII_INTERRUPT_PIN; // Enable the interrupt
}