The regulators defined in the FDT typically have limits associated
with them. The diff below enforces those limits.
Enforcing the limits also happens when the regulator is registered.
As a consequence regulators will be properly initialized even when the
firmware (i.e. U-Boot) doesn't do that.
ok?
Index: dev/ofw/ofw_regulator.c
===================================================================
RCS file: /cvs/src/sys/dev/ofw/ofw_regulator.c,v
retrieving revision 1.2
diff -u -p -r1.2 ofw_regulator.c
--- dev/ofw/ofw_regulator.c 18 Nov 2017 13:48:50 -0000 1.2
+++ dev/ofw/ofw_regulator.c 16 Dec 2017 16:37:46 -0000
@@ -30,6 +30,18 @@ LIST_HEAD(, regulator_device) regulator_
void
regulator_register(struct regulator_device *rd)
{
+ rd->rd_min = OF_getpropint(rd->rd_node, "regulator-min-microvolt", 0);
+ rd->rd_max = OF_getpropint(rd->rd_node, "regulator-max-microvolt", ~0);
+ KASSERT(rd->rd_min <= rd->rd_max);
+
+ if (rd->rd_get_voltage && rd->rd_set_voltage) {
+ uint32_t voltage = rd->rd_get_voltage(rd->rd_cookie);
+ if (voltage < rd->rd_min)
+ rd->rd_set_voltage(rd->rd_cookie, rd->rd_min);
+ if (voltage > rd->rd_max)
+ rd->rd_set_voltage(rd->rd_cookie, rd->rd_max);
+ }
+
rd->rd_phandle = OF_getpropint(rd->rd_node, "phandle", 0);
if (rd->rd_phandle == 0)
return;
@@ -127,8 +139,12 @@ regulator_set_voltage(uint32_t phandle,
break;
}
+ /* Check limits. */
+ if (rd && (voltage < rd->rd_min || voltage > rd->rd_max))
+ return EINVAL;
+
if (rd && rd->rd_set_voltage)
return rd->rd_set_voltage(rd->rd_cookie, voltage);
- return -1;
+ return ENODEV;
}
Index: dev/ofw/ofw_regulator.h
===================================================================
RCS file: /cvs/src/sys/dev/ofw/ofw_regulator.h,v
retrieving revision 1.3
diff -u -p -r1.3 ofw_regulator.h
--- dev/ofw/ofw_regulator.h 18 Nov 2017 21:03:23 -0000 1.3
+++ dev/ofw/ofw_regulator.h 16 Dec 2017 16:37:46 -0000
@@ -24,6 +24,8 @@ struct regulator_device {
uint32_t (*rd_get_voltage)(void *);
int (*rd_set_voltage)(void *, uint32_t);
+ uint32_t rd_min, rd_max;
+
LIST_ENTRY(regulator_device) rd_list;
uint32_t rd_phandle;
};