103-MIPS-BCM63XX-add-OHCI-EHCI-configuration-bits-to-com.patch 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. From 28758a9da77954ed323f86123ef448c6a563c037 Mon Sep 17 00:00:00 2001
  2. From: Florian Fainelli <florian@openwrt.org>
  3. Date: Mon, 28 Jan 2013 20:06:22 +0100
  4. Subject: [PATCH 04/11] MIPS: BCM63XX: add OHCI/EHCI configuration bits to
  5. common USB code
  6. This patch updates the common USB code touching the USB private
  7. registers with the specific bits to properly enable OHCI and EHCI
  8. controllers on BCM63xx SoCs. As a result we now need to protect access
  9. to Read Modify Write sequences using a spinlock because we cannot
  10. guarantee that any of the exposed helper will not be called
  11. concurrently.
  12. Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
  13. Signed-off-by: Florian Fainelli <florian@openwrt.org>
  14. ---
  15. arch/mips/bcm63xx/usb-common.c | 97 ++++++++++++++++++++
  16. .../include/asm/mach-bcm63xx/bcm63xx_usb_priv.h | 2 +
  17. 2 files changed, 99 insertions(+)
  18. --- a/arch/mips/bcm63xx/usb-common.c
  19. +++ b/arch/mips/bcm63xx/usb-common.c
  20. @@ -5,10 +5,12 @@
  21. * License. See the file "COPYING" in the main directory of this archive
  22. * for more details.
  23. *
  24. + * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
  25. * Copyright (C) 2012 Kevin Cernekee <cernekee@gmail.com>
  26. * Copyright (C) 2012 Broadcom Corporation
  27. *
  28. */
  29. +#include <linux/spinlock.h>
  30. #include <linux/export.h>
  31. #include <bcm63xx_cpu.h>
  32. @@ -16,9 +18,14 @@
  33. #include <bcm63xx_io.h>
  34. #include <bcm63xx_usb_priv.h>
  35. +static DEFINE_SPINLOCK(usb_priv_reg_lock);
  36. +
  37. void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device)
  38. {
  39. u32 val;
  40. + unsigned long flags;
  41. +
  42. + spin_lock_irqsave(&usb_priv_reg_lock, flags);
  43. val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
  44. if (is_device) {
  45. @@ -36,12 +43,17 @@ void bcm63xx_usb_priv_select_phy_mode(u3
  46. else
  47. val &= ~USBH_PRIV_SWAP_USBD_MASK;
  48. bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG);
  49. +
  50. + spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
  51. }
  52. EXPORT_SYMBOL(bcm63xx_usb_priv_select_phy_mode);
  53. void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on)
  54. {
  55. u32 val;
  56. + unsigned long flags;
  57. +
  58. + spin_lock_irqsave(&usb_priv_reg_lock, flags);
  59. val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG);
  60. if (is_on)
  61. @@ -49,5 +61,90 @@ void bcm63xx_usb_priv_select_pullup(u32
  62. else
  63. val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT);
  64. bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG);
  65. +
  66. + spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
  67. }
  68. EXPORT_SYMBOL(bcm63xx_usb_priv_select_pullup);
  69. +
  70. +/* The following array represents the meaning of the DESC/DATA
  71. + * endian swapping with respect to the CPU configured endianness
  72. + *
  73. + * DATA ENDN mmio descriptor
  74. + * 0 0 BE invalid
  75. + * 0 1 BE LE
  76. + * 1 0 BE BE
  77. + * 1 1 BE invalid
  78. + *
  79. + * Since BCM63XX SoCs are configured to be in big-endian mode
  80. + * we want configuration at line 3.
  81. + */
  82. +void bcm63xx_usb_priv_ohci_cfg_set(void)
  83. +{
  84. + u32 reg;
  85. + unsigned long flags;
  86. +
  87. + spin_lock_irqsave(&usb_priv_reg_lock, flags);
  88. +
  89. + if (BCMCPU_IS_6348())
  90. + bcm_rset_writel(RSET_OHCI_PRIV, 0, OHCI_PRIV_REG);
  91. + else if (BCMCPU_IS_6358()) {
  92. + reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
  93. + reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
  94. + reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
  95. + bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
  96. + /*
  97. + * The magic value comes for the original vendor BSP
  98. + * and is needed for USB to work. Datasheet does not
  99. + * help, so the magic value is used as-is.
  100. + */
  101. + bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
  102. + USBH_PRIV_TEST_6358_REG);
  103. +
  104. + } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
  105. + reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
  106. + reg &= ~USBH_PRIV_SWAP_OHCI_ENDN_MASK;
  107. + reg |= USBH_PRIV_SWAP_OHCI_DATA_MASK;
  108. + bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
  109. +
  110. + reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
  111. + reg |= USBH_PRIV_SETUP_IOC_MASK;
  112. + bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
  113. + }
  114. +
  115. + spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
  116. +}
  117. +
  118. +void bcm63xx_usb_priv_ehci_cfg_set(void)
  119. +{
  120. + u32 reg;
  121. + unsigned long flags;
  122. +
  123. + spin_lock_irqsave(&usb_priv_reg_lock, flags);
  124. +
  125. + if (BCMCPU_IS_6358()) {
  126. + reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6358_REG);
  127. + reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
  128. + reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
  129. + bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6358_REG);
  130. +
  131. + /*
  132. + * The magic value comes for the original vendor BSP
  133. + * and is needed for USB to work. Datasheet does not
  134. + * help, so the magic value is used as-is.
  135. + */
  136. + bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020,
  137. + USBH_PRIV_TEST_6358_REG);
  138. +
  139. + } else if (BCMCPU_IS_6328() || BCMCPU_IS_6362() || BCMCPU_IS_6368()) {
  140. + reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG);
  141. + reg &= ~USBH_PRIV_SWAP_EHCI_ENDN_MASK;
  142. + reg |= USBH_PRIV_SWAP_EHCI_DATA_MASK;
  143. + bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_6368_REG);
  144. +
  145. + reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SETUP_6368_REG);
  146. + reg |= USBH_PRIV_SETUP_IOC_MASK;
  147. + bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SETUP_6368_REG);
  148. + }
  149. +
  150. + spin_unlock_irqrestore(&usb_priv_reg_lock, flags);
  151. +}
  152. --- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
  153. +++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_usb_priv.h
  154. @@ -5,5 +5,7 @@
  155. void bcm63xx_usb_priv_select_phy_mode(u32 portmask, bool is_device);
  156. void bcm63xx_usb_priv_select_pullup(u32 portmask, bool is_on);
  157. +void bcm63xx_usb_priv_ohci_cfg_set(void);
  158. +void bcm63xx_usb_priv_ehci_cfg_set(void);
  159. #endif /* BCM63XX_USB_PRIV_H_ */