1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/iommu.h> 3 #include <linux/platform_device.h> 4 #include <linux/of.h> 5 #include <linux/module.h> 6 #include <linux/stmmac.h> 7 #include <linux/clk.h> 8 9 #include "stmmac_platform.h" 10 11 static const char *const mgbe_clks[] = { 12 "rx-pcs", "tx", "tx-pcs", "mac-divider", "mac", "mgbe", "ptp-ref", "mac" 13 }; 14 15 struct tegra_mgbe { 16 struct device *dev; 17 18 struct clk_bulk_data *clks; 19 20 struct reset_control *rst_mac; 21 struct reset_control *rst_pcs; 22 23 u32 iommu_sid; 24 25 void __iomem *hv; 26 void __iomem *regs; 27 void __iomem *xpcs; 28 29 struct mii_bus *mii; 30 }; 31 32 #define XPCS_WRAP_UPHY_RX_CONTROL 0x801c 33 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_SW_OVRD BIT(31) 34 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_PCS_PHY_RDY BIT(10) 35 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_CDR_RESET BIT(9) 36 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_CAL_EN BIT(8) 37 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_SLEEP (BIT(7) | BIT(6)) 38 #define XPCS_WRAP_UPHY_RX_CONTROL_AUX_RX_IDDQ BIT(5) 39 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_IDDQ BIT(4) 40 #define XPCS_WRAP_UPHY_RX_CONTROL_RX_DATA_EN BIT(0) 41 #define XPCS_WRAP_UPHY_HW_INIT_CTRL 0x8020 42 #define XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN BIT(0) 43 #define XPCS_WRAP_UPHY_HW_INIT_CTRL_RX_EN BIT(2) 44 #define XPCS_WRAP_UPHY_STATUS 0x8044 45 #define XPCS_WRAP_UPHY_STATUS_TX_P_UP BIT(0) 46 #define XPCS_WRAP_IRQ_STATUS 0x8050 47 #define XPCS_WRAP_IRQ_STATUS_PCS_LINK_STS BIT(6) 48 49 #define XPCS_REG_ADDR_SHIFT 10 50 #define XPCS_REG_ADDR_MASK 0x1fff 51 #define XPCS_ADDR 0x3fc 52 53 #define MGBE_WRAP_COMMON_INTR_ENABLE 0x8704 54 #define MAC_SBD_INTR BIT(2) 55 #define MGBE_WRAP_AXI_ASID0_CTRL 0x8400 56 57 static int __maybe_unused tegra_mgbe_suspend(struct device *dev) 58 { 59 struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(dev); 60 int err; 61 62 err = stmmac_suspend(dev); 63 if (err) 64 return err; 65 66 clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks); 67 68 return reset_control_assert(mgbe->rst_mac); 69 } 70 71 static int __maybe_unused tegra_mgbe_resume(struct device *dev) 72 { 73 struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(dev); 74 u32 value; 75 int err; 76 77 err = clk_bulk_prepare_enable(ARRAY_SIZE(mgbe_clks), mgbe->clks); 78 if (err < 0) 79 return err; 80 81 err = reset_control_deassert(mgbe->rst_mac); 82 if (err < 0) 83 return err; 84 85 /* Enable common interrupt at wrapper level */ 86 writel(MAC_SBD_INTR, mgbe->regs + MGBE_WRAP_COMMON_INTR_ENABLE); 87 88 /* Program SID */ 89 writel(mgbe->iommu_sid, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL); 90 91 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_STATUS); 92 if ((value & XPCS_WRAP_UPHY_STATUS_TX_P_UP) == 0) { 93 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL); 94 value |= XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN; 95 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL); 96 } 97 98 err = readl_poll_timeout(mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL, value, 99 (value & XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN) == 0, 100 500, 500 * 2000); 101 if (err < 0) { 102 dev_err(mgbe->dev, "timeout waiting for TX lane to become enabled\n"); 103 clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks); 104 return err; 105 } 106 107 err = stmmac_resume(dev); 108 if (err < 0) 109 clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks); 110 111 return err; 112 } 113 114 static int mgbe_uphy_lane_bringup_serdes_up(struct net_device *ndev, void *mgbe_data) 115 { 116 struct tegra_mgbe *mgbe = (struct tegra_mgbe *)mgbe_data; 117 u32 value; 118 int err; 119 120 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 121 value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_SW_OVRD; 122 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 123 124 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 125 value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_IDDQ; 126 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 127 128 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 129 value &= ~XPCS_WRAP_UPHY_RX_CONTROL_AUX_RX_IDDQ; 130 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 131 132 usleep_range(10, 20); /* 50ns min delay needed as per HW design */ 133 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 134 value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_SLEEP; 135 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 136 137 usleep_range(10, 20); /* 500ns min delay needed as per HW design */ 138 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 139 value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_CAL_EN; 140 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 141 142 err = readl_poll_timeout(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL, value, 143 (value & XPCS_WRAP_UPHY_RX_CONTROL_RX_CAL_EN) == 0, 144 1000, 1000 * 2000); 145 if (err < 0) { 146 dev_err(mgbe->dev, "timeout waiting for RX calibration to become enabled\n"); 147 return err; 148 } 149 150 usleep_range(10, 20); /* 50ns min delay needed as per HW design */ 151 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 152 value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_DATA_EN; 153 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 154 155 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 156 value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_PCS_PHY_RDY; 157 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 158 159 usleep_range(10, 20); /* 50ns min delay needed as per HW design */ 160 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 161 value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_CDR_RESET; 162 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 163 164 usleep_range(10, 20); /* 50ns min delay needed as per HW design */ 165 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 166 value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_PCS_PHY_RDY; 167 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 168 169 msleep(30); /* 30ms delay needed as per HW design */ 170 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 171 value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_CDR_RESET; 172 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 173 174 err = readl_poll_timeout(mgbe->xpcs + XPCS_WRAP_IRQ_STATUS, value, 175 value & XPCS_WRAP_IRQ_STATUS_PCS_LINK_STS, 176 500, 500 * 2000); 177 if (err < 0) { 178 dev_err(mgbe->dev, "timeout waiting for link to become ready\n"); 179 return err; 180 } 181 182 /* clear status */ 183 writel(value, mgbe->xpcs + XPCS_WRAP_IRQ_STATUS); 184 185 return 0; 186 } 187 188 static void mgbe_uphy_lane_bringup_serdes_down(struct net_device *ndev, void *mgbe_data) 189 { 190 struct tegra_mgbe *mgbe = (struct tegra_mgbe *)mgbe_data; 191 u32 value; 192 193 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 194 value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_SW_OVRD; 195 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 196 197 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 198 value &= ~XPCS_WRAP_UPHY_RX_CONTROL_RX_DATA_EN; 199 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 200 201 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 202 value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_SLEEP; 203 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 204 205 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 206 value |= XPCS_WRAP_UPHY_RX_CONTROL_AUX_RX_IDDQ; 207 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 208 209 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 210 value |= XPCS_WRAP_UPHY_RX_CONTROL_RX_IDDQ; 211 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_RX_CONTROL); 212 } 213 214 static int tegra_mgbe_probe(struct platform_device *pdev) 215 { 216 struct plat_stmmacenet_data *plat; 217 struct stmmac_resources res; 218 struct tegra_mgbe *mgbe; 219 int irq, err, i; 220 u32 value; 221 222 mgbe = devm_kzalloc(&pdev->dev, sizeof(*mgbe), GFP_KERNEL); 223 if (!mgbe) 224 return -ENOMEM; 225 226 mgbe->dev = &pdev->dev; 227 228 memset(&res, 0, sizeof(res)); 229 230 irq = platform_get_irq(pdev, 0); 231 if (irq < 0) 232 return irq; 233 234 mgbe->hv = devm_platform_ioremap_resource_byname(pdev, "hypervisor"); 235 if (IS_ERR(mgbe->hv)) 236 return PTR_ERR(mgbe->hv); 237 238 mgbe->regs = devm_platform_ioremap_resource_byname(pdev, "mac"); 239 if (IS_ERR(mgbe->regs)) 240 return PTR_ERR(mgbe->regs); 241 242 mgbe->xpcs = devm_platform_ioremap_resource_byname(pdev, "xpcs"); 243 if (IS_ERR(mgbe->xpcs)) 244 return PTR_ERR(mgbe->xpcs); 245 246 /* get controller's stream id from iommu property in device tree */ 247 if (!tegra_dev_iommu_get_stream_id(mgbe->dev, &mgbe->iommu_sid)) { 248 dev_err(mgbe->dev, "failed to get iommu stream id\n"); 249 return -EINVAL; 250 } 251 252 res.addr = mgbe->regs; 253 res.irq = irq; 254 255 mgbe->clks = devm_kcalloc(&pdev->dev, ARRAY_SIZE(mgbe_clks), 256 sizeof(*mgbe->clks), GFP_KERNEL); 257 if (!mgbe->clks) 258 return -ENOMEM; 259 260 for (i = 0; i < ARRAY_SIZE(mgbe_clks); i++) 261 mgbe->clks[i].id = mgbe_clks[i]; 262 263 err = devm_clk_bulk_get(mgbe->dev, ARRAY_SIZE(mgbe_clks), mgbe->clks); 264 if (err < 0) 265 return err; 266 267 err = clk_bulk_prepare_enable(ARRAY_SIZE(mgbe_clks), mgbe->clks); 268 if (err < 0) 269 return err; 270 271 /* Perform MAC reset */ 272 mgbe->rst_mac = devm_reset_control_get(&pdev->dev, "mac"); 273 if (IS_ERR(mgbe->rst_mac)) { 274 err = PTR_ERR(mgbe->rst_mac); 275 goto disable_clks; 276 } 277 278 err = reset_control_assert(mgbe->rst_mac); 279 if (err < 0) 280 goto disable_clks; 281 282 usleep_range(2000, 4000); 283 284 err = reset_control_deassert(mgbe->rst_mac); 285 if (err < 0) 286 goto disable_clks; 287 288 /* Perform PCS reset */ 289 mgbe->rst_pcs = devm_reset_control_get(&pdev->dev, "pcs"); 290 if (IS_ERR(mgbe->rst_pcs)) { 291 err = PTR_ERR(mgbe->rst_pcs); 292 goto disable_clks; 293 } 294 295 err = reset_control_assert(mgbe->rst_pcs); 296 if (err < 0) 297 goto disable_clks; 298 299 usleep_range(2000, 4000); 300 301 err = reset_control_deassert(mgbe->rst_pcs); 302 if (err < 0) 303 goto disable_clks; 304 305 plat = devm_stmmac_probe_config_dt(pdev, res.mac); 306 if (IS_ERR(plat)) { 307 err = PTR_ERR(plat); 308 goto disable_clks; 309 } 310 311 plat->has_xgmac = 1; 312 plat->flags |= STMMAC_FLAG_TSO_EN; 313 plat->pmt = 1; 314 plat->bsp_priv = mgbe; 315 316 if (!plat->mdio_node) 317 plat->mdio_node = of_get_child_by_name(pdev->dev.of_node, "mdio"); 318 319 if (!plat->mdio_bus_data) { 320 plat->mdio_bus_data = devm_kzalloc(&pdev->dev, sizeof(*plat->mdio_bus_data), 321 GFP_KERNEL); 322 if (!plat->mdio_bus_data) { 323 err = -ENOMEM; 324 goto disable_clks; 325 } 326 } 327 328 plat->mdio_bus_data->needs_reset = true; 329 330 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_STATUS); 331 if ((value & XPCS_WRAP_UPHY_STATUS_TX_P_UP) == 0) { 332 value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL); 333 value |= XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN; 334 writel(value, mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL); 335 } 336 337 err = readl_poll_timeout(mgbe->xpcs + XPCS_WRAP_UPHY_HW_INIT_CTRL, value, 338 (value & XPCS_WRAP_UPHY_HW_INIT_CTRL_TX_EN) == 0, 339 500, 500 * 2000); 340 if (err < 0) { 341 dev_err(mgbe->dev, "timeout waiting for TX lane to become enabled\n"); 342 goto disable_clks; 343 } 344 345 plat->serdes_powerup = mgbe_uphy_lane_bringup_serdes_up; 346 plat->serdes_powerdown = mgbe_uphy_lane_bringup_serdes_down; 347 348 /* Tx FIFO Size - 128KB */ 349 plat->tx_fifo_size = 131072; 350 /* Rx FIFO Size - 192KB */ 351 plat->rx_fifo_size = 196608; 352 353 /* Enable common interrupt at wrapper level */ 354 writel(MAC_SBD_INTR, mgbe->regs + MGBE_WRAP_COMMON_INTR_ENABLE); 355 356 /* Program SID */ 357 writel(mgbe->iommu_sid, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL); 358 359 plat->flags |= STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP; 360 361 err = stmmac_dvr_probe(&pdev->dev, plat, &res); 362 if (err < 0) 363 goto disable_clks; 364 365 return 0; 366 367 disable_clks: 368 clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks); 369 370 return err; 371 } 372 373 static void tegra_mgbe_remove(struct platform_device *pdev) 374 { 375 struct tegra_mgbe *mgbe = get_stmmac_bsp_priv(&pdev->dev); 376 377 clk_bulk_disable_unprepare(ARRAY_SIZE(mgbe_clks), mgbe->clks); 378 379 stmmac_pltfr_remove(pdev); 380 } 381 382 static const struct of_device_id tegra_mgbe_match[] = { 383 { .compatible = "nvidia,tegra234-mgbe", }, 384 { } 385 }; 386 MODULE_DEVICE_TABLE(of, tegra_mgbe_match); 387 388 static SIMPLE_DEV_PM_OPS(tegra_mgbe_pm_ops, tegra_mgbe_suspend, tegra_mgbe_resume); 389 390 static struct platform_driver tegra_mgbe_driver = { 391 .probe = tegra_mgbe_probe, 392 .remove = tegra_mgbe_remove, 393 .driver = { 394 .name = "tegra-mgbe", 395 .pm = &tegra_mgbe_pm_ops, 396 .of_match_table = tegra_mgbe_match, 397 }, 398 }; 399 module_platform_driver(tegra_mgbe_driver); 400 401 MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>"); 402 MODULE_DESCRIPTION("NVIDIA Tegra MGBE driver"); 403 MODULE_LICENSE("GPL"); 404