drivers: ethernet: xlnx_gem: Zynq-7000 support for the Xilinx GEM driver

Add support for the Xilinx Zynq-7000 SoC family to this driver. This
includes some SoC-specific register accesses when setting an updated
TX clock divider, also, the device tree binding now supports higher
MDC clock divisor values when the current target SoC is a Zynq rather
than a ZynqMP.

With regards to the use of this driver in a QEMU simulation of the
Zynq-7000, the Kconfig file is modified so that the driver is not
enabled unless QEMU networking is set to Ethernet mode.

Signed-off-by: Immo Birnbaum <Immo.Birnbaum@weidmueller.com>
This commit is contained in:
Immo Birnbaum 2021-07-15 13:10:33 +02:00 committed by Carles Cufí
commit 266875ead0
4 changed files with 84 additions and 12 deletions

View file

@ -114,11 +114,18 @@ static int eth_xlnx_gem_dev_init(const struct device *dev)
"%s invalid max./nominal link speed value %u",
dev->name, (uint32_t)dev_conf->max_link_speed);
/* MDC clock divider validity check */
/* MDC clock divider validity check, SoC dependent */
#if defined(CONFIG_SOC_XILINX_ZYNQMP)
__ASSERT(dev_conf->mdc_divider <= MDC_DIVIDER_48,
"%s invalid MDC clock divider value %u, must be in "
"range 0 to %u", dev->name, dev_conf->mdc_divider,
(uint32_t)MDC_DIVIDER_48);
#elif defined(CONFIG_SOC_SERIES_XILINX_ZYNQ7000)
__ASSERT(dev_conf->mdc_divider <= MDC_DIVIDER_224,
"%s invalid MDC clock divider value %u, must be in "
"range 0 to %u", dev->name, dev_conf->mdc_divider,
(uint32_t)MDC_DIVIDER_224);
#endif
/* AMBA AHB configuration options */
__ASSERT((dev_conf->amba_dbus_width == AMBA_AHB_DBUS_WIDTH_32BIT ||
@ -775,6 +782,7 @@ static void eth_xlnx_gem_configure_clocks(const struct device *dev)
}
}
#if defined(CONFIG_SOC_XILINX_ZYNQMP)
/*
* ZynqMP register crl_apb.GEMx_REF_CTRL:
* RX_CLKACT bit [26]
@ -808,6 +816,27 @@ static void eth_xlnx_gem_configure_clocks(const struct device *dev)
if ((tmp & ETH_XLNX_CRL_APB_WPROT_BIT) > 0) {
sys_write32(tmp, ETH_XLNX_CRL_APB_WPROT_REGISTER_ADDRESS);
}
# elif defined(CONFIG_SOC_SERIES_XILINX_ZYNQ7000)
clk_ctrl_reg = sys_read32(dev_conf->clk_ctrl_reg_address);
clk_ctrl_reg &= ~((ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK <<
ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR0_SHIFT) |
(ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK <<
ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR1_SHIFT));
clk_ctrl_reg |= ((div0 & ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK) <<
ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR0_SHIFT) |
((div1 & ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK) <<
ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR1_SHIFT);
/*
* SLCR must be unlocked prior to and locked after writing to
* the clock configuration register.
*/
sys_write32(ETH_XLNX_SLCR_UNLOCK_KEY,
ETH_XLNX_SLCR_UNLOCK_REGISTER_ADDRESS);
sys_write32(clk_ctrl_reg, dev_conf->clk_ctrl_reg_address);
sys_write32(ETH_XLNX_SLCR_LOCK_KEY,
ETH_XLNX_SLCR_LOCK_REGISTER_ADDRESS);
#endif /* CONFIG_SOC_XILINX_ZYNQMP / CONFIG_SOC_SERIES_XILINX_ZYNQ7000 */
LOG_DBG("%s set clock dividers div0/1 %u/%u for target "
"frequency %u Hz", dev->name, div0, div1, target);