diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2012-05-01 10:59:38 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2012-07-21 00:02:18 -0400 |
commit | 5aa7dad305594ea30d21e23b3036565042adf50c (patch) | |
tree | d9c7c2962e35c63ffe7d4ad2d48e8e99109dadb4 /drivers/mmc | |
parent | a7d1a1ebd8f5858a812ac3d5fbbc178b4959a63b (diff) |
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>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/slot-gpio.c | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c index 41689da14b8d..058242916cef 100644 --- a/drivers/mmc/core/slot-gpio.c +++ b/drivers/mmc/core/slot-gpio.c | |||
@@ -18,7 +18,9 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | 19 | ||
20 | struct mmc_gpio { | 20 | struct mmc_gpio { |
21 | int ro_gpio; | ||
21 | int cd_gpio; | 22 | int cd_gpio; |
23 | char *ro_label; | ||
22 | char cd_label[0]; | 24 | char cd_label[0]; |
23 | }; | 25 | }; |
24 | 26 | ||
@@ -43,11 +45,14 @@ static int mmc_gpio_alloc(struct mmc_host *host) | |||
43 | * before device_add(), i.e., between mmc_alloc_host() and | 45 | * before device_add(), i.e., between mmc_alloc_host() and |
44 | * mmc_add_host() | 46 | * mmc_add_host() |
45 | */ | 47 | */ |
46 | ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + len, | 48 | ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len, |
47 | GFP_KERNEL); | 49 | GFP_KERNEL); |
48 | if (ctx) { | 50 | if (ctx) { |
51 | ctx->ro_label = ctx->cd_label + len; | ||
49 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); | 52 | snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); |
53 | snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); | ||
50 | ctx->cd_gpio = -EINVAL; | 54 | ctx->cd_gpio = -EINVAL; |
55 | ctx->ro_gpio = -EINVAL; | ||
51 | host->slot.handler_priv = ctx; | 56 | host->slot.handler_priv = ctx; |
52 | } | 57 | } |
53 | } | 58 | } |
@@ -57,6 +62,18 @@ static int mmc_gpio_alloc(struct mmc_host *host) | |||
57 | return ctx ? 0 : -ENOMEM; | 62 | return ctx ? 0 : -ENOMEM; |
58 | } | 63 | } |
59 | 64 | ||
65 | int mmc_gpio_get_ro(struct mmc_host *host) | ||
66 | { | ||
67 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
68 | |||
69 | if (!ctx || !gpio_is_valid(ctx->ro_gpio)) | ||
70 | return -ENOSYS; | ||
71 | |||
72 | return !gpio_get_value_cansleep(ctx->ro_gpio) ^ | ||
73 | !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH); | ||
74 | } | ||
75 | EXPORT_SYMBOL(mmc_gpio_get_ro); | ||
76 | |||
60 | int mmc_gpio_get_cd(struct mmc_host *host) | 77 | int mmc_gpio_get_cd(struct mmc_host *host) |
61 | { | 78 | { |
62 | struct mmc_gpio *ctx = host->slot.handler_priv; | 79 | struct mmc_gpio *ctx = host->slot.handler_priv; |
@@ -69,6 +86,24 @@ int mmc_gpio_get_cd(struct mmc_host *host) | |||
69 | } | 86 | } |
70 | EXPORT_SYMBOL(mmc_gpio_get_cd); | 87 | EXPORT_SYMBOL(mmc_gpio_get_cd); |
71 | 88 | ||
89 | int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio) | ||
90 | { | ||
91 | struct mmc_gpio *ctx; | ||
92 | int ret; | ||
93 | |||
94 | if (!gpio_is_valid(gpio)) | ||
95 | return -EINVAL; | ||
96 | |||
97 | ret = mmc_gpio_alloc(host); | ||
98 | if (ret < 0) | ||
99 | return ret; | ||
100 | |||
101 | ctx = host->slot.handler_priv; | ||
102 | |||
103 | return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); | ||
104 | } | ||
105 | EXPORT_SYMBOL(mmc_gpio_request_ro); | ||
106 | |||
72 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) | 107 | int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) |
73 | { | 108 | { |
74 | struct mmc_gpio *ctx; | 109 | struct mmc_gpio *ctx; |
@@ -117,6 +152,21 @@ int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) | |||
117 | } | 152 | } |
118 | EXPORT_SYMBOL(mmc_gpio_request_cd); | 153 | EXPORT_SYMBOL(mmc_gpio_request_cd); |
119 | 154 | ||
155 | void mmc_gpio_free_ro(struct mmc_host *host) | ||
156 | { | ||
157 | struct mmc_gpio *ctx = host->slot.handler_priv; | ||
158 | int gpio; | ||
159 | |||
160 | if (!ctx || !gpio_is_valid(ctx->ro_gpio)) | ||
161 | return; | ||
162 | |||
163 | gpio = ctx->ro_gpio; | ||
164 | ctx->ro_gpio = -EINVAL; | ||
165 | |||
166 | gpio_free(gpio); | ||
167 | } | ||
168 | EXPORT_SYMBOL(mmc_gpio_free_ro); | ||
169 | |||
120 | void mmc_gpio_free_cd(struct mmc_host *host) | 170 | void mmc_gpio_free_cd(struct mmc_host *host) |
121 | { | 171 | { |
122 | struct mmc_gpio *ctx = host->slot.handler_priv; | 172 | struct mmc_gpio *ctx = host->slot.handler_priv; |