Hi, Please do not post in html format to the list. Use plain text format. >I am using OMAP-2430 based custom board. I am facing some issue with MMC >card detection. When I use NFS as file system my card is getting detected. I >have a requirement of using ramdisk as the filesystem, which is of size >20MB.When I use 20MB ramdisk as the filesystem, the MMC card is not getting >detected. The usage of any root filesystem (NFS or Ramdisk) should not have any impact on how the driver works.I did not face any such issue when I test the driver on our boards. >I want to give you one more input. When I use 4MB ramdisk, the mmc driver >detects the card. I think its a timing issue. I changed in the architecture >specific file (arch/arm/mach-omap/board-2530xxx-mmc.c) the following and got >my card detected by the driver. The 100ms time is required for PBIAS to stabilize. I tested this on our 2430 as well as 3430 SDP's. This delay has no relation to what type of file system is being used. This delay is required while MMC power up sequence only. I think you should debug this on your board a little bit instead of directly increasing this delay. Regards, Madhu ________________________________ From: Arun KS [mailto:getarunks@xxxxxxxxx] Sent: Wednesday, December 26, 2007 6:05 PM To: Madhusudhan Chikkature Rajashekar Cc: linux-omap@xxxxxxxxxxxxxxx Subject: Re: [Resending: PATCH 2/6] MMC/SD board specific update for OMAP2430/3430 Dear Madhu, I am using OMAP-2430 based custom board. I am facing some issue with MMC card detection. When I use NFS as file system my card is getting detected. I have a requirement of using ramdisk as the filesystem, which is of size 20MB. When I use 20MB ramdisk as the filesystem, the MMC card is not getting detected. I want to give you one more input. When I use 4MB ramdisk, the mmc driver detects the card. I think its a timing issue. I changed in the architecture specific file (arch/arm/mach-omap/board-2530xxx-mmc.c) the following and got my card detected by the driver. ret = twl4030_i2c_write_u8(TWL4030 _MODULE_PM_RECEIVER, VSEL_S2_CLR, VMMC1_DEDICATED); if (ret != 0) goto err; //msleep(100); mdelay(5000); omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) | 0x7, OMAP2_CONTROL_PBIAS); And I think this is not the right way to make it work. Please provide your suggestions/comments on this. Thanks Arun K S On Dec 20, 2007 3:34 PM, Madhusudhan Chikkature Rajashekar <madhu.cr@xxxxxx> wrote: This patch adds OMAP2430/3430 MMC board specific file. Signed-off-by: Madhusudhan Chikkature<madhu.cr@xxxxxx> --- arch/arm/mach-omap2/Makefile | 6 arch/arm/mach-omap2/board-2430sdp.c | 9 arch/arm/mach-omap2/board-3430sdp.c | 9 arch/arm/mach-omap2/board-sdp-hsmmc.c | 277 ++++++++++++++++++++++++++++++ include/asm-arm/arch-omap/board- 2430sdp.h | 1 include/asm-arm/arch-omap/board-3430sdp.h | 1 include/asm-arm/arch-omap/mmc.h | 4 7 files changed, 305 insertions(+), 2 deletions(-) Index: linux-omap-2.6/arch/arm/mach-omap2/Makefile =================================================================== --- linux-omap-2.6.orig/arch/arm/mach-omap2/Makefile 2007-12-18 17:35:45.000000000 +0530 +++ linux-omap-2.6/arch/arm/mach-omap2/Makefile 2007-12-20 09:58: 19.406872653 +0530 @@ -24,10 +24,12 @@ obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \ board-2430sdp-flash.o \ - board-2430sdp-usb.o + board-2430sdp-usb.o \ + board-sdp-hsmmc.o obj-$(CONFIG_MACH_OMAP_2430OSK) += board-2430osk.o obj-$(CONFIG_MACH_OMAP_3430SDP) += board-3430sdp.o \ - board-3430sdp-usb.o + board-3430sdp-usb.o \ + board-sdp-hsmmc.o obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o \ board-apollon-mmc.o \ board-apollon-keys.o Index: linux-omap-2.6/arch/arm/mach-omap2/board-2430sdp.c =================================================================== --- linux-omap-2.6.orig/arch/arm/mach-omap2/board-2430sdp.c 2007-12-18 17:35: 45.000000000 +0530 +++ linux-omap-2.6/arch/arm/mach-omap2/board-2430sdp.c 2007-12-20 13:43:30.478304771 +0530 @@ -355,10 +355,18 @@ .console_speed = 115200, }; +static struct omap_mmc_config sdp2430_mmc_config __initdata = { + .mmc [0] = { + .enabled = 1, + .wire4 = 1, + }, +}; + static struct omap_board_config_kernel sdp2430_config[] __initdata = { {OMAP_TAG_UART, &sdp2430_uart_config}, {OMAP_TAG_LCD, &sdp2430_lcd_config}, {OMAP_TAG_SERIAL_CONSOLE, &sdp2430_serial_console_config}, + {OMAP_TAG_MMC, &sdp2430_mmc_config}, }; static int __init omap2430_i2c_init(void) @@ -381,6 +389,7 @@ spi_register_board_info(sdp2430_spi_board_info, ARRAY_SIZE(sdp2430_spi_board_info)); ads7846_dev_init(); + sdp_mmc_init(); /* turn off secondary LCD backlight */ omap_set_gpio_direction(SECONDARY_LCD_GPIO, 0); Index: linux-omap-2.6/arch/arm/mach-omap2/board-3430sdp.c =================================================================== --- linux-omap-2.6.orig/arch/arm/mach-omap2/board- 3430sdp.c 2007-12-18 17:35:45.000000000 +0530 +++ linux-omap-2.6/arch/arm/mach-omap2/board-3430sdp.c 2007-12-20 13:44:43.101999310 +0530 @@ -307,9 +307,17 @@ .ctrl_name = "internal", }; +static struct omap_mmc_config sdp3430_mmc_config __initdata = { + .mmc [0] = { + .enabled = 1, + .wire4 = 1, + }, +}; + static struct omap_board_config_kernel sdp3430_config[] __initdata = { { OMAP_TAG_UART, &sdp3430_uart_config }, {OMAP_TAG_LCD, &sdp3430_lcd_config}, + {OMAP_TAG_MMC, &sdp3430_mmc_config }, }; static int __init omap3430_i2c_init(void) @@ -330,6 +338,7 @@ ads7846_dev_init(); omap_serial_init(); sdp3430_usb_init(); + sdp_mmc_init(); } static void __init omap_3430sdp_map_io(void) Index: linux-omap-2.6 /arch/arm/mach-omap2/board-sdp-hsmmc.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-omap-2.6/arch/arm/mach-omap2/board-sdp-hsmmc.c 2007-12-20 11:55:12.960615567 +0530 @@ -0,0 +1,277 @@ +/* + * linux/arch/arm/mach-omap2/board-sdp-hsmmc.c + * + * Copyright (C) 2007 Texas Instruments + * Author: Texas Instruments + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/err.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/delay.h> +#include <asm/hardware.h> +#include <asm/arch/twl4030.h> +#include <asm/arch/mmc.h> +#include <asm/arch/board.h> +#include <asm/io.h> + +#ifdef CONFIG_MMC_OMAP_HS + +#define VMMC1_DEV_GRP 0x27 +#define P1_DEV_GRP 0x20 +#define VMMC1_DEDICATED 0x2A +#define VSEL_3V 0x02 +#define VSEL_18V 0x00 +#define TWL_GPIO_PUPDCTR1 0x13 +#define TWL_GPIO_IMR1A 0x1C +#define TWL_GPIO_ISR1A 0x19 +#define LDO_CLR 0x00 +#define VSEL_S2_CLR 0x40 +#define GPIO_0_BIT_POS 1 << 0 +#define MMC1_CD_IRQ 0 +#define MMC2_CD_IRQ 1 + +static irqreturn_t mmc_omap_cd_handler(int irq, void *dev_id) +{ + int detect; + + detect = twl4030_get_gpio_datain(MMC1_CD_IRQ); + omap_mmc_notify_card_detect(dev_id, 0, detect); + return IRQ_HANDLED; +} + +/* + * MMC Slot Initialization. + */ +static int sdp_mmc_late_init(struct device *dev) +{ + int ret = 0; + + /* + * Configure TWL4030 GPIO parameters for MMC hotplug irq + */ + ret = twl4030_request_gpio(MMC1_CD_IRQ); + if (ret != 0) + goto err; + + ret = twl4030_set_gpio_edge_ctrl(MMC1_CD_IRQ, + TWL4030_GPIO_EDGE_RISING | TWL4030_GPIO_EDGE_FALLING); + if (ret != 0) + goto err; + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, 0x02, + TWL_GPIO_PUPDCTR1); + if (ret != 0) + goto err; + + ret = twl4030_set_gpio_debounce(MMC1_CD_IRQ, TWL4030_GPIO_IS_ENABLE); + if (ret != 0) + goto err; + + ret = request_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ), + mmc_omap_cd_handler, IRQF_DISABLED, "MMC1_CD_IRQ", dev); + if (ret < 0) + goto err; + + return ret; +err: + dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n"); + + return ret; +} + +static void sdp_mmc_cleanup(struct device *dev) +{ + int ret = 0; + + ret = twl4030_free_gpio(MMC1_CD_IRQ); + free_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ), dev); + if (ret != 0) + dev_err(dev, "Failed to configure TWL4030 GPIO IRQ\n"); +} + +#ifdef CONFIG_PM + +/* + * To mask and unmask MMC Card Detect Interrupt + * mask : 1 + * unmask : 0 + */ +static int mask_cd_interrupt(int mask) +{ + u8 reg = 0, ret = 0; + + ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, ®, TWL_GPIO_IMR1A); + if (ret != 0) + goto err; + + reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS); + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_IMR1A); + if (ret != 0) + goto err; + + ret = twl4030_i2c_read_u8(TWL4030_MODULE_GPIO, ®, TWL_GPIO_ISR1A); + if (ret != 0) + goto err; + + reg = (mask == 1) ? (reg | GPIO_0_BIT_POS) : (reg & ~GPIO_0_BIT_POS); + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_GPIO, reg, TWL_GPIO_ISR1A); + if (ret != 0) + goto err; +err: + return ret; +} + +static int sdp_mmc_suspend(struct device *dev, int slot) +{ + int ret = 0; + + disable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ)); + ret = mask_cd_interrupt(1); + + return ret; +} + +static int sdp_mmc_resume(struct device *dev, int slot) +{ + int ret = 0; + + enable_irq(TWL4030_GPIO_IRQ_NO(MMC1_CD_IRQ)); + ret = mask_cd_interrupt(0); + + return ret; +} + +#endif + +static int sdp_mmc_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + u32 vdd_sel = 0, devconf = 0, reg = 0; + int ret = 0; + + /* REVISIT: Using address directly till the control.h defines + * are settled. + */ +#if defined(CONFIG_ARCH_OMAP2430) + #define OMAP2_CONTROL_PBIAS 0x490024A0 +#else + #define OMAP2_CONTROL_PBIAS 0x48002520 +#endif + + if (power_on == 1) { + if (cpu_is_omap24xx()) + devconf = omap_readl(0x490022E8); + else + devconf = omap_readl(0x48002274); + + switch (1 << vdd) { + case MMC_VDD_33_34: + case MMC_VDD_32_33: + vdd_sel = VSEL_3V; + if (cpu_is_omap24xx()) + devconf = (reg | (1 << 31)); + break; + case MMC_VDD_165_195: + vdd_sel = VSEL_18V; + if (cpu_is_omap24xx()) + devconf = (devconf & ~(1 << 31)); + } + + if (cpu_is_omap24xx()) + omap_writel(devconf, 0x490022E8); + else + omap_writel(devconf | 1 << 24, 0x48002274); + + omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) | 1 << 2, + OMAP2_CONTROL_PBIAS); + omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) & ~(1 << 1), + OMAP2_CONTROL_PBIAS); + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + P1_DEV_GRP, VMMC1_DEV_GRP); + if (ret != 0) + goto err; + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + vdd_sel, VMMC1_DEDICATED); + if (ret != 0) + goto err; + + msleep(100); + reg = omap_readl(OMAP2_CONTROL_PBIAS); + reg = (vdd_sel == VSEL_18V) ? ((reg | 0x6) & ~0x1) + : (reg | 0x7); + omap_writel(reg, OMAP2_CONTROL_PBIAS); + + return ret; + + } else if (power_on == 0) { + /* Power OFF */ + + /* For MMC1, Toggle PBIAS before every power up sequence */ + omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) & ~(1 << 1), + OMAP2_CONTROL_PBIAS); + ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + LDO_CLR, VMMC1_DEV_GRP); + if (ret != 0) + goto err; + + ret = twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, + VSEL_S2_CLR, VMMC1_DEDICATED); + if (ret != 0) + goto err; + + /* 100ms delay required for PBIAS configuration */ + msleep(100); + omap_writel(omap_readl(OMAP2_CONTROL_PBIAS) | 0x7, + OMAP2_CONTROL_PBIAS); + } else { + ret = -1; + goto err; + } + + return 0; +err: + return 1; +} + +static struct omap_mmc_platform_data sdp_mmc_data = { + .nr_slots = 1, + .switch_slot = NULL, + .init = sdp_mmc_late_init, + .cleanup = sdp_mmc_cleanup, +#ifdef CONFIG_PM + .suspend = sdp_mmc_suspend, + .resume = sdp_mmc_resume, +#endif + .slots[0] = { + .set_power = sdp_mmc_set_power, + .set_bus_mode = NULL, + .get_ro = NULL, + .get_cover_state = NULL, + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 | + MMC_VDD_165_195, + .name = "first slot", + }, +}; + +void __init sdp_mmc_init(void) +{ + omap_set_mmc_info(1, &sdp_mmc_data); +} + +#else + +void __init sdp_mmc_init(void) +{ + +} + +#endif Index: linux-omap-2.6/include/asm-arm/arch-omap/mmc.h =================================================================== --- linux-omap-2.6.orig/include/asm-arm/arch-omap/mmc.h 2007-12-18 17:35:47.000000000 +0530 +++ linux-omap-2.6 /include/asm-arm/arch-omap/mmc.h 2007-12-20 09:55:30.576241765 +0530 @@ -36,6 +36,10 @@ int (* init)(struct device *dev); void (* cleanup)(struct device *dev); + /* To handle board related suspend/resume functionality for MMC */ + int (*suspend)(struct device *dev, int slot); + int (*resume)(struct device *dev, int slot); + struct omap_mmc_slot_data { int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); int (* set_power)(struct device *dev, int slot, int power_on, int vdd); Index: linux-omap-2.6/include/asm-arm/arch-omap/board-2430sdp.h =================================================================== --- linux-omap-2.6.orig/include/asm-arm/arch-omap/board-2430sdp.h 2007-12-20 13:36:07.000000000 +0530 +++ linux-omap-2.6/include/asm-arm/arch-omap/board-2430sdp.h 2007-12-20 13:42:29.753232612 +0530 @@ -48,5 +48,6 @@ /* Function prototypes */ extern void __init sdp2430_flash_init(void); extern void __init sdp2430_usb_init(void); +extern void sdp_mmc_init(void); #endif /* __ASM_ARCH_OMAP_2430SDP_H */ Index: linux-omap-2.6 /include/asm-arm/arch-omap/board-3430sdp.h =================================================================== --- linux-omap-2.6.orig/include/asm-arm/arch-omap/board-3430sdp.h 2007-12-20 10:20:46.000000000 +0530 +++ linux-omap-2.6/include/asm-arm/arch-omap/board-3430sdp.h 2007-12-20 13:44:33.821293922 +0530 @@ -30,6 +30,7 @@ #define __ASM_ARCH_OMAP_3430SDP_H extern void sdp3430_usb_init(void); +extern void sdp_mmc_init(void); #define DEBUG_BASE 0x08000000 /* debug board */ - To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html - To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html