+ All Categories
Home > Engineering > Arm device tree and linux device drivers

Arm device tree and linux device drivers

Date post: 22-May-2015
Category:
Upload: houcheng-lin
View: 2,990 times
Download: 7 times
Share this document with a friend
Description:
A brief talk on arm device tree and how kernel loading the corresponding hardware drivers
Popular Tags:
19
Arm device tree and device driver initialization Houcheng Lin CCMA, ITRI
Transcript
Page 1: Arm device tree and linux device drivers

Arm device tree and device driver initialization

Houcheng Lin

CCMA, ITRI

Page 2: Arm device tree and linux device drivers

Agenda

• Problem: one kernel source to support all arm boards

• Boot with device tree binary

• Device tree syntax

• Machine init code

• Device init code

• x86 platform (one kernel binary support almost all boards)

Page 3: Arm device tree and linux device drivers

Problem:One kernel source to support all arm boards

OS kernel

memory,mmu

timer Block device

netdevice

CPU,cache

Hardware HAL

hardware board

Kernelsource

build

select board

Page 4: Arm device tree and linux device drivers

Kernel startup code have to initialize these hardware

• Startup code initialize following hardware– CPU, cache, MMU (usually comes with feature reg)

– exception table, GDT, then perform mode switching and enable MMU

– Interrupt controller, bridge chip

– timers, RTC, flash

– IO, block, network and optional devices

• Its purpose is kernel want to use them to– enable some kernel feature

– convert into usable kernel resources

arch

machine

board

Page 5: Arm device tree and linux device drivers

One kernel source support all boards, a solution

• Horizontal and vertical divide these code– arch specific include and source– machine specific include and source– board specific include and source

• Pick one board– Header and Makefile links defines

and objects– One board header file that links

arch/ machine specific headers– One board Makefile that links arch/

machine specific sources’ objects

• Kernel config file– Generate header file and Makefile

include for needed kernel feature or drivers

arm

exynos tegra

ve eb aa bb

Page 6: Arm device tree and linux device drivers

An example

#include <arm.h>#include <enynos.h>

#define UART0 0x00100c#define TIMER0 0x00200c#define UART_INT 23#define UART_INT 8

board header file

ARCH := armMACH := vexpress

ARCH_LIB := (ARCH)_lib.aMACH_OBJ = (MACH)_lib.aBOARD_OBJ := vexpress.ortos.elf:

$(LD) $(LDFLAGS) $(KERNEL_OBJ) \$(ARCH_LIB) $(MACH_OBJ) $(BOARD_OBJ)

board Makefile

arch/arm/*.c *.h Makefilearch/arm/machine/<machine-name>/*.c *.h Makefilearch/arm/board/<board-name>/*.c *.h Makefile

Source directory

Page 7: Arm device tree and linux device drivers

Linux arm community’s initial work

• As hardware more powerful and support MMU, Linux add support to arm

• Linux ARM community starts to write codes and use this approach to support all arm boards

• Some problem when lots of arm boards’ code committed into kenrel:– huge number of #defines in headers– code is hard to maintain

• redundant code• stepping on each others toes (guys uses different names)• merge conflicts

Page 8: Arm device tree and linux device drivers

Linus comment on 2001

I don't know who to "blame". I don't care. It really doesn't matter. you guys need to push back on the people sending you crap

Gaah. Guys, this whole ARM thing is a f*cking pain in the ass

steping on others toesThat usb_musb_init() thing in arch/arm/mach-omap2/usb-musb.calso seems to be totally insane.

Note: the layered and division approach can’t not handle various arm hardware and corresponding, existing sources

stop the crazy renaming already!

crap

ARM vendors do crazy shit

Page 9: Arm device tree and linux device drivers

ARM device tree

• Device tree is a data structure for describing hardware• It extract board level detail from kernel source code to

device tree script (dts)• Each board has one dts file• Benefit

– moved hardware relevant #defines to dts– keep driver or init code one one copied; describe

variations in dts file. EX: memory mapped address, interrupt number, active-low, output pin number, peferedphy interface, etc

– Now, single kernel binary can support multiple similar boards

Page 10: Arm device tree and linux device drivers

Example DTS:vexpress-v2p-ca15.dts

/ {model = "V2P-CA15";arm,hbi = <0x237>;arm,vexpress,site = <0xf>;compatible = "arm,vexpress,v2p-ca15,tc1",

"arm,vexpress,v2p-ca15", "arm,vexpress";

cpu { … }memory { …. }timer {

compatible = "arm,armv7-timer";interrupts = <1 13 0xf08>,

<1 14 0xf08>,<1 11 0xf08>,<1 10 0xf08>;

}…../include/ "vexpress-v2m-rs1.dtsi"

};

vexpress-v2p-ca15-tc1.dts

motherboard {model = "V2P-P1";arm,hbi = <0x237>;arm,vexpress,site = <0xf>;compatible = "arm,vexpress,v2m-p1“,

"simple-bus";#address-cells = <2>; /* SMB chip-select number and offset */flash@2,0000 { …. };ethernet@3,02000 {

compatible = "smsc,lan9118";reg = <3 0x02000000 0x10000>;interrupts = <15>;phy-mode = "mii";smsc,irq-active-high;vdd33a-supply=<&v2m_fixed_3v3>;....

};};

vexpress-v2m-rs1.dti

Page 11: Arm device tree and linux device drivers

Device tree work flow

reference [2]

Page 12: Arm device tree and linux device drivers

Device Tree Binary pass to kernel

• A device tree is passed to the kernel at boot time, kernel reference it during initialization

r0: 0r1: architecture IDr2: pointer to DTB

reference [1]

Page 13: Arm device tree and linux device drivers

machine-init code with device tree

1. kernel run compatible machine-init() via compatible string match

2. Machine-init() create devices under system bus. Bus is also match by compatible string.

…..……static void __init v2m_dt_init(void){

l2x0_of_init(0x00400000, 0xfe0fffff);of_platform_populate(NULL, v2m_dt_bus_match, NULL, NULL);

}static const char * const v2m_dt_match[] __initconst = {

"arm,vexpress",NULL,

};DT_MACHINE_START(VEXPRESS_DT, "ARM-Versatile Express")

.dt_compat = v2m_dt_match,

.smp = smp_ops(vexpress_smp_ops),

.smp_init = smp_init_ops(vexpress_smp_init_ops),

.map_io = v2m_dt_map_io,

.init_early = v2m_dt_init_early,

.init_machine= v2m_dt_init,MACHINE_END

arch/arm/mach-vexpress/v2m.c

arch/arm/mach-ooo/v3m.c…..……

It creates devices under this compatible bus

struct of_device_id v2m_dt_bus_match[] = {{ .compatible = "simple-bus", },{ .compatible = "arm,amba-bus", },{ .compatible = "arm,vexpress,config-bus", },{}};

1.

2.

Page 14: Arm device tree and linux device drivers

Device-init code with device tree

1. Kernel runs all modules’ module-initfunction

2. The module-init function register platfrom driver

3. For every created platform device, it call its platform driver’s probe function

4. In probe, can access properties in device tree node and create a Linux kernel device object with private data

#ifdef CONFIG_OFstatic const struct of_device_id gdr_match[] = {

{ .compatible = "defer-reset" },};MODULE_DEVICE_TABLE(of, gdr_match);#endif

static struct platform_driver gdr_driver = {.probe = gdr_probe,.driver = {

.name = DRIVER_NAME,.owner = THIS_MODULE,.of_match_table = of_match_ptr(gdr_match),

}};static int __init gdr_init(void){

….platform_driver_register(&gdr_driver);

}module_init(gdr_init);

int gdr_probe(struct platform_device *pdev_gdr) {…..of_property_read_u32(of_node, “duration”, &duration);…..

}1.

2.

3.

4.

Page 15: Arm device tree and linux device drivers

How x86 platform works ?

• In x86, one single kernel binary can support all hardware platforms. How can do it ?

• BIOS hides the low level hardware detail – BIOS initialize low level (memory, cpu, clock, voltage, current, … )– BIOS provide memory size and hard disk information to Linux

boot-loader

• Smart bus enumerate optional devices(PCI bridge or USB root hub )– enumerate devices to Linux kernel – get device identity and resource requirement– optional device’s driver may encapsulated as module and

initialized in ramdisk stage

• PC industry is much more standardized than arm hardware

$$

$$

Page 16: Arm device tree and linux device drivers

X86 Platform boot, real mode

(boot-loader)

(compressed kernel)loaded by boot-loader

http://duartes.org/gustavo/blog/post/kernel-boot-process/

Page 17: Arm device tree and linux device drivers

Access >1MB in real mode

The shuffling of the kernel back and forth in memory is to overcome limitations of the PC BIOS memory addressability (640k), and free up several hundred kilobytes of system memory (the actual amount freed is reported by the system). The 4k is used for handling virtual memory. The special load instructions (trampoline) are required to 'cheat' the system, as the instructions load part of the kernel into memory locations beyond the 640k barrier that the (then currently running "real mode") system knows about. In the process of shuffling the kernel around, the memory originally written to by the BIOS, and also where the setup and system programs were loaded are overwritten by the kernel image, hence the need for moving them to a safe place, beyond where the uncompressed kernel image is loaded. The actual load is slightly more complicated on x86 systems as not all BIOSs report their memory on the same registers, report information in different ways, or map their memory/system resources in unconventional ways. Also, some BIOSs must be prodded for information several times or have A20 Gate problems.

http://en.wikibooks.org/wiki/The_Linux_Kernel/Booting

Page 18: Arm device tree and linux device drivers

Mode switch

reference [1]

Page 19: Arm device tree and linux device drivers

Reference

[1] http://duartes.org/gustavo/blog/post/kernel-boot-process/

[2] http://www.slideshare.net/softpapa/device-tree-support-on-arm-linux-8930303

[3] http://en.wikibooks.org/wiki/The_Linux_Kernel/Booting

[4] Linux kernel source, vexpress board

[5] Linux kernel documentation, Platform Devices and Drivers


Recommended