diff options
Diffstat (limited to 'arch/arm/mach-mx3/mach-pcm043.c')
-rw-r--r-- | arch/arm/mach-mx3/mach-pcm043.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/arch/arm/mach-mx3/mach-pcm043.c b/arch/arm/mach-mx3/mach-pcm043.c index 25942b8e8be..1bf1ec2eef5 100644 --- a/arch/arm/mach-mx3/mach-pcm043.c +++ b/arch/arm/mach-mx3/mach-pcm043.c @@ -26,8 +26,12 @@ #include <linux/gpio.h> #include <linux/smc911x.h> #include <linux/interrupt.h> +#include <linux/delay.h> #include <linux/i2c.h> #include <linux/i2c/at24.h> +#include <linux/usb/otg.h> +#include <linux/usb/ulpi.h> +#include <linux/fsl_devices.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -44,6 +48,10 @@ #include <mach/ipu.h> #include <mach/mx3fb.h> #include <mach/mxc_nand.h> +#include <mach/mxc_ehci.h> +#include <mach/ulpi.h> +#include <mach/audmux.h> +#include <mach/ssi.h> #include "devices.h" @@ -205,6 +213,94 @@ static struct pad_desc pcm043_pads[] = { MX35_PAD_D3_CLS__IPU_DISPB_D3_CLS, /* gpio */ MX35_PAD_ATA_CS0__GPIO2_6, + /* USB host */ + MX35_PAD_I2C2_CLK__USB_TOP_USBH2_PWR, + MX35_PAD_I2C2_DAT__USB_TOP_USBH2_OC, + /* SSI */ + MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS, + MX35_PAD_STXD4__AUDMUX_AUD4_TXD, + MX35_PAD_SRXD4__AUDMUX_AUD4_RXD, + MX35_PAD_SCK4__AUDMUX_AUD4_TXC, +}; + +#define AC97_GPIO_TXFS (1 * 32 + 31) +#define AC97_GPIO_TXD (1 * 32 + 28) +#define AC97_GPIO_RESET (1 * 32 + 0) + +static void pcm043_ac97_warm_reset(struct snd_ac97 *ac97) +{ + struct pad_desc txfs_gpio = MX35_PAD_STXFS4__GPIO2_31; + struct pad_desc txfs = MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS; + int ret; + + ret = gpio_request(AC97_GPIO_TXFS, "SSI"); + if (ret) { + printk("failed to get GPIO_TXFS: %d\n", ret); + return; + } + + mxc_iomux_v3_setup_pad(&txfs_gpio); + + /* warm reset */ + gpio_direction_output(AC97_GPIO_TXFS, 1); + udelay(2); + gpio_set_value(AC97_GPIO_TXFS, 0); + + gpio_free(AC97_GPIO_TXFS); + mxc_iomux_v3_setup_pad(&txfs); +} + +static void pcm043_ac97_cold_reset(struct snd_ac97 *ac97) +{ + struct pad_desc txfs_gpio = MX35_PAD_STXFS4__GPIO2_31; + struct pad_desc txfs = MX35_PAD_STXFS4__AUDMUX_AUD4_TXFS; + struct pad_desc txd_gpio = MX35_PAD_STXD4__GPIO2_28; + struct pad_desc txd = MX35_PAD_STXD4__AUDMUX_AUD4_TXD; + struct pad_desc reset_gpio = MX35_PAD_SD2_CMD__GPIO2_0; + int ret; + + ret = gpio_request(AC97_GPIO_TXFS, "SSI"); + if (ret) + goto err1; + + ret = gpio_request(AC97_GPIO_TXD, "SSI"); + if (ret) + goto err2; + + ret = gpio_request(AC97_GPIO_RESET, "SSI"); + if (ret) + goto err3; + + mxc_iomux_v3_setup_pad(&txfs_gpio); + mxc_iomux_v3_setup_pad(&txd_gpio); + mxc_iomux_v3_setup_pad(&reset_gpio); + + gpio_direction_output(AC97_GPIO_TXFS, 0); + gpio_direction_output(AC97_GPIO_TXD, 0); + + /* cold reset */ + gpio_direction_output(AC97_GPIO_RESET, 0); + udelay(10); + gpio_direction_output(AC97_GPIO_RESET, 1); + + mxc_iomux_v3_setup_pad(&txd); + mxc_iomux_v3_setup_pad(&txfs); + + gpio_free(AC97_GPIO_RESET); +err3: + gpio_free(AC97_GPIO_TXD); +err2: + gpio_free(AC97_GPIO_TXFS); +err1: + if (ret) + printk("%s failed with %d\n", __func__, ret); + mdelay(1); +} + +static struct imx_ssi_platform_data pcm043_ssi_pdata = { + .ac97_reset = pcm043_ac97_cold_reset, + .ac97_warm_reset = pcm043_ac97_warm_reset, + .flags = IMX_SSI_USE_AC97, }; static struct mxc_nand_platform_data pcm037_nand_board_info = { @@ -212,6 +308,37 @@ static struct mxc_nand_platform_data pcm037_nand_board_info = { .hw_ecc = 1, }; +static struct mxc_usbh_platform_data otg_pdata = { + .portsc = MXC_EHCI_MODE_UTMI, + .flags = MXC_EHCI_INTERFACE_DIFF_UNI, +}; + +static struct mxc_usbh_platform_data usbh1_pdata = { + .portsc = MXC_EHCI_MODE_SERIAL, + .flags = MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY | + MXC_EHCI_IPPUE_DOWN, +}; + +static struct fsl_usb2_platform_data otg_device_pdata = { + .operating_mode = FSL_USB2_DR_DEVICE, + .phy_mode = FSL_USB2_PHY_UTMI, +}; + +static int otg_mode_host; + +static int __init pcm043_otg_mode(char *options) +{ + if (!strcmp(options, "host")) + otg_mode_host = 1; + else if (!strcmp(options, "device")) + otg_mode_host = 0; + else + pr_info("otg_mode neither \"host\" nor \"device\". " + "Defaulting to device\n"); + return 0; +} +__setup("otg_mode=", pcm043_otg_mode); + /* * Board specific initialization. */ @@ -219,10 +346,23 @@ static void __init mxc_board_init(void) { mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads)); + mxc_audmux_v2_configure_port(3, + MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ + MXC_AUDMUX_V2_PTCR_TFSEL(0) | + MXC_AUDMUX_V2_PTCR_TFSDIR, + MXC_AUDMUX_V2_PDCR_RXDSEL(0)); + + mxc_audmux_v2_configure_port(0, + MXC_AUDMUX_V2_PTCR_SYN | /* 4wire mode */ + MXC_AUDMUX_V2_PTCR_TCSEL(3) | + MXC_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */ + MXC_AUDMUX_V2_PDCR_RXDSEL(3)); + platform_add_devices(devices, ARRAY_SIZE(devices)); mxc_register_device(&mxc_uart_device0, &uart_pdata); mxc_register_device(&mxc_nand_device, &pcm037_nand_board_info); + mxc_register_device(&imx_ssi_device0, &pcm043_ssi_pdata); mxc_register_device(&mxc_uart_device1, &uart_pdata); @@ -235,6 +375,20 @@ static void __init mxc_board_init(void) mxc_register_device(&mx3_ipu, &mx3_ipu_data); mxc_register_device(&mx3_fb, &mx3fb_pdata); + +#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); + + mxc_register_device(&mxc_otg_host, &otg_pdata); + } + + mxc_register_device(&mxc_usbh1, &usbh1_pdata); +#endif + if (!otg_mode_host) + mxc_register_device(&mxc_otg_udc_device, &otg_device_pdata); + } static void __init pcm043_timer_init(void) |