Archived
14
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
linux-2.6/arch/arm/mach-omap2/devices.c
Tony Lindgren d88746652b omap mmc: Add better MMC low-level init
This will simplify the MMC low-level init, and make it more
flexible to add support for a newer MMC controller in the
following patches.

The patch rearranges platform data and gets rid of slot vs
controller confusion in the old data structures. Also fix
device id numbering in the clock code.

Some code snippets are based on an earlier patch by
Russell King <linux@arm.linux.org.uk>.

Cc: Pierre Ossman <drzeus-mmc@drzeus.cx>
Signed-off-by: Tony Lindgren <tony@atomide.com>
2008-12-10 17:37:16 -08:00

429 lines
9.3 KiB
C

/*
* linux/arch/arm/mach-omap2/devices.c
*
* OMAP2 platform device setup/initialization
*
* 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.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <mach/hardware.h>
#include <asm/mach-types.h>
#include <asm/mach/map.h>
#include <mach/tc.h>
#include <mach/board.h>
#include <mach/mux.h>
#include <mach/gpio.h>
#include <mach/eac.h>
#include <mach/mmc.h>
#if defined(CONFIG_OMAP_DSP) || defined(CONFIG_OMAP_DSP_MODULE)
#define OMAP2_MBOX_BASE IO_ADDRESS(OMAP24XX_MAILBOX_BASE)
static struct resource mbox_resources[] = {
{
.start = OMAP2_MBOX_BASE,
.end = OMAP2_MBOX_BASE + 0x11f,
.flags = IORESOURCE_MEM,
},
{
.start = INT_24XX_MAIL_U0_MPU,
.flags = IORESOURCE_IRQ,
},
{
.start = INT_24XX_MAIL_U3_MPU,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device mbox_device = {
.name = "mailbox",
.id = -1,
.num_resources = ARRAY_SIZE(mbox_resources),
.resource = mbox_resources,
};
static inline void omap_init_mbox(void)
{
platform_device_register(&mbox_device);
}
#else
static inline void omap_init_mbox(void) { }
#endif
#if defined(CONFIG_OMAP_STI)
#if defined(CONFIG_ARCH_OMAP2)
#define OMAP2_STI_BASE 0x48068000
#define OMAP2_STI_CHANNEL_BASE 0x54000000
#define OMAP2_STI_IRQ 4
static struct resource sti_resources[] = {
{
.start = OMAP2_STI_BASE,
.end = OMAP2_STI_BASE + 0x7ff,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP2_STI_CHANNEL_BASE,
.end = OMAP2_STI_CHANNEL_BASE + SZ_64K - 1,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP2_STI_IRQ,
.flags = IORESOURCE_IRQ,
}
};
#elif defined(CONFIG_ARCH_OMAP3)
#define OMAP3_SDTI_BASE 0x54500000
#define OMAP3_SDTI_CHANNEL_BASE 0x54600000
static struct resource sti_resources[] = {
{
.start = OMAP3_SDTI_BASE,
.end = OMAP3_SDTI_BASE + 0xFFF,
.flags = IORESOURCE_MEM,
},
{
.start = OMAP3_SDTI_CHANNEL_BASE,
.end = OMAP3_SDTI_CHANNEL_BASE + SZ_1M - 1,
.flags = IORESOURCE_MEM,
}
};
#endif
static struct platform_device sti_device = {
.name = "sti",
.id = -1,
.num_resources = ARRAY_SIZE(sti_resources),
.resource = sti_resources,
};
static inline void omap_init_sti(void)
{
platform_device_register(&sti_device);
}
#else
static inline void omap_init_sti(void) {}
#endif
#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
#include <mach/mcspi.h>
#define OMAP2_MCSPI1_BASE 0x48098000
#define OMAP2_MCSPI2_BASE 0x4809a000
#define OMAP2_MCSPI3_BASE 0x480b8000
#define OMAP2_MCSPI4_BASE 0x480ba000
static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
.num_cs = 4,
};
static struct resource omap2_mcspi1_resources[] = {
{
.start = OMAP2_MCSPI1_BASE,
.end = OMAP2_MCSPI1_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device omap2_mcspi1 = {
.name = "omap2_mcspi",
.id = 1,
.num_resources = ARRAY_SIZE(omap2_mcspi1_resources),
.resource = omap2_mcspi1_resources,
.dev = {
.platform_data = &omap2_mcspi1_config,
},
};
static struct omap2_mcspi_platform_config omap2_mcspi2_config = {
.num_cs = 2,
};
static struct resource omap2_mcspi2_resources[] = {
{
.start = OMAP2_MCSPI2_BASE,
.end = OMAP2_MCSPI2_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device omap2_mcspi2 = {
.name = "omap2_mcspi",
.id = 2,
.num_resources = ARRAY_SIZE(omap2_mcspi2_resources),
.resource = omap2_mcspi2_resources,
.dev = {
.platform_data = &omap2_mcspi2_config,
},
};
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
static struct omap2_mcspi_platform_config omap2_mcspi3_config = {
.num_cs = 2,
};
static struct resource omap2_mcspi3_resources[] = {
{
.start = OMAP2_MCSPI3_BASE,
.end = OMAP2_MCSPI3_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device omap2_mcspi3 = {
.name = "omap2_mcspi",
.id = 3,
.num_resources = ARRAY_SIZE(omap2_mcspi3_resources),
.resource = omap2_mcspi3_resources,
.dev = {
.platform_data = &omap2_mcspi3_config,
},
};
#endif
#ifdef CONFIG_ARCH_OMAP3
static struct omap2_mcspi_platform_config omap2_mcspi4_config = {
.num_cs = 1,
};
static struct resource omap2_mcspi4_resources[] = {
{
.start = OMAP2_MCSPI4_BASE,
.end = OMAP2_MCSPI4_BASE + 0xff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device omap2_mcspi4 = {
.name = "omap2_mcspi",
.id = 4,
.num_resources = ARRAY_SIZE(omap2_mcspi4_resources),
.resource = omap2_mcspi4_resources,
.dev = {
.platform_data = &omap2_mcspi4_config,
},
};
#endif
static void omap_init_mcspi(void)
{
platform_device_register(&omap2_mcspi1);
platform_device_register(&omap2_mcspi2);
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3)
platform_device_register(&omap2_mcspi3);
#endif
#ifdef CONFIG_ARCH_OMAP3
platform_device_register(&omap2_mcspi4);
#endif
}
#else
static inline void omap_init_mcspi(void) {}
#endif
#ifdef CONFIG_SND_OMAP24XX_EAC
#define OMAP2_EAC_BASE 0x48090000
static struct resource omap2_eac_resources[] = {
{
.start = OMAP2_EAC_BASE,
.end = OMAP2_EAC_BASE + 0x109,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device omap2_eac_device = {
.name = "omap24xx-eac",
.id = -1,
.num_resources = ARRAY_SIZE(omap2_eac_resources),
.resource = omap2_eac_resources,
.dev = {
.platform_data = NULL,
},
};
void omap_init_eac(struct eac_platform_data *pdata)
{
omap2_eac_device.dev.platform_data = pdata;
platform_device_register(&omap2_eac_device);
}
#else
void omap_init_eac(struct eac_platform_data *pdata) {}
#endif
#ifdef CONFIG_OMAP_SHA1_MD5
static struct resource sha1_md5_resources[] = {
{
.start = OMAP24XX_SEC_SHA1MD5_BASE,
.end = OMAP24XX_SEC_SHA1MD5_BASE + 0x64,
.flags = IORESOURCE_MEM,
},
{
.start = INT_24XX_SHA1MD5,
.flags = IORESOURCE_IRQ,
}
};
static struct platform_device sha1_md5_device = {
.name = "OMAP SHA1/MD5",
.id = -1,
.num_resources = ARRAY_SIZE(sha1_md5_resources),
.resource = sha1_md5_resources,
};
static void omap_init_sha1_md5(void)
{
platform_device_register(&sha1_md5_device);
}
#else
static inline void omap_init_sha1_md5(void) { }
#endif
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
int controller_nr)
{
if (cpu_is_omap2420() && controller_nr == 0) {
omap_cfg_reg(H18_24XX_MMC_CMD);
omap_cfg_reg(H15_24XX_MMC_CLKI);
omap_cfg_reg(G19_24XX_MMC_CLKO);
omap_cfg_reg(F20_24XX_MMC_DAT0);
omap_cfg_reg(F19_24XX_MMC_DAT_DIR0);
omap_cfg_reg(G18_24XX_MMC_CMD_DIR);
if (mmc_controller->slots[0].wire4) {
omap_cfg_reg(H14_24XX_MMC_DAT1);
omap_cfg_reg(E19_24XX_MMC_DAT2);
omap_cfg_reg(D19_24XX_MMC_DAT3);
omap_cfg_reg(E20_24XX_MMC_DAT_DIR1);
omap_cfg_reg(F18_24XX_MMC_DAT_DIR2);
omap_cfg_reg(E18_24XX_MMC_DAT_DIR3);
}
/*
* Use internal loop-back in MMC/SDIO Module Input Clock
* selection
*/
if (mmc_controller->slots[0].internal_clock) {
u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
v |= (1 << 24);
omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
}
}
}
void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
int nr_controllers)
{
int i;
for (i = 0; i < nr_controllers; i++) {
unsigned long base, size;
unsigned int irq = 0;
if (!mmc_data[i])
continue;
omap2_mmc_mux(mmc_data[i], i);
switch (i) {
case 0:
base = OMAP2_MMC1_BASE;
irq = INT_24XX_MMC_IRQ;
break;
case 1:
base = OMAP2_MMC2_BASE;
irq = INT_24XX_MMC2_IRQ;
break;
case 2:
if (!cpu_is_omap34xx())
return;
base = OMAP3_MMC3_BASE;
irq = INT_34XX_MMC3_IRQ;
break;
default:
continue;
}
if (cpu_is_omap2420())
size = OMAP2420_MMC_SIZE;
else
size = HSMMC_SIZE;
omap_mmc_add(i, base, size, irq, mmc_data[i]);
};
}
#endif
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
#define OMAP_HDQ_BASE 0x480B2000
#endif
static struct resource omap_hdq_resources[] = {
{
.start = OMAP_HDQ_BASE,
.end = OMAP_HDQ_BASE + 0x1C,
.flags = IORESOURCE_MEM,
},
{
.start = INT_24XX_HDQ_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device omap_hdq_dev = {
.name = "omap_hdq",
.id = 0,
.dev = {
.platform_data = NULL,
},
.num_resources = ARRAY_SIZE(omap_hdq_resources),
.resource = omap_hdq_resources,
};
static inline void omap_hdq_init(void)
{
(void) platform_device_register(&omap_hdq_dev);
}
#else
static inline void omap_hdq_init(void) {}
#endif
/*-------------------------------------------------------------------------*/
static int __init omap2_init_devices(void)
{
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
omap_init_mbox();
omap_init_mcspi();
omap_hdq_init();
omap_init_sti();
omap_init_sha1_md5();
return 0;
}
arch_initcall(omap2_init_devices);