TWL4030 Add usb PHY support
authorTom Rix <Tom.Rix@windriver.com>
Sat, 31 Oct 2009 17:37:40 +0000 (12:37 -0500)
committerRemy Bohmer <linux@bohmer.net>
Sun, 20 Dec 2009 11:47:37 +0000 (12:47 +0100)
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
drivers/usb/phy/Makefile [new file with mode: 0644]
drivers/usb/phy/twl4030.c [new file with mode: 0644]
include/twl4030.h

index 536ccb3e32fc33cd3d47d8e16d7cb92c6f9cc1ae..b3ab8b3c1c2dafe7a4c0c8da0e8c93ab9d39d7e2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -243,6 +243,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 (file)
index 0000000..200b907
--- /dev/null
@@ -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 (file)
index 0000000..54d2e61
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * 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@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@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;
+
+       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;
+
+       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;
+}
+
+static void twl4030_usb_ldo_init(void)
+{
+       /* Enable writing to power configuration registers */
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0xC0,
+                            TWL4030_PM_MASTER_PROTECT_KEY);
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x0C,
+                            TWL4030_PM_MASTER_PROTECT_KEY);
+
+       /* put VUSB3V1 LDO in active state */
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+                            TWL4030_PM_RECEIVER_VUSB_DEDICATED2);
+
+       /* input to VUSB3V1 LDO is from VBAT, not VBUS */
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x14,
+                            TWL4030_PM_RECEIVER_VUSB_DEDICATED1);
+
+       /* turn on 3.1V regulator */
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+                            TWL4030_PM_RECEIVER_VUSB3V1_DEV_GRP);
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+                            TWL4030_PM_RECEIVER_VUSB3V1_TYPE);
+
+       /* turn on 1.5V regulator */
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+                            TWL4030_PM_RECEIVER_VUSB1V5_DEV_GRP);
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+                            TWL4030_PM_RECEIVER_VUSB1V5_TYPE);
+
+       /* turn on 1.8V regulator */
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+                            TWL4030_PM_RECEIVER_VUSB1V8_DEV_GRP);
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+                            TWL4030_PM_RECEIVER_VUSB1V8_TYPE);
+
+       /* disable access to power configuration registers */
+       twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x00,
+                            TWL4030_PM_MASTER_PROTECT_KEY);
+}
+
+static void twl4030_phy_power(void)
+{
+       u8 pwr, clk;
+
+       /* Power the PHY */
+       pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL);
+       pwr &= ~PHYPWD;
+       twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr);
+       /* 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;
+       }
+
+       /* 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);
+
+       /* Clear the opmode bits to ensure normal encode */
+       twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK);
+
+       /* 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;
+}
index f260ecb8b12ad565c651a9512073c0eff7493249..feaec47b36afd512d132bfe68dce84a026d671e5 100644 (file)
 #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)
+#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
+#define TWL4030_USB_MCPC_IO_CTRL_CLR                   0x35
+#define TWL4030_USB_MCPC_CTRL2                         0x36
+#define TWL4030_USB_MCPC_CTRL2_SET                     0x37
+#define TWL4030_USB_MCPC_CTRL2_CLR                     0x38
+#define TWL4030_USB_OTHER_FUNC_CTRL                    0x80
+#define TWL4030_USB_OTHER_FUNC_CTRL_SET                        0x81
+#define TWL4030_USB_OTHER_FUNC_CTRL_CLR                        0x82
+#define TWL4030_USB_OTHER_IFC_CTRL                     0x83
+#define TWL4030_USB_OTHER_IFC_CTRL_SET                 0x84
+#define TWL4030_USB_OTHER_IFC_CTRL_CLR                 0x85
+#define TWL4030_USB_OTHER_INT_EN_RISE_SET              0x87
+#define TWL4030_USB_OTHER_INT_EN_RISE_CLR              0x88
+#define TWL4030_USB_OTHER_INT_EN_FALL                  0x89
+#define TWL4030_USB_OTHER_INT_EN_FALL_SET              0x8A
+#define TWL4030_USB_OTHER_INT_EN_FALL_CLR              0x8B
+#define TWL4030_USB_OTHER_INT_STS                      0x8C
+#define TWL4030_USB_OTHER_INT_LATCH                    0x8D
+#define TWL4030_USB_ID_STATUS                          0x96
+#define TWL4030_USB_CARKIT_SM_1_INT_EN                 0x97
+#define TWL4030_USB_CARKIT_SM_1_INT_EN_SET             0x98
+#define TWL4030_USB_CARKIT_SM_1_INT_EN_CLR             0x99
+#define TWL4030_USB_CARKIT_SM_1_INT_STS                        0x9A
+#define TWL4030_USB_CARKIT_SM_1_INT_LATCH              0x9B
+#define TWL4030_USB_CARKIT_SM_2_INT_EN                 0x9C
+#define TWL4030_USB_CARKIT_SM_2_INT_EN_SET             0x9D
+#define TWL4030_USB_CARKIT_SM_2_INT_EN_CLR             0x9E
+#define TWL4030_USB_CARKIT_SM_2_INT_STS                        0x9F
+#define TWL4030_USB_CARKIT_SM_2_INT_LATCH              0xA0
+#define TWL4030_USB_CARKIT_SM_CTRL                     0xA1
+#define TWL4030_USB_CARKIT_SM_CTRL_SET                 0xA2
+#define TWL4030_USB_CARKIT_SM_CTRL_CLR                 0xA3
+#define TWL4030_USB_CARKIT_SM_CMD                      0xA4
+#define TWL4030_USB_CARKIT_SM_CMD_SET                  0xA5
+#define TWL4030_USB_CARKIT_SM_CMD_CLR                  0xA6
+#define TWL4030_USB_CARKIT_SM_CMD_STS                  0xA7
+#define TWL4030_USB_CARKIT_SM_STATUS                   0xA8
+#define TWL4030_USB_CARKIT_SM_ERR_STATUS               0xAA
+#define TWL4030_USB_CARKIT_SM_CTRL_STATE               0xAB
+#define TWL4030_USB_POWER_CTRL                         0xAC
+#define TWL4030_USB_POWER_CTRL_SET                     0xAD
+#define TWL4030_USB_POWER_CTRL_CLR                     0xAE
+#define TWL4030_USB_OTHER_IFC_CTRL2                    0xAF
+#define TWL4030_USB_OTHER_IFC_CTRL2_SET                        0xB0
+#define TWL4030_USB_OTHER_IFC_CTRL2_CLR                        0xB1
+#define TWL4030_USB_REG_CTRL_EN                                0xB2
+#define TWL4030_USB_REG_CTRL_EN_SET                    0xB3
+#define TWL4030_USB_REG_CTRL_EN_CLR                    0xB4
+#define TWL4030_USB_REG_CTRL_ERROR                     0xB5
+#define TWL4030_USB_OTHER_FUNC_CTRL2                   0xB8
+#define TWL4030_USB_OTHER_FUNC_CTRL2_SET               0xB9
+#define TWL4030_USB_OTHER_FUNC_CTRL2_CLR               0xBA
+#define TWL4030_USB_CARKIT_ANA_CTRL                    0xBB
+#define TWL4030_USB_CARKIT_ANA_CTRL_SET                        0xBC
+#define TWL4030_USB_CARKIT_ANA_CTRL_CLR                        0xBD
+#define TWL4030_USB_VBUS_DEBOUNCE                      0xC0
+#define TWL4030_USB_ID_DEBOUNCE                                0xC1
+#define TWL4030_USB_TPH_DP_CON_MIN                     0xC2
+#define TWL4030_USB_TPH_DP_CON_MAX                     0xC3
+#define TWL4030_USB_TCR_DP_CON_MIN                     0xC4
+#define TWL4030_USB_TCR_DP_CON_MAX                     0xC5
+#define TWL4030_USB_TPH_DP_PD_SHORT                    0xC6
+#define TWL4030_USB_TPH_CMD_DLY                                0xC7
+#define TWL4030_USB_TPH_DET_RST                                0xC8
+#define TWL4030_USB_TPH_AUD_BIAS                       0xC9
+#define TWL4030_USB_TCR_UART_DET_MIN                   0xCA
+#define TWL4030_USB_TCR_UART_DET_MAX                   0xCB
+#define TWL4030_USB_TPH_ID_INT_PW                      0xCD
+#define TWL4030_USB_TACC_ID_INT_WAIT                   0xCE
+#define TWL4030_USB_TACC_ID_INT_PW                     0xCF
+#define TWL4030_USB_TPH_CMD_WAIT                       0xD0
+#define TWL4030_USB_TPH_ACK_WAIT                       0xD1
+#define TWL4030_USB_TPH_DP_DISC_DET                    0xD2
+#define TWL4030_USB_VBAT_TIMER                         0xD3
+#define TWL4030_USB_CARKIT_4W_DEBUG                    0xE0
+#define TWL4030_USB_CARKIT_5W_DEBUG                    0xE1
+#define TWL4030_USB_PHY_PWR_CTRL                       0xFD
+#define TWL4030_USB_PHY_CLK_CTRL                       0xFE
+#define TWL4030_USB_PHY_CLK_CTRL_STS                   0xFF
 
 /*
  * Convience functions to read and write from TWL4030
@@ -398,4 +506,9 @@ void twl4030_power_mmc_init(void);
  */
 void twl4030_led_init(void);
 
+/*
+ * USB
+ */
+int twl4030_usb_ulpi_init(void);
+
 #endif /* TWL4030_H */