[PATCH 24/29] mmc: add a simple generic OF parser

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

 



Many MMC host drivers already use OF data to obtain their platform-specific
configuration. Each of them is doing this in its special way, whereas many
parameters are identical and can easily be generalised. This patch adds
such a generic parser. So far it only adds and handles very few basic
properties. New ones can be added in the future as required.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@xxxxxx>
Cc: Grant Likely <grant.likely@xxxxxxxxxxxx>
---
 drivers/mmc/core/Makefile |    2 +
 drivers/mmc/core/of.c     |   91 +++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mmc/host.h  |   12 ++++++
 3 files changed, 105 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mmc/core/of.c

diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
index 38ed210..aa7727e 100644
--- a/drivers/mmc/core/Makefile
+++ b/drivers/mmc/core/Makefile
@@ -9,4 +9,6 @@ mmc_core-y			:= core.o bus.o host.o \
 				   sdio_cis.o sdio_io.o sdio_irq.o \
 				   quirks.o slot-gpio.o
 
+mmc_core-$(CONFIG_OF)		+= of.o
+
 mmc_core-$(CONFIG_DEBUG_FS)	+= debugfs.o
diff --git a/drivers/mmc/core/of.c b/drivers/mmc/core/of.c
new file mode 100644
index 0000000..2fba115
--- /dev/null
+++ b/drivers/mmc/core/of.c
@@ -0,0 +1,91 @@
+/*
+ * Generic MMC OF parser
+ *
+ * Copyright (C) 2012, Guennadi Liakhovetski <g.liakhovetski@xxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
+/*
+ * Implementation-specific capabilities, that the controller driver usually
+ * cannot autodetect and has to receive from an external source, e.g., from
+ * platform data or from OF are:
+ *
+ * MMC_CAP_4_BIT_DATA: depends on the board layout: how many data lines are
+ *			connected
+ * MMC_CAP_8_BIT_DATA: ditto
+ * MMC_CAP2_INVERTED_CD: card-detect active-low (0 == card present)
+ * MMC_CAP2_INVERTED_RO: write-protect active-low (0 == read-only)
+ *	Some features might be supplied as GPIO bindings:
+ * MMC_CAP_SDIO_IRQ: depends, whether an SDIO IRQ line is connected
+ * MMC_CAP_NEEDS_POLL: is a card-detect pin connected?
+ * MMC_CAP_NONREMOVABLE: can also be a board feature, also, some media-types
+ *			(eMMC?) are intrinsicly non-removable
+ *	Others can be retrieved from regulators:
+ * MMC_CAP_POWER_OFF_CARD
+ */
+
+void mmc_of_get(struct mmc_host *mmc)
+{
+	struct device *dev = mmc_dev(mmc);
+	struct device_node *node = dev->of_node;
+	enum of_gpio_flags flags;
+	unsigned int gpio;
+	int ret;
+
+	if (!node || !of_device_is_available(node))
+		return;
+
+	if (of_get_property(node, "mmc,4_bit_data", NULL))
+		mmc->caps |= MMC_CAP_4_BIT_DATA;
+	if (of_get_property(node, "mmc,8_bit_data", NULL))
+		mmc->caps |= MMC_CAP_8_BIT_DATA;
+	if (of_get_property(node, "mmc,sdio_irq", NULL))
+		mmc->caps |= MMC_CAP_SDIO_IRQ;
+	if (of_get_property(node, "mmc,nonremovable", NULL))
+		mmc->caps |= MMC_CAP_NONREMOVABLE;
+	if (of_get_property(node, "mmc,needs_poll", NULL))
+		mmc->caps |= MMC_CAP_NEEDS_POLL;
+	if (of_get_property(node, "mmc,inverted_cd", NULL))
+		mmc->caps2 |= MMC_CAP2_INVERTED_CD;
+	if (of_get_property(node, "mmc,inverted_ro", NULL))
+		mmc->caps2 |= MMC_CAP2_INVERTED_RO;
+
+	/*
+	 * Both mmc_gpio_request_cd() and mmc_gpio_request_ro() check for
+	 * gpio_valid(), so, no need to check for error
+	 */
+
+	gpio = of_get_named_gpio_flags(node, "cd-gpios", 0, &flags);
+	ret = mmc_gpio_request_cd(mmc, gpio);
+	if (ret < 0)
+		dev_warn(mmc->parent, "Failed to obtain CD GPIO: %d\n", ret);
+
+	gpio = of_get_named_gpio_flags(node, "ro-gpios", 0, &flags);
+	ret = mmc_gpio_request_ro(mmc, gpio);
+	if (ret < 0)
+		dev_warn(mmc->parent, "Failed to obtain RO GPIO: %d\n", ret);
+}
+EXPORT_SYMBOL(mmc_of_get);
+
+void mmc_of_put(struct mmc_host *mmc)
+{
+	struct device_node *node = mmc_dev(mmc)->of_node;
+
+	if (!node || !of_device_is_available(node))
+		return;
+
+	mmc_gpio_free_ro(mmc);
+	mmc_gpio_free_cd(mmc);
+}
+EXPORT_SYMBOL(mmc_of_put);
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index f8157a9..94b3805 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -450,4 +450,16 @@ static inline unsigned int mmc_host_clk_rate(struct mmc_host *host)
 	return host->ios.clock;
 }
 #endif
+
+#ifdef CONFIG_OF
+void mmc_of_get(struct mmc_host *mmc);
+void mmc_of_put(struct mmc_host *mmc);
+#else
+static inline void mmc_of_get(struct mmc_host *mmc)
+{
+}
+static inline void mmc_of_put(struct mmc_host *mmc)
+{
+}
+#endif
 #endif /* LINUX_MMC_HOST_H */
-- 
1.7.2.5

--
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