Devicetree source files
The following section provides informations about how devicetree source files must be written to be compatible with the GAP_SDK.
Devicetree source files purpose is to specify informations about the hardware. In GAP_SDK, a hardware peripheral is represented as a pi_device_t object. A pi_device_t object has three members :
A data structure pointer. It contains the driver’s internal data.
A config structure pointer. It contains the driver configuration.
An api structure pointer. It contains the driver’s api.
The goal of the device tree is to provide for each required driver an instanciated pi_device_t object with its three pointers initialized. Added to this, it must initilize the members of the configuration structure.
Devicetree source file is made of nodes, each one contains one or multiple properties. Each pi_device_t object to create is described into one node. We call them device nodes
Device node
A device node aims to provide all data to create a pi_device_t object in the SDK. To be rightfully parsed and read by the SDK, a device node must repsect the following organization:
It must have a status property set to ok
It must have a sys subnode. It contains the system properties of the driver.
It must have a conf subnode. It contains the data that will be outputed in the configuration structure.
It may have a pads subnode. It contains definition of the pads required by the device.
It may have a defs subnode. It contains additionnal definition that may be useful.
Here is an example with the mx25u51245g device
node_label: node_name
{
status = "okay";
sys
{
// System properties
device_name = "";
driver_name = "";
device_type = "";
device_board = "";
device_driver = "";
device_instance = "";
device_data = "";
};
conf
{
// Configuration properties
};
pads
{
// Pads properties
};
defs
{
// Additional defines
};
};
mx25u51245g: mx25u51245g
{
status = "okay";
sys
{
// System properties
device_name = "mx25u51245g";
driver_name = "mx25u51245g";
device_type = "flash";
device_board = "gap9mod_v1_0_b";
device_driver = "bsp/flash/mx25u51245g.h";
device_instance = ""; // Not used here
device_data = ""; // Not used here
};
conf
{
// Configuration properties
spi_itf = <0>;
spi_cs = <0>;
size = <0x00800000>;
sector_size = <4096>;
xip_en = <0>;
baudrate = <0>;
};
pads
{
// Pads properties
ck = "GAP9_PADMUX(1, 0,-1)";
dq0 = "GAP9_PADMUX(2, 0,-1)";
dq1 = "GAP9_PADMUX(3, 0,-1)";
dq2 = "GAP9_PADMUX(4, 0,-1)";
dq3 = "GAP9_PADMUX(5, 0,-1)";
dq4 = "GAP9_PADMUX(6, 0,-1)";
dq5 = "GAP9_PADMUX(7, 0,-1)";
dq6 = "GAP9_PADMUX(8, 0,-1)";
dq7 = "GAP9_PADMUX(9, 0,-1)";
sn0 = "GAP9_PADMUX(10,0,-1)";
csn1 = "GAP9_PADMUX(11,0,-1)";
rwds = "GAP9_PADMUX(12,0,-1)";
};
defs
{
// None
}
};
Status property
This property is mandatory to specify to the parser that this node contains data to compute. Any node without this property set to “okay” will not be parsed.
Sys subnode
The sys subnode gather system properties such as :
driver_name: Driver name as it defined in the SDK.
device_name: The device name. Used to create unique instance names in case a board embedds the same hardware twice.
device_type: The device type. Used to identify default driver.
device_board: The board on which the driver is available
device_driver: The path to include its driver in the sdk
device_instance: Used to differenciate multiple instances of one driver. This is used to not involve all instance of one driver (like only UART1 instead of all UART devices)
device_data: Advanced mode. Used to let a driver handle its data structure by itself. Set this field to “NULL” to do so.
Conf subnode
The conf subnode gather data that will be stored in the device’s configuration structure. Property names must match members names in the configuration structure. For each property, a define will be outputed in the C header file with the following format :
#define DT_DRIVERNAME_PROPERTYNAME PROPERTYVALUE
Here is an example with the mx25u51245g flash driver
typedef struct pi_mx25u51245g_conf
{
struct pi_flash_conf flash;
int spi_itf;
int spi_cs;
int xip_en;
uint32_t size;
uint32_t baudrate;
uint16_t sector_size;
}pi_mx25u51245g_conf_t;
conf
{
spi_itf = <0>;
spi_cs = <0>;
size = <0x00800000>;
sector_size = <4096>;
xip_en = <0>;
baudrate = <20000000>;
};
// Header file
#define DT_MX25U51245G_BAUDRATE 20000000
#define DT_MX25U51245G_XIP_EN 0
#define DT_MX25U51245G_SECTOR_SIZE 4096
#define DT_MX25U51245G_SIZE 8388608
#define DT_MX25U51245G_SPI_CS 0
#define DT_MX25U51245G_SPI_ITF 0
// Source file
pi_mx25u51245g_conf_t mx25u51245g_conf = {
.baudrate = DT_MX25U51245G_BAUDRATE,
.xip_en = DT_MX25U51245G_XIP_EN,
.sector_size = DT_MX25U51245G_SECTOR_SIZE,
.size = DT_MX25U51245G_SIZE,
.spi_cs = DT_MX25U51245G_SPI_CS,
.spi_itf = DT_MX25U51245G_SPI_ITF,
};
Pads subnode
The pads subnode describe how to initialize the pads required by the hardware. A pad must be described with the following syntax :
GAP9_PADMUX(34, 1,-1)
Its arguments are:
1. Pad ID (34) Identification of the pad. It can be a pad known from the pi_pad_e enum type in the SDK.
2. Pad alternate function (1) Configuration of the pad’s alternate function. It can be a value from pi_pad_func_e enum type in the SDK. (0,1,2,3). As an example, setting this argument to ‘1’ will set the pad into GPIO mode at startup.
3. Pad Mux group configuration (-1) Pad reprogrammation feature. Configure a pad’s new function. Set this argument to the ID of the desired function. This id is defined by the pi_pad_mux_group_sel_e enum type from the SDK. Either the numerical value or the enum name can be put as an argument. When unused, this argument can be set to -1 or PI_PAD_MUX_GROUP_NONE (which is a new enum value created specially for devicetree purpose).
Warning
Reprogrammation feature is only available for the following pads: (34,35,40,41,42,43,44,45,60,61,62,63,67,68)
Warning
When using the reprogrammation feature, a pad must have its alternate function set to “0”
As an example, pads 44 and 45 are connected to the FTDI on the GAP9EVK board baudrate their alternate 0 function is by default set to I2C2 peripheral. To be able to discuss with the host via UART1 using this pads, you need to configure them as the following :
GAP9_PADMUX(44, 0, PI_PAD_MUX_GROUP_UART1_RX)
GAP9_PADMUX(45, 0, PI_PAD_MUX_GROUP_UART1_TX)
Note
PI_PAD_MUX_GROUP_UART1_RX is by default linked with pad 65. Normally, this pad also needs to be set to alternate 0 and its reprogrammmable feature needs to be set to another function to avoid any conflict. The devicetree parser is aware of such dependencies. It handles it automatically.
The parser collect all pads definition and output macros containing the pad registers value that configure them as described in the device tree.
Note
If a pad is set multiple times to different values, the parser will output an error.
Defs subnode
The defs subnode offers a way to create additionnal defines which are not meant to be stored into the configuration structure. They may refer to any specific driver implementation on a board. As an example, the audioaddon V1.1 board includes two AK4332 components sharing the same slave address. To be driven, a GPIO is set to 0 to drive one AK4332 and 1 to drive the other. Here is a way to define such data:
defs
{
slave_address = "(0x10)";
left_id = <0>;
right_id = <1>;
};
// Header file
#define DT_AK4332_SLAVE_ADDRESS (0x10)
#define DT_AK4332_LEFT_ID 0
#define DT_AK4332_RIGHT_ID 1
Using a node to configure pads only
Some situations may occur where we just want to specify how pads must be initialized like the JTAG interface. In this case, only the sys and pads subnodes are required into the device node
Here is an example of the GAP9EVK’s JTAG node :
jtag: jtag
{
status = "okay";
sys
{
device_name = "jtag";
driver_name = "jtag";
device_type = "io";
device_board = "gap9_evk_v1_3";
};
pads
{
tck = "GAP9_PADMUX(81,0,-1)";
tdi = "GAP9_PADMUX(82,0,-1)";
tdo = "GAP9_PADMUX(83,0,-1)";
tms = "GAP9_PADMUX(84,0,-1)";
trst = "GAP9_PADMUX(85,0,-1)";
};
};
#define PAD_JTAG_TRST PI_PAD_085
#define PAD_JTAG_TMS PI_PAD_084
#define PAD_JTAG_TDO PI_PAD_083
#define PAD_JTAG_TDI PI_PAD_082
#define PAD_JTAG_TCK PI_PAD_081
#define PADFUN5_INIT 0x55555001
The lack of conf subnode avoid to generate the pi_device_t instance and its members one.