1 // SPDX-License-Identifier: GPL-2.0
5 * This is code moved from drivers/net/dwc_eth_qos.c , which is:
6 * Copyright (c) 2016, NVIDIA CORPORATION.
10 #include <asm/cache.h>
16 #include <dm/device_compat.h>
29 #include <linux/bitfield.h>
30 #include <linux/delay.h>
32 #include "dwc_eth_qos.h"
34 /* SYSCFG registers */
35 #define SYSCFG_PMCSETR 0x04
36 #define SYSCFG_PMCCLRR 0x44
38 #define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16)
39 #define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17)
41 #define SYSCFG_PMCSETR_ETH_SELMII BIT(20)
43 #define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21)
44 #define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0x0
45 #define SYSCFG_PMCSETR_ETH_SEL_RGMII 0x1
46 #define SYSCFG_PMCSETR_ETH_SEL_RMII 0x4
48 static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
50 struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev);
52 if (!CONFIG_IS_ENABLED(CLK))
55 return clk_get_rate(&eqos->clk_master_bus);
58 static int eqos_start_clks_stm32(struct udevice *dev)
60 struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev);
63 if (!CONFIG_IS_ENABLED(CLK))
66 dev_dbg(dev, "%s:\n", __func__);
68 ret = clk_enable(&eqos->clk_master_bus);
70 dev_err(dev, "clk_enable(clk_master_bus) failed: %d\n", ret);
74 ret = clk_enable(&eqos->clk_rx);
76 dev_err(dev, "clk_enable(clk_rx) failed: %d\n", ret);
77 goto err_disable_clk_master_bus;
80 ret = clk_enable(&eqos->clk_tx);
82 dev_err(dev, "clk_enable(clk_tx) failed: %d\n", ret);
83 goto err_disable_clk_rx;
86 if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) {
87 ret = clk_enable(&eqos->clk_ck);
89 dev_err(dev, "clk_enable(clk_ck) failed: %d\n", ret);
90 goto err_disable_clk_tx;
92 eqos->clk_ck_enabled = true;
95 dev_dbg(dev, "%s: OK\n", __func__);
99 clk_disable(&eqos->clk_tx);
101 clk_disable(&eqos->clk_rx);
102 err_disable_clk_master_bus:
103 clk_disable(&eqos->clk_master_bus);
105 dev_dbg(dev, "%s: FAILED: %d\n", __func__, ret);
110 static int eqos_stop_clks_stm32(struct udevice *dev)
112 struct eqos_priv __maybe_unused *eqos = dev_get_priv(dev);
114 if (!CONFIG_IS_ENABLED(CLK))
117 dev_dbg(dev, "%s:\n", __func__);
119 clk_disable(&eqos->clk_tx);
120 clk_disable(&eqos->clk_rx);
121 clk_disable(&eqos->clk_master_bus);
123 dev_dbg(dev, "%s: OK\n", __func__);
128 static int eqos_probe_syscfg_stm32(struct udevice *dev,
129 phy_interface_t interface_type)
131 /* Ethernet 50MHz RMII clock selection. */
132 const bool eth_ref_clk_sel = dev_read_bool(dev, "st,eth-ref-clk-sel");
133 /* Gigabit Ethernet 125MHz clock selection. */
134 const bool eth_clk_sel = dev_read_bool(dev, "st,eth-clk-sel");
138 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
142 switch (interface_type) {
143 case PHY_INTERFACE_MODE_MII:
144 dev_dbg(dev, "PHY_INTERFACE_MODE_MII\n");
145 value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK,
146 SYSCFG_PMCSETR_ETH_SEL_GMII_MII);
147 value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
149 case PHY_INTERFACE_MODE_GMII:
150 dev_dbg(dev, "PHY_INTERFACE_MODE_GMII\n");
151 value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK,
152 SYSCFG_PMCSETR_ETH_SEL_GMII_MII);
154 value |= SYSCFG_PMCSETR_ETH_CLK_SEL;
156 case PHY_INTERFACE_MODE_RMII:
157 dev_dbg(dev, "PHY_INTERFACE_MODE_RMII\n");
158 value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK,
159 SYSCFG_PMCSETR_ETH_SEL_RMII);
161 value |= SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
163 case PHY_INTERFACE_MODE_RGMII:
164 case PHY_INTERFACE_MODE_RGMII_ID:
165 case PHY_INTERFACE_MODE_RGMII_RXID:
166 case PHY_INTERFACE_MODE_RGMII_TXID:
167 dev_dbg(dev, "PHY_INTERFACE_MODE_RGMII\n");
168 value = FIELD_PREP(SYSCFG_PMCSETR_ETH_SEL_MASK,
169 SYSCFG_PMCSETR_ETH_SEL_RGMII);
171 value |= SYSCFG_PMCSETR_ETH_CLK_SEL;
174 dev_dbg(dev, "Do not manage %d interface\n",
176 /* Do not manage others interfaces */
180 /* clear and set ETH configuration bits */
181 writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
182 SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
183 syscfg + SYSCFG_PMCCLRR);
184 writel(value, syscfg + SYSCFG_PMCSETR);
189 static int eqos_probe_resources_stm32(struct udevice *dev)
191 struct eqos_priv *eqos = dev_get_priv(dev);
192 phy_interface_t interface;
195 dev_dbg(dev, "%s:\n", __func__);
197 interface = eqos->config->interface(dev);
199 if (interface == PHY_INTERFACE_MODE_NA) {
200 dev_err(dev, "Invalid PHY interface\n");
204 ret = eqos_probe_syscfg_stm32(dev, interface);
208 ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
210 dev_err(dev, "clk_get_by_name(master_bus) failed: %d\n", ret);
214 ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
216 dev_err(dev, "clk_get_by_name(rx) failed: %d\n", ret);
220 ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
222 dev_err(dev, "clk_get_by_name(tx) failed: %d\n", ret);
226 /* Get ETH_CLK clocks (optional) */
227 ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
229 dev_warn(dev, "No phy clock provided %d\n", ret);
231 dev_dbg(dev, "%s: OK\n", __func__);
237 dev_dbg(dev, "%s: returns %d\n", __func__, ret);
242 static int eqos_remove_resources_stm32(struct udevice *dev)
244 dev_dbg(dev, "%s:\n", __func__);
249 static struct eqos_ops eqos_stm32_ops = {
250 .eqos_inval_desc = eqos_inval_desc_generic,
251 .eqos_flush_desc = eqos_flush_desc_generic,
252 .eqos_inval_buffer = eqos_inval_buffer_generic,
253 .eqos_flush_buffer = eqos_flush_buffer_generic,
254 .eqos_probe_resources = eqos_probe_resources_stm32,
255 .eqos_remove_resources = eqos_remove_resources_stm32,
256 .eqos_stop_resets = eqos_null_ops,
257 .eqos_start_resets = eqos_null_ops,
258 .eqos_stop_clks = eqos_stop_clks_stm32,
259 .eqos_start_clks = eqos_start_clks_stm32,
260 .eqos_calibrate_pads = eqos_null_ops,
261 .eqos_disable_calibration = eqos_null_ops,
262 .eqos_set_tx_clk_speed = eqos_null_ops,
263 .eqos_get_enetaddr = eqos_null_ops,
264 .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
267 struct eqos_config __maybe_unused eqos_stm32mp15_config = {
268 .reg_access_always_ok = false,
271 .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
272 .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
273 .axi_bus_width = EQOS_AXI_WIDTH_64,
274 .interface = dev_read_phy_mode,
275 .ops = &eqos_stm32_ops