[kernel] update to 2.6.25.20, 2.6.26.8, 2.6.27.5 and refresh patches
[openwrt.git] / target / linux / brcm63xx / patches-2.6.27 / 008-usb_ehci_support.patch
1 From 2940d1996c86c4c4dd7a82214f846d0c0b707165 Mon Sep 17 00:00:00 2001
2 From: Maxime Bizon <mbizon@freebox.fr>
3 Date: Mon, 21 Jul 2008 18:24:42 +0200
4 Subject: [PATCH] [MIPS] BCM63XX: Add USB EHCI support.
5
6 Signed-off-by: Maxime Bizon <mbizon@freebox.fr>
7 ---
8  arch/mips/bcm63xx/Kconfig                          |    2 +
9  arch/mips/bcm63xx/Makefile                         |    1 +
10  arch/mips/bcm63xx/dev-usb-ehci.c                   |   50 +++++++
11  drivers/usb/host/ehci-bcm63xx.c                    |  152 ++++++++++++++++++++
12  drivers/usb/host/ehci-hcd.c                        |    5 +
13  drivers/usb/host/ehci.h                            |    5 +
14  .../asm-mips/mach-bcm63xx/bcm63xx_dev_usb_ehci.h   |    6 +
15  7 files changed, 221 insertions(+), 0 deletions(-)
16  create mode 100644 arch/mips/bcm63xx/dev-usb-ehci.c
17  create mode 100644 drivers/usb/host/ehci-bcm63xx.c
18  create mode 100644 include/asm-mips/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
19
20 --- a/arch/mips/bcm63xx/Kconfig
21 +++ b/arch/mips/bcm63xx/Kconfig
22 @@ -14,4 +14,6 @@ config BCM63XX_CPU_6358
23         select USB_ARCH_HAS_OHCI
24         select USB_OHCI_BIG_ENDIAN_DESC
25         select USB_OHCI_BIG_ENDIAN_MMIO
26 +       select USB_ARCH_HAS_EHCI
27 +       select USB_EHCI_BIG_ENDIAN_MMIO
28  endmenu
29 --- a/arch/mips/bcm63xx/Makefile
30 +++ b/arch/mips/bcm63xx/Makefile
31 @@ -2,4 +2,5 @@ obj-y           += clk.o cpu.o cs.o gpio.o irq.o 
32  obj-y          += dev-uart.o
33  obj-y          += dev-pcmcia.o
34  obj-y          += dev-usb-ohci.o
35 +obj-y          += dev-usb-ehci.o
36  obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
37 --- /dev/null
38 +++ b/arch/mips/bcm63xx/dev-usb-ehci.c
39 @@ -0,0 +1,50 @@
40 +/*
41 + * This file is subject to the terms and conditions of the GNU General Public
42 + * License.  See the file "COPYING" in the main directory of this archive
43 + * for more details.
44 + *
45 + * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
46 + */
47 +
48 +#include <linux/init.h>
49 +#include <linux/kernel.h>
50 +#include <linux/platform_device.h>
51 +#include <bcm63xx_cpu.h>
52 +#include <bcm63xx_dev_usb_ehci.h>
53 +
54 +static struct resource ehci_resources[] = {
55 +       {
56 +               .start          = -1, /* filled at runtime */
57 +               .end            = -1, /* filled at runtime */
58 +               .flags          = IORESOURCE_MEM,
59 +       },
60 +       {
61 +               .start          = -1, /* filled at runtime */
62 +               .flags          = IORESOURCE_IRQ,
63 +       },
64 +};
65 +
66 +static u64 ehci_dmamask = ~(u32)0;
67 +
68 +static struct platform_device bcm63xx_ehci_device = {
69 +       .name           = "bcm63xx_ehci",
70 +       .id             = 0,
71 +       .num_resources  = ARRAY_SIZE(ehci_resources),
72 +       .resource       = ehci_resources,
73 +       .dev            = {
74 +               .dma_mask               = &ehci_dmamask,
75 +               .coherent_dma_mask      = 0xffffffff,
76 +       },
77 +};
78 +
79 +int __init bcm63xx_ehci_register(void)
80 +{
81 +       if (!BCMCPU_IS_6358())
82 +               return 0;
83 +
84 +       ehci_resources[0].start = bcm63xx_regset_address(RSET_EHCI0);
85 +       ehci_resources[0].end = ehci_resources[0].start;
86 +       ehci_resources[0].end += RSET_EHCI_SIZE - 1;
87 +       ehci_resources[1].start = bcm63xx_get_irq_number(IRQ_EHCI0);
88 +       return platform_device_register(&bcm63xx_ehci_device);
89 +}
90 --- /dev/null
91 +++ b/drivers/usb/host/ehci-bcm63xx.c
92 @@ -0,0 +1,152 @@
93 +/*
94 + * This file is subject to the terms and conditions of the GNU General Public
95 + * License.  See the file "COPYING" in the main directory of this archive
96 + * for more details.
97 + *
98 + * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
99 + */
100 +
101 +#include <linux/init.h>
102 +#include <linux/platform_device.h>
103 +#include <bcm63xx_cpu.h>
104 +#include <bcm63xx_regs.h>
105 +#include <bcm63xx_io.h>
106 +
107 +static int ehci_bcm63xx_setup(struct usb_hcd *hcd)
108 +{
109 +       struct ehci_hcd *ehci = hcd_to_ehci(hcd);
110 +       int retval;
111 +
112 +       retval = ehci_halt(ehci);
113 +       if (retval)
114 +               return retval;
115 +
116 +       retval = ehci_init(hcd);
117 +       if (retval)
118 +               return retval;
119 +
120 +       hcd->has_tt = 1;
121 +       ehci_reset(ehci);
122 +       ehci_port_power(ehci, 0);
123 +
124 +       return retval;
125 +}
126 +
127 +
128 +static const struct hc_driver ehci_bcm63xx_hc_driver = {
129 +       .description =          hcd_name,
130 +       .product_desc =         "BCM63XX integrated EHCI controller",
131 +       .hcd_priv_size =        sizeof(struct ehci_hcd),
132 +
133 +       .irq =                  ehci_irq,
134 +       .flags =                HCD_MEMORY | HCD_USB2,
135 +
136 +       .reset =                ehci_bcm63xx_setup,
137 +       .start =                ehci_run,
138 +       .stop =                 ehci_stop,
139 +       .shutdown =             ehci_shutdown,
140 +
141 +       .urb_enqueue =          ehci_urb_enqueue,
142 +       .urb_dequeue =          ehci_urb_dequeue,
143 +       .endpoint_disable =     ehci_endpoint_disable,
144 +
145 +       .get_frame_number =     ehci_get_frame,
146 +
147 +       .hub_status_data =      ehci_hub_status_data,
148 +       .hub_control =          ehci_hub_control,
149 +       .bus_suspend =          ehci_bus_suspend,
150 +       .bus_resume =           ehci_bus_resume,
151 +       .relinquish_port =      ehci_relinquish_port,
152 +       .port_handed_over =     ehci_port_handed_over,
153 +};
154 +
155 +static int __devinit ehci_hcd_bcm63xx_drv_probe(struct platform_device *pdev)
156 +{
157 +       struct resource *res_mem, *res_irq;
158 +       struct usb_hcd *hcd;
159 +       struct ehci_hcd *ehci;
160 +       u32 reg;
161 +       int ret;
162 +
163 +       res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
164 +       res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
165 +       if (!res_mem || !res_irq)
166 +               return -ENODEV;
167 +
168 +       reg = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_REG);
169 +       reg &= ~USBH_PRIV_SWAP_EHCI_DATA_MASK;
170 +       reg |= USBH_PRIV_SWAP_EHCI_ENDN_MASK;
171 +       bcm_rset_writel(RSET_USBH_PRIV, reg, USBH_PRIV_SWAP_REG);
172 +
173 +       /* don't ask... */
174 +       bcm_rset_writel(RSET_USBH_PRIV, 0x1c0020, USBH_PRIV_TEST_REG);
175 +
176 +       hcd = usb_create_hcd(&ehci_bcm63xx_hc_driver, &pdev->dev, "bcm63xx");
177 +       if (!hcd)
178 +               return -ENOMEM;
179 +       hcd->rsrc_start = res_mem->start;
180 +       hcd->rsrc_len = res_mem->end - res_mem->start + 1;
181 +
182 +       if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
183 +               pr_debug("request_mem_region failed\n");
184 +               ret = -EBUSY;
185 +               goto out;
186 +       }
187 +
188 +       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
189 +       if (!hcd->regs) {
190 +               pr_debug("ioremap failed\n");
191 +               ret = -EIO;
192 +               goto out1;
193 +       }
194 +
195 +       ehci = hcd_to_ehci(hcd);
196 +       ehci->big_endian_mmio = 1;
197 +       ehci->big_endian_desc = 0;
198 +       ehci->caps = hcd->regs;
199 +       ehci->regs = hcd->regs +
200 +               HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
201 +       ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
202 +       ehci->sbrn = 0x20;
203 +
204 +       ret = usb_add_hcd(hcd, res_irq->start, IRQF_DISABLED);
205 +       if (ret)
206 +               goto out2;
207 +
208 +       platform_set_drvdata(pdev, hcd);
209 +       return 0;
210 +
211 +out2:
212 +       iounmap(hcd->regs);
213 +out1:
214 +       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
215 +out:
216 +       usb_put_hcd(hcd);
217 +       return ret;
218 +}
219 +
220 +static int __devexit ehci_hcd_bcm63xx_drv_remove(struct platform_device *pdev)
221 +{
222 +       struct usb_hcd *hcd;
223 +
224 +       hcd = platform_get_drvdata(pdev);
225 +       usb_remove_hcd(hcd);
226 +       iounmap(hcd->regs);
227 +       usb_put_hcd(hcd);
228 +       release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
229 +       platform_set_drvdata(pdev, NULL);
230 +       return 0;
231 +}
232 +
233 +static struct platform_driver ehci_hcd_bcm63xx_driver = {
234 +       .probe          = ehci_hcd_bcm63xx_drv_probe,
235 +       .remove         = __devexit_p(ehci_hcd_bcm63xx_drv_remove),
236 +       .shutdown       = usb_hcd_platform_shutdown,
237 +       .driver         = {
238 +               .name   = "bcm63xx_ehci",
239 +               .owner  = THIS_MODULE,
240 +               .bus    = &platform_bus_type
241 +       },
242 +};
243 +
244 +MODULE_ALIAS("platform:bcm63xx_ehci");
245 --- a/drivers/usb/host/ehci-hcd.c
246 +++ b/drivers/usb/host/ehci-hcd.c
247 @@ -1040,6 +1040,11 @@ MODULE_LICENSE ("GPL");
248  #define        PLATFORM_DRIVER         ixp4xx_ehci_driver
249  #endif
250  
251 +#ifdef CONFIG_BCM63XX
252 +#include "ehci-bcm63xx.c"
253 +#define        PLATFORM_DRIVER         ehci_hcd_bcm63xx_driver
254 +#endif
255 +
256  #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \
257      !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER)
258  #error "missing bus glue for ehci-hcd"
259 --- a/drivers/usb/host/ehci.h
260 +++ b/drivers/usb/host/ehci.h
261 @@ -755,6 +755,11 @@ ehci_port_speed(struct ehci_hcd *ehci, u
262  #define writel_be(val, addr)   __raw_writel(val, (__force unsigned *)addr)
263  #endif
264  
265 +#if defined(CONFIG_MIPS) && defined(CONFIG_BCM63XX)
266 +#define readl_be(addr)         __raw_readl((__force unsigned *)addr)
267 +#define writel_be(val, addr)   __raw_writel(val, (__force unsigned *)addr)
268 +#endif
269 +
270  static inline unsigned int ehci_readl(const struct ehci_hcd *ehci,
271                 __u32 __iomem * regs)
272  {
273 --- /dev/null
274 +++ b/include/asm-mips/mach-bcm63xx/bcm63xx_dev_usb_ehci.h
275 @@ -0,0 +1,6 @@
276 +#ifndef BCM63XX_DEV_USB_EHCI_H_
277 +#define BCM63XX_DEV_USB_EHCI_H_
278 +
279 +int bcm63xx_ehci_register(void);
280 +
281 +#endif /* BCM63XX_DEV_USB_EHCI_H_ */