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.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_slave; 33 34 struct gpio_desc *reset; 35 }; 36 37 static struct clk *dwc_eth_find_clk(struct plat_stmmacenet_data *plat_dat, 38 const char *name) 39 { 40 for (int i = 0; i < plat_dat->num_clks; i++) 41 if (strcmp(plat_dat->clks[i].id, name) == 0) 42 return plat_dat->clks[i].clk; 43 44 return NULL; 45 } 46 47 static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, 48 struct plat_stmmacenet_data *plat_dat) 49 { 50 struct device *dev = &pdev->dev; 51 u32 burst_map = 0; 52 u32 bit_index = 0; 53 u32 a_index = 0; 54 55 if (!plat_dat->axi) { 56 plat_dat->axi = devm_kzalloc(&pdev->dev, 57 sizeof(struct stmmac_axi), 58 GFP_KERNEL); 59 60 if (!plat_dat->axi) 61 return -ENOMEM; 62 } 63 64 plat_dat->axi->axi_lpi_en = device_property_read_bool(dev, 65 "snps,en-lpi"); 66 if (device_property_read_u32(dev, "snps,write-requests", 67 &plat_dat->axi->axi_wr_osr_lmt)) { 68 /** 69 * Since the register has a reset value of 1, if property 70 * is missing, default to 1. 71 */ 72 plat_dat->axi->axi_wr_osr_lmt = 1; 73 } else { 74 /** 75 * If property exists, to keep the behavior from dwc_eth_qos, 76 * subtract one after parsing. 77 */ 78 plat_dat->axi->axi_wr_osr_lmt--; 79 } 80 81 if (device_property_read_u32(dev, "snps,read-requests", 82 &plat_dat->axi->axi_rd_osr_lmt)) { 83 /** 84 * Since the register has a reset value of 1, if property 85 * is missing, default to 1. 86 */ 87 plat_dat->axi->axi_rd_osr_lmt = 1; 88 } else { 89 /** 90 * If property exists, to keep the behavior from dwc_eth_qos, 91 * subtract one after parsing. 92 */ 93 plat_dat->axi->axi_rd_osr_lmt--; 94 } 95 device_property_read_u32(dev, "snps,burst-map", &burst_map); 96 97 /* converts burst-map bitmask to burst array */ 98 for (bit_index = 0; bit_index < 7; bit_index++) { 99 if (burst_map & (1 << bit_index)) { 100 switch (bit_index) { 101 case 0: 102 plat_dat->axi->axi_blen[a_index] = 4; break; 103 case 1: 104 plat_dat->axi->axi_blen[a_index] = 8; break; 105 case 2: 106 plat_dat->axi->axi_blen[a_index] = 16; break; 107 case 3: 108 plat_dat->axi->axi_blen[a_index] = 32; break; 109 case 4: 110 plat_dat->axi->axi_blen[a_index] = 64; break; 111 case 5: 112 plat_dat->axi->axi_blen[a_index] = 128; break; 113 case 6: 114 plat_dat->axi->axi_blen[a_index] = 256; break; 115 default: 116 break; 117 } 118 a_index++; 119 } 120 } 121 122 /* dwc-qos needs GMAC4, AAL, TSO and PMT */ 123 plat_dat->has_gmac4 = 1; 124 plat_dat->dma_cfg->aal = 1; 125 plat_dat->flags |= STMMAC_FLAG_TSO_EN; 126 plat_dat->pmt = 1; 127 128 return 0; 129 } 130 131 static int dwc_qos_probe(struct platform_device *pdev, 132 struct plat_stmmacenet_data *plat_dat, 133 struct stmmac_resources *stmmac_res) 134 { 135 plat_dat->pclk = dwc_eth_find_clk(plat_dat, "phy_ref_clk"); 136 137 return 0; 138 } 139 140 #define SDMEMCOMPPADCTRL 0x8800 141 #define SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD BIT(31) 142 143 #define AUTO_CAL_CONFIG 0x8804 144 #define AUTO_CAL_CONFIG_START BIT(31) 145 #define AUTO_CAL_CONFIG_ENABLE BIT(29) 146 147 #define AUTO_CAL_STATUS 0x880c 148 #define AUTO_CAL_STATUS_ACTIVE BIT(31) 149 150 static void tegra_eqos_fix_speed(void *priv, int speed, unsigned int mode) 151 { 152 struct tegra_eqos *eqos = priv; 153 bool needs_calibration = false; 154 u32 value; 155 int err; 156 157 switch (speed) { 158 case SPEED_1000: 159 case SPEED_100: 160 needs_calibration = true; 161 fallthrough; 162 163 case SPEED_10: 164 break; 165 166 default: 167 dev_err(eqos->dev, "invalid speed %d\n", speed); 168 break; 169 } 170 171 if (needs_calibration) { 172 /* calibrate */ 173 value = readl(eqos->regs + SDMEMCOMPPADCTRL); 174 value |= SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD; 175 writel(value, eqos->regs + SDMEMCOMPPADCTRL); 176 177 udelay(1); 178 179 value = readl(eqos->regs + AUTO_CAL_CONFIG); 180 value |= AUTO_CAL_CONFIG_START | AUTO_CAL_CONFIG_ENABLE; 181 writel(value, eqos->regs + AUTO_CAL_CONFIG); 182 183 err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS, 184 value, 185 value & AUTO_CAL_STATUS_ACTIVE, 186 1, 10); 187 if (err < 0) { 188 dev_err(eqos->dev, "calibration did not start\n"); 189 goto failed; 190 } 191 192 err = readl_poll_timeout_atomic(eqos->regs + AUTO_CAL_STATUS, 193 value, 194 (value & AUTO_CAL_STATUS_ACTIVE) == 0, 195 20, 200); 196 if (err < 0) { 197 dev_err(eqos->dev, "calibration didn't finish\n"); 198 goto failed; 199 } 200 201 failed: 202 value = readl(eqos->regs + SDMEMCOMPPADCTRL); 203 value &= ~SDMEMCOMPPADCTRL_PAD_E_INPUT_OR_E_PWRD; 204 writel(value, eqos->regs + SDMEMCOMPPADCTRL); 205 } else { 206 value = readl(eqos->regs + AUTO_CAL_CONFIG); 207 value &= ~AUTO_CAL_CONFIG_ENABLE; 208 writel(value, eqos->regs + AUTO_CAL_CONFIG); 209 } 210 } 211 212 static int tegra_eqos_init(struct platform_device *pdev, void *priv) 213 { 214 struct tegra_eqos *eqos = priv; 215 unsigned long rate; 216 u32 value; 217 218 rate = clk_get_rate(eqos->clk_slave); 219 220 value = (rate / 1000000) - 1; 221 writel(value, eqos->regs + GMAC_1US_TIC_COUNTER); 222 223 return 0; 224 } 225 226 static int tegra_eqos_probe(struct platform_device *pdev, 227 struct plat_stmmacenet_data *plat_dat, 228 struct stmmac_resources *res) 229 { 230 struct device *dev = &pdev->dev; 231 struct tegra_eqos *eqos; 232 int err; 233 234 eqos = devm_kzalloc(&pdev->dev, sizeof(*eqos), GFP_KERNEL); 235 if (!eqos) 236 return -ENOMEM; 237 238 eqos->dev = &pdev->dev; 239 eqos->regs = res->addr; 240 eqos->clk_slave = plat_dat->stmmac_clk; 241 242 if (!is_of_node(dev->fwnode)) 243 goto bypass_clk_reset_gpio; 244 245 plat_dat->clk_tx_i = dwc_eth_find_clk(plat_dat, "tx"); 246 247 eqos->reset = devm_gpiod_get(&pdev->dev, "phy-reset", GPIOD_OUT_HIGH); 248 if (IS_ERR(eqos->reset)) { 249 err = PTR_ERR(eqos->reset); 250 return err; 251 } 252 253 usleep_range(2000, 4000); 254 gpiod_set_value(eqos->reset, 0); 255 256 /* MDIO bus was already reset just above */ 257 plat_dat->mdio_bus_data->needs_reset = false; 258 259 eqos->rst = devm_reset_control_get(&pdev->dev, "eqos"); 260 if (IS_ERR(eqos->rst)) { 261 err = PTR_ERR(eqos->rst); 262 goto reset_phy; 263 } 264 265 err = reset_control_assert(eqos->rst); 266 if (err < 0) 267 goto reset_phy; 268 269 usleep_range(2000, 4000); 270 271 err = reset_control_deassert(eqos->rst); 272 if (err < 0) 273 goto reset_phy; 274 275 usleep_range(2000, 4000); 276 277 bypass_clk_reset_gpio: 278 plat_dat->fix_mac_speed = tegra_eqos_fix_speed; 279 plat_dat->set_clk_tx_rate = stmmac_set_clk_tx_rate; 280 plat_dat->init = tegra_eqos_init; 281 plat_dat->bsp_priv = eqos; 282 plat_dat->flags |= STMMAC_FLAG_SPH_DISABLE; 283 284 err = tegra_eqos_init(pdev, eqos); 285 if (err < 0) 286 goto reset; 287 288 return 0; 289 reset: 290 reset_control_assert(eqos->rst); 291 reset_phy: 292 gpiod_set_value(eqos->reset, 1); 293 294 return err; 295 } 296 297 static void tegra_eqos_remove(struct platform_device *pdev) 298 { 299 struct tegra_eqos *eqos = get_stmmac_bsp_priv(&pdev->dev); 300 301 reset_control_assert(eqos->rst); 302 gpiod_set_value(eqos->reset, 1); 303 } 304 305 struct dwc_eth_dwmac_data { 306 int (*probe)(struct platform_device *pdev, 307 struct plat_stmmacenet_data *plat_dat, 308 struct stmmac_resources *res); 309 void (*remove)(struct platform_device *pdev); 310 const char *stmmac_clk_name; 311 }; 312 313 static const struct dwc_eth_dwmac_data dwc_qos_data = { 314 .probe = dwc_qos_probe, 315 .stmmac_clk_name = "apb_pclk", 316 }; 317 318 static const struct dwc_eth_dwmac_data tegra_eqos_data = { 319 .probe = tegra_eqos_probe, 320 .remove = tegra_eqos_remove, 321 .stmmac_clk_name = "slave_bus", 322 }; 323 324 static const struct dwc_eth_dwmac_data fsd_eqos_data = { 325 .stmmac_clk_name = "slave_bus", 326 }; 327 328 static int dwc_eth_dwmac_probe(struct platform_device *pdev) 329 { 330 const struct dwc_eth_dwmac_data *data; 331 struct plat_stmmacenet_data *plat_dat; 332 struct stmmac_resources stmmac_res; 333 int ret; 334 335 data = device_get_match_data(&pdev->dev); 336 337 memset(&stmmac_res, 0, sizeof(struct stmmac_resources)); 338 339 /** 340 * Since stmmac_platform supports name IRQ only, basic platform 341 * resource initialization is done in the glue logic. 342 */ 343 stmmac_res.irq = platform_get_irq(pdev, 0); 344 if (stmmac_res.irq < 0) 345 return stmmac_res.irq; 346 stmmac_res.wol_irq = stmmac_res.irq; 347 348 stmmac_res.addr = devm_platform_ioremap_resource(pdev, 0); 349 if (IS_ERR(stmmac_res.addr)) 350 return PTR_ERR(stmmac_res.addr); 351 352 plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac); 353 if (IS_ERR(plat_dat)) 354 return PTR_ERR(plat_dat); 355 356 ret = devm_clk_bulk_get_all(&pdev->dev, &plat_dat->clks); 357 if (ret < 0) 358 return dev_err_probe(&pdev->dev, ret, "Failed to retrieve all required clocks\n"); 359 plat_dat->num_clks = ret; 360 361 ret = clk_bulk_prepare_enable(plat_dat->num_clks, plat_dat->clks); 362 if (ret) 363 return dev_err_probe(&pdev->dev, ret, "Failed to enable clocks\n"); 364 365 plat_dat->stmmac_clk = dwc_eth_find_clk(plat_dat, 366 data->stmmac_clk_name); 367 368 if (data->probe) 369 ret = data->probe(pdev, plat_dat, &stmmac_res); 370 if (ret < 0) { 371 dev_err_probe(&pdev->dev, ret, "failed to probe subdriver\n"); 372 clk_bulk_disable_unprepare(plat_dat->num_clks, plat_dat->clks); 373 return ret; 374 } 375 376 ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); 377 if (ret) 378 goto remove; 379 380 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 381 if (ret) 382 goto remove; 383 384 return ret; 385 386 remove: 387 if (data->remove) 388 data->remove(pdev); 389 390 return ret; 391 } 392 393 static void dwc_eth_dwmac_remove(struct platform_device *pdev) 394 { 395 const struct dwc_eth_dwmac_data *data = device_get_match_data(&pdev->dev); 396 struct plat_stmmacenet_data *plat_dat = dev_get_platdata(&pdev->dev); 397 398 stmmac_dvr_remove(&pdev->dev); 399 400 if (data->remove) 401 data->remove(pdev); 402 403 if (plat_dat) 404 clk_bulk_disable_unprepare(plat_dat->num_clks, plat_dat->clks); 405 } 406 407 static const struct of_device_id dwc_eth_dwmac_match[] = { 408 { .compatible = "snps,dwc-qos-ethernet-4.10", .data = &dwc_qos_data }, 409 { .compatible = "nvidia,tegra186-eqos", .data = &tegra_eqos_data }, 410 { .compatible = "tesla,fsd-ethqos", .data = &fsd_eqos_data }, 411 { } 412 }; 413 MODULE_DEVICE_TABLE(of, dwc_eth_dwmac_match); 414 415 static struct platform_driver dwc_eth_dwmac_driver = { 416 .probe = dwc_eth_dwmac_probe, 417 .remove = dwc_eth_dwmac_remove, 418 .driver = { 419 .name = "dwc-eth-dwmac", 420 .pm = &stmmac_pltfr_pm_ops, 421 .of_match_table = dwc_eth_dwmac_match, 422 }, 423 }; 424 module_platform_driver(dwc_eth_dwmac_driver); 425 426 MODULE_AUTHOR("Joao Pinto <jpinto@synopsys.com>"); 427 MODULE_DESCRIPTION("Synopsys DWC Ethernet Quality-of-Service v4.10a driver"); 428 MODULE_LICENSE("GPL v2"); 429