Ramping up the voltage of a regulator takes time; the target voltage
is not reached instantaniously.  And typically you should not continue
until the target voltage has been reached.  For example, if we want to
increase the clock speed of a CPU, we typically also need to increase
the voltage.  And we shouldn't increase the clock speed until we've
reached the voltage that is needed to sustain that clock speed.
Otherwise bad things will happen.

The diff makes regulator_set_voltage() wait until the target voltage
should have been reached.  The code uses delay(9) since the we
typically only have to wait a couple of microseconds.  For now, this
only waits when ramping up since waiting generally isn't necessary if
we're ramping down.

ok?


Index: dev/ofw/ofw_regulator.c
===================================================================
RCS file: /cvs/src/sys/dev/ofw/ofw_regulator.c,v
retrieving revision 1.4
diff -u -p -r1.4 ofw_regulator.c
--- dev/ofw/ofw_regulator.c     18 Dec 2017 09:13:47 -0000      1.4
+++ dev/ofw/ofw_regulator.c     1 Aug 2018 15:56:27 -0000
@@ -34,6 +34,9 @@ regulator_register(struct regulator_devi
        rd->rd_max = OF_getpropint(rd->rd_node, "regulator-max-microvolt", ~0);
        KASSERT(rd->rd_min <= rd->rd_max);
 
+       rd->rd_ramp_delay =
+           OF_getpropint(rd->rd_node, "regulator-ramp-delay", 0);
+
        if (rd->rd_get_voltage && rd->rd_set_voltage) {
                uint32_t voltage = rd->rd_get_voltage(rd->rd_cookie);
                if (voltage < rd->rd_min)
@@ -153,6 +156,8 @@ int
 regulator_set_voltage(uint32_t phandle, uint32_t voltage)
 {
        struct regulator_device *rd;
+       uint32_t old, delta;
+       int error;
 
        LIST_FOREACH(rd, &regulator_devices, rd_list) {
                if (rd->rd_phandle == phandle)
@@ -163,8 +168,15 @@ regulator_set_voltage(uint32_t phandle, 
        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);
+       if (rd && rd->rd_set_voltage) {
+               old = rd->rd_get_voltage(rd->rd_cookie);
+               error = rd->rd_set_voltage(rd->rd_cookie, voltage);
+               if (voltage > old && rd->rd_ramp_delay > 0) {
+                       delta = voltage - old;
+                       delay(howmany(delta, rd->rd_ramp_delay));
+               }
+               return error;
+       }
 
        return ENODEV;
 }
Index: dev/ofw/ofw_regulator.h
===================================================================
RCS file: /cvs/src/sys/dev/ofw/ofw_regulator.h,v
retrieving revision 1.5
diff -u -p -r1.5 ofw_regulator.h
--- dev/ofw/ofw_regulator.h     18 Dec 2017 09:13:47 -0000      1.5
+++ dev/ofw/ofw_regulator.h     1 Aug 2018 15:56:27 -0000
@@ -26,6 +26,7 @@ struct regulator_device {
        int     (*rd_enable)(void *, int);
 
        uint32_t rd_min, rd_max;
+       uint32_t rd_ramp_delay;
 
        LIST_ENTRY(regulator_device) rd_list;
        uint32_t rd_phandle;

Reply via email to