Commit 1269625177f120d659f66b18de4b532b16c44561
1 parent
b979d3d4c5
Exists in
v2017.01-smarct4x
and in
28 other branches
dm: Update the of-platdata README for the new features
Revise the content based on the v2 additions. This is kept as a separate patch to avoid confusing those who have already reviewed the v1 series. Signed-off-by: Simon Glass <sjg@chromium.org> Suggested-by: Tom Rini <trini@konsulko.com>
Showing 1 changed file with 76 additions and 34 deletions Inline Diff
doc/driver-model/of-plat.txt
| 1 | Driver Model Compiled-in Device Tree / Platform Data | 1 | Driver Model Compiled-in Device Tree / Platform Data |
| 2 | ==================================================== | 2 | ==================================================== |
| 3 | 3 | ||
| 4 | 4 | ||
| 5 | Introduction | 5 | Introduction |
| 6 | ------------ | 6 | ------------ |
| 7 | 7 | ||
| 8 | Device tree is the standard configuration method in U-Boot. It is used to | 8 | Device tree is the standard configuration method in U-Boot. It is used to |
| 9 | define what devices are in the system and provide configuration information | 9 | define what devices are in the system and provide configuration information |
| 10 | to these devices. | 10 | to these devices. |
| 11 | 11 | ||
| 12 | The overhead of adding device tree access to U-Boot is fairly modest, | 12 | The overhead of adding device tree access to U-Boot is fairly modest, |
| 13 | approximately 3KB on Thumb 2 (plus the size of the DT itself). This means | 13 | approximately 3KB on Thumb 2 (plus the size of the DT itself). This means |
| 14 | that in most cases it is best to use device tree for configuration. | 14 | that in most cases it is best to use device tree for configuration. |
| 15 | 15 | ||
| 16 | However there are some very constrained environments where U-Boot needs to | 16 | However there are some very constrained environments where U-Boot needs to |
| 17 | work. These include SPL with severe memory limitations. For example, some | 17 | work. These include SPL with severe memory limitations. For example, some |
| 18 | SoCs require a 16KB SPL image which must include a full MMC stack. In this | 18 | SoCs require a 16KB SPL image which must include a full MMC stack. In this |
| 19 | case the overhead of device tree access may be too great. | 19 | case the overhead of device tree access may be too great. |
| 20 | 20 | ||
| 21 | It is possible to create platform data manually by defining C structures | 21 | It is possible to create platform data manually by defining C structures |
| 22 | for it, and referencing that data in a U_BOOT_DEVICE() declaration. This | 22 | for it, and reference that data in a U_BOOT_DEVICE() declaration. This |
| 23 | bypasses the use of device tree completely, but is an available option for | 23 | bypasses the use of device tree completely, effectively creating a parallel |
| 24 | SPL. | 24 | configuration mechanism. But it is an available option for SPL. |
| 25 | 25 | ||
| 26 | As an alternative, a new 'of-platdata' feature is provided. This converts | 26 | As an alternative, a new 'of-platdata' feature is provided. This converts the |
| 27 | device tree contents into C code which can be compiled into the SPL binary. | 27 | device tree contents into C code which can be compiled into the SPL binary. |
| 28 | This saves the 3KB of code overhead and perhaps a few hundred more bytes due | 28 | This saves the 3KB of code overhead and perhaps a few hundred more bytes due |
| 29 | to more efficient storage of the data. | 29 | to more efficient storage of the data. |
| 30 | 30 | ||
| 31 | Note: Quite a bit of thought has gone into the design of this feature. | ||
| 32 | However it still has many rough edges and comments and suggestions are | ||
| 33 | strongly encouraged! Quite possibly there is a much better approach. | ||
| 31 | 34 | ||
| 35 | |||
| 32 | Caveats | 36 | Caveats |
| 33 | ------- | 37 | ------- |
| 34 | 38 | ||
| 35 | There are many problems with this features. It should only be used when | 39 | There are many problems with this features. It should only be used when |
| 36 | stricly necessary. Notable problems include: | 40 | strictly necessary. Notable problems include: |
| 37 | 41 | ||
| 38 | - Device tree does not describe data types but the C code must define a | 42 | - Device tree does not describe data types. But the C code must define a |
| 39 | type for each property. Thesee are guessed using heuristics which | 43 | type for each property. These are guessed using heuristics which |
| 40 | are wrong in several fairly common cases. For example an 8-byte value | 44 | are wrong in several fairly common cases. For example an 8-byte value |
| 41 | is considered to be a 2-item integer array, and is byte-swapped. A | 45 | is considered to be a 2-item integer array, and is byte-swapped. A |
| 42 | boolean value that is not present means 'false', but cannot be | 46 | boolean value that is not present means 'false', but cannot be |
| 43 | included in the structures since there is generally no mention of it | 47 | included in the structures since there is generally no mention of it |
| 44 | in the device tree file. | 48 | in the device tree file. |
| 45 | 49 | ||
| 46 | - Naming of nodes and properties is automatic. This means that they follow | 50 | - Naming of nodes and properties is automatic. This means that they follow |
| 47 | the naming in the device tree, which may result in C identifiers that | 51 | the naming in the device tree, which may result in C identifiers that |
| 48 | look a bit strange | 52 | look a bit strange. |
| 49 | 53 | ||
| 50 | - It is not possible to find a value given a property name. Code must use | 54 | - It is not possible to find a value given a property name. Code must use |
| 51 | the associated C member variable directly in the code. This makes | 55 | the associated C member variable directly in the code. This makes |
| 52 | the code less robust in the face of device-tree changes. It also | 56 | the code less robust in the face of device-tree changes. It also |
| 53 | makes it very unlikely that your driver code will be useful for more | 57 | makes it very unlikely that your driver code will be useful for more |
| 54 | than one SoC. Even if the code is common, each SoC will end up with | 58 | than one SoC. Even if the code is common, each SoC will end up with |
| 55 | a different C struct and format for the platform data. | 59 | a different C struct name, and a likely a different format for the |
| 60 | platform data. | ||
| 56 | 61 | ||
| 57 | - The platform data is provided to drivers as a C structure. The driver | 62 | - The platform data is provided to drivers as a C structure. The driver |
| 58 | must use the same structure to access the data. Since a driver | 63 | must use the same structure to access the data. Since a driver |
| 59 | normally also supports device tree it must use #ifdef to separate | 64 | normally also supports device tree it must use #ifdef to separate |
| 60 | out this code, since the structures are only available in SPL. | 65 | out this code, since the structures are only available in SPL. |
| 61 | 66 | ||
| 62 | 67 | ||
| 63 | How it works | 68 | How it works |
| 64 | ------------ | 69 | ------------ |
| 65 | 70 | ||
| 66 | The feature is enabled by CONFIG SPL_OF_PLATDATA. This is only available | 71 | The feature is enabled by CONFIG SPL_OF_PLATDATA. This is only available |
| 67 | in SPL and should be tested with: | 72 | in SPL and should be tested with: |
| 68 | 73 | ||
| 69 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) | 74 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) |
| 70 | 75 | ||
| 71 | A new tool called 'dtoc' converts a device tree file either into a set of | 76 | A new tool called 'dtoc' converts a device tree file either into a set of |
| 72 | struct declarations, one for each compatible node, or a set of | 77 | struct declarations, one for each compatible node, or a set of |
| 73 | U_BOOT_DEVICE() declarations along with the actual platform data for each | 78 | U_BOOT_DEVICE() declarations along with the actual platform data for each |
| 74 | device. As an example, consider this MMC node: | 79 | device. As an example, consider this MMC node: |
| 75 | 80 | ||
| 76 | sdmmc: dwmmc@ff0c0000 { | 81 | sdmmc: dwmmc@ff0c0000 { |
| 77 | compatible = "rockchip,rk3288-dw-mshc"; | 82 | compatible = "rockchip,rk3288-dw-mshc"; |
| 78 | clock-freq-min-max = <400000 150000000>; | 83 | clock-freq-min-max = <400000 150000000>; |
| 79 | clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, | 84 | clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, |
| 80 | <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; | 85 | <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; |
| 81 | clock-names = "biu", "ciu", "ciu_drv", "ciu_sample"; | 86 | clock-names = "biu", "ciu", "ciu_drv", "ciu_sample"; |
| 82 | fifo-depth = <0x100>; | 87 | fifo-depth = <0x100>; |
| 83 | interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; | 88 | interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; |
| 84 | reg = <0xff0c0000 0x4000>; | 89 | reg = <0xff0c0000 0x4000>; |
| 85 | bus-width = <4>; | 90 | bus-width = <4>; |
| 86 | cap-mmc-highspeed; | 91 | cap-mmc-highspeed; |
| 87 | cap-sd-highspeed; | 92 | cap-sd-highspeed; |
| 88 | card-detect-delay = <200>; | 93 | card-detect-delay = <200>; |
| 89 | disable-wp; | 94 | disable-wp; |
| 90 | num-slots = <1>; | 95 | num-slots = <1>; |
| 91 | pinctrl-names = "default"; | 96 | pinctrl-names = "default"; |
| 92 | pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; | 97 | pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; |
| 93 | vmmc-supply = <&vcc_sd>; | 98 | vmmc-supply = <&vcc_sd>; |
| 94 | status = "okay"; | 99 | status = "okay"; |
| 95 | u-boot,dm-pre-reloc; | 100 | u-boot,dm-pre-reloc; |
| 96 | }; | 101 | }; |
| 97 | 102 | ||
| 98 | 103 | ||
| 99 | Some of these properties are dropped by U-Boot under control of the | 104 | Some of these properties are dropped by U-Boot under control of the |
| 100 | CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce | 105 | CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce |
| 101 | the following C struct declaration: | 106 | the following C struct declaration: |
| 102 | 107 | ||
| 103 | struct dtd_rockchip_rk3288_dw_mshc { | 108 | struct dtd_rockchip_rk3288_dw_mshc { |
| 104 | fdt32_t bus_width; | 109 | fdt32_t bus_width; |
| 105 | bool cap_mmc_highspeed; | 110 | bool cap_mmc_highspeed; |
| 106 | bool cap_sd_highspeed; | 111 | bool cap_sd_highspeed; |
| 107 | fdt32_t card_detect_delay; | 112 | fdt32_t card_detect_delay; |
| 108 | fdt32_t clock_freq_min_max[2]; | 113 | fdt32_t clock_freq_min_max[2]; |
| 109 | struct phandle_2_cell clocks[4]; | 114 | struct phandle_2_cell clocks[4]; |
| 110 | bool disable_wp; | 115 | bool disable_wp; |
| 111 | fdt32_t fifo_depth; | 116 | fdt32_t fifo_depth; |
| 112 | fdt32_t interrupts[3]; | 117 | fdt32_t interrupts[3]; |
| 113 | fdt32_t num_slots; | 118 | fdt32_t num_slots; |
| 114 | fdt32_t reg[2]; | 119 | fdt32_t reg[2]; |
| 115 | bool u_boot_dm_pre_reloc; | ||
| 116 | fdt32_t vmmc_supply; | 120 | fdt32_t vmmc_supply; |
| 117 | }; | 121 | }; |
| 118 | 122 | ||
| 119 | and the following device declaration: | 123 | and the following device declaration: |
| 120 | 124 | ||
| 121 | static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = { | 125 | static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = { |
| 122 | .fifo_depth = 0x100, | 126 | .fifo_depth = 0x100, |
| 123 | .cap_sd_highspeed = true, | 127 | .cap_sd_highspeed = true, |
| 124 | .interrupts = {0x0, 0x20, 0x4}, | 128 | .interrupts = {0x0, 0x20, 0x4}, |
| 125 | .clock_freq_min_max = {0x61a80, 0x8f0d180}, | 129 | .clock_freq_min_max = {0x61a80, 0x8f0d180}, |
| 126 | .vmmc_supply = 0xb, | 130 | .vmmc_supply = 0xb, |
| 127 | .num_slots = 0x1, | 131 | .num_slots = 0x1, |
| 128 | .clocks = {{&dtv_clock_controller_at_ff760000, 456}, {&dtv_clock_controller_at_ff760000, 68}, {&dtv_clock_controller_at_ff760000, 114}, {&dtv_clock_controller_at_ff760000, 118}}, | 132 | .clocks = {{&dtv_clock_controller_at_ff760000, 456}, |
| 133 | {&dtv_clock_controller_at_ff760000, 68}, | ||
| 134 | {&dtv_clock_controller_at_ff760000, 114}, | ||
| 135 | {&dtv_clock_controller_at_ff760000, 118}}, | ||
| 129 | .cap_mmc_highspeed = true, | 136 | .cap_mmc_highspeed = true, |
| 130 | .disable_wp = true, | 137 | .disable_wp = true, |
| 131 | .bus_width = 0x4, | 138 | .bus_width = 0x4, |
| 132 | .u_boot_dm_pre_reloc = true, | 139 | .u_boot_dm_pre_reloc = true, |
| 133 | .reg = {0xff0c0000, 0x4000}, | 140 | .reg = {0xff0c0000, 0x4000}, |
| 134 | .card_detect_delay = 0xc8, | 141 | .card_detect_delay = 0xc8, |
| 135 | }; | 142 | }; |
| 136 | U_BOOT_DEVICE(dwmmc_at_ff0c0000) = { | 143 | U_BOOT_DEVICE(dwmmc_at_ff0c0000) = { |
| 137 | .name = "rockchip_rk3288_dw_mshc", | 144 | .name = "rockchip_rk3288_dw_mshc", |
| 138 | .platdata = &dtv_dwmmc_at_ff0c0000, | 145 | .platdata = &dtv_dwmmc_at_ff0c0000, |
| 146 | .platdata_size = sizeof(dtv_dwmmc_at_ff0c0000), | ||
| 139 | }; | 147 | }; |
| 140 | 148 | ||
| 141 | The device is then instantiated at run-time and the platform data can be | 149 | The device is then instantiated at run-time and the platform data can be |
| 142 | accessed using: | 150 | accessed using: |
| 143 | 151 | ||
| 144 | struct udevice *dev; | 152 | struct udevice *dev; |
| 145 | struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_platdata(dev); | 153 | struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_platdata(dev); |
| 146 | 154 | ||
| 147 | This avoids the code overhead of converting the device tree data to | 155 | This avoids the code overhead of converting the device tree data to |
| 148 | platform data in the driver. The ofdata_to_platdata() method should | 156 | platform data in the driver. The ofdata_to_platdata() method should |
| 149 | therefore do nothing in such a driver. | 157 | therefore do nothing in such a driver. |
| 150 | 158 | ||
| 151 | 159 | ||
| 160 | Converting of-platdata to a useful form | ||
| 161 | --------------------------------------- | ||
| 162 | |||
| 163 | Of course it would be possible use the of-platdata directly in your driver | ||
| 164 | whenever configuration information is required. However this meands that the | ||
| 165 | driver will not be able to support device tree, since the of-platdata | ||
| 166 | structure is not available when device tree is used. It would make no sense | ||
| 167 | to use this structure if device tree were available, since the structure has | ||
| 168 | all the limitations metioned in caveats above. | ||
| 169 | |||
| 170 | Therefore it is recommended that the of-platdata structure should be used | ||
| 171 | only in the probe() method of your driver. It cannot be used in the | ||
| 172 | ofdata_to_platdata() method since this is not called when platform data is | ||
| 173 | already present. | ||
| 174 | |||
| 175 | |||
| 152 | How to structure your driver | 176 | How to structure your driver |
| 153 | ---------------------------- | 177 | ---------------------------- |
| 154 | 178 | ||
| 155 | Drivers should always support device tree as an option. The of-platdata | 179 | Drivers should always support device tree as an option. The of-platdata |
| 156 | feature is intended as a add-on to existing drivers. | 180 | feature is intended as a add-on to existing drivers. |
| 157 | 181 | ||
| 158 | Your driver should directly access the platdata struct in its probe() | 182 | Your driver should convert the platdata struct in its probe() method. The |
| 159 | method. The existing device tree decoding logic should be kept in the | 183 | existing device tree decoding logic should be kept in the |
| 160 | ofdata_to_platdata() and wrapped with #ifdef. | 184 | ofdata_to_platdata() method and wrapped with #if. |
| 161 | 185 | ||
| 162 | For example: | 186 | For example: |
| 163 | 187 | ||
| 164 | #include <dt-structs.h> | 188 | #include <dt-structs.h> |
| 165 | 189 | ||
| 166 | struct mmc_platdata { | 190 | struct mmc_platdata { |
| 167 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) | 191 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) |
| 168 | /* Put this first */ | 192 | /* Put this first since driver model will copy the data here */ |
| 169 | struct dtd_mmc dtplat; | 193 | struct dtd_mmc dtplat; |
| 170 | #endif | 194 | #endif |
| 171 | /* | 195 | /* |
| 172 | * Other fields can go here, to be filled in by decoding from | 196 | * Other fields can go here, to be filled in by decoding from |
| 173 | * the device tree. They will point to random memory in the | 197 | * the device tree (or the C structures when of-platdata is used). |
| 174 | * of-plat case. | ||
| 175 | */ | 198 | */ |
| 176 | int fifo_depth; | 199 | int fifo_depth; |
| 177 | }; | 200 | }; |
| 178 | 201 | ||
| 179 | static int mmc_ofdata_to_platdata(struct udevice *dev) | 202 | static int mmc_ofdata_to_platdata(struct udevice *dev) |
| 180 | { | 203 | { |
| 181 | #if !CONFIG_IS_ENABLED(SPL_OF_PLATDATA) | 204 | #if !CONFIG_IS_ENABLED(SPL_OF_PLATDATA) |
| 205 | /* Decode the device tree data */ | ||
| 182 | struct mmc_platdata *plat = dev_get_platdata(dev); | 206 | struct mmc_platdata *plat = dev_get_platdata(dev); |
| 183 | const void *blob = gd->fdt_blob; | 207 | const void *blob = gd->fdt_blob; |
| 184 | int node = dev->of_offset; | 208 | int node = dev->of_offset; |
| 185 | 209 | ||
| 186 | plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0); | 210 | plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0); |
| 187 | #endif | 211 | #endif |
| 188 | 212 | ||
| 189 | return 0; | 213 | return 0; |
| 190 | } | 214 | } |
| 191 | 215 | ||
| 192 | static int mmc_probe(struct udevice *dev) | 216 | static int mmc_probe(struct udevice *dev) |
| 193 | { | 217 | { |
| 194 | struct mmc_platdata *plat = dev_get_platdata(dev); | 218 | struct mmc_platdata *plat = dev_get_platdata(dev); |
| 219 | |||
| 195 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) | 220 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) |
| 221 | /* Decode the of-platdata from the C structures */ | ||
| 196 | struct dtd_mmc *dtplat = &plat->dtplat; | 222 | struct dtd_mmc *dtplat = &plat->dtplat; |
| 197 | 223 | ||
| 198 | /* Set up the device from the dtplat data */ | 224 | plat->fifo_depth = dtplat->fifo_depth; |
| 199 | writel(dtplat->fifo_depth, ...) | 225 | #endif |
| 200 | #else | ||
| 201 | /* Set up the device from the plat data */ | 226 | /* Set up the device from the plat data */ |
| 202 | writel(plat->fifo_depth, ...) | 227 | writel(plat->fifo_depth, ...) |
| 203 | #endif | ||
| 204 | } | 228 | } |
| 205 | 229 | ||
| 206 | static const struct udevice_id mmc_ids[] = { | 230 | static const struct udevice_id mmc_ids[] = { |
| 207 | { .compatible = "vendor,mmc" }, | 231 | { .compatible = "vendor,mmc" }, |
| 208 | { } | 232 | { } |
| 209 | }; | 233 | }; |
| 210 | 234 | ||
| 211 | U_BOOT_DRIVER(mmc_drv) = { | 235 | U_BOOT_DRIVER(mmc_drv) = { |
| 212 | .name = "mmc", | 236 | .name = "mmc", |
| 213 | .id = UCLASS_MMC, | 237 | .id = UCLASS_MMC, |
| 214 | .of_match = mmc_ids, | 238 | .of_match = mmc_ids, |
| 215 | .ofdata_to_platdata = mmc_ofdata_to_platdata, | 239 | .ofdata_to_platdata = mmc_ofdata_to_platdata, |
| 216 | .probe = mmc_probe, | 240 | .probe = mmc_probe, |
| 217 | .priv_auto_alloc_size = sizeof(struct mmc_priv), | 241 | .priv_auto_alloc_size = sizeof(struct mmc_priv), |
| 218 | .platdata_auto_alloc_size = sizeof(struct mmc_platdata), | 242 | .platdata_auto_alloc_size = sizeof(struct mmc_platdata), |
| 219 | }; | 243 | }; |
| 220 | 244 | ||
| 221 | 245 | ||
| 222 | In the case where SPL_OF_PLATDATA is enabled, platdata_auto_alloc_size is | 246 | In the case where SPL_OF_PLATDATA is enabled, platdata_auto_alloc_size is |
| 223 | ignored, and the platform data points to the C structure data. In the case | 247 | still used to allocate space for the platform data. This is different from |
| 224 | where device tree is used, the platform data is allocated, and starts | 248 | the normal behaviour and is triggered by the use of of-platdata (strictly |
| 225 | zeroed. In this case the ofdata_to_platdata() method should set up the | 249 | speaking it is a non-zero platdata_size which triggers this). |
| 226 | platform data. | ||
| 227 | 250 | ||
| 228 | SPL must use either of-platdata or device tree. Drivers cannot use both. | 251 | The of-platdata struct contents is copied from the C structure data to the |
| 229 | The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled, | 252 | start of the newly allocated area. In the case where device tree is used, |
| 230 | since the device-tree access code is not compiled in. | 253 | the platform data is allocated, and starts zeroed. In this case the |
| 254 | ofdata_to_platdata() method should still set up the platform data (and the | ||
| 255 | of-platdata struct will not be present). | ||
| 231 | 256 | ||
| 257 | SPL must use either of-platdata or device tree. Drivers cannot use both at | ||
| 258 | the same time, but they must support device tree. Supporting of-platdata is | ||
| 259 | optional. | ||
| 232 | 260 | ||
| 261 | The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled, | ||
| 262 | since the device-tree access code is not compiled in. A corollary is that | ||
| 263 | a board can only move to using of-platdata if all the drivers it uses support | ||
| 264 | it. There would be little point in having some drivers require the device | ||
| 265 | tree data, since then libfdt would still be needed for those drivers and | ||
| 266 | there would be no code-size benefit. | ||
| 267 | |||
| 233 | Internals | 268 | Internals |
| 234 | --------- | 269 | --------- |
| 235 | 270 | ||
| 236 | The dt-structs.h file includes the generated file | 271 | The dt-structs.h file includes the generated file |
| 237 | (include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled. | 272 | (include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled. |
| 238 | Otherwise (such as in U-Boot proper) these structs are not available. This | 273 | Otherwise (such as in U-Boot proper) these structs are not available. This |
| 239 | prevents them being used inadvertently. | 274 | prevents them being used inadvertently. All usage must be bracketed with |
| 275 | #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA). | ||
| 240 | 276 | ||
| 241 | The dt-platdata.c file contains the device declarations and is is built in | 277 | The dt-platdata.c file contains the device declarations and is is built in |
| 242 | spl/dt-platdata.c. | 278 | spl/dt-platdata.c. |
| 243 | 279 | ||
| 244 | Some phandles (thsoe that are recognised as such) are converted into | 280 | Some phandles (thsoe that are recognised as such) are converted into |
| 245 | points to platform data. This pointer can potentially be used to access the | 281 | points to platform data. This pointer can potentially be used to access the |
| 246 | referenced device (by searching for the pointer value). This feature is not | 282 | referenced device (by searching for the pointer value). This feature is not |
| 247 | yet implemented, however. | 283 | yet implemented, however. |
| 248 | 284 | ||
| 249 | The beginnings of a libfdt Python module are provided. So far this only | 285 | The beginnings of a libfdt Python module are provided. So far this only |
| 250 | implements a subset of the features. | 286 | implements a subset of the features. |
| 251 | 287 | ||
| 252 | The 'swig' tool is needed to build the libfdt Python module. | 288 | The 'swig' tool is needed to build the libfdt Python module. If this is not |
| 289 | found then the Python model is not used and a fallback is used instead, which | ||
| 290 | makes use of fdtget. | ||
| 253 | 291 | ||
| 254 | 292 | ||
| 293 | Credits | ||
| 294 | ------- | ||
| 295 | |||
| 296 | This is an implementation of an idea by Tom Rini <trini@konsulko.com>. | ||
| 297 | |||
| 298 | |||
| 255 | Future work | 299 | Future work |
| 256 | ----------- | 300 | ----------- |
| 257 | - Add unit tests | ||
| 258 | - Add a sandbox_spl functional test | ||
| 259 | - Consider programmatically reading binding files instead of device tree | 301 | - Consider programmatically reading binding files instead of device tree |
| 260 | contents | 302 | contents |
| 261 | - Drop the device tree data from the SPL image | ||
| 262 | - Complete the phandle feature | 303 | - Complete the phandle feature |