source: trunk/target/linux/brcm47xx/patches-2.6.39/022-USB-Add-ehci-ssb-driver.patch @ 27008

Last change on this file since 27008 was 27008, checked in by hauke, 5 years ago

brcm47xx: initial 2.6.39 support for brcm47xx

Thank you Peter Wagner for the patch

File size: 8.0 KB
  • drivers/usb/host/Kconfig

    a b config USB_OXU210HP_HCD 
    215215          To compile this driver as a module, choose M here: the 
    216216          module will be called oxu210hp-hcd. 
    217217 
     218config USB_EHCI_HCD_SSB 
     219        bool "EHCI support for Broadcom SSB EHCI core" 
     220        depends on USB_EHCI_HCD && (SSB = y || SSB = USB_EHCI_HCD) && EXPERIMENTAL 
     221        default n 
     222        ---help--- 
     223          Support for the Sonics Silicon Backplane (SSB) attached 
     224          Broadcom USB EHCI core. 
     225 
     226          This device is present in some embedded devices with 
     227          Broadcom based SSB bus. 
     228 
     229          If unsure, say N. 
     230 
    218231config USB_ISP116X_HCD 
    219232        tristate "ISP116X HCD support" 
    220233        depends on USB 
  • drivers/usb/host/ehci-hcd.c

    a b MODULE_LICENSE ("GPL"); 
    12651265#define PLATFORM_DRIVER         tegra_ehci_driver 
    12661266#endif 
    12671267 
     1268#ifdef CONFIG_USB_EHCI_HCD_SSB 
     1269#include "ehci-ssb.c" 
     1270#define SSB_EHCI_DRIVER         ssb_ehci_driver 
     1271#endif 
     1272 
    12681273#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ 
    12691274    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ 
    1270     !defined(XILINX_OF_PLATFORM_DRIVER) 
     1275    !defined(XILINX_OF_PLATFORM_DRIVER) && !defined(SSB_EHCI_DRIVER) 
    12711276#error "missing bus glue for ehci-hcd" 
    12721277#endif 
    12731278 
    static int __init ehci_hcd_init(void) 
    13271332        if (retval < 0) 
    13281333                goto clean4; 
    13291334#endif 
     1335 
     1336#ifdef SSB_EHCI_DRIVER 
     1337        retval = ssb_driver_register(&SSB_EHCI_DRIVER); 
     1338        if (retval < 0) 
     1339                goto clean5; 
     1340#endif 
    13301341        return retval; 
    13311342 
     1343#ifdef SSB_EHCI_DRIVER 
     1344        /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */ 
     1345clean5: 
     1346#endif 
    13321347#ifdef XILINX_OF_PLATFORM_DRIVER 
    1333         /* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */ 
     1348        platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); 
    13341349clean4: 
    13351350#endif 
    13361351#ifdef OF_PLATFORM_DRIVER 
    module_init(ehci_hcd_init); 
    13611376 
    13621377static void __exit ehci_hcd_cleanup(void) 
    13631378{ 
     1379#ifdef SSB_EHCI_DRIVER 
     1380        ssb_driver_unregister(&SSB_EHCI_DRIVER); 
     1381#endif 
    13641382#ifdef XILINX_OF_PLATFORM_DRIVER 
    13651383        platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); 
    13661384#endif 
  • new file drivers/usb/host/ehci-ssb.c

    - +  
     1/* 
     2 * Sonics Silicon Backplane 
     3 * Broadcom USB-core EHCI driver (SSB bus glue) 
     4 * 
     5 * Copyright 2007 Steven Brown <sbrown@cortland.com> 
     6 * Copyright 2010 Hauke Mehrtens <hauke@hauke-m.de> 
     7 * 
     8 * Derived from the OHCI-SSB driver 
     9 * Copyright 2007 Michael Buesch <mb@bu3sch.de> 
     10 * 
     11 * Derived from the EHCI-PCI driver 
     12 * Copyright (c) 2000-2004 by David Brownell 
     13 * 
     14 * Derived from the OHCI-PCI driver 
     15 * Copyright 1999 Roman Weissgaerber 
     16 * Copyright 2000-2002 David Brownell 
     17 * Copyright 1999 Linus Torvalds 
     18 * Copyright 1999 Gregory P. Smith 
     19 * 
     20 * Derived from the USBcore related parts of Broadcom-SB 
     21 * Copyright 2005 Broadcom Corporation 
     22 * 
     23 * Licensed under the GNU/GPL. See COPYING for details. 
     24 */ 
     25#include <linux/ssb/ssb.h> 
     26 
     27 
     28struct ssb_ehci_device { 
     29        struct ehci_hcd ehci; /* _must_ be at the beginning. */ 
     30}; 
     31 
     32static inline 
     33struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd) 
     34{ 
     35        return (struct ssb_ehci_device *)(hcd->hcd_priv); 
     36} 
     37 
     38static int ssb_ehci_reset(struct usb_hcd *hcd) 
     39{ 
     40        struct ehci_hcd *ehci = hcd_to_ehci(hcd); 
     41        int err; 
     42 
     43        ehci->caps = hcd->regs; 
     44        ehci->regs = hcd->regs + 
     45                HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); 
     46 
     47        dbg_hcs_params(ehci, "reset"); 
     48        dbg_hcc_params(ehci, "reset"); 
     49 
     50        ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); 
     51 
     52        err = ehci_halt(ehci); 
     53 
     54        if (err) 
     55                return err; 
     56 
     57        err = ehci_init(hcd); 
     58 
     59        if (err) 
     60                return err; 
     61 
     62        ehci_reset(ehci); 
     63 
     64        return err; 
     65} 
     66 
     67static const struct hc_driver ssb_ehci_hc_driver = { 
     68        .description            = "ssb-usb-ehci", 
     69        .product_desc           = "SSB EHCI Controller", 
     70        .hcd_priv_size          = sizeof(struct ssb_ehci_device), 
     71 
     72        .irq                    = ehci_irq, 
     73        .flags                  = HCD_MEMORY | HCD_USB2, 
     74 
     75        .reset                  = ssb_ehci_reset, 
     76        .start                  = ehci_run, 
     77        .stop                   = ehci_stop, 
     78        .shutdown               = ehci_shutdown, 
     79 
     80        .urb_enqueue            = ehci_urb_enqueue, 
     81        .urb_dequeue            = ehci_urb_dequeue, 
     82        .endpoint_disable       = ehci_endpoint_disable, 
     83        .endpoint_reset         = ehci_endpoint_reset, 
     84 
     85        .get_frame_number       = ehci_get_frame, 
     86 
     87        .hub_status_data        = ehci_hub_status_data, 
     88        .hub_control            = ehci_hub_control, 
     89#if defined(CONFIG_PM) 
     90        .bus_suspend            = ehci_bus_suspend, 
     91        .bus_resume             = ehci_bus_resume, 
     92#endif 
     93        .relinquish_port        = ehci_relinquish_port, 
     94        .port_handed_over       = ehci_port_handed_over, 
     95 
     96        .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, 
     97}; 
     98 
     99static void ssb_ehci_detach(struct ssb_device *dev) 
     100{ 
     101        struct usb_hcd *hcd = ssb_get_drvdata(dev); 
     102 
     103        if (hcd->driver->shutdown) 
     104                hcd->driver->shutdown(hcd); 
     105        usb_remove_hcd(hcd); 
     106        iounmap(hcd->regs); 
     107        release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 
     108        usb_put_hcd(hcd); 
     109        ssb_device_disable(dev, 0); 
     110} 
     111 
     112static int ssb_ehci_attach(struct ssb_device *dev) 
     113{ 
     114        struct ssb_ehci_device *ehcidev; 
     115        struct usb_hcd *hcd; 
     116        int err = -ENOMEM; 
     117        u32 tmp; 
     118 
     119        if (dma_set_mask(dev->dma_dev, DMA_BIT_MASK(32)) || 
     120            dma_set_coherent_mask(dev->dma_dev, DMA_BIT_MASK(32))) 
     121                return -EOPNOTSUPP; 
     122 
     123        /* 
     124         * USB 2.0 special considerations: 
     125         * 
     126         * In addition to the standard SSB reset sequence, the Host Control 
     127         * Register must be programmed to bring the USB core and various phy 
     128         * components out of reset. 
     129         */ 
     130        ssb_device_enable(dev, 0); 
     131        ssb_write32(dev, 0x200, 0x7ff); 
     132 
     133        /* Change Flush control reg */ 
     134        tmp = ssb_read32(dev, 0x400); 
     135        tmp &= ~8; 
     136        ssb_write32(dev, 0x400, tmp); 
     137        tmp = ssb_read32(dev, 0x400); 
     138 
     139        /* Change Shim control reg */ 
     140        tmp = ssb_read32(dev, 0x304); 
     141        tmp &= ~0x100; 
     142        ssb_write32(dev, 0x304, tmp); 
     143        tmp = ssb_read32(dev, 0x304); 
     144 
     145        udelay(1); 
     146 
     147        /* Work around for 5354 failures */ 
     148        if (dev->id.revision == 2 && dev->bus->chip_id == 0x5354) { 
     149                /* Change syn01 reg */ 
     150                tmp = 0x00fe00fe; 
     151                ssb_write32(dev, 0x894, tmp); 
     152 
     153                /* Change syn03 reg */ 
     154                tmp = ssb_read32(dev, 0x89c); 
     155                tmp |= 0x1; 
     156                ssb_write32(dev, 0x89c, tmp); 
     157        } 
     158 
     159        hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev, 
     160                             dev_name(dev->dev)); 
     161        if (!hcd) 
     162                goto err_dev_disable; 
     163 
     164        ehcidev = hcd_to_ssb_ehci(hcd); 
     165        tmp = ssb_read32(dev, SSB_ADMATCH0); 
     166        hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; /* ehci core offset */ 
     167        hcd->rsrc_len = 0x100; /* ehci reg block size */ 
     168        /* 
     169         * start & size modified per sbutils.c 
     170         */ 
     171        hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 
     172        if (!hcd->regs) 
     173                goto err_put_hcd; 
     174        err = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); 
     175        if (err) 
     176                goto err_iounmap; 
     177 
     178        ssb_set_drvdata(dev, hcd); 
     179 
     180        return err; 
     181 
     182err_iounmap: 
     183        iounmap(hcd->regs); 
     184err_put_hcd: 
     185        usb_put_hcd(hcd); 
     186err_dev_disable: 
     187        ssb_device_disable(dev, 0); 
     188        return err; 
     189} 
     190 
     191static int ssb_ehci_probe(struct ssb_device *dev, 
     192                const struct ssb_device_id *id) 
     193{ 
     194        int err; 
     195        u16 chipid_top; 
     196 
     197        /* USBcores are only connected on embedded devices. */ 
     198        chipid_top = (dev->bus->chip_id & 0xFF00); 
     199        if (chipid_top != 0x4700 && chipid_top != 0x5300) 
     200                return -ENODEV; 
     201 
     202        /* TODO: Probably need checks here; is the core connected? */ 
     203 
     204        if (usb_disabled()) 
     205                return -ENODEV; 
     206 
     207        err = ssb_ehci_attach(dev); 
     208 
     209        return err; 
     210} 
     211 
     212static void ssb_ehci_remove(struct ssb_device *dev) 
     213{ 
     214        ssb_ehci_detach(dev); 
     215} 
     216 
     217#ifdef CONFIG_PM 
     218 
     219static int ssb_ehci_suspend(struct ssb_device *dev, pm_message_t state) 
     220{ 
     221        ssb_device_disable(dev, 0); 
     222 
     223        return 0; 
     224} 
     225 
     226static int ssb_ehci_resume(struct ssb_device *dev) 
     227{ 
     228        struct usb_hcd *hcd = ssb_get_drvdata(dev); 
     229        struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd); 
     230 
     231        ssb_device_enable(dev, 0); 
     232 
     233        ehci_finish_controller_resume(hcd); 
     234        return 0; 
     235} 
     236 
     237#else /* !CONFIG_PM */ 
     238#define ssb_ehci_suspend        NULL 
     239#define ssb_ehci_resume NULL 
     240#endif /* CONFIG_PM */ 
     241 
     242static const struct ssb_device_id ssb_ehci_table[] = { 
     243        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), 
     244        SSB_DEVTABLE_END 
     245}; 
     246MODULE_DEVICE_TABLE(ssb, ssb_ehci_table); 
     247 
     248static struct ssb_driver ssb_ehci_driver = { 
     249        .name           = KBUILD_MODNAME, 
     250        .id_table       = ssb_ehci_table, 
     251        .probe          = ssb_ehci_probe, 
     252        .remove         = ssb_ehci_remove, 
     253        .suspend        = ssb_ehci_suspend, 
     254        .resume         = ssb_ehci_resume, 
     255}; 
Note: See TracBrowser for help on using the repository browser.