Ticket #3365: ssb-ehci-25.patch

File ssb-ehci-25.patch, 13.8 KB (added by sbrown, 9 years ago)

Revised patch that doesn't hack ssb core scanner

  • build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ehci-hcd.c

    diff -ur ../openwrt-25/build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ehci-hcd.c build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ehci-hcd.c
    old new  
    10431043#define PLATFORM_DRIVER         ixp4xx_ehci_driver 
    10441044#endif 
    10451045 
    1046 #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ 
    1047     !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) 
     1046#ifdef CONFIG_USB_EHCI_HCD_SSB 
     1047#include "ehci-ssb.c" 
     1048#define SSB_EHCI_DRIVER         ssb_ehci_driver 
     1049#endif 
     1050 
     1051#if !defined(PCI_DRIVER) && \ 
     1052    !defined(PLATFORM_DRIVER) && \ 
     1053    !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) && \ 
     1054    !defined(SSB_EHCI_DRIVER) 
    10481055#error "missing bus glue for ehci-hcd" 
    10491056#endif 
    10501057 
     
    10861093        if (retval < 0) 
    10871094                goto clean3; 
    10881095#endif 
     1096 
     1097#ifdef SSB_EHCI_DRIVER 
     1098        retval = ssb_driver_register(&SSB_EHCI_DRIVER); 
     1099        if (retval < 0) 
     1100                goto clean4; 
     1101#endif 
     1102 
    10891103        return retval; 
    10901104 
     1105#ifdef SSB_EHCI_DRIVER 
     1106clean4: 
     1107        ssb_driver_unregister(&SSB_EHCI_DRIVER); 
     1108#endif 
    10911109#ifdef OF_PLATFORM_DRIVER 
    10921110        /* of_unregister_platform_driver(&OF_PLATFORM_DRIVER); */ 
    10931111clean3: 
     
    11291147#ifdef DEBUG 
    11301148        debugfs_remove(ehci_debug_root); 
    11311149#endif 
     1150#ifdef SSB_EHCI_DRIVER 
     1151        ssb_driver_unregister(&SSB_EHCI_DRIVER); 
     1152#endif 
    11321153} 
    11331154module_exit(ehci_hcd_cleanup); 
    11341155 
  • build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ehci-ssb.c

    diff -ur ../openwrt-25/build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ehci-ssb.c build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ehci-ssb.c
    old new  
     1/* 
     2 * Sonics Silicon Backplane 
     3 * Broadcom USB-core EHCI driver (SSB bus glue) 
     4 *  
     5 * Copyright 2007 Steven Brown <sbrown@cortland.com> 
     6 * 
     7 * Derived from the OHCI-SSB driver 
     8 * Copyright 2007 Michael Buesch <mb@bu3sch.de> 
     9 * 
     10 * Derived from the EHCI-PCI driver 
     11 * Copyright (c) 2000-2004 by David Brownell 
     12 * 
     13 * Derived from the OHCI-PCI driver 
     14 * Copyright 1999 Roman Weissgaerber 
     15 * Copyright 2000-2002 David Brownell 
     16 * Copyright 1999 Linus Torvalds 
     17 * Copyright 1999 Gregory P. Smith 
     18 * 
     19 * Derived from the USBcore related parts of Broadcom-SB 
     20 * Copyright 2005 Broadcom Corporation 
     21 * 
     22 * Licensed under the GNU/GPL. See COPYING for details. 
     23 */ 
     24#include <linux/ssb/ssb.h> 
     25 
     26extern int ssb_ohci_attach(struct ssb_device *dev); 
     27extern void ssb_ohci_detach(struct ssb_device *dev); 
     28 
     29#define SSB_OHCI_TMSLOW_HOSTMODE        (1 << 29) 
     30 
     31struct ssb_ehci_device { 
     32        struct ehci_hcd ehci; /* _must_ be at the beginning. */ 
     33 
     34        u32 enable_flags; 
     35}; 
     36 
     37static inline 
     38struct ssb_ehci_device *hcd_to_ssb_ehci(struct usb_hcd *hcd) 
     39{ 
     40        return (struct ssb_ehci_device *)(hcd->hcd_priv); 
     41} 
     42 
     43 
     44static int ssb_ehci_reset(struct usb_hcd *hcd) 
     45{ 
     46        struct ehci_hcd *ehci = hcd_to_ehci(hcd); 
     47        int err; 
     48 
     49 ehci->caps = hcd->regs; 
     50 ehci->regs = hcd->regs +  
     51   HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); 
     52 
     53 dbg_hcs_params(ehci, "reset"); 
     54 dbg_hcc_params(ehci, "reset"); 
     55 
     56 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); 
     57 
     58 err = ehci_halt(ehci); 
     59 
     60 if (err) 
     61   return err; 
     62 
     63 err = ehci_init(hcd); 
     64 
     65 if (err) 
     66   return err; 
     67 
     68 ehci_port_power(ehci, 0); 
     69 
     70        return err; 
     71} 
     72 
     73static int ssb_ehci_start(struct usb_hcd *hcd) 
     74{ 
     75        struct ehci_hcd *ehci = hcd_to_ehci(hcd); 
     76        int err; 
     77 
     78        err = ehci_run(hcd); 
     79        if (err < 0) { 
     80                ehci_err(ehci, "can't start\n"); 
     81                ehci_stop(hcd); 
     82        } 
     83 
     84        return err; 
     85} 
     86 
     87#ifdef CONFIG_PM 
     88static int ssb_ehci_hcd_suspend(struct usb_hcd *hcd, pm_message_t message) 
     89{ 
     90        struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd); 
     91        struct ehci_hcd *ehci = &ehcidev->ehci; 
     92        unsigned long flags; 
     93 
     94        spin_lock_irqsave(&ehci->lock, flags); 
     95 
     96        ehci_writel(ehci, EHCI_INTR_MIE, &ehci->regs->intrdisable); 
     97        ehci_readl(ehci, &ehci->regs->intrdisable); /* commit write */ 
     98 
     99        /* make sure snapshot being resumed re-enumerates everything */ 
     100        if (message.event == PM_EVENT_PRETHAW) 
     101                ehci_usb_reset(ehci); 
     102 
     103        clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 
     104 
     105        spin_unlock_irqrestore(&ehci->lock, flags); 
     106        return 0; 
     107} 
     108 
     109static int ssb_ehci_hcd_resume(struct usb_hcd *hcd) 
     110{ 
     111        set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 
     112        usb_hcd_resume_root_hub(hcd); 
     113        return 0; 
     114} 
     115#endif /* CONFIG_PM */ 
     116 
     117static const struct hc_driver ssb_ehci_hc_driver = { 
     118        .description            = "ssb-usb-ehci", 
     119        .product_desc           = "SSB EHCI Controller", 
     120        .hcd_priv_size          = sizeof(struct ssb_ehci_device), 
     121 
     122        .irq                    = ehci_irq, 
     123        .flags                  = HCD_MEMORY | HCD_USB2, 
     124 
     125        .reset                  = ssb_ehci_reset, 
     126        .start                  = ssb_ehci_start, 
     127        .stop                   = ehci_stop, 
     128        .shutdown               = ehci_shutdown, 
     129 
     130#ifdef CONFIG_PM 
     131        .suspend                = ssb_ehci_hcd_suspend, 
     132        .resume                 = ssb_ehci_hcd_resume, 
     133#endif 
     134 
     135        .urb_enqueue            = ehci_urb_enqueue, 
     136        .urb_dequeue            = ehci_urb_dequeue, 
     137        .endpoint_disable       = ehci_endpoint_disable, 
     138 
     139        .get_frame_number       = ehci_get_frame, 
     140 
     141        .hub_status_data        = ehci_hub_status_data, 
     142        .hub_control            = ehci_hub_control, 
     143//      .hub_irq_enable         = ehci_rhsc_enable, 
     144#ifdef CONFIG_PM 
     145        .bus_suspend            = ehci_bus_suspend, 
     146        .bus_resume             = ehci_bus_resume, 
     147#endif 
     148 
     149//      .start_port_reset       = ehci_start_port_reset, 
     150}; 
     151 
     152static void ssb_ehci_detach(struct ssb_device *dev) 
     153{ 
     154        struct usb_hcd *hcd = ssb_get_drvdata(dev); 
     155 
     156        usb_remove_hcd(hcd); 
     157        iounmap(hcd->regs); 
     158        usb_put_hcd(hcd); 
     159 
     160#ifdef CONFIG_USB_OHCI_HCD_SSB 
     161/* 
     162 * Also detach the companion ohci device 
     163 */ 
     164        ssb_ohci_detach(dev->companion); 
     165//      ssb_device_disable(dev, 0); 
     166#endif 
     167} 
     168 
     169static int ssb_ehci_attach(struct ssb_device *dev) 
     170{ 
     171        struct ssb_ehci_device *ehcidev; 
     172        struct usb_hcd *hcd; 
     173        int err = -ENOMEM; 
     174        u32 tmp, flags = 0; 
     175 
     176 /* 
     177  * THE FOLLOWING COMMENTS PRESERVED FROM GPL SOURCE RELEASE 
     178  * 
     179  * The USB core requires a special bit to be set during core 
     180  * reset to enable host (OHCI) mode. Resetting the SB core in 
     181  * pcibios_enable_device() is a hack for compatibility with 
     182  * vanilla usb-ohci so that it does not have to know about 
     183  * SB. A driver that wants to use the USB core in device mode 
     184  * should know about SB and should reset the bit back to 0 
     185  * after calling pcibios_enable_device(). 
     186  */ 
     187 
     188 /* 
     189  * USB 2.0 special considerations: 
     190  * 
     191  * 1. Since the core supports both OHCI and EHCI functions, it must 
     192  *    only be reset once. 
     193  * 
     194  * 2. In addition to the standard SB reset sequence, the Host Control 
     195  *    Register must be programmed to bring the USB core and various 
     196  *    phy components out of reset. 
     197  */ 
     198 
     199        if (ssb_device_is_enabled(dev)) 
     200                goto core_already_enabled; 
     201 
     202        ssb_device_enable(dev, 0); 
     203        ssb_write32(dev, 0x200, 0x7ff); 
     204        udelay(1); 
     205        if (dev->id.revision == 1) { // bug in rev 1 
     206 
     207                /* Change Flush control reg */ 
     208                tmp = ssb_read32(dev, 0x400); 
     209                tmp &= ~8; 
     210                ssb_write32(dev, 0x400, tmp); 
     211                tmp = ssb_read32(dev, 0x400); 
     212                printk("USB20H fcr: 0x%0x\n", tmp); 
     213 
     214                /* Change Shim control reg */ 
     215                tmp = ssb_read32(dev, 0x304); 
     216                tmp &= ~0x100; 
     217                ssb_write32(dev, 0x304, tmp); 
     218                tmp = ssb_read32(dev, 0x304); 
     219                printk("USB20H shim: 0x%0x\n", tmp); 
     220        } 
     221 
     222core_already_enabled: 
     223        /* 
     224         * Try to understand the dma mask stuff 
     225         */ 
     226        tmp = ssb_read32(dev, SSB_TMSHIGH); 
     227        err = ssb_dma_set_mask(dev, DMA_32BIT_MASK); 
     228        if (err) 
     229          return -EOPNOTSUPP; 
     230 
     231        hcd = usb_create_hcd(&ssb_ehci_hc_driver, dev->dev, 
     232                        dev->dev->bus_id); 
     233        if (!hcd) 
     234                goto err_dev_disable; 
     235        ehcidev = hcd_to_ssb_ehci(hcd); 
     236        ehcidev->enable_flags = flags; 
     237 
     238        tmp = ssb_read32(dev, SSB_ADMATCH0); 
     239        hcd->rsrc_start = ssb_admatch_base(tmp) + 0x800; // offset for ehci core 
     240        hcd->rsrc_len = 0x100 /*ssb_admatch_size(tmp)*/; // size of ehci reg block 
     241        /* 
     242         * start & size modified per sbutils.c 
     243         */ 
     244        hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 
     245        if (!hcd->regs) 
     246                goto err_put_hcd; 
     247        err = usb_add_hcd(hcd, dev->irq, IRQF_SHARED | IRQF_DISABLED); 
     248        if (err) 
     249                goto err_iounmap; 
     250 
     251        ssb_set_drvdata(dev, hcd); 
     252 
     253#ifdef CONFIG_USB_OHCI_HCD_SSB 
     254        /* 
     255         * attach ohci (companion) device in this core 
     256         * 
     257         * add new device as a copy of the ehci device 
     258         * change coreid to SSB_DEV_USB11_HOSTDEV 
     259         * call ohci_ssb_attach(dev) to attach ohci device in this core 
     260         */ 
     261 
     262        dev->companion = &dev->bus->devices[dev->bus->nr_devices]; 
     263        dev->bus->nr_devices++; 
     264        if (dev->bus->nr_devices > ARRAY_SIZE(dev->bus->devices)) { 
     265                printk(KERN_ERR  
     266                        "More than %d devs, could not create ohci dev (%d)\n", 
     267                        SSB_MAX_NR_CORES, dev->bus->nr_devices); 
     268                        return err; 
     269        } 
     270        memcpy(dev->companion, dev, sizeof(struct ssb_device)); 
     271        dev->companion->id.coreid = SSB_DEV_USB11_HOSTDEV; 
     272        err = ssb_ohci_attach(dev->companion); 
     273        return err; 
     274#endif 
     275 
     276err_iounmap: 
     277        iounmap(hcd->regs); 
     278err_put_hcd: 
     279        usb_put_hcd(hcd); 
     280err_dev_disable: 
     281        ssb_device_disable(dev, flags); 
     282        return err; 
     283} 
     284 
     285static int ssb_ehci_probe(struct ssb_device *dev, 
     286                const struct ssb_device_id *id) 
     287{ 
     288        int err; 
     289        u16 chipid_top; 
     290 
     291        /* USBcores are only connected on embedded devices. */ 
     292        chipid_top = (dev->bus->chip_id & 0xFF00); 
     293        if (chipid_top != 0x4700 && chipid_top != 0x5300) 
     294                return -ENODEV; 
     295 
     296        /* TODO: Probably need checks here; is the core connected? */ 
     297 
     298        if (usb_disabled()) 
     299                return -ENODEV; 
     300 
     301        err = ssb_ehci_attach(dev); 
     302 
     303        return err; 
     304} 
     305 
     306static void ssb_ehci_remove(struct ssb_device *dev) 
     307{ 
     308        ssb_ehci_detach(dev); 
     309} 
     310 
     311#ifdef CONFIG_PM 
     312 
     313static int ssb_ehci_suspend(struct ssb_device *dev, pm_message_t state) 
     314{ 
     315        ssb_device_disable(dev, 0); 
     316 
     317        return 0; 
     318} 
     319 
     320static int ssb_ehci_resume(struct ssb_device *dev) 
     321{ 
     322        struct usb_hcd *hcd = ssb_get_drvdata(dev); 
     323        struct ssb_ehci_device *ehcidev = hcd_to_ssb_ehci(hcd); 
     324 
     325        ssb_device_enable(dev, ehcidev->enable_flags); 
     326 
     327        return 0; 
     328} 
     329 
     330#else /* !CONFIG_PM */ 
     331#define ssb_ehci_suspend        NULL 
     332#define ssb_ehci_resume NULL 
     333#endif /* CONFIG_PM */ 
     334 
     335static const struct ssb_device_id ssb_ehci_table[] = { 
     336        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), 
     337        SSB_DEVTABLE_END 
     338}; 
     339MODULE_DEVICE_TABLE(ssb, ssb_ehci_table); 
     340 
     341static struct ssb_driver ssb_ehci_driver = { 
     342        .name           = KBUILD_MODNAME, 
     343        .id_table       = ssb_ehci_table, 
     344        .probe          = ssb_ehci_probe, 
     345        .remove         = ssb_ehci_remove, 
     346        .suspend        = ssb_ehci_suspend, 
     347        .resume         = ssb_ehci_resume, 
     348}; 
  • build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/Kconfig

    diff -ur ../openwrt-25/build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/Kconfig build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/Kconfig
    old new  
    8383          Enables support for the USB controller present on the PowerPC 
    8484          OpenFirmware platform bus. 
    8585 
     86config USB_EHCI_HCD_SSB 
     87        bool "EHCI support for Broadcom SSB EHCI core" 
     88        depends on USB_EHCI_HCD && SSB && EXPERIMENTAL 
     89        default n 
     90        ---help--- 
     91          Support for the Sonics Silicon Backplane (SSB) attached 
     92          Broadcom USB EHCI core. 
     93 
     94          This device is present in some embedded devices with 
     95          Broadcom based SSB bus. 
     96 
     97          If unsure, say N. 
     98 
    8699config USB_ISP116X_HCD 
    87100        tristate "ISP116X HCD support" 
    88101        depends on USB 
  • build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ohci-ssb.c

    diff -ur ../openwrt-25/build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ohci-ssb.c build_dir/linux-brcm47xx/linux-2.6.25.4/drivers/usb/host/ohci-ssb.c
    old new  
    132132        usb_remove_hcd(hcd); 
    133133        iounmap(hcd->regs); 
    134134        usb_put_hcd(hcd); 
    135         ssb_device_disable(dev, 0); 
    136135} 
    137136 
    138 static int ssb_ohci_attach(struct ssb_device *dev) 
     137EXPORT_SYMBOL_GPL(ssb_ohci_detach); 
     138 
     139int ssb_ohci_attach(struct ssb_device *dev) 
    139140{ 
    140141        struct ssb_ohci_device *ohcidev; 
    141142        struct usb_hcd *hcd; 
    142143        int err = -ENOMEM; 
    143144        u32 tmp, flags = 0; 
    144145 
     146        if (!(ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET)) 
     147                goto core_already_enabled;  
    145148        /* 
    146149         * THE FOLLOWING COMMENTS PRESERVED FROM GPL SOURCE RELEASE 
    147150         * 
     
    170173         *    phy components out of reset.  
    171174         */ 
    172175 
    173         else if (dev->id.coreid == SSB_DEV_USB20_HOST) { 
    174 #warning FIX ME need test for core being up & exit 
     176        else if (dev->id.coreid == SSB_DEV_USB11_HOST) { 
     177                if (ssb_device_is_enabled(dev)) 
     178                        goto core_already_enabled;  
    175179                ssb_device_enable(dev, 0); 
    176180                ssb_write32(dev, 0x200, 0x7ff); 
    177181                udelay(1); 
     
    195199        else 
    196200                ssb_device_enable(dev, 0); 
    197201 
     202core_already_enabled: 
    198203 /* 
    199204  * Set dma mask - 32 bit mask is just an assumption 
    200205  */ 
     
    231236        return err; 
    232237} 
    233238 
     239EXPORT_SYMBOL_GPL(ssb_ohci_attach); 
     240 
    234241static int ssb_ohci_probe(struct ssb_device *dev, 
    235242                const struct ssb_device_id *id) 
    236243{ 
     
    290297static const struct ssb_device_id ssb_ohci_table[] = { 
    291298        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOSTDEV, SSB_ANY_REV), 
    292299        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB11_HOST, SSB_ANY_REV), 
     300#ifndef CONFIG_USB_EHCI_HCD_SSB 
    293301        SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_USB20_HOST, SSB_ANY_REV), 
     302#endif 
    294303        SSB_DEVTABLE_END 
    295304}; 
    296305MODULE_DEVICE_TABLE(ssb, ssb_ohci_table); 
  • build_dir/linux-brcm47xx/linux-2.6.25.4/include/linux/ssb/ssb.h

    diff -ur ../openwrt-25/build_dir/linux-brcm47xx/linux-2.6.25.4/include/linux/ssb/ssb.h build_dir/linux-brcm47xx/linux-2.6.25.4/include/linux/ssb/ssb.h
    old new  
    144144        /* Internal-only stuff follows. */ 
    145145        void *drvdata;          /* Per-device data */ 
    146146        void *devtypedata;      /* Per-devicetype (eg 802.11) data */ 
     147        struct ssb_device *companion; /* ohci companion device, used by ssb_ehci driver */ 
    147148}; 
    148149 
    149150/* Go from struct device to struct ssb_device. */