15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-1.0+ 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * OHCI HCD (Host Controller Driver) for USB. 41da177e4SLinus Torvalds * 51da177e4SLinus Torvalds * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> 61da177e4SLinus Torvalds * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> 71da177e4SLinus Torvalds * (C) Copyright 2002 Hewlett-Packard Company 81da177e4SLinus Torvalds * 91da177e4SLinus Torvalds * SA1111 Bus Glue 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * Written by Christopher Hoover <ch@hpl.hp.com> 12ac310bb5SUwe Kleine-König * Based on fragments of previous driver by Russell King et al. 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * This file is licenced under the GPL. 151da177e4SLinus Torvalds */ 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds #include <asm/mach-types.h> 181da177e4SLinus Torvalds #include <asm/hardware/sa1111.h> 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds #ifndef CONFIG_SA1111 211da177e4SLinus Torvalds #error "This file is SA-1111 bus glue. CONFIG_SA1111 must be defined." 221da177e4SLinus Torvalds #endif 231da177e4SLinus Torvalds 242213536dSRussell King #define USB_STATUS 0x0118 252213536dSRussell King #define USB_RESET 0x011c 262213536dSRussell King #define USB_IRQTEST 0x0120 272213536dSRussell King 282213536dSRussell King #define USB_RESET_FORCEIFRESET (1 << 0) 292213536dSRussell King #define USB_RESET_FORCEHCRESET (1 << 1) 302213536dSRussell King #define USB_RESET_CLKGENRESET (1 << 2) 312213536dSRussell King #define USB_RESET_SIMSCALEDOWN (1 << 3) 322213536dSRussell King #define USB_RESET_USBINTTEST (1 << 4) 332213536dSRussell King #define USB_RESET_SLEEPSTBYEN (1 << 5) 342213536dSRussell King #define USB_RESET_PWRSENSELOW (1 << 6) 352213536dSRussell King #define USB_RESET_PWRCTRLLOW (1 << 7) 362213536dSRussell King 372213536dSRussell King #define USB_STATUS_IRQHCIRMTWKUP (1 << 7) 382213536dSRussell King #define USB_STATUS_IRQHCIBUFFACC (1 << 8) 392213536dSRussell King #define USB_STATUS_NIRQHCIM (1 << 9) 402213536dSRussell King #define USB_STATUS_NHCIMFCLR (1 << 10) 412213536dSRussell King #define USB_STATUS_USBPWRSENSE (1 << 11) 422213536dSRussell King 43132db99aSRussell King #if 0 44132db99aSRussell King static void dump_hci_status(struct usb_hcd *hcd, const char *label) 45132db99aSRussell King { 46263bf612SRussell King unsigned long status = readl_relaxed(hcd->regs + USB_STATUS); 47132db99aSRussell King 483879e304SGreg Kroah-Hartman printk(KERN_DEBUG "%s USB_STATUS = { %s%s%s%s%s}\n", label, 49132db99aSRussell King ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""), 50132db99aSRussell King ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""), 51132db99aSRussell King ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "), 52132db99aSRussell King ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "), 53132db99aSRussell King ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : "")); 54132db99aSRussell King } 55132db99aSRussell King #endif 56132db99aSRussell King 5781e6ca3eSRussell King static int ohci_sa1111_reset(struct usb_hcd *hcd) 5881e6ca3eSRussell King { 5981e6ca3eSRussell King struct ohci_hcd *ohci = hcd_to_ohci(hcd); 6081e6ca3eSRussell King 6181e6ca3eSRussell King ohci_hcd_init(ohci); 6281e6ca3eSRussell King return ohci_init(ohci); 6381e6ca3eSRussell King } 6481e6ca3eSRussell King 6541ac7b3aSBill Pemberton static int ohci_sa1111_start(struct usb_hcd *hcd) 66132db99aSRussell King { 67132db99aSRussell King struct ohci_hcd *ohci = hcd_to_ohci(hcd); 68132db99aSRussell King int ret; 69132db99aSRussell King 70132db99aSRussell King ret = ohci_run(ohci); 71132db99aSRussell King if (ret < 0) { 7281e6ca3eSRussell King ohci_err(ohci, "can't start\n"); 73132db99aSRussell King ohci_stop(hcd); 74132db99aSRussell King } 7581e6ca3eSRussell King return ret; 76132db99aSRussell King } 77132db99aSRussell King 78132db99aSRussell King static const struct hc_driver ohci_sa1111_hc_driver = { 79132db99aSRussell King .description = hcd_name, 80132db99aSRussell King .product_desc = "SA-1111 OHCI", 81132db99aSRussell King .hcd_priv_size = sizeof(struct ohci_hcd), 82132db99aSRussell King 83132db99aSRussell King /* 84132db99aSRussell King * generic hardware linkage 85132db99aSRussell King */ 86132db99aSRussell King .irq = ohci_irq, 877b81cb6bSChristoph Hellwig .flags = HCD_USB11 | HCD_DMA | HCD_MEMORY, 88132db99aSRussell King 89132db99aSRussell King /* 90132db99aSRussell King * basic lifecycle operations 91132db99aSRussell King */ 9281e6ca3eSRussell King .reset = ohci_sa1111_reset, 93132db99aSRussell King .start = ohci_sa1111_start, 94132db99aSRussell King .stop = ohci_stop, 95846a7048SRussell King .shutdown = ohci_shutdown, 96132db99aSRussell King 97132db99aSRussell King /* 98132db99aSRussell King * managing i/o requests and associated device resources 99132db99aSRussell King */ 100132db99aSRussell King .urb_enqueue = ohci_urb_enqueue, 101132db99aSRussell King .urb_dequeue = ohci_urb_dequeue, 102132db99aSRussell King .endpoint_disable = ohci_endpoint_disable, 103132db99aSRussell King 104132db99aSRussell King /* 105132db99aSRussell King * scheduling support 106132db99aSRussell King */ 107132db99aSRussell King .get_frame_number = ohci_get_frame, 108132db99aSRussell King 109132db99aSRussell King /* 110132db99aSRussell King * root hub support 111132db99aSRussell King */ 112132db99aSRussell King .hub_status_data = ohci_hub_status_data, 113132db99aSRussell King .hub_control = ohci_hub_control, 114132db99aSRussell King #ifdef CONFIG_PM 115132db99aSRussell King .bus_suspend = ohci_bus_suspend, 116132db99aSRussell King .bus_resume = ohci_bus_resume, 117132db99aSRussell King #endif 118132db99aSRussell King .start_port_reset = ohci_start_port_reset, 119132db99aSRussell King }; 1201da177e4SLinus Torvalds 121ae99ddbcSRussell King static int sa1111_start_hc(struct sa1111_dev *dev) 1221da177e4SLinus Torvalds { 1231da177e4SLinus Torvalds unsigned int usb_rst = 0; 124ae99ddbcSRussell King int ret; 1251da177e4SLinus Torvalds 1263f878dbcSRussell King dev_dbg(&dev->dev, "starting SA-1111 OHCI USB Controller\n"); 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds if (machine_is_xp860() || 1296ebb8f0fSRussell King machine_is_assabet() || 1301da177e4SLinus Torvalds machine_is_pfs168() || 1311da177e4SLinus Torvalds machine_is_badge4()) 1321da177e4SLinus Torvalds usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW; 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds /* 1351da177e4SLinus Torvalds * Configure the power sense and control lines. Place the USB 1361da177e4SLinus Torvalds * host controller in reset. 1371da177e4SLinus Torvalds */ 138263bf612SRussell King writel_relaxed(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET, 1392213536dSRussell King dev->mapbase + USB_RESET); 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds /* 1421da177e4SLinus Torvalds * Now, carefully enable the USB clock, and take 1431da177e4SLinus Torvalds * the USB host controller out of reset. 1441da177e4SLinus Torvalds */ 145ae99ddbcSRussell King ret = sa1111_enable_device(dev); 146ae99ddbcSRussell King if (ret == 0) { 1471da177e4SLinus Torvalds udelay(11); 148263bf612SRussell King writel_relaxed(usb_rst, dev->mapbase + USB_RESET); 1491da177e4SLinus Torvalds } 1501da177e4SLinus Torvalds 151ae99ddbcSRussell King return ret; 152ae99ddbcSRussell King } 153ae99ddbcSRussell King 1541da177e4SLinus Torvalds static void sa1111_stop_hc(struct sa1111_dev *dev) 1551da177e4SLinus Torvalds { 1561da177e4SLinus Torvalds unsigned int usb_rst; 1579cb0f819SRussell King 1583f878dbcSRussell King dev_dbg(&dev->dev, "stopping SA-1111 OHCI USB Controller\n"); 1591da177e4SLinus Torvalds 1601da177e4SLinus Torvalds /* 1611da177e4SLinus Torvalds * Put the USB host controller into reset. 1621da177e4SLinus Torvalds */ 163263bf612SRussell King usb_rst = readl_relaxed(dev->mapbase + USB_RESET); 164263bf612SRussell King writel_relaxed(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET, 1652213536dSRussell King dev->mapbase + USB_RESET); 1661da177e4SLinus Torvalds 1671da177e4SLinus Torvalds /* 1681da177e4SLinus Torvalds * Stop the USB clock. 1691da177e4SLinus Torvalds */ 1701da177e4SLinus Torvalds sa1111_disable_device(dev); 1711da177e4SLinus Torvalds } 1721da177e4SLinus Torvalds 1731da177e4SLinus Torvalds /** 174132db99aSRussell King * ohci_hcd_sa1111_probe - initialize SA-1111-based HCDs 1751da177e4SLinus Torvalds * 1761da177e4SLinus Torvalds * Allocates basic resources for this USB host controller, and 177132db99aSRussell King * then invokes the start() method for the HCD associated with it. 1781da177e4SLinus Torvalds */ 179132db99aSRussell King static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev) 1801da177e4SLinus Torvalds { 1811da177e4SLinus Torvalds struct usb_hcd *hcd; 18278655197SRussell King int ret, irq; 1831da177e4SLinus Torvalds 184132db99aSRussell King if (usb_disabled()) 185132db99aSRussell King return -ENODEV; 186132db99aSRussell King 1874ffb4318SRussell King /* 1884ffb4318SRussell King * We don't call dma_set_mask_and_coherent() here because the 1894ffb4318SRussell King * DMA mask has already been appropraitely setup by the core 1904ffb4318SRussell King * SA-1111 bus code (which includes bug workarounds.) 1914ffb4318SRussell King */ 1924ffb4318SRussell King 193132db99aSRussell King hcd = usb_create_hcd(&ohci_sa1111_hc_driver, &dev->dev, "sa1111"); 1941da177e4SLinus Torvalds if (!hcd) 1951da177e4SLinus Torvalds return -ENOMEM; 1969cb0f819SRussell King 1971da177e4SLinus Torvalds hcd->rsrc_start = dev->res.start; 19828f65c11SJoe Perches hcd->rsrc_len = resource_size(&dev->res); 1991da177e4SLinus Torvalds 20078655197SRussell King irq = sa1111_get_irq(dev, 1); 20178655197SRussell King if (irq <= 0) { 20278655197SRussell King ret = irq ? : -ENXIO; 20378655197SRussell King goto err1; 20478655197SRussell King } 20578655197SRussell King 206*9ba26f5cSArnd Bergmann /* 207*9ba26f5cSArnd Bergmann * According to the "Intel StrongARM SA-1111 Microprocessor Companion 208*9ba26f5cSArnd Bergmann * Chip Specification Update" (June 2000), erratum #7, there is a 209*9ba26f5cSArnd Bergmann * significant bug in the SA1111 SDRAM shared memory controller. If 210*9ba26f5cSArnd Bergmann * an access to a region of memory above 1MB relative to the bank base, 211*9ba26f5cSArnd Bergmann * it is important that address bit 10 _NOT_ be asserted. Depending 212*9ba26f5cSArnd Bergmann * on the configuration of the RAM, bit 10 may correspond to one 213*9ba26f5cSArnd Bergmann * of several different (processor-relative) address bits. 214*9ba26f5cSArnd Bergmann * 215*9ba26f5cSArnd Bergmann * Section 4.6 of the "Intel StrongARM SA-1111 Development Module 216*9ba26f5cSArnd Bergmann * User's Guide" mentions that jumpers R51 and R52 control the 217*9ba26f5cSArnd Bergmann * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or 218*9ba26f5cSArnd Bergmann * SDRAM bank 1 on Neponset). The default configuration selects 219*9ba26f5cSArnd Bergmann * Assabet, so any address in bank 1 is necessarily invalid. 220*9ba26f5cSArnd Bergmann * 221*9ba26f5cSArnd Bergmann * As a workaround, use a bounce buffer in addressable memory 222*9ba26f5cSArnd Bergmann * as local_mem, relying on ZONE_DMA to provide an area that 223*9ba26f5cSArnd Bergmann * fits within the above constraints. 224*9ba26f5cSArnd Bergmann * 225*9ba26f5cSArnd Bergmann * SZ_64K is an estimate for what size this might need. 226*9ba26f5cSArnd Bergmann */ 227*9ba26f5cSArnd Bergmann ret = usb_hcd_setup_local_mem(hcd, 0, 0, SZ_64K); 228*9ba26f5cSArnd Bergmann if (ret) 229*9ba26f5cSArnd Bergmann goto err1; 230*9ba26f5cSArnd Bergmann 2311da177e4SLinus Torvalds if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 2323879e304SGreg Kroah-Hartman dev_dbg(&dev->dev, "request_mem_region failed\n"); 233132db99aSRussell King ret = -EBUSY; 2341da177e4SLinus Torvalds goto err1; 2351da177e4SLinus Torvalds } 2369cb0f819SRussell King 2371da177e4SLinus Torvalds hcd->regs = dev->mapbase; 2381da177e4SLinus Torvalds 239ae99ddbcSRussell King ret = sa1111_start_hc(dev); 240ae99ddbcSRussell King if (ret) 241ae99ddbcSRussell King goto err2; 242ae99ddbcSRussell King 24378655197SRussell King ret = usb_add_hcd(hcd, irq, 0); 2443c9740a1SPeter Chen if (ret == 0) { 2453c9740a1SPeter Chen device_wakeup_enable(hcd->self.controller); 246132db99aSRussell King return ret; 2473c9740a1SPeter Chen } 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds sa1111_stop_hc(dev); 250ae99ddbcSRussell King err2: 2511da177e4SLinus Torvalds release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 2521da177e4SLinus Torvalds err1: 2531da177e4SLinus Torvalds usb_put_hcd(hcd); 254132db99aSRussell King return ret; 2551da177e4SLinus Torvalds } 2561da177e4SLinus Torvalds 2571da177e4SLinus Torvalds /** 258132db99aSRussell King * ohci_hcd_sa1111_remove - shutdown processing for SA-1111-based HCDs 2591da177e4SLinus Torvalds * @dev: USB Host Controller being removed 2601da177e4SLinus Torvalds * 261132db99aSRussell King * Reverses the effect of ohci_hcd_sa1111_probe(), first invoking 262132db99aSRussell King * the HCD's stop() method. 2631da177e4SLinus Torvalds */ 264074a6bdaSUwe Kleine-König static void ohci_hcd_sa1111_remove(struct sa1111_dev *dev) 2651da177e4SLinus Torvalds { 266132db99aSRussell King struct usb_hcd *hcd = sa1111_get_drvdata(dev); 267132db99aSRussell King 2681da177e4SLinus Torvalds usb_remove_hcd(hcd); 2691da177e4SLinus Torvalds sa1111_stop_hc(dev); 2701da177e4SLinus Torvalds release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 2711da177e4SLinus Torvalds usb_put_hcd(hcd); 2721da177e4SLinus Torvalds } 2731da177e4SLinus Torvalds 2746c771d30SRussell King static void ohci_hcd_sa1111_shutdown(struct device *_dev) 275846a7048SRussell King { 2766c771d30SRussell King struct sa1111_dev *dev = to_sa1111_device(_dev); 277846a7048SRussell King struct usb_hcd *hcd = sa1111_get_drvdata(dev); 278846a7048SRussell King 279846a7048SRussell King if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { 280846a7048SRussell King hcd->driver->shutdown(hcd); 281846a7048SRussell King sa1111_stop_hc(dev); 282846a7048SRussell King } 283846a7048SRussell King } 284846a7048SRussell King 2851da177e4SLinus Torvalds static struct sa1111_driver ohci_hcd_sa1111_driver = { 2861da177e4SLinus Torvalds .drv = { 2871da177e4SLinus Torvalds .name = "sa1111-ohci", 2881ebcd765SRussell King .owner = THIS_MODULE, 2896c771d30SRussell King .shutdown = ohci_hcd_sa1111_shutdown, 2901da177e4SLinus Torvalds }, 2911da177e4SLinus Torvalds .devid = SA1111_DEVID_USB, 292132db99aSRussell King .probe = ohci_hcd_sa1111_probe, 293132db99aSRussell King .remove = ohci_hcd_sa1111_remove, 2941da177e4SLinus Torvalds }; 295