From 71461ca523de36365cb91c3b987c3361b6b496de Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 5 Nov 2008 19:24:37 -0800 Subject: [PATCH] HSMMC: Improve the interface for hsmmc_init() Improve the interface for hsmmc_init() Based on earlier code snippet and patch by David Brownell . Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-2430sdp.c | 11 ++- arch/arm/mach-omap2/board-3430sdp.c | 17 +++- arch/arm/mach-omap2/board-apollon-mmc.c | 2 +- arch/arm/mach-omap2/board-h4-mmc.c | 4 +- arch/arm/mach-omap2/board-ldp.c | 11 ++- arch/arm/mach-omap2/board-n800-mmc.c | 2 +- arch/arm/mach-omap2/board-omap2evm.c | 11 ++- arch/arm/mach-omap2/board-omap3beagle.c | 11 ++- arch/arm/mach-omap2/board-omap3evm.c | 11 ++- arch/arm/mach-omap2/board-omap3pandora.c | 11 ++- arch/arm/mach-omap2/board-overo.c | 17 +++- arch/arm/mach-omap2/devices.c | 2 +- arch/arm/mach-omap2/mmc-twl4030.c | 102 ++++++++++++++--------- arch/arm/mach-omap2/mmc-twl4030.h | 26 ++++++ arch/arm/plat-omap/include/mach/mmc.h | 6 +- drivers/mmc/host/omap.c | 2 +- drivers/mmc/host/omap_hsmmc.c | 2 +- 17 files changed, 187 insertions(+), 61 deletions(-) create mode 100644 arch/arm/mach-omap2/mmc-twl4030.h diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c index 8532ef380d2..e3a3131e698 100644 --- a/arch/arm/mach-omap2/board-2430sdp.c +++ b/arch/arm/mach-omap2/board-2430sdp.c @@ -387,6 +387,15 @@ static int __init omap2430_i2c_init(void) return 0; } +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + }, + {} /* Terminator */ +}; + static void __init omap_2430sdp_init(void) { omap2430_i2c_init(); @@ -404,7 +413,7 @@ static void __init omap_2430sdp_init(void) spi_register_board_info(sdp2430_spi_board_info, ARRAY_SIZE(sdp2430_spi_board_info)); ads7846_dev_init(); - hsmmc_init(HSMMC1); + hsmmc_init(mmc); /* turn off secondary LCD backlight */ omap_set_gpio_direction(SECONDARY_LCD_GPIO, 0); diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c index 1813c919bf2..f2dea78c16c 100644 --- a/arch/arm/mach-omap2/board-3430sdp.c +++ b/arch/arm/mach-omap2/board-3430sdp.c @@ -46,6 +46,7 @@ #include #include "sdram-qimonda-hyb18m512160af-6.h" +#include "mmc-twl4030.h" #define CONFIG_DISABLE_HFCLK 1 @@ -444,6 +445,20 @@ static int __init omap3430_i2c_init(void) return 0; } +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 8, + .gpio_cd = -EINVAL, + }, + { + .mmc = 2, + .wires = 8, + .gpio_cd = -EINVAL, + }, + {} /* Terminator */ +}; + extern void __init sdp3430_flash_init(void); static void __init omap_3430sdp_init(void) @@ -465,7 +480,7 @@ static void __init omap_3430sdp_init(void) omap_serial_init(); usb_musb_init(); usb_ehci_init(); - hsmmc_init(HSMMC1 | HSMMC2); + hsmmc_init(mmc); } static void __init omap_3430sdp_map_io(void) diff --git a/arch/arm/mach-omap2/board-apollon-mmc.c b/arch/arm/mach-omap2/board-apollon-mmc.c index 35c2c07b08d..3197741ec47 100644 --- a/arch/arm/mach-omap2/board-apollon-mmc.c +++ b/arch/arm/mach-omap2/board-apollon-mmc.c @@ -68,7 +68,7 @@ static struct omap_mmc_platform_data mmc1_data = { .cleanup = apollon_mmc_cleanup, .dma_mask = 0xffffffff, .slots[0] = { - .wire4 = 1, + .wires = 4, /* * Use internal loop-back in MMC/SDIO Module Input Clock diff --git a/arch/arm/mach-omap2/board-h4-mmc.c b/arch/arm/mach-omap2/board-h4-mmc.c index 06119e9d0f9..48c0358b781 100644 --- a/arch/arm/mach-omap2/board-h4-mmc.c +++ b/arch/arm/mach-omap2/board-h4-mmc.c @@ -231,7 +231,7 @@ static struct omap_mmc_platform_data mmc1_data = { .cleanup = h4_mmc_cleanup, .dma_mask = 0xffffffff, .slots[0] = { - .wire4 = 1, + .wires = 4, .set_power = h4_mmc_set_power, .set_bus_mode = h4_mmc_set_bus_mode, .get_cover_state= h4_mmc_slot1_cover_state, @@ -241,7 +241,7 @@ static struct omap_mmc_platform_data mmc1_data = { .name = "slot1", }, .slots[1] = { - .wire4 = 1, + .wires = 4, .set_power = h4_mmc_set_power, .set_bus_mode = h4_mmc_set_bus_mode, .get_cover_state= h4_mmc_slot2_cover_state, diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c index 54346c754be..cf79de8d6cb 100644 --- a/arch/arm/mach-omap2/board-ldp.c +++ b/arch/arm/mach-omap2/board-ldp.c @@ -338,6 +338,15 @@ static int __init omap_i2c_init(void) return 0; } +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + }, + {} /* Terminator */ +}; + static void __init omap_ldp_init(void) { omap_i2c_init(); @@ -352,7 +361,7 @@ static void __init omap_ldp_init(void) ads7846_dev_init(); omap_serial_init(); usb_musb_init(); - hsmmc_init(HSMMC1); + hsmmc_init(mmc); } static void __init omap_ldp_map_io(void) diff --git a/arch/arm/mach-omap2/board-n800-mmc.c b/arch/arm/mach-omap2/board-n800-mmc.c index 9242356f96c..8b78180242d 100644 --- a/arch/arm/mach-omap2/board-n800-mmc.c +++ b/arch/arm/mach-omap2/board-n800-mmc.c @@ -308,7 +308,7 @@ static struct omap_mmc_platform_data mmc1_data = { .max_freq = 24000000, .dma_mask = 0xffffffff, .slots[0] = { - .wire4 = 1, + .wires = 4, .set_power = n800_mmc_set_power, .set_bus_mode = n800_mmc_set_bus_mode, .get_cover_state= n800_mmc_get_cover_state, diff --git a/arch/arm/mach-omap2/board-omap2evm.c b/arch/arm/mach-omap2/board-omap2evm.c index 68aebe794d1..4cb85df2977 100644 --- a/arch/arm/mach-omap2/board-omap2evm.c +++ b/arch/arm/mach-omap2/board-omap2evm.c @@ -337,6 +337,15 @@ static struct platform_device *omap2_evm_devices[] __initdata = { &omap2evm_smc911x_device, }; +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + }, + {} /* Terminator */ +}; + static void __init omap2_evm_init(void) { omap2_evm_i2c_init(); @@ -347,7 +356,7 @@ static void __init omap2_evm_init(void) spi_register_board_info(omap2evm_spi_board_info, ARRAY_SIZE(omap2evm_spi_board_info)); omap_serial_init(); - hsmmc_init(HSMMC1); + hsmmc_init(mmc); omap2evm_flash_init(); ads7846_dev_init(); } diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 062a28b0061..0f1c841a29b 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -297,6 +297,15 @@ static void __init omap3beagle_flash_init(void) } } +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 8, + .gpio_cd = TWL4030_GPIO_IRQ_NO(0), + }, + {} /* Terminator */ +}; + static void __init omap3_beagle_init(void) { omap3_beagle_i2c_init(); @@ -309,7 +318,7 @@ static void __init omap3_beagle_init(void) omap_cfg_reg(AH8_34XX_GPIO29); gpio_request(29, "mmc0_wp"); gpio_direction_input(29); - hsmmc_init(HSMMC1); + hsmmc_init(mmc); omap_cfg_reg(J25_34XX_GPIO170); gpio_request(170, "DVI_nPD"); diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index 614fa02cd7a..eb21bc56517 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -233,6 +233,15 @@ static struct platform_device *omap3_evm_devices[] __initdata = { &omap3evm_smc911x_device, }; +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + }, + {} /* Terminator */ +}; + static void __init omap3_evm_init(void) { omap3_evm_i2c_init(); @@ -245,7 +254,7 @@ static void __init omap3_evm_init(void) ARRAY_SIZE(omap3evm_spi_board_info)); omap_serial_init(); - hsmmc_init(HSMMC1); + hsmmc_init(mmc); usb_musb_init(); usb_ehci_init(); omap3evm_flash_init(); diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c index ee001bb5775..12f032786cb 100644 --- a/arch/arm/mach-omap2/board-omap3pandora.c +++ b/arch/arm/mach-omap2/board-omap3pandora.c @@ -201,6 +201,15 @@ static struct platform_device *omap3pandora_devices[] __initdata = { &omap3pandora_lcd_device, }; +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + }, + {} /* Terminator */ +}; + static void __init omap3pandora_init(void) { omap3pandora_i2c_init(); @@ -208,7 +217,7 @@ static void __init omap3pandora_init(void) omap_board_config = omap3pandora_config; omap_board_config_size = ARRAY_SIZE(omap3pandora_config); omap_serial_init(); - hsmmc_init(HSMMC1); + hsmmc_init(mmc); usb_musb_init(); usb_ehci_init(); omap3pandora_flash_init(); diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 4f0b5d401ff..a45a44029cd 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -50,6 +50,7 @@ #include "sdram-micron-mt46h32m32lf-6.h" #include "twl4030-generic-scripts.h" +#include "mmc-twl4030.h" #define NAND_BLOCK_SIZE SZ_128K #define GPMC_CS0_BASE 0x60 @@ -207,6 +208,20 @@ static struct platform_device *overo_devices[] __initdata = { &overo_lcd_device, }; +static struct twl4030_hsmmc_info mmc[] __initdata = { + { + .mmc = 1, + .wires = 4, + .gpio_cd = -EINVAL, + }, + { + .mmc = 2, + .wires = 4, + .gpio_cd = -EINVAL, + }, + {} /* Terminator */ +}; + static void __init overo_init(void) { overo_i2c_init(); @@ -214,7 +229,7 @@ static void __init overo_init(void) omap_board_config = overo_config; omap_board_config_size = ARRAY_SIZE(overo_config); omap_serial_init(); - hsmmc_init(HSMMC1); + hsmmc_init(mmc); usb_musb_init(); usb_ehci_init(); overo_flash_init(); diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c index 0dd8b964b2e..241e41800d4 100644 --- a/arch/arm/mach-omap2/devices.c +++ b/arch/arm/mach-omap2/devices.c @@ -371,7 +371,7 @@ static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller, 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) { + if (mmc_controller->slots[0].wires == 4) { omap_cfg_reg(H14_24XX_MMC_DAT1); omap_cfg_reg(E19_24XX_MMC_DAT2); omap_cfg_reg(D19_24XX_MMC_DAT3); diff --git a/arch/arm/mach-omap2/mmc-twl4030.c b/arch/arm/mach-omap2/mmc-twl4030.c index 4bf2578bd05..a1a68ff23fa 100644 --- a/arch/arm/mach-omap2/mmc-twl4030.c +++ b/arch/arm/mach-omap2/mmc-twl4030.c @@ -23,6 +23,8 @@ #include #include +#include "mmc-twl4030.h" + #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) #define TWL_GPIO_IMR1A 0x1C @@ -149,7 +151,7 @@ static int hsmmc1_suspend(struct device *dev, int slot) { int ret = 0; - disable_irq(TWL4030_GPIO_IRQ_NO(0)); + disable_irq(hsmmc[0].card_detect_gpio); ret = mask_cd_interrupt(1); return ret; @@ -159,12 +161,15 @@ static int hsmmc1_resume(struct device *dev, int slot) { int ret = 0; - enable_irq(TWL4030_GPIO_IRQ_NO(0)); + enable_irq(hsmmc[0].card_detect_gpio); ret = mask_cd_interrupt(0); return ret; } +#else +#define hsmmc1_suspend NULL +#define hsmmc1_resume NULL #endif /* @@ -316,42 +321,14 @@ static int hsmmc2_set_power(struct device *dev, int slot, int power_on, int vdd) return ret; } -static struct omap_mmc_platform_data mmc1_data = { - .nr_slots = 1, - .init = hsmmc1_late_init, - .cleanup = hsmmc1_cleanup, -#ifdef CONFIG_PM - .suspend = hsmmc1_suspend, - .resume = hsmmc1_resume, -#endif - .dma_mask = 0xffffffff, - .slots[0] = { - .wire4 = 1, - .set_power = hsmmc1_set_power, - .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34 | - MMC_VDD_165_195, - .name = "first slot", - - .card_detect_irq = TWL4030_GPIO_IRQ_NO(0), - .card_detect = hsmmc1_card_detect, - }, -}; - -static struct omap_mmc_platform_data mmc2_data = { - .nr_slots = 1, - .slots[0] = { - .set_power = hsmmc2_set_power, - .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | - MMC_VDD_29_30 | MMC_VDD_30_31 | - MMC_VDD_31_32 | MMC_VDD_32_33, - .name = "second slot", - }, -}; - static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC]; -void __init hsmmc_init(int controller_mask) +#define HSMMC_NAME_LEN 9 + +void __init hsmmc_init(struct twl4030_hsmmc_info *controllers) { + struct twl4030_hsmmc_info *c; + if (cpu_is_omap2430()) { control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE; hsmmc[1].control_devconf_offset = OMAP243X_CONTROL_DEVCONF1; @@ -360,12 +337,55 @@ void __init hsmmc_init(int controller_mask) hsmmc[1].control_devconf_offset = OMAP343X_CONTROL_DEVCONF1; } - if (controller_mask & HSMMC1) - hsmmc_data[0] = &mmc1_data; - if (controller_mask & HSMMC2) - hsmmc_data[1] = &mmc2_data; - if (controller_mask & HSMMC3) - pr_err("HSMMC: Unknown configuration for controller 3\n"); + for (c = controllers; c->mmc; c++) { + struct omap_mmc_platform_data *mmc; + char *name; + + mmc = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL); + if (!mmc) { + pr_err("Cannot allocate memory for mmc device!\n"); + return; + } + + name = kzalloc(HSMMC_NAME_LEN, GFP_KERNEL); + if (!name) { + kfree(mmc); + pr_err("Cannot allocate memory for mmc name!\n"); + return; + } + + sprintf(name, "mmc%islot%i", c->mmc, 1); + mmc->slots[0].name = name; + mmc->nr_slots = 1; + mmc->slots[0].ocr_mask = MMC_VDD_165_195 | + MMC_VDD_26_27 | MMC_VDD_27_28 | + MMC_VDD_29_30 | + MMC_VDD_30_31 | MMC_VDD_31_32; + mmc->slots[0].wires = c->wires; + if (c->gpio_cd != -EINVAL) + mmc->slots[0].card_detect_irq = c->gpio_cd; + mmc->dma_mask = 0xffffffff; + + switch (c->mmc) { + case 1: + mmc->init = hsmmc1_late_init; + mmc->cleanup = hsmmc1_cleanup; + mmc->suspend = hsmmc1_suspend; + mmc->resume = hsmmc1_resume; + mmc->slots[0].set_power = hsmmc1_set_power; + mmc->slots[0].card_detect = hsmmc1_card_detect; + hsmmc_data[0] = mmc; + break; + case 2: + mmc->slots[0].set_power = hsmmc2_set_power; + hsmmc_data[1] = mmc; + break; + default: + pr_err("Unknown MMC configuration!\n"); + return; + } + } + omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC); } diff --git a/arch/arm/mach-omap2/mmc-twl4030.h b/arch/arm/mach-omap2/mmc-twl4030.h new file mode 100644 index 00000000000..5777d3369fb --- /dev/null +++ b/arch/arm/mach-omap2/mmc-twl4030.h @@ -0,0 +1,26 @@ +/* + * MMC definitions for OMAP2 + * + * 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. + */ + +#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \ + defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE) + +struct twl4030_hsmmc_info { + u8 mmc; /* controller 1/2/3 */ + u8 wires; /* 1/4/8 wires */ + int gpio_cd; /* or -EINVAL */ +}; + +void hsmmc_init(struct twl4030_hsmmc_info *); + +#else + +static inline void hsmmc_init(struct twl4030_hsmmc_info *) +{ +} + +#endif diff --git a/arch/arm/plat-omap/include/mach/mmc.h b/arch/arm/plat-omap/include/mach/mmc.h index 0c2ef3b8956..48895d2696c 100644 --- a/arch/arm/plat-omap/include/mach/mmc.h +++ b/arch/arm/plat-omap/include/mach/mmc.h @@ -71,7 +71,7 @@ struct omap_mmc_platform_data { unsigned cover:1; /* 4 wire signaling is optional, and is only used for SD/SDIO */ - unsigned wire4:1; + u8 wires; /* use the internal clock */ unsigned internal_clock:1; @@ -111,7 +111,6 @@ void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers); -void hsmmc_init(int controller_mask); int omap_mmc_add(int id, unsigned long base, unsigned long size, unsigned int irq, struct omap_mmc_platform_data *data); #else @@ -123,9 +122,6 @@ static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, int nr_controllers) { } -static inline void hsmmc_init(int controller_mask) -{ -} static inline int omap_mmc_add(int id, unsigned long base, unsigned long size, unsigned int irq, struct omap_mmc_platform_data *data) { diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index c6544d2d072..67d7b7fef08 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1317,7 +1317,7 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) host->slots[id] = slot; mmc->caps = 0; - if (host->pdata->slots[id].wire4) + if (host->pdata->slots[id].wires >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; mmc->ops = &mmc_omap_ops; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 3ba24be0113..8f92f809277 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -936,7 +936,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev) mmc->ocr_avail = mmc_slot(host).ocr_mask; mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; - if (pdata->slots[host->slot_id].wire4) + if (pdata->slots[host->slot_id].wires >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; /* Only MMC1 supports 3.0V */ -- 2.41.0