]>
Commit | Line | Data |
---|---|---|
5fc783b5 PF |
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> | |
15845608 | 10 | #include <dm/device_compat.h> |
5fc783b5 PF |
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 | ||
5fc783b5 PF |
36 | static ulong eqos_get_tick_clk_rate_imx(struct udevice *dev) |
37 | { | |
15845608 MV |
38 | struct eqos_priv *eqos = dev_get_priv(dev); |
39 | ||
40 | return clk_get_rate(&eqos->clk_master_bus); | |
5fc783b5 PF |
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; | |
15845608 | 47 | int ret; |
5fc783b5 PF |
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 | ||
f9e950b9 MV |
58 | ret = board_interface_eth_init(dev, interface); |
59 | if (ret) | |
60 | return -EINVAL; | |
61 | ||
15845608 MV |
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); | |
c9309f40 | 73 | goto err_probe; |
15845608 MV |
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); | |
c9309f40 | 79 | goto err_probe; |
15845608 MV |
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); | |
c9309f40 | 85 | goto err_probe; |
15845608 MV |
86 | } |
87 | ||
88 | debug("%s: OK\n", __func__); | |
89 | return 0; | |
90 | ||
15845608 MV |
91 | err_probe: |
92 | ||
93 | debug("%s: returns %d\n", __func__, ret); | |
94 | return ret; | |
95 | } | |
96 | ||
97 | static int eqos_remove_resources_imx(struct udevice *dev) | |
98 | { | |
15845608 | 99 | debug("%s(dev=%p):\n", __func__, dev); |
15845608 MV |
100 | return 0; |
101 | } | |
102 | ||
103 | static int eqos_start_clks_imx(struct udevice *dev) | |
104 | { | |
105 | struct eqos_priv *eqos = dev_get_priv(dev); | |
106 | int ret; | |
107 | ||
108 | debug("%s(dev=%p):\n", __func__, dev); | |
109 | ||
110 | ret = clk_enable(&eqos->clk_master_bus); | |
111 | if (ret < 0) { | |
112 | dev_dbg(dev, "clk_enable(clk_master_bus) failed: %d", ret); | |
113 | goto err; | |
114 | } | |
115 | ||
116 | ret = clk_enable(&eqos->clk_ptp_ref); | |
117 | if (ret < 0) { | |
118 | dev_dbg(dev, "clk_enable(clk_ptp_ref) failed: %d", ret); | |
119 | goto err_disable_clk_master_bus; | |
120 | } | |
121 | ||
122 | ret = clk_enable(&eqos->clk_tx); | |
123 | if (ret < 0) { | |
124 | dev_dbg(dev, "clk_enable(clk_tx) failed: %d", ret); | |
125 | goto err_disable_clk_ptp_ref; | |
126 | } | |
127 | ||
128 | ret = clk_enable(&eqos->clk_ck); | |
129 | if (ret < 0) { | |
130 | dev_dbg(dev, "clk_enable(clk_ck) failed: %d", ret); | |
131 | goto err_disable_clk_tx; | |
132 | } | |
133 | ||
134 | debug("%s: OK\n", __func__); | |
135 | return 0; | |
136 | ||
137 | err_disable_clk_tx: | |
138 | clk_disable(&eqos->clk_tx); | |
139 | err_disable_clk_ptp_ref: | |
140 | clk_disable(&eqos->clk_ptp_ref); | |
141 | err_disable_clk_master_bus: | |
142 | clk_disable(&eqos->clk_master_bus); | |
143 | err: | |
144 | debug("%s: FAILED: %d\n", __func__, ret); | |
145 | return ret; | |
146 | } | |
147 | ||
148 | static int eqos_stop_clks_imx(struct udevice *dev) | |
149 | { | |
150 | struct eqos_priv *eqos = dev_get_priv(dev); | |
151 | ||
152 | debug("%s(dev=%p):\n", __func__, dev); | |
153 | ||
154 | clk_disable(&eqos->clk_ck); | |
155 | clk_disable(&eqos->clk_tx); | |
156 | clk_disable(&eqos->clk_ptp_ref); | |
157 | clk_disable(&eqos->clk_master_bus); | |
158 | ||
5fc783b5 PF |
159 | debug("%s: OK\n", __func__); |
160 | return 0; | |
161 | } | |
162 | ||
163 | static int eqos_set_tx_clk_speed_imx(struct udevice *dev) | |
164 | { | |
165 | struct eqos_priv *eqos = dev_get_priv(dev); | |
166 | ulong rate; | |
167 | int ret; | |
168 | ||
9e1f79bd SS |
169 | if (device_is_compatible(dev, "nxp,imx93-dwmac-eqos")) |
170 | return 0; | |
171 | ||
5fc783b5 PF |
172 | debug("%s(dev=%p):\n", __func__, dev); |
173 | ||
2e9b3014 MV |
174 | if (eqos->phy->interface == PHY_INTERFACE_MODE_RMII) |
175 | rate = 5000; /* 5000 kHz = 5 MHz */ | |
176 | else | |
177 | rate = 2500; /* 2500 kHz = 2.5 MHz */ | |
178 | ||
179 | if (eqos->phy->speed == SPEED_1000 && | |
180 | (eqos->phy->interface == PHY_INTERFACE_MODE_RGMII || | |
181 | eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_ID || | |
182 | eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_RXID || | |
183 | eqos->phy->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { | |
184 | rate *= 50; /* Use 50x base rate i.e. 125 MHz */ | |
185 | } else if (eqos->phy->speed == SPEED_100) { | |
186 | rate *= 10; /* Use 10x base rate */ | |
187 | } else if (eqos->phy->speed == SPEED_10) { | |
188 | rate *= 1; /* Use base rate */ | |
189 | } else { | |
5fc783b5 PF |
190 | pr_err("invalid speed %d", eqos->phy->speed); |
191 | return -EINVAL; | |
192 | } | |
193 | ||
2e9b3014 MV |
194 | rate *= 1000; /* clk_set_rate() operates in Hz */ |
195 | ||
15845608 | 196 | ret = clk_set_rate(&eqos->clk_tx, rate); |
5fc783b5 PF |
197 | if (ret < 0) { |
198 | pr_err("imx (tx_clk, %lu) failed: %d", rate, ret); | |
199 | return ret; | |
200 | } | |
201 | ||
202 | return 0; | |
203 | } | |
204 | ||
a6242514 PF |
205 | static int eqos_get_enetaddr_imx(struct udevice *dev) |
206 | { | |
207 | struct eth_pdata *pdata = dev_get_plat(dev); | |
208 | ||
209 | imx_get_mac_from_fuse(dev_seq(dev), pdata->enetaddr); | |
210 | ||
211 | return 0; | |
212 | } | |
213 | ||
5fc783b5 PF |
214 | static struct eqos_ops eqos_imx_ops = { |
215 | .eqos_inval_desc = eqos_inval_desc_generic, | |
216 | .eqos_flush_desc = eqos_flush_desc_generic, | |
217 | .eqos_inval_buffer = eqos_inval_buffer_generic, | |
218 | .eqos_flush_buffer = eqos_flush_buffer_generic, | |
219 | .eqos_probe_resources = eqos_probe_resources_imx, | |
15845608 | 220 | .eqos_remove_resources = eqos_remove_resources_imx, |
5fc783b5 PF |
221 | .eqos_stop_resets = eqos_null_ops, |
222 | .eqos_start_resets = eqos_null_ops, | |
15845608 MV |
223 | .eqos_stop_clks = eqos_stop_clks_imx, |
224 | .eqos_start_clks = eqos_start_clks_imx, | |
5fc783b5 PF |
225 | .eqos_calibrate_pads = eqos_null_ops, |
226 | .eqos_disable_calibration = eqos_null_ops, | |
227 | .eqos_set_tx_clk_speed = eqos_set_tx_clk_speed_imx, | |
a6242514 PF |
228 | .eqos_get_enetaddr = eqos_get_enetaddr_imx, |
229 | .eqos_get_tick_clk_rate = eqos_get_tick_clk_rate_imx, | |
5fc783b5 PF |
230 | }; |
231 | ||
232 | struct eqos_config __maybe_unused eqos_imx_config = { | |
233 | .reg_access_always_ok = false, | |
234 | .mdio_wait = 10, | |
235 | .swr_wait = 50, | |
236 | .config_mac = EQOS_MAC_RXQ_CTRL0_RXQ0EN_ENABLED_DCB, | |
237 | .config_mac_mdio = EQOS_MAC_MDIO_ADDRESS_CR_250_300, | |
238 | .axi_bus_width = EQOS_AXI_WIDTH_64, | |
239 | .interface = dev_read_phy_mode, | |
240 | .ops = &eqos_imx_ops | |
241 | }; |