diff options
author | Keshava Munegowda <keshava_mgowda@ti.com> | 2011-03-01 09:38:21 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-03-01 10:02:49 -0500 |
commit | 19403165c272cc4ed00c97973e7271714b009708 (patch) | |
tree | 9f0923ec4d4514b9a9d615d5ca8d3d0bb0e881ce /drivers/usb | |
parent | 3b68ae73d8afa925807ebaae7eb14e2afd43f5b5 (diff) |
usb: host: omap: ehci and ohci simplification
The ehci and ohci drivers are simplified; Since
UHH and TLL initialization, clock handling are
done by common usbhs core driver, these functionalities
are removed from ehci and ohci drivers.
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 1016 | ||||
-rw-r--r-- | drivers/usb/host/ohci-omap3.c | 584 |
2 files changed, 132 insertions, 1468 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 18df6c6a5803..7e41a95c5ceb 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c | |||
@@ -4,9 +4,10 @@ | |||
4 | * Bus Glue for the EHCI controllers in OMAP3/4 | 4 | * Bus Glue for the EHCI controllers in OMAP3/4 |
5 | * Tested on several OMAP3 boards, and OMAP4 Pandaboard | 5 | * Tested on several OMAP3 boards, and OMAP4 Pandaboard |
6 | * | 6 | * |
7 | * Copyright (C) 2007-2010 Texas Instruments, Inc. | 7 | * Copyright (C) 2007-2011 Texas Instruments, Inc. |
8 | * Author: Vikram Pandita <vikram.pandita@ti.com> | 8 | * Author: Vikram Pandita <vikram.pandita@ti.com> |
9 | * Author: Anand Gadiyar <gadiyar@ti.com> | 9 | * Author: Anand Gadiyar <gadiyar@ti.com> |
10 | * Author: Keshava Munegowda <keshava_mgowda@ti.com> | ||
10 | * | 11 | * |
11 | * Copyright (C) 2009 Nokia Corporation | 12 | * Copyright (C) 2009 Nokia Corporation |
12 | * Contact: Felipe Balbi <felipe.balbi@nokia.com> | 13 | * Contact: Felipe Balbi <felipe.balbi@nokia.com> |
@@ -27,116 +28,19 @@ | |||
27 | * along with this program; if not, write to the Free Software | 28 | * along with this program; if not, write to the Free Software |
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
29 | * | 30 | * |
30 | * TODO (last updated Nov 21, 2010): | 31 | * TODO (last updated Feb 27, 2010): |
31 | * - add kernel-doc | 32 | * - add kernel-doc |
32 | * - enable AUTOIDLE | 33 | * - enable AUTOIDLE |
33 | * - add suspend/resume | 34 | * - add suspend/resume |
34 | * - move workarounds to board-files | ||
35 | * - factor out code common to OHCI | ||
36 | * - add HSIC and TLL support | 35 | * - add HSIC and TLL support |
37 | * - convert to use hwmod and runtime PM | 36 | * - convert to use hwmod and runtime PM |
38 | */ | 37 | */ |
39 | 38 | ||
40 | #include <linux/platform_device.h> | 39 | #include <linux/platform_device.h> |
41 | #include <linux/clk.h> | ||
42 | #include <linux/gpio.h> | ||
43 | #include <linux/regulator/consumer.h> | ||
44 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
45 | #include <linux/usb/ulpi.h> | 41 | #include <linux/usb/ulpi.h> |
46 | #include <plat/usb.h> | 42 | #include <plat/usb.h> |
47 | 43 | ||
48 | /* | ||
49 | * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES | ||
50 | * Use ehci_omap_readl()/ehci_omap_writel() functions | ||
51 | */ | ||
52 | |||
53 | /* TLL Register Set */ | ||
54 | #define OMAP_USBTLL_REVISION (0x00) | ||
55 | #define OMAP_USBTLL_SYSCONFIG (0x10) | ||
56 | #define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) | ||
57 | #define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) | ||
58 | #define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) | ||
59 | #define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) | ||
60 | #define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) | ||
61 | |||
62 | #define OMAP_USBTLL_SYSSTATUS (0x14) | ||
63 | #define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) | ||
64 | |||
65 | #define OMAP_USBTLL_IRQSTATUS (0x18) | ||
66 | #define OMAP_USBTLL_IRQENABLE (0x1C) | ||
67 | |||
68 | #define OMAP_TLL_SHARED_CONF (0x30) | ||
69 | #define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) | ||
70 | #define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) | ||
71 | #define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) | ||
72 | #define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) | ||
73 | #define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) | ||
74 | |||
75 | #define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) | ||
76 | #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) | ||
77 | #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) | ||
78 | #define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) | ||
79 | #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) | ||
80 | #define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) | ||
81 | |||
82 | #define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num) | ||
83 | #define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num) | ||
84 | #define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num) | ||
85 | #define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num) | ||
86 | #define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num) | ||
87 | #define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num) | ||
88 | #define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num) | ||
89 | #define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num) | ||
90 | #define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) | ||
91 | |||
92 | #define OMAP_TLL_CHANNEL_COUNT 3 | ||
93 | #define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 0) | ||
94 | #define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 1) | ||
95 | #define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 2) | ||
96 | |||
97 | /* UHH Register Set */ | ||
98 | #define OMAP_UHH_REVISION (0x00) | ||
99 | #define OMAP_UHH_SYSCONFIG (0x10) | ||
100 | #define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12) | ||
101 | #define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8) | ||
102 | #define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3) | ||
103 | #define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2) | ||
104 | #define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1) | ||
105 | #define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0) | ||
106 | |||
107 | #define OMAP_UHH_SYSSTATUS (0x14) | ||
108 | #define OMAP_UHH_HOSTCONFIG (0x40) | ||
109 | #define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0) | ||
110 | #define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0) | ||
111 | #define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11) | ||
112 | #define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12) | ||
113 | #define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2) | ||
114 | #define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3) | ||
115 | #define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4) | ||
116 | #define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5) | ||
117 | #define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8) | ||
118 | #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) | ||
119 | #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) | ||
120 | |||
121 | /* OMAP4-specific defines */ | ||
122 | #define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR (3 << 2) | ||
123 | #define OMAP4_UHH_SYSCONFIG_NOIDLE (1 << 2) | ||
124 | |||
125 | #define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR (3 << 4) | ||
126 | #define OMAP4_UHH_SYSCONFIG_NOSTDBY (1 << 4) | ||
127 | #define OMAP4_UHH_SYSCONFIG_SOFTRESET (1 << 0) | ||
128 | |||
129 | #define OMAP4_P1_MODE_CLEAR (3 << 16) | ||
130 | #define OMAP4_P1_MODE_TLL (1 << 16) | ||
131 | #define OMAP4_P1_MODE_HSIC (3 << 16) | ||
132 | #define OMAP4_P2_MODE_CLEAR (3 << 18) | ||
133 | #define OMAP4_P2_MODE_TLL (1 << 18) | ||
134 | #define OMAP4_P2_MODE_HSIC (3 << 18) | ||
135 | |||
136 | #define OMAP_REV2_TLL_CHANNEL_COUNT 2 | ||
137 | |||
138 | #define OMAP_UHH_DEBUG_CSR (0x44) | ||
139 | |||
140 | /* EHCI Register Set */ | 44 | /* EHCI Register Set */ |
141 | #define EHCI_INSNREG04 (0xA0) | 45 | #define EHCI_INSNREG04 (0xA0) |
142 | #define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5) | 46 | #define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5) |
@@ -148,141 +52,24 @@ | |||
148 | #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 | 52 | #define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 |
149 | #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 | 53 | #define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 |
150 | 54 | ||
151 | /* Values of UHH_REVISION - Note: these are not given in the TRM */ | 55 | /*-------------------------------------------------------------------------*/ |
152 | #define OMAP_EHCI_REV1 0x00000010 /* OMAP3 */ | ||
153 | #define OMAP_EHCI_REV2 0x50700100 /* OMAP4 */ | ||
154 | 56 | ||
155 | #define is_omap_ehci_rev1(x) (x->omap_ehci_rev == OMAP_EHCI_REV1) | 57 | static const struct hc_driver ehci_omap_hc_driver; |
156 | #define is_omap_ehci_rev2(x) (x->omap_ehci_rev == OMAP_EHCI_REV2) | ||
157 | 58 | ||
158 | #define is_ehci_phy_mode(x) (x == OMAP_EHCI_PORT_MODE_PHY) | ||
159 | #define is_ehci_tll_mode(x) (x == OMAP_EHCI_PORT_MODE_TLL) | ||
160 | #define is_ehci_hsic_mode(x) (x == OMAP_EHCI_PORT_MODE_HSIC) | ||
161 | 59 | ||
162 | /*-------------------------------------------------------------------------*/ | 60 | static inline void ehci_write(void __iomem *base, u32 reg, u32 val) |
163 | |||
164 | static inline void ehci_omap_writel(void __iomem *base, u32 reg, u32 val) | ||
165 | { | 61 | { |
166 | __raw_writel(val, base + reg); | 62 | __raw_writel(val, base + reg); |
167 | } | 63 | } |
168 | 64 | ||
169 | static inline u32 ehci_omap_readl(void __iomem *base, u32 reg) | 65 | static inline u32 ehci_read(void __iomem *base, u32 reg) |
170 | { | 66 | { |
171 | return __raw_readl(base + reg); | 67 | return __raw_readl(base + reg); |
172 | } | 68 | } |
173 | 69 | ||
174 | static inline void ehci_omap_writeb(void __iomem *base, u8 reg, u8 val) | 70 | static void omap_ehci_soft_phy_reset(struct platform_device *pdev, u8 port) |
175 | { | ||
176 | __raw_writeb(val, base + reg); | ||
177 | } | ||
178 | |||
179 | static inline u8 ehci_omap_readb(void __iomem *base, u8 reg) | ||
180 | { | ||
181 | return __raw_readb(base + reg); | ||
182 | } | ||
183 | |||
184 | /*-------------------------------------------------------------------------*/ | ||
185 | |||
186 | struct ehci_hcd_omap { | ||
187 | struct ehci_hcd *ehci; | ||
188 | struct device *dev; | ||
189 | |||
190 | struct clk *usbhost_ick; | ||
191 | struct clk *usbhost_hs_fck; | ||
192 | struct clk *usbhost_fs_fck; | ||
193 | struct clk *usbtll_fck; | ||
194 | struct clk *usbtll_ick; | ||
195 | struct clk *xclk60mhsp1_ck; | ||
196 | struct clk *xclk60mhsp2_ck; | ||
197 | struct clk *utmi_p1_fck; | ||
198 | struct clk *usbhost_p1_fck; | ||
199 | struct clk *usbtll_p1_fck; | ||
200 | struct clk *utmi_p2_fck; | ||
201 | struct clk *usbhost_p2_fck; | ||
202 | struct clk *usbtll_p2_fck; | ||
203 | |||
204 | /* FIXME the following two workarounds are | ||
205 | * board specific not silicon-specific so these | ||
206 | * should be moved to board-file instead. | ||
207 | * | ||
208 | * Maybe someone from TI will know better which | ||
209 | * board is affected and needs the workarounds | ||
210 | * to be applied | ||
211 | */ | ||
212 | |||
213 | /* gpio for resetting phy */ | ||
214 | int reset_gpio_port[OMAP3_HS_USB_PORTS]; | ||
215 | |||
216 | /* phy reset workaround */ | ||
217 | int phy_reset; | ||
218 | |||
219 | /* IP revision */ | ||
220 | u32 omap_ehci_rev; | ||
221 | |||
222 | /* desired phy_mode: TLL, PHY */ | ||
223 | enum usbhs_omap_port_mode port_mode[OMAP3_HS_USB_PORTS]; | ||
224 | |||
225 | void __iomem *uhh_base; | ||
226 | void __iomem *tll_base; | ||
227 | void __iomem *ehci_base; | ||
228 | |||
229 | /* Regulators for USB PHYs. | ||
230 | * Each PHY can have a separate regulator. | ||
231 | */ | ||
232 | struct regulator *regulator[OMAP3_HS_USB_PORTS]; | ||
233 | }; | ||
234 | |||
235 | /*-------------------------------------------------------------------------*/ | ||
236 | |||
237 | static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask, | ||
238 | u8 tll_channel_count) | ||
239 | { | ||
240 | unsigned reg; | ||
241 | int i; | ||
242 | |||
243 | /* Program the 3 TLL channels upfront */ | ||
244 | for (i = 0; i < tll_channel_count; i++) { | ||
245 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); | ||
246 | |||
247 | /* Disable AutoIdle, BitStuffing and use SDR Mode */ | ||
248 | reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE | ||
249 | | OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF | ||
250 | | OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE); | ||
251 | ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); | ||
252 | } | ||
253 | |||
254 | /* Program Common TLL register */ | ||
255 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF); | ||
256 | reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON | ||
257 | | OMAP_TLL_SHARED_CONF_USB_DIVRATION | ||
258 | | OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN); | ||
259 | reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; | ||
260 | |||
261 | ehci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); | ||
262 | |||
263 | /* Enable channels now */ | ||
264 | for (i = 0; i < tll_channel_count; i++) { | ||
265 | reg = ehci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); | ||
266 | |||
267 | /* Enable only the reg that is needed */ | ||
268 | if (!(tll_channel_mask & 1<<i)) | ||
269 | continue; | ||
270 | |||
271 | reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; | ||
272 | ehci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); | ||
273 | |||
274 | ehci_omap_writeb(omap->tll_base, | ||
275 | OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe); | ||
276 | dev_dbg(omap->dev, "ULPI_SCRATCH_REG[ch=%d]= 0x%02x\n", | ||
277 | i+1, ehci_omap_readb(omap->tll_base, | ||
278 | OMAP_TLL_ULPI_SCRATCH_REGISTER(i))); | ||
279 | } | ||
280 | } | ||
281 | |||
282 | /*-------------------------------------------------------------------------*/ | ||
283 | |||
284 | static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port) | ||
285 | { | 71 | { |
72 | struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); | ||
286 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | 73 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); |
287 | unsigned reg = 0; | 74 | unsigned reg = 0; |
288 | 75 | ||
@@ -296,600 +83,20 @@ static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port) | |||
296 | /* start ULPI access*/ | 83 | /* start ULPI access*/ |
297 | | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); | 84 | | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); |
298 | 85 | ||
299 | ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg); | 86 | ehci_write(hcd->regs, EHCI_INSNREG05_ULPI, reg); |
300 | 87 | ||
301 | /* Wait for ULPI access completion */ | 88 | /* Wait for ULPI access completion */ |
302 | while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI) | 89 | while ((ehci_read(hcd->regs, EHCI_INSNREG05_ULPI) |
303 | & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { | 90 | & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { |
304 | cpu_relax(); | 91 | cpu_relax(); |
305 | 92 | ||
306 | if (time_after(jiffies, timeout)) { | 93 | if (time_after(jiffies, timeout)) { |
307 | dev_dbg(omap->dev, "phy reset operation timed out\n"); | 94 | dev_dbg(&pdev->dev, "phy reset operation timed out\n"); |
308 | break; | 95 | break; |
309 | } | 96 | } |
310 | } | 97 | } |
311 | } | 98 | } |
312 | 99 | ||
313 | /* omap_start_ehc | ||
314 | * - Start the TI USBHOST controller | ||
315 | */ | ||
316 | static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | ||
317 | { | ||
318 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | ||
319 | u8 tll_ch_mask = 0; | ||
320 | unsigned reg = 0; | ||
321 | int ret = 0; | ||
322 | |||
323 | dev_dbg(omap->dev, "starting TI EHCI USB Controller\n"); | ||
324 | |||
325 | /* Enable Clocks for USBHOST */ | ||
326 | omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick"); | ||
327 | if (IS_ERR(omap->usbhost_ick)) { | ||
328 | ret = PTR_ERR(omap->usbhost_ick); | ||
329 | goto err_host_ick; | ||
330 | } | ||
331 | clk_enable(omap->usbhost_ick); | ||
332 | |||
333 | omap->usbhost_hs_fck = clk_get(omap->dev, "hs_fck"); | ||
334 | if (IS_ERR(omap->usbhost_hs_fck)) { | ||
335 | ret = PTR_ERR(omap->usbhost_hs_fck); | ||
336 | goto err_host_120m_fck; | ||
337 | } | ||
338 | clk_enable(omap->usbhost_hs_fck); | ||
339 | |||
340 | omap->usbhost_fs_fck = clk_get(omap->dev, "fs_fck"); | ||
341 | if (IS_ERR(omap->usbhost_fs_fck)) { | ||
342 | ret = PTR_ERR(omap->usbhost_fs_fck); | ||
343 | goto err_host_48m_fck; | ||
344 | } | ||
345 | clk_enable(omap->usbhost_fs_fck); | ||
346 | |||
347 | if (omap->phy_reset) { | ||
348 | /* Refer: ISSUE1 */ | ||
349 | if (gpio_is_valid(omap->reset_gpio_port[0])) { | ||
350 | gpio_request(omap->reset_gpio_port[0], | ||
351 | "USB1 PHY reset"); | ||
352 | gpio_direction_output(omap->reset_gpio_port[0], 0); | ||
353 | } | ||
354 | |||
355 | if (gpio_is_valid(omap->reset_gpio_port[1])) { | ||
356 | gpio_request(omap->reset_gpio_port[1], | ||
357 | "USB2 PHY reset"); | ||
358 | gpio_direction_output(omap->reset_gpio_port[1], 0); | ||
359 | } | ||
360 | |||
361 | /* Hold the PHY in RESET for enough time till DIR is high */ | ||
362 | udelay(10); | ||
363 | } | ||
364 | |||
365 | /* Configure TLL for 60Mhz clk for ULPI */ | ||
366 | omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck"); | ||
367 | if (IS_ERR(omap->usbtll_fck)) { | ||
368 | ret = PTR_ERR(omap->usbtll_fck); | ||
369 | goto err_tll_fck; | ||
370 | } | ||
371 | clk_enable(omap->usbtll_fck); | ||
372 | |||
373 | omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick"); | ||
374 | if (IS_ERR(omap->usbtll_ick)) { | ||
375 | ret = PTR_ERR(omap->usbtll_ick); | ||
376 | goto err_tll_ick; | ||
377 | } | ||
378 | clk_enable(omap->usbtll_ick); | ||
379 | |||
380 | omap->omap_ehci_rev = ehci_omap_readl(omap->uhh_base, | ||
381 | OMAP_UHH_REVISION); | ||
382 | dev_dbg(omap->dev, "OMAP UHH_REVISION 0x%x\n", | ||
383 | omap->omap_ehci_rev); | ||
384 | |||
385 | /* | ||
386 | * Enable per-port clocks as needed (newer controllers only). | ||
387 | * - External ULPI clock for PHY mode | ||
388 | * - Internal clocks for TLL and HSIC modes (TODO) | ||
389 | */ | ||
390 | if (is_omap_ehci_rev2(omap)) { | ||
391 | switch (omap->port_mode[0]) { | ||
392 | case OMAP_EHCI_PORT_MODE_PHY: | ||
393 | omap->xclk60mhsp1_ck = clk_get(omap->dev, | ||
394 | "xclk60mhsp1_ck"); | ||
395 | if (IS_ERR(omap->xclk60mhsp1_ck)) { | ||
396 | ret = PTR_ERR(omap->xclk60mhsp1_ck); | ||
397 | dev_err(omap->dev, | ||
398 | "Unable to get Port1 ULPI clock\n"); | ||
399 | } | ||
400 | |||
401 | omap->utmi_p1_fck = clk_get(omap->dev, | ||
402 | "utmi_p1_gfclk"); | ||
403 | if (IS_ERR(omap->utmi_p1_fck)) { | ||
404 | ret = PTR_ERR(omap->utmi_p1_fck); | ||
405 | dev_err(omap->dev, | ||
406 | "Unable to get utmi_p1_fck\n"); | ||
407 | } | ||
408 | |||
409 | ret = clk_set_parent(omap->utmi_p1_fck, | ||
410 | omap->xclk60mhsp1_ck); | ||
411 | if (ret != 0) { | ||
412 | dev_err(omap->dev, | ||
413 | "Unable to set P1 f-clock\n"); | ||
414 | } | ||
415 | break; | ||
416 | case OMAP_EHCI_PORT_MODE_TLL: | ||
417 | omap->xclk60mhsp1_ck = clk_get(omap->dev, | ||
418 | "init_60m_fclk"); | ||
419 | if (IS_ERR(omap->xclk60mhsp1_ck)) { | ||
420 | ret = PTR_ERR(omap->xclk60mhsp1_ck); | ||
421 | dev_err(omap->dev, | ||
422 | "Unable to get Port1 ULPI clock\n"); | ||
423 | } | ||
424 | |||
425 | omap->utmi_p1_fck = clk_get(omap->dev, | ||
426 | "utmi_p1_gfclk"); | ||
427 | if (IS_ERR(omap->utmi_p1_fck)) { | ||
428 | ret = PTR_ERR(omap->utmi_p1_fck); | ||
429 | dev_err(omap->dev, | ||
430 | "Unable to get utmi_p1_fck\n"); | ||
431 | } | ||
432 | |||
433 | ret = clk_set_parent(omap->utmi_p1_fck, | ||
434 | omap->xclk60mhsp1_ck); | ||
435 | if (ret != 0) { | ||
436 | dev_err(omap->dev, | ||
437 | "Unable to set P1 f-clock\n"); | ||
438 | } | ||
439 | |||
440 | omap->usbhost_p1_fck = clk_get(omap->dev, | ||
441 | "usb_host_hs_utmi_p1_clk"); | ||
442 | if (IS_ERR(omap->usbhost_p1_fck)) { | ||
443 | ret = PTR_ERR(omap->usbhost_p1_fck); | ||
444 | dev_err(omap->dev, | ||
445 | "Unable to get HOST PORT 1 clk\n"); | ||
446 | } else { | ||
447 | clk_enable(omap->usbhost_p1_fck); | ||
448 | } | ||
449 | |||
450 | omap->usbtll_p1_fck = clk_get(omap->dev, | ||
451 | "usb_tll_hs_usb_ch0_clk"); | ||
452 | |||
453 | if (IS_ERR(omap->usbtll_p1_fck)) { | ||
454 | ret = PTR_ERR(omap->usbtll_p1_fck); | ||
455 | dev_err(omap->dev, | ||
456 | "Unable to get TLL CH0 clk\n"); | ||
457 | } else { | ||
458 | clk_enable(omap->usbtll_p1_fck); | ||
459 | } | ||
460 | break; | ||
461 | /* TODO */ | ||
462 | default: | ||
463 | break; | ||
464 | } | ||
465 | switch (omap->port_mode[1]) { | ||
466 | case OMAP_EHCI_PORT_MODE_PHY: | ||
467 | omap->xclk60mhsp2_ck = clk_get(omap->dev, | ||
468 | "xclk60mhsp2_ck"); | ||
469 | if (IS_ERR(omap->xclk60mhsp2_ck)) { | ||
470 | ret = PTR_ERR(omap->xclk60mhsp2_ck); | ||
471 | dev_err(omap->dev, | ||
472 | "Unable to get Port2 ULPI clock\n"); | ||
473 | } | ||
474 | |||
475 | omap->utmi_p2_fck = clk_get(omap->dev, | ||
476 | "utmi_p2_gfclk"); | ||
477 | if (IS_ERR(omap->utmi_p2_fck)) { | ||
478 | ret = PTR_ERR(omap->utmi_p2_fck); | ||
479 | dev_err(omap->dev, | ||
480 | "Unable to get utmi_p2_fck\n"); | ||
481 | } | ||
482 | |||
483 | ret = clk_set_parent(omap->utmi_p2_fck, | ||
484 | omap->xclk60mhsp2_ck); | ||
485 | if (ret != 0) { | ||
486 | dev_err(omap->dev, | ||
487 | "Unable to set P2 f-clock\n"); | ||
488 | } | ||
489 | break; | ||
490 | case OMAP_EHCI_PORT_MODE_TLL: | ||
491 | omap->xclk60mhsp2_ck = clk_get(omap->dev, | ||
492 | "init_60m_fclk"); | ||
493 | if (IS_ERR(omap->xclk60mhsp2_ck)) { | ||
494 | ret = PTR_ERR(omap->xclk60mhsp2_ck); | ||
495 | dev_err(omap->dev, | ||
496 | "Unable to get Port2 ULPI clock\n"); | ||
497 | } | ||
498 | |||
499 | omap->utmi_p2_fck = clk_get(omap->dev, | ||
500 | "utmi_p2_gfclk"); | ||
501 | if (IS_ERR(omap->utmi_p2_fck)) { | ||
502 | ret = PTR_ERR(omap->utmi_p2_fck); | ||
503 | dev_err(omap->dev, | ||
504 | "Unable to get utmi_p2_fck\n"); | ||
505 | } | ||
506 | |||
507 | ret = clk_set_parent(omap->utmi_p2_fck, | ||
508 | omap->xclk60mhsp2_ck); | ||
509 | if (ret != 0) { | ||
510 | dev_err(omap->dev, | ||
511 | "Unable to set P2 f-clock\n"); | ||
512 | } | ||
513 | |||
514 | omap->usbhost_p2_fck = clk_get(omap->dev, | ||
515 | "usb_host_hs_utmi_p2_clk"); | ||
516 | if (IS_ERR(omap->usbhost_p2_fck)) { | ||
517 | ret = PTR_ERR(omap->usbhost_p2_fck); | ||
518 | dev_err(omap->dev, | ||
519 | "Unable to get HOST PORT 2 clk\n"); | ||
520 | } else { | ||
521 | clk_enable(omap->usbhost_p2_fck); | ||
522 | } | ||
523 | |||
524 | omap->usbtll_p2_fck = clk_get(omap->dev, | ||
525 | "usb_tll_hs_usb_ch1_clk"); | ||
526 | |||
527 | if (IS_ERR(omap->usbtll_p2_fck)) { | ||
528 | ret = PTR_ERR(omap->usbtll_p2_fck); | ||
529 | dev_err(omap->dev, | ||
530 | "Unable to get TLL CH1 clk\n"); | ||
531 | } else { | ||
532 | clk_enable(omap->usbtll_p2_fck); | ||
533 | } | ||
534 | break; | ||
535 | /* TODO */ | ||
536 | default: | ||
537 | break; | ||
538 | } | ||
539 | } | ||
540 | |||
541 | |||
542 | /* perform TLL soft reset, and wait until reset is complete */ | ||
543 | ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | ||
544 | OMAP_USBTLL_SYSCONFIG_SOFTRESET); | ||
545 | |||
546 | /* Wait for TLL reset to complete */ | ||
547 | while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) | ||
548 | & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { | ||
549 | cpu_relax(); | ||
550 | |||
551 | if (time_after(jiffies, timeout)) { | ||
552 | dev_dbg(omap->dev, "operation timed out\n"); | ||
553 | ret = -EINVAL; | ||
554 | goto err_sys_status; | ||
555 | } | ||
556 | } | ||
557 | |||
558 | dev_dbg(omap->dev, "TLL RESET DONE\n"); | ||
559 | |||
560 | /* (1<<3) = no idle mode only for initial debugging */ | ||
561 | ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | ||
562 | OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | | ||
563 | OMAP_USBTLL_SYSCONFIG_SIDLEMODE | | ||
564 | OMAP_USBTLL_SYSCONFIG_CACTIVITY); | ||
565 | |||
566 | |||
567 | /* Put UHH in NoIdle/NoStandby mode */ | ||
568 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); | ||
569 | if (is_omap_ehci_rev1(omap)) { | ||
570 | reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP | ||
571 | | OMAP_UHH_SYSCONFIG_SIDLEMODE | ||
572 | | OMAP_UHH_SYSCONFIG_CACTIVITY | ||
573 | | OMAP_UHH_SYSCONFIG_MIDLEMODE); | ||
574 | reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; | ||
575 | |||
576 | |||
577 | } else if (is_omap_ehci_rev2(omap)) { | ||
578 | reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; | ||
579 | reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; | ||
580 | reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; | ||
581 | reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; | ||
582 | } | ||
583 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); | ||
584 | |||
585 | reg = ehci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); | ||
586 | |||
587 | /* setup ULPI bypass and burst configurations */ | ||
588 | reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | ||
589 | | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | ||
590 | | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); | ||
591 | reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; | ||
592 | |||
593 | if (is_omap_ehci_rev1(omap)) { | ||
594 | if (omap->port_mode[0] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
595 | reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; | ||
596 | if (omap->port_mode[1] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
597 | reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; | ||
598 | if (omap->port_mode[2] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
599 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | ||
600 | |||
601 | /* Bypass the TLL module for PHY mode operation */ | ||
602 | if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) { | ||
603 | dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); | ||
604 | if (is_ehci_phy_mode(omap->port_mode[0]) || | ||
605 | is_ehci_phy_mode(omap->port_mode[1]) || | ||
606 | is_ehci_phy_mode(omap->port_mode[2])) | ||
607 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | ||
608 | else | ||
609 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | ||
610 | } else { | ||
611 | dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); | ||
612 | if (is_ehci_phy_mode(omap->port_mode[0])) | ||
613 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | ||
614 | else if (is_ehci_tll_mode(omap->port_mode[0])) | ||
615 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | ||
616 | |||
617 | if (is_ehci_phy_mode(omap->port_mode[1])) | ||
618 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | ||
619 | else if (is_ehci_tll_mode(omap->port_mode[1])) | ||
620 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | ||
621 | |||
622 | if (is_ehci_phy_mode(omap->port_mode[2])) | ||
623 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | ||
624 | else if (is_ehci_tll_mode(omap->port_mode[2])) | ||
625 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | ||
626 | } | ||
627 | } else if (is_omap_ehci_rev2(omap)) { | ||
628 | /* Clear port mode fields for PHY mode*/ | ||
629 | reg &= ~OMAP4_P1_MODE_CLEAR; | ||
630 | reg &= ~OMAP4_P2_MODE_CLEAR; | ||
631 | |||
632 | if (is_ehci_tll_mode(omap->port_mode[0])) | ||
633 | reg |= OMAP4_P1_MODE_TLL; | ||
634 | else if (is_ehci_hsic_mode(omap->port_mode[0])) | ||
635 | reg |= OMAP4_P1_MODE_HSIC; | ||
636 | |||
637 | if (is_ehci_tll_mode(omap->port_mode[1])) | ||
638 | reg |= OMAP4_P2_MODE_TLL; | ||
639 | else if (is_ehci_hsic_mode(omap->port_mode[1])) | ||
640 | reg |= OMAP4_P2_MODE_HSIC; | ||
641 | } | ||
642 | |||
643 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); | ||
644 | dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); | ||
645 | |||
646 | |||
647 | /* | ||
648 | * An undocumented "feature" in the OMAP3 EHCI controller, | ||
649 | * causes suspended ports to be taken out of suspend when | ||
650 | * the USBCMD.Run/Stop bit is cleared (for example when | ||
651 | * we do ehci_bus_suspend). | ||
652 | * This breaks suspend-resume if the root-hub is allowed | ||
653 | * to suspend. Writing 1 to this undocumented register bit | ||
654 | * disables this feature and restores normal behavior. | ||
655 | */ | ||
656 | ehci_omap_writel(omap->ehci_base, EHCI_INSNREG04, | ||
657 | EHCI_INSNREG04_DISABLE_UNSUSPEND); | ||
658 | |||
659 | if ((omap->port_mode[0] == OMAP_EHCI_PORT_MODE_TLL) || | ||
660 | (omap->port_mode[1] == OMAP_EHCI_PORT_MODE_TLL) || | ||
661 | (omap->port_mode[2] == OMAP_EHCI_PORT_MODE_TLL)) { | ||
662 | |||
663 | if (omap->port_mode[0] == OMAP_EHCI_PORT_MODE_TLL) | ||
664 | tll_ch_mask |= OMAP_TLL_CHANNEL_1_EN_MASK; | ||
665 | if (omap->port_mode[1] == OMAP_EHCI_PORT_MODE_TLL) | ||
666 | tll_ch_mask |= OMAP_TLL_CHANNEL_2_EN_MASK; | ||
667 | if (omap->port_mode[2] == OMAP_EHCI_PORT_MODE_TLL) | ||
668 | tll_ch_mask |= OMAP_TLL_CHANNEL_3_EN_MASK; | ||
669 | |||
670 | /* Enable UTMI mode for required TLL channels */ | ||
671 | omap_usb_utmi_init(omap, tll_ch_mask, OMAP_TLL_CHANNEL_COUNT); | ||
672 | } | ||
673 | |||
674 | if (omap->phy_reset) { | ||
675 | /* Refer ISSUE1: | ||
676 | * Hold the PHY in RESET for enough time till | ||
677 | * PHY is settled and ready | ||
678 | */ | ||
679 | udelay(10); | ||
680 | |||
681 | if (gpio_is_valid(omap->reset_gpio_port[0])) | ||
682 | gpio_set_value(omap->reset_gpio_port[0], 1); | ||
683 | |||
684 | if (gpio_is_valid(omap->reset_gpio_port[1])) | ||
685 | gpio_set_value(omap->reset_gpio_port[1], 1); | ||
686 | } | ||
687 | |||
688 | /* Soft reset the PHY using PHY reset command over ULPI */ | ||
689 | if (omap->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) | ||
690 | omap_ehci_soft_phy_reset(omap, 0); | ||
691 | if (omap->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) | ||
692 | omap_ehci_soft_phy_reset(omap, 1); | ||
693 | |||
694 | return 0; | ||
695 | |||
696 | err_sys_status: | ||
697 | |||
698 | if (omap->usbtll_p2_fck != NULL) { | ||
699 | clk_disable(omap->usbtll_p2_fck); | ||
700 | clk_put(omap->usbtll_p2_fck); | ||
701 | } | ||
702 | if (omap->usbhost_p2_fck != NULL) { | ||
703 | clk_disable(omap->usbhost_p2_fck); | ||
704 | clk_put(omap->usbhost_p2_fck); | ||
705 | } | ||
706 | if (omap->usbtll_p1_fck != NULL) { | ||
707 | clk_disable(omap->usbtll_p1_fck); | ||
708 | clk_put(omap->usbtll_p1_fck); | ||
709 | } | ||
710 | if (omap->usbhost_p1_fck != NULL) { | ||
711 | clk_disable(omap->usbhost_p1_fck); | ||
712 | clk_put(omap->usbhost_p1_fck); | ||
713 | } | ||
714 | |||
715 | clk_disable(omap->utmi_p2_fck); | ||
716 | clk_put(omap->utmi_p2_fck); | ||
717 | clk_disable(omap->xclk60mhsp2_ck); | ||
718 | clk_put(omap->xclk60mhsp2_ck); | ||
719 | clk_disable(omap->utmi_p1_fck); | ||
720 | clk_put(omap->utmi_p1_fck); | ||
721 | clk_disable(omap->xclk60mhsp1_ck); | ||
722 | clk_put(omap->xclk60mhsp1_ck); | ||
723 | clk_disable(omap->usbtll_ick); | ||
724 | clk_put(omap->usbtll_ick); | ||
725 | |||
726 | err_tll_ick: | ||
727 | clk_disable(omap->usbtll_fck); | ||
728 | clk_put(omap->usbtll_fck); | ||
729 | |||
730 | err_tll_fck: | ||
731 | clk_disable(omap->usbhost_fs_fck); | ||
732 | clk_put(omap->usbhost_fs_fck); | ||
733 | |||
734 | if (omap->phy_reset) { | ||
735 | if (gpio_is_valid(omap->reset_gpio_port[0])) | ||
736 | gpio_free(omap->reset_gpio_port[0]); | ||
737 | |||
738 | if (gpio_is_valid(omap->reset_gpio_port[1])) | ||
739 | gpio_free(omap->reset_gpio_port[1]); | ||
740 | } | ||
741 | |||
742 | err_host_48m_fck: | ||
743 | clk_disable(omap->usbhost_hs_fck); | ||
744 | clk_put(omap->usbhost_hs_fck); | ||
745 | |||
746 | err_host_120m_fck: | ||
747 | clk_disable(omap->usbhost_ick); | ||
748 | clk_put(omap->usbhost_ick); | ||
749 | |||
750 | err_host_ick: | ||
751 | return ret; | ||
752 | } | ||
753 | |||
754 | static void omap_stop_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) | ||
755 | { | ||
756 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | ||
757 | |||
758 | dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n"); | ||
759 | |||
760 | /* Reset OMAP modules for insmod/rmmod to work */ | ||
761 | ehci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, | ||
762 | is_omap_ehci_rev2(omap) ? | ||
763 | OMAP4_UHH_SYSCONFIG_SOFTRESET : | ||
764 | OMAP_UHH_SYSCONFIG_SOFTRESET); | ||
765 | while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) | ||
766 | & (1 << 0))) { | ||
767 | cpu_relax(); | ||
768 | |||
769 | if (time_after(jiffies, timeout)) | ||
770 | dev_dbg(omap->dev, "operation timed out\n"); | ||
771 | } | ||
772 | |||
773 | while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) | ||
774 | & (1 << 1))) { | ||
775 | cpu_relax(); | ||
776 | |||
777 | if (time_after(jiffies, timeout)) | ||
778 | dev_dbg(omap->dev, "operation timed out\n"); | ||
779 | } | ||
780 | |||
781 | while (!(ehci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) | ||
782 | & (1 << 2))) { | ||
783 | cpu_relax(); | ||
784 | |||
785 | if (time_after(jiffies, timeout)) | ||
786 | dev_dbg(omap->dev, "operation timed out\n"); | ||
787 | } | ||
788 | |||
789 | ehci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1)); | ||
790 | |||
791 | while (!(ehci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) | ||
792 | & (1 << 0))) { | ||
793 | cpu_relax(); | ||
794 | |||
795 | if (time_after(jiffies, timeout)) | ||
796 | dev_dbg(omap->dev, "operation timed out\n"); | ||
797 | } | ||
798 | |||
799 | if (omap->usbtll_fck != NULL) { | ||
800 | clk_disable(omap->usbtll_fck); | ||
801 | clk_put(omap->usbtll_fck); | ||
802 | omap->usbtll_fck = NULL; | ||
803 | } | ||
804 | |||
805 | if (omap->usbhost_ick != NULL) { | ||
806 | clk_disable(omap->usbhost_ick); | ||
807 | clk_put(omap->usbhost_ick); | ||
808 | omap->usbhost_ick = NULL; | ||
809 | } | ||
810 | |||
811 | if (omap->usbhost_fs_fck != NULL) { | ||
812 | clk_disable(omap->usbhost_fs_fck); | ||
813 | clk_put(omap->usbhost_fs_fck); | ||
814 | omap->usbhost_fs_fck = NULL; | ||
815 | } | ||
816 | |||
817 | if (omap->usbhost_hs_fck != NULL) { | ||
818 | clk_disable(omap->usbhost_hs_fck); | ||
819 | clk_put(omap->usbhost_hs_fck); | ||
820 | omap->usbhost_hs_fck = NULL; | ||
821 | } | ||
822 | |||
823 | if (omap->usbtll_ick != NULL) { | ||
824 | clk_disable(omap->usbtll_ick); | ||
825 | clk_put(omap->usbtll_ick); | ||
826 | omap->usbtll_ick = NULL; | ||
827 | } | ||
828 | |||
829 | if (is_omap_ehci_rev2(omap)) { | ||
830 | if (omap->xclk60mhsp1_ck != NULL) { | ||
831 | clk_disable(omap->xclk60mhsp1_ck); | ||
832 | clk_put(omap->xclk60mhsp1_ck); | ||
833 | omap->xclk60mhsp1_ck = NULL; | ||
834 | } | ||
835 | |||
836 | if (omap->utmi_p1_fck != NULL) { | ||
837 | clk_disable(omap->utmi_p1_fck); | ||
838 | clk_put(omap->utmi_p1_fck); | ||
839 | omap->utmi_p1_fck = NULL; | ||
840 | } | ||
841 | |||
842 | if (omap->xclk60mhsp2_ck != NULL) { | ||
843 | clk_disable(omap->xclk60mhsp2_ck); | ||
844 | clk_put(omap->xclk60mhsp2_ck); | ||
845 | omap->xclk60mhsp2_ck = NULL; | ||
846 | } | ||
847 | |||
848 | if (omap->utmi_p2_fck != NULL) { | ||
849 | clk_disable(omap->utmi_p2_fck); | ||
850 | clk_put(omap->utmi_p2_fck); | ||
851 | omap->utmi_p2_fck = NULL; | ||
852 | } | ||
853 | |||
854 | if (omap->usbtll_p2_fck != NULL) { | ||
855 | clk_disable(omap->usbtll_p2_fck); | ||
856 | clk_put(omap->usbtll_p2_fck); | ||
857 | omap->usbtll_p2_fck = NULL; | ||
858 | } | ||
859 | |||
860 | if (omap->usbhost_p2_fck != NULL) { | ||
861 | clk_disable(omap->usbhost_p2_fck); | ||
862 | clk_put(omap->usbhost_p2_fck); | ||
863 | omap->usbhost_p2_fck = NULL; | ||
864 | } | ||
865 | |||
866 | if (omap->usbtll_p1_fck != NULL) { | ||
867 | clk_disable(omap->usbtll_p1_fck); | ||
868 | clk_put(omap->usbtll_p1_fck); | ||
869 | omap->usbtll_p1_fck = NULL; | ||
870 | } | ||
871 | |||
872 | if (omap->usbhost_p1_fck != NULL) { | ||
873 | clk_disable(omap->usbhost_p1_fck); | ||
874 | clk_put(omap->usbhost_p1_fck); | ||
875 | omap->usbhost_p1_fck = NULL; | ||
876 | } | ||
877 | } | ||
878 | |||
879 | if (omap->phy_reset) { | ||
880 | if (gpio_is_valid(omap->reset_gpio_port[0])) | ||
881 | gpio_free(omap->reset_gpio_port[0]); | ||
882 | |||
883 | if (gpio_is_valid(omap->reset_gpio_port[1])) | ||
884 | gpio_free(omap->reset_gpio_port[1]); | ||
885 | } | ||
886 | |||
887 | dev_dbg(omap->dev, "Clock to USB host has been disabled\n"); | ||
888 | } | ||
889 | |||
890 | /*-------------------------------------------------------------------------*/ | ||
891 | |||
892 | static const struct hc_driver ehci_omap_hc_driver; | ||
893 | 100 | ||
894 | /* configure so an HC device and id are always provided */ | 101 | /* configure so an HC device and id are always provided */ |
895 | /* always called with process context; sleeping is OK */ | 102 | /* always called with process context; sleeping is OK */ |
@@ -903,155 +110,113 @@ static const struct hc_driver ehci_omap_hc_driver; | |||
903 | */ | 110 | */ |
904 | static int ehci_hcd_omap_probe(struct platform_device *pdev) | 111 | static int ehci_hcd_omap_probe(struct platform_device *pdev) |
905 | { | 112 | { |
906 | struct usbhs_omap_board_data *pdata = pdev->dev.platform_data; | 113 | struct device *dev = &pdev->dev; |
907 | struct ehci_hcd_omap *omap; | 114 | struct ehci_hcd_omap_platform_data *pdata = dev->platform_data; |
908 | struct resource *res; | 115 | struct resource *res; |
909 | struct usb_hcd *hcd; | 116 | struct usb_hcd *hcd; |
117 | void __iomem *regs; | ||
118 | struct ehci_hcd *omap_ehci; | ||
119 | int ret = -ENODEV; | ||
120 | int irq; | ||
910 | 121 | ||
911 | int irq = platform_get_irq(pdev, 0); | 122 | if (usb_disabled()) |
912 | int ret = -ENODEV; | 123 | return -ENODEV; |
913 | int i; | ||
914 | char supply[7]; | ||
915 | 124 | ||
916 | if (!pdata) { | 125 | if (!dev->parent) { |
917 | dev_dbg(&pdev->dev, "missing platform_data\n"); | 126 | dev_err(dev, "Missing parent device\n"); |
918 | goto err_pdata; | 127 | return -ENODEV; |
919 | } | 128 | } |
920 | 129 | ||
921 | if (usb_disabled()) | 130 | irq = platform_get_irq_byname(pdev, "ehci-irq"); |
922 | goto err_disabled; | 131 | if (irq < 0) { |
132 | dev_err(dev, "EHCI irq failed\n"); | ||
133 | return -ENODEV; | ||
134 | } | ||
923 | 135 | ||
924 | omap = kzalloc(sizeof(*omap), GFP_KERNEL); | 136 | res = platform_get_resource_byname(pdev, |
925 | if (!omap) { | 137 | IORESOURCE_MEM, "ehci"); |
926 | ret = -ENOMEM; | 138 | if (!res) { |
927 | goto err_disabled; | 139 | dev_err(dev, "UHH EHCI get resource failed\n"); |
140 | return -ENODEV; | ||
141 | } | ||
142 | |||
143 | regs = ioremap(res->start, resource_size(res)); | ||
144 | if (!regs) { | ||
145 | dev_err(dev, "UHH EHCI ioremap failed\n"); | ||
146 | return -ENOMEM; | ||
928 | } | 147 | } |
929 | 148 | ||
930 | hcd = usb_create_hcd(&ehci_omap_hc_driver, &pdev->dev, | 149 | hcd = usb_create_hcd(&ehci_omap_hc_driver, dev, |
931 | dev_name(&pdev->dev)); | 150 | dev_name(dev)); |
932 | if (!hcd) { | 151 | if (!hcd) { |
933 | dev_err(&pdev->dev, "failed to create hcd with err %d\n", ret); | 152 | dev_err(dev, "failed to create hcd with err %d\n", ret); |
934 | ret = -ENOMEM; | 153 | ret = -ENOMEM; |
935 | goto err_create_hcd; | 154 | goto err_io; |
936 | } | 155 | } |
937 | 156 | ||
938 | platform_set_drvdata(pdev, omap); | ||
939 | omap->dev = &pdev->dev; | ||
940 | omap->phy_reset = pdata->phy_reset; | ||
941 | omap->reset_gpio_port[0] = pdata->reset_gpio_port[0]; | ||
942 | omap->reset_gpio_port[1] = pdata->reset_gpio_port[1]; | ||
943 | omap->reset_gpio_port[2] = pdata->reset_gpio_port[2]; | ||
944 | omap->port_mode[0] = pdata->port_mode[0]; | ||
945 | omap->port_mode[1] = pdata->port_mode[1]; | ||
946 | omap->port_mode[2] = pdata->port_mode[2]; | ||
947 | omap->ehci = hcd_to_ehci(hcd); | ||
948 | omap->ehci->sbrn = 0x20; | ||
949 | |||
950 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci"); | ||
951 | |||
952 | hcd->rsrc_start = res->start; | 157 | hcd->rsrc_start = res->start; |
953 | hcd->rsrc_len = resource_size(res); | 158 | hcd->rsrc_len = resource_size(res); |
159 | hcd->regs = regs; | ||
954 | 160 | ||
955 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | 161 | ret = omap_usbhs_enable(dev); |
956 | if (!hcd->regs) { | 162 | if (ret) { |
957 | dev_err(&pdev->dev, "EHCI ioremap failed\n"); | 163 | dev_err(dev, "failed to start usbhs with err %d\n", ret); |
958 | ret = -ENOMEM; | 164 | goto err_enable; |
959 | goto err_ioremap; | ||
960 | } | ||
961 | |||
962 | /* we know this is the memory we want, no need to ioremap again */ | ||
963 | omap->ehci->caps = hcd->regs; | ||
964 | omap->ehci_base = hcd->regs; | ||
965 | |||
966 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); | ||
967 | omap->uhh_base = ioremap(res->start, resource_size(res)); | ||
968 | if (!omap->uhh_base) { | ||
969 | dev_err(&pdev->dev, "UHH ioremap failed\n"); | ||
970 | ret = -ENOMEM; | ||
971 | goto err_uhh_ioremap; | ||
972 | } | 165 | } |
973 | 166 | ||
974 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll"); | 167 | /* |
975 | omap->tll_base = ioremap(res->start, resource_size(res)); | 168 | * An undocumented "feature" in the OMAP3 EHCI controller, |
976 | if (!omap->tll_base) { | 169 | * causes suspended ports to be taken out of suspend when |
977 | dev_err(&pdev->dev, "TLL ioremap failed\n"); | 170 | * the USBCMD.Run/Stop bit is cleared (for example when |
978 | ret = -ENOMEM; | 171 | * we do ehci_bus_suspend). |
979 | goto err_tll_ioremap; | 172 | * This breaks suspend-resume if the root-hub is allowed |
980 | } | 173 | * to suspend. Writing 1 to this undocumented register bit |
174 | * disables this feature and restores normal behavior. | ||
175 | */ | ||
176 | ehci_write(regs, EHCI_INSNREG04, | ||
177 | EHCI_INSNREG04_DISABLE_UNSUSPEND); | ||
981 | 178 | ||
982 | /* get ehci regulator and enable */ | 179 | /* Soft reset the PHY using PHY reset command over ULPI */ |
983 | for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { | 180 | if (pdata->port_mode[0] == OMAP_EHCI_PORT_MODE_PHY) |
984 | if (omap->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) { | 181 | omap_ehci_soft_phy_reset(pdev, 0); |
985 | omap->regulator[i] = NULL; | 182 | if (pdata->port_mode[1] == OMAP_EHCI_PORT_MODE_PHY) |
986 | continue; | 183 | omap_ehci_soft_phy_reset(pdev, 1); |
987 | } | ||
988 | snprintf(supply, sizeof(supply), "hsusb%d", i); | ||
989 | omap->regulator[i] = regulator_get(omap->dev, supply); | ||
990 | if (IS_ERR(omap->regulator[i])) { | ||
991 | omap->regulator[i] = NULL; | ||
992 | dev_dbg(&pdev->dev, | ||
993 | "failed to get ehci port%d regulator\n", i); | ||
994 | } else { | ||
995 | regulator_enable(omap->regulator[i]); | ||
996 | } | ||
997 | } | ||
998 | 184 | ||
999 | ret = omap_start_ehc(omap, hcd); | 185 | omap_ehci = hcd_to_ehci(hcd); |
1000 | if (ret) { | 186 | omap_ehci->sbrn = 0x20; |
1001 | dev_err(&pdev->dev, "failed to start ehci with err %d\n", ret); | ||
1002 | goto err_start; | ||
1003 | } | ||
1004 | 187 | ||
1005 | omap->ehci->regs = hcd->regs | 188 | /* we know this is the memory we want, no need to ioremap again */ |
1006 | + HC_LENGTH(readl(&omap->ehci->caps->hc_capbase)); | 189 | omap_ehci->caps = hcd->regs; |
190 | omap_ehci->regs = hcd->regs | ||
191 | + HC_LENGTH(readl(&omap_ehci->caps->hc_capbase)); | ||
1007 | 192 | ||
1008 | dbg_hcs_params(omap->ehci, "reset"); | 193 | dbg_hcs_params(omap_ehci, "reset"); |
1009 | dbg_hcc_params(omap->ehci, "reset"); | 194 | dbg_hcc_params(omap_ehci, "reset"); |
1010 | 195 | ||
1011 | /* cache this readonly data; minimize chip reads */ | 196 | /* cache this readonly data; minimize chip reads */ |
1012 | omap->ehci->hcs_params = readl(&omap->ehci->caps->hcs_params); | 197 | omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params); |
1013 | 198 | ||
1014 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); | 199 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); |
1015 | if (ret) { | 200 | if (ret) { |
1016 | dev_err(&pdev->dev, "failed to add hcd with err %d\n", ret); | 201 | dev_err(dev, "failed to add hcd with err %d\n", ret); |
1017 | goto err_add_hcd; | 202 | goto err_add_hcd; |
1018 | } | 203 | } |
1019 | 204 | ||
1020 | /* root ports should always stay powered */ | 205 | /* root ports should always stay powered */ |
1021 | ehci_port_power(omap->ehci, 1); | 206 | ehci_port_power(omap_ehci, 1); |
1022 | 207 | ||
1023 | return 0; | 208 | return 0; |
1024 | 209 | ||
1025 | err_add_hcd: | 210 | err_add_hcd: |
1026 | omap_stop_ehc(omap, hcd); | 211 | omap_usbhs_disable(dev); |
1027 | 212 | ||
1028 | err_start: | 213 | err_enable: |
1029 | for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { | ||
1030 | if (omap->regulator[i]) { | ||
1031 | regulator_disable(omap->regulator[i]); | ||
1032 | regulator_put(omap->regulator[i]); | ||
1033 | } | ||
1034 | } | ||
1035 | iounmap(omap->tll_base); | ||
1036 | |||
1037 | err_tll_ioremap: | ||
1038 | iounmap(omap->uhh_base); | ||
1039 | |||
1040 | err_uhh_ioremap: | ||
1041 | iounmap(hcd->regs); | ||
1042 | |||
1043 | err_ioremap: | ||
1044 | usb_put_hcd(hcd); | 214 | usb_put_hcd(hcd); |
1045 | 215 | ||
1046 | err_create_hcd: | 216 | err_io: |
1047 | kfree(omap); | ||
1048 | err_disabled: | ||
1049 | err_pdata: | ||
1050 | return ret; | 217 | return ret; |
1051 | } | 218 | } |
1052 | 219 | ||
1053 | /* may be called without controller electrically present */ | ||
1054 | /* may be called with controller, bus, and devices active */ | ||
1055 | 220 | ||
1056 | /** | 221 | /** |
1057 | * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs | 222 | * ehci_hcd_omap_remove - shutdown processing for EHCI HCDs |
@@ -1063,31 +228,18 @@ err_pdata: | |||
1063 | */ | 228 | */ |
1064 | static int ehci_hcd_omap_remove(struct platform_device *pdev) | 229 | static int ehci_hcd_omap_remove(struct platform_device *pdev) |
1065 | { | 230 | { |
1066 | struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); | 231 | struct device *dev = &pdev->dev; |
1067 | struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); | 232 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
1068 | int i; | ||
1069 | 233 | ||
1070 | usb_remove_hcd(hcd); | 234 | usb_remove_hcd(hcd); |
1071 | omap_stop_ehc(omap, hcd); | 235 | omap_usbhs_disable(dev); |
1072 | iounmap(hcd->regs); | ||
1073 | for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) { | ||
1074 | if (omap->regulator[i]) { | ||
1075 | regulator_disable(omap->regulator[i]); | ||
1076 | regulator_put(omap->regulator[i]); | ||
1077 | } | ||
1078 | } | ||
1079 | iounmap(omap->tll_base); | ||
1080 | iounmap(omap->uhh_base); | ||
1081 | usb_put_hcd(hcd); | 236 | usb_put_hcd(hcd); |
1082 | kfree(omap); | ||
1083 | |||
1084 | return 0; | 237 | return 0; |
1085 | } | 238 | } |
1086 | 239 | ||
1087 | static void ehci_hcd_omap_shutdown(struct platform_device *pdev) | 240 | static void ehci_hcd_omap_shutdown(struct platform_device *pdev) |
1088 | { | 241 | { |
1089 | struct ehci_hcd_omap *omap = platform_get_drvdata(pdev); | 242 | struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); |
1090 | struct usb_hcd *hcd = ehci_to_hcd(omap->ehci); | ||
1091 | 243 | ||
1092 | if (hcd->driver->shutdown) | 244 | if (hcd->driver->shutdown) |
1093 | hcd->driver->shutdown(hcd); | 245 | hcd->driver->shutdown(hcd); |
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c index 3f9db87fe525..6048f2f64f73 100644 --- a/drivers/usb/host/ohci-omap3.c +++ b/drivers/usb/host/ohci-omap3.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * Copyright (C) 2007-2010 Texas Instruments, Inc. | 7 | * Copyright (C) 2007-2010 Texas Instruments, Inc. |
8 | * Author: Vikram Pandita <vikram.pandita@ti.com> | 8 | * Author: Vikram Pandita <vikram.pandita@ti.com> |
9 | * Author: Anand Gadiyar <gadiyar@ti.com> | 9 | * Author: Anand Gadiyar <gadiyar@ti.com> |
10 | * Author: Keshava Munegowda <keshava_mgowda@ti.com> | ||
10 | * | 11 | * |
11 | * Based on ehci-omap.c and some other ohci glue layers | 12 | * Based on ehci-omap.c and some other ohci glue layers |
12 | * | 13 | * |
@@ -24,150 +25,15 @@ | |||
24 | * along with this program; if not, write to the Free Software | 25 | * along with this program; if not, write to the Free Software |
25 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 26 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
26 | * | 27 | * |
27 | * TODO (last updated Mar 10th, 2010): | 28 | * TODO (last updated Feb 27, 2011): |
28 | * - add kernel-doc | 29 | * - add kernel-doc |
29 | * - Factor out code common to EHCI to a separate file | ||
30 | * - Make EHCI and OHCI coexist together | ||
31 | * - needs newer silicon versions to actually work | ||
32 | * - the last one to be loaded currently steps on the other's toes | ||
33 | * - Add hooks for configuring transceivers, etc. at init/exit | ||
34 | * - Add aggressive clock-management code | ||
35 | */ | 30 | */ |
36 | 31 | ||
37 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
38 | #include <linux/clk.h> | ||
39 | |||
40 | #include <plat/usb.h> | 33 | #include <plat/usb.h> |
41 | 34 | ||
42 | /* | ||
43 | * OMAP USBHOST Register addresses: VIRTUAL ADDRESSES | ||
44 | * Use ohci_omap_readl()/ohci_omap_writel() functions | ||
45 | */ | ||
46 | |||
47 | /* TLL Register Set */ | ||
48 | #define OMAP_USBTLL_REVISION (0x00) | ||
49 | #define OMAP_USBTLL_SYSCONFIG (0x10) | ||
50 | #define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) | ||
51 | #define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) | ||
52 | #define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) | ||
53 | #define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) | ||
54 | #define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) | ||
55 | |||
56 | #define OMAP_USBTLL_SYSSTATUS (0x14) | ||
57 | #define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) | ||
58 | |||
59 | #define OMAP_USBTLL_IRQSTATUS (0x18) | ||
60 | #define OMAP_USBTLL_IRQENABLE (0x1C) | ||
61 | |||
62 | #define OMAP_TLL_SHARED_CONF (0x30) | ||
63 | #define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) | ||
64 | #define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) | ||
65 | #define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) | ||
66 | #define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) | ||
67 | #define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) | ||
68 | |||
69 | #define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) | ||
70 | #define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT 24 | ||
71 | #define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) | ||
72 | #define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) | ||
73 | #define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) | ||
74 | #define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) | ||
75 | #define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS (1 << 1) | ||
76 | #define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) | ||
77 | |||
78 | #define OMAP_TLL_CHANNEL_COUNT 3 | ||
79 | |||
80 | /* UHH Register Set */ | ||
81 | #define OMAP_UHH_REVISION (0x00) | ||
82 | #define OMAP_UHH_SYSCONFIG (0x10) | ||
83 | #define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12) | ||
84 | #define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8) | ||
85 | #define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3) | ||
86 | #define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2) | ||
87 | #define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1) | ||
88 | #define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0) | ||
89 | |||
90 | #define OMAP_UHH_SYSSTATUS (0x14) | ||
91 | #define OMAP_UHH_SYSSTATUS_UHHRESETDONE (1 << 0) | ||
92 | #define OMAP_UHH_SYSSTATUS_OHCIRESETDONE (1 << 1) | ||
93 | #define OMAP_UHH_SYSSTATUS_EHCIRESETDONE (1 << 2) | ||
94 | #define OMAP_UHH_HOSTCONFIG (0x40) | ||
95 | #define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0) | ||
96 | #define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0) | ||
97 | #define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11) | ||
98 | #define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12) | ||
99 | #define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2) | ||
100 | #define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3) | ||
101 | #define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4) | ||
102 | #define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5) | ||
103 | #define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8) | ||
104 | #define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) | ||
105 | #define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) | ||
106 | |||
107 | #define OMAP_UHH_DEBUG_CSR (0x44) | ||
108 | |||
109 | /*-------------------------------------------------------------------------*/ | 35 | /*-------------------------------------------------------------------------*/ |
110 | 36 | ||
111 | static inline void ohci_omap_writel(void __iomem *base, u32 reg, u32 val) | ||
112 | { | ||
113 | __raw_writel(val, base + reg); | ||
114 | } | ||
115 | |||
116 | static inline u32 ohci_omap_readl(void __iomem *base, u32 reg) | ||
117 | { | ||
118 | return __raw_readl(base + reg); | ||
119 | } | ||
120 | |||
121 | static inline void ohci_omap_writeb(void __iomem *base, u8 reg, u8 val) | ||
122 | { | ||
123 | __raw_writeb(val, base + reg); | ||
124 | } | ||
125 | |||
126 | static inline u8 ohci_omap_readb(void __iomem *base, u8 reg) | ||
127 | { | ||
128 | return __raw_readb(base + reg); | ||
129 | } | ||
130 | |||
131 | /*-------------------------------------------------------------------------*/ | ||
132 | |||
133 | struct ohci_hcd_omap3 { | ||
134 | struct ohci_hcd *ohci; | ||
135 | struct device *dev; | ||
136 | |||
137 | struct clk *usbhost_ick; | ||
138 | struct clk *usbhost2_120m_fck; | ||
139 | struct clk *usbhost1_48m_fck; | ||
140 | struct clk *usbtll_fck; | ||
141 | struct clk *usbtll_ick; | ||
142 | |||
143 | /* port_mode: TLL/PHY, 2/3/4/6-PIN, DP-DM/DAT-SE0 */ | ||
144 | enum usbhs_omap_port_mode port_mode[OMAP3_HS_USB_PORTS]; | ||
145 | void __iomem *uhh_base; | ||
146 | void __iomem *tll_base; | ||
147 | void __iomem *ohci_base; | ||
148 | |||
149 | unsigned es2_compatibility:1; | ||
150 | }; | ||
151 | |||
152 | /*-------------------------------------------------------------------------*/ | ||
153 | |||
154 | static void ohci_omap3_clock_power(struct ohci_hcd_omap3 *omap, int on) | ||
155 | { | ||
156 | if (on) { | ||
157 | clk_enable(omap->usbtll_ick); | ||
158 | clk_enable(omap->usbtll_fck); | ||
159 | clk_enable(omap->usbhost_ick); | ||
160 | clk_enable(omap->usbhost1_48m_fck); | ||
161 | clk_enable(omap->usbhost2_120m_fck); | ||
162 | } else { | ||
163 | clk_disable(omap->usbhost2_120m_fck); | ||
164 | clk_disable(omap->usbhost1_48m_fck); | ||
165 | clk_disable(omap->usbhost_ick); | ||
166 | clk_disable(omap->usbtll_fck); | ||
167 | clk_disable(omap->usbtll_ick); | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static int ohci_omap3_init(struct usb_hcd *hcd) | 37 | static int ohci_omap3_init(struct usb_hcd *hcd) |
172 | { | 38 | { |
173 | dev_dbg(hcd->self.controller, "starting OHCI controller\n"); | 39 | dev_dbg(hcd->self.controller, "starting OHCI controller\n"); |
@@ -175,7 +41,6 @@ static int ohci_omap3_init(struct usb_hcd *hcd) | |||
175 | return ohci_init(hcd_to_ohci(hcd)); | 41 | return ohci_init(hcd_to_ohci(hcd)); |
176 | } | 42 | } |
177 | 43 | ||
178 | |||
179 | /*-------------------------------------------------------------------------*/ | 44 | /*-------------------------------------------------------------------------*/ |
180 | 45 | ||
181 | static int ohci_omap3_start(struct usb_hcd *hcd) | 46 | static int ohci_omap3_start(struct usb_hcd *hcd) |
@@ -202,325 +67,6 @@ static int ohci_omap3_start(struct usb_hcd *hcd) | |||
202 | 67 | ||
203 | /*-------------------------------------------------------------------------*/ | 68 | /*-------------------------------------------------------------------------*/ |
204 | 69 | ||
205 | /* | ||
206 | * convert the port-mode enum to a value we can use in the FSLSMODE | ||
207 | * field of USBTLL_CHANNEL_CONF | ||
208 | */ | ||
209 | static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode) | ||
210 | { | ||
211 | switch (mode) { | ||
212 | case OMAP_USBHS_PORT_MODE_UNUSED: | ||
213 | case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0: | ||
214 | return 0x0; | ||
215 | |||
216 | case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM: | ||
217 | return 0x1; | ||
218 | |||
219 | case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0: | ||
220 | return 0x2; | ||
221 | |||
222 | case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM: | ||
223 | return 0x3; | ||
224 | |||
225 | case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0: | ||
226 | return 0x4; | ||
227 | |||
228 | case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM: | ||
229 | return 0x5; | ||
230 | |||
231 | case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0: | ||
232 | return 0x6; | ||
233 | |||
234 | case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM: | ||
235 | return 0x7; | ||
236 | |||
237 | case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0: | ||
238 | return 0xA; | ||
239 | |||
240 | case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM: | ||
241 | return 0xB; | ||
242 | default: | ||
243 | pr_warning("Invalid port mode, using default\n"); | ||
244 | return 0x0; | ||
245 | } | ||
246 | } | ||
247 | |||
248 | static void ohci_omap3_tll_config(struct ohci_hcd_omap3 *omap) | ||
249 | { | ||
250 | u32 reg; | ||
251 | int i; | ||
252 | |||
253 | /* Program TLL SHARED CONF */ | ||
254 | reg = ohci_omap_readl(omap->tll_base, OMAP_TLL_SHARED_CONF); | ||
255 | reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN; | ||
256 | reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN; | ||
257 | reg |= OMAP_TLL_SHARED_CONF_USB_DIVRATION; | ||
258 | reg |= OMAP_TLL_SHARED_CONF_FCLK_IS_ON; | ||
259 | ohci_omap_writel(omap->tll_base, OMAP_TLL_SHARED_CONF, reg); | ||
260 | |||
261 | /* Program each TLL channel */ | ||
262 | /* | ||
263 | * REVISIT: Only the 3-pin and 4-pin PHY modes have | ||
264 | * actually been tested. | ||
265 | */ | ||
266 | for (i = 0; i < OMAP_TLL_CHANNEL_COUNT; i++) { | ||
267 | |||
268 | /* Enable only those channels that are actually used */ | ||
269 | if (omap->port_mode[i] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
270 | continue; | ||
271 | |||
272 | reg = ohci_omap_readl(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i)); | ||
273 | reg |= ohci_omap3_fslsmode(omap->port_mode[i]) | ||
274 | << OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT; | ||
275 | reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS; | ||
276 | reg |= OMAP_TLL_CHANNEL_CONF_CHANEN; | ||
277 | ohci_omap_writel(omap->tll_base, OMAP_TLL_CHANNEL_CONF(i), reg); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /* omap3_start_ohci | ||
282 | * - Start the TI USBHOST controller | ||
283 | */ | ||
284 | static int omap3_start_ohci(struct ohci_hcd_omap3 *omap, struct usb_hcd *hcd) | ||
285 | { | ||
286 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | ||
287 | u32 reg = 0; | ||
288 | int ret = 0; | ||
289 | |||
290 | dev_dbg(omap->dev, "starting TI OHCI USB Controller\n"); | ||
291 | |||
292 | /* Get all the clock handles we need */ | ||
293 | omap->usbhost_ick = clk_get(omap->dev, "usbhost_ick"); | ||
294 | if (IS_ERR(omap->usbhost_ick)) { | ||
295 | dev_err(omap->dev, "could not get usbhost_ick\n"); | ||
296 | ret = PTR_ERR(omap->usbhost_ick); | ||
297 | goto err_host_ick; | ||
298 | } | ||
299 | |||
300 | omap->usbhost2_120m_fck = clk_get(omap->dev, "usbhost_120m_fck"); | ||
301 | if (IS_ERR(omap->usbhost2_120m_fck)) { | ||
302 | dev_err(omap->dev, "could not get usbhost_120m_fck\n"); | ||
303 | ret = PTR_ERR(omap->usbhost2_120m_fck); | ||
304 | goto err_host_120m_fck; | ||
305 | } | ||
306 | |||
307 | omap->usbhost1_48m_fck = clk_get(omap->dev, "usbhost_48m_fck"); | ||
308 | if (IS_ERR(omap->usbhost1_48m_fck)) { | ||
309 | dev_err(omap->dev, "could not get usbhost_48m_fck\n"); | ||
310 | ret = PTR_ERR(omap->usbhost1_48m_fck); | ||
311 | goto err_host_48m_fck; | ||
312 | } | ||
313 | |||
314 | omap->usbtll_fck = clk_get(omap->dev, "usbtll_fck"); | ||
315 | if (IS_ERR(omap->usbtll_fck)) { | ||
316 | dev_err(omap->dev, "could not get usbtll_fck\n"); | ||
317 | ret = PTR_ERR(omap->usbtll_fck); | ||
318 | goto err_tll_fck; | ||
319 | } | ||
320 | |||
321 | omap->usbtll_ick = clk_get(omap->dev, "usbtll_ick"); | ||
322 | if (IS_ERR(omap->usbtll_ick)) { | ||
323 | dev_err(omap->dev, "could not get usbtll_ick\n"); | ||
324 | ret = PTR_ERR(omap->usbtll_ick); | ||
325 | goto err_tll_ick; | ||
326 | } | ||
327 | |||
328 | /* Now enable all the clocks in the correct order */ | ||
329 | ohci_omap3_clock_power(omap, 1); | ||
330 | |||
331 | /* perform TLL soft reset, and wait until reset is complete */ | ||
332 | ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | ||
333 | OMAP_USBTLL_SYSCONFIG_SOFTRESET); | ||
334 | |||
335 | /* Wait for TLL reset to complete */ | ||
336 | while (!(ohci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) | ||
337 | & OMAP_USBTLL_SYSSTATUS_RESETDONE)) { | ||
338 | cpu_relax(); | ||
339 | |||
340 | if (time_after(jiffies, timeout)) { | ||
341 | dev_dbg(omap->dev, "operation timed out\n"); | ||
342 | ret = -EINVAL; | ||
343 | goto err_sys_status; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | dev_dbg(omap->dev, "TLL reset done\n"); | ||
348 | |||
349 | /* (1<<3) = no idle mode only for initial debugging */ | ||
350 | ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, | ||
351 | OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | | ||
352 | OMAP_USBTLL_SYSCONFIG_SIDLEMODE | | ||
353 | OMAP_USBTLL_SYSCONFIG_CACTIVITY); | ||
354 | |||
355 | |||
356 | /* Put UHH in NoIdle/NoStandby mode */ | ||
357 | reg = ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSCONFIG); | ||
358 | reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP | ||
359 | | OMAP_UHH_SYSCONFIG_SIDLEMODE | ||
360 | | OMAP_UHH_SYSCONFIG_CACTIVITY | ||
361 | | OMAP_UHH_SYSCONFIG_MIDLEMODE); | ||
362 | reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE; | ||
363 | reg &= ~OMAP_UHH_SYSCONFIG_SOFTRESET; | ||
364 | |||
365 | ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg); | ||
366 | |||
367 | reg = ohci_omap_readl(omap->uhh_base, OMAP_UHH_HOSTCONFIG); | ||
368 | |||
369 | /* setup ULPI bypass and burst configurations */ | ||
370 | reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN | ||
371 | | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN | ||
372 | | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); | ||
373 | reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; | ||
374 | |||
375 | /* | ||
376 | * REVISIT: Pi_CONNECT_STATUS controls MStandby | ||
377 | * assertion and Swakeup generation - let us not | ||
378 | * worry about this for now. OMAP HWMOD framework | ||
379 | * might take care of this later. If not, we can | ||
380 | * update these registers when adding aggressive | ||
381 | * clock management code. | ||
382 | * | ||
383 | * For now, turn off all the Pi_CONNECT_STATUS bits | ||
384 | * | ||
385 | if (omap->port_mode[0] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
386 | reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; | ||
387 | if (omap->port_mode[1] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
388 | reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; | ||
389 | if (omap->port_mode[2] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
390 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | ||
391 | */ | ||
392 | reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS; | ||
393 | reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS; | ||
394 | reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS; | ||
395 | |||
396 | if (omap->es2_compatibility) { | ||
397 | /* | ||
398 | * All OHCI modes need to go through the TLL, | ||
399 | * unlike in the EHCI case. So use UTMI mode | ||
400 | * for all ports for OHCI, on ES2.x silicon | ||
401 | */ | ||
402 | dev_dbg(omap->dev, "OMAP3 ES version <= ES2.1\n"); | ||
403 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS; | ||
404 | } else { | ||
405 | dev_dbg(omap->dev, "OMAP3 ES version > ES2.1\n"); | ||
406 | if (omap->port_mode[0] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
407 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | ||
408 | else | ||
409 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS; | ||
410 | |||
411 | if (omap->port_mode[1] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
412 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | ||
413 | else | ||
414 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS; | ||
415 | |||
416 | if (omap->port_mode[2] == OMAP_USBHS_PORT_MODE_UNUSED) | ||
417 | reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | ||
418 | else | ||
419 | reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS; | ||
420 | |||
421 | } | ||
422 | ohci_omap_writel(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg); | ||
423 | dev_dbg(omap->dev, "UHH setup done, uhh_hostconfig=%x\n", reg); | ||
424 | |||
425 | ohci_omap3_tll_config(omap); | ||
426 | |||
427 | return 0; | ||
428 | |||
429 | err_sys_status: | ||
430 | ohci_omap3_clock_power(omap, 0); | ||
431 | clk_put(omap->usbtll_ick); | ||
432 | |||
433 | err_tll_ick: | ||
434 | clk_put(omap->usbtll_fck); | ||
435 | |||
436 | err_tll_fck: | ||
437 | clk_put(omap->usbhost1_48m_fck); | ||
438 | |||
439 | err_host_48m_fck: | ||
440 | clk_put(omap->usbhost2_120m_fck); | ||
441 | |||
442 | err_host_120m_fck: | ||
443 | clk_put(omap->usbhost_ick); | ||
444 | |||
445 | err_host_ick: | ||
446 | return ret; | ||
447 | } | ||
448 | |||
449 | static void omap3_stop_ohci(struct ohci_hcd_omap3 *omap, struct usb_hcd *hcd) | ||
450 | { | ||
451 | unsigned long timeout = jiffies + msecs_to_jiffies(100); | ||
452 | |||
453 | dev_dbg(omap->dev, "stopping TI EHCI USB Controller\n"); | ||
454 | |||
455 | /* Reset USBHOST for insmod/rmmod to work */ | ||
456 | ohci_omap_writel(omap->uhh_base, OMAP_UHH_SYSCONFIG, | ||
457 | OMAP_UHH_SYSCONFIG_SOFTRESET); | ||
458 | while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) | ||
459 | & OMAP_UHH_SYSSTATUS_UHHRESETDONE)) { | ||
460 | cpu_relax(); | ||
461 | |||
462 | if (time_after(jiffies, timeout)) | ||
463 | dev_dbg(omap->dev, "operation timed out\n"); | ||
464 | } | ||
465 | |||
466 | while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) | ||
467 | & OMAP_UHH_SYSSTATUS_OHCIRESETDONE)) { | ||
468 | cpu_relax(); | ||
469 | |||
470 | if (time_after(jiffies, timeout)) | ||
471 | dev_dbg(omap->dev, "operation timed out\n"); | ||
472 | } | ||
473 | |||
474 | while (!(ohci_omap_readl(omap->uhh_base, OMAP_UHH_SYSSTATUS) | ||
475 | & OMAP_UHH_SYSSTATUS_EHCIRESETDONE)) { | ||
476 | cpu_relax(); | ||
477 | |||
478 | if (time_after(jiffies, timeout)) | ||
479 | dev_dbg(omap->dev, "operation timed out\n"); | ||
480 | } | ||
481 | |||
482 | ohci_omap_writel(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1)); | ||
483 | |||
484 | while (!(ohci_omap_readl(omap->tll_base, OMAP_USBTLL_SYSSTATUS) | ||
485 | & (1 << 0))) { | ||
486 | cpu_relax(); | ||
487 | |||
488 | if (time_after(jiffies, timeout)) | ||
489 | dev_dbg(omap->dev, "operation timed out\n"); | ||
490 | } | ||
491 | |||
492 | ohci_omap3_clock_power(omap, 0); | ||
493 | |||
494 | if (omap->usbtll_fck != NULL) { | ||
495 | clk_put(omap->usbtll_fck); | ||
496 | omap->usbtll_fck = NULL; | ||
497 | } | ||
498 | |||
499 | if (omap->usbhost_ick != NULL) { | ||
500 | clk_put(omap->usbhost_ick); | ||
501 | omap->usbhost_ick = NULL; | ||
502 | } | ||
503 | |||
504 | if (omap->usbhost1_48m_fck != NULL) { | ||
505 | clk_put(omap->usbhost1_48m_fck); | ||
506 | omap->usbhost1_48m_fck = NULL; | ||
507 | } | ||
508 | |||
509 | if (omap->usbhost2_120m_fck != NULL) { | ||
510 | clk_put(omap->usbhost2_120m_fck); | ||
511 | omap->usbhost2_120m_fck = NULL; | ||
512 | } | ||
513 | |||
514 | if (omap->usbtll_ick != NULL) { | ||
515 | clk_put(omap->usbtll_ick); | ||
516 | omap->usbtll_ick = NULL; | ||
517 | } | ||
518 | |||
519 | dev_dbg(omap->dev, "Clock to USB host has been disabled\n"); | ||
520 | } | ||
521 | |||
522 | /*-------------------------------------------------------------------------*/ | ||
523 | |||
524 | static const struct hc_driver ohci_omap3_hc_driver = { | 70 | static const struct hc_driver ohci_omap3_hc_driver = { |
525 | .description = hcd_name, | 71 | .description = hcd_name, |
526 | .product_desc = "OMAP3 OHCI Host Controller", | 72 | .product_desc = "OMAP3 OHCI Host Controller", |
@@ -580,107 +126,77 @@ static const struct hc_driver ohci_omap3_hc_driver = { | |||
580 | */ | 126 | */ |
581 | static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) | 127 | static int __devinit ohci_hcd_omap3_probe(struct platform_device *pdev) |
582 | { | 128 | { |
583 | struct usbhs_omap_board_data *pdata = pdev->dev.platform_data; | 129 | struct device *dev = &pdev->dev; |
584 | struct ohci_hcd_omap3 *omap; | 130 | struct usb_hcd *hcd = NULL; |
585 | struct resource *res; | 131 | void __iomem *regs = NULL; |
586 | struct usb_hcd *hcd; | 132 | struct resource *res; |
587 | int ret = -ENODEV; | 133 | int ret = -ENODEV; |
588 | int irq; | 134 | int irq; |
589 | 135 | ||
590 | if (usb_disabled()) | 136 | if (usb_disabled()) |
591 | goto err_disabled; | 137 | goto err_end; |
592 | 138 | ||
593 | if (!pdata) { | 139 | if (!dev->parent) { |
594 | dev_dbg(&pdev->dev, "missing platform_data\n"); | 140 | dev_err(dev, "Missing parent device\n"); |
595 | goto err_pdata; | 141 | return -ENODEV; |
596 | } | 142 | } |
597 | 143 | ||
598 | irq = platform_get_irq(pdev, 0); | 144 | irq = platform_get_irq_byname(pdev, "ohci-irq"); |
145 | if (irq < 0) { | ||
146 | dev_err(dev, "OHCI irq failed\n"); | ||
147 | return -ENODEV; | ||
148 | } | ||
599 | 149 | ||
600 | omap = kzalloc(sizeof(*omap), GFP_KERNEL); | 150 | res = platform_get_resource_byname(pdev, |
601 | if (!omap) { | 151 | IORESOURCE_MEM, "ohci"); |
602 | ret = -ENOMEM; | 152 | if (!ret) { |
603 | goto err_disabled; | 153 | dev_err(dev, "UHH OHCI get resource failed\n"); |
154 | return -ENOMEM; | ||
604 | } | 155 | } |
605 | 156 | ||
606 | hcd = usb_create_hcd(&ohci_omap3_hc_driver, &pdev->dev, | 157 | regs = ioremap(res->start, resource_size(res)); |
607 | dev_name(&pdev->dev)); | 158 | if (!regs) { |
608 | if (!hcd) { | 159 | dev_err(dev, "UHH OHCI ioremap failed\n"); |
609 | ret = -ENOMEM; | 160 | return -ENOMEM; |
610 | goto err_create_hcd; | ||
611 | } | 161 | } |
612 | 162 | ||
613 | platform_set_drvdata(pdev, omap); | ||
614 | omap->dev = &pdev->dev; | ||
615 | omap->port_mode[0] = pdata->port_mode[0]; | ||
616 | omap->port_mode[1] = pdata->port_mode[1]; | ||
617 | omap->port_mode[2] = pdata->port_mode[2]; | ||
618 | omap->es2_compatibility = pdata->es2_compatibility; | ||
619 | omap->ohci = hcd_to_ohci(hcd); | ||
620 | 163 | ||
621 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci"); | 164 | hcd = usb_create_hcd(&ohci_omap3_hc_driver, dev, |
165 | dev_name(dev)); | ||
166 | if (!hcd) { | ||
167 | dev_err(dev, "usb_create_hcd failed\n"); | ||
168 | goto err_io; | ||
169 | } | ||
622 | 170 | ||
623 | hcd->rsrc_start = res->start; | 171 | hcd->rsrc_start = res->start; |
624 | hcd->rsrc_len = resource_size(res); | 172 | hcd->rsrc_len = resource_size(res); |
173 | hcd->regs = regs; | ||
625 | 174 | ||
626 | hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); | 175 | ret = omap_usbhs_enable(dev); |
627 | if (!hcd->regs) { | ||
628 | dev_err(&pdev->dev, "OHCI ioremap failed\n"); | ||
629 | ret = -ENOMEM; | ||
630 | goto err_ioremap; | ||
631 | } | ||
632 | |||
633 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh"); | ||
634 | omap->uhh_base = ioremap(res->start, resource_size(res)); | ||
635 | if (!omap->uhh_base) { | ||
636 | dev_err(&pdev->dev, "UHH ioremap failed\n"); | ||
637 | ret = -ENOMEM; | ||
638 | goto err_uhh_ioremap; | ||
639 | } | ||
640 | |||
641 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll"); | ||
642 | omap->tll_base = ioremap(res->start, resource_size(res)); | ||
643 | if (!omap->tll_base) { | ||
644 | dev_err(&pdev->dev, "TLL ioremap failed\n"); | ||
645 | ret = -ENOMEM; | ||
646 | goto err_tll_ioremap; | ||
647 | } | ||
648 | |||
649 | ret = omap3_start_ohci(omap, hcd); | ||
650 | if (ret) { | 176 | if (ret) { |
651 | dev_dbg(&pdev->dev, "failed to start ohci\n"); | 177 | dev_dbg(dev, "failed to start ohci\n"); |
652 | goto err_start; | 178 | goto err_end; |
653 | } | 179 | } |
654 | 180 | ||
655 | ohci_hcd_init(omap->ohci); | 181 | ohci_hcd_init(hcd_to_ohci(hcd)); |
656 | 182 | ||
657 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); | 183 | ret = usb_add_hcd(hcd, irq, IRQF_DISABLED); |
658 | if (ret) { | 184 | if (ret) { |
659 | dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret); | 185 | dev_dbg(dev, "failed to add hcd with err %d\n", ret); |
660 | goto err_add_hcd; | 186 | goto err_add_hcd; |
661 | } | 187 | } |
662 | 188 | ||
663 | return 0; | 189 | return 0; |
664 | 190 | ||
665 | err_add_hcd: | 191 | err_add_hcd: |
666 | omap3_stop_ohci(omap, hcd); | 192 | omap_usbhs_disable(dev); |
667 | |||
668 | err_start: | ||
669 | iounmap(omap->tll_base); | ||
670 | |||
671 | err_tll_ioremap: | ||
672 | iounmap(omap->uhh_base); | ||
673 | |||
674 | err_uhh_ioremap: | ||
675 | iounmap(hcd->regs); | ||
676 | 193 | ||
677 | err_ioremap: | 194 | err_end: |
678 | usb_put_hcd(hcd); | 195 | usb_put_hcd(hcd); |
679 | 196 | ||
680 | err_create_hcd: | 197 | err_io: |
681 | kfree(omap); | 198 | iounmap(regs); |
682 | err_pdata: | 199 | |
683 | err_disabled: | ||
684 | return ret; | 200 | return ret; |
685 | } | 201 | } |
686 | 202 | ||
@@ -699,24 +215,20 @@ err_disabled: | |||
699 | */ | 215 | */ |
700 | static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev) | 216 | static int __devexit ohci_hcd_omap3_remove(struct platform_device *pdev) |
701 | { | 217 | { |
702 | struct ohci_hcd_omap3 *omap = platform_get_drvdata(pdev); | 218 | struct device *dev = &pdev->dev; |
703 | struct usb_hcd *hcd = ohci_to_hcd(omap->ohci); | 219 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
704 | 220 | ||
705 | usb_remove_hcd(hcd); | ||
706 | omap3_stop_ohci(omap, hcd); | ||
707 | iounmap(hcd->regs); | 221 | iounmap(hcd->regs); |
708 | iounmap(omap->tll_base); | 222 | usb_remove_hcd(hcd); |
709 | iounmap(omap->uhh_base); | 223 | omap_usbhs_disable(dev); |
710 | usb_put_hcd(hcd); | 224 | usb_put_hcd(hcd); |
711 | kfree(omap); | ||
712 | 225 | ||
713 | return 0; | 226 | return 0; |
714 | } | 227 | } |
715 | 228 | ||
716 | static void ohci_hcd_omap3_shutdown(struct platform_device *pdev) | 229 | static void ohci_hcd_omap3_shutdown(struct platform_device *pdev) |
717 | { | 230 | { |
718 | struct ohci_hcd_omap3 *omap = platform_get_drvdata(pdev); | 231 | struct usb_hcd *hcd = dev_get_drvdata(&pdev->dev); |
719 | struct usb_hcd *hcd = ohci_to_hcd(omap->ohci); | ||
720 | 232 | ||
721 | if (hcd->driver->shutdown) | 233 | if (hcd->driver->shutdown) |
722 | hcd->driver->shutdown(hcd); | 234 | hcd->driver->shutdown(hcd); |