[PATCH 3/3] Separate out TWL4030 phy init code into its own udc_musb_platform_init() function.

10 views
Skip to first unread message

Atin Malaviya

unread,
Jan 30, 2009, 10:55:54 AM1/30/09
to beagl...@googlegroups.com
u-boot, omap3-dev-usb branch. Separated out phy init code into a platform init function.
---
drivers/usb/Makefile | 1 +
drivers/usb/twl4030-usb.c | 169 ++++++++++++++++++++++++++++++++++++++++
drivers/usb/usbdcore_musb.c | 135 +-------------------------------
include/configs/omap3_beagle.h | 1 +
include/usbdcore_musb.h | 3 +
5 files changed, 177 insertions(+), 132 deletions(-)
create mode 100644 drivers/usb/twl4030-usb.c

diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 0d31615..b56025b 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -43,6 +43,7 @@ COBJS-$(CONFIG_OMAP1510) += usbdcore_omap1510.o
COBJS-$(CONFIG_OMAP1610) += usbdcore_omap1510.o
COBJS-$(CONFIG_MPC885_FAMILY) += usbdcore_mpc8xx.o
COBJS-$(CONFIG_MUSB) += usbdcore_musb.o
+COBJS-$(CONFIG_TWL4030_USB) += twl4030-usb.o
endif

COBJS := $(COBJS-y)
diff --git a/drivers/usb/twl4030-usb.c b/drivers/usb/twl4030-usb.c
new file mode 100644
index 0000000..c4f28f9
--- /dev/null
+++ b/drivers/usb/twl4030-usb.c
@@ -0,0 +1,169 @@
+/*
+ * twl4030-usb - TWL4030 USB transceiver, talking to OMAP OTG controller
+ *
+ * (C) Copyright 2008 Atin Malaviya (atin.m...@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...@nokia.com>
+ *
+ * Author: Atin Malaviya (atin.m...@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 <common.h>
+#include <i2c.h>
+
+#define FUNC_CTRL (0x04)
+# define OPMODE_MASK (3 << 3) /* bits 3 and 4 */
+# define XCVRSELECT_MASK (3 << 0) /* bits 0 and 1 */
+#define IFC_CTRL (0x07)
+# define CARKITMODE (1 << 2)
+#define POWER_CTRL (0xAC)
+# define OTG_ENAB (1 << 5)
+#define PHY_PWR_CTRL (0xFD)
+# define PHYPWD (1 << 0)
+#define PHY_CLK_CTRL (0xFE)
+# define CLOCKGATING_EN (1 << 2)
+# define CLK32K_EN (1 << 1)
+# define REQ_PHY_DPLL_CLK (1 << 0)
+#define PHY_CLK_CTRL_STS (0xFF)
+# define PHY_DPLL_CLK (1 << 0)
+
+static int twl4030_i2c_write(u8 group, u8 reg, u8 data)
+{
+ int ret = 0;
+ ret = i2c_write(group, reg, 1, &data, 1);
+ if (ret != 0) {
+ serial_printf("TWL4030:I2C:Write[0x%x, 0x%x] Error %d\n", group, reg, ret);
+ }
+ return ret;
+}
+
+static int twl4030_i2c_read(u8 group, u8 reg, u8 *data)
+{
+ int ret = 0;
+ ret = i2c_read(group, reg, 1, data, 1);
+ if (ret != 0) {
+ serial_printf("TWL4030:I2C:Read[0x%x, 0x%x] Error %d\n", group, reg, ret);
+ }
+ return ret;
+}
+
+static int twl4030_usb_write(u8 address, u8 data)
+{
+ int ret = 0;
+ ret = twl4030_i2c_write(PWRMGT_ADDR_ID1, address, data);
+ if (ret != 0) {
+ serial_printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
+ }
+ return ret;
+}
+
+static int twl4030_usb_read(u8 address)
+{
+ u8 data;
+ int ret = 0;
+ ret = twl4030_i2c_read(PWRMGT_ADDR_ID1, address, &data);
+ if (ret == 0) {
+ ret = data;
+ } else {
+ serial_printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
+ }
+ return ret;
+}
+
+static int twl4030_usb_set_bits(u8 reg, u8 bits)
+{
+ return twl4030_usb_write(reg + 1, bits);
+}
+
+static int twl4030_usb_clear_bits(u8 reg, u8 bits)
+{
+ return twl4030_usb_write(reg + 2, bits);
+}
+
+static void twl4030_usb_ldo_init(void)
+{
+ /* Enable writing to power configuration registers */
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, PROTECT_KEY, 0xC0);
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, PROTECT_KEY, 0x0C);
+
+ /* put VUSB3V1 LDO in active state */
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB_DEDICATED2, 0);
+
+ /* input to VUSB3V1 LDO is from VBAT, not VBUS */
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB_DEDICATED1, 0x14);
+
+ /* turn on 3.1V regulator */
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB3V1_DEV_GRP, 0x20);
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB3V1_TYPE, 0);
+
+ /* turn on 1.5V regulator */
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB1V5_DEV_GRP, 0x20);
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB1V5_TYPE, 0);
+
+ /* turn on 1.8V regulator */
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB1V8_DEV_GRP, 0x20);
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB1V8_TYPE, 0);
+
+ /* disable access to power configuration registers */
+ twl4030_i2c_write(PWRMGT_ADDR_ID4, PROTECT_KEY, 0);
+}
+
+static void twl4030_phy_power(void)
+{
+ u8 pwr;
+
+ pwr = twl4030_usb_read(PHY_PWR_CTRL);
+ pwr &= ~PHYPWD;
+ twl4030_usb_write(PHY_PWR_CTRL, pwr);
+ twl4030_usb_write(PHY_CLK_CTRL,
+ twl4030_usb_read(PHY_CLK_CTRL) |
+ (CLOCKGATING_EN | CLK32K_EN));
+}
+
+int udc_musb_platform_init(void)
+{
+ unsigned long timeout;
+
+ /* twl4030 ldo init */
+ twl4030_usb_ldo_init();
+
+ /* Enable the twl4030 phy */
+ twl4030_phy_power();
+
+ /* enable DPLL to access PHY registers over I2C */
+ twl4030_usb_write(PHY_CLK_CTRL,twl4030_usb_read(PHY_CLK_CTRL) | REQ_PHY_DPLL_CLK);
+ timeout = get_timer(0) + CONFIG_SYS_HZ;
+ while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK) && get_timer(0) < timeout) {
+ udelay(10);
+ }
+ if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK)) {
+ serial_printf("Timeout setting T2 HSUSB PHY DPLL clock\n");
+ return -1;
+ }
+
+ /* Enable ULPI mode */
+ twl4030_usb_clear_bits(IFC_CTRL, CARKITMODE);
+ twl4030_usb_set_bits(POWER_CTRL, OTG_ENAB);
+ twl4030_usb_clear_bits(FUNC_CTRL,XCVRSELECT_MASK | OPMODE_MASK);
+ /* let ULPI control the DPLL clock */
+ twl4030_usb_write(PHY_CLK_CTRL,twl4030_usb_read(PHY_CLK_CTRL) & ~REQ_PHY_DPLL_CLK);
+ return 0;
+}
diff --git a/drivers/usb/usbdcore_musb.c b/drivers/usb/usbdcore_musb.c
index 89ebede..f9bc888 100644
--- a/drivers/usb/usbdcore_musb.c
+++ b/drivers/usb/usbdcore_musb.c
@@ -26,7 +26,6 @@

#include <common.h>

-#include <i2c.h>
#include <asm/io.h>
#include <asm/arch/clocks.h>
#include <asm/arch/clocks_omap3.h>
@@ -505,115 +504,6 @@ static void musb_reset(void)
do_set_address = 0;
}

-#define FUNC_CTRL (0x04)
-# define OPMODE_MASK (3 << 3) /* bits 3 and 4 */
-# define XCVRSELECT_MASK (3 << 0) /* bits 0 and 1 */
-#define IFC_CTRL (0x07)
-# define CARKITMODE (1 << 2)
-#define POWER_CTRL (0xAC)
-# define OTG_ENAB (1 << 5)
-#define PHY_PWR_CTRL (0xFD)
-# define PHYPWD (1 << 0)
-#define PHY_CLK_CTRL (0xFE)
-# define CLOCKGATING_EN (1 << 2)
-# define CLK32K_EN (1 << 1)
-# define REQ_PHY_DPLL_CLK (1 << 0)
-#define PHY_CLK_CTRL_STS (0xFF)
-# define PHY_DPLL_CLK (1 << 0)
-
-static int twl4030_i2c_write(u8 group, u8 reg, u8 data)
-{
- int ret = 0;
- ret = i2c_write(group, reg, 1, &data, 1);
- if (ret != 0) {
- serial_printf("TWL4030:I2C:Write[0x%x, 0x%x] Error %d\n", group, reg, ret);
- }
- return ret;
-}
-
-static int twl4030_i2c_read(u8 group, u8 reg, u8 *data)
-{
- int ret = 0;
- ret = i2c_read(group, reg, 1, data, 1);
- if (ret != 0) {
- serial_printf("TWL4030:I2C:Read[0x%x, 0x%x] Error %d\n", group, reg, ret);
- }
- return ret;
-}
-
-static int twl4030_usb_write(u8 address, u8 data)
-{
- int ret = 0;
- ret = twl4030_i2c_write(PWRMGT_ADDR_ID1, address, data);
- if (ret != 0) {
- serial_printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
- }
- return ret;
-}
-
-static int twl4030_usb_read(u8 address)
-{
- u8 data;
- int ret = 0;
- ret = twl4030_i2c_read(PWRMGT_ADDR_ID1, address, &data);
- if (ret == 0) {
- ret = data;
- } else {
- serial_printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
- }
- return ret;
-}
-
-static int twl4030_usb_set_bits(u8 reg, u8 bits)
-{
- return twl4030_usb_write(reg + 1, bits);
-}
-
-static int twl4030_usb_clear_bits(u8 reg, u8 bits)
-{
- return twl4030_usb_write(reg + 2, bits);
-}
-
-static void twl4030_usb_ldo_init(void)
-{
- /* Enable writing to power configuration registers */
- twl4030_i2c_write(PWRMGT_ADDR_ID4, PROTECT_KEY, 0xC0);
- twl4030_i2c_write(PWRMGT_ADDR_ID4, PROTECT_KEY, 0x0C);
-
- /* put VUSB3V1 LDO in active state */
- twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB_DEDICATED2, 0);
-
- /* input to VUSB3V1 LDO is from VBAT, not VBUS */
- twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB_DEDICATED1, 0x14);
-
- /* turn on 3.1V regulator */
- twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB3V1_DEV_GRP, 0x20);
- twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB3V1_TYPE, 0);
-
- /* turn on 1.5V regulator */
- twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB1V5_DEV_GRP, 0x20);
- twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB1V5_TYPE, 0);
-
- /* turn on 1.8V regulator */
- twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB1V8_DEV_GRP, 0x20);
- twl4030_i2c_write(PWRMGT_ADDR_ID4, VUSB1V8_TYPE, 0);
-
- /* disable access to power configuration registers */
- twl4030_i2c_write(PWRMGT_ADDR_ID4, PROTECT_KEY, 0);
-}
-
-static void twl4030_phy_power(void)
-{
- u8 pwr;
-
- pwr = twl4030_usb_read(PHY_PWR_CTRL);
- pwr &= ~PHYPWD;
- twl4030_usb_write(PHY_PWR_CTRL, pwr);
- twl4030_usb_write(PHY_CLK_CTRL,
- twl4030_usb_read(PHY_CLK_CTRL) |
- (CLOCKGATING_EN | CLK32K_EN));
-}
-
/* Public functions - called by usbdcore, usbtty, etc. */
void udc_irq(void)
{
@@ -805,34 +695,15 @@ void udc_unset_nak(int epid)
/* Start to initialize h/w stuff */
int udc_init(void)
{
- unsigned long timeout;
-
/* Clock is initialized on the board code */

/* MUSB soft-reset */
outl(2, UDC_SYSCONFIG);

- /* twl4030 ldo init */
- twl4030_usb_ldo_init();
-
- /* Enable the twl4030 phy */
- twl4030_phy_power();
-
- /* enable DPLL to access PHY registers over I2C */
- twl4030_usb_write(PHY_CLK_CTRL,twl4030_usb_read(PHY_CLK_CTRL) | REQ_PHY_DPLL_CLK);
- timeout = get_timer(0) + CONFIG_SYS_HZ;
- while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK) && get_timer(0) < timeout) {
- udelay(10);
+ if (udc_musb_platform_init()) {
+ serial_printf("udc_init: platform init failed\n");
+ return -1;
}
- if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK))
- serial_printf("Timeout setting T2 HSUSB PHY DPLL clock\n");
-
- /* Enable ULPI mode */
- twl4030_usb_clear_bits(IFC_CTRL, CARKITMODE);
- twl4030_usb_set_bits(POWER_CTRL, OTG_ENAB);
- twl4030_usb_clear_bits(FUNC_CTRL,XCVRSELECT_MASK | OPMODE_MASK);
- /* let ULPI control the DPLL clock */
- twl4030_usb_write(PHY_CLK_CTRL,twl4030_usb_read(PHY_CLK_CTRL) & ~REQ_PHY_DPLL_CLK);

outl(inl(UDC_FORCESTDBY) & ~1,UDC_FORCESTDBY); /* disable MSTANDBY */
outl(inl(UDC_SYSCONFIG) | (2<<12),UDC_SYSCONFIG); /* enable SMARTSTDBY */
diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index 214f3ff..f5c22f1 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -106,6 +106,7 @@
#define CONFIG_USB_DEVICE 1
#define CONFIG_USB_TTY 1
#define CONFIG_MUSB 1 /* Enable USB driver*/
+#define CONFIG_TWL4030_USB 1 /* Enable TWL4030 USB */

/* Allow console in serial and USB at the same time */
#define CONFIG_CONSOLE_MUX 1
diff --git a/include/usbdcore_musb.h b/include/usbdcore_musb.h
index dcaf5f6..24882dd 100644
--- a/include/usbdcore_musb.h
+++ b/include/usbdcore_musb.h
@@ -112,4 +112,7 @@ void udc_startup_events(struct usb_device_instance *device);
void udc_setup_ep(struct usb_device_instance *device, unsigned int ep,
struct usb_endpoint_instance *endpoint);

+/* platform specific initialization */
+int udc_musb_platform_init(void);
+
#endif /* __USBDCORE_MUSB_H__ */
--
1.5.6.3

Reply all
Reply to author
Forward
0 new messages