Skip to contentSkip to conversation

mmc: Add support for marking hpi as broken through devicetree

PATCH Superseded Hans de Goede 3 participants 5 messages Mar 29, 2015 – Mar 31, 2015

Subsystems (3)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/2 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.

---
 Documentation/devicetree/bindings/mmc/mmc-card.txt | 31 ++++++++++++++++++++++
 drivers/mmc/core/mmc.c                             | 10 ++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/mmc-card.txt
Documentation/devicetree/bindings/mmc/mmc-card.txt new file +31 -0
new file mode 100644
index 0000000..0cc67fb
@@ -0,0 +1,31 @@
+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";
+
+	mmmcard: mmccard at 0 {
+		reg = <0>;
+		compatible = "mmc-card";
+		broken-hpi;
+	};
+};
drivers/mmc/core/mmc.c +9 -1
index 1d41e85..8d18920 100644
@@ -11,6 +11,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/pm_runtime.h>
@@ -336,6 +337,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 {
 	int err = 0, idx;
 	unsigned int part_size;
+	struct device_node *np = card->dev.of_node;
+	bool broken_hpi = false;
 
 	/* 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];
@@ -349,6 +352,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 		}
 	}
 
+	if (np && of_device_is_compatible(np, "mmc-card"))
+		broken_hpi = of_property_read_bool(np, "broken-hpi");
+
 	/*
 	 * The EXT_CSD format is meant to be forward compatible. As long
 	 * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV
@@ -494,7 +500,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 		}
 
 		/* 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;
 			if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
 				card->ext_csd.hpi_cmd =	MMC_STOP_TRANSMISSION;
@@ -1251,6 +1257,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
 		card->ocr = ocr;
 		card->type = MMC_TYPE_MMC;
 		card->rca = 1;
+		/* Also gets done by mmc_add_card, but we need early access */
+		card->dev.of_node = mmc_of_find_child_device(host, 0);
 		memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
 	}
 
Signature · 1 line
2.3.4
#1 lore raw

PATCH 2/2 ARM: dts: sun5i: Add broken-hpi property for Utoo-P66 eMMC

The eMMC on the A13 based Utoo-P66 tablet does not properly support hpi, and trying to enable it results in the eMMC not working, so add a child-node describing the eMMC, and set the broken-hpi property on it.

---
 arch/arm/boot/dts/sun5i-a13-utoo-p66.dts | 6 ++++++
 1 file changed, 6 insertions(+)
arch/arm/boot/dts/sun5i-a13-utoo-p66.dts +6 -0
index 6c9f5f3..5b572fa 100644
@@ -150,6 +150,12 @@
 	bus-width = <8>;
 	non-removable;
 	status = "okay";
+
+	mmmcard: mmccard at 0 {
+		reg = <0>;
+		compatible = "mmc-card";
+		broken-hpi;
+	};
 };
 
 &pio {
Signature · 1 line
2.3.4
#2 lore raw

PATCH 2/2 ARM: dts: sun5i: Add broken-hpi property for Utoo-P66 eMMC

Hello.

Quoted 14 lines · Hans de Goede

The eMMC on the A13 based Utoo-P66 tablet does not properly support hpi, and trying to enable it results in the eMMC not working, so add a child-node describing the eMMC, and set the broken-hpi property on it.

---
  arch/arm/boot/dts/sun5i-a13-utoo-p66.dts | 6 ++++++
  1 file changed, 6 insertions(+)
arch/arm/boot/dts/sun5i-a13-utoo-p66.dts +0 -0
index 6c9f5f3..5b572fa 100644

arch/arm/boot/dts/sun5i-a13-utoo-p66.dts line 154

Quoted 5 lines
arch/arm/boot/dts/sun5i-a13-utoo-p66.dts +2 -0
@@ -150,6 +150,12 @@
  	bus-width = <8>;
  	non-removable;
  	status = "okay";
+
+	mmmcard: mmccard at 0 {
    Not "mmcard:"? :-)

[...]

WBR, Sergei

#3 lore raw

PATCH 1/2 mmc: Add support for marking hpi as broken through devicetree

In reply to Hans de Goede
Quoted 10 lines · Hans de Goede

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.

Seems like a reasonable approach!

Quoted 14 lines
---
 Documentation/devicetree/bindings/mmc/mmc-card.txt | 31 ++++++++++++++++++++++
 drivers/mmc/core/mmc.c                             | 10 ++++++-
 2 files changed, 40 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/mmc-card.txt
Documentation/devicetree/bindings/mmc/mmc-card.txt new file +0 -0
new file mode 100644
index 0000000..0cc67fb

Documentation/devicetree/bindings/mmc/mmc-card.txt line 10

Quoted 10 lines
Documentation/devicetree/bindings/mmc/mmc-card.txt new file +10 -0
@@ -0,0 +1,31 @@
+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>

Instead of using a compatible, why can we just use "reg = <0>"?

Quoted 71 lines
Documentation/devicetree/bindings/mmc/mmc-card.txt new file +21 -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";
+
+       mmmcard: mmccard at 0 {
+               reg = <0>;
+               compatible = "mmc-card";
+               broken-hpi;
+       };
+};
drivers/mmc/core/mmc.c +9 -2
index 1d41e85..8d18920 100644
@@ -11,6 +11,7 @@
  */
 
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/pm_runtime.h>
@@ -336,6 +337,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
 {
        int err = 0, idx;
        unsigned int part_size;
+       struct device_node *np = card->dev.of_node;
+       bool broken_hpi = false;
 
        /* 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];
@@ -349,6 +352,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
                }
        }
 
+       if (np && of_device_is_compatible(np, "mmc-card"))
+               broken_hpi = of_property_read_bool(np, "broken-hpi");
+
        /*
         * The EXT_CSD format is meant to be forward compatible. As long
         * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV
@@ -494,7 +500,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
                }
 
                /* 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;
                        if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
                                card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
@@ -1251,6 +1257,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                card->ocr = ocr;
                card->type = MMC_TYPE_MMC;
                card->rca = 1;
+               /* Also gets done by mmc_add_card, but we need early access */
+               card->dev.of_node = mmc_of_find_child_device(host, 0);
                memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
        }
 
--
Quoted 2 lines

2.3.4

Kind regards
Uffe

#4 lore raw

PATCH 1/2 mmc: Add support for marking hpi as broken through devicetree

Hi,

Quoted 32 lines · Ulf Hansson
Quoted 10 lines · Hans de Goede

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.

Seems like a reasonable approach!

Quoted 18 lines
---
  Documentation/devicetree/bindings/mmc/mmc-card.txt | 31 ++++++++++++++++++++++
  drivers/mmc/core/mmc.c                             | 10 ++++++-
  2 files changed, 40 insertions(+), 1 deletion(-)

create mode 100644 Documentation/devicetree/bindings/mmc/mmc-card.txt

Documentation/devicetree/bindings/mmc/mmc-card.txt new file +4 -0
new file mode 100644
index 0000000..0cc67fb
@@ -0,0 +1,31 @@
+mmc-card / eMMC bindings
+------------------------
+
+This documents describes the devicetree bindings for a mmc-host controller
Quoted 8 lines

Documentation/devicetree/bindings/mmc/mmc-card.txt line 10

Quoted 6 lines
Documentation/devicetree/bindings/mmc/mmc-card.txt new file +6 -0
+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>

Instead of using a compatible, why can we just use "reg = <0>"?

Yes we could do that, but using a compatible is sort of the standard way to ensure that the contents of the node match the same binding rules as the code parsing the node. e.g. i2c child nodes also have a compatible string, as does the oob irq info for broadcom sdio wifi cards, which is the one existing user of mmc host child nodes I'm aware of.

Regards,

Hans

Quoted 78 lines
Quoted 72 lines
Documentation/devicetree/bindings/mmc/mmc-card.txt new file +21 -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";
+
+       mmmcard: mmccard at 0 {
+               reg = <0>;
+               compatible = "mmc-card";
+               broken-hpi;
+       };
+};
drivers/mmc/core/mmc.c +9 -2
index 1d41e85..8d18920 100644
@@ -11,6 +11,7 @@
   */
 
  #include <linux/err.h>
+#include <linux/of.h>
  #include <linux/slab.h>
  #include <linux/stat.h>
  #include <linux/pm_runtime.h>
@@ -336,6 +337,8 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
  {
         int err = 0, idx;
         unsigned int part_size;
+       struct device_node *np = card->dev.of_node;
+       bool broken_hpi = false;
 
         /* 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];
@@ -349,6 +352,9 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
                 }
         }
 
+       if (np && of_device_is_compatible(np, "mmc-card"))
+               broken_hpi = of_property_read_bool(np, "broken-hpi");
+
         /*
          * The EXT_CSD format is meant to be forward compatible. As long
          * as CSD_STRUCTURE does not change, all values for EXT_CSD_REV
@@ -494,7 +500,7 @@ static int mmc_decode_ext_csd(struct mmc_card *card, u8 *ext_csd)
                 }
 
                 /* 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;
                         if (ext_csd[EXT_CSD_HPI_FEATURES] & 0x2)
                                 card->ext_csd.hpi_cmd = MMC_STOP_TRANSMISSION;
@@ -1251,6 +1257,8 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
                 card->ocr = ocr;
                 card->type = MMC_TYPE_MMC;
                 card->rca = 1;
+               /* Also gets done by mmc_add_card, but we need early access */
+               card->dev.of_node = mmc_of_find_child_device(host, 0);
                 memcpy(card->raw_cid, cid, sizeof(card->raw_cid));
         }
 
--
Quoted 2 lines

2.3.4

Kind regards
Uffe