/** * usb_hcd_pxa27x_remove - shutdown processing for pxa27x-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_pxa27x_probe(), first invoking * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * */ void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *pdev) { struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); usb_remove_hcd(hcd); pxa27x_stop_hc(ohci, &pdev->dev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); clk_put(ohci->clk); }
static int ohci_hcd_pxa27x_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); if (time_before(jiffies, ohci->ohci.next_statechange)) msleep(5); ohci->ohci.next_statechange = jiffies; pxa27x_stop_hc(ohci, dev); return 0; }
/** * ohci_hcd_pxa27x_remove - shutdown processing for pxa27x-based HCDs * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of ohci_hcd_pxa27x_probe(), first invoking * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * */ static int ohci_hcd_pxa27x_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd); unsigned int i; usb_remove_hcd(hcd); pxa27x_stop_hc(pxa_ohci, &pdev->dev); for (i = 0; i < 3; ++i) pxa27x_ohci_set_vbus_power(pxa_ohci, i, false); usb_put_hcd(hcd); return 0; }
static int ohci_hcd_pxa27x_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct pxa27x_ohci *ohci = to_pxa27x_ohci(hcd); struct pxaohci_platform_data *inf = dev->platform_data; int status; if (time_before(jiffies, ohci->ohci.next_statechange)) msleep(5); ohci->ohci.next_statechange = jiffies; if ((status = pxa27x_start_hc(ohci, dev)) < 0) return status; /* Select Power Management Mode */ pxa27x_ohci_select_pmm(ohci, inf->port_mode); ohci_finish_controller_resume(hcd); return 0; }
static int ohci_hcd_pxa27x_drv_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd); struct ohci_hcd *ohci = hcd_to_ohci(hcd); bool do_wakeup = device_may_wakeup(dev); int ret; if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; ret = ohci_suspend(hcd, do_wakeup); if (ret) return ret; pxa27x_stop_hc(pxa_ohci, dev); return ret; }
static int ohci_hcd_pxa27x_drv_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd); struct pxaohci_platform_data *inf = dev_get_platdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); int status; if (time_before(jiffies, ohci->next_statechange)) msleep(5); ohci->next_statechange = jiffies; status = pxa27x_start_hc(pxa_ohci, dev); if (status < 0) return status; /* Select Power Management Mode */ pxa27x_ohci_select_pmm(pxa_ohci, inf->port_mode); ohci_resume(hcd, false); return 0; }
static int pxa27x_ohci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct pxa27x_ohci *pxa_ohci = to_pxa27x_ohci(hcd); int ret; switch (typeReq) { case SetPortFeature: case ClearPortFeature: if (!wIndex || wIndex > 3) return -EPIPE; if (wValue != USB_PORT_FEAT_POWER) break; ret = pxa27x_ohci_set_vbus_power(pxa_ohci, wIndex - 1, typeReq == SetPortFeature); if (ret) return ret; break; } return ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); }
/** * usb_hcd_pxa27x_probe - initialize pxa27x-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. * */ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device *pdev) { int retval, irq; struct usb_hcd *hcd; struct pxaohci_platform_data *inf; struct pxa27x_ohci *pxa_ohci; struct ohci_hcd *ohci; struct resource *r; struct clk *usb_clk; retval = ohci_pxa_of_init(pdev); if (retval) return retval; inf = dev_get_platdata(&pdev->dev); if (!inf) return -ENODEV; irq = platform_get_irq(pdev, 0); if (irq < 0) { pr_err("no resource of IORESOURCE_IRQ"); return -ENXIO; } usb_clk = clk_get(&pdev->dev, NULL); if (IS_ERR(usb_clk)) return PTR_ERR(usb_clk); hcd = usb_create_hcd (driver, &pdev->dev, "pxa27x"); if (!hcd) { retval = -ENOMEM; goto err0; } r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { pr_err("no resource of IORESOURCE_MEM"); retval = -ENXIO; goto err1; } hcd->rsrc_start = r->start; hcd->rsrc_len = resource_size(r); if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { pr_debug("request_mem_region failed"); retval = -EBUSY; goto err1; } hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { pr_debug("ioremap failed"); retval = -ENOMEM; goto err2; } /* initialize "struct pxa27x_ohci" */ pxa_ohci = to_pxa27x_ohci(hcd); pxa_ohci->clk = usb_clk; pxa_ohci->mmio_base = (void __iomem *)hcd->regs; retval = pxa27x_start_hc(pxa_ohci, &pdev->dev); if (retval < 0) { pr_debug("pxa27x_start_hc failed"); goto err3; } /* Select Power Management Mode */ pxa27x_ohci_select_pmm(pxa_ohci, inf->port_mode); if (inf->power_budget) hcd->power_budget = inf->power_budget; /* The value of NDP in roothub_a is incorrect on this hardware */ ohci = hcd_to_ohci(hcd); ohci->num_ports = 3; retval = usb_add_hcd(hcd, irq, 0); if (retval == 0) return retval; pxa27x_stop_hc(pxa_ohci, &pdev->dev); err3: iounmap(hcd->regs); err2: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); err0: clk_put(usb_clk); return retval; }
/** * ohci_hcd_pxa27x_probe - initialize pxa27x-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() method for the HCD associated with it * through the hotplug entry's driver_data. * */ static int ohci_hcd_pxa27x_probe(struct platform_device *pdev) { int retval, irq; struct usb_hcd *hcd; struct pxaohci_platform_data *inf; struct pxa27x_ohci *pxa_ohci; struct ohci_hcd *ohci; struct resource *r; struct clk *usb_clk; unsigned int i; retval = ohci_pxa_of_init(pdev); if (retval) return retval; inf = dev_get_platdata(&pdev->dev); if (!inf) return -ENODEV; irq = platform_get_irq(pdev, 0); if (irq < 0) { pr_err("no resource of IORESOURCE_IRQ"); return irq; } usb_clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(usb_clk)) return PTR_ERR(usb_clk); hcd = usb_create_hcd(&ohci_pxa27x_hc_driver, &pdev->dev, "pxa27x"); if (!hcd) return -ENOMEM; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); hcd->regs = devm_ioremap_resource(&pdev->dev, r); if (IS_ERR(hcd->regs)) { retval = PTR_ERR(hcd->regs); goto err; } hcd->rsrc_start = r->start; hcd->rsrc_len = resource_size(r); /* initialize "struct pxa27x_ohci" */ pxa_ohci = to_pxa27x_ohci(hcd); pxa_ohci->clk = usb_clk; pxa_ohci->mmio_base = (void __iomem *)hcd->regs; for (i = 0; i < 3; ++i) { char name[6]; if (!(inf->flags & (ENABLE_PORT1 << i))) continue; sprintf(name, "vbus%u", i + 1); pxa_ohci->vbus[i] = devm_regulator_get(&pdev->dev, name); } retval = pxa27x_start_hc(pxa_ohci, &pdev->dev); if (retval < 0) { pr_debug("pxa27x_start_hc failed"); goto err; } /* Select Power Management Mode */ pxa27x_ohci_select_pmm(pxa_ohci, inf->port_mode); if (inf->power_budget) hcd->power_budget = inf->power_budget; /* The value of NDP in roothub_a is incorrect on this hardware */ ohci = hcd_to_ohci(hcd); ohci->num_ports = 3; retval = usb_add_hcd(hcd, irq, 0); if (retval == 0) { device_wakeup_enable(hcd->self.controller); return retval; } pxa27x_stop_hc(pxa_ohci, &pdev->dev); err: usb_put_hcd(hcd); return retval; }