时钟
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;
}