On Wed, Dec 8, 2010 at 3:20 PM, Felipe Balbi <balbi@xxxxxx> wrote: > On Wed, Dec 08, 2010 at 09:31:15PM +0530, Hema HK wrote: >> >> Adding the twl6030-usb transceiver support for OMAP4 musb driver. >> >> OMAP4 supports 2 types of transceiver interface. >> >> 1. UTMI: The PHY is embedded within OMAP4. The transceiver functionality >> is split between the twl6030 PMIC chip and OMAP4430. The VBUS, ID pin >> sensing and OTG SRP generation part is integrated in TWL6030 and UTMI PHY >> functionality is embedded within the OMAP4430. >> >> There is no direct interactions between the MUSB controller and TWL6030 >> chip to communicate the session-valid, session-end and ID-GND events. >> It has to be done through a software by setting/resetting bits in >> one of the control module register of OMAP4430 which in turn toggles >> the appropriate signals to MUSB controller. >> >> The internal transceiver has functional clocks and >> powerdown bits to powerdown the PHY for power saving. >> >> Since there is no option available for having 2 transceiver drivers >> for one USB controller, internal PHY specific APIs are passed through >> plaform_data function pointers to use in the twl6030-usb transceiver >> driver. >> >> 2. ULPI interface is provided for off-chip transceivers. >> >> Signed-off-by: Hema HK <hemahk@xxxxxx> >> Cc: Felipe Balbi <balbi@xxxxxx> >> Cc: Tony Lindgren <tony@xxxxxxxxxxx> >> Cc: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx> >> --- >> arch/arm/mach-omap2/omap_phy_internal.c | 133 ++++++++ >> arch/arm/plat-omap/include/plat/usb.h | 4 >> drivers/usb/otg/Makefile | 1 >> drivers/usb/otg/twl6030-usb.c | 514 >> ++++++++++++++++++++++++++++++++ >> 4 files changed, 652 insertions(+) >> >> Index: linux-2.6/arch/arm/mach-omap2/omap_phy_internal.c >> =================================================================== >> --- /dev/null >> +++ linux-2.6/arch/arm/mach-omap2/omap_phy_internal.c >> @@ -0,0 +1,148 @@ >> +/* >> + * This file configures the internal USB PHY in OMAP4430. Used >> + * with TWL6030 transceiver and MUSB on OMAP4430. >> + * >> + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com >> + * 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: Hema HK <hemahk@xxxxxx> > > ^^ you need a space after * OK. > >> + * 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/types.h> >> +#include <linux/errno.h> >> +#include <linux/delay.h> >> +#include <linux/clk.h> >> +#include <linux/io.h> >> +#include <linux/err.h> >> +#include <linux/usb.h> >> + >> +#include <plat/usb.h> >> + >> +/* OMAP control module register for UTMI PHY */ >> +#define CONTROL_DEV_CONF 0x300 >> +#define PHY_PD 0x1 >> + >> +#define USBOTGHS_CONTROL 0x33c >> +#define AVALID BIT(0) >> +#define BVALID BIT(1) >> +#define VBUSVALID BIT(2) >> +#define SESSEND BIT(3) >> +#define IDDIG BIT(4) >> + >> +static struct clk *phyclk, *clk48m, *clk32k; >> +static void __iomem *ctrl_base; >> + >> +int omap4430_phy_init(struct device *dev) >> +{ >> + ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K); >> + if (!ctrl_base) { >> + dev_err(dev, "control module ioremap failed\n"); >> + return -ENOMEM; >> + } >> + /* Power down the phy */ >> + __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); >> + phyclk = clk_get(dev, "ocp2scp_usb_phy_ick"); >> + >> + if (IS_ERR(phyclk)) { >> + dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n"); >> + iounmap(ctrl_base); >> + return PTR_ERR(phyclk); >> + } >> + >> + clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m"); >> + if (IS_ERR(clk48m)) { >> + dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n"); >> + clk_put(phyclk); >> + iounmap(ctrl_base); >> + return PTR_ERR(clk48m); >> + } >> + >> + clk32k = clk_get(dev, "usb_phy_cm_clk32k"); >> + if (IS_ERR(clk32k)) { >> + dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n"); >> + clk_put(phyclk); >> + clk_put(clk48m); >> + iounmap(ctrl_base); >> + return PTR_ERR(clk32k); >> + } >> + return 0; >> +} >> + >> +int omap4430_phy_set_clk(struct device *dev, int on) >> +{ >> + static int state; >> + >> + if (on && !state) { >> + /* Enable the phy clocks */ >> + clk_enable(phyclk); >> + clk_enable(clk48m); >> + clk_enable(clk32k); >> + state = 1; >> + } else if (state) { >> + /* Disable the phy clocks */ >> + clk_disable(phyclk); >> + clk_disable(clk48m); >> + clk_disable(clk32k); >> + state = 0; >> + } >> + return 0; >> +} >> + >> +int omap4430_phy_power(struct device *dev, int ID, int on) >> +{ >> + if (on) { >> + /* enabled the clocks */ >> + omap4430_phy_set_clk(dev, 1); >> + /* power on the phy */ >> + if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) { >> + __raw_writel(~PHY_PD, ctrl_base + >> CONTROL_DEV_CONF); >> + mdelay(200); >> + } >> + if (ID) >> + /* enable VBUS valid, IDDIG groung */ >> + __raw_writel(AVALID | VBUSVALID, ctrl_base + >> + USBOTGHS_CONTROL); >> + else >> + /* >> + * Enable VBUS Valid, AValid and IDDIG >> + * high impedence >> + */ >> + __raw_writel(IDDIG | AVALID | VBUSVALID, >> + ctrl_base + >> USBOTGHS_CONTROL); >> + } else { >> + /* Enable session END and IDIG to high impedence. */ >> + __raw_writel(SESSEND | IDDIG, ctrl_base + >> + USBOTGHS_CONTROL); >> + /* Disable the clocks */ >> + omap4430_phy_set_clk(dev, 0); >> + /* Power down the phy */ >> + __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); >> + } >> + >> + return 0; >> +} >> + >> +int omap4430_phy_exit(struct device *dev) >> +{ >> + if (ctrl_base) >> + iounmap(ctrl_base); >> + if (phyclk) >> + clk_put(phyclk); >> + if (clk48m) >> + clk_put(clk48m); >> + if (clk32k) >> + clk_put(clk32k); >> + >> + return 0; >> +} >> + >> + > > two blank lines at the end of file. I like to use one, but people say it > should be none :-p Fine. I will remove the blank lines. > > Anyway, can this be converted into a platform driver ? Then you could > power it on/off with pm_runtime ?!? You wouldn't need to export > functions either. > > It could be that's not possible, but doesn't hurt asking. pm_runime will take care of this as there is no device build done for PHY. This device does not have any IRQs or sysconfig registers. This device has only 2 clocks associated with it and that too these are considered as optional clocks. So using it is decided to use the clock framework for this device. > >> Index: linux-2.6/arch/arm/plat-omap/include/plat/usb.h >> =================================================================== >> --- linux-2.6.orig/arch/arm/plat-omap/include/plat/usb.h >> +++ linux-2.6/arch/arm/plat-omap/include/plat/usb.h >> @@ -79,6 +79,12 @@ extern void usb_ehci_init(const struct e >> >> extern void usb_ohci_init(const struct ohci_hcd_omap_platform_data >> *pdata); >> >> +extern int omap4430_phy_power(struct device *dev, int ID, int on); >> +extern int omap4430_phy_set_clk(struct device *dev, int on); >> +extern int omap4430_phy_init(struct device *dev); >> +extern int omap4430_phy_exit(struct device *dev); >> + >> + > > one blank line only. OK. > >> Index: linux-2.6/drivers/usb/otg/twl6030-usb.c >> =================================================================== >> --- /dev/null >> +++ linux-2.6/drivers/usb/otg/twl6030-usb.c >> @@ -0,0 +1,520 @@ >> +/* >> + * twl6030_usb - TWL6030 USB transceiver, talking to OMAP OTG driver. >> + * >> + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com >> + * 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: Hema HK <hemahk@xxxxxx> > > ^^ space OK. > >> + * 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/init.h> >> +#include <linux/interrupt.h> >> +#include <linux/platform_device.h> >> +#include <linux/io.h> >> +#include <linux/usb/otg.h> >> +#include <linux/i2c/twl.h> >> +#include <linux/regulator/consumer.h> >> +#include <linux/err.h> >> +#include <linux/notifier.h> >> +#include <linux/slab.h> >> + >> +/* usb register definitions */ >> +#define USB_VENDOR_ID_LSB 0x00 >> +#define USB_VENDOR_ID_MSB 0x01 >> +#define USB_PRODUCT_ID_LSB 0x02 >> +#define USB_PRODUCT_ID_MSB 0x03 >> +#define USB_VBUS_CTRL_SET 0x04 >> +#define USB_VBUS_CTRL_CLR 0x05 >> +#define USB_ID_CTRL_SET 0x06 >> +#define USB_ID_CTRL_CLR 0x07 >> +#define USB_VBUS_INT_SRC 0x08 >> +#define USB_VBUS_INT_LATCH_SET 0x09 >> +#define USB_VBUS_INT_LATCH_CLR 0x0A >> +#define USB_VBUS_INT_EN_LO_SET 0x0B >> +#define USB_VBUS_INT_EN_LO_CLR 0x0C >> +#define USB_VBUS_INT_EN_HI_SET 0x0D >> +#define USB_VBUS_INT_EN_HI_CLR 0x0E >> +#define USB_ID_INT_SRC 0x0F >> +#define USB_ID_INT_LATCH_SET 0x10 >> +#define USB_ID_INT_LATCH_CLR 0x11 >> + >> + >> +#define USB_ID_INT_EN_LO_SET 0x12 >> +#define USB_ID_INT_EN_LO_CLR 0x13 >> +#define USB_ID_INT_EN_HI_SET 0x14 >> +#define USB_ID_INT_EN_HI_CLR 0x15 > > I wonder why HW people didn't follow ULPI spec here. What a mess... > >> +#define USB_OTG_ADP_CTRL 0x16 >> +#define USB_OTG_ADP_HIGH 0x17 >> +#define USB_OTG_ADP_LOW 0x18 >> +#define USB_OTG_ADP_RISE 0x19 >> +#define USB_OTG_REVISION 0x1A > > ... then these would only be a set of extended registers. > >> +/* to be moved to LDO */ >> +#define MISC2 0xE5 >> +#define CFG_LDO_PD2 0xF5 > > prepend with USB_ OK. > >> +#define USB_BACKUP_REG 0xFA >> + >> +#define STS_HW_CONDITIONS 0x21 >> + >> +/* In module TWL6030_MODULE_PM_MASTER */ >> +#define PROTECT_KEY 0x0E > > defined in <linux/i2c/twl.h> > >> +#define STS_HW_CONDITIONS 0x21 >> +#define STS_USB_ID BIT(2) >> + >> +/* In module TWL6030_MODULE_PM_RECEIVER */ >> +#define VUSB_DEDICATED1 0x7D >> +#define VUSB_DEDICATED2 0x7E >> +#define VUSB1V5_DEV_GRP 0x71 >> +#define VUSB1V5_TYPE 0x72 >> +#define VUSB1V5_REMAP 0x73 >> +#define VUSB1V8_DEV_GRP 0x74 >> +#define VUSB1V8_TYPE 0x75 >> +#define VUSB1V8_REMAP 0x76 >> +#define VUSB3V1_DEV_GRP 0x77 >> +#define VUSB3V1_TYPE 0x78 >> +#define VUSB3V1_REMAP 0x79 >> + >> +/* In module TWL6030_MODULE_PM_RECEIVER */ >> +#define VUSB_CFG_TRANS 0x71 >> +#define VUSB_CFG_STATE 0x72 >> +#define VUSB_CFG_VOLTAGE 0x73 >> + >> +/* in module TWL6030_MODULE_MAIN_CHARGE */ >> + >> +#define CHARGERUSB_CTRL1 0x8 >> + >> +#define CONTROLLER_STAT1 0x03 >> +#define VBUS_DET BIT(2) >> + >> + >> +/* OMAP control module register for UTMI PHY */ >> +#define ONTROL_DEV_CONF 0x300 > > did you mean CONTROL ?? I need to remove this from this file as these are not used here. > >> +#define PHY_PD 0x1 >> + >> +#define USBOTGHS_CONTROL 0x33c >> +#define AVALID BIT(0) >> +#define BVALID BIT(1) >> +#define VBUSVALID BIT(2) >> +#define SESSEND BIT(3) >> +#define IDDIG BIT(4) > > these are likely to give namespace colision at some point, append with > USB_ or better change USB_ to TWL6030_USB_ These are not required so i will remove them. > >> +static int __devinit twl6030_usb_probe(struct platform_device *pdev) >> +{ >> + struct twl6030_usb *twl; >> + int status, err; >> + struct twl4030_usb_data *pdata; >> + struct device *dev = &pdev->dev; >> + pdata = dev->platform_data; >> + >> + twl = kzalloc(sizeof *twl, GFP_KERNEL); >> + if (!twl) >> + return -ENOMEM; >> + >> + twl->dev = &pdev->dev; >> + twl->irq1 = platform_get_irq(pdev, 0); >> + twl->irq2 = platform_get_irq(pdev, 1); >> + twl->otg.dev = twl->dev; >> + twl->otg.label = "twl6030"; >> + twl->otg.set_host = twl6030_set_host; >> + twl->otg.set_peripheral = twl6030_set_peripheral; >> + twl->asleep = 1; > > better to read this from HW and avoid problems if bootloaders wakes this > one up. I don'e need this anymore. > > -- > balbi > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html