aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2015-04-01 11:26:23 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2015-04-02 04:59:10 -0400
commit81f8a7be6642b4c26ab681b2e0f4c4120a6de1b0 (patch)
tree24868729a06b2b5fe678e7c9649c7e5a90cff9dc
parent2391b340ca5b7dd041a2bf86afe12bc004acb583 (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.txt31
-rw-r--r--drivers/mmc/core/mmc.c10
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 @@
1mmc-card / eMMC bindings
2------------------------
3
4This documents describes the devicetree bindings for a mmc-host controller
5child node describing a mmc-card / an eMMC, see "Use of Function subnodes"
6in mmc.txt
7
8Required properties:
9-compatible : Must be "mmc-card"
10-reg : Must be <0>
11
12Optional 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
16Example:
17
18&mmc2 {
19 pinctrl-names = "default";
20 pinctrl-0 = <&mmc2_pins_a>;
21 vmmc-supply = <&reg_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;