ehci-fsl.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /*
  2. * (C) Copyright 2009, 2011 Freescale Semiconductor, Inc.
  3. *
  4. * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
  5. *
  6. * Author: Tor Krill tor@excito.com
  7. *
  8. * SPDX-License-Identifier: GPL-2.0+
  9. */
  10. #include <common.h>
  11. #include <pci.h>
  12. #include <usb.h>
  13. #include <asm/io.h>
  14. #include <usb/ehci-fsl.h>
  15. #include <hwconfig.h>
  16. #include <fsl_usb.h>
  17. #include <fdt_support.h>
  18. #include "ehci.h"
  19. #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT
  20. #define CONFIG_USB_MAX_CONTROLLER_COUNT 1
  21. #endif
  22. static void set_txfifothresh(struct usb_ehci *, u32);
  23. /* Check USB PHY clock valid */
  24. static int usb_phy_clk_valid(struct usb_ehci *ehci)
  25. {
  26. if (!((in_be32(&ehci->control) & PHY_CLK_VALID) ||
  27. in_be32(&ehci->prictrl))) {
  28. printf("USB PHY clock invalid!\n");
  29. return 0;
  30. } else {
  31. return 1;
  32. }
  33. }
  34. /*
  35. * Create the appropriate control structures to manage
  36. * a new EHCI host controller.
  37. *
  38. * Excerpts from linux ehci fsl driver.
  39. */
  40. int ehci_hcd_init(int index, enum usb_init_type init,
  41. struct ehci_hccr **hccr, struct ehci_hcor **hcor)
  42. {
  43. struct usb_ehci *ehci = NULL;
  44. const char *phy_type = NULL;
  45. size_t len;
  46. char current_usb_controller[5];
  47. #ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
  48. char usb_phy[5];
  49. usb_phy[0] = '\0';
  50. #endif
  51. if (has_erratum_a007075()) {
  52. /*
  53. * A 5ms delay is needed after applying soft-reset to the
  54. * controller to let external ULPI phy come out of reset.
  55. * This delay needs to be added before re-initializing
  56. * the controller after soft-resetting completes
  57. */
  58. mdelay(5);
  59. }
  60. memset(current_usb_controller, '\0', 5);
  61. snprintf(current_usb_controller, 4, "usb%d", index+1);
  62. switch (index) {
  63. case 0:
  64. ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR;
  65. break;
  66. case 1:
  67. ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB2_ADDR;
  68. break;
  69. default:
  70. printf("ERROR: wrong controller index!!\n");
  71. return -EINVAL;
  72. };
  73. *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength);
  74. *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
  75. HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
  76. /* Set to Host mode */
  77. setbits_le32(&ehci->usbmode, CM_HOST);
  78. out_be32(&ehci->snoop1, SNOOP_SIZE_2GB);
  79. out_be32(&ehci->snoop2, 0x80000000 | SNOOP_SIZE_2GB);
  80. /* Init phy */
  81. if (hwconfig_sub(current_usb_controller, "phy_type"))
  82. phy_type = hwconfig_subarg(current_usb_controller,
  83. "phy_type", &len);
  84. else
  85. phy_type = getenv("usb_phy_type");
  86. if (!phy_type) {
  87. #ifdef CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY
  88. /* if none specified assume internal UTMI */
  89. strcpy(usb_phy, "utmi");
  90. phy_type = usb_phy;
  91. #else
  92. printf("WARNING: USB phy type not defined !!\n");
  93. return -1;
  94. #endif
  95. }
  96. if (!strncmp(phy_type, "utmi", 4)) {
  97. #if defined(CONFIG_SYS_FSL_USB_INTERNAL_UTMI_PHY)
  98. clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
  99. PHY_CLK_SEL_UTMI);
  100. clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
  101. UTMI_PHY_EN);
  102. udelay(1000); /* delay required for PHY Clk to appear */
  103. #endif
  104. out_le32(&(*hcor)->or_portsc[0], PORT_PTS_UTMI);
  105. clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
  106. USB_EN);
  107. } else {
  108. clrsetbits_be32(&ehci->control, CONTROL_REGISTER_W1C_MASK,
  109. PHY_CLK_SEL_ULPI);
  110. clrsetbits_be32(&ehci->control, UTMI_PHY_EN |
  111. CONTROL_REGISTER_W1C_MASK, USB_EN);
  112. udelay(1000); /* delay required for PHY Clk to appear */
  113. if (!usb_phy_clk_valid(ehci))
  114. return -EINVAL;
  115. out_le32(&(*hcor)->or_portsc[0], PORT_PTS_ULPI);
  116. }
  117. out_be32(&ehci->prictrl, 0x0000000c);
  118. out_be32(&ehci->age_cnt_limit, 0x00000040);
  119. out_be32(&ehci->sictrl, 0x00000001);
  120. in_le32(&ehci->usbmode);
  121. if (has_erratum_a007798())
  122. set_txfifothresh(ehci, TXFIFOTHRESH);
  123. if (has_erratum_a004477()) {
  124. /*
  125. * When reset is issued while any ULPI transaction is ongoing
  126. * then it may result to corruption of ULPI Function Control
  127. * Register which eventually causes phy clock to enter low
  128. * power mode which stops the clock. Thus delay is required
  129. * before reset to let ongoing ULPI transaction complete.
  130. */
  131. udelay(1);
  132. }
  133. return 0;
  134. }
  135. /*
  136. * Destroy the appropriate control structures corresponding
  137. * the the EHCI host controller.
  138. */
  139. int ehci_hcd_stop(int index)
  140. {
  141. return 0;
  142. }
  143. /*
  144. * Setting the value of TXFIFO_THRESH field in TXFILLTUNING register
  145. * to counter DDR latencies in writing data into Tx buffer.
  146. * This prevents Tx buffer from getting underrun
  147. */
  148. static void set_txfifothresh(struct usb_ehci *ehci, u32 txfifo_thresh)
  149. {
  150. u32 cmd;
  151. cmd = ehci_readl(&ehci->txfilltuning);
  152. cmd &= ~TXFIFO_THRESH_MASK;
  153. cmd |= TXFIFO_THRESH(txfifo_thresh);
  154. ehci_writel(&ehci->txfilltuning, cmd);
  155. }
  156. #if defined(CONFIG_HAS_FSL_DR_USB) || defined(CONFIG_HAS_FSL_MPH_USB)
  157. static int fdt_fixup_usb_mode_phy_type(void *blob, const char *mode,
  158. const char *phy_type, int start_offset)
  159. {
  160. const char *compat_dr = "fsl-usb2-dr";
  161. const char *compat_mph = "fsl-usb2-mph";
  162. const char *prop_mode = "dr_mode";
  163. const char *prop_type = "phy_type";
  164. const char *node_type = NULL;
  165. int node_offset;
  166. int err;
  167. node_offset = fdt_node_offset_by_compatible(blob,
  168. start_offset, compat_mph);
  169. if (node_offset < 0) {
  170. node_offset = fdt_node_offset_by_compatible(blob,
  171. start_offset,
  172. compat_dr);
  173. if (node_offset < 0) {
  174. printf("WARNING: could not find compatible node: %s",
  175. fdt_strerror(node_offset));
  176. return -1;
  177. }
  178. node_type = compat_dr;
  179. } else {
  180. node_type = compat_mph;
  181. }
  182. if (mode) {
  183. err = fdt_setprop(blob, node_offset, prop_mode, mode,
  184. strlen(mode) + 1);
  185. if (err < 0)
  186. printf("WARNING: could not set %s for %s: %s.\n",
  187. prop_mode, node_type, fdt_strerror(err));
  188. }
  189. if (phy_type) {
  190. err = fdt_setprop(blob, node_offset, prop_type, phy_type,
  191. strlen(phy_type) + 1);
  192. if (err < 0)
  193. printf("WARNING: could not set %s for %s: %s.\n",
  194. prop_type, node_type, fdt_strerror(err));
  195. }
  196. return node_offset;
  197. }
  198. static const char *fdt_usb_get_node_type(void *blob, int start_offset,
  199. int *node_offset)
  200. {
  201. const char *compat_dr = "fsl-usb2-dr";
  202. const char *compat_mph = "fsl-usb2-mph";
  203. const char *node_type = NULL;
  204. *node_offset = fdt_node_offset_by_compatible(blob, start_offset,
  205. compat_mph);
  206. if (*node_offset < 0) {
  207. *node_offset = fdt_node_offset_by_compatible(blob,
  208. start_offset,
  209. compat_dr);
  210. if (*node_offset < 0) {
  211. printf("ERROR: could not find compatible node: %s\n",
  212. fdt_strerror(*node_offset));
  213. } else {
  214. node_type = compat_dr;
  215. }
  216. } else {
  217. node_type = compat_mph;
  218. }
  219. return node_type;
  220. }
  221. static int fdt_fixup_usb_erratum(void *blob, const char *prop_erratum,
  222. int start_offset)
  223. {
  224. int node_offset, err;
  225. const char *node_type = NULL;
  226. node_type = fdt_usb_get_node_type(blob, start_offset, &node_offset);
  227. if (!node_type)
  228. return -1;
  229. err = fdt_setprop(blob, node_offset, prop_erratum, NULL, 0);
  230. if (err < 0) {
  231. printf("ERROR: could not set %s for %s: %s.\n",
  232. prop_erratum, node_type, fdt_strerror(err));
  233. }
  234. return node_offset;
  235. }
  236. void fdt_fixup_dr_usb(void *blob, bd_t *bd)
  237. {
  238. static const char * const modes[] = { "host", "peripheral", "otg" };
  239. static const char * const phys[] = { "ulpi", "utmi", "utmi_dual" };
  240. int usb_erratum_a006261_off = -1;
  241. int usb_erratum_a007075_off = -1;
  242. int usb_erratum_a007792_off = -1;
  243. int usb_erratum_a005697_off = -1;
  244. int usb_mode_off = -1;
  245. int usb_phy_off = -1;
  246. char str[5];
  247. int i, j;
  248. for (i = 1; i <= CONFIG_USB_MAX_CONTROLLER_COUNT; i++) {
  249. const char *dr_mode_type = NULL;
  250. const char *dr_phy_type = NULL;
  251. int mode_idx = -1, phy_idx = -1;
  252. snprintf(str, 5, "%s%d", "usb", i);
  253. if (hwconfig(str)) {
  254. for (j = 0; j < ARRAY_SIZE(modes); j++) {
  255. if (hwconfig_subarg_cmp(str, "dr_mode",
  256. modes[j])) {
  257. mode_idx = j;
  258. break;
  259. }
  260. }
  261. for (j = 0; j < ARRAY_SIZE(phys); j++) {
  262. if (hwconfig_subarg_cmp(str, "phy_type",
  263. phys[j])) {
  264. phy_idx = j;
  265. break;
  266. }
  267. }
  268. if (mode_idx < 0 && phy_idx < 0) {
  269. printf("WARNING: invalid phy or mode\n");
  270. return;
  271. }
  272. if (mode_idx > -1)
  273. dr_mode_type = modes[mode_idx];
  274. if (phy_idx > -1)
  275. dr_phy_type = phys[phy_idx];
  276. }
  277. if (has_dual_phy())
  278. dr_phy_type = phys[2];
  279. usb_mode_off = fdt_fixup_usb_mode_phy_type(blob,
  280. dr_mode_type, NULL,
  281. usb_mode_off);
  282. if (usb_mode_off < 0)
  283. return;
  284. usb_phy_off = fdt_fixup_usb_mode_phy_type(blob,
  285. NULL, dr_phy_type,
  286. usb_phy_off);
  287. if (usb_phy_off < 0)
  288. return;
  289. if (has_erratum_a006261()) {
  290. usb_erratum_a006261_off = fdt_fixup_usb_erratum
  291. (blob,
  292. "fsl,usb-erratum-a006261",
  293. usb_erratum_a006261_off);
  294. if (usb_erratum_a006261_off < 0)
  295. return;
  296. }
  297. if (has_erratum_a007075()) {
  298. usb_erratum_a007075_off = fdt_fixup_usb_erratum
  299. (blob,
  300. "fsl,usb-erratum-a007075",
  301. usb_erratum_a007075_off);
  302. if (usb_erratum_a007075_off < 0)
  303. return;
  304. }
  305. if (has_erratum_a007792()) {
  306. usb_erratum_a007792_off = fdt_fixup_usb_erratum
  307. (blob,
  308. "fsl,usb-erratum-a007792",
  309. usb_erratum_a007792_off);
  310. if (usb_erratum_a007792_off < 0)
  311. return;
  312. }
  313. if (has_erratum_a005697()) {
  314. usb_erratum_a005697_off = fdt_fixup_usb_erratum
  315. (blob,
  316. "fsl,usb-erratum-a005697",
  317. usb_erratum_a005697_off);
  318. if (usb_erratum_a005697_off < 0)
  319. return;
  320. }
  321. }
  322. }
  323. #endif