core.c 17.7 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-2007 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

Pierre Ossman's avatar
Pierre Ossman committed
38
39
extern int mmc_attach_mmc(struct mmc_host *host, u32 ocr);
extern int mmc_attach_sd(struct mmc_host *host, u32 ocr);
Pierre Ossman's avatar
Pierre Ossman committed
40
extern int mmc_attach_sdio(struct mmc_host *host, u32 ocr);
Linus Torvalds's avatar
Linus Torvalds committed
41

42
43
static struct workqueue_struct *workqueue;

David Brownell's avatar
David Brownell committed
44
45
46
47
48
49
50
51
/*
 * 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);

52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/*
 * 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
69
/**
70
71
72
 *	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
73
74
 *
 *	MMC drivers should call this function when they have completed
75
 *	their processing of a request.
Linus Torvalds's avatar
Linus Torvalds committed
76
77
78
79
 */
void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq)
{
	struct mmc_command *cmd = mrq->cmd;
80
81
	int err = cmd->error;

David Brownell's avatar
David Brownell committed
82
83
84
85
86
	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
87
	if (err && cmd->retries) {
88
89
90
		pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
			mmc_hostname(host), cmd->opcode, err);

Linus Torvalds's avatar
Linus Torvalds committed
91
92
93
		cmd->retries--;
		cmd->error = 0;
		host->ops->request(host, mrq);
94
	} else {
Pierre Ossman's avatar
Pierre Ossman committed
95
96
		led_trigger_event(host->led, LED_OFF);

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
		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
118
119
120
121
122
	}
}

EXPORT_SYMBOL(mmc_request_done);

123
static void
Linus Torvalds's avatar
Linus Torvalds committed
124
125
mmc_start_request(struct mmc_host *host, struct mmc_request *mrq)
{
Pierre Ossman's avatar
Pierre Ossman committed
126
127
128
129
#ifdef CONFIG_MMC_DEBUG
	unsigned int i, sz;
#endif

130
131
132
	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
133

134
135
136
137
138
	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,
139
			mrq->data->timeout_ns / 1000000,
140
141
142
143
144
145
146
147
148
			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
149
	WARN_ON(!host->claimed);
Linus Torvalds's avatar
Linus Torvalds committed
150

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

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

Pierre Ossman's avatar
Pierre Ossman committed
161
162
163
164
165
166
167
#ifdef CONFIG_MMC_DEBUG
		sz = 0;
		for (i = 0;i < mrq->data->sg_len;i++)
			sz += mrq->data->sg[i].length;
		BUG_ON(sz != mrq->data->blocks * mrq->data->blksz);
#endif

Linus Torvalds's avatar
Linus Torvalds committed
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
		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
185
186
187
188
189
190
191
192
193
194
/**
 *	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
195
{
196
	DECLARE_COMPLETION_ONSTACK(complete);
Linus Torvalds's avatar
Linus Torvalds committed
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221

	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;

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

	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);

239
240
241
242
/**
 *	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
243
244
245
 *
 *	Computes the data timeout parameters according to the
 *	correct algorithm given the card type.
246
 */
247
void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card)
248
249
250
{
	unsigned int mult;

251
252
253
254
255
256
257
258
259
	/*
	 * 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;
	}

260
261
262
263
264
265
266
267
268
	/*
	 * 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.
	 */
269
	if (data->flags & MMC_DATA_WRITE)
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
		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);

285
		if (data->flags & MMC_DATA_WRITE)
286
287
288
289
			limit_us = 250000;
		else
			limit_us = 100000;

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

Linus Torvalds's avatar
Linus Torvalds committed
301
/**
302
 *	__mmc_claim_host - exclusively claim a host
Linus Torvalds's avatar
Linus Torvalds committed
303
 *	@host: mmc host to claim
304
 *	@abort: whether or not the operation should be aborted
Linus Torvalds's avatar
Linus Torvalds committed
305
 *
306
307
308
309
 *	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
310
 */
311
int __mmc_claim_host(struct mmc_host *host, atomic_t *abort)
Linus Torvalds's avatar
Linus Torvalds committed
312
313
314
{
	DECLARE_WAITQUEUE(wait, current);
	unsigned long flags;
315
	int stop;
Linus Torvalds's avatar
Linus Torvalds committed
316

317
318
	might_sleep();

Linus Torvalds's avatar
Linus Torvalds committed
319
320
321
322
	add_wait_queue(&host->wq, &wait);
	spin_lock_irqsave(&host->lock, flags);
	while (1) {
		set_current_state(TASK_UNINTERRUPTIBLE);
323
324
		stop = abort ? atomic_read(abort) : 0;
		if (stop || !host->claimed)
Linus Torvalds's avatar
Linus Torvalds committed
325
326
327
328
329
330
			break;
		spin_unlock_irqrestore(&host->lock, flags);
		schedule();
		spin_lock_irqsave(&host->lock, flags);
	}
	set_current_state(TASK_RUNNING);
331
332
333
334
	if (!stop)
		host->claimed = 1;
	else
		wake_up(&host->wq);
Linus Torvalds's avatar
Linus Torvalds committed
335
336
	spin_unlock_irqrestore(&host->lock, flags);
	remove_wait_queue(&host->wq, &wait);
337
	return stop;
Linus Torvalds's avatar
Linus Torvalds committed
338
339
}

340
EXPORT_SYMBOL(__mmc_claim_host);
Linus Torvalds's avatar
Linus Torvalds committed
341
342
343
344
345
346
347
348
349
350
351
352

/**
 *	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;

353
	WARN_ON(!host->claimed);
Linus Torvalds's avatar
Linus Torvalds committed
354
355

	spin_lock_irqsave(&host->lock, flags);
Pierre Ossman's avatar
Pierre Ossman committed
356
	host->claimed = 0;
Linus Torvalds's avatar
Linus Torvalds committed
357
358
359
360
361
362
363
	spin_unlock_irqrestore(&host->lock, flags);

	wake_up(&host->wq);
}

EXPORT_SYMBOL(mmc_release_host);

Pierre Ossman's avatar
Pierre Ossman committed
364
365
366
367
/*
 * Internal function that does the actual ios call to the host driver,
 * optionally printing some debug output.
 */
368
369
370
371
static inline void mmc_set_ios(struct mmc_host *host)
{
	struct mmc_ios *ios = &host->ios;

372
373
	pr_debug("%s: clock %uHz busmode %u powermode %u cs %u Vdd %u "
		"width %u timing %u\n",
374
375
		 mmc_hostname(host), ios->clock, ios->bus_mode,
		 ios->power_mode, ios->chip_select, ios->vdd,
376
		 ios->bus_width, ios->timing);
377

378
379
380
	host->ops->set_ios(host, ios);
}

Pierre Ossman's avatar
Pierre Ossman committed
381
382
383
/*
 * Control chip select pin on a host.
 */
Pierre Ossman's avatar
Pierre Ossman committed
384
void mmc_set_chip_select(struct mmc_host *host, int mode)
Linus Torvalds's avatar
Linus Torvalds committed
385
{
Pierre Ossman's avatar
Pierre Ossman committed
386
387
	host->ios.chip_select = mode;
	mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
388
389
}

Pierre Ossman's avatar
Pierre Ossman committed
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
/*
 * 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
423
424
425
426
/*
 * Mask off any voltages we don't support and select
 * the lowest voltage
 */
Pierre Ossman's avatar
Pierre Ossman committed
427
u32 mmc_select_voltage(struct mmc_host *host, u32 ocr)
Linus Torvalds's avatar
Linus Torvalds committed
428
429
430
431
432
433
434
435
436
{
	int bit;

	ocr &= host->ocr_avail;

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

437
		ocr &= 3 << bit;
Linus Torvalds's avatar
Linus Torvalds committed
438
439

		host->ios.vdd = bit;
440
		mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
441
442
443
444
445
446
447
	} else {
		ocr = 0;
	}

	return ocr;
}

Pierre Ossman's avatar
Pierre Ossman committed
448
/*
Pierre Ossman's avatar
Pierre Ossman committed
449
 * Select timing parameters for host.
Pierre Ossman's avatar
Pierre Ossman committed
450
 */
Pierre Ossman's avatar
Pierre Ossman committed
451
void mmc_set_timing(struct mmc_host *host, unsigned int timing)
Pierre Ossman's avatar
Pierre Ossman committed
452
{
Pierre Ossman's avatar
Pierre Ossman committed
453
454
	host->ios.timing = timing;
	mmc_set_ios(host);
Pierre Ossman's avatar
Pierre Ossman committed
455
456
}

Linus Torvalds's avatar
Linus Torvalds committed
457
/*
458
459
460
461
462
463
464
465
466
 * 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
467
468
469
470
471
472
 */
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
473
474
475
476
477
478
479
	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
480
	host->ios.power_mode = MMC_POWER_UP;
Pierre Ossman's avatar
Pierre Ossman committed
481
	host->ios.bus_width = MMC_BUS_WIDTH_1;
482
	host->ios.timing = MMC_TIMING_LEGACY;
483
	mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
484

Pierre Ossman's avatar
Pierre Ossman committed
485
486
487
488
489
	/*
	 * 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
490
491
492

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

Pierre Ossman's avatar
Pierre Ossman committed
495
496
497
498
	/*
	 * 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
499
500
501
502
503
504
505
	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
506
507
508
509
	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
510
	host->ios.power_mode = MMC_POWER_OFF;
Pierre Ossman's avatar
Pierre Ossman committed
511
	host->ios.bus_width = MMC_BUS_WIDTH_1;
512
	host->ios.timing = MMC_TIMING_LEGACY;
513
	mmc_set_ios(host);
Linus Torvalds's avatar
Linus Torvalds committed
514
515
}

516
517
518
/*
 * Cleanup when the last reference to the bus operator is dropped.
 */
519
static void __mmc_release_bus(struct mmc_host *host)
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
{
	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
555
/*
Pierre Ossman's avatar
Pierre Ossman committed
556
557
 * 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
558
 */
Pierre Ossman's avatar
Pierre Ossman committed
559
void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops)
Linus Torvalds's avatar
Linus Torvalds committed
560
{
Pierre Ossman's avatar
Pierre Ossman committed
561
	unsigned long flags;
562

Pierre Ossman's avatar
Pierre Ossman committed
563
564
	BUG_ON(!host);
	BUG_ON(!ops);
565

566
	WARN_ON(!host->claimed);
567

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

Pierre Ossman's avatar
Pierre Ossman committed
570
571
	BUG_ON(host->bus_ops);
	BUG_ON(host->bus_refs);
Pierre Ossman's avatar
Pierre Ossman committed
572

Pierre Ossman's avatar
Pierre Ossman committed
573
574
575
	host->bus_ops = ops;
	host->bus_refs = 1;
	host->bus_dead = 0;
Pierre Ossman's avatar
Pierre Ossman committed
576

Pierre Ossman's avatar
Pierre Ossman committed
577
	spin_unlock_irqrestore(&host->lock, flags);
Pierre Ossman's avatar
Pierre Ossman committed
578
579
}

Pierre Ossman's avatar
Pierre Ossman committed
580
581
582
583
584
/*
 * 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)
585
{
Pierre Ossman's avatar
Pierre Ossman committed
586
	unsigned long flags;
587

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

590
591
	WARN_ON(!host->claimed);
	WARN_ON(!host->bus_ops);
592

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

Pierre Ossman's avatar
Pierre Ossman committed
595
	host->bus_dead = 1;
596

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

Pierre Ossman's avatar
Pierre Ossman committed
599
	mmc_power_off(host);
Linus Torvalds's avatar
Linus Torvalds committed
600

Pierre Ossman's avatar
Pierre Ossman committed
601
	mmc_bus_put(host);
Linus Torvalds's avatar
Linus Torvalds committed
602
603
604
605
606
}

/**
 *	mmc_detect_change - process change of state on a MMC socket
 *	@host: host which changed state.
607
 *	@delay: optional delay to wait before detection (jiffies)
Linus Torvalds's avatar
Linus Torvalds committed
608
 *
Pierre Ossman's avatar
Pierre Ossman committed
609
610
611
612
 *	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
613
 */
614
void mmc_detect_change(struct mmc_host *host, unsigned long delay)
Linus Torvalds's avatar
Linus Torvalds committed
615
{
616
#ifdef CONFIG_MMC_DEBUG
617
	unsigned long flags;
Andrew Morton's avatar
Andrew Morton committed
618
	spin_lock_irqsave(&host->lock, flags);
619
	WARN_ON(host->removed);
Andrew Morton's avatar
Andrew Morton committed
620
	spin_unlock_irqrestore(&host->lock, flags);
621
622
#endif

David Howells's avatar
David Howells committed
623
	mmc_schedule_delayed_work(&host->detect, delay);
Linus Torvalds's avatar
Linus Torvalds committed
624
625
626
627
628
}

EXPORT_SYMBOL(mmc_detect_change);


629
void mmc_rescan(struct work_struct *work)
Linus Torvalds's avatar
Linus Torvalds committed
630
{
David Howells's avatar
David Howells committed
631
632
	struct mmc_host *host =
		container_of(work, struct mmc_host, detect.work);
Pierre Ossman's avatar
Pierre Ossman committed
633
634
	u32 ocr;
	int err;
Linus Torvalds's avatar
Linus Torvalds committed
635

Pierre Ossman's avatar
Pierre Ossman committed
636
	mmc_bus_get(host);
637

Pierre Ossman's avatar
Pierre Ossman committed
638
	if (host->bus_ops == NULL) {
Linus Torvalds's avatar
Linus Torvalds committed
639
		/*
Pierre Ossman's avatar
Pierre Ossman committed
640
641
		 * Only we can add a new handler, so it's safe to
		 * release the lock here.
Linus Torvalds's avatar
Linus Torvalds committed
642
		 */
Pierre Ossman's avatar
Pierre Ossman committed
643
		mmc_bus_put(host);
Linus Torvalds's avatar
Linus Torvalds committed
644

Pierre Ossman's avatar
Pierre Ossman committed
645
		mmc_claim_host(host);
Linus Torvalds's avatar
Linus Torvalds committed
646

Pierre Ossman's avatar
Pierre Ossman committed
647
648
		mmc_power_up(host);
		mmc_go_idle(host);
Linus Torvalds's avatar
Linus Torvalds committed
649

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

Pierre Ossman's avatar
Pierre Ossman committed
652
653
654
655
656
657
658
659
660
661
662
663
664
		/*
		 * 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);
			return;
		}

		/*
		 * ...then normal SD...
		 */
Pierre Ossman's avatar
Pierre Ossman committed
665
		err = mmc_send_app_op_cond(host, 0, &ocr);
Pierre Ossman's avatar
Pierre Ossman committed
666
		if (!err) {
Pierre Ossman's avatar
Pierre Ossman committed
667
668
			if (mmc_attach_sd(host, ocr))
				mmc_power_off(host);
Pierre Ossman's avatar
Pierre Ossman committed
669
670
671
672
673
674
675
676
677
			return;
		}

		/*
		 * ...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
678
				mmc_power_off(host);
Pierre Ossman's avatar
Pierre Ossman committed
679
			return;
Pierre Ossman's avatar
Pierre Ossman committed
680
		}
Pierre Ossman's avatar
Pierre Ossman committed
681
682
683

		mmc_release_host(host);
		mmc_power_off(host);
Pierre Ossman's avatar
Pierre Ossman committed
684
685
686
687
688
689
	} else {
		if (host->bus_ops->detect && !host->bus_dead)
			host->bus_ops->detect(host);

		mmc_bus_put(host);
	}
Linus Torvalds's avatar
Linus Torvalds committed
690
691
}

692
void mmc_start_host(struct mmc_host *host)
Linus Torvalds's avatar
Linus Torvalds committed
693
{
694
695
	mmc_power_off(host);
	mmc_detect_change(host, 0);
Linus Torvalds's avatar
Linus Torvalds committed
696
697
}

698
void mmc_stop_host(struct mmc_host *host)
Linus Torvalds's avatar
Linus Torvalds committed
699
{
700
#ifdef CONFIG_MMC_DEBUG
701
702
	unsigned long flags;
	spin_lock_irqsave(&host->lock, flags);
703
	host->removed = 1;
704
	spin_unlock_irqrestore(&host->lock, flags);
705
706
707
708
#endif

	mmc_flush_scheduled_work();

Pierre Ossman's avatar
Pierre Ossman committed
709
710
711
712
713
714
715
716
	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
717
	}
Pierre Ossman's avatar
Pierre Ossman committed
718
719
720
	mmc_bus_put(host);

	BUG_ON(host->card);
Linus Torvalds's avatar
Linus Torvalds committed
721
722
723
724
725
726
727
728
729
730
731

	mmc_power_off(host);
}

#ifdef CONFIG_PM

/**
 *	mmc_suspend_host - suspend a host
 *	@host: mmc host
 *	@state: suspend mode (PM_SUSPEND_xxx)
 */
732
int mmc_suspend_host(struct mmc_host *host, pm_message_t state)
Linus Torvalds's avatar
Linus Torvalds committed
733
{
Pierre Ossman's avatar
Pierre Ossman committed
734
735
	mmc_flush_scheduled_work();

Pierre Ossman's avatar
Pierre Ossman committed
736
737
	mmc_bus_get(host);
	if (host->bus_ops && !host->bus_dead) {
738
739
740
741
742
743
744
745
746
747
		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
748
	}
Pierre Ossman's avatar
Pierre Ossman committed
749
750
	mmc_bus_put(host);

Linus Torvalds's avatar
Linus Torvalds committed
751
752
753
754
755
756
757
758
759
760
761
762
763
	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)
{
764
765
766
767
768
769
770
771
772
773
774
775
776
	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
777
778
779
780
781
782
783
784

	return 0;
}

EXPORT_SYMBOL(mmc_resume_host);

#endif

785
786
787
788
789
790
791
792
793
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
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
	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);

814
815
816
817
818
	return ret;
}

static void __exit mmc_exit(void)
{
Pierre Ossman's avatar
Pierre Ossman committed
819
	sdio_unregister_bus();
820
821
822
823
824
	mmc_unregister_host_class();
	mmc_unregister_bus();
	destroy_workqueue(workqueue);
}

825
subsys_initcall(mmc_init);
826
827
module_exit(mmc_exit);

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