[PATCH 3/5] pcm037: Add USB Host support

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

 



Signed-off-by: Sascha Hauer <s.hauer@xxxxxxxxxxxxxx>
---
 arch/arm/mach-mx3/Kconfig  |    1 +
 arch/arm/mach-mx3/pcm037.c |  135 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 136 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-mx3/Kconfig b/arch/arm/mach-mx3/Kconfig
index 194b842..4bb7d69 100644
--- a/arch/arm/mach-mx3/Kconfig
+++ b/arch/arm/mach-mx3/Kconfig
@@ -30,6 +30,7 @@ config MACH_MX31ADS_WM1133_EV1
 config MACH_PCM037
 	bool "Support Phytec pcm037 (i.MX31) platforms"
 	select ARCH_MX31
+	select MXC_ULPI
 	help
 	  Include support for Phytec pcm037 platform. This includes
 	  specific configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx3/pcm037.c b/arch/arm/mach-mx3/pcm037.c
index b5227d8..dd16452 100644
--- a/arch/arm/mach-mx3/pcm037.c
+++ b/arch/arm/mach-mx3/pcm037.c
@@ -28,6 +28,7 @@
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
+#include <linux/delay.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -43,6 +44,8 @@
 #ifdef CONFIG_I2C_IMX
 #include <mach/i2c.h>
 #endif
+#include <mach/mxc_ehci.h>
+#include <mach/ulpi.h>
 
 #include "devices.h"
 
@@ -210,6 +213,136 @@ static int uart2_pins[] = {
 	MX31_PIN_CSPI3_MISO__TXD3
 };
 
+static int isp1504_set_vbus_power(void __iomem *view, int on)
+{
+	int vid, pid, ret = 0;
+
+	vid = (ulpi_read(ISP1504_VID_HIGH, view) << 8) |
+		 ulpi_read(ISP1504_VID_LOW, view);
+	pid = (ulpi_read(ISP1504_PID_HIGH, view) << 8) |
+		 ulpi_read(ISP1504_PID_LOW, view);
+
+	pr_info("ULPI Vendor ID 0x%x    Product ID 0x%x\n", vid, pid);
+	if (vid != 0x4cc || pid != 0x1504) {
+		pr_err("No ISP1504 found\n");
+		return -1;
+	}
+
+	if (on) {
+		ret = ulpi_set(DRV_VBUS_EXT |	/* enable external Vbus */
+			    DRV_VBUS |		/* enable internal Vbus */
+			    USE_EXT_VBUS_IND |	/* use external indicator */
+			    CHRG_VBUS,		/* charge Vbus */
+			    ISP1504_OTGCTL, view);
+	} else {
+		ret = ulpi_clear(DRV_VBUS_EXT |	/* disable external Vbus */
+			      DRV_VBUS,		/* disable internal Vbus */
+			      ISP1504_OTGCTL, view);
+
+		ret |= ulpi_set(USE_EXT_VBUS_IND | /* use external indicator */
+			    DISCHRG_VBUS,	   /* discharge Vbus */
+			    ISP1504_OTGCTL, view);
+	}
+
+	return ret;
+}
+
+static int pcm037_otg_init(struct platform_device *pdev)
+{
+	int ret;
+	unsigned int tmp;
+
+	tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x600);
+	tmp &= ~((3 << 21) | 1);
+	tmp |= (1 << 5) | (1 << 16) | (1 << 19) | (1 << 11) | (1 << 20);
+	writel(tmp, IO_ADDRESS(OTG_BASE_ADDR) + 0x600);
+
+	tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x184);
+	tmp &= ~(3 << 30);
+	tmp |= 2 << 30;
+	writel(tmp, IO_ADDRESS(OTG_BASE_ADDR) + 0x184);
+
+	mxc_iomux_mode(MX31_PIN_USBOTG_DATA0__USBOTG_DATA0);
+	mxc_iomux_mode(MX31_PIN_USBOTG_DATA1__USBOTG_DATA1);
+	mxc_iomux_mode(MX31_PIN_USBOTG_DATA2__USBOTG_DATA2);
+	mxc_iomux_mode(MX31_PIN_USBOTG_DATA3__USBOTG_DATA3);
+	mxc_iomux_mode(MX31_PIN_USBOTG_DATA4__USBOTG_DATA4);
+	mxc_iomux_mode(MX31_PIN_USBOTG_DATA5__USBOTG_DATA5);
+	mxc_iomux_mode(MX31_PIN_USBOTG_DATA6__USBOTG_DATA6);
+	mxc_iomux_mode(MX31_PIN_USBOTG_DATA7__USBOTG_DATA7);
+	mxc_iomux_mode(MX31_PIN_USBOTG_CLK__USBOTG_CLK);
+	mxc_iomux_mode(MX31_PIN_USBOTG_DIR__USBOTG_DIR);
+	mxc_iomux_mode(MX31_PIN_USBOTG_NXT__USBOTG_NXT);
+	mxc_iomux_mode(MX31_PIN_USBOTG_STP__USBOTG_STP);
+
+	mdelay(10);
+
+	ret = isp1504_set_vbus_power(IO_ADDRESS(OTG_BASE_ADDR + 0x170), 1);
+
+	return 0;
+}
+
+struct mxc_usbh_platform_data otg_pdata = {
+	.init = pcm037_otg_init,
+};
+
+static int pcm037_usbh2_init(struct platform_device *pdev)
+{
+	int ret;
+	unsigned int tmp;
+
+	tmp = readl(IO_ADDRESS(IOMUXC_BASE_ADDR + 0x8));
+	tmp |= 1 << 11;
+	writel(tmp, IO_ADDRESS(IOMUXC_BASE_ADDR + 0x8));
+
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_CLK, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_DIR, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_NXT, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_STP, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_DATA0, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_USBH2_DATA1, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_STXD3, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_SRXD3, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_SCK3, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_SFS3, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_STXD6, IOMUX_CONFIG_FUNC));
+	mxc_iomux_mode(IOMUX_MODE(MX31_PIN_SRXD6, IOMUX_CONFIG_FUNC));
+
+#define H2_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
+	mxc_iomux_set_pad(MX31_PIN_USBH2_CLK, H2_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DIR, H2_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_NXT, H2_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_STP, H2_PAD_CFG);
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA0, H2_PAD_CFG); /* USBH2_DATA0 */
+	mxc_iomux_set_pad(MX31_PIN_USBH2_DATA1, H2_PAD_CFG); /* USBH2_DATA1 */
+	mxc_iomux_set_pad(MX31_PIN_SRXD6, H2_PAD_CFG);	/* USBH2_DATA2 */
+	mxc_iomux_set_pad(MX31_PIN_STXD6, H2_PAD_CFG);	/* USBH2_DATA3 */
+	mxc_iomux_set_pad(MX31_PIN_SFS3, H2_PAD_CFG);	/* USBH2_DATA4 */
+	mxc_iomux_set_pad(MX31_PIN_SCK3, H2_PAD_CFG);	/* USBH2_DATA5 */
+	mxc_iomux_set_pad(MX31_PIN_SRXD3, H2_PAD_CFG);	/* USBH2_DATA6 */
+	mxc_iomux_set_pad(MX31_PIN_STXD3, H2_PAD_CFG);	/* USBH2_DATA7 */
+
+	tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x600);
+	tmp &= ~((3 << 21) | 1);
+	tmp |= (1 << 5) | (1 << 16) | (1 << 19) | (1 << 20);
+	writel(tmp, IO_ADDRESS(OTG_BASE_ADDR) + 0x600);
+
+	tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x584);
+	tmp &= ~(3 << 30);
+	tmp |= 2 << 30;
+	writel(tmp, IO_ADDRESS(OTG_BASE_ADDR) + 0x584);
+
+	mdelay(10);
+
+	ret = isp1504_set_vbus_power(IO_ADDRESS(OTG_BASE_ADDR + 0x570), 1);
+
+	return 0;
+}
+
+struct mxc_usbh_platform_data usbh2_pdata = {
+	.init = pcm037_usbh2_init,
+};
+
 /*
  * Board specific initialization.
  */
@@ -239,6 +372,8 @@ static void __init mxc_board_init(void)
 #endif
 	mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info);
 	mxc_register_device(&mxcsdhc_device0, &sdhc_pdata);
+	mxc_register_device(&mxc_otg, &otg_pdata);
+	mxc_register_device(&mxc_usbh2, &usbh2_pdata);
 }
 
 static void __init pcm037_timer_init(void)
-- 
1.6.2.1

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux