summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuotao Fu <l.fu@pengutronix.de>2009-06-25 12:40:13 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2009-07-01 09:17:59 +0200
commitd5d730edbb422c9d69eb57087c1f2361246822de (patch)
tree44df40a43d3e0411bca70a3cffba2841f59a270b
parentd284206d42d96af1210cec07eccd955f1c2fe386 (diff)
downloadlinux-2.6-d5d730edbb422c9d69eb57087c1f2361246822de.tar.gz
linux-2.6-d5d730edbb422c9d69eb57087c1f2361246822de.tar.xz
pca100: add otg support
Signed-off-by: Luotao Fu <l.fu@pengutronix.de>
-rw-r--r--arch/arm/mach-mx2/pca100.c108
1 files changed, 108 insertions, 0 deletions
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 <linux/delay.h>
#include <linux/irq.h>
#include <linux/gpio.h>
+#include <linux/fsl_devices.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
@@ -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);