On Wed, Dec 8, 2010 at 3:53 PM, Kalliguddi, Hema <[email protected]> wrote:
> On Wed, Dec 8, 2010 at 3:20 PM, Felipe Balbi <[email protected]> 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 <[email protected]>
>>> Cc: Felipe Balbi <[email protected]>
>>> Cc: Tony Lindgren <[email protected]>
>>> Cc: David Brownell <[email protected]>
>>> ---
>>> 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 <[email protected]>
>>
>> ^^ 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 <[email protected]>
>>
>> ^^ 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-omap" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html