Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-1.0+
0002 /*
0003  * OHCI HCD (Host Controller Driver) for USB.
0004  *
0005  * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
0006  * (C) Copyright 2000-2005 David Brownell
0007  * (C) Copyright 2002 Hewlett-Packard Company
0008  * (C) Copyright 2008 Magnus Damm
0009  *
0010  * SM501 Bus Glue - based on ohci-omap.c
0011  *
0012  * This file is licenced under the GPL.
0013  */
0014 
0015 #include <linux/interrupt.h>
0016 #include <linux/jiffies.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/dma-mapping.h>
0019 #include <linux/sm501.h>
0020 #include <linux/sm501-regs.h>
0021 
0022 static int ohci_sm501_init(struct usb_hcd *hcd)
0023 {
0024     return ohci_init(hcd_to_ohci(hcd));
0025 }
0026 
0027 static int ohci_sm501_start(struct usb_hcd *hcd)
0028 {
0029     struct device *dev = hcd->self.controller;
0030     int ret;
0031 
0032     ret = ohci_run(hcd_to_ohci(hcd));
0033     if (ret < 0) {
0034         dev_err(dev, "can't start %s", hcd->self.bus_name);
0035         ohci_stop(hcd);
0036     }
0037 
0038     return ret;
0039 }
0040 
0041 /*-------------------------------------------------------------------------*/
0042 
0043 static const struct hc_driver ohci_sm501_hc_driver = {
0044     .description =      hcd_name,
0045     .product_desc =     "SM501 OHCI",
0046     .hcd_priv_size =    sizeof(struct ohci_hcd),
0047 
0048     /*
0049      * generic hardware linkage
0050      */
0051     .irq =          ohci_irq,
0052     .flags =        HCD_USB11 | HCD_MEMORY,
0053 
0054     /*
0055      * basic lifecycle operations
0056      */
0057     .reset =        ohci_sm501_init,
0058     .start =        ohci_sm501_start,
0059     .stop =         ohci_stop,
0060     .shutdown =     ohci_shutdown,
0061 
0062     /*
0063      * managing i/o requests and associated device resources
0064      */
0065     .urb_enqueue =      ohci_urb_enqueue,
0066     .urb_dequeue =      ohci_urb_dequeue,
0067     .endpoint_disable = ohci_endpoint_disable,
0068 
0069     /*
0070      * scheduling support
0071      */
0072     .get_frame_number = ohci_get_frame,
0073 
0074     /*
0075      * root hub support
0076      */
0077     .hub_status_data =  ohci_hub_status_data,
0078     .hub_control =      ohci_hub_control,
0079 #ifdef  CONFIG_PM
0080     .bus_suspend =      ohci_bus_suspend,
0081     .bus_resume =       ohci_bus_resume,
0082 #endif
0083     .start_port_reset = ohci_start_port_reset,
0084 };
0085 
0086 /*-------------------------------------------------------------------------*/
0087 
0088 static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
0089 {
0090     const struct hc_driver *driver = &ohci_sm501_hc_driver;
0091     struct device *dev = &pdev->dev;
0092     struct resource *res, *mem;
0093     int retval, irq;
0094     struct usb_hcd *hcd = NULL;
0095 
0096     irq = retval = platform_get_irq(pdev, 0);
0097     if (retval < 0)
0098         goto err0;
0099 
0100     mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0101     if (mem == NULL) {
0102         dev_err(dev, "no resource definition for memory\n");
0103         retval = -ENOENT;
0104         goto err0;
0105     }
0106 
0107     if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
0108         dev_err(dev, "request_mem_region failed\n");
0109         retval = -EBUSY;
0110         goto err0;
0111     }
0112 
0113     /* allocate, reserve and remap resources for registers */
0114     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0115     if (res == NULL) {
0116         dev_err(dev, "no resource definition for registers\n");
0117         retval = -ENOENT;
0118         goto err1;
0119     }
0120 
0121     hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
0122     if (!hcd) {
0123         retval = -ENOMEM;
0124         goto err1;
0125     }
0126 
0127     hcd->rsrc_start = res->start;
0128     hcd->rsrc_len = resource_size(res);
0129 
0130     if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, pdev->name)) {
0131         dev_err(dev, "request_mem_region failed\n");
0132         retval = -EBUSY;
0133         goto err3;
0134     }
0135 
0136     hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
0137     if (hcd->regs == NULL) {
0138         dev_err(dev, "cannot remap registers\n");
0139         retval = -ENXIO;
0140         goto err4;
0141     }
0142 
0143     ohci_hcd_init(hcd_to_ohci(hcd));
0144 
0145     /* The sm501 chip is equipped with local memory that may be used
0146      * by on-chip devices such as the video controller and the usb host.
0147      * This driver uses genalloc so that usb allocations with
0148      * gen_pool_dma_alloc() allocate from this local memory. The dma_handle
0149      * returned by gen_pool_dma_alloc() will be an offset starting from 0
0150      * for the first local memory byte.
0151      *
0152      * So as long as data is allocated using gen_pool_dma_alloc() all is
0153      * fine. This is however not always the case - buffers may be allocated
0154      * using kmalloc() - so the usb core needs to be told that it must copy
0155      * data into our local memory if the buffers happen to be placed in
0156      * regular memory. A non-null hcd->localmem_pool initialized by
0157      * the call to usb_hcd_setup_local_mem() below does just that.
0158      */
0159 
0160     retval = usb_hcd_setup_local_mem(hcd, mem->start,
0161                      mem->start - mem->parent->start,
0162                      resource_size(mem));
0163     if (retval < 0)
0164         goto err5;
0165     retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
0166     if (retval)
0167         goto err5;
0168     device_wakeup_enable(hcd->self.controller);
0169 
0170     /* enable power and unmask interrupts */
0171 
0172     sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
0173     sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0);
0174 
0175     return 0;
0176 err5:
0177     iounmap(hcd->regs);
0178 err4:
0179     release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
0180 err3:
0181     usb_put_hcd(hcd);
0182 err1:
0183     release_mem_region(mem->start, resource_size(mem));
0184 err0:
0185     return retval;
0186 }
0187 
0188 static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
0189 {
0190     struct usb_hcd *hcd = platform_get_drvdata(pdev);
0191     struct resource *mem;
0192 
0193     usb_remove_hcd(hcd);
0194     iounmap(hcd->regs);
0195     release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
0196     usb_put_hcd(hcd);
0197     mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0198     if (mem)
0199         release_mem_region(mem->start, resource_size(mem));
0200 
0201     /* mask interrupts and disable power */
0202 
0203     sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6);
0204     sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0);
0205 
0206     return 0;
0207 }
0208 
0209 /*-------------------------------------------------------------------------*/
0210 
0211 #ifdef CONFIG_PM
0212 static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
0213 {
0214     struct device *dev = &pdev->dev;
0215     struct usb_hcd  *hcd = platform_get_drvdata(pdev);
0216     struct ohci_hcd *ohci = hcd_to_ohci(hcd);
0217     bool do_wakeup = device_may_wakeup(dev);
0218     int ret;
0219 
0220     if (time_before(jiffies, ohci->next_statechange))
0221         msleep(5);
0222     ohci->next_statechange = jiffies;
0223 
0224     ret = ohci_suspend(hcd, do_wakeup);
0225     if (ret)
0226         return ret;
0227 
0228     sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
0229     return ret;
0230 }
0231 
0232 static int ohci_sm501_resume(struct platform_device *pdev)
0233 {
0234     struct device *dev = &pdev->dev;
0235     struct usb_hcd  *hcd = platform_get_drvdata(pdev);
0236     struct ohci_hcd *ohci = hcd_to_ohci(hcd);
0237 
0238     if (time_before(jiffies, ohci->next_statechange))
0239         msleep(5);
0240     ohci->next_statechange = jiffies;
0241 
0242     sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
0243     ohci_resume(hcd, false);
0244     return 0;
0245 }
0246 #else
0247 #define ohci_sm501_suspend NULL
0248 #define ohci_sm501_resume NULL
0249 #endif
0250 
0251 /*-------------------------------------------------------------------------*/
0252 
0253 /*
0254  * Driver definition to register with the SM501 bus
0255  */
0256 static struct platform_driver ohci_hcd_sm501_driver = {
0257     .probe      = ohci_hcd_sm501_drv_probe,
0258     .remove     = ohci_hcd_sm501_drv_remove,
0259     .shutdown   = usb_hcd_platform_shutdown,
0260     .suspend    = ohci_sm501_suspend,
0261     .resume     = ohci_sm501_resume,
0262     .driver     = {
0263         .name   = "sm501-usb",
0264     },
0265 };
0266 MODULE_ALIAS("platform:sm501-usb");