1// SPDX-License-Identifier: GPL-2.0 2/* Renesas Ethernet SERDES device driver 3 * 4 * Copyright (C) 2022 Renesas Electronics Corporation 5 */ 6 7#include <linux/delay.h> 8#include <linux/err.h> 9#include <linux/iopoll.h> 10#include <linux/kernel.h> 11#include <linux/of.h> 12#include <linux/phy.h> 13#include <linux/phy/phy.h> 14#include <linux/platform_device.h> 15#include <linux/reset.h> 16 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 22 23struct r8a779f0_eth_serdes_drv_data; 24struct r8a779f0_eth_serdes_channel { 25 struct r8a779f0_eth_serdes_drv_data *dd; 26 struct phy *phy; 27 void __iomem *addr; 28 phy_interface_t phy_interface; 29 int speed; 30 int index; 31}; 32 33struct r8a779f0_eth_serdes_drv_data { 34 void __iomem *addr; 35 struct platform_device *pdev; 36 struct reset_control *reset; 37 struct r8a779f0_eth_serdes_channel channel[R8A779F0_ETH_SERDES_NUM]; 38 bool initialized; 39}; 40 41/* 42 * The datasheet describes initialization procedure without any information 43 * about registers' name/bits. So, this is all black magic to initialize 44 * the hardware. 45 */ 46static void r8a779f0_eth_serdes_write32(void __iomem *addr, u32 offs, u32 bank, u32 data) 47{ 48 iowrite32(bank, addr + R8A779F0_ETH_SERDES_BANK_SELECT); 49 iowrite32(data, addr + offs); 50} 51 52static int 53r8a779f0_eth_serdes_reg_wait(struct r8a779f0_eth_serdes_channel *channel, 54 u32 offs, u32 bank, u32 mask, u32 expected) 55{ 56 int ret; 57 u32 val; 58 59 iowrite32(bank, channel->addr + R8A779F0_ETH_SERDES_BANK_SELECT); 60 61 ret = readl_poll_timeout_atomic(channel->addr + offs, val, 62 (val & mask) == expected, 63 1, R8A779F0_ETH_SERDES_TIMEOUT_US); 64 if (ret) 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); 68 69 return ret; 70} 71 72static int 73r8a779f0_eth_serdes_common_init_ram(struct r8a779f0_eth_serdes_drv_data *dd) 74{ 75 struct r8a779f0_eth_serdes_channel *channel; 76 int i, ret; 77 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); 81 if (ret) 82 return ret; 83 } 84 85 r8a779f0_eth_serdes_write32(dd->addr, 0x026c, 0x180, 0x03); 86 87 return ret; 88} 89 90static int 91r8a779f0_eth_serdes_common_setting(struct r8a779f0_eth_serdes_channel *channel) 92{ 93 struct r8a779f0_eth_serdes_drv_data *dd = channel->dd; 94 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); 102 return 0; 103 default: 104 return -EOPNOTSUPP; 105 } 106} 107 108static int 109r8a779f0_eth_serdes_chan_setting(struct r8a779f0_eth_serdes_channel *channel) 110{ 111 int ret; 112 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); 131 if (ret) 132 return ret; 133 134 r8a779f0_eth_serdes_write32(channel->addr, 0x0148, 0x180, 0x0101); 135 ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0148, 0x0180, BIT(0), 0); 136 if (ret) 137 return ret; 138 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); 145 if (ret) 146 return ret; 147 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); 152 153 /* For AN_ON */ 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); 157 break; 158 default: 159 return -EOPNOTSUPP; 160 } 161 162 return 0; 163} 164 165static int 166r8a779f0_eth_serdes_chan_speed(struct r8a779f0_eth_serdes_channel *channel) 167{ 168 int ret; 169 170 switch (channel->phy_interface) { 171 case PHY_INTERFACE_MODE_SGMII: 172 /* For AN_ON */ 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); 178 if (ret) 179 return ret; 180 r8a779f0_eth_serdes_write32(channel->addr, 0x0008, 0x1f80, 0x0000); 181 break; 182 default: 183 return -EOPNOTSUPP; 184 } 185 186 return 0; 187} 188 189 190static int r8a779f0_eth_serdes_monitor_linkup(struct r8a779f0_eth_serdes_channel *channel) 191{ 192 int i, ret; 193 194 for (i = 0; i < R8A779F0_ETH_SERDES_NUM_RETRY_LINKUP; i++) { 195 ret = r8a779f0_eth_serdes_reg_wait(channel, 0x0004, 0x300, 196 BIT(2), BIT(2)); 197 if (!ret) 198 break; 199 200 /* restart */ 201 r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x0100); 202 udelay(1); 203 r8a779f0_eth_serdes_write32(channel->addr, 0x0144, 0x180, 0x0000); 204 } 205 206 return ret; 207} 208 209static int r8a779f0_eth_serdes_hw_init(struct r8a779f0_eth_serdes_channel *channel) 210{ 211 struct r8a779f0_eth_serdes_drv_data *dd = channel->dd; 212 int i, ret; 213 214 if (dd->initialized) 215 return 0; 216 217 reset_control_reset(dd->reset); 218 219 usleep_range(1000, 2000); 220 221 ret = r8a779f0_eth_serdes_common_init_ram(dd); 222 if (ret) 223 return ret; 224 225 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) { 226 ret = r8a779f0_eth_serdes_reg_wait(&dd->channel[i], 0x0000, 227 0x300, BIT(15), 0); 228 if (ret) 229 return ret; 230 } 231 232 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) 233 r8a779f0_eth_serdes_write32(dd->channel[i].addr, 0x03d4, 0x380, 0x0443); 234 235 ret = r8a779f0_eth_serdes_common_setting(channel); 236 if (ret) 237 return ret; 238 239 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) 240 r8a779f0_eth_serdes_write32(dd->channel[i].addr, 0x03d0, 0x380, 0x0001); 241 242 243 r8a779f0_eth_serdes_write32(dd->addr, 0x0000, 0x380, 0x8000); 244 245 ret = r8a779f0_eth_serdes_common_init_ram(dd); 246 if (ret) 247 return ret; 248 249 return r8a779f0_eth_serdes_reg_wait(&dd->channel[0], 0x0000, 0x380, BIT(15), 0); 250} 251 252static int r8a779f0_eth_serdes_init(struct phy *p) 253{ 254 struct r8a779f0_eth_serdes_channel *channel = phy_get_drvdata(p); 255 int ret; 256 257 ret = r8a779f0_eth_serdes_hw_init(channel); 258 if (!ret) 259 channel->dd->initialized = true; 260 261 return ret; 262} 263 264static int r8a779f0_eth_serdes_exit(struct phy *p) 265{ 266 struct r8a779f0_eth_serdes_channel *channel = phy_get_drvdata(p); 267 268 channel->dd->initialized = false; 269 270 return 0; 271} 272 273static int r8a779f0_eth_serdes_hw_init_late(struct r8a779f0_eth_serdes_channel 274*channel) 275{ 276 int ret; 277 278 ret = r8a779f0_eth_serdes_chan_setting(channel); 279 if (ret) 280 return ret; 281 282 ret = r8a779f0_eth_serdes_chan_speed(channel); 283 if (ret) 284 return ret; 285 286 r8a779f0_eth_serdes_write32(channel->addr, 0x03c0, 0x380, 0x0000); 287 288 r8a779f0_eth_serdes_write32(channel->addr, 0x03d0, 0x380, 0x0000); 289 290 return r8a779f0_eth_serdes_monitor_linkup(channel); 291} 292 293static int r8a779f0_eth_serdes_power_on(struct phy *p) 294{ 295 struct r8a779f0_eth_serdes_channel *channel = phy_get_drvdata(p); 296 297 return r8a779f0_eth_serdes_hw_init_late(channel); 298} 299 300static int r8a779f0_eth_serdes_set_mode(struct phy *p, enum phy_mode mode, 301 int submode) 302{ 303 struct r8a779f0_eth_serdes_channel *channel = phy_get_drvdata(p); 304 305 if (mode != PHY_MODE_ETHERNET) 306 return -EOPNOTSUPP; 307 308 switch (submode) { 309 case PHY_INTERFACE_MODE_GMII: 310 case PHY_INTERFACE_MODE_SGMII: 311 case PHY_INTERFACE_MODE_USXGMII: 312 channel->phy_interface = submode; 313 return 0; 314 default: 315 return -EOPNOTSUPP; 316 } 317} 318 319static int r8a779f0_eth_serdes_set_speed(struct phy *p, int speed) 320{ 321 struct r8a779f0_eth_serdes_channel *channel = phy_get_drvdata(p); 322 323 channel->speed = speed; 324 325 return 0; 326} 327 328static 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, 334}; 335 336static struct phy *r8a779f0_eth_serdes_xlate(struct device *dev, 337 const struct of_phandle_args *args) 338{ 339 struct r8a779f0_eth_serdes_drv_data *dd = dev_get_drvdata(dev); 340 341 if (args->args[0] >= R8A779F0_ETH_SERDES_NUM) 342 return ERR_PTR(-ENODEV); 343 344 return dd->channel[args->args[0]].phy; 345} 346 347static const struct of_device_id r8a779f0_eth_serdes_of_table[] = { 348 { .compatible = "renesas,r8a779f0-ether-serdes", }, 349 { } 350}; 351MODULE_DEVICE_TABLE(of, r8a779f0_eth_serdes_of_table); 352 353static int r8a779f0_eth_serdes_probe(struct platform_device *pdev) 354{ 355 struct r8a779f0_eth_serdes_drv_data *dd; 356 struct phy_provider *provider; 357 int i; 358 359 dd = devm_kzalloc(&pdev->dev, sizeof(*dd), GFP_KERNEL); 360 if (!dd) 361 return -ENOMEM; 362 363 platform_set_drvdata(pdev, dd); 364 dd->pdev = pdev; 365 dd->addr = devm_platform_ioremap_resource(pdev, 0); 366 if (IS_ERR(dd->addr)) 367 return PTR_ERR(dd->addr); 368 369 dd->reset = devm_reset_control_get(&pdev->dev, NULL); 370 if (IS_ERR(dd->reset)) 371 return PTR_ERR(dd->reset); 372 373 for (i = 0; i < R8A779F0_ETH_SERDES_NUM; i++) { 374 struct r8a779f0_eth_serdes_channel *channel = &dd->channel[i]; 375 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; 381 channel->dd = dd; 382 channel->index = i; 383 phy_set_drvdata(channel->phy, channel); 384 } 385 386 provider = devm_of_phy_provider_register(&pdev->dev, 387 r8a779f0_eth_serdes_xlate); 388 if (IS_ERR(provider)) 389 return PTR_ERR(provider); 390 391 pm_runtime_enable(&pdev->dev); 392 pm_runtime_get_sync(&pdev->dev); 393 394 return 0; 395} 396 397static void r8a779f0_eth_serdes_remove(struct platform_device *pdev) 398{ 399 pm_runtime_put(&pdev->dev); 400 pm_runtime_disable(&pdev->dev); 401 402 platform_set_drvdata(pdev, NULL); 403} 404 405static struct platform_driver r8a779f0_eth_serdes_driver_platform = { 406 .probe = r8a779f0_eth_serdes_probe, 407 .remove_new = r8a779f0_eth_serdes_remove, 408 .driver = { 409 .name = "r8a779f0_eth_serdes", 410 .of_match_table = r8a779f0_eth_serdes_of_table, 411 } 412}; 413module_platform_driver(r8a779f0_eth_serdes_driver_platform); 414MODULE_AUTHOR("Yoshihiro Shimoda"); 415MODULE_DESCRIPTION("Renesas Ethernet SERDES device driver"); 416MODULE_LICENSE("GPL"); 417