ehci-mpc512x.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * (C) Copyright 2010, Damien Dusha, <d.dusha@gmail.com>
  3. *
  4. * (C) Copyright 2009, Value Team S.p.A.
  5. * Francesco Rendine, <francesco.rendine@valueteam.com>
  6. *
  7. * (C) Copyright 2009 Freescale Semiconductor, Inc.
  8. *
  9. * (C) Copyright 2008, Excito Elektronik i Sk=E5ne AB
  10. *
  11. * Author: Tor Krill tor@excito.com
  12. *
  13. * SPDX-License-Identifier: GPL-2.0+
  14. */
  15. #include <common.h>
  16. #include <pci.h>
  17. #include <usb.h>
  18. #include <asm/io.h>
  19. #include <usb/ehci-ci.h>
  20. #include "ehci.h"
  21. static void fsl_setup_phy(volatile struct ehci_hcor *);
  22. static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci);
  23. static int reset_usb_controller(volatile struct usb_ehci *ehci);
  24. static void usb_platform_dr_init(volatile struct usb_ehci *ehci);
  25. /*
  26. * Initialize SOC FSL EHCI Controller
  27. *
  28. * This code is derived from EHCI FSL USB Linux driver for MPC5121
  29. *
  30. */
  31. int ehci_hcd_init(int index, enum usb_init_type init,
  32. struct ehci_hccr **hccr, struct ehci_hcor **hcor)
  33. {
  34. volatile struct usb_ehci *ehci;
  35. /* Hook the memory mapped registers for EHCI-Controller */
  36. ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR;
  37. *hccr = (struct ehci_hccr *)((uint32_t)&(ehci->caplength));
  38. *hcor = (struct ehci_hcor *)((uint32_t) *hccr +
  39. HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
  40. /* configure interface for UTMI_WIDE */
  41. usb_platform_dr_init(ehci);
  42. /* Init Phy USB0 to UTMI+ */
  43. fsl_setup_phy(*hcor);
  44. /* Set to host mode */
  45. fsl_platform_set_host_mode(ehci);
  46. /*
  47. * Setting the burst size seems to be required to prevent the
  48. * USB from hanging when communicating with certain USB Mass
  49. * storage devices. This was determined by analysing the
  50. * EHCI registers under Linux vs U-Boot and burstsize was the
  51. * major non-interrupt related difference between the two
  52. * implementations.
  53. *
  54. * Some USB sticks behave better than others. In particular,
  55. * the following USB stick is especially problematic:
  56. * 0930:6545 Toshiba Corp
  57. *
  58. * The burstsize is set here to match the Linux implementation.
  59. */
  60. out_be32(&ehci->burstsize, FSL_EHCI_TXPBURST(8) |
  61. FSL_EHCI_RXPBURST(8));
  62. return 0;
  63. }
  64. /*
  65. * Destroy the appropriate control structures corresponding
  66. * the the EHCI host controller.
  67. */
  68. int ehci_hcd_stop(int index)
  69. {
  70. volatile struct usb_ehci *ehci;
  71. int exit_status = 0;
  72. /* Reset the USB controller */
  73. ehci = (struct usb_ehci *)CONFIG_SYS_FSL_USB1_ADDR;
  74. exit_status = reset_usb_controller(ehci);
  75. return exit_status;
  76. }
  77. static int reset_usb_controller(volatile struct usb_ehci *ehci)
  78. {
  79. unsigned int i;
  80. /* Command a reset of the USB Controller */
  81. out_be32(&(ehci->usbcmd), CMD_RESET);
  82. /* Wait for the reset process to finish */
  83. for (i = 65535 ; i > 0 ; i--) {
  84. /*
  85. * The host will set this bit to zero once the
  86. * reset process is complete
  87. */
  88. if ((in_be32(&(ehci->usbcmd)) & CMD_RESET) == 0)
  89. return 0;
  90. }
  91. /* Hub did not reset in time */
  92. return -1;
  93. }
  94. static void fsl_setup_phy(volatile struct ehci_hcor *hcor)
  95. {
  96. uint32_t portsc;
  97. portsc = ehci_readl(&hcor->or_portsc[0]);
  98. portsc &= ~(PORT_PTS_MSK | PORT_PTS_PTW);
  99. /* Enable the phy mode to UTMI Wide */
  100. portsc |= PORT_PTS_PTW;
  101. portsc |= PORT_PTS_UTMI;
  102. ehci_writel(&hcor->or_portsc[0], portsc);
  103. }
  104. static void fsl_platform_set_host_mode(volatile struct usb_ehci *ehci)
  105. {
  106. uint32_t temp;
  107. temp = in_le32(&ehci->usbmode);
  108. temp |= CM_HOST | ES_BE;
  109. out_le32(&ehci->usbmode, temp);
  110. }
  111. static void usb_platform_dr_init(volatile struct usb_ehci *ehci)
  112. {
  113. /* Configure interface for UTMI_WIDE */
  114. out_be32(&ehci->isiphyctrl, PHYCTRL_PHYE | PHYCTRL_PXE);
  115. out_be32(&ehci->usbgenctrl, GC_PPP | GC_PFP );
  116. }