1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Generic GPIO card-detect helper 4 * 5 * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de> 6 */ 7 8 #include <linux/err.h> 9 #include <linux/gpio/consumer.h> 10 #include <linux/interrupt.h> 11 #include <linux/jiffies.h> 12 #include <linux/mmc/host.h> 13 #include <linux/mmc/slot-gpio.h> 14 #include <linux/module.h> 15 #include <linux/slab.h> 16 17 #include "slot-gpio.h" 18 19 struct mmc_gpio { 20 struct gpio_desc *ro_gpio; 21 struct gpio_desc *cd_gpio; 22 irqreturn_t (*cd_gpio_isr)(int irq, void *dev_id); 23 char *ro_label; 24 char *cd_label; 25 u32 cd_debounce_delay_ms; 26 int cd_irq; 27 }; 28 29 static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) 30 { 31 /* Schedule a card detection after a debounce timeout */ 32 struct mmc_host *host = dev_id; 33 struct mmc_gpio *ctx = host->slot.handler_priv; 34 35 host->trigger_card_event = true; 36 mmc_detect_change(host, msecs_to_jiffies(ctx->cd_debounce_delay_ms)); 37 38 return IRQ_HANDLED; 39 } 40 41 int mmc_gpio_alloc(struct mmc_host *host) 42 { 43 const char *devname = dev_name(host->parent); 44 struct mmc_gpio *ctx; 45 46 ctx = devm_kzalloc(host->parent, sizeof(*ctx), GFP_KERNEL); 47 if (!ctx) 48 return -ENOMEM; 49 50 ctx->cd_debounce_delay_ms = 200; 51 ctx->cd_label = devm_kasprintf(host->parent, GFP_KERNEL, "%s cd", devname); 52 if (!ctx->cd_label) 53 return -ENOMEM; 54 ctx->ro_label = devm_kasprintf(host->parent, GFP_KERNEL, "%s ro", devname); 55 if (!ctx->ro_label) 56 return -ENOMEM; 57 ctx->cd_irq = -EINVAL; 58 host->slot.handler_priv = ctx; 59 host->slot.cd_irq = -EINVAL; 60 61 return 0; 62 } 63 64 void mmc_gpio_set_cd_irq(struct mmc_host *host, int irq) 65 { 66 struct mmc_gpio *ctx = host->slot.handler_priv; 67 68 if (!ctx || irq < 0) 69 return; 70 71 ctx->cd_irq = irq; 72 } 73 EXPORT_SYMBOL(mmc_gpio_set_cd_irq); 74 75 int mmc_gpio_get_ro(struct mmc_host *host) 76 { 77 struct mmc_gpio *ctx = host->slot.handler_priv; 78 79 if (!ctx || !ctx->ro_gpio) 80 return -ENOSYS; 81 82 return gpiod_get_value_cansleep(ctx->ro_gpio); 83 } 84 EXPORT_SYMBOL(mmc_gpio_get_ro); 85 86 int mmc_gpio_get_cd(struct mmc_host *host) 87 { 88 struct mmc_gpio *ctx = host->slot.handler_priv; 89 int cansleep; 90 91 if (!ctx || !ctx->cd_gpio) 92 return -ENOSYS; 93 94 cansleep = gpiod_cansleep(ctx->cd_gpio); 95 return cansleep ? 96 gpiod_get_value_cansleep(ctx->cd_gpio) : 97 gpiod_get_value(ctx->cd_gpio); 98 } 99 EXPORT_SYMBOL(mmc_gpio_get_cd); 100 101 void mmc_gpiod_request_cd_irq(struct mmc_host *host) 102 { 103 struct mmc_gpio *ctx = host->slot.handler_priv; 104 int irq = -EINVAL; 105 int ret; 106 107 if (host->slot.cd_irq >= 0 || !ctx || !ctx->cd_gpio) 108 return; 109 110 /* 111 * Do not use IRQ if the platform prefers to poll, e.g., because that 112 * IRQ number is already used by another unit and cannot be shared. 113 */ 114 if (ctx->cd_irq >= 0) 115 irq = ctx->cd_irq; 116 else if (!(host->caps & MMC_CAP_NEEDS_POLL)) 117 irq = gpiod_to_irq(ctx->cd_gpio); 118 119 if (irq >= 0) { 120 if (!ctx->cd_gpio_isr) 121 ctx->cd_gpio_isr = mmc_gpio_cd_irqt; 122 ret = devm_request_threaded_irq(host->parent, irq, 123 NULL, ctx->cd_gpio_isr, 124 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 125 ctx->cd_label, host); 126 if (ret < 0) 127 irq = ret; 128 } 129 130 host->slot.cd_irq = irq; 131 132 if (irq < 0) 133 host->caps |= MMC_CAP_NEEDS_POLL; 134 } 135 EXPORT_SYMBOL(mmc_gpiod_request_cd_irq); 136 137 int mmc_gpio_set_cd_wake(struct mmc_host *host, bool on) 138 { 139 int ret = 0; 140 141 if (!(host->caps & MMC_CAP_CD_WAKE) || 142 host->slot.cd_irq < 0 || 143 on == host->slot.cd_wake_enabled) 144 return 0; 145 146 if (on) { 147 ret = enable_irq_wake(host->slot.cd_irq); 148 host->slot.cd_wake_enabled = !ret; 149 } else { 150 disable_irq_wake(host->slot.cd_irq); 151 host->slot.cd_wake_enabled = false; 152 } 153 154 return ret; 155 } 156 EXPORT_SYMBOL(mmc_gpio_set_cd_wake); 157 158 /* Register an alternate interrupt service routine for 159 * the card-detect GPIO. 160 */ 161 void mmc_gpio_set_cd_isr(struct mmc_host *host, 162 irqreturn_t (*isr)(int irq, void *dev_id)) 163 { 164 struct mmc_gpio *ctx = host->slot.handler_priv; 165 166 WARN_ON(ctx->cd_gpio_isr); 167 ctx->cd_gpio_isr = isr; 168 } 169 EXPORT_SYMBOL(mmc_gpio_set_cd_isr); 170 171 /** 172 * mmc_gpiod_request_cd - request a gpio descriptor for card-detection 173 * @host: mmc host 174 * @con_id: function within the GPIO consumer 175 * @idx: index of the GPIO to obtain in the consumer 176 * @override_active_level: ignore %GPIO_ACTIVE_LOW flag 177 * @debounce: debounce time in microseconds 178 * 179 * Note that this must be called prior to mmc_add_host() 180 * otherwise the caller must also call mmc_gpiod_request_cd_irq(). 181 * 182 * Returns zero on success, else an error. 183 */ 184 int mmc_gpiod_request_cd(struct mmc_host *host, const char *con_id, 185 unsigned int idx, bool override_active_level, 186 unsigned int debounce) 187 { 188 struct mmc_gpio *ctx = host->slot.handler_priv; 189 struct gpio_desc *desc; 190 int ret; 191 192 desc = devm_gpiod_get_index(host->parent, con_id, idx, GPIOD_IN); 193 if (IS_ERR(desc)) 194 return PTR_ERR(desc); 195 196 /* Update default label if no con_id provided */ 197 if (!con_id) 198 gpiod_set_consumer_name(desc, ctx->cd_label); 199 200 if (debounce) { 201 ret = gpiod_set_debounce(desc, debounce); 202 if (ret < 0) 203 ctx->cd_debounce_delay_ms = debounce / 1000; 204 } 205 206 /* override forces default (active-low) polarity ... */ 207 if (override_active_level && !gpiod_is_active_low(desc)) 208 gpiod_toggle_active_low(desc); 209 210 /* ... or active-high */ 211 if (host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH) 212 gpiod_toggle_active_low(desc); 213 214 ctx->cd_gpio = desc; 215 216 return 0; 217 } 218 EXPORT_SYMBOL(mmc_gpiod_request_cd); 219 220 bool mmc_can_gpio_cd(struct mmc_host *host) 221 { 222 struct mmc_gpio *ctx = host->slot.handler_priv; 223 224 return ctx->cd_gpio ? true : false; 225 } 226 EXPORT_SYMBOL(mmc_can_gpio_cd); 227 228 /** 229 * mmc_gpiod_request_ro - request a gpio descriptor for write protection 230 * @host: mmc host 231 * @con_id: function within the GPIO consumer 232 * @idx: index of the GPIO to obtain in the consumer 233 * @debounce: debounce time in microseconds 234 * 235 * Returns zero on success, else an error. 236 */ 237 int mmc_gpiod_request_ro(struct mmc_host *host, const char *con_id, 238 unsigned int idx, unsigned int debounce) 239 { 240 struct mmc_gpio *ctx = host->slot.handler_priv; 241 struct gpio_desc *desc; 242 int ret; 243 244 desc = devm_gpiod_get_index(host->parent, con_id, idx, GPIOD_IN); 245 if (IS_ERR(desc)) 246 return PTR_ERR(desc); 247 248 /* Update default label if no con_id provided */ 249 if (!con_id) 250 gpiod_set_consumer_name(desc, ctx->ro_label); 251 252 if (debounce) { 253 ret = gpiod_set_debounce(desc, debounce); 254 if (ret < 0) 255 return ret; 256 } 257 258 if (host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH) 259 gpiod_toggle_active_low(desc); 260 261 ctx->ro_gpio = desc; 262 263 return 0; 264 } 265 EXPORT_SYMBOL(mmc_gpiod_request_ro); 266 267 bool mmc_can_gpio_ro(struct mmc_host *host) 268 { 269 struct mmc_gpio *ctx = host->slot.handler_priv; 270 271 return ctx->ro_gpio ? true : false; 272 } 273 EXPORT_SYMBOL(mmc_can_gpio_ro); 274