Around revision [900], MutekH got support for Flattened device trees. = Rationale = Flattened device trees (FDT) are useful to get a list of all available hardware where no hardware-based enumeration exists (aka PnP, like PCI, USB, ... provides). FDT provides normalized representation of the hardware platform without adding specific initialization code. The normalization comes from IEEE1275 (aka Open Firmware); while Open Firmware also defined heavy things (like a Forth interpreter), we only use the FDT information. Using FDT is mainstream, is also used by Linux and BSD, supported by U-Boot and other bootloaders. = References = * You may learn many things [http://www.google.com/search?q=flattened%20device%20tree googling] for "flattened device tree". * The `dtc` utility used to compile `.dts` files in MutekH is mainteained at http://git.jdl.com/. You may: * Browse the git there http://git.jdl.com/gitweb/ * Download a snapshot http://git.jdl.com/software/ This repository also includes some documentation and a reference library for handling FDTs. * The Linux kernel documentation tree contains [http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=blob;f=Documentation/powerpc/booting-without-of.txt;h=79f533f38c6112d64bed9398c44d31cf3b552f6b;hb=HEAD an useful document] about device trees (`Documentation/powerpc/booting-without-of.txt`) = Implementation = In MutekH, FDT is handled through an hardware enumerator device driver, it behaves like the other enumerators (PCI, ISAPnP). = MutekH-Specific Node syntax quick reference = == Processors == Processor nodes look like: {{{ Mips,32@0 { name = "Mips,32"; device_type = "cpu"; reg = <0>; }; }}} `reg`:: This is the CPU identification number `device_type`:: must be `"cpu"` There is a couple of optional attributes: `ipi_icudev`:: This is a reference to the ICU device handling IPIs for this CPU `ipi_no`:: This is the IPI register number in the said ICU device. == Memories == Memory nodes look like: {{{ memory@0 { device_type = "memory"; cached; reg = <0x61100000 0x00100000>; }; }}} `device_type`:: must be "memory" `reg`:: must be a couple of
with both the values respecting `#address-cells` and `#size-cells`. There are two optional attributes: `cached`:: The memory is cacheable `coherent`:: The memory is cached and coherent (`cached` is implied, setting it is optional) == References to interrupt controllers == Interrupts controller are referenced from one node to another in order to describe the interrupt tree. References are handled through the following properties: `icudev`:: Must be a path to an existing ICU device, enclosing in `&{}` is syntactic `irq`:: Is the irq number in `icudev`. Example: {{{ icu@0 { device_type = "soclib:icu"; input_count = <2>; reg = <0x20600000 0x20>; icudev = &{/cpus/Mips,32@0}; irq = <0>; }; tty@0 { device_type = "soclib:tty"; tty_count = <1>; reg = <0x90600000 0x10>; icudev = &{/icu@0}; irq = <1>; }; }}} Here the ICU device for `/tty@0` is `/icu@0` (device at address 0x20600000), which in turn references `/cpus/Mips,32@0` as its ICU device. == Parameter structure construction for calling `_init` functions == Some devices require a structure containing parameters in order to correctly initialize them. This case is handled in the FDT description. Let's see the example of the `soclib:xicu` component. It needs a structure containing: {{{ struct soclib_xicu_param_s { size_t output_line_no; }; }}} In the driver, the id definition is: {{{ static const struct driver_param_binder_s xicu_param_binder[] = { PARAM_BIND(struct soclib_xicu_param_s, output_line_no, PARAM_DATATYPE_INT), { 0 } }; static const struct devenum_ident_s xicu_soclib_ids[] = { DEVENUM_FDTNAME_ENTRY("soclib:xicu", sizeof(struct soclib_xicu_param_s), xicu_param_binder), { 0 } }; }}} This informs the FDT parser this device will need a parameter structure, with the parameters described in the `xicu_param_binder` correctly filled-in. In this table, there is one entry telling the `output_line_no` parameter is an integer. Available data types are: `PARAM_DATATYPE_INT`:: a simple integer `PARAM_DATATYPE_DEVICE_PTR`:: a device reference (`&{/node/path}` in the device tree source), which will be transparently translated to a `struct device_s *` before filling the structure. Device must exist in the tree. `PARAM_DATATYPE_ADDR`:: an address, `#address-cells` will be honored `PARAM_DATATYPE_BOOL`:: a simple boolean, i.e. a property with no value, if present it is true, if absent it is false (like the `cached` attribute in memory nodes) = Example = Drivers may export themselves as FDT-aware, and define which device name string to match. For instance, the following subtree defines a tty device: {{{ tty@0 { device_type = "soclib:tty"; tty_count = <1>; reg = <0x90600000 0x10>; icudev = &{/icu@0}; irq = <1>; }; }}} In turn, the SoCLib tty driver declares itself (in source:trunk/mutekh/drivers/device/char/tty-soclib/tty-soclib.c#L146) as: Note there is no parameter structure definition, so the two last arguments of `DEVENUM_FDTNAME_ENTRY` are 0. {{{ static const struct devenum_ident_s tty_soclib_ids[] = { DEVENUM_FDTNAME_ENTRY("soclib:tty", 0, 0), { 0 } }; const struct driver_s tty_soclib_drv = { .class = device_class_char, .id_table = tty_soclib_ids, .f_init = tty_soclib_init, .f_cleanup = tty_soclib_cleanup, .f_irq = tty_soclib_irq, .f.chr = { .f_request = tty_soclib_request, } }; }}} This will make the FDT enumerator use the correct driver, matching `"soclib:tty"`