[PATCH 1/5] usb/otg/ulpi: extend the generic ulpi driver.

Igor Grinberg grinberg at compulab.co.il
Wed Jun 2 03:40:46 EDT 2010


This patch extends the generic ulpi driver with support for
Function and Interface control of upli phy.

Signed-off-by: Igor Grinberg <grinberg at compulab.co.il>
Signed-off-by: Mike Rapoport <mike at compulab.co.il>
---
 arch/arm/mach-mx2/mach-pca100.c       |   10 ++++-
 arch/arm/mach-mx3/mach-armadillo5x0.c |   10 ++++-
 arch/arm/mach-mx3/mach-mx31lite.c     |    5 ++-
 arch/arm/mach-mx3/mach-mx31moboard.c  |    5 ++-
 arch/arm/mach-mx3/mach-pcm037.c       |   10 ++++-
 arch/arm/mach-mx3/mach-pcm043.c       |    5 ++-
 drivers/usb/otg/Kconfig               |    2 -
 drivers/usb/otg/ulpi.c                |   64 +++++++++++++++++++++++++++++----
 include/linux/usb/ulpi.h              |   25 ++++++++++++-
 9 files changed, 117 insertions(+), 19 deletions(-)

diff --git a/arch/arm/mach-mx2/mach-pca100.c b/arch/arm/mach-mx2/mach-pca100.c
index 778fff2..0f2ece0 100644
--- a/arch/arm/mach-mx2/mach-pca100.c
+++ b/arch/arm/mach-mx2/mach-pca100.c
@@ -356,13 +356,19 @@ static void __init pca100_init(void)
 #if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+						USB_OTG_DRV_VBUS |
+						USB_OTG_DRV_VBUS_EXT,
+						ULPI_IC_DEFAULT,
+						ULPI_FC_DEFAULT);
 
 		mxc_register_device(&mxc_otg_host, &otg_pdata);
 	}
 
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+					  USB_OTG_DRV_VBUS |
+					  USB_OTG_DRV_VBUS_EXT,
+					  ULPI_IC_DEFAULT,
+					  ULPI_FC_DEFAULT);
 
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 #endif
diff --git a/arch/arm/mach-mx3/mach-armadillo5x0.c b/arch/arm/mach-mx3/mach-armadillo5x0.c
index 5f72ec9..81904d4 100644
--- a/arch/arm/mach-mx3/mach-armadillo5x0.c
+++ b/arch/arm/mach-mx3/mach-armadillo5x0.c
@@ -552,9 +552,15 @@ static void __init armadillo5x0_init(void)
 	/* USB */
 #if defined(CONFIG_USB_ULPI)
 	usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+					   USB_OTG_DRV_VBUS |
+					   USB_OTG_DRV_VBUS_EXT,
+					   ULPI_IC_DEFAULT,
+					   ULPI_FC_DEFAULT);
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+					  USB_OTG_DRV_VBUS |
+					  USB_OTG_DRV_VBUS_EXT,
+					  ULPI_IC_DEFAULT,
+					  ULPI_FC_DEFAULT);
 
 	mxc_register_device(&mxc_otg_host, &usbotg_pdata);
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
diff --git a/arch/arm/mach-mx3/mach-mx31lite.c b/arch/arm/mach-mx3/mach-mx31lite.c
index 2b6d114..9413be4 100644
--- a/arch/arm/mach-mx3/mach-mx31lite.c
+++ b/arch/arm/mach-mx3/mach-mx31lite.c
@@ -261,7 +261,10 @@ static void __init mxc_board_init(void)
 #if defined(CONFIG_USB_ULPI)
 	/* USB */
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+					  USB_OTG_DRV_VBUS |
+					  USB_OTG_DRV_VBUS_EXT,
+					  ULPI_IC_DEFAULT,
+					  ULPI_FC_DEFAULT);
 
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 #endif
diff --git a/arch/arm/mach-mx3/mach-mx31moboard.c b/arch/arm/mach-mx3/mach-mx31moboard.c
index fccb920..620f21a 100644
--- a/arch/arm/mach-mx3/mach-mx31moboard.c
+++ b/arch/arm/mach-mx3/mach-mx31moboard.c
@@ -391,7 +391,10 @@ static struct mxc_usbh_platform_data usbh2_pdata = {
 static int __init moboard_usbh2_init(void)
 {
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+					  USB_OTG_DRV_VBUS |
+					  USB_OTG_DRV_VBUS_EXT,
+					  ULPI_IC_DEFAULT,
+					  ULPI_FC_DEFAULT);
 
 	return mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 }
diff --git a/arch/arm/mach-mx3/mach-pcm037.c b/arch/arm/mach-mx3/mach-pcm037.c
index 2df1ec5..33471c4 100644
--- a/arch/arm/mach-mx3/mach-pcm037.c
+++ b/arch/arm/mach-mx3/mach-pcm037.c
@@ -657,13 +657,19 @@ static void __init mxc_board_init(void)
 #if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+						USB_OTG_DRV_VBUS |
+						USB_OTG_DRV_VBUS_EXT,
+						ULPI_IC_DEFAULT,
+						ULPI_FC_DEFAULT);
 
 		mxc_register_device(&mxc_otg_host, &otg_pdata);
 	}
 
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+					  USB_OTG_DRV_VBUS |
+					  USB_OTG_DRV_VBUS_EXT,
+					  ULPI_IC_DEFAULT,
+					  ULPI_FC_DEFAULT);
 
 	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 #endif
diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c
index 1bf1ec2..63d8719 100644
--- a/arch/arm/mach-mx3/mach-pcm043.c
+++ b/arch/arm/mach-mx3/mach-pcm043.c
@@ -379,7 +379,10 @@ static void __init mxc_board_init(void)
 #if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
 		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				USB_OTG_DRV_VBUS | USB_OTG_DRV_VBUS_EXT);
+						USB_OTG_DRV_VBUS |
+						USB_OTG_DRV_VBUS_EXT,
+						ULPI_IC_DEFAULT,
+						ULPI_FC_DEFAULT);
 
 		mxc_register_device(&mxc_otg_host, &otg_pdata);
 	}
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 3d2d3e5..3b12895 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -49,8 +49,6 @@ config USB_ULPI
 	  Enable this to support ULPI connected USB OTG transceivers which
 	  are likely found on embedded boards.
 
-	  The only chip currently supported is NXP's ISP1504
-
 config TWL4030_USB
 	tristate "TWL4030 USB Transceiver Driver"
 	depends on TWL4030_CORE && REGULATOR_TWL4030
diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c
index 9010225..0e7a826 100644
--- a/drivers/usb/otg/ulpi.c
+++ b/drivers/usb/otg/ulpi.c
@@ -34,6 +34,7 @@
 #define ULPI_VID_HIGH        0x01    /* Vendor ID high */
 #define ULPI_PID_LOW         0x02    /* Product ID low */
 #define ULPI_PID_HIGH        0x03    /* Product ID high */
+#define ULPI_FUNCTL          0x04    /* Function Control */
 #define ULPI_ITFCTL          0x07    /* Interface Control */
 #define ULPI_OTGCTL          0x0A    /* OTG Control */
 
@@ -60,25 +61,51 @@ static unsigned int ulpi_ids[] = {
 	ULPI_ID(0x04cc, 0x1504),	/* NXP ISP1504 */
 };
 
-static int ulpi_set_flags(struct otg_transceiver *otg)
+static int ulpi_set_otg_flags(struct otg_transceiver *otg)
 {
+	unsigned int otg_flags = otg->flags & 0xff;
 	unsigned int flags = 0;
 
-	if (otg->flags & USB_OTG_PULLUP_ID)
+	if (otg_flags & USB_OTG_PULLUP_ID)
 		flags |= ID_PULL_UP;
 
-	if (otg->flags & USB_OTG_PULLDOWN_DM)
+	if (otg_flags & USB_OTG_PULLDOWN_DM)
 		flags |= DM_PULL_DOWN;
 
-	if (otg->flags & USB_OTG_PULLDOWN_DP)
+	if (otg_flags & USB_OTG_PULLDOWN_DP)
 		flags |= DP_PULL_DOWN;
 
-	if (otg->flags & USB_OTG_EXT_VBUS_INDICATOR)
+	if (otg_flags & USB_OTG_EXT_VBUS_INDICATOR)
 		flags |= USE_EXT_VBUS_IND;
 
 	return otg_io_write(otg, flags, ULPI_OTGCTL + ULPI_REG_SET);
 }
 
+static int ulpi_set_fc_flags(struct otg_transceiver *otg)
+{
+	unsigned int fc_flags = (otg->flags >> 16) & 0xff;
+
+	/*
+	 * Bit 6 in Function Control Register is SuspendM
+	 * 1 - Powered.
+	 * 0 - Suspend.
+	 */
+	fc_flags |= (1 << 6);
+
+	return otg_io_write(otg, fc_flags, ULPI_FUNCTL + ULPI_REG_SET);
+}
+
+static inline int ulpi_set_flags(struct otg_transceiver *otg)
+{
+	int ret;
+
+	ret = ulpi_set_otg_flags(otg);
+	if (ret)
+		return ret;
+
+	return ulpi_set_fc_flags(otg);
+}
+
 static int ulpi_init(struct otg_transceiver *otg)
 {
 	int i, vid, pid;
@@ -98,6 +125,28 @@ static int ulpi_init(struct otg_transceiver *otg)
 	return -ENODEV;
 }
 
+static int ulpi_set_host(struct otg_transceiver *otg, struct usb_bus *host)
+{
+	unsigned int ic_flags = (otg->flags >> 8) & 0xff;
+	unsigned int ic = ic_flags & ~0x7;
+
+	if (!host) {
+		otg->host = NULL;
+		return 0;
+	}
+
+	otg->host = host;
+
+	if (ic_flags & ULPI_IC_3PIN)
+		ic |= ULPI_IC_3PIN;
+	else if (ic_flags & ULPI_IC_CARKIT)
+		ic |= ULPI_IC_CARKIT;
+	else
+		ic |= ULPI_IC_6PIN;
+
+	return otg_io_write(otg, ic, ULPI_ITFCTL + ULPI_REG_SET);
+}
+
 static int ulpi_set_vbus(struct otg_transceiver *otg, bool on)
 {
 	unsigned int flags = otg_io_read(otg, ULPI_OTGCTL);
@@ -117,7 +166,7 @@ static int ulpi_set_vbus(struct otg_transceiver *otg, bool on)
 
 struct otg_transceiver *
 otg_ulpi_create(struct otg_io_access_ops *ops,
-		unsigned int flags)
+		u8 otg_flags, u8 ic_flags, u8 fc_flags)
 {
 	struct otg_transceiver *otg;
 
@@ -126,9 +175,10 @@ otg_ulpi_create(struct otg_io_access_ops *ops,
 		return NULL;
 
 	otg->label	= "ULPI";
-	otg->flags	= flags;
+	otg->flags	= otg_flags | (ic_flags << 8) | (fc_flags << 16);
 	otg->io_ops	= ops;
 	otg->init	= ulpi_init;
+	otg->set_host	= ulpi_set_host;
 	otg->set_vbus	= ulpi_set_vbus;
 
 	return otg;
diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h
index 20675c6..8318067 100644
--- a/include/linux/usb/ulpi.h
+++ b/include/linux/usb/ulpi.h
@@ -1,7 +1,30 @@
 #ifndef __LINUX_USB_ULPI_H
 #define __LINUX_USB_ULPI_H
 
+/* ULPI Function Control Register bits */
+#define ULPI_FC_HS	0		/* Enable HS tcvr */
+#define ULPI_FC_FS	(0x1 << 0)	/* Enable FS tcvr */
+#define ULPI_FC_LS	(0x2 << 0)	/* Enable LS tcvr */
+#define ULPI_FC_FS_LS	(0x3 << 0)	/* Enable FS tcvr for LS packets */
+#define ULPI_FC_TRM_SEL	(0x1 << 2)	/* Internal pullup and HS termination */
+#define ULPI_FC_NODRV	(0x1 << 3)	/* Non-Driving Operation */
+#define ULPI_FC_NONRZI	(0x1 << 4)	/* Disable bit-stuff and NRZI encode */
+#define ULPI_FC_RESET	(0x1 << 5)	/* Reset the UTMI core */
+#define ULPI_FC_DEFAULT	0x41		/* Function Control Register Default */
+
+
+/* ULPI Interface Register bits */
+#define ULPI_IC_6PIN	(1 << 0)	/* XCVR 6 serial pin mode */
+#define ULPI_IC_3PIN	(1 << 1)	/* XCVR 3 serial pin mode */
+#define ULPI_IC_CARKIT	(1 << 2)	/* Carkit mode */
+#define ULPI_IC_CLKSPND	(1 << 3)	/* Active low clock suspend */
+#define ULPI_IC_AUTORES	(1 << 4)	/* PHY auto transmit resume signal */
+#define ULPI_IC_VBUSINV	(1 << 5)	/* Invert the external VBUS indicator */
+#define ULPI_IC_INDPT	(1 << 6)	/* Indicator Pass Through */
+#define ULPI_IC_DISPRT	(1 << 7)	/* Interface Protect Disable */
+#define ULPI_IC_DEFAULT	0x0		/* Interface Control Register Default */
+
 struct otg_transceiver *otg_ulpi_create(struct otg_io_access_ops *ops,
-					unsigned int flags);
+					u8 fc_flags, u8 ic_flags, u8 otg_flags);
 
 #endif /* __LINUX_USB_ULPI_H */
-- 
1.6.4.4




More information about the linux-arm-kernel mailing list