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 2061da177e4SLinus Torvalds if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 2073879e304SGreg Kroah-Hartman dev_dbg(&dev->dev, "request_mem_region failed\n"); 208132db99aSRussell King ret = -EBUSY; 2091da177e4SLinus Torvalds goto err1; 2101da177e4SLinus Torvalds } 2119cb0f819SRussell King 2121da177e4SLinus Torvalds hcd->regs = dev->mapbase; 2131da177e4SLinus Torvalds 214ae99ddbcSRussell King ret = sa1111_start_hc(dev); 215ae99ddbcSRussell King if (ret) 216ae99ddbcSRussell King goto err2; 217ae99ddbcSRussell King 21878655197SRussell King ret = usb_add_hcd(hcd, irq, 0); 2193c9740a1SPeter Chen if (ret == 0) { 2203c9740a1SPeter Chen device_wakeup_enable(hcd->self.controller); 221132db99aSRussell King return ret; 2223c9740a1SPeter Chen } 2231da177e4SLinus Torvalds 2241da177e4SLinus Torvalds sa1111_stop_hc(dev); 225ae99ddbcSRussell King err2: 2261da177e4SLinus Torvalds release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 2271da177e4SLinus Torvalds err1: 2281da177e4SLinus Torvalds usb_put_hcd(hcd); 229132db99aSRussell King return ret; 2301da177e4SLinus Torvalds } 2311da177e4SLinus Torvalds 2321da177e4SLinus Torvalds /** 233132db99aSRussell King * ohci_hcd_sa1111_remove - shutdown processing for SA-1111-based HCDs 2341da177e4SLinus Torvalds * @dev: USB Host Controller being removed 2351da177e4SLinus Torvalds * 236132db99aSRussell King * Reverses the effect of ohci_hcd_sa1111_probe(), first invoking 237132db99aSRussell King * the HCD's stop() method. 2381da177e4SLinus Torvalds */ 239*074a6bdaSUwe Kleine-König static void ohci_hcd_sa1111_remove(struct sa1111_dev *dev) 2401da177e4SLinus Torvalds { 241132db99aSRussell King struct usb_hcd *hcd = sa1111_get_drvdata(dev); 242132db99aSRussell King 2431da177e4SLinus Torvalds usb_remove_hcd(hcd); 2441da177e4SLinus Torvalds sa1111_stop_hc(dev); 2451da177e4SLinus Torvalds release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 2461da177e4SLinus Torvalds usb_put_hcd(hcd); 2471da177e4SLinus Torvalds } 2481da177e4SLinus Torvalds 2496c771d30SRussell King static void ohci_hcd_sa1111_shutdown(struct device *_dev) 250846a7048SRussell King { 2516c771d30SRussell King struct sa1111_dev *dev = to_sa1111_device(_dev); 252846a7048SRussell King struct usb_hcd *hcd = sa1111_get_drvdata(dev); 253846a7048SRussell King 254846a7048SRussell King if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { 255846a7048SRussell King hcd->driver->shutdown(hcd); 256846a7048SRussell King sa1111_stop_hc(dev); 257846a7048SRussell King } 258846a7048SRussell King } 259846a7048SRussell King 2601da177e4SLinus Torvalds static struct sa1111_driver ohci_hcd_sa1111_driver = { 2611da177e4SLinus Torvalds .drv = { 2621da177e4SLinus Torvalds .name = "sa1111-ohci", 2631ebcd765SRussell King .owner = THIS_MODULE, 2646c771d30SRussell King .shutdown = ohci_hcd_sa1111_shutdown, 2651da177e4SLinus Torvalds }, 2661da177e4SLinus Torvalds .devid = SA1111_DEVID_USB, 267132db99aSRussell King .probe = ohci_hcd_sa1111_probe, 268132db99aSRussell King .remove = ohci_hcd_sa1111_remove, 2691da177e4SLinus Torvalds }; 270