static int exynos_ohci_remove(struct platform_device *pdev) { struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); struct usb_hcd *hcd = exynos_ohci->hcd; pm_runtime_disable(&pdev->dev); exynos_ohci->power_on = 0; exynos_pm_unregister_notifier(&exynos_ohci->lpa_nb); remove_ohci_sys_file(hcd_to_ohci(hcd)); usb_remove_hcd(hcd); if (exynos_ohci->otg) exynos_ohci->otg->set_host(exynos_ohci->otg, &exynos_ohci->hcd->self); exynos_ohci_phy_disable(exynos_ohci); clk_disable_unprepare(exynos_ohci->clk); usb_put_hcd(hcd); return 0; }
static int exynos_ohci_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct platform_device *pdev = to_platform_device(dev); bool do_wakeup = device_may_wakeup(dev); unsigned long flags; int rc = ohci_suspend(hcd, do_wakeup); if (rc) return rc; spin_lock_irqsave(&ohci->lock, flags); if (exynos_ohci->otg) exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); exynos_ohci_phy_disable(pdev); clk_disable_unprepare(exynos_ohci->clk); spin_unlock_irqrestore(&ohci->lock, flags); return 0; }
static ssize_t store_ohci_power(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct platform_device *pdev = to_platform_device(dev); struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev); struct usb_hcd *hcd = exynos_ohci->hcd; int power_on; int irq; int retval; if (sscanf(buf, "%d", &power_on) != 1) return -EINVAL; device_lock(dev); if (!power_on && exynos_ohci->power_on) { printk(KERN_DEBUG "%s: EHCI turns off\n", __func__); pm_runtime_forbid(dev); exynos_ohci->power_on = 0; usb_remove_hcd(hcd); exynos_ohci_phy_disable(exynos_ohci); } else if (power_on) { printk(KERN_DEBUG "%s: EHCI turns on\n", __func__); if (exynos_ohci->power_on) { pm_runtime_forbid(dev); usb_remove_hcd(hcd); } else { exynos_ohci_phy_enable(exynos_ohci); } irq = platform_get_irq(pdev, 0); retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval < 0) { dev_err(dev, "Power On Fail\n"); goto exit; } /* * OHCI root hubs are expected to handle remote wakeup. * So, wakeup flag init defaults for root hubs. */ device_wakeup_enable(&hcd->self.root_hub->dev); exynos_ohci->power_on = 1; pm_runtime_allow(dev); } exit: device_unlock(dev); return count; }
static int exynos_ohci_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct exynos_ohci_hcd *exynos_ohci = to_exynos_ohci(hcd); usb_remove_hcd(hcd); if (exynos_ohci->otg) exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); exynos_ohci_phy_disable(pdev); clk_disable_unprepare(exynos_ohci->clk); usb_put_hcd(hcd); return 0; }
static int exynos_ohci_suspend(struct device *dev) { struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev); struct usb_hcd *hcd = exynos_ohci->hcd; struct ohci_hcd *ohci = hcd_to_ohci(hcd); unsigned long flags; int rc = 0; /* * Root hub was already suspended. Disable irq emission and * mark HW unaccessible, bail out if RH has been resumed. Use * the spinlock to properly synchronize with possible pending * RH suspend or resume activity. */ spin_lock_irqsave(&ohci->lock, flags); if (ohci->rh_state != OHCI_RH_SUSPENDED && ohci->rh_state != OHCI_RH_HALTED) { rc = -EINVAL; goto fail; } clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); if (exynos_ohci->otg) exynos_ohci->otg->set_host(exynos_ohci->otg, &exynos_ohci->hcd->self); exynos_ohci_phy_disable(exynos_ohci); clk_disable_unprepare(exynos_ohci->clk); fail: spin_unlock_irqrestore(&ohci->lock, flags); return rc; }
static int exynos_ohci_probe(struct platform_device *pdev) { struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data; struct exynos_ohci_hcd *exynos_ohci; struct usb_hcd *hcd; struct ohci_hcd *ohci; struct resource *res; struct usb_phy *phy; int irq; int err; /* * Right now device-tree probed devices don't get dma_mask set. * Since shared usb code relies on it, set it here for now. * Once we move to full device tree support this will vanish off. */ if (!pdev->dev.dma_mask) pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; if (!pdev->dev.coherent_dma_mask) pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); exynos_ohci = devm_kzalloc(&pdev->dev, sizeof(struct exynos_ohci_hcd), GFP_KERNEL); if (!exynos_ohci) return -ENOMEM; if (of_device_is_compatible(pdev->dev.of_node, "samsung,exynos5440-ohci")) goto skip_phy; phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0); if (IS_ERR(phy)) { /* Fallback to pdata */ if (!pdata) { dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); return -EPROBE_DEFER; } else { exynos_ohci->pdata = pdata; } } else { exynos_ohci->phy = phy; exynos_ohci->otg = phy->otg; } skip_phy: exynos_ohci->dev = &pdev->dev; hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); return -ENOMEM; } exynos_ohci->hcd = hcd; exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost"); if (IS_ERR(exynos_ohci->clk)) { dev_err(&pdev->dev, "Failed to get usbhost clock\n"); err = PTR_ERR(exynos_ohci->clk); goto fail_clk; } err = clk_prepare_enable(exynos_ohci->clk); if (err) goto fail_clk; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Failed to get I/O memory\n"); err = -ENXIO; goto fail_io; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "Failed to remap I/O memory\n"); err = -ENOMEM; goto fail_io; } irq = platform_get_irq(pdev, 0); if (!irq) { dev_err(&pdev->dev, "Failed to get IRQ\n"); err = -ENODEV; goto fail_io; } if (exynos_ohci->otg) exynos_ohci->otg->set_host(exynos_ohci->otg, &exynos_ohci->hcd->self); /* Make sure PHY is initialized */ exynos_ohci_phy_enable(exynos_ohci); if (exynos_ohci->phy) /* * PHY can be runtime suspended (e.g. by EHCI driver), so * make sure PHY is active */ pm_runtime_get_sync(exynos_ohci->phy->dev); ohci = hcd_to_ohci(hcd); ohci_hcd_init(ohci); err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); goto fail_add_hcd; } platform_set_drvdata(pdev, exynos_ohci); /* * OHCI root hubs are expected to handle remote wakeup. * So, wakeup flag init defaults for root hubs. */ device_wakeup_enable(&hcd->self.root_hub->dev); if (create_ohci_sys_file(ohci)) dev_err(&pdev->dev, "Failed to create ehci sys file\n"); exynos_ohci->lpa_nb.notifier_call = exynos_ohci_lpa_event; exynos_ohci->lpa_nb.next = NULL; exynos_ohci->lpa_nb.priority = 0; err = exynos_pm_register_notifier(&exynos_ohci->lpa_nb); if (err) dev_err(&pdev->dev, "Failed to register lpa notifier\n"); exynos_ohci->power_on = 1; pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); return 0; fail_add_hcd: if (exynos_ohci->phy) pm_runtime_put_sync(exynos_ohci->phy->dev); exynos_ohci_phy_disable(exynos_ohci); fail_io: clk_disable_unprepare(exynos_ohci->clk); fail_clk: usb_put_hcd(hcd); return err; }
static int exynos_ohci_probe(struct platform_device *pdev) { struct exynos_ohci_hcd *exynos_ohci; struct usb_hcd *hcd; struct resource *res; struct usb_phy *phy; int irq; int err; /* * Right now device-tree probed devices don't get dma_mask set. * Since shared usb code relies on it, set it here for now. * Once we move to full device tree support this will vanish off. */ err = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (err) return err; hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev, dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); return -ENOMEM; } exynos_ohci = to_exynos_ohci(hcd); if (of_device_is_compatible(pdev->dev.of_node, "samsung,exynos5440-ohci")) goto skip_phy; phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR(phy)) { usb_put_hcd(hcd); dev_warn(&pdev->dev, "no platform data or transceiver defined\n"); return -EPROBE_DEFER; } else { exynos_ohci->phy = phy; exynos_ohci->otg = phy->otg; } skip_phy: exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost"); if (IS_ERR(exynos_ohci->clk)) { dev_err(&pdev->dev, "Failed to get usbhost clock\n"); err = PTR_ERR(exynos_ohci->clk); goto fail_clk; } err = clk_prepare_enable(exynos_ohci->clk); if (err) goto fail_clk; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { dev_err(&pdev->dev, "Failed to get I/O memory\n"); err = -ENXIO; goto fail_io; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); hcd->regs = devm_ioremap(&pdev->dev, res->start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "Failed to remap I/O memory\n"); err = -ENOMEM; goto fail_io; } irq = platform_get_irq(pdev, 0); if (!irq) { dev_err(&pdev->dev, "Failed to get IRQ\n"); err = -ENODEV; goto fail_io; } if (exynos_ohci->otg) exynos_ohci->otg->set_host(exynos_ohci->otg, &hcd->self); platform_set_drvdata(pdev, hcd); exynos_ohci_phy_enable(pdev); err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); goto fail_add_hcd; } device_wakeup_enable(hcd->self.controller); return 0; fail_add_hcd: exynos_ohci_phy_disable(pdev); fail_io: clk_disable_unprepare(exynos_ohci->clk); fail_clk: usb_put_hcd(hcd); return err; }