On Wed, May 30, 2012 at 8:04 PM, Kishon Vijay Abraham I <kishon@xxxxxx> wrote: > All phy related programming like enabling/disabling the clocks, powering > on/off the phy is taken care of by this driver. It is also used for OTG > related functionality like srp. > > Cc: Felipe Balbi <balbi@xxxxxx> > Signed-off-by: Kishon Vijay Abraham I <kishon@xxxxxx> > --- > drivers/usb/otg/Kconfig | 17 ++- > drivers/usb/otg/Makefile | 1 + > drivers/usb/otg/omap-usb2.c | 232 +++++++++++++++++++++++++++++++++++++ > include/linux/usb/omap_usb.h | 47 ++++++++ > include/linux/usb/phy_companion.h | 34 ++++++ > 5 files changed, 327 insertions(+), 4 deletions(-) > create mode 100644 drivers/usb/otg/omap-usb2.c > create mode 100644 include/linux/usb/omap_usb.h > create mode 100644 include/linux/usb/phy_companion.h > [...] > diff --git a/drivers/usb/otg/omap-usb2.c b/drivers/usb/otg/omap-usb2.c > new file mode 100644 > index 0000000..ccd74b6 > --- /dev/null > +++ b/drivers/usb/otg/omap-usb2.c > @@ -0,0 +1,232 @@ > +/* > + * omap-usb2.c - USB PHY, talking to musb controller in OMAP. > + * > + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com s/2011/2012 > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * Author: Kishon Vijay Abraham I <kishon@xxxxxx> > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > + * > + */ > + > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/slab.h> > +#include <linux/of.h> > +#include <linux/usb/omap_usb.h> > +#include <linux/usb/phy_companion.h> > +#include <linux/clk.h> > +#include <linux/err.h> > +#include <linux/pm_runtime.h> > +#include <linux/delay.h> Do you need it ? > +#include <linux/mfd/omap_control.h> > +#include <linux/usb/omap4_usb_phy.h> > + > +/** > + * omap_usb2_set_comparator - links the comparator present in the sytem with > + * this phy > + * @comparator - the companion phy(comparator) for this phy > + * > + * The phy companion driver should call this API passing the phy_companion > + * filled with set_vbus and start_srp to be used by usb phy. > + * > + * For use by phy companion driver > + */ > +void omap_usb2_set_comparator(struct phy_companion *comparator) > +{ > + struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2); > + struct omap_usb *phy = phy_to_omapusb(x); > + > + phy->comparator = comparator; > +} > +EXPORT_SYMBOL_GPL(omap_usb2_set_comparator); > + > +static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled) > +{ > + struct omap_usb *phy = phy_to_omapusb(otg->phy); > + > + if (!phy->comparator) > + return -ENODEV; > + > + return phy->comparator->set_vbus(phy->comparator, enabled); > +} > + > +static int omap_usb_start_srp(struct usb_otg *otg) > +{ > + struct omap_usb *phy = phy_to_omapusb(otg->phy); > + > + if (!phy->comparator) > + return -ENODEV; > + > + return phy->comparator->start_srp(phy->comparator); > +} > + > +static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host) > +{ > + struct usb_phy *phy = otg->phy; > + > + otg->host = host; > + if (!host) > + phy->state = OTG_STATE_UNDEFINED; > + > + return 0; > +} > + > +static int omap_usb_set_peripheral(struct usb_otg *otg, > + struct usb_gadget *gadget) > +{ > + struct usb_phy *phy = otg->phy; > + > + otg->gadget = gadget; > + if (!gadget) > + phy->state = OTG_STATE_UNDEFINED; > + > + return 0; > +} > + > +static int omap_usb2_suspend(struct usb_phy *x, int suspend) > +{ > + struct omap_usb *phy = phy_to_omapusb(x); > + > + if (suspend && !phy->is_suspended) { > + pm_runtime_put_sync(phy->dev); > + phy->is_suspended = 1; > + } else if (!suspend && phy->is_suspended) { > + pm_runtime_get_sync(phy->dev); > + phy->is_suspended = 0; > + } > + > + return 0; > +} > + > +static int __devinit omap_usb2_probe(struct platform_device *pdev) > +{ > + struct omap_usb *phy; > + struct usb_otg *otg; > + > + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); > + if (!phy) { > + dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); > + return -ENOMEM; > + } > + > + otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); > + if (!otg) { > + dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n"); > + return -ENOMEM; > + } > + > + phy->dev = &pdev->dev; > + > + phy->phy.dev = phy->dev; > + phy->phy.label = "omap-usb2"; > + phy->phy.set_suspend = omap_usb2_suspend; > + phy->phy.otg = otg; > + > + phy->control_dev = omap_control_get(); > + if (IS_ERR(phy->control_dev)) { > + dev_err(&pdev->dev, "no control device present in system\n"); > + return PTR_ERR(phy->control_dev); > + } > + > + phy->is_suspended = 1; > + omap4_usb_phy_power(phy->control_dev, 0); > + > + otg->set_host = omap_usb_set_host; > + otg->set_peripheral = omap_usb_set_peripheral; > + otg->set_vbus = omap_usb_set_vbus; > + otg->start_srp = omap_usb_start_srp; > + otg->phy = &phy->phy; > + > + phy->wkupclk = clk_get(phy->dev, "usb_phy_cm_clk32k"); Error check missing here. > + > + usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2); > + unnecessary extra line > + platform_set_drvdata(pdev, phy); > + this one too > + pm_runtime_enable(phy->dev); > + > + return 0; > +} > + > +static int __devexit omap_usb2_remove(struct platform_device *pdev) > +{ > + struct omap_usb *phy = platform_get_drvdata(pdev); > + > + usb_remove_phy(&phy->phy); > + platform_set_drvdata(pdev, NULL); > + > + return 0; > +} > + > +#ifdef CONFIG_PM s/ CONFIG_PM/CONFIG_SUSPEND otherwise you will get build warning with !CONFIG_SUSPEND > + > +static int omap_usb2_runtime_suspend(struct device *dev) > +{ > + struct platform_device *pdev = to_platform_device(dev); > + struct omap_usb *phy = platform_get_drvdata(pdev); > + > + clk_disable(phy->wkupclk); > + omap4_usb_phy_power(phy->control_dev, 0); > + > + return 0; > +} > + > +static int omap_usb2_runtime_resume(struct device *dev) > +{ > + struct platform_device *pdev = to_platform_device(dev); > + struct omap_usb *phy = platform_get_drvdata(pdev); > + > + omap4_usb_phy_power(phy->control_dev, 1); > + clk_enable(phy->wkupclk); > + > + return 0; > +} > + > +static const struct dev_pm_ops omap_usb2_pm_ops = { > + SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume, > + NULL) > +}; > + > +#define DEV_PM_OPS (&omap_usb2_pm_ops) > +#else > +#define DEV_PM_OPS NULL > +#endif > + > +static struct platform_driver omap_usb2_driver = { > + .probe = omap_usb2_probe, > + .remove = __devexit_p(omap_usb2_remove), > + .driver = { > + .name = "omap-usb2", > + .owner = THIS_MODULE, > + .pm = DEV_PM_OPS, > + }, > +}; > + > +static int __init usb2_omap_init(void) > +{ > + return platform_driver_register(&omap_usb2_driver); > +} > +arch_initcall(usb2_omap_init); > + > +static void __exit usb2_omap_exit(void) > +{ > + platform_driver_unregister(&omap_usb2_driver); > +} > +module_exit(usb2_omap_exit); > + > +MODULE_ALIAS("platform: omap_usb2"); > +MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@xxxxxx>"); > +MODULE_DESCRIPTION("OMAP USB2 PHY DRIVER"); > +MODULE_LICENSE("GPL"); > diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h > new file mode 100644 > index 0000000..8d781df > --- /dev/null > +++ b/include/linux/usb/omap_usb.h > @@ -0,0 +1,47 @@ > +/* > + * omap_usb.h -- omap usb2 phy header file > + * > + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com s/2011/2012 > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * Author: Kishon Vijay Abraham I <kishon@xxxxxx> > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. > + * > + */ > + > +#ifndef __DRIVERS_OMAP_USB2_H > +#define __DRIVERS_OMAP_USB2_H > + > +#include <linux/usb/otg.h> > + > +struct omap_usb { > + struct usb_phy phy; > + struct phy_companion *comparator; > + struct device *dev; > + struct device *control_dev; > + struct clk *wkupclk; > + u8 is_suspended:1; > +}; > + > +#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy) > + > +#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE) > +void omap_usb2_set_comparator(struct phy_companion *comparator); > +#else > +static inline void omap_usb2_set_comparator(struct phy_companion *comparator) > +{ > +} > +#endif > + > +#endif /* __DRIVERS_OMAP_USB_H */ > diff --git a/include/linux/usb/phy_companion.h b/include/linux/usb/phy_companion.h > new file mode 100644 > index 0000000..321290f > --- /dev/null > +++ b/include/linux/usb/phy_companion.h > @@ -0,0 +1,34 @@ > +/* > + * phy-companion.h -- phy companion to indicate the comparator part of PHY > + * > + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com Here too.. Regards Santosh -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html