[U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support

Jean-Christophe PLAGNIOL-VILLARD
2009-09-05T00:02:56Z

On 15:12 Fri 04 Sep , Tom Rix wrote:
> The twl4030 provides a PHY device for connecting a link device,
> like musb, to physical connection.
>
> This change adds the twl4030 usb registers and functions for
> initializing the PHY as required by omap3.
>
> Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
> ---
> Makefile | 1 +
> drivers/usb/phy/Makefile | 44 +++++++++++
> drivers/usb/phy/twl4030.c | 184 +++++++++++++++++++++++++++++++++++++++++++++
> include/twl4030.h | 143 +++++++++++++++++++++++++++++++----
> 4 files changed, 357 insertions(+), 15 deletions(-)
> create mode 100644 drivers/usb/phy/Makefile
> create mode 100644 drivers/usb/phy/twl4030.c
>
> diff --git a/Makefile b/Makefile
> index 329e0f5..dcaa1dc 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -241,6 +241,7 @@ LIBS += drivers/twserial/libtws.a
> LIBS += drivers/usb/gadget/libusb_gadget.a
> LIBS += drivers/usb/host/libusb_host.a
> LIBS += drivers/usb/musb/libusb_musb.a
> +LIBS += drivers/usb/phy/libusb_phy.a
> LIBS += drivers/video/libvideo.a
> LIBS += drivers/watchdog/libwatchdog.a
> LIBS += common/libcommon.a
> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
> new file mode 100644
> index 0000000..200b907
> --- /dev/null
> +++ b/drivers/usb/phy/Makefile
> @@ -0,0 +1,44 @@
> +#
> +# Copyright (c) 2009 Wind River Systems, Inc.
> +# Tom Rix <Tom.Rix@windriver.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.
> +#
> +# 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., 59 Temple Place, Suite 330, Boston,
> +# MA 02111-1307 USA
> +#
> +
> +include $(TOPDIR)/config.mk
> +
> +LIB := $(obj)libusb_phy.a
> +
> +COBJS-$(CONFIG_TWL4030_USB) += twl4030.o
> +COBJS-y := twl4030.o
> +
> +COBJS := $(COBJS-y)
> +SRCS := $(COBJS:.o=.c)
> +OBJS := $(addprefix $(obj),$(COBJS))
> +
> +all: $(LIB)
> +
> +$(LIB): $(obj).depend $(OBJS)
> + $(AR) $(ARFLAGS) $@ $(OBJS)
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/drivers/usb/phy/twl4030.c b/drivers/usb/phy/twl4030.c
> new file mode 100644
> index 0000000..32f1df3
> --- /dev/null
> +++ b/drivers/usb/phy/twl4030.c
> @@ -0,0 +1,184 @@
> +/*
> + * Copyright (c) 2009 Wind River Systems, Inc.
> + * Tom Rix <Tom.Rix@windriver.com>
> + *
> + * This is file is based on
> + * repository git.gitorious.org/u-boot-omap3/mainline.git,
> + * branch omap3-dev-usb, file drivers/usb/gadget/twl4030_usb.c
> + *
> + * This is the unique part of its copyright :
> + *
> + * ------------------------------------------------------------------------
> + *
> + * * (C) Copyright 2009 Atin Malaviya (atin.malaviya at gmail.com)
> + *
> + * Based on: twl4030_usb.c in linux 2.6 (drivers/i2c/chips/twl4030_usb.c)
> + * Copyright (C) 2004-2007 Texas Instruments
> + * Copyright (C) 2008 Nokia Corporation
> + * Contact: Felipe Balbi <felipe.balbi@nokia.com>
> + *
> + * Author: Atin Malaviya (atin.malaviya at gmail.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.
> + *
> + * 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., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#include <twl4030.h>
> +
> +/* Defines for bits in registers */
> +#define OPMODE_MASK (3 << 3)
> +#define XCVRSELECT_MASK (3 << 0)
> +#define CARKITMODE (1 << 2)
> +#define OTG_ENAB (1 << 5)
> +#define PHYPWD (1 << 0)
> +#define CLOCKGATING_EN (1 << 2)
> +#define CLK32K_EN (1 << 1)
> +#define REQ_PHY_DPLL_CLK (1 << 0)
> +#define PHY_DPLL_CLK (1 << 0)
> +
> +static int twl4030_usb_write(u8 address, u8 data)
> +{
> + int ret;
please add an empty line
> + ret = twl4030_i2c_write_u8(TWL4030_CHIP_USB, data, address);
> + if (ret != 0)
> + printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
> +
> + return ret;
> +}
> +
> +static int twl4030_usb_read(u8 address)
> +{
> + u8 data;
> + int ret;
please add an empty line
> + ret = twl4030_i2c_read_u8(TWL4030_CHIP_USB, &data, address);

> + if (ret == 0)
> + ret = data;
> + else
> + printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
> +
> + return ret;
why not this and avoid the copy of data
if (ret != 0) {
printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
return ret;
}

return data;
}

> +
> +static void twl4030_phy_power(void)
> +{
> + u8 pwr, clk;
please add an empty line
> + /* Power the PHY */
> + pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL);
> + pwr &= ~PHYPWD;
> + twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr);
please add an empty line to make it more readable
> + /* Enable clocks */
> + clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
> + clk |= CLOCKGATING_EN | CLK32K_EN;
> + twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
> +}
> +
> +/*
> + * Initiaze the ULPI interface
> + * ULPI : Universal Transceiver Macrocell Low Pin Interface
> + * An interface between the USB link controller like musb and the
> + * the PHY or transceiver that drives the actual bus.
> + */
> +int twl4030_usb_ulpi_init(void)
> +{
> + long timeout = 1000 * 1000; /* 1 sec */;
> + u8 clk, sts, pwr;
> +
> + /* twl4030 ldo init */
> + twl4030_usb_ldo_init();
> +
> + /* Enable the twl4030 phy */
> + twl4030_phy_power();
> +
> + /* Enable DPLL to access PHY registers over I2C */
> + clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
> + clk |= REQ_PHY_DPLL_CLK;
> + twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
> +
> + /* Check if the PHY DPLL is locked */
> + sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
> + while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
> + udelay(10);
> + sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
> + timeout -= 10;
> + }
why not set time to 100 * 1000
and just decrease by 1
> +
> + /* Final check */
> + sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
> + if (!(sts & PHY_DPLL_CLK)) {
> + printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n");
> + return -1;
> + }
> +
> + /*
> + * There are two circuit blocks attached to the PHY,
> + * Carkit and USB OTG. Disable Carkit and enable USB OTG
> + */
> + twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE);
> + pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL);
> + pwr |= OTG_ENAB;
> + twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr);
please add an empty line to make it more readable
> + /* Clear the opmode bits to ensure normal encode */
> + twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK);
please add an empty line to make it more readable
> + /* Clear the xcvrselect bits to enable the high speed transeiver */
> + twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK);
> +
> + /* Let ULPI control the DPLL clock */
> + clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
> + clk &= ~REQ_PHY_DPLL_CLK;
> + twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
> +
> + return 0;
> +}
> diff --git a/include/twl4030.h b/include/twl4030.h
> index f260ecb..feaec47 100644
> --- a/include/twl4030.h
> +++ b/include/twl4030.h
> @@ -342,21 +342,129 @@
> #define TWL4030_KEYPAD_CTRL_SOFT_NRST (1 << 0)
>
> /* USB */
> -#define TWL4030_USB_FUNC_CTRL (0x04)
> -#define TWL4030_USB_OPMODE_MASK (3 << 3)
> -#define TWL4030_USB_XCVRSELECT_MASK (3 << 0)
> -#define TWL4030_USB_IFC_CTRL (0x07)
> -#define TWL4030_USB_CARKITMODE (1 << 2)
> -#define TWL4030_USB_POWER_CTRL (0xAC)
> -#define TWL4030_USB_OTG_ENAB (1 << 5)
> -#define TWL4030_USB_PHY_PWR_CTRL (0xFD)
> -#define TWL4030_USB_PHYPWD (1 << 0)
> -#define TWL4030_USB_PHY_CLK_CTRL (0xFE)
> -#define TWL4030_USB_CLOCKGATING_EN (1 << 2)
> -#define TWL4030_USB_CLK32K_EN (1 << 1)
> -#define TWL4030_USB_REQ_PHY_DPLL_CLK (1 << 0)
> -#define TWL4030_USB_PHY_CLK_CTRL_STS (0xFF)
> -#define TWL4030_USB_PHY_DPLL_CLK (1 << 0)
make some enums by group of function will be better as it simplify the code
> +#define TWL4030_USB_VENDOR_ID_LO 0x00
> +#define TWL4030_USB_VENDOR_ID_HI 0x01
> +#define TWL4030_USB_PRODUCT_ID_LO 0x02
> +#define TWL4030_USB_PRODUCT_ID_HI 0x03
> +#define TWL4030_USB_FUNC_CTRL 0x04
> +#define TWL4030_USB_FUNC_CTRL_SET 0x05
> +#define TWL4030_USB_FUNC_CTRL_CLR 0x06
> +#define TWL4030_USB_IFC_CTRL 0x07
> +#define TWL4030_USB_IFC_CTRL_SET 0x08
> +#define TWL4030_USB_IFC_CTRL_CLR 0x09
> +#define TWL4030_USB_OTG_CTRL 0x0A
> +#define TWL4030_USB_OTG_CTRL_SET 0x0B
> +#define TWL4030_USB_OTG_CTRL_CLR 0x0C
> +#define TWL4030_USB_USB_INT_EN_RISE 0x0D
> +#define TWL4030_USB_USB_INT_EN_RISE_SET 0x0E
> +#define TWL4030_USB_USB_INT_EN_RISE_CLR 0x0F
> +#define TWL4030_USB_USB_INT_EN_FALL 0x10
> +#define TWL4030_USB_USB_INT_EN_FALL_SET 0x11
> +#define TWL4030_USB_USB_INT_EN_FALL_CLR 0x12
> +#define TWL4030_USB_USB_INT_STS 0x13
> +#define TWL4030_USB_USB_INT_LATCH 0x14
> +#define TWL4030_USB_DEBUG 0x15
> +#define TWL4030_USB_SCRATCH_REG 0x16
> +#define TWL4030_USB_SCRATCH_REG_SET 0x17
> +#define TWL4030_USB_SCRATCH_REG_CLR 0x18
> +#define TWL4030_USB_CARKIT_CTRL 0x19
> +#define TWL4030_USB_CARKIT_CTRL_SET 0x1A
> +#define TWL4030_USB_CARKIT_CTRL_CLR 0x1B
> +#define TWL4030_USB_CARKIT_INT_DELAY 0x1C
> +#define TWL4030_USB_CARKIT_INT_EN 0x1D
> +#define TWL4030_USB_CARKIT_INT_EN_SET 0x1E
> +#define TWL4030_USB_CARKIT_INT_EN_CLR 0x1F
> +#define TWL4030_USB_CARKIT_INT_STS 0x20
> +#define TWL4030_USB_CARKIT_INT_LATCH 0x21
> +#define TWL4030_USB_CARKIT_PLS_CTRL 0x22
> +#define TWL4030_USB_CARKIT_PLS_CTRL_SET 0x23
> +#define TWL4030_USB_CARKIT_PLS_CTRL_CLR 0x24
> +#define TWL4030_USB_TRANS_POS_WIDTH 0x25
> +#define TWL4030_USB_TRANS_NEG_WIDTH 0x26
> +#define TWL4030_USB_RCV_PLTY_RECOVERY 0x27
> +#define TWL4030_USB_MCPC_CTRL 0x30
> +#define TWL4030_USB_MCPC_CTRL_SET 0x31
> +#define TWL4030_USB_MCPC_CTRL_CLR 0x32
> +#define TWL4030_USB_MCPC_IO_CTRL 0x33
> +#define TWL4030_USB_MCPC_IO_CTRL_SET 0x34

Best Regards,
J.