diff options
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/host/alchemy-common.c | 337 | ||||
-rw-r--r-- | drivers/usb/host/ehci-au1xxx.c | 77 | ||||
-rw-r--r-- | drivers/usb/host/ohci-au1xxx.c | 110 |
4 files changed, 359 insertions, 166 deletions
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 624a362f2fee..436cd71c6bec 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -35,3 +35,4 @@ obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o | |||
35 | obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o | 35 | obj-$(CONFIG_USB_IMX21_HCD) += imx21-hcd.o |
36 | obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o | 36 | obj-$(CONFIG_USB_FSL_MPH_DR_OF) += fsl-mph-dr-of.o |
37 | obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o | 37 | obj-$(CONFIG_USB_OCTEON2_COMMON) += octeon2-common.o |
38 | obj-$(CONFIG_MIPS_ALCHEMY) += alchemy-common.o | ||
diff --git a/drivers/usb/host/alchemy-common.c b/drivers/usb/host/alchemy-common.c new file mode 100644 index 000000000000..b4192c964d0d --- /dev/null +++ b/drivers/usb/host/alchemy-common.c | |||
@@ -0,0 +1,337 @@ | |||
1 | /* | ||
2 | * USB block power/access management abstraction. | ||
3 | * | ||
4 | * Au1000+: The OHCI block control register is at the far end of the OHCI memory | ||
5 | * area. Au1550 has OHCI on different base address. No need to handle | ||
6 | * UDC here. | ||
7 | * Au1200: one register to control access and clocks to O/EHCI, UDC and OTG | ||
8 | * as well as the PHY for EHCI and UDC. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | #include <linux/syscore_ops.h> | ||
17 | #include <asm/mach-au1x00/au1000.h> | ||
18 | |||
19 | /* control register offsets */ | ||
20 | #define AU1000_OHCICFG 0x7fffc | ||
21 | #define AU1550_OHCICFG 0x07ffc | ||
22 | #define AU1200_USBCFG 0x04 | ||
23 | |||
24 | /* Au1000 USB block config bits */ | ||
25 | #define USBHEN_RD (1 << 4) /* OHCI reset-done indicator */ | ||
26 | #define USBHEN_CE (1 << 3) /* OHCI block clock enable */ | ||
27 | #define USBHEN_E (1 << 2) /* OHCI block enable */ | ||
28 | #define USBHEN_C (1 << 1) /* OHCI block coherency bit */ | ||
29 | #define USBHEN_BE (1 << 0) /* OHCI Big-Endian */ | ||
30 | |||
31 | /* Au1200 USB config bits */ | ||
32 | #define USBCFG_PFEN (1 << 31) /* prefetch enable (undoc) */ | ||
33 | #define USBCFG_RDCOMB (1 << 30) /* read combining (undoc) */ | ||
34 | #define USBCFG_UNKNOWN (5 << 20) /* unknown, leave this way */ | ||
35 | #define USBCFG_SSD (1 << 23) /* serial short detect en */ | ||
36 | #define USBCFG_PPE (1 << 19) /* HS PHY PLL */ | ||
37 | #define USBCFG_UCE (1 << 18) /* UDC clock enable */ | ||
38 | #define USBCFG_ECE (1 << 17) /* EHCI clock enable */ | ||
39 | #define USBCFG_OCE (1 << 16) /* OHCI clock enable */ | ||
40 | #define USBCFG_FLA(x) (((x) & 0x3f) << 8) | ||
41 | #define USBCFG_UCAM (1 << 7) /* coherent access (undoc) */ | ||
42 | #define USBCFG_GME (1 << 6) /* OTG mem access */ | ||
43 | #define USBCFG_DBE (1 << 5) /* UDC busmaster enable */ | ||
44 | #define USBCFG_DME (1 << 4) /* UDC mem enable */ | ||
45 | #define USBCFG_EBE (1 << 3) /* EHCI busmaster enable */ | ||
46 | #define USBCFG_EME (1 << 2) /* EHCI mem enable */ | ||
47 | #define USBCFG_OBE (1 << 1) /* OHCI busmaster enable */ | ||
48 | #define USBCFG_OME (1 << 0) /* OHCI mem enable */ | ||
49 | #define USBCFG_INIT_AU1200 (USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\ | ||
50 | USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \ | ||
51 | USBCFG_GME | USBCFG_DBE | USBCFG_DME | \ | ||
52 | USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \ | ||
53 | USBCFG_OME) | ||
54 | |||
55 | |||
56 | static DEFINE_SPINLOCK(alchemy_usb_lock); | ||
57 | |||
58 | |||
59 | static inline void __au1200_ohci_control(void __iomem *base, int enable) | ||
60 | { | ||
61 | unsigned long r = __raw_readl(base + AU1200_USBCFG); | ||
62 | if (enable) { | ||
63 | __raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG); | ||
64 | wmb(); | ||
65 | udelay(2000); | ||
66 | } else { | ||
67 | __raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG); | ||
68 | wmb(); | ||
69 | udelay(1000); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static inline void __au1200_ehci_control(void __iomem *base, int enable) | ||
74 | { | ||
75 | unsigned long r = __raw_readl(base + AU1200_USBCFG); | ||
76 | if (enable) { | ||
77 | __raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG); | ||
78 | wmb(); | ||
79 | udelay(1000); | ||
80 | } else { | ||
81 | if (!(r & USBCFG_UCE)) /* UDC also off? */ | ||
82 | r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */ | ||
83 | __raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG); | ||
84 | wmb(); | ||
85 | udelay(1000); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | static inline void __au1200_udc_control(void __iomem *base, int enable) | ||
90 | { | ||
91 | unsigned long r = __raw_readl(base + AU1200_USBCFG); | ||
92 | if (enable) { | ||
93 | __raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG); | ||
94 | wmb(); | ||
95 | } else { | ||
96 | if (!(r & USBCFG_ECE)) /* EHCI also off? */ | ||
97 | r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */ | ||
98 | __raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG); | ||
99 | wmb(); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | static inline int au1200_coherency_bug(void) | ||
104 | { | ||
105 | #if defined(CONFIG_DMA_COHERENT) | ||
106 | /* Au1200 AB USB does not support coherent memory */ | ||
107 | if (!(read_c0_prid() & 0xff)) { | ||
108 | printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n"); | ||
109 | printk(KERN_INFO "Au1200 USB: update your board or re-configure" | ||
110 | " the kernel\n"); | ||
111 | return -ENODEV; | ||
112 | } | ||
113 | #endif | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static inline int au1200_usb_control(int block, int enable) | ||
118 | { | ||
119 | void __iomem *base = | ||
120 | (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); | ||
121 | int ret = 0; | ||
122 | |||
123 | switch (block) { | ||
124 | case ALCHEMY_USB_OHCI0: | ||
125 | ret = au1200_coherency_bug(); | ||
126 | if (ret && enable) | ||
127 | goto out; | ||
128 | __au1200_ohci_control(base, enable); | ||
129 | break; | ||
130 | case ALCHEMY_USB_UDC0: | ||
131 | __au1200_udc_control(base, enable); | ||
132 | break; | ||
133 | case ALCHEMY_USB_EHCI0: | ||
134 | ret = au1200_coherency_bug(); | ||
135 | if (ret && enable) | ||
136 | goto out; | ||
137 | __au1200_ehci_control(base, enable); | ||
138 | break; | ||
139 | default: | ||
140 | ret = -ENODEV; | ||
141 | } | ||
142 | out: | ||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | |||
147 | /* initialize USB block(s) to a known working state */ | ||
148 | static inline void au1200_usb_init(void) | ||
149 | { | ||
150 | void __iomem *base = | ||
151 | (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); | ||
152 | __raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG); | ||
153 | wmb(); | ||
154 | udelay(1000); | ||
155 | } | ||
156 | |||
157 | static inline void au1000_usb_init(unsigned long rb, int reg) | ||
158 | { | ||
159 | void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg); | ||
160 | unsigned long r = __raw_readl(base); | ||
161 | |||
162 | #if defined(__BIG_ENDIAN) | ||
163 | r |= USBHEN_BE; | ||
164 | #endif | ||
165 | r |= USBHEN_C; | ||
166 | |||
167 | __raw_writel(r, base); | ||
168 | wmb(); | ||
169 | udelay(1000); | ||
170 | } | ||
171 | |||
172 | |||
173 | static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg) | ||
174 | { | ||
175 | void __iomem *base = (void __iomem *)KSEG1ADDR(rb); | ||
176 | unsigned long r = __raw_readl(base + creg); | ||
177 | |||
178 | if (enable) { | ||
179 | __raw_writel(r | USBHEN_CE, base + creg); | ||
180 | wmb(); | ||
181 | udelay(1000); | ||
182 | __raw_writel(r | USBHEN_CE | USBHEN_E, base + creg); | ||
183 | wmb(); | ||
184 | udelay(1000); | ||
185 | |||
186 | /* wait for reset complete (read reg twice: au1500 erratum) */ | ||
187 | while (__raw_readl(base + creg), | ||
188 | !(__raw_readl(base + creg) & USBHEN_RD)) | ||
189 | udelay(1000); | ||
190 | } else { | ||
191 | __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg); | ||
192 | wmb(); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static inline int au1000_usb_control(int block, int enable, unsigned long rb, | ||
197 | int creg) | ||
198 | { | ||
199 | int ret = 0; | ||
200 | |||
201 | switch (block) { | ||
202 | case ALCHEMY_USB_OHCI0: | ||
203 | __au1xx0_ohci_control(enable, rb, creg); | ||
204 | break; | ||
205 | default: | ||
206 | ret = -ENODEV; | ||
207 | } | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | /* | ||
212 | * alchemy_usb_control - control Alchemy on-chip USB blocks | ||
213 | * @block: USB block to target | ||
214 | * @enable: set 1 to enable a block, 0 to disable | ||
215 | */ | ||
216 | int alchemy_usb_control(int block, int enable) | ||
217 | { | ||
218 | unsigned long flags; | ||
219 | int ret; | ||
220 | |||
221 | spin_lock_irqsave(&alchemy_usb_lock, flags); | ||
222 | switch (alchemy_get_cputype()) { | ||
223 | case ALCHEMY_CPU_AU1000: | ||
224 | case ALCHEMY_CPU_AU1500: | ||
225 | case ALCHEMY_CPU_AU1100: | ||
226 | ret = au1000_usb_control(block, enable, | ||
227 | AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); | ||
228 | break; | ||
229 | case ALCHEMY_CPU_AU1550: | ||
230 | ret = au1000_usb_control(block, enable, | ||
231 | AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); | ||
232 | break; | ||
233 | case ALCHEMY_CPU_AU1200: | ||
234 | ret = au1200_usb_control(block, enable); | ||
235 | break; | ||
236 | default: | ||
237 | ret = -ENODEV; | ||
238 | } | ||
239 | spin_unlock_irqrestore(&alchemy_usb_lock, flags); | ||
240 | return ret; | ||
241 | } | ||
242 | EXPORT_SYMBOL_GPL(alchemy_usb_control); | ||
243 | |||
244 | |||
245 | static unsigned long alchemy_usb_pmdata[2]; | ||
246 | |||
247 | static void au1000_usb_pm(unsigned long br, int creg, int susp) | ||
248 | { | ||
249 | void __iomem *base = (void __iomem *)KSEG1ADDR(br); | ||
250 | |||
251 | if (susp) { | ||
252 | alchemy_usb_pmdata[0] = __raw_readl(base + creg); | ||
253 | /* There appears to be some undocumented reset register.... */ | ||
254 | __raw_writel(0, base + 0x04); | ||
255 | wmb(); | ||
256 | __raw_writel(0, base + creg); | ||
257 | wmb(); | ||
258 | } else { | ||
259 | __raw_writel(alchemy_usb_pmdata[0], base + creg); | ||
260 | wmb(); | ||
261 | } | ||
262 | } | ||
263 | |||
264 | static void au1200_usb_pm(int susp) | ||
265 | { | ||
266 | void __iomem *base = | ||
267 | (void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR); | ||
268 | if (susp) { | ||
269 | /* save OTG_CAP/MUX registers which indicate port routing */ | ||
270 | /* FIXME: write an OTG driver to do that */ | ||
271 | alchemy_usb_pmdata[0] = __raw_readl(base + 0x00); | ||
272 | alchemy_usb_pmdata[1] = __raw_readl(base + 0x04); | ||
273 | } else { | ||
274 | /* restore access to all MMIO areas */ | ||
275 | au1200_usb_init(); | ||
276 | |||
277 | /* restore OTG_CAP/MUX registers */ | ||
278 | __raw_writel(alchemy_usb_pmdata[0], base + 0x00); | ||
279 | __raw_writel(alchemy_usb_pmdata[1], base + 0x04); | ||
280 | wmb(); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | static void alchemy_usb_pm(int susp) | ||
285 | { | ||
286 | switch (alchemy_get_cputype()) { | ||
287 | case ALCHEMY_CPU_AU1000: | ||
288 | case ALCHEMY_CPU_AU1500: | ||
289 | case ALCHEMY_CPU_AU1100: | ||
290 | au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp); | ||
291 | break; | ||
292 | case ALCHEMY_CPU_AU1550: | ||
293 | au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp); | ||
294 | break; | ||
295 | case ALCHEMY_CPU_AU1200: | ||
296 | au1200_usb_pm(susp); | ||
297 | break; | ||
298 | } | ||
299 | } | ||
300 | |||
301 | static int alchemy_usb_suspend(void) | ||
302 | { | ||
303 | alchemy_usb_pm(1); | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static void alchemy_usb_resume(void) | ||
308 | { | ||
309 | alchemy_usb_pm(0); | ||
310 | } | ||
311 | |||
312 | static struct syscore_ops alchemy_usb_pm_ops = { | ||
313 | .suspend = alchemy_usb_suspend, | ||
314 | .resume = alchemy_usb_resume, | ||
315 | }; | ||
316 | |||
317 | static int __init alchemy_usb_init(void) | ||
318 | { | ||
319 | switch (alchemy_get_cputype()) { | ||
320 | case ALCHEMY_CPU_AU1000: | ||
321 | case ALCHEMY_CPU_AU1500: | ||
322 | case ALCHEMY_CPU_AU1100: | ||
323 | au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); | ||
324 | break; | ||
325 | case ALCHEMY_CPU_AU1550: | ||
326 | au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); | ||
327 | break; | ||
328 | case ALCHEMY_CPU_AU1200: | ||
329 | au1200_usb_init(); | ||
330 | break; | ||
331 | } | ||
332 | |||
333 | register_syscore_ops(&alchemy_usb_pm_ops); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | arch_initcall(alchemy_usb_init); | ||
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index 42ae57409908..e480dc17394d 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c | |||
@@ -14,61 +14,9 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <asm/mach-au1x00/au1000.h> | 15 | #include <asm/mach-au1x00/au1000.h> |
16 | 16 | ||
17 | #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) | ||
18 | #define USB_MCFG_PFEN (1<<31) | ||
19 | #define USB_MCFG_RDCOMB (1<<30) | ||
20 | #define USB_MCFG_SSDEN (1<<23) | ||
21 | #define USB_MCFG_PHYPLLEN (1<<19) | ||
22 | #define USB_MCFG_UCECLKEN (1<<18) | ||
23 | #define USB_MCFG_EHCCLKEN (1<<17) | ||
24 | #ifdef CONFIG_DMA_COHERENT | ||
25 | #define USB_MCFG_UCAM (1<<7) | ||
26 | #else | ||
27 | #define USB_MCFG_UCAM (0) | ||
28 | #endif | ||
29 | #define USB_MCFG_EBMEN (1<<3) | ||
30 | #define USB_MCFG_EMEMEN (1<<2) | ||
31 | |||
32 | #define USBH_ENABLE_CE (USB_MCFG_PHYPLLEN | USB_MCFG_EHCCLKEN) | ||
33 | #define USBH_ENABLE_INIT (USB_MCFG_PFEN | USB_MCFG_RDCOMB | \ | ||
34 | USBH_ENABLE_CE | USB_MCFG_SSDEN | \ | ||
35 | USB_MCFG_UCAM | USB_MCFG_EBMEN | \ | ||
36 | USB_MCFG_EMEMEN) | ||
37 | |||
38 | #define USBH_DISABLE (USB_MCFG_EBMEN | USB_MCFG_EMEMEN) | ||
39 | 17 | ||
40 | extern int usb_disabled(void); | 18 | extern int usb_disabled(void); |
41 | 19 | ||
42 | static void au1xxx_start_ehc(void) | ||
43 | { | ||
44 | /* enable clock to EHCI block and HS PHY PLL*/ | ||
45 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG); | ||
46 | au_sync(); | ||
47 | udelay(1000); | ||
48 | |||
49 | /* enable EHCI mmio */ | ||
50 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); | ||
51 | au_sync(); | ||
52 | udelay(1000); | ||
53 | } | ||
54 | |||
55 | static void au1xxx_stop_ehc(void) | ||
56 | { | ||
57 | unsigned long c; | ||
58 | |||
59 | /* Disable mem */ | ||
60 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG); | ||
61 | au_sync(); | ||
62 | udelay(1000); | ||
63 | |||
64 | /* Disable EHC clock. If the HS PHY is unused disable it too. */ | ||
65 | c = au_readl(USB_HOST_CONFIG) & ~USB_MCFG_EHCCLKEN; | ||
66 | if (!(c & USB_MCFG_UCECLKEN)) /* UDC disabled? */ | ||
67 | c &= ~USB_MCFG_PHYPLLEN; /* yes: disable HS PHY PLL */ | ||
68 | au_writel(c, USB_HOST_CONFIG); | ||
69 | au_sync(); | ||
70 | } | ||
71 | |||
72 | static int au1xxx_ehci_setup(struct usb_hcd *hcd) | 20 | static int au1xxx_ehci_setup(struct usb_hcd *hcd) |
73 | { | 21 | { |
74 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 22 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
@@ -136,16 +84,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | |||
136 | if (usb_disabled()) | 84 | if (usb_disabled()) |
137 | return -ENODEV; | 85 | return -ENODEV; |
138 | 86 | ||
139 | #if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) | ||
140 | /* Au1200 AB USB does not support coherent memory */ | ||
141 | if (!(read_c0_prid() & 0xff)) { | ||
142 | printk(KERN_INFO "%s: this is chip revision AB!\n", pdev->name); | ||
143 | printk(KERN_INFO "%s: update your board or re-configure" | ||
144 | " the kernel\n", pdev->name); | ||
145 | return -ENODEV; | ||
146 | } | ||
147 | #endif | ||
148 | |||
149 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { | 87 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { |
150 | pr_debug("resource[1] is not IORESOURCE_IRQ"); | 88 | pr_debug("resource[1] is not IORESOURCE_IRQ"); |
151 | return -ENOMEM; | 89 | return -ENOMEM; |
@@ -171,7 +109,11 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | |||
171 | goto err2; | 109 | goto err2; |
172 | } | 110 | } |
173 | 111 | ||
174 | au1xxx_start_ehc(); | 112 | if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) { |
113 | printk(KERN_INFO "%s: controller init failed!\n", pdev->name); | ||
114 | ret = -ENODEV; | ||
115 | goto err3; | ||
116 | } | ||
175 | 117 | ||
176 | ehci = hcd_to_ehci(hcd); | 118 | ehci = hcd_to_ehci(hcd); |
177 | ehci->caps = hcd->regs; | 119 | ehci->caps = hcd->regs; |
@@ -187,7 +129,8 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | |||
187 | return ret; | 129 | return ret; |
188 | } | 130 | } |
189 | 131 | ||
190 | au1xxx_stop_ehc(); | 132 | alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); |
133 | err3: | ||
191 | iounmap(hcd->regs); | 134 | iounmap(hcd->regs); |
192 | err2: | 135 | err2: |
193 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 136 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
@@ -201,10 +144,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) | |||
201 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 144 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
202 | 145 | ||
203 | usb_remove_hcd(hcd); | 146 | usb_remove_hcd(hcd); |
147 | alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); | ||
204 | iounmap(hcd->regs); | 148 | iounmap(hcd->regs); |
205 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 149 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
206 | usb_put_hcd(hcd); | 150 | usb_put_hcd(hcd); |
207 | au1xxx_stop_ehc(); | ||
208 | platform_set_drvdata(pdev, NULL); | 151 | platform_set_drvdata(pdev, NULL); |
209 | 152 | ||
210 | return 0; | 153 | return 0; |
@@ -236,7 +179,7 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) | |||
236 | // could save FLADJ in case of Vaux power loss | 179 | // could save FLADJ in case of Vaux power loss |
237 | // ... we'd only use it to handle clock skew | 180 | // ... we'd only use it to handle clock skew |
238 | 181 | ||
239 | au1xxx_stop_ehc(); | 182 | alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); |
240 | 183 | ||
241 | return rc; | 184 | return rc; |
242 | } | 185 | } |
@@ -246,7 +189,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev) | |||
246 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 189 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
247 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); | 190 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
248 | 191 | ||
249 | au1xxx_start_ehc(); | 192 | alchemy_usb_control(ALCHEMY_USB_EHCI0, 1); |
250 | 193 | ||
251 | // maybe restore FLADJ | 194 | // maybe restore FLADJ |
252 | 195 | ||
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index 958d985f2951..299d719495f1 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c | |||
@@ -23,92 +23,9 @@ | |||
23 | 23 | ||
24 | #include <asm/mach-au1x00/au1000.h> | 24 | #include <asm/mach-au1x00/au1000.h> |
25 | 25 | ||
26 | #ifndef CONFIG_SOC_AU1200 | ||
27 | |||
28 | #define USBH_ENABLE_BE (1<<0) | ||
29 | #define USBH_ENABLE_C (1<<1) | ||
30 | #define USBH_ENABLE_E (1<<2) | ||
31 | #define USBH_ENABLE_CE (1<<3) | ||
32 | #define USBH_ENABLE_RD (1<<4) | ||
33 | |||
34 | #ifdef __LITTLE_ENDIAN | ||
35 | #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C) | ||
36 | #elif defined(__BIG_ENDIAN) | ||
37 | #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | \ | ||
38 | USBH_ENABLE_BE) | ||
39 | #else | ||
40 | #error not byte order defined | ||
41 | #endif | ||
42 | |||
43 | #else /* Au1200 */ | ||
44 | |||
45 | #define USB_HOST_CONFIG (USB_MSR_BASE + USB_MSR_MCFG) | ||
46 | #define USB_MCFG_PFEN (1<<31) | ||
47 | #define USB_MCFG_RDCOMB (1<<30) | ||
48 | #define USB_MCFG_SSDEN (1<<23) | ||
49 | #define USB_MCFG_OHCCLKEN (1<<16) | ||
50 | #ifdef CONFIG_DMA_COHERENT | ||
51 | #define USB_MCFG_UCAM (1<<7) | ||
52 | #else | ||
53 | #define USB_MCFG_UCAM (0) | ||
54 | #endif | ||
55 | #define USB_MCFG_OBMEN (1<<1) | ||
56 | #define USB_MCFG_OMEMEN (1<<0) | ||
57 | |||
58 | #define USBH_ENABLE_CE USB_MCFG_OHCCLKEN | ||
59 | |||
60 | #define USBH_ENABLE_INIT (USB_MCFG_PFEN | USB_MCFG_RDCOMB | \ | ||
61 | USBH_ENABLE_CE | USB_MCFG_SSDEN | \ | ||
62 | USB_MCFG_UCAM | \ | ||
63 | USB_MCFG_OBMEN | USB_MCFG_OMEMEN) | ||
64 | |||
65 | #define USBH_DISABLE (USB_MCFG_OBMEN | USB_MCFG_OMEMEN) | ||
66 | |||
67 | #endif /* Au1200 */ | ||
68 | 26 | ||
69 | extern int usb_disabled(void); | 27 | extern int usb_disabled(void); |
70 | 28 | ||
71 | static void au1xxx_start_ohc(void) | ||
72 | { | ||
73 | /* enable host controller */ | ||
74 | #ifndef CONFIG_SOC_AU1200 | ||
75 | au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG); | ||
76 | au_sync(); | ||
77 | udelay(1000); | ||
78 | |||
79 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); | ||
80 | au_sync(); | ||
81 | udelay(1000); | ||
82 | |||
83 | /* wait for reset complete (read register twice; see au1500 errata) */ | ||
84 | while (au_readl(USB_HOST_CONFIG), | ||
85 | !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) | ||
86 | udelay(1000); | ||
87 | |||
88 | #else /* Au1200 */ | ||
89 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_CE, USB_HOST_CONFIG); | ||
90 | au_sync(); | ||
91 | udelay(1000); | ||
92 | |||
93 | au_writel(au_readl(USB_HOST_CONFIG) | USBH_ENABLE_INIT, USB_HOST_CONFIG); | ||
94 | au_sync(); | ||
95 | udelay(2000); | ||
96 | #endif /* Au1200 */ | ||
97 | } | ||
98 | |||
99 | static void au1xxx_stop_ohc(void) | ||
100 | { | ||
101 | #ifdef CONFIG_SOC_AU1200 | ||
102 | /* Disable mem */ | ||
103 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_DISABLE, USB_HOST_CONFIG); | ||
104 | au_sync(); | ||
105 | udelay(1000); | ||
106 | #endif | ||
107 | /* Disable clock */ | ||
108 | au_writel(au_readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); | ||
109 | au_sync(); | ||
110 | } | ||
111 | |||
112 | static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd) | 29 | static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd) |
113 | { | 30 | { |
114 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); | 31 | struct ohci_hcd *ohci = hcd_to_ohci(hcd); |
@@ -178,17 +95,6 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | |||
178 | if (usb_disabled()) | 95 | if (usb_disabled()) |
179 | return -ENODEV; | 96 | return -ENODEV; |
180 | 97 | ||
181 | #if defined(CONFIG_SOC_AU1200) && defined(CONFIG_DMA_COHERENT) | ||
182 | /* Au1200 AB USB does not support coherent memory */ | ||
183 | if (!(read_c0_prid() & 0xff)) { | ||
184 | printk(KERN_INFO "%s: this is chip revision AB !!\n", | ||
185 | pdev->name); | ||
186 | printk(KERN_INFO "%s: update your board or re-configure " | ||
187 | "the kernel\n", pdev->name); | ||
188 | return -ENODEV; | ||
189 | } | ||
190 | #endif | ||
191 | |||
192 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { | 98 | if (pdev->resource[1].flags != IORESOURCE_IRQ) { |
193 | pr_debug("resource[1] is not IORESOURCE_IRQ\n"); | 99 | pr_debug("resource[1] is not IORESOURCE_IRQ\n"); |
194 | return -ENOMEM; | 100 | return -ENOMEM; |
@@ -214,7 +120,12 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | |||
214 | goto err2; | 120 | goto err2; |
215 | } | 121 | } |
216 | 122 | ||
217 | au1xxx_start_ohc(); | 123 | if (alchemy_usb_control(ALCHEMY_USB_OHCI0, 1)) { |
124 | printk(KERN_INFO "%s: controller init failed!\n", pdev->name); | ||
125 | ret = -ENODEV; | ||
126 | goto err3; | ||
127 | } | ||
128 | |||
218 | ohci_hcd_init(hcd_to_ohci(hcd)); | 129 | ohci_hcd_init(hcd_to_ohci(hcd)); |
219 | 130 | ||
220 | ret = usb_add_hcd(hcd, pdev->resource[1].start, | 131 | ret = usb_add_hcd(hcd, pdev->resource[1].start, |
@@ -224,7 +135,8 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | |||
224 | return ret; | 135 | return ret; |
225 | } | 136 | } |
226 | 137 | ||
227 | au1xxx_stop_ohc(); | 138 | alchemy_usb_control(ALCHEMY_USB_OHCI0, 0); |
139 | err3: | ||
228 | iounmap(hcd->regs); | 140 | iounmap(hcd->regs); |
229 | err2: | 141 | err2: |
230 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 142 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
@@ -238,7 +150,7 @@ static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) | |||
238 | struct usb_hcd *hcd = platform_get_drvdata(pdev); | 150 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
239 | 151 | ||
240 | usb_remove_hcd(hcd); | 152 | usb_remove_hcd(hcd); |
241 | au1xxx_stop_ohc(); | 153 | alchemy_usb_control(ALCHEMY_USB_OHCI0, 0); |
242 | iounmap(hcd->regs); | 154 | iounmap(hcd->regs); |
243 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); | 155 | release_mem_region(hcd->rsrc_start, hcd->rsrc_len); |
244 | usb_put_hcd(hcd); | 156 | usb_put_hcd(hcd); |
@@ -275,7 +187,7 @@ static int ohci_hcd_au1xxx_drv_suspend(struct device *dev) | |||
275 | 187 | ||
276 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 188 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
277 | 189 | ||
278 | au1xxx_stop_ohc(); | 190 | alchemy_usb_control(ALCHEMY_USB_OHCI0, 0); |
279 | bail: | 191 | bail: |
280 | spin_unlock_irqrestore(&ohci->lock, flags); | 192 | spin_unlock_irqrestore(&ohci->lock, flags); |
281 | 193 | ||
@@ -286,7 +198,7 @@ static int ohci_hcd_au1xxx_drv_resume(struct device *dev) | |||
286 | { | 198 | { |
287 | struct usb_hcd *hcd = dev_get_drvdata(dev); | 199 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
288 | 200 | ||
289 | au1xxx_start_ohc(); | 201 | alchemy_usb_control(ALCHEMY_USB_OHCI0, 1); |
290 | 202 | ||
291 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 203 | set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
292 | ohci_finish_controller_resume(hcd); | 204 | ohci_finish_controller_resume(hcd); |