0002-macb-Add-support-for-SiFive-FU540-C000.patch 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. From 4181aa6e771dcc09b62eb3495bd09bf151b8bd9d Mon Sep 17 00:00:00 2001
  2. From: Yash Shah <yash.shah@sifive.com>
  3. Date: Tue, 18 Jun 2019 13:26:08 +0530
  4. Subject: [PATCH 2/6] macb: Add support for SiFive FU540-C000
  5. The management IP block is tightly coupled with the Cadence MACB IP
  6. block on the FU540, and manages many of the boundary signals from the
  7. MACB IP. This patch only controls the tx_clk input signal to the MACB
  8. IP. Future patches may add support for monitoring or controlling other
  9. IP boundary signals.
  10. Signed-off-by: Yash Shah <yash.shah@sifive.com>
  11. Upstream-Status: Accepted [5.3]
  12. ---
  13. drivers/net/ethernet/cadence/macb_main.c | 123 +++++++++++++++++++++++
  14. 1 file changed, 123 insertions(+)
  15. diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
  16. index 262a28ff81fc..111bf51a8405 100644
  17. --- a/drivers/net/ethernet/cadence/macb_main.c
  18. +++ b/drivers/net/ethernet/cadence/macb_main.c
  19. @@ -7,6 +7,7 @@
  20. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  21. #include <linux/clk.h>
  22. +#include <linux/clk-provider.h>
  23. #include <linux/crc32.h>
  24. #include <linux/module.h>
  25. #include <linux/moduleparam.h>
  26. @@ -37,6 +38,15 @@
  27. #include <linux/pm_runtime.h>
  28. #include "macb.h"
  29. +/* This structure is only used for MACB on SiFive FU540 devices */
  30. +struct sifive_fu540_macb_mgmt {
  31. + void __iomem *reg;
  32. + unsigned long rate;
  33. + struct clk_hw hw;
  34. +};
  35. +
  36. +static struct sifive_fu540_macb_mgmt *mgmt;
  37. +
  38. #define MACB_RX_BUFFER_SIZE 128
  39. #define RX_BUFFER_MULTIPLE 64 /* bytes */
  40. @@ -3943,6 +3953,116 @@ static int at91ether_init(struct platform_device *pdev)
  41. return 0;
  42. }
  43. +static unsigned long fu540_macb_tx_recalc_rate(struct clk_hw *hw,
  44. + unsigned long parent_rate)
  45. +{
  46. + return mgmt->rate;
  47. +}
  48. +
  49. +static long fu540_macb_tx_round_rate(struct clk_hw *hw, unsigned long rate,
  50. + unsigned long *parent_rate)
  51. +{
  52. + if (WARN_ON(rate < 2500000))
  53. + return 2500000;
  54. + else if (rate == 2500000)
  55. + return 2500000;
  56. + else if (WARN_ON(rate < 13750000))
  57. + return 2500000;
  58. + else if (WARN_ON(rate < 25000000))
  59. + return 25000000;
  60. + else if (rate == 25000000)
  61. + return 25000000;
  62. + else if (WARN_ON(rate < 75000000))
  63. + return 25000000;
  64. + else if (WARN_ON(rate < 125000000))
  65. + return 125000000;
  66. + else if (rate == 125000000)
  67. + return 125000000;
  68. +
  69. + WARN_ON(rate > 125000000);
  70. +
  71. + return 125000000;
  72. +}
  73. +
  74. +static int fu540_macb_tx_set_rate(struct clk_hw *hw, unsigned long rate,
  75. + unsigned long parent_rate)
  76. +{
  77. + rate = fu540_macb_tx_round_rate(hw, rate, &parent_rate);
  78. + if (rate != 125000000)
  79. + iowrite32(1, mgmt->reg);
  80. + else
  81. + iowrite32(0, mgmt->reg);
  82. + mgmt->rate = rate;
  83. +
  84. + return 0;
  85. +}
  86. +
  87. +static const struct clk_ops fu540_c000_ops = {
  88. + .recalc_rate = fu540_macb_tx_recalc_rate,
  89. + .round_rate = fu540_macb_tx_round_rate,
  90. + .set_rate = fu540_macb_tx_set_rate,
  91. +};
  92. +
  93. +static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
  94. + struct clk **hclk, struct clk **tx_clk,
  95. + struct clk **rx_clk, struct clk **tsu_clk)
  96. +{
  97. + struct clk_init_data init;
  98. + int err = 0;
  99. +
  100. + err = macb_clk_init(pdev, pclk, hclk, tx_clk, rx_clk, tsu_clk);
  101. + if (err)
  102. + return err;
  103. +
  104. + mgmt = devm_kzalloc(&pdev->dev, sizeof(*mgmt), GFP_KERNEL);
  105. + if (!mgmt)
  106. + return -ENOMEM;
  107. +
  108. + init.name = "sifive-gemgxl-mgmt";
  109. + init.ops = &fu540_c000_ops;
  110. + init.flags = 0;
  111. + init.num_parents = 0;
  112. +
  113. + mgmt->rate = 0;
  114. + mgmt->hw.init = &init;
  115. +
  116. + *tx_clk = clk_register(NULL, &mgmt->hw);
  117. + if (IS_ERR(*tx_clk))
  118. + return PTR_ERR(*tx_clk);
  119. +
  120. + err = clk_prepare_enable(*tx_clk);
  121. + if (err)
  122. + dev_err(&pdev->dev, "failed to enable tx_clk (%u)\n", err);
  123. + else
  124. + dev_info(&pdev->dev, "Registered clk switch '%s'\n", init.name);
  125. +
  126. + return 0;
  127. +}
  128. +
  129. +static int fu540_c000_init(struct platform_device *pdev)
  130. +{
  131. + struct resource *res;
  132. +
  133. + res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  134. + if (!res)
  135. + return -ENODEV;
  136. +
  137. + mgmt->reg = ioremap(res->start, resource_size(res));
  138. + if (!mgmt->reg)
  139. + return -ENOMEM;
  140. +
  141. + return macb_init(pdev);
  142. +}
  143. +
  144. +static const struct macb_config fu540_c000_config = {
  145. + .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_JUMBO |
  146. + MACB_CAPS_GEM_HAS_PTP,
  147. + .dma_burst_length = 16,
  148. + .clk_init = fu540_c000_clk_init,
  149. + .init = fu540_c000_init,
  150. + .jumbo_max_len = 10240,
  151. +};
  152. +
  153. static const struct macb_config at91sam9260_config = {
  154. .caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
  155. .clk_init = macb_clk_init,
  156. @@ -4032,6 +4152,7 @@ static const struct of_device_id macb_dt_ids[] = {
  157. { .compatible = "cdns,emac", .data = &emac_config },
  158. { .compatible = "cdns,zynqmp-gem", .data = &zynqmp_config},
  159. { .compatible = "cdns,zynq-gem", .data = &zynq_config },
  160. + { .compatible = "sifive,fu540-macb", .data = &fu540_c000_config },
  161. { /* sentinel */ }
  162. };
  163. MODULE_DEVICE_TABLE(of, macb_dt_ids);
  164. @@ -4239,6 +4360,7 @@ static int macb_probe(struct platform_device *pdev)
  165. err_disable_clocks:
  166. clk_disable_unprepare(tx_clk);
  167. + clk_unregister(tx_clk);
  168. clk_disable_unprepare(hclk);
  169. clk_disable_unprepare(pclk);
  170. clk_disable_unprepare(rx_clk);
  171. @@ -4273,6 +4395,7 @@ static int macb_remove(struct platform_device *pdev)
  172. pm_runtime_dont_use_autosuspend(&pdev->dev);
  173. if (!pm_runtime_suspended(&pdev->dev)) {
  174. clk_disable_unprepare(bp->tx_clk);
  175. + clk_unregister(bp->tx_clk);
  176. clk_disable_unprepare(bp->hclk);
  177. clk_disable_unprepare(bp->pclk);
  178. clk_disable_unprepare(bp->rx_clk);
  179. --
  180. 2.22.0