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