1 // SPDX-License-Identifier: GPL-2.0
2 /* Renesas Ethernet SERDES device driver
4 * Copyright (C) 2022 Renesas Electronics Corporation
7 #include <linux/delay.h>
9 #include <linux/iopoll.h>
10 #include <linux/kernel.h>
12 #include <linux/phy.h>
13 #include <linux/phy/phy.h>
14 #include <linux/platform_device.h>
15 #include <linux/reset.h>
17 #define R8A779F0_ETH_SERDES_NUM 3
18 #define R8A779F0_ETH_SERDES_OFFSET 0x0400
19 #define R8A779F0_ETH_SERDES_BANK_SELECT 0x03fc
20 #define R8A779F0_ETH_SERDES_TIMEOUT_US 100000
21 #define R8A779F0_ETH_SERDES_NUM_RETRY_LINKUP 3
23 struct r8a779f0_eth_serdes_drv_data
;
24 struct r8a779f0_eth_serdes_channel
{
25 struct r8a779f0_eth_serdes_drv_data
*dd
;
28 phy_interface_t phy_interface
;
33 struct r8a779f0_eth_serdes_drv_data
{
35 struct platform_device
*pdev
;
36 struct reset_control
*reset
;
37 struct r8a779f0_eth_serdes_channel channel
[R8A779F0_ETH_SERDES_NUM
];
42 * The datasheet describes initialization procedure without any information
43 * about registers' name/bits. So, this is all black magic to initialize
46 static void r8a779f0_eth_serdes_write32(void __iomem
*addr
, u32 offs
, u32 bank
, u32 data
)
48 iowrite32(bank
, addr
+ R8A779F0_ETH_SERDES_BANK_SELECT
);
49 iowrite32(data
, addr
+ offs
);
53 r8a779f0_eth_serdes_reg_wait(struct r8a779f0_eth_serdes_channel
*channel
,
54 u32 offs
, u32 bank
, u32 mask
, u32 expected
)
59 iowrite32(bank
, channel
->addr
+ R8A779F0_ETH_SERDES_BANK_SELECT
);
61 ret
= readl_poll_timeout_atomic(channel
->addr
+ offs
, val
,
62 (val
& mask
) == expected
,
63 1, R8A779F0_ETH_SERDES_TIMEOUT_US
);
65 dev_dbg(&channel
->phy
->dev
,
66 "%s: index %d, offs %x, bank %x, mask %x, expected %x\n",
67 __func__
, channel
->index
, offs
, bank
, mask
, expected
);
73 r8a779f0_eth_serdes_common_init_ram(struct r8a779f0_eth_serdes_drv_data
*dd
)
75 struct r8a779f0_eth_serdes_channel
*channel
;
78 for (i
= 0; i
< R8A779F0_ETH_SERDES_NUM
; i
++) {
79 channel
= &dd
->channel
[i
];
80 ret
= r8a779f0_eth_serdes_reg_wait(channel
, 0x026c, 0x180, BIT(0), 0x01);
85 r8a779f0_eth_serdes_write32(dd
->addr
, 0x026c, 0x180, 0x03);
91 r8a779f0_eth_serdes_common_setting(struct r8a779f0_eth_serdes_channel
*channel
)
93 struct r8a779f0_eth_serdes_drv_data
*dd
= channel
->dd
;
95 switch (channel
->phy_interface
) {
96 case PHY_INTERFACE_MODE_SGMII
:
97 r8a779f0_eth_serdes_write32(dd
->addr
, 0x0244, 0x180, 0x0097);
98 r8a779f0_eth_serdes_write32(dd
->addr
, 0x01d0, 0x180, 0x0060);
99 r8a779f0_eth_serdes_write32(dd
->addr
, 0x01d8, 0x180, 0x2200);
100 r8a779f0_eth_serdes_write32(dd
->addr
, 0x01d4, 0x180, 0x0000);
101 r8a779f0_eth_serdes_write32(dd
->addr
, 0x01e0, 0x180, 0x003d);
109 r8a779f0_eth_serdes_chan_setting(struct r8a779f0_eth_serdes_channel
*channel
)
113 switch (channel
->phy_interface
) {
114 case PHY_INTERFACE_MODE_SGMII
:
115 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0000, 0x380, 0x2000);
116 r8a779f0_eth_serdes_write32(channel
->addr
, 0x01c0, 0x180, 0x0011);
117 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0248, 0x180, 0x0540);
118 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0258, 0x180, 0x0015);
119 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0144, 0x180, 0x0100);
120 r8a779f0_eth_serdes_write32(channel
->addr
, 0x01a0, 0x180, 0x0000);
121 r8a779f0_eth_serdes_write32(channel
->addr
, 0x00d0, 0x180, 0x0002);
122 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0150, 0x180, 0x0003);
123 r8a779f0_eth_serdes_write32(channel
->addr
, 0x00c8, 0x180, 0x0100);
124 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0148, 0x180, 0x0100);
125 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0174, 0x180, 0x0000);
126 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0160, 0x180, 0x0007);
127 r8a779f0_eth_serdes_write32(channel
->addr
, 0x01ac, 0x180, 0x0000);
128 r8a779f0_eth_serdes_write32(channel
->addr
, 0x00c4, 0x180, 0x0310);
129 r8a779f0_eth_serdes_write32(channel
->addr
, 0x00c8, 0x180, 0x0101);
130 ret
= r8a779f0_eth_serdes_reg_wait(channel
, 0x00c8, 0x0180, BIT(0), 0);
134 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0148, 0x180, 0x0101);
135 ret
= r8a779f0_eth_serdes_reg_wait(channel
, 0x0148, 0x0180, BIT(0), 0);
139 r8a779f0_eth_serdes_write32(channel
->addr
, 0x00c4, 0x180, 0x1310);
140 r8a779f0_eth_serdes_write32(channel
->addr
, 0x00d8, 0x180, 0x1800);
141 r8a779f0_eth_serdes_write32(channel
->addr
, 0x00dc, 0x180, 0x0000);
142 r8a779f0_eth_serdes_write32(channel
->addr
, 0x001c, 0x300, 0x0001);
143 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0000, 0x380, 0x2100);
144 ret
= r8a779f0_eth_serdes_reg_wait(channel
, 0x0000, 0x0380, BIT(8), 0);
148 if (channel
->speed
== 1000)
149 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0000, 0x1f00, 0x0140);
150 else if (channel
->speed
== 100)
151 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0000, 0x1f00, 0x2100);
154 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0004, 0x1f80, 0x0005);
155 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0028, 0x1f80, 0x07a1);
156 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0000, 0x1f80, 0x0208);
166 r8a779f0_eth_serdes_chan_speed(struct r8a779f0_eth_serdes_channel
*channel
)
170 switch (channel
->phy_interface
) {
171 case PHY_INTERFACE_MODE_SGMII
:
173 if (channel
->speed
== 1000)
174 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0000, 0x1f00, 0x1140);
175 else if (channel
->speed
== 100)
176 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0000, 0x1f00, 0x3100);
177 ret
= r8a779f0_eth_serdes_reg_wait(channel
, 0x0008, 0x1f80, BIT(0), 1);
180 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0008, 0x1f80, 0x0000);
190 static int r8a779f0_eth_serdes_monitor_linkup(struct r8a779f0_eth_serdes_channel
*channel
)
194 for (i
= 0; i
< R8A779F0_ETH_SERDES_NUM_RETRY_LINKUP
; i
++) {
195 ret
= r8a779f0_eth_serdes_reg_wait(channel
, 0x0004, 0x300,
201 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0144, 0x180, 0x0100);
203 r8a779f0_eth_serdes_write32(channel
->addr
, 0x0144, 0x180, 0x0000);
209 static int r8a779f0_eth_serdes_hw_init(struct r8a779f0_eth_serdes_channel
*channel
)
211 struct r8a779f0_eth_serdes_drv_data
*dd
= channel
->dd
;
217 reset_control_reset(dd
->reset
);
219 usleep_range(1000, 2000);
221 ret
= r8a779f0_eth_serdes_common_init_ram(dd
);
225 for (i
= 0; i
< R8A779F0_ETH_SERDES_NUM
; i
++) {
226 ret
= r8a779f0_eth_serdes_reg_wait(&dd
->channel
[i
], 0x0000,
232 for (i
= 0; i
< R8A779F0_ETH_SERDES_NUM
; i
++)
233 r8a779f0_eth_serdes_write32(dd
->channel
[i
].addr
, 0x03d4, 0x380, 0x0443);
235 ret
= r8a779f0_eth_serdes_common_setting(channel
);
239 for (i
= 0; i
< R8A779F0_ETH_SERDES_NUM
; i
++)
240 r8a779f0_eth_serdes_write32(dd
->channel
[i
].addr
, 0x03d0, 0x380, 0x0001);
243 r8a779f0_eth_serdes_write32(dd
->addr
, 0x0000, 0x380, 0x8000);
245 ret
= r8a779f0_eth_serdes_common_init_ram(dd
);
249 return r8a779f0_eth_serdes_reg_wait(&dd
->channel
[0], 0x0000, 0x380, BIT(15), 0);
252 static int r8a779f0_eth_serdes_init(struct phy
*p
)
254 struct r8a779f0_eth_serdes_channel
*channel
= phy_get_drvdata(p
);
257 ret
= r8a779f0_eth_serdes_hw_init(channel
);
259 channel
->dd
->initialized
= true;
264 static int r8a779f0_eth_serdes_exit(struct phy
*p
)
266 struct r8a779f0_eth_serdes_channel
*channel
= phy_get_drvdata(p
);
268 channel
->dd
->initialized
= false;
273 static int r8a779f0_eth_serdes_hw_init_late(struct r8a779f0_eth_serdes_channel
278 ret
= r8a779f0_eth_serdes_chan_setting(channel
);
282 ret
= r8a779f0_eth_serdes_chan_speed(channel
);
286 r8a779f0_eth_serdes_write32(channel
->addr
, 0x03c0, 0x380, 0x0000);
288 r8a779f0_eth_serdes_write32(channel
->addr
, 0x03d0, 0x380, 0x0000);
290 return r8a779f0_eth_serdes_monitor_linkup(channel
);
293 static int r8a779f0_eth_serdes_power_on(struct phy
*p
)
295 struct r8a779f0_eth_serdes_channel
*channel
= phy_get_drvdata(p
);
297 return r8a779f0_eth_serdes_hw_init_late(channel
);
300 static int r8a779f0_eth_serdes_set_mode(struct phy
*p
, enum phy_mode mode
,
303 struct r8a779f0_eth_serdes_channel
*channel
= phy_get_drvdata(p
);
305 if (mode
!= PHY_MODE_ETHERNET
)
309 case PHY_INTERFACE_MODE_GMII
:
310 case PHY_INTERFACE_MODE_SGMII
:
311 case PHY_INTERFACE_MODE_USXGMII
:
312 channel
->phy_interface
= submode
;
319 static int r8a779f0_eth_serdes_set_speed(struct phy
*p
, int speed
)
321 struct r8a779f0_eth_serdes_channel
*channel
= phy_get_drvdata(p
);
323 channel
->speed
= speed
;
328 static const struct phy_ops r8a779f0_eth_serdes_ops
= {
329 .init
= r8a779f0_eth_serdes_init
,
330 .exit
= r8a779f0_eth_serdes_exit
,
331 .power_on
= r8a779f0_eth_serdes_power_on
,
332 .set_mode
= r8a779f0_eth_serdes_set_mode
,
333 .set_speed
= r8a779f0_eth_serdes_set_speed
,
336 static struct phy
*r8a779f0_eth_serdes_xlate(struct device
*dev
,
337 const struct of_phandle_args
*args
)
339 struct r8a779f0_eth_serdes_drv_data
*dd
= dev_get_drvdata(dev
);
341 if (args
->args
[0] >= R8A779F0_ETH_SERDES_NUM
)
342 return ERR_PTR(-ENODEV
);
344 return dd
->channel
[args
->args
[0]].phy
;
347 static const struct of_device_id r8a779f0_eth_serdes_of_table
[] = {
348 { .compatible
= "renesas,r8a779f0-ether-serdes", },
351 MODULE_DEVICE_TABLE(of
, r8a779f0_eth_serdes_of_table
);
353 static int r8a779f0_eth_serdes_probe(struct platform_device
*pdev
)
355 struct r8a779f0_eth_serdes_drv_data
*dd
;
356 struct phy_provider
*provider
;
359 dd
= devm_kzalloc(&pdev
->dev
, sizeof(*dd
), GFP_KERNEL
);
363 platform_set_drvdata(pdev
, dd
);
365 dd
->addr
= devm_platform_ioremap_resource(pdev
, 0);
366 if (IS_ERR(dd
->addr
))
367 return PTR_ERR(dd
->addr
);
369 dd
->reset
= devm_reset_control_get(&pdev
->dev
, NULL
);
370 if (IS_ERR(dd
->reset
))
371 return PTR_ERR(dd
->reset
);
373 for (i
= 0; i
< R8A779F0_ETH_SERDES_NUM
; i
++) {
374 struct r8a779f0_eth_serdes_channel
*channel
= &dd
->channel
[i
];
376 channel
->phy
= devm_phy_create(&pdev
->dev
, NULL
,
377 &r8a779f0_eth_serdes_ops
);
378 if (IS_ERR(channel
->phy
))
379 return PTR_ERR(channel
->phy
);
380 channel
->addr
= dd
->addr
+ R8A779F0_ETH_SERDES_OFFSET
* i
;
383 phy_set_drvdata(channel
->phy
, channel
);
386 provider
= devm_of_phy_provider_register(&pdev
->dev
,
387 r8a779f0_eth_serdes_xlate
);
388 if (IS_ERR(provider
))
389 return PTR_ERR(provider
);
391 pm_runtime_enable(&pdev
->dev
);
392 pm_runtime_get_sync(&pdev
->dev
);
397 static void r8a779f0_eth_serdes_remove(struct platform_device
*pdev
)
399 pm_runtime_put(&pdev
->dev
);
400 pm_runtime_disable(&pdev
->dev
);
402 platform_set_drvdata(pdev
, NULL
);
405 static struct platform_driver r8a779f0_eth_serdes_driver_platform
= {
406 .probe
= r8a779f0_eth_serdes_probe
,
407 .remove
= r8a779f0_eth_serdes_remove
,
409 .name
= "r8a779f0_eth_serdes",
410 .of_match_table
= r8a779f0_eth_serdes_of_table
,
413 module_platform_driver(r8a779f0_eth_serdes_driver_platform
);
414 MODULE_AUTHOR("Yoshihiro Shimoda");
415 MODULE_DESCRIPTION("Renesas Ethernet SERDES device driver");
416 MODULE_LICENSE("GPL");