/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #include <common.h> #include <io.h> #include <init.h> #include <sizes.h> #include <platform_ide.h> #include <mach/imx27-regs.h> #include <mach/iomux-mx27.h> #include <mach/weim.h> #include <mach/gpio.h> #include <mach/devices-imx27.h> #include <usb/chipidea-imx.h> #define GPIO_IDE_POWER (GPIO_PORTE + 18) #define GPIO_IDE_PCOE (GPIO_PORTF + 7) #define GPIO_IDE_RESET (GPIO_PORTF + 10) static struct resource pcm970_ide_resources[] = { { .start = MX27_PCMCIA_MEM_BASE_ADDR, .end = MX27_PCMCIA_MEM_BASE_ADDR + SZ_1K - 1, .flags = IORESOURCE_MEM, }, }; static void pcm970_ide_reset(int state) { /* Switch reset line to low/high state */ gpio_set_value(GPIO_IDE_RESET, !!state); } static struct ide_port_info pcm970_ide_pdata = { .ioport_shift = 0, .reset = &pcm970_ide_reset, }; static struct device_d pcm970_ide_device = { .id = DEVICE_ID_DYNAMIC, .name = "ide_intf", .num_resources = ARRAY_SIZE(pcm970_ide_resources), .resource = pcm970_ide_resources, .platform_data = &pcm970_ide_pdata, }; static void pcm970_ide_init(void) { uint32_t i; unsigned int mode[] = { /* PCMCIA */ PF20_PF_PC_CD1, PF19_PF_PC_CD2, PF18_PF_PC_WAIT, PF17_PF_PC_READY, PF16_PF_PC_PWRON, PF14_PF_PC_VS1, PF13_PF_PC_VS2, PF12_PF_PC_BVD1, PF11_PF_PC_BVD2, PF9_PF_PC_IOIS16, PF8_PF_PC_RW, GPIO_IDE_PCOE | GPIO_GPIO | GPIO_OUT, /* PCOE */ GPIO_IDE_RESET | GPIO_GPIO | GPIO_OUT, /* Reset */ GPIO_IDE_POWER | GPIO_GPIO | GPIO_OUT, /* Power */ }; for (i = 0; i < ARRAY_SIZE(mode); i++) imx_gpio_mode(mode[i] | GPIO_PUEN); /* Always set PCOE signal to low */ gpio_set_value(GPIO_IDE_PCOE, 0); /* Assert RESET line */ gpio_set_value(GPIO_IDE_RESET, 0); /* Power up CF-card (Also switched on User-LED) */ gpio_set_value(GPIO_IDE_POWER, 1); mdelay(10); /* Reset PCMCIA Status Change Register */ writel(0x00000fff, MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_PSCR); mdelay(10); /* Check PCMCIA Input Pins Register for Card Detect & Power */ if ((readl(MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_PIPR) & ((1 << 8) | (3 << 3))) != (1 << 8)) { printf("CompactFlash card not found. Driver not enabled.\n"); return; } /* Disable all interrupts */ writel(0, MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_PER); /* Disable all PCMCIA banks */ for (i = 0; i < 5; i++) writel(0, MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_POR(i)); /* Not use internal PCOE */ writel(0, MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_PGCR); /* Setup PCMCIA bank0 for Common memory mode */ writel(0, MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_PBR(0)); writel(0, MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_POFR(0)); writel((0 << 25) | (17 << 17) | (4 << 11) | (3 << 5) | 0xf, MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_POR(0)); /* Clear PCMCIA General Status Register */ writel(0x0000001f, MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_PGSR); /* Make PCMCIA bank0 valid */ i = readl(MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_POR(0)); writel(i | (1 << 29), MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_POR(0)); platform_device_register(&pcm970_ide_device); } static void pcm970_mmc_init(void) { uint32_t i; unsigned int mode[] = { /* SD2 */ PB4_PF_SD2_D0, PB5_PF_SD2_D1, PB6_PF_SD2_D2, PB7_PF_SD2_D3, PB8_PF_SD2_CMD, PB9_PF_SD2_CLK, }; for (i = 0; i < ARRAY_SIZE(mode); i++) imx_gpio_mode(mode[i]); imx27_add_mmc1(NULL); } struct imxusb_platformdata pcm970_usbh2_pdata = { .flags = MXC_EHCI_MODE_ULPI | MXC_EHCI_INTERFACE_DIFF_UNI, .mode = IMX_USB_MODE_HOST, }; static int pcm970_init(void) { int i; unsigned int mode[] = { /* USB Host 2 */ PA0_PF_USBH2_CLK, PA1_PF_USBH2_DIR, PA2_PF_USBH2_DATA7, PA3_PF_USBH2_NXT, 4 | GPIO_PORTA | GPIO_GPIO | GPIO_OUT, PD19_AF_USBH2_DATA4, PD20_AF_USBH2_DATA3, PD21_AF_USBH2_DATA6, PD22_AF_USBH2_DATA0, PD23_AF_USBH2_DATA2, PD24_AF_USBH2_DATA1, PD26_AF_USBH2_DATA5, }; for (i = 0; i < ARRAY_SIZE(mode); i++) imx_gpio_mode(mode[i]); /* Configure SJA1000 on cs4 */ imx27_setup_weimcs(4, 0x0000DCF6, 0x444A0301, 0x44443302); if (IS_ENABLED(CONFIG_USB)) { /* Stop ULPI */ gpio_direction_output(4, 1); mdelay(1); imx_gpio_mode(PA4_PF_USBH2_STP); imx27_add_usbh2(&pcm970_usbh2_pdata); } if (IS_ENABLED(CONFIG_DISK_INTF_PLATFORM_IDE)) pcm970_ide_init(); if (IS_ENABLED(CONFIG_MCI_IMX)) pcm970_mmc_init(); return 0; } late_initcall(pcm970_init);