usb-musb.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * linux/arch/arm/mach-omap2/usb-musb.c
  3. *
  4. * This file will contain the board specific details for the
  5. * MENTOR USB OTG controller on OMAP3430
  6. *
  7. * Copyright (C) 2007-2008 Texas Instruments
  8. * Copyright (C) 2008 Nokia Corporation
  9. * Author: Vikram Pandita
  10. *
  11. * Generalization by:
  12. * Felipe Balbi <felipe.balbi@nokia.com>
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License version 2 as
  16. * published by the Free Software Foundation.
  17. */
  18. #include <linux/types.h>
  19. #include <linux/errno.h>
  20. #include <linux/delay.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/clk.h>
  23. #include <linux/dma-mapping.h>
  24. #include <linux/io.h>
  25. #include <linux/usb/musb.h>
  26. #include <mach/hardware.h>
  27. #include <mach/irqs.h>
  28. #include <mach/am35xx.h>
  29. #include <plat/usb.h>
  30. #include "control.h"
  31. #if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
  32. static void am35x_musb_reset(void)
  33. {
  34. u32 regval;
  35. /* Reset the musb interface */
  36. regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
  37. regval |= AM35XX_USBOTGSS_SW_RST;
  38. omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
  39. regval &= ~AM35XX_USBOTGSS_SW_RST;
  40. omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
  41. regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
  42. }
  43. static void am35x_musb_phy_power(u8 on)
  44. {
  45. unsigned long timeout = jiffies + msecs_to_jiffies(100);
  46. u32 devconf2;
  47. if (on) {
  48. /*
  49. * Start the on-chip PHY and its PLL.
  50. */
  51. devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
  52. devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
  53. devconf2 |= CONF2_PHY_PLLON;
  54. omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
  55. pr_info(KERN_INFO "Waiting for PHY clock good...\n");
  56. while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
  57. & CONF2_PHYCLKGD)) {
  58. cpu_relax();
  59. if (time_after(jiffies, timeout)) {
  60. pr_err(KERN_ERR "musb PHY clock good timed out\n");
  61. break;
  62. }
  63. }
  64. } else {
  65. /*
  66. * Power down the on-chip PHY.
  67. */
  68. devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
  69. devconf2 &= ~CONF2_PHY_PLLON;
  70. devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN;
  71. omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
  72. }
  73. }
  74. static void am35x_musb_clear_irq(void)
  75. {
  76. u32 regval;
  77. regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
  78. regval |= AM35XX_USBOTGSS_INT_CLR;
  79. omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
  80. regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
  81. }
  82. static void am35x_musb_set_mode(u8 musb_mode)
  83. {
  84. u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
  85. devconf2 &= ~CONF2_OTGMODE;
  86. switch (musb_mode) {
  87. #ifdef CONFIG_USB_MUSB_HDRC_HCD
  88. case MUSB_HOST: /* Force VBUS valid, ID = 0 */
  89. devconf2 |= CONF2_FORCE_HOST;
  90. break;
  91. #endif
  92. #ifdef CONFIG_USB_GADGET_MUSB_HDRC
  93. case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */
  94. devconf2 |= CONF2_FORCE_DEVICE;
  95. break;
  96. #endif
  97. #ifdef CONFIG_USB_MUSB_OTG
  98. case MUSB_OTG: /* Don't override the VBUS/ID comparators */
  99. devconf2 |= CONF2_NO_OVERRIDE;
  100. break;
  101. #endif
  102. default:
  103. pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
  104. }
  105. omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
  106. }
  107. static struct resource musb_resources[] = {
  108. [0] = { /* start and end set dynamically */
  109. .flags = IORESOURCE_MEM,
  110. },
  111. [1] = { /* general IRQ */
  112. .start = INT_243X_HS_USB_MC,
  113. .flags = IORESOURCE_IRQ,
  114. .name = "mc",
  115. },
  116. [2] = { /* DMA IRQ */
  117. .start = INT_243X_HS_USB_DMA,
  118. .flags = IORESOURCE_IRQ,
  119. .name = "dma",
  120. },
  121. };
  122. static struct musb_hdrc_config musb_config = {
  123. .multipoint = 1,
  124. .dyn_fifo = 1,
  125. .num_eps = 16,
  126. .ram_bits = 12,
  127. };
  128. static struct musb_hdrc_platform_data musb_plat = {
  129. #ifdef CONFIG_USB_MUSB_OTG
  130. .mode = MUSB_OTG,
  131. #elif defined(CONFIG_USB_MUSB_HDRC_HCD)
  132. .mode = MUSB_HOST,
  133. #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
  134. .mode = MUSB_PERIPHERAL,
  135. #endif
  136. /* .clock is set dynamically */
  137. .config = &musb_config,
  138. /* REVISIT charge pump on TWL4030 can supply up to
  139. * 100 mA ... but this value is board-specific, like
  140. * "mode", and should be passed to usb_musb_init().
  141. */
  142. .power = 50, /* up to 100 mA */
  143. };
  144. static u64 musb_dmamask = DMA_BIT_MASK(32);
  145. static struct platform_device musb_device = {
  146. .name = "musb-omap2430",
  147. .id = -1,
  148. .dev = {
  149. .dma_mask = &musb_dmamask,
  150. .coherent_dma_mask = DMA_BIT_MASK(32),
  151. .platform_data = &musb_plat,
  152. },
  153. .num_resources = ARRAY_SIZE(musb_resources),
  154. .resource = musb_resources,
  155. };
  156. void __init usb_musb_init(struct omap_musb_board_data *board_data)
  157. {
  158. if (cpu_is_omap243x()) {
  159. musb_resources[0].start = OMAP243X_HS_BASE;
  160. } else if (cpu_is_omap3517() || cpu_is_omap3505()) {
  161. musb_device.name = "musb-am35x";
  162. musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
  163. musb_resources[1].start = INT_35XX_USBOTG_IRQ;
  164. board_data->set_phy_power = am35x_musb_phy_power;
  165. board_data->clear_irq = am35x_musb_clear_irq;
  166. board_data->set_mode = am35x_musb_set_mode;
  167. board_data->reset = am35x_musb_reset;
  168. } else if (cpu_is_omap34xx()) {
  169. musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
  170. } else if (cpu_is_omap44xx()) {
  171. musb_resources[0].start = OMAP44XX_HSUSB_OTG_BASE;
  172. musb_resources[1].start = OMAP44XX_IRQ_HS_USB_MC_N;
  173. musb_resources[2].start = OMAP44XX_IRQ_HS_USB_DMA_N;
  174. }
  175. musb_resources[0].end = musb_resources[0].start + SZ_4K - 1;
  176. /*
  177. * REVISIT: This line can be removed once all the platforms using
  178. * musb_core.c have been converted to use use clkdev.
  179. */
  180. musb_plat.clock = "ick";
  181. musb_plat.board_data = board_data;
  182. musb_plat.power = board_data->power >> 1;
  183. musb_plat.mode = board_data->mode;
  184. musb_plat.extvbus = board_data->extvbus;
  185. if (platform_device_register(&musb_device) < 0)
  186. printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
  187. }
  188. #else
  189. void __init usb_musb_init(struct omap_musb_board_data *board_data)
  190. {
  191. }
  192. #endif /* CONFIG_USB_MUSB_SOC */