diff options
Diffstat (limited to 'arch/arm/mach-mx3/mx31moboard-devboard.c')
-rw-r--r-- | arch/arm/mach-mx3/mx31moboard-devboard.c | 166 |
1 files changed, 159 insertions, 7 deletions
diff --git a/arch/arm/mach-mx3/mx31moboard-devboard.c b/arch/arm/mach-mx3/mx31moboard-devboard.c index d080b4add79c..8fc624f141cb 100644 --- a/arch/arm/mach-mx3/mx31moboard-devboard.c +++ b/arch/arm/mach-mx3/mx31moboard-devboard.c @@ -16,33 +16,185 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/types.h> +#include <linux/gpio.h> #include <linux/init.h> - +#include <linux/interrupt.h> #include <linux/platform_device.h> +#include <linux/types.h> + +#include <linux/usb/otg.h> -#include <mach/hardware.h> #include <mach/common.h> #include <mach/imx-uart.h> #include <mach/iomux-mx3.h> +#include <mach/hardware.h> +#include <mach/mmc.h> +#include <mach/mxc_ehci.h> +#include <mach/ulpi.h> #include "devices.h" +static unsigned int devboard_pins[] = { + /* UART1 */ + MX31_PIN_CTS2__CTS2, MX31_PIN_RTS2__RTS2, + MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2, + /* SDHC2 */ + MX31_PIN_PC_PWRON__SD2_DATA3, MX31_PIN_PC_VS1__SD2_DATA2, + MX31_PIN_PC_READY__SD2_DATA1, MX31_PIN_PC_WAIT_B__SD2_DATA0, + MX31_PIN_PC_CD2_B__SD2_CLK, MX31_PIN_PC_CD1_B__SD2_CMD, + MX31_PIN_ATA_DIOR__GPIO3_28, MX31_PIN_ATA_DIOW__GPIO3_29, + /* USB H1 */ + MX31_PIN_CSPI1_MISO__USBH1_RXDP, MX31_PIN_CSPI1_MOSI__USBH1_RXDM, + MX31_PIN_CSPI1_SS0__USBH1_TXDM, MX31_PIN_CSPI1_SS1__USBH1_TXDP, + MX31_PIN_CSPI1_SS2__USBH1_RCV, MX31_PIN_CSPI1_SCLK__USBH1_OEB, + MX31_PIN_CSPI1_SPI_RDY__USBH1_FS, MX31_PIN_SFS6__USBH1_SUSPEND, + MX31_PIN_NFRE_B__GPIO1_11, MX31_PIN_NFALE__GPIO1_12, +}; + static struct imxuart_platform_data uart_pdata = { .flags = IMXUART_HAVE_RTSCTS, }; -static int mxc_uart1_pins[] = { - MX31_PIN_CTS2__CTS2, MX31_PIN_RTS2__RTS2, - MX31_PIN_TXD2__TXD2, MX31_PIN_RXD2__RXD2, +#define SDHC2_CD IOMUX_TO_GPIO(MX31_PIN_ATA_DIOR) +#define SDHC2_WP IOMUX_TO_GPIO(MX31_PIN_ATA_DIOW) + +static int devboard_sdhc2_get_ro(struct device *dev) +{ + return !gpio_get_value(SDHC2_WP); +} + +static int devboard_sdhc2_init(struct device *dev, irq_handler_t detect_irq, + void *data) +{ + int ret; + + ret = gpio_request(SDHC2_CD, "sdhc-detect"); + if (ret) + return ret; + + gpio_direction_input(SDHC2_CD); + + ret = gpio_request(SDHC2_WP, "sdhc-wp"); + if (ret) + goto err_gpio_free; + gpio_direction_input(SDHC2_WP); + + ret = request_irq(gpio_to_irq(SDHC2_CD), detect_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "sdhc2-card-detect", data); + if (ret) + goto err_gpio_free_2; + + return 0; + +err_gpio_free_2: + gpio_free(SDHC2_WP); +err_gpio_free: + gpio_free(SDHC2_CD); + + return ret; +} + +static void devboard_sdhc2_exit(struct device *dev, void *data) +{ + free_irq(gpio_to_irq(SDHC2_CD), data); + gpio_free(SDHC2_WP); + gpio_free(SDHC2_CD); +} + +static struct imxmmc_platform_data sdhc2_pdata = { + .get_ro = devboard_sdhc2_get_ro, + .init = devboard_sdhc2_init, + .exit = devboard_sdhc2_exit, }; +#define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \ + PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU) + +static int devboard_usbh1_hw_init(struct platform_device *pdev) +{ + mxc_iomux_set_gpr(MUX_PGP_USB_SUSPEND, true); + + mxc_iomux_set_pad(MX31_PIN_CSPI1_MISO, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_MOSI, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SS0, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SS1, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SS2, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SCLK, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG); + mxc_iomux_set_pad(MX31_PIN_SFS6, USB_PAD_CFG); + + return 0; +} + +#define USBH1_VBUSEN_B IOMUX_TO_GPIO(MX31_PIN_NFRE_B) +#define USBH1_MODE IOMUX_TO_GPIO(MX31_PIN_NFALE) + +static int devboard_isp1105_init(struct otg_transceiver *otg) +{ + int ret = gpio_request(USBH1_MODE, "usbh1-mode"); + if (ret) + return ret; + /* single ended */ + gpio_direction_output(USBH1_MODE, 0); + + ret = gpio_request(USBH1_VBUSEN_B, "usbh1-vbusen"); + if (ret) { + gpio_free(USBH1_MODE); + return ret; + } + gpio_direction_output(USBH1_VBUSEN_B, 1); + + return 0; +} + + +static int devboard_isp1105_set_vbus(struct otg_transceiver *otg, bool on) +{ + if (on) + gpio_set_value(USBH1_VBUSEN_B, 0); + else + gpio_set_value(USBH1_VBUSEN_B, 1); + + return 0; +} + +static struct mxc_usbh_platform_data usbh1_pdata = { + .init = devboard_usbh1_hw_init, + .portsc = MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL, + .flags = MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI, +}; + +static int __init devboard_usbh1_init(void) +{ + struct otg_transceiver *otg; + + otg = kzalloc(sizeof(*otg), GFP_KERNEL); + if (!otg) + return -ENOMEM; + + otg->label = "ISP1105"; + otg->init = devboard_isp1105_init; + otg->set_vbus = devboard_isp1105_set_vbus; + + usbh1_pdata.otg = otg; + + return mxc_register_device(&mx31_usbh1, &usbh1_pdata); +} + /* * system init for baseboard usage. Will be called by mx31moboard init. */ void __init mx31moboard_devboard_init(void) { printk(KERN_INFO "Initializing mx31devboard peripherals\n"); - mxc_iomux_setup_multiple_pins(mxc_uart1_pins, ARRAY_SIZE(mxc_uart1_pins), "uart1"); + + mxc_iomux_setup_multiple_pins(devboard_pins, ARRAY_SIZE(devboard_pins), + "devboard"); + mxc_register_device(&mxc_uart_device1, &uart_pdata); + + mxc_register_device(&mxcsdhc_device1, &sdhc2_pdata); + + devboard_usbh1_init(); } |