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