e3f55dd981738244cef7ed01ec72cbfef899e0e2
[pandora-u-boot.git] / drivers / net / dwc_eth_qos_imx.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2022 NXP
4  */
5
6 #include <common.h>
7 #include <clk.h>
8 #include <cpu_func.h>
9 #include <dm.h>
10 #include <dm/device_compat.h>
11 #include <errno.h>
12 #include <eth_phy.h>
13 #include <log.h>
14 #include <malloc.h>
15 #include <memalign.h>
16 #include <miiphy.h>
17 #include <net.h>
18 #include <netdev.h>
19 #include <phy.h>
20 #include <reset.h>
21 #include <wait_bit.h>
22 #include <asm/arch/clock.h>
23 #include <asm/cache.h>
24 #include <asm/gpio.h>
25 #include <asm/io.h>
26 #include <asm/mach-imx/sys_proto.h>
27 #include <linux/delay.h>
28
29 #include "dwc_eth_qos.h"
30
31 __weak u32 imx_get_eqos_csr_clk(void)
32 {
33         return 100 * 1000000;
34 }
35
36 static ulong eqos_get_tick_clk_rate_imx(struct udevice *dev)
37 {
38         struct eqos_priv *eqos = dev_get_priv(dev);
39
40         return clk_get_rate(&eqos->clk_master_bus);
41 }
42
43 static int eqos_probe_resources_imx(struct udevice *dev)
44 {
45         struct eqos_priv *eqos = dev_get_priv(dev);
46         phy_interface_t interface;
47         int ret;
48
49         debug("%s(dev=%p):\n", __func__, dev);
50
51         interface = eqos->config->interface(dev);
52
53         if (interface == PHY_INTERFACE_MODE_NA) {
54                 pr_err("Invalid PHY interface\n");
55                 return -EINVAL;
56         }
57
58         ret = board_interface_eth_init(dev, interface);
59         if (ret)
60                 return -EINVAL;
61
62         eqos->max_speed = dev_read_u32_default(dev, "max-speed", 0);
63
64         ret = clk_get_by_name(dev, "stmmaceth", &eqos->clk_master_bus);
65         if (ret) {
66                 dev_dbg(dev, "clk_get_by_name(master_bus) failed: %d", ret);
67                 goto err_probe;
68         }
69
70         ret = clk_get_by_name(dev, "ptp_ref", &eqos->clk_ptp_ref);
71         if (ret) {
72                 dev_dbg(dev, "clk_get_by_name(ptp_ref) failed: %d", ret);
73                 goto err_free_clk_master_bus;
74         }
75
76         ret = clk_get_by_name(dev, "tx", &eqos->clk_tx);
77         if (ret) {
78                 dev_dbg(dev, "clk_get_by_name(tx) failed: %d", ret);
79                 goto err_free_clk_ptp_ref;
80         }
81
82         ret = clk_get_by_name(dev, "pclk", &eqos->clk_ck);
83         if (ret) {
84                 dev_dbg(dev, "clk_get_by_name(pclk) failed: %d", ret);
85                 goto err_free_clk_tx;
86         }
87
88         debug("%s: OK\n", __func__);
89         return 0;
90
91 err_free_clk_tx:
92         clk_free(&eqos->clk_tx);
93 err_free_clk_ptp_ref:
94         clk_free(&eqos->clk_ptp_ref);
95 err_free_clk_master_bus:
96         clk_free(&eqos->clk_master_bus);
97 err_probe:
98
99         debug("%s: returns %d\n", __func__, ret);
100         return ret;
101 }
102
103 static int eqos_remove_resources_imx(struct udevice *dev)
104 {
105         struct eqos_priv *eqos = dev_get_priv(dev);
106
107         debug("%s(dev=%p):\n", __func__, dev);
108
109         clk_free(&eqos->clk_ck);
110         clk_free(&eqos->clk_tx);
111         clk_free(&eqos->clk_ptp_ref);
112         clk_free(&eqos->clk_master_bus);
113
114         debug("%s: OK\n", __func__);
115         return 0;
116 }
117
118 static int eqos_start_clks_imx(struct udevice *dev)
119 {
120         struct eqos_priv *eqos = dev_get_priv(dev);
121         int ret;
122
123         debug("%s(dev=%p):\n", __func__, dev);
124
125         ret = clk_enable(&eqos->clk_master_bus);
126         if (ret < 0) {
127                 dev_dbg(dev, "clk_enable(clk_master_bus) failed: %d", ret);
128                 goto err;
129         }
130
131         ret = clk_enable(&eqos->clk_ptp_ref);
132         if (ret < 0) {
133                 dev_dbg(dev, "clk_enable(clk_ptp_ref) failed: %d", ret);
134                 goto err_disable_clk_master_bus;
135         }
136
137         ret = clk_enable(&eqos->clk_tx);
138         if (ret < 0) {
139                 dev_dbg(dev, "clk_enable(clk_tx) failed: %d", ret);
140                 goto err_disable_clk_ptp_ref;
141         }
142
143         ret = clk_enable(&eqos->clk_ck);
144         if (ret < 0) {
145                 dev_dbg(dev, "clk_enable(clk_ck) failed: %d", ret);
146                 goto err_disable_clk_tx;
147         }
148
149         debug("%s: OK\n", __func__);
150         return 0;
151
152 err_disable_clk_tx:
153         clk_disable(&eqos->clk_tx);
154 err_disable_clk_ptp_ref:
155         clk_disable(&eqos->clk_ptp_ref);
156 err_disable_clk_master_bus:
157         clk_disable(&eqos->clk_master_bus);
158 err:
159         debug("%s: FAILED: %d\n", __func__, ret);
160         return ret;
161 }
162
163 static int eqos_stop_clks_imx(struct udevice *dev)
164 {
165         struct eqos_priv *eqos = dev_get_priv(dev);
166
167         debug("%s(dev=%p):\n", __func__, dev);
168
169         clk_disable(&eqos->clk_ck);
170         clk_disable(&eqos->clk_tx);
171         clk_disable(&eqos->clk_ptp_ref);
172         clk_disable(&eqos->clk_master_bus);
173
174         debug("%s: OK\n", __func__);
175         return 0;
176 }
177
178 static int eqos_set_tx_clk_speed_imx(struct udevice *dev)
179 {
180         struct eqos_priv *eqos = dev_get_priv(dev);
181         ulong rate;
182         int ret;
183
184         if (device_is_compatible(dev, "nxp,imx93-dwmac-eqos"))
185                 return 0;
186
187         debug("%s(dev=%p):\n", __func__, dev);
188
189         if (eqos->phy->interface == PHY_INTERFACE_MODE_RMII)
190                 rate = 5000;    /* 5000 kHz = 5 MHz */
191         else
192                 rate = 2500;    /* 2500 kHz = 2.5 MHz */
193
194         if (eqos->phy->speed == SPEED_1000 &&
195             (eqos->phy->interface == PHY_INTERFACE_MODE_RGMII ||
196              eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_ID ||
197              eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_RXID ||
198              eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
199                 rate *= 50;     /* Use 50x base rate i.e. 125 MHz */
200         } else if (eqos->phy->speed == SPEED_100) {
201                 rate *= 10;     /* Use 10x base rate */
202         } else if (eqos->phy->speed == SPEED_10) {
203                 rate *= 1;      /* Use base rate */
204         } else {
205                 pr_err("invalid speed %d", eqos->phy->speed);
206                 return -EINVAL;
207         }
208
209         rate *= 1000;   /* clk_set_rate() operates in Hz */
210
211         ret = clk_set_rate(&eqos->clk_tx, rate);
212         if (ret < 0) {
213                 pr_err("imx (tx_clk, %lu) failed: %d", rate, ret);
214                 return ret;
215         }
216
217         return 0;
218 }
219
220 static int eqos_get_enetaddr_imx(struct udevice *dev)
221 {
222         struct eth_pdata *pdata = dev_get_plat(dev);
223
224         imx_get_mac_from_fuse(dev_seq(dev), pdata->enetaddr);
225
226         return 0;
227 }
228
229 static struct eqos_ops eqos_imx_ops = {
230         .eqos_inval_desc = eqos_inval_desc_generic,
231         .eqos_flush_desc = eqos_flush_desc_generic,
232         .eqos_inval_buffer = eqos_inval_buffer_generic,
233         .eqos_flush_buffer = eqos_flush_buffer_generic,
234         .eqos_probe_resources = eqos_probe_resources_imx,
235         .eqos_remove_resources = eqos_remove_resources_imx,
236         .eqos_stop_resets = eqos_null_ops,
237         .eqos_start_resets = eqos_null_ops,
238         .eqos_stop_clks = eqos_stop_clks_imx,
239         .eqos_start_clks = eqos_start_clks_imx,
240         .eqos_calibrate_pads = eqos_null_ops,
241         .eqos_disable_calibration = eqos_null_ops,
242         .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_imx,
243         .eqos_get_enetaddr = eqos_get_enetaddr_imx,
244         .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_imx,
245 };
246
247 struct eqos_config __maybe_unused eqos_imx_config = {
248         .reg_access_always_ok = false,
249         .mdio_wait = 10,
250         .swr_wait = 50,
251         .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB,
252         .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300,
253         .axi_bus_width = EQOS_AXI_WIDTH_64,
254         .interface = dev_read_phy_mode,
255         .ops = &eqos_imx_ops
256 };