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 eqos->rst = devm_reset_control_get(&pdev->dev, "eqos"); 337 if (IS_ERR(eqos->rst)) { 338 err = PTR_ERR(eqos->rst); 339 goto reset_phy; 340 } 341 342 err = reset_control_assert(eqos->rst); 343 if (err < 0) 344 goto reset_phy; 345 346 usleep_range(2000, 4000); 347 348 err = reset_control_deassert(eqos->rst); 349 if (err < 0) 350 goto reset_phy; 351 352 usleep_range(2000, 4000); 353 354 data->fix_mac_speed = tegra_eqos_fix_speed; 355 data->init = tegra_eqos_init; 356 data->bsp_priv = eqos; 357 358 err = tegra_eqos_init(pdev, eqos); 359 if (err < 0) 360 goto reset; 361 362 out: 363 return eqos; 364 365 reset: 366 reset_control_assert(eqos->rst); 367 reset_phy: 368 gpiod_set_value(eqos->reset, 1); 369 disable_tx: 370 clk_disable_unprepare(eqos->clk_tx); 371 disable_rx: 372 clk_disable_unprepare(eqos->clk_rx); 373 disable_slave: 374 clk_disable_unprepare(eqos->clk_slave); 375 disable_master: 376 clk_disable_unprepare(eqos->clk_master); 377 error: 378 eqos = ERR_PTR(err); 379 goto out; 380 } 381 382 static int tegra_eqos_remove(struct platform_device *pdev) 383 { 384 struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev); 385 386 reset_control_assert(eqos->rst); 387 gpiod_set_value(eqos->reset, 1); 388 clk_disable_unprepare(eqos->clk_tx); 389 clk_disable_unprepare(eqos->clk_rx); 390 clk_disable_unprepare(eqos->clk_slave); 391 clk_disable_unprepare(eqos->clk_master); 392 393 return 0; 394 } 395 396 struct dwc_eth_dwmac_data { 397 void *(*probe)(struct platform_device *pdev, 398 struct plat_stmmacenet_data *data, 399 struct stmmac_resources *res); 400 int (*remove)(struct platform_device *pdev); 401 }; 402 403 static const struct dwc_eth_dwmac_data dwc_qos_data = { 404 .probe = dwc_qos_probe, 405 .remove = dwc_qos_remove, 406 }; 407 408 static const struct dwc_eth_dwmac_data tegra_eqos_data = { 409 .probe = tegra_eqos_probe, 410 .remove = tegra_eqos_remove, 411 }; 412 413 static int dwc_eth_dwmac_probe(struct platform_device *pdev) 414 { 415 const struct dwc_eth_dwmac_data *data; 416 struct plat_stmmacenet_data *plat_dat; 417 struct stmmac_resources stmmac_res; 418 struct resource *res; 419 void *priv; 420 int ret; 421 422 data = of_device_get_match_data(&pdev->dev); 423 424 memset(&stmmac_res, 0, sizeof(struct stmmac_resources)); 425 426 /** 427 * Since stmmac_platform supports name IRQ only, basic platform 428 * resource initialization is done in the glue logic. 429 */ 430 stmmac_res.irq = platform_get_irq(pdev, 0); 431 if (stmmac_res.irq < 0) { 432 if (stmmac_res.irq != -EPROBE_DEFER) 433 dev_err(&pdev->dev, 434 "IRQ configuration information not found\n"); 435 436 return stmmac_res.irq; 437 } 438 stmmac_res.wol_irq = stmmac_res.irq; 439 440 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 441 stmmac_res.addr = devm_ioremap_resource(&pdev->dev, res); 442 if (IS_ERR(stmmac_res.addr)) 443 return PTR_ERR(stmmac_res.addr); 444 445 plat_dat = stmmac_probe_config_dt(pdev, &stmmac_res.mac); 446 if (IS_ERR(plat_dat)) 447 return PTR_ERR(plat_dat); 448 449 priv = data->probe(pdev, plat_dat, &stmmac_res); 450 if (IS_ERR(priv)) { 451 ret = PTR_ERR(priv); 452 453 if (ret != -EPROBE_DEFER) 454 dev_err(&pdev->dev, "failed to probe subdriver: %d\n", 455 ret); 456 457 goto remove_config; 458 } 459 460 ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); 461 if (ret) 462 goto remove; 463 464 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 465 if (ret) 466 goto remove; 467 468 return ret; 469 470 remove: 471 data->remove(pdev); 472 remove_config: 473 stmmac_remove_config_dt(pdev, plat_dat); 474 475 return ret; 476 } 477 478 static int dwc_eth_dwmac_remove(struct platform_device *pdev) 479 { 480 struct net_device *ndev = platform_get_drvdata(pdev); 481 struct stmmac_priv *priv = netdev_priv(ndev); 482 const struct dwc_eth_dwmac_data *data; 483 int err; 484 485 data = of_device_get_match_data(&pdev->dev); 486 487 err = stmmac_dvr_remove(&pdev->dev); 488 if (err < 0) 489 dev_err(&pdev->dev, "failed to remove platform: %d\n", err); 490 491 err = data->remove(pdev); 492 if (err < 0) 493 dev_err(&pdev->dev, "failed to remove subdriver: %d\n", err); 494 495 stmmac_remove_config_dt(pdev, priv->plat); 496 497 return err; 498 } 499 500 static const struct of_device_id dwc_eth_dwmac_match[] = { 501 { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data }, 502 { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data }, 503 { } 504 }; 505 MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); 506 507 static struct platform_driver dwc_eth_dwmac_driver = { 508 .probe = dwc_eth_dwmac_probe, 509 .remove = dwc_eth_dwmac_remove, 510 .driver = { 511 .name = "dwc-eth-dwmac", 512 .pm = &stmmac_pltfr_pm_ops, 513 .of_match_table = dwc_eth_dwmac_match, 514 }, 515 }; 516 module_platform_driver(dwc_eth_dwmac_driver); 517 518 MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>"); 519 MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver"); 520 MODULE_LICENSE("GPL v2"); 521