[PATCH/RFC] mmc: sh_mmcif: revision-specific configuration from Device Tree

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

 




Add compatibility strings to configure MMCIF revision-specific features.
MMCIF blocks are always integrated into SoCs, so, we use SoC model to
distinguish between MMCIF versions.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski+renesas@xxxxxxxxx>
---

Hi Chris,
I marked this as RFC, because having no access to the MMC standard I'm not 
certain about VccQ requirements for MMC DDR. On the one hand a comment in 
mmc.c says
	 * EXT_CSD_CARD_TYPE_DDR_1_8V means 3.3V or 1.8V vccq.
which suggests, that DDR (DDR50?) can be used with VccQ = 3.3V, 1.8V and 
1.2V at least. But in mmc_init_card() DDR50 is only requested from the 
driver if either MMC_CAP_1_8V_DDR or MMC_CAP_1_2V_DDR is specified in 
host's capabilities. So, I'm actually not sure whether MMC_CAP_UHS_DDR50 
alone without 1_8V or 1_2V makes sense. That's also what I implemented in 
this patch - DDR50 is only enabled in combination with either 1.2 or 1.8V 
capability. Is this correct?

 Documentation/devicetree/bindings/mmc/sh_mmcif.txt |   15 ++++
 drivers/mmc/host/sh_mmcif.c                        |   68 +++++++++++++++++--
 2 files changed, 75 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/mmc/sh_mmcif.txt

diff --git a/Documentation/devicetree/bindings/mmc/sh_mmcif.txt b/Documentation/devicetree/bindings/mmc/sh_mmcif.txt
new file mode 100644
index 0000000..a0e7fee
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sh_mmcif.txt
@@ -0,0 +1,15 @@
+* Renesas MMCIF MMC controller
+
+The MMCIF driver uses the standard mmc DT parser to evaluate all standard MMC DT
+properties. Additionally the following properties must or can be used:
+
+Compulsory properties:
+- compatible:	must be one of
+		"renesas,sh-mmcif" for generic MMCIF blocks
+		"renesas,sh-mmcif-r8a73a4" for MMCIF on R8A73A4 (APE6)
+		"renesas,sh-mmcif-r8a7740" for MMCIF on R8A7740 (A1)
+		"renesas,sh-mmcif-r8a7790" for MMCIF on R8A7790 (H2)
+		"renesas,sh-mmcif-sh73a0" for MMCIF on SH73A0 (AG5)
+		"renesas,sh-mmcif-sh7372" for MMCIF on SH7372 (AP4)
+
+Further, any standard MMC DT properties from mmc.txt can be used.
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 444f83b..a4bd784 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -57,6 +57,7 @@
 #include <linux/mmc/slot-gpio.h>
 #include <linux/mod_devicetable.h>
 #include <linux/mutex.h>
+#include <linux/of_device.h>
 #include <linux/pagemap.h>
 #include <linux/platform_device.h>
 #include <linux/pm_qos.h>
@@ -257,6 +258,39 @@ struct sh_mmcif_host {
 	bool			dma_active;
 };
 
+struct sh_mmcif_of_data {
+	unsigned int	ccs_enable : 1;
+	unsigned int	clk_ctrl2_enable : 1;
+	unsigned int	uhs_ddr_1v8 : 1;
+	unsigned int	uhs_ddr_1v2 : 1;
+};
+
+enum {
+	R8A73A4,
+	R8A7740,
+	R8A7790,
+	SH7372,
+	SH73A0,
+};
+
+static const struct sh_mmcif_of_data sh_mmcif_of_cfg[] = {
+	[R8A73A4] = {
+		.uhs_ddr_1v8 = 1,
+	},
+	[R8A7740] = {
+		/* all disabled */
+	},
+	[R8A7790] = {
+		.clk_ctrl2_enable = 1,
+	},
+	[SH73A0] = {
+		.uhs_ddr_1v8 = 1,
+	},
+	[SH7372] = {
+		.ccs_enable = 1,
+	},
+};
+
 static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
 					unsigned int reg, u32 val)
 {
@@ -1362,8 +1396,21 @@ static void sh_mmcif_init_ocr(struct sh_mmcif_host *host)
 		dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
 }
 
+static const struct of_device_id mmcif_of_match[] = {
+	{.compatible = "renesas,sh-mmcif"},
+	{.compatible = "renesas,sh-mmcif-r8a73a4", .data = &sh_mmcif_of_cfg[R8A73A4]},
+	{.compatible = "renesas,sh-mmcif-r8a7740", .data = &sh_mmcif_of_cfg[R8A7740]},
+	{.compatible = "renesas,sh-mmcif-r8a7790", .data = &sh_mmcif_of_cfg[R8A7790]},
+	{.compatible = "renesas,sh-mmcif-sh73a0", .data = &sh_mmcif_of_cfg[SH73A0]},
+	{.compatible = "renesas,sh-mmcif-sh7372", .data = &sh_mmcif_of_cfg[SH7372]},
+	{}
+};
+MODULE_DEVICE_TABLE(of, mmcif_of_match);
+
 static int sh_mmcif_probe(struct platform_device *pdev)
 {
+	const struct of_device_id *of_id =
+		of_match_device(mmcif_of_match, &pdev->dev);
 	int ret = 0, irq[2];
 	struct mmc_host *mmc;
 	struct sh_mmcif_host *host;
@@ -1403,8 +1450,19 @@ static int sh_mmcif_probe(struct platform_device *pdev)
 	host->mmc	= mmc;
 	host->addr	= reg;
 	host->timeout	= msecs_to_jiffies(1000);
-	host->ccs_enable = !pd || !pd->ccs_unsupported;
-	host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present;
+
+	if (of_id && of_id->data) {
+		const struct sh_mmcif_of_data *of_data = of_id->data;
+		host->ccs_enable = of_data->ccs_enable;
+		host->clk_ctrl2_enable = of_data->clk_ctrl2_enable;
+		if (of_data->uhs_ddr_1v8)
+			mmc->caps |= MMC_CAP_UHS_DDR50 | MMC_CAP_1_8V_DDR;
+		if (of_data->uhs_ddr_1v2)
+			mmc->caps |= MMC_CAP_UHS_DDR50 | MMC_CAP_1_2V_DDR;
+	} else {
+		host->ccs_enable = !pd || !pd->ccs_unsupported;
+		host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present;
+	}
 
 	host->pd = pdev;
 
@@ -1564,12 +1622,6 @@ static int sh_mmcif_resume(struct device *dev)
 #define sh_mmcif_resume		NULL
 #endif	/* CONFIG_PM */
 
-static const struct of_device_id mmcif_of_match[] = {
-	{ .compatible = "renesas,sh-mmcif" },
-	{ }
-};
-MODULE_DEVICE_TABLE(of, mmcif_of_match);
-
 static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
 	.suspend = sh_mmcif_suspend,
 	.resume = sh_mmcif_resume,
-- 
1.7.2.5

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




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux