From: David Brownell Date: Fri, 1 Jul 2005 12:16:11 +0000 (-0700) Subject: [PATCH] ARM: OMAP: MMC initialization X-Git-Tag: v2.6.13-omap1~82 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=4014a6befde8f6a993586907eb6a44df824a70f2;p=linux-2.6-omap-h63xx.git [PATCH] ARM: OMAP: MMC initialization This updates the MMC initialization: - OMAP_TAG_MMC updates: * Re-factor contents into one struct per silicon block * Provide information that's useful for SD support, like whether the board is wired for 4-wire transfers and what gpio (if any) is used to sense the writeprotect slider. * Allows for "nonstandard" muxing options, which would mostly affect boards using MMC2. * Report whether the MMC switch should use the card detect model, or the cover switch model. * Updated/tested board config only for H2 (not H3 or VoiceBlue). - MMC device initialization moved into mach-omap/omap1/device.c and out of the MMC driver itself. - Removed the "what MMC blocks to configure" option from Kconfig; the board-specific MMC tag holds this info (and more). This new device init hook should be easy to reuse to set up any of the other integrated devices. Signed-off-by: David Brownell --- diff --git a/arch/arm/mach-omap/omap1/Makefile b/arch/arm/mach-omap/omap1/Makefile index c19772f11dd..181a93deaae 100644 --- a/arch/arm/mach-omap/omap1/Makefile +++ b/arch/arm/mach-omap/omap1/Makefile @@ -3,7 +3,7 @@ # # Common support -obj-y := io.o id.o irq.o time.o serial.o +obj-y := io.o id.o irq.o time.o serial.o devices.o led-y := leds.o # Specific board support diff --git a/arch/arm/mach-omap/omap1/board-h2.c b/arch/arm/mach-omap/omap1/board-h2.c index c695af8aec0..ad05605f7f7 100644 --- a/arch/arm/mach-omap/omap1/board-h2.c +++ b/arch/arm/mach-omap/omap1/board-h2.c @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -151,9 +152,13 @@ static struct omap_usb_config h2_usb_config __initdata = { }; static struct omap_mmc_config h2_mmc_config __initdata = { - .mmc_blocks = 1, - .mmc1_power_pin = -1, /* tps65010 gpio3 */ - .mmc1_switch_pin = OMAP_MPUIO(1), + .mmc [0] = { + .enabled = 1, + .wire4 = 1, + .wp_pin = OMAP_MPUIO(3), + .power_pin = -1, /* tps65010 gpio3 */ + .switch_pin = OMAP_MPUIO(1), + }, }; static struct omap_board_config_kernel h2_config[] = { @@ -169,6 +174,10 @@ static void __init h2_init(void) h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys(); h2_flash_resource.end += SZ_32M - 1; + /* MMC: card detect and WP */ + // omap_cfg_reg(U19_ARMIO1); /* CD */ + omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */ + platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); omap_board_config = h2_config; omap_board_config_size = ARRAY_SIZE(h2_config); diff --git a/arch/arm/mach-omap/omap1/board-h3.c b/arch/arm/mach-omap/omap1/board-h3.c index 533bb4470d8..34cbd421995 100644 --- a/arch/arm/mach-omap/omap1/board-h3.c +++ b/arch/arm/mach-omap/omap1/board-h3.c @@ -161,10 +161,12 @@ static struct omap_usb_config h3_usb_config __initdata = { .pins[1] = 3, }; -static struct omap_mmc_config h3_mmc_config __initdata_or_module = { - .mmc_blocks = 1, - .mmc1_power_pin = -1, /* tps65010 GPIO4 */ - .mmc1_switch_pin = OMAP_MPUIO(1), +static struct omap_mmc_config h3_mmc_config __initdata = { + .mmc[0] = { + .enabled = 1, + .power_pin = -1, /* tps65010 GPIO4 */ + .switch_pin = OMAP_MPUIO(1), + }, }; static struct omap_board_config_kernel h3_config[] = { diff --git a/arch/arm/mach-omap/omap1/board-voiceblue.c b/arch/arm/mach-omap/omap1/board-voiceblue.c index 7b0ab909c34..1cff4a415cd 100644 --- a/arch/arm/mach-omap/omap1/board-voiceblue.c +++ b/arch/arm/mach-omap/omap1/board-voiceblue.c @@ -144,9 +144,11 @@ static struct omap_usb_config voiceblue_usb_config __initdata = { }; static struct omap_mmc_config voiceblue_mmc_config __initdata = { - .mmc_blocks = 1, - .mmc1_power_pin = 2, - .mmc1_switch_pin = -1, + .mmc[0] = { + .enabled = 1, + .power_pin = 2, + .switch_pin = -1, + }, }; static struct omap_boot_reason_config voiceblue_boot_reason; diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index b094a95cc3a..89e50528894 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -77,25 +77,6 @@ config MMC_OMAP If unsure, say N. -config MMC_OMAP16XX_BLOCK1 - boolean "First MMC block on OMAP16XX" - depends on ARCH_OMAP16XX && MMC_OMAP - default y if MACH_OMAP_H2 || MACH_OMAP_H3 - help - This enables the first of two MMC blocks on OMAP1610 multimedia - processor. You need to enable the correct block to activate your - MMC slot. - -config MMC_OMAP16XX_BLOCK2 - boolean "Second MMC block on OMAP16XX" - depends on ARCH_OMAP16XX && MMC_OMAP - default n if MACH_OMAP_H2 || MACH_OMAP_H3 - default y - help - This enables the second of two MMC blocks on OMAP1610 multimedia - processor. You need to enable the correct block to activate your - MMC slot. - config MMC_WBSD tristate "Winbond W83L51xD SD/MMC Card Interface support" depends on MMC && ISA_DMA_API diff --git a/drivers/mmc/omap.c b/drivers/mmc/omap.c index 2c034e8cc47..9b5e4e8c2e8 100644 --- a/drivers/mmc/omap.c +++ b/drivers/mmc/omap.c @@ -44,8 +44,8 @@ #define DRIVER_NAME "mmci-omap" #ifdef CONFIG_MMC_DEBUG -//#define DBG(x...) printk(KERN_DEBUG x) -#define DBG(x...) printk(x) +#define DBG(x...) pr_debug(x) +//#define DBG(x...) printk(x) #else #define DBG(x...) do { } while (0) #endif @@ -54,11 +54,6 @@ * when the cover switch is open */ #define OMAP_MMC_SWITCH_POLL_DELAY 500 -static s16 mmc1_power_pin = -1, - mmc2_power_pin = -1; -static s16 mmc1_switch_pin = -1, - mmc2_switch_pin = -1; - static int mmc_omap_enable_poll = 1; struct mmc_omap_host { @@ -81,17 +76,15 @@ struct mmc_omap_host { unsigned char datadir; u16 * buffer; u32 bytesleft; - int power_pin; - - int use_dma, dma_ch; + short power_pin; + short wp_pin; + short use_dma, dma_ch; struct completion dma_completion; int switch_pin; struct work_struct switch_work; struct timer_list switch_timer; int switch_last_state; - - unsigned char sd_support; }; static inline int @@ -394,11 +387,11 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs) } if (status & OMAP_MMC_STAT_CMD_TOUT) { - // Command timeout + /* Timeouts are routine with some commands */ if (host->cmd) { - /* Timeouts are normal in case of MMC_SEND_STATUS */ if (host->cmd->opcode != MMC_ALL_SEND_CID && host->cmd->opcode != MMC_SEND_OP_COND && + host->cmd->opcode != MMC_APP_CMD && !mmc_omap_cover_is_open(host)) printk(KERN_ERR "MMC%d: Command timeout, CMD%d\n", host->id, host->cmd->opcode); @@ -417,10 +410,10 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id, struct pt_regs *regs) } if (status & OMAP_MMC_STAT_OCR_BUSY) { - // OCR Busy - if (host->cmd && host->cmd->opcode != MMC_SEND_OP_COND && - host->cmd->opcode != MMC_SET_RELATIVE_ADDR) { - printk(KERN_DEBUG "MMC%d: OCR busy error, CMD%d\n", + /* OCR Busy ... happens a lot */ + if (host->cmd && host->cmd->opcode != MMC_SEND_OP_COND + && host->cmd->opcode != MMC_SET_RELATIVE_ADDR) { + DBG("MMC%d: OCR busy error, CMD%d\n", host->id, host->cmd->opcode); } } @@ -849,6 +842,8 @@ static void mmc_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) dsor = 250; } + /* REVISIT: if (ios->bus_width == MMC_BUS_WIDTH_4) dsor |= 1 << 15; */ + switch (ios->power_mode) { case MMC_POWER_OFF: mmc_omap_power(host, 0); @@ -887,6 +882,7 @@ static struct mmc_host_ops mmc_omap_ops = { static int __init mmc_omap_probe(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); + struct omap_mmc_conf *minfo = dev->platform_data; struct mmc_host *mmc; struct mmc_omap_host *host = NULL; int ret = 0; @@ -913,7 +909,7 @@ static int __init mmc_omap_probe(struct device *dev) host = mmc_priv(mmc); host->mmc = mmc; - host->id = (pdev->resource[0].start == IO_ADDRESS(OMAP_MMC1_BASE)) ? 1 : 2; + host->id = pdev->id; host->clk = clk_get(dev, (host->id == 1) ? "mmc1_ck" : "mmc2_ck"); if (IS_ERR(host->clk)) { @@ -921,46 +917,15 @@ static int __init mmc_omap_probe(struct device *dev) goto out; } - if (host->id == 1) { - omap_cfg_reg(MMC_CMD); - omap_cfg_reg(MMC_CLK); - omap_cfg_reg(MMC_DAT0); - if (cpu_is_omap1710()) { - omap_cfg_reg(M15_1710_MMC_CLKI); - omap_cfg_reg(P19_1710_MMC_CMDDIR); - omap_cfg_reg(P20_1710_MMC_DATDIR0); - } - if (host->sd_support) { - omap_cfg_reg(MMC_DAT1); - omap_cfg_reg(MMC_DAT2); - omap_cfg_reg(MMC_DAT3); - } - host->power_pin = mmc1_power_pin; - host->switch_pin = mmc1_switch_pin; - } else { - omap_cfg_reg(Y8_1610_MMC2_CMD); - omap_cfg_reg(Y10_1610_MMC2_CLK); - omap_cfg_reg(R18_1610_MMC2_CLKIN); - omap_cfg_reg(W8_1610_MMC2_DAT0); - if (host->sd_support) { - omap_cfg_reg(V8_1610_MMC2_DAT1); - omap_cfg_reg(W15_1610_MMC2_DAT2); - omap_cfg_reg(R10_1610_MMC2_DAT3); - } - - /* These are needed for the level shifter */ - omap_cfg_reg(V9_1610_MMC2_CMDDIR); - omap_cfg_reg(V5_1610_MMC2_DATDIR0); - omap_cfg_reg(W19_1610_MMC2_DATDIR1); - - host->power_pin = mmc2_power_pin; - host->switch_pin = mmc2_switch_pin; - - /* Feedback clock must be set on OMAP-1710 MMC2 */ - if (cpu_is_omap1710()) - omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24), - MOD_CONF_CTRL_1); - } + /* REVISIT: SD-only support, when core merged + * - if (minfo->wire4) mmc->caps |= MMC_CAP_4_BIT_DATA; + * - mmc_omap_ops.get_ro uses wp_pin to sense slider + * Also, use minfo->cover to decide how to manage + * the card detect sensing. + */ + host->power_pin = minfo->power_pin; + host->switch_pin = minfo->switch_pin; + host->wp_pin = minfo->wp_pin; host->use_dma = 1; host->dma_ch = -1; @@ -1122,60 +1087,6 @@ static int mmc_omap_resume(struct device *dev, u32 level) #define mmc_omap_resume NULL #endif -static void mmc_release(struct device *dev) -{ - /* Nothing to release? */ -} - -static struct resource mmc1_resources[] = { - { - .start = IO_ADDRESS(OMAP_MMC1_BASE), - .end = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_MMC, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct resource mmc2_resources[] = { - { - .start = IO_ADDRESS(OMAP_MMC2_BASE), - .end = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f, - .flags = IORESOURCE_MEM, - }, - { - .start = INT_1610_MMC2, - .flags = IORESOURCE_IRQ, - }, -}; - - -static u64 mmc_dmamask = 0xffffffff; - -static struct platform_device mmc_omap_device1 = { - .name = "mmci-omap", - .id = 1, - .dev = { - .release = mmc_release, - .dma_mask = &mmc_dmamask, - }, - .num_resources = ARRAY_SIZE(mmc1_resources), - .resource = mmc1_resources, -}; - -static struct platform_device mmc_omap_device2 = { - .name = "mmci-omap", - .id = 2, - .dev = { - .release = mmc_release, - .dma_mask = &mmc_dmamask, - }, - .num_resources = ARRAY_SIZE(mmc2_resources), - .resource = mmc2_resources, -}; - static struct device_driver mmc_omap_driver = { .name = "mmci-omap", .bus = &platform_bus_type, @@ -1185,72 +1096,14 @@ static struct device_driver mmc_omap_driver = { .resume = mmc_omap_resume, }; -static int enable_blocks = 0; - static int __init mmc_omap_init(void) { - int ret; - const struct omap_mmc_config *minfo; - - minfo = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config); - if (minfo != NULL) { - enable_blocks = minfo->mmc_blocks; - if (enable_blocks & 1) { - mmc1_power_pin = minfo->mmc1_power_pin; - mmc1_switch_pin = minfo->mmc1_switch_pin; - } - if (enable_blocks & 2) { - mmc2_power_pin = minfo->mmc2_power_pin; - mmc2_switch_pin = minfo->mmc2_switch_pin; - } - } else { -#if defined(CONFIG_ARCH_OMAP1510) || defined(CONFIG_MMC_OMAP16XX_BLOCK1) - enable_blocks |= 1; -#endif -#if defined(CONFIG_MMC_OMAP16XX_BLOCK2) - enable_blocks |= 2; -#endif - } - if (enable_blocks == 0) { - printk(KERN_INFO "OMAP MMC driver not loaded\n"); - return -ENODEV; - } - - if (enable_blocks & 1) { - ret = platform_device_register(&mmc_omap_device1); - if (ret != 0) - return -ENODEV; - } - - if (enable_blocks & 2) { - ret = platform_device_register(&mmc_omap_device2); - if (ret != 0) - goto free1; - } - - ret = driver_register(&mmc_omap_driver); - if (ret == 0) - return 0; - - if (enable_blocks & 2) - platform_device_unregister(&mmc_omap_device2); - -free1: - if (enable_blocks & 1) - platform_device_unregister(&mmc_omap_device1); - - return -ENODEV; + return driver_register(&mmc_omap_driver); } static void __exit mmc_omap_exit(void) { driver_unregister(&mmc_omap_driver); - - if (enable_blocks & 2) - platform_device_unregister(&mmc_omap_device2); - - if (enable_blocks & 1) - platform_device_unregister(&mmc_omap_device1); } module_init(mmc_omap_init); diff --git a/drivers/mmc/omap.h b/drivers/mmc/omap.h index 9ab89b73692..c954d355a5e 100644 --- a/drivers/mmc/omap.h +++ b/drivers/mmc/omap.h @@ -1,9 +1,6 @@ #ifndef DRIVERS_MEDIA_MMC_OMAP_H #define DRIVERS_MEDIA_MMC_OMAP_H -#define OMAP_MMC1_BASE 0xfffb7800 -#define OMAP_MMC2_BASE 0xfffb7c00 - #define OMAP_MMC_REG_CMD 0x00 #define OMAP_MMC_REG_ARGL 0x04 #define OMAP_MMC_REG_ARGH 0x08 diff --git a/include/asm-arm/arch-omap/board.h b/include/asm-arm/arch-omap/board.h index d45fe719db6..cdaa161b7d5 100644 --- a/include/asm-arm/arch-omap/board.h +++ b/include/asm-arm/arch-omap/board.h @@ -30,10 +30,23 @@ struct omap_clock_config { u8 system_clock_type; }; +struct omap_mmc_conf { + unsigned enabled:1; + /* nomux means "standard" muxing is wrong on this board, and that + * board-specific code handled it before common init logic. + */ + unsigned nomux:1; + /* switch pin can be for card detect (default) or card cover */ + unsigned cover:1; + /* 4 wire signaling is optional, and is only used for SD/SDIO */ + unsigned wire4:1; + s16 power_pin; + s16 switch_pin; + s16 wp_pin; +}; + struct omap_mmc_config { - u8 mmc_blocks; - s16 mmc1_power_pin, mmc2_power_pin; - s16 mmc1_switch_pin, mmc2_switch_pin; + struct omap_mmc_conf mmc[2]; }; struct omap_serial_console_config {