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 23 struct r8a779f0_eth_serdes_drv_data; 24 struct 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 33 struct 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 */ 46 static 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 52 static int 53 r8a779f0_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 72 static int 73 r8a779f0_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 90 static int 91 r8a779f0_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 108 static int 109 r8a779f0_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 165 static int 166 r8a779f0_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 190 static 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 209 static 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 252 static 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 264 static 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 273 static 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 293 static 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 300 static 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 319 static 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 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, 334 }; 335 336 static struct phy *r8a779f0_eth_serdes_xlate(struct device *dev, 337 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 347 static const struct of_device_id r8a779f0_eth_serdes_of_table[] = { 348 { .compatible = "renesas,r8a779f0-ether-serdes", }, 349 { } 350 }; 351 MODULE_DEVICE_TABLE(of, r8a779f0_eth_serdes_of_table); 352 353 static 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 397 static 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 405 static 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 }; 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"); 417