blob: bd1fdd3a667d379a7ca9f9d905cb61635a91babb [file] [log] [blame]
Marek Vasut8ec30772023-03-19 18:09:43 +01001// SPDX-License-Identifier: GPL-2.0
2/* Renesas Ethernet SERDES device driver
3 *
4 * Copyright (C) 2022 Renesas Electronics Corporation
5 */
6
7#include <asm/io.h>
8#include <clk-uclass.h>
9#include <clk.h>
10#include <common.h>
11#include <div64.h>
12#include <dm.h>
13#include <dm/device_compat.h>
14#include <dm/lists.h>
15#include <dm/of_access.h>
16#include <generic-phy.h>
17#include <linux/bitfield.h>
18#include <linux/bitops.h>
19#include <linux/delay.h>
20#include <linux/iopoll.h>
21#include <log.h>
22#include <reset.h>
23#include <syscon.h>
24
25#define R8A779F0_ETH_SERDES_NUM 3
26#define R8A779F0_ETH_SERDES_OFFSET 0x0400
27#define R8A779F0_ETH_SERDES_BANK_SELECT 0x03fc
28#define R8A779F0_ETH_SERDES_TIMEOUT_US 100000
29#define R8A779F0_ETH_SERDES_NUM_RETRY_LINKUP 3
30
31struct r8a779f0_eth_serdes_drv_data;
32struct r8a779f0_eth_serdes_channel {
33 struct r8a779f0_eth_serdes_drv_data *dd;
34 struct phy *phy;
35 void __iomem *addr;
36 phy_interface_t phy_interface;
37 int speed;
38 int index;
39};
40
41struct r8a779f0_eth_serdes_drv_data {
42 void __iomem *addr;
43 struct reset_ctl *reset;
44 struct r8a779f0_eth_serdes_channel channel[R8A779F0_ETH_SERDES_NUM];
45 bool initialized;
46};
47
48/*
49 * The datasheet describes initialization procedure without any information
50 * about registers' name/bits. So, this is all black magic to initialize
51 * the hardware.
52 */
53static void r8a779f0_eth_serdes_write32(void __iomem *addr, u32 offs, u32 bank, u32 data)
54{
55 writel(bank, addr + R8A779F0_ETH_SERDES_BANK_SELECT);
56 writel(data, addr + offs);
57}
58
59static int
60r8a779f0_eth_serdes_reg_wait(struct r8a779f0_eth_serdes_channel *channel,
61 u32 offs, u32 bank, u32 mask, u32 expected)
62{
63 u32 val = 0;
64 int ret;
65
66 writel(bank, channel->addr + R8A779F0_ETH_SERDES_BANK_SELECT);
67
68 ret = readl_poll_timeout(channel->addr + offs, val,
69 (val & mask) == expected,
70 R8A779F0_ETH_SERDES_TIMEOUT_US);
71 if (ret)
72 dev_dbg(channel->phy->dev,
73 "%s: index %d, offs %x, bank %x, mask %x, expected %x\n",
74 __func__, channel->index, offs, bank, mask, expected);
75
76 return ret;
77}
78
79static int
80r8a779f0_eth_serdes_common_init_ram(struct r8a779f0_eth_serdes_drv_data *dd)
81{
82 struct r8a779f0_eth_serdes_channel *channel;
83 int i, ret;
84
85 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
86 channel = &dd->channel[i];
87 ret = r8a779f0_eth_serdes_reg_wait(channel, 0x026c, 0x180, BIT(0), 0x01);
88 if (ret)
89 return ret;
90 }
91
92 r8a779f0_eth_serdes_write32(dd->addr, 0x026c, 0x180, 0x03);
93
94 return ret;
95}
96
97static int
98r8a779f0_eth_serdes_common_setting(struct r8a779f0_eth_serdes_channel *channel)
99{
100 struct r8a779f0_eth_serdes_drv_data *dd = channel->dd;
101
102 switch (channel->phy_interface) {
103 case PHY_INTERFACE_MODE_SGMII:
104 r8a779f0_eth_serdes_write32(dd->addr, 0x0244, 0x180, 0x0097);
105 r8a779f0_eth_serdes_write32(dd->addr, 0x01d0, 0x180, 0x0060);
106 r8a779f0_eth_serdes_write32(dd->addr, 0x01d8, 0x180, 0x2200);
107 r8a779f0_eth_serdes_write32(dd->addr, 0x01d4, 0x180, 0x0000);
108 r8a779f0_eth_serdes_write32(dd->addr, 0x01e0, 0x180, 0x003d);
109 return 0;
110 default:
111 return -EOPNOTSUPP;
112 }
113}
114
115static int
116r8a779f0_eth_serdes_chan_setting(struct r8a779f0_eth_serdes_channel *channel)
117{
118 int ret;
119
120 switch (channel->phy_interface) {
121 case PHY_INTERFACE_MODE_SGMII:
122 r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x380, 0x2000);
123 r8a779f0_eth_serdes_write32(channel->addr, 0x01c0, 0x180, 0x0011);
124 r8a779f0_eth_serdes_write32(channel->addr, 0x0248, 0x180, 0x0540);
125 r8a779f0_eth_serdes_write32(channel->addr, 0x0258, 0x180, 0x0015);
126 r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x0100);
127 r8a779f0_eth_serdes_write32(channel->addr, 0x01a0, 0x180, 0x0000);
128 r8a779f0_eth_serdes_write32(channel->addr, 0x00d0, 0x180, 0x0002);
129 r8a779f0_eth_serdes_write32(channel->addr, 0x0150, 0x180, 0x0003);
130 r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0100);
131 r8a779f0_eth_serdes_write32(channel->addr, 0x0148, 0x180, 0x0100);
132 r8a779f0_eth_serdes_write32(channel->addr, 0x0174, 0x180, 0x0000);
133 r8a779f0_eth_serdes_write32(channel->addr, 0x0160, 0x180, 0x0007);
134 r8a779f0_eth_serdes_write32(channel->addr, 0x01ac, 0x180, 0x0000);
135 r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x0310);
136 r8a779f0_eth_serdes_write32(channel->addr, 0x00c8, 0x180, 0x0101);
137 ret = r8a779f0_eth_serdes_reg_wait(channel, 0x00c8, 0x0180, BIT(0), 0);
138 if (ret)
139 return ret;
140
141 r8a779f0_eth_serdes_write32(channel->addr, 0x0148, 0x180, 0x0101);
142 ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0148, 0x0180, BIT(0), 0);
143 if (ret)
144 return ret;
145
146 r8a779f0_eth_serdes_write32(channel->addr, 0x00c4, 0x180, 0x1310);
147 r8a779f0_eth_serdes_write32(channel->addr, 0x00d8, 0x180, 0x1800);
148 r8a779f0_eth_serdes_write32(channel->addr, 0x00dc, 0x180, 0x0000);
149 r8a779f0_eth_serdes_write32(channel->addr, 0x001c, 0x300, 0x0001);
150 r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x380, 0x2100);
151 ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0000, 0x0380, BIT(8), 0);
152 if (ret)
153 return ret;
154
155 if (channel->speed == 1000)
156 r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x0140);
157 else if (channel->speed == 100)
158 r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x2100);
159
160 /* For AN_ON */
161 r8a779f0_eth_serdes_write32(channel->addr, 0x0004, 0x1f80, 0x0005);
162 r8a779f0_eth_serdes_write32(channel->addr, 0x0028, 0x1f80, 0x07a1);
163 r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f80, 0x0208);
164 break;
165 default:
166 return -EOPNOTSUPP;
167 }
168
169 return 0;
170}
171
172static int
173r8a779f0_eth_serdes_chan_speed(struct r8a779f0_eth_serdes_channel *channel)
174{
175 int ret;
176
177 switch (channel->phy_interface) {
178 case PHY_INTERFACE_MODE_SGMII:
179 /* For AN_ON */
180 if (channel->speed == 1000)
181 r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x1140);
182 else if (channel->speed == 100)
183 r8a779f0_eth_serdes_write32(channel->addr, 0x0000, 0x1f00, 0x3100);
184 ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0008, 0x1f80, BIT(0), 1);
185 if (ret)
186 return ret;
187 r8a779f0_eth_serdes_write32(channel->addr, 0x0008, 0x1f80, 0x0000);
188 break;
189 default:
190 return -EOPNOTSUPP;
191 }
192
193 return 0;
194}
195
196static int r8a779f0_eth_serdes_monitor_linkup(struct r8a779f0_eth_serdes_channel *channel)
197{
198 int i, ret;
199
200 for (i = 0; i < R8A779F0_ETH_SERDES_NUM_RETRY_LINKUP; i++) {
201 ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0004, 0x300,
202 BIT(2), BIT(2));
203 if (!ret)
204 break;
205
206 /* restart */
207 r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x0100);
208 udelay(1);
209 r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x0000);
210 }
211
212 return ret;
213}
214
215static int r8a779f0_eth_serdes_hw_init(struct r8a779f0_eth_serdes_channel *channel)
216{
217 struct r8a779f0_eth_serdes_drv_data *dd = channel->dd;
218 int i, ret;
219
220 if (dd->initialized)
221 return 0;
222
223 ret = r8a779f0_eth_serdes_common_init_ram(dd);
224 if (ret)
225 return ret;
226
227 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
228 ret = r8a779f0_eth_serdes_reg_wait(&dd->channel[i], 0x0000,
229 0x300, BIT(15), 0);
230 if (ret)
231 return ret;
232 }
233
234 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++)
235 r8a779f0_eth_serdes_write32(dd->channel[i].addr, 0x03d4, 0x380, 0x0443);
236
237 ret = r8a779f0_eth_serdes_common_setting(channel);
238 if (ret)
239 return ret;
240
241 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++)
242 r8a779f0_eth_serdes_write32(dd->channel[i].addr, 0x03d0, 0x380, 0x0001);
243
244 r8a779f0_eth_serdes_write32(dd->addr, 0x0000, 0x380, 0x8000);
245
246 ret = r8a779f0_eth_serdes_common_init_ram(dd);
247 if (ret)
248 return ret;
249
250 return r8a779f0_eth_serdes_reg_wait(&dd->channel[0], 0x0000, 0x380, BIT(15), 0);
251}
252
253static int r8a779f0_eth_serdes_init(struct phy *p)
254{
255 struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(p->dev);
256 struct r8a779f0_eth_serdes_channel *channel = dd->channel + p->id;
257 int ret;
258
259 ret = r8a779f0_eth_serdes_hw_init(channel);
260 if (!ret)
261 channel->dd->initialized = true;
262
263 return ret;
264}
265
266static int r8a779f0_eth_serdes_hw_init_late(struct r8a779f0_eth_serdes_channel *channel)
267{
268 int ret;
269
270 ret = r8a779f0_eth_serdes_chan_setting(channel);
271 if (ret)
272 return ret;
273
274 ret = r8a779f0_eth_serdes_chan_speed(channel);
275 if (ret)
276 return ret;
277
278 r8a779f0_eth_serdes_write32(channel->addr, 0x03c0, 0x380, 0x0000);
279
280 r8a779f0_eth_serdes_write32(channel->addr, 0x03d0, 0x380, 0x0000);
281
282 return r8a779f0_eth_serdes_monitor_linkup(channel);
283}
284
285static int r8a779f0_eth_serdes_power_on(struct phy *p)
286{
287 struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(p->dev);
288 struct r8a779f0_eth_serdes_channel *channel = dd->channel + p->id;
289
290 return r8a779f0_eth_serdes_hw_init_late(channel);
291}
292
293static int r8a779f0_eth_serdes_set_mode(struct phy *p, enum phy_mode mode,
294 int submode)
295{
296 struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(p->dev);
297 struct r8a779f0_eth_serdes_channel *channel = dd->channel + p->id;
298
299 if (mode != PHY_MODE_ETHERNET)
300 return -EOPNOTSUPP;
301
302 switch (submode) {
303 case PHY_INTERFACE_MODE_GMII:
304 case PHY_INTERFACE_MODE_SGMII:
305 case PHY_INTERFACE_MODE_USXGMII:
306 channel->phy_interface = submode;
307 return 0;
308 default:
309 return -EOPNOTSUPP;
310 }
311}
312
313static int r8a779f0_eth_serdes_set_speed(struct phy *p, int speed)
314{
315 struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(p->dev);
316 struct r8a779f0_eth_serdes_channel *channel = dd->channel + p->id;
317
318 channel->speed = speed;
319
320 return 0;
321}
322
323static int r8a779f0_eth_serdes_of_xlate(struct phy *phy,
324 struct ofnode_phandle_args *args)
325{
326 if (args->args_count < 1)
327 return -ENODEV;
328
329 if (args->args[0] >= R8A779F0_ETH_SERDES_NUM)
330 return -ENODEV;
331
332 phy->id = args->args[0];
333
334 return 0;
335}
336
337static const struct phy_ops r8a779f0_eth_serdes_ops = {
338 .init = r8a779f0_eth_serdes_init,
339 .power_on = r8a779f0_eth_serdes_power_on,
340 .set_mode = r8a779f0_eth_serdes_set_mode,
341 .set_speed = r8a779f0_eth_serdes_set_speed,
342 .of_xlate = r8a779f0_eth_serdes_of_xlate,
343};
344
345static const struct udevice_id r8a779f0_eth_serdes_of_table[] = {
346 { .compatible = "renesas,r8a779f0-ether-serdes", },
347 { }
348};
349
350static int r8a779f0_eth_serdes_probe(struct udevice *dev)
351{
352 struct r8a779f0_eth_serdes_drv_data *dd = dev_get_priv(dev);
353 int i;
354
355 dd->addr = dev_read_addr_ptr(dev);
356 if (!dd->addr)
357 return -EINVAL;
358
359 dd->reset = devm_reset_control_get(dev, NULL);
360 if (IS_ERR(dd->reset))
361 return PTR_ERR(dd->reset);
362
363 reset_assert(dd->reset);
364 reset_deassert(dd->reset);
365
366 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) {
367 struct r8a779f0_eth_serdes_channel *channel = &dd->channel[i];
368
369 channel->addr = dd->addr + R8A779F0_ETH_SERDES_OFFSET * i;
370 channel->dd = dd;
371 channel->index = i;
372 }
373
374 return 0;
375}
376
377U_BOOT_DRIVER(r8a779f0_eth_serdes_driver_platform) = {
378 .name = "r8a779f0_eth_serdes",
379 .id = UCLASS_PHY,
380 .of_match = r8a779f0_eth_serdes_of_table,
381 .probe = r8a779f0_eth_serdes_probe,
382 .ops = &r8a779f0_eth_serdes_ops,
383 .priv_auto = sizeof(struct r8a779f0_eth_serdes_drv_data),
384};