linux/drivers/mmc/core/pwrseq.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2014 Linaro Ltd
   3 *
   4 * Author: Ulf Hansson <ulf.hansson@linaro.org>
   5 *
   6 * License terms: GNU General Public License (GPL) version 2
   7 *
   8 *  MMC power sequence management
   9 */
  10#include <linux/kernel.h>
  11#include <linux/platform_device.h>
  12#include <linux/err.h>
  13#include <linux/of.h>
  14#include <linux/of_platform.h>
  15
  16#include <linux/mmc/host.h>
  17
  18#include "pwrseq.h"
  19
  20struct mmc_pwrseq_match {
  21        const char *compatible;
  22        struct mmc_pwrseq *(*alloc)(struct mmc_host *host, struct device *dev);
  23};
  24
  25static struct mmc_pwrseq_match pwrseq_match[] = {
  26        {
  27                .compatible = "mmc-pwrseq-simple",
  28                .alloc = mmc_pwrseq_simple_alloc,
  29        }, {
  30                .compatible = "mmc-pwrseq-emmc",
  31                .alloc = mmc_pwrseq_emmc_alloc,
  32        },
  33};
  34
  35static struct mmc_pwrseq_match *mmc_pwrseq_find(struct device_node *np)
  36{
  37        struct mmc_pwrseq_match *match = ERR_PTR(-ENODEV);
  38        int i;
  39
  40        for (i = 0; i < ARRAY_SIZE(pwrseq_match); i++) {
  41                if (of_device_is_compatible(np, pwrseq_match[i].compatible)) {
  42                        match = &pwrseq_match[i];
  43                        break;
  44                }
  45        }
  46
  47        return match;
  48}
  49
  50int mmc_pwrseq_alloc(struct mmc_host *host)
  51{
  52        struct platform_device *pdev;
  53        struct device_node *np;
  54        struct mmc_pwrseq_match *match;
  55        struct mmc_pwrseq *pwrseq;
  56        int ret = 0;
  57
  58        np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0);
  59        if (!np)
  60                return 0;
  61
  62        pdev = of_find_device_by_node(np);
  63        if (!pdev) {
  64                ret = -ENODEV;
  65                goto err;
  66        }
  67
  68        match = mmc_pwrseq_find(np);
  69        if (IS_ERR(match)) {
  70                ret = PTR_ERR(match);
  71                goto err;
  72        }
  73
  74        pwrseq = match->alloc(host, &pdev->dev);
  75        if (IS_ERR(pwrseq)) {
  76                ret = PTR_ERR(pwrseq);
  77                goto err;
  78        }
  79
  80        host->pwrseq = pwrseq;
  81        dev_info(host->parent, "allocated mmc-pwrseq\n");
  82
  83err:
  84        of_node_put(np);
  85        return ret;
  86}
  87
  88void mmc_pwrseq_pre_power_on(struct mmc_host *host)
  89{
  90        struct mmc_pwrseq *pwrseq = host->pwrseq;
  91
  92        if (pwrseq && pwrseq->ops && pwrseq->ops->pre_power_on)
  93                pwrseq->ops->pre_power_on(host);
  94}
  95
  96void mmc_pwrseq_post_power_on(struct mmc_host *host)
  97{
  98        struct mmc_pwrseq *pwrseq = host->pwrseq;
  99
 100        if (pwrseq && pwrseq->ops && pwrseq->ops->post_power_on)
 101                pwrseq->ops->post_power_on(host);
 102}
 103
 104void mmc_pwrseq_power_off(struct mmc_host *host)
 105{
 106        struct mmc_pwrseq *pwrseq = host->pwrseq;
 107
 108        if (pwrseq && pwrseq->ops && pwrseq->ops->power_off)
 109                pwrseq->ops->power_off(host);
 110}
 111
 112void mmc_pwrseq_free(struct mmc_host *host)
 113{
 114        struct mmc_pwrseq *pwrseq = host->pwrseq;
 115
 116        if (pwrseq && pwrseq->ops && pwrseq->ops->free)
 117                pwrseq->ops->free(host);
 118
 119        host->pwrseq = NULL;
 120}
 121