aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTuomas Tynkkynen <ttynkkynen@nvidia.com>2014-07-21 11:38:48 -0400
committerMark Brown <broonie@linaro.org>2014-07-25 13:43:48 -0400
commit04eca28cde52cdf9eb91e127cc358ad79a8ec53b (patch)
treecb4507f5e7f2430325312c86332fbe3ce887879b
parent7171511eaec5bf23fb06078f59784a3a0626b38f (diff)
regulator: Add helpers for low-level register access
Add helper functions that allow regulator consumers to obtain low-level details about the regulator hardware, like the voltage selector register address and such. These details can be useful when configuring hardware or firmware that want to do low-level access to regulators, with no involvement from the kernel. The use-case for Tegra is a voltage-controlled oscillator clocksource which has control logic to change the supply voltage via I2C to achieve a desired output clock rate. Signed-off-by: Tuomas Tynkkynen <ttynkkynen@nvidia.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/power/regulator/consumer.txt35
-rw-r--r--drivers/regulator/core.c71
-rw-r--r--include/linux/regulator/consumer.h26
3 files changed, 132 insertions, 0 deletions
diff --git a/Documentation/power/regulator/consumer.txt b/Documentation/power/regulator/consumer.txt
index 55c4175d8099..81c0e2b49cd8 100644
--- a/Documentation/power/regulator/consumer.txt
+++ b/Documentation/power/regulator/consumer.txt
@@ -180,3 +180,38 @@ int regulator_unregister_notifier(struct regulator *regulator,
180 180
181Regulators use the kernel notifier framework to send event to their interested 181Regulators use the kernel notifier framework to send event to their interested
182consumers. 182consumers.
183
1847. Regulator Direct Register Access
185===================================
186Some kinds of power management hardware or firmware are designed such that
187they need to do low-level hardware access to regulators, with no involvement
188from the kernel. Examples of such devices are:
189
190- clocksource with a voltage-controlled oscillator and control logic to change
191 the supply voltage over I2C to achieve a desired output clock rate
192- thermal management firmware that can issue an arbitrary I2C transaction to
193 perform system poweroff during overtemperature conditions
194
195To set up such a device/firmware, various parameters like I2C address of the
196regulator, addresses of various regulator registers etc. need to be configured
197to it. The regulator framework provides the following helpers for querying
198these details.
199
200Bus-specific details, like I2C addresses or transfer rates are handled by the
201regmap framework. To get the regulator's regmap (if supported), use :-
202
203struct regmap *regulator_get_regmap(struct regulator *regulator);
204
205To obtain the hardware register offset and bitmask for the regulator's voltage
206selector register, use :-
207
208int regulator_get_hardware_vsel_register(struct regulator *regulator,
209 unsigned *vsel_reg,
210 unsigned *vsel_mask);
211
212To convert a regulator framework voltage selector code (used by
213regulator_list_voltage) to a hardware-specific voltage selector that can be
214directly written to the voltage selector register, use :-
215
216int regulator_list_hardware_vsel(struct regulator *regulator,
217 unsigned selector);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 4c1f999041dd..486b5908469e 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2222,6 +2222,77 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector)
2222EXPORT_SYMBOL_GPL(regulator_list_voltage); 2222EXPORT_SYMBOL_GPL(regulator_list_voltage);
2223 2223
2224/** 2224/**
2225 * regulator_get_regmap - get the regulator's register map
2226 * @regulator: regulator source
2227 *
2228 * Returns the register map for the given regulator, or an ERR_PTR value
2229 * if the regulator doesn't use regmap.
2230 */
2231struct regmap *regulator_get_regmap(struct regulator *regulator)
2232{
2233 struct regmap *map = regulator->rdev->regmap;
2234
2235 return map ? map : ERR_PTR(-EOPNOTSUPP);
2236}
2237
2238/**
2239 * regulator_get_hardware_vsel_register - get the HW voltage selector register
2240 * @regulator: regulator source
2241 * @vsel_reg: voltage selector register, output parameter
2242 * @vsel_mask: mask for voltage selector bitfield, output parameter
2243 *
2244 * Returns the hardware register offset and bitmask used for setting the
2245 * regulator voltage. This might be useful when configuring voltage-scaling
2246 * hardware or firmware that can make I2C requests behind the kernel's back,
2247 * for example.
2248 *
2249 * On success, the output parameters @vsel_reg and @vsel_mask are filled in
2250 * and 0 is returned, otherwise a negative errno is returned.
2251 */
2252int regulator_get_hardware_vsel_register(struct regulator *regulator,
2253 unsigned *vsel_reg,
2254 unsigned *vsel_mask)
2255{
2256 struct regulator_dev *rdev = regulator->rdev;
2257 struct regulator_ops *ops = rdev->desc->ops;
2258
2259 if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
2260 return -EOPNOTSUPP;
2261
2262 *vsel_reg = rdev->desc->vsel_reg;
2263 *vsel_mask = rdev->desc->vsel_mask;
2264
2265 return 0;
2266}
2267EXPORT_SYMBOL_GPL(regulator_get_hardware_vsel_register);
2268
2269/**
2270 * regulator_list_hardware_vsel - get the HW-specific register value for a selector
2271 * @regulator: regulator source
2272 * @selector: identify voltage to list
2273 *
2274 * Converts the selector to a hardware-specific voltage selector that can be
2275 * directly written to the regulator registers. The address of the voltage
2276 * register can be determined by calling @regulator_get_hardware_vsel_register.
2277 *
2278 * On error a negative errno is returned.
2279 */
2280int regulator_list_hardware_vsel(struct regulator *regulator,
2281 unsigned selector)
2282{
2283 struct regulator_dev *rdev = regulator->rdev;
2284 struct regulator_ops *ops = rdev->desc->ops;
2285
2286 if (selector >= rdev->desc->n_voltages)
2287 return -EINVAL;
2288 if (ops->set_voltage_sel != regulator_set_voltage_sel_regmap)
2289 return -EOPNOTSUPP;
2290
2291 return selector;
2292}
2293EXPORT_SYMBOL_GPL(regulator_list_hardware_vsel);
2294
2295/**
2225 * regulator_get_linear_step - return the voltage step size between VSEL values 2296 * regulator_get_linear_step - return the voltage step size between VSEL values
2226 * @regulator: regulator source 2297 * @regulator: regulator source
2227 * 2298 *
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index a2d9d81038d1..0b1c8d09a6b1 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -37,6 +37,7 @@
37 37
38struct device; 38struct device;
39struct notifier_block; 39struct notifier_block;
40struct regmap;
40 41
41/* 42/*
42 * Regulator operating modes. 43 * Regulator operating modes.
@@ -215,6 +216,13 @@ int regulator_set_optimum_mode(struct regulator *regulator, int load_uA);
215 216
216int regulator_allow_bypass(struct regulator *regulator, bool allow); 217int regulator_allow_bypass(struct regulator *regulator, bool allow);
217 218
219struct regmap *regulator_get_regmap(struct regulator *regulator);
220int regulator_get_hardware_vsel_register(struct regulator *regulator,
221 unsigned *vsel_reg,
222 unsigned *vsel_mask);
223int regulator_list_hardware_vsel(struct regulator *regulator,
224 unsigned selector);
225
218/* regulator notifier block */ 226/* regulator notifier block */
219int regulator_register_notifier(struct regulator *regulator, 227int regulator_register_notifier(struct regulator *regulator,
220 struct notifier_block *nb); 228 struct notifier_block *nb);
@@ -452,6 +460,24 @@ static inline int regulator_allow_bypass(struct regulator *regulator,
452 return 0; 460 return 0;
453} 461}
454 462
463struct regmap *regulator_get_regmap(struct regulator *regulator)
464{
465 return ERR_PTR(-EOPNOTSUPP);
466}
467
468int regulator_get_hardware_vsel_register(struct regulator *regulator,
469 unsigned *vsel_reg,
470 unsigned *vsel_mask)
471{
472 return -EOPNOTSUPP;
473}
474
475int regulator_list_hardware_vsel(struct regulator *regulator,
476 unsigned selector)
477{
478 return -EOPNOTSUPP;
479}
480
455static inline int regulator_register_notifier(struct regulator *regulator, 481static inline int regulator_register_notifier(struct regulator *regulator,
456 struct notifier_block *nb) 482 struct notifier_block *nb)
457{ 483{