blob: 9d57e8db76418d79896645b74c86efbcec6e83f2 [file] [log] [blame]
Jonas Karlman098ee4f2023-10-01 19:17:19 +00001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright Contributors to the U-Boot project.
4 *
5 * rk_gmac_ops ported from linux drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
6 *
7 * Ported code is intentionally left as close as possible with linux counter
8 * part in order to simplify future porting of fixes and support for other SoCs.
9 */
10
11#include <common.h>
12#include <clk.h>
13#include <dm.h>
14#include <dm/device_compat.h>
15#include <net.h>
16#include <phy.h>
17#include <regmap.h>
18#include <reset.h>
19#include <syscon.h>
20#include <asm/gpio.h>
21#include <linux/delay.h>
22
23#include "dwc_eth_qos.h"
24
25struct rk_gmac_ops {
26 const char *compatible;
27 int (*set_to_rgmii)(struct udevice *dev,
28 int tx_delay, int rx_delay);
29 int (*set_to_rmii)(struct udevice *dev);
30 int (*set_gmac_speed)(struct udevice *dev);
31 u32 regs[3];
32};
33
34struct rockchip_platform_data {
35 struct reset_ctl_bulk resets;
36 const struct rk_gmac_ops *ops;
37 int id;
38 struct regmap *grf;
39};
40
41#define HIWORD_UPDATE(val, mask, shift) \
42 ((val) << (shift) | (mask) << ((shift) + 16))
43
44#define GRF_BIT(nr) (BIT(nr) | BIT((nr) + 16))
45#define GRF_CLR_BIT(nr) (BIT((nr) + 16))
46
47#define RK3568_GRF_GMAC0_CON0 0x0380
48#define RK3568_GRF_GMAC0_CON1 0x0384
49#define RK3568_GRF_GMAC1_CON0 0x0388
50#define RK3568_GRF_GMAC1_CON1 0x038c
51
52/* RK3568_GRF_GMAC0_CON1 && RK3568_GRF_GMAC1_CON1 */
53#define RK3568_GMAC_PHY_INTF_SEL_RGMII \
54 (GRF_BIT(4) | GRF_CLR_BIT(5) | GRF_CLR_BIT(6))
55#define RK3568_GMAC_PHY_INTF_SEL_RMII \
56 (GRF_CLR_BIT(4) | GRF_CLR_BIT(5) | GRF_BIT(6))
57#define RK3568_GMAC_FLOW_CTRL GRF_BIT(3)
58#define RK3568_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(3)
59#define RK3568_GMAC_RXCLK_DLY_ENABLE GRF_BIT(1)
60#define RK3568_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(1)
61#define RK3568_GMAC_TXCLK_DLY_ENABLE GRF_BIT(0)
62#define RK3568_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(0)
63
64/* RK3568_GRF_GMAC0_CON0 && RK3568_GRF_GMAC1_CON0 */
65#define RK3568_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 8)
66#define RK3568_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0)
67
68static int rk3568_set_to_rgmii(struct udevice *dev,
69 int tx_delay, int rx_delay)
70{
71 struct eth_pdata *pdata = dev_get_plat(dev);
72 struct rockchip_platform_data *data = pdata->priv_pdata;
73 u32 con0, con1;
74
75 con0 = (data->id == 1) ? RK3568_GRF_GMAC1_CON0 :
76 RK3568_GRF_GMAC0_CON0;
77 con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
78 RK3568_GRF_GMAC0_CON1;
79
80 regmap_write(data->grf, con0,
81 RK3568_GMAC_CLK_RX_DL_CFG(rx_delay) |
82 RK3568_GMAC_CLK_TX_DL_CFG(tx_delay));
83
84 regmap_write(data->grf, con1,
85 RK3568_GMAC_PHY_INTF_SEL_RGMII |
86 RK3568_GMAC_RXCLK_DLY_ENABLE |
87 RK3568_GMAC_TXCLK_DLY_ENABLE);
88
89 return 0;
90}
91
92static int rk3568_set_to_rmii(struct udevice *dev)
93{
94 struct eth_pdata *pdata = dev_get_plat(dev);
95 struct rockchip_platform_data *data = pdata->priv_pdata;
96 u32 con1;
97
98 con1 = (data->id == 1) ? RK3568_GRF_GMAC1_CON1 :
99 RK3568_GRF_GMAC0_CON1;
100 regmap_write(data->grf, con1, RK3568_GMAC_PHY_INTF_SEL_RMII);
101
102 return 0;
103}
104
105static int rk3568_set_gmac_speed(struct udevice *dev)
106{
107 struct eqos_priv *eqos = dev_get_priv(dev);
108 ulong rate;
109 int ret;
110
111 switch (eqos->phy->speed) {
112 case SPEED_10:
113 rate = 2500000;
114 break;
115 case SPEED_100:
116 rate = 25000000;
117 break;
118 case SPEED_1000:
119 rate = 125000000;
120 break;
121 default:
122 return -EINVAL;
123 }
124
125 ret = clk_set_rate(&eqos->clk_tx, rate);
126 if (ret < 0)
127 return ret;
128
129 return 0;
130}
131
132static const struct rk_gmac_ops rk_gmac_ops[] = {
133 {
134 .compatible = "rockchip,rk3568-gmac",
135 .set_to_rgmii = rk3568_set_to_rgmii,
136 .set_to_rmii = rk3568_set_to_rmii,
137 .set_gmac_speed = rk3568_set_gmac_speed,
138 .regs = {
139 0xfe2a0000, /* gmac0 */
140 0xfe010000, /* gmac1 */
141 0x0, /* sentinel */
142 },
143 },
144 { }
145};
146
147static const struct rk_gmac_ops *get_rk_gmac_ops(struct udevice *dev)
148{
149 const struct rk_gmac_ops *ops = rk_gmac_ops;
150
151 while (ops->compatible) {
152 if (device_is_compatible(dev, ops->compatible))
153 return ops;
154 ops++;
155 }
156
157 return NULL;
158}
159
160static int eqos_probe_resources_rk(struct udevice *dev)
161{
162 struct eqos_priv *eqos = dev_get_priv(dev);
163 struct eth_pdata *pdata = dev_get_plat(dev);
164 struct rockchip_platform_data *data;
165 int reset_flags = GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE;
166 int ret;
167
168 data = calloc(1, sizeof(struct rockchip_platform_data));
169 if (!data)
170 return -ENOMEM;
171
172 data->ops = get_rk_gmac_ops(dev);
173 if (!data->ops) {
174 ret = -EINVAL;
175 goto err_free;
176 }
177
178 for (int i = 0; data->ops->regs[i]; i++) {
179 if (data->ops->regs[i] == (u32)eqos->regs) {
180 data->id = i;
181 break;
182 }
183 }
184
185 pdata->priv_pdata = data;
186 pdata->phy_interface = eqos->config->interface(dev);
187 pdata->max_speed = eqos->max_speed;
188
189 if (pdata->phy_interface == PHY_INTERFACE_MODE_NA) {
190 pr_err("Invalid PHY interface\n");
191 ret = -EINVAL;
192 goto err_free;
193 }
194
195 data->grf = syscon_regmap_lookup_by_phandle(dev, "rockchip,grf");
196 if (IS_ERR(data->grf)) {
197 dev_err(dev, "Missing rockchip,grf property\n");
198 ret = -EINVAL;
199 goto err_free;
200 }
201
202 ret = reset_get_bulk(dev, &data->resets);
203 if (ret < 0)
204 goto err_free;
205
206 reset_assert_bulk(&data->resets);
207
208 ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
209 if (ret) {
210 dev_dbg(dev, "clk_get_by_name(stmmaceth) failed: %d", ret);
211 goto err_release_resets;
212 }
213
214 ret = clk_get_by_name(dev, "clk_mac_speed", &eqos->clk_tx);
215 if (ret) {
216 dev_dbg(dev, "clk_get_by_name(clk_mac_speed) failed: %d", ret);
217 goto err_free_clk_master_bus;
218 }
219
220 /* snps,reset props are deprecated, do bare minimum to support them */
221 if (dev_read_bool(dev, "snps,reset-active-low"))
222 reset_flags |= GPIOD_ACTIVE_LOW;
223
224 dev_read_u32_array(dev, "snps,reset-delays-us", eqos->reset_delays, 3);
225
226 gpio_request_by_name(dev, "snps,reset-gpio", 0,
227 &eqos->phy_reset_gpio, reset_flags);
228
229 return 0;
230
231err_free_clk_master_bus:
232 clk_free(&eqos->clk_master_bus);
233err_release_resets:
234 reset_release_bulk(&data->resets);
235err_free:
236 free(data);
237
238 return ret;
239}
240
241static int eqos_remove_resources_rk(struct udevice *dev)
242{
243 struct eqos_priv *eqos = dev_get_priv(dev);
244 struct eth_pdata *pdata = dev_get_plat(dev);
245 struct rockchip_platform_data *data = pdata->priv_pdata;
246
247 if (dm_gpio_is_valid(&eqos->phy_reset_gpio))
248 dm_gpio_free(dev, &eqos->phy_reset_gpio);
249
250 clk_free(&eqos->clk_tx);
251 clk_free(&eqos->clk_master_bus);
252 reset_release_bulk(&data->resets);
253 free(data);
254
255 return 0;
256}
257
258static int eqos_stop_resets_rk(struct udevice *dev)
259{
260 struct eth_pdata *pdata = dev_get_plat(dev);
261 struct rockchip_platform_data *data = pdata->priv_pdata;
262
263 return reset_assert_bulk(&data->resets);
264}
265
266static int eqos_start_resets_rk(struct udevice *dev)
267{
268 struct eth_pdata *pdata = dev_get_plat(dev);
269 struct rockchip_platform_data *data = pdata->priv_pdata;
270
271 return reset_deassert_bulk(&data->resets);
272}
273
274static int eqos_stop_clks_rk(struct udevice *dev)
275{
276 return 0;
277}
278
279static int eqos_start_clks_rk(struct udevice *dev)
280{
281 struct eqos_priv *eqos = dev_get_priv(dev);
282 struct eth_pdata *pdata = dev_get_plat(dev);
283 struct rockchip_platform_data *data = pdata->priv_pdata;
284 int tx_delay, rx_delay, ret;
285
286 if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) {
287 udelay(eqos->reset_delays[1]);
288
289 ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0);
290 if (ret < 0)
291 return ret;
292
293 udelay(eqos->reset_delays[2]);
294 }
295
296 tx_delay = dev_read_u32_default(dev, "tx_delay", 0x30);
297 rx_delay = dev_read_u32_default(dev, "rx_delay", 0x10);
298
299 switch (pdata->phy_interface) {
300 case PHY_INTERFACE_MODE_RGMII:
301 return data->ops->set_to_rgmii(dev, tx_delay, rx_delay);
302 case PHY_INTERFACE_MODE_RGMII_ID:
303 return data->ops->set_to_rgmii(dev, 0, 0);
304 case PHY_INTERFACE_MODE_RGMII_RXID:
305 return data->ops->set_to_rgmii(dev, tx_delay, 0);
306 case PHY_INTERFACE_MODE_RGMII_TXID:
307 return data->ops->set_to_rgmii(dev, 0, rx_delay);
308 case PHY_INTERFACE_MODE_RMII:
309 return data->ops->set_to_rmii(dev);
310 }
311
312 return -EINVAL;
313}
314
315static int eqos_set_tx_clk_speed_rk(struct udevice *dev)
316{
317 struct eth_pdata *pdata = dev_get_plat(dev);
318 struct rockchip_platform_data *data = pdata->priv_pdata;
319
320 return data->ops->set_gmac_speed(dev);
321}
322
323static ulong eqos_get_tick_clk_rate_rk(struct udevice *dev)
324{
325 struct eqos_priv *eqos = dev_get_priv(dev);
326
327 return clk_get_rate(&eqos->clk_master_bus);
328}
329
330static struct eqos_ops eqos_rockchip_ops = {
331 .eqos_inval_desc = eqos_inval_desc_generic,
332 .eqos_flush_desc = eqos_flush_desc_generic,
333 .eqos_inval_buffer = eqos_inval_buffer_generic,
334 .eqos_flush_buffer = eqos_flush_buffer_generic,
335 .eqos_probe_resources = eqos_probe_resources_rk,
336 .eqos_remove_resources = eqos_remove_resources_rk,
337 .eqos_stop_resets = eqos_stop_resets_rk,
338 .eqos_start_resets = eqos_start_resets_rk,
339 .eqos_stop_clks = eqos_stop_clks_rk,
340 .eqos_start_clks = eqos_start_clks_rk,
341 .eqos_calibrate_pads = eqos_null_ops,
342 .eqos_disable_calibration = eqos_null_ops,
343 .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_rk,
344 .eqos_get_enetaddr = eqos_null_ops,
345 .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_rk,
346};
347
348struct eqos_config eqos_rockchip_config = {
349 .reg_access_always_ok = false,
350 .mdio_wait = 10,
351 .swr_wait = 50,
352 .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
353 .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_100_150,
354 .axi_bus_width = EQOS_AXI_WIDTH_64,
355 .interface = dev_read_phy_mode,
356 .ops = &eqos_rockchip_ops,
357};