blob: cfda757133eeea81232b63778907eb325ccaf0f9 [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>
27#include <wait_bit.h>
28#include <linux/delay.h>
29
30#include "dwc_eth_qos.h"
31
32static ulong eqos_get_tick_clk_rate_stm32(struct udevice *dev)
33{
34#ifdef CONFIG_CLK
35 struct eqos_priv *eqos = dev_get_priv(dev);
36
37 return clk_get_rate(&eqos->clk_master_bus);
38#else
39 return 0;
40#endif
41}
42
43static int eqos_start_clks_stm32(struct udevice *dev)
44{
45#ifdef CONFIG_CLK
46 struct eqos_priv *eqos = dev_get_priv(dev);
47 int ret;
48
49 debug("%s(dev=%p):\n", __func__, dev);
50
51 ret = clk_enable(&eqos->clk_master_bus);
52 if (ret < 0) {
53 pr_err("clk_enable(clk_master_bus) failed: %d", ret);
54 goto err;
55 }
56
57 ret = clk_enable(&eqos->clk_rx);
58 if (ret < 0) {
59 pr_err("clk_enable(clk_rx) failed: %d", ret);
60 goto err_disable_clk_master_bus;
61 }
62
63 ret = clk_enable(&eqos->clk_tx);
64 if (ret < 0) {
65 pr_err("clk_enable(clk_tx) failed: %d", ret);
66 goto err_disable_clk_rx;
67 }
68
69 if (clk_valid(&eqos->clk_ck) && !eqos->clk_ck_enabled) {
70 ret = clk_enable(&eqos->clk_ck);
71 if (ret < 0) {
72 pr_err("clk_enable(clk_ck) failed: %d", ret);
73 goto err_disable_clk_tx;
74 }
75 eqos->clk_ck_enabled = true;
76 }
77#endif
78
79 debug("%s: OK\n", __func__);
80 return 0;
81
82#ifdef CONFIG_CLK
83err_disable_clk_tx:
84 clk_disable(&eqos->clk_tx);
85err_disable_clk_rx:
86 clk_disable(&eqos->clk_rx);
87err_disable_clk_master_bus:
88 clk_disable(&eqos->clk_master_bus);
89err:
90 debug("%s: FAILED: %d\n", __func__, ret);
91 return ret;
92#endif
93}
94
95static int eqos_stop_clks_stm32(struct udevice *dev)
96{
97#ifdef CONFIG_CLK
98 struct eqos_priv *eqos = dev_get_priv(dev);
99
100 debug("%s(dev=%p):\n", __func__, dev);
101
102 clk_disable(&eqos->clk_tx);
103 clk_disable(&eqos->clk_rx);
104 clk_disable(&eqos->clk_master_bus);
105#endif
106
107 debug("%s: OK\n", __func__);
108 return 0;
109}
110
111static int eqos_probe_resources_stm32(struct udevice *dev)
112{
113 struct eqos_priv *eqos = dev_get_priv(dev);
114 int ret;
115 phy_interface_t interface;
116
117 debug("%s(dev=%p):\n", __func__, dev);
118
119 interface = eqos->config->interface(dev);
120
121 if (interface == PHY_INTERFACE_MODE_NA) {
122 pr_err("Invalid PHY interface\n");
123 return -EINVAL;
124 }
125
126 ret = board_interface_eth_init(dev, interface);
127 if (ret)
128 return -EINVAL;
129
130 ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
131 if (ret) {
132 pr_err("clk_get_by_name(master_bus) failed: %d", ret);
133 goto err_probe;
134 }
135
136 ret = clk_get_by_name(dev, "mac-clk-rx", &eqos->clk_rx);
137 if (ret) {
138 pr_err("clk_get_by_name(rx) failed: %d", ret);
139 goto err_probe;
140 }
141
142 ret = clk_get_by_name(dev, "mac-clk-tx", &eqos->clk_tx);
143 if (ret) {
144 pr_err("clk_get_by_name(tx) failed: %d", ret);
145 goto err_probe;
146 }
147
148 /* Get ETH_CLK clocks (optional) */
149 ret = clk_get_by_name(dev, "eth-ck", &eqos->clk_ck);
150 if (ret)
151 pr_warn("No phy clock provided %d", ret);
152
153 debug("%s: OK\n", __func__);
154 return 0;
155
156err_probe:
157
158 debug("%s: returns %d\n", __func__, ret);
159 return ret;
160}
161
162static int eqos_remove_resources_stm32(struct udevice *dev)
163{
164 debug("%s(dev=%p):\n", __func__, dev);
165
166 return 0;
167}
168
169static struct eqos_ops eqos_stm32_ops = {
170 .eqos_inval_desc = eqos_inval_desc_generic,
171 .eqos_flush_desc = eqos_flush_desc_generic,
172 .eqos_inval_buffer = eqos_inval_buffer_generic,
173 .eqos_flush_buffer = eqos_flush_buffer_generic,
174 .eqos_probe_resources = eqos_probe_resources_stm32,
175 .eqos_remove_resources = eqos_remove_resources_stm32,
176 .eqos_stop_resets = eqos_null_ops,
177 .eqos_start_resets = eqos_null_ops,
178 .eqos_stop_clks = eqos_stop_clks_stm32,
179 .eqos_start_clks = eqos_start_clks_stm32,
180 .eqos_calibrate_pads = eqos_null_ops,
181 .eqos_disable_calibration = eqos_null_ops,
182 .eqos_set_tx_clk_speed = eqos_null_ops,
183 .eqos_get_enetaddr = eqos_null_ops,
184 .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_stm32
185};
186
187struct eqos_config __maybe_unused eqos_stm32_config = {
188 .reg_access_always_ok = false,
189 .mdio_wait = 10000,
190 .swr_wait = 50,
191 .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_AV,
192 .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
193 .axi_bus_width = EQOS_AXI_WIDTH_64,
194 .interface = dev_read_phy_mode,
195 .ops = &eqos_stm32_ops
196};