PageRenderTime 60ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/sys/mips/mediatek/mtk_usb_phy.c

https://bitbucket.org/freebsd/freebsd-base
C | 326 lines | 233 code | 49 blank | 44 comment | 26 complexity | ecc40bb4472fca813cd5167222168de6 MD5 | raw file
  1. /*-
  2. * Copyright (c) 2016 Stanislav Galabov.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include <sys/cdefs.h>
  26. __FBSDID("$FreeBSD$");
  27. #include <sys/stddef.h>
  28. #include <sys/param.h>
  29. #include <sys/types.h>
  30. #include <sys/kernel.h>
  31. #include <sys/bus.h>
  32. #include <sys/module.h>
  33. #include <machine/bus.h>
  34. #include <dev/fdt/fdt_common.h>
  35. #include <dev/fdt/fdt_clock.h>
  36. #include <mips/mediatek/fdt_reset.h>
  37. #include <dev/ofw/ofw_bus.h>
  38. #include <dev/ofw/ofw_bus_subr.h>
  39. #include <mips/mediatek/mtk_sysctl.h>
  40. #include <mips/mediatek/mtk_soc.h>
  41. #include <mips/mediatek/mtk_usb_phy.h>
  42. #define RESET_ASSERT_DELAY 1000
  43. #define RESET_DEASSERT_DELAY 10000
  44. struct mtk_usb_phy_softc {
  45. device_t dev;
  46. struct resource * res;
  47. uint32_t fm_base;
  48. uint32_t u2_base;
  49. uint32_t sr_coef;
  50. uint32_t socid;
  51. };
  52. #define USB_PHY_READ(_sc, _off) bus_read_4((_sc)->res, (_off))
  53. #define USB_PHY_WRITE(_sc, _off, _val) bus_write_4((_sc)->res, (_off), (_val))
  54. #define USB_PHY_CLR_SET(_sc, _off, _clr, _set) \
  55. USB_PHY_WRITE(_sc, _off, ((USB_PHY_READ(_sc, _off) & ~(_clr)) | (_set)))
  56. #define USB_PHY_READ_U2(_sc, _off) \
  57. USB_PHY_READ((_sc), ((_sc)->u2_base + (_off)))
  58. #define USB_PHY_WRITE_U2(_sc, _off, _val) \
  59. USB_PHY_WRITE((_sc), ((_sc)->u2_base + (_off)), (_val))
  60. #define USB_PHY_CLR_SET_U2(_sc, _off, _clr, _set) \
  61. USB_PHY_WRITE_U2((_sc), (_off), ((USB_PHY_READ_U2((_sc), (_off)) & \
  62. ~(_clr)) | (_set)))
  63. #define USB_PHY_BARRIER(_sc) bus_barrier((_sc)->res, 0, 0, \
  64. BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ)
  65. #define USB_PHY_READ_FM(_sc, _off) \
  66. USB_PHY_READ((_sc), ((_sc)->fm_base + (_off)))
  67. #define USB_PHY_WRITE_FM(_sc, _off) \
  68. USB_PHY_WRITE((_sc), ((_sc)->fm_base + (_off)), (_val))
  69. #define USB_PHY_CLR_SET_FM(_sc, _off, _clr, _set) \
  70. USB_PHY_WRITE_U2((_sc), (_off), ((USB_PHY_READ_U2((_sc), (_off)) & \
  71. ~(_clr)) | (_set)))
  72. static void mtk_usb_phy_mt7621_init(device_t);
  73. static void mtk_usb_phy_mt7628_init(device_t);
  74. static struct ofw_compat_data compat_data[] = {
  75. { "ralink,mt7620-usbphy", MTK_SOC_MT7620A },
  76. { "mediatek,mt7620-usbphy", MTK_SOC_MT7620A },
  77. { "ralink,mt7628an-usbphy", MTK_SOC_MT7628 },
  78. { "ralink,rt3352-usbphy", MTK_SOC_RT3352 },
  79. { "ralink,rt3050-usbphy", MTK_SOC_RT3050 },
  80. { NULL, MTK_SOC_UNKNOWN }
  81. };
  82. static int
  83. mtk_usb_phy_probe(device_t dev)
  84. {
  85. struct mtk_usb_phy_softc *sc = device_get_softc(dev);
  86. if (!ofw_bus_status_okay(dev))
  87. return (ENXIO);
  88. if ((sc->socid =
  89. ofw_bus_search_compatible(dev, compat_data)->ocd_data) ==
  90. MTK_SOC_UNKNOWN)
  91. return (ENXIO);
  92. device_set_desc(dev, "MTK USB PHY");
  93. return (0);
  94. }
  95. static int
  96. mtk_usb_phy_attach(device_t dev)
  97. {
  98. struct mtk_usb_phy_softc * sc = device_get_softc(dev);
  99. phandle_t node;
  100. uint32_t val;
  101. int rid;
  102. sc->dev = dev;
  103. /* Get our FDT node and SoC id */
  104. node = ofw_bus_get_node(dev);
  105. /* Now let's see about setting USB to host or device mode */
  106. /* XXX: is it the same for all SoCs? */
  107. val = mtk_sysctl_get(SYSCTL_SYSCFG1);
  108. if (OF_hasprop(node, "mtk,usb-device"))
  109. val &= ~SYSCFG1_USB_HOST_MODE;
  110. else
  111. val |= SYSCFG1_USB_HOST_MODE;
  112. mtk_sysctl_set(SYSCTL_SYSCFG1, val);
  113. /* If we have clocks defined - enable them */
  114. if (OF_hasprop(node, "clocks"))
  115. fdt_clock_enable_all(dev);
  116. /* If we have resets defined - perform a reset sequence */
  117. if (OF_hasprop(node, "resets")) {
  118. fdt_reset_assert_all(dev);
  119. DELAY(RESET_ASSERT_DELAY);
  120. fdt_reset_deassert_all(dev);
  121. DELAY(RESET_DEASSERT_DELAY);
  122. }
  123. /* Careful, some devices actually require resources */
  124. if (OF_hasprop(node, "reg")) {
  125. rid = 0;
  126. sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  127. RF_ACTIVE);
  128. if (sc->res == NULL) {
  129. device_printf(dev, "could not map memory\n");
  130. return (ENXIO);
  131. }
  132. } else {
  133. sc->res = NULL;
  134. }
  135. /* Some SoCs require specific USB PHY init... handle these */
  136. switch (sc->socid) {
  137. case MTK_SOC_MT7628: /* Fallthrough */
  138. case MTK_SOC_MT7688:
  139. if (sc->res == NULL)
  140. return (ENXIO);
  141. sc->fm_base = MT7628_FM_FEG_BASE;
  142. sc->u2_base = MT7628_U2_BASE;
  143. sc->sr_coef = MT7628_SR_COEF;
  144. mtk_usb_phy_mt7628_init(dev);
  145. break;
  146. case MTK_SOC_MT7621:
  147. if (sc->res == NULL)
  148. return (ENXIO);
  149. sc->fm_base = MT7621_FM_FEG_BASE;
  150. sc->u2_base = MT7621_U2_BASE;
  151. sc->sr_coef = MT7621_SR_COEF;
  152. mtk_usb_phy_mt7621_init(dev);
  153. break;
  154. }
  155. /* We no longer need the resources, release them */
  156. if (sc->res != NULL)
  157. bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);
  158. return (0);
  159. }
  160. static int
  161. mtk_usb_phy_detach(device_t dev)
  162. {
  163. struct mtk_usb_phy_softc *sc = device_get_softc(dev);
  164. phandle_t node;
  165. /* Get our FDT node */
  166. node = ofw_bus_get_node(dev);
  167. /* If we have resets defined - assert them */
  168. if (OF_hasprop(node, "resets"))
  169. fdt_reset_assert_all(dev);
  170. /* If we have clocks defined - disable them */
  171. if (OF_hasprop(node, "clocks"))
  172. fdt_clock_disable_all(dev);
  173. /* Finally, release resources, if any were allocated */
  174. if (sc->res != NULL)
  175. bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->res);
  176. return (0);
  177. }
  178. /*
  179. * Things currently seem to work a lot better without slew rate calibration
  180. * both on MT7621 and MT7688, so we leave it out for now.
  181. */
  182. #ifdef notyet
  183. static void
  184. mtk_usb_phy_slew_rate_calibration(struct mtk_usb_phy_softc *sc)
  185. {
  186. uint32_t val;
  187. int i;
  188. USB_PHY_CLR_SET_U2(sc, U2_PHY_ACR0, 0, SRCAL_EN);
  189. USB_PHY_BARRIER(sc);
  190. DELAY(1000);
  191. USB_PHY_CLR_SET_FM(sc, U2_PHY_FMMONR1, 0, FRCK_EN);
  192. USB_PHY_BARRIER(sc);
  193. USB_PHY_CLR_SET_FM(sc, U2_PHY_FMCR0, CYCLECNT, 0x400);
  194. USB_PHY_BARRIER(sc);
  195. USB_PHY_CLR_SET_FM(sc, U2_PHY_FMCR0, 0, FDET_EN);
  196. USB_PHY_BARRIER(sc);
  197. for (i = 0; i < 1000; i++) {
  198. if ((val = USB_PHY_READ_FM(sc, U2_PHY_FMMONR0)) != 0) {
  199. device_printf(sc->dev, "DONE with FDET\n");
  200. break;
  201. }
  202. DELAY(10000);
  203. }
  204. device_printf(sc->dev, "After FDET\n");
  205. USB_PHY_CLR_SET_FM(sc, U2_PHY_FMCR0, FDET_EN, 0);
  206. USB_PHY_BARRIER(sc);
  207. USB_PHY_CLR_SET_FM(sc, U2_PHY_FMMONR1, FRCK_EN, 0);
  208. USB_PHY_BARRIER(sc);
  209. USB_PHY_CLR_SET_U2(sc, U2_PHY_ACR0, SRCAL_EN, 0);
  210. USB_PHY_BARRIER(sc);
  211. DELAY(1000);
  212. if (val == 0) {
  213. USB_PHY_CLR_SET_U2(sc, U2_PHY_ACR0, SRCTRL, 0x4 << SRCTRL_OFF);
  214. USB_PHY_BARRIER(sc);
  215. } else {
  216. val = ((((1024 * 25 * sc->sr_coef) / val) + 500) / 1000) &
  217. SRCTRL_MSK;
  218. USB_PHY_CLR_SET_U2(sc, U2_PHY_ACR0, SRCTRL, val << SRCTRL_OFF);
  219. USB_PHY_BARRIER(sc);
  220. }
  221. }
  222. #endif
  223. static void
  224. mtk_usb_phy_mt7621_init(device_t dev)
  225. {
  226. #ifdef notyet
  227. struct mtk_usb_phy_softc *sc = device_get_softc(dev);
  228. /* Slew rate calibration only, but for 2 ports */
  229. mtk_usb_phy_slew_rate_calibration(sc);
  230. sc->u2_base = MT7621_U2_BASE_P1;
  231. mtk_usb_phy_slew_rate_calibration(sc);
  232. #endif
  233. }
  234. static void
  235. mtk_usb_phy_mt7628_init(device_t dev)
  236. {
  237. struct mtk_usb_phy_softc *sc = device_get_softc(dev);
  238. /* XXX: possibly add barriers between the next writes? */
  239. USB_PHY_WRITE_U2(sc, U2_PHY_DCR0, 0x00ffff02);
  240. USB_PHY_BARRIER(sc);
  241. USB_PHY_WRITE_U2(sc, U2_PHY_DCR0, 0x00555502);
  242. USB_PHY_BARRIER(sc);
  243. USB_PHY_WRITE_U2(sc, U2_PHY_DCR0, 0x00aaaa02);
  244. USB_PHY_BARRIER(sc);
  245. USB_PHY_WRITE_U2(sc, U2_PHY_DCR0, 0x00000402);
  246. USB_PHY_BARRIER(sc);
  247. USB_PHY_WRITE_U2(sc, U2_PHY_AC0, 0x0048086a);
  248. USB_PHY_BARRIER(sc);
  249. USB_PHY_WRITE_U2(sc, U2_PHY_AC1, 0x4400001c);
  250. USB_PHY_BARRIER(sc);
  251. USB_PHY_WRITE_U2(sc, U2_PHY_ACR3, 0xc0200000);
  252. USB_PHY_BARRIER(sc);
  253. USB_PHY_WRITE_U2(sc, U2_PHY_DTM0, 0x02000000);
  254. USB_PHY_BARRIER(sc);
  255. #ifdef notyet
  256. /* Slew rate calibration */
  257. mtk_usb_phy_slew_rate_calibration(sc);
  258. #endif
  259. }
  260. static device_method_t mtk_usb_phy_methods[] = {
  261. /* Device interface */
  262. DEVMETHOD(device_probe, mtk_usb_phy_probe),
  263. DEVMETHOD(device_attach, mtk_usb_phy_attach),
  264. DEVMETHOD(device_detach, mtk_usb_phy_detach),
  265. DEVMETHOD(device_suspend, bus_generic_suspend),
  266. DEVMETHOD(device_resume, bus_generic_resume),
  267. DEVMETHOD(device_shutdown, bus_generic_shutdown),
  268. DEVMETHOD_END
  269. };
  270. static driver_t mtk_usb_phy_driver = {
  271. .name = "usbphy",
  272. .methods = mtk_usb_phy_methods,
  273. .size = sizeof(struct mtk_usb_phy_softc),
  274. };
  275. static devclass_t mtk_usb_phy_devclass;
  276. DRIVER_MODULE(usbphy, simplebus, mtk_usb_phy_driver, mtk_usb_phy_devclass, 0,
  277. 0);