3 #include <linux/platform_device.h>
4 #include <linux/serial_core.h>
6 #include <linux/delay.h>
8 #include <linux/usb/ch9.h>
10 #include <plat/regs-otg.h>
12 #include <asm/mach/arch.h>
13 #include <asm/mach-types.h>
15 #include <mach/regs-clock.h>
17 #define ETC6PUD (S5PV310_VA_GPIO2 + 0x228)
24 static bool usbotg_clk_enabled;
25 static bool usbhost_clk_enabled;
27 static void usb_clk_get(enum usb_clk_type clk_type, int check_enabled)
31 if (clk_type == USBOTG_CLK) {
33 if (usbotg_clk_enabled)
35 usbotg_clk_enabled = true;
38 usb_clk = clk_get(NULL, "usbotg");
40 if (IS_ERR(usb_clk)) {
41 printk(KERN_ERR"cannot get usbotg clock\n");
44 } else if (clk_type == USBHOST_CLK) {
46 if (usbhost_clk_enabled)
48 usbhost_clk_enabled = true;
51 usb_clk = clk_get(NULL, "usbhost");
53 if (IS_ERR(usb_clk)) {
54 printk(KERN_ERR"cannot get usbhost clock\n");
58 printk(KERN_ERR"Undefine usb_clock\n");
66 static void usb_clk_put(enum usb_clk_type clk_type, int check_enabled)
70 if (clk_type == USBOTG_CLK) {
72 if (!usbotg_clk_enabled)
74 usbotg_clk_enabled = false;
77 usb_clk = clk_get(NULL, "usbotg");
79 if (IS_ERR(usb_clk)) {
80 printk(KERN_ERR"cannot get usbotg clock\n");
83 } else if (clk_type == USBHOST_CLK) {
85 if (!usbhost_clk_enabled)
87 usbhost_clk_enabled = false;
90 usb_clk = clk_get(NULL, "usbhost");
92 if (IS_ERR(usb_clk)) {
93 printk(KERN_ERR"cannot get usbhost clock\n");
97 printk(KERN_ERR"Undefine usb_clock\n");
101 clk_disable(usb_clk);
105 /* Initializes OTG Phy. */
106 void otg_phy_init(void)
108 usb_clk_get(USBOTG_CLK, 1);
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);
119 __raw_writel(__raw_readl(S3C_USBOTG_RSTCON)
120 &~(0x7<<0), S3C_USBOTG_RSTCON);
123 EXPORT_SYMBOL(otg_phy_init);
125 /* OTG PHY Power Off */
126 void otg_phy_off(void)
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);
133 usb_clk_put(USBOTG_CLK, 1);
135 EXPORT_SYMBOL(otg_phy_off);
137 void usb_host_phy_init(void)
139 pr_debug("setup-usb: %s\n", __func__);
141 /* Must be enable usbhost & usbotg clk */
142 usb_clk_get(USBHOST_CLK, 1);
143 usb_clk_get(USBOTG_CLK, 0);
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);
152 __raw_writel((__raw_readl(ETC6PUD) & ~(0x3 << 14)) | (0x3 << 14),
156 __raw_writel((__raw_readl(ETC6PUD) & ~(0x3 << 14)) | (0x1 << 14),
160 __raw_writel(__raw_readl(S5P_USBHOST_PHY_CONTROL)
161 |(0x1<<0), S5P_USBHOST_PHY_CONTROL);
163 /* floating prevention logic : disable */
164 __raw_writel((__raw_readl(S3C_USBOTG_PHY1CON) | (0x1<<0)),
167 /* set hsic phy0,1 to normal */
168 __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR) & ~(0xf<<9)),
172 __raw_writel((__raw_readl(S3C_USBOTG_PHYPWR) & ~(0x7<<6)),
175 /* set clock source for PLL (24MHz) */
176 __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK) | (0x1<<7) | (0x3<<0)),
179 /* reset all ports of both PHY and Link */
180 __raw_writel((__raw_readl(S3C_USBOTG_RSTCON) | (0x1<<6) | (0x7<<3)),
183 __raw_writel((__raw_readl(S3C_USBOTG_RSTCON) & ~(0x1<<6) & ~(0x7<<3)),
187 usb_clk_put(USBOTG_CLK, 0);
190 EXPORT_SYMBOL(usb_host_phy_init);
192 void usb_host_phy_off(void)
194 pr_debug("setup-usb: %s\n", __func__);
196 usb_clk_get(USBOTG_CLK, 0);
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);
203 usb_clk_put(USBOTG_CLK, 0);
204 usb_clk_put(USBHOST_CLK, 1);
206 EXPORT_SYMBOL(usb_host_phy_off);
208 /* FIXME: This function check the state of USB HOST before entering LPA mode */
209 int is_usb_host_phy_suspend(void)
214 usb_clk_get(USBOTG_CLK, 0);
216 /* Check USBOTG phy power */
217 reg = __raw_readl(S3C_USBOTG_PHYPWR);
221 usb_clk_put(USBOTG_CLK, 0);
222 printk(KERN_DEBUG "USBOTG is Active state\n");
226 /* Check USBHOST phy power */
227 usb_clk_get(USBHOST_CLK, 0);
229 local_irq_save(flags);
230 reg = __raw_readl(S5P_USBHOST_PHY_CONTROL);
231 if (reg & (1 << 0)) {
232 local_irq_restore(flags);
234 usb_clk_put(USBHOST_CLK, 0);
235 usb_clk_put(USBOTG_CLK, 0);
236 printk(KERN_DEBUG "USBHOST is Power-ON\n");
240 usb_clk_put(USBHOST_CLK, 0);
241 usb_clk_put(USBOTG_CLK, 0);
244 EXPORT_SYMBOL(is_usb_host_phy_suspend);
247 void usb_host_phy_suspend(void)
249 unsigned int reg = __raw_readl(S3C_USBOTG_PHYPWR);
251 pr_debug("setup-usb: %s\n", __func__);
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)),
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);
263 usb_clk_put(USBOTG_CLK, 0);
264 usb_clk_put(USBHOST_CLK, 1);
266 EXPORT_SYMBOL(usb_host_phy_suspend);
268 void usb_host_phy_resume(void)
270 pr_debug("setup-usb: %s\n", __func__);
272 usb_clk_get(USBHOST_CLK, 1);
273 usb_clk_get(USBOTG_CLK, 0);
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)),
281 usb_clk_put(USBOTG_CLK, 0);
284 EXPORT_SYMBOL(usb_host_phy_resume);
286 /* For LPM(L1) suspend */
287 void usb_host_phy_sleep(void)
289 unsigned int reg = __raw_readl(S3C_USBOTG_PHYPWR);
291 usb_clk_get(USBOTG_CLK, 0);
293 /* if OHCI isn't used, 7 bit clear */
294 __raw_writel((__raw_readl(S3C_USBOTG_PHYCLK) & ~(0x1<<7)),
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);
302 usb_clk_put(USBOTG_CLK, 0);
304 EXPORT_SYMBOL(usb_host_phy_sleep);
306 void usb_host_phy_wakeup(void)
308 usb_clk_get(USBOTG_CLK, 0);
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)),
316 usb_clk_put(USBOTG_CLK, 0);
318 EXPORT_SYMBOL(usb_host_phy_wakeup);
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)
325 usb_clk_get(USBOTG_CLK, 1);
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);
334 __raw_writel((__raw_readl(S3C_USBOTG_RSTCON)
335 &~(0x3<<1))|(0x1<<0), S3C_USBOTG_RSTCON);
337 __raw_writel((__raw_readl(S3C_USBOTG_RSTCON)
338 &~(0x7<<0)), S3C_USBOTG_RSTCON);
341 __raw_writel((__raw_readl(S3C_UDC_OTG_GUSBCFG)
342 |(0x3<<8)), S3C_UDC_OTG_GUSBCFG);
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)
352 EXPORT_SYMBOL(otg_host_phy_init);