Friday, April 26, 2013

Quick and Dirty userspace testing of regulator with virtual consumer

Writing a driver for a new regulator is usually fun, until you need to test the darned thing. Many of the users of the regulator is probably not yet ready in an development environment and need to test cant wait.
I had recently a similar situation and found CONFIG_REGULATOR_VIRTUAL_CONSUMER
You'd probably register and provide and regulator supply, but without a driver using it in a controlled environment (read shell script or so), it is hard to poke holes completely into your driver.

Steps are rather simple.
Assumption - you already have a regulator registered in the system and you are aware of the regulator name - You can also figure out it's name by the following (an example from 3.9-rc8 on Beagle-XM):
# head /sys/class/regulator/*/name
==> /sys/class/regulator/regulator.0/name <==
regulator-dummy
==> /sys/class/regulator/regulator.1/name <==
VDD1
==> /sys/class/regulator/regulator.2/name <==
VDAC
==> /sys/class/regulator/regulator.3/name <==
VPLL2
==> /sys/class/regulator/regulator.4/name <==
VMMC1
==> /sys/class/regulator/regulator.5/name <==
VUSB1V5
==> /sys/class/regulator/regulator.6/name <==
VUSB1V8
==> /sys/class/regulator/regulator.7/name <==
VUSB3V1
==> /sys/class/regulator/regulator.8/name <==
VSIM
Assume for the moment, we'd like to test VSIM. Fastest is often the simplest for testing needs. We introduce an dummy device which virtual-consumer picks up and exposes sysfs nodes- late init is usually an handy place to plug this dummy device injector ;)
char name[] = "VSIM";
struct platform_device_info devinfo = {
 .name = "reg-virt-consumer",
 .id = 0, /* if registering more than a single regulator, increment the ID */
 .data = name,
 .size_data = sizeof(name),
};
platform_device_register_full(&devinfo);

NOTE: do this for every "virtual consumer" you need to add for testing
Bingo, job done. Now you should be able to see the virtual consumer (the .0 matches to the id we give)
/ # ls -al /sys/devices/platform/reg-virt-consumer.0
total 0
drwxr-xr-x    3 root     root             0 Dec 31 20:30 .
drwxr-xr-x   17 root     root             0 Dec 31 20:30 ..
lrwxrwxrwx    1 root     root             0 Dec 31 23:15 driver -> ../../../bus/platform/drivers/reg-virt-consumer
-rw-rw-rw-    1 root     root          4096 Dec 31 23:15 max_microamps
-rw-rw-rw-    1 root     root          4096 Dec 31 20:30 max_microvolts
-rw-rw-rw-    1 root     root          4096 Dec 31 23:15 min_microamps
-rw-rw-rw-    1 root     root          4096 Dec 31 20:30 min_microvolts
-r--r--r--    1 root     root          4096 Dec 31 23:15 modalias
-rw-rw-rw-    1 root     root          4096 Dec 31 23:15 mode
drwxr-xr-x    2 root     root             0 Dec 31 23:15 power
lrwxrwxrwx    1 root     root             0 Dec 31 23:15 subsystem -> ../../../bus/platform
-rw-r--r--    1 root     root          4096 Dec 31 23:15 uevent
/ # 
Here is a quick test:
REG=/sys/class/regulator/regulator.8
CONS=/sys/devices/platform/reg-virt-consumer.0
for V in 1000000 1200000
do
 echo -n "$V">$CONS/min_microvolts
 echo -n "$V">$CONS/max_microvolts
 echo "Tried $V, Voltage =" `cat $REG/microvolts`
done
Now the homework: do this using device tree :)
More info: Documentation/ABI/testing/sysfs-class-regulator and https://www.kernel.org/doc/htmldocs/regulator.html - Happy hacking..
Caveats: posting upstream patches making this standard user-space control for regulators is usually frowned upon.