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:
parent
f668474e4d
commit
266875ead0
4 changed files with 84 additions and 12 deletions
|
@ -11,7 +11,8 @@ DT_COMPAT_XLNX_GEM := xlnx,gem
|
||||||
menuconfig ETH_XLNX_GEM
|
menuconfig ETH_XLNX_GEM
|
||||||
bool "Xilinx GEM Ethernet driver"
|
bool "Xilinx GEM Ethernet driver"
|
||||||
default $(dt_compat_enabled,$(DT_COMPAT_XLNX_GEM))
|
default $(dt_compat_enabled,$(DT_COMPAT_XLNX_GEM))
|
||||||
depends on SOC_XILINX_ZYNQMP_RPU
|
depends on SOC_XILINX_ZYNQMP_RPU || SOC_SERIES_XILINX_ZYNQ7000
|
||||||
|
depends on !QEMU_TARGET || (QEMU_TARGET && NET_QEMU_ETHERNET)
|
||||||
help
|
help
|
||||||
Enable Xilinx GEM Ethernet driver.
|
Enable Xilinx GEM Ethernet driver.
|
||||||
|
|
||||||
|
|
|
@ -114,11 +114,18 @@ static int eth_xlnx_gem_dev_init(const struct device *dev)
|
||||||
"%s invalid max./nominal link speed value %u",
|
"%s invalid max./nominal link speed value %u",
|
||||||
dev->name, (uint32_t)dev_conf->max_link_speed);
|
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,
|
__ASSERT(dev_conf->mdc_divider <= MDC_DIVIDER_48,
|
||||||
"%s invalid MDC clock divider value %u, must be in "
|
"%s invalid MDC clock divider value %u, must be in "
|
||||||
"range 0 to %u", dev->name, dev_conf->mdc_divider,
|
"range 0 to %u", dev->name, dev_conf->mdc_divider,
|
||||||
(uint32_t)MDC_DIVIDER_48);
|
(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 */
|
/* AMBA AHB configuration options */
|
||||||
__ASSERT((dev_conf->amba_dbus_width == AMBA_AHB_DBUS_WIDTH_32BIT ||
|
__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:
|
* ZynqMP register crl_apb.GEMx_REF_CTRL:
|
||||||
* RX_CLKACT bit [26]
|
* 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) {
|
if ((tmp & ETH_XLNX_CRL_APB_WPROT_BIT) > 0) {
|
||||||
sys_write32(tmp, ETH_XLNX_CRL_APB_WPROT_REGISTER_ADDRESS);
|
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 "
|
LOG_DBG("%s set clock dividers div0/1 %u/%u for target "
|
||||||
"frequency %u Hz", dev->name, div0, div1, target);
|
"frequency %u Hz", dev->name, div0, div1, target);
|
||||||
|
|
|
@ -110,8 +110,30 @@
|
||||||
#define ETH_XLNX_GEM_CKSUM_NOT_TCP_OR_UDP_ERROR 0x00000006
|
#define ETH_XLNX_GEM_CKSUM_NOT_TCP_OR_UDP_ERROR 0x00000006
|
||||||
#define ETH_XLNX_GEM_CKSUM_PREMATURE_END_ERROR 0x00000007
|
#define ETH_XLNX_GEM_CKSUM_PREMATURE_END_ERROR 0x00000007
|
||||||
|
|
||||||
|
#if defined(CONFIG_SOC_SERIES_XILINX_ZYNQ7000)
|
||||||
/*
|
/*
|
||||||
* TX clock configuration: comp.
|
* Zynq-7000 TX clock configuration:
|
||||||
|
*
|
||||||
|
* SLCR unlock & lock registers, magic words:
|
||||||
|
* comp. Zynq-7000 TRM, chapter B.28, registers SLCR_LOCK and SLCR_UNLOCK,
|
||||||
|
* p. 1576f.
|
||||||
|
*
|
||||||
|
* GEMx_CLK_CTRL (SLCR) registers:
|
||||||
|
* [25 .. 20] Reference clock divisor 1
|
||||||
|
* [13 .. 08] Reference clock divisor 0
|
||||||
|
* [00] Clock active bit
|
||||||
|
*/
|
||||||
|
#define ETH_XLNX_SLCR_LOCK_REGISTER_ADDRESS 0xF8000004
|
||||||
|
#define ETH_XLNX_SLCR_UNLOCK_REGISTER_ADDRESS 0xF8000008
|
||||||
|
#define ETH_XLNX_SLCR_LOCK_KEY 0x767B
|
||||||
|
#define ETH_XLNX_SLCR_UNLOCK_KEY 0xDF0D
|
||||||
|
#define ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR_MASK 0x0000003F
|
||||||
|
#define ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR1_SHIFT 20
|
||||||
|
#define ETH_XLNX_SLCR_GEMX_CLK_CTRL_DIVISOR0_SHIFT 8
|
||||||
|
#define ETH_XLNX_CRL_APB_GEMX_REF_CTRL_CLKACT_BIT 0x02000000
|
||||||
|
#elif defined(CONFIG_SOC_XILINX_ZYNQMP)
|
||||||
|
/*
|
||||||
|
* UltraScale TX clock configuration: comp.
|
||||||
* https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
|
* https://www.xilinx.com/html_docs/registers/ug1087/ug1087-zynq-ultrascale-registers.html
|
||||||
*
|
*
|
||||||
* CRL_WPROT (CRL_APB) register:
|
* CRL_WPROT (CRL_APB) register:
|
||||||
|
@ -130,6 +152,7 @@
|
||||||
#define ETH_XLNX_CRL_APB_GEMX_REF_CTRL_DIVISOR0_SHIFT 8
|
#define ETH_XLNX_CRL_APB_GEMX_REF_CTRL_DIVISOR0_SHIFT 8
|
||||||
#define ETH_XLNX_CRL_APB_GEMX_REF_CTRL_RX_CLKACT_BIT 0x04000000
|
#define ETH_XLNX_CRL_APB_GEMX_REF_CTRL_RX_CLKACT_BIT 0x04000000
|
||||||
#define ETH_XLNX_CRL_APB_GEMX_REF_CTRL_CLKACT_BIT 0x02000000
|
#define ETH_XLNX_CRL_APB_GEMX_REF_CTRL_CLKACT_BIT 0x02000000
|
||||||
|
#endif /* CONFIG_SOC_SERIES_XILINX_ZYNQ7000 || CONFIG_SOC_XILINX_ZYNQMP */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register offsets within the respective GEM's address space:
|
* Register offsets within the respective GEM's address space:
|
||||||
|
@ -495,9 +518,15 @@ struct eth_xlnx_dma_area_gem##port {\
|
||||||
};
|
};
|
||||||
|
|
||||||
/* DMA memory area instantiation macro */
|
/* DMA memory area instantiation macro */
|
||||||
|
#ifdef CONFIG_SOC_SERIES_XILINX_ZYNQ7000
|
||||||
#define ETH_XLNX_GEM_DMA_AREA_INST(port) \
|
#define ETH_XLNX_GEM_DMA_AREA_INST(port) \
|
||||||
static struct eth_xlnx_dma_area_gem##port eth_xlnx_gem##port##_dma_area \
|
static struct eth_xlnx_dma_area_gem##port eth_xlnx_gem##port##_dma_area\
|
||||||
|
__ocm_bss_section __aligned(4096);
|
||||||
|
#else
|
||||||
|
#define ETH_XLNX_GEM_DMA_AREA_INST(port) \
|
||||||
|
static struct eth_xlnx_dma_area_gem##port eth_xlnx_gem##port##_dma_area\
|
||||||
__aligned(4096);
|
__aligned(4096);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Interrupt configuration function macro */
|
/* Interrupt configuration function macro */
|
||||||
#define ETH_XLNX_GEM_CONFIG_IRQ_FUNC(port) \
|
#define ETH_XLNX_GEM_CONFIG_IRQ_FUNC(port) \
|
||||||
|
@ -564,16 +593,23 @@ enum eth_xlnx_amba_dbus_width {
|
||||||
* @brief MDC clock divider configuration enumeration type.
|
* @brief MDC clock divider configuration enumeration type.
|
||||||
*
|
*
|
||||||
* Enumeration type containing the supported clock divider values
|
* Enumeration type containing the supported clock divider values
|
||||||
* used to generate the MDIO interface clock (MDC) from the ZynqMP's
|
* used to generate the MDIO interface clock (MDC) from either the
|
||||||
* LPD LSBUS clock. This is a configuration item in the controller's
|
* cpu_1x clock (Zynq-7000) or the LPD LSBUS clock (UltraScale).
|
||||||
* net_cfg register.
|
* This is a configuration item in the controller's net_cfg register.
|
||||||
*/
|
*/
|
||||||
enum eth_xlnx_mdc_clock_divider {
|
enum eth_xlnx_mdc_clock_divider {
|
||||||
/* The values of this enum are consecutively numbered */
|
/* The values of this enum are consecutively numbered */
|
||||||
MDC_DIVIDER_8 = 0,
|
MDC_DIVIDER_8 = 0,
|
||||||
MDC_DIVIDER_16,
|
MDC_DIVIDER_16,
|
||||||
MDC_DIVIDER_32,
|
MDC_DIVIDER_32,
|
||||||
MDC_DIVIDER_48
|
MDC_DIVIDER_48,
|
||||||
|
#ifdef CONFIG_SOC_SERIES_XILINX_ZYNQ7000
|
||||||
|
/* Dividers > 48 are only available in the Zynq-7000 */
|
||||||
|
MDC_DIVIDER_64,
|
||||||
|
MDC_DIVIDER_96,
|
||||||
|
MDC_DIVIDER_128,
|
||||||
|
MDC_DIVIDER_224
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,14 +10,20 @@
|
||||||
#define XLNX_GEM_PHY_AUTO_DETECT 0
|
#define XLNX_GEM_PHY_AUTO_DETECT 0
|
||||||
|
|
||||||
/* MDC divider values */
|
/* MDC divider values */
|
||||||
#define XLNX_GEM_MDC_DIVIDER_8 0 /* LPD_LSBUS_CLK < 20 MHz */
|
/* The following values are supported by both the Zynq-7000 and the ZynqMP */
|
||||||
#define XLNX_GEM_MDC_DIVIDER_16 1 /* LPD_LSBUS_CLK 20 - 40 MHz */
|
#define XLNX_GEM_MDC_DIVIDER_8 0 /* cpu_1x or LPD_LSBUS_CLK < 20 MHz */
|
||||||
#define XLNX_GEM_MDC_DIVIDER_32 2 /* LPD_LSBUS_CLK 40 - 80 MHz */
|
#define XLNX_GEM_MDC_DIVIDER_16 1 /* cpu_1x or LPD_LSBUS_CLK 20 - 40 MHz */
|
||||||
|
#define XLNX_GEM_MDC_DIVIDER_32 2 /* cpu_1x or LPD_LSBUS_CLK 40 - 80 MHz */
|
||||||
/*
|
/*
|
||||||
* According to the ZynqMP's gem.network_config register documentation,
|
* According to the ZynqMP's gem.network_config register documentation,
|
||||||
* divider /32 is to be used for a 100 MHz LPD LSBUS clock.
|
* divider /32 is to be used for a 100 MHz LPD LSBUS clock.
|
||||||
*/
|
*/
|
||||||
#define XLNX_GEM_MDC_DIVIDER_48 3 /* LPD_LSBUS_CLK 80 - 120 MHz */
|
/* The following values are supported by the Zynq-7000 only */
|
||||||
|
#define XLNX_GEM_MDC_DIVIDER_48 3 /* cpu_1x 80 - 120 MHz */
|
||||||
|
#define XLNX_GEM_MDC_DIVIDER_64 4 /* cpu_1x 120 - 160 MHz */
|
||||||
|
#define XLNX_GEM_MDC_DIVIDER_96 5 /* cpu_1x 160 - 240 MHz */
|
||||||
|
#define XLNX_GEM_MDC_DIVIDER_128 6 /* cpu_1x 240 - 320 MHz */
|
||||||
|
#define XLNX_GEM_MDC_DIVIDER_224 7 /* cpu_1x 320 - 540 MHz */
|
||||||
|
|
||||||
/* Link speed values */
|
/* Link speed values */
|
||||||
#define XLNX_GEM_LINK_SPEED_10MBIT 1
|
#define XLNX_GEM_LINK_SPEED_10MBIT 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue