1 /* 2 * Generic GPIO card-detect helper 3 * 4 * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11 #include <linux/err.h> 12 #include <linux/gpio.h> 13 #include <linux/interrupt.h> 14 #include <linux/jiffies.h> 15 #include <linux/mmc/host.h> 16 #include <linux/mmc/slot-gpio.h> 17 #include <linux/module.h> 18 #include <linux/slab.h> 19 20 struct mmc_gpio { 21 int ro_gpio; 22 int cd_gpio; 23 char *ro_label; 24 char cd_label[0]; 25 }; 26 27 static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id) 28 { 29 /* Schedule a card detection after a debounce timeout */ 30 mmc_detect_change(dev_id, msecs_to_jiffies(100)); 31 return IRQ_HANDLED; 32 } 33 34 static int mmc_gpio_alloc(struct mmc_host *host) 35 { 36 size_t len = strlen(dev_name(host->parent)) + 4; 37 struct mmc_gpio *ctx; 38 39 mutex_lock(&host->slot.lock); 40 41 ctx = host->slot.handler_priv; 42 if (!ctx) { 43 /* 44 * devm_kzalloc() can be called after device_initialize(), even 45 * before device_add(), i.e., between mmc_alloc_host() and 46 * mmc_add_host() 47 */ 48 ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len, 49 GFP_KERNEL); 50 if (ctx) { 51 ctx->ro_label = ctx->cd_label + len; 52 snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent)); 53 snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent)); 54 ctx->cd_gpio = -EINVAL; 55 ctx->ro_gpio = -EINVAL; 56 host->slot.handler_priv = ctx; 57 } 58 } 59 60 mutex_unlock(&host->slot.lock); 61 62 return ctx ? 0 : -ENOMEM; 63 } 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 77 int mmc_gpio_get_cd(struct mmc_host *host) 78 { 79 struct mmc_gpio *ctx = host->slot.handler_priv; 80 81 if (!ctx || !gpio_is_valid(ctx->cd_gpio)) 82 return -ENOSYS; 83 84 return !gpio_get_value_cansleep(ctx->cd_gpio) ^ 85 !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH); 86 } 87 EXPORT_SYMBOL(mmc_gpio_get_cd); 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 ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label); 104 if (ret < 0) 105 return ret; 106 107 ctx->ro_gpio = gpio; 108 109 return 0; 110 } 111 EXPORT_SYMBOL(mmc_gpio_request_ro); 112 113 int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio) 114 { 115 struct mmc_gpio *ctx; 116 int irq = gpio_to_irq(gpio); 117 int ret; 118 119 ret = mmc_gpio_alloc(host); 120 if (ret < 0) 121 return ret; 122 123 ctx = host->slot.handler_priv; 124 125 ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label); 126 if (ret < 0) 127 /* 128 * don't bother freeing memory. It might still get used by other 129 * slot functions, in any case it will be freed, when the device 130 * is destroyed. 131 */ 132 return ret; 133 134 /* 135 * Even if gpio_to_irq() returns a valid IRQ number, the platform might 136 * still prefer to poll, e.g., because that IRQ number is already used 137 * by another unit and cannot be shared. 138 */ 139 if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL) 140 irq = -EINVAL; 141 142 if (irq >= 0) { 143 ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt, 144 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 145 ctx->cd_label, host); 146 if (ret < 0) 147 irq = ret; 148 } 149 150 host->slot.cd_irq = irq; 151 152 if (irq < 0) 153 host->caps |= MMC_CAP_NEEDS_POLL; 154 155 ctx->cd_gpio = gpio; 156 157 return 0; 158 } 159 EXPORT_SYMBOL(mmc_gpio_request_cd); 160 161 void mmc_gpio_free_ro(struct mmc_host *host) 162 { 163 struct mmc_gpio *ctx = host->slot.handler_priv; 164 int gpio; 165 166 if (!ctx || !gpio_is_valid(ctx->ro_gpio)) 167 return; 168 169 gpio = ctx->ro_gpio; 170 ctx->ro_gpio = -EINVAL; 171 172 gpio_free(gpio); 173 } 174 EXPORT_SYMBOL(mmc_gpio_free_ro); 175 176 void mmc_gpio_free_cd(struct mmc_host *host) 177 { 178 struct mmc_gpio *ctx = host->slot.handler_priv; 179 int gpio; 180 181 if (!ctx || !gpio_is_valid(ctx->cd_gpio)) 182 return; 183 184 if (host->slot.cd_irq >= 0) { 185 free_irq(host->slot.cd_irq, host); 186 host->slot.cd_irq = -EINVAL; 187 } 188 189 gpio = ctx->cd_gpio; 190 ctx->cd_gpio = -EINVAL; 191 192 gpio_free(gpio); 193 } 194 EXPORT_SYMBOL(mmc_gpio_free_cd); 195