Use gpio_find_by_chip_name() to find the GPIO pins as they can be dynamically allocated on various gpio_chips. Note that we don't want to touch the platform data as it can now specify the GPIO offset on a named gpio_chip. This removes the need to use callbacks to set the GPIO pins in platform data. Cc: Chris Ball <cjb@xxxxxxxxxx> Cc: Grant Likely <grant.likely@xxxxxxxxxxxx> Cc: Rajendra Nayak <rnayak@xxxxxx> Signed-off-by: Tony Lindgren <tony@xxxxxxxxxxx> --- arch/arm/mach-omap2/hsmmc.c | 3 + arch/arm/mach-omap2/hsmmc.h | 5 ++ arch/arm/plat-omap/include/plat/mmc.h | 3 + drivers/gpio/gpio-twl4030.c | 2 + drivers/mmc/host/omap_hsmmc.c | 109 +++++++++++++++++++++------------ 5 files changed, 82 insertions(+), 40 deletions(-) diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index a97876d..dda88f7 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -323,7 +323,10 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, mmc->get_context_loss_count = hsmmc_get_context_loss; + mmc->slots[0].gpiochip_cd = c->gpiochip_cd; mmc->slots[0].switch_pin = c->gpio_cd; + + mmc->slots[0].gpiochip_wp = c->gpiochip_wp; mmc->slots[0].gpio_wp = c->gpio_wp; mmc->slots[0].remux = c->remux; diff --git a/arch/arm/mach-omap2/hsmmc.h b/arch/arm/mach-omap2/hsmmc.h index 07831cc..ffbb78d 100644 --- a/arch/arm/mach-omap2/hsmmc.h +++ b/arch/arm/mach-omap2/hsmmc.h @@ -22,8 +22,13 @@ struct omap2_hsmmc_info { bool no_off_init; /* no power off when not in MMC sleep state */ bool vcc_aux_disable_is_sleep; /* Regulator off remapped to sleep */ bool deferred; /* mmc needs a deferred probe */ + + char *gpiochip_cd; /* Optional gpiochip for gpio_cd */ int gpio_cd; /* or -EINVAL */ + + char *gpiochip_wp; /* Optional gpiochip for gpio_wp */ int gpio_wp; /* or -EINVAL */ + char *name; /* or NULL for default */ struct platform_device *pdev; /* mmc controller instance */ int ocr_mask; /* temporary HACK */ diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h index f75946c..cbfbdc3 100644 --- a/arch/arm/plat-omap/include/plat/mmc.h +++ b/arch/arm/plat-omap/include/plat/mmc.h @@ -130,7 +130,10 @@ struct omap_mmc_platform_data { #define HSMMC_HAS_UPDATED_RESET (1 << 1) unsigned features; + char *gpiochip_cd; /* optional gpiochip for card detect */ int switch_pin; /* gpio (card detect) */ + + char *gpiochip_wp; /* optional gpiochip for write protect */ int gpio_wp; /* gpio (write protect) */ int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c index b8b4f22..d0f266c 100644 --- a/drivers/gpio/gpio-twl4030.c +++ b/drivers/gpio/gpio-twl4030.c @@ -391,6 +391,7 @@ static int __devinit gpio_twl4030_debounce(u32 debounce, u8 mmc_cd) } static int gpio_twl4030_remove(struct platform_device *pdev); +static struct platform_driver gpio_twl4030_driver; static int __devinit gpio_twl4030_probe(struct platform_device *pdev) { @@ -430,6 +431,7 @@ no_irqs: pdata->debounce, pdata->mmc_cd, ret); + twl_gpiochip.label = gpio_twl4030_driver.driver.name; twl_gpiochip.base = pdata->gpio_base; twl_gpiochip.ngpio = TWL4030_GPIO_MAX; twl_gpiochip.dev = &pdev->dev; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index fd0c661..1aa2420 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -176,6 +176,8 @@ struct omap_hsmmc_host { int use_dma, dma_ch; int dma_line_tx, dma_line_rx; int slot_id; + int gpio_cd; + int gpio_wp; int got_dbclk; int response_busy; int context_loss; @@ -192,26 +194,29 @@ struct omap_hsmmc_host { static int omap_hsmmc_card_detect(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = + platform_get_drvdata(to_platform_device(dev)); /* NOTE: assumes card detect signal is active-low */ - return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); + return !gpio_get_value_cansleep(host->gpio_cd); } static int omap_hsmmc_get_wp(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = + platform_get_drvdata(to_platform_device(dev)); /* NOTE: assumes write protect signal is active-high */ - return gpio_get_value_cansleep(mmc->slots[0].gpio_wp); + return gpio_get_value_cansleep(host->gpio_wp); } static int omap_hsmmc_get_cover_state(struct device *dev, int slot) { - struct omap_mmc_platform_data *mmc = dev->platform_data; + struct omap_hsmmc_host *host = + platform_get_drvdata(to_platform_device(dev)); /* NOTE: assumes card detect signal is active-low */ - return !gpio_get_value_cansleep(mmc->slots[0].switch_pin); + return !gpio_get_value_cansleep(host->gpio_cd); } #ifdef CONFIG_PM @@ -497,55 +502,80 @@ static inline int omap_hsmmc_have_reg(void) #endif -static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) +static int omap_hsmmc_gpio_init(struct omap_hsmmc_host *host) { - int ret; - - if (gpio_is_valid(pdata->slots[0].switch_pin)) { - if (pdata->slots[0].cover) - pdata->slots[0].get_cover_state = + struct omap_mmc_platform_data *pdata = host->pdata; + struct omap_mmc_slot_data *slot = &pdata->slots[0]; + int gpio, ret; + + gpio = slot->switch_pin; + if (slot->gpiochip_cd) + gpio = gpio_find_by_chip_name(slot->gpiochip_cd, gpio); + if (gpio_is_valid(gpio)) { + if (slot->cover) + slot->get_cover_state = omap_hsmmc_get_cover_state; else - pdata->slots[0].card_detect = omap_hsmmc_card_detect; - pdata->slots[0].card_detect_irq = - gpio_to_irq(pdata->slots[0].switch_pin); - ret = gpio_request(pdata->slots[0].switch_pin, "mmc_cd"); + slot->card_detect = omap_hsmmc_card_detect; + slot->card_detect_irq = + gpio_to_irq(gpio); + ret = gpio_request(gpio, "mmc_cd"); if (ret) return ret; - ret = gpio_direction_input(pdata->slots[0].switch_pin); + ret = gpio_direction_input(gpio); if (ret) goto err_free_sp; - } else - pdata->slots[0].switch_pin = -EINVAL; + host->gpio_cd = gpio; + } else { + if (slot->gpiochip_cd) { + pr_warning("MMC %s card detect GPIO chip %s unavailable\n", + slot->name, slot->gpiochip_cd); + ret = -ENODEV; + goto err_free_sp; + } + host->gpio_cd = -EINVAL; + } - if (gpio_is_valid(pdata->slots[0].gpio_wp)) { - pdata->slots[0].get_ro = omap_hsmmc_get_wp; - ret = gpio_request(pdata->slots[0].gpio_wp, "mmc_wp"); + gpio = slot->gpio_wp; + if (slot->gpiochip_wp) + gpio = gpio_find_by_chip_name(slot->gpiochip_wp, gpio); + if (gpio_is_valid(gpio)) { + slot->get_ro = omap_hsmmc_get_wp; + ret = gpio_request(gpio, "mmc_wp"); if (ret) goto err_free_cd; - ret = gpio_direction_input(pdata->slots[0].gpio_wp); + ret = gpio_direction_input(gpio); if (ret) goto err_free_wp; - } else - pdata->slots[0].gpio_wp = -EINVAL; + host->gpio_wp = gpio; + } else { + if (slot->gpiochip_wp) { + pr_warning("MMC %s write protect GPIO chip %s unavailable\n", + slot->name, slot->gpiochip_wp); + ret = -ENODEV; + goto err_free_wp; + } + host->gpio_wp = -EINVAL; + } return 0; err_free_wp: - gpio_free(pdata->slots[0].gpio_wp); + if (gpio_is_valid(host->gpio_wp)) + gpio_free(host->gpio_wp); err_free_cd: - if (gpio_is_valid(pdata->slots[0].switch_pin)) + if (gpio_is_valid(host->gpio_cd)) err_free_sp: - gpio_free(pdata->slots[0].switch_pin); + gpio_free(host->gpio_cd); return ret; } -static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) +static void omap_hsmmc_gpio_free(struct omap_hsmmc_host *host) { - if (gpio_is_valid(pdata->slots[0].gpio_wp)) - gpio_free(pdata->slots[0].gpio_wp); - if (gpio_is_valid(pdata->slots[0].switch_pin)) - gpio_free(pdata->slots[0].switch_pin); + if (gpio_is_valid(host->gpio_wp)) + gpio_free(host->gpio_wp); + if (gpio_is_valid(host->gpio_cd)) + gpio_free(host->gpio_cd); } /* @@ -1876,10 +1906,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) if (res == NULL) return -EBUSY; - ret = omap_hsmmc_gpio_init(pdata); - if (ret) - goto err; - mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev); if (!mmc) { ret = -ENOMEM; @@ -1903,6 +1929,10 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); + ret = omap_hsmmc_gpio_init(host); + if (ret) + goto err1; + mmc->ops = &omap_hsmmc_ops; /* @@ -2093,8 +2123,7 @@ err1: platform_set_drvdata(pdev, NULL); mmc_free_host(mmc); err_alloc: - omap_hsmmc_gpio_free(pdata); -err: + omap_hsmmc_gpio_free(host); release_mem_region(res->start, resource_size(res)); return ret; } @@ -2125,7 +2154,7 @@ static int omap_hsmmc_remove(struct platform_device *pdev) mmc_free_host(host->mmc); iounmap(host->base); - omap_hsmmc_gpio_free(pdev->dev.platform_data); + omap_hsmmc_gpio_free(host); } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html