On Wed, Dec 8, 2010 at 3:53 PM, Kalliguddi, Hema <hemahk@xxxxxx> wrote: > 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. I mean pm_runime will not 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. Yes. Some of these registers are not used now. But required when OTG2.0 support is provided. >> >>> +/* to be moved to LDO */ >>> +#define MISC2 0xE5 >>> +#define CFG_LDO_PD2 0xF5 >> >> prepend with USB_ > OK. These are not the USB_OTG registers under in TWL6030 Ideally would bedefined in twl.h. I think i will move these to twl.h file. >> >>> +#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> OK. I will remove from here. >> >>> +#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