dwmac-dwc-qos-eth.c 12 KB

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