phy-rockchip-inno-usb2.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Rockchip USB2.0 PHY with Innosilicon IP block driver
  4. *
  5. * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd
  6. * Copyright (C) 2020 Amarula Solutions(India)
  7. */
  8. #include <common.h>
  9. #include <clk.h>
  10. #include <dm.h>
  11. #include <dm/device_compat.h>
  12. #include <dm/lists.h>
  13. #include <generic-phy.h>
  14. #include <reset.h>
  15. #include <syscon.h>
  16. #include <asm/gpio.h>
  17. #include <asm/io.h>
  18. #include <linux/iopoll.h>
  19. #include <asm/arch-rockchip/clock.h>
  20. DECLARE_GLOBAL_DATA_PTR;
  21. #define usleep_range(a, b) udelay((b))
  22. #define BIT_WRITEABLE_SHIFT 16
  23. enum rockchip_usb2phy_port_id {
  24. USB2PHY_PORT_OTG,
  25. USB2PHY_PORT_HOST,
  26. USB2PHY_NUM_PORTS,
  27. };
  28. struct usb2phy_reg {
  29. unsigned int offset;
  30. unsigned int bitend;
  31. unsigned int bitstart;
  32. unsigned int disable;
  33. unsigned int enable;
  34. };
  35. struct rockchip_usb2phy_port_cfg {
  36. struct usb2phy_reg phy_sus;
  37. struct usb2phy_reg bvalid_det_en;
  38. struct usb2phy_reg bvalid_det_st;
  39. struct usb2phy_reg bvalid_det_clr;
  40. struct usb2phy_reg ls_det_en;
  41. struct usb2phy_reg ls_det_st;
  42. struct usb2phy_reg ls_det_clr;
  43. struct usb2phy_reg utmi_avalid;
  44. struct usb2phy_reg utmi_bvalid;
  45. struct usb2phy_reg utmi_ls;
  46. struct usb2phy_reg utmi_hstdet;
  47. };
  48. struct rockchip_usb2phy_cfg {
  49. unsigned int reg;
  50. const struct rockchip_usb2phy_port_cfg port_cfgs[USB2PHY_NUM_PORTS];
  51. };
  52. struct rockchip_usb2phy {
  53. void *reg_base;
  54. struct clk phyclk;
  55. const struct rockchip_usb2phy_cfg *phy_cfg;
  56. };
  57. static inline int property_enable(void *reg_base,
  58. const struct usb2phy_reg *reg, bool en)
  59. {
  60. unsigned int val, mask, tmp;
  61. tmp = en ? reg->enable : reg->disable;
  62. mask = GENMASK(reg->bitend, reg->bitstart);
  63. val = (tmp << reg->bitstart) | (mask << BIT_WRITEABLE_SHIFT);
  64. return writel(val, reg_base + reg->offset);
  65. }
  66. static const
  67. struct rockchip_usb2phy_port_cfg *us2phy_get_port(struct phy *phy)
  68. {
  69. struct udevice *parent = dev_get_parent(phy->dev);
  70. struct rockchip_usb2phy *priv = dev_get_priv(parent);
  71. const struct rockchip_usb2phy_cfg *phy_cfg = priv->phy_cfg;
  72. return &phy_cfg->port_cfgs[phy->id];
  73. }
  74. static int rockchip_usb2phy_power_on(struct phy *phy)
  75. {
  76. struct udevice *parent = dev_get_parent(phy->dev);
  77. struct rockchip_usb2phy *priv = dev_get_priv(parent);
  78. const struct rockchip_usb2phy_port_cfg *port_cfg = us2phy_get_port(phy);
  79. property_enable(priv->reg_base, &port_cfg->phy_sus, false);
  80. /* waiting for the utmi_clk to become stable */
  81. usleep_range(1500, 2000);
  82. return 0;
  83. }
  84. static int rockchip_usb2phy_power_off(struct phy *phy)
  85. {
  86. struct udevice *parent = dev_get_parent(phy->dev);
  87. struct rockchip_usb2phy *priv = dev_get_priv(parent);
  88. const struct rockchip_usb2phy_port_cfg *port_cfg = us2phy_get_port(phy);
  89. property_enable(priv->reg_base, &port_cfg->phy_sus, true);
  90. return 0;
  91. }
  92. static int rockchip_usb2phy_init(struct phy *phy)
  93. {
  94. struct udevice *parent = dev_get_parent(phy->dev);
  95. struct rockchip_usb2phy *priv = dev_get_priv(parent);
  96. const struct rockchip_usb2phy_port_cfg *port_cfg = us2phy_get_port(phy);
  97. int ret;
  98. ret = clk_enable(&priv->phyclk);
  99. if (ret) {
  100. dev_err(phy->dev, "failed to enable phyclk (ret=%d)\n", ret);
  101. return ret;
  102. }
  103. if (phy->id == USB2PHY_PORT_OTG) {
  104. property_enable(priv->reg_base, &port_cfg->bvalid_det_clr, true);
  105. property_enable(priv->reg_base, &port_cfg->bvalid_det_en, true);
  106. } else if (phy->id == USB2PHY_PORT_HOST) {
  107. property_enable(priv->reg_base, &port_cfg->bvalid_det_clr, true);
  108. property_enable(priv->reg_base, &port_cfg->bvalid_det_en, true);
  109. }
  110. return 0;
  111. }
  112. static int rockchip_usb2phy_exit(struct phy *phy)
  113. {
  114. struct udevice *parent = dev_get_parent(phy->dev);
  115. struct rockchip_usb2phy *priv = dev_get_priv(parent);
  116. clk_disable(&priv->phyclk);
  117. return 0;
  118. }
  119. static int rockchip_usb2phy_of_xlate(struct phy *phy,
  120. struct ofnode_phandle_args *args)
  121. {
  122. const char *name = phy->dev->name;
  123. if (!strcasecmp(name, "host-port"))
  124. phy->id = USB2PHY_PORT_HOST;
  125. else if (!strcasecmp(name, "otg-port"))
  126. phy->id = USB2PHY_PORT_OTG;
  127. else
  128. dev_err(phy->dev, "improper %s device\n", name);
  129. return 0;
  130. }
  131. static struct phy_ops rockchip_usb2phy_ops = {
  132. .init = rockchip_usb2phy_init,
  133. .exit = rockchip_usb2phy_exit,
  134. .power_on = rockchip_usb2phy_power_on,
  135. .power_off = rockchip_usb2phy_power_off,
  136. .of_xlate = rockchip_usb2phy_of_xlate,
  137. };
  138. static int rockchip_usb2phy_probe(struct udevice *dev)
  139. {
  140. struct rockchip_usb2phy *priv = dev_get_priv(dev);
  141. const struct rockchip_usb2phy_cfg *phy_cfgs;
  142. unsigned int reg;
  143. int index, ret;
  144. priv->reg_base = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
  145. if (IS_ERR(priv->reg_base))
  146. return PTR_ERR(priv->reg_base);
  147. ret = ofnode_read_u32(dev_ofnode(dev), "reg", &reg);
  148. if (ret) {
  149. dev_err(dev, "failed to read reg property (ret = %d)\n", ret);
  150. return ret;
  151. }
  152. phy_cfgs = (const struct rockchip_usb2phy_cfg *)
  153. dev_get_driver_data(dev);
  154. if (!phy_cfgs)
  155. return -EINVAL;
  156. /* find out a proper config which can be matched with dt. */
  157. index = 0;
  158. while (phy_cfgs[index].reg) {
  159. if (phy_cfgs[index].reg == reg) {
  160. priv->phy_cfg = &phy_cfgs[index];
  161. break;
  162. }
  163. ++index;
  164. }
  165. if (!priv->phy_cfg) {
  166. dev_err(dev, "failed find proper phy-cfg\n");
  167. return -EINVAL;
  168. }
  169. ret = clk_get_by_name(dev, "phyclk", &priv->phyclk);
  170. if (ret) {
  171. dev_err(dev, "failed to get the phyclk (ret=%d)\n", ret);
  172. return ret;
  173. }
  174. return 0;
  175. }
  176. static int rockchip_usb2phy_bind(struct udevice *dev)
  177. {
  178. struct udevice *usb2phy_dev;
  179. ofnode node;
  180. const char *name;
  181. int ret = 0;
  182. dev_for_each_subnode(node, dev) {
  183. if (!ofnode_valid(node)) {
  184. dev_info(dev, "subnode %s not found\n", dev->name);
  185. return -ENXIO;
  186. }
  187. name = ofnode_get_name(node);
  188. dev_dbg(dev, "subnode %s\n", name);
  189. ret = device_bind_driver_to_node(dev, "rockchip_usb2phy_port",
  190. name, node, &usb2phy_dev);
  191. if (ret) {
  192. dev_err(dev,
  193. "'%s' cannot bind 'rockchip_usb2phy_port'\n", name);
  194. return ret;
  195. }
  196. }
  197. return ret;
  198. }
  199. static const struct rockchip_usb2phy_cfg rk3399_usb2phy_cfgs[] = {
  200. {
  201. .reg = 0xe450,
  202. .port_cfgs = {
  203. [USB2PHY_PORT_OTG] = {
  204. .phy_sus = { 0xe454, 1, 0, 2, 1 },
  205. .bvalid_det_en = { 0xe3c0, 3, 3, 0, 1 },
  206. .bvalid_det_st = { 0xe3e0, 3, 3, 0, 1 },
  207. .bvalid_det_clr = { 0xe3d0, 3, 3, 0, 1 },
  208. .utmi_avalid = { 0xe2ac, 7, 7, 0, 1 },
  209. .utmi_bvalid = { 0xe2ac, 12, 12, 0, 1 },
  210. },
  211. [USB2PHY_PORT_HOST] = {
  212. .phy_sus = { 0xe458, 1, 0, 0x2, 0x1 },
  213. .ls_det_en = { 0xe3c0, 6, 6, 0, 1 },
  214. .ls_det_st = { 0xe3e0, 6, 6, 0, 1 },
  215. .ls_det_clr = { 0xe3d0, 6, 6, 0, 1 },
  216. .utmi_ls = { 0xe2ac, 22, 21, 0, 1 },
  217. .utmi_hstdet = { 0xe2ac, 23, 23, 0, 1 }
  218. }
  219. },
  220. },
  221. {
  222. .reg = 0xe460,
  223. .port_cfgs = {
  224. [USB2PHY_PORT_OTG] = {
  225. .phy_sus = { 0xe464, 1, 0, 2, 1 },
  226. .bvalid_det_en = { 0xe3c0, 8, 8, 0, 1 },
  227. .bvalid_det_st = { 0xe3e0, 8, 8, 0, 1 },
  228. .bvalid_det_clr = { 0xe3d0, 8, 8, 0, 1 },
  229. .utmi_avalid = { 0xe2ac, 10, 10, 0, 1 },
  230. .utmi_bvalid = { 0xe2ac, 16, 16, 0, 1 },
  231. },
  232. [USB2PHY_PORT_HOST] = {
  233. .phy_sus = { 0xe468, 1, 0, 0x2, 0x1 },
  234. .ls_det_en = { 0xe3c0, 11, 11, 0, 1 },
  235. .ls_det_st = { 0xe3e0, 11, 11, 0, 1 },
  236. .ls_det_clr = { 0xe3d0, 11, 11, 0, 1 },
  237. .utmi_ls = { 0xe2ac, 26, 25, 0, 1 },
  238. .utmi_hstdet = { 0xe2ac, 27, 27, 0, 1 }
  239. }
  240. },
  241. },
  242. { /* sentinel */ }
  243. };
  244. static const struct udevice_id rockchip_usb2phy_ids[] = {
  245. {
  246. .compatible = "rockchip,rk3399-usb2phy",
  247. .data = (ulong)&rk3399_usb2phy_cfgs,
  248. },
  249. { /* sentinel */ }
  250. };
  251. U_BOOT_DRIVER(rockchip_usb2phy_port) = {
  252. .name = "rockchip_usb2phy_port",
  253. .id = UCLASS_PHY,
  254. .ops = &rockchip_usb2phy_ops,
  255. };
  256. U_BOOT_DRIVER(rockchip_usb2phy) = {
  257. .name = "rockchip_usb2phy",
  258. .id = UCLASS_PHY,
  259. .of_match = rockchip_usb2phy_ids,
  260. .probe = rockchip_usb2phy_probe,
  261. .bind = rockchip_usb2phy_bind,
  262. .priv_auto_alloc_size = sizeof(struct rockchip_usb2phy),
  263. };