[PATCH V4 3/4] mmc: pwrseq: Initial support for the simple MMC power sequence provider

Alexandre Courbot gnurou at gmail.com
Tue Feb 10 00:34:33 PST 2015


On Mon, Jan 19, 2015 at 6:13 PM, Ulf Hansson <ulf.hansson at linaro.org> wrote:
> 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 at linaro.org>
> ---
>
> Changes in v4:
>         - Fixed call to kfree().
>
> ---
>  drivers/mmc/core/Makefile        |  2 +-
>  drivers/mmc/core/pwrseq.c        | 61 +++++++++++++++++++++++++++++++++++++++-
>  drivers/mmc/core/pwrseq.h        |  2 ++
>  drivers/mmc/core/pwrseq_simple.c | 48 +++++++++++++++++++++++++++++++
>  4 files changed, 111 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/mmc/core/pwrseq_simple.c
>
> diff --git a/drivers/mmc/core/Makefile b/drivers/mmc/core/Makefile
> index ccdd35f..b39cbd2 100644
> --- a/drivers/mmc/core/Makefile
> +++ b/drivers/mmc/core/Makefile
> @@ -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
> diff --git a/drivers/mmc/core/pwrseq.c b/drivers/mmc/core/pwrseq.c
> index bd08772..2cea00e 100644
> --- a/drivers/mmc/core/pwrseq.c
> +++ b/drivers/mmc/core/pwrseq.c
> @@ -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)
> diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h
> index 12aaf2b..bd860d8 100644
> --- a/drivers/mmc/core/pwrseq.h
> +++ b/drivers/mmc/core/pwrseq.h
> @@ -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
> index 0000000..61c991e
> --- /dev/null
> +++ b/drivers/mmc/core/pwrseq_simple.c
> @@ -0,0 +1,48 @@
> +/*
> + *  Copyright (C) 2014 Linaro Ltd
> + *
> + * Author: Ulf Hansson <ulf.hansson at 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;

How about making this function return a struct mmc_pwrseq * so this
last line can be moved to mmc_pwrseq_alloc() instead of requiring all
power sequences to do it?

The same applies to

    host->pwrseq = NULL;

in mmc_pwrseq_simple_free(), which could be done in mmc_pwrseq_free() it seems.



More information about the linux-arm-kernel mailing list