xref: /openbmc/linux/arch/mips/alchemy/common/usb.c (revision 457c8996)
1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2216d0fdeSFlorian Fainelli /*
3216d0fdeSFlorian Fainelli  * USB block power/access management abstraction.
4216d0fdeSFlorian Fainelli  *
5216d0fdeSFlorian Fainelli  * Au1000+: The OHCI block control register is at the far end of the OHCI memory
6216d0fdeSFlorian Fainelli  *	    area. Au1550 has OHCI on different base address. No need to handle
7216d0fdeSFlorian Fainelli  *	    UDC here.
8216d0fdeSFlorian Fainelli  * Au1200:  one register to control access and clocks to O/EHCI, UDC and OTG
9216d0fdeSFlorian Fainelli  *	    as well as the PHY for EHCI and UDC.
10216d0fdeSFlorian Fainelli  *
11216d0fdeSFlorian Fainelli  */
12216d0fdeSFlorian Fainelli 
133feae784SManuel Lauss #include <linux/clk.h>
1426dd3e4fSPaul Gortmaker #include <linux/export.h>
15216d0fdeSFlorian Fainelli #include <linux/init.h>
16216d0fdeSFlorian Fainelli #include <linux/io.h>
17216d0fdeSFlorian Fainelli #include <linux/spinlock.h>
18216d0fdeSFlorian Fainelli #include <linux/syscore_ops.h>
198ff374b9SMaciej W. Rozycki #include <asm/cpu.h>
20216d0fdeSFlorian Fainelli #include <asm/mach-au1x00/au1000.h>
21216d0fdeSFlorian Fainelli 
22216d0fdeSFlorian Fainelli /* control register offsets */
23216d0fdeSFlorian Fainelli #define AU1000_OHCICFG	0x7fffc
24216d0fdeSFlorian Fainelli #define AU1550_OHCICFG	0x07ffc
25216d0fdeSFlorian Fainelli #define AU1200_USBCFG	0x04
26216d0fdeSFlorian Fainelli 
27216d0fdeSFlorian Fainelli /* Au1000 USB block config bits */
28216d0fdeSFlorian Fainelli #define USBHEN_RD	(1 << 4)		/* OHCI reset-done indicator */
29216d0fdeSFlorian Fainelli #define USBHEN_CE	(1 << 3)		/* OHCI block clock enable */
30216d0fdeSFlorian Fainelli #define USBHEN_E	(1 << 2)		/* OHCI block enable */
31216d0fdeSFlorian Fainelli #define USBHEN_C	(1 << 1)		/* OHCI block coherency bit */
32216d0fdeSFlorian Fainelli #define USBHEN_BE	(1 << 0)		/* OHCI Big-Endian */
33216d0fdeSFlorian Fainelli 
34216d0fdeSFlorian Fainelli /* Au1200 USB config bits */
35216d0fdeSFlorian Fainelli #define USBCFG_PFEN	(1 << 31)		/* prefetch enable (undoc) */
36216d0fdeSFlorian Fainelli #define USBCFG_RDCOMB	(1 << 30)		/* read combining (undoc) */
37216d0fdeSFlorian Fainelli #define USBCFG_UNKNOWN	(5 << 20)		/* unknown, leave this way */
38216d0fdeSFlorian Fainelli #define USBCFG_SSD	(1 << 23)		/* serial short detect en */
39216d0fdeSFlorian Fainelli #define USBCFG_PPE	(1 << 19)		/* HS PHY PLL */
40216d0fdeSFlorian Fainelli #define USBCFG_UCE	(1 << 18)		/* UDC clock enable */
41216d0fdeSFlorian Fainelli #define USBCFG_ECE	(1 << 17)		/* EHCI clock enable */
42216d0fdeSFlorian Fainelli #define USBCFG_OCE	(1 << 16)		/* OHCI clock enable */
43216d0fdeSFlorian Fainelli #define USBCFG_FLA(x)	(((x) & 0x3f) << 8)
44216d0fdeSFlorian Fainelli #define USBCFG_UCAM	(1 << 7)		/* coherent access (undoc) */
45216d0fdeSFlorian Fainelli #define USBCFG_GME	(1 << 6)		/* OTG mem access */
46216d0fdeSFlorian Fainelli #define USBCFG_DBE	(1 << 5)		/* UDC busmaster enable */
47216d0fdeSFlorian Fainelli #define USBCFG_DME	(1 << 4)		/* UDC mem enable */
48216d0fdeSFlorian Fainelli #define USBCFG_EBE	(1 << 3)		/* EHCI busmaster enable */
49216d0fdeSFlorian Fainelli #define USBCFG_EME	(1 << 2)		/* EHCI mem enable */
50216d0fdeSFlorian Fainelli #define USBCFG_OBE	(1 << 1)		/* OHCI busmaster enable */
51216d0fdeSFlorian Fainelli #define USBCFG_OME	(1 << 0)		/* OHCI mem enable */
52216d0fdeSFlorian Fainelli #define USBCFG_INIT_AU1200	(USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\
53216d0fdeSFlorian Fainelli 				 USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \
54216d0fdeSFlorian Fainelli 				 USBCFG_GME | USBCFG_DBE | USBCFG_DME |	       \
55216d0fdeSFlorian Fainelli 				 USBCFG_EBE | USBCFG_EME | USBCFG_OBE |	       \
56216d0fdeSFlorian Fainelli 				 USBCFG_OME)
57216d0fdeSFlorian Fainelli 
58216d0fdeSFlorian Fainelli /* Au1300 USB config registers */
59216d0fdeSFlorian Fainelli #define USB_DWC_CTRL1		0x00
60216d0fdeSFlorian Fainelli #define USB_DWC_CTRL2		0x04
61216d0fdeSFlorian Fainelli #define USB_VBUS_TIMER		0x10
62216d0fdeSFlorian Fainelli #define USB_SBUS_CTRL		0x14
63216d0fdeSFlorian Fainelli #define USB_MSR_ERR		0x18
64216d0fdeSFlorian Fainelli #define USB_DWC_CTRL3		0x1C
65216d0fdeSFlorian Fainelli #define USB_DWC_CTRL4		0x20
66216d0fdeSFlorian Fainelli #define USB_OTG_STATUS		0x28
67216d0fdeSFlorian Fainelli #define USB_DWC_CTRL5		0x2C
68216d0fdeSFlorian Fainelli #define USB_DWC_CTRL6		0x30
69216d0fdeSFlorian Fainelli #define USB_DWC_CTRL7		0x34
70216d0fdeSFlorian Fainelli #define USB_PHY_STATUS		0xC0
71216d0fdeSFlorian Fainelli #define USB_INT_STATUS		0xC4
72216d0fdeSFlorian Fainelli #define USB_INT_ENABLE		0xC8
73216d0fdeSFlorian Fainelli 
74216d0fdeSFlorian Fainelli #define USB_DWC_CTRL1_OTGD	0x04 /* set to DISable OTG */
75216d0fdeSFlorian Fainelli #define USB_DWC_CTRL1_HSTRS	0x02 /* set to ENable EHCI */
76216d0fdeSFlorian Fainelli #define USB_DWC_CTRL1_DCRS	0x01 /* set to ENable UDC */
77216d0fdeSFlorian Fainelli 
78216d0fdeSFlorian Fainelli #define USB_DWC_CTRL2_PHY1RS	0x04 /* set to enable PHY1 */
79216d0fdeSFlorian Fainelli #define USB_DWC_CTRL2_PHY0RS	0x02 /* set to enable PHY0 */
80216d0fdeSFlorian Fainelli #define USB_DWC_CTRL2_PHYRS	0x01 /* set to enable PHY */
81216d0fdeSFlorian Fainelli 
82216d0fdeSFlorian Fainelli #define USB_DWC_CTRL3_OHCI1_CKEN	(1 << 19)
83216d0fdeSFlorian Fainelli #define USB_DWC_CTRL3_OHCI0_CKEN	(1 << 18)
84216d0fdeSFlorian Fainelli #define USB_DWC_CTRL3_EHCI0_CKEN	(1 << 17)
85216d0fdeSFlorian Fainelli #define USB_DWC_CTRL3_OTG0_CKEN		(1 << 16)
86216d0fdeSFlorian Fainelli 
87216d0fdeSFlorian Fainelli #define USB_SBUS_CTRL_SBCA		0x04 /* coherent access */
88216d0fdeSFlorian Fainelli 
89216d0fdeSFlorian Fainelli #define USB_INTEN_FORCE			0x20
90216d0fdeSFlorian Fainelli #define USB_INTEN_PHY			0x10
91216d0fdeSFlorian Fainelli #define USB_INTEN_UDC			0x08
92216d0fdeSFlorian Fainelli #define USB_INTEN_EHCI			0x04
93216d0fdeSFlorian Fainelli #define USB_INTEN_OHCI1			0x02
94216d0fdeSFlorian Fainelli #define USB_INTEN_OHCI0			0x01
95216d0fdeSFlorian Fainelli 
96216d0fdeSFlorian Fainelli static DEFINE_SPINLOCK(alchemy_usb_lock);
97216d0fdeSFlorian Fainelli 
__au1300_usb_phyctl(void __iomem * base,int enable)98216d0fdeSFlorian Fainelli static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
99216d0fdeSFlorian Fainelli {
100216d0fdeSFlorian Fainelli 	unsigned long r, s;
101216d0fdeSFlorian Fainelli 
102216d0fdeSFlorian Fainelli 	r = __raw_readl(base + USB_DWC_CTRL2);
103216d0fdeSFlorian Fainelli 	s = __raw_readl(base + USB_DWC_CTRL3);
104216d0fdeSFlorian Fainelli 
105216d0fdeSFlorian Fainelli 	s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
106216d0fdeSFlorian Fainelli 		USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
107216d0fdeSFlorian Fainelli 
108216d0fdeSFlorian Fainelli 	if (enable) {
109216d0fdeSFlorian Fainelli 		/* simply enable all PHYs */
110216d0fdeSFlorian Fainelli 		r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
111216d0fdeSFlorian Fainelli 		     USB_DWC_CTRL2_PHYRS;
112216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL2);
113216d0fdeSFlorian Fainelli 		wmb();
114216d0fdeSFlorian Fainelli 	} else if (!s) {
115216d0fdeSFlorian Fainelli 		/* no USB block active, do disable all PHYs */
116216d0fdeSFlorian Fainelli 		r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
117216d0fdeSFlorian Fainelli 		       USB_DWC_CTRL2_PHYRS);
118216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL2);
119216d0fdeSFlorian Fainelli 		wmb();
120216d0fdeSFlorian Fainelli 	}
121216d0fdeSFlorian Fainelli }
122216d0fdeSFlorian Fainelli 
__au1300_ohci_control(void __iomem * base,int enable,int id)123216d0fdeSFlorian Fainelli static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
124216d0fdeSFlorian Fainelli {
125216d0fdeSFlorian Fainelli 	unsigned long r;
126216d0fdeSFlorian Fainelli 
127216d0fdeSFlorian Fainelli 	if (enable) {
128216d0fdeSFlorian Fainelli 		__raw_writel(1, base + USB_DWC_CTRL7);	/* start OHCI clock */
129216d0fdeSFlorian Fainelli 		wmb();
130216d0fdeSFlorian Fainelli 
131216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL3);	/* enable OHCI block */
132216d0fdeSFlorian Fainelli 		r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
133216d0fdeSFlorian Fainelli 			       : USB_DWC_CTRL3_OHCI1_CKEN;
134216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL3);
135216d0fdeSFlorian Fainelli 		wmb();
136216d0fdeSFlorian Fainelli 
137216d0fdeSFlorian Fainelli 		__au1300_usb_phyctl(base, enable);	/* power up the PHYs */
138216d0fdeSFlorian Fainelli 
139216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_INT_ENABLE);
140216d0fdeSFlorian Fainelli 		r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
141216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_INT_ENABLE);
142216d0fdeSFlorian Fainelli 		wmb();
143216d0fdeSFlorian Fainelli 
144216d0fdeSFlorian Fainelli 		/* reset the OHCI start clock bit */
145216d0fdeSFlorian Fainelli 		__raw_writel(0, base + USB_DWC_CTRL7);
146216d0fdeSFlorian Fainelli 		wmb();
147216d0fdeSFlorian Fainelli 	} else {
148216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_INT_ENABLE);
149216d0fdeSFlorian Fainelli 		r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
150216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_INT_ENABLE);
151216d0fdeSFlorian Fainelli 		wmb();
152216d0fdeSFlorian Fainelli 
153216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL3);
154216d0fdeSFlorian Fainelli 		r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
155216d0fdeSFlorian Fainelli 				 : USB_DWC_CTRL3_OHCI1_CKEN);
156216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL3);
157216d0fdeSFlorian Fainelli 		wmb();
158216d0fdeSFlorian Fainelli 
159216d0fdeSFlorian Fainelli 		__au1300_usb_phyctl(base, enable);
160216d0fdeSFlorian Fainelli 	}
161216d0fdeSFlorian Fainelli }
162216d0fdeSFlorian Fainelli 
__au1300_ehci_control(void __iomem * base,int enable)163216d0fdeSFlorian Fainelli static inline void __au1300_ehci_control(void __iomem *base, int enable)
164216d0fdeSFlorian Fainelli {
165216d0fdeSFlorian Fainelli 	unsigned long r;
166216d0fdeSFlorian Fainelli 
167216d0fdeSFlorian Fainelli 	if (enable) {
168216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL3);
169216d0fdeSFlorian Fainelli 		r |= USB_DWC_CTRL3_EHCI0_CKEN;
170216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL3);
171216d0fdeSFlorian Fainelli 		wmb();
172216d0fdeSFlorian Fainelli 
173216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL1);
174216d0fdeSFlorian Fainelli 		r |= USB_DWC_CTRL1_HSTRS;
175216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL1);
176216d0fdeSFlorian Fainelli 		wmb();
177216d0fdeSFlorian Fainelli 
178216d0fdeSFlorian Fainelli 		__au1300_usb_phyctl(base, enable);
179216d0fdeSFlorian Fainelli 
180216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_INT_ENABLE);
181216d0fdeSFlorian Fainelli 		r |= USB_INTEN_EHCI;
182216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_INT_ENABLE);
183216d0fdeSFlorian Fainelli 		wmb();
184216d0fdeSFlorian Fainelli 	} else {
185216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_INT_ENABLE);
186216d0fdeSFlorian Fainelli 		r &= ~USB_INTEN_EHCI;
187216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_INT_ENABLE);
188216d0fdeSFlorian Fainelli 		wmb();
189216d0fdeSFlorian Fainelli 
190216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL1);
191216d0fdeSFlorian Fainelli 		r &= ~USB_DWC_CTRL1_HSTRS;
192216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL1);
193216d0fdeSFlorian Fainelli 		wmb();
194216d0fdeSFlorian Fainelli 
195216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL3);
196216d0fdeSFlorian Fainelli 		r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
197216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL3);
198216d0fdeSFlorian Fainelli 		wmb();
199216d0fdeSFlorian Fainelli 
200216d0fdeSFlorian Fainelli 		__au1300_usb_phyctl(base, enable);
201216d0fdeSFlorian Fainelli 	}
202216d0fdeSFlorian Fainelli }
203216d0fdeSFlorian Fainelli 
__au1300_udc_control(void __iomem * base,int enable)204216d0fdeSFlorian Fainelli static inline void __au1300_udc_control(void __iomem *base, int enable)
205216d0fdeSFlorian Fainelli {
206216d0fdeSFlorian Fainelli 	unsigned long r;
207216d0fdeSFlorian Fainelli 
208216d0fdeSFlorian Fainelli 	if (enable) {
209216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL1);
210216d0fdeSFlorian Fainelli 		r |= USB_DWC_CTRL1_DCRS;
211216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL1);
212216d0fdeSFlorian Fainelli 		wmb();
213216d0fdeSFlorian Fainelli 
214216d0fdeSFlorian Fainelli 		__au1300_usb_phyctl(base, enable);
215216d0fdeSFlorian Fainelli 
216216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_INT_ENABLE);
217216d0fdeSFlorian Fainelli 		r |= USB_INTEN_UDC;
218216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_INT_ENABLE);
219216d0fdeSFlorian Fainelli 		wmb();
220216d0fdeSFlorian Fainelli 	} else {
221216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_INT_ENABLE);
222216d0fdeSFlorian Fainelli 		r &= ~USB_INTEN_UDC;
223216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_INT_ENABLE);
224216d0fdeSFlorian Fainelli 		wmb();
225216d0fdeSFlorian Fainelli 
226216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL1);
227216d0fdeSFlorian Fainelli 		r &= ~USB_DWC_CTRL1_DCRS;
228216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL1);
229216d0fdeSFlorian Fainelli 		wmb();
230216d0fdeSFlorian Fainelli 
231216d0fdeSFlorian Fainelli 		__au1300_usb_phyctl(base, enable);
232216d0fdeSFlorian Fainelli 	}
233216d0fdeSFlorian Fainelli }
234216d0fdeSFlorian Fainelli 
__au1300_otg_control(void __iomem * base,int enable)235216d0fdeSFlorian Fainelli static inline void __au1300_otg_control(void __iomem *base, int enable)
236216d0fdeSFlorian Fainelli {
237216d0fdeSFlorian Fainelli 	unsigned long r;
238216d0fdeSFlorian Fainelli 	if (enable) {
239216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL3);
240216d0fdeSFlorian Fainelli 		r |= USB_DWC_CTRL3_OTG0_CKEN;
241216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL3);
242216d0fdeSFlorian Fainelli 		wmb();
243216d0fdeSFlorian Fainelli 
244216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL1);
245216d0fdeSFlorian Fainelli 		r &= ~USB_DWC_CTRL1_OTGD;
246216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL1);
247216d0fdeSFlorian Fainelli 		wmb();
248216d0fdeSFlorian Fainelli 
249216d0fdeSFlorian Fainelli 		__au1300_usb_phyctl(base, enable);
250216d0fdeSFlorian Fainelli 	} else {
251216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL1);
252216d0fdeSFlorian Fainelli 		r |= USB_DWC_CTRL1_OTGD;
253216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL1);
254216d0fdeSFlorian Fainelli 		wmb();
255216d0fdeSFlorian Fainelli 
256216d0fdeSFlorian Fainelli 		r = __raw_readl(base + USB_DWC_CTRL3);
257216d0fdeSFlorian Fainelli 		r &= ~USB_DWC_CTRL3_OTG0_CKEN;
258216d0fdeSFlorian Fainelli 		__raw_writel(r, base + USB_DWC_CTRL3);
259216d0fdeSFlorian Fainelli 		wmb();
260216d0fdeSFlorian Fainelli 
261216d0fdeSFlorian Fainelli 		__au1300_usb_phyctl(base, enable);
262216d0fdeSFlorian Fainelli 	}
263216d0fdeSFlorian Fainelli }
264216d0fdeSFlorian Fainelli 
au1300_usb_control(int block,int enable)265216d0fdeSFlorian Fainelli static inline int au1300_usb_control(int block, int enable)
266216d0fdeSFlorian Fainelli {
267216d0fdeSFlorian Fainelli 	void __iomem *base =
268216d0fdeSFlorian Fainelli 		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
269216d0fdeSFlorian Fainelli 	int ret = 0;
270216d0fdeSFlorian Fainelli 
271216d0fdeSFlorian Fainelli 	switch (block) {
272216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_OHCI0:
273216d0fdeSFlorian Fainelli 		__au1300_ohci_control(base, enable, 0);
274216d0fdeSFlorian Fainelli 		break;
275216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_OHCI1:
276216d0fdeSFlorian Fainelli 		__au1300_ohci_control(base, enable, 1);
277216d0fdeSFlorian Fainelli 		break;
278216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_EHCI0:
279216d0fdeSFlorian Fainelli 		__au1300_ehci_control(base, enable);
280216d0fdeSFlorian Fainelli 		break;
281216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_UDC0:
282216d0fdeSFlorian Fainelli 		__au1300_udc_control(base, enable);
283216d0fdeSFlorian Fainelli 		break;
284216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_OTG0:
285216d0fdeSFlorian Fainelli 		__au1300_otg_control(base, enable);
286216d0fdeSFlorian Fainelli 		break;
287216d0fdeSFlorian Fainelli 	default:
288216d0fdeSFlorian Fainelli 		ret = -ENODEV;
289216d0fdeSFlorian Fainelli 	}
290216d0fdeSFlorian Fainelli 	return ret;
291216d0fdeSFlorian Fainelli }
292216d0fdeSFlorian Fainelli 
au1300_usb_init(void)293216d0fdeSFlorian Fainelli static inline void au1300_usb_init(void)
294216d0fdeSFlorian Fainelli {
295216d0fdeSFlorian Fainelli 	void __iomem *base =
296216d0fdeSFlorian Fainelli 		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
297216d0fdeSFlorian Fainelli 
298216d0fdeSFlorian Fainelli 	/* set some sane defaults.  Note: we don't fiddle with DWC_CTRL4
299216d0fdeSFlorian Fainelli 	 * here at all: Port 2 routing (EHCI or UDC) must be set either
300216d0fdeSFlorian Fainelli 	 * by boot firmware or platform init code; I can't autodetect
301216d0fdeSFlorian Fainelli 	 * a sane setting.
302216d0fdeSFlorian Fainelli 	 */
303216d0fdeSFlorian Fainelli 	__raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
304216d0fdeSFlorian Fainelli 	wmb();
305216d0fdeSFlorian Fainelli 	__raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
306216d0fdeSFlorian Fainelli 	wmb();
307216d0fdeSFlorian Fainelli 	__raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
308216d0fdeSFlorian Fainelli 	wmb();
309216d0fdeSFlorian Fainelli 	__raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
310216d0fdeSFlorian Fainelli 	wmb();
311216d0fdeSFlorian Fainelli 	/* set coherent access bit */
312216d0fdeSFlorian Fainelli 	__raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
313216d0fdeSFlorian Fainelli 	wmb();
314216d0fdeSFlorian Fainelli }
315216d0fdeSFlorian Fainelli 
__au1200_ohci_control(void __iomem * base,int enable)316216d0fdeSFlorian Fainelli static inline void __au1200_ohci_control(void __iomem *base, int enable)
317216d0fdeSFlorian Fainelli {
318216d0fdeSFlorian Fainelli 	unsigned long r = __raw_readl(base + AU1200_USBCFG);
319216d0fdeSFlorian Fainelli 	if (enable) {
320216d0fdeSFlorian Fainelli 		__raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG);
321216d0fdeSFlorian Fainelli 		wmb();
322216d0fdeSFlorian Fainelli 		udelay(2000);
323216d0fdeSFlorian Fainelli 	} else {
324216d0fdeSFlorian Fainelli 		__raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG);
325216d0fdeSFlorian Fainelli 		wmb();
326216d0fdeSFlorian Fainelli 		udelay(1000);
327216d0fdeSFlorian Fainelli 	}
328216d0fdeSFlorian Fainelli }
329216d0fdeSFlorian Fainelli 
__au1200_ehci_control(void __iomem * base,int enable)330216d0fdeSFlorian Fainelli static inline void __au1200_ehci_control(void __iomem *base, int enable)
331216d0fdeSFlorian Fainelli {
332216d0fdeSFlorian Fainelli 	unsigned long r = __raw_readl(base + AU1200_USBCFG);
333216d0fdeSFlorian Fainelli 	if (enable) {
334216d0fdeSFlorian Fainelli 		__raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG);
335216d0fdeSFlorian Fainelli 		wmb();
336216d0fdeSFlorian Fainelli 		udelay(1000);
337216d0fdeSFlorian Fainelli 	} else {
338216d0fdeSFlorian Fainelli 		if (!(r & USBCFG_UCE))		/* UDC also off? */
339216d0fdeSFlorian Fainelli 			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */
340216d0fdeSFlorian Fainelli 		__raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG);
341216d0fdeSFlorian Fainelli 		wmb();
342216d0fdeSFlorian Fainelli 		udelay(1000);
343216d0fdeSFlorian Fainelli 	}
344216d0fdeSFlorian Fainelli }
345216d0fdeSFlorian Fainelli 
__au1200_udc_control(void __iomem * base,int enable)346216d0fdeSFlorian Fainelli static inline void __au1200_udc_control(void __iomem *base, int enable)
347216d0fdeSFlorian Fainelli {
348216d0fdeSFlorian Fainelli 	unsigned long r = __raw_readl(base + AU1200_USBCFG);
349216d0fdeSFlorian Fainelli 	if (enable) {
350216d0fdeSFlorian Fainelli 		__raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG);
351216d0fdeSFlorian Fainelli 		wmb();
352216d0fdeSFlorian Fainelli 	} else {
353216d0fdeSFlorian Fainelli 		if (!(r & USBCFG_ECE))		/* EHCI also off? */
354216d0fdeSFlorian Fainelli 			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */
355216d0fdeSFlorian Fainelli 		__raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG);
356216d0fdeSFlorian Fainelli 		wmb();
357216d0fdeSFlorian Fainelli 	}
358216d0fdeSFlorian Fainelli }
359216d0fdeSFlorian Fainelli 
au1200_usb_control(int block,int enable)360216d0fdeSFlorian Fainelli static inline int au1200_usb_control(int block, int enable)
361216d0fdeSFlorian Fainelli {
362216d0fdeSFlorian Fainelli 	void __iomem *base =
363216d0fdeSFlorian Fainelli 			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
364216d0fdeSFlorian Fainelli 
365216d0fdeSFlorian Fainelli 	switch (block) {
366216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_OHCI0:
367216d0fdeSFlorian Fainelli 		__au1200_ohci_control(base, enable);
368216d0fdeSFlorian Fainelli 		break;
369216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_UDC0:
370216d0fdeSFlorian Fainelli 		__au1200_udc_control(base, enable);
371216d0fdeSFlorian Fainelli 		break;
372216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_EHCI0:
373216d0fdeSFlorian Fainelli 		__au1200_ehci_control(base, enable);
374216d0fdeSFlorian Fainelli 		break;
375216d0fdeSFlorian Fainelli 	default:
376739cec8fSManuel Lauss 		return -ENODEV;
377216d0fdeSFlorian Fainelli 	}
378739cec8fSManuel Lauss 	return 0;
379216d0fdeSFlorian Fainelli }
380216d0fdeSFlorian Fainelli 
381216d0fdeSFlorian Fainelli 
382216d0fdeSFlorian Fainelli /* initialize USB block(s) to a known working state */
au1200_usb_init(void)383216d0fdeSFlorian Fainelli static inline void au1200_usb_init(void)
384216d0fdeSFlorian Fainelli {
385216d0fdeSFlorian Fainelli 	void __iomem *base =
386216d0fdeSFlorian Fainelli 			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
387216d0fdeSFlorian Fainelli 	__raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG);
388216d0fdeSFlorian Fainelli 	wmb();
389216d0fdeSFlorian Fainelli 	udelay(1000);
390216d0fdeSFlorian Fainelli }
391216d0fdeSFlorian Fainelli 
au1000_usb_init(unsigned long rb,int reg)3923feae784SManuel Lauss static inline int au1000_usb_init(unsigned long rb, int reg)
393216d0fdeSFlorian Fainelli {
394216d0fdeSFlorian Fainelli 	void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
395216d0fdeSFlorian Fainelli 	unsigned long r = __raw_readl(base);
3963feae784SManuel Lauss 	struct clk *c;
3973feae784SManuel Lauss 
3983feae784SManuel Lauss 	/* 48MHz check. Don't init if no one can provide it */
3993feae784SManuel Lauss 	c = clk_get(NULL, "usbh_clk");
4003feae784SManuel Lauss 	if (IS_ERR(c))
4013feae784SManuel Lauss 		return -ENODEV;
4023feae784SManuel Lauss 	if (clk_round_rate(c, 48000000) != 48000000) {
4033feae784SManuel Lauss 		clk_put(c);
4043feae784SManuel Lauss 		return -ENODEV;
4053feae784SManuel Lauss 	}
4063feae784SManuel Lauss 	if (clk_set_rate(c, 48000000)) {
4073feae784SManuel Lauss 		clk_put(c);
4083feae784SManuel Lauss 		return -ENODEV;
4093feae784SManuel Lauss 	}
4103feae784SManuel Lauss 	clk_put(c);
411216d0fdeSFlorian Fainelli 
412216d0fdeSFlorian Fainelli #if defined(__BIG_ENDIAN)
413216d0fdeSFlorian Fainelli 	r |= USBHEN_BE;
414216d0fdeSFlorian Fainelli #endif
415216d0fdeSFlorian Fainelli 	r |= USBHEN_C;
416216d0fdeSFlorian Fainelli 
417216d0fdeSFlorian Fainelli 	__raw_writel(r, base);
418216d0fdeSFlorian Fainelli 	wmb();
419216d0fdeSFlorian Fainelli 	udelay(1000);
4203feae784SManuel Lauss 
4213feae784SManuel Lauss 	return 0;
422216d0fdeSFlorian Fainelli }
423216d0fdeSFlorian Fainelli 
424216d0fdeSFlorian Fainelli 
__au1xx0_ohci_control(int enable,unsigned long rb,int creg)425216d0fdeSFlorian Fainelli static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
426216d0fdeSFlorian Fainelli {
427216d0fdeSFlorian Fainelli 	void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
428216d0fdeSFlorian Fainelli 	unsigned long r = __raw_readl(base + creg);
4293feae784SManuel Lauss 	struct clk *c = clk_get(NULL, "usbh_clk");
4303feae784SManuel Lauss 
4313feae784SManuel Lauss 	if (IS_ERR(c))
4323feae784SManuel Lauss 		return;
433216d0fdeSFlorian Fainelli 
434216d0fdeSFlorian Fainelli 	if (enable) {
4353feae784SManuel Lauss 		if (clk_prepare_enable(c))
4363feae784SManuel Lauss 			goto out;
4373feae784SManuel Lauss 
438216d0fdeSFlorian Fainelli 		__raw_writel(r | USBHEN_CE, base + creg);
439216d0fdeSFlorian Fainelli 		wmb();
440216d0fdeSFlorian Fainelli 		udelay(1000);
441216d0fdeSFlorian Fainelli 		__raw_writel(r | USBHEN_CE | USBHEN_E, base + creg);
442216d0fdeSFlorian Fainelli 		wmb();
443216d0fdeSFlorian Fainelli 		udelay(1000);
444216d0fdeSFlorian Fainelli 
445216d0fdeSFlorian Fainelli 		/* wait for reset complete (read reg twice: au1500 erratum) */
446216d0fdeSFlorian Fainelli 		while (__raw_readl(base + creg),
447216d0fdeSFlorian Fainelli 			!(__raw_readl(base + creg) & USBHEN_RD))
448216d0fdeSFlorian Fainelli 			udelay(1000);
449216d0fdeSFlorian Fainelli 	} else {
450216d0fdeSFlorian Fainelli 		__raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
451216d0fdeSFlorian Fainelli 		wmb();
4523feae784SManuel Lauss 		clk_disable_unprepare(c);
453216d0fdeSFlorian Fainelli 	}
4543feae784SManuel Lauss out:
4553feae784SManuel Lauss 	clk_put(c);
456216d0fdeSFlorian Fainelli }
457216d0fdeSFlorian Fainelli 
au1000_usb_control(int block,int enable,unsigned long rb,int creg)458216d0fdeSFlorian Fainelli static inline int au1000_usb_control(int block, int enable, unsigned long rb,
459216d0fdeSFlorian Fainelli 				     int creg)
460216d0fdeSFlorian Fainelli {
461216d0fdeSFlorian Fainelli 	int ret = 0;
462216d0fdeSFlorian Fainelli 
463216d0fdeSFlorian Fainelli 	switch (block) {
464216d0fdeSFlorian Fainelli 	case ALCHEMY_USB_OHCI0:
465216d0fdeSFlorian Fainelli 		__au1xx0_ohci_control(enable, rb, creg);
466216d0fdeSFlorian Fainelli 		break;
467216d0fdeSFlorian Fainelli 	default:
468216d0fdeSFlorian Fainelli 		ret = -ENODEV;
469216d0fdeSFlorian Fainelli 	}
470216d0fdeSFlorian Fainelli 	return ret;
471216d0fdeSFlorian Fainelli }
472216d0fdeSFlorian Fainelli 
473216d0fdeSFlorian Fainelli /*
474216d0fdeSFlorian Fainelli  * alchemy_usb_control - control Alchemy on-chip USB blocks
475216d0fdeSFlorian Fainelli  * @block:	USB block to target
476216d0fdeSFlorian Fainelli  * @enable:	set 1 to enable a block, 0 to disable
477216d0fdeSFlorian Fainelli  */
alchemy_usb_control(int block,int enable)478216d0fdeSFlorian Fainelli int alchemy_usb_control(int block, int enable)
479216d0fdeSFlorian Fainelli {
480216d0fdeSFlorian Fainelli 	unsigned long flags;
481216d0fdeSFlorian Fainelli 	int ret;
482216d0fdeSFlorian Fainelli 
483216d0fdeSFlorian Fainelli 	spin_lock_irqsave(&alchemy_usb_lock, flags);
484216d0fdeSFlorian Fainelli 	switch (alchemy_get_cputype()) {
485216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1000:
486216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1500:
487216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1100:
488216d0fdeSFlorian Fainelli 		ret = au1000_usb_control(block, enable,
489216d0fdeSFlorian Fainelli 			AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
490216d0fdeSFlorian Fainelli 		break;
491216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1550:
492216d0fdeSFlorian Fainelli 		ret = au1000_usb_control(block, enable,
493216d0fdeSFlorian Fainelli 			AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
494216d0fdeSFlorian Fainelli 		break;
495216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1200:
496216d0fdeSFlorian Fainelli 		ret = au1200_usb_control(block, enable);
497216d0fdeSFlorian Fainelli 		break;
498216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1300:
499216d0fdeSFlorian Fainelli 		ret = au1300_usb_control(block, enable);
500216d0fdeSFlorian Fainelli 		break;
501216d0fdeSFlorian Fainelli 	default:
502216d0fdeSFlorian Fainelli 		ret = -ENODEV;
503216d0fdeSFlorian Fainelli 	}
504216d0fdeSFlorian Fainelli 	spin_unlock_irqrestore(&alchemy_usb_lock, flags);
505216d0fdeSFlorian Fainelli 	return ret;
506216d0fdeSFlorian Fainelli }
507216d0fdeSFlorian Fainelli EXPORT_SYMBOL_GPL(alchemy_usb_control);
508216d0fdeSFlorian Fainelli 
509216d0fdeSFlorian Fainelli 
510216d0fdeSFlorian Fainelli static unsigned long alchemy_usb_pmdata[2];
511216d0fdeSFlorian Fainelli 
au1000_usb_pm(unsigned long br,int creg,int susp)512216d0fdeSFlorian Fainelli static void au1000_usb_pm(unsigned long br, int creg, int susp)
513216d0fdeSFlorian Fainelli {
514216d0fdeSFlorian Fainelli 	void __iomem *base = (void __iomem *)KSEG1ADDR(br);
515216d0fdeSFlorian Fainelli 
516216d0fdeSFlorian Fainelli 	if (susp) {
517216d0fdeSFlorian Fainelli 		alchemy_usb_pmdata[0] = __raw_readl(base + creg);
518216d0fdeSFlorian Fainelli 		/* There appears to be some undocumented reset register.... */
519216d0fdeSFlorian Fainelli 		__raw_writel(0, base + 0x04);
520216d0fdeSFlorian Fainelli 		wmb();
521216d0fdeSFlorian Fainelli 		__raw_writel(0, base + creg);
522216d0fdeSFlorian Fainelli 		wmb();
523216d0fdeSFlorian Fainelli 	} else {
524216d0fdeSFlorian Fainelli 		__raw_writel(alchemy_usb_pmdata[0], base + creg);
525216d0fdeSFlorian Fainelli 		wmb();
526216d0fdeSFlorian Fainelli 	}
527216d0fdeSFlorian Fainelli }
528216d0fdeSFlorian Fainelli 
au1200_usb_pm(int susp)529216d0fdeSFlorian Fainelli static void au1200_usb_pm(int susp)
530216d0fdeSFlorian Fainelli {
531216d0fdeSFlorian Fainelli 	void __iomem *base =
532216d0fdeSFlorian Fainelli 			(void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR);
533216d0fdeSFlorian Fainelli 	if (susp) {
534216d0fdeSFlorian Fainelli 		/* save OTG_CAP/MUX registers which indicate port routing */
535216d0fdeSFlorian Fainelli 		/* FIXME: write an OTG driver to do that */
536216d0fdeSFlorian Fainelli 		alchemy_usb_pmdata[0] = __raw_readl(base + 0x00);
537216d0fdeSFlorian Fainelli 		alchemy_usb_pmdata[1] = __raw_readl(base + 0x04);
538216d0fdeSFlorian Fainelli 	} else {
539216d0fdeSFlorian Fainelli 		/* restore access to all MMIO areas */
540216d0fdeSFlorian Fainelli 		au1200_usb_init();
541216d0fdeSFlorian Fainelli 
542216d0fdeSFlorian Fainelli 		/* restore OTG_CAP/MUX registers */
543216d0fdeSFlorian Fainelli 		__raw_writel(alchemy_usb_pmdata[0], base + 0x00);
544216d0fdeSFlorian Fainelli 		__raw_writel(alchemy_usb_pmdata[1], base + 0x04);
545216d0fdeSFlorian Fainelli 		wmb();
546216d0fdeSFlorian Fainelli 	}
547216d0fdeSFlorian Fainelli }
548216d0fdeSFlorian Fainelli 
au1300_usb_pm(int susp)549216d0fdeSFlorian Fainelli static void au1300_usb_pm(int susp)
550216d0fdeSFlorian Fainelli {
551216d0fdeSFlorian Fainelli 	void __iomem *base =
552216d0fdeSFlorian Fainelli 			(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
553216d0fdeSFlorian Fainelli 	/* remember Port2 routing */
554216d0fdeSFlorian Fainelli 	if (susp) {
555216d0fdeSFlorian Fainelli 		alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
556216d0fdeSFlorian Fainelli 	} else {
557216d0fdeSFlorian Fainelli 		au1300_usb_init();
558216d0fdeSFlorian Fainelli 		__raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
559216d0fdeSFlorian Fainelli 		wmb();
560216d0fdeSFlorian Fainelli 	}
561216d0fdeSFlorian Fainelli }
562216d0fdeSFlorian Fainelli 
alchemy_usb_pm(int susp)563216d0fdeSFlorian Fainelli static void alchemy_usb_pm(int susp)
564216d0fdeSFlorian Fainelli {
565216d0fdeSFlorian Fainelli 	switch (alchemy_get_cputype()) {
566216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1000:
567216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1500:
568216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1100:
569216d0fdeSFlorian Fainelli 		au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp);
570216d0fdeSFlorian Fainelli 		break;
571216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1550:
572216d0fdeSFlorian Fainelli 		au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp);
573216d0fdeSFlorian Fainelli 		break;
574216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1200:
575216d0fdeSFlorian Fainelli 		au1200_usb_pm(susp);
576216d0fdeSFlorian Fainelli 		break;
577216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1300:
578216d0fdeSFlorian Fainelli 		au1300_usb_pm(susp);
579216d0fdeSFlorian Fainelli 		break;
580216d0fdeSFlorian Fainelli 	}
581216d0fdeSFlorian Fainelli }
582216d0fdeSFlorian Fainelli 
alchemy_usb_suspend(void)583216d0fdeSFlorian Fainelli static int alchemy_usb_suspend(void)
584216d0fdeSFlorian Fainelli {
585216d0fdeSFlorian Fainelli 	alchemy_usb_pm(1);
586216d0fdeSFlorian Fainelli 	return 0;
587216d0fdeSFlorian Fainelli }
588216d0fdeSFlorian Fainelli 
alchemy_usb_resume(void)589216d0fdeSFlorian Fainelli static void alchemy_usb_resume(void)
590216d0fdeSFlorian Fainelli {
591216d0fdeSFlorian Fainelli 	alchemy_usb_pm(0);
592216d0fdeSFlorian Fainelli }
593216d0fdeSFlorian Fainelli 
594216d0fdeSFlorian Fainelli static struct syscore_ops alchemy_usb_pm_ops = {
595216d0fdeSFlorian Fainelli 	.suspend	= alchemy_usb_suspend,
596216d0fdeSFlorian Fainelli 	.resume		= alchemy_usb_resume,
597216d0fdeSFlorian Fainelli };
598216d0fdeSFlorian Fainelli 
alchemy_usb_init(void)599216d0fdeSFlorian Fainelli static int __init alchemy_usb_init(void)
600216d0fdeSFlorian Fainelli {
6013feae784SManuel Lauss 	int ret = 0;
6023feae784SManuel Lauss 
603216d0fdeSFlorian Fainelli 	switch (alchemy_get_cputype()) {
604216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1000:
605216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1500:
606216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1100:
6073feae784SManuel Lauss 		ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
6083feae784SManuel Lauss 				      AU1000_OHCICFG);
609216d0fdeSFlorian Fainelli 		break;
610216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1550:
6113feae784SManuel Lauss 		ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
6123feae784SManuel Lauss 				      AU1550_OHCICFG);
613216d0fdeSFlorian Fainelli 		break;
614216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1200:
615216d0fdeSFlorian Fainelli 		au1200_usb_init();
616216d0fdeSFlorian Fainelli 		break;
617216d0fdeSFlorian Fainelli 	case ALCHEMY_CPU_AU1300:
618216d0fdeSFlorian Fainelli 		au1300_usb_init();
619216d0fdeSFlorian Fainelli 		break;
620216d0fdeSFlorian Fainelli 	}
621216d0fdeSFlorian Fainelli 
6223feae784SManuel Lauss 	if (!ret)
623216d0fdeSFlorian Fainelli 		register_syscore_ops(&alchemy_usb_pm_ops);
624216d0fdeSFlorian Fainelli 
6253feae784SManuel Lauss 	return ret;
626216d0fdeSFlorian Fainelli }
627216d0fdeSFlorian Fainelli arch_initcall(alchemy_usb_init);
628