blob: 7520a136ed07807f96048e123a5bc8e2a3faeb06 [file] [log] [blame]
Marek Vasut426ca622024-03-26 13:07:22 +01001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2024, Marek Vasut <marex@denx.de>
4 *
5 * This is code moved from drivers/net/dwc_eth_qos.c , which is:
6 * Copyright (c) 2016, NVIDIA CORPORATION.
7 */
8
9#include <common.h>
10#include <asm/cache.h>
11#include <asm/gpio.h>
12#include <asm/io.h>
13#include <clk.h>
14#include <cpu_func.h>
15#include <dm.h>
16#include <dm/device_compat.h>
17#include <errno.h>
18#include <eth_phy.h>
19#include <log.h>
20#include <malloc.h>
21#include <memalign.h>
22#include <miiphy.h>
23#include <net.h>
24#include <netdev.h>
25#include <phy.h>
26#include <reset.h>
Marek Vasut7595bfc2024-03-26 13:07:24 +010027#include <syscon.h>
Marek Vasut426ca622024-03-26 13:07:22 +010028#include <wait_bit.h>
29#include <linux/delay.h>
30
31#include "dwc_eth_qos.h"
32
Marek Vasut7595bfc2024-03-26 13:07:24 +010033/* SYSCFG registers */
34#define SYSCFG_PMCSETR 0x04
35#define SYSCFG_PMCCLRR 0x44
36
37#define SYSCFG_PMCSETR_ETH_CLK_SEL BIT(16)
38#define SYSCFG_PMCSETR_ETH_REF_CLK_SEL BIT(17)
39
40#define SYSCFG_PMCSETR_ETH_SELMII BIT(20)
41
42#define SYSCFG_PMCSETR_ETH_SEL_MASK GENMASK(23, 21)
43#define SYSCFG_PMCSETR_ETH_SEL_GMII_MII 0
44#define SYSCFG_PMCSETR_ETH_SEL_RGMII BIT(21)
45#define SYSCFG_PMCSETR_ETH_SEL_RMII BIT(23)
46
Marek Vasut426ca622024-03-26 13:07:22 +010047static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
48{
49#ifdef CONFIG_CLK
50 struct eqos_priv *eqos = dev_get_priv(dev);
51
52 return clk_get_rate(&eqos->clk_master_bus);
53#else
54 return 0;
55#endif
56}
57
58static int eqos_start_clks_stm32(struct udevice *dev)
59{
60#ifdef CONFIG_CLK
61 struct eqos_priv *eqos = dev_get_priv(dev);
62 int ret;
63
64 debug("%s(dev=%p):\n", __func__, dev);
65
66 ret = clk_enable(&eqos->clk_master_bus);
67 if (ret < 0) {
68 pr_err("clk_enable(clk_master_bus) failed: %d", ret);
69 goto err;
70 }
71
72 ret = clk_enable(&eqos->clk_rx);
73 if (ret < 0) {
74 pr_err("clk_enable(clk_rx) failed: %d", ret);
75 goto err_disable_clk_master_bus;
76 }
77
78 ret = clk_enable(&eqos->clk_tx);
79 if (ret < 0) {
80 pr_err("clk_enable(clk_tx) failed: %d", ret);
81 goto err_disable_clk_rx;
82 }
83
84 if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) {
85 ret = clk_enable(&eqos->clk_ck);
86 if (ret < 0) {
87 pr_err("clk_enable(clk_ck) failed: %d", ret);
88 goto err_disable_clk_tx;
89 }
90 eqos->clk_ck_enabled = true;
91 }
92#endif
93
94 debug("%s: OK\n", __func__);
95 return 0;
96
97#ifdef CONFIG_CLK
98err_disable_clk_tx:
99 clk_disable(&eqos->clk_tx);
100err_disable_clk_rx:
101 clk_disable(&eqos->clk_rx);
102err_disable_clk_master_bus:
103 clk_disable(&eqos->clk_master_bus);
104err:
105 debug("%s: FAILED: %d\n", __func__, ret);
106 return ret;
107#endif
108}
109
110static int eqos_stop_clks_stm32(struct udevice *dev)
111{
112#ifdef CONFIG_CLK
113 struct eqos_priv *eqos = dev_get_priv(dev);
114
115 debug("%s(dev=%p):\n", __func__, dev);
116
117 clk_disable(&eqos->clk_tx);
118 clk_disable(&eqos->clk_rx);
119 clk_disable(&eqos->clk_master_bus);
120#endif
121
122 debug("%s: OK\n", __func__);
123 return 0;
124}
125
Marek Vasut7595bfc2024-03-26 13:07:24 +0100126static int eqos_probe_syscfg_stm32(struct udevice *dev,
127 phy_interface_t interface_type)
128{
129 bool eth_ref_clk_sel_reg = false;
130 bool eth_clk_sel_reg = false;
131 u8 *syscfg;
132 u32 value;
133
134 /* Gigabit Ethernet 125MHz clock selection. */
135 eth_clk_sel_reg = dev_read_bool(dev, "st,eth-clk-sel");
136
137 /* Ethernet 50Mhz RMII clock selection */
138 eth_ref_clk_sel_reg = dev_read_bool(dev, "st,eth-ref-clk-sel");
139
140 syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG);
141 if (!syscfg)
142 return -ENODEV;
143
144 switch (interface_type) {
145 case PHY_INTERFACE_MODE_MII:
146 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
147 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
148 log_debug("PHY_INTERFACE_MODE_MII\n");
149 break;
150 case PHY_INTERFACE_MODE_GMII:
151 if (eth_clk_sel_reg)
152 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII |
153 SYSCFG_PMCSETR_ETH_CLK_SEL;
154 else
155 value = SYSCFG_PMCSETR_ETH_SEL_GMII_MII;
156 log_debug("PHY_INTERFACE_MODE_GMII\n");
157 break;
158 case PHY_INTERFACE_MODE_RMII:
159 if (eth_ref_clk_sel_reg)
160 value = SYSCFG_PMCSETR_ETH_SEL_RMII |
161 SYSCFG_PMCSETR_ETH_REF_CLK_SEL;
162 else
163 value = SYSCFG_PMCSETR_ETH_SEL_RMII;
164 log_debug("PHY_INTERFACE_MODE_RMII\n");
165 break;
166 case PHY_INTERFACE_MODE_RGMII:
167 case PHY_INTERFACE_MODE_RGMII_ID:
168 case PHY_INTERFACE_MODE_RGMII_RXID:
169 case PHY_INTERFACE_MODE_RGMII_TXID:
170 if (eth_clk_sel_reg)
171 value = SYSCFG_PMCSETR_ETH_SEL_RGMII |
172 SYSCFG_PMCSETR_ETH_CLK_SEL;
173 else
174 value = SYSCFG_PMCSETR_ETH_SEL_RGMII;
175 log_debug("PHY_INTERFACE_MODE_RGMII\n");
176 break;
177 default:
178 log_debug("Do not manage %d interface\n",
179 interface_type);
180 /* Do not manage others interfaces */
181 return -EINVAL;
182 }
183
184 /* clear and set ETH configuration bits */
185 writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII |
186 SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL,
187 syscfg + SYSCFG_PMCCLRR);
188 writel(value, syscfg + SYSCFG_PMCSETR);
189
190 return 0;
191}
192
Marek Vasut426ca622024-03-26 13:07:22 +0100193static int eqos_probe_resources_stm32(struct udevice *dev)
194{
195 struct eqos_priv *eqos = dev_get_priv(dev);
Marek Vasut426ca622024-03-26 13:07:22 +0100196 phy_interface_t interface;
Marek Vasut7595bfc2024-03-26 13:07:24 +0100197 int ret;
Marek Vasut426ca622024-03-26 13:07:22 +0100198
199 debug("%s(dev=%p):\n", __func__, dev);
200
201 interface = eqos->config->interface(dev);
202
203 if (interface == PHY_INTERFACE_MODE_NA) {
204 pr_err("Invalid PHY interface\n");
205 return -EINVAL;
206 }
207
Marek Vasut7595bfc2024-03-26 13:07:24 +0100208 ret = eqos_probe_syscfg_stm32(dev, interface);
Marek Vasut426ca622024-03-26 13:07:22 +0100209 if (ret)
210 return -EINVAL;
211
212 ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
213 if (ret) {
214 pr_err("clk_get_by_name(master_bus) failed: %d", ret);
215 goto err_probe;
216 }
217
218 ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
219 if (ret) {
220 pr_err("clk_get_by_name(rx) failed: %d", ret);
221 goto err_probe;
222 }
223
224 ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
225 if (ret) {
226 pr_err("clk_get_by_name(tx) failed: %d", ret);
227 goto err_probe;
228 }
229
230 /* Get ETH_CLK clocks (optional) */
231 ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
232 if (ret)
233 pr_warn("No phy clock provided %d", ret);
234
235 debug("%s: OK\n", __func__);
236 return 0;
237
238err_probe:
239
240 debug("%s: returns %d\n", __func__, ret);
241 return ret;
242}
243
244static int eqos_remove_resources_stm32(struct udevice *dev)
245{
246 debug("%s(dev=%p):\n", __func__, dev);
247
248 return 0;
249}
250
251static struct eqos_ops eqos_stm32_ops = {
252 .eqos_inval_desc = eqos_inval_desc_generic,
253 .eqos_flush_desc = eqos_flush_desc_generic,
254 .eqos_inval_buffer = eqos_inval_buffer_generic,
255 .eqos_flush_buffer = eqos_flush_buffer_generic,
256 .eqos_probe_resources = eqos_probe_resources_stm32,
257 .eqos_remove_resources = eqos_remove_resources_stm32,
258 .eqos_stop_resets = eqos_null_ops,
259 .eqos_start_resets = eqos_null_ops,
260 .eqos_stop_clks = eqos_stop_clks_stm32,
261 .eqos_start_clks = eqos_start_clks_stm32,
262 .eqos_calibrate_pads = eqos_null_ops,
263 .eqos_disable_calibration = eqos_null_ops,
264 .eqos_set_tx_clk_speed = eqos_null_ops,
265 .eqos_get_enetaddr = eqos_null_ops,
266 .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
267};
268
Marek Vasut944ba372024-03-26 13:07:23 +0100269struct eqos_config __maybe_unused eqos_stm32mp15_config = {
Marek Vasut426ca622024-03-26 13:07:22 +0100270 .reg_access_always_ok = false,
271 .mdio_wait = 10000,
272 .swr_wait = 50,
273 .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
274 .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
275 .axi_bus_width = EQOS_AXI_WIDTH_64,
276 .interface = dev_read_phy_mode,
277 .ops = &eqos_stm32_ops
278};