1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Synopsys DWC Ethernet Quality-of-Service v4.10a linux driver 4 * 5 * Copyright (C) 2016 Joao Pinto <jpinto@synopsys.com> 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/clk-provider.h> 10 #include <linux/device.h> 11 #include <linux/gpio/consumer.h> 12 #include <linux/ethtool.h> 13 #include <linux/io.h> 14 #include <linux/iopoll.h> 15 #include <linux/ioport.h> 16 #include <linux/module.h> 17 #include <linux/of_device.h> 18 #include <linux/of_net.h> 19 #include <linux/mfd/syscon.h> 20 #include <linux/platform_device.h> 21 #include <linux/reset.h> 22 #include <linux/stmmac.h> 23 24 #include "stmmac_platform.h" 25 #include "dwmac4.h" 26 27 struct tegra_eqos { 28 struct device *dev; 29 void __iomem *regs; 30 31 struct reset_control *rst; 32 struct clk *clk_master; 33 struct clk *clk_slave; 34 struct clk *clk_tx; 35 struct clk *clk_rx; 36 37 struct gpio_desc *reset; 38 }; 39 40 static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, 41 struct plat_stmmacenet_data *plat_dat) 42 { 43 struct device_node *np = pdev->dev.of_node; 44 u32 burst_map = 0; 45 u32 bit_index = 0; 46 u32 a_index = 0; 47 48 if (!plat_dat->axi) { 49 plat_dat->axi = kzalloc(sizeof(struct stmmac_axi), GFP_KERNEL); 50 51 if (!plat_dat->axi) 52 return -ENOMEM; 53 } 54 55 plat_dat->axi->axi_lpi_en = of_property_read_bool(np, "snps,en-lpi"); 56 if (of_property_read_u32(np, "snps,write-requests", 57 &plat_dat->axi->axi_wr_osr_lmt)) { 58 /** 59 * Since the register has a reset value of 1, if property 60 * is missing, default to 1. 61 */ 62 plat_dat->axi->axi_wr_osr_lmt = 1; 63 } else { 64 /** 65 * If property exists, to keep the behavior from dwc_eth_qos, 66 * subtract one after parsing. 67 */ 68 plat_dat->axi->axi_wr_osr_lmt--; 69 } 70 71 if (of_property_read_u32(np, "snps,read-requests", 72 &plat_dat->axi->axi_rd_osr_lmt)) { 73 /** 74 * Since the register has a reset value of 1, if property 75 * is missing, default to 1. 76 */ 77 plat_dat->axi->axi_rd_osr_lmt = 1; 78 } else { 79 /** 80 * If property exists, to keep the behavior from dwc_eth_qos, 81 * subtract one after parsing. 82 */ 83 plat_dat->axi->axi_rd_osr_lmt--; 84 } 85 of_property_read_u32(np, "snps,burst-map", &burst_map); 86 87 /* converts burst-map bitmask to burst array */ 88 for (bit_index = 0; bit_index < 7; bit_index++) { 89 if (burst_map & (1 << bit_index)) { 90 switch (bit_index) { 91 case 0: 92 plat_dat->axi->axi_blen[a_index] = 4; break; 93 case 1: 94 plat_dat->axi->axi_blen[a_index] = 8; break; 95 case 2: 96 plat_dat->axi->axi_blen[a_index] = 16; break; 97 case 3: 98 plat_dat->axi->axi_blen[a_index] = 32; break; 99 case 4: 100 plat_dat->axi->axi_blen[a_index] = 64; break; 101 case 5: 102 plat_dat->axi->axi_blen[a_index] = 128; break; 103 case 6: 104 plat_dat->axi->axi_blen[a_index] = 256; break; 105 default: 106 break; 107 } 108 a_index++; 109 } 110 } 111 112 /* dwc-qos needs GMAC4, AAL, TSO and PMT */ 113 plat_dat->has_gmac4 = 1; 114 plat_dat->dma_cfg->aal = 1; 115 plat_dat->tso_en = 1; 116 plat_dat->pmt = 1; 117 118 return 0; 119 } 120 121 static void *dwc_qos_probe(struct platform_device *pdev, 122 struct plat_stmmacenet_data *plat_dat, 123 struct stmmac_resources *stmmac_res) 124 { 125 int err; 126 127 plat_dat->stmmac_clk = devm_clk_get(&pdev->dev, "apb_pclk"); 128 if (IS_ERR(plat_dat->stmmac_clk)) { 129 dev_err(&pdev->dev, "apb_pclk clock not found.\n"); 130 return ERR_CAST(plat_dat->stmmac_clk); 131 } 132 133 err = clk_prepare_enable(plat_dat->stmmac_clk); 134 if (err < 0) { 135 dev_err(&pdev->dev, "failed to enable apb_pclk clock: %d\n", 136 err); 137 return ERR_PTR(err); 138 } 139 140 plat_dat->pclk = devm_clk_get(&pdev->dev, "phy_ref_clk"); 141 if (IS_ERR(plat_dat->pclk)) { 142 dev_err(&pdev->dev, "phy_ref_clk clock not found.\n"); 143 err = PTR_ERR(plat_dat->pclk); 144 goto disable; 145 } 146 147 err = clk_prepare_enable(plat_dat->pclk); 148 if (err < 0) { 149 dev_err(&pdev->dev, "failed to enable phy_ref clock: %d\n", 150 err); 151 goto disable; 152 } 153 154 return NULL; 155 156 disable: 157 clk_disable_unprepare(plat_dat->stmmac_clk); 158 return ERR_PTR(err); 159 } 160 161 static int dwc_qos_remove(struct platform_device *pdev) 162 { 163 struct net_device *ndev = platform_get_drvdata(pdev); 164 struct stmmac_priv *priv = netdev_priv(ndev); 165 166 clk_disable_unprepare(priv->plat->pclk); 167 clk_disable_unprepare(priv->plat->stmmac_clk); 168 169 return 0; 170 } 171 172 #define SDMEMCOMPPADCTRL 0x8800 173 #define SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31) 174 175 #define AUTO_CAL_CONFIG 0x8804 176 #define AUTO_CAL_CONFIG_START BIT(31) 177 #define AUTO_CAL_CONFIG_ENABLE BIT(29) 178 179 #define AUTO_CAL_STATUS 0x880c 180 #define AUTO_CAL_STATUS_ACTIVE BIT(31) 181 182 static void tegra_eqos_fix_speed(void *priv, unsigned int speed) 183 { 184 struct tegra_eqos *eqos = priv; 185 unsigned long rate = 125000000; 186 bool needs_calibration = false; 187 u32 value; 188 int err; 189 190 switch (speed) { 191 case SPEED_1000: 192 needs_calibration = true; 193 rate = 125000000; 194 break; 195 196 case SPEED_100: 197 needs_calibration = true; 198 rate = 25000000; 199 break; 200 201 case SPEED_10: 202 rate = 2500000; 203 break; 204 205 default: 206 dev_err(eqos->dev, "invalid speed %u\n", speed); 207 break; 208 } 209 210 if (needs_calibration) { 211 /* calibrate */ 212 value = readl(eqos->regs + SDMEMCOMPPADCTRL); 213 value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD; 214 writel(value, eqos->regs + SDMEMCOMPPADCTRL); 215 216 udelay(1); 217 218 value = readl(eqos->regs + AUTO_CAL_CONFIG); 219 value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE; 220 writel(value, eqos->regs + AUTO_CAL_CONFIG); 221 222 err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS, 223 value, 224 value & AUTO_CAL_STATUS_ACTIVE, 225 1, 10); 226 if (err < 0) { 227 dev_err(eqos->dev, "calibration did not start\n"); 228 goto failed; 229 } 230 231 err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS, 232 value, 233 (value & AUTO_CAL_STATUS_ACTIVE) == 0, 234 20, 200); 235 if (err < 0) { 236 dev_err(eqos->dev, "calibration didn't finish\n"); 237 goto failed; 238 } 239 240 failed: 241 value = readl(eqos->regs + SDMEMCOMPPADCTRL); 242 value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD; 243 writel(value, eqos->regs + SDMEMCOMPPADCTRL); 244 } else { 245 value = readl(eqos->regs + AUTO_CAL_CONFIG); 246 value &= ~AUTO_CAL_CONFIG_ENABLE; 247 writel(value, eqos->regs + AUTO_CAL_CONFIG); 248 } 249 250 err = clk_set_rate(eqos->clk_tx, rate); 251 if (err < 0) 252 dev_err(eqos->dev, "failed to set TX rate: %d\n", err); 253 } 254 255 static int tegra_eqos_init(struct platform_device *pdev, void *priv) 256 { 257 struct tegra_eqos *eqos = priv; 258 unsigned long rate; 259 u32 value; 260 261 rate = clk_get_rate(eqos->clk_slave); 262 263 value = (rate / 1000000) - 1; 264 writel(value, eqos->regs + GMAC_1US_TIC_COUNTER); 265 266 return 0; 267 } 268 269 static void *tegra_eqos_probe(struct platform_device *pdev, 270 struct plat_stmmacenet_data *data, 271 struct stmmac_resources *res) 272 { 273 struct tegra_eqos *eqos; 274 int err; 275 276 eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL); 277 if (!eqos) { 278 err = -ENOMEM; 279 goto error; 280 } 281 282 eqos->dev = &pdev->dev; 283 eqos->regs = res->addr; 284 285 eqos->clk_master = devm_clk_get(&pdev->dev, "master_bus"); 286 if (IS_ERR(eqos->clk_master)) { 287 err = PTR_ERR(eqos->clk_master); 288 goto error; 289 } 290 291 err = clk_prepare_enable(eqos->clk_master); 292 if (err < 0) 293 goto error; 294 295 eqos->clk_slave = devm_clk_get(&pdev->dev, "slave_bus"); 296 if (IS_ERR(eqos->clk_slave)) { 297 err = PTR_ERR(eqos->clk_slave); 298 goto disable_master; 299 } 300 301 data->stmmac_clk = eqos->clk_slave; 302 303 err = clk_prepare_enable(eqos->clk_slave); 304 if (err < 0) 305 goto disable_master; 306 307 eqos->clk_rx = devm_clk_get(&pdev->dev, "rx"); 308 if (IS_ERR(eqos->clk_rx)) { 309 err = PTR_ERR(eqos->clk_rx); 310 goto disable_slave; 311 } 312 313 err = clk_prepare_enable(eqos->clk_rx); 314 if (err < 0) 315 goto disable_slave; 316 317 eqos->clk_tx = devm_clk_get(&pdev->dev, "tx"); 318 if (IS_ERR(eqos->clk_tx)) { 319 err = PTR_ERR(eqos->clk_tx); 320 goto disable_rx; 321 } 322 323 err = clk_prepare_enable(eqos->clk_tx); 324 if (err < 0) 325 goto disable_rx; 326 327 eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH); 328 if (IS_ERR(eqos->reset)) { 329 err = PTR_ERR(eqos->reset); 330 goto disable_tx; 331 } 332 333 usleep_range(2000, 4000); 334 gpiod_set_value(eqos->reset, 0); 335 336 /* MDIO bus was already reset just above */ 337 data->mdio_bus_data->needs_reset = false; 338 339 eqos->rst = devm_reset_control_get(&pdev->dev, "eqos"); 340 if (IS_ERR(eqos->rst)) { 341 err = PTR_ERR(eqos->rst); 342 goto reset_phy; 343 } 344 345 err = reset_control_assert(eqos->rst); 346 if (err < 0) 347 goto reset_phy; 348 349 usleep_range(2000, 4000); 350 351 err = reset_control_deassert(eqos->rst); 352 if (err < 0) 353 goto reset_phy; 354 355 usleep_range(2000, 4000); 356 357 data->fix_mac_speed = tegra_eqos_fix_speed; 358 data->init = tegra_eqos_init; 359 data->bsp_priv = eqos; 360 361 err = tegra_eqos_init(pdev, eqos); 362 if (err < 0) 363 goto reset; 364 365 out: 366 return eqos; 367 368 reset: 369 reset_control_assert(eqos->rst); 370 reset_phy: 371 gpiod_set_value(eqos->reset, 1); 372 disable_tx: 373 clk_disable_unprepare(eqos->clk_tx); 374 disable_rx: 375 clk_disable_unprepare(eqos->clk_rx); 376 disable_slave: 377 clk_disable_unprepare(eqos->clk_slave); 378 disable_master: 379 clk_disable_unprepare(eqos->clk_master); 380 error: 381 eqos = ERR_PTR(err); 382 goto out; 383 } 384 385 static int tegra_eqos_remove(struct platform_device *pdev) 386 { 387 struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev); 388 389 reset_control_assert(eqos->rst); 390 gpiod_set_value(eqos->reset, 1); 391 clk_disable_unprepare(eqos->clk_tx); 392 clk_disable_unprepare(eqos->clk_rx); 393 clk_disable_unprepare(eqos->clk_slave); 394 clk_disable_unprepare(eqos->clk_master); 395 396 return 0; 397 } 398 399 struct dwc_eth_dwmac_data { 400 void *(*probe)(struct platform_device *pdev, 401 struct plat_stmmacenet_data *data, 402 struct stmmac_resources *res); 403 int (*remove)(struct platform_device *pdev); 404 }; 405 406 static const struct dwc_eth_dwmac_data dwc_qos_data = { 407 .probe = dwc_qos_probe, 408 .remove = dwc_qos_remove, 409 }; 410 411 static const struct dwc_eth_dwmac_data tegra_eqos_data = { 412 .probe = tegra_eqos_probe, 413 .remove = tegra_eqos_remove, 414 }; 415 416 static int dwc_eth_dwmac_probe(struct platform_device *pdev) 417 { 418 const struct dwc_eth_dwmac_data *data; 419 struct plat_stmmacenet_data *plat_dat; 420 struct stmmac_resources stmmac_res; 421 void *priv; 422 int ret; 423 424 data = of_device_get_match_data(&pdev->dev); 425 426 memset(&stmmac_res, 0, sizeof(struct stmmac_resources)); 427 428 /** 429 * Since stmmac_platform supports name IRQ only, basic platform 430 * resource initialization is done in the glue logic. 431 */ 432 stmmac_res.irq = platform_get_irq(pdev, 0); 433 if (stmmac_res.irq < 0) 434 return stmmac_res.irq; 435 stmmac_res.wol_irq = stmmac_res.irq; 436 437 stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0); 438 if (IS_ERR(stmmac_res.addr)) 439 return PTR_ERR(stmmac_res.addr); 440 441 plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); 442 if (IS_ERR(plat_dat)) 443 return PTR_ERR(plat_dat); 444 445 priv = data->probe(pdev, plat_dat, &stmmac_res); 446 if (IS_ERR(priv)) { 447 ret = PTR_ERR(priv); 448 449 if (ret != -EPROBE_DEFER) 450 dev_err(&pdev->dev, "failed to probe subdriver: %d\n", 451 ret); 452 453 goto remove_config; 454 } 455 456 ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); 457 if (ret) 458 goto remove; 459 460 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 461 if (ret) 462 goto remove; 463 464 return ret; 465 466 remove: 467 data->remove(pdev); 468 remove_config: 469 stmmac_remove_config_dt(pdev, plat_dat); 470 471 return ret; 472 } 473 474 static int dwc_eth_dwmac_remove(struct platform_device *pdev) 475 { 476 struct net_device *ndev = platform_get_drvdata(pdev); 477 struct stmmac_priv *priv = netdev_priv(ndev); 478 const struct dwc_eth_dwmac_data *data; 479 int err; 480 481 data = of_device_get_match_data(&pdev->dev); 482 483 err = stmmac_dvr_remove(&pdev->dev); 484 if (err < 0) 485 dev_err(&pdev->dev, "failed to remove platform: %d\n", err); 486 487 err = data->remove(pdev); 488 if (err < 0) 489 dev_err(&pdev->dev, "failed to remove subdriver: %d\n", err); 490 491 stmmac_remove_config_dt(pdev, priv->plat); 492 493 return err; 494 } 495 496 static const struct of_device_id dwc_eth_dwmac_match[] = { 497 { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data }, 498 { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data }, 499 { } 500 }; 501 MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); 502 503 static struct platform_driver dwc_eth_dwmac_driver = { 504 .probe = dwc_eth_dwmac_probe, 505 .remove = dwc_eth_dwmac_remove, 506 .driver = { 507 .name = "dwc-eth-dwmac", 508 .pm = &stmmac_pltfr_pm_ops, 509 .of_match_table = dwc_eth_dwmac_match, 510 }, 511 }; 512 module_platform_driver(dwc_eth_dwmac_driver); 513 514 MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>"); 515 MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver"); 516 MODULE_LICENSE("GPL v2"); 517