5d72b0c290db22d784a68770803f112d7818dae8
[openwrt.git] / target / linux / ar71xx / files / arch / mips / ar71xx / dev-usb.c
1 /*
2  *  Atheros AR71xx USB host device support
3  *
4  *  Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
5  *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
6  *
7  *  Parts of this file are based on Atheros' 2.6.15 BSP
8  *
9  *  This program is free software; you can redistribute it and/or modify it
10  *  under the terms of the GNU General Public License version 2 as published
11  *  by the Free Software Foundation.
12  */
13
14 #include <linux/kernel.h>
15 #include <linux/init.h>
16 #include <linux/delay.h>
17 #include <linux/dma-mapping.h>
18 #include <linux/platform_device.h>
19
20 #include <asm/mach-ar71xx/ar71xx.h>
21 #include <asm/mach-ar71xx/platform.h>
22
23 #include "dev-usb.h"
24
25 /*
26  * OHCI (USB full speed host controller)
27  */
28 static struct resource ar71xx_ohci_resources[] = {
29         [0] = {
30                 .start  = AR71XX_OHCI_BASE,
31                 .end    = AR71XX_OHCI_BASE + AR71XX_OHCI_SIZE - 1,
32                 .flags  = IORESOURCE_MEM,
33         },
34         [1] = {
35                 .start  = AR71XX_MISC_IRQ_OHCI,
36                 .end    = AR71XX_MISC_IRQ_OHCI,
37                 .flags  = IORESOURCE_IRQ,
38         },
39 };
40
41 static struct resource ar7240_ohci_resources[] = {
42         [0] = {
43                 .start  = AR7240_OHCI_BASE,
44                 .end    = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1,
45                 .flags  = IORESOURCE_MEM,
46         },
47         [1] = {
48                 .start  = AR71XX_CPU_IRQ_USB,
49                 .end    = AR71XX_CPU_IRQ_USB,
50                 .flags  = IORESOURCE_IRQ,
51         },
52 };
53
54 static u64 ar71xx_ohci_dmamask = DMA_BIT_MASK(32);
55 static struct platform_device ar71xx_ohci_device = {
56         .name           = "ar71xx-ohci",
57         .id             = -1,
58         .resource       = ar71xx_ohci_resources,
59         .num_resources  = ARRAY_SIZE(ar71xx_ohci_resources),
60         .dev = {
61                 .dma_mask               = &ar71xx_ohci_dmamask,
62                 .coherent_dma_mask      = DMA_BIT_MASK(32),
63         },
64 };
65
66 /*
67  * EHCI (USB high/full speed host controller)
68  */
69 static struct resource ar71xx_ehci_resources[] = {
70         [0] = {
71                 .start  = AR71XX_EHCI_BASE,
72                 .end    = AR71XX_EHCI_BASE + AR71XX_EHCI_SIZE - 1,
73                 .flags  = IORESOURCE_MEM,
74         },
75         [1] = {
76                 .start  = AR71XX_CPU_IRQ_USB,
77                 .end    = AR71XX_CPU_IRQ_USB,
78                 .flags  = IORESOURCE_IRQ,
79         },
80 };
81
82 static u64 ar71xx_ehci_dmamask = DMA_BIT_MASK(32);
83 static struct ar71xx_ehci_platform_data ar71xx_ehci_data;
84
85 static struct platform_device ar71xx_ehci_device = {
86         .name           = "ar71xx-ehci",
87         .id             = -1,
88         .resource       = ar71xx_ehci_resources,
89         .num_resources  = ARRAY_SIZE(ar71xx_ehci_resources),
90         .dev = {
91                 .dma_mask               = &ar71xx_ehci_dmamask,
92                 .coherent_dma_mask      = DMA_BIT_MASK(32),
93                 .platform_data          = &ar71xx_ehci_data,
94         },
95 };
96
97 #define AR71XX_USB_RESET_MASK \
98         (RESET_MODULE_USB_HOST | RESET_MODULE_USB_PHY \
99         | RESET_MODULE_USB_OHCI_DLL)
100
101 #define AR7240_USB_RESET_MASK \
102         (RESET_MODULE_USB_HOST | RESET_MODULE_USB_OHCI_DLL_7240)
103
104 static void __init ar71xx_usb_setup(void)
105 {
106         ar71xx_device_stop(AR71XX_USB_RESET_MASK);
107         mdelay(1000);
108         ar71xx_device_start(AR71XX_USB_RESET_MASK);
109
110         /* Turning on the Buff and Desc swap bits */
111         ar71xx_usb_ctrl_wr(USB_CTRL_REG_CONFIG, 0xf0000);
112
113         /* WAR for HW bug. Here it adjusts the duration between two SOFS */
114         ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x20c00);
115
116         mdelay(900);
117
118         platform_device_register(&ar71xx_ohci_device);
119         platform_device_register(&ar71xx_ehci_device);
120 }
121
122 static void __init ar7240_usb_setup(void)
123 {
124         ar71xx_device_stop(AR7240_USB_RESET_MASK);
125         mdelay(1000);
126         ar71xx_device_start(AR7240_USB_RESET_MASK);
127
128         /* WAR for HW bug. Here it adjusts the duration between two SOFS */
129         ar71xx_usb_ctrl_wr(USB_CTRL_REG_FLADJ, 0x3);
130
131         ar71xx_ohci_device.resource = ar7240_ohci_resources;
132         ar71xx_ohci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources);
133         platform_device_register(&ar71xx_ohci_device);
134 }
135
136 static void __init ar7241_usb_setup(void)
137 {
138         ar71xx_device_start(AR724X_RESET_USBSUS_OVERRIDE);
139         mdelay(10);
140
141         ar71xx_device_start(AR724X_RESET_USB_HOST);
142         mdelay(10);
143
144         ar71xx_device_start(AR724X_RESET_USB_PHY);
145         mdelay(10);
146
147         ar71xx_ehci_data.is_ar91xx = 1;
148         ar71xx_ehci_device.resource = ar7240_ohci_resources;
149         ar71xx_ehci_device.num_resources = ARRAY_SIZE(ar7240_ohci_resources);
150         platform_device_register(&ar71xx_ehci_device);
151 }
152
153 static void __init ar91xx_usb_setup(void)
154 {
155         ar71xx_device_stop(RESET_MODULE_USBSUS_OVERRIDE);
156         mdelay(10);
157
158         ar71xx_device_start(RESET_MODULE_USB_HOST);
159         mdelay(10);
160
161         ar71xx_device_start(RESET_MODULE_USB_PHY);
162         mdelay(10);
163
164         ar71xx_ehci_data.is_ar91xx = 1;
165         platform_device_register(&ar71xx_ehci_device);
166 }
167
168 void __init ar71xx_add_device_usb(void)
169 {
170         switch (ar71xx_soc) {
171         case AR71XX_SOC_AR7240:
172                 ar7240_usb_setup();
173                 break;
174
175         case AR71XX_SOC_AR7241:
176         case AR71XX_SOC_AR7242:
177                 ar7241_usb_setup();
178                 break;
179
180         case AR71XX_SOC_AR7130:
181         case AR71XX_SOC_AR7141:
182         case AR71XX_SOC_AR7161:
183                 ar71xx_usb_setup();
184                 break;
185
186         case AR71XX_SOC_AR9130:
187         case AR71XX_SOC_AR9132:
188         case AR71XX_SOC_AR9330:
189         case AR71XX_SOC_AR9331:
190         case AR71XX_SOC_AR9341:
191         case AR71XX_SOC_AR9342:
192         case AR71XX_SOC_AR9344:
193                 ar91xx_usb_setup();
194                 break;
195
196         default:
197                 BUG();
198         }
199 }