patch to latest usbhost patch
[kernel-power] / usbhost / usb / musb / omap2430.c
1 /*
2  * Copyright (C) 2005-2007 by Texas Instruments
3  * Some code has been taken from tusb6010.c
4  * Copyrights for that are attributable to:
5  * Copyright (C) 2006 Nokia Corporation
6  * Jarkko Nikula <jarkko.nikula@nokia.com>
7  * Tony Lindgren <tony@atomide.com>
8  *
9  * This file is part of the Inventra Controller Driver for Linux.
10  *
11  * The Inventra Controller Driver for Linux is free software; you
12  * can redistribute it and/or modify it under the terms of the GNU
13  * General Public License version 2 as published by the Free Software
14  * Foundation.
15  *
16  * The Inventra Controller Driver for Linux is distributed in
17  * the hope that it will be useful, but WITHOUT ANY WARRANTY;
18  * without even the implied warranty of MERCHANTABILITY or
19  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
20  * License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with The Inventra Controller Driver for Linux ; if not,
24  * write to the Free Software Foundation, Inc., 59 Temple Place,
25  * Suite 330, Boston, MA  02111-1307  USA
26  *
27  */
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/sched.h>
31 #include <linux/slab.h>
32 #include <linux/init.h>
33 #include <linux/list.h>
34 #include <linux/clk.h>
35 #include <linux/io.h>
36
37 #include <asm/mach-types.h>
38 #include <mach/hardware.h>
39 #include <mach/mux.h>
40
41 #include <linux/i2c/twl4030.h>
42
43 #include "musb_core.h"
44 #include "omap2430.h"
45
46 #ifdef CONFIG_ARCH_OMAP3430
47 #define get_cpu_rev()   2
48 #endif
49
50 #define MUSB_TIMEOUT_A_WAIT_BCON        1100
51
52 static struct timer_list musb_idle_timer;
53
54 static void musb_vbus_work(struct work_struct *data)
55 {
56         struct musb *musb = container_of(data, struct musb, vbus_work);
57         u8 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
58
59         /* clear/set requirements for musb to work with DPS on omap3 */
60         if (musb->board && musb->board->set_pm_limits && !musb->is_charger)
61                 musb->board->set_pm_limits(musb->controller,
62                                         (devctl & MUSB_DEVCTL_VBUS));
63 }
64
65 static void musb_do_idle(unsigned long _musb)
66 {
67         struct musb     *musb = (void *)_musb;
68         unsigned long   flags;
69 #ifdef CONFIG_USB_MUSB_HDRC_HCD
70         u8      power;
71 #endif
72         u8      devctl;
73
74         spin_lock_irqsave(&musb->lock, flags);
75
76         devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
77
78         switch (musb->xceiv->state) {
79         case OTG_STATE_A_WAIT_BCON:
80                 if(host_mode(musb->mregs))
81                         break; /*Don't time out*/
82
83                 devctl &= ~MUSB_DEVCTL_SESSION;
84                 musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
85
86                 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
87                 if (!host_mode(musb->mregs)) {
88                         musb->xceiv->state = OTG_STATE_B_IDLE;
89                         MUSB_DEV_MODE(musb);
90                 } else {
91                         musb->xceiv->state = OTG_STATE_A_IDLE;
92                         MUSB_HST_MODE(musb);
93                 }
94                 break;
95 #ifdef CONFIG_USB_MUSB_HDRC_HCD
96         case OTG_STATE_A_SUSPEND:
97                 /* finish RESUME signaling? */
98                 if (musb->port1_status & MUSB_PORT_STAT_RESUME) {
99                         power = musb_readb(musb->mregs, MUSB_POWER);
100                         power &= ~MUSB_POWER_RESUME;
101                         DBG(1, "root port resume stopped, power %02x\n", power);
102                         musb_writeb(musb->mregs, MUSB_POWER, power);
103                         musb->is_active = 1;
104                         musb->port1_status &= ~(USB_PORT_STAT_SUSPEND
105                                                 | MUSB_PORT_STAT_RESUME);
106                         musb->port1_status |= USB_PORT_STAT_C_SUSPEND << 16;
107                         usb_hcd_poll_rh_status(musb_to_hcd(musb));
108                         /* NOTE: it might really be A_WAIT_BCON ... */
109                         musb->xceiv->state = OTG_STATE_A_HOST;
110                 }
111                 break;
112 #endif
113 #ifdef CONFIG_USB_MUSB_HDRC_HCD
114         case OTG_STATE_A_HOST:
115
116
117                 devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
118                 if (!host_mode(musb->mregs))
119                         musb->xceiv->state = OTG_STATE_B_IDLE;
120                 /*Don't time out if host*/
121                 //              else
122                 //      musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
123 #endif
124         default:
125                 break;
126         }
127         spin_unlock_irqrestore(&musb->lock, flags);
128 }
129
130
131 void musb_platform_try_idle(struct musb *musb, unsigned long timeout)
132 {
133         unsigned long           default_timeout = jiffies + msecs_to_jiffies(3);
134         static unsigned long    last_timer;
135
136         if (timeout == 0)
137                 timeout = default_timeout;
138
139         /* Never idle if active, or when VBUS timeout is not set as host */
140         if (musb->is_active || ((musb->a_wait_bcon == 0)
141                         && (musb->xceiv->state == OTG_STATE_A_WAIT_BCON))) {
142                 DBG(6, "%s active, deleting timer\n", otg_state_string(musb));
143                 del_timer(&musb_idle_timer);
144                 last_timer = jiffies;
145                 return;
146         }
147
148         if (time_after(last_timer, timeout)) {
149                 if (!timer_pending(&musb_idle_timer))
150                         last_timer = timeout;
151                 else {
152                         DBG(6, "Longer idle timer already pending, ignoring\n");
153                         return;
154                 }
155         }
156         last_timer = timeout;
157
158         DBG(6, "%s inactive, for idle timer for %lu ms\n",
159                 otg_state_string(musb),
160                 (unsigned long)jiffies_to_msecs(timeout - jiffies));
161         mod_timer(&musb_idle_timer, timeout);
162 }
163
164 void musb_platform_enable(struct musb *musb)
165 {
166         twl4030_upd_usb_suspended(0);
167 }
168 void musb_platform_disable(struct musb *musb)
169 {
170         twl4030_upd_usb_suspended(musb->is_suspended);
171 }
172 static void omap_vbus_power(struct musb *musb, int is_on, int sleeping)
173 {
174 }
175
176 static void omap_set_vbus(struct musb *musb, int is_on)
177 {
178         u8              devctl;
179         /* HDRC controls CPEN, but beware current surges during device
180          * connect.  They can trigger transient overcurrent conditions
181          * that must be ignored.
182          */
183
184         devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
185
186         if (is_on) {
187                 musb->is_active = 1;
188                 musb->xceiv->default_a = 1;
189                 musb->xceiv->state = OTG_STATE_A_WAIT_VRISE;
190                 devctl |= MUSB_DEVCTL_SESSION;
191                 MUSB_HST_MODE(musb);
192                 
193                 if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
194                         /*Power is already applied. Skip VRISE and go directly to BCON.*/
195                         musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
196                 }
197
198
199         } else {
200                 musb->is_active = 0;
201
202                 /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
203                  * jumping right to B_IDLE...
204                  */
205
206                 musb->xceiv->default_a = 0;
207                 musb->xceiv->state = OTG_STATE_B_IDLE;
208                 devctl &= ~MUSB_DEVCTL_SESSION;
209
210                 MUSB_DEV_MODE(musb);
211         }
212         musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
213
214         DBG(1, "VBUS %s, devctl %02x "
215                 /* otg %3x conf %08x prcm %08x */ "\n",
216                 otg_state_string(musb),
217                 musb_readb(musb->mregs, MUSB_DEVCTL));
218 }
219 static int omap_set_power(struct otg_transceiver *x, unsigned mA)
220 {
221         return 0;
222 }
223
224 static int musb_platform_resume(struct musb *musb);
225
226 int musb_platform_set_mode(struct musb *musb, u8 musb_mode)
227 {
228         struct usb_hcd  *hcd;
229         struct usb_bus  *host;
230         u8              devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
231
232         devctl |= MUSB_DEVCTL_SESSION;
233         musb_writeb(musb->mregs, MUSB_DEVCTL, devctl);
234
235         switch (musb_mode) {
236 #ifdef CONFIG_USB_MUSB_HDRC_HCD
237         case MUSB_HOST:
238                 hcd = musb_to_hcd(musb);
239                 host = hcd_to_bus(hcd);
240
241                 otg_set_host(musb->xceiv, host);
242                 break;
243 #endif
244 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
245         case MUSB_PERIPHERAL:
246                 otg_set_peripheral(musb->xceiv, &musb->g);
247                 break;
248 #endif
249 #ifdef CONFIG_USB_MUSB_OTG
250         case MUSB_OTG:
251                 break;
252 #endif
253         default:
254                 return -EINVAL;
255         }
256         return 0;
257 }
258
259 int __init musb_platform_init(struct musb *musb)
260 {
261         struct otg_transceiver *x = otg_get_transceiver();
262         u32 l;
263
264 #if defined(CONFIG_ARCH_OMAP2430)
265         omap_cfg_reg(AE5_2430_USB0HS_STP);
266 #endif
267
268         musb->suspendm = true;
269         musb->xceiv = x;
270         musb_platform_resume(musb);
271
272         l = omap_readl(OTG_SYSCONFIG);
273         l &= ~ENABLEWAKEUP;     /* disable wakeup */
274         l &= ~NOSTDBY;          /* remove possible nostdby */
275         l |= SMARTSTDBY;        /* enable smart standby */
276         l &= ~AUTOIDLE;         /* disable auto idle */
277         l &= ~NOIDLE;           /* remove possible noidle */
278         l |= SMARTIDLE;         /* enable smart idle */
279         /*
280          * MUSB AUTOIDLE don't work in 3430.
281          * Workaround by Richard Woodruff/TI
282          */
283         if (!cpu_is_omap3430())
284                 l |= AUTOIDLE;  /* enable auto idle */
285         omap_writel(l, OTG_SYSCONFIG);
286
287         l = omap_readl(OTG_INTERFSEL);
288         l |= ULPI_12PIN;
289         omap_writel(l, OTG_INTERFSEL);
290
291         pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
292                         "sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
293                         omap_readl(OTG_REVISION), omap_readl(OTG_SYSCONFIG),
294                         omap_readl(OTG_SYSSTATUS), omap_readl(OTG_INTERFSEL),
295                         omap_readl(OTG_SIMENABLE));
296
297         omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
298
299         if (is_host_enabled(musb))
300                 musb->board_set_vbus = omap_set_vbus;
301         if (is_peripheral_enabled(musb))
302                 musb->xceiv->set_power = omap_set_power;
303         musb->a_wait_bcon = MUSB_TIMEOUT_A_WAIT_BCON;
304
305         setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb);
306         INIT_WORK(&musb->vbus_work, musb_vbus_work);
307
308         return 0;
309 }
310
311 int musb_platform_suspend(struct musb *musb)
312 {
313         u32 l;
314
315         if (!musb->clock)
316                 return 0;
317
318         /* in any role */
319         l = omap_readl(OTG_FORCESTDBY);
320         l |= ENABLEFORCE;       /* enable MSTANDBY */
321         omap_writel(l, OTG_FORCESTDBY);
322
323         l = omap_readl(OTG_SYSCONFIG);
324         l |= ENABLEWAKEUP;      /* enable wakeup */
325         omap_writel(l, OTG_SYSCONFIG);
326
327         if (musb->xceiv->set_suspend)
328                 musb->xceiv->set_suspend(musb->xceiv, 1);
329
330         if (musb->set_clock)
331                 musb->set_clock(musb->clock, 0);
332         else
333                 clk_disable(musb->clock);
334
335         return 0;
336 }
337
338 static int musb_platform_resume(struct musb *musb)
339 {
340         u32 l;
341
342         if (!musb->clock)
343                 return 0;
344
345         if (musb->xceiv->set_suspend)
346                 musb->xceiv->set_suspend(musb->xceiv, 0);
347
348         if (musb->set_clock)
349                 musb->set_clock(musb->clock, 1);
350         else
351                 clk_enable(musb->clock);
352
353         l = omap_readl(OTG_SYSCONFIG);
354         l &= ~ENABLEWAKEUP;     /* disable wakeup */
355         omap_writel(l, OTG_SYSCONFIG);
356
357         l = omap_readl(OTG_FORCESTDBY);
358         l &= ~ENABLEFORCE;      /* disable MSTANDBY */
359         omap_writel(l, OTG_FORCESTDBY);
360
361         return 0;
362 }
363
364
365 int musb_platform_exit(struct musb *musb)
366 {
367
368         omap_vbus_power(musb, 0 /*off*/, 1);
369
370         musb_platform_suspend(musb);
371
372         clk_put(musb->clock);
373         musb->clock = 0;
374
375         return 0;
376 }
377
378 #ifdef CONFIG_PM
379
380 void musb_save_ctx_and_suspend(struct usb_gadget *gadget, int overwrite)
381 {
382         struct musb *musb = gadget_to_musb(gadget);
383         u32 l;
384         unsigned long   flags;
385         unsigned long   tmo;
386
387         spin_lock_irqsave(&musb->lock, flags);
388         if (overwrite)
389                 /* Save register context */
390                 musb_save_ctx(musb);
391         spin_unlock_irqrestore(&musb->lock, flags);
392
393         DBG(3, "allow sleep\n");
394         /* Do soft reset. This needs to be done with broken AUTOIDLE */
395         tmo = jiffies + msecs_to_jiffies(300);
396         omap_writel(SOFTRST, OTG_SYSCONFIG);
397         while (!omap_readl(OTG_SYSSTATUS)) {
398                 if (time_after(jiffies, tmo)) {
399                         WARN(1, "musb failed to recover from reset!");
400                         break;
401                 }
402         }
403
404         l = omap_readl(OTG_FORCESTDBY);
405         l |= ENABLEFORCE;       /* enable MSTANDBY */
406         omap_writel(l, OTG_FORCESTDBY);
407
408         l = ENABLEWAKEUP;       /* enable wakeup */
409         omap_writel(l, OTG_SYSCONFIG);
410         /* Use AUTOIDLE here or the device may fail to hit sleep */
411         l |= AUTOIDLE;
412         omap_writel(l, OTG_SYSCONFIG);
413
414         if (musb->board && musb->board->xceiv_power)
415                 musb->board->xceiv_power(0);
416         /* Now it's safe to get rid of the buggy AUTOIDLE */
417         l &= ~AUTOIDLE;
418         omap_writel(l, OTG_SYSCONFIG);
419
420         musb->is_charger = 0;
421
422         /* clear constraints */
423         if (musb->board && musb->board->set_pm_limits)
424                 musb->board->set_pm_limits(musb->controller, 0);
425 }
426 EXPORT_SYMBOL_GPL(musb_save_ctx_and_suspend);
427
428 void musb_restore_ctx_and_resume(struct usb_gadget *gadget)
429 {
430         struct musb *musb = gadget_to_musb(gadget);
431         u32 l;
432         u8 r;
433         unsigned long   flags;
434
435         DBG(3, "restoring register context for %s\n","musb_restore_ctx_and_resume");
436
437         if (musb->board && musb->board->xceiv_power)
438                 musb->board->xceiv_power(1);
439
440         spin_lock_irqsave(&musb->lock, flags);
441         if (musb->set_clock)
442                 musb->set_clock(musb->clock, 1);
443         else
444                 clk_enable(musb->clock);
445
446         if(host_mode(musb->mregs)) {
447                 musb_force_term(musb->mregs,MUSB_TERM_HOST_FULLSPEED);
448                 r = musb_ulpi_readb(musb->mregs,ISP1704_FUNC_CTRL);
449         } else {
450                 /* Recover OTG control */
451                 r = musb_ulpi_readb(musb->mregs, ISP1704_OTG_CTRL);
452                 r |= ISP1704_OTG_CTRL_IDPULLUP | ISP1704_OTG_CTRL_DP_PULLDOWN;
453                 musb_ulpi_writeb(musb->mregs, ISP1704_OTG_CTRL, r);
454                 r = ISP1704_FUNC_CTRL_FULL_SPEED;
455         }
456         /* Recover FUNC control */
457         r |= ISP1704_FUNC_CTRL_SUSPENDM | ISP1704_FUNC_CTRL_RESET;
458         musb_ulpi_writeb(musb->mregs, ISP1704_FUNC_CTRL, r);
459
460         l = omap_readl(OTG_SYSCONFIG);
461         l &= ~ENABLEWAKEUP;     /* disable wakeup */
462         omap_writel(l, OTG_SYSCONFIG);
463
464         l = omap_readl(OTG_FORCESTDBY);
465         l &= ~ENABLEFORCE;      /* disable MSTANDBY */
466         omap_writel(l, OTG_FORCESTDBY);
467
468         l = omap_readl(OTG_SYSCONFIG);
469         l &= ~ENABLEWAKEUP;     /* disable wakeup */
470         l &= ~NOSTDBY;          /* remove possible nostdby */
471         l |= SMARTSTDBY;        /* enable smart standby */
472         l &= ~AUTOIDLE;         /* disable auto idle */
473         l &= ~NOIDLE;           /* remove possible noidle */
474         l |= SMARTIDLE;         /* enable smart idle */
475         omap_writel(l, OTG_SYSCONFIG);
476
477         l = omap_readl(OTG_INTERFSEL);
478         l |= ULPI_12PIN;
479         omap_writel(l, OTG_INTERFSEL);
480
481         /* Restore register context */
482         musb_restore_ctx(musb);
483
484         /* set constraints */
485         schedule_work(&musb->vbus_work);
486         spin_unlock_irqrestore(&musb->lock, flags);
487 }
488 EXPORT_SYMBOL_GPL(musb_restore_ctx_and_resume);
489 #endif