Notes on DeviceTree

Found the basic info here: http://forum.pine64.org/showthread.php?tid=648.

/boot/pine64/*.dtb are device-tree Blobs. To convert from these to readable form and back there is the dtc tool, which can be found as part of kernel distributions, linux-pine64/scripts/dtc/dtc

As it is a standalone C program the executable can be copied to somewhere like /usr/local/bin.

However, since it also exists as a package in the debian system, it can be installed in the usual way with

apt install device-tree-compiler

This also installs a man-page for it, so man dtb will show useful info about the tool.

To convert the blob in dtfile.dtb into readable source: (input is dtb blob, output is dts source, put it into the file indicated by -o)

dtc -I dtb -O dts -o dtfile.dts dtfile.dtb

To convert the readable source dtfile.dts into the proper blob, similar to the above:

dtc -I dts -O dtb -o dtfile.dtb dtfile.dts

Now for understanding what-all is in the device-tree file! We see regulator 21 is the gpio0ldo that we were looking for earlier, when trying to find out how to turn it on for the twi0

2016-09-02

When i looked at the early output on the serial line of a pine64 starting up, I see the states of the various power-supply channels show up as being turned on or off, and with various voltages.

The last one, gpio0, seems to match the name of the driving voltage for the TP port, where the VCC-CTP output voltage does not appear to have been turned on. Could there be something useful here?

So when looking for the names such as dcdc1_vol and eldo1_vol, i find a section power_sply in the in the cleartext dts-file (sun50i-a64-pine64-plus.dts, converted from the sun50i-a64-pine64-plus.dtb) where these names appear.

The ones that are turned off have only the hex value shown as _vol, voltage

The last one is called gpio0_vol and it has value <0xc1c> which translates to the value 3100 shown in the boot output. These values appear to be millivolts, several of the others are shown as 1800 and 3300, so this means the setting here should be 3.1 V when turned on.

Now the values for the ones that are turned on are shown with the high bits 0xf4 on their values. But the low bits don't quite seem to match or do they? The first one, dcdc1_vol for example it is on and has 3300 millivolts set, but 0xf24 = 3876? However, 0xf4f24 = 1003300, so turning on appears to be done by adding a decimal million to the number. (which clearly won't translate to kilovolts...)

Boot message text: Line in block power_sply in the .dts file: Decimal value
device_type = 3253, onoff=1 device_type = "power_sply";?
dcdc1_vol = 3300, onoff=1 dcdc1_vol = <0xf4f24>;1003300
dcdc2_vol = 1100, onoff=1 dcdc2_vol = <0xf468c>;1001100
dcdc6_vol = 1100, onoff=1 dcdc6_vol = <0xf468c>;1001100
aldo1_vol = 2800, onoff=0 aldo1_vol = <0xaf0>;2800
aldo2_vol = 1800, onoff=1 aldo2_vol = <0xf4948>;1001800
aldo3_vol = 3000, onoff=1 aldo3_vol = <0xf4df8>;1003000
dldo1_vol = 3300, onoff=0 dldo1_vol = <0xce4>;3300
dldo2_vol = 3300, onoff=0 dldo2_vol = <0xce4>;3300
dldo3_vol = 2800, onoff=0 dldo3_vol = <0xaf0>;2800
dldo4_vol = 3300, onoff=1 dldo4_vol = <0xf4f24>;1003300
eldo1_vol = 1800, onoff=1 eldo1_vol = <0xf4948>;1001800
eldo2_vol = 1800, onoff=0 eldo2_vol = <0x708>;1800
eldo3_vol = 1800, onoff=0 eldo3_vol = <0x708>;1800
fldo1_vol = 1200, onoff=0 fldo1_vol = <0x4b0>;1200
fldo2_vol = 1100, onoff=1 fldo2_vol = <0xf468c>;1001100
gpio0_vol = 3100, onoff=0 gpio0_vol = <0xc1c>;3100

Now, what if we change the value for gpio0_vol to 1003100 = 0xf4e5c?

No that didn't work...

This info and the corresponding device-tree info appears to be the description of state-info having been setup in the earlier bootup process.

2016-12-17

There is a useful overview of the various regulator channels in /sys/class/regulator/dump

Recap: sysfs reference to this power supply channel of interest:

/sys/devices/platform/axp81x_board/axp-regulator.30/regulator/regulator.21/name
/sys/devices/platform/axp81x_board/axp-regulator.30/regulator/regulator.21/state

There was a forum post about a driver for the Touchpad, and looking at the initialization source for that, there is a number of calls to kernel functions named things like: regulator_get(), regulator_set_voltage(), and so on. There is a large set of these functions, as evidenced by man -k regulator (when having the section 9 kernel functions documentation installed).

#include <linux/regulator/consumer.h>

Seems that we can turn these regulators on and off via these functions, notably, regulator_get() to acces a regulator, then regulator_enable(), regulator_disable(), regulator_get_voltage() to see the set output voltage. Initial attempts at the reading functions indicate that the names of the regulators are the ones found in the file name in the sysfs locations above. Thus the name of interest here is "axp81x_gpio0ldo".

Time to go find the soldering iron!

And indeed, connecting a pcf8574 and a ds1621 here, then once power is turned on, we see that it is working, both units appear in the i2cdetect -y 0 listing, and they work as expected.

To Pine 64+ main page

Proc fs

There is a lot of informative stuff in the /proc/device-tree hierarchy, where the structure of the .dtb file shows as a set of directories and files, with recognizeable names.

Correlating this with the Allwinner_A64_User_Manual_V1.0.pdf, we can see how various devices are present, disabled, and so on. There is the soc@01c00000 and under this we see various devices such as twi@0x01c2ac00, twi@0x01c2b000, and twi@0x01c2b400, whose identifiers correspond to the register addresses on page 538 in that manual. Now this exist on PE15/PE14, as function #3 (011) for these two wires. PE15 and PE14 are not readily available.

Similarly, there is the pinctrl@01f02c00 which maps the set of PL ports. including subsections for s_cir (IR receiver), spwm, s_uart0, s_rsb0 and s_jtag0 pin allocations.

What might be more interesting is to see how to allocate and prep the R_TWI 0x01F02400. which sits as a possibility behind gpio-361 PL9 (SDA) and gpio-360 PL8 (SCL). Like the s_uart, there has to be the pin allocations defined in the pinctrl@01f02c00 section along with the others there, then the device as a sibling to the s_uart@1f02800 in the soc section. And also perhaps another entry in the aliases list.

All this will also require that there is code to enumerate, find and configure the device in the kernel somewhere. Typical uses seen all over the place, is calling of_get_property() to read some setting out of some place in the device tree.

#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>

const char *xstring;
struct device_node *np;
np = of_find_node_by_type(NULL, "cpu");
if(!np) return(0);
xstring = of_get_property(np, "compatible", NULL);

the np->name can also be of interest in the above.

Some interesting examples of this can be seen in the file /drivers/tty/serial/sunxi-uart.c

These functions all starting with of_ are defined in the files in /drivers/of

Here we see it starts out by looking at the aliases, of_alias_get_id(), where it wants something with a name beginning with "serial", then starts working on that.

Looking at /drivers/i2c/busses/i2c-sunxi.h we see the address registers defined as per manual section 7.1.5 pages 538 and following. Aliases are supposed to be twi# for these.

So we can make another alias, twi3, of the R_TWI with the correct settings and it might be made to work? Similar can be tried with the S_UART, on the Wifi pins? (TX=W9=PL2, Rx=W11=PL3, Gnd=W12) naming this as alias serial5.


Powered by Apache

Valid XHTML 1.0!