Re: Devicetree: Initialization order of mmc block devices?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 19.07.2012 15:13, Arnd Bergmann wrote:
On Wednesday 18 July 2012, Dirk Behme wrote:
Any idea how we could influence the initialization order of the mmc block devices using a DT based kernel? Ensuring that the internal, hard wired mmc card is always mapped to mmcblk0?

I think the best solution would be to parse the "/aliases" device node
and look for an "mmc0" or "mmc1" property with a phandle to the respective
device. That's how we sort the serial ports. We have the of_alias_get_id()
function to pick out a node from there, so it should be possible to use
that in the mmc core similar to how we use it in the uart drivers.

Looking at the serial example you mentioned and trying to adapt that for mmcblkX I tried something like below [1] on a Freescale i.MX6 board and it seems to work :) Is this what you had in mind?

While I think the DT/of_alias_get_id() part looks ok (?), the way of passing the retrieved value from the driver sdhci-esdhc-imx.c to the block.c is quite hackish. I took it from the examples how this was hacked in the past.

Is there any better way of passing the information read in the driver by of_alias_get_id() to block.c? With the value read by of_alias_get_id() we somehow have to set name_idx in block.c.

Best regards

Dirk

[1]

Just fyi: From hardware point of view, usdhc1 connects the removable SD card, while usdhc3 attaches the non-removable eMMC. With the alias, independent if the SD card is there or not, the eMMC becomes always mmcblk1. And this is what we like to achieve here.

---
 arch/arm/boot/dts/imx6q-sabrelite.dts         |    5 +++++
 arch/arm/plat-mxc/include/mach/esdhc.h |    1 +
 drivers/mmc/card/block.c               |    6 ++++--
 drivers/mmc/host/sdhci-esdhc-imx.c     |   14 ++++++++++++++
 include/linux/mmc/host.h               |    3 +++
 5 files changed, 27 insertions(+), 2 deletions(-)

Index: a/arch/arm/boot/dts/imx6q-sabrelite.dts
===================================================================
--- a/arch/arm/boot/dts/imx6q-sabrelite.dts
+++ b/arch/arm/boot/dts/imx6q-sabrelite.dts
@@ -18,6 +18,11 @@
 	model = "Freescale i.MX6 Quad sabrelite Sample Board";
 	compatible = "fsl,imx6q-sabrelite", "fsl,imx6q";

+	aliases {
+		mmcblk0 = &usdhc1;
+		mmcblk1 = &usdhc3;
+	};
+
 	memory {
 		reg = <0x10000000 0x40000000>;
 	};
 	Index: freescale-linux-2.6-imx.git/drivers/mmc/host/sdhci-esdhc-imx.c
===================================================================
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -447,10 +447,21 @@ sdhci_esdhc_imx_probe_dt(struct platform
 			 struct esdhc_platform_data *boarddata)
 {
 	struct device_node *np = pdev->dev.of_node;
+	int ret;

 	if (!np)
 		return -ENODEV;

+	ret = of_alias_get_id(np, "mmcblk");
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
+		return -ENODEV;
+	}
+
+	boarddata->devidx = ret;
+
 	if (of_get_property(np, "fsl,card-wired", NULL))
 		boarddata->cd_type = ESDHC_CD_PERMANENT;

@@ -581,6 +592,9 @@ static int __devinit sdhci_esdhc_imx_pro
 					host->mmc->parent->platform_data);
 	}

+	/* copy mmc block device index */
+	host->mmc->devidx = boarddata->devidx;
+
 	/* write_protect */
 	if (boarddata->wp_type == ESDHC_WP_GPIO) {
 		err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
Index: a/arch/arm/plat-mxc/include/mach/esdhc.h
===================================================================
--- a/arch/arm/plat-mxc/include/mach/esdhc.h
+++ bt/arch/arm/plat-mxc/include/mach/esdhc.h
@@ -41,5 +41,6 @@ struct esdhc_platform_data {
 	enum wp_types wp_type;
 	enum cd_types cd_type;
 	int vdd_180;
+	unsigned int devidx;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
Index: freescale-linux-2.6-imx.git/drivers/mmc/card/block.c
===================================================================
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1466,7 +1466,8 @@ static struct mmc_blk_data *mmc_blk_allo
 	struct mmc_blk_data *md;
 	int devidx, ret;

-	devidx = find_first_zero_bit(dev_use, max_devices);
+	devidx = find_next_zero_bit(dev_use, max_devices,
+			card->host->devidx);
 	if (devidx >= max_devices)
 		return ERR_PTR(-ENOSPC);
 	__set_bit(devidx, dev_use);
@@ -1484,7 +1485,8 @@ static struct mmc_blk_data *mmc_blk_allo
 	 * index anymore so we keep track of a name index.
 	 */
 	if (!subname) {
-		md->name_idx = find_first_zero_bit(name_use, max_devices);
+		md->name_idx = find_next_zero_bit(name_use, max_devices,
+				card->host->devidx);
 		__set_bit(md->name_idx, name_use);
 	} else
 		md->name_idx = ((struct mmc_blk_data *)
Index: a/include/linux/mmc/host.h
===================================================================
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -326,6 +326,9 @@ struct mmc_host {

 	unsigned int		actual_clock;	/* Actual HC clock rate */

+	/* preferred mmc block device index (mmcblkX) */
+	unsigned int		devidx;
+
 	unsigned long		private[0] ____cacheline_aligned;
 };

--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux