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

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

kernel: update to linux-3.0 and refresh patches.

Thank you Peter Wagner for the patch

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

    a b config USB_OXU210HP_HCD 
    230230          To compile this driver as a module, choose M here: the 
    231231          module will be called oxu210hp-hcd. 
    232232 
     233config USB_EHCI_HCD_SSB 
     234        bool "EHCI support for Broadcom SSB EHCI core" 
     235        depends on USB_EHCI_HCD && (SSB = y || SSB = USB_EHCI_HCD) && EXPERIMENTAL 
     236        default n 
     237        ---help--- 
     238          Support for the Sonics Silicon Backplane (SSB) attached 
     239          Broadcom USB EHCI core. 
     240 
     241          This device is present in some embedded devices with 
     242          Broadcom based SSB bus. 
     243 
     244          If unsure, say N. 
     245 
    233246config USB_ISP116X_HCD 
    234247        tristate "ISP116X HCD support" 
    235248        depends on USB 
  • drivers/usb/host/ehci-hcd.c

    a b MODULE_LICENSE ("GPL"); 
    12861286#define PLATFORM_DRIVER         ehci_grlib_driver 
    12871287#endif 
    12881288 
     1289#ifdef CONFIG_USB_EHCI_HCD_SSB 
     1290#include "ehci-ssb.c" 
     1291#define SSB_EHCI_DRIVER         ssb_ehci_driver 
     1292#endif 
     1293 
    12891294#if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ 
    12901295    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ 
    1291     !defined(XILINX_OF_PLATFORM_DRIVER) 
     1296    !defined(XILINX_OF_PLATFORM_DRIVER) && !defined(SSB_EHCI_DRIVER) 
    12921297#error "missing bus glue for ehci-hcd" 
    12931298#endif 
    12941299 
    static int __init ehci_hcd_init(void) 
    13481353        if (retval < 0) 
    13491354                goto clean4; 
    13501355#endif 
     1356 
     1357#ifdef SSB_EHCI_DRIVER 
     1358        retval = ssb_driver_register(&SSB_EHCI_DRIVER); 
     1359        if (retval < 0) 
     1360                goto clean5; 
     1361#endif 
    13511362        return retval; 
    13521363 
     1364#ifdef SSB_EHCI_DRIVER 
     1365        /* ssb_driver_unregister(&SSB_EHCI_DRIVER); */ 
     1366clean5: 
     1367#endif 
    13531368#ifdef XILINX_OF_PLATFORM_DRIVER 
    1354         /* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */ 
     1369        platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); 
    13551370clean4: 
    13561371#endif 
    13571372#ifdef OF_PLATFORM_DRIVER 
    module_init(ehci_hcd_init); 
    13821397 
    13831398static void __exit ehci_hcd_cleanup(void) 
    13841399{ 
     1400#ifdef SSB_EHCI_DRIVER 
     1401        ssb_driver_unregister(&SSB_EHCI_DRIVER); 
     1402#endif 
    13851403#ifdef XILINX_OF_PLATFORM_DRIVER 
    13861404        platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); 
    13871405#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, 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.