aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/usb/host
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-ath79.c204
-rw-r--r--drivers/usb/host/ehci-au1xxx.c323
-rw-r--r--drivers/usb/host/ehci-cns3xxx.c171
-rw-r--r--drivers/usb/host/ehci-ixp4xx.c156
-rw-r--r--drivers/usb/host/ehci-lpm.c84
-rw-r--r--drivers/usb/host/ohci-ath79.c151
-rw-r--r--drivers/usb/host/ohci-au1xxx.c319
-rw-r--r--drivers/usb/host/ohci-cns3xxx.c165
-rw-r--r--drivers/usb/host/ohci-pnx4008.c453
-rw-r--r--drivers/usb/host/ohci-pnx8550.c242
-rw-r--r--drivers/usb/host/ohci-ppc-soc.c215
-rw-r--r--drivers/usb/host/ohci-sh.c142
-rw-r--r--drivers/usb/host/ohci-ssb.c260
13 files changed, 2885 insertions, 0 deletions
diff --git a/drivers/usb/host/ehci-ath79.c b/drivers/usb/host/ehci-ath79.c
new file mode 100644
index 00000000000..4d2e88d04da
--- /dev/null
+++ b/drivers/usb/host/ehci-ath79.c
@@ -0,0 +1,204 @@
1/*
2 * Bus Glue for Atheros AR7XXX/AR9XXX built-in EHCI controller.
3 *
4 * Copyright (C) 2008-2011 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 * Copyright (C) 2007 Atheros Communications, Inc.
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
13 */
14
15#include <linux/platform_device.h>
16
17enum {
18 EHCI_ATH79_IP_V1 = 0,
19 EHCI_ATH79_IP_V2,
20};
21
22static const struct platform_device_id ehci_ath79_id_table[] = {
23 {
24 .name = "ar71xx-ehci",
25 .driver_data = EHCI_ATH79_IP_V1,
26 },
27 {
28 .name = "ar724x-ehci",
29 .driver_data = EHCI_ATH79_IP_V2,
30 },
31 {
32 .name = "ar913x-ehci",
33 .driver_data = EHCI_ATH79_IP_V2,
34 },
35 {
36 /* terminating entry */
37 },
38};
39
40MODULE_DEVICE_TABLE(platform, ehci_ath79_id_table);
41
42static int ehci_ath79_init(struct usb_hcd *hcd)
43{
44 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
45 struct platform_device *pdev = to_platform_device(hcd->self.controller);
46 const struct platform_device_id *id;
47 int ret;
48
49 id = platform_get_device_id(pdev);
50 if (!id) {
51 dev_err(hcd->self.controller, "missing device id\n");
52 return -EINVAL;
53 }
54
55 switch (id->driver_data) {
56 case EHCI_ATH79_IP_V1:
57 ehci->has_synopsys_hc_bug = 1;
58
59 ehci->caps = hcd->regs;
60 ehci->regs = hcd->regs +
61 HC_LENGTH(ehci,
62 ehci_readl(ehci, &ehci->caps->hc_capbase));
63 break;
64
65 case EHCI_ATH79_IP_V2:
66 hcd->has_tt = 1;
67
68 ehci->caps = hcd->regs + 0x100;
69 ehci->regs = hcd->regs + 0x100 +
70 HC_LENGTH(ehci,
71 ehci_readl(ehci, &ehci->caps->hc_capbase));
72 break;
73
74 default:
75 BUG();
76 }
77
78 dbg_hcs_params(ehci, "reset");
79 dbg_hcc_params(ehci, "reset");
80 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
81 ehci->sbrn = 0x20;
82
83 ehci_reset(ehci);
84
85 ret = ehci_init(hcd);
86 if (ret)
87 return ret;
88
89 ehci_port_power(ehci, 0);
90
91 return 0;
92}
93
94static const struct hc_driver ehci_ath79_hc_driver = {
95 .description = hcd_name,
96 .product_desc = "Atheros built-in EHCI controller",
97 .hcd_priv_size = sizeof(struct ehci_hcd),
98 .irq = ehci_irq,
99 .flags = HCD_MEMORY | HCD_USB2,
100
101 .reset = ehci_ath79_init,
102 .start = ehci_run,
103 .stop = ehci_stop,
104 .shutdown = ehci_shutdown,
105
106 .urb_enqueue = ehci_urb_enqueue,
107 .urb_dequeue = ehci_urb_dequeue,
108 .endpoint_disable = ehci_endpoint_disable,
109 .endpoint_reset = ehci_endpoint_reset,
110
111 .get_frame_number = ehci_get_frame,
112
113 .hub_status_data = ehci_hub_status_data,
114 .hub_control = ehci_hub_control,
115
116 .relinquish_port = ehci_relinquish_port,
117 .port_handed_over = ehci_port_handed_over,
118
119 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
120};
121
122static int ehci_ath79_probe(struct platform_device *pdev)
123{
124 struct usb_hcd *hcd;
125 struct resource *res;
126 int irq;
127 int ret;
128
129 if (usb_disabled())
130 return -ENODEV;
131
132 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
133 if (!res) {
134 dev_dbg(&pdev->dev, "no IRQ specified\n");
135 return -ENODEV;
136 }
137 irq = res->start;
138
139 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
140 if (!res) {
141 dev_dbg(&pdev->dev, "no base address specified\n");
142 return -ENODEV;
143 }
144
145 hcd = usb_create_hcd(&ehci_ath79_hc_driver, &pdev->dev,
146 dev_name(&pdev->dev));
147 if (!hcd)
148 return -ENOMEM;
149
150 hcd->rsrc_start = res->start;
151 hcd->rsrc_len = resource_size(res);
152
153 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
154 dev_dbg(&pdev->dev, "controller already in use\n");
155 ret = -EBUSY;
156 goto err_put_hcd;
157 }
158
159 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
160 if (!hcd->regs) {
161 dev_dbg(&pdev->dev, "error mapping memory\n");
162 ret = -EFAULT;
163 goto err_release_region;
164 }
165
166 ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
167 if (ret)
168 goto err_iounmap;
169
170 return 0;
171
172err_iounmap:
173 iounmap(hcd->regs);
174
175err_release_region:
176 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
177err_put_hcd:
178 usb_put_hcd(hcd);
179 return ret;
180}
181
182static int ehci_ath79_remove(struct platform_device *pdev)
183{
184 struct usb_hcd *hcd = platform_get_drvdata(pdev);
185
186 usb_remove_hcd(hcd);
187 iounmap(hcd->regs);
188 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
189 usb_put_hcd(hcd);
190
191 return 0;
192}
193
194static struct platform_driver ehci_ath79_driver = {
195 .probe = ehci_ath79_probe,
196 .remove = ehci_ath79_remove,
197 .id_table = ehci_ath79_id_table,
198 .driver = {
199 .owner = THIS_MODULE,
200 .name = "ath79-ehci",
201 }
202};
203
204MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ehci");
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
new file mode 100644
index 00000000000..42ae5740990
--- /dev/null
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -0,0 +1,323 @@
1/*
2 * EHCI HCD (Host Controller Driver) for USB.
3 *
4 * Bus Glue for AMD Alchemy Au1xxx
5 *
6 * Based on "ohci-au1xxx.c" by Matt Porter <mporter@kernel.crashing.org>
7 *
8 * Modified for AMD Alchemy Au1200 EHC
9 * by K.Boge <karsten.boge@amd.com>
10 *
11 * This file is licenced under the GPL.
12 */
13
14#include <linux/platform_device.h>
15#include <asm/mach-au1x00/au1000.h>
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
40extern int usb_disabled(void);
41
42static 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
55static 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
72static int au1xxx_ehci_setup(struct usb_hcd *hcd)
73{
74 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
75 int ret = ehci_init(hcd);
76
77 ehci->need_io_watchdog = 0;
78 return ret;
79}
80
81static const struct hc_driver ehci_au1xxx_hc_driver = {
82 .description = hcd_name,
83 .product_desc = "Au1xxx EHCI",
84 .hcd_priv_size = sizeof(struct ehci_hcd),
85
86 /*
87 * generic hardware linkage
88 */
89 .irq = ehci_irq,
90 .flags = HCD_MEMORY | HCD_USB2,
91
92 /*
93 * basic lifecycle operations
94 *
95 * FIXME -- ehci_init() doesn't do enough here.
96 * See ehci-ppc-soc for a complete implementation.
97 */
98 .reset = au1xxx_ehci_setup,
99 .start = ehci_run,
100 .stop = ehci_stop,
101 .shutdown = ehci_shutdown,
102
103 /*
104 * managing i/o requests and associated device resources
105 */
106 .urb_enqueue = ehci_urb_enqueue,
107 .urb_dequeue = ehci_urb_dequeue,
108 .endpoint_disable = ehci_endpoint_disable,
109 .endpoint_reset = ehci_endpoint_reset,
110
111 /*
112 * scheduling support
113 */
114 .get_frame_number = ehci_get_frame,
115
116 /*
117 * root hub support
118 */
119 .hub_status_data = ehci_hub_status_data,
120 .hub_control = ehci_hub_control,
121 .bus_suspend = ehci_bus_suspend,
122 .bus_resume = ehci_bus_resume,
123 .relinquish_port = ehci_relinquish_port,
124 .port_handed_over = ehci_port_handed_over,
125
126 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
127};
128
129static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
130{
131 struct usb_hcd *hcd;
132 struct ehci_hcd *ehci;
133 struct resource *res;
134 int ret;
135
136 if (usb_disabled())
137 return -ENODEV;
138
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) {
150 pr_debug("resource[1] is not IORESOURCE_IRQ");
151 return -ENOMEM;
152 }
153 hcd = usb_create_hcd(&ehci_au1xxx_hc_driver, &pdev->dev, "Au1xxx");
154 if (!hcd)
155 return -ENOMEM;
156
157 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
158 hcd->rsrc_start = res->start;
159 hcd->rsrc_len = resource_size(res);
160
161 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
162 pr_debug("request_mem_region failed");
163 ret = -EBUSY;
164 goto err1;
165 }
166
167 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
168 if (!hcd->regs) {
169 pr_debug("ioremap failed");
170 ret = -ENOMEM;
171 goto err2;
172 }
173
174 au1xxx_start_ehc();
175
176 ehci = hcd_to_ehci(hcd);
177 ehci->caps = hcd->regs;
178 ehci->regs = hcd->regs +
179 HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
180 /* cache this readonly data; minimize chip reads */
181 ehci->hcs_params = readl(&ehci->caps->hcs_params);
182
183 ret = usb_add_hcd(hcd, pdev->resource[1].start,
184 IRQF_DISABLED | IRQF_SHARED);
185 if (ret == 0) {
186 platform_set_drvdata(pdev, hcd);
187 return ret;
188 }
189
190 au1xxx_stop_ehc();
191 iounmap(hcd->regs);
192err2:
193 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
194err1:
195 usb_put_hcd(hcd);
196 return ret;
197}
198
199static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
200{
201 struct usb_hcd *hcd = platform_get_drvdata(pdev);
202
203 usb_remove_hcd(hcd);
204 iounmap(hcd->regs);
205 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
206 usb_put_hcd(hcd);
207 au1xxx_stop_ehc();
208 platform_set_drvdata(pdev, NULL);
209
210 return 0;
211}
212
213#ifdef CONFIG_PM
214static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
215{
216 struct usb_hcd *hcd = dev_get_drvdata(dev);
217 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
218 unsigned long flags;
219 int rc = 0;
220
221 if (time_before(jiffies, ehci->next_statechange))
222 msleep(10);
223
224 /* Root hub was already suspended. Disable irq emission and
225 * mark HW unaccessible. The PM and USB cores make sure that
226 * the root hub is either suspended or stopped.
227 */
228 ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
229 spin_lock_irqsave(&ehci->lock, flags);
230 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
231 (void)ehci_readl(ehci, &ehci->regs->intr_enable);
232
233 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
234 spin_unlock_irqrestore(&ehci->lock, flags);
235
236 // could save FLADJ in case of Vaux power loss
237 // ... we'd only use it to handle clock skew
238
239 au1xxx_stop_ehc();
240
241 return rc;
242}
243
244static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
245{
246 struct usb_hcd *hcd = dev_get_drvdata(dev);
247 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
248
249 au1xxx_start_ehc();
250
251 // maybe restore FLADJ
252
253 if (time_before(jiffies, ehci->next_statechange))
254 msleep(100);
255
256 /* Mark hardware accessible again as we are out of D3 state by now */
257 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
258
259 /* If CF is still set, we maintained PCI Vaux power.
260 * Just undo the effect of ehci_pci_suspend().
261 */
262 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
263 int mask = INTR_MASK;
264
265 ehci_prepare_ports_for_controller_resume(ehci);
266 if (!hcd->self.root_hub->do_remote_wakeup)
267 mask &= ~STS_PCD;
268 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
269 ehci_readl(ehci, &ehci->regs->intr_enable);
270 return 0;
271 }
272
273 ehci_dbg(ehci, "lost power, restarting\n");
274 usb_root_hub_lost_power(hcd->self.root_hub);
275
276 /* Else reset, to cope with power loss or flush-to-storage
277 * style "resume" having let BIOS kick in during reboot.
278 */
279 (void) ehci_halt(ehci);
280 (void) ehci_reset(ehci);
281
282 /* emptying the schedule aborts any urbs */
283 spin_lock_irq(&ehci->lock);
284 if (ehci->reclaim)
285 end_unlink_async(ehci);
286 ehci_work(ehci);
287 spin_unlock_irq(&ehci->lock);
288
289 ehci_writel(ehci, ehci->command, &ehci->regs->command);
290 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
291 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
292
293 /* here we "know" root ports should always stay powered */
294 ehci_port_power(ehci, 1);
295
296 hcd->state = HC_STATE_SUSPENDED;
297
298 return 0;
299}
300
301static const struct dev_pm_ops au1xxx_ehci_pmops = {
302 .suspend = ehci_hcd_au1xxx_drv_suspend,
303 .resume = ehci_hcd_au1xxx_drv_resume,
304};
305
306#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops
307
308#else
309#define AU1XXX_EHCI_PMOPS NULL
310#endif
311
312static struct platform_driver ehci_hcd_au1xxx_driver = {
313 .probe = ehci_hcd_au1xxx_drv_probe,
314 .remove = ehci_hcd_au1xxx_drv_remove,
315 .shutdown = usb_hcd_platform_shutdown,
316 .driver = {
317 .name = "au1xxx-ehci",
318 .owner = THIS_MODULE,
319 .pm = AU1XXX_EHCI_PMOPS,
320 }
321};
322
323MODULE_ALIAS("platform:au1xxx-ehci");
diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c
new file mode 100644
index 00000000000..6536abdea6e
--- /dev/null
+++ b/drivers/usb/host/ehci-cns3xxx.c
@@ -0,0 +1,171 @@
1/*
2 * Copyright 2008 Cavium Networks
3 *
4 * This file is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, Version 2, as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/platform_device.h>
10#include <linux/atomic.h>
11#include <mach/cns3xxx.h>
12#include <mach/pm.h>
13
14static int cns3xxx_ehci_init(struct usb_hcd *hcd)
15{
16 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
17 int retval;
18
19 /*
20 * EHCI and OHCI share the same clock and power,
21 * resetting twice would cause the 1st controller been reset.
22 * Therefore only do power up at the first up device, and
23 * power down at the last down device.
24 *
25 * Set USB AHB INCR length to 16
26 */
27 if (atomic_inc_return(&usb_pwr_ref) == 1) {
28 cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
29 cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
30 cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
31 __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
32 MISC_CHIP_CONFIG_REG);
33 }
34
35 ehci->caps = hcd->regs;
36 ehci->regs = hcd->regs
37 + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
38 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
39
40 hcd->has_tt = 0;
41 ehci_reset(ehci);
42
43 retval = ehci_init(hcd);
44 if (retval)
45 return retval;
46
47 ehci_port_power(ehci, 0);
48
49 return retval;
50}
51
52static const struct hc_driver cns3xxx_ehci_hc_driver = {
53 .description = hcd_name,
54 .product_desc = "CNS3XXX EHCI Host Controller",
55 .hcd_priv_size = sizeof(struct ehci_hcd),
56 .irq = ehci_irq,
57 .flags = HCD_MEMORY | HCD_USB2,
58 .reset = cns3xxx_ehci_init,
59 .start = ehci_run,
60 .stop = ehci_stop,
61 .shutdown = ehci_shutdown,
62 .urb_enqueue = ehci_urb_enqueue,
63 .urb_dequeue = ehci_urb_dequeue,
64 .endpoint_disable = ehci_endpoint_disable,
65 .endpoint_reset = ehci_endpoint_reset,
66 .get_frame_number = ehci_get_frame,
67 .hub_status_data = ehci_hub_status_data,
68 .hub_control = ehci_hub_control,
69#ifdef CONFIG_PM
70 .bus_suspend = ehci_bus_suspend,
71 .bus_resume = ehci_bus_resume,
72#endif
73 .relinquish_port = ehci_relinquish_port,
74 .port_handed_over = ehci_port_handed_over,
75
76 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
77};
78
79static int cns3xxx_ehci_probe(struct platform_device *pdev)
80{
81 struct device *dev = &pdev->dev;
82 struct usb_hcd *hcd;
83 const struct hc_driver *driver = &cns3xxx_ehci_hc_driver;
84 struct resource *res;
85 int irq;
86 int retval;
87
88 if (usb_disabled())
89 return -ENODEV;
90
91 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
92 if (!res) {
93 dev_err(dev, "Found HC with no IRQ.\n");
94 return -ENODEV;
95 }
96 irq = res->start;
97
98 hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
99 if (!hcd)
100 return -ENOMEM;
101
102 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
103 if (!res) {
104 dev_err(dev, "Found HC with no register addr.\n");
105 retval = -ENODEV;
106 goto err1;
107 }
108
109 hcd->rsrc_start = res->start;
110 hcd->rsrc_len = resource_size(res);
111
112 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
113 driver->description)) {
114 dev_dbg(dev, "controller already in use\n");
115 retval = -EBUSY;
116 goto err1;
117 }
118
119 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
120 if (hcd->regs == NULL) {
121 dev_dbg(dev, "error mapping memory\n");
122 retval = -EFAULT;
123 goto err2;
124 }
125
126 retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
127 if (retval == 0)
128 return retval;
129
130 iounmap(hcd->regs);
131err2:
132 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
133err1:
134 usb_put_hcd(hcd);
135
136 return retval;
137}
138
139static int cns3xxx_ehci_remove(struct platform_device *pdev)
140{
141 struct usb_hcd *hcd = platform_get_drvdata(pdev);
142
143 usb_remove_hcd(hcd);
144 iounmap(hcd->regs);
145 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
146
147 /*
148 * EHCI and OHCI share the same clock and power,
149 * resetting twice would cause the 1st controller been reset.
150 * Therefore only do power up at the first up device, and
151 * power down at the last down device.
152 */
153 if (atomic_dec_return(&usb_pwr_ref) == 0)
154 cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
155
156 usb_put_hcd(hcd);
157
158 platform_set_drvdata(pdev, NULL);
159
160 return 0;
161}
162
163MODULE_ALIAS("platform:cns3xxx-ehci");
164
165static struct platform_driver cns3xxx_ehci_driver = {
166 .probe = cns3xxx_ehci_probe,
167 .remove = cns3xxx_ehci_remove,
168 .driver = {
169 .name = "cns3xxx-ehci",
170 },
171};
diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c
new file mode 100644
index 00000000000..c4460f3d009
--- /dev/null
+++ b/drivers/usb/host/ehci-ixp4xx.c
@@ -0,0 +1,156 @@
1/*
2 * IXP4XX EHCI Host Controller Driver
3 *
4 * Author: Vladimir Barinov <vbarinov@embeddedalley.com>
5 *
6 * Based on "ehci-fsl.c" by Randy Vinson <rvinson@mvista.com>
7 *
8 * 2007 (c) MontaVista Software, Inc. This file is licensed under
9 * the terms of the GNU General Public License version 2. This program
10 * is licensed "as is" without any warranty of any kind, whether express
11 * or implied.
12 */
13
14#include <linux/platform_device.h>
15
16static int ixp4xx_ehci_init(struct usb_hcd *hcd)
17{
18 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
19 int retval = 0;
20
21 ehci->big_endian_desc = 1;
22 ehci->big_endian_mmio = 1;
23
24 ehci->caps = hcd->regs + 0x100;
25 ehci->regs = hcd->regs + 0x100
26 + HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
27 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
28
29 hcd->has_tt = 1;
30 ehci_reset(ehci);
31
32 retval = ehci_init(hcd);
33 if (retval)
34 return retval;
35
36 ehci_port_power(ehci, 0);
37
38 return retval;
39}
40
41static const struct hc_driver ixp4xx_ehci_hc_driver = {
42 .description = hcd_name,
43 .product_desc = "IXP4XX EHCI Host Controller",
44 .hcd_priv_size = sizeof(struct ehci_hcd),
45 .irq = ehci_irq,
46 .flags = HCD_MEMORY | HCD_USB2,
47 .reset = ixp4xx_ehci_init,
48 .start = ehci_run,
49 .stop = ehci_stop,
50 .shutdown = ehci_shutdown,
51 .urb_enqueue = ehci_urb_enqueue,
52 .urb_dequeue = ehci_urb_dequeue,
53 .endpoint_disable = ehci_endpoint_disable,
54 .endpoint_reset = ehci_endpoint_reset,
55 .get_frame_number = ehci_get_frame,
56 .hub_status_data = ehci_hub_status_data,
57 .hub_control = ehci_hub_control,
58#if defined(CONFIG_PM)
59 .bus_suspend = ehci_bus_suspend,
60 .bus_resume = ehci_bus_resume,
61#endif
62 .relinquish_port = ehci_relinquish_port,
63 .port_handed_over = ehci_port_handed_over,
64
65 .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
66};
67
68static int ixp4xx_ehci_probe(struct platform_device *pdev)
69{
70 struct usb_hcd *hcd;
71 const struct hc_driver *driver = &ixp4xx_ehci_hc_driver;
72 struct resource *res;
73 int irq;
74 int retval;
75
76 if (usb_disabled())
77 return -ENODEV;
78
79 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
80 if (!res) {
81 dev_err(&pdev->dev,
82 "Found HC with no IRQ. Check %s setup!\n",
83 dev_name(&pdev->dev));
84 return -ENODEV;
85 }
86 irq = res->start;
87
88 hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
89 if (!hcd) {
90 retval = -ENOMEM;
91 goto fail_create_hcd;
92 }
93
94 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
95 if (!res) {
96 dev_err(&pdev->dev,
97 "Found HC with no register addr. Check %s setup!\n",
98 dev_name(&pdev->dev));
99 retval = -ENODEV;
100 goto fail_request_resource;
101 }
102 hcd->rsrc_start = res->start;
103 hcd->rsrc_len = resource_size(res);
104
105 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
106 driver->description)) {
107 dev_dbg(&pdev->dev, "controller already in use\n");
108 retval = -EBUSY;
109 goto fail_request_resource;
110 }
111
112 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
113 if (hcd->regs == NULL) {
114 dev_dbg(&pdev->dev, "error mapping memory\n");
115 retval = -EFAULT;
116 goto fail_ioremap;
117 }
118
119 retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
120 if (retval)
121 goto fail_add_hcd;
122
123 return retval;
124
125fail_add_hcd:
126 iounmap(hcd->regs);
127fail_ioremap:
128 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
129fail_request_resource:
130 usb_put_hcd(hcd);
131fail_create_hcd:
132 dev_err(&pdev->dev, "init %s fail, %d\n", dev_name(&pdev->dev), retval);
133 return retval;
134}
135
136static int ixp4xx_ehci_remove(struct platform_device *pdev)
137{
138 struct usb_hcd *hcd = platform_get_drvdata(pdev);
139
140 usb_remove_hcd(hcd);
141 iounmap(hcd->regs);
142 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
143 usb_put_hcd(hcd);
144
145 return 0;
146}
147
148MODULE_ALIAS("platform:ixp4xx-ehci");
149
150static struct platform_driver ixp4xx_ehci_driver = {
151 .probe = ixp4xx_ehci_probe,
152 .remove = ixp4xx_ehci_remove,
153 .driver = {
154 .name = "ixp4xx-ehci",
155 },
156};
diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c
new file mode 100644
index 00000000000..2111627a19d
--- /dev/null
+++ b/drivers/usb/host/ehci-lpm.c
@@ -0,0 +1,84 @@
1/* ehci-lpm.c EHCI HCD LPM support code
2 * Copyright (c) 2008 - 2010, Intel Corporation.
3 * Author: Jacob Pan <jacob.jun.pan@intel.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
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
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17*/
18
19/* this file is part of ehci-hcd.c */
20static int __maybe_unused ehci_lpm_set_da(struct ehci_hcd *ehci,
21 int dev_addr, int port_num)
22{
23 u32 __iomem portsc;
24
25 ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num);
26 if (port_num > HCS_N_PORTS(ehci->hcs_params)) {
27 ehci_dbg(ehci, "invalid port number %d\n", port_num);
28 return -ENODEV;
29 }
30 portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]);
31 portsc &= ~PORT_DEV_ADDR;
32 portsc |= dev_addr<<25;
33 ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]);
34 return 0;
35}
36
37/*
38 * this function is used to check if the device support LPM
39 * if yes, mark the PORTSC register with PORT_LPM bit
40 */
41static int __maybe_unused ehci_lpm_check(struct ehci_hcd *ehci, int port)
42{
43 u32 __iomem *portsc ;
44 u32 val32;
45 int retval;
46
47 portsc = &ehci->regs->port_status[port-1];
48 val32 = ehci_readl(ehci, portsc);
49 if (!(val32 & PORT_DEV_ADDR)) {
50 ehci_dbg(ehci, "LPM: no device attached\n");
51 return -ENODEV;
52 }
53 val32 |= PORT_LPM;
54 ehci_writel(ehci, val32, portsc);
55 msleep(5);
56 val32 |= PORT_SUSPEND;
57 ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port);
58 ehci_writel(ehci, val32, portsc);
59 /* wait for ACK */
60 msleep(10);
61 retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS,
62 PORTSC_SUSPEND_STS_ACK, 125);
63 dbg_port(ehci, "LPM", port, val32);
64 if (retval != -ETIMEDOUT) {
65 ehci_dbg(ehci, "LPM: device ACK for LPM\n");
66 val32 |= PORT_LPM;
67 /*
68 * now device should be in L1 sleep, let's wake up the device
69 * so that we can complete enumeration.
70 */
71 ehci_writel(ehci, val32, portsc);
72 msleep(10);
73 val32 |= PORT_RESUME;
74 ehci_writel(ehci, val32, portsc);
75 } else {
76 ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n",
77 retval);
78 val32 &= ~PORT_LPM;
79 retval = -ETIMEDOUT;
80 ehci_writel(ehci, val32, portsc);
81 }
82
83 return retval;
84}
diff --git a/drivers/usb/host/ohci-ath79.c b/drivers/usb/host/ohci-ath79.c
new file mode 100644
index 00000000000..c620c50f677
--- /dev/null
+++ b/drivers/usb/host/ohci-ath79.c
@@ -0,0 +1,151 @@
1/*
2 * OHCI HCD (Host Controller Driver) for USB.
3 *
4 * Bus Glue for Atheros AR71XX/AR724X built-in OHCI controller.
5 *
6 * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
7 * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
8 *
9 * Parts of this file are based on Atheros' 2.6.15 BSP
10 * Copyright (C) 2007 Atheros Communications, Inc.
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License version 2 as published
14 * by the Free Software Foundation.
15 */
16
17#include <linux/platform_device.h>
18
19static int __devinit ohci_ath79_start(struct usb_hcd *hcd)
20{
21 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
22 int ret;
23
24 ret = ohci_init(ohci);
25 if (ret < 0)
26 return ret;
27
28 ret = ohci_run(ohci);
29 if (ret < 0)
30 goto err;
31
32 return 0;
33
34err:
35 ohci_stop(hcd);
36 return ret;
37}
38
39static const struct hc_driver ohci_ath79_hc_driver = {
40 .description = hcd_name,
41 .product_desc = "Atheros built-in OHCI controller",
42 .hcd_priv_size = sizeof(struct ohci_hcd),
43
44 .irq = ohci_irq,
45 .flags = HCD_USB11 | HCD_MEMORY,
46
47 .start = ohci_ath79_start,
48 .stop = ohci_stop,
49 .shutdown = ohci_shutdown,
50
51 .urb_enqueue = ohci_urb_enqueue,
52 .urb_dequeue = ohci_urb_dequeue,
53 .endpoint_disable = ohci_endpoint_disable,
54
55 /*
56 * scheduling support
57 */
58 .get_frame_number = ohci_get_frame,
59
60 /*
61 * root hub support
62 */
63 .hub_status_data = ohci_hub_status_data,
64 .hub_control = ohci_hub_control,
65 .start_port_reset = ohci_start_port_reset,
66};
67
68static int ohci_ath79_probe(struct platform_device *pdev)
69{
70 struct usb_hcd *hcd;
71 struct resource *res;
72 int irq;
73 int ret;
74
75 if (usb_disabled())
76 return -ENODEV;
77
78 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
79 if (!res) {
80 dev_dbg(&pdev->dev, "no IRQ specified\n");
81 return -ENODEV;
82 }
83 irq = res->start;
84
85 hcd = usb_create_hcd(&ohci_ath79_hc_driver, &pdev->dev,
86 dev_name(&pdev->dev));
87 if (!hcd)
88 return -ENOMEM;
89
90 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
91 if (!res) {
92 dev_dbg(&pdev->dev, "no base address specified\n");
93 ret = -ENODEV;
94 goto err_put_hcd;
95 }
96 hcd->rsrc_start = res->start;
97 hcd->rsrc_len = resource_size(res);
98
99 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
100 dev_dbg(&pdev->dev, "controller already in use\n");
101 ret = -EBUSY;
102 goto err_put_hcd;
103 }
104
105 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
106 if (!hcd->regs) {
107 dev_dbg(&pdev->dev, "error mapping memory\n");
108 ret = -EFAULT;
109 goto err_release_region;
110 }
111
112 ohci_hcd_init(hcd_to_ohci(hcd));
113
114 ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
115 if (ret)
116 goto err_stop_hcd;
117
118 return 0;
119
120err_stop_hcd:
121 iounmap(hcd->regs);
122err_release_region:
123 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
124err_put_hcd:
125 usb_put_hcd(hcd);
126 return ret;
127}
128
129static int ohci_ath79_remove(struct platform_device *pdev)
130{
131 struct usb_hcd *hcd = platform_get_drvdata(pdev);
132
133 usb_remove_hcd(hcd);
134 iounmap(hcd->regs);
135 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
136 usb_put_hcd(hcd);
137
138 return 0;
139}
140
141static struct platform_driver ohci_hcd_ath79_driver = {
142 .probe = ohci_ath79_probe,
143 .remove = ohci_ath79_remove,
144 .shutdown = usb_hcd_platform_shutdown,
145 .driver = {
146 .name = "ath79-ohci",
147 .owner = THIS_MODULE,
148 },
149};
150
151MODULE_ALIAS(PLATFORM_MODULE_PREFIX "ath79-ohci");
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
new file mode 100644
index 00000000000..958d985f295
--- /dev/null
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -0,0 +1,319 @@
1/*
2 * OHCI HCD (Host Controller Driver) for USB.
3 *
4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
5 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
6 * (C) Copyright 2002 Hewlett-Packard Company
7 *
8 * Bus Glue for AMD Alchemy Au1xxx
9 *
10 * Written by Christopher Hoover <ch@hpl.hp.com>
11 * Based on fragments of previous driver by Russell King et al.
12 *
13 * Modified for LH7A404 from ohci-sa1111.c
14 * by Durgesh Pattamatta <pattamattad@sharpsec.com>
15 * Modified for AMD Alchemy Au1xxx
16 * by Matt Porter <mporter@kernel.crashing.org>
17 *
18 * This file is licenced under the GPL.
19 */
20
21#include <linux/platform_device.h>
22#include <linux/signal.h>
23
24#include <asm/mach-au1x00/au1000.h>
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
69extern int usb_disabled(void);
70
71static 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
99static 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
112static int __devinit ohci_au1xxx_start(struct usb_hcd *hcd)
113{
114 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
115 int ret;
116
117 ohci_dbg(ohci, "ohci_au1xxx_start, ohci:%p", ohci);
118
119 if ((ret = ohci_init(ohci)) < 0)
120 return ret;
121
122 if ((ret = ohci_run(ohci)) < 0) {
123 err ("can't start %s", hcd->self.bus_name);
124 ohci_stop(hcd);
125 return ret;
126 }
127
128 return 0;
129}
130
131static const struct hc_driver ohci_au1xxx_hc_driver = {
132 .description = hcd_name,
133 .product_desc = "Au1xxx OHCI",
134 .hcd_priv_size = sizeof(struct ohci_hcd),
135
136 /*
137 * generic hardware linkage
138 */
139 .irq = ohci_irq,
140 .flags = HCD_USB11 | HCD_MEMORY,
141
142 /*
143 * basic lifecycle operations
144 */
145 .start = ohci_au1xxx_start,
146 .stop = ohci_stop,
147 .shutdown = ohci_shutdown,
148
149 /*
150 * managing i/o requests and associated device resources
151 */
152 .urb_enqueue = ohci_urb_enqueue,
153 .urb_dequeue = ohci_urb_dequeue,
154 .endpoint_disable = ohci_endpoint_disable,
155
156 /*
157 * scheduling support
158 */
159 .get_frame_number = ohci_get_frame,
160
161 /*
162 * root hub support
163 */
164 .hub_status_data = ohci_hub_status_data,
165 .hub_control = ohci_hub_control,
166#ifdef CONFIG_PM
167 .bus_suspend = ohci_bus_suspend,
168 .bus_resume = ohci_bus_resume,
169#endif
170 .start_port_reset = ohci_start_port_reset,
171};
172
173static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
174{
175 int ret;
176 struct usb_hcd *hcd;
177
178 if (usb_disabled())
179 return -ENODEV;
180
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) {
193 pr_debug("resource[1] is not IORESOURCE_IRQ\n");
194 return -ENOMEM;
195 }
196
197 hcd = usb_create_hcd(&ohci_au1xxx_hc_driver, &pdev->dev, "au1xxx");
198 if (!hcd)
199 return -ENOMEM;
200
201 hcd->rsrc_start = pdev->resource[0].start;
202 hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
203
204 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
205 pr_debug("request_mem_region failed\n");
206 ret = -EBUSY;
207 goto err1;
208 }
209
210 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
211 if (!hcd->regs) {
212 pr_debug("ioremap failed\n");
213 ret = -ENOMEM;
214 goto err2;
215 }
216
217 au1xxx_start_ohc();
218 ohci_hcd_init(hcd_to_ohci(hcd));
219
220 ret = usb_add_hcd(hcd, pdev->resource[1].start,
221 IRQF_DISABLED | IRQF_SHARED);
222 if (ret == 0) {
223 platform_set_drvdata(pdev, hcd);
224 return ret;
225 }
226
227 au1xxx_stop_ohc();
228 iounmap(hcd->regs);
229err2:
230 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
231err1:
232 usb_put_hcd(hcd);
233 return ret;
234}
235
236static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
237{
238 struct usb_hcd *hcd = platform_get_drvdata(pdev);
239
240 usb_remove_hcd(hcd);
241 au1xxx_stop_ohc();
242 iounmap(hcd->regs);
243 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
244 usb_put_hcd(hcd);
245 platform_set_drvdata(pdev, NULL);
246
247 return 0;
248}
249
250#ifdef CONFIG_PM
251static int ohci_hcd_au1xxx_drv_suspend(struct device *dev)
252{
253 struct usb_hcd *hcd = dev_get_drvdata(dev);
254 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
255 unsigned long flags;
256 int rc;
257
258 rc = 0;
259
260 /* Root hub was already suspended. Disable irq emission and
261 * mark HW unaccessible, bail out if RH has been resumed. Use
262 * the spinlock to properly synchronize with possible pending
263 * RH suspend or resume activity.
264 *
265 * This is still racy as hcd->state is manipulated outside of
266 * any locks =P But that will be a different fix.
267 */
268 spin_lock_irqsave(&ohci->lock, flags);
269 if (hcd->state != HC_STATE_SUSPENDED) {
270 rc = -EINVAL;
271 goto bail;
272 }
273 ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
274 (void)ohci_readl(ohci, &ohci->regs->intrdisable);
275
276 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
277
278 au1xxx_stop_ohc();
279bail:
280 spin_unlock_irqrestore(&ohci->lock, flags);
281
282 return rc;
283}
284
285static int ohci_hcd_au1xxx_drv_resume(struct device *dev)
286{
287 struct usb_hcd *hcd = dev_get_drvdata(dev);
288
289 au1xxx_start_ohc();
290
291 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
292 ohci_finish_controller_resume(hcd);
293
294 return 0;
295}
296
297static const struct dev_pm_ops au1xxx_ohci_pmops = {
298 .suspend = ohci_hcd_au1xxx_drv_suspend,
299 .resume = ohci_hcd_au1xxx_drv_resume,
300};
301
302#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops
303
304#else
305#define AU1XXX_OHCI_PMOPS NULL
306#endif
307
308static struct platform_driver ohci_hcd_au1xxx_driver = {
309 .probe = ohci_hcd_au1xxx_drv_probe,
310 .remove = ohci_hcd_au1xxx_drv_remove,
311 .shutdown = usb_hcd_platform_shutdown,
312 .driver = {
313 .name = "au1xxx-ohci",
314 .owner = THIS_MODULE,
315 .pm = AU1XXX_OHCI_PMOPS,
316 },
317};
318
319MODULE_ALIAS("platform:au1xxx-ohci");
diff --git a/drivers/usb/host/ohci-cns3xxx.c b/drivers/usb/host/ohci-cns3xxx.c
new file mode 100644
index 00000000000..5a00a1e1c6c
--- /dev/null
+++ b/drivers/usb/host/ohci-cns3xxx.c
@@ -0,0 +1,165 @@
1/*
2 * Copyright 2008 Cavium Networks
3 *
4 * This file is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, Version 2, as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/platform_device.h>
10#include <linux/atomic.h>
11#include <mach/cns3xxx.h>
12#include <mach/pm.h>
13
14static int __devinit
15cns3xxx_ohci_start(struct usb_hcd *hcd)
16{
17 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
18 int ret;
19
20 /*
21 * EHCI and OHCI share the same clock and power,
22 * resetting twice would cause the 1st controller been reset.
23 * Therefore only do power up at the first up device, and
24 * power down at the last down device.
25 *
26 * Set USB AHB INCR length to 16
27 */
28 if (atomic_inc_return(&usb_pwr_ref) == 1) {
29 cns3xxx_pwr_power_up(1 << PM_PLL_HM_PD_CTRL_REG_OFFSET_PLL_USB);
30 cns3xxx_pwr_clk_en(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
31 cns3xxx_pwr_soft_rst(1 << PM_SOFT_RST_REG_OFFST_USB_HOST);
32 __raw_writel((__raw_readl(MISC_CHIP_CONFIG_REG) | (0X2 << 24)),
33 MISC_CHIP_CONFIG_REG);
34 }
35
36 ret = ohci_init(ohci);
37 if (ret < 0)
38 return ret;
39
40 ohci->num_ports = 1;
41
42 ret = ohci_run(ohci);
43 if (ret < 0) {
44 err("can't start %s", hcd->self.bus_name);
45 ohci_stop(hcd);
46 return ret;
47 }
48 return 0;
49}
50
51static const struct hc_driver cns3xxx_ohci_hc_driver = {
52 .description = hcd_name,
53 .product_desc = "CNS3XXX OHCI Host controller",
54 .hcd_priv_size = sizeof(struct ohci_hcd),
55 .irq = ohci_irq,
56 .flags = HCD_USB11 | HCD_MEMORY,
57 .start = cns3xxx_ohci_start,
58 .stop = ohci_stop,
59 .shutdown = ohci_shutdown,
60 .urb_enqueue = ohci_urb_enqueue,
61 .urb_dequeue = ohci_urb_dequeue,
62 .endpoint_disable = ohci_endpoint_disable,
63 .get_frame_number = ohci_get_frame,
64 .hub_status_data = ohci_hub_status_data,
65 .hub_control = ohci_hub_control,
66#ifdef CONFIG_PM
67 .bus_suspend = ohci_bus_suspend,
68 .bus_resume = ohci_bus_resume,
69#endif
70 .start_port_reset = ohci_start_port_reset,
71};
72
73static int cns3xxx_ohci_probe(struct platform_device *pdev)
74{
75 struct device *dev = &pdev->dev;
76 struct usb_hcd *hcd;
77 const struct hc_driver *driver = &cns3xxx_ohci_hc_driver;
78 struct resource *res;
79 int irq;
80 int retval;
81
82 if (usb_disabled())
83 return -ENODEV;
84
85 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
86 if (!res) {
87 dev_err(dev, "Found HC with no IRQ.\n");
88 return -ENODEV;
89 }
90 irq = res->start;
91
92 hcd = usb_create_hcd(driver, dev, dev_name(dev));
93 if (!hcd)
94 return -ENOMEM;
95
96 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
97 if (!res) {
98 dev_err(dev, "Found HC with no register addr.\n");
99 retval = -ENODEV;
100 goto err1;
101 }
102 hcd->rsrc_start = res->start;
103 hcd->rsrc_len = resource_size(res);
104
105 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len,
106 driver->description)) {
107 dev_dbg(dev, "controller already in use\n");
108 retval = -EBUSY;
109 goto err1;
110 }
111
112 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
113 if (!hcd->regs) {
114 dev_dbg(dev, "error mapping memory\n");
115 retval = -EFAULT;
116 goto err2;
117 }
118
119 ohci_hcd_init(hcd_to_ohci(hcd));
120
121 retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
122 if (retval == 0)
123 return retval;
124
125 iounmap(hcd->regs);
126err2:
127 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
128err1:
129 usb_put_hcd(hcd);
130 return retval;
131}
132
133static int cns3xxx_ohci_remove(struct platform_device *pdev)
134{
135 struct usb_hcd *hcd = platform_get_drvdata(pdev);
136
137 usb_remove_hcd(hcd);
138 iounmap(hcd->regs);
139 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
140
141 /*
142 * EHCI and OHCI share the same clock and power,
143 * resetting twice would cause the 1st controller been reset.
144 * Therefore only do power up at the first up device, and
145 * power down at the last down device.
146 */
147 if (atomic_dec_return(&usb_pwr_ref) == 0)
148 cns3xxx_pwr_clk_dis(1 << PM_CLK_GATE_REG_OFFSET_USB_HOST);
149
150 usb_put_hcd(hcd);
151
152 platform_set_drvdata(pdev, NULL);
153
154 return 0;
155}
156
157MODULE_ALIAS("platform:cns3xxx-ohci");
158
159static struct platform_driver ohci_hcd_cns3xxx_driver = {
160 .probe = cns3xxx_ohci_probe,
161 .remove = cns3xxx_ohci_remove,
162 .driver = {
163 .name = "cns3xxx-ohci",
164 },
165};
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
new file mode 100644
index 00000000000..653d6a60edb
--- /dev/null
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -0,0 +1,453 @@
1/*
2 * drivers/usb/host/ohci-pnx4008.c
3 *
4 * driver for Philips PNX4008 USB Host
5 *
6 * Authors: Dmitry Chigirev <source@mvista.com>
7 * Vitaly Wool <vitalywool@gmail.com>
8 *
9 * register initialization is based on code examples provided by Philips
10 * Copyright (c) 2005 Koninklijke Philips Electronics N.V.
11 *
12 * NOTE: This driver does not have suspend/resume functionality
13 * This driver is intended for engineering development purposes only
14 *
15 * 2005-2006 (c) MontaVista Software, Inc. This file is licensed under
16 * the terms of the GNU General Public License version 2. This program
17 * is licensed "as is" without any warranty of any kind, whether express
18 * or implied.
19 */
20#include <linux/clk.h>
21#include <linux/platform_device.h>
22#include <linux/i2c.h>
23
24#include <mach/hardware.h>
25#include <asm/io.h>
26
27#include <mach/platform.h>
28#include <mach/irqs.h>
29#include <mach/gpio.h>
30
31#define USB_CTRL IO_ADDRESS(PNX4008_PWRMAN_BASE + 0x64)
32
33/* USB_CTRL bit defines */
34#define USB_SLAVE_HCLK_EN (1 << 24)
35#define USB_HOST_NEED_CLK_EN (1 << 21)
36
37#define USB_OTG_CLK_CTRL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF4)
38#define USB_OTG_CLK_STAT IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0xFF8)
39
40/* USB_OTG_CLK_CTRL bit defines */
41#define AHB_M_CLOCK_ON (1 << 4)
42#define OTG_CLOCK_ON (1 << 3)
43#define I2C_CLOCK_ON (1 << 2)
44#define DEV_CLOCK_ON (1 << 1)
45#define HOST_CLOCK_ON (1 << 0)
46
47#define USB_OTG_STAT_CONTROL IO_ADDRESS(PNX4008_USB_CONFIG_BASE + 0x110)
48
49/* USB_OTG_STAT_CONTROL bit defines */
50#define TRANSPARENT_I2C_EN (1 << 7)
51#define HOST_EN (1 << 0)
52
53/* ISP1301 USB transceiver I2C registers */
54#define ISP1301_MODE_CONTROL_1 0x04 /* u8 read, set, +1 clear */
55
56#define MC1_SPEED_REG (1 << 0)
57#define MC1_SUSPEND_REG (1 << 1)
58#define MC1_DAT_SE0 (1 << 2)
59#define MC1_TRANSPARENT (1 << 3)
60#define MC1_BDIS_ACON_EN (1 << 4)
61#define MC1_OE_INT_EN (1 << 5)
62#define MC1_UART_EN (1 << 6)
63#define MC1_MASK 0x7f
64
65#define ISP1301_MODE_CONTROL_2 0x12 /* u8 read, set, +1 clear */
66
67#define MC2_GLOBAL_PWR_DN (1 << 0)
68#define MC2_SPD_SUSP_CTRL (1 << 1)
69#define MC2_BI_DI (1 << 2)
70#define MC2_TRANSP_BDIR0 (1 << 3)
71#define MC2_TRANSP_BDIR1 (1 << 4)
72#define MC2_AUDIO_EN (1 << 5)
73#define MC2_PSW_EN (1 << 6)
74#define MC2_EN2V7 (1 << 7)
75
76#define ISP1301_OTG_CONTROL_1 0x06 /* u8 read, set, +1 clear */
77# define OTG1_DP_PULLUP (1 << 0)
78# define OTG1_DM_PULLUP (1 << 1)
79# define OTG1_DP_PULLDOWN (1 << 2)
80# define OTG1_DM_PULLDOWN (1 << 3)
81# define OTG1_ID_PULLDOWN (1 << 4)
82# define OTG1_VBUS_DRV (1 << 5)
83# define OTG1_VBUS_DISCHRG (1 << 6)
84# define OTG1_VBUS_CHRG (1 << 7)
85#define ISP1301_OTG_STATUS 0x10 /* u8 readonly */
86# define OTG_B_SESS_END (1 << 6)
87# define OTG_B_SESS_VLD (1 << 7)
88
89#define ISP1301_I2C_ADDR 0x2C
90
91#define ISP1301_I2C_MODE_CONTROL_1 0x4
92#define ISP1301_I2C_MODE_CONTROL_2 0x12
93#define ISP1301_I2C_OTG_CONTROL_1 0x6
94#define ISP1301_I2C_OTG_CONTROL_2 0x10
95#define ISP1301_I2C_INTERRUPT_SOURCE 0x8
96#define ISP1301_I2C_INTERRUPT_LATCH 0xA
97#define ISP1301_I2C_INTERRUPT_FALLING 0xC
98#define ISP1301_I2C_INTERRUPT_RISING 0xE
99#define ISP1301_I2C_REG_CLEAR_ADDR 1
100
101static struct i2c_driver isp1301_driver;
102static struct i2c_client *isp1301_i2c_client;
103
104extern int usb_disabled(void);
105extern int ocpi_enable(void);
106
107static struct clk *usb_clk;
108
109static const unsigned short normal_i2c[] =
110 { ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END };
111
112static int isp1301_probe(struct i2c_client *client,
113 const struct i2c_device_id *id)
114{
115 return 0;
116}
117
118static int isp1301_remove(struct i2c_client *client)
119{
120 return 0;
121}
122
123static const struct i2c_device_id isp1301_id[] = {
124 { "isp1301_pnx", 0 },
125 { }
126};
127
128static struct i2c_driver isp1301_driver = {
129 .driver = {
130 .name = "isp1301_pnx",
131 },
132 .probe = isp1301_probe,
133 .remove = isp1301_remove,
134 .id_table = isp1301_id,
135};
136
137static void i2c_write(u8 buf, u8 subaddr)
138{
139 char tmpbuf[2];
140
141 tmpbuf[0] = subaddr; /*register number */
142 tmpbuf[1] = buf; /*register data */
143 i2c_master_send(isp1301_i2c_client, &tmpbuf[0], 2);
144}
145
146static void isp1301_configure(void)
147{
148 /* PNX4008 only supports DAT_SE0 USB mode */
149 /* PNX4008 R2A requires setting the MAX603 to output 3.6V */
150 /* Power up externel charge-pump */
151
152 i2c_write(MC1_DAT_SE0 | MC1_SPEED_REG, ISP1301_I2C_MODE_CONTROL_1);
153 i2c_write(~(MC1_DAT_SE0 | MC1_SPEED_REG),
154 ISP1301_I2C_MODE_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
155 i2c_write(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL,
156 ISP1301_I2C_MODE_CONTROL_2);
157 i2c_write(~(MC2_BI_DI | MC2_PSW_EN | MC2_SPD_SUSP_CTRL),
158 ISP1301_I2C_MODE_CONTROL_2 | ISP1301_I2C_REG_CLEAR_ADDR);
159 i2c_write(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN,
160 ISP1301_I2C_OTG_CONTROL_1);
161 i2c_write(~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN),
162 ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
163 i2c_write(0xFF,
164 ISP1301_I2C_INTERRUPT_LATCH | ISP1301_I2C_REG_CLEAR_ADDR);
165 i2c_write(0xFF,
166 ISP1301_I2C_INTERRUPT_FALLING | ISP1301_I2C_REG_CLEAR_ADDR);
167 i2c_write(0xFF,
168 ISP1301_I2C_INTERRUPT_RISING | ISP1301_I2C_REG_CLEAR_ADDR);
169
170}
171
172static inline void isp1301_vbus_on(void)
173{
174 i2c_write(OTG1_VBUS_DRV, ISP1301_I2C_OTG_CONTROL_1);
175}
176
177static inline void isp1301_vbus_off(void)
178{
179 i2c_write(OTG1_VBUS_DRV,
180 ISP1301_I2C_OTG_CONTROL_1 | ISP1301_I2C_REG_CLEAR_ADDR);
181}
182
183static void pnx4008_start_hc(void)
184{
185 unsigned long tmp = __raw_readl(USB_OTG_STAT_CONTROL) | HOST_EN;
186 __raw_writel(tmp, USB_OTG_STAT_CONTROL);
187 isp1301_vbus_on();
188}
189
190static void pnx4008_stop_hc(void)
191{
192 unsigned long tmp;
193 isp1301_vbus_off();
194 tmp = __raw_readl(USB_OTG_STAT_CONTROL) & ~HOST_EN;
195 __raw_writel(tmp, USB_OTG_STAT_CONTROL);
196}
197
198static int __devinit ohci_pnx4008_start(struct usb_hcd *hcd)
199{
200 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
201 int ret;
202
203 if ((ret = ohci_init(ohci)) < 0)
204 return ret;
205
206 if ((ret = ohci_run(ohci)) < 0) {
207 dev_err(hcd->self.controller, "can't start\n");
208 ohci_stop(hcd);
209 return ret;
210 }
211 return 0;
212}
213
214static const struct hc_driver ohci_pnx4008_hc_driver = {
215 .description = hcd_name,
216 .product_desc = "pnx4008 OHCI",
217
218 /*
219 * generic hardware linkage
220 */
221 .irq = ohci_irq,
222 .flags = HCD_USB11 | HCD_MEMORY,
223
224 .hcd_priv_size = sizeof(struct ohci_hcd),
225 /*
226 * basic lifecycle operations
227 */
228 .start = ohci_pnx4008_start,
229 .stop = ohci_stop,
230 .shutdown = ohci_shutdown,
231
232 /*
233 * managing i/o requests and associated device resources
234 */
235 .urb_enqueue = ohci_urb_enqueue,
236 .urb_dequeue = ohci_urb_dequeue,
237 .endpoint_disable = ohci_endpoint_disable,
238
239 /*
240 * scheduling support
241 */
242 .get_frame_number = ohci_get_frame,
243
244 /*
245 * root hub support
246 */
247 .hub_status_data = ohci_hub_status_data,
248 .hub_control = ohci_hub_control,
249#ifdef CONFIG_PM
250 .bus_suspend = ohci_bus_suspend,
251 .bus_resume = ohci_bus_resume,
252#endif
253 .start_port_reset = ohci_start_port_reset,
254};
255
256#define USB_CLOCK_MASK (AHB_M_CLOCK_ON| OTG_CLOCK_ON | HOST_CLOCK_ON | I2C_CLOCK_ON)
257
258static void pnx4008_set_usb_bits(void)
259{
260 start_int_set_falling_edge(SE_USB_OTG_ATX_INT_N);
261 start_int_ack(SE_USB_OTG_ATX_INT_N);
262 start_int_umask(SE_USB_OTG_ATX_INT_N);
263
264 start_int_set_rising_edge(SE_USB_OTG_TIMER_INT);
265 start_int_ack(SE_USB_OTG_TIMER_INT);
266 start_int_umask(SE_USB_OTG_TIMER_INT);
267
268 start_int_set_rising_edge(SE_USB_I2C_INT);
269 start_int_ack(SE_USB_I2C_INT);
270 start_int_umask(SE_USB_I2C_INT);
271
272 start_int_set_rising_edge(SE_USB_INT);
273 start_int_ack(SE_USB_INT);
274 start_int_umask(SE_USB_INT);
275
276 start_int_set_rising_edge(SE_USB_NEED_CLK_INT);
277 start_int_ack(SE_USB_NEED_CLK_INT);
278 start_int_umask(SE_USB_NEED_CLK_INT);
279
280 start_int_set_rising_edge(SE_USB_AHB_NEED_CLK_INT);
281 start_int_ack(SE_USB_AHB_NEED_CLK_INT);
282 start_int_umask(SE_USB_AHB_NEED_CLK_INT);
283}
284
285static void pnx4008_unset_usb_bits(void)
286{
287 start_int_mask(SE_USB_OTG_ATX_INT_N);
288 start_int_mask(SE_USB_OTG_TIMER_INT);
289 start_int_mask(SE_USB_I2C_INT);
290 start_int_mask(SE_USB_INT);
291 start_int_mask(SE_USB_NEED_CLK_INT);
292 start_int_mask(SE_USB_AHB_NEED_CLK_INT);
293}
294
295static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
296{
297 struct usb_hcd *hcd = 0;
298 struct ohci_hcd *ohci;
299 const struct hc_driver *driver = &ohci_pnx4008_hc_driver;
300 struct i2c_adapter *i2c_adap;
301 struct i2c_board_info i2c_info;
302
303 int ret = 0, irq;
304
305 dev_dbg(&pdev->dev, "%s: " DRIVER_DESC " (pnx4008)\n", hcd_name);
306 if (usb_disabled()) {
307 err("USB is disabled");
308 ret = -ENODEV;
309 goto out;
310 }
311
312 if (pdev->num_resources != 2
313 || pdev->resource[0].flags != IORESOURCE_MEM
314 || pdev->resource[1].flags != IORESOURCE_IRQ) {
315 err("Invalid resource configuration");
316 ret = -ENODEV;
317 goto out;
318 }
319
320 /* Enable AHB slave USB clock, needed for further USB clock control */
321 __raw_writel(USB_SLAVE_HCLK_EN | (1 << 19), USB_CTRL);
322
323 ret = i2c_add_driver(&isp1301_driver);
324 if (ret < 0) {
325 err("failed to add ISP1301 driver");
326 goto out;
327 }
328 i2c_adap = i2c_get_adapter(2);
329 memset(&i2c_info, 0, sizeof(struct i2c_board_info));
330 strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
331 isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
332 normal_i2c, NULL);
333 i2c_put_adapter(i2c_adap);
334 if (!isp1301_i2c_client) {
335 err("failed to connect I2C to ISP1301 USB Transceiver");
336 ret = -ENODEV;
337 goto out_i2c_driver;
338 }
339
340 isp1301_configure();
341
342 /* Enable USB PLL */
343 usb_clk = clk_get(&pdev->dev, "ck_pll5");
344 if (IS_ERR(usb_clk)) {
345 err("failed to acquire USB PLL");
346 ret = PTR_ERR(usb_clk);
347 goto out1;
348 }
349
350 ret = clk_enable(usb_clk);
351 if (ret < 0) {
352 err("failed to start USB PLL");
353 goto out2;
354 }
355
356 ret = clk_set_rate(usb_clk, 48000);
357 if (ret < 0) {
358 err("failed to set USB clock rate");
359 goto out3;
360 }
361
362 __raw_writel(__raw_readl(USB_CTRL) | USB_HOST_NEED_CLK_EN, USB_CTRL);
363
364 /* Set to enable all needed USB clocks */
365 __raw_writel(USB_CLOCK_MASK, USB_OTG_CLK_CTRL);
366
367 while ((__raw_readl(USB_OTG_CLK_STAT) & USB_CLOCK_MASK) !=
368 USB_CLOCK_MASK) ;
369
370 hcd = usb_create_hcd (driver, &pdev->dev, dev_name(&pdev->dev));
371 if (!hcd) {
372 err("Failed to allocate HC buffer");
373 ret = -ENOMEM;
374 goto out3;
375 }
376
377 /* Set all USB bits in the Start Enable register */
378 pnx4008_set_usb_bits();
379
380 hcd->rsrc_start = pdev->resource[0].start;
381 hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
382 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
383 dev_dbg(&pdev->dev, "request_mem_region failed\n");
384 ret = -ENOMEM;
385 goto out4;
386 }
387 hcd->regs = (void __iomem *)pdev->resource[0].start;
388
389 irq = platform_get_irq(pdev, 0);
390 if (irq < 0) {
391 ret = -ENXIO;
392 goto out4;
393 }
394
395 pnx4008_start_hc();
396 platform_set_drvdata(pdev, hcd);
397 ohci = hcd_to_ohci(hcd);
398 ohci_hcd_init(ohci);
399
400 dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
401 ret = usb_add_hcd(hcd, irq, IRQF_DISABLED);
402 if (ret == 0)
403 return ret;
404
405 pnx4008_stop_hc();
406out4:
407 pnx4008_unset_usb_bits();
408 usb_put_hcd(hcd);
409out3:
410 clk_disable(usb_clk);
411out2:
412 clk_put(usb_clk);
413out1:
414 i2c_unregister_device(isp1301_i2c_client);
415 isp1301_i2c_client = NULL;
416out_i2c_driver:
417 i2c_del_driver(&isp1301_driver);
418out:
419 return ret;
420}
421
422static int usb_hcd_pnx4008_remove(struct platform_device *pdev)
423{
424 struct usb_hcd *hcd = platform_get_drvdata(pdev);
425
426 usb_remove_hcd(hcd);
427 pnx4008_stop_hc();
428 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
429 usb_put_hcd(hcd);
430 pnx4008_unset_usb_bits();
431 clk_disable(usb_clk);
432 clk_put(usb_clk);
433 i2c_unregister_device(isp1301_i2c_client);
434 isp1301_i2c_client = NULL;
435 i2c_del_driver(&isp1301_driver);
436
437 platform_set_drvdata(pdev, NULL);
438
439 return 0;
440}
441
442/* work with hotplug and coldplug */
443MODULE_ALIAS("platform:usb-ohci");
444
445static struct platform_driver usb_hcd_pnx4008_driver = {
446 .driver = {
447 .name = "usb-ohci",
448 .owner = THIS_MODULE,
449 },
450 .probe = usb_hcd_pnx4008_probe,
451 .remove = usb_hcd_pnx4008_remove,
452};
453
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
new file mode 100644
index 00000000000..28467e288a9
--- /dev/null
+++ b/drivers/usb/host/ohci-pnx8550.c
@@ -0,0 +1,242 @@
1/*
2 * OHCI HCD (Host Controller Driver) for USB.
3 *
4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
5 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
6 * (C) Copyright 2002 Hewlett-Packard Company
7 * (C) Copyright 2005 Embedded Alley Solutions, Inc.
8 *
9 * Bus Glue for PNX8550
10 *
11 * Written by Christopher Hoover <ch@hpl.hp.com>
12 * Based on fragments of previous driver by Russell King et al.
13 *
14 * Modified for LH7A404 from ohci-sa1111.c
15 * by Durgesh Pattamatta <pattamattad@sharpsec.com>
16 *
17 * Modified for PNX8550 from ohci-sa1111.c and sa-omap.c
18 * by Vitaly Wool <vitalywool@gmail.com>
19 *
20 * This file is licenced under the GPL.
21 */
22
23#include <linux/device.h>
24#include <linux/platform_device.h>
25#include <asm/mach-pnx8550/usb.h>
26#include <asm/mach-pnx8550/int.h>
27#include <asm/mach-pnx8550/pci.h>
28
29#ifndef CONFIG_PNX8550
30#error "This file is PNX8550 bus glue. CONFIG_PNX8550 must be defined."
31#endif
32
33extern int usb_disabled(void);
34
35/*-------------------------------------------------------------------------*/
36
37static void pnx8550_start_hc(struct platform_device *dev)
38{
39 /*
40 * Set register CLK48CTL to enable and 48MHz
41 */
42 outl(0x00000003, PCI_BASE | 0x0004770c);
43
44 /*
45 * Set register CLK12CTL to enable and 48MHz
46 */
47 outl(0x00000003, PCI_BASE | 0x00047710);
48
49 udelay(100);
50}
51
52static void pnx8550_stop_hc(struct platform_device *dev)
53{
54 udelay(10);
55}
56
57
58/*-------------------------------------------------------------------------*/
59
60/* configure so an HC device and id are always provided */
61/* always called with process context; sleeping is OK */
62
63
64/**
65 * usb_hcd_pnx8550_probe - initialize pnx8550-based HCDs
66 * Context: !in_interrupt()
67 *
68 * Allocates basic resources for this USB host controller, and
69 * then invokes the start() method for the HCD associated with it
70 * through the hotplug entry's driver_data.
71 *
72 */
73int usb_hcd_pnx8550_probe (const struct hc_driver *driver,
74 struct platform_device *dev)
75{
76 int retval;
77 struct usb_hcd *hcd;
78
79 if (dev->resource[0].flags != IORESOURCE_MEM ||
80 dev->resource[1].flags != IORESOURCE_IRQ) {
81 dev_err (&dev->dev,"invalid resource type\n");
82 return -ENOMEM;
83 }
84
85 hcd = usb_create_hcd (driver, &dev->dev, "pnx8550");
86 if (!hcd)
87 return -ENOMEM;
88 hcd->rsrc_start = dev->resource[0].start;
89 hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
90
91 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
92 dev_err(&dev->dev, "request_mem_region [0x%08llx, 0x%08llx] "
93 "failed\n", hcd->rsrc_start, hcd->rsrc_len);
94 retval = -EBUSY;
95 goto err1;
96 }
97
98 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
99 if (!hcd->regs) {
100 dev_err(&dev->dev, "ioremap [[0x%08llx, 0x%08llx] failed\n",
101 hcd->rsrc_start, hcd->rsrc_len);
102 retval = -ENOMEM;
103 goto err2;
104 }
105
106 pnx8550_start_hc(dev);
107
108 ohci_hcd_init(hcd_to_ohci(hcd));
109
110 retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED);
111 if (retval == 0)
112 return retval;
113
114 pnx8550_stop_hc(dev);
115 iounmap(hcd->regs);
116 err2:
117 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
118 err1:
119 usb_put_hcd(hcd);
120 return retval;
121}
122
123
124/* may be called without controller electrically present */
125/* may be called with controller, bus, and devices active */
126
127/**
128 * usb_hcd_pnx8550_remove - shutdown processing for pnx8550-based HCDs
129 * @dev: USB Host Controller being removed
130 * Context: !in_interrupt()
131 *
132 * Reverses the effect of usb_hcd_pnx8550_probe(), first invoking
133 * the HCD's stop() method. It is always called from a thread
134 * context, normally "rmmod", "apmd", or something similar.
135 *
136 */
137void usb_hcd_pnx8550_remove (struct usb_hcd *hcd, struct platform_device *dev)
138{
139 usb_remove_hcd(hcd);
140 pnx8550_stop_hc(dev);
141 iounmap(hcd->regs);
142 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
143 usb_put_hcd(hcd);
144}
145
146/*-------------------------------------------------------------------------*/
147
148static int __devinit
149ohci_pnx8550_start (struct usb_hcd *hcd)
150{
151 struct ohci_hcd *ohci = hcd_to_ohci (hcd);
152 int ret;
153
154 ohci_dbg (ohci, "ohci_pnx8550_start, ohci:%p", ohci);
155
156 if ((ret = ohci_init(ohci)) < 0)
157 return ret;
158
159 if ((ret = ohci_run (ohci)) < 0) {
160 err ("can't start %s", hcd->self.bus_name);
161 ohci_stop (hcd);
162 return ret;
163 }
164
165 return 0;
166}
167
168/*-------------------------------------------------------------------------*/
169
170static const struct hc_driver ohci_pnx8550_hc_driver = {
171 .description = hcd_name,
172 .product_desc = "PNX8550 OHCI",
173 .hcd_priv_size = sizeof(struct ohci_hcd),
174
175 /*
176 * generic hardware linkage
177 */
178 .irq = ohci_irq,
179 .flags = HCD_USB11 | HCD_MEMORY,
180
181 /*
182 * basic lifecycle operations
183 */
184 .start = ohci_pnx8550_start,
185 .stop = ohci_stop,
186
187 /*
188 * managing i/o requests and associated device resources
189 */
190 .urb_enqueue = ohci_urb_enqueue,
191 .urb_dequeue = ohci_urb_dequeue,
192 .endpoint_disable = ohci_endpoint_disable,
193
194 /*
195 * scheduling support
196 */
197 .get_frame_number = ohci_get_frame,
198
199 /*
200 * root hub support
201 */
202 .hub_status_data = ohci_hub_status_data,
203 .hub_control = ohci_hub_control,
204#ifdef CONFIG_PM
205 .bus_suspend = ohci_bus_suspend,
206 .bus_resume = ohci_bus_resume,
207#endif
208 .start_port_reset = ohci_start_port_reset,
209};
210
211/*-------------------------------------------------------------------------*/
212
213static int ohci_hcd_pnx8550_drv_probe(struct platform_device *pdev)
214{
215 int ret;
216
217 if (usb_disabled())
218 return -ENODEV;
219
220 ret = usb_hcd_pnx8550_probe(&ohci_pnx8550_hc_driver, pdev);
221 return ret;
222}
223
224static int ohci_hcd_pnx8550_drv_remove(struct platform_device *pdev)
225{
226 struct usb_hcd *hcd = platform_get_drvdata(pdev);
227
228 usb_hcd_pnx8550_remove(hcd, pdev);
229 return 0;
230}
231
232MODULE_ALIAS("platform:pnx8550-ohci");
233
234static struct platform_driver ohci_hcd_pnx8550_driver = {
235 .driver = {
236 .name = "pnx8550-ohci",
237 .owner = THIS_MODULE,
238 },
239 .probe = ohci_hcd_pnx8550_drv_probe,
240 .remove = ohci_hcd_pnx8550_drv_remove,
241};
242
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
new file mode 100644
index 00000000000..c0f595c4448
--- /dev/null
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -0,0 +1,215 @@
1/*
2 * OHCI HCD (Host Controller Driver) for USB.
3 *
4 * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
5 * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
6 * (C) Copyright 2002 Hewlett-Packard Company
7 * (C) Copyright 2003-2005 MontaVista Software Inc.
8 *
9 * Bus Glue for PPC On-Chip OHCI driver
10 * Tested on Freescale MPC5200 and IBM STB04xxx
11 *
12 * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
13 *
14 * This file is licenced under the GPL.
15 */
16
17#include <linux/platform_device.h>
18#include <linux/signal.h>
19
20/* configure so an HC device and id are always provided */
21/* always called with process context; sleeping is OK */
22
23/**
24 * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
25 * Context: !in_interrupt()
26 *
27 * Allocates basic resources for this USB host controller.
28 *
29 * Store this function in the HCD's struct pci_driver as probe().
30 */
31static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
32 struct platform_device *pdev)
33{
34 int retval;
35 struct usb_hcd *hcd;
36 struct ohci_hcd *ohci;
37 struct resource *res;
38 int irq;
39
40 pr_debug("initializing PPC-SOC USB Controller\n");
41
42 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
43 if (!res) {
44 pr_debug("%s: no irq\n", __FILE__);
45 return -ENODEV;
46 }
47 irq = res->start;
48
49 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
50 if (!res) {
51 pr_debug("%s: no reg addr\n", __FILE__);
52 return -ENODEV;
53 }
54
55 hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB");
56 if (!hcd)
57 return -ENOMEM;
58 hcd->rsrc_start = res->start;
59 hcd->rsrc_len = resource_size(res);
60
61 if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
62 pr_debug("%s: request_mem_region failed\n", __FILE__);
63 retval = -EBUSY;
64 goto err1;
65 }
66
67 hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
68 if (!hcd->regs) {
69 pr_debug("%s: ioremap failed\n", __FILE__);
70 retval = -ENOMEM;
71 goto err2;
72 }
73
74 ohci = hcd_to_ohci(hcd);
75 ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
76
77#ifdef CONFIG_PPC_MPC52xx
78 /* MPC52xx doesn't need frame_no shift */
79 ohci->flags |= OHCI_QUIRK_FRAME_NO;
80#endif
81 ohci_hcd_init(ohci);
82
83 retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
84 if (retval == 0)
85 return retval;
86
87 pr_debug("Removing PPC-SOC USB Controller\n");
88
89 iounmap(hcd->regs);
90 err2:
91 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
92 err1:
93 usb_put_hcd(hcd);
94 return retval;
95}
96
97
98/* may be called without controller electrically present */
99/* may be called with controller, bus, and devices active */
100
101/**
102 * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
103 * @pdev: USB Host Controller being removed
104 * Context: !in_interrupt()
105 *
106 * Reverses the effect of usb_hcd_ppc_soc_probe().
107 * It is always called from a thread
108 * context, normally "rmmod", "apmd", or something similar.
109 *
110 */
111static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
112 struct platform_device *pdev)
113{
114 usb_remove_hcd(hcd);
115
116 pr_debug("stopping PPC-SOC USB Controller\n");
117
118 iounmap(hcd->regs);
119 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
120 usb_put_hcd(hcd);
121}
122
123static int __devinit
124ohci_ppc_soc_start(struct usb_hcd *hcd)
125{
126 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
127 int ret;
128
129 if ((ret = ohci_init(ohci)) < 0)
130 return ret;
131
132 if ((ret = ohci_run(ohci)) < 0) {
133 err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
134 ohci_stop(hcd);
135 return ret;
136 }
137
138 return 0;
139}
140
141static const struct hc_driver ohci_ppc_soc_hc_driver = {
142 .description = hcd_name,
143 .hcd_priv_size = sizeof(struct ohci_hcd),
144
145 /*
146 * generic hardware linkage
147 */
148 .irq = ohci_irq,
149 .flags = HCD_USB11 | HCD_MEMORY,
150
151 /*
152 * basic lifecycle operations
153 */
154 .start = ohci_ppc_soc_start,
155 .stop = ohci_stop,
156 .shutdown = ohci_shutdown,
157
158 /*
159 * managing i/o requests and associated device resources
160 */
161 .urb_enqueue = ohci_urb_enqueue,
162 .urb_dequeue = ohci_urb_dequeue,
163 .endpoint_disable = ohci_endpoint_disable,
164
165 /*
166 * scheduling support
167 */
168 .get_frame_number = ohci_get_frame,
169
170 /*
171 * root hub support
172 */
173 .hub_status_data = ohci_hub_status_data,
174 .hub_control = ohci_hub_control,
175#ifdef CONFIG_PM
176 .bus_suspend = ohci_bus_suspend,
177 .bus_resume = ohci_bus_resume,
178#endif
179 .start_port_reset = ohci_start_port_reset,
180};
181
182static int ohci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
183{
184 int ret;
185
186 if (usb_disabled())
187 return -ENODEV;
188
189 ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
190 return ret;
191}
192
193static int ohci_hcd_ppc_soc_drv_remove(struct platform_device *pdev)
194{
195 struct usb_hcd *hcd = platform_get_drvdata(pdev);
196
197 usb_hcd_ppc_soc_remove(hcd, pdev);
198 return 0;
199}
200
201static struct platform_driver ohci_hcd_ppc_soc_driver = {
202 .probe = ohci_hcd_ppc_soc_drv_probe,
203 .remove = ohci_hcd_ppc_soc_drv_remove,
204 .shutdown = usb_hcd_platform_shutdown,
205#ifdef CONFIG_PM
206 /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
207 /*.resume = ohci_hcd_ppc_soc_drv_resume,*/
208#endif
209 .driver = {
210 .name = "ppc-soc-ohci",
211 .owner = THIS_MODULE,
212 },
213};
214
215MODULE_ALIAS("platform:ppc-soc-ohci");
diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c
new file mode 100644
index 00000000000..14cecb52a9f
--- /dev/null
+++ b/drivers/usb/host/ohci-sh.c
@@ -0,0 +1,142 @@
1/*
2 * OHCI HCD (Host Controller Driver) for USB.
3 *
4 * Copyright (C) 2008 Renesas Solutions Corp.
5 *
6 * Author : Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 */
22
23#include <linux/platform_device.h>
24
25static int ohci_sh_start(struct usb_hcd *hcd)
26{
27 struct ohci_hcd *ohci = hcd_to_ohci(hcd);
28
29 ohci_hcd_init(ohci);
30 ohci_init(ohci);
31 ohci_run(ohci);
32 hcd->state = HC_STATE_RUNNING;
33 return 0;
34}
35
36static const struct hc_driver ohci_sh_hc_driver = {
37 .description = hcd_name,
38 .product_desc = "SuperH OHCI",
39 .hcd_priv_size = sizeof(struct ohci_hcd),
40
41 /*
42 * generic hardware linkage
43 */
44 .irq = ohci_irq,
45 .flags = HCD_USB11 | HCD_MEMORY,
46
47 /*
48 * basic lifecycle operations
49 */
50 .start = ohci_sh_start,
51 .stop = ohci_stop,
52 .shutdown = ohci_shutdown,
53
54 /*
55 * managing i/o requests and associated device resources
56 */
57 .urb_enqueue = ohci_urb_enqueue,
58 .urb_dequeue = ohci_urb_dequeue,
59 .endpoint_disable = ohci_endpoint_disable,
60
61 /*
62 * scheduling support
63 */
64 .get_frame_number = ohci_get_frame,
65
66 /*
67 * root hub support
68 */
69 .hub_status_data = ohci_hub_status_data,
70 .hub_control = ohci_hub_control,
71#ifdef CONFIG_PM
72 .bus_suspend = ohci_bus_suspend,
73 .bus_resume = ohci_bus_resume,
74#endif
75 .start_port_reset = ohci_start_port_reset,
76};
77
78/*-------------------------------------------------------------------------*/
79
80static int ohci_hcd_sh_probe(struct platform_device *pdev)
81{
82 struct resource *res = NULL;
83 struct usb_hcd *hcd = NULL;
84 int irq = -1;
85 int ret;
86
87 if (usb_disabled())
88 return -ENODEV;
89
90 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
91 if (!res) {
92 err("platform_get_resource error.");
93 return -ENODEV;
94 }
95
96 irq = platform_get_irq(pdev, 0);
97 if (irq < 0) {
98 err("platform_get_irq error.");
99 return -ENODEV;
100 }
101
102 /* initialize hcd */
103 hcd = usb_create_hcd(&ohci_sh_hc_driver, &pdev->dev, (char *)hcd_name);
104 if (!hcd) {
105 err("Failed to create hcd");
106 return -ENOMEM;
107 }
108
109 hcd->regs = (void __iomem *)res->start;
110 hcd->rsrc_start = res->start;
111 hcd->rsrc_len = resource_size(res);
112 ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
113 if (ret != 0) {
114 err("Failed to add hcd");
115 usb_put_hcd(hcd);
116 return ret;
117 }
118
119 return ret;
120}
121
122static int ohci_hcd_sh_remove(struct platform_device *pdev)
123{
124 struct usb_hcd *hcd = platform_get_drvdata(pdev);
125
126 usb_remove_hcd(hcd);
127 usb_put_hcd(hcd);
128
129 return 0;
130}
131
132static struct platform_driver ohci_hcd_sh_driver = {
133 .probe = ohci_hcd_sh_probe,
134 .remove = ohci_hcd_sh_remove,
135 .shutdown = usb_hcd_platform_shutdown,
136 .driver = {
137 .name = "sh_ohci",
138 .owner = THIS_MODULE,
139 },
140};
141
142MODULE_ALIAS("platform:sh_ohci");
diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c
new file mode 100644
index 00000000000..c4aea3b8315
--- /dev/null
+++ b/drivers/usb/host/ohci-ssb.c
@@ -0,0 +1,260 @@
1/*
2 * Sonics Silicon Backplane
3 * Broadcom USB-core OHCI driver
4 *
5 * Copyright 2007 Michael Buesch <m@bues.ch>
6 *
7 * Derived from the OHCI-PCI driver
8 * Copyright 1999 Roman Weissgaerber
9 * Copyright 2000-2002 David Brownell
10 * Copyright 1999 Linus Torvalds
11 * Copyright 1999 Gregory P. Smith
12 *
13 * Derived from the USBcore related parts of Broadcom-SB
14 * Copyright 2005 Broadcom Corporation
15 *
16 * Licensed under the GNU/GPL. See COPYING for details.
17 */
18#include <linux/ssb/ssb.h>
19
20
21#define SSB_OHCI_TMSLOW_HOSTMODE (1 << 29)
22
23struct ssb_ohci_device {
24 struct ohci_hcd ohci; /* _must_ be at the beginning. */
25
26 u32 enable_flags;
27};
28
29static inline
30struct ssb_ohci_device *hcd_to_ssb_ohci(struct usb_hcd *hcd)
31{
32 return (struct ssb_ohci_device *)(hcd->hcd_priv);
33}
34
35
36static int ssb_ohci_reset(struct usb_hcd *hcd)
37{
38 struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
39 struct ohci_hcd *ohci = &ohcidev->ohci;
40 int err;
41
42 ohci_hcd_init(ohci);
43 err = ohci_init(ohci);
44
45 return err;
46}
47
48static int ssb_ohci_start(struct usb_hcd *hcd)
49{
50 struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
51 struct ohci_hcd *ohci = &ohcidev->ohci;
52 int err;
53
54 err = ohci_run(ohci);
55 if (err < 0) {
56 ohci_err(ohci, "can't start\n");
57 ohci_stop(hcd);
58 }
59
60 return err;
61}
62
63static const struct hc_driver ssb_ohci_hc_driver = {
64 .description = "ssb-usb-ohci",
65 .product_desc = "SSB OHCI Controller",
66 .hcd_priv_size = sizeof(struct ssb_ohci_device),
67
68 .irq = ohci_irq,
69 .flags = HCD_MEMORY | HCD_USB11,
70
71 .reset = ssb_ohci_reset,
72 .start = ssb_ohci_start,
73 .stop = ohci_stop,
74 .shutdown = ohci_shutdown,
75
76 .urb_enqueue = ohci_urb_enqueue,
77 .urb_dequeue = ohci_urb_dequeue,
78 .endpoint_disable = ohci_endpoint_disable,
79
80 .get_frame_number = ohci_get_frame,
81
82 .hub_status_data = ohci_hub_status_data,
83 .hub_control = ohci_hub_control,
84#ifdef CONFIG_PM
85 .bus_suspend = ohci_bus_suspend,
86 .bus_resume = ohci_bus_resume,
87#endif
88
89 .start_port_reset = ohci_start_port_reset,
90};
91
92static void ssb_ohci_detach(struct ssb_device *dev)
93{
94 struct usb_hcd *hcd = ssb_get_drvdata(dev);
95
96 if (hcd->driver->shutdown)
97 hcd->driver->shutdown(hcd);
98 usb_remove_hcd(hcd);
99 iounmap(hcd->regs);
100 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
101 usb_put_hcd(hcd);
102 ssb_device_disable(dev, 0);
103}
104
105static int ssb_ohci_attach(struct ssb_device *dev)
106{
107 struct ssb_ohci_device *ohcidev;
108 struct usb_hcd *hcd;
109 int err = -ENOMEM;
110 u32 tmp, flags = 0;
111
112 if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) ||
113 dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32)))
114 return -EOPNOTSUPP;
115
116 if (dev->id.coreid == SSB_DEV_USB11_HOSTDEV) {
117 /* Put the device into host-mode. */
118 flags |= SSB_OHCI_TMSLOW_HOSTMODE;
119 ssb_device_enable(dev, flags);
120 } else if (dev->id.coreid == SSB_DEV_USB20_HOST) {
121 /*
122 * USB 2.0 special considerations:
123 *
124 * In addition to the standard SSB reset sequence, the Host
125 * Control Register must be programmed to bring the USB core
126 * and various phy components out of reset.
127 */
128 ssb_device_enable(dev, 0);
129 ssb_write32(dev, 0x200, 0x7ff);
130
131 /* Change Flush control reg */
132 tmp = ssb_read32(dev, 0x400);
133 tmp &= ~8;
134 ssb_write32(dev, 0x400, tmp);
135 tmp = ssb_read32(dev, 0x400);
136
137 /* Change Shim control reg */
138 tmp = ssb_read32(dev, 0x304);
139 tmp &= ~0x100;
140 ssb_write32(dev, 0x304, tmp);
141 tmp = ssb_read32(dev, 0x304);
142
143 udelay(1);
144
145 /* Work around for 5354 failures */
146 if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) {
147 /* Change syn01 reg */
148 tmp = 0x00fe00fe;
149 ssb_write32(dev, 0x894, tmp);
150
151 /* Change syn03 reg */
152 tmp = ssb_read32(dev, 0x89c);
153 tmp |= 0x1;
154 ssb_write32(dev, 0x89c, tmp);
155 }
156 } else
157 ssb_device_enable(dev, 0);
158
159 hcd = usb_create_hcd(&ssb_ohci_hc_driver, dev->dev,
160 dev_name(dev->dev));
161 if (!hcd)
162 goto err_dev_disable;
163 ohcidev = hcd_to_ssb_ohci(hcd);
164 ohcidev->enable_flags = flags;
165
166 tmp = ssb_read32(dev, SSB_ADMATCH0);
167 hcd->rsrc_start = ssb_admatch_base(tmp);
168 hcd->rsrc_len = ssb_admatch_size(tmp);
169 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
170 if (!hcd->regs)
171 goto err_put_hcd;
172 err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
173 if (err)
174 goto err_iounmap;
175
176 ssb_set_drvdata(dev, hcd);
177
178 return err;
179
180err_iounmap:
181 iounmap(hcd->regs);
182err_put_hcd:
183 usb_put_hcd(hcd);
184err_dev_disable:
185 ssb_device_disable(dev, flags);
186 return err;
187}
188
189static int ssb_ohci_probe(struct ssb_device *dev,
190 const struct ssb_device_id *id)
191{
192 int err;
193 u16 chipid_top;
194
195 /* USBcores are only connected on embedded devices. */
196 chipid_top = (dev->bus->chip_id & 0xFF00);
197 if (chipid_top != 0x4700 && chipid_top != 0x5300)
198 return -ENODEV;
199
200 /* TODO: Probably need checks here; is the core connected? */
201
202 if (usb_disabled())
203 return -ENODEV;
204
205 /* We currently always attach SSB_DEV_USB11_HOSTDEV
206 * as HOST OHCI. If we want to attach it as Client device,
207 * we must branch here and call into the (yet to
208 * be written) Client mode driver. Same for remove(). */
209
210 err = ssb_ohci_attach(dev);
211
212 return err;
213}
214
215static void ssb_ohci_remove(struct ssb_device *dev)
216{
217 ssb_ohci_detach(dev);
218}
219
220#ifdef CONFIG_PM
221
222static int ssb_ohci_suspend(struct ssb_device *dev, pm_message_t state)
223{
224 ssb_device_disable(dev, 0);
225
226 return 0;
227}
228
229static int ssb_ohci_resume(struct ssb_device *dev)
230{
231 struct usb_hcd *hcd = ssb_get_drvdata(dev);
232 struct ssb_ohci_device *ohcidev = hcd_to_ssb_ohci(hcd);
233
234 ssb_device_enable(dev, ohcidev->enable_flags);
235
236 ohci_finish_controller_resume(hcd);
237 return 0;
238}
239
240#else /* !CONFIG_PM */
241#define ssb_ohci_suspend NULL
242#define ssb_ohci_resume NULL
243#endif /* CONFIG_PM */
244
245static const struct ssb_device_id ssb_ohci_table[] = {
246 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV),
247 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV),
248 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV),
249 SSB_DEVTABLE_END
250};
251MODULE_DEVICE_TABLE(ssb, ssb_ohci_table);
252
253static struct ssb_driver ssb_ohci_driver = {
254 .name = KBUILD_MODNAME,
255 .id_table = ssb_ohci_table,
256 .probe = ssb_ohci_probe,
257 .remove = ssb_ohci_remove,
258 .suspend = ssb_ohci_suspend,
259 .resume = ssb_ohci_resume,
260};