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