diff options
author | Kevin Liu <kliu5@marvell.com> | 2013-02-28 15:29:29 +0800 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2013-03-22 12:23:34 -0400 |
commit | 1450734ec61cda7bbb77afc8cb412b9d64c62d9a (patch) | |
tree | 0019832660b15a182491655abe66d8082b29be27 /drivers/mmc | |
parent | 51e7e8b632d8e564ba494dfa61358ac1a97e4ceb (diff) | |
download | linux-1450734ec61cda7bbb77afc8cb412b9d64c62d9a.tar.bz2 |
mmc: core: enhance card removal judgement for slow removal
Function _mmc_detect_card_removed will be called to know whether
the card is still present when host->bus_ops->detect is called.
In current code, the return value of this function generally only
depend on the result of sending cmd13 to card, which may not safe
for card with detection support like slot gpio detection.
Because the communication status between host and card may out of
sync with the detect status if remove the card slowly or hands shake
during the process. The direct reason is the async between card
detect switch and card/slot pad contaction in hardware, which is
defined by spec.
The spec define card insert/remove sequence as below (both standard size
SD card and MicroSD card have the same sequence):
"Part 1 Standard Size SD Card Mechanical Addendum Ver4.00 Final,
Appendix C: Card Detection Switch" (Take normally open type as example)
a)SD card insertion sequence:
The card detection switch should be turned on after all SD card
contact pads are connected to the host connector contact pads.
b)SD removal sequence:
The card detection switch should be turned off when the SD card
is just going to be removed and before any SD card contact pad is
disconnected from the host connector contact pad.
Below is the sequence when this issue occur (Take slot gpio detection
as example and remove the card slowly during the process):
1. gpio level changed and card detect interrupt triggered.
2. mmc_rescan was launched.
3. the card pads were still contacted with the slot pads because of slow
removal. So _mmc_detect_card_removed and mmc_rescan think card was
still present (cmd13 succeed).
4. card pads were discontacted from the card slot pads.
So the card was actually removed finally but the card removal event
has been missed by system.
The interval length between step 1 and step 4 depends on the
card removal speed. If it's longer than the detect work schedule
delay which is 200ms, this issue will likely happen.
This patch add the card detect status check in function
_mmc_detect_card_removed if cmd13 check succeed and host->ops->get_cd
provided. If get_cd detect no card present then schedule another detect
work 200ms later.
Signed-off-by: Kevin Liu <kliu5@marvell.com>
Tested-by: Johan Rudholm <johan.rudholm@stericsson.com>
Reviewed-by: Philip Rakity <prakity@nvidia.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/core.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 08a3cf2a7610..3bf1c462eded 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -2289,6 +2289,19 @@ int _mmc_detect_card_removed(struct mmc_host *host) return 1; ret = host->bus_ops->alive(host); + + /* + * Card detect status and alive check may be out of sync if card is + * removed slowly, when card detect switch changes while card/slot + * pads are still contacted in hardware (refer to "SD Card Mechanical + * Addendum, Appendix C: Card Detection Switch"). So reschedule a + * detect work 200ms later for this case. + */ + if (!ret && host->ops->get_cd && !host->ops->get_cd(host)) { + mmc_detect_change(host, msecs_to_jiffies(200)); + pr_debug("%s: card removed too slowly\n", mmc_hostname(host)); + } + if (ret) { mmc_card_set_removed(host->card); pr_debug("%s: card remove detected\n", mmc_hostname(host)); |