gphy.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /*
  2. * This program is free software; you can redistribute it and/or modify it
  3. * under the terms of the GNU General Public License version 2 as published
  4. * by the Free Software Foundation.
  5. *
  6. * Copyright (C) 2012 John Crispin <blogic@phrozen.org>
  7. * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
  8. * Copyright (C) 2017 Hauke Mehrtens <hauke@hauke-m.de>
  9. */
  10. #include <linux/clk.h>
  11. #include <linux/delay.h>
  12. #include <linux/dma-mapping.h>
  13. #include <linux/firmware.h>
  14. #include <linux/mfd/syscon.h>
  15. #include <linux/module.h>
  16. #include <linux/reboot.h>
  17. #include <linux/regmap.h>
  18. #include <linux/reset.h>
  19. #include <linux/of_device.h>
  20. #include <linux/of_platform.h>
  21. #include <linux/property.h>
  22. #include <dt-bindings/mips/lantiq_rcu_gphy.h>
  23. #include <lantiq_soc.h>
  24. #define XRX200_GPHY_FW_ALIGN (16 * 1024)
  25. struct xway_gphy_priv {
  26. struct clk *gphy_clk_gate;
  27. struct reset_control *gphy_reset;
  28. struct reset_control *gphy_reset2;
  29. void __iomem *membase;
  30. char *fw_name;
  31. };
  32. struct xway_gphy_match_data {
  33. char *fe_firmware_name;
  34. char *ge_firmware_name;
  35. };
  36. static const struct xway_gphy_match_data xrx200a1x_gphy_data = {
  37. .fe_firmware_name = "lantiq/xrx200_phy22f_a14.bin",
  38. .ge_firmware_name = "lantiq/xrx200_phy11g_a14.bin",
  39. };
  40. static const struct xway_gphy_match_data xrx200a2x_gphy_data = {
  41. .fe_firmware_name = "lantiq/xrx200_phy22f_a22.bin",
  42. .ge_firmware_name = "lantiq/xrx200_phy11g_a22.bin",
  43. };
  44. static const struct xway_gphy_match_data xrx300_gphy_data = {
  45. .fe_firmware_name = "lantiq/xrx300_phy22f_a21.bin",
  46. .ge_firmware_name = "lantiq/xrx300_phy11g_a21.bin",
  47. };
  48. static const struct of_device_id xway_gphy_match[] = {
  49. { .compatible = "lantiq,xrx200a1x-gphy", .data = &xrx200a1x_gphy_data },
  50. { .compatible = "lantiq,xrx200a2x-gphy", .data = &xrx200a2x_gphy_data },
  51. { .compatible = "lantiq,xrx300-gphy", .data = &xrx300_gphy_data },
  52. { .compatible = "lantiq,xrx330-gphy", .data = &xrx300_gphy_data },
  53. {},
  54. };
  55. MODULE_DEVICE_TABLE(of, xway_gphy_match);
  56. static int xway_gphy_load(struct device *dev, struct xway_gphy_priv *priv,
  57. dma_addr_t *dev_addr)
  58. {
  59. const struct firmware *fw;
  60. void *fw_addr;
  61. dma_addr_t dma_addr;
  62. size_t size;
  63. int ret;
  64. ret = request_firmware(&fw, priv->fw_name, dev);
  65. if (ret) {
  66. dev_err(dev, "failed to load firmware: %s, error: %i\n",
  67. priv->fw_name, ret);
  68. return ret;
  69. }
  70. /*
  71. * GPHY cores need the firmware code in a persistent and contiguous
  72. * memory area with a 16 kB boundary aligned start address.
  73. */
  74. size = fw->size + XRX200_GPHY_FW_ALIGN;
  75. fw_addr = dmam_alloc_coherent(dev, size, &dma_addr, GFP_KERNEL);
  76. if (fw_addr) {
  77. fw_addr = PTR_ALIGN(fw_addr, XRX200_GPHY_FW_ALIGN);
  78. *dev_addr = ALIGN(dma_addr, XRX200_GPHY_FW_ALIGN);
  79. memcpy(fw_addr, fw->data, fw->size);
  80. } else {
  81. dev_err(dev, "failed to alloc firmware memory\n");
  82. ret = -ENOMEM;
  83. }
  84. release_firmware(fw);
  85. return ret;
  86. }
  87. static int xway_gphy_of_probe(struct platform_device *pdev,
  88. struct xway_gphy_priv *priv)
  89. {
  90. struct device *dev = &pdev->dev;
  91. const struct xway_gphy_match_data *gphy_fw_name_cfg;
  92. u32 gphy_mode;
  93. int ret;
  94. struct resource *res_gphy;
  95. gphy_fw_name_cfg = of_device_get_match_data(dev);
  96. priv->gphy_clk_gate = devm_clk_get(dev, NULL);
  97. if (IS_ERR(priv->gphy_clk_gate)) {
  98. dev_err(dev, "Failed to lookup gate clock\n");
  99. return PTR_ERR(priv->gphy_clk_gate);
  100. }
  101. res_gphy = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  102. priv->membase = devm_ioremap_resource(dev, res_gphy);
  103. if (IS_ERR(priv->membase))
  104. return PTR_ERR(priv->membase);
  105. priv->gphy_reset = devm_reset_control_get(dev, "gphy");
  106. if (IS_ERR(priv->gphy_reset)) {
  107. if (PTR_ERR(priv->gphy_reset) != -EPROBE_DEFER)
  108. dev_err(dev, "Failed to lookup gphy reset\n");
  109. return PTR_ERR(priv->gphy_reset);
  110. }
  111. priv->gphy_reset2 = devm_reset_control_get_optional(dev, "gphy2");
  112. if (IS_ERR(priv->gphy_reset2))
  113. return PTR_ERR(priv->gphy_reset2);
  114. ret = device_property_read_u32(dev, "lantiq,gphy-mode", &gphy_mode);
  115. /* Default to GE mode */
  116. if (ret)
  117. gphy_mode = GPHY_MODE_GE;
  118. switch (gphy_mode) {
  119. case GPHY_MODE_FE:
  120. priv->fw_name = gphy_fw_name_cfg->fe_firmware_name;
  121. break;
  122. case GPHY_MODE_GE:
  123. priv->fw_name = gphy_fw_name_cfg->ge_firmware_name;
  124. break;
  125. default:
  126. dev_err(dev, "Unknown GPHY mode %d\n", gphy_mode);
  127. return -EINVAL;
  128. }
  129. return 0;
  130. }
  131. static int xway_gphy_probe(struct platform_device *pdev)
  132. {
  133. struct device *dev = &pdev->dev;
  134. struct xway_gphy_priv *priv;
  135. dma_addr_t fw_addr = 0;
  136. int ret;
  137. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  138. if (!priv)
  139. return -ENOMEM;
  140. ret = xway_gphy_of_probe(pdev, priv);
  141. if (ret)
  142. return ret;
  143. ret = clk_prepare_enable(priv->gphy_clk_gate);
  144. if (ret)
  145. return ret;
  146. ret = xway_gphy_load(dev, priv, &fw_addr);
  147. if (ret) {
  148. clk_disable_unprepare(priv->gphy_clk_gate);
  149. return ret;
  150. }
  151. reset_control_assert(priv->gphy_reset);
  152. reset_control_assert(priv->gphy_reset2);
  153. iowrite32be(fw_addr, priv->membase);
  154. reset_control_deassert(priv->gphy_reset);
  155. reset_control_deassert(priv->gphy_reset2);
  156. platform_set_drvdata(pdev, priv);
  157. return ret;
  158. }
  159. static int xway_gphy_remove(struct platform_device *pdev)
  160. {
  161. struct xway_gphy_priv *priv = platform_get_drvdata(pdev);
  162. iowrite32be(0, priv->membase);
  163. clk_disable_unprepare(priv->gphy_clk_gate);
  164. return 0;
  165. }
  166. static struct platform_driver xway_gphy_driver = {
  167. .probe = xway_gphy_probe,
  168. .remove = xway_gphy_remove,
  169. .driver = {
  170. .name = "xway-rcu-gphy",
  171. .of_match_table = xway_gphy_match,
  172. },
  173. };
  174. module_platform_driver(xway_gphy_driver);
  175. MODULE_FIRMWARE("lantiq/xrx300_phy11g_a21.bin");
  176. MODULE_FIRMWARE("lantiq/xrx300_phy22f_a21.bin");
  177. MODULE_FIRMWARE("lantiq/xrx200_phy11g_a14.bin");
  178. MODULE_FIRMWARE("lantiq/xrx200_phy11g_a22.bin");
  179. MODULE_FIRMWARE("lantiq/xrx200_phy22f_a14.bin");
  180. MODULE_FIRMWARE("lantiq/xrx200_phy22f_a22.bin");
  181. MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
  182. MODULE_DESCRIPTION("Lantiq XWAY GPHY Firmware Loader");
  183. MODULE_LICENSE("GPL");