aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/extres
diff options
context:
space:
mode:
authorMichal Meloun <mmel@FreeBSD.org>2016-10-18 12:27:46 +0000
committerMichal Meloun <mmel@FreeBSD.org>2016-10-18 12:27:46 +0000
commitfd02931841e4060fb56ac4f69ed92e2c4f7b0083 (patch)
treedbff4725f59e8fab01aaaa8ca9338adc76f8cef2 /sys/dev/extres
parent4d517b66a0a097169d9045a9f064b2a58776d4aa (diff)
downloadsrc-fd02931841e4060fb56ac4f69ed92e2c4f7b0083.tar.gz
src-fd02931841e4060fb56ac4f69ed92e2c4f7b0083.zip
REGULATOR: Move functions for handling with regulator ranges to
common file. They can be useful for other PMICs. MFC after: 2 weeks
Notes
Notes: svn path=/head/; revision=307558
Diffstat (limited to 'sys/dev/extres')
-rw-r--r--sys/dev/extres/regulator/regulator.c86
-rw-r--r--sys/dev/extres/regulator/regulator.h19
2 files changed, 105 insertions, 0 deletions
diff --git a/sys/dev/extres/regulator/regulator.c b/sys/dev/extres/regulator/regulator.c
index 729de6b69b10..10307b135dea 100644
--- a/sys/dev/extres/regulator/regulator.c
+++ b/sys/dev/extres/regulator/regulator.c
@@ -53,6 +53,8 @@ __FBSDID("$FreeBSD$");
MALLOC_DEFINE(M_REGULATOR, "regulator", "Regulator framework");
+#define DIV_ROUND_UP(n,d) howmany(n, d)
+
/* Forward declarations. */
struct regulator;
struct regnode;
@@ -984,3 +986,87 @@ regulator_get_by_ofw_property(device_t cdev, phandle_t cnode, char *name,
return (regulator_get_by_id(cdev, regdev, id, reg));
}
#endif
+
+/* --------------------------------------------------------------------------
+ *
+ * Regulator utility functions.
+ *
+ */
+
+/* Convert raw selector value to real voltage */
+int
+regulator_range_sel8_to_volt(struct regulator_range *ranges, int nranges,
+ uint8_t sel, int *volt)
+{
+ struct regulator_range *range;
+ int i;
+
+ if (nranges == 0)
+ panic("Voltage regulator have zero ranges\n");
+
+ for (i = 0; i < nranges ; i++) {
+ range = ranges + i;
+
+ if (!(sel >= range->min_sel &&
+ sel <= range->max_sel))
+ continue;
+
+ sel -= range->min_sel;
+
+ *volt = range->min_uvolt + sel * range->step_uvolt;
+ return (0);
+ }
+
+ return (ERANGE);
+}
+
+int
+regulator_range_volt_to_sel8(struct regulator_range *ranges, int nranges,
+ int min_uvolt, int max_uvolt, uint8_t *out_sel)
+{
+ struct regulator_range *range;
+ uint8_t sel;
+ int uvolt;
+ int rv, i;
+
+ if (nranges == 0)
+ panic("Voltage regulator have zero ranges\n");
+
+ for (i = 0; i < nranges; i++) {
+ range = ranges + i;
+ uvolt = range->min_uvolt +
+ (range->max_sel - range->min_sel) * range->step_uvolt;
+
+ if ((min_uvolt > uvolt) ||
+ (max_uvolt < range->min_uvolt))
+ continue;
+
+ if (min_uvolt <= range->min_uvolt)
+ min_uvolt = range->min_uvolt;
+
+ /* if step == 0 -> fixed voltage range. */
+ if (range->step_uvolt == 0)
+ sel = 0;
+ else
+ sel = DIV_ROUND_UP(min_uvolt - range->min_uvolt,
+ range->step_uvolt);
+
+
+ sel += range->min_sel;
+
+ break;
+ }
+
+ if (i >= nranges)
+ return (ERANGE);
+
+ /* Verify new settings. */
+ rv = regulator_range_sel8_to_volt(ranges, nranges, sel, &uvolt);
+ if (rv != 0)
+ return (rv);
+ if ((uvolt < min_uvolt) || (uvolt > max_uvolt))
+ return (ERANGE);
+
+ *out_sel = sel;
+ return (0);
+}
diff --git a/sys/dev/extres/regulator/regulator.h b/sys/dev/extres/regulator/regulator.h
index e509a7e74349..75d673d37c00 100644
--- a/sys/dev/extres/regulator/regulator.h
+++ b/sys/dev/extres/regulator/regulator.h
@@ -67,9 +67,22 @@ struct regnode_init_def {
#ifdef FDT
phandle_t ofw_node; /* OFW node of regulator */
#endif
+};
+struct regulator_range {
+ int min_uvolt;
+ int step_uvolt;
+ uint8_t min_sel;
+ uint8_t max_sel;
};
+#define REG_RANGE_INIT(_min_sel, _max_sel, _min_uvolt, _step_uvolt) { \
+ .min_sel = _min_sel, \
+ .max_sel = _max_sel, \
+ .min_uvolt = _min_uvolt, \
+ .step_uvolt = _step_uvolt, \
+}
+
/*
* Shorthands for constructing method tables.
*/
@@ -125,4 +138,10 @@ int regulator_parse_ofw_stdparam(device_t dev, phandle_t node,
struct regnode_init_def *def);
#endif
+/* Utility functions */
+int regulator_range_volt_to_sel8(struct regulator_range *ranges, int nranges,
+ int min_uvolt, int max_uvolt, uint8_t *out_sel);
+int regulator_range_sel8_to_volt(struct regulator_range *ranges, int nranges,
+ uint8_t sel, int *volt);
+
#endif /* _DEV_EXTRES_REGULATOR_H_ */