aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/alchemy-common.c
diff options
context:
space:
mode:
authorManuel Lauss <manuel.lauss@googlemail.com>2011-11-01 15:03:30 -0400
committerRalf Baechle <ralf@linux-mips.org>2011-12-07 17:02:05 -0500
commit809f36c6f4a0568178c909ff1096ca83eae33f7d (patch)
tree6b99b1ac701c0bd581811c39e85856f3bcbda22d /drivers/usb/host/alchemy-common.c
parentfb469f084fdf1631e31d87270f5263c20a7f5cd6 (diff)
MIPS: Alchemy: Au1300 SoC support
Add basic support for the Au1300 variant(s): - New GPIO/Interrupt controller - DBDMA ids - USB setup - MMC support - enable various PSC drivers - detection code. Signed-off-by: Manuel Lauss <manuel.lauss@googlemail.com> To: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/2866/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers/usb/host/alchemy-common.c')
-rw-r--r--drivers/usb/host/alchemy-common.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/drivers/usb/host/alchemy-common.c b/drivers/usb/host/alchemy-common.c
index b4192c964d0d..936af8359fb2 100644
--- a/drivers/usb/host/alchemy-common.c
+++ b/drivers/usb/host/alchemy-common.c
@@ -52,9 +52,263 @@
52 USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \ 52 USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \
53 USBCFG_OME) 53 USBCFG_OME)
54 54
55/* Au1300 USB config registers */
56#define USB_DWC_CTRL1 0x00
57#define USB_DWC_CTRL2 0x04
58#define USB_VBUS_TIMER 0x10
59#define USB_SBUS_CTRL 0x14
60#define USB_MSR_ERR 0x18
61#define USB_DWC_CTRL3 0x1C
62#define USB_DWC_CTRL4 0x20
63#define USB_OTG_STATUS 0x28
64#define USB_DWC_CTRL5 0x2C
65#define USB_DWC_CTRL6 0x30
66#define USB_DWC_CTRL7 0x34
67#define USB_PHY_STATUS 0xC0
68#define USB_INT_STATUS 0xC4
69#define USB_INT_ENABLE 0xC8
70
71#define USB_DWC_CTRL1_OTGD 0x04 /* set to DISable OTG */
72#define USB_DWC_CTRL1_HSTRS 0x02 /* set to ENable EHCI */
73#define USB_DWC_CTRL1_DCRS 0x01 /* set to ENable UDC */
74
75#define USB_DWC_CTRL2_PHY1RS 0x04 /* set to enable PHY1 */
76#define USB_DWC_CTRL2_PHY0RS 0x02 /* set to enable PHY0 */
77#define USB_DWC_CTRL2_PHYRS 0x01 /* set to enable PHY */
78
79#define USB_DWC_CTRL3_OHCI1_CKEN (1 << 19)
80#define USB_DWC_CTRL3_OHCI0_CKEN (1 << 18)
81#define USB_DWC_CTRL3_EHCI0_CKEN (1 << 17)
82#define USB_DWC_CTRL3_OTG0_CKEN (1 << 16)
83
84#define USB_SBUS_CTRL_SBCA 0x04 /* coherent access */
85
86#define USB_INTEN_FORCE 0x20
87#define USB_INTEN_PHY 0x10
88#define USB_INTEN_UDC 0x08
89#define USB_INTEN_EHCI 0x04
90#define USB_INTEN_OHCI1 0x02
91#define USB_INTEN_OHCI0 0x01
55 92
56static DEFINE_SPINLOCK(alchemy_usb_lock); 93static DEFINE_SPINLOCK(alchemy_usb_lock);
57 94
95static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
96{
97 unsigned long r, s;
98
99 r = __raw_readl(base + USB_DWC_CTRL2);
100 s = __raw_readl(base + USB_DWC_CTRL3);
101
102 s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
103 USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
104
105 if (enable) {
106 /* simply enable all PHYs */
107 r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
108 USB_DWC_CTRL2_PHYRS;
109 __raw_writel(r, base + USB_DWC_CTRL2);
110 wmb();
111 } else if (!s) {
112 /* no USB block active, do disable all PHYs */
113 r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
114 USB_DWC_CTRL2_PHYRS);
115 __raw_writel(r, base + USB_DWC_CTRL2);
116 wmb();
117 }
118}
119
120static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
121{
122 unsigned long r;
123
124 if (enable) {
125 __raw_writel(1, base + USB_DWC_CTRL7); /* start OHCI clock */
126 wmb();
127
128 r = __raw_readl(base + USB_DWC_CTRL3); /* enable OHCI block */
129 r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
130 : USB_DWC_CTRL3_OHCI1_CKEN;
131 __raw_writel(r, base + USB_DWC_CTRL3);
132 wmb();
133
134 __au1300_usb_phyctl(base, enable); /* power up the PHYs */
135
136 r = __raw_readl(base + USB_INT_ENABLE);
137 r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
138 __raw_writel(r, base + USB_INT_ENABLE);
139 wmb();
140
141 /* reset the OHCI start clock bit */
142 __raw_writel(0, base + USB_DWC_CTRL7);
143 wmb();
144 } else {
145 r = __raw_readl(base + USB_INT_ENABLE);
146 r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
147 __raw_writel(r, base + USB_INT_ENABLE);
148 wmb();
149
150 r = __raw_readl(base + USB_DWC_CTRL3);
151 r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
152 : USB_DWC_CTRL3_OHCI1_CKEN);
153 __raw_writel(r, base + USB_DWC_CTRL3);
154 wmb();
155
156 __au1300_usb_phyctl(base, enable);
157 }
158}
159
160static inline void __au1300_ehci_control(void __iomem *base, int enable)
161{
162 unsigned long r;
163
164 if (enable) {
165 r = __raw_readl(base + USB_DWC_CTRL3);
166 r |= USB_DWC_CTRL3_EHCI0_CKEN;
167 __raw_writel(r, base + USB_DWC_CTRL3);
168 wmb();
169
170 r = __raw_readl(base + USB_DWC_CTRL1);
171 r |= USB_DWC_CTRL1_HSTRS;
172 __raw_writel(r, base + USB_DWC_CTRL1);
173 wmb();
174
175 __au1300_usb_phyctl(base, enable);
176
177 r = __raw_readl(base + USB_INT_ENABLE);
178 r |= USB_INTEN_EHCI;
179 __raw_writel(r, base + USB_INT_ENABLE);
180 wmb();
181 } else {
182 r = __raw_readl(base + USB_INT_ENABLE);
183 r &= ~USB_INTEN_EHCI;
184 __raw_writel(r, base + USB_INT_ENABLE);
185 wmb();
186
187 r = __raw_readl(base + USB_DWC_CTRL1);
188 r &= ~USB_DWC_CTRL1_HSTRS;
189 __raw_writel(r, base + USB_DWC_CTRL1);
190 wmb();
191
192 r = __raw_readl(base + USB_DWC_CTRL3);
193 r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
194 __raw_writel(r, base + USB_DWC_CTRL3);
195 wmb();
196
197 __au1300_usb_phyctl(base, enable);
198 }
199}
200
201static inline void __au1300_udc_control(void __iomem *base, int enable)
202{
203 unsigned long r;
204
205 if (enable) {
206 r = __raw_readl(base + USB_DWC_CTRL1);
207 r |= USB_DWC_CTRL1_DCRS;
208 __raw_writel(r, base + USB_DWC_CTRL1);
209 wmb();
210
211 __au1300_usb_phyctl(base, enable);
212
213 r = __raw_readl(base + USB_INT_ENABLE);
214 r |= USB_INTEN_UDC;
215 __raw_writel(r, base + USB_INT_ENABLE);
216 wmb();
217 } else {
218 r = __raw_readl(base + USB_INT_ENABLE);
219 r &= ~USB_INTEN_UDC;
220 __raw_writel(r, base + USB_INT_ENABLE);
221 wmb();
222
223 r = __raw_readl(base + USB_DWC_CTRL1);
224 r &= ~USB_DWC_CTRL1_DCRS;
225 __raw_writel(r, base + USB_DWC_CTRL1);
226 wmb();
227
228 __au1300_usb_phyctl(base, enable);
229 }
230}
231
232static inline void __au1300_otg_control(void __iomem *base, int enable)
233{
234 unsigned long r;
235 if (enable) {
236 r = __raw_readl(base + USB_DWC_CTRL3);
237 r |= USB_DWC_CTRL3_OTG0_CKEN;
238 __raw_writel(r, base + USB_DWC_CTRL3);
239 wmb();
240
241 r = __raw_readl(base + USB_DWC_CTRL1);
242 r &= ~USB_DWC_CTRL1_OTGD;
243 __raw_writel(r, base + USB_DWC_CTRL1);
244 wmb();
245
246 __au1300_usb_phyctl(base, enable);
247 } else {
248 r = __raw_readl(base + USB_DWC_CTRL1);
249 r |= USB_DWC_CTRL1_OTGD;
250 __raw_writel(r, base + USB_DWC_CTRL1);
251 wmb();
252
253 r = __raw_readl(base + USB_DWC_CTRL3);
254 r &= ~USB_DWC_CTRL3_OTG0_CKEN;
255 __raw_writel(r, base + USB_DWC_CTRL3);
256 wmb();
257
258 __au1300_usb_phyctl(base, enable);
259 }
260}
261
262static inline int au1300_usb_control(int block, int enable)
263{
264 void __iomem *base =
265 (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
266 int ret = 0;
267
268 switch (block) {
269 case ALCHEMY_USB_OHCI0:
270 __au1300_ohci_control(base, enable, 0);
271 break;
272 case ALCHEMY_USB_OHCI1:
273 __au1300_ohci_control(base, enable, 1);
274 break;
275 case ALCHEMY_USB_EHCI0:
276 __au1300_ehci_control(base, enable);
277 break;
278 case ALCHEMY_USB_UDC0:
279 __au1300_udc_control(base, enable);
280 break;
281 case ALCHEMY_USB_OTG0:
282 __au1300_otg_control(base, enable);
283 break;
284 default:
285 ret = -ENODEV;
286 }
287 return ret;
288}
289
290static inline void au1300_usb_init(void)
291{
292 void __iomem *base =
293 (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
294
295 /* set some sane defaults. Note: we don't fiddle with DWC_CTRL4
296 * here at all: Port 2 routing (EHCI or UDC) must be set either
297 * by boot firmware or platform init code; I can't autodetect
298 * a sane setting.
299 */
300 __raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
301 wmb();
302 __raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
303 wmb();
304 __raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
305 wmb();
306 __raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
307 wmb();
308 /* set coherent access bit */
309 __raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
310 wmb();
311}
58 312
59static inline void __au1200_ohci_control(void __iomem *base, int enable) 313static inline void __au1200_ohci_control(void __iomem *base, int enable)
60{ 314{
@@ -233,6 +487,9 @@ int alchemy_usb_control(int block, int enable)
233 case ALCHEMY_CPU_AU1200: 487 case ALCHEMY_CPU_AU1200:
234 ret = au1200_usb_control(block, enable); 488 ret = au1200_usb_control(block, enable);
235 break; 489 break;
490 case ALCHEMY_CPU_AU1300:
491 ret = au1300_usb_control(block, enable);
492 break;
236 default: 493 default:
237 ret = -ENODEV; 494 ret = -ENODEV;
238 } 495 }
@@ -281,6 +538,20 @@ static void au1200_usb_pm(int susp)
281 } 538 }
282} 539}
283 540
541static void au1300_usb_pm(int susp)
542{
543 void __iomem *base =
544 (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
545 /* remember Port2 routing */
546 if (susp) {
547 alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
548 } else {
549 au1300_usb_init();
550 __raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
551 wmb();
552 }
553}
554
284static void alchemy_usb_pm(int susp) 555static void alchemy_usb_pm(int susp)
285{ 556{
286 switch (alchemy_get_cputype()) { 557 switch (alchemy_get_cputype()) {
@@ -295,6 +566,9 @@ static void alchemy_usb_pm(int susp)
295 case ALCHEMY_CPU_AU1200: 566 case ALCHEMY_CPU_AU1200:
296 au1200_usb_pm(susp); 567 au1200_usb_pm(susp);
297 break; 568 break;
569 case ALCHEMY_CPU_AU1300:
570 au1300_usb_pm(susp);
571 break;
298 } 572 }
299} 573}
300 574
@@ -328,6 +602,9 @@ static int __init alchemy_usb_init(void)
328 case ALCHEMY_CPU_AU1200: 602 case ALCHEMY_CPU_AU1200:
329 au1200_usb_init(); 603 au1200_usb_init();
330 break; 604 break;
605 case ALCHEMY_CPU_AU1300:
606 au1300_usb_init();
607 break;
331 } 608 }
332 609
333 register_syscore_ops(&alchemy_usb_pm_ops); 610 register_syscore_ops(&alchemy_usb_pm_ops);