0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/err.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013
0014 #include <linux/mmc/host.h>
0015
0016 #include "pwrseq.h"
0017
0018 static DEFINE_MUTEX(pwrseq_list_mutex);
0019 static LIST_HEAD(pwrseq_list);
0020
0021 int mmc_pwrseq_alloc(struct mmc_host *host)
0022 {
0023 struct device_node *np;
0024 struct mmc_pwrseq *p;
0025
0026 np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0);
0027 if (!np)
0028 return 0;
0029
0030 mutex_lock(&pwrseq_list_mutex);
0031 list_for_each_entry(p, &pwrseq_list, pwrseq_node) {
0032 if (p->dev->of_node == np) {
0033 if (!try_module_get(p->owner))
0034 dev_err(host->parent,
0035 "increasing module refcount failed\n");
0036 else
0037 host->pwrseq = p;
0038
0039 break;
0040 }
0041 }
0042
0043 of_node_put(np);
0044 mutex_unlock(&pwrseq_list_mutex);
0045
0046 if (!host->pwrseq)
0047 return -EPROBE_DEFER;
0048
0049 dev_info(host->parent, "allocated mmc-pwrseq\n");
0050
0051 return 0;
0052 }
0053
0054 void mmc_pwrseq_pre_power_on(struct mmc_host *host)
0055 {
0056 struct mmc_pwrseq *pwrseq = host->pwrseq;
0057
0058 if (pwrseq && pwrseq->ops->pre_power_on)
0059 pwrseq->ops->pre_power_on(host);
0060 }
0061
0062 void mmc_pwrseq_post_power_on(struct mmc_host *host)
0063 {
0064 struct mmc_pwrseq *pwrseq = host->pwrseq;
0065
0066 if (pwrseq && pwrseq->ops->post_power_on)
0067 pwrseq->ops->post_power_on(host);
0068 }
0069
0070 void mmc_pwrseq_power_off(struct mmc_host *host)
0071 {
0072 struct mmc_pwrseq *pwrseq = host->pwrseq;
0073
0074 if (pwrseq && pwrseq->ops->power_off)
0075 pwrseq->ops->power_off(host);
0076 }
0077
0078 void mmc_pwrseq_reset(struct mmc_host *host)
0079 {
0080 struct mmc_pwrseq *pwrseq = host->pwrseq;
0081
0082 if (pwrseq && pwrseq->ops->reset)
0083 pwrseq->ops->reset(host);
0084 }
0085
0086 void mmc_pwrseq_free(struct mmc_host *host)
0087 {
0088 struct mmc_pwrseq *pwrseq = host->pwrseq;
0089
0090 if (pwrseq) {
0091 module_put(pwrseq->owner);
0092 host->pwrseq = NULL;
0093 }
0094 }
0095
0096 int mmc_pwrseq_register(struct mmc_pwrseq *pwrseq)
0097 {
0098 if (!pwrseq || !pwrseq->ops || !pwrseq->dev)
0099 return -EINVAL;
0100
0101 mutex_lock(&pwrseq_list_mutex);
0102 list_add(&pwrseq->pwrseq_node, &pwrseq_list);
0103 mutex_unlock(&pwrseq_list_mutex);
0104
0105 return 0;
0106 }
0107 EXPORT_SYMBOL_GPL(mmc_pwrseq_register);
0108
0109 void mmc_pwrseq_unregister(struct mmc_pwrseq *pwrseq)
0110 {
0111 if (pwrseq) {
0112 mutex_lock(&pwrseq_list_mutex);
0113 list_del(&pwrseq->pwrseq_node);
0114 mutex_unlock(&pwrseq_list_mutex);
0115 }
0116 }
0117 EXPORT_SYMBOL_GPL(mmc_pwrseq_unregister);