diff options
author | Jonas Aaberg <jonas.aberg@stericsson.com> | 2010-10-26 11:33:23 +0200 |
---|---|---|
committer | Robert Marklund <robert.marklund@stericsson.com> | 2011-10-05 13:00:47 +0200 |
commit | 43f089edfa32815718084d2a2d6ecb19c5b0d1ac (patch) | |
tree | 11ba4fcfdc184fc5049f43c86e7d0da384e2cb2d | |
parent | 8311bfaf0698d43b2c091881b518558f8be57303 (diff) |
regulator: dbx500-prcmu: add support for special regulators
The DMA driver needs to be able to enable/disable its regulator
in atomic context, which is not supported by the regulator framework.
This patch adds an interface for such special cases.
Change-Id: I3e6efab1cb2be47cdcea18bf1038ee8be54a4bea
Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com>
Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32109
-rw-r--r-- | drivers/regulator/dbx500-prcmu.c | 85 | ||||
-rw-r--r-- | include/linux/mfd/dbx500-prcmu.h | 75 |
2 files changed, 160 insertions, 0 deletions
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c index 409cb8574fe..3bc6e0e5189 100644 --- a/drivers/regulator/dbx500-prcmu.c +++ b/drivers/regulator/dbx500-prcmu.c @@ -60,3 +60,88 @@ struct ux500_regulator { void (*enable)(void); int (*disable)(void); }; +static struct ux500_regulator ux500_atomic_regulators[] = { + { + .name = "dma40.0", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, + { + .name = "ssp0", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, + { + .name = "ssp1", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, + { + .name = "spi0", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, + { + .name = "spi1", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, + { + .name = "spi2", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, + { + .name = "spi3", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, + { + .name = "cryp1", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, + { + .name = "hash1", + .enable = power_state_active_enable, + .disable = power_state_active_disable, + }, +}; + +struct ux500_regulator *__must_check ux500_regulator_get(struct device *dev) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ux500_atomic_regulators); i++) { + if (!strcmp(dev_name(dev), ux500_atomic_regulators[i].name)) + return &ux500_atomic_regulators[i]; + } + + return ERR_PTR(-EINVAL); +} +EXPORT_SYMBOL_GPL(ux500_regulator_get); + +int ux500_regulator_atomic_enable(struct ux500_regulator *regulator) +{ + if (regulator) { + regulator->enable(); + return 0; + } + return -EINVAL; +} +EXPORT_SYMBOL_GPL(ux500_regulator_atomic_enable); + +int ux500_regulator_atomic_disable(struct ux500_regulator *regulator) +{ + if (regulator) + return regulator->disable(); + else + return -EINVAL; +} +EXPORT_SYMBOL_GPL(ux500_regulator_atomic_disable); + +void ux500_regulator_put(struct ux500_regulator *regulator) +{ + /* Here for symetric reasons and for possible future use */ +} +EXPORT_SYMBOL_GPL(ux500_regulator_put); diff --git a/include/linux/mfd/dbx500-prcmu.h b/include/linux/mfd/dbx500-prcmu.h index 7da5694f8ca..072a4c70059 100644 --- a/include/linux/mfd/dbx500-prcmu.h +++ b/include/linux/mfd/dbx500-prcmu.h @@ -10,6 +10,7 @@ #include <linux/interrupt.h> #include <linux/notifier.h> +#include <linux/err.h> #include <asm/mach-types.h> /* PRCMU Wakeup defines */ @@ -549,4 +550,78 @@ static inline int prcmu_qos_remove_notifier(int prcmu_qos_class, #endif +struct ux500_regulator; + +#ifdef CONFIG_REGULATOR +/* + * NOTE! The device will be connected to the correct regulator by this + * new framework. A list with connections will match up dev_name(dev) + * to the specific regulator. This follows the same principle as the + * normal regulator framework. + * + * This framework shall only be used in special cases when a regulator + * has to be enabled/disabled in atomic context. + */ + +/** + * ux500_regulator_get() + * + * @dev: Drivers device struct + * + * Returns a ux500_regulator struct. Shall be used as argument for + * ux500_regulator_atomic_enable/disable calls. + * Return ERR_PTR(-EINVAL) upon no matching regulator found. + */ +struct ux500_regulator *__must_check ux500_regulator_get(struct device *dev); + +/** + * ux500_regulator_atomic_enable() + * + * @regulator: Regulator handle, provided from ux500_regulator_get. + * + * The enable/disable functions keep an internal counter, so every + * enable must be paired with an disable in order to turn off regulator. + */ +int ux500_regulator_atomic_enable(struct ux500_regulator *regulator); + +/** + * ux500_regulator_atomic_disable() + * + * @regulator: Regulator handle, provided from ux500_regulator_get. + * + */ +int ux500_regulator_atomic_disable(struct ux500_regulator *regulator); + +/** + * ux500_regulator_put() + * + * @regulator: Regulator handle, provided from ux500_regulator_get. + */ +void ux500_regulator_put(struct ux500_regulator *regulator); + +#else + +static inline struct ux500_regulator *__must_check +ux500_regulator_get(struct device *dev) +{ + return ERR_PTR(-EINVAL); +} + +static inline int +ux500_regulator_atomic_enable(struct ux500_regulator *regulator) +{ + return -EINVAL; +} + +static inline int +ux500_regulator_atomic_disable(struct ux500_regulator *regulator) +{ + return -EINVAL; +} + +static inline void ux500_regulator_put(struct ux500_regulator *regulator) +{ +} +#endif /* CONFIG_REGULATOR */ + #endif /* __MACH_PRCMU_H */ |