Commit 81f8a7be authored by Hans de Goede's avatar Hans de Goede Committed by Ulf Hansson

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: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 2391b340
mmc-card / eMMC bindings
------------------------
This documents describes the devicetree bindings for a mmc-host controller
child node describing a mmc-card / an eMMC, see "Use of Function subnodes"
in mmc.txt
Required properties:
-compatible : Must be "mmc-card"
-reg : Must be <0>
Optional properties:
-broken-hpi : Use this to indicate that the mmc-card has a broken hpi
implementation, and that hpi should not be used
Example:
&mmc2 {
pinctrl-names = "default";
pinctrl-0 = <&mmc2_pins_a>;
vmmc-supply = <&reg_vcc3v3>;
bus-width = <8>;
non-removable;
status = "okay";
mmccard: mmccard@0 {
reg = <0>;
compatible = "mmc-card";
broken-hpi;
};
};
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
*/ */
#include <linux/err.h> #include <linux/err.h>
#include <linux/of.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
...@@ -336,6 +337,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd) ...@@ -336,6 +337,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
{ {
int err = 0, idx; int err = 0, idx;
unsigned int part_size; unsigned int part_size;
struct device_node *np;
bool broken_hpi = false;
/* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */
card->ext_csd.raw_ext_csd_structure = ext_csd[EXT_CSD_STRUCTURE]; 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,6 +352,11 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
} }
} }
np = mmc_of_find_child_device(card->host, 0);
if (np && of_device_is_compatible(np, "mmc-card"))
broken_hpi = of_property_read_bool(np, "broken-hpi");
of_node_put(np);
/* /*
* The EXT_CSD format is meant to be forward compatible. As long * The EXT_CSD format is meant to be forward compatible. As long
* as CSD_STRUCTURE does not change, all values for EXT_CSD_REV * 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,7 +502,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
} }
/* check whether the eMMC card supports HPI */ /* check whether the eMMC card supports HPI */
if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1) { if (!broken_hpi && (ext_csd[EXT_CSD_HPI_FEATURES] & 0x1)) {
card->ext_csd.hpi = 1; card->ext_csd.hpi = 1;
if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2) if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION; card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment