From d5d730edbb422c9d69eb57087c1f2361246822de Mon Sep 17 00:00:00 2001 From: Luotao Fu Date: Thu, 25 Jun 2009 12:40:13 +0200 Subject: pca100: add otg support Signed-off-by: Luotao Fu --- arch/arm/mach-mx2/pca100.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/arch/arm/mach-mx2/pca100.c b/arch/arm/mach-mx2/pca100.c index ed801feb9d4..0de0e18a1f7 100644 --- a/arch/arm/mach-mx2/pca100.c +++ b/arch/arm/mach-mx2/pca100.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -313,6 +314,82 @@ static struct mxc_usbh_platform_data ehci2_pdata = { .init = pca100_usbh2_init, }; +static int mxc_otg_pins[] = { + PC7_PF_USBOTG_DATA5, + PC8_PF_USBOTG_DATA6, + PC9_PF_USBOTG_DATA0, + PC10_PF_USBOTG_DATA2, + PC11_PF_USBOTG_DATA1, + PC12_PF_USBOTG_DATA4, + PC13_PF_USBOTG_DATA3, + PE0_PF_USBOTG_NXT, + PE1_PF_USBOTG_STP, + PE2_PF_USBOTG_DIR, + PE24_PF_USBOTG_CLK, + PE25_PF_USBOTG_DATA7, +}; + +static int pca100_otg_phy_cs_req_setval(int cs_value) +{ + int ret; + + ret = gpio_request(GPIO_PORTB + 23, "usb-otg-cs"); + if (ret) + return ret; + + gpio_direction_output(GPIO_PORTB + 23, cs_value); + + return 0; +} + +static int pca100_otg_init(struct platform_device *pdev) +{ + int ret; + unsigned int tmp; + + /* request phy /cs line and disable it */ + ret = pca100_otg_phy_cs_req_setval(1); + if (ret) + return ret; + + ret = mxc_gpio_setup_multiple_pins(mxc_otg_pins, + ARRAY_SIZE(mxc_otg_pins), "otg"); + if (ret) + return ret; + + tmp = readl(IO_ADDRESS(OTG_BASE_ADDR) + 0x600); + tmp &= ~((3 << 29) | 1); + tmp |= (1 << 28) | (1 << 27) | (1 << 24); + 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); + + mdelay(10); + + /* enable phy */ + gpio_set_value(GPIO_PORTB + 23, 0); + udelay(10); + + ret = isp1504_set_vbus_power(IO_ADDRESS(OTG_BASE_ADDR + 0x170), 1); + if (ret) + printk(KERN_ERR "pca100: Failed to enable otg phy (%d)\n", ret); + + return ret; +} + +static struct mxc_usbh_platform_data otg_host_pdata = { + .init = pca100_otg_init, +}; + +static struct fsl_usb2_platform_data otg_device_pdata = { + .operating_mode = FSL_USB2_DR_DEVICE, + .phy_mode = FSL_USB2_PHY_ULPI, +}; + static struct spi_eeprom at25320 = { .name = "at25320an", .byte_len = 4096, @@ -367,6 +444,21 @@ static struct imxmmc_platform_data sdhc_pdata = { .exit = pca100_sdhc2_exit, }; +static int otg_mode_host; + +static int __init pca100_otg_mode(char *options) +{ + if (!strcmp(options, "host")) + otg_mode_host = 1; + else if (!strcmp(options, "device")) + otg_mode_host = 0; + else + pr_info("pca100_otg_mode neither \"host\" nor \"device\". " + "Defaulting to device\n"); + return 0; +} +__setup("pca100_otg_mode=", pca100_otg_mode); + static void __init pca100_init(void) { int ret; @@ -394,6 +486,22 @@ static void __init pca100_init(void) mxc_gpio_mode((GPIO_PORTB | 24) | GPIO_GPIO | GPIO_OUT); mxc_register_device(&mxc_ehci2, &ehci2_pdata); + /* cs on otg phy */ + mxc_gpio_mode((GPIO_PORTB | 23) | GPIO_GPIO | GPIO_OUT); + if (otg_mode_host) + mxc_register_device(&mxc_otg, &otg_host_pdata); + else { + mxc_gpio_setup_multiple_pins(mxc_otg_pins, + ARRAY_SIZE(mxc_otg_pins), "otg"); + + /* enable phy by pulling down /cs line */ + ret = pca100_otg_phy_cs_req_setval(0); + if (ret) + printk(KERN_ERR "pca100: Failed to enable otg phy\n"); + + mxc_register_device(&otg_udc_device, &otg_device_pdata); + } + mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT); mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_OUT); -- cgit v1.2.3