return -ENOMEM;
}
- dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (node) {
+ dwc->usb2_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
+ dwc->usb3_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 1);
+ } else {
+ dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
+ }
+
if (IS_ERR_OR_NULL(dwc->usb2_phy)) {
dev_err(dev, "no usb2 phy configured\n");
return -EPROBE_DEFER;
}
- dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3);
if (IS_ERR_OR_NULL(dwc->usb3_phy)) {
dev_err(dev, "no usb3 phy configured\n");
return -EPROBE_DEFER;
}
+ usb_phy_set_suspend(dwc->usb2_phy, 0);
+ usb_phy_set_suspend(dwc->usb3_phy, 0);
+
spin_lock_init(&dwc->lock);
platform_set_drvdata(pdev, dwc);
else
dwc->maximum_speed = DWC3_DCFG_SUPERSPEED;
- if (of_get_property(node, "tx-fifo-resize", NULL))
- dwc->needs_fifo_resize = true;
+ dwc->needs_fifo_resize = of_property_read_bool(node, "tx-fifo-resize");
pm_runtime_enable(dev);
pm_runtime_get_sync(dev);
static int dwc3_remove(struct platform_device *pdev)
{
struct dwc3 *dwc = platform_get_drvdata(pdev);
- struct resource *res;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ usb_phy_set_suspend(dwc->usb2_phy, 1);
+ usb_phy_set_suspend(dwc->usb3_phy, 1);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}
+ #ifdef CONFIG_OF
+ static const struct of_device_id of_dwc3_match[] = {
+ {
+ .compatible = "synopsys,dwc3"
+ },
+ { },
+ };
+ MODULE_DEVICE_TABLE(of, of_dwc3_match);
+ #endif
+
static struct platform_driver dwc3_driver = {
.probe = dwc3_probe,
.remove = dwc3_remove,
.driver = {
.name = "dwc3",
+ .of_match_table = of_match_ptr(of_dwc3_match),
},
};
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+ #include <linux/usb/phy.h>
#include <linux/platform_data/s3c-hsotg.h>
#include <mach/map.h>
* struct s3c_hsotg - driver state.
* @dev: The parent device supplied to the probe function
* @driver: USB gadget driver
- * @plat: The platform specific configuration data.
+ * @phy: The otg phy transceiver structure for phy control.
+ * @plat: The platform specific configuration data. This can be removed once
+ * all SoCs support usb transceiver.
* @regs: The memory area mapped for accessing registers.
* @irq: The IRQ number we are using
* @supplies: Definition of USB power supplies
struct s3c_hsotg {
struct device *dev;
struct usb_gadget_driver *driver;
+ struct usb_phy *phy;
struct s3c_hsotg_plat *plat;
spinlock_t lock;
struct platform_device *pdev = to_platform_device(hsotg->dev);
dev_dbg(hsotg->dev, "pdev 0x%p\n", pdev);
- if (hsotg->plat->phy_init)
+
+ if (hsotg->phy)
+ usb_phy_init(hsotg->phy);
+ else if (hsotg->plat->phy_init)
hsotg->plat->phy_init(pdev, hsotg->plat->phy_type);
}
{
struct platform_device *pdev = to_platform_device(hsotg->dev);
- if (hsotg->plat->phy_exit)
+ if (hsotg->phy)
+ usb_phy_shutdown(hsotg->phy);
+ else if (hsotg->plat->phy_exit)
hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type);
}
return 0;
}
-static struct usb_gadget_ops s3c_hsotg_gadget_ops = {
+static const struct usb_gadget_ops s3c_hsotg_gadget_ops = {
.get_frame = s3c_hsotg_gadget_getframe,
.udc_start = s3c_hsotg_udc_start,
.udc_stop = s3c_hsotg_udc_stop,
/**
* s3c_hsotg_release - release callback for hsotg device
* @dev: Device to for which release is called
+ *
+ * Nothing to do as the resource is allocated using devm_ API.
*/
static void s3c_hsotg_release(struct device *dev)
{
- struct s3c_hsotg *hsotg = dev_get_drvdata(dev);
-
- kfree(hsotg);
}
/**
static int s3c_hsotg_probe(struct platform_device *pdev)
{
struct s3c_hsotg_plat *plat = pdev->dev.platform_data;
+ struct usb_phy *phy;
struct device *dev = &pdev->dev;
struct s3c_hsotg_ep *eps;
struct s3c_hsotg *hsotg;
int ret;
int i;
- plat = pdev->dev.platform_data;
- if (!plat) {
- dev_err(&pdev->dev, "no platform data defined\n");
- return -EINVAL;
- }
-
hsotg = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsotg), GFP_KERNEL);
if (!hsotg) {
dev_err(dev, "cannot get memory\n");
return -ENOMEM;
}
+ phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(phy)) {
+ /* Fallback for pdata */
+ plat = pdev->dev.platform_data;
+ if (!plat) {
+ dev_err(&pdev->dev, "no platform data or transceiver defined\n");
+ return -EPROBE_DEFER;
+ } else {
+ hsotg->plat = plat;
+ }
+ } else {
+ hsotg->phy = phy;
+ }
+
hsotg->dev = dev;
- hsotg->plat = plat;
hsotg->clk = devm_clk_get(&pdev->dev, "otg");
if (IS_ERR(hsotg->clk)) {
for (i = 0; i < ARRAY_SIZE(hsotg->supplies); i++)
hsotg->supplies[i].supply = s3c_hsotg_supply_names[i];
- ret = regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hsotg->supplies),
hsotg->supplies);
if (ret) {
dev_err(dev, "failed to request supplies: %d\n", ret);
kfree(eps);
err_supplies:
s3c_hsotg_phy_disable(hsotg);
- regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
-
err_clk:
clk_disable_unprepare(hsotg->clk);
}
s3c_hsotg_phy_disable(hsotg);
- regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies);
clk_disable_unprepare(hsotg->clk);
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/platform_data/usb-ehci-s5p.h>
+ #include <linux/usb/phy.h>
+ #include <linux/usb/samsung_usb_phy.h>
#include <plat/usb-phy.h>
#define EHCI_INSNREG00(base) (base + 0x90)
struct device *dev;
struct usb_hcd *hcd;
struct clk *clk;
+ struct usb_phy *phy;
+ struct usb_otg *otg;
+ struct s5p_ehci_platdata *pdata;
};
static const struct hc_driver s5p_ehci_hc_driver = {
.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
};
+ static void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci)
+ {
+ struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
+
+ if (s5p_ehci->phy)
+ usb_phy_init(s5p_ehci->phy);
+ else if (s5p_ehci->pdata->phy_init)
+ s5p_ehci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
+ }
+
+ static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci)
+ {
+ struct platform_device *pdev = to_platform_device(s5p_ehci->dev);
+
+ if (s5p_ehci->phy)
+ usb_phy_shutdown(s5p_ehci->phy);
+ else if (s5p_ehci->pdata->phy_exit)
+ s5p_ehci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
+ }
+
static void s5p_setup_vbus_gpio(struct platform_device *pdev)
{
int err;
static int s5p_ehci_probe(struct platform_device *pdev)
{
- struct s5p_ehci_platdata *pdata;
+ struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
struct s5p_ehci_hcd *s5p_ehci;
struct usb_hcd *hcd;
struct ehci_hcd *ehci;
struct resource *res;
+ struct usb_phy *phy;
int irq;
int err;
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "No platform data defined\n");
- return -EINVAL;
- }
-
/*
* Right now device-tree probed devices don't get dma_mask set.
* Since shared usb code relies on it, set it here for now.
if (!s5p_ehci)
return -ENOMEM;
+ phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(phy)) {
+ /* Fallback to pdata */
+ if (!pdata) {
+ dev_warn(&pdev->dev, "no platform data or transceiver defined\n");
+ return -EPROBE_DEFER;
+ } else {
+ s5p_ehci->pdata = pdata;
+ }
+ } else {
+ s5p_ehci->phy = phy;
+ s5p_ehci->otg = phy->otg;
+ }
+
s5p_ehci->dev = &pdev->dev;
hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev,
goto fail_io;
}
- if (pdata->phy_init)
- pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+ if (s5p_ehci->otg)
+ s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+
+ s5p_ehci_phy_enable(s5p_ehci);
ehci = hcd_to_ehci(hcd);
ehci->caps = hcd->regs;
err = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (err) {
dev_err(&pdev->dev, "Failed to add USB HCD\n");
- goto fail_io;
+ goto fail_add_hcd;
}
platform_set_drvdata(pdev, s5p_ehci);
return 0;
+ fail_add_hcd:
+ s5p_ehci_phy_disable(s5p_ehci);
fail_io:
clk_disable_unprepare(s5p_ehci->clk);
fail_clk:
static int s5p_ehci_remove(struct platform_device *pdev)
{
- struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
struct usb_hcd *hcd = s5p_ehci->hcd;
usb_remove_hcd(hcd);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+ if (s5p_ehci->otg)
+ s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+
+ s5p_ehci_phy_disable(s5p_ehci);
clk_disable_unprepare(s5p_ehci->clk);
struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
struct usb_hcd *hcd = s5p_ehci->hcd;
bool do_wakeup = device_may_wakeup(dev);
- struct platform_device *pdev = to_platform_device(dev);
- struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
int rc;
rc = ehci_suspend(hcd, do_wakeup);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+ if (s5p_ehci->otg)
+ s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+
+ s5p_ehci_phy_disable(s5p_ehci);
clk_disable_unprepare(s5p_ehci->clk);
{
struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
struct usb_hcd *hcd = s5p_ehci->hcd;
- struct platform_device *pdev = to_platform_device(dev);
- struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
clk_prepare_enable(s5p_ehci->clk);
- if (pdata && pdata->phy_init)
- pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+ if (s5p_ehci->otg)
+ s5p_ehci->otg->set_host(s5p_ehci->otg, &s5p_ehci->hcd->self);
+
+ s5p_ehci_phy_enable(s5p_ehci);
/* DMA burst Enable */
writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
#ifdef CONFIG_OF
static const struct of_device_id exynos_ehci_match[] = {
- { .compatible = "samsung,exynos-ehci" },
+ { .compatible = "samsung,exynos4210-ehci" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_ehci_match);
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/platform_data/usb-exynos.h>
+ #include <linux/usb/phy.h>
+ #include <linux/usb/samsung_usb_phy.h>
#include <plat/usb-phy.h>
struct exynos_ohci_hcd {
struct device *dev;
struct usb_hcd *hcd;
struct clk *clk;
+ struct usb_phy *phy;
+ struct usb_otg *otg;
+ struct exynos4_ohci_platdata *pdata;
};
+ static void exynos_ohci_phy_enable(struct exynos_ohci_hcd *exynos_ohci)
+ {
+ struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+
+ if (exynos_ohci->phy)
+ usb_phy_init(exynos_ohci->phy);
+ else if (exynos_ohci->pdata->phy_init)
+ exynos_ohci->pdata->phy_init(pdev, USB_PHY_TYPE_HOST);
+ }
+
+ static void exynos_ohci_phy_disable(struct exynos_ohci_hcd *exynos_ohci)
+ {
+ struct platform_device *pdev = to_platform_device(exynos_ohci->dev);
+
+ if (exynos_ohci->phy)
+ usb_phy_shutdown(exynos_ohci->phy);
+ else if (exynos_ohci->pdata->phy_exit)
+ exynos_ohci->pdata->phy_exit(pdev, USB_PHY_TYPE_HOST);
+ }
+
static int ohci_exynos_reset(struct usb_hcd *hcd)
{
return ohci_init(hcd_to_ohci(hcd));
static int exynos_ohci_probe(struct platform_device *pdev)
{
- struct exynos4_ohci_platdata *pdata;
+ 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;
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "No platform data defined\n");
- return -EINVAL;
- }
-
/*
* Right now device-tree probed devices don't get dma_mask set.
* Since shared usb code relies on it, set it here for now.
if (!exynos_ohci)
return -ENOMEM;
+ phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR_OR_NULL(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;
+ }
+
exynos_ohci->dev = &pdev->dev;
hcd = usb_create_hcd(&exynos_ohci_hc_driver, &pdev->dev,
goto fail_io;
}
- if (pdata->phy_init)
- pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+ if (exynos_ohci->otg)
+ exynos_ohci->otg->set_host(exynos_ohci->otg,
+ &exynos_ohci->hcd->self);
+
+ exynos_ohci_phy_enable(exynos_ohci);
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_io;
+ goto fail_add_hcd;
}
platform_set_drvdata(pdev, exynos_ohci);
return 0;
+ fail_add_hcd:
+ exynos_ohci_phy_disable(exynos_ohci);
fail_io:
clk_disable_unprepare(exynos_ohci->clk);
fail_clk:
static int exynos_ohci_remove(struct platform_device *pdev)
{
- struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
struct exynos_ohci_hcd *exynos_ohci = platform_get_drvdata(pdev);
struct usb_hcd *hcd = exynos_ohci->hcd;
usb_remove_hcd(hcd);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+ 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);
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);
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
unsigned long flags;
int rc = 0;
clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
- if (pdata && pdata->phy_exit)
- pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
+ 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);
{
struct exynos_ohci_hcd *exynos_ohci = dev_get_drvdata(dev);
struct usb_hcd *hcd = exynos_ohci->hcd;
- struct platform_device *pdev = to_platform_device(dev);
- struct exynos4_ohci_platdata *pdata = pdev->dev.platform_data;
clk_prepare_enable(exynos_ohci->clk);
- if (pdata && pdata->phy_init)
- pdata->phy_init(pdev, S5P_USB_PHY_HOST);
+ if (exynos_ohci->otg)
+ exynos_ohci->otg->set_host(exynos_ohci->otg,
+ &exynos_ohci->hcd->self);
+
+ exynos_ohci_phy_enable(exynos_ohci);
ohci_resume(hcd, false);
#ifdef CONFIG_OF
static const struct of_device_id exynos_ohci_match[] = {
- { .compatible = "samsung,exynos-ohci" },
+ { .compatible = "samsung,exynos4210-ohci" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_ohci_match);
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/usb/musb-omap.h>
+ #include <linux/usb/omap_control_usb.h>
#include "musb_core.h"
#include "omap2430.h"
struct platform_device *musb;
enum omap_musb_vbus_id_status status;
struct work_struct omap_musb_mailbox_work;
- u32 __iomem *control_otghs;
+ struct device *control_otghs;
};
#define glue_to_musb(g) platform_get_drvdata(g->musb)
static struct timer_list musb_idle_timer;
- /**
- * omap4_usb_phy_mailbox - write to usb otg mailbox
- * @glue: struct omap2430_glue *
- * @val: the value to be written to the mailbox
- *
- * On detection of a device (ID pin is grounded), this API should be called
- * to set AVALID, VBUSVALID and ID pin is grounded.
- *
- * When OMAP is connected to a host (OMAP in device mode), this API
- * is called to set AVALID, VBUSVALID and ID pin in high impedance.
- *
- * XXX: This function will be removed once we have a seperate driver for
- * control module
- */
- static void omap4_usb_phy_mailbox(struct omap2430_glue *glue, u32 val)
- {
- if (glue->control_otghs)
- writel(val, glue->control_otghs);
- }
-
static void musb_do_idle(unsigned long _musb)
{
struct musb *musb = (void *)_musb;
void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
{
struct omap2430_glue *glue = _glue;
- struct musb *musb = glue_to_musb(glue);
- glue->status = status;
- if (!musb) {
- dev_err(glue->dev, "musb core is not yet ready\n");
+ if (glue && glue_to_musb(glue)) {
+ glue->status = status;
+ } else {
+ pr_err("%s: musb core is not yet ready\n", __func__);
return;
}
static void omap_musb_set_mailbox(struct omap2430_glue *glue)
{
- u32 val;
struct musb *musb = glue_to_musb(glue);
struct device *dev = musb->controller;
struct musb_hdrc_platform_data *pdata = dev->platform_data;
musb->xceiv->last_event = USB_EVENT_ID;
if (musb->gadget_driver) {
pm_runtime_get_sync(dev);
- val = AVALID | VBUSVALID;
- omap4_usb_phy_mailbox(glue, val);
+ omap_control_usb_set_mode(glue->control_otghs,
+ USB_MODE_HOST);
omap2430_musb_set_vbus(musb, 1);
}
break;
musb->xceiv->last_event = USB_EVENT_VBUS;
if (musb->gadget_driver)
pm_runtime_get_sync(dev);
- val = IDDIG | AVALID | VBUSVALID;
- omap4_usb_phy_mailbox(glue, val);
+ omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
break;
case OMAP_MUSB_ID_FLOAT:
if (musb->xceiv->otg->set_vbus)
otg_set_vbus(musb->xceiv->otg, 0);
}
- val = SESSEND | IDDIG;
- omap4_usb_phy_mailbox(glue, val);
+ omap_control_usb_set_mode(glue->control_otghs,
+ USB_MODE_DISCONNECT);
break;
default:
dev_dbg(dev, "ID float\n");
* up through ULPI. TWL4030-family PMICs include one,
* which needs a driver, drivers aren't always needed.
*/
- musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
+ if (dev->parent->of_node)
+ musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
+ "usb-phy", 0);
+ else
+ musb->xceiv = devm_usb_get_phy_dev(dev, 0);
+
if (IS_ERR_OR_NULL(musb->xceiv)) {
pr_err("HS USB OTG: no transceiver configured\n");
- return -ENODEV;
+ return -EPROBE_DEFER;
}
musb->isr = omap2430_musb_interrupt;
static void omap2430_musb_enable(struct musb *musb)
{
u8 devctl;
- u32 val;
unsigned long timeout = jiffies + msecs_to_jiffies(1000);
struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
switch (glue->status) {
case OMAP_MUSB_ID_GROUND:
- val = AVALID | VBUSVALID;
- omap4_usb_phy_mailbox(glue, val);
+ omap_control_usb_set_mode(glue->control_otghs, USB_MODE_HOST);
if (data->interface_type != MUSB_INTERFACE_UTMI)
break;
devctl = musb_readb(musb->mregs, MUSB_DEVCTL);
break;
case OMAP_MUSB_VBUS_VALID:
- val = IDDIG | AVALID | VBUSVALID;
- omap4_usb_phy_mailbox(glue, val);
+ omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
break;
default:
static void omap2430_musb_disable(struct musb *musb)
{
- u32 val;
struct device *dev = musb->controller;
struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
- if (glue->status != OMAP_MUSB_UNKNOWN) {
- val = SESSEND | IDDIG;
- omap4_usb_phy_mailbox(glue, val);
- }
+ if (glue->status != OMAP_MUSB_UNKNOWN)
+ omap_control_usb_set_mode(glue->control_otghs,
+ USB_MODE_DISCONNECT);
}
static int omap2430_musb_exit(struct musb *musb)
struct omap2430_glue *glue;
struct device_node *np = pdev->dev.of_node;
struct musb_hdrc_config *config;
- struct resource *res;
int ret = -ENOMEM;
glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
glue->musb = musb;
glue->status = OMAP_MUSB_UNKNOWN;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-
- glue->control_otghs = devm_request_and_ioremap(&pdev->dev, res);
- if (glue->control_otghs == NULL)
- dev_dbg(&pdev->dev, "Failed to obtain control memory\n");
-
if (np) {
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev,
"failed to allocate musb platfrom data\n");
- ret = -ENOMEM;
goto err2;
}
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(&pdev->dev,
- "failed to allocate musb board data\n");
- ret = -ENOMEM;
+ "failed to allocate musb board data\n");
goto err2;
}
config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
- if (!data) {
+ if (!config) {
dev_err(&pdev->dev,
"failed to allocate musb hdrc config\n");
goto err2;
of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits);
of_property_read_u32(np, "power", (u32 *)&pdata->power);
config->multipoint = of_property_read_bool(np, "multipoint");
+ pdata->has_mailbox = of_property_read_bool(np,
+ "ti,has-mailbox");
pdata->board_data = data;
pdata->config = config;
}
+ if (pdata->has_mailbox) {
+ glue->control_otghs = omap_get_control_dev();
+ if (IS_ERR(glue->control_otghs)) {
+ dev_vdbg(&pdev->dev, "Failed to get control device\n");
+ return -ENODEV;
+ }
+ } else {
+ glue->control_otghs = ERR_PTR(-ENODEV);
+ }
pdata->platform_ops = &omap2430_ops;
platform_set_drvdata(pdev, glue);
unsigned int i;
for (i = 0; i < mvotg->clknum; i++)
- clk_enable(mvotg->clk[i]);
+ clk_prepare_enable(mvotg->clk[i]);
}
static void otg_clock_disable(struct mv_otg *mvotg)
unsigned int i;
for (i = 0; i < mvotg->clknum; i++)
- clk_disable(mvotg->clk[i]);
+ clk_disable_unprepare(mvotg->clk[i]);
}
static int mv_otg_enable_internal(struct mv_otg *mvotg)
struct usb_otg *otg;
int old_state;
- mvotg = container_of((struct delayed_work *)work, struct mv_otg, work);
+ mvotg = container_of(to_delayed_work(work), struct mv_otg, work);
run:
/* work queue is single thread, or we need spin_lock to protect */
int mv_otg_remove(struct platform_device *pdev)
{
struct mv_otg *mvotg = platform_get_drvdata(pdev);
- int clk_i;
sysfs_remove_group(&mvotg->pdev->dev.kobj, &inputs_attr_group);
- if (mvotg->irq)
- free_irq(mvotg->irq, mvotg);
-
- if (mvotg->pdata->vbus)
- free_irq(mvotg->pdata->vbus->irq, mvotg);
- if (mvotg->pdata->id)
- free_irq(mvotg->pdata->id->irq, mvotg);
-
if (mvotg->qwork) {
flush_workqueue(mvotg->qwork);
destroy_workqueue(mvotg->qwork);
mv_otg_disable(mvotg);
- if (mvotg->cap_regs)
- iounmap(mvotg->cap_regs);
-
- if (mvotg->phy_regs)
- iounmap(mvotg->phy_regs);
-
- for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
- clk_put(mvotg->clk[clk_i]);
-
usb_remove_phy(&mvotg->phy);
platform_set_drvdata(pdev, NULL);
- kfree(mvotg->phy.otg);
- kfree(mvotg);
-
return 0;
}
}
size = sizeof(*mvotg) + sizeof(struct clk *) * pdata->clknum;
- mvotg = kzalloc(size, GFP_KERNEL);
+ mvotg = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
if (!mvotg) {
dev_err(&pdev->dev, "failed to allocate memory!\n");
return -ENOMEM;
}
- otg = kzalloc(sizeof *otg, GFP_KERNEL);
- if (!otg) {
- kfree(mvotg);
+ otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
+ if (!otg)
return -ENOMEM;
- }
platform_set_drvdata(pdev, mvotg);
mvotg->clknum = pdata->clknum;
for (clk_i = 0; clk_i < mvotg->clknum; clk_i++) {
- mvotg->clk[clk_i] = clk_get(&pdev->dev, pdata->clkname[clk_i]);
+ mvotg->clk[clk_i] = devm_clk_get(&pdev->dev,
+ pdata->clkname[clk_i]);
if (IS_ERR(mvotg->clk[clk_i])) {
retval = PTR_ERR(mvotg->clk[clk_i]);
- goto err_put_clk;
+ return retval;
}
}
mvotg->qwork = create_singlethread_workqueue("mv_otg_queue");
if (!mvotg->qwork) {
dev_dbg(&pdev->dev, "cannot create workqueue for OTG\n");
- retval = -ENOMEM;
- goto err_put_clk;
+ return -ENOMEM;
}
INIT_DELAYED_WORK(&mvotg->work, mv_otg_work);
goto err_destroy_workqueue;
}
- mvotg->phy_regs = ioremap(r->start, resource_size(r));
+ mvotg->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (mvotg->phy_regs == NULL) {
dev_err(&pdev->dev, "failed to map phy I/O memory\n");
retval = -EFAULT;
if (r == NULL) {
dev_err(&pdev->dev, "no I/O memory resource defined\n");
retval = -ENODEV;
- goto err_unmap_phyreg;
+ goto err_destroy_workqueue;
}
- mvotg->cap_regs = ioremap(r->start, resource_size(r));
+ mvotg->cap_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (mvotg->cap_regs == NULL) {
dev_err(&pdev->dev, "failed to map I/O memory\n");
retval = -EFAULT;
- goto err_unmap_phyreg;
+ goto err_destroy_workqueue;
}
/* we will acces controller register, so enable the udc controller */
retval = mv_otg_enable_internal(mvotg);
if (retval) {
dev_err(&pdev->dev, "mv otg enable error %d\n", retval);
- goto err_unmap_capreg;
+ goto err_destroy_workqueue;
}
mvotg->op_regs =
+ (readl(mvotg->cap_regs) & CAPLENGTH_MASK));
if (pdata->id) {
- retval = request_threaded_irq(pdata->id->irq, NULL,
- mv_otg_inputs_irq,
- IRQF_ONESHOT, "id", mvotg);
+ retval = devm_request_threaded_irq(&pdev->dev, pdata->id->irq,
+ NULL, mv_otg_inputs_irq,
+ IRQF_ONESHOT, "id", mvotg);
if (retval) {
dev_info(&pdev->dev,
"Failed to request irq for ID\n");
if (pdata->vbus) {
mvotg->clock_gating = 1;
- retval = request_threaded_irq(pdata->vbus->irq, NULL,
- mv_otg_inputs_irq,
- IRQF_ONESHOT, "vbus", mvotg);
+ retval = devm_request_threaded_irq(&pdev->dev, pdata->vbus->irq,
+ NULL, mv_otg_inputs_irq,
+ IRQF_ONESHOT, "vbus", mvotg);
if (retval) {
dev_info(&pdev->dev,
"Failed to request irq for VBUS, "
}
mvotg->irq = r->start;
- if (request_irq(mvotg->irq, mv_otg_irq, IRQF_SHARED,
+ if (devm_request_irq(&pdev->dev, mvotg->irq, mv_otg_irq, IRQF_SHARED,
driver_name, mvotg)) {
dev_err(&pdev->dev, "Request irq %d for OTG failed\n",
mvotg->irq);
if (retval < 0) {
dev_err(&pdev->dev, "can't register transceiver, %d\n",
retval);
- goto err_free_irq;
+ goto err_disable_clk;
}
retval = sysfs_create_group(&pdev->dev.kobj, &inputs_attr_group);
if (retval < 0) {
dev_dbg(&pdev->dev,
"Can't register sysfs attr group: %d\n", retval);
- goto err_set_transceiver;
+ goto err_remove_phy;
}
spin_lock_init(&mvotg->wq_lock);
return 0;
-err_set_transceiver:
+err_remove_phy:
usb_remove_phy(&mvotg->phy);
-err_free_irq:
- free_irq(mvotg->irq, mvotg);
err_disable_clk:
- if (pdata->vbus)
- free_irq(pdata->vbus->irq, mvotg);
- if (pdata->id)
- free_irq(pdata->id->irq, mvotg);
mv_otg_disable_internal(mvotg);
-err_unmap_capreg:
- iounmap(mvotg->cap_regs);
-err_unmap_phyreg:
- iounmap(mvotg->phy_regs);
err_destroy_workqueue:
flush_workqueue(mvotg->qwork);
destroy_workqueue(mvotg->qwork);
-err_put_clk:
- for (clk_i--; clk_i >= 0; clk_i--)
- clk_put(mvotg->clk[clk_i]);
platform_set_drvdata(pdev, NULL);
- kfree(otg);
- kfree(mvotg);
return retval;
}