blob: 47d1708810bd43412bf2b6263466b1c0d69b6615 [file] [log] [blame]
Pierre Ossman5c4e6f12007-05-21 20:23:20 +02001/*
2 * linux/drivers/mmc/sdio.c
3 *
4 * Copyright 2006-2007 Pierre Ossman
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 as published by
8 * the Free Software Foundation; either version 2 of the License, or (at
9 * your option) any later version.
10 */
11
12#include <linux/err.h>
13
14#include <linux/mmc/host.h>
15#include <linux/mmc/card.h>
Pierre Ossman35c66c12007-06-11 20:25:43 +020016#include <linux/mmc/sdio.h>
Pierre Ossmane29a7d72007-05-26 13:48:18 +020017#include <linux/mmc/sdio_func.h>
Pierre Ossman5c4e6f12007-05-21 20:23:20 +020018
19#include "core.h"
20#include "bus.h"
Michal Miroslaw71578a12010-08-10 18:01:40 -070021#include "sd.h"
Pierre Ossmane29a7d72007-05-26 13:48:18 +020022#include "sdio_bus.h"
Pierre Ossman5c4e6f12007-05-21 20:23:20 +020023#include "mmc_ops.h"
24#include "sd_ops.h"
25#include "sdio_ops.h"
Nicolas Pitreb7261262007-06-16 02:04:16 -040026#include "sdio_cis.h"
Pierre Ossman5c4e6f12007-05-21 20:23:20 +020027
Pierre Ossman05970072007-06-11 21:01:00 +020028static int sdio_read_fbr(struct sdio_func *func)
29{
30 int ret;
31 unsigned char data;
32
33 ret = mmc_io_rw_direct(func->card, 0, 0,
David Vrabel7616ee92007-08-08 14:23:05 +010034 SDIO_FBR_BASE(func->num) + SDIO_FBR_STD_IF, 0, &data);
Pierre Ossman05970072007-06-11 21:01:00 +020035 if (ret)
36 goto out;
37
38 data &= 0x0f;
39
40 if (data == 0x0f) {
41 ret = mmc_io_rw_direct(func->card, 0, 0,
David Vrabel7616ee92007-08-08 14:23:05 +010042 SDIO_FBR_BASE(func->num) + SDIO_FBR_STD_IF_EXT, 0, &data);
Pierre Ossman05970072007-06-11 21:01:00 +020043 if (ret)
44 goto out;
45 }
46
47 func->class = data;
48
49out:
50 return ret;
51}
52
Pierre Ossmane29a7d72007-05-26 13:48:18 +020053static int sdio_init_func(struct mmc_card *card, unsigned int fn)
54{
Pierre Ossman05970072007-06-11 21:01:00 +020055 int ret;
Pierre Ossmane29a7d72007-05-26 13:48:18 +020056 struct sdio_func *func;
57
58 BUG_ON(fn > SDIO_MAX_FUNCS);
59
60 func = sdio_alloc_func(card);
61 if (IS_ERR(func))
62 return PTR_ERR(func);
63
64 func->num = fn;
65
Pierre Ossman05970072007-06-11 21:01:00 +020066 ret = sdio_read_fbr(func);
67 if (ret)
68 goto fail;
69
Pierre Ossman1a632f82007-07-30 15:15:30 +020070 ret = sdio_read_func_cis(func);
Nicolas Pitreb7261262007-06-16 02:04:16 -040071 if (ret)
72 goto fail;
73
Pierre Ossmane29a7d72007-05-26 13:48:18 +020074 card->sdio_func[fn - 1] = func;
75
76 return 0;
Pierre Ossman05970072007-06-11 21:01:00 +020077
78fail:
79 /*
80 * It is okay to remove the function here even though we hold
81 * the host lock as we haven't registered the device yet.
82 */
83 sdio_remove_func(func);
84 return ret;
Pierre Ossmane29a7d72007-05-26 13:48:18 +020085}
86
Pierre Ossman35c66c12007-06-11 20:25:43 +020087static int sdio_read_cccr(struct mmc_card *card)
88{
89 int ret;
90 int cccr_vsn;
91 unsigned char data;
92
93 memset(&card->cccr, 0, sizeof(struct sdio_cccr));
94
95 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CCCR, 0, &data);
96 if (ret)
97 goto out;
98
99 cccr_vsn = data & 0x0f;
100
101 if (cccr_vsn > SDIO_CCCR_REV_1_20) {
102 printk(KERN_ERR "%s: unrecognised CCCR structure version %d\n",
103 mmc_hostname(card->host), cccr_vsn);
104 return -EINVAL;
105 }
106
107 card->cccr.sdio_vsn = (data & 0xf0) >> 4;
108
109 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_CAPS, 0, &data);
110 if (ret)
111 goto out;
112
113 if (data & SDIO_CCCR_CAP_SMB)
114 card->cccr.multi_block = 1;
115 if (data & SDIO_CCCR_CAP_LSC)
116 card->cccr.low_speed = 1;
117 if (data & SDIO_CCCR_CAP_4BLS)
118 card->cccr.wide_bus = 1;
119
120 if (cccr_vsn >= SDIO_CCCR_REV_1_10) {
121 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_POWER, 0, &data);
122 if (ret)
123 goto out;
124
125 if (data & SDIO_POWER_SMPC)
126 card->cccr.high_power = 1;
127 }
128
129 if (cccr_vsn >= SDIO_CCCR_REV_1_20) {
130 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &data);
131 if (ret)
132 goto out;
133
134 if (data & SDIO_SPEED_SHS)
135 card->cccr.high_speed = 1;
136 }
137
138out:
139 return ret;
140}
141
Pierre Ossman4ff64712007-07-30 18:23:53 +0200142static int sdio_enable_wide(struct mmc_card *card)
143{
144 int ret;
145 u8 ctrl;
146
147 if (!(card->host->caps & MMC_CAP_4_BIT_DATA))
148 return 0;
149
150 if (card->cccr.low_speed && !card->cccr.wide_bus)
151 return 0;
152
153 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
154 if (ret)
155 return ret;
156
157 ctrl |= SDIO_BUS_WIDTH_4BIT;
158
159 ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
160 if (ret)
161 return ret;
162
163 mmc_set_bus_width(card->host, MMC_BUS_WIDTH_4);
164
165 return 0;
166}
167
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200168/*
Ohad Ben-Cohen006ebd52009-09-22 16:45:07 -0700169 * If desired, disconnect the pull-up resistor on CD/DAT[3] (pin 1)
170 * of the card. This may be required on certain setups of boards,
171 * controllers and embedded sdio device which do not need the card's
172 * pull-up. As a result, card detection is disabled and power is saved.
173 */
174static int sdio_disable_cd(struct mmc_card *card)
175{
176 int ret;
177 u8 ctrl;
178
179 if (!card->cccr.disable_cd)
180 return 0;
181
182 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
183 if (ret)
184 return ret;
185
186 ctrl |= SDIO_BUS_CD_DISABLE;
187
188 return mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
189}
190
191/*
Daniel Drake6b5eda32010-03-05 13:43:34 -0800192 * Devices that remain active during a system suspend are
193 * put back into 1-bit mode.
194 */
195static int sdio_disable_wide(struct mmc_card *card)
196{
197 int ret;
198 u8 ctrl;
199
200 if (!(card->host->caps & MMC_CAP_4_BIT_DATA))
201 return 0;
202
203 if (card->cccr.low_speed && !card->cccr.wide_bus)
204 return 0;
205
206 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl);
207 if (ret)
208 return ret;
209
210 if (!(ctrl & SDIO_BUS_WIDTH_4BIT))
211 return 0;
212
213 ctrl &= ~SDIO_BUS_WIDTH_4BIT;
214 ctrl |= SDIO_BUS_ASYNC_INT;
215
216 ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL);
217 if (ret)
218 return ret;
219
220 mmc_set_bus_width(card->host, MMC_BUS_WIDTH_1);
221
222 return 0;
223}
224
225/*
Pierre Ossmand16f5772008-08-31 17:22:46 +0200226 * Test if the card supports high-speed mode and, if so, switch to it.
227 */
228static int sdio_enable_hs(struct mmc_card *card)
229{
230 int ret;
231 u8 speed;
232
233 if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
234 return 0;
235
236 if (!card->cccr.high_speed)
237 return 0;
238
239 ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed);
240 if (ret)
241 return ret;
242
243 speed |= SDIO_SPEED_EHS;
244
245 ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL);
246 if (ret)
247 return ret;
248
Michal Miroslaw71578a12010-08-10 18:01:40 -0700249 return 1;
250}
Pierre Ossmand16f5772008-08-31 17:22:46 +0200251
Michal Miroslaw71578a12010-08-10 18:01:40 -0700252static unsigned mmc_sdio_get_max_clock(struct mmc_card *card)
253{
254 unsigned max_dtr;
255
256 if (mmc_card_highspeed(card)) {
257 /*
258 * The SDIO specification doesn't mention how
259 * the CIS transfer speed register relates to
260 * high-speed, but it seems that 50 MHz is
261 * mandatory.
262 */
263 max_dtr = 50000000;
264 } else {
265 max_dtr = card->cis.max_dtr;
266 }
267
268 return max_dtr;
Pierre Ossmand16f5772008-08-31 17:22:46 +0200269}
270
271/*
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700272 * Handle the detection and initialisation of a card.
273 *
274 * In the case of a resume, "oldcard" will contain the card
275 * we're trying to reinitialise.
276 */
277static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
Chris Ball3bca4cf72010-03-05 13:43:33 -0800278 struct mmc_card *oldcard, int powered_resume)
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700279{
280 struct mmc_card *card;
281 int err;
282
283 BUG_ON(!host);
284 WARN_ON(!host->claimed);
285
286 /*
287 * Inform the card of the voltage
288 */
Chris Ball3bca4cf72010-03-05 13:43:33 -0800289 if (!powered_resume) {
290 err = mmc_send_io_op_cond(host, host->ocr, &ocr);
291 if (err)
292 goto err;
293 }
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700294
295 /*
296 * For SPI, enable CRC as appropriate.
297 */
298 if (mmc_host_is_spi(host)) {
299 err = mmc_spi_set_crc(host, use_spi_crc);
300 if (err)
301 goto err;
302 }
303
304 /*
305 * Allocate card structure.
306 */
307 card = mmc_alloc_card(host, NULL);
308 if (IS_ERR(card)) {
309 err = PTR_ERR(card);
310 goto err;
311 }
312
313 card->type = MMC_TYPE_SDIO;
314
315 /*
Daniel Mack3fcb0272010-04-01 10:03:25 +0200316 * Call the optional HC's init_card function to handle quirks.
317 */
318 if (host->ops->init_card)
319 host->ops->init_card(host, card);
320
321 /*
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700322 * For native busses: set card RCA and quit open drain mode.
323 */
Chris Ball3bca4cf72010-03-05 13:43:33 -0800324 if (!powered_resume && !mmc_host_is_spi(host)) {
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700325 err = mmc_send_relative_addr(host, &card->rca);
326 if (err)
327 goto remove;
328
329 mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
330 }
331
332 /*
333 * Select card, as all following commands rely on that.
334 */
Chris Ball3bca4cf72010-03-05 13:43:33 -0800335 if (!powered_resume && !mmc_host_is_spi(host)) {
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700336 err = mmc_select_card(card);
337 if (err)
338 goto remove;
339 }
340
341 /*
342 * Read the common registers.
343 */
344 err = sdio_read_cccr(card);
345 if (err)
346 goto remove;
347
348 /*
349 * Read the common CIS tuples.
350 */
351 err = sdio_read_common_cis(card);
352 if (err)
353 goto remove;
354
355 if (oldcard) {
356 int same = (card->cis.vendor == oldcard->cis.vendor &&
357 card->cis.device == oldcard->cis.device);
358 mmc_remove_card(card);
359 if (!same) {
360 err = -ENOENT;
361 goto err;
362 }
363 card = oldcard;
Nicolas Pitre95cdfb72009-09-22 16:45:29 -0700364 return 0;
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700365 }
366
367 /*
368 * Switch to high-speed (if supported).
369 */
370 err = sdio_enable_hs(card);
Michal Miroslaw71578a12010-08-10 18:01:40 -0700371 if (err > 0)
372 mmc_sd_go_highspeed(card);
373 else if (err)
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700374 goto remove;
375
376 /*
377 * Change to the card's maximum speed.
378 */
Michal Miroslaw71578a12010-08-10 18:01:40 -0700379 mmc_set_clock(host, mmc_sdio_get_max_clock(card));
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700380
381 /*
382 * Switch to wider bus (if supported).
383 */
384 err = sdio_enable_wide(card);
385 if (err)
386 goto remove;
387
388 if (!oldcard)
389 host->card = card;
390 return 0;
391
392remove:
393 if (!oldcard)
394 mmc_remove_card(card);
395
396err:
397 return err;
398}
399
400/*
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200401 * Host is being removed. Free up the current card.
402 */
403static void mmc_sdio_remove(struct mmc_host *host)
404{
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200405 int i;
406
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200407 BUG_ON(!host);
408 BUG_ON(!host->card);
409
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200410 for (i = 0;i < host->card->sdio_funcs;i++) {
411 if (host->card->sdio_func[i]) {
412 sdio_remove_func(host->card->sdio_func[i]);
413 host->card->sdio_func[i] = NULL;
414 }
415 }
416
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200417 mmc_remove_card(host->card);
418 host->card = NULL;
419}
420
421/*
422 * Card detection callback from host.
423 */
424static void mmc_sdio_detect(struct mmc_host *host)
425{
426 int err;
427
428 BUG_ON(!host);
429 BUG_ON(!host->card);
430
431 mmc_claim_host(host);
432
433 /*
434 * Just check if our card has been removed.
435 */
436 err = mmc_select_card(host->card);
437
438 mmc_release_host(host);
439
440 if (err) {
441 mmc_sdio_remove(host);
442
443 mmc_claim_host(host);
444 mmc_detach_bus(host);
445 mmc_release_host(host);
446 }
447}
448
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700449/*
450 * SDIO suspend. We need to suspend all functions separately.
451 * Therefore all registered functions must have drivers with suspend
452 * and resume methods. Failing that we simply remove the whole card.
453 */
Nicolas Pitre95cdfb72009-09-22 16:45:29 -0700454static int mmc_sdio_suspend(struct mmc_host *host)
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700455{
Nicolas Pitre95cdfb72009-09-22 16:45:29 -0700456 int i, err = 0;
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700457
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700458 for (i = 0; i < host->card->sdio_funcs; i++) {
459 struct sdio_func *func = host->card->sdio_func[i];
460 if (func && sdio_func_present(func) && func->dev.driver) {
461 const struct dev_pm_ops *pmops = func->dev.driver->pm;
462 if (!pmops || !pmops->suspend || !pmops->resume) {
Nicolas Pitre95cdfb72009-09-22 16:45:29 -0700463 /* force removal of entire card in that case */
464 err = -ENOSYS;
465 } else
466 err = pmops->suspend(&func->dev);
467 if (err)
468 break;
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700469 }
470 }
Nicolas Pitre95cdfb72009-09-22 16:45:29 -0700471 while (err && --i >= 0) {
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700472 struct sdio_func *func = host->card->sdio_func[i];
473 if (func && sdio_func_present(func) && func->dev.driver) {
474 const struct dev_pm_ops *pmops = func->dev.driver->pm;
475 pmops->resume(&func->dev);
476 }
477 }
Nicolas Pitre95cdfb72009-09-22 16:45:29 -0700478
Daniel Drake6b5eda32010-03-05 13:43:34 -0800479 if (!err && host->pm_flags & MMC_PM_KEEP_POWER) {
480 mmc_claim_host(host);
481 sdio_disable_wide(host->card);
482 mmc_release_host(host);
483 }
484
Nicolas Pitre95cdfb72009-09-22 16:45:29 -0700485 return err;
486}
487
488static int mmc_sdio_resume(struct mmc_host *host)
489{
490 int i, err;
491
492 BUG_ON(!host);
493 BUG_ON(!host->card);
494
495 /* Basic card reinitialization. */
496 mmc_claim_host(host);
Chris Ball3bca4cf72010-03-05 13:43:33 -0800497 err = mmc_sdio_init_card(host, host->ocr, host->card,
498 (host->pm_flags & MMC_PM_KEEP_POWER));
Daniel Drake6b5eda32010-03-05 13:43:34 -0800499 if (!err)
500 /* We may have switched to 1-bit mode during suspend. */
501 err = sdio_enable_wide(host->card);
Nicolas Pitre40216842010-03-05 13:43:34 -0800502 if (!err && host->sdio_irqs)
503 mmc_signal_sdio_irq(host);
Nicolas Pitre95cdfb72009-09-22 16:45:29 -0700504 mmc_release_host(host);
505
506 /*
507 * If the card looked to be the same as before suspending, then
508 * we proceed to resume all card functions. If one of them returns
509 * an error then we simply return that error to the core and the
510 * card will be redetected as new. It is the responsibility of
511 * the function driver to perform further tests with the extra
512 * knowledge it has of the card to confirm the card is indeed the
513 * same as before suspending (same MAC address for network cards,
514 * etc.) and return an error otherwise.
515 */
516 for (i = 0; !err && i < host->card->sdio_funcs; i++) {
517 struct sdio_func *func = host->card->sdio_func[i];
518 if (func && sdio_func_present(func) && func->dev.driver) {
519 const struct dev_pm_ops *pmops = func->dev.driver->pm;
520 err = pmops->resume(&func->dev);
521 }
522 }
523
524 return err;
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700525}
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200526
527static const struct mmc_bus_ops mmc_sdio_ops = {
528 .remove = mmc_sdio_remove,
529 .detect = mmc_sdio_detect,
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700530 .suspend = mmc_sdio_suspend,
531 .resume = mmc_sdio_resume,
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200532};
533
534
535/*
536 * Starting point for SDIO card init.
537 */
538int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
539{
540 int err;
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200541 int i, funcs;
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200542 struct mmc_card *card;
543
544 BUG_ON(!host);
Pierre Ossmand84075c82007-08-09 13:23:56 +0200545 WARN_ON(!host->claimed);
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200546
547 mmc_attach_bus(host, &mmc_sdio_ops);
548
549 /*
550 * Sanity check the voltages that the card claims to
551 * support.
552 */
553 if (ocr & 0x7F) {
554 printk(KERN_WARNING "%s: card claims to support voltages "
555 "below the defined range. These will be ignored.\n",
556 mmc_hostname(host));
557 ocr &= ~0x7F;
558 }
559
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200560 host->ocr = mmc_select_voltage(host, ocr);
561
562 /*
563 * Can we support the voltage(s) of the card(s)?
564 */
565 if (!host->ocr) {
566 err = -EINVAL;
567 goto err;
568 }
569
570 /*
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700571 * Detect and init the card.
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200572 */
Chris Ball3bca4cf72010-03-05 13:43:33 -0800573 err = mmc_sdio_init_card(host, host->ocr, NULL, 0);
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200574 if (err)
575 goto err;
Nicolas Pitre17d33e12009-09-22 16:45:28 -0700576 card = host->card;
David Brownellaf517152007-08-08 09:11:32 -0700577
578 /*
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200579 * The number of functions on the card is encoded inside
580 * the ocr.
581 */
Matt Fleminge8812792009-12-17 15:27:18 -0800582 funcs = (ocr & 0x70000000) >> 28;
583 card->sdio_funcs = 0;
Pierre Ossman4ff64712007-07-30 18:23:53 +0200584
585 /*
Ohad Ben-Cohen006ebd52009-09-22 16:45:07 -0700586 * If needed, disconnect card detection pull-up resistor.
587 */
588 err = sdio_disable_cd(card);
589 if (err)
590 goto remove;
591
592 /*
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200593 * Initialize (but don't add) all present functions.
594 */
Matt Fleminge8812792009-12-17 15:27:18 -0800595 for (i = 0; i < funcs; i++, card->sdio_funcs++) {
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200596 err = sdio_init_func(host->card, i + 1);
597 if (err)
598 goto remove;
599 }
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200600
601 mmc_release_host(host);
602
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200603 /*
604 * First add the card to the driver model...
605 */
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200606 err = mmc_add_card(host->card);
607 if (err)
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200608 goto remove_added;
609
610 /*
611 * ...then the SDIO functions.
612 */
613 for (i = 0;i < funcs;i++) {
614 err = sdio_add_func(host->card->sdio_func[i]);
615 if (err)
616 goto remove_added;
617 }
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200618
619 return 0;
620
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200621
622remove_added:
623 /* Remove without lock if the device has been added. */
624 mmc_sdio_remove(host);
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200625 mmc_claim_host(host);
Pierre Ossmane29a7d72007-05-26 13:48:18 +0200626remove:
627 /* And with lock if it hasn't been added. */
628 if (host->card)
629 mmc_sdio_remove(host);
Pierre Ossman5c4e6f12007-05-21 20:23:20 +0200630err:
631 mmc_detach_bus(host);
632 mmc_release_host(host);
633
634 printk(KERN_ERR "%s: error %d whilst initialising SDIO card\n",
635 mmc_hostname(host), err);
636
637 return err;
638}
639