mmc: core: add WP pin handler to slot functions
Card Write-Protect pin is often implemented, using a GPIO, which makes it simple to provide a generic handler for it. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Chris Ball <cjb@laptop.org>
This commit is contained in:

committed by
Chris Ball

parent
a7d1a1ebd8
commit
5aa7dad305
@@ -18,7 +18,9 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
|
||||||
struct mmc_gpio {
|
struct mmc_gpio {
|
||||||
|
int ro_gpio;
|
||||||
int cd_gpio;
|
int cd_gpio;
|
||||||
|
char *ro_label;
|
||||||
char cd_label[0];
|
char cd_label[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -43,11 +45,14 @@ static int mmc_gpio_alloc(struct mmc_host *host)
|
|||||||
* before device_add(), i.e., between mmc_alloc_host() and
|
* before device_add(), i.e., between mmc_alloc_host() and
|
||||||
* mmc_add_host()
|
* mmc_add_host()
|
||||||
*/
|
*/
|
||||||
ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len,
|
ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len,
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (ctx) {
|
if (ctx) {
|
||||||
|
ctx->ro_label = ctx->cd_label + len;
|
||||||
snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
|
snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
|
||||||
|
snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
|
||||||
ctx->cd_gpio = -EINVAL;
|
ctx->cd_gpio = -EINVAL;
|
||||||
|
ctx->ro_gpio = -EINVAL;
|
||||||
host->slot.handler_priv = ctx;
|
host->slot.handler_priv = ctx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +62,18 @@ static int mmc_gpio_alloc(struct mmc_host *host)
|
|||||||
return ctx ? 0 : -ENOMEM;
|
return ctx ? 0 : -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mmc_gpio_get_ro(struct mmc_host *host)
|
||||||
|
{
|
||||||
|
struct mmc_gpio *ctx = host->slot.handler_priv;
|
||||||
|
|
||||||
|
if (!ctx || !gpio_is_valid(ctx->ro_gpio))
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
return !gpio_get_value_cansleep(ctx->ro_gpio) ^
|
||||||
|
!!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mmc_gpio_get_ro);
|
||||||
|
|
||||||
int mmc_gpio_get_cd(struct mmc_host *host)
|
int mmc_gpio_get_cd(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
struct mmc_gpio *ctx = host->slot.handler_priv;
|
struct mmc_gpio *ctx = host->slot.handler_priv;
|
||||||
@@ -69,6 +86,24 @@ int mmc_gpio_get_cd(struct mmc_host *host)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_gpio_get_cd);
|
EXPORT_SYMBOL(mmc_gpio_get_cd);
|
||||||
|
|
||||||
|
int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
|
||||||
|
{
|
||||||
|
struct mmc_gpio *ctx;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!gpio_is_valid(gpio))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = mmc_gpio_alloc(host);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ctx = host->slot.handler_priv;
|
||||||
|
|
||||||
|
return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mmc_gpio_request_ro);
|
||||||
|
|
||||||
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
|
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
|
||||||
{
|
{
|
||||||
struct mmc_gpio *ctx;
|
struct mmc_gpio *ctx;
|
||||||
@@ -117,6 +152,21 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(mmc_gpio_request_cd);
|
EXPORT_SYMBOL(mmc_gpio_request_cd);
|
||||||
|
|
||||||
|
void mmc_gpio_free_ro(struct mmc_host *host)
|
||||||
|
{
|
||||||
|
struct mmc_gpio *ctx = host->slot.handler_priv;
|
||||||
|
int gpio;
|
||||||
|
|
||||||
|
if (!ctx || !gpio_is_valid(ctx->ro_gpio))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gpio = ctx->ro_gpio;
|
||||||
|
ctx->ro_gpio = -EINVAL;
|
||||||
|
|
||||||
|
gpio_free(gpio);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(mmc_gpio_free_ro);
|
||||||
|
|
||||||
void mmc_gpio_free_cd(struct mmc_host *host)
|
void mmc_gpio_free_cd(struct mmc_host *host)
|
||||||
{
|
{
|
||||||
struct mmc_gpio *ctx = host->slot.handler_priv;
|
struct mmc_gpio *ctx = host->slot.handler_priv;
|
||||||
|
@@ -13,6 +13,10 @@
|
|||||||
|
|
||||||
struct mmc_host;
|
struct mmc_host;
|
||||||
|
|
||||||
|
int mmc_gpio_get_ro(struct mmc_host *host);
|
||||||
|
int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
|
||||||
|
void mmc_gpio_free_ro(struct mmc_host *host);
|
||||||
|
|
||||||
int mmc_gpio_get_cd(struct mmc_host *host);
|
int mmc_gpio_get_cd(struct mmc_host *host);
|
||||||
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
|
int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
|
||||||
void mmc_gpio_free_cd(struct mmc_host *host);
|
void mmc_gpio_free_cd(struct mmc_host *host);
|
||||||
|
Reference in New Issue
Block a user