diff options
author | Russell King <rmk+kernel@armlinux.org.uk> | 2016-08-31 03:49:46 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@armlinux.org.uk> | 2016-09-22 04:39:02 -0400 |
commit | ac61b6001a636ab9aa954b5f9a996056cd8519f4 (patch) | |
tree | d2c5e8c5344232f0dc781c68b23f0cdbb3375408 | |
parent | a1d0500261e788f9b1d068e3167b2a77ad0abfc4 (diff) |
pcmcia: soc_common: add support for Vcc and Vpp regulators
Add support for handling supply regulators in the soc_common code. This
allows us to separate out the board specifics for setting voltages from
the PCMCIA code.
We detect when setting a voltage fails, and report this fact - some
platforms have fixed-voltage supplies (eg, for CF sockets at 3.3V) and
we need to ignore attempts to configure for 5V, as per the existing
board specific drivers.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r-- | drivers/pcmcia/soc_common.c | 37 | ||||
-rw-r--r-- | drivers/pcmcia/soc_common.h | 11 |
2 files changed, 47 insertions, 1 deletions
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 6d0ec291f475..15e332aca0f3 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/module.h> | 43 | #include <linux/module.h> |
44 | #include <linux/moduleparam.h> | 44 | #include <linux/moduleparam.h> |
45 | #include <linux/mutex.h> | 45 | #include <linux/mutex.h> |
46 | #include <linux/regulator/consumer.h> | ||
46 | #include <linux/spinlock.h> | 47 | #include <linux/spinlock.h> |
47 | #include <linux/timer.h> | 48 | #include <linux/timer.h> |
48 | 49 | ||
@@ -80,6 +81,41 @@ EXPORT_SYMBOL(soc_pcmcia_debug); | |||
80 | #define to_soc_pcmcia_socket(x) \ | 81 | #define to_soc_pcmcia_socket(x) \ |
81 | container_of(x, struct soc_pcmcia_socket, socket) | 82 | container_of(x, struct soc_pcmcia_socket, socket) |
82 | 83 | ||
84 | int soc_pcmcia_regulator_set(struct soc_pcmcia_socket *skt, | ||
85 | struct soc_pcmcia_regulator *r, int v) | ||
86 | { | ||
87 | bool on; | ||
88 | int ret; | ||
89 | |||
90 | if (!r->reg) | ||
91 | return 0; | ||
92 | |||
93 | on = v != 0; | ||
94 | if (r->on == on) | ||
95 | return 0; | ||
96 | |||
97 | if (on) { | ||
98 | ret = regulator_set_voltage(r->reg, v * 100000, v * 100000); | ||
99 | if (ret) { | ||
100 | int vout = regulator_get_voltage(r->reg) / 100000; | ||
101 | |||
102 | dev_warn(&skt->socket.dev, | ||
103 | "CS requested %s=%u.%uV, applying %u.%uV\n", | ||
104 | r == &skt->vcc ? "Vcc" : "Vpp", | ||
105 | v / 10, v % 10, vout / 10, vout % 10); | ||
106 | } | ||
107 | |||
108 | ret = regulator_enable(r->reg); | ||
109 | } else { | ||
110 | regulator_disable(r->reg); | ||
111 | } | ||
112 | if (ret == 0) | ||
113 | r->on = on; | ||
114 | |||
115 | return ret; | ||
116 | } | ||
117 | EXPORT_SYMBOL_GPL(soc_pcmcia_regulator_set); | ||
118 | |||
83 | static unsigned short | 119 | static unsigned short |
84 | calc_speed(unsigned short *spds, int num, unsigned short dflt) | 120 | calc_speed(unsigned short *spds, int num, unsigned short dflt) |
85 | { | 121 | { |
@@ -119,7 +155,6 @@ static void __soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt, | |||
119 | if (skt->ops->hw_shutdown) | 155 | if (skt->ops->hw_shutdown) |
120 | skt->ops->hw_shutdown(skt); | 156 | skt->ops->hw_shutdown(skt); |
121 | 157 | ||
122 | |||
123 | clk_disable_unprepare(skt->clk); | 158 | clk_disable_unprepare(skt->clk); |
124 | } | 159 | } |
125 | 160 | ||
diff --git a/drivers/pcmcia/soc_common.h b/drivers/pcmcia/soc_common.h index 39c1e15167f3..18a6df5ca374 100644 --- a/drivers/pcmcia/soc_common.h +++ b/drivers/pcmcia/soc_common.h | |||
@@ -19,6 +19,12 @@ | |||
19 | struct device; | 19 | struct device; |
20 | struct gpio_desc; | 20 | struct gpio_desc; |
21 | struct pcmcia_low_level; | 21 | struct pcmcia_low_level; |
22 | struct regulator; | ||
23 | |||
24 | struct soc_pcmcia_regulator { | ||
25 | struct regulator *reg; | ||
26 | bool on; | ||
27 | }; | ||
22 | 28 | ||
23 | /* | 29 | /* |
24 | * This structure encapsulates per-socket state which we might need to | 30 | * This structure encapsulates per-socket state which we might need to |
@@ -64,6 +70,8 @@ struct soc_pcmcia_socket { | |||
64 | 70 | ||
65 | struct gpio_desc *gpio_reset; | 71 | struct gpio_desc *gpio_reset; |
66 | struct gpio_desc *gpio_bus_enable; | 72 | struct gpio_desc *gpio_bus_enable; |
73 | struct soc_pcmcia_regulator vcc; | ||
74 | struct soc_pcmcia_regulator vpp; | ||
67 | 75 | ||
68 | unsigned int irq_state; | 76 | unsigned int irq_state; |
69 | 77 | ||
@@ -146,6 +154,9 @@ int soc_pcmcia_request_gpiods(struct soc_pcmcia_socket *skt); | |||
146 | void soc_common_cf_socket_state(struct soc_pcmcia_socket *skt, | 154 | void soc_common_cf_socket_state(struct soc_pcmcia_socket *skt, |
147 | struct pcmcia_state *state); | 155 | struct pcmcia_state *state); |
148 | 156 | ||
157 | int soc_pcmcia_regulator_set(struct soc_pcmcia_socket *skt, | ||
158 | struct soc_pcmcia_regulator *r, int v); | ||
159 | |||
149 | #ifdef CONFIG_PCMCIA_DEBUG | 160 | #ifdef CONFIG_PCMCIA_DEBUG |
150 | 161 | ||
151 | extern void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, | 162 | extern void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func, |