phy-intel-keembay-usb.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Intel Keem Bay USB PHY driver
  4. * Copyright (C) 2020 Intel Corporation
  5. */
  6. #include <linux/bitfield.h>
  7. #include <linux/bits.h>
  8. #include <linux/clk.h>
  9. #include <linux/delay.h>
  10. #include <linux/mod_devicetable.h>
  11. #include <linux/module.h>
  12. #include <linux/phy/phy.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/regmap.h>
  15. /* USS (USB Subsystem) clock control registers */
  16. #define USS_CPR_CLK_EN 0x00
  17. #define USS_CPR_CLK_SET 0x04
  18. #define USS_CPR_CLK_CLR 0x08
  19. #define USS_CPR_RST_EN 0x10
  20. #define USS_CPR_RST_SET 0x14
  21. #define USS_CPR_RST_CLR 0x18
  22. /* USS clock/reset bit fields */
  23. #define USS_CPR_PHY_TST BIT(6)
  24. #define USS_CPR_LOW_JIT BIT(5)
  25. #define USS_CPR_CORE BIT(4)
  26. #define USS_CPR_SUSPEND BIT(3)
  27. #define USS_CPR_ALT_REF BIT(2)
  28. #define USS_CPR_REF BIT(1)
  29. #define USS_CPR_SYS BIT(0)
  30. #define USS_CPR_MASK GENMASK(6, 0)
  31. /* USS APB slave registers */
  32. #define USS_USB_CTRL_CFG0 0x10
  33. #define VCC_RESET_N_MASK BIT(31)
  34. #define USS_USB_PHY_CFG0 0x30
  35. #define POR_MASK BIT(15)
  36. #define PHY_RESET_MASK BIT(14)
  37. #define PHY_REF_USE_PAD_MASK BIT(5)
  38. #define USS_USB_PHY_CFG6 0x64
  39. #define PHY0_SRAM_EXT_LD_DONE_MASK BIT(23)
  40. #define USS_USB_PARALLEL_IF_CTRL 0xa0
  41. #define USB_PHY_CR_PARA_SEL_MASK BIT(2)
  42. #define USS_USB_TSET_SIGNALS_AND_GLOB 0xac
  43. #define USB_PHY_CR_PARA_CLK_EN_MASK BIT(7)
  44. #define USS_USB_STATUS_REG 0xb8
  45. #define PHY0_SRAM_INIT_DONE_MASK BIT(3)
  46. #define USS_USB_TIEOFFS_CONSTANTS_REG1 0xc0
  47. #define IDDQ_ENABLE_MASK BIT(10)
  48. struct keembay_usb_phy {
  49. struct device *dev;
  50. struct regmap *regmap_cpr;
  51. struct regmap *regmap_slv;
  52. };
  53. static const struct regmap_config keembay_regmap_config = {
  54. .reg_bits = 32,
  55. .val_bits = 32,
  56. .reg_stride = 4,
  57. .max_register = USS_USB_TIEOFFS_CONSTANTS_REG1,
  58. };
  59. static int keembay_usb_clocks_on(struct keembay_usb_phy *priv)
  60. {
  61. int ret;
  62. ret = regmap_update_bits(priv->regmap_cpr, USS_CPR_CLK_SET,
  63. USS_CPR_MASK, USS_CPR_MASK);
  64. if (ret) {
  65. dev_err(priv->dev, "error clock set: %d\n", ret);
  66. return ret;
  67. }
  68. ret = regmap_update_bits(priv->regmap_cpr, USS_CPR_RST_SET,
  69. USS_CPR_MASK, USS_CPR_MASK);
  70. if (ret) {
  71. dev_err(priv->dev, "error reset set: %d\n", ret);
  72. return ret;
  73. }
  74. ret = regmap_update_bits(priv->regmap_slv,
  75. USS_USB_TIEOFFS_CONSTANTS_REG1,
  76. IDDQ_ENABLE_MASK,
  77. FIELD_PREP(IDDQ_ENABLE_MASK, 0));
  78. if (ret) {
  79. dev_err(priv->dev, "error iddq disable: %d\n", ret);
  80. return ret;
  81. }
  82. /* Wait 30us to ensure all analog blocks are powered up. */
  83. usleep_range(30, 60);
  84. ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG0,
  85. PHY_REF_USE_PAD_MASK,
  86. FIELD_PREP(PHY_REF_USE_PAD_MASK, 1));
  87. if (ret)
  88. dev_err(priv->dev, "error ref clock select: %d\n", ret);
  89. return ret;
  90. }
  91. static int keembay_usb_core_off(struct keembay_usb_phy *priv)
  92. {
  93. int ret;
  94. ret = regmap_update_bits(priv->regmap_slv, USS_USB_CTRL_CFG0,
  95. VCC_RESET_N_MASK,
  96. FIELD_PREP(VCC_RESET_N_MASK, 0));
  97. if (ret)
  98. dev_err(priv->dev, "error core reset: %d\n", ret);
  99. return ret;
  100. }
  101. static int keembay_usb_core_on(struct keembay_usb_phy *priv)
  102. {
  103. int ret;
  104. ret = regmap_update_bits(priv->regmap_slv, USS_USB_CTRL_CFG0,
  105. VCC_RESET_N_MASK,
  106. FIELD_PREP(VCC_RESET_N_MASK, 1));
  107. if (ret)
  108. dev_err(priv->dev, "error core on: %d\n", ret);
  109. return ret;
  110. }
  111. static int keembay_usb_phys_on(struct keembay_usb_phy *priv)
  112. {
  113. int ret;
  114. ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG0,
  115. POR_MASK | PHY_RESET_MASK,
  116. FIELD_PREP(POR_MASK | PHY_RESET_MASK, 0));
  117. if (ret)
  118. dev_err(priv->dev, "error phys on: %d\n", ret);
  119. return ret;
  120. }
  121. static int keembay_usb_phy_init(struct phy *phy)
  122. {
  123. struct keembay_usb_phy *priv = phy_get_drvdata(phy);
  124. u32 val;
  125. int ret;
  126. ret = keembay_usb_core_off(priv);
  127. if (ret)
  128. return ret;
  129. /*
  130. * According to Keem Bay datasheet, wait minimum 20us after clock
  131. * enable before bringing PHYs out of reset.
  132. */
  133. usleep_range(20, 40);
  134. ret = keembay_usb_phys_on(priv);
  135. if (ret)
  136. return ret;
  137. ret = regmap_update_bits(priv->regmap_slv,
  138. USS_USB_TSET_SIGNALS_AND_GLOB,
  139. USB_PHY_CR_PARA_CLK_EN_MASK,
  140. FIELD_PREP(USB_PHY_CR_PARA_CLK_EN_MASK, 0));
  141. if (ret) {
  142. dev_err(priv->dev, "error cr clock disable: %d\n", ret);
  143. return ret;
  144. }
  145. /*
  146. * According to Keem Bay datasheet, wait 2us after disabling the
  147. * clock into the USB 3.x parallel interface.
  148. */
  149. udelay(2);
  150. ret = regmap_update_bits(priv->regmap_slv,
  151. USS_USB_PARALLEL_IF_CTRL,
  152. USB_PHY_CR_PARA_SEL_MASK,
  153. FIELD_PREP(USB_PHY_CR_PARA_SEL_MASK, 1));
  154. if (ret) {
  155. dev_err(priv->dev, "error cr select: %d\n", ret);
  156. return ret;
  157. }
  158. ret = regmap_update_bits(priv->regmap_slv,
  159. USS_USB_TSET_SIGNALS_AND_GLOB,
  160. USB_PHY_CR_PARA_CLK_EN_MASK,
  161. FIELD_PREP(USB_PHY_CR_PARA_CLK_EN_MASK, 1));
  162. if (ret) {
  163. dev_err(priv->dev, "error cr clock enable: %d\n", ret);
  164. return ret;
  165. }
  166. ret = regmap_read_poll_timeout(priv->regmap_slv, USS_USB_STATUS_REG,
  167. val, val & PHY0_SRAM_INIT_DONE_MASK,
  168. USEC_PER_MSEC, 10 * USEC_PER_MSEC);
  169. if (ret) {
  170. dev_err(priv->dev, "SRAM init not done: %d\n", ret);
  171. return ret;
  172. }
  173. ret = regmap_update_bits(priv->regmap_slv, USS_USB_PHY_CFG6,
  174. PHY0_SRAM_EXT_LD_DONE_MASK,
  175. FIELD_PREP(PHY0_SRAM_EXT_LD_DONE_MASK, 1));
  176. if (ret) {
  177. dev_err(priv->dev, "error SRAM init done set: %d\n", ret);
  178. return ret;
  179. }
  180. /*
  181. * According to Keem Bay datasheet, wait 20us after setting the
  182. * SRAM load done bit, before releasing the controller reset.
  183. */
  184. usleep_range(20, 40);
  185. return keembay_usb_core_on(priv);
  186. }
  187. static const struct phy_ops ops = {
  188. .init = keembay_usb_phy_init,
  189. .owner = THIS_MODULE,
  190. };
  191. static int keembay_usb_phy_probe(struct platform_device *pdev)
  192. {
  193. struct device *dev = &pdev->dev;
  194. struct keembay_usb_phy *priv;
  195. struct phy *generic_phy;
  196. struct phy_provider *phy_provider;
  197. void __iomem *base;
  198. int ret;
  199. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  200. if (!priv)
  201. return -ENOMEM;
  202. base = devm_platform_ioremap_resource_byname(pdev, "cpr-apb-base");
  203. if (IS_ERR(base))
  204. return PTR_ERR(base);
  205. priv->regmap_cpr = devm_regmap_init_mmio(dev, base,
  206. &keembay_regmap_config);
  207. if (IS_ERR(priv->regmap_cpr))
  208. return PTR_ERR(priv->regmap_cpr);
  209. base = devm_platform_ioremap_resource_byname(pdev, "slv-apb-base");
  210. if (IS_ERR(base))
  211. return PTR_ERR(base);
  212. priv->regmap_slv = devm_regmap_init_mmio(dev, base,
  213. &keembay_regmap_config);
  214. if (IS_ERR(priv->regmap_slv))
  215. return PTR_ERR(priv->regmap_slv);
  216. generic_phy = devm_phy_create(dev, dev->of_node, &ops);
  217. if (IS_ERR(generic_phy))
  218. return dev_err_probe(dev, PTR_ERR(generic_phy),
  219. "failed to create PHY\n");
  220. phy_set_drvdata(generic_phy, priv);
  221. phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
  222. if (IS_ERR(phy_provider))
  223. return dev_err_probe(dev, PTR_ERR(phy_provider),
  224. "failed to register phy provider\n");
  225. /* Setup USB subsystem clocks */
  226. ret = keembay_usb_clocks_on(priv);
  227. if (ret)
  228. return ret;
  229. /* and turn on the DWC3 core, prior to DWC3 driver init. */
  230. return keembay_usb_core_on(priv);
  231. }
  232. static const struct of_device_id keembay_usb_phy_dt_ids[] = {
  233. { .compatible = "intel,keembay-usb-phy" },
  234. {}
  235. };
  236. MODULE_DEVICE_TABLE(of, keembay_usb_phy_dt_ids);
  237. static struct platform_driver keembay_usb_phy_driver = {
  238. .probe = keembay_usb_phy_probe,
  239. .driver = {
  240. .name = "keembay-usb-phy",
  241. .of_match_table = keembay_usb_phy_dt_ids,
  242. },
  243. };
  244. module_platform_driver(keembay_usb_phy_driver);
  245. MODULE_AUTHOR("Wan Ahmad Zainie <[email protected]>");
  246. MODULE_DESCRIPTION("Intel Keem Bay USB PHY driver");
  247. MODULE_LICENSE("GPL v2");