Re: [PATCH 2/7] usb: otg: Adding twl6030-usb transceiver driver for

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux