core.c 18.5 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
/*
2
 *  linux/drivers/mmc/core/core.c
Linus Torvalds's avatar
Linus Torvalds committed
3
4
 *
 *  Copyright (C) 2003-2004 Russell King, All Rights Reserved.
5
 *  SD support Copyright (C) 2004 Ian Molton, All Rights Reserved.
6
 *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
7
 *  MMCv4 support Copyright (C) 2006 Philip Langdale, All Rights Reserved.
Linus Torvalds's avatar
Linus Torvalds committed
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/pagemap.h>
#include <linux/err.h>
Pierre Ossman's avatar
Pierre Ossman committed
21
#include <linux/leds.h>
Pierre Ossman's avatar
Pierre Ossman committed
22
#include <linux/scatterlist.h>
Linus Torvalds's avatar
Linus Torvalds committed
23
24
25

#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
Pierre Ossman's avatar
Pierre Ossman committed
26
27
#include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
Linus Torvalds's avatar
Linus Torvalds committed
28

29
#include "core.h"
30
31
#include "bus.h"
#include "host.h"
Pierre Ossman's avatar
Pierre Ossman committed
32
#include "sdio_bus.h"
Pierre Ossman's avatar
Pierre Ossman committed
33
34
35

#include "mmc_ops.h"
#include "sd_ops.h"
Pierre Ossman's avatar
Pierre Ossman committed
36
#include "sdio_ops.h"
Linus Torvalds's avatar
Linus Torvalds committed
37

38
39
static struct workqueue_struct *workqueue;

David Brownell's avatar
David Brownell committed
40
41
42
43
44
45
46
47
/*
 * Enabling software CRCs on the data blocks can be a significant (30%)
 * performance cost, and for other reasons may not always be desired.
 * So we allow it it to be disabled.
 */
int use_spi_crc = 1;
module_param(use_spi_crc, bool, 0);

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
 * Internal function. Schedule delayed work in the MMC work queue.
 */
static int mmc_schedule_delayed_work(struct delayed_work *work,
				     unsigned long delay)
{
	return queue_delayed_work(workqueue, work, delay);
}

/*
 * Internal function. Flush all scheduled work from the MMC work queue.
 */
static void mmc_flush_scheduled_work(void)
{
	flush_workqueue(workqueue);
}

Linus Torvalds's avatar
Linus Torvalds committed
65
/**
66
67
68
 *	mmc_request_done - finish processing an MMC request
 *	@host: MMC host which completed request
 *	@mrq: MMC request which request
Linus Torvalds's avatar
Linus Torvalds committed
69
70
 *
 *	MMC drivers should call this function when they have completed
71
 *	their processing of a request.
Linus Torvalds's avatar
Linus Torvalds committed
72
73
74
75
 */
void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
{
	struct mmc_command *cmd = mrq->cmd;
76
77
	int err = cmd->error;

David Brownell's avatar
David Brownell committed
78
79
80
81
82
	if (err && cmd->retries && mmc_host_is_spi(host)) {
		if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)
			cmd->retries = 0;
	}

Linus Torvalds's avatar
Linus Torvalds committed
83
	if (err && cmd->retries) {
84
85
86
		pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
			mmc_hostname(host), cmd->opcode, err);

Linus Torvalds's avatar
Linus Torvalds committed
87
88
89
		cmd->retries--;
		cmd->error = 0;
		host->ops->request(host, mrq);
90
	} else {
Pierre Ossman's avatar
Pierre Ossman committed
91
92
		led_trigger_event(host->led, LED_OFF);

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
		pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
			mmc_hostname(host), cmd->opcode, err,
			cmd->resp[0], cmd->resp[1],
			cmd->resp[2], cmd->resp[3]);

		if (mrq->data) {
			pr_debug("%s:     %d bytes transferred: %d\n",
				mmc_hostname(host),
				mrq->data->bytes_xfered, mrq->data->error);
		}

		if (mrq->stop) {
			pr_debug("%s:     (CMD%u): %d: %08x %08x %08x %08x\n",
				mmc_hostname(host), mrq->stop->opcode,
				mrq->stop->error,
				mrq->stop->resp[0], mrq->stop->resp[1],
				mrq->stop->resp[2], mrq->stop->resp[3]);
		}

		if (mrq->done)
			mrq->done(mrq);
Linus Torvalds's avatar
Linus Torvalds committed
114
115
116
117
118
	}
}

EXPORT_SYMBOL(mmc_request_done);

119
static void
Linus Torvalds's avatar
Linus Torvalds committed
120
121
mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
{
Pierre Ossman's avatar
Pierre Ossman committed
122
123
#ifdef CONFIG_MMC_DEBUG
	unsigned int i, sz;
124
	struct scatterlist *sg;
Pierre Ossman's avatar
Pierre Ossman committed
125
126
#endif

127
128
129
	pr_debug("%s: starting CMD%u arg %08x flags %08x\n",
		 mmc_hostname(host), mrq->cmd->opcode,
		 mrq->cmd->arg, mrq->cmd->flags);
Linus Torvalds's avatar
Linus Torvalds committed
130

131
132
133
134
135
	if (mrq->data) {
		pr_debug("%s:     blksz %d blocks %d flags %08x "
			"tsac %d ms nsac %d\n",
			mmc_hostname(host), mrq->data->blksz,
			mrq->data->blocks, mrq->data->flags,
136
			mrq->data->timeout_ns / 1000000,
137
138
139
140
141
142
143
144
145
			mrq->data->timeout_clks);
	}

	if (mrq->stop) {
		pr_debug("%s:     CMD%u arg %08x flags %08x\n",
			 mmc_hostname(host), mrq->stop->opcode,
			 mrq->stop->arg, mrq->stop->flags);
	}

Pierre Ossman's avatar
Pierre Ossman committed
146
	WARN_ON(!host->claimed);
Linus Torvalds's avatar
Linus Torvalds committed
147

Pierre Ossman's avatar
Pierre Ossman committed
148
149
	led_trigger_event(host->led, LED_FULL);

Linus Torvalds's avatar
Linus Torvalds committed
150
151
152
	mrq->cmd->error = 0;
	mrq->cmd->mrq = mrq;
	if (mrq->data) {
153
		BUG_ON(mrq->data->blksz > host->max_blk_size);
154
155
156
		BUG_ON(mrq->data->blocks > host->max_blk_count);
		BUG_ON(mrq->data->blocks * mrq->data->blksz >
			host->max_req_size);
157

Pierre Ossman's avatar
Pierre Ossman committed
158
159
#ifdef CONFIG_MMC_DEBUG
		sz = 0;
160
161
		for_each_sg(mrq->data->sg, sg, mrq->data->sg_len, i)
			sz += sg->length;
Pierre Ossman's avatar
Pierre Ossman committed
162
163
164
		BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
#endif

Linus Torvalds's avatar
Linus Torvalds committed
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
		mrq->cmd->data = mrq->data;
		mrq->data->error = 0;
		mrq->data->mrq = mrq;
		if (mrq->stop) {
			mrq->data->stop = mrq->stop;
			mrq->stop->error = 0;
			mrq->stop->mrq = mrq;
		}
	}
	host->ops->request(host, mrq);
}

static void mmc_wait_done(struct mmc_request *mrq)
{
	complete(mrq->done_data);
}

Pierre Ossman's avatar
Pierre Ossman committed
182
183
184
185
186
187
188
189
190
191
/**
 *	mmc_wait_for_req - start a request and wait for completion
 *	@host: MMC host to start command
 *	@mrq: MMC request to start
 *
 *	Start a new MMC custom command request for a host, and wait
 *	for the command to complete. Does not attempt to parse the
 *	response.
 */
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
Linus Torvalds's avatar
Linus Torvalds committed
192
{
193
	DECLARE_COMPLETION_ONSTACK(complete);
Linus Torvalds's avatar
Linus Torvalds committed
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218

	mrq->done_data = &complete;
	mrq->done = mmc_wait_done;

	mmc_start_request(host, mrq);

	wait_for_completion(&complete);
}

EXPORT_SYMBOL(mmc_wait_for_req);

/**
 *	mmc_wait_for_cmd - start a command and wait for completion
 *	@host: MMC host to start command
 *	@cmd: MMC command to start
 *	@retries: maximum number of retries
 *
 *	Start a new MMC command for a host, and wait for the command
 *	to complete.  Return any error that occurred while the command
 *	was executing.  Do not attempt to parse the response.
 */
int mmc_wait_for_cmd(struct mmc_host *host, struct mmc_command *cmd, int retries)
{
	struct mmc_request mrq;

219
	WARN_ON(!host->claimed);
Linus Torvalds's avatar
Linus Torvalds committed
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235

	memset(&mrq, 0, sizeof(struct mmc_request));

	memset(cmd->resp, 0, sizeof(cmd->resp));
	cmd->retries = retries;

	mrq.cmd = cmd;
	cmd->data = NULL;

	mmc_wait_for_req(host, &mrq);

	return cmd->error;
}

EXPORT_SYMBOL(mmc_wait_for_cmd);

236
237
238
239
/**
 *	mmc_set_data_timeout - set the timeout for a data command
 *	@data: data phase for command
 *	@card: the MMC card associated with the data transfer
Pierre Ossman's avatar
Pierre Ossman committed
240
241
242
 *
 *	Computes the data timeout parameters according to the
 *	correct algorithm given the card type.
243
 */
244
void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
245
246
247
{
	unsigned int mult;

248
249
250
251
252
253
254
255
256
	/*
	 * SDIO cards only define an upper 1 s limit on access.
	 */
	if (mmc_card_sdio(card)) {
		data->timeout_ns = 1000000000;
		data->timeout_clks = 0;
		return;
	}

257
258
259
260
261
262
263
264
265
	/*
	 * SD cards use a 100 multiplier rather than 10
	 */
	mult = mmc_card_sd(card) ? 100 : 10;

	/*
	 * Scale up the multiplier (and therefore the timeout) by
	 * the r2w factor for writes.
	 */
266
	if (data->flags & MMC_DATA_WRITE)
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
		mult <<= card->csd.r2w_factor;

	data->timeout_ns = card->csd.tacc_ns * mult;
	data->timeout_clks = card->csd.tacc_clks * mult;

	/*
	 * SD cards also have an upper limit on the timeout.
	 */
	if (mmc_card_sd(card)) {
		unsigned int timeout_us, limit_us;

		timeout_us = data->timeout_ns / 1000;
		timeout_us += data->timeout_clks * 1000 /
			(card->host->ios.clock / 1000);

282
		if (data->flags & MMC_DATA_WRITE)
283
284
285
286
			limit_us = 250000;
		else
			limit_us = 100000;

287
288
289
290
		/*
		 * SDHC cards always use these fixed values.
		 */
		if (timeout_us > limit_us || mmc_card_blockaddr(card)) {
291
292
293
294
295
296
297
			data->timeout_ns = limit_us * 1000;
			data->timeout_clks = 0;
		}
	}
}
EXPORT_SYMBOL(mmc_set_data_timeout);

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
/**
 *	mmc_align_data_size - pads a transfer size to a more optimal value
 *	@card: the MMC card associated with the data transfer
 *	@sz: original transfer size
 *
 *	Pads the original data size with a number of extra bytes in
 *	order to avoid controller bugs and/or performance hits
 *	(e.g. some controllers revert to PIO for certain sizes).
 *
 *	Returns the improved size, which might be unmodified.
 *
 *	Note that this function is only relevant when issuing a
 *	single scatter gather entry.
 */
unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz)
{
	/*
	 * FIXME: We don't have a system for the controller to tell
	 * the core about its problems yet, so for now we just 32-bit
	 * align the size.
	 */
	sz = ((sz + 3) / 4) * 4;

	return sz;
}
EXPORT_SYMBOL(mmc_align_data_size);

Linus Torvalds's avatar
Linus Torvalds committed
325
/**
326
 *	__mmc_claim_host - exclusively claim a host
Linus Torvalds's avatar
Linus Torvalds committed
327
 *	@host: mmc host to claim
328
 *	@abort: whether or not the operation should be aborted
Linus Torvalds's avatar
Linus Torvalds committed
329
 *
330
331
332
333
 *	Claim a host for a set of operations.  If @abort is non null and
 *	dereference a non-zero value then this will return prematurely with
 *	that non-zero value without acquiring the lock.  Returns zero
 *	with the lock held otherwise.
Linus Torvalds's avatar
Linus Torvalds committed
334
 */
335
int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
Linus Torvalds's avatar
Linus Torvalds committed
336
337
338
{
	DECLARE_WAITQUEUE(wait, current);
	unsigned long flags;
339
	int stop;
Linus Torvalds's avatar
Linus Torvalds committed
340

341
342
	might_sleep();

Linus Torvalds's avatar
Linus Torvalds committed
343
344
345
346
	add_wait_queue(&host->wq, &wait);
	spin_lock_irqsave(&host->lock, flags);
	while (1) {
		set_current_state(TASK_UNINTERRUPTIBLE);
347
348
		stop = abort ? atomic_read(abort) : 0;
		if (stop || !host->claimed)
Linus Torvalds's avatar
Linus Torvalds committed
349
350
351
352
353
354
			break;
		spin_unlock_irqrestore(&host->lock, flags);
		schedule();
		spin_lock_irqsave(&host->lock, flags);
	}
	set_current_state(TASK_RUNNING);
355
356
357
358
	if (!stop)
		host->claimed = 1;
	else
		wake_up(&host->wq);
Linus Torvalds's avatar
Linus Torvalds committed
359
360
	spin_unlock_irqrestore(&host->lock, flags);
	remove_wait_queue(&host->wq, &wait);
361
	return stop;
Linus Torvalds's avatar
Linus Torvalds committed
362
363
}

364
EXPORT_SYMBOL(__mmc_claim_host);
Linus Torvalds's avatar
Linus Torvalds committed
365
366
367
368
369
370
371
372
373
374
375
376

/**
 *	mmc_release_host - release a host
 *	@host: mmc host to release
 *
 *	Release a MMC host, allowing others to claim the host
 *	for their operations.
 */
void mmc_release_host(struct mmc_host *host)
{
	unsigned long flags;

377
	WARN_ON(!host->claimed);
Linus Torvalds's avatar
Linus Torvalds committed
378
379

	spin_lock_irqsave(&host->lock, flags);
Pierre Ossman's avatar
Pierre Ossman committed
380
	host->claimed = 0;
Linus Torvalds's avatar
Linus Torvalds committed
381
382
383
384
385
386
387
	spin_unlock_irqrestore(&host->lock, flags);

	wake_up(&host->wq);
}

EXPORT_SYMBOL(mmc_release_host);

Pierre Ossman's avatar
Pierre Ossman committed
388
389
390
391
/*
 * Internal function that does the actual ios call to the host driver,
 * optionally printing some debug output.
 */
392
393
394
395
static inline void mmc_set_ios(struct mmc_host *host)
{
	struct mmc_ios *ios = &host->ios;

396
397
	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
		"width %u timing %u\n",
398
399
		 mmc_hostname(host), ios->clock, ios->bus_mode,
		 ios->power_mode, ios->chip_select, ios->vdd,
400
		 ios->bus_width, ios->timing);
401

402
403
404
	host->ops->set_ios(host, ios);
}

Pierre Ossman's avatar
Pierre Ossman committed
405
406
407
/*
 * Control chip select pin on a host.
 */
Pierre Ossman's avatar
Pierre Ossman committed
408
void mmc_set_chip_select(struct mmc_host *host, int mode)
Linus Torvalds's avatar
Linus Torvalds committed
409
{
Pierre Ossman's avatar
Pierre Ossman committed
410
411
	host->ios.chip_select = mode;
	mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
412
413
}

Pierre Ossman's avatar
Pierre Ossman committed
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
/*
 * Sets the host clock to the highest possible frequency that
 * is below "hz".
 */
void mmc_set_clock(struct mmc_host *host, unsigned int hz)
{
	WARN_ON(hz < host->f_min);

	if (hz > host->f_max)
		hz = host->f_max;

	host->ios.clock = hz;
	mmc_set_ios(host);
}

/*
 * Change the bus mode (open drain/push-pull) of a host.
 */
void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode)
{
	host->ios.bus_mode = mode;
	mmc_set_ios(host);
}

/*
 * Change data bus width of a host.
 */
void mmc_set_bus_width(struct mmc_host *host, unsigned int width)
{
	host->ios.bus_width = width;
	mmc_set_ios(host);
}

Linus Torvalds's avatar
Linus Torvalds committed
447
448
449
450
/*
 * Mask off any voltages we don't support and select
 * the lowest voltage
 */
Pierre Ossman's avatar
Pierre Ossman committed
451
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
Linus Torvalds's avatar
Linus Torvalds committed
452
453
454
455
456
457
458
459
460
{
	int bit;

	ocr &= host->ocr_avail;

	bit = ffs(ocr);
	if (bit) {
		bit -= 1;

461
		ocr &= 3 << bit;
Linus Torvalds's avatar
Linus Torvalds committed
462
463

		host->ios.vdd = bit;
464
		mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
465
466
467
468
469
470
471
	} else {
		ocr = 0;
	}

	return ocr;
}

Pierre Ossman's avatar
Pierre Ossman committed
472
/*
Pierre Ossman's avatar
Pierre Ossman committed
473
 * Select timing parameters for host.
Pierre Ossman's avatar
Pierre Ossman committed
474
 */
Pierre Ossman's avatar
Pierre Ossman committed
475
void mmc_set_timing(struct mmc_host *host, unsigned int timing)
Pierre Ossman's avatar
Pierre Ossman committed
476
{
Pierre Ossman's avatar
Pierre Ossman committed
477
478
	host->ios.timing = timing;
	mmc_set_ios(host);
Pierre Ossman's avatar
Pierre Ossman committed
479
480
}

Linus Torvalds's avatar
Linus Torvalds committed
481
/*
482
483
484
485
486
487
488
489
490
 * Apply power to the MMC stack.  This is a two-stage process.
 * First, we enable power to the card without the clock running.
 * We then wait a bit for the power to stabilise.  Finally,
 * enable the bus drivers and clock to the card.
 *
 * We must _NOT_ enable the clock prior to power stablising.
 *
 * If a host does all the power sequencing itself, ignore the
 * initial MMC_POWER_UP stage.
Linus Torvalds's avatar
Linus Torvalds committed
491
492
493
494
495
496
 */
static void mmc_power_up(struct mmc_host *host)
{
	int bit = fls(host->ocr_avail) - 1;

	host->ios.vdd = bit;
David Brownell's avatar
David Brownell committed
497
498
499
500
501
502
503
	if (mmc_host_is_spi(host)) {
		host->ios.chip_select = MMC_CS_HIGH;
		host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
	} else {
		host->ios.chip_select = MMC_CS_DONTCARE;
		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
	}
Linus Torvalds's avatar
Linus Torvalds committed
504
	host->ios.power_mode = MMC_POWER_UP;
Pierre Ossman's avatar
Pierre Ossman committed
505
	host->ios.bus_width = MMC_BUS_WIDTH_1;
506
	host->ios.timing = MMC_TIMING_LEGACY;
507
	mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
508

Pierre Ossman's avatar
Pierre Ossman committed
509
510
511
512
513
	/*
	 * This delay should be sufficient to allow the power supply
	 * to reach the minimum voltage.
	 */
	mmc_delay(2);
Linus Torvalds's avatar
Linus Torvalds committed
514
515
516

	host->ios.clock = host->f_min;
	host->ios.power_mode = MMC_POWER_ON;
517
	mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
518

Pierre Ossman's avatar
Pierre Ossman committed
519
520
521
522
	/*
	 * This delay must be at least 74 clock sizes, or 1 ms, or the
	 * time required to reach a stable voltage.
	 */
Linus Torvalds's avatar
Linus Torvalds committed
523
524
525
526
527
528
529
	mmc_delay(2);
}

static void mmc_power_off(struct mmc_host *host)
{
	host->ios.clock = 0;
	host->ios.vdd = 0;
David Brownell's avatar
David Brownell committed
530
531
532
533
	if (!mmc_host_is_spi(host)) {
		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
		host->ios.chip_select = MMC_CS_DONTCARE;
	}
Linus Torvalds's avatar
Linus Torvalds committed
534
	host->ios.power_mode = MMC_POWER_OFF;
Pierre Ossman's avatar
Pierre Ossman committed
535
	host->ios.bus_width = MMC_BUS_WIDTH_1;
536
	host->ios.timing = MMC_TIMING_LEGACY;
537
	mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
538
539
}

540
541
542
/*
 * Cleanup when the last reference to the bus operator is dropped.
 */
543
static void __mmc_release_bus(struct mmc_host *host)
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
{
	BUG_ON(!host);
	BUG_ON(host->bus_refs);
	BUG_ON(!host->bus_dead);

	host->bus_ops = NULL;
}

/*
 * Increase reference count of bus operator
 */
static inline void mmc_bus_get(struct mmc_host *host)
{
	unsigned long flags;

	spin_lock_irqsave(&host->lock, flags);
	host->bus_refs++;
	spin_unlock_irqrestore(&host->lock, flags);
}

/*
 * Decrease reference count of bus operator and free it if
 * it is the last reference.
 */
static inline void mmc_bus_put(struct mmc_host *host)
{
	unsigned long flags;

	spin_lock_irqsave(&host->lock, flags);
	host->bus_refs--;
	if ((host->bus_refs == 0) && host->bus_ops)
		__mmc_release_bus(host);
	spin_unlock_irqrestore(&host->lock, flags);
}

Linus Torvalds's avatar
Linus Torvalds committed
579
/*
Pierre Ossman's avatar
Pierre Ossman committed
580
581
 * Assign a mmc bus handler to a host. Only one bus handler may control a
 * host at any given time.
Linus Torvalds's avatar
Linus Torvalds committed
582
 */
Pierre Ossman's avatar
Pierre Ossman committed
583
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
Linus Torvalds's avatar
Linus Torvalds committed
584
{
Pierre Ossman's avatar
Pierre Ossman committed
585
	unsigned long flags;
586

Pierre Ossman's avatar
Pierre Ossman committed
587
588
	BUG_ON(!host);
	BUG_ON(!ops);
589

590
	WARN_ON(!host->claimed);
591

Pierre Ossman's avatar
Pierre Ossman committed
592
	spin_lock_irqsave(&host->lock, flags);
593

Pierre Ossman's avatar
Pierre Ossman committed
594
595
	BUG_ON(host->bus_ops);
	BUG_ON(host->bus_refs);
Pierre Ossman's avatar
Pierre Ossman committed
596

Pierre Ossman's avatar
Pierre Ossman committed
597
598
599
	host->bus_ops = ops;
	host->bus_refs = 1;
	host->bus_dead = 0;
Pierre Ossman's avatar
Pierre Ossman committed
600

Pierre Ossman's avatar
Pierre Ossman committed
601
	spin_unlock_irqrestore(&host->lock, flags);
Pierre Ossman's avatar
Pierre Ossman committed
602
603
}

Pierre Ossman's avatar
Pierre Ossman committed
604
605
606
607
608
/*
 * Remove the current bus handler from a host. Assumes that there are
 * no interesting cards left, so the bus is powered down.
 */
void mmc_detach_bus(struct mmc_host *host)
609
{
Pierre Ossman's avatar
Pierre Ossman committed
610
	unsigned long flags;
611

Pierre Ossman's avatar
Pierre Ossman committed
612
	BUG_ON(!host);
613

614
615
	WARN_ON(!host->claimed);
	WARN_ON(!host->bus_ops);
616

Pierre Ossman's avatar
Pierre Ossman committed
617
	spin_lock_irqsave(&host->lock, flags);
618

Pierre Ossman's avatar
Pierre Ossman committed
619
	host->bus_dead = 1;
620

Pierre Ossman's avatar
Pierre Ossman committed
621
	spin_unlock_irqrestore(&host->lock, flags);
Linus Torvalds's avatar
Linus Torvalds committed
622

Pierre Ossman's avatar
Pierre Ossman committed
623
	mmc_power_off(host);
Linus Torvalds's avatar
Linus Torvalds committed
624

Pierre Ossman's avatar
Pierre Ossman committed
625
	mmc_bus_put(host);
Linus Torvalds's avatar
Linus Torvalds committed
626
627
628
629
630
}

/**
 *	mmc_detect_change - process change of state on a MMC socket
 *	@host: host which changed state.
631
 *	@delay: optional delay to wait before detection (jiffies)
Linus Torvalds's avatar
Linus Torvalds committed
632
 *
Pierre Ossman's avatar
Pierre Ossman committed
633
634
635
636
 *	MMC drivers should call this when they detect a card has been
 *	inserted or removed. The MMC layer will confirm that any
 *	present card is still functional, and initialize any newly
 *	inserted.
Linus Torvalds's avatar
Linus Torvalds committed
637
 */
638
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
Linus Torvalds's avatar
Linus Torvalds committed
639
{
640
#ifdef CONFIG_MMC_DEBUG
641
	unsigned long flags;
Andrew Morton's avatar
Andrew Morton committed
642
	spin_lock_irqsave(&host->lock, flags);
643
	WARN_ON(host->removed);
Andrew Morton's avatar
Andrew Morton committed
644
	spin_unlock_irqrestore(&host->lock, flags);
645
646
#endif

David Howells's avatar
David Howells committed
647
	mmc_schedule_delayed_work(&host->detect, delay);
Linus Torvalds's avatar
Linus Torvalds committed
648
649
650
651
652
}

EXPORT_SYMBOL(mmc_detect_change);


653
void mmc_rescan(struct work_struct *work)
Linus Torvalds's avatar
Linus Torvalds committed
654
{
David Howells's avatar
David Howells committed
655
656
	struct mmc_host *host =
		container_of(work, struct mmc_host, detect.work);
Pierre Ossman's avatar
Pierre Ossman committed
657
658
	u32 ocr;
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
659

Pierre Ossman's avatar
Pierre Ossman committed
660
	mmc_bus_get(host);
661

Pierre Ossman's avatar
Pierre Ossman committed
662
	if (host->bus_ops == NULL) {
Linus Torvalds's avatar
Linus Torvalds committed
663
		/*
Pierre Ossman's avatar
Pierre Ossman committed
664
665
		 * Only we can add a new handler, so it's safe to
		 * release the lock here.
Linus Torvalds's avatar
Linus Torvalds committed
666
		 */
Pierre Ossman's avatar
Pierre Ossman committed
667
		mmc_bus_put(host);
Linus Torvalds's avatar
Linus Torvalds committed
668

669
670
671
		if (host->ops->get_cd && host->ops->get_cd(host) == 0)
			goto out;

Pierre Ossman's avatar
Pierre Ossman committed
672
		mmc_claim_host(host);
Linus Torvalds's avatar
Linus Torvalds committed
673

Pierre Ossman's avatar
Pierre Ossman committed
674
675
		mmc_power_up(host);
		mmc_go_idle(host);
Linus Torvalds's avatar
Linus Torvalds committed
676

Pierre Ossman's avatar
Pierre Ossman committed
677
		mmc_send_if_cond(host, host->ocr_avail);
Linus Torvalds's avatar
Linus Torvalds committed
678

Pierre Ossman's avatar
Pierre Ossman committed
679
680
681
682
683
684
685
		/*
		 * First we search for SDIO...
		 */
		err = mmc_send_io_op_cond(host, 0, &ocr);
		if (!err) {
			if (mmc_attach_sdio(host, ocr))
				mmc_power_off(host);
686
			goto out;
Pierre Ossman's avatar
Pierre Ossman committed
687
688
689
690
691
		}

		/*
		 * ...then normal SD...
		 */
Pierre Ossman's avatar
Pierre Ossman committed
692
		err = mmc_send_app_op_cond(host, 0, &ocr);
Pierre Ossman's avatar
Pierre Ossman committed
693
		if (!err) {
Pierre Ossman's avatar
Pierre Ossman committed
694
695
			if (mmc_attach_sd(host, ocr))
				mmc_power_off(host);
696
			goto out;
Pierre Ossman's avatar
Pierre Ossman committed
697
698
699
700
701
702
703
704
		}

		/*
		 * ...and finally MMC.
		 */
		err = mmc_send_op_cond(host, 0, &ocr);
		if (!err) {
			if (mmc_attach_mmc(host, ocr))
Pierre Ossman's avatar
Pierre Ossman committed
705
				mmc_power_off(host);
706
			goto out;
Pierre Ossman's avatar
Pierre Ossman committed
707
		}
Pierre Ossman's avatar
Pierre Ossman committed
708
709
710

		mmc_release_host(host);
		mmc_power_off(host);
Pierre Ossman's avatar
Pierre Ossman committed
711
712
713
714
715
716
	} else {
		if (host->bus_ops->detect && !host->bus_dead)
			host->bus_ops->detect(host);

		mmc_bus_put(host);
	}
717
718
719
out:
	if (host->caps & MMC_CAP_NEEDS_POLL)
		mmc_schedule_delayed_work(&host->detect, HZ);
Linus Torvalds's avatar
Linus Torvalds committed
720
721
}

722
void mmc_start_host(struct mmc_host *host)
Linus Torvalds's avatar
Linus Torvalds committed
723
{
724
725
	mmc_power_off(host);
	mmc_detect_change(host, 0);
Linus Torvalds's avatar
Linus Torvalds committed
726
727
}

728
void mmc_stop_host(struct mmc_host *host)
Linus Torvalds's avatar
Linus Torvalds committed
729
{
730
#ifdef CONFIG_MMC_DEBUG
731
732
	unsigned long flags;
	spin_lock_irqsave(&host->lock, flags);
733
	host->removed = 1;
734
	spin_unlock_irqrestore(&host->lock, flags);
735
736
737
738
#endif

	mmc_flush_scheduled_work();

Pierre Ossman's avatar
Pierre Ossman committed
739
740
741
742
743
744
745
746
	mmc_bus_get(host);
	if (host->bus_ops && !host->bus_dead) {
		if (host->bus_ops->remove)
			host->bus_ops->remove(host);

		mmc_claim_host(host);
		mmc_detach_bus(host);
		mmc_release_host(host);
Linus Torvalds's avatar
Linus Torvalds committed
747
	}
Pierre Ossman's avatar
Pierre Ossman committed
748
749
750
	mmc_bus_put(host);

	BUG_ON(host->card);
Linus Torvalds's avatar
Linus Torvalds committed
751
752
753
754
755
756
757
758
759
760
761

	mmc_power_off(host);
}

#ifdef CONFIG_PM

/**
 *	mmc_suspend_host - suspend a host
 *	@host: mmc host
 *	@state: suspend mode (PM_SUSPEND_xxx)
 */
762
int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
Linus Torvalds's avatar
Linus Torvalds committed
763
{
Pierre Ossman's avatar
Pierre Ossman committed
764
765
	mmc_flush_scheduled_work();

Pierre Ossman's avatar
Pierre Ossman committed
766
767
	mmc_bus_get(host);
	if (host->bus_ops && !host->bus_dead) {
768
769
770
771
772
773
774
775
776
777
		if (host->bus_ops->suspend)
			host->bus_ops->suspend(host);
		if (!host->bus_ops->resume) {
			if (host->bus_ops->remove)
				host->bus_ops->remove(host);

			mmc_claim_host(host);
			mmc_detach_bus(host);
			mmc_release_host(host);
		}
Pierre Ossman's avatar
Pierre Ossman committed
778
	}
Pierre Ossman's avatar
Pierre Ossman committed
779
780
	mmc_bus_put(host);

Linus Torvalds's avatar
Linus Torvalds committed
781
782
783
784
785
786
787
788
789
790
791
792
793
	mmc_power_off(host);

	return 0;
}

EXPORT_SYMBOL(mmc_suspend_host);

/**
 *	mmc_resume_host - resume a previously suspended host
 *	@host: mmc host
 */
int mmc_resume_host(struct mmc_host *host)
{
794
795
796
797
798
799
800
801
802
803
804
805
806
	mmc_bus_get(host);
	if (host->bus_ops && !host->bus_dead) {
		mmc_power_up(host);
		BUG_ON(!host->bus_ops->resume);
		host->bus_ops->resume(host);
	}
	mmc_bus_put(host);

	/*
	 * We add a slight delay here so that resume can progress
	 * in parallel.
	 */
	mmc_detect_change(host, 1);
Linus Torvalds's avatar
Linus Torvalds committed
807
808
809
810
811
812
813
814

	return 0;
}

EXPORT_SYMBOL(mmc_resume_host);

#endif

815
816
817
818
819
820
821
822
823
static int __init mmc_init(void)
{
	int ret;

	workqueue = create_singlethread_workqueue("kmmcd");
	if (!workqueue)
		return -ENOMEM;

	ret = mmc_register_bus();
Pierre Ossman's avatar
Pierre Ossman committed
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
	if (ret)
		goto destroy_workqueue;

	ret = mmc_register_host_class();
	if (ret)
		goto unregister_bus;

	ret = sdio_register_bus();
	if (ret)
		goto unregister_host_class;

	return 0;

unregister_host_class:
	mmc_unregister_host_class();
unregister_bus:
	mmc_unregister_bus();
destroy_workqueue:
	destroy_workqueue(workqueue);

844
845
846
847
848
	return ret;
}

static void __exit mmc_exit(void)
{
Pierre Ossman's avatar
Pierre Ossman committed
849
	sdio_unregister_bus();
850
851
852
853
854
	mmc_unregister_host_class();
	mmc_unregister_bus();
	destroy_workqueue(workqueue);
}

855
subsys_initcall(mmc_init);
856
857
module_exit(mmc_exit);

Linus Torvalds's avatar
Linus Torvalds committed
858
MODULE_LICENSE("GPL");