POD Drivers
Contents
Driver generation mechanism
POD is able to generate the drivers corresponding to the components present in the project and this for a given operating system. The source code of a driver and for a dedicated operating system is located in the drivers/ directory of the component
Note: Operating System represent here an entire system like a distribution, not only the kernel. We can have several linux drivers but in different OS-distribution |
The driver generation mechanism is a three step process:
- selection of the template source code depending on the targeted operating system. The template located in the drivers/ directory of a component is copied in the drivers/ directory of the project
- modification of the copied sources (done by POD)
- integration of the resulting code to the software tree (where the compilation will take place)
Source code selection
Once the project built, POD creates a drivers/ directory in the project directory. The driver files for the targeted OS are then copied to this directory.
Source code modification
The template source code has several special tags embeded in the comments. These tags help POD to specify and to modify the sources.
These tags are represented as following :
/*$tag$*/
If the tag foreach:list_of_somethings is written at the beginning of a line, POD will write one line for each element of the list.
- foreach:instance : written before a code bloc, must be ended by foreach:instance:end. Tags used with foreach:instance are:
- instance_name : name of the instance.
- instance_num : number of the instance
- registers_base_address:interface_name : Base address of the register in the interface connected to the processor bus.
- interrupt_number : indicates the number of interruptions connected to the irq manager.
- generic:generic_name : writes the value of a generic.
- register:interfacename:registername:attribute : writes the attribute value of one register
- number_of_instances : gives the number of instances of the same component in project.
- main_clock : gives the frequency of the main clock connected to the FPGA (in kHz).
All values are written in upper case.
For example, to generate a Linux UART driver with 2 UART instances, named UART1 and UART2, the code to be generated will looks like :
#define UART1_INPUT_CLOCK 96000000
#define UART2_INPUT_CLOCK 96000000
#define UART1_BASE 0x10
#define UART2_BASE 0x20
#define UART1_IRQ IRQ_FPGA(0)
#define UART2_IRQ IRQ_FPGA(1)
static struct plat_serial8250_port ocore_16550_data[] = {
PORT( APF9328_FPGA_VIRT+UART1_BASE, APF9328_FPGA_PHYS+UART1_BASE, UART1_INPUT_CLOCK, UART1_IRQ ),
PORT( APF9328_FPGA_VIRT+UART2_BASE, APF9328_FPGA_PHYS+UART2_BASE, UART2_INPUT_CLOCK, UART2_IRQ ),
{ },
};
static struct platform_device ocore_16550_device = {
.name = "serial8250", /* we use generic 8250/16550 Linux layer */
.id = PLAT8250_DEV_PLATFORM1,
.dev = {
.platform_data = ocore_16550_data,
},
};
Thus the following template has to be written :
/*$foreach:instance$*/
#define /*$instance_name$*/_INPUT_CLOCK /*$generic:clock_speed$*/
#define /*$instance_name$*/_BASE /*$register_base_address:swb16$*/
#define /*$instance_name$*/_IRQ IRQ_FPGA(/*$interrupt_number$*/)
/*$foreach:instance:end$*/
static struct plat_serial8250_port ocore_16550_data[] = {
/*$foreach:instance$*/
PORT( APF9328_FPGA_VIRT+/*$instance_name$*/_BASE,
APF9328_FPGA_PHYS+/*$instance_name$*/_BASE,
/*$instance_name$*/_INPUT_CLOCK,
/*$instance_name$*/_IRQ ),
/*$foreach:instance:end$*/
{ },
};
static struct platform_device ocore_16550_device = {
.name = "serial8250", /* we use generic 8250/16550 Linux layer */
.id = PLAT8250_DEV_PLATFORM1,
.dev = {
.platform_data = ocore_16550_data,
},
};
Driver integration
Once the source codes filled in, they can be copied in the software development tree. The destination for an Armadeus tree is the special directory POD/.