时钟
MAC 和 PHY 的协同工作共牵涉到以下时钟,Luban-Lite 已将时钟部分处理完整,不需要用户除 scons --menuconfig
配置 MAC 使用 external clk
或 internal clk
之外的其 他任何修改
MAC 工作时钟
MAC 的内部工作时钟通过 PLL 分频获得,为 50M, 工作时钟不会因为方案的不同而不同,为一固定值 配置代码在
“packages/third-party/lwip/contrib/ports/drv/aic/aic_mac_ll.c”
中。
void aicmac_low_level_init(uint32_t port, bool en)
{
uint32_t id = CLK_GMAC0 + port;
/* pin-mux */
/* mac clock */
if (en) {
/* Set clock frequence = 50M */
hal_clk_set_freq(id, 50000000);
/* clock enable & reset deassert */
hal_clk_enable_deassertrst_iter(id);
} else {
/* clock enable & reset deassert */
hal_clk_disable_assertrst(id);
}
}
MDC 时钟
MDC 时钟是 mdio 的工作时钟,是 MAC 和 PHY 进行配置的工作时钟,双方在使用初期会有一个协 商,一般是 MAC 通知 PHY,该时钟为 MAC
通过模块的内部工作时钟处理生成,也不会因为方案的 不同而不同,为一固定值。MDIO 时钟初始化在
“packages/third-party/lwip/contrib/ports/drv/aic/aicmac.c”
文件的 init 函数中
int aicmac_init(uint32_t port) { ... /* MDCIO Internal Clock Select */ tmpreg = readl(MAC(port, mdioctl)); tmpreg &= ~(ETH_MDIOCTL_CR_MSK); ahbclk = hal_clk_get_freq(CLK_AHB0); if ((ahbclk >= 20000000) && (ahbclk < 35000000)) { tmpreg |= ETH_MDIOCTL_CR_Div16; } else if ((ahbclk >= 35000000) && (ahbclk < 60000000)) { tmpreg |= ETH_MDIOCTL_CR_Div26; } else if ((ahbclk >= 60000000) && (ahbclk < 100000000)) { tmpreg |= ETH_MDIOCTL_CR_Div42; } else if ((ahbclk >= 100000000) && (ahbclk < 150000000)) { tmpreg |= ETH_MDIOCTL_CR_Div62; } else if ((ahbclk >= 150000000) && (ahbclk < 250000000)) { tmpreg |= ETH_MDIOCTL_CR_Div102; } else /* ((ahbclk >= 250000000)&&(ahbclk <= 300000000)) */ { tmpreg |= ETH_MDIOCTL_CR_Div124; } writel(tmpreg, MAC(port, mdioctl)); ... ... }
MDC 时钟配置错误,则 MAC 和 PHY 的通信不通,呈现的现象是 MAC 无法发现 PHY 设备
PHY 工作时钟
一般 PHY 的工作时钟是 25M, 一般的设计是外挂一个晶振提供时钟给 PHY 模组, AIC 不同型号芯片都对外提供几组时钟,也可以使用该时钟供给 PHY 模块工作。
该时钟 (clk-out2) 使能在 “target/soc name/board name/sys_clk.c”
中配置。如果需要可以打开
struct aic_sysclk aic_sysclk_config[] = { ... {25000000, CLK_OUT2}, ... }; void aic_board_sysclk_init(void) { uint32_t i = 0; for (i=0; i<sizeof(aic_sysclk_config)/sizeof(struct aic_sysclk); i++) { hal_clk_set_freq(aic_sysclk_config[i].clk_id, aic_sysclk_config[i].freq); } /* Enable sys clk */ hal_clk_enable_deassertrst_iter(CLK_GPIO); hal_clk_enable_deassertrst_iter(CLK_GTC); #ifdef AIC_USING_GMAC0 hal_clk_enable_deassertrst_iter(CLK_OUT2); #endif }
MDATA 时钟
MDATA 时钟 为 MAC 和 PHY 进行数据传输的时钟,对于百兆和千兆有不同的使用方式
-
百兆网络:可以是 MAC 供给 PHY, 也可以是 PHY 供给 MAC
-
千兆网络:只能是 MAC 供给 PHY,RGMII0-TXCK 端口
代码中会根据
scons --menuconfig
中的配置来决定 MAC 使用的时钟来源是内部时钟还是外部时钟static s32 syscfg_gmac_init(u32 ch) { #ifdef AIC_SYSCFG_DRV_V10 u32 cfg_reg = ch ? SYSCFG_GMAC1_CFG : SYSCFG_GMAC0_CFG; #else u32 cfg_reg = SYSCFG_GMAC0_CFG; #endif s32 cfg; cfg = syscfg_readl(cfg_reg); if (ch == 0) { #ifdef AIC_SYSCFG_DRV_V10 #ifdef AIC_DEV_GMAC0_RGMII cfg |= SYSCFG_GMAC_PHY_RGMII_1000M; #else cfg &= ~SYSCFG_GMAC_PHY_RGMII_1000M; #endif #endif #ifdef AIC_DEV_GMAC0_PHY_EXTCLK cfg |= SYSCFG_GMAC_RMII_EXTCLK_SEL; #endif #if AIC_DEV_GMAC0_TXDELAY cfg |= (AIC_DEV_GMAC0_TXDELAY << SYSCFG_GMAC_TXDLY_SEL_SHIFT); #endif #if AIC_DEV_GMAC0_RXDELAY cfg |= (AIC_DEV_GMAC0_RXDELAY << SYSCFG_GMAC_RXDLY_SEL_SHIFT); #endif } else if (ch == 1) { #ifdef AIC_SYSCFG_DRV_V10 #ifdef AIC_DEV_GMAC1_RGMII cfg |= SYSCFG_GMAC_PHY_RGMII_1000M; #else cfg &= ~SYSCFG_GMAC_PHY_RGMII_1000M; #endif #endif #ifdef AIC_DEV_GMAC1_PHY_EXTCLK cfg |= SYSCFG_GMAC_RMII_EXTCLK_SEL; #endif #if AIC_DEV_GMAC1_TXDELAY cfg |= (AIC_DEV_GMAC1_TXDELAY << SYSCFG_GMAC_TXDLY_SEL_SHIFT); #endif #if AIC_DEV_GMAC1_RXDELAY cfg |= (AIC_DEV_GMAC1_RXDELAY << SYSCFG_GMAC_RXDLY_SEL_SHIFT); #endif } syscfg_writel(cfg, cfg_reg); return 0; }