Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * UHCI HCD (Host Controller Driver) for GRLIB GRUSBHC
0004  *
0005  * Copyright (c) 2011 Jan Andersson <jan@gaisler.com>
0006  *
0007  * This file is based on UHCI PCI HCD:
0008  * (C) Copyright 1999 Linus Torvalds
0009  * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
0010  * (C) Copyright 1999 Randy Dunlap
0011  * (C) Copyright 1999 Georg Acher, acher@in.tum.de
0012  * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
0013  * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
0014  * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
0015  * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
0016  *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
0017  * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
0018  * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu
0019  */
0020 
0021 #include <linux/device.h>
0022 #include <linux/of_irq.h>
0023 #include <linux/of_address.h>
0024 #include <linux/of_platform.h>
0025 
0026 static int uhci_grlib_init(struct usb_hcd *hcd)
0027 {
0028     struct uhci_hcd *uhci = hcd_to_uhci(hcd);
0029 
0030     /*
0031      * Probe to determine the endianness of the controller.
0032      * We know that bit 7 of the PORTSC1 register is always set
0033      * and bit 15 is always clear.  If uhci_readw() yields a value
0034      * with bit 7 (0x80) turned on then the current little-endian
0035      * setting is correct.  Otherwise we assume the value was
0036      * byte-swapped; hence the register interface and presumably
0037      * also the descriptors are big-endian.
0038      */
0039     if (!(uhci_readw(uhci, USBPORTSC1) & 0x80)) {
0040         uhci->big_endian_mmio = 1;
0041         uhci->big_endian_desc = 1;
0042     }
0043 
0044     uhci->rh_numports = uhci_count_ports(hcd);
0045 
0046     /* Set up pointers to generic functions */
0047     uhci->reset_hc = uhci_generic_reset_hc;
0048     uhci->check_and_reset_hc = uhci_generic_check_and_reset_hc;
0049     /* No special actions need to be taken for the functions below */
0050     uhci->configure_hc = NULL;
0051     uhci->resume_detect_interrupts_are_broken = NULL;
0052     uhci->global_suspend_mode_is_broken = NULL;
0053 
0054     /* Reset if the controller isn't already safely quiescent. */
0055     check_and_reset_hc(uhci);
0056     return 0;
0057 }
0058 
0059 static const struct hc_driver uhci_grlib_hc_driver = {
0060     .description =      hcd_name,
0061     .product_desc =     "GRLIB GRUSBHC UHCI Host Controller",
0062     .hcd_priv_size =    sizeof(struct uhci_hcd),
0063 
0064     /* Generic hardware linkage */
0065     .irq =          uhci_irq,
0066     .flags =        HCD_MEMORY | HCD_DMA | HCD_USB11,
0067 
0068     /* Basic lifecycle operations */
0069     .reset =        uhci_grlib_init,
0070     .start =        uhci_start,
0071 #ifdef CONFIG_PM
0072     .pci_suspend =      NULL,
0073     .pci_resume =       NULL,
0074     .bus_suspend =      uhci_rh_suspend,
0075     .bus_resume =       uhci_rh_resume,
0076 #endif
0077     .stop =         uhci_stop,
0078 
0079     .urb_enqueue =      uhci_urb_enqueue,
0080     .urb_dequeue =      uhci_urb_dequeue,
0081 
0082     .endpoint_disable = uhci_hcd_endpoint_disable,
0083     .get_frame_number = uhci_hcd_get_frame_number,
0084 
0085     .hub_status_data =  uhci_hub_status_data,
0086     .hub_control =      uhci_hub_control,
0087 };
0088 
0089 
0090 static int uhci_hcd_grlib_probe(struct platform_device *op)
0091 {
0092     struct device_node *dn = op->dev.of_node;
0093     struct usb_hcd *hcd;
0094     struct uhci_hcd *uhci = NULL;
0095     struct resource res;
0096     int irq;
0097     int rv;
0098 
0099     if (usb_disabled())
0100         return -ENODEV;
0101 
0102     dev_dbg(&op->dev, "initializing GRUSBHC UHCI USB Controller\n");
0103 
0104     rv = of_address_to_resource(dn, 0, &res);
0105     if (rv)
0106         return rv;
0107 
0108     /* usb_create_hcd requires dma_mask != NULL */
0109     op->dev.dma_mask = &op->dev.coherent_dma_mask;
0110     hcd = usb_create_hcd(&uhci_grlib_hc_driver, &op->dev,
0111             "GRUSBHC UHCI USB");
0112     if (!hcd)
0113         return -ENOMEM;
0114 
0115     hcd->rsrc_start = res.start;
0116     hcd->rsrc_len = resource_size(&res);
0117 
0118     irq = irq_of_parse_and_map(dn, 0);
0119     if (irq == NO_IRQ) {
0120         printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__);
0121         rv = -EBUSY;
0122         goto err_usb;
0123     }
0124 
0125     hcd->regs = devm_ioremap_resource(&op->dev, &res);
0126     if (IS_ERR(hcd->regs)) {
0127         rv = PTR_ERR(hcd->regs);
0128         goto err_irq;
0129     }
0130 
0131     uhci = hcd_to_uhci(hcd);
0132 
0133     uhci->regs = hcd->regs;
0134 
0135     rv = usb_add_hcd(hcd, irq, 0);
0136     if (rv)
0137         goto err_irq;
0138 
0139     device_wakeup_enable(hcd->self.controller);
0140     return 0;
0141 
0142 err_irq:
0143     irq_dispose_mapping(irq);
0144 err_usb:
0145     usb_put_hcd(hcd);
0146 
0147     return rv;
0148 }
0149 
0150 static int uhci_hcd_grlib_remove(struct platform_device *op)
0151 {
0152     struct usb_hcd *hcd = platform_get_drvdata(op);
0153 
0154     dev_dbg(&op->dev, "stopping GRLIB GRUSBHC UHCI USB Controller\n");
0155 
0156     usb_remove_hcd(hcd);
0157 
0158     irq_dispose_mapping(hcd->irq);
0159     usb_put_hcd(hcd);
0160 
0161     return 0;
0162 }
0163 
0164 /* Make sure the controller is quiescent and that we're not using it
0165  * any more.  This is mainly for the benefit of programs which, like kexec,
0166  * expect the hardware to be idle: not doing DMA or generating IRQs.
0167  *
0168  * This routine may be called in a damaged or failing kernel.  Hence we
0169  * do not acquire the spinlock before shutting down the controller.
0170  */
0171 static void uhci_hcd_grlib_shutdown(struct platform_device *op)
0172 {
0173     struct usb_hcd *hcd = platform_get_drvdata(op);
0174 
0175     uhci_hc_died(hcd_to_uhci(hcd));
0176 }
0177 
0178 static const struct of_device_id uhci_hcd_grlib_of_match[] = {
0179     { .name = "GAISLER_UHCI", },
0180     { .name = "01_027", },
0181     {},
0182 };
0183 MODULE_DEVICE_TABLE(of, uhci_hcd_grlib_of_match);
0184 
0185 
0186 static struct platform_driver uhci_grlib_driver = {
0187     .probe      = uhci_hcd_grlib_probe,
0188     .remove     = uhci_hcd_grlib_remove,
0189     .shutdown   = uhci_hcd_grlib_shutdown,
0190     .driver = {
0191         .name = "grlib-uhci",
0192         .of_match_table = uhci_hcd_grlib_of_match,
0193     },
0194 };