211 lines
5.0 KiB
C
211 lines
5.0 KiB
C
/*
|
|
* 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/ulpi.h>
|
|
|
|
#define GPIO_IDE_POWER (GPIO_PORTE + 18)
|
|
#define GPIO_IDE_PCOE (GPIO_PORTF + 7)
|
|
#define GPIO_IDE_RESET (GPIO_PORTF + 10)
|
|
|
|
#ifdef CONFIG_USB
|
|
static void pcm970_usbh2_init(void)
|
|
{
|
|
uint32_t temp;
|
|
|
|
temp = readl(MX27_USB_OTG_BASE_ADDR + 0x600);
|
|
temp &= ~((3 << 21) | 1);
|
|
temp |= (1 << 5) | (1 << 16) | (1 << 19) | (1 << 20);
|
|
writel(temp, MX27_USB_OTG_BASE_ADDR + 0x600);
|
|
|
|
temp = readl(MX27_USB_OTG_BASE_ADDR + 0x584);
|
|
temp &= ~(3 << 30);
|
|
temp |= 2 << 30;
|
|
writel(temp, MX27_USB_OTG_BASE_ADDR + 0x584);
|
|
|
|
mdelay(10);
|
|
|
|
if (!ulpi_setup((void *)(MX27_USB_OTG_BASE_ADDR + 0x570), 1))
|
|
add_generic_usb_ehci_device(DEVICE_ID_DYNAMIC, MX27_USB_OTG_BASE_ADDR + 0x400, NULL);
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_DISK_INTF_PLATFORM_IDE
|
|
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 */
|
|
writel(readl(MX27_PCMCIA_POR(0)) | (1 << 29),
|
|
MX27_PCMCIA_CTL_BASE_ADDR + MX27_PCMCIA_POR(0));
|
|
|
|
platform_device_register(&pcm970_ide_device);
|
|
}
|
|
#endif
|
|
|
|
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);
|
|
}
|
|
|
|
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,
|
|
PA4_PF_USBH2_STP,
|
|
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);
|
|
|
|
#ifdef CONFIG_USB
|
|
pcm970_usbh2_init();
|
|
#endif
|
|
|
|
#ifdef CONFIG_DISK_INTF_PLATFORM_IDE
|
|
pcm970_ide_init();
|
|
#endif
|
|
|
|
if (IS_ENABLED(CONFIG_MCI_IMX))
|
|
pcm970_mmc_init();
|
|
|
|
return 0;
|
|
}
|
|
|
|
late_initcall(pcm970_init);
|