diff --git a/os/hal/include/mii.h b/os/hal/include/mii.h index 89ba69810..969f4a9d5 100644 --- a/os/hal/include/mii.h +++ b/os/hal/include/mii.h @@ -178,6 +178,7 @@ #define MII_DM9161_ID 0x0181b8a0 #define MII_AM79C875_ID 0x00225540 #define MII_KS8721_ID 0x00221610 +#define MII_STE101P_ID 0x00061C50 #endif /* _MII_H_ */ diff --git a/os/hal/platforms/STM32/mac_lld.c b/os/hal/platforms/STM32/mac_lld.c index 37ca9e106..01a28a8b4 100644 --- a/os/hal/platforms/STM32/mac_lld.c +++ b/os/hal/platforms/STM32/mac_lld.c @@ -29,7 +29,7 @@ #include "ch.h" #include "hal.h" #include "mii.h" -# + #if HAL_USE_MAC || defined(__DOXYGEN__) /*===========================================================================*/ @@ -38,6 +38,20 @@ #define BUFFER_SLICE ((((MAC_BUFFERS_SIZE - 1) | 3) + 1) / 4) +/* MII divider optimal value.*/ +#if (STM32_HCLK >= 60000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div42 +#elif (STM32_HCLK >= 35000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div26 +#elif (STM32_HCLK >= 20000000) +#define MACMIIDR_CR ETH_MACMIIAR_CR_Div16 +#else +#error "STM32_HCLK below minimum frequency for ETH operations (20MHz)" +#endif + +/* PHY address.*/ +#define MACMIIDR_PA (32 << 11) + /*===========================================================================*/ /* Driver exported variables. */ /*===========================================================================*/ @@ -64,6 +78,55 @@ static uint32_t tb[MAC_TRANSMIT_BUFFERS * BUFFER_SLICE]; /* Driver local functions. */ /*===========================================================================*/ +/** + * @brief Writes a PHY register. + * + * @param[in] reg register number + * @param[in] value new register value + */ +static void mii_write_phy(uint16_t reg, uint16_t value) { + uint32_t miiar; + + miiar = ETH->MACMIIAR | ETH_MACMIIAR_MW | ETH_MACMIIAR_MB; + miiar = (miiar & ~ETH_MACMIIAR_MR) | (reg << 6); + ETH->MACMIIDR = value; + ETH->MACMIIAR = miiar; + while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) + ; +} + +/** + * @brief Reads a PHY register. + * + * @param[in] reg register number + */ +static uint16_t mii_read_phy(uint16_t reg) { + uint32_t miiar; + + miiar = ETH->MACMIIAR | ETH_MACMIIAR_MB; + miiar = (miiar & ~(ETH_MACMIIAR_MR | ETH_MACMIIAR_MW)) | (reg << 6); + ETH->MACMIIAR = miiar; + while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) != 0) + ; + return (uint16_t)ETH->MACMIIDR; +} + +/** + * @brief MII/RMII interface initialization. + */ +static void mii_init(void) { + uint32_t i; + + for (i = 0; i < 31; i++) { + ETH->MACMIIDR = (i << 6) | MACMIIDR_CR; + if ((mii_read_phy(MII_PHYSID1) == (PHY_ID >> 16)) && + (mii_read_phy(MII_PHYSID2) == (PHY_ID & 0xFFF0))) + return; + } + /* Wrong or defective board.*/ + chSysHalt(); +} + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -121,6 +184,9 @@ void mac_lld_start(MACDriver *macp) { while (ETH->DMABMR & ETH_DMABMR_SR) ; + /* MII initialization.*/ + mii_init(); + /* Descriptor chains pointers.*/ ETH->DMARDLAR = (uint32_t)rd; ETH->DMATDLAR = (uint32_t)rd;