From ca93142b6dac3cef164197686236d5a16e5a63de Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 1 May 2012 16:27:25 +0200 Subject: [PATCH] --- yaml --- r: 312825 b: refs/heads/master c: befe4048d8d20483a62636e20f3dbffebf85a1c1 h: refs/heads/master i: 312823: 95d1642a10df582e1b8df7382ae9eca33a11d37f v: v3 --- [refs] | 2 +- trunk/drivers/mmc/core/slot-gpio.c | 56 ++++++++++++++++++++++------- trunk/include/linux/mmc/slot-gpio.h | 2 ++ 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/[refs] b/[refs] index 7f67bf2f6a5b..3171c883389c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5c08d7fae0815cd163a98e05c8d94fc0de77ff67 +refs/heads/master: befe4048d8d20483a62636e20f3dbffebf85a1c1 diff --git a/trunk/drivers/mmc/core/slot-gpio.c b/trunk/drivers/mmc/core/slot-gpio.c index 468e5a0e5126..92cba02c04be 100644 --- a/trunk/drivers/mmc/core/slot-gpio.c +++ b/trunk/drivers/mmc/core/slot-gpio.c @@ -18,7 +18,7 @@ #include struct mmc_gpio { - unsigned int cd_gpio; + int cd_gpio; char cd_label[0]; }; @@ -29,6 +29,18 @@ static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) return IRQ_HANDLED; } +int mmc_gpio_get_cd(struct mmc_host *host) +{ + struct mmc_gpio *ctx = host->slot.handler_priv; + + if (!ctx || !gpio_is_valid(ctx->cd_gpio)) + return -ENOSYS; + + return !gpio_get_value_cansleep(ctx->cd_gpio) ^ + !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); +} +EXPORT_SYMBOL(mmc_gpio_get_cd); + int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) { size_t len = strlen(dev_name(host->parent)) + 4; @@ -36,9 +48,6 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) int irq = gpio_to_irq(gpio); int ret; - if (irq < 0) - return irq; - ctx = kmalloc(sizeof(*ctx) + len, GFP_KERNEL); if (!ctx) return -ENOMEM; @@ -49,20 +58,32 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) if (ret < 0) goto egpioreq; - ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt, + /* + * Even if gpio_to_irq() returns a valid IRQ number, the platform might + * still prefer to poll, e.g., because that IRQ number is already used + * by another unit and cannot be shared. + */ + if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) + irq = -EINVAL; + + if (irq >= 0) { + ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ctx->cd_label, host); - if (ret < 0) - goto eirqreq; + if (ret < 0) + irq = ret; + } - ctx->cd_gpio = gpio; host->slot.cd_irq = irq; + + if (irq < 0) + host->caps |= MMC_CAP_NEEDS_POLL; + + ctx->cd_gpio = gpio; host->slot.handler_priv = ctx; return 0; -eirqreq: - gpio_free(gpio); egpioreq: kfree(ctx); return ret; @@ -72,12 +93,21 @@ EXPORT_SYMBOL(mmc_gpio_request_cd); void mmc_gpio_free_cd(struct mmc_host *host) { struct mmc_gpio *ctx = host->slot.handler_priv; + int gpio; - if (!ctx) + if (!ctx || !gpio_is_valid(ctx->cd_gpio)) return; - free_irq(host->slot.cd_irq, host); - gpio_free(ctx->cd_gpio); + if (host->slot.cd_irq >= 0) { + free_irq(host->slot.cd_irq, host); + host->slot.cd_irq = -EINVAL; + } + + gpio = ctx->cd_gpio; + ctx->cd_gpio = -EINVAL; + + gpio_free(gpio); + host->slot.handler_priv = NULL; kfree(ctx); } EXPORT_SYMBOL(mmc_gpio_free_cd); diff --git a/trunk/include/linux/mmc/slot-gpio.h b/trunk/include/linux/mmc/slot-gpio.h index edfaa3254373..1a977d7ba3ba 100644 --- a/trunk/include/linux/mmc/slot-gpio.h +++ b/trunk/include/linux/mmc/slot-gpio.h @@ -12,6 +12,8 @@ #define MMC_SLOT_GPIO_H struct mmc_host; + +int mmc_gpio_get_cd(struct mmc_host *host); int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio); void mmc_gpio_free_cd(struct mmc_host *host);