^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-1.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * OHCI HCD (Host Controller Driver) for USB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * (C) Copyright 2000-2005 David Brownell
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (C) Copyright 2002 Hewlett-Packard Company
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * (C) Copyright 2008 Magnus Damm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * SM501 Bus Glue - based on ohci-omap.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This file is licenced under the GPL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/jiffies.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/sm501.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/sm501-regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) static int ohci_sm501_init(struct usb_hcd *hcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) return ohci_init(hcd_to_ohci(hcd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static int ohci_sm501_start(struct usb_hcd *hcd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) struct device *dev = hcd->self.controller;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) ret = ohci_run(hcd_to_ohci(hcd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) dev_err(dev, "can't start %s", hcd->self.bus_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) ohci_stop(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) /*-------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static const struct hc_driver ohci_sm501_hc_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .description = hcd_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .product_desc = "SM501 OHCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .hcd_priv_size = sizeof(struct ohci_hcd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * generic hardware linkage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .irq = ohci_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .flags = HCD_USB11 | HCD_MEMORY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * basic lifecycle operations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) .reset = ohci_sm501_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) .start = ohci_sm501_start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .stop = ohci_stop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .shutdown = ohci_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * managing i/o requests and associated device resources
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .urb_enqueue = ohci_urb_enqueue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .urb_dequeue = ohci_urb_dequeue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .endpoint_disable = ohci_endpoint_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * scheduling support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) .get_frame_number = ohci_get_frame,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * root hub support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) .hub_status_data = ohci_hub_status_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) .hub_control = ohci_hub_control,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .bus_suspend = ohci_bus_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) .bus_resume = ohci_bus_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .start_port_reset = ohci_start_port_reset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*-------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) const struct hc_driver *driver = &ohci_sm501_hc_driver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) struct resource *res, *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int retval, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct usb_hcd *hcd = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) irq = retval = platform_get_irq(pdev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) goto err0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (mem == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) dev_err(dev, "no resource definition for memory\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) retval = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) goto err0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) dev_err(dev, "request_mem_region failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) retval = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) goto err0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* allocate, reserve and remap resources for registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (res == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) dev_err(dev, "no resource definition for registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) retval = -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (!hcd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) retval = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) goto err1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) hcd->rsrc_start = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) hcd->rsrc_len = resource_size(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, pdev->name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) dev_err(dev, "request_mem_region failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) retval = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) goto err3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (hcd->regs == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) dev_err(dev, "cannot remap registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) retval = -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto err4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ohci_hcd_init(hcd_to_ohci(hcd));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) /* The sm501 chip is equipped with local memory that may be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) * by on-chip devices such as the video controller and the usb host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * This driver uses genalloc so that usb allocations with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * gen_pool_dma_alloc() allocate from this local memory. The dma_handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) * returned by gen_pool_dma_alloc() will be an offset starting from 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * for the first local memory byte.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) * So as long as data is allocated using gen_pool_dma_alloc() all is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * fine. This is however not always the case - buffers may be allocated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) * using kmalloc() - so the usb core needs to be told that it must copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) * data into our local memory if the buffers happen to be placed in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) * regular memory. A non-null hcd->localmem_pool initialized by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) * the call to usb_hcd_setup_local_mem() below does just that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) retval = usb_hcd_setup_local_mem(hcd, mem->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) mem->start - mem->parent->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) resource_size(mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (retval < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) goto err5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (retval)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) goto err5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) device_wakeup_enable(hcd->self.controller);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* enable power and unmask interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) sm501_modify_reg(dev->parent, SM501_IRQ_MASK, 1 << 6, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) err5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) iounmap(hcd->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) err4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) err3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) usb_put_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) err1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) release_mem_region(mem->start, resource_size(mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) err0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return retval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) static int ohci_hcd_sm501_drv_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) struct usb_hcd *hcd = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) struct resource *mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) usb_remove_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) iounmap(hcd->regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) usb_put_hcd(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) release_mem_region(mem->start, resource_size(mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /* mask interrupts and disable power */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) sm501_modify_reg(pdev->dev.parent, SM501_IRQ_MASK, 0, 1 << 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) sm501_unit_power(pdev->dev.parent, SM501_GATE_USB_HOST, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /*-------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #ifdef CONFIG_PM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) static int ohci_sm501_suspend(struct platform_device *pdev, pm_message_t msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct usb_hcd *hcd = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct ohci_hcd *ohci = hcd_to_ohci(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) bool do_wakeup = device_may_wakeup(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (time_before(jiffies, ohci->next_statechange))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) msleep(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) ohci->next_statechange = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) ret = ohci_suspend(hcd, do_wakeup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int ohci_sm501_resume(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct usb_hcd *hcd = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct ohci_hcd *ohci = hcd_to_ohci(hcd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (time_before(jiffies, ohci->next_statechange))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) msleep(5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ohci->next_statechange = jiffies;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) sm501_unit_power(dev->parent, SM501_GATE_USB_HOST, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ohci_resume(hcd, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #define ohci_sm501_suspend NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) #define ohci_sm501_resume NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /*-------------------------------------------------------------------------*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * Driver definition to register with the SM501 bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static struct platform_driver ohci_hcd_sm501_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .probe = ohci_hcd_sm501_drv_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .remove = ohci_hcd_sm501_drv_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .shutdown = usb_hcd_platform_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .suspend = ohci_sm501_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) .resume = ohci_sm501_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) .name = "sm501-usb",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) MODULE_ALIAS("platform:sm501-usb");