dwmac-meson8b.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Amlogic Meson8b, Meson8m2 and GXBB DWMAC glue layer
  4. *
  5. * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
  6. */
  7. #include <linux/bitfield.h>
  8. #include <linux/clk.h>
  9. #include <linux/clk-provider.h>
  10. #include <linux/device.h>
  11. #include <linux/ethtool.h>
  12. #include <linux/io.h>
  13. #include <linux/ioport.h>
  14. #include <linux/module.h>
  15. #include <linux/of.h>
  16. #include <linux/of_net.h>
  17. #include <linux/mfd/syscon.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/stmmac.h>
  20. #include "stmmac_platform.h"
  21. #define PRG_ETH0 0x0
  22. #define PRG_ETH0_RGMII_MODE BIT(0)
  23. #define PRG_ETH0_EXT_PHY_MODE_MASK GENMASK(2, 0)
  24. /* mux to choose between fclk_div2 (bit unset) and mpll2 (bit set) */
  25. #define PRG_ETH0_CLK_M250_SEL_MASK GENMASK(4, 4)
  26. /* TX clock delay in ns = "8ns / 4 * tx_dly_val" (where 8ns are exactly one
  27. * cycle of the 125MHz RGMII TX clock):
  28. * 0ns = 0x0, 2ns = 0x1, 4ns = 0x2, 6ns = 0x3
  29. */
  30. #define PRG_ETH0_TXDLY_MASK GENMASK(6, 5)
  31. /* divider for the result of m250_sel */
  32. #define PRG_ETH0_CLK_M250_DIV_SHIFT 7
  33. #define PRG_ETH0_CLK_M250_DIV_WIDTH 3
  34. #define PRG_ETH0_RGMII_TX_CLK_EN 10
  35. #define PRG_ETH0_INVERTED_RMII_CLK BIT(11)
  36. #define PRG_ETH0_TX_AND_PHY_REF_CLK BIT(12)
  37. /* Bypass (= 0, the signal from the GPIO input directly connects to the
  38. * internal sampling) or enable (= 1) the internal logic for RXEN and RXD[3:0]
  39. * timing tuning.
  40. */
  41. #define PRG_ETH0_ADJ_ENABLE BIT(13)
  42. /* Controls whether the RXEN and RXD[3:0] signals should be aligned with the
  43. * input RX rising/falling edge and sent to the Ethernet internals. This sets
  44. * the automatically delay and skew automatically (internally).
  45. */
  46. #define PRG_ETH0_ADJ_SETUP BIT(14)
  47. /* An internal counter based on the "timing-adjustment" clock. The counter is
  48. * cleared on both, the falling and rising edge of the RX_CLK. This selects the
  49. * delay (= the counter value) when to start sampling RXEN and RXD[3:0].
  50. */
  51. #define PRG_ETH0_ADJ_DELAY GENMASK(19, 15)
  52. /* Adjusts the skew between each bit of RXEN and RXD[3:0]. If a signal has a
  53. * large input delay, the bit for that signal (RXEN = bit 0, RXD[3] = bit 1,
  54. * ...) can be configured to be 1 to compensate for a delay of about 1ns.
  55. */
  56. #define PRG_ETH0_ADJ_SKEW GENMASK(24, 20)
  57. #define PRG_ETH1 0x4
  58. /* Defined for adding a delay to the input RX_CLK for better timing.
  59. * Each step is 200ps. These bits are used with external RGMII PHYs
  60. * because RGMII RX only has the small window. cfg_rxclk_dly can
  61. * adjust the window between RX_CLK and RX_DATA and improve the stability
  62. * of "rx data valid".
  63. */
  64. #define PRG_ETH1_CFG_RXCLK_DLY GENMASK(19, 16)
  65. struct meson8b_dwmac;
  66. struct meson8b_dwmac_data {
  67. int (*set_phy_mode)(struct meson8b_dwmac *dwmac);
  68. bool has_prg_eth1_rgmii_rx_delay;
  69. };
  70. struct meson8b_dwmac {
  71. struct device *dev;
  72. void __iomem *regs;
  73. const struct meson8b_dwmac_data *data;
  74. phy_interface_t phy_mode;
  75. struct clk *rgmii_tx_clk;
  76. u32 tx_delay_ns;
  77. u32 rx_delay_ps;
  78. struct clk *timing_adj_clk;
  79. };
  80. struct meson8b_dwmac_clk_configs {
  81. struct clk_mux m250_mux;
  82. struct clk_divider m250_div;
  83. struct clk_fixed_factor fixed_div2;
  84. struct clk_gate rgmii_tx_en;
  85. };
  86. static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg,
  87. u32 mask, u32 value)
  88. {
  89. u32 data;
  90. data = readl(dwmac->regs + reg);
  91. data &= ~mask;
  92. data |= (value & mask);
  93. writel(data, dwmac->regs + reg);
  94. }
  95. static struct clk *meson8b_dwmac_register_clk(struct meson8b_dwmac *dwmac,
  96. const char *name_suffix,
  97. const struct clk_parent_data *parents,
  98. int num_parents,
  99. const struct clk_ops *ops,
  100. struct clk_hw *hw)
  101. {
  102. struct clk_init_data init = { };
  103. char clk_name[32];
  104. snprintf(clk_name, sizeof(clk_name), "%s#%s", dev_name(dwmac->dev),
  105. name_suffix);
  106. init.name = clk_name;
  107. init.ops = ops;
  108. init.flags = CLK_SET_RATE_PARENT;
  109. init.parent_data = parents;
  110. init.num_parents = num_parents;
  111. hw->init = &init;
  112. return devm_clk_register(dwmac->dev, hw);
  113. }
  114. static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac)
  115. {
  116. struct clk *clk;
  117. struct device *dev = dwmac->dev;
  118. static const struct clk_parent_data mux_parents[] = {
  119. { .fw_name = "clkin0", },
  120. { .index = -1, },
  121. };
  122. static const struct clk_div_table div_table[] = {
  123. { .div = 2, .val = 2, },
  124. { .div = 3, .val = 3, },
  125. { .div = 4, .val = 4, },
  126. { .div = 5, .val = 5, },
  127. { .div = 6, .val = 6, },
  128. { .div = 7, .val = 7, },
  129. { /* end of array */ }
  130. };
  131. struct meson8b_dwmac_clk_configs *clk_configs;
  132. struct clk_parent_data parent_data = { };
  133. clk_configs = devm_kzalloc(dev, sizeof(*clk_configs), GFP_KERNEL);
  134. if (!clk_configs)
  135. return -ENOMEM;
  136. clk_configs->m250_mux.reg = dwmac->regs + PRG_ETH0;
  137. clk_configs->m250_mux.shift = __ffs(PRG_ETH0_CLK_M250_SEL_MASK);
  138. clk_configs->m250_mux.mask = PRG_ETH0_CLK_M250_SEL_MASK >>
  139. clk_configs->m250_mux.shift;
  140. clk = meson8b_dwmac_register_clk(dwmac, "m250_sel", mux_parents,
  141. ARRAY_SIZE(mux_parents), &clk_mux_ops,
  142. &clk_configs->m250_mux.hw);
  143. if (WARN_ON(IS_ERR(clk)))
  144. return PTR_ERR(clk);
  145. parent_data.hw = &clk_configs->m250_mux.hw;
  146. clk_configs->m250_div.reg = dwmac->regs + PRG_ETH0;
  147. clk_configs->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
  148. clk_configs->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
  149. clk_configs->m250_div.table = div_table;
  150. clk_configs->m250_div.flags = CLK_DIVIDER_ALLOW_ZERO |
  151. CLK_DIVIDER_ROUND_CLOSEST;
  152. clk = meson8b_dwmac_register_clk(dwmac, "m250_div", &parent_data, 1,
  153. &clk_divider_ops,
  154. &clk_configs->m250_div.hw);
  155. if (WARN_ON(IS_ERR(clk)))
  156. return PTR_ERR(clk);
  157. parent_data.hw = &clk_configs->m250_div.hw;
  158. clk_configs->fixed_div2.mult = 1;
  159. clk_configs->fixed_div2.div = 2;
  160. clk = meson8b_dwmac_register_clk(dwmac, "fixed_div2", &parent_data, 1,
  161. &clk_fixed_factor_ops,
  162. &clk_configs->fixed_div2.hw);
  163. if (WARN_ON(IS_ERR(clk)))
  164. return PTR_ERR(clk);
  165. parent_data.hw = &clk_configs->fixed_div2.hw;
  166. clk_configs->rgmii_tx_en.reg = dwmac->regs + PRG_ETH0;
  167. clk_configs->rgmii_tx_en.bit_idx = PRG_ETH0_RGMII_TX_CLK_EN;
  168. clk = meson8b_dwmac_register_clk(dwmac, "rgmii_tx_en", &parent_data, 1,
  169. &clk_gate_ops,
  170. &clk_configs->rgmii_tx_en.hw);
  171. if (WARN_ON(IS_ERR(clk)))
  172. return PTR_ERR(clk);
  173. dwmac->rgmii_tx_clk = clk;
  174. return 0;
  175. }
  176. static int meson8b_set_phy_mode(struct meson8b_dwmac *dwmac)
  177. {
  178. switch (dwmac->phy_mode) {
  179. case PHY_INTERFACE_MODE_RGMII:
  180. case PHY_INTERFACE_MODE_RGMII_RXID:
  181. case PHY_INTERFACE_MODE_RGMII_ID:
  182. case PHY_INTERFACE_MODE_RGMII_TXID:
  183. /* enable RGMII mode */
  184. meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
  185. PRG_ETH0_RGMII_MODE,
  186. PRG_ETH0_RGMII_MODE);
  187. break;
  188. case PHY_INTERFACE_MODE_RMII:
  189. /* disable RGMII mode -> enables RMII mode */
  190. meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
  191. PRG_ETH0_RGMII_MODE, 0);
  192. break;
  193. default:
  194. dev_err(dwmac->dev, "fail to set phy-mode %s\n",
  195. phy_modes(dwmac->phy_mode));
  196. return -EINVAL;
  197. }
  198. return 0;
  199. }
  200. static int meson_axg_set_phy_mode(struct meson8b_dwmac *dwmac)
  201. {
  202. int phy_intf_sel;
  203. phy_intf_sel = stmmac_get_phy_intf_sel(dwmac->phy_mode);
  204. if (phy_intf_sel != PHY_INTF_SEL_RGMII &&
  205. phy_intf_sel != PHY_INTF_SEL_RMII) {
  206. dev_err(dwmac->dev, "fail to set phy-mode %s\n",
  207. phy_modes(dwmac->phy_mode));
  208. return phy_intf_sel < 0 ? phy_intf_sel : -EINVAL;
  209. }
  210. meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_EXT_PHY_MODE_MASK,
  211. FIELD_PREP(PRG_ETH0_EXT_PHY_MODE_MASK,
  212. phy_intf_sel));
  213. return 0;
  214. }
  215. static void meson8b_clk_disable_unprepare(void *data)
  216. {
  217. clk_disable_unprepare(data);
  218. }
  219. static int meson8b_devm_clk_prepare_enable(struct meson8b_dwmac *dwmac,
  220. struct clk *clk)
  221. {
  222. int ret;
  223. ret = clk_prepare_enable(clk);
  224. if (ret)
  225. return ret;
  226. return devm_add_action_or_reset(dwmac->dev,
  227. meson8b_clk_disable_unprepare, clk);
  228. }
  229. static int meson8b_init_rgmii_delays(struct meson8b_dwmac *dwmac)
  230. {
  231. u32 tx_dly_config, rx_adj_config, cfg_rxclk_dly, delay_config;
  232. int ret;
  233. rx_adj_config = 0;
  234. cfg_rxclk_dly = 0;
  235. tx_dly_config = FIELD_PREP(PRG_ETH0_TXDLY_MASK,
  236. dwmac->tx_delay_ns >> 1);
  237. if (dwmac->data->has_prg_eth1_rgmii_rx_delay)
  238. cfg_rxclk_dly = FIELD_PREP(PRG_ETH1_CFG_RXCLK_DLY,
  239. dwmac->rx_delay_ps / 200);
  240. else if (dwmac->rx_delay_ps == 2000)
  241. rx_adj_config = PRG_ETH0_ADJ_ENABLE | PRG_ETH0_ADJ_SETUP;
  242. switch (dwmac->phy_mode) {
  243. case PHY_INTERFACE_MODE_RGMII:
  244. delay_config = tx_dly_config | rx_adj_config;
  245. break;
  246. case PHY_INTERFACE_MODE_RGMII_RXID:
  247. delay_config = tx_dly_config;
  248. cfg_rxclk_dly = 0;
  249. break;
  250. case PHY_INTERFACE_MODE_RGMII_TXID:
  251. delay_config = rx_adj_config;
  252. break;
  253. case PHY_INTERFACE_MODE_RGMII_ID:
  254. case PHY_INTERFACE_MODE_RMII:
  255. delay_config = 0;
  256. cfg_rxclk_dly = 0;
  257. break;
  258. default:
  259. dev_err(dwmac->dev, "unsupported phy-mode %s\n",
  260. phy_modes(dwmac->phy_mode));
  261. return -EINVAL;
  262. }
  263. if (delay_config & PRG_ETH0_ADJ_ENABLE) {
  264. if (!dwmac->timing_adj_clk) {
  265. dev_err(dwmac->dev,
  266. "The timing-adjustment clock is mandatory for the RX delay re-timing\n");
  267. return -EINVAL;
  268. }
  269. /* The timing adjustment logic is driven by a separate clock */
  270. ret = meson8b_devm_clk_prepare_enable(dwmac,
  271. dwmac->timing_adj_clk);
  272. if (ret) {
  273. dev_err(dwmac->dev,
  274. "Failed to enable the timing-adjustment clock\n");
  275. return ret;
  276. }
  277. }
  278. meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK |
  279. PRG_ETH0_ADJ_ENABLE | PRG_ETH0_ADJ_SETUP |
  280. PRG_ETH0_ADJ_DELAY | PRG_ETH0_ADJ_SKEW,
  281. delay_config);
  282. meson8b_dwmac_mask_bits(dwmac, PRG_ETH1, PRG_ETH1_CFG_RXCLK_DLY,
  283. cfg_rxclk_dly);
  284. return 0;
  285. }
  286. static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
  287. {
  288. int ret;
  289. if (phy_interface_mode_is_rgmii(dwmac->phy_mode)) {
  290. /* only relevant for RMII mode -> disable in RGMII mode */
  291. meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
  292. PRG_ETH0_INVERTED_RMII_CLK, 0);
  293. /* Configure the 125MHz RGMII TX clock, the IP block changes
  294. * the output automatically (= without us having to configure
  295. * a register) based on the line-speed (125MHz for Gbit speeds,
  296. * 25MHz for 100Mbit/s and 2.5MHz for 10Mbit/s).
  297. */
  298. ret = clk_set_rate(dwmac->rgmii_tx_clk, 125 * 1000 * 1000);
  299. if (ret) {
  300. dev_err(dwmac->dev,
  301. "failed to set RGMII TX clock\n");
  302. return ret;
  303. }
  304. ret = meson8b_devm_clk_prepare_enable(dwmac,
  305. dwmac->rgmii_tx_clk);
  306. if (ret) {
  307. dev_err(dwmac->dev,
  308. "failed to enable the RGMII TX clock\n");
  309. return ret;
  310. }
  311. } else {
  312. /* invert internal clk_rmii_i to generate 25/2.5 tx_rx_clk */
  313. meson8b_dwmac_mask_bits(dwmac, PRG_ETH0,
  314. PRG_ETH0_INVERTED_RMII_CLK,
  315. PRG_ETH0_INVERTED_RMII_CLK);
  316. }
  317. /* enable TX_CLK and PHY_REF_CLK generator */
  318. meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TX_AND_PHY_REF_CLK,
  319. PRG_ETH0_TX_AND_PHY_REF_CLK);
  320. return 0;
  321. }
  322. static int meson8b_dwmac_probe(struct platform_device *pdev)
  323. {
  324. struct plat_stmmacenet_data *plat_dat;
  325. struct stmmac_resources stmmac_res;
  326. struct meson8b_dwmac *dwmac;
  327. int ret;
  328. ret = stmmac_get_platform_resources(pdev, &stmmac_res);
  329. if (ret)
  330. return ret;
  331. plat_dat = devm_stmmac_probe_config_dt(pdev, stmmac_res.mac);
  332. if (IS_ERR(plat_dat))
  333. return PTR_ERR(plat_dat);
  334. dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
  335. if (!dwmac)
  336. return -ENOMEM;
  337. dwmac->data = (const struct meson8b_dwmac_data *)
  338. of_device_get_match_data(&pdev->dev);
  339. if (!dwmac->data)
  340. return -EINVAL;
  341. dwmac->regs = devm_platform_ioremap_resource(pdev, 1);
  342. if (IS_ERR(dwmac->regs))
  343. return PTR_ERR(dwmac->regs);
  344. dwmac->dev = &pdev->dev;
  345. dwmac->phy_mode = plat_dat->phy_interface;
  346. /* use 2ns as fallback since this value was previously hardcoded */
  347. if (of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay-ns",
  348. &dwmac->tx_delay_ns))
  349. dwmac->tx_delay_ns = 2;
  350. /* RX delay defaults to 0ps since this is what many boards use */
  351. if (of_property_read_u32(pdev->dev.of_node, "rx-internal-delay-ps",
  352. &dwmac->rx_delay_ps)) {
  353. if (!of_property_read_u32(pdev->dev.of_node,
  354. "amlogic,rx-delay-ns",
  355. &dwmac->rx_delay_ps))
  356. /* convert ns to ps */
  357. dwmac->rx_delay_ps *= 1000;
  358. }
  359. if (dwmac->data->has_prg_eth1_rgmii_rx_delay) {
  360. if (dwmac->rx_delay_ps > 3000 || dwmac->rx_delay_ps % 200) {
  361. dev_err(dwmac->dev,
  362. "The RGMII RX delay range is 0..3000ps in 200ps steps");
  363. return -EINVAL;
  364. }
  365. } else {
  366. if (dwmac->rx_delay_ps != 0 && dwmac->rx_delay_ps != 2000) {
  367. dev_err(dwmac->dev,
  368. "The only allowed RGMII RX delays values are: 0ps, 2000ps");
  369. return -EINVAL;
  370. }
  371. }
  372. dwmac->timing_adj_clk = devm_clk_get_optional(dwmac->dev,
  373. "timing-adjustment");
  374. if (IS_ERR(dwmac->timing_adj_clk))
  375. return PTR_ERR(dwmac->timing_adj_clk);
  376. ret = meson8b_init_rgmii_delays(dwmac);
  377. if (ret)
  378. return ret;
  379. ret = meson8b_init_rgmii_tx_clk(dwmac);
  380. if (ret)
  381. return ret;
  382. ret = dwmac->data->set_phy_mode(dwmac);
  383. if (ret)
  384. return ret;
  385. ret = meson8b_init_prg_eth(dwmac);
  386. if (ret)
  387. return ret;
  388. plat_dat->bsp_priv = dwmac;
  389. return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
  390. }
  391. static const struct meson8b_dwmac_data meson8b_dwmac_data = {
  392. .set_phy_mode = meson8b_set_phy_mode,
  393. .has_prg_eth1_rgmii_rx_delay = false,
  394. };
  395. static const struct meson8b_dwmac_data meson_axg_dwmac_data = {
  396. .set_phy_mode = meson_axg_set_phy_mode,
  397. .has_prg_eth1_rgmii_rx_delay = false,
  398. };
  399. static const struct meson8b_dwmac_data meson_g12a_dwmac_data = {
  400. .set_phy_mode = meson_axg_set_phy_mode,
  401. .has_prg_eth1_rgmii_rx_delay = true,
  402. };
  403. static const struct of_device_id meson8b_dwmac_match[] = {
  404. {
  405. .compatible = "amlogic,meson8b-dwmac",
  406. .data = &meson8b_dwmac_data,
  407. },
  408. {
  409. .compatible = "amlogic,meson8m2-dwmac",
  410. .data = &meson8b_dwmac_data,
  411. },
  412. {
  413. .compatible = "amlogic,meson-gxbb-dwmac",
  414. .data = &meson8b_dwmac_data,
  415. },
  416. {
  417. .compatible = "amlogic,meson-axg-dwmac",
  418. .data = &meson_axg_dwmac_data,
  419. },
  420. {
  421. .compatible = "amlogic,meson-g12a-dwmac",
  422. .data = &meson_g12a_dwmac_data,
  423. },
  424. { }
  425. };
  426. MODULE_DEVICE_TABLE(of, meson8b_dwmac_match);
  427. static struct platform_driver meson8b_dwmac_driver = {
  428. .probe = meson8b_dwmac_probe,
  429. .remove = stmmac_pltfr_remove,
  430. .driver = {
  431. .name = "meson8b-dwmac",
  432. .pm = &stmmac_pltfr_pm_ops,
  433. .of_match_table = meson8b_dwmac_match,
  434. },
  435. };
  436. module_platform_driver(meson8b_dwmac_driver);
  437. MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
  438. MODULE_DESCRIPTION("Amlogic Meson8b, Meson8m2 and GXBB DWMAC glue layer");
  439. MODULE_LICENSE("GPL v2");