upload tizen1.0 source
[kernel/linux-2.6.36.git] / arch / arm / mach-s5pv310 / setup-usb.c
1 #define DEBUG
2
3 #include <linux/platform_device.h>
4 #include <linux/serial_core.h>
5 #include <linux/io.h>
6 #include <linux/delay.h>
7 #include <linux/clk.h>
8 #include <linux/usb/ch9.h>
9
10 #include <plat/regs-otg.h>
11
12 #include <asm/mach/arch.h>
13 #include <asm/mach-types.h>
14
15 #include <mach/regs-clock.h>
16
17 #define ETC6PUD         (S5PV310_VA_GPIO2 + 0x228)
18
19 enum usb_clk_type {
20         USBOTG_CLK,
21         USBHOST_CLK,
22 };
23
24 static bool usbotg_clk_enabled;
25 static bool usbhost_clk_enabled;
26
27 static void usb_clk_get(enum usb_clk_type clk_type, int check_enabled)
28 {
29         struct clk *usb_clk;
30
31         if (clk_type == USBOTG_CLK) {
32                 if (check_enabled) {
33                         if (usbotg_clk_enabled)
34                                 return;
35                         usbotg_clk_enabled = true;
36                 }
37
38                 usb_clk = clk_get(NULL, "usbotg");
39
40                 if (IS_ERR(usb_clk)) {
41                         printk(KERN_ERR"cannot get usbotg clock\n");
42                         return;
43                 }
44         } else if (clk_type == USBHOST_CLK) {
45                 if (check_enabled) {
46                         if (usbhost_clk_enabled)
47                                 return;
48                         usbhost_clk_enabled = true;
49                 }
50
51                 usb_clk = clk_get(NULL, "usbhost");
52
53                 if (IS_ERR(usb_clk)) {
54                         printk(KERN_ERR"cannot get usbhost clock\n");
55                         return;
56                 }
57         } else {
58                 printk(KERN_ERR"Undefine usb_clock\n");
59                 return ;
60         }
61
62         clk_enable(usb_clk);
63         clk_put(usb_clk);
64 }
65
66 static void usb_clk_put(enum usb_clk_type clk_type, int check_enabled)
67 {
68         struct clk *usb_clk;
69
70         if (clk_type == USBOTG_CLK) {
71                 if (check_enabled) {
72                         if (!usbotg_clk_enabled)
73                                 return;
74                         usbotg_clk_enabled = false;
75                 }
76
77                 usb_clk = clk_get(NULL, "usbotg");
78
79                 if (IS_ERR(usb_clk)) {
80                         printk(KERN_ERR"cannot get usbotg clock\n");
81                         return;
82                 }
83         } else if (clk_type == USBHOST_CLK) {
84                 if (check_enabled) {
85                         if (!usbhost_clk_enabled)
86                                 return;
87                         usbhost_clk_enabled = false;
88                 }
89
90                 usb_clk = clk_get(NULL, "usbhost");
91
92                 if (IS_ERR(usb_clk)) {
93                         printk(KERN_ERR"cannot get usbhost clock\n");
94                         return;
95                 }
96         } else {
97                 printk(KERN_ERR"Undefine usb_clock\n");
98                 return ;
99         }
100
101         clk_disable(usb_clk);
102         clk_put(usb_clk);
103 }
104
105 /* Initializes OTG Phy. */
106 void otg_phy_init(void)
107 {
108         usb_clk_get(USBOTG_CLK, 1);
109
110         __raw_writel(__raw_readl(S5P_USBOTG_PHY_CONTROL)
111                 |(0x1<<0), S5P_USBOTG_PHY_CONTROL);
112         __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR)
113                 &~(0x7<<3)&~(0x1<<0)), S3C_USBOTG_PHYPWR);
114         __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK)
115                 &~(0x5<<2))|(0x3<<0), S3C_USBOTG_PHYCLK); /* PLL 24Mhz */
116         __raw_writel((__raw_readl(S3C_USBOTG_RSTCON)
117                 &~(0x3<<1))|(0x1<<0), S3C_USBOTG_RSTCON);
118         udelay(10);
119         __raw_writel(__raw_readl(S3C_USBOTG_RSTCON)
120                 &~(0x7<<0), S3C_USBOTG_RSTCON);
121         udelay(10);
122 }
123 EXPORT_SYMBOL(otg_phy_init);
124
125 /* OTG PHY Power Off */
126 void otg_phy_off(void)
127 {
128         __raw_writel(__raw_readl(S3C_USBOTG_PHYPWR)
129                 |(0x3<<3), S3C_USBOTG_PHYPWR);
130         __raw_writel(__raw_readl(S5P_USBOTG_PHY_CONTROL)
131                 &~(1<<0), S5P_USBOTG_PHY_CONTROL);
132
133         usb_clk_put(USBOTG_CLK, 1);
134 }
135 EXPORT_SYMBOL(otg_phy_off);
136
137 void usb_host_phy_init(void)
138 {
139         pr_debug("setup-usb: %s\n", __func__);
140
141         /*  Must be enable usbhost & usbotg clk  */
142         usb_clk_get(USBHOST_CLK, 1);
143         usb_clk_get(USBOTG_CLK, 0);
144
145         if (__raw_readl(S5P_USBHOST_PHY_CONTROL) & (0x1<<0)) {
146                 printk(KERN_ERR"[usb_host_phy_init]Already power on PHY\n");
147                 usb_clk_get(USBOTG_CLK, 0);
148                 return;
149         }
150
151         /* EVT1 */
152         __raw_writel((__raw_readl(ETC6PUD) & ~(0x3 << 14)) | (0x3 << 14),
153                 ETC6PUD);
154         /* EVT0 */
155 #if 0
156         __raw_writel((__raw_readl(ETC6PUD) & ~(0x3 << 14)) | (0x1 << 14),
157                 ETC6PUD);
158 #endif
159
160         __raw_writel(__raw_readl(S5P_USBHOST_PHY_CONTROL)
161                 |(0x1<<0), S5P_USBHOST_PHY_CONTROL);
162
163         /* floating prevention logic : disable */
164         __raw_writel((__raw_readl(S3C_USBOTG_PHY1CON) | (0x1<<0)),
165                 S3C_USBOTG_PHY1CON);
166
167         /* set hsic phy0,1 to normal */
168         __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR) & ~(0xf<<9)),
169                 S3C_USBOTG_PHYPWR);
170
171         /* phy-power on */
172         __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR) & ~(0x7<<6)),
173                 S3C_USBOTG_PHYPWR);
174
175         /* set clock source for PLL (24MHz) */
176         __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK) | (0x1<<7) | (0x3<<0)),
177                 S3C_USBOTG_PHYCLK);
178
179         /* reset all ports of both PHY and Link */
180         __raw_writel((__raw_readl(S3C_USBOTG_RSTCON) | (0x1<<6) | (0x7<<3)),
181                 S3C_USBOTG_RSTCON);
182         udelay(10);
183         __raw_writel((__raw_readl(S3C_USBOTG_RSTCON) & ~(0x1<<6) & ~(0x7<<3)),
184                 S3C_USBOTG_RSTCON);
185         udelay(50);
186
187         usb_clk_put(USBOTG_CLK, 0);
188
189 }
190 EXPORT_SYMBOL(usb_host_phy_init);
191
192 void usb_host_phy_off(void)
193 {
194         pr_debug("setup-usb: %s\n", __func__);
195
196         usb_clk_get(USBOTG_CLK, 0);
197
198         __raw_writel(__raw_readl(S3C_USBOTG_PHYPWR)
199                 |(0x1<<7)|(0x1<<6), S3C_USBOTG_PHYPWR);
200         __raw_writel(__raw_readl(S5P_USBHOST_PHY_CONTROL)
201                 &~(1<<0), S5P_USBHOST_PHY_CONTROL);
202
203         usb_clk_put(USBOTG_CLK, 0);
204         usb_clk_put(USBHOST_CLK, 1);
205 }
206 EXPORT_SYMBOL(usb_host_phy_off);
207
208 /* FIXME: This function check the state of USB HOST before entering LPA mode */
209 int is_usb_host_phy_suspend(void)
210 {
211         unsigned int reg;
212         unsigned long flags;
213
214         usb_clk_get(USBOTG_CLK, 0);
215
216         /* Check USBOTG phy power */
217         reg = __raw_readl(S3C_USBOTG_PHYPWR);
218         reg = reg >> 6;
219         reg &= (1 << 0);
220         if (!reg) {
221                 usb_clk_put(USBOTG_CLK, 0);
222                 printk(KERN_DEBUG "USBOTG is Active state\n");
223                 return 1;
224         }
225
226         /* Check USBHOST phy power */
227         usb_clk_get(USBHOST_CLK, 0);
228
229         local_irq_save(flags);
230         reg = __raw_readl(S5P_USBHOST_PHY_CONTROL);
231         if (reg & (1 << 0)) {
232                 local_irq_restore(flags);
233
234                 usb_clk_put(USBHOST_CLK, 0);
235                 usb_clk_put(USBOTG_CLK, 0);
236                 printk(KERN_DEBUG "USBHOST is Power-ON\n");
237                 return 1;
238         }
239
240         usb_clk_put(USBHOST_CLK, 0);
241         usb_clk_put(USBOTG_CLK, 0);
242         return 0;
243 }
244 EXPORT_SYMBOL(is_usb_host_phy_suspend);
245
246 /* For L2 suspend */
247 void usb_host_phy_suspend(void)
248 {
249         unsigned int reg = __raw_readl(S3C_USBOTG_PHYPWR);
250
251         pr_debug("setup-usb: %s\n", __func__);
252
253         usb_clk_get(USBOTG_CLK, 0);
254         /* if OHCI isn't used, 7 bit clear */
255         __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK) & ~(0x1<<7)),
256                 S3C_USBOTG_PHYCLK);
257
258         reg |= (0x1<<6);  /* phy port0 suspend */
259         reg |= (0x1<<9);  /* phy hsic port0 suspend */
260         reg |= (0x1<<11); /* phy hsic port1 suspend */
261         __raw_writel(reg, S3C_USBOTG_PHYPWR);
262
263         usb_clk_put(USBOTG_CLK, 0);
264         usb_clk_put(USBHOST_CLK, 1);
265 }
266 EXPORT_SYMBOL(usb_host_phy_suspend);
267
268 void usb_host_phy_resume(void)
269 {
270         pr_debug("setup-usb: %s\n", __func__);
271
272         usb_clk_get(USBHOST_CLK, 1);
273         usb_clk_get(USBOTG_CLK, 0);
274
275         __raw_writel(__raw_readl(S3C_USBOTG_PHYPWR)
276                 & ~((0x1<<6)|(0x1<<9)|(0x1<<11)), S3C_USBOTG_PHYPWR);
277         /* if OHCI 48mhz, 7 bit set */
278         __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK) | (0x1<<7)),
279                 S3C_USBOTG_PHYCLK);
280
281         usb_clk_put(USBOTG_CLK, 0);
282
283 }
284 EXPORT_SYMBOL(usb_host_phy_resume);
285
286 /* For LPM(L1) suspend */
287 void usb_host_phy_sleep(void)
288 {
289         unsigned int reg = __raw_readl(S3C_USBOTG_PHYPWR);
290
291         usb_clk_get(USBOTG_CLK, 0);
292
293         /* if OHCI isn't used, 7 bit clear */
294         __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK) & ~(0x1<<7)),
295                 S3C_USBOTG_PHYCLK);
296
297         reg |= (0x1<<8);  /* phy port0 sleep */
298         reg |= (0x1<<10); /* phy hsic port0 sleep */
299         reg |= (0x1<<12); /* phy hsic port1 sleep */
300         __raw_writel(reg, S3C_USBOTG_PHYPWR);
301
302         usb_clk_put(USBOTG_CLK, 0);
303 }
304 EXPORT_SYMBOL(usb_host_phy_sleep);
305
306 void usb_host_phy_wakeup(void)
307 {
308         usb_clk_get(USBOTG_CLK, 0);
309
310         __raw_writel(__raw_readl(S3C_USBOTG_PHYPWR)
311                 & ~((0x1<<8)|(0x1<<10)|(0x1<<12)), S3C_USBOTG_PHYPWR);
312         /* if OHCI 48mhz, 7 bit set */
313         __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK) | (0x1<<7)),
314                 S3C_USBOTG_PHYCLK);
315
316         usb_clk_put(USBOTG_CLK, 0);
317 }
318 EXPORT_SYMBOL(usb_host_phy_wakeup);
319
320 /* soonyong.cho : We received below code from MCCI. This function can enable otg host. */
321 #ifdef CONFIG_USB_S3C_OTG_HOST
322 /* Initializes OTG Phy */
323 void otg_host_phy_init(void)
324 {
325         usb_clk_get(USBOTG_CLK, 1);
326
327     __raw_writel(__raw_readl(S5P_USBOTG_PHY_CONTROL)
328                 |(0x1<<0), S5P_USBOTG_PHY_CONTROL);
329     __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR)
330         &~(0x7<<3)&~(0x1<<0)), S3C_USBOTG_PHYPWR);
331     __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK)
332         &~(0x1<<4))|(0x7<<0), S3C_USBOTG_PHYCLK);
333
334     __raw_writel((__raw_readl(S3C_USBOTG_RSTCON)
335         &~(0x3<<1))|(0x1<<0), S3C_USBOTG_RSTCON);
336     udelay(10);
337     __raw_writel((__raw_readl(S3C_USBOTG_RSTCON)
338         &~(0x7<<0)), S3C_USBOTG_RSTCON);
339     udelay(10);
340
341     __raw_writel((__raw_readl(S3C_UDC_OTG_GUSBCFG)
342         |(0x3<<8)), S3C_UDC_OTG_GUSBCFG);
343
344     printk("otg_host_phy_int : USBPHYCTL=0x%x,PHYPWR=0x%x,PHYCLK=0x%x,PHYTUNE=0x%x,USBCFG=0x%x\n",
345         readl(S5P_USBOTG_PHY_CONTROL),
346         readl(S3C_USBOTG_PHYPWR),
347         readl(S3C_USBOTG_PHYCLK),
348         readl(S3C_USBOTG_PHYTUNE),
349         readl(S3C_UDC_OTG_GUSBCFG)
350         );
351 }
352 EXPORT_SYMBOL(otg_host_phy_init);
353 #endif