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>
This commit is contained in:
parent
a1d0500261
commit
ac61b6001a
|
@ -43,6 +43,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/timer.h>
|
||||
|
||||
|
@ -80,6 +81,41 @@ EXPORT_SYMBOL(soc_pcmcia_debug);
|
|||
#define to_soc_pcmcia_socket(x) \
|
||||
container_of(x, struct soc_pcmcia_socket, socket)
|
||||
|
||||
int soc_pcmcia_regulator_set(struct soc_pcmcia_socket *skt,
|
||||
struct soc_pcmcia_regulator *r, int v)
|
||||
{
|
||||
bool on;
|
||||
int ret;
|
||||
|
||||
if (!r->reg)
|
||||
return 0;
|
||||
|
||||
on = v != 0;
|
||||
if (r->on == on)
|
||||
return 0;
|
||||
|
||||
if (on) {
|
||||
ret = regulator_set_voltage(r->reg, v * 100000, v * 100000);
|
||||
if (ret) {
|
||||
int vout = regulator_get_voltage(r->reg) / 100000;
|
||||
|
||||
dev_warn(&skt->socket.dev,
|
||||
"CS requested %s=%u.%uV, applying %u.%uV\n",
|
||||
r == &skt->vcc ? "Vcc" : "Vpp",
|
||||
v / 10, v % 10, vout / 10, vout % 10);
|
||||
}
|
||||
|
||||
ret = regulator_enable(r->reg);
|
||||
} else {
|
||||
regulator_disable(r->reg);
|
||||
}
|
||||
if (ret == 0)
|
||||
r->on = on;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(soc_pcmcia_regulator_set);
|
||||
|
||||
static unsigned short
|
||||
calc_speed(unsigned short *spds, int num, unsigned short dflt)
|
||||
{
|
||||
|
@ -119,7 +155,6 @@ static void __soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt,
|
|||
if (skt->ops->hw_shutdown)
|
||||
skt->ops->hw_shutdown(skt);
|
||||
|
||||
|
||||
clk_disable_unprepare(skt->clk);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,12 @@
|
|||
struct device;
|
||||
struct gpio_desc;
|
||||
struct pcmcia_low_level;
|
||||
struct regulator;
|
||||
|
||||
struct soc_pcmcia_regulator {
|
||||
struct regulator *reg;
|
||||
bool on;
|
||||
};
|
||||
|
||||
/*
|
||||
* This structure encapsulates per-socket state which we might need to
|
||||
|
@ -64,6 +70,8 @@ struct soc_pcmcia_socket {
|
|||
|
||||
struct gpio_desc *gpio_reset;
|
||||
struct gpio_desc *gpio_bus_enable;
|
||||
struct soc_pcmcia_regulator vcc;
|
||||
struct soc_pcmcia_regulator vpp;
|
||||
|
||||
unsigned int irq_state;
|
||||
|
||||
|
@ -146,6 +154,9 @@ int soc_pcmcia_request_gpiods(struct soc_pcmcia_socket *skt);
|
|||
void soc_common_cf_socket_state(struct soc_pcmcia_socket *skt,
|
||||
struct pcmcia_state *state);
|
||||
|
||||
int soc_pcmcia_regulator_set(struct soc_pcmcia_socket *skt,
|
||||
struct soc_pcmcia_regulator *r, int v);
|
||||
|
||||
#ifdef CONFIG_PCMCIA_DEBUG
|
||||
|
||||
extern void soc_pcmcia_debug(struct soc_pcmcia_socket *skt, const char *func,
|
||||
|
|
Loading…
Reference in New Issue