diff options
author | Tom Rini <trini@konsulko.com> | 2023-07-21 09:57:59 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2023-07-21 09:57:59 -0400 |
commit | e7f7e2e1e22fd719a8810ba488a9451635b13d1b (patch) | |
tree | 0dda2ed98b772b44ae61b041d402f9618cd18670 /drivers/net/zynq_gem.c | |
parent | e896279ac39ebb97f23e6132bf7668a61e1cd86b (diff) | |
parent | a1190b4d6a9bf3a45038e3eba4a11de4be2b1cca (diff) |
Merge tag 'xilinx-for-v2023.10-rc1-v2' of https://source.denx.de/u-boot/custodians/u-boot-microblaze
Xilinx changes for v2023.10-rc1 v2
axi_emac:
- Change return value if RX packet is not ready
cadence_qspi:
- Enable flash reset for Versal NET
dt:
- Various DT syncups with Linux kernel
- SOM - reserved pmufw memory location
fpga:
- Add load event
mtd:
- Add missing dependency for FLASH_CFI_MTD
spi/nand:
- Minor cleanup in Xilinx drivers
versal-net:
- Prioritize boot device in boot_targets
- Wire mini ospi/qspi/emmc configurations
watchdog:
- Use new versal-wwdt property
xilinx:
- fix sparse warnings in various places ps7_init*
- add missing headers
- consolidate code around zynqmp_mmio_read/write
- switch to amd.com email
zynqmp_clk:
- Add handling for gem rx/tsu clocks
zynq_gem:
- Configure mdio clock at run time
zynq:
- Enable fdt overlay support
zynq_sdhci:
- Call dll reset only for ZynqMP SOCs
Diffstat (limited to 'drivers/net/zynq_gem.c')
-rw-r--r-- | drivers/net/zynq_gem.c | 57 |
1 files changed, 49 insertions, 8 deletions
diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 211b2c6e556..f3cdfb0275d 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -30,6 +30,7 @@ #include <asm/arch/hardware.h> #include <asm/arch/sys_proto.h> #include <dm/device_compat.h> +#include <linux/bitfield.h> #include <linux/bitops.h> #include <linux/err.h> #include <linux/errno.h> @@ -67,11 +68,6 @@ #define ZYNQ_GEM_NWCFG_FSREM 0x00020000 /* FCS removal */ #define ZYNQ_GEM_NWCFG_SGMII_ENBL 0x08000000 /* SGMII Enable */ #define ZYNQ_GEM_NWCFG_PCS_SEL 0x00000800 /* PCS select */ -#ifdef CONFIG_ARM64 -#define ZYNQ_GEM_NWCFG_MDCCLKDIV 0x00100000 /* Div pclk by 64, max 160MHz */ -#else -#define ZYNQ_GEM_NWCFG_MDCCLKDIV 0x000c0000 /* Div pclk by 48, max 120MHz */ -#endif #ifdef CONFIG_ARM64 # define ZYNQ_GEM_DBUS_WIDTH (1 << 21) /* 64 bit bus */ @@ -81,8 +77,7 @@ #define ZYNQ_GEM_NWCFG_INIT (ZYNQ_GEM_DBUS_WIDTH | \ ZYNQ_GEM_NWCFG_FDEN | \ - ZYNQ_GEM_NWCFG_FSREM | \ - ZYNQ_GEM_NWCFG_MDCCLKDIV) + ZYNQ_GEM_NWCFG_FSREM) #define ZYNQ_GEM_NWSR_MDIOIDLE_MASK 0x00000004 /* PHY management idle */ @@ -141,6 +136,18 @@ #define RXCLK_EN BIT(0) +/* GEM specific constants for CLK. */ +#define GEM_CLK_DIV8 0 +#define GEM_CLK_DIV16 1 +#define GEM_CLK_DIV32 2 +#define GEM_CLK_DIV48 3 +#define GEM_CLK_DIV64 4 +#define GEM_CLK_DIV96 5 +#define GEM_CLK_DIV128 6 +#define GEM_CLK_DIV224 7 + +#define GEM_MDC_SET(val) FIELD_PREP(GENMASK(20, 18), val) + /* Device registers */ struct zynq_gem_regs { u32 nwctrl; /* 0x0 - Network Control reg */ @@ -220,6 +227,7 @@ struct zynq_gem_priv { struct mii_dev *bus; struct clk rx_clk; struct clk tx_clk; + struct clk pclk; u32 max_speed; bool int_pcs; bool dma_64bit; @@ -352,6 +360,32 @@ static int zynq_phy_init(struct udevice *dev) return phy_config(priv->phydev); } +static u32 gem_mdc_clk_div(struct zynq_gem_priv *priv) +{ + u32 config; + unsigned long pclk_hz; + + pclk_hz = clk_get_rate(&priv->pclk); + if (pclk_hz <= 20000000) + config = GEM_MDC_SET(GEM_CLK_DIV8); + else if (pclk_hz <= 40000000) + config = GEM_MDC_SET(GEM_CLK_DIV16); + else if (pclk_hz <= 80000000) + config = GEM_MDC_SET(GEM_CLK_DIV32); + else if (pclk_hz <= 120000000) + config = GEM_MDC_SET(GEM_CLK_DIV48); + else if (pclk_hz <= 160000000) + config = GEM_MDC_SET(GEM_CLK_DIV64); + else if (pclk_hz <= 240000000) + config = GEM_MDC_SET(GEM_CLK_DIV96); + else if (pclk_hz <= 320000000) + config = GEM_MDC_SET(GEM_CLK_DIV128); + else + config = GEM_MDC_SET(GEM_CLK_DIV224); + + return config; +} + static int zynq_gem_init(struct udevice *dev) { u32 i, nwconfig; @@ -460,7 +494,8 @@ static int zynq_gem_init(struct udevice *dev) return -1; } - nwconfig = ZYNQ_GEM_NWCFG_INIT; + nwconfig = gem_mdc_clk_div(priv); + nwconfig |= ZYNQ_GEM_NWCFG_INIT; /* * Set SGMII enable PCS selection only if internal PCS/PMA @@ -828,6 +863,12 @@ static int zynq_gem_probe(struct udevice *dev) } } + ret = clk_get_by_name(dev, "pclk", &priv->pclk); + if (ret < 0) { + dev_err(dev, "failed to get pclk clock\n"); + goto err2; + } + if (IS_ENABLED(CONFIG_DM_ETH_PHY)) priv->bus = eth_phy_get_mdio_bus(dev); |