1 /* 2 * linux/drivers/mmc/core/sdio_irq.c 3 * 4 * Author: Nicolas Pitre 5 * Created: June 18, 2007 6 * Copyright: MontaVista Software Inc. 7 * 8 * Copyright 2008 Pierre Ossman 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or (at 13 * your option) any later version. 14 */ 15 16 #include <linux/kernel.h> 17 #include <linux/sched.h> 18 #include <linux/kthread.h> 19 #include <linux/export.h> 20 #include <linux/wait.h> 21 #include <linux/delay.h> 22 23 #include <linux/mmc/core.h> 24 #include <linux/mmc/host.h> 25 #include <linux/mmc/card.h> 26 #include <linux/mmc/sdio.h> 27 #include <linux/mmc/sdio_func.h> 28 29 #include "sdio_ops.h" 30 31 static int process_sdio_pending_irqs(struct mmc_host *host) 32 { 33 struct mmc_card *card = host->card; 34 int i, ret, count; 35 unsigned char pending; 36 struct sdio_func *func; 37 38 /* 39 * Optimization, if there is only 1 function interrupt registered 40 * and we know an IRQ was signaled then call irq handler directly. 41 * Otherwise do the full probe. 42 */ 43 func = card->sdio_single_irq; 44 if (func && host->sdio_irq_pending) { 45 func->irq_handler(func); 46 return 1; 47 } 48 49 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending); 50 if (ret) { 51 pr_debug("%s: error %d reading SDIO_CCCR_INTx\n", 52 mmc_card_id(card), ret); 53 return ret; 54 } 55 56 if (pending && mmc_card_broken_irq_polling(card) && 57 !(host->caps & MMC_CAP_SDIO_IRQ)) { 58 unsigned char dummy; 59 60 /* A fake interrupt could be created when we poll SDIO_CCCR_INTx 61 * register with a Marvell SD8797 card. A dummy CMD52 read to 62 * function 0 register 0xff can avoid this. 63 */ 64 mmc_io_rw_direct(card, 0, 0, 0xff, 0, &dummy); 65 } 66 67 count = 0; 68 for (i = 1; i <= 7; i++) { 69 if (pending & (1 << i)) { 70 func = card->sdio_func[i - 1]; 71 if (!func) { 72 pr_warning("%s: pending IRQ for " 73 "non-existent function\n", 74 mmc_card_id(card)); 75 ret = -EINVAL; 76 } else if (func->irq_handler) { 77 func->irq_handler(func); 78 count++; 79 } else { 80 pr_warning("%s: pending IRQ with no handler\n", 81 sdio_func_id(func)); 82 ret = -EINVAL; 83 } 84 } 85 } 86 87 if (count) 88 return count; 89 90 return ret; 91 } 92 93 void sdio_run_irqs(struct mmc_host *host) 94 { 95 mmc_claim_host(host); 96 host->sdio_irq_pending = true; 97 process_sdio_pending_irqs(host); 98 mmc_release_host(host); 99 } 100 EXPORT_SYMBOL_GPL(sdio_run_irqs); 101 102 static int sdio_irq_thread(void *_host) 103 { 104 struct mmc_host *host = _host; 105 struct sched_param param = { .sched_priority = 1 }; 106 unsigned long period, idle_period; 107 int ret; 108 109 sched_setscheduler(current, SCHED_FIFO, ¶m); 110 111 /* 112 * We want to allow for SDIO cards to work even on non SDIO 113 * aware hosts. One thing that non SDIO host cannot do is 114 * asynchronous notification of pending SDIO card interrupts 115 * hence we poll for them in that case. 116 */ 117 idle_period = msecs_to_jiffies(10); 118 period = (host->caps & MMC_CAP_SDIO_IRQ) ? 119 MAX_SCHEDULE_TIMEOUT : idle_period; 120 121 pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n", 122 mmc_hostname(host), period); 123 124 do { 125 /* 126 * We claim the host here on drivers behalf for a couple 127 * reasons: 128 * 129 * 1) it is already needed to retrieve the CCCR_INTx; 130 * 2) we want the driver(s) to clear the IRQ condition ASAP; 131 * 3) we need to control the abort condition locally. 132 * 133 * Just like traditional hard IRQ handlers, we expect SDIO 134 * IRQ handlers to be quick and to the point, so that the 135 * holding of the host lock does not cover too much work 136 * that doesn't require that lock to be held. 137 */ 138 ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort); 139 if (ret) 140 break; 141 ret = process_sdio_pending_irqs(host); 142 host->sdio_irq_pending = false; 143 mmc_release_host(host); 144 145 /* 146 * Give other threads a chance to run in the presence of 147 * errors. 148 */ 149 if (ret < 0) { 150 set_current_state(TASK_INTERRUPTIBLE); 151 if (!kthread_should_stop()) 152 schedule_timeout(HZ); 153 set_current_state(TASK_RUNNING); 154 } 155 156 /* 157 * Adaptive polling frequency based on the assumption 158 * that an interrupt will be closely followed by more. 159 * This has a substantial benefit for network devices. 160 */ 161 if (!(host->caps & MMC_CAP_SDIO_IRQ)) { 162 if (ret > 0) 163 period /= 2; 164 else { 165 period++; 166 if (period > idle_period) 167 period = idle_period; 168 } 169 } 170 171 set_current_state(TASK_INTERRUPTIBLE); 172 if (host->caps & MMC_CAP_SDIO_IRQ) { 173 mmc_host_clk_hold(host); 174 host->ops->enable_sdio_irq(host, 1); 175 mmc_host_clk_release(host); 176 } 177 if (!kthread_should_stop()) 178 schedule_timeout(period); 179 set_current_state(TASK_RUNNING); 180 } while (!kthread_should_stop()); 181 182 if (host->caps & MMC_CAP_SDIO_IRQ) { 183 mmc_host_clk_hold(host); 184 host->ops->enable_sdio_irq(host, 0); 185 mmc_host_clk_release(host); 186 } 187 188 pr_debug("%s: IRQ thread exiting with code %d\n", 189 mmc_hostname(host), ret); 190 191 return ret; 192 } 193 194 static int sdio_card_irq_get(struct mmc_card *card) 195 { 196 struct mmc_host *host = card->host; 197 198 WARN_ON(!host->claimed); 199 200 if (!host->sdio_irqs++) { 201 if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) { 202 atomic_set(&host->sdio_irq_thread_abort, 0); 203 host->sdio_irq_thread = 204 kthread_run(sdio_irq_thread, host, 205 "ksdioirqd/%s", mmc_hostname(host)); 206 if (IS_ERR(host->sdio_irq_thread)) { 207 int err = PTR_ERR(host->sdio_irq_thread); 208 host->sdio_irqs--; 209 return err; 210 } 211 } else { 212 mmc_host_clk_hold(host); 213 host->ops->enable_sdio_irq(host, 1); 214 mmc_host_clk_release(host); 215 } 216 } 217 218 return 0; 219 } 220 221 static int sdio_card_irq_put(struct mmc_card *card) 222 { 223 struct mmc_host *host = card->host; 224 225 WARN_ON(!host->claimed); 226 BUG_ON(host->sdio_irqs < 1); 227 228 if (!--host->sdio_irqs) { 229 if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) { 230 atomic_set(&host->sdio_irq_thread_abort, 1); 231 kthread_stop(host->sdio_irq_thread); 232 } else { 233 mmc_host_clk_hold(host); 234 host->ops->enable_sdio_irq(host, 0); 235 mmc_host_clk_release(host); 236 } 237 } 238 239 return 0; 240 } 241 242 /* If there is only 1 function registered set sdio_single_irq */ 243 static void sdio_single_irq_set(struct mmc_card *card) 244 { 245 struct sdio_func *func; 246 int i; 247 248 card->sdio_single_irq = NULL; 249 if ((card->host->caps & MMC_CAP_SDIO_IRQ) && 250 card->host->sdio_irqs == 1) 251 for (i = 0; i < card->sdio_funcs; i++) { 252 func = card->sdio_func[i]; 253 if (func && func->irq_handler) { 254 card->sdio_single_irq = func; 255 break; 256 } 257 } 258 } 259 260 /** 261 * sdio_claim_irq - claim the IRQ for a SDIO function 262 * @func: SDIO function 263 * @handler: IRQ handler callback 264 * 265 * Claim and activate the IRQ for the given SDIO function. The provided 266 * handler will be called when that IRQ is asserted. The host is always 267 * claimed already when the handler is called so the handler must not 268 * call sdio_claim_host() nor sdio_release_host(). 269 */ 270 int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler) 271 { 272 int ret; 273 unsigned char reg; 274 275 BUG_ON(!func); 276 BUG_ON(!func->card); 277 278 pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func)); 279 280 if (func->irq_handler) { 281 pr_debug("SDIO: IRQ for %s already in use.\n", sdio_func_id(func)); 282 return -EBUSY; 283 } 284 285 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, ®); 286 if (ret) 287 return ret; 288 289 reg |= 1 << func->num; 290 291 reg |= 1; /* Master interrupt enable */ 292 293 ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL); 294 if (ret) 295 return ret; 296 297 func->irq_handler = handler; 298 ret = sdio_card_irq_get(func->card); 299 if (ret) 300 func->irq_handler = NULL; 301 sdio_single_irq_set(func->card); 302 303 return ret; 304 } 305 EXPORT_SYMBOL_GPL(sdio_claim_irq); 306 307 /** 308 * sdio_release_irq - release the IRQ for a SDIO function 309 * @func: SDIO function 310 * 311 * Disable and release the IRQ for the given SDIO function. 312 */ 313 int sdio_release_irq(struct sdio_func *func) 314 { 315 int ret; 316 unsigned char reg; 317 318 BUG_ON(!func); 319 BUG_ON(!func->card); 320 321 pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func)); 322 323 if (func->irq_handler) { 324 func->irq_handler = NULL; 325 sdio_card_irq_put(func->card); 326 sdio_single_irq_set(func->card); 327 } 328 329 ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, ®); 330 if (ret) 331 return ret; 332 333 reg &= ~(1 << func->num); 334 335 /* Disable master interrupt with the last function interrupt */ 336 if (!(reg & 0xFE)) 337 reg = 0; 338 339 ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL); 340 if (ret) 341 return ret; 342 343 return 0; 344 } 345 EXPORT_SYMBOL_GPL(sdio_release_irq); 346 347