diff options
-rw-r--r-- | drivers/mmc/core/pwrseq_simple.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c index 61c991e4009d..0958c696137f 100644 --- a/drivers/mmc/core/pwrseq_simple.c +++ b/drivers/mmc/core/pwrseq_simple.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/device.h> | 12 | #include <linux/device.h> |
13 | #include <linux/err.h> | 13 | #include <linux/err.h> |
14 | #include <linux/gpio/consumer.h> | ||
14 | 15 | ||
15 | #include <linux/mmc/host.h> | 16 | #include <linux/mmc/host.h> |
16 | 17 | ||
@@ -18,31 +19,68 @@ | |||
18 | 19 | ||
19 | struct mmc_pwrseq_simple { | 20 | struct mmc_pwrseq_simple { |
20 | struct mmc_pwrseq pwrseq; | 21 | struct mmc_pwrseq pwrseq; |
22 | struct gpio_desc *reset_gpio; | ||
21 | }; | 23 | }; |
22 | 24 | ||
25 | static void mmc_pwrseq_simple_pre_power_on(struct mmc_host *host) | ||
26 | { | ||
27 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, | ||
28 | struct mmc_pwrseq_simple, pwrseq); | ||
29 | |||
30 | if (!IS_ERR(pwrseq->reset_gpio)) | ||
31 | gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); | ||
32 | } | ||
33 | |||
34 | static void mmc_pwrseq_simple_post_power_on(struct mmc_host *host) | ||
35 | { | ||
36 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, | ||
37 | struct mmc_pwrseq_simple, pwrseq); | ||
38 | |||
39 | if (!IS_ERR(pwrseq->reset_gpio)) | ||
40 | gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); | ||
41 | } | ||
42 | |||
23 | static void mmc_pwrseq_simple_free(struct mmc_host *host) | 43 | static void mmc_pwrseq_simple_free(struct mmc_host *host) |
24 | { | 44 | { |
25 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, | 45 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, |
26 | struct mmc_pwrseq_simple, pwrseq); | 46 | struct mmc_pwrseq_simple, pwrseq); |
27 | 47 | ||
48 | if (!IS_ERR(pwrseq->reset_gpio)) | ||
49 | gpiod_put(pwrseq->reset_gpio); | ||
50 | |||
28 | kfree(pwrseq); | 51 | kfree(pwrseq); |
29 | host->pwrseq = NULL; | 52 | host->pwrseq = NULL; |
30 | } | 53 | } |
31 | 54 | ||
32 | static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { | 55 | static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { |
56 | .pre_power_on = mmc_pwrseq_simple_pre_power_on, | ||
57 | .post_power_on = mmc_pwrseq_simple_post_power_on, | ||
58 | .power_off = mmc_pwrseq_simple_pre_power_on, | ||
33 | .free = mmc_pwrseq_simple_free, | 59 | .free = mmc_pwrseq_simple_free, |
34 | }; | 60 | }; |
35 | 61 | ||
36 | int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) | 62 | int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) |
37 | { | 63 | { |
38 | struct mmc_pwrseq_simple *pwrseq; | 64 | struct mmc_pwrseq_simple *pwrseq; |
65 | int ret = 0; | ||
39 | 66 | ||
40 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple), GFP_KERNEL); | 67 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple), GFP_KERNEL); |
41 | if (!pwrseq) | 68 | if (!pwrseq) |
42 | return -ENOMEM; | 69 | return -ENOMEM; |
43 | 70 | ||
71 | pwrseq->reset_gpio = gpiod_get_index(dev, "reset", 0, GPIOD_OUT_HIGH); | ||
72 | if (IS_ERR(pwrseq->reset_gpio) && | ||
73 | PTR_ERR(pwrseq->reset_gpio) != -ENOENT && | ||
74 | PTR_ERR(pwrseq->reset_gpio) != -ENOSYS) { | ||
75 | ret = PTR_ERR(pwrseq->reset_gpio); | ||
76 | goto free; | ||
77 | } | ||
78 | |||
44 | pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; | 79 | pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; |
45 | host->pwrseq = &pwrseq->pwrseq; | 80 | host->pwrseq = &pwrseq->pwrseq; |
46 | 81 | ||
47 | return 0; | 82 | return 0; |
83 | free: | ||
84 | kfree(pwrseq); | ||
85 | return ret; | ||
48 | } | 86 | } |