diff mbox

[6/7] MMC: mmci: Enable Device Tree support for ux500 variants

Message ID 1333621534-29627-6-git-send-email-lee.jones@linaro.org
State New
Headers show

Commit Message

Lee Jones April 5, 2012, 10:25 a.m. UTC
Provide a means to collect attributes specific to ST-Ericsson's
ux500 variant series. This patch registers itself as the AMBA
driver to be called during the probe process. Once all
attributes and ux500 specifics are are collected the normal
mmci core probe is called.

Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
 arch/arm/boot/dts/snowball.dts         |   21 ++++++++++--
 arch/arm/mach-ux500/board-mop500-sdi.c |    4 +-
 arch/arm/mach-ux500/board-mop500.c     |    3 +-
 arch/arm/mach-ux500/board-mop500.h     |    4 ++
 drivers/mmc/host/mmci.c                |   58 +++++++++++++++++++++++++++++--
 5 files changed, 80 insertions(+), 10 deletions(-)
diff mbox

Patch

diff --git a/arch/arm/boot/dts/snowball.dts b/arch/arm/boot/dts/snowball.dts
index 0cec47b..8e2a609 100644
--- a/arch/arm/boot/dts/snowball.dts
+++ b/arch/arm/boot/dts/snowball.dts
@@ -87,13 +87,28 @@ 
 			};
 		};
 
+		// External Micro SD slot
 		sdi@80126000 {
-			status = "enabled";
-			cd-gpios = <&gpio6 26>;
+			arm,primecell-periphid = <0x10480180>;
+			clock-frequency = <50000000>;
+			bus-width = <8>;
+			mmc-cap-mmc-highspeed;
+
+			#gpio-cells = <1>;
+			cd-gpios  = <&gpio6 26>; // 218
+			cd-inverted;
+
+			status = "okay";
 		};
 
+		// On-board eMMC
 		sdi@80114000 {
-			status = "enabled";
+			arm,primecell-periphid = <0x10480180>;
+		        clock-frequency = <50000000>;
+			bus-width = <8>;
+			mmc-cap-mmc-highspeed;
+
+			status = "okay";
 		};
 
 		uart@80120000 {
diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c
index 920251c..18ff781 100644
--- a/arch/arm/mach-ux500/board-mop500-sdi.c
+++ b/arch/arm/mach-ux500/board-mop500-sdi.c
@@ -80,7 +80,7 @@  static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 };
 #endif
 
-static struct mmci_platform_data mop500_sdi0_data = {
+struct mmci_platform_data mop500_sdi0_data = {
 	.ios_handler	= mop500_sdi0_ios_handler,
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 50000000,
@@ -227,7 +227,7 @@  static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
 };
 #endif
 
-static struct mmci_platform_data mop500_sdi4_data = {
+struct mmci_platform_data mop500_sdi4_data = {
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 50000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index a47d6bd..d2c3a5c 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -759,6 +759,8 @@  struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
 	/* Requires DMA bindings. */
 	OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0",  &ssp0_plat),
+	OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
+	OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
 	/* Requires clock name bindings. */
 	OF_DEV_AUXDATA("stmicroelectronics,nomadik-gpio", 0x8012e000, "gpio.0", NULL),
 	OF_DEV_AUXDATA("stmicroelectronics,nomadik-gpio", 0x8012e080, "gpio.1", NULL),
@@ -815,7 +817,6 @@  static void __init u8500_init_machine(void)
 		platform_add_devices(snowball_of_platform_devs,
 				ARRAY_SIZE(snowball_of_platform_devs));
 
-		snowball_sdi_init(parent);
 	} else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
 		/*
 		 * The HREFv60 board removed a GPIO expander and routed
diff --git a/arch/arm/mach-ux500/board-mop500.h b/arch/arm/mach-ux500/board-mop500.h
index fdcfa87..384baf7 100644
--- a/arch/arm/mach-ux500/board-mop500.h
+++ b/arch/arm/mach-ux500/board-mop500.h
@@ -7,6 +7,8 @@ 
 #ifndef __BOARD_MOP500_H
 #define __BOARD_MOP500_H
 
+#include <linux/amba/mmci.h>
+
 /* Snowball specific GPIO assignments, this board has no GPIO expander */
 #define SNOWBALL_ACCEL_INT1_GPIO	163
 #define SNOWBALL_ACCEL_INT2_GPIO	164
@@ -74,6 +76,8 @@ 
 #define SNOWBALL_EN_3V3_ETH_GPIO	MOP500_AB8500_PIN_GPIO(26)	/* GPIO26 */
 
 struct i2c_board_info;
+extern struct mmci_platform_data mop500_sdi0_data;
+extern struct mmci_platform_data mop500_sdi4_data;
 
 extern void mop500_sdi_init(struct device *parent);
 extern void snowball_sdi_init(struct device *parent);
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 032b847..8538d55 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -15,6 +15,7 @@ 
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/highmem.h>
@@ -1196,21 +1197,70 @@  static const struct mmc_host_ops mmci_ops = {
 	.get_cd		= mmci_get_cd,
 };
 
+#ifdef CONFIG_OF
+static void mmci_dt_populate_generic_pdata(struct device_node *np,
+					struct mmci_platform_data *pdata)
+{
+	int bus_width = 0;
+
+	of_property_read_u32(np, "wp-gpios", &pdata->gpio_wp);
+	if (!pdata->gpio_wp)
+		pdata->gpio_wp = -1;
+
+	of_property_read_u32(np, "cd-gpios", &pdata->gpio_cd);
+	if (!pdata->gpio_cd)
+		pdata->gpio_cd = -1;
+
+	if (of_get_property(np, "cd-inverted", NULL))
+		pdata->cd_invert = true;
+	else
+		pdata->cd_invert = false;
+
+	of_property_read_u32(np, "clock-frequency", &pdata->f_max);
+	if (!pdata->f_max)
+		pr_warn("%s has no 'clock-frequency' property\n", np->full_name);
+
+	if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL))
+		pdata->capabilities |= MMC_CAP_MMC_HIGHSPEED;
+	if (of_get_property(np, "mmc-cap-sd-highspeed", NULL))
+		pdata->capabilities |= MMC_CAP_SD_HIGHSPEED;
+
+	of_property_read_u32(np, "bus-width", &bus_width);
+	switch (bus_width) {
+	case 0 :
+		/* No bus-width supplied. */
+		break;
+	case 4 :
+		pdata->capabilities |= MMC_CAP_4_BIT_DATA;
+		break;
+	case 8 :
+		pdata->capabilities |= MMC_CAP_8_BIT_DATA;
+		break;
+	default :
+		pr_warn("%s: Unsupported bus width\n", np->full_name);
+	}
+}
+#endif
+
 static int __devinit mmci_probe(struct amba_device *dev,
 	const struct amba_id *id)
 {
 	struct mmci_platform_data *plat = dev->dev.platform_data;
+	struct device_node *np = dev->dev.of_node;
 	struct variant_data *variant = id->data;
 	struct mmci_host *host;
 	struct mmc_host *mmc;
 	int ret;
 
-	/* must have platform data */
-	if (!plat) {
-		ret = -EINVAL;
-		goto out;
+	/* Must have platform data or Device Tree. */
+	if (!plat && !np) {
+		dev_err(&dev->dev, "No plat data or DT found\n");
+		return -EINVAL;
 	}
 
+	if (np)
+		mmci_dt_populate_generic_pdata(np, plat);
+
 	ret = amba_request_regions(dev, DRIVER_NAME);
 	if (ret)
 		goto out;