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