]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/arm/mach-mx6/usb_h1.c
d983e2870045c0e27c85d12aba1a177e5d2de12d
[karo-tx-linux.git] / arch / arm / mach-mx6 / usb_h1.c
1 /*
2  * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/types.h>
21 #include <linux/delay.h>
22 #include <linux/clk.h>
23 #include <linux/platform_device.h>
24 #include <linux/fsl_devices.h>
25 #include <linux/gpio.h>
26 #include <linux/io.h>
27 #include <linux/delay.h>
28 #include <mach/arc_otg.h>
29 #include <mach/hardware.h>
30 #include "devices-imx6q.h"
31 #include "regs-anadig.h"
32 #include "usb.h"
33
34 static struct clk *usb_oh3_clk;
35 extern int clk_get_usecount(struct clk *clk);
36 static struct fsl_usb2_platform_data usbh1_config;
37
38 static void fsl_platform_h1_set_usb_phy_dis(
39                 struct fsl_usb2_platform_data *pdata, bool enable)
40 {
41         u32 usb_phy_ctrl_dcdt = 0;
42         void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
43         usb_phy_ctrl_dcdt = __raw_readl(
44                         MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_CTRL) &
45                         BM_USBPHY_CTRL_ENHOSTDISCONDETECT;
46         if (enable) {
47                 if (usb_phy_ctrl_dcdt == 0) {
48                         __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
49                                         anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR);
50
51                         __raw_writel(BM_USBPHY_PWD_RXPWDENV,
52                                         MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_PWD_SET);
53
54                         udelay(300);
55
56                         __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
57                                 MX6_IO_ADDRESS(pdata->phy_regs)
58                                 + HW_USBPHY_CTRL_SET);
59
60                         UH1_USBSTS |= (1 << 7);
61
62                         while ((UH1_USBSTS & (1 << 7)) == 0)
63                                 ;
64
65                         udelay(2);
66
67                         __raw_writel(BM_USBPHY_PWD_RXPWDENV,
68                                         MX6_IO_ADDRESS(pdata->phy_regs) + HW_USBPHY_PWD_CLR);
69
70                         __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS,
71                                         anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET);
72
73                 }
74         } else {
75                 if (usb_phy_ctrl_dcdt
76                                 == BM_USBPHY_CTRL_ENHOSTDISCONDETECT)
77                         __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
78                                 MX6_IO_ADDRESS(pdata->phy_regs)
79                                 + HW_USBPHY_CTRL_CLR);
80         }
81 }
82
83 static void usbh1_internal_phy_clock_gate(bool on)
84 {
85         void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
86         if (on) {
87                 __raw_writel(BM_USBPHY_CTRL_CLKGATE, phy_reg + HW_USBPHY_CTRL_CLR);
88         } else {
89                 __raw_writel(BM_USBPHY_CTRL_CLKGATE, phy_reg + HW_USBPHY_CTRL_SET);
90         }
91 }
92
93 static void usbh1_platform_phy_power_on(void)
94 {
95         void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
96         __raw_writel(BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG,
97                                 anatop_base_addr + HW_ANADIG_ANA_MISC0_SET);
98 }
99
100 static int usb_phy_enable(struct fsl_usb2_platform_data *pdata)
101 {
102         u32 tmp;
103         void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
104         void __iomem *phy_ctrl;
105
106         /* Stop then Reset */
107         UH1_USBCMD &= ~UCMD_RUN_STOP;
108         while (UH1_USBCMD & UCMD_RUN_STOP)
109                 ;
110
111         UH1_USBCMD |= UCMD_RESET;
112         while ((UH1_USBCMD) & (UCMD_RESET))
113                 ;
114         /* Reset USBPHY module */
115         phy_ctrl = phy_reg + HW_USBPHY_CTRL;
116         tmp = __raw_readl(phy_ctrl);
117         tmp |= BM_USBPHY_CTRL_SFTRST;
118         __raw_writel(tmp, phy_ctrl);
119         udelay(10);
120
121         /* Remove CLKGATE and SFTRST */
122         tmp = __raw_readl(phy_ctrl);
123         tmp &= ~(BM_USBPHY_CTRL_CLKGATE | BM_USBPHY_CTRL_SFTRST);
124         __raw_writel(tmp, phy_ctrl);
125         udelay(10);
126
127         /* Power up the PHY */
128         __raw_writel(0, phy_reg + HW_USBPHY_PWD);
129         /* enable FS/LS device */
130         tmp = __raw_readl(phy_reg + HW_USBPHY_CTRL);
131         tmp |= (BM_USBPHY_CTRL_ENUTMILEVEL2 | BM_USBPHY_CTRL_ENUTMILEVEL3);
132         __raw_writel(tmp, phy_reg + HW_USBPHY_CTRL);
133
134         if (!usb_icbug_swfix_need())
135                 __raw_writel((1 << 17), phy_reg + HW_USBPHY_IP_SET);
136         if (cpu_is_mx6sl())
137                 __raw_writel((1 << 18), phy_reg + HW_USBPHY_IP_SET);
138         return 0;
139 }
140 static int fsl_usb_host_init_ext(struct platform_device *pdev)
141 {
142         int ret;
143         struct clk *usb_clk;
144         usb_clk = clk_get(NULL, "usboh3_clk");
145         clk_enable(usb_clk);
146         usb_oh3_clk = usb_clk;
147
148         ret = fsl_usb_host_init(pdev);
149         if (ret) {
150                 printk(KERN_ERR "host1 init fails......\n");
151                 return ret;
152         }
153         usbh1_internal_phy_clock_gate(true);
154         usb_phy_enable(pdev->dev.platform_data);
155
156         return 0;
157 }
158
159 static void fsl_usb_host_uninit_ext(struct platform_device *pdev)
160 {
161         struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
162
163         fsl_usb_host_uninit(pdata);
164
165         clk_disable(usb_oh3_clk);
166         clk_put(usb_oh3_clk);
167
168 }
169
170 static void usbh1_clock_gate(bool on)
171 {
172         pr_debug("%s: on is %d\n", __func__, on);
173         if (on) {
174                 clk_enable(usb_oh3_clk);
175         } else {
176                 clk_disable(usb_oh3_clk);
177         }
178 }
179
180 static void _wake_up_enable(struct fsl_usb2_platform_data *pdata, bool enable)
181 {
182         void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
183
184         pr_debug("host1, %s, enable is %d\n", __func__, enable);
185         if (enable) {
186                 __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP | BM_USBPHY_CTRL_ENVBUSCHG_WKUP
187                                 | BM_USBPHY_CTRL_ENDPDMCHG_WKUP
188                                 | BM_USBPHY_CTRL_ENAUTOSET_USBCLKS
189                                 | BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD
190                                 | BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE
191                                 | BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE
192                                 | BM_USBPHY_CTRL_ENAUTO_PWRON_PLL , phy_reg + HW_USBPHY_CTRL_SET);
193                 USB_H1_CTRL |= (UCTRL_OWIE);
194         } else {
195                 USB_H1_CTRL &= ~(UCTRL_OWIE);
196                 __raw_writel(BM_USBPHY_CTRL_ENIDCHG_WKUP | BM_USBPHY_CTRL_ENVBUSCHG_WKUP
197                                 | BM_USBPHY_CTRL_ENDPDMCHG_WKUP, phy_reg + HW_USBPHY_CTRL_CLR);
198                 /* The interrupt must be disabled for at least 3
199                 * cycles of the standby clock(32k Hz) , that is 0.094 ms*/
200                 udelay(100);
201         }
202 }
203
204 static void usbh1_platform_rh_suspend_swfix(struct fsl_usb2_platform_data *pdata)
205 {
206         void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
207         u32 tmp;
208         u32 index = 0;
209
210         /* before we set and then clear PWD bit,
211          * we must wait LS to be J */
212         if ((UH1_PORTSC1 & (3 << 26)) != (1 << 26)) {
213                 while (((UH1_PORTSC1 & PORTSC_LS_MASK) != PORTSC_LS_J_STATE) &&
214                                 (index < 1000)) {
215                         index++;
216                         udelay(4);
217                 }
218         } else {
219                 while (((UH1_PORTSC1 & PORTSC_LS_MASK) != PORTSC_LS_K_STATE) &&
220                                 (index < 1000)) {
221                         index++;
222                         udelay(4);
223                 }
224         }
225
226         if (index >= 1000)
227                 printk(KERN_INFO "%s big error\n", __func__);
228
229         tmp = (BM_USBPHY_PWD_TXPWDFS
230                 | BM_USBPHY_PWD_TXPWDIBIAS
231                 | BM_USBPHY_PWD_TXPWDV2I
232                 | BM_USBPHY_PWD_RXPWDENV
233                 | BM_USBPHY_PWD_RXPWD1PT1
234                 | BM_USBPHY_PWD_RXPWDDIFF
235                 | BM_USBPHY_PWD_RXPWDRX);
236         __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET);
237
238         __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR);
239
240         fsl_platform_h1_set_usb_phy_dis(pdata, 0);
241 }
242
243 static void usbh1_platform_rh_resume_swfix(struct fsl_usb2_platform_data *pdata)
244 {
245         u32 index = 0;
246
247         if ((UOG_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH)
248                 return ;
249         while ((UH1_PORTSC1 & PORTSC_PORT_FORCE_RESUME)
250                         && (index < 1000)) {
251                 udelay(500);
252                 index++;
253         }
254         if (index >= 1000)
255                 printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n",
256                 __func__, __LINE__);
257         /* We should add some delay to wait for the device switch to
258           * High-Speed 45ohm termination resistors mode. */
259         udelay(500);
260         fsl_platform_h1_set_usb_phy_dis(pdata, 1);
261 }
262
263 static void usbh1_platform_rh_suspend(struct fsl_usb2_platform_data *pdata)
264 {
265         /*for mx6sl ,we do not need any sw fix*/
266         if (cpu_is_mx6sl())
267                 return ;
268         __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
269                 MX6_IO_ADDRESS(pdata->phy_regs)
270                 + HW_USBPHY_CTRL_CLR);
271 }
272
273 static void usbh1_platform_rh_resume(struct fsl_usb2_platform_data *pdata)
274 {
275         u32 index = 0;
276
277         /*for mx6sl ,we do not need any sw fix*/
278         if (cpu_is_mx6sl())
279                 return ;
280         if ((UOG_PORTSC1 & (PORTSC_PORT_SPEED_MASK)) != PORTSC_PORT_SPEED_HIGH)
281                 return ;
282         while ((UH1_PORTSC1 & PORTSC_PORT_FORCE_RESUME)
283                         && (index < 1000)) {
284                 udelay(500);
285                 index++;
286         }
287         if (index >= 1000)
288                 printk(KERN_ERR "failed to wait for the resume finished in %s() line:%d\n",
289                 __func__, __LINE__);
290         /* We should add some delay to wait for the device switch to
291           * High-Speed 45ohm termination resistors mode. */
292         udelay(500);
293         __raw_writel(BM_USBPHY_CTRL_ENHOSTDISCONDETECT,
294                 MX6_IO_ADDRESS(pdata->phy_regs)
295                 + HW_USBPHY_CTRL_SET);
296 }
297
298 static void _phy_lowpower_suspend(struct fsl_usb2_platform_data *pdata, bool enable)
299 {
300         u32 tmp;
301         void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
302         pr_debug("host1, %s, enable is %d\n", __func__, enable);
303         if (enable) {
304                 UH1_PORTSC1 |= PORTSC_PHCD;
305
306                 pr_debug("%s, Poweroff UTMI \n", __func__);
307
308                 tmp = (BM_USBPHY_PWD_TXPWDFS
309                         | BM_USBPHY_PWD_TXPWDIBIAS
310                         | BM_USBPHY_PWD_TXPWDV2I
311                         | BM_USBPHY_PWD_RXPWDENV
312                         | BM_USBPHY_PWD_RXPWD1PT1
313                         | BM_USBPHY_PWD_RXPWDDIFF
314                         | BM_USBPHY_PWD_RXPWDRX);
315                 __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_SET);
316
317                 usbh1_internal_phy_clock_gate(false);
318         } else {
319                 if (UH1_PORTSC1 & PORTSC_PHCD) {
320                         UH1_PORTSC1 &= ~PORTSC_PHCD;
321                         mdelay(1);
322                 }
323                 usbh1_internal_phy_clock_gate(true);
324                 tmp = (BM_USBPHY_PWD_TXPWDFS
325                         | BM_USBPHY_PWD_TXPWDIBIAS
326                         | BM_USBPHY_PWD_TXPWDV2I
327                         | BM_USBPHY_PWD_RXPWDENV
328                         | BM_USBPHY_PWD_RXPWD1PT1
329                         | BM_USBPHY_PWD_RXPWDDIFF
330                         | BM_USBPHY_PWD_RXPWDRX);
331                 __raw_writel(tmp, phy_reg + HW_USBPHY_PWD_CLR);
332
333         }
334 }
335
336 static enum usb_wakeup_event _is_usbh1_wakeup(struct fsl_usb2_platform_data *pdata)
337 {
338         u32 wakeup_req = USB_H1_CTRL & UCTRL_OWIR;
339
340         if (wakeup_req)
341                 return WAKEUP_EVENT_DPDM;
342         pr_err("host1, %s, invalid wake up\n", __func__);
343         return WAKEUP_EVENT_INVALID;
344 }
345
346 static void h1_wakeup_handler(struct fsl_usb2_platform_data *pdata)
347 {
348         _wake_up_enable(pdata, false);
349         _phy_lowpower_suspend(pdata, false);
350 }
351
352 static void usbh1_wakeup_event_clear(void)
353 {
354         void __iomem *phy_reg = MX6_IO_ADDRESS(USB_PHY1_BASE_ADDR);
355         u32 wakeup_irq_bits;
356
357         wakeup_irq_bits = BM_USBPHY_CTRL_RESUME_IRQ | BM_USBPHY_CTRL_WAKEUP_IRQ;
358         if (__raw_readl(phy_reg + HW_USBPHY_CTRL) && wakeup_irq_bits) {
359                 /* clear the wakeup interrupt status */
360                 __raw_writel(wakeup_irq_bits, phy_reg + HW_USBPHY_CTRL_CLR);
361         }
362 }
363
364 static struct fsl_usb2_platform_data usbh1_config = {
365         .name           = "Host 1",
366         .init           = fsl_usb_host_init_ext,
367         .exit           = fsl_usb_host_uninit_ext,
368         .operating_mode = FSL_USB2_MPH_HOST,
369         .phy_mode = FSL_USB2_PHY_UTMI_WIDE,
370         .power_budget = 500,    /* 500 mA max power */
371         .wake_up_enable = _wake_up_enable,
372         .usb_clock_for_pm  = usbh1_clock_gate,
373         .platform_set_disconnect_det = fsl_platform_h1_set_usb_phy_dis,
374         .phy_lowpower_suspend = _phy_lowpower_suspend,
375         .is_wakeup_event = _is_usbh1_wakeup,
376         .wakeup_handler = h1_wakeup_handler,
377         .platform_phy_power_on = usbh1_platform_phy_power_on,
378         .transceiver = "utmi",
379         .phy_regs = USB_PHY1_BASE_ADDR,
380 };
381 static struct fsl_usb2_wakeup_platform_data usbh1_wakeup_config = {
382                 .name = "USBH1 wakeup",
383                 .usb_clock_for_pm  = usbh1_clock_gate,
384                 .usb_pdata = {&usbh1_config, NULL, NULL},
385                 .usb_wakeup_exhandle = usbh1_wakeup_event_clear,
386 };
387
388 static struct platform_device *pdev, *pdev_wakeup;
389 static driver_vbus_func  mx6_set_usb_host1_vbus;
390
391 static int  __init mx6_usb_h1_init(void)
392 {
393         static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
394         struct imx_fsl_usb2_wakeup_data imx6q_fsl_hs_wakeup_data[] = {
395                 imx_fsl_usb2_wakeup_data_entry_single(MX6Q, 1, HS1)};
396         struct imx_fsl_usb2_wakeup_data  imx6sl_fsl_hs_wakeup_data[] = {
397                 imx_fsl_usb2_wakeup_data_entry_single(MX6SL, 1, HS1)};
398         struct imx_mxc_ehci_data imx6q_mxc_ehci_hs_data[] = {
399                 imx_mxc_ehci_data_entry_single(MX6Q, 1, HS1)};
400         struct imx_mxc_ehci_data imx6sl_mxc_ehci_hs_data[] = {
401                 imx_mxc_ehci_data_entry_single(MX6SL, 1, HS1)};
402
403         mx6_get_host1_vbus_func(&mx6_set_usb_host1_vbus);
404         usbh1_config.platform_driver_vbus = mx6_set_usb_host1_vbus;
405
406         /* Some phy and power's special controls for host1
407          * 1. The external charger detector needs to be disabled
408          * or the signal at DP will be poor
409          * 2. The PLL's power and output to usb for host 1
410          * is totally controlled by IC, so the Software only needs
411          * to enable them at initializtion.
412          */
413         __raw_writel(BM_ANADIG_USB2_CHRG_DETECT_EN_B  \
414                         | BM_ANADIG_USB2_CHRG_DETECT_CHK_CHRG_B, \
415                         anatop_base_addr + HW_ANADIG_USB2_CHRG_DETECT);
416         __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_BYPASS,
417                         anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR);
418         __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_ENABLE  \
419                         | BM_ANADIG_USB2_PLL_480_CTRL_POWER \
420                         | BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, \
421                         anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET);
422
423         usbh1_config.wakeup_pdata = &usbh1_wakeup_config;
424         if (usb_icbug_swfix_need()) {
425                 usbh1_config.platform_rh_suspend = usbh1_platform_rh_suspend_swfix;
426                 usbh1_config.platform_rh_resume  = usbh1_platform_rh_resume_swfix;
427         } else {
428                 usbh1_config.platform_rh_suspend = usbh1_platform_rh_suspend;
429                 usbh1_config.platform_rh_resume  = usbh1_platform_rh_resume;
430         }
431         if (cpu_is_mx6sl())
432                 pdev = imx6sl_add_fsl_ehci_hs(1, &usbh1_config);
433         else
434                 pdev = imx6q_add_fsl_ehci_hs(1, &usbh1_config);
435         usbh1_wakeup_config.usb_pdata[0] = pdev->dev.platform_data;
436         if (cpu_is_mx6sl())
437                 pdev_wakeup = imx6sl_add_fsl_usb2_hs_wakeup(1, &usbh1_wakeup_config);
438         else
439                 pdev_wakeup = imx6q_add_fsl_usb2_hs_wakeup(1, &usbh1_wakeup_config);
440         platform_device_add(pdev);
441         ((struct fsl_usb2_platform_data *)(pdev->dev.platform_data))->wakeup_pdata =
442                 (struct fsl_usb2_wakeup_platform_data *)(pdev_wakeup->dev.platform_data);
443         return 0;
444 }
445 module_init(mx6_usb_h1_init);
446
447 static void __exit mx6_usb_h1_exit(void)
448 {
449         static void __iomem *anatop_base_addr = MX6_IO_ADDRESS(ANATOP_BASE_ADDR);
450
451         platform_device_unregister(pdev);
452         platform_device_unregister(pdev_wakeup);
453         __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_BYPASS,
454                         anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_SET);
455         __raw_writel(BM_ANADIG_USB2_PLL_480_CTRL_ENABLE  \
456                         | BM_ANADIG_USB2_PLL_480_CTRL_POWER \
457                         | BM_ANADIG_USB2_PLL_480_CTRL_EN_USB_CLKS, \
458                         anatop_base_addr + HW_ANADIG_USB2_PLL_480_CTRL_CLR);
459
460         return ;
461 }
462 module_exit(mx6_usb_h1_exit);
463
464 MODULE_AUTHOR("Freescale Semiconductor");
465 MODULE_LICENSE("GPL");