diff options
Diffstat (limited to 'arch/arm/mach-omap2/usb-musb.c')
-rw-r--r-- | arch/arm/mach-omap2/usb-musb.c | 219 |
1 files changed, 83 insertions, 136 deletions
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index 5298949d4b11..a9d4d143086d 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c | |||
@@ -30,118 +30,11 @@ | |||
30 | #include <mach/irqs.h> | 30 | #include <mach/irqs.h> |
31 | #include <mach/am35xx.h> | 31 | #include <mach/am35xx.h> |
32 | #include <plat/usb.h> | 32 | #include <plat/usb.h> |
33 | #include "control.h" | 33 | #include <plat/omap_device.h> |
34 | #include "mux.h" | ||
34 | 35 | ||
35 | #if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X) | 36 | #if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X) |
36 | 37 | ||
37 | static void am35x_musb_reset(void) | ||
38 | { | ||
39 | u32 regval; | ||
40 | |||
41 | /* Reset the musb interface */ | ||
42 | regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); | ||
43 | |||
44 | regval |= AM35XX_USBOTGSS_SW_RST; | ||
45 | omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET); | ||
46 | |||
47 | regval &= ~AM35XX_USBOTGSS_SW_RST; | ||
48 | omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET); | ||
49 | |||
50 | regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); | ||
51 | } | ||
52 | |||
53 | static void am35x_musb_phy_power(u8 on) | ||
54 | { | ||
55 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | ||
56 | u32 devconf2; | ||
57 | |||
58 | if (on) { | ||
59 | /* | ||
60 | * Start the on-chip PHY and its PLL. | ||
61 | */ | ||
62 | devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
63 | |||
64 | devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN); | ||
65 | devconf2 |= CONF2_PHY_PLLON; | ||
66 | |||
67 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
68 | |||
69 | pr_info(KERN_INFO "Waiting for PHY clock good...\n"); | ||
70 | while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2) | ||
71 | & CONF2_PHYCLKGD)) { | ||
72 | cpu_relax(); | ||
73 | |||
74 | if (time_after(jiffies, timeout)) { | ||
75 | pr_err(KERN_ERR "musb PHY clock good timed out\n"); | ||
76 | break; | ||
77 | } | ||
78 | } | ||
79 | } else { | ||
80 | /* | ||
81 | * Power down the on-chip PHY. | ||
82 | */ | ||
83 | devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
84 | |||
85 | devconf2 &= ~CONF2_PHY_PLLON; | ||
86 | devconf2 |= CONF2_PHYPWRDN | CONF2_OTGPWRDN; | ||
87 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
88 | } | ||
89 | } | ||
90 | |||
91 | static void am35x_musb_clear_irq(void) | ||
92 | { | ||
93 | u32 regval; | ||
94 | |||
95 | regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | ||
96 | regval |= AM35XX_USBOTGSS_INT_CLR; | ||
97 | omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR); | ||
98 | regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); | ||
99 | } | ||
100 | |||
101 | static void am35x_musb_set_mode(u8 musb_mode) | ||
102 | { | ||
103 | u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2); | ||
104 | |||
105 | devconf2 &= ~CONF2_OTGMODE; | ||
106 | switch (musb_mode) { | ||
107 | #ifdef CONFIG_USB_MUSB_HDRC_HCD | ||
108 | case MUSB_HOST: /* Force VBUS valid, ID = 0 */ | ||
109 | devconf2 |= CONF2_FORCE_HOST; | ||
110 | break; | ||
111 | #endif | ||
112 | #ifdef CONFIG_USB_GADGET_MUSB_HDRC | ||
113 | case MUSB_PERIPHERAL: /* Force VBUS valid, ID = 1 */ | ||
114 | devconf2 |= CONF2_FORCE_DEVICE; | ||
115 | break; | ||
116 | #endif | ||
117 | #ifdef CONFIG_USB_MUSB_OTG | ||
118 | case MUSB_OTG: /* Don't override the VBUS/ID comparators */ | ||
119 | devconf2 |= CONF2_NO_OVERRIDE; | ||
120 | break; | ||
121 | #endif | ||
122 | default: | ||
123 | pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode); | ||
124 | } | ||
125 | |||
126 | omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2); | ||
127 | } | ||
128 | |||
129 | static struct resource musb_resources[] = { | ||
130 | [0] = { /* start and end set dynamically */ | ||
131 | .flags = IORESOURCE_MEM, | ||
132 | }, | ||
133 | [1] = { /* general IRQ */ | ||
134 | .start = INT_243X_HS_USB_MC, | ||
135 | .flags = IORESOURCE_IRQ, | ||
136 | .name = "mc", | ||
137 | }, | ||
138 | [2] = { /* DMA IRQ */ | ||
139 | .start = INT_243X_HS_USB_DMA, | ||
140 | .flags = IORESOURCE_IRQ, | ||
141 | .name = "dma", | ||
142 | }, | ||
143 | }; | ||
144 | |||
145 | static struct musb_hdrc_config musb_config = { | 38 | static struct musb_hdrc_config musb_config = { |
146 | .multipoint = 1, | 39 | .multipoint = 1, |
147 | .dyn_fifo = 1, | 40 | .dyn_fifo = 1, |
@@ -169,38 +62,65 @@ static struct musb_hdrc_platform_data musb_plat = { | |||
169 | 62 | ||
170 | static u64 musb_dmamask = DMA_BIT_MASK(32); | 63 | static u64 musb_dmamask = DMA_BIT_MASK(32); |
171 | 64 | ||
172 | static struct platform_device musb_device = { | 65 | static struct omap_device_pm_latency omap_musb_latency[] = { |
173 | .name = "musb-omap2430", | 66 | { |
174 | .id = -1, | 67 | .deactivate_func = omap_device_idle_hwmods, |
175 | .dev = { | 68 | .activate_func = omap_device_enable_hwmods, |
176 | .dma_mask = &musb_dmamask, | 69 | .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, |
177 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
178 | .platform_data = &musb_plat, | ||
179 | }, | 70 | }, |
180 | .num_resources = ARRAY_SIZE(musb_resources), | ||
181 | .resource = musb_resources, | ||
182 | }; | 71 | }; |
183 | 72 | ||
73 | static void usb_musb_mux_init(struct omap_musb_board_data *board_data) | ||
74 | { | ||
75 | switch (board_data->interface_type) { | ||
76 | case MUSB_INTERFACE_UTMI: | ||
77 | omap_mux_init_signal("usba0_otg_dp", OMAP_PIN_INPUT); | ||
78 | omap_mux_init_signal("usba0_otg_dm", OMAP_PIN_INPUT); | ||
79 | break; | ||
80 | case MUSB_INTERFACE_ULPI: | ||
81 | omap_mux_init_signal("usba0_ulpiphy_clk", | ||
82 | OMAP_PIN_INPUT_PULLDOWN); | ||
83 | omap_mux_init_signal("usba0_ulpiphy_stp", | ||
84 | OMAP_PIN_INPUT_PULLDOWN); | ||
85 | omap_mux_init_signal("usba0_ulpiphy_dir", | ||
86 | OMAP_PIN_INPUT_PULLDOWN); | ||
87 | omap_mux_init_signal("usba0_ulpiphy_nxt", | ||
88 | OMAP_PIN_INPUT_PULLDOWN); | ||
89 | omap_mux_init_signal("usba0_ulpiphy_dat0", | ||
90 | OMAP_PIN_INPUT_PULLDOWN); | ||
91 | omap_mux_init_signal("usba0_ulpiphy_dat1", | ||
92 | OMAP_PIN_INPUT_PULLDOWN); | ||
93 | omap_mux_init_signal("usba0_ulpiphy_dat2", | ||
94 | OMAP_PIN_INPUT_PULLDOWN); | ||
95 | omap_mux_init_signal("usba0_ulpiphy_dat3", | ||
96 | OMAP_PIN_INPUT_PULLDOWN); | ||
97 | omap_mux_init_signal("usba0_ulpiphy_dat4", | ||
98 | OMAP_PIN_INPUT_PULLDOWN); | ||
99 | omap_mux_init_signal("usba0_ulpiphy_dat5", | ||
100 | OMAP_PIN_INPUT_PULLDOWN); | ||
101 | omap_mux_init_signal("usba0_ulpiphy_dat6", | ||
102 | OMAP_PIN_INPUT_PULLDOWN); | ||
103 | omap_mux_init_signal("usba0_ulpiphy_dat7", | ||
104 | OMAP_PIN_INPUT_PULLDOWN); | ||
105 | break; | ||
106 | default: | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
184 | void __init usb_musb_init(struct omap_musb_board_data *board_data) | 111 | void __init usb_musb_init(struct omap_musb_board_data *board_data) |
185 | { | 112 | { |
186 | if (cpu_is_omap243x()) { | 113 | struct omap_hwmod *oh; |
187 | musb_resources[0].start = OMAP243X_HS_BASE; | 114 | struct omap_device *od; |
188 | } else if (cpu_is_omap3517() || cpu_is_omap3505()) { | 115 | struct platform_device *pdev; |
189 | musb_device.name = "musb-am35x"; | 116 | struct device *dev; |
190 | musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE; | 117 | int bus_id = -1; |
191 | musb_resources[1].start = INT_35XX_USBOTG_IRQ; | 118 | const char *oh_name, *name; |
192 | board_data->set_phy_power = am35x_musb_phy_power; | 119 | |
193 | board_data->clear_irq = am35x_musb_clear_irq; | 120 | if (cpu_is_omap3517() || cpu_is_omap3505()) { |
194 | board_data->set_mode = am35x_musb_set_mode; | ||
195 | board_data->reset = am35x_musb_reset; | ||
196 | } else if (cpu_is_omap34xx()) { | ||
197 | musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE; | ||
198 | } else if (cpu_is_omap44xx()) { | 121 | } else if (cpu_is_omap44xx()) { |
199 | musb_resources[0].start = OMAP44XX_HSUSB_OTG_BASE; | 122 | usb_musb_mux_init(board_data); |
200 | musb_resources[1].start = OMAP44XX_IRQ_HS_USB_MC_N; | ||
201 | musb_resources[2].start = OMAP44XX_IRQ_HS_USB_DMA_N; | ||
202 | } | 123 | } |
203 | musb_resources[0].end = musb_resources[0].start + SZ_4K - 1; | ||
204 | 124 | ||
205 | /* | 125 | /* |
206 | * REVISIT: This line can be removed once all the platforms using | 126 | * REVISIT: This line can be removed once all the platforms using |
@@ -212,8 +132,35 @@ void __init usb_musb_init(struct omap_musb_board_data *board_data) | |||
212 | musb_plat.mode = board_data->mode; | 132 | musb_plat.mode = board_data->mode; |
213 | musb_plat.extvbus = board_data->extvbus; | 133 | musb_plat.extvbus = board_data->extvbus; |
214 | 134 | ||
215 | if (platform_device_register(&musb_device) < 0) | 135 | if (cpu_is_omap3517() || cpu_is_omap3505()) { |
216 | printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n"); | 136 | oh_name = "am35x_otg_hs"; |
137 | name = "musb-am35x"; | ||
138 | } else { | ||
139 | oh_name = "usb_otg_hs"; | ||
140 | name = "musb-omap2430"; | ||
141 | } | ||
142 | |||
143 | oh = omap_hwmod_lookup(oh_name); | ||
144 | if (!oh) { | ||
145 | pr_err("Could not look up %s\n", oh_name); | ||
146 | return; | ||
147 | } | ||
148 | |||
149 | od = omap_device_build(name, bus_id, oh, &musb_plat, | ||
150 | sizeof(musb_plat), omap_musb_latency, | ||
151 | ARRAY_SIZE(omap_musb_latency), false); | ||
152 | if (IS_ERR(od)) { | ||
153 | pr_err("Could not build omap_device for %s %s\n", | ||
154 | name, oh_name); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | pdev = &od->pdev; | ||
159 | dev = &pdev->dev; | ||
160 | get_device(dev); | ||
161 | dev->dma_mask = &musb_dmamask; | ||
162 | dev->coherent_dma_mask = musb_dmamask; | ||
163 | put_device(dev); | ||
217 | } | 164 | } |
218 | 165 | ||
219 | #else | 166 | #else |