]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/usb/musb/omap2430.c
musb_hdrc: MUSB HOST support on 2430SDP
[linux-2.6-omap-h63xx.git] / drivers / usb / musb / omap2430.c
1 /*
2  * Copyright (C) 2005-2006 by Texas Instruments
3  *
4  * This file is part of the Inventra Controller Driver for Linux.
5  *
6  * The Inventra Controller Driver for Linux is free software; you
7  * can redistribute it and/or modify it under the terms of the GNU
8  * General Public License version 2 as published by the Free Software
9  * Foundation.
10  *
11  * The Inventra Controller Driver for Linux is distributed in
12  * the hope that it will be useful, but WITHOUT ANY WARRANTY;
13  * without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15  * License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with The Inventra Controller Driver for Linux ; if not,
19  * write to the Free Software Foundation, Inc., 59 Temple Place,
20  * Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/sched.h>
26 #include <linux/slab.h>
27 #include <linux/init.h>
28 #include <linux/list.h>
29 #include <linux/clk.h>
30
31 #include <asm/io.h>
32 #include <asm/mach-types.h>
33 #include <asm/arch/hardware.h>
34 #include <asm/arch/mux.h>
35
36 #include "musbdefs.h"
37 #include "omap2430.h"
38
39 #ifdef CONFIG_ARCH_OMAP3430
40 #define get_cpu_rev()   2
41 #endif
42
43
44 void musb_platform_enable(struct musb *musb)
45 {
46 }
47 void musb_platform_disable(struct musb *musb)
48 {
49 }
50 static void omap_vbus_power(struct musb *musb, int is_on, int sleeping)
51 {
52 }
53
54 static void omap_set_vbus(struct musb *musb, int is_on)
55 {
56         u8              devctl;
57         /* HDRC controls CPEN, but beware current surges during device
58          * connect.  They can trigger transient overcurrent conditions
59          * that must be ignored.
60          */
61
62         devctl = musb_readb(musb->pRegs, MGC_O_HDRC_DEVCTL);
63
64         if (is_on) {
65                 musb->is_active = 1;
66                 musb->xceiv.default_a = 1;
67                 musb->xceiv.state = OTG_STATE_A_WAIT_VRISE;
68                 devctl |= MGC_M_DEVCTL_SESSION;
69
70                 MUSB_HST_MODE(musb);
71         } else {
72                 musb->is_active = 0;
73
74                 /* NOTE:  we're skipping A_WAIT_VFALL -> A_IDLE and
75                  * jumping right to B_IDLE...
76                  */
77
78                 musb->xceiv.default_a = 0;
79                 musb->xceiv.state = OTG_STATE_B_IDLE;
80                 devctl &= ~MGC_M_DEVCTL_SESSION;
81
82                 MUSB_DEV_MODE(musb);
83         }
84         musb_writeb(musb->pRegs, MGC_O_HDRC_DEVCTL, devctl);
85
86         DBG(1, "VBUS %s, devctl %02x "
87                 /* otg %3x conf %08x prcm %08x */ "\n",
88                 otg_state_string(musb),
89                 musb_readb(musb->pRegs, MGC_O_HDRC_DEVCTL));
90 }
91 static int omap_set_power(struct otg_transceiver *x, unsigned mA)
92 {
93         return 0;
94 }
95
96 int musb_platform_resume(struct musb *musb);
97
98 int __init musb_platform_init(struct musb *musb)
99 {
100 #if defined(CONFIG_ARCH_OMAP2430)
101         omap_cfg_reg(AE5_2430_USB0HS_STP);
102         /* get the clock */
103         musb->clock = clk_get((struct device *)musb->controller, "usbhs_ick");
104 #else
105         musb->clock = clk_get((struct device *)musb->controller, "hsusb_ick");
106 #endif
107         if(IS_ERR(musb->clock))
108                 return PTR_ERR(musb->clock);
109
110         musb_platform_resume(musb);
111
112         OTG_INTERFSEL_REG |= ULPI_12PIN;
113
114         pr_debug("HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
115                         "sysstatus 0x%x, intrfsel 0x%x, simenable  0x%x\n",
116                         OTG_REVISION_REG, OTG_SYSCONFIG_REG, OTG_SYSSTATUS_REG,
117                         OTG_INTERFSEL_REG, OTG_SIMENABLE_REG);
118
119         omap_vbus_power(musb, musb->board_mode == MUSB_HOST, 1);
120
121
122         if (is_host_enabled(musb))
123                 musb->board_set_vbus = omap_set_vbus;
124         if (is_peripheral_enabled(musb))
125                 musb->xceiv.set_power = omap_set_power;
126
127         return 0;
128 }
129
130 int musb_platform_suspend(struct musb *musb)
131 {
132         /* in any role */
133         OTG_FORCESTDBY_REG &= ~ENABLEFORCE; /* disable MSTANDBY */
134         OTG_SYSCONFIG_REG &= FORCESTDBY;        /* enable force standby */
135         OTG_SYSCONFIG_REG &= ~AUTOIDLE;         /* disable auto idle */
136         OTG_SYSCONFIG_REG |= SMARTIDLE;         /* enable smart idle */
137         OTG_FORCESTDBY_REG |= ENABLEFORCE; /* enable MSTANDBY */
138         OTG_SYSCONFIG_REG |= AUTOIDLE;          /* enable auto idle */
139
140         clk_disable(musb->clock);
141         return 0;
142 }
143
144 int musb_platform_resume(struct musb *musb)
145 {
146         clk_enable(musb->clock);
147
148         OTG_FORCESTDBY_REG &= ~ENABLEFORCE; /* disable MSTANDBY */
149         OTG_SYSCONFIG_REG |= SMARTSTDBY;        /* enable smart standby */
150         OTG_SYSCONFIG_REG &= ~AUTOIDLE;         /* disable auto idle */
151         OTG_SYSCONFIG_REG |= SMARTIDLE;         /* enable smart idle */
152         OTG_SYSCONFIG_REG |= AUTOIDLE;          /* enable auto idle */
153
154         return 0;
155 }
156
157
158 int musb_platform_exit(struct musb *musb)
159 {
160
161         omap_vbus_power(musb, 0 /*off*/, 1);
162
163         musb_platform_suspend(musb);
164
165         clk_put(musb->clock);
166         musb->clock = 0;
167
168         return 0;
169 }