Update of /cvsroot/gc-linux/linux/drivers/usb/host In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv31074/drivers/usb/host Modified Files: Kconfig Makefile ehci-hcd.c ehci.h ohci-hcd.c ohci-q.c ohci.h rvl-sthcd.c Added Files: ehci-mipc.c ohci-mipc.c Log Message: Merge gc-linux-v2.6.30. Index: ohci-q.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/usb/host/ohci-q.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ohci-q.c 25 Oct 2009 18:45:36 -0000 1.1 --- ohci-q.c 25 Oct 2009 18:50:27 -0000 1.2 *************** *** 616,619 **** --- 616,622 ---- /* FALLTHROUGH */ case PIPE_BULK: + if (ohci->flags & OHCI_QUIRK_WII) + ohci_mipc_bulk_quirk(ohci); + info = is_out ? TD_T_TOGGLE | TD_CC | TD_DP_OUT *************** *** 647,650 **** --- 650,656 ---- */ case PIPE_CONTROL: + if (ohci->flags & OHCI_QUIRK_WII) + ohci_mipc_control_quirk(ohci); + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; td_fill (ohci, info, urb->setup_dma, 8, urb, cnt++); Index: ehci.h =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/usb/host/ehci.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ehci.h 25 Oct 2009 18:45:36 -0000 1.1 --- ehci.h 25 Oct 2009 18:50:27 -0000 1.2 *************** *** 38,41 **** --- 38,62 ---- #endif + /* + * Some platforms have weird constraints when accessing memory. + * + * For example, the Nintendo Wii video game console is unable to perform + * non-32 bit writes to non-cached memory for its second block of 64MB of RAM. + * As this platform also requires CONFIG_NOT_COHERENT, all memory allocated + * using the dma memory allocation functions can only be written using + * 32-bit accesses. + * + * Because of this constraint, as a workaround, we make sure that all + * fields in struct ehci_qh (which is allocated from a dma pool) are + * always 32 bit fields. + * Note that the remaining structs allocated from dma-able memory are already + * 32 bit fields. + */ + #ifdef CONFIG_USB_EHCI_HCD_MIPC + #define ehci_fld(type) u32 + #else + #define ehci_fld(type) type + #endif + /* statistics can be kept for for tuning/monitoring */ struct ehci_stats { *************** *** 336,340 **** unsigned stamp; ! u8 qh_state; #define QH_STATE_LINKED 1 /* HC sees this */ #define QH_STATE_UNLINK 2 /* HC may still see this */ --- 357,361 ---- unsigned stamp; ! ehci_fld(u8) qh_state; #define QH_STATE_LINKED 1 /* HC sees this */ #define QH_STATE_UNLINK 2 /* HC may still see this */ *************** *** 343,356 **** #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ ! u8 xacterrs; /* XactErr retry counter */ #define QH_XACTERR_MAX 32 /* XactErr retry limit */ /* periodic schedule info */ ! u8 usecs; /* intr bandwidth */ ! u8 gap_uf; /* uframes split/csplit gap */ ! u8 c_usecs; /* ... split completion bw */ ! u16 tt_usecs; /* tt downstream bandwidth */ ! unsigned short period; /* polling interval */ ! unsigned short start; /* where polling starts */ #define NO_FRAME ((unsigned short)~0) /* pick new start */ struct usb_device *dev; /* access to TT */ --- 364,377 ---- #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ ! ehci_fld(u8) xacterrs; /* XactErr retry counter */ #define QH_XACTERR_MAX 32 /* XactErr retry limit */ /* periodic schedule info */ ! ehci_fld(u8) usecs; /* intr bandwidth */ ! ehci_fld(u8) gap_uf; /* uframes split/csplit gap */ ! ehci_fld(u8) c_usecs; /* ... split completion bw */ ! ehci_fld(u16) tt_usecs; /* tt downstream bandwidth */ ! ehci_fld(unsigned short) period; /* polling interval */ ! ehci_fld(unsigned short) start; /* where polling starts */ #define NO_FRAME ((unsigned short)~0) /* pick new start */ struct usb_device *dev; /* access to TT */ *************** *** 589,592 **** --- 610,631 ---- #endif + #ifdef CONFIG_USB_EHCI_HCD_MIPC + + #include <asm/starlet-mini.h> + + static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, + __u32 __iomem *regs) + { + return mipc_in_be32(regs); + } + + static inline void ehci_writel(const struct ehci_hcd *ehci, + const unsigned int val, __u32 __iomem *regs) + { + mipc_out_be32(regs, val); + } + + #else + /* * Big-endian read/write functions are arch-specific. *************** *** 622,625 **** --- 661,666 ---- } + #endif /* CONFIG_USB_EHCI_HCD_MIPC */ + /* * On certain ppc-44x SoC there is a HW issue, that could only worked around with Index: Kconfig =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/usb/host/Kconfig,v retrieving revision 1.8 retrieving revision 1.9 diff -C2 -d -r1.8 -r1.9 *** Kconfig 25 Oct 2009 18:45:36 -0000 1.8 --- Kconfig 25 Oct 2009 18:50:27 -0000 1.9 *************** *** 94,97 **** --- 94,105 ---- OpenFirmware platform bus. + config USB_EHCI_HCD_MIPC + bool "Nintendo Wii EHCI USB controller support via 'mini'" + depends on USB_EHCI_HCD && STARLET_MINI + default y + ---help--- + Say Y here to support the EHCI USB controller found in the + Nintendo Wii video game console. + config USB_OXU210HP_HCD tristate "OXU210HP HCD support" *************** *** 170,173 **** --- 178,190 ---- OpenFirmware platform bus. + config USB_OHCI_HCD_MIPC + bool "Nintendo Wii OHCI USB controller support via 'mini'" + depends on USB_OHCI_HCD && STARLET_MINI + select USB_OHCI_LITTLE_ENDIAN + default y + ---help--- + Say Y here to support the OHCI USB controller found in the + Nintendo Wii video game console. + config USB_OHCI_HCD_PPC_OF_BE bool "Support big endian HC" *************** *** 323,326 **** --- 340,362 ---- SH7366 and SH7723 processors. + config USB_WII_HCD + tristate "Nintendo Wii HCD support" + depends on USB && STARLET_IOS && !HIGHMEM && EXPERIMENTAL + help + The Nintendo Wii includes a USB 1.1 host controller that can be + accessed through the API provided by the starlet subsystem. + + Enable this option if you plan to use the internal Nintendo Wii + bluetooth dongle or any USB peripheral connected to the external + ports. + + USB devices using isochronous transfers are not supported. + Use of USB hubs is partially supported. + + Use completely at you own risk. If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called rvl-sthcd. + config USB_WHCI_HCD tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" Index: Makefile =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/usb/host/Makefile,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** Makefile 25 Oct 2009 18:33:47 -0000 1.5 --- Makefile 25 Oct 2009 18:50:27 -0000 1.6 *************** *** 29,31 **** --- 29,32 ---- obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o obj-$(CONFIG_USB_ISP1760_HCD) += isp1760.o + obj-$(CONFIG_USB_WII_HCD) += rvl-sthcd.o obj-$(CONFIG_USB_HWA_HCD) += hwa-hc.o Index: ohci.h =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/usb/host/ohci.h,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ohci.h 25 Oct 2009 18:45:36 -0000 1.1 --- ohci.h 25 Oct 2009 18:50:27 -0000 1.2 *************** *** 17,20 **** --- 17,42 ---- /* + * Some platforms have weird constraints when accessing memory. + * + * For example, the Nintendo Wii video game console is unable to perform + * non-32 bit writes to non-cached memory for its second block of 64MB of RAM. + * As this platform also requires CONFIG_NOT_COHERENT_CACHE, all memory + * allocated using the dma memory allocation functions can only be written + * using 32-bit accesses. + * + * Because of this constraint, as a workaround, we make sure that all + * fields in struct ed and td (which are allocated from dma pools) are + * always 32 bit fields. + * Note that the remaining structs allocated from dma-able memory are already + * 32 bit fields. + */ + #ifdef CONFIG_USB_OHCI_HCD_MIPC + #define ohci_fld(type) u32 + #else + #define ohci_fld(type) type + #endif + + + /* * OHCI Endpoint Descriptor (ED) ... holds TD queue * See OHCI spec, section 4.2 *************** *** 52,70 **** * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... */ ! u8 state; /* ED_{IDLE,UNLINK,OPER} */ #define ED_IDLE 0x00 /* NOT linked to HC */ #define ED_UNLINK 0x01 /* being unlinked from hc */ #define ED_OPER 0x02 /* IS linked to hc */ ! u8 type; /* PIPE_{BULK,...} */ /* periodic scheduling params (for intr and iso) */ ! u8 branch; ! u16 interval; ! u16 load; ! u16 last_iso; /* iso only */ /* HC may see EDs on rm_list until next frame (frame_no == tick) */ ! u16 tick; } __attribute__ ((aligned(16))); --- 74,92 ---- * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... */ ! ohci_fld(u8) state; /* ED_{IDLE,UNLINK,OPER} */ #define ED_IDLE 0x00 /* NOT linked to HC */ #define ED_UNLINK 0x01 /* being unlinked from hc */ #define ED_OPER 0x02 /* IS linked to hc */ ! ohci_fld(u8) type; /* PIPE_{BULK,...} */ /* periodic scheduling params (for intr and iso) */ ! ohci_fld(u8) branch; ! ohci_fld(u16) interval; ! ohci_fld(u16) load; ! ohci_fld(u16) last_iso; /* iso only */ /* HC may see EDs on rm_list until next frame (frame_no == tick) */ ! ohci_fld(u16) tick; } __attribute__ ((aligned(16))); *************** *** 119,123 **** /* rest are purely for the driver's use */ ! __u8 index; struct ed *ed; struct td *td_hash; /* dma-->td hashtable */ --- 141,145 ---- /* rest are purely for the driver's use */ ! ohci_fld(__u8) index; struct ed *ed; struct td *td_hash; /* dma-->td hashtable */ *************** *** 403,406 **** --- 425,429 ---- #define OHCI_QUIRK_HUB_POWER 0x100 /* distrust firmware power/oc setup */ #define OHCI_QUIRK_AMD_ISO 0x200 /* ISO transfers*/ + #define OHCI_QUIRK_WII 0x400 /* Hollywood chipset */ // there are also chip quirks/bugs in init logic *************** *** 537,540 **** --- 560,594 ---- #endif + #ifdef CONFIG_USB_OHCI_HCD_MIPC + + #include <asm/starlet-mini.h> + + static inline unsigned int _ohci_readl(const struct ohci_hcd *ohci, + __hc32 __iomem *regs) + { + return mipc_in_be32(regs); + } + + static inline void _ohci_writel(const struct ohci_hcd *ohci, + const unsigned int val, __hc32 __iomem *regs) + { + mipc_out_be32(regs, val); + } + + extern void ohci_mipc_control_quirk(struct ohci_hcd *ohci); + extern void ohci_mipc_bulk_quirk(struct ohci_hcd *ohci); + + #else + + static inline void ohci_mipc_control_quirk(struct ohci_hcd *ohci) + { + return; + } + + static inline void ohci_mipc_bulk_quirk(struct ohci_hcd *ohci) + { + return; + } + /* * Big-endian read/write functions are arch-specific. *************** *** 566,569 **** --- 620,625 ---- } + #endif /* CONFIG_USB_OHCI_HCD_MIPC */ + #ifdef CONFIG_ARCH_LH7A404 /* Marc Singer: at the time this code was written, the LH7A404 Index: ohci-hcd.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/usb/host/ohci-hcd.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ohci-hcd.c 25 Oct 2009 18:45:36 -0000 1.1 --- ohci-hcd.c 25 Oct 2009 18:50:27 -0000 1.2 *************** *** 1062,1065 **** --- 1062,1070 ---- #endif + #ifdef CONFIG_USB_OHCI_HCD_MIPC + #include "ohci-mipc.c" + #define OF_PLATFORM_DRIVER ohci_hcd_mipc_driver + #endif + #ifdef CONFIG_PPC_PS3 #include "ohci-ps3.c" --- NEW FILE: ehci-mipc.c --- /* * drivers/usb/host/ehci-mipc.c * * Nintendo Wii USB Enhanced Host Controller Interface via 'mini' IPC (mipc). * Copyright (C) 2009 The GameCube Linux Team * Copyright (C) 2009 Albert Herranz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * Based on ehci-ppc-of.c * * EHCI HCD (Host Controller Driver) for USB. * * Bus Glue for PPC On-Chip EHCI driver on the of_platform bus * Tested on AMCC PPC 440EPx * * Valentine Barshak <vba...@ru...> * * Based on "ehci-ppc-soc.c" by Stefan Roese <sr...@de...> * and "ohci-ppc-of.c" by Sylvain Munaut <tn...@24...> * * This file is licenced under the GPL. */ #include <linux/signal.h> #include <linux/of.h> #include <linux/of_platform.h> #include <asm/starlet.h> #define DRV_MODULE_NAME "ehci-mipc" #define DRV_DESCRIPTION "USB Enhanced Host Controller Interface via MINI" #define DRV_AUTHOR "Albert Herranz" #define HOLLYWOOD_EHCI_CTL 0x0d0400cc #define HOLLYWOOD_EHCI_CTL_INTE (1<<15) /* called during probe() after chip reset completes */ static int ehci_mipc_reset(struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *ehci_ctl; int error; error = ehci_halt(ehci); if (error) goto out; error = ehci_init(hcd); if (error) goto out; ehci_ctl = mipc_ioremap(HOLLYWOOD_EHCI_CTL, 4); if (!ehci_ctl) { printk(KERN_ERR __FILE__ ": ioremap failed\n"); error = -EBUSY; goto out; } /* enable notification of EHCI interrupts */ mipc_out_be32(ehci_ctl, mipc_in_be32(ehci_ctl) | HOLLYWOOD_EHCI_CTL_INTE); mipc_iounmap(ehci_ctl); ehci->sbrn = 0x20; error = ehci_reset(ehci); out: return error; } static const struct hc_driver ehci_mipc_hc_driver = { .description = hcd_name, .product_desc = "Nintendo Wii EHCI Host Controller", .hcd_priv_size = sizeof(struct ehci_hcd), /* * generic hardware linkage */ .irq = ehci_irq, .flags = HCD_USB2 | HCD_BOUNCE_DMA_MEM, /* * basic lifecycle operations */ .reset = ehci_mipc_reset, .start = ehci_run, .stop = ehci_stop, .shutdown = ehci_shutdown, /* * managing i/o requests and associated device resources */ .urb_enqueue = ehci_urb_enqueue, .urb_dequeue = ehci_urb_dequeue, .endpoint_disable = ehci_endpoint_disable, /* * scheduling support */ .get_frame_number = ehci_get_frame, /* * root hub support */ .hub_status_data = ehci_hub_status_data, .hub_control = ehci_hub_control, #ifdef CONFIG_PM .bus_suspend = ehci_bus_suspend, .bus_resume = ehci_bus_resume, #endif .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, }; static int __devinit ehci_hcd_mipc_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dn = op->node; struct usb_hcd *hcd; struct ehci_hcd *ehci = NULL; struct resource res; dma_addr_t coherent_mem_addr; size_t coherent_mem_size; int irq; int error = -ENODEV; if (usb_disabled()) goto out; if (starlet_get_ipc_flavour() != STARLET_IPC_MINI) goto out; dev_dbg(&op->dev, "initializing " DRV_MODULE_NAME " USB Controller\n"); error = of_address_to_resource(dn, 0, &res); if (error) goto out; hcd = usb_create_hcd(&ehci_mipc_hc_driver, &op->dev, DRV_MODULE_NAME); if (!hcd) { error = -ENOMEM; goto out; } hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); error = of_address_to_resource(dn, 1, &res); if (error) { /* satisfy coherent memory allocations from mem1 or mem2 */ dev_warn(&op->dev, "using normal memory\n"); } else { coherent_mem_addr = res.start; coherent_mem_size = res.end - res.start + 1; if (!dma_declare_coherent_memory(&op->dev, coherent_mem_addr, coherent_mem_addr, coherent_mem_size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) { dev_err(&op->dev, "error declaring %u bytes of" " coherent memory at 0x%p\n", coherent_mem_size, (void *)coherent_mem_addr); error = -EBUSY; goto err_decl_coherent; } } irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); error = -EBUSY; goto err_irq; } hcd->regs = mipc_ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { printk(KERN_ERR __FILE__ ": ioremap failed\n"); error = -EBUSY; goto err_ioremap; } ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; ehci->regs = hcd->regs + HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); /* cache this readonly data; minimize chip reads */ ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); error = usb_add_hcd(hcd, irq, 0); if (error == 0) return 0; mipc_iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: dma_release_declared_memory(&op->dev); err_decl_coherent: usb_put_hcd(hcd); out: return error; } static int ehci_hcd_mipc_remove(struct of_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); dev_dbg(&op->dev, "stopping " DRV_MODULE_NAME " USB Controller\n"); usb_remove_hcd(hcd); mipc_iounmap(hcd->regs); irq_dispose_mapping(hcd->irq); dma_release_declared_memory(&op->dev); usb_put_hcd(hcd); return 0; } static int ehci_hcd_mipc_shutdown(struct of_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); return 0; } static struct of_device_id ehci_hcd_mipc_match[] = { { .compatible = "nintendo,hollywood-ehci", }, {}, }; MODULE_DEVICE_TABLE(of, ehci_hcd_mipc_match); static struct of_platform_driver ehci_hcd_mipc_driver = { .name = DRV_MODULE_NAME, .match_table = ehci_hcd_mipc_match, .probe = ehci_hcd_mipc_probe, .remove = ehci_hcd_mipc_remove, .shutdown = ehci_hcd_mipc_shutdown, .driver = { .name = DRV_MODULE_NAME, .owner = THIS_MODULE, }, }; --- NEW FILE: ohci-mipc.c --- /* * drivers/usb/host/ohci-mipc.c * * Nintendo Wii USB Open Host Controller Interface via 'mini' IPC (mipc). * Copyright (C) 2009 The GameCube Linux Team * Copyright (C) 2009 Albert Herranz * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * Based on ohci-ppc-of.c * * OHCI HCD (Host Controller Driver) for USB. * * (C) Copyright 1999 Roman Weissgaerber <we...@vi...> * (C) Copyright 2000-2002 David Brownell <dbr...@us...> * (C) Copyright 2002 Hewlett-Packard Company * (C) Copyright 2006 Sylvain Munaut <tn...@24...> * * Bus glue for OHCI HC on the of_platform bus * * Modified for of_platform bus from ohci-sa1111.c * * This file is licenced under the GPL. */ #include <linux/signal.h> #include <linux/of_platform.h> #include <asm/prom.h> #include <asm/starlet.h> #include <asm/time.h> /* for get_tbl() */ #define DRV_MODULE_NAME "ohci-mipc" #define DRV_DESCRIPTION "USB Open Host Controller Interface for MINI" #define DRV_AUTHOR "Albert Herranz" #define HOLLYWOOD_EHCI_CTL 0x0d0400cc /* vendor control register */ #define HOLLYWOOD_EHCI_CTL_OH0INTE (1<<11) /* oh0 interrupt enable */ #define HOLLYWOOD_EHCI_CTL_OH1INTE (1<<12) /* oh1 interrupt enable */ #define __spin_event_timeout(condition, timeout_usecs, result, __end_tbl) \ for (__end_tbl = get_tbl() + tb_ticks_per_usec * timeout_usecs; \ !(result = (condition)) && (int)(__end_tbl - get_tbl()) > 0;) static DEFINE_SPINLOCK(control_quirk_lock); void ohci_mipc_control_quirk(struct ohci_hcd *ohci) { static struct ed *ed; /* empty ED */ struct td *td; /* dummy TD */ __hc32 head; __hc32 current; unsigned long ctx; int result; unsigned long flags; /* * One time only. * Allocate and keep a special empty ED with just a dummy TD. */ if (!ed) { ed = ed_alloc(ohci, GFP_ATOMIC); if (!ed) return; td = td_alloc(ohci, GFP_ATOMIC); if (!td) { ed_free(ohci, ed); ed = NULL; return; } ed->hwNextED = 0; ed->hwTailP = ed->hwHeadP = cpu_to_hc32(ohci, td->td_dma & ED_MASK); ed->hwINFO |= cpu_to_hc32(ohci, ED_OUT); wmb(); } spin_lock_irqsave(&control_quirk_lock, flags); /* * The OHCI USB host controllers on the Nintendo Wii * video game console stop working when new TDs are * added to a scheduled control ED after a transfer has * has taken place on it. * * Before scheduling any new control TD, we make the * controller happy by always loading a special control ED * with a single dummy TD and letting the controller attempt * the transfer. * The controller won't do anything with it, as the special * ED has no TDs, but it will keep the controller from failing * on the next transfer. */ head = ohci_readl(ohci, &ohci->regs->ed_controlhead); if (head) { /* * Load the special empty ED and tell the controller to * process the control list. */ ohci_writel(ohci, ed->dma, &ohci->regs->ed_controlhead); ohci_writel (ohci, ohci->hc_control | OHCI_CTRL_CLE, &ohci->regs->control); ohci_writel (ohci, OHCI_CLF, &ohci->regs->cmdstatus); /* spin until the controller is done with the control list */ current = ohci_readl(ohci, &ohci->regs->ed_controlcurrent); __spin_event_timeout(!current, 10 /* usecs */, result, ctx) { cpu_relax(); current = ohci_readl(ohci, &ohci->regs->ed_controlcurrent); } /* restore the old control head and control settings */ ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); ohci_writel(ohci, head, &ohci->regs->ed_controlhead); } spin_unlock_irqrestore(&control_quirk_lock, flags); } void ohci_mipc_bulk_quirk(struct ohci_hcd *ohci) { /* * There seem to be issues too with the bulk list processing on the * OHCI controller found in the Nintendo Wii video game console. * The exact problem remains still unidentified, but adding a small * delay seems to workaround it. * * As an example, without this quirk the wiimote controller stops * responding after a few seconds because one of its bulk endpoint * descriptors gets stuck. */ udelay(250); } static int __devinit ohci_mipc_start(struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci(hcd); void __iomem *ehci_ctl; int error; error = ohci_init(ohci); if (error) goto out; ehci_ctl = mipc_ioremap(HOLLYWOOD_EHCI_CTL, 4); if (!ehci_ctl) { printk(KERN_ERR __FILE__ ": ioremap failed\n"); error = -EBUSY; ohci_stop(hcd); goto out; } /* enable notification of OHCI interrupts */ mipc_out_be32(ehci_ctl, mipc_in_be32(ehci_ctl) | 0xe0000 | HOLLYWOOD_EHCI_CTL_OH0INTE | HOLLYWOOD_EHCI_CTL_OH1INTE); mipc_iounmap(ehci_ctl); error = ohci_run(ohci); if (error) { err("can't start %s", ohci_to_hcd(ohci)->self.bus_name); ohci_stop(hcd); goto out; } out: return error; } static const struct hc_driver ohci_mipc_hc_driver = { .description = hcd_name, .product_desc = "Nintendo Wii OHCI Host Controller", .hcd_priv_size = sizeof(struct ohci_hcd), /* * generic hardware linkage */ .irq = ohci_irq, .flags = HCD_USB11 | HCD_BOUNCE_DMA_MEM, /* * basic lifecycle operations */ .start = ohci_mipc_start, .stop = ohci_stop, .shutdown = ohci_shutdown, /* * managing i/o requests and associated device resources */ .urb_enqueue = ohci_urb_enqueue, .urb_dequeue = ohci_urb_dequeue, .endpoint_disable = ohci_endpoint_disable, /* * scheduling support */ .get_frame_number = ohci_get_frame, /* * root hub support */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, #endif .start_port_reset = ohci_start_port_reset, }; static int __devinit ohci_hcd_mipc_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dn = op->node; struct usb_hcd *hcd; struct ohci_hcd *ohci = NULL; struct resource res; dma_addr_t coherent_mem_addr; size_t coherent_mem_size; int irq; int error = -ENODEV; if (usb_disabled()) goto out; if (starlet_get_ipc_flavour() != STARLET_IPC_MINI) goto out; dev_dbg(&op->dev, "initializing " DRV_MODULE_NAME " USB Controller\n"); error = of_address_to_resource(dn, 0, &res); if (error) goto out; hcd = usb_create_hcd(&ohci_mipc_hc_driver, &op->dev, DRV_MODULE_NAME); if (!hcd) { error = -ENOMEM; goto out; } hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); error = of_address_to_resource(dn, 1, &res); if (error) { /* satisfy coherent memory allocations from mem1 or mem2 */ dev_warn(&op->dev, "using normal memory\n"); } else { coherent_mem_addr = res.start; coherent_mem_size = res.end - res.start + 1; if (!dma_declare_coherent_memory(&op->dev, coherent_mem_addr, coherent_mem_addr, coherent_mem_size, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) { dev_err(&op->dev, "error declaring %u bytes of" " coherent memory at 0x%p\n", coherent_mem_size, (void *)coherent_mem_addr); error = -EBUSY; goto err_decl_coherent; } } irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n"); error = -EBUSY; goto err_irq; } hcd->regs = mipc_ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { printk(KERN_ERR __FILE__ ": ioremap failed\n"); error = -EBUSY; goto err_ioremap; } ohci = hcd_to_ohci(hcd); ohci->flags |= OHCI_QUIRK_WII; ohci_hcd_init(ohci); error = usb_add_hcd(hcd, irq, IRQF_DISABLED); if (error) goto err_add_hcd; return 0; err_add_hcd: mipc_iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: dma_release_declared_memory(&op->dev); err_decl_coherent: usb_put_hcd(hcd); out: return error; } static int ohci_hcd_mipc_remove(struct of_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); dev_set_drvdata(&op->dev, NULL); dev_dbg(&op->dev, "stopping " DRV_MODULE_NAME " USB Controller\n"); usb_remove_hcd(hcd); mipc_iounmap(hcd->regs); irq_dispose_mapping(hcd->irq); dma_release_declared_memory(&op->dev); usb_put_hcd(hcd); return 0; } static int ohci_hcd_mipc_shutdown(struct of_device *op) { struct usb_hcd *hcd = dev_get_drvdata(&op->dev); if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); return 0; } static struct of_device_id ohci_hcd_mipc_match[] = { { .compatible = "nintendo,hollywood-ohci", }, {}, }; MODULE_DEVICE_TABLE(of, ohci_hcd_mipc_match); static struct of_platform_driver ohci_hcd_mipc_driver = { .name = DRV_MODULE_NAME, .match_table = ohci_hcd_mipc_match, .probe = ohci_hcd_mipc_probe, .remove = ohci_hcd_mipc_remove, .shutdown = ohci_hcd_mipc_shutdown, .driver = { .name = DRV_MODULE_NAME, .owner = THIS_MODULE, }, }; Index: ehci-hcd.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/usb/host/ehci-hcd.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** ehci-hcd.c 25 Oct 2009 18:45:36 -0000 1.1 --- ehci-hcd.c 25 Oct 2009 18:50:27 -0000 1.2 *************** *** 1063,1066 **** --- 1063,1071 ---- #endif + #ifdef CONFIG_USB_EHCI_HCD_MIPC + #include "ehci-mipc.c" + #define OF_PLATFORM_DRIVER ehci_hcd_mipc_driver + #endif + #ifdef CONFIG_PLAT_ORION #include "ehci-orion.c" Index: rvl-sthcd.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/usb/host/rvl-sthcd.c,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** rvl-sthcd.c 1 Feb 2009 18:29:35 -0000 1.5 --- rvl-sthcd.c 25 Oct 2009 18:50:27 -0000 1.6 *************** *** 36,39 **** --- 36,40 ---- #include <linux/usb.h> #include <asm/starlet.h> + #include <asm/starlet-ios.h> #include "../core/hcd.h" *************** *** 45,49 **** "Albert Herranz" ! static char sthcd_driver_version[] = "0.4i"; #define drv_printk(level, format, arg...) \ --- 46,50 ---- "Albert Herranz" ! static char sthcd_driver_version[] = "0.5i"; #define drv_printk(level, format, arg...) \ *************** *** 2264,2267 **** --- 2265,2271 ---- int error = -ENOMEM; + if (starlet_get_ipc_flavour() != STARLET_IPC_IOS) + return -ENODEV; + /* * We can't use normal dma as starlet requires MEM2 buffers *************** *** 2329,2333 **** static struct of_device_id sthcd_of_match[] = { ! { .compatible = "nintendo,starlet-hcd" }, { }, }; --- 2333,2337 ---- static struct of_device_id sthcd_of_match[] = { ! { .compatible = "nintendo,starlet-ios-hcd" }, { }, }; |