11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * OHCI HCD (Host Controller Driver) for USB. 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> 51da177e4SLinus Torvalds * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net> 61da177e4SLinus Torvalds * (C) Copyright 2002 Hewlett-Packard Company 71da177e4SLinus Torvalds * 81da177e4SLinus Torvalds * SA1111 Bus Glue 91da177e4SLinus Torvalds * 101da177e4SLinus Torvalds * Written by Christopher Hoover <ch@hpl.hp.com> 11ac310bb5SUwe Kleine-König * Based on fragments of previous driver by Russell King et al. 121da177e4SLinus Torvalds * 131da177e4SLinus Torvalds * This file is licenced under the GPL. 141da177e4SLinus Torvalds */ 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds #include <asm/mach-types.h> 171da177e4SLinus Torvalds #include <asm/hardware/sa1111.h> 181da177e4SLinus Torvalds 191da177e4SLinus Torvalds #ifndef CONFIG_SA1111 201da177e4SLinus Torvalds #error "This file is SA-1111 bus glue. CONFIG_SA1111 must be defined." 211da177e4SLinus Torvalds #endif 221da177e4SLinus Torvalds 232213536dSRussell King #define USB_STATUS 0x0118 242213536dSRussell King #define USB_RESET 0x011c 252213536dSRussell King #define USB_IRQTEST 0x0120 262213536dSRussell King 272213536dSRussell King #define USB_RESET_FORCEIFRESET (1 << 0) 282213536dSRussell King #define USB_RESET_FORCEHCRESET (1 << 1) 292213536dSRussell King #define USB_RESET_CLKGENRESET (1 << 2) 302213536dSRussell King #define USB_RESET_SIMSCALEDOWN (1 << 3) 312213536dSRussell King #define USB_RESET_USBINTTEST (1 << 4) 322213536dSRussell King #define USB_RESET_SLEEPSTBYEN (1 << 5) 332213536dSRussell King #define USB_RESET_PWRSENSELOW (1 << 6) 342213536dSRussell King #define USB_RESET_PWRCTRLLOW (1 << 7) 352213536dSRussell King 362213536dSRussell King #define USB_STATUS_IRQHCIRMTWKUP (1 << 7) 372213536dSRussell King #define USB_STATUS_IRQHCIBUFFACC (1 << 8) 382213536dSRussell King #define USB_STATUS_NIRQHCIM (1 << 9) 392213536dSRussell King #define USB_STATUS_NHCIMFCLR (1 << 10) 402213536dSRussell King #define USB_STATUS_USBPWRSENSE (1 << 11) 412213536dSRussell King 42132db99aSRussell King #if 0 43132db99aSRussell King static void dump_hci_status(struct usb_hcd *hcd, const char *label) 44132db99aSRussell King { 45132db99aSRussell King unsigned long status = sa1111_readl(hcd->regs + USB_STATUS); 46132db99aSRussell King 473879e304SGreg Kroah-Hartman printk(KERN_DEBUG "%s USB_STATUS = { %s%s%s%s%s}\n", label, 48132db99aSRussell King ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""), 49132db99aSRussell King ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""), 50132db99aSRussell King ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "), 51132db99aSRussell King ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "), 52132db99aSRussell King ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : "")); 53132db99aSRussell King } 54132db99aSRussell King #endif 55132db99aSRussell King 5681e6ca3eSRussell King static int ohci_sa1111_reset(struct usb_hcd *hcd) 5781e6ca3eSRussell King { 5881e6ca3eSRussell King struct ohci_hcd *ohci = hcd_to_ohci(hcd); 5981e6ca3eSRussell King 6081e6ca3eSRussell King ohci_hcd_init(ohci); 6181e6ca3eSRussell King return ohci_init(ohci); 6281e6ca3eSRussell King } 6381e6ca3eSRussell King 6441ac7b3aSBill Pemberton static int ohci_sa1111_start(struct usb_hcd *hcd) 65132db99aSRussell King { 66132db99aSRussell King struct ohci_hcd *ohci = hcd_to_ohci(hcd); 67132db99aSRussell King int ret; 68132db99aSRussell King 69132db99aSRussell King ret = ohci_run(ohci); 70132db99aSRussell King if (ret < 0) { 7181e6ca3eSRussell King ohci_err(ohci, "can't start\n"); 72132db99aSRussell King ohci_stop(hcd); 73132db99aSRussell King } 7481e6ca3eSRussell King return ret; 75132db99aSRussell King } 76132db99aSRussell King 77132db99aSRussell King static const struct hc_driver ohci_sa1111_hc_driver = { 78132db99aSRussell King .description = hcd_name, 79132db99aSRussell King .product_desc = "SA-1111 OHCI", 80132db99aSRussell King .hcd_priv_size = sizeof(struct ohci_hcd), 81132db99aSRussell King 82132db99aSRussell King /* 83132db99aSRussell King * generic hardware linkage 84132db99aSRussell King */ 85132db99aSRussell King .irq = ohci_irq, 86132db99aSRussell King .flags = HCD_USB11 | HCD_MEMORY, 87132db99aSRussell King 88132db99aSRussell King /* 89132db99aSRussell King * basic lifecycle operations 90132db99aSRussell King */ 9181e6ca3eSRussell King .reset = ohci_sa1111_reset, 92132db99aSRussell King .start = ohci_sa1111_start, 93132db99aSRussell King .stop = ohci_stop, 94846a7048SRussell King .shutdown = ohci_shutdown, 95132db99aSRussell King 96132db99aSRussell King /* 97132db99aSRussell King * managing i/o requests and associated device resources 98132db99aSRussell King */ 99132db99aSRussell King .urb_enqueue = ohci_urb_enqueue, 100132db99aSRussell King .urb_dequeue = ohci_urb_dequeue, 101132db99aSRussell King .endpoint_disable = ohci_endpoint_disable, 102132db99aSRussell King 103132db99aSRussell King /* 104132db99aSRussell King * scheduling support 105132db99aSRussell King */ 106132db99aSRussell King .get_frame_number = ohci_get_frame, 107132db99aSRussell King 108132db99aSRussell King /* 109132db99aSRussell King * root hub support 110132db99aSRussell King */ 111132db99aSRussell King .hub_status_data = ohci_hub_status_data, 112132db99aSRussell King .hub_control = ohci_hub_control, 113132db99aSRussell King #ifdef CONFIG_PM 114132db99aSRussell King .bus_suspend = ohci_bus_suspend, 115132db99aSRussell King .bus_resume = ohci_bus_resume, 116132db99aSRussell King #endif 117132db99aSRussell King .start_port_reset = ohci_start_port_reset, 118132db99aSRussell King }; 1191da177e4SLinus Torvalds 120ae99ddbcSRussell King static int sa1111_start_hc(struct sa1111_dev *dev) 1211da177e4SLinus Torvalds { 1221da177e4SLinus Torvalds unsigned int usb_rst = 0; 123ae99ddbcSRussell King int ret; 1241da177e4SLinus Torvalds 1253f878dbcSRussell King dev_dbg(&dev->dev, "starting SA-1111 OHCI USB Controller\n"); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds if (machine_is_xp860() || 1286ebb8f0fSRussell King machine_is_assabet() || 1291da177e4SLinus Torvalds machine_is_pfs168() || 1301da177e4SLinus Torvalds machine_is_badge4()) 1311da177e4SLinus Torvalds usb_rst = USB_RESET_PWRSENSELOW | USB_RESET_PWRCTRLLOW; 1321da177e4SLinus Torvalds 1331da177e4SLinus Torvalds /* 1341da177e4SLinus Torvalds * Configure the power sense and control lines. Place the USB 1351da177e4SLinus Torvalds * host controller in reset. 1361da177e4SLinus Torvalds */ 1371da177e4SLinus Torvalds sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET, 1382213536dSRussell King dev->mapbase + USB_RESET); 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds /* 1411da177e4SLinus Torvalds * Now, carefully enable the USB clock, and take 1421da177e4SLinus Torvalds * the USB host controller out of reset. 1431da177e4SLinus Torvalds */ 144ae99ddbcSRussell King ret = sa1111_enable_device(dev); 145ae99ddbcSRussell King if (ret == 0) { 1461da177e4SLinus Torvalds udelay(11); 1472213536dSRussell King sa1111_writel(usb_rst, dev->mapbase + USB_RESET); 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 150ae99ddbcSRussell King return ret; 151ae99ddbcSRussell King } 152ae99ddbcSRussell King 1531da177e4SLinus Torvalds static void sa1111_stop_hc(struct sa1111_dev *dev) 1541da177e4SLinus Torvalds { 1551da177e4SLinus Torvalds unsigned int usb_rst; 1569cb0f819SRussell King 1573f878dbcSRussell King dev_dbg(&dev->dev, "stopping SA-1111 OHCI USB Controller\n"); 1581da177e4SLinus Torvalds 1591da177e4SLinus Torvalds /* 1601da177e4SLinus Torvalds * Put the USB host controller into reset. 1611da177e4SLinus Torvalds */ 1622213536dSRussell King usb_rst = sa1111_readl(dev->mapbase + USB_RESET); 1631da177e4SLinus Torvalds sa1111_writel(usb_rst | USB_RESET_FORCEIFRESET | USB_RESET_FORCEHCRESET, 1642213536dSRussell King dev->mapbase + USB_RESET); 1651da177e4SLinus Torvalds 1661da177e4SLinus Torvalds /* 1671da177e4SLinus Torvalds * Stop the USB clock. 1681da177e4SLinus Torvalds */ 1691da177e4SLinus Torvalds sa1111_disable_device(dev); 1701da177e4SLinus Torvalds } 1711da177e4SLinus Torvalds 1721da177e4SLinus Torvalds /** 173132db99aSRussell King * ohci_hcd_sa1111_probe - initialize SA-1111-based HCDs 1741da177e4SLinus Torvalds * 1751da177e4SLinus Torvalds * Allocates basic resources for this USB host controller, and 176132db99aSRussell King * then invokes the start() method for the HCD associated with it. 1771da177e4SLinus Torvalds */ 178132db99aSRussell King static int ohci_hcd_sa1111_probe(struct sa1111_dev *dev) 1791da177e4SLinus Torvalds { 1801da177e4SLinus Torvalds struct usb_hcd *hcd; 18178655197SRussell King int ret, irq; 1821da177e4SLinus Torvalds 183132db99aSRussell King if (usb_disabled()) 184132db99aSRussell King return -ENODEV; 185132db99aSRussell King 1864ffb4318SRussell King /* 1874ffb4318SRussell King * We don't call dma_set_mask_and_coherent() here because the 1884ffb4318SRussell King * DMA mask has already been appropraitely setup by the core 1894ffb4318SRussell King * SA-1111 bus code (which includes bug workarounds.) 1904ffb4318SRussell King */ 1914ffb4318SRussell King 192132db99aSRussell King hcd = usb_create_hcd(&ohci_sa1111_hc_driver, &dev->dev, "sa1111"); 1931da177e4SLinus Torvalds if (!hcd) 1941da177e4SLinus Torvalds return -ENOMEM; 1959cb0f819SRussell King 1961da177e4SLinus Torvalds hcd->rsrc_start = dev->res.start; 19728f65c11SJoe Perches hcd->rsrc_len = resource_size(&dev->res); 1981da177e4SLinus Torvalds 19978655197SRussell King irq = sa1111_get_irq(dev, 1); 20078655197SRussell King if (irq <= 0) { 20178655197SRussell King ret = irq ? : -ENXIO; 20278655197SRussell King goto err1; 20378655197SRussell King } 20478655197SRussell King 2051da177e4SLinus Torvalds if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { 2063879e304SGreg Kroah-Hartman dev_dbg(&dev->dev, "request_mem_region failed\n"); 207132db99aSRussell King ret = -EBUSY; 2081da177e4SLinus Torvalds goto err1; 2091da177e4SLinus Torvalds } 2109cb0f819SRussell King 2111da177e4SLinus Torvalds hcd->regs = dev->mapbase; 2121da177e4SLinus Torvalds 213ae99ddbcSRussell King ret = sa1111_start_hc(dev); 214ae99ddbcSRussell King if (ret) 215ae99ddbcSRussell King goto err2; 216ae99ddbcSRussell King 21778655197SRussell King ret = usb_add_hcd(hcd, irq, 0); 2183c9740a1SPeter Chen if (ret == 0) { 2193c9740a1SPeter Chen device_wakeup_enable(hcd->self.controller); 220132db99aSRussell King return ret; 2213c9740a1SPeter Chen } 2221da177e4SLinus Torvalds 2231da177e4SLinus Torvalds sa1111_stop_hc(dev); 224ae99ddbcSRussell King err2: 2251da177e4SLinus Torvalds release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 2261da177e4SLinus Torvalds err1: 2271da177e4SLinus Torvalds usb_put_hcd(hcd); 228132db99aSRussell King return ret; 2291da177e4SLinus Torvalds } 2301da177e4SLinus Torvalds 2311da177e4SLinus Torvalds /** 232132db99aSRussell King * ohci_hcd_sa1111_remove - shutdown processing for SA-1111-based HCDs 2331da177e4SLinus Torvalds * @dev: USB Host Controller being removed 2341da177e4SLinus Torvalds * 235132db99aSRussell King * Reverses the effect of ohci_hcd_sa1111_probe(), first invoking 236132db99aSRussell King * the HCD's stop() method. 2371da177e4SLinus Torvalds */ 238132db99aSRussell King static int ohci_hcd_sa1111_remove(struct sa1111_dev *dev) 2391da177e4SLinus Torvalds { 240132db99aSRussell King struct usb_hcd *hcd = sa1111_get_drvdata(dev); 241132db99aSRussell King 2421da177e4SLinus Torvalds usb_remove_hcd(hcd); 2431da177e4SLinus Torvalds sa1111_stop_hc(dev); 2441da177e4SLinus Torvalds release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 2451da177e4SLinus Torvalds usb_put_hcd(hcd); 2461da177e4SLinus Torvalds 2471da177e4SLinus Torvalds return 0; 2481da177e4SLinus Torvalds } 2491da177e4SLinus Torvalds 2506c771d30SRussell King static void ohci_hcd_sa1111_shutdown(struct device *_dev) 251846a7048SRussell King { 2526c771d30SRussell King struct sa1111_dev *dev = to_sa1111_device(_dev); 253846a7048SRussell King struct usb_hcd *hcd = sa1111_get_drvdata(dev); 254846a7048SRussell King 255846a7048SRussell King if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { 256846a7048SRussell King hcd->driver->shutdown(hcd); 257846a7048SRussell King sa1111_stop_hc(dev); 258846a7048SRussell King } 259846a7048SRussell King } 260846a7048SRussell King 2611da177e4SLinus Torvalds static struct sa1111_driver ohci_hcd_sa1111_driver = { 2621da177e4SLinus Torvalds .drv = { 2631da177e4SLinus Torvalds .name = "sa1111-ohci", 2641ebcd765SRussell King .owner = THIS_MODULE, 2656c771d30SRussell King .shutdown = ohci_hcd_sa1111_shutdown, 2661da177e4SLinus Torvalds }, 2671da177e4SLinus Torvalds .devid = SA1111_DEVID_USB, 268132db99aSRussell King .probe = ohci_hcd_sa1111_probe, 269132db99aSRussell King .remove = ohci_hcd_sa1111_remove, 2701da177e4SLinus Torvalds }; 271