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
31static 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_warn("%s: pending IRQ for non-existent function\n",
73					mmc_card_id(card));
74				ret = -EINVAL;
75			} else if (func->irq_handler) {
76				func->irq_handler(func);
77				count++;
78			} else {
79				pr_warn("%s: pending IRQ with no handler\n",
80					sdio_func_id(func));
81				ret = -EINVAL;
82			}
83		}
84	}
85
86	if (count)
87		return count;
88
89	return ret;
90}
91
92void sdio_run_irqs(struct mmc_host *host)
93{
94	mmc_claim_host(host);
95	host->sdio_irq_pending = true;
96	process_sdio_pending_irqs(host);
97	mmc_release_host(host);
98}
99EXPORT_SYMBOL_GPL(sdio_run_irqs);
100
101static int sdio_irq_thread(void *_host)
102{
103	struct mmc_host *host = _host;
104	struct sched_param param = { .sched_priority = 1 };
105	unsigned long period, idle_period;
106	int ret;
107
108	sched_setscheduler(current, SCHED_FIFO, &param);
109
110	/*
111	 * We want to allow for SDIO cards to work even on non SDIO
112	 * aware hosts.  One thing that non SDIO host cannot do is
113	 * asynchronous notification of pending SDIO card interrupts
114	 * hence we poll for them in that case.
115	 */
116	idle_period = msecs_to_jiffies(10);
117	period = (host->caps & MMC_CAP_SDIO_IRQ) ?
118		MAX_SCHEDULE_TIMEOUT : idle_period;
119
120	pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n",
121		 mmc_hostname(host), period);
122
123	do {
124		/*
125		 * We claim the host here on drivers behalf for a couple
126		 * reasons:
127		 *
128		 * 1) it is already needed to retrieve the CCCR_INTx;
129		 * 2) we want the driver(s) to clear the IRQ condition ASAP;
130		 * 3) we need to control the abort condition locally.
131		 *
132		 * Just like traditional hard IRQ handlers, we expect SDIO
133		 * IRQ handlers to be quick and to the point, so that the
134		 * holding of the host lock does not cover too much work
135		 * that doesn't require that lock to be held.
136		 */
137		ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort);
138		if (ret)
139			break;
140		ret = process_sdio_pending_irqs(host);
141		host->sdio_irq_pending = false;
142		mmc_release_host(host);
143
144		/*
145		 * Give other threads a chance to run in the presence of
146		 * errors.
147		 */
148		if (ret < 0) {
149			set_current_state(TASK_INTERRUPTIBLE);
150			if (!kthread_should_stop())
151				schedule_timeout(HZ);
152			set_current_state(TASK_RUNNING);
153		}
154
155		/*
156		 * Adaptive polling frequency based on the assumption
157		 * that an interrupt will be closely followed by more.
158		 * This has a substantial benefit for network devices.
159		 */
160		if (!(host->caps & MMC_CAP_SDIO_IRQ)) {
161			if (ret > 0)
162				period /= 2;
163			else {
164				period++;
165				if (period > idle_period)
166					period = idle_period;
167			}
168		}
169
170		set_current_state(TASK_INTERRUPTIBLE);
171		if (host->caps & MMC_CAP_SDIO_IRQ) {
172			mmc_host_clk_hold(host);
173			host->ops->enable_sdio_irq(host, 1);
174			mmc_host_clk_release(host);
175		}
176		if (!kthread_should_stop())
177			schedule_timeout(period);
178		set_current_state(TASK_RUNNING);
179	} while (!kthread_should_stop());
180
181	if (host->caps & MMC_CAP_SDIO_IRQ) {
182		mmc_host_clk_hold(host);
183		host->ops->enable_sdio_irq(host, 0);
184		mmc_host_clk_release(host);
185	}
186
187	pr_debug("%s: IRQ thread exiting with code %d\n",
188		 mmc_hostname(host), ret);
189
190	return ret;
191}
192
193static int sdio_card_irq_get(struct mmc_card *card)
194{
195	struct mmc_host *host = card->host;
196
197	WARN_ON(!host->claimed);
198
199	if (!host->sdio_irqs++) {
200		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
201			atomic_set(&host->sdio_irq_thread_abort, 0);
202			host->sdio_irq_thread =
203				kthread_run(sdio_irq_thread, host,
204					    "ksdioirqd/%s", mmc_hostname(host));
205			if (IS_ERR(host->sdio_irq_thread)) {
206				int err = PTR_ERR(host->sdio_irq_thread);
207				host->sdio_irqs--;
208				return err;
209			}
210		} else if (host->caps & MMC_CAP_SDIO_IRQ) {
211			mmc_host_clk_hold(host);
212			host->ops->enable_sdio_irq(host, 1);
213			mmc_host_clk_release(host);
214		}
215	}
216
217	return 0;
218}
219
220static int sdio_card_irq_put(struct mmc_card *card)
221{
222	struct mmc_host *host = card->host;
223
224	WARN_ON(!host->claimed);
225	BUG_ON(host->sdio_irqs < 1);
226
227	if (!--host->sdio_irqs) {
228		if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) {
229			atomic_set(&host->sdio_irq_thread_abort, 1);
230			kthread_stop(host->sdio_irq_thread);
231		} else if (host->caps & MMC_CAP_SDIO_IRQ) {
232			mmc_host_clk_hold(host);
233			host->ops->enable_sdio_irq(host, 0);
234			mmc_host_clk_release(host);
235		}
236	}
237
238	return 0;
239}
240
241/* If there is only 1 function registered set sdio_single_irq */
242static void sdio_single_irq_set(struct mmc_card *card)
243{
244	struct sdio_func *func;
245	int i;
246
247	card->sdio_single_irq = NULL;
248	if ((card->host->caps & MMC_CAP_SDIO_IRQ) &&
249	    card->host->sdio_irqs == 1)
250		for (i = 0; i < card->sdio_funcs; i++) {
251		       func = card->sdio_func[i];
252		       if (func && func->irq_handler) {
253			       card->sdio_single_irq = func;
254			       break;
255		       }
256	       }
257}
258
259/**
260 *	sdio_claim_irq - claim the IRQ for a SDIO function
261 *	@func: SDIO function
262 *	@handler: IRQ handler callback
263 *
264 *	Claim and activate the IRQ for the given SDIO function. The provided
265 *	handler will be called when that IRQ is asserted.  The host is always
266 *	claimed already when the handler is called so the handler must not
267 *	call sdio_claim_host() nor sdio_release_host().
268 */
269int sdio_claim_irq(struct sdio_func *func, sdio_irq_handler_t *handler)
270{
271	int ret;
272	unsigned char reg;
273
274	BUG_ON(!func);
275	BUG_ON(!func->card);
276
277	pr_debug("SDIO: Enabling IRQ for %s...\n", sdio_func_id(func));
278
279	if (func->irq_handler) {
280		pr_debug("SDIO: IRQ for %s already in use.\n", sdio_func_id(func));
281		return -EBUSY;
282	}
283
284	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
285	if (ret)
286		return ret;
287
288	reg |= 1 << func->num;
289
290	reg |= 1; /* Master interrupt enable */
291
292	ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
293	if (ret)
294		return ret;
295
296	func->irq_handler = handler;
297	ret = sdio_card_irq_get(func->card);
298	if (ret)
299		func->irq_handler = NULL;
300	sdio_single_irq_set(func->card);
301
302	return ret;
303}
304EXPORT_SYMBOL_GPL(sdio_claim_irq);
305
306/**
307 *	sdio_release_irq - release the IRQ for a SDIO function
308 *	@func: SDIO function
309 *
310 *	Disable and release the IRQ for the given SDIO function.
311 */
312int sdio_release_irq(struct sdio_func *func)
313{
314	int ret;
315	unsigned char reg;
316
317	BUG_ON(!func);
318	BUG_ON(!func->card);
319
320	pr_debug("SDIO: Disabling IRQ for %s...\n", sdio_func_id(func));
321
322	if (func->irq_handler) {
323		func->irq_handler = NULL;
324		sdio_card_irq_put(func->card);
325		sdio_single_irq_set(func->card);
326	}
327
328	ret = mmc_io_rw_direct(func->card, 0, 0, SDIO_CCCR_IENx, 0, &reg);
329	if (ret)
330		return ret;
331
332	reg &= ~(1 << func->num);
333
334	/* Disable master interrupt with the last function interrupt */
335	if (!(reg & 0xFE))
336		reg = 0;
337
338	ret = mmc_io_rw_direct(func->card, 1, 0, SDIO_CCCR_IENx, reg, NULL);
339	if (ret)
340		return ret;
341
342	return 0;
343}
344EXPORT_SYMBOL_GPL(sdio_release_irq);
345
346