diff options
author | Hans de Goede <hdegoede@redhat.com> | 2015-04-01 11:26:23 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2015-04-02 04:59:10 -0400 |
commit | 81f8a7be6642b4c26ab681b2e0f4c4120a6de1b0 (patch) | |
tree | 24868729a06b2b5fe678e7c9649c7e5a90cff9dc | |
parent | 2391b340ca5b7dd041a2bf86afe12bc004acb583 (diff) |
mmc: Add support for marking hpi as broken through devicetree
The eMMC on a tablet I've will stop working / communicating as soon as
the kernel executes:
mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HPI_MGMT, 1,
card->ext_csd.generic_cmd6_time);
There seems to be no way to reliable identify eMMC-s which have a broken
hpi implementation, but at least for eMMC's which are soldered onto a board
we can work around this by specifying that hpi is broken in devicetree.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/mmc/mmc-card.txt | 31 | ||||
-rw-r--r-- | drivers/mmc/core/mmc.c | 10 |
2 files changed, 40 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/mmc/mmc-card.txt b/Documentation/devicetree/bindings/mmc/mmc-card.txt new file mode 100644 index 000000000000..a70fcd65b9ea --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mmc-card.txt | |||
@@ -0,0 +1,31 @@ | |||
1 | mmc-card / eMMC bindings | ||
2 | ------------------------ | ||
3 | |||
4 | This documents describes the devicetree bindings for a mmc-host controller | ||
5 | child node describing a mmc-card / an eMMC, see "Use of Function subnodes" | ||
6 | in mmc.txt | ||
7 | |||
8 | Required properties: | ||
9 | -compatible : Must be "mmc-card" | ||
10 | -reg : Must be <0> | ||
11 | |||
12 | Optional properties: | ||
13 | -broken-hpi : Use this to indicate that the mmc-card has a broken hpi | ||
14 | implementation, and that hpi should not be used | ||
15 | |||
16 | Example: | ||
17 | |||
18 | &mmc2 { | ||
19 | pinctrl-names = "default"; | ||
20 | pinctrl-0 = <&mmc2_pins_a>; | ||
21 | vmmc-supply = <®_vcc3v3>; | ||
22 | bus-width = <8>; | ||
23 | non-removable; | ||
24 | status = "okay"; | ||
25 | |||
26 | mmccard: mmccard@0 { | ||
27 | reg = <0>; | ||
28 | compatible = "mmc-card"; | ||
29 | broken-hpi; | ||
30 | }; | ||
31 | }; | ||
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 1d41e8541f38..c84131e28625 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/of.h> | ||
14 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
15 | #include <linux/stat.h> | 16 | #include <linux/stat.h> |
16 | #include <linux/pm_runtime.h> | 17 | #include <linux/pm_runtime.h> |
@@ -336,6 +337,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
336 | { | 337 | { |
337 | int err = 0, idx; | 338 | int err = 0, idx; |
338 | unsigned int part_size; | 339 | unsigned int part_size; |
340 | struct device_node *np; | ||
341 | bool broken_hpi = false; | ||
339 | 342 | ||
340 | /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ | 343 | /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ |
341 | card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; | 344 | card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; |
@@ -349,6 +352,11 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
349 | } | 352 | } |
350 | } | 353 | } |
351 | 354 | ||
355 | np = mmc_of_find_child_device(card->host, 0); | ||
356 | if (np && of_device_is_compatible(np, "mmc-card")) | ||
357 | broken_hpi = of_property_read_bool(np, "broken-hpi"); | ||
358 | of_node_put(np); | ||
359 | |||
352 | /* | 360 | /* |
353 | * The EXT_CSD format is meant to be forward compatible. As long | 361 | * The EXT_CSD format is meant to be forward compatible. As long |
354 | * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV | 362 | * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV |
@@ -494,7 +502,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) | |||
494 | } | 502 | } |
495 | 503 | ||
496 | /* check whether the eMMC card supports HPI */ | 504 | /* check whether the eMMC card supports HPI */ |
497 | if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) { | 505 | if (!broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) { |
498 | card->ext_csd.hpi = 1; | 506 | card->ext_csd.hpi = 1; |
499 | if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) | 507 | if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) |
500 | card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; | 508 | card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; |