mmc: pwrseq: Initial support for the simple MMC power sequence provider
authorUlf Hansson <ulf.hansson@linaro.org>
Fri, 5 Dec 2014 13:36:58 +0000 (14:36 +0100)
committerUlf Hansson <ulf.hansson@linaro.org>
Wed, 28 Jan 2015 11:32:07 +0000 (12:32 +0100)
To add the core part for the MMC power sequence, let's start by adding
initial support for the simple MMC power sequence provider.

In this initial step, the MMC power sequence node are fetched and the
compatible string for the simple MMC power sequence provider are
verified.

At this point we don't parse the node for any properties, but instead
that will be handled from following patches. Since there are no
properties supported yet, let's just implement the ->alloc() and the
->free() callbacks.

Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Tested-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
Reviewed-by: Javier Martinez Canillas <javier.martinez@collabora.co.uk>
drivers/mmc/core/Makefile
drivers/mmc/core/pwrseq.c
drivers/mmc/core/pwrseq.h
drivers/mmc/core/pwrseq_simple.c [new file with mode: 0644]

index ccdd35f782560aefa816612b93e155b44d928603..b39cbd2f830b631ae0d5ded85a9496719c99d1a0 100644 (file)
@@ -8,5 +8,5 @@ mmc_core-y                      := core.o bus.o host.o \
                                   sdio.o sdio_ops.o sdio_bus.o \
                                   sdio_cis.o sdio_io.o sdio_irq.o \
                                   quirks.o slot-gpio.o
-mmc_core-$(CONFIG_OF)          += pwrseq.o
+mmc_core-$(CONFIG_OF)          += pwrseq.o pwrseq_simple.o
 mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
index bd087723929fd81484255254bf6dae4b981900b2..2cea00ed4e655d26aae4bb6af62d32077b5bafb0 100644 (file)
@@ -7,14 +7,73 @@
  *
  *  MMC power sequence management
  */
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+
 #include <linux/mmc/host.h>
 
 #include "pwrseq.h"
 
+struct mmc_pwrseq_match {
+       const char *compatible;
+       int (*alloc)(struct mmc_host *host, struct device *dev);
+};
+
+static struct mmc_pwrseq_match pwrseq_match[] = {
+       {
+               .compatible = "mmc-pwrseq-simple",
+               .alloc = mmc_pwrseq_simple_alloc,
+       },
+};
+
+static struct mmc_pwrseq_match *mmc_pwrseq_find(struct device_node *np)
+{
+       struct mmc_pwrseq_match *match = ERR_PTR(-ENODEV);
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(pwrseq_match); i++) {
+               if (of_device_is_compatible(np, pwrseq_match[i].compatible)) {
+                       match = &pwrseq_match[i];
+                       break;
+               }
+       }
+
+       return match;
+}
 
 int mmc_pwrseq_alloc(struct mmc_host *host)
 {
-       return 0;
+       struct platform_device *pdev;
+       struct device_node *np;
+       struct mmc_pwrseq_match *match;
+       int ret = 0;
+
+       np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0);
+       if (!np)
+               return 0;
+
+       pdev = of_find_device_by_node(np);
+       if (!pdev) {
+               ret = -ENODEV;
+               goto err;
+       }
+
+       match = mmc_pwrseq_find(np);
+       if (IS_ERR(match)) {
+               ret = PTR_ERR(match);
+               goto err;
+       }
+
+       ret = match->alloc(host, &pdev->dev);
+       if (!ret)
+               dev_info(host->parent, "allocated mmc-pwrseq\n");
+
+err:
+       of_node_put(np);
+       return ret;
 }
 
 void mmc_pwrseq_pre_power_on(struct mmc_host *host)
index 12aaf2b4745bf84354dcee314a855136be123e45..bd860d88f116c920077754ef28ab9741825622d7 100644 (file)
@@ -27,6 +27,8 @@ void mmc_pwrseq_post_power_on(struct mmc_host *host);
 void mmc_pwrseq_power_off(struct mmc_host *host);
 void mmc_pwrseq_free(struct mmc_host *host);
 
+int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev);
+
 #else
 
 static inline int mmc_pwrseq_alloc(struct mmc_host *host) { return 0; }
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
new file mode 100644 (file)
index 0000000..61c991e
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (C) 2014 Linaro Ltd
+ *
+ * Author: Ulf Hansson <ulf.hansson@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ *  Simple MMC power sequence management
+ */
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/err.h>
+
+#include <linux/mmc/host.h>
+
+#include "pwrseq.h"
+
+struct mmc_pwrseq_simple {
+       struct mmc_pwrseq pwrseq;
+};
+
+static void mmc_pwrseq_simple_free(struct mmc_host *host)
+{
+       struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq,
+                                       struct mmc_pwrseq_simple, pwrseq);
+
+       kfree(pwrseq);
+       host->pwrseq = NULL;
+}
+
+static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
+       .free = mmc_pwrseq_simple_free,
+};
+
+int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev)
+{
+       struct mmc_pwrseq_simple *pwrseq;
+
+       pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple), GFP_KERNEL);
+       if (!pwrseq)
+               return -ENOMEM;
+
+       pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops;
+       host->pwrseq = &pwrseq->pwrseq;
+
+       return 0;
+}