Commit | Line | Data |
---|---|---|
8c96f89c UH |
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 | * Simple MMC power sequence management | |
9 | */ | |
10 | #include <linux/kernel.h> | |
11 | #include <linux/slab.h> | |
12 | #include <linux/device.h> | |
13 | #include <linux/err.h> | |
862b5dcf | 14 | #include <linux/gpio/consumer.h> |
8c96f89c UH |
15 | |
16 | #include <linux/mmc/host.h> | |
17 | ||
18 | #include "pwrseq.h" | |
19 | ||
20 | struct mmc_pwrseq_simple { | |
21 | struct mmc_pwrseq pwrseq; | |
862b5dcf | 22 | struct gpio_desc *reset_gpio; |
8c96f89c UH |
23 | }; |
24 | ||
862b5dcf UH |
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 | ||
8c96f89c UH |
43 | static void mmc_pwrseq_simple_free(struct mmc_host *host) |
44 | { | |
45 | struct mmc_pwrseq_simple *pwrseq = container_of(host->pwrseq, | |
46 | struct mmc_pwrseq_simple, pwrseq); | |
47 | ||
862b5dcf UH |
48 | if (!IS_ERR(pwrseq->reset_gpio)) |
49 | gpiod_put(pwrseq->reset_gpio); | |
50 | ||
8c96f89c UH |
51 | kfree(pwrseq); |
52 | host->pwrseq = NULL; | |
53 | } | |
54 | ||
55 | static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = { | |
862b5dcf UH |
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, | |
8c96f89c UH |
59 | .free = mmc_pwrseq_simple_free, |
60 | }; | |
61 | ||
62 | int mmc_pwrseq_simple_alloc(struct mmc_host *host, struct device *dev) | |
63 | { | |
64 | struct mmc_pwrseq_simple *pwrseq; | |
862b5dcf | 65 | int ret = 0; |
8c96f89c UH |
66 | |
67 | pwrseq = kzalloc(sizeof(struct mmc_pwrseq_simple), GFP_KERNEL); | |
68 | if (!pwrseq) | |
69 | return -ENOMEM; | |
70 | ||
862b5dcf UH |
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 | ||
8c96f89c UH |
79 | pwrseq->pwrseq.ops = &mmc_pwrseq_simple_ops; |
80 | host->pwrseq = &pwrseq->pwrseq; | |
81 | ||
82 | return 0; | |
862b5dcf UH |
83 | free: |
84 | kfree(pwrseq); | |
85 | return ret; | |
8c96f89c | 86 | } |