Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 1 | .. SPDX-License-Identifier: GPL-2.0+ |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 2 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 3 | Compiled-in Device Tree / Platform Data |
| 4 | ======================================= |
| 5 | |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 6 | |
| 7 | Introduction |
| 8 | ------------ |
| 9 | |
| 10 | Device tree is the standard configuration method in U-Boot. It is used to |
| 11 | define what devices are in the system and provide configuration information |
| 12 | to these devices. |
| 13 | |
| 14 | The overhead of adding device tree access to U-Boot is fairly modest, |
| 15 | approximately 3KB on Thumb 2 (plus the size of the DT itself). This means |
| 16 | that in most cases it is best to use device tree for configuration. |
| 17 | |
| 18 | However there are some very constrained environments where U-Boot needs to |
| 19 | work. These include SPL with severe memory limitations. For example, some |
| 20 | SoCs require a 16KB SPL image which must include a full MMC stack. In this |
| 21 | case the overhead of device tree access may be too great. |
| 22 | |
| 23 | It is possible to create platform data manually by defining C structures |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 24 | for it, and reference that data in a U_BOOT_DEVICE() declaration. This |
| 25 | bypasses the use of device tree completely, effectively creating a parallel |
| 26 | configuration mechanism. But it is an available option for SPL. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 27 | |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 28 | As an alternative, a new 'of-platdata' feature is provided. This converts the |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 29 | device tree contents into C code which can be compiled into the SPL binary. |
| 30 | This saves the 3KB of code overhead and perhaps a few hundred more bytes due |
| 31 | to more efficient storage of the data. |
| 32 | |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 33 | Note: Quite a bit of thought has gone into the design of this feature. |
| 34 | However it still has many rough edges and comments and suggestions are |
| 35 | strongly encouraged! Quite possibly there is a much better approach. |
| 36 | |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 37 | |
| 38 | Caveats |
| 39 | ------- |
| 40 | |
| 41 | There are many problems with this features. It should only be used when |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 42 | strictly necessary. Notable problems include: |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 43 | |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 44 | - Device tree does not describe data types. But the C code must define a |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 45 | type for each property. These are guessed using heuristics which |
| 46 | are wrong in several fairly common cases. For example an 8-byte value |
| 47 | is considered to be a 2-item integer array, and is byte-swapped. A |
| 48 | boolean value that is not present means 'false', but cannot be |
| 49 | included in the structures since there is generally no mention of it |
| 50 | in the device tree file. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 51 | |
| 52 | - Naming of nodes and properties is automatic. This means that they follow |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 53 | the naming in the device tree, which may result in C identifiers that |
| 54 | look a bit strange. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 55 | |
| 56 | - It is not possible to find a value given a property name. Code must use |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 57 | the associated C member variable directly in the code. This makes |
| 58 | the code less robust in the face of device-tree changes. It also |
| 59 | makes it very unlikely that your driver code will be useful for more |
| 60 | than one SoC. Even if the code is common, each SoC will end up with |
| 61 | a different C struct name, and a likely a different format for the |
| 62 | platform data. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 63 | |
| 64 | - The platform data is provided to drivers as a C structure. The driver |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 65 | must use the same structure to access the data. Since a driver |
| 66 | normally also supports device tree it must use #ifdef to separate |
| 67 | out this code, since the structures are only available in SPL. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 68 | |
| 69 | |
| 70 | How it works |
| 71 | ------------ |
| 72 | |
Simon Goldschmidt | 49ce8ca | 2019-01-16 20:40:18 +0100 | [diff] [blame] | 73 | The feature is enabled by CONFIG OF_PLATDATA. This is only available in |
| 74 | SPL/TPL and should be tested with: |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 75 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 76 | .. code-block:: c |
| 77 | |
| 78 | #if CONFIG_IS_ENABLED(OF_PLATDATA) |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 79 | |
| 80 | A new tool called 'dtoc' converts a device tree file either into a set of |
Simon Goldschmidt | 49ce8ca | 2019-01-16 20:40:18 +0100 | [diff] [blame] | 81 | struct declarations, one for each compatible node, and a set of |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 82 | U_BOOT_DEVICE() declarations along with the actual platform data for each |
| 83 | device. As an example, consider this MMC node: |
| 84 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 85 | .. code-block:: none |
| 86 | |
| 87 | sdmmc: dwmmc@ff0c0000 { |
| 88 | compatible = "rockchip,rk3288-dw-mshc"; |
| 89 | clock-freq-min-max = <400000 150000000>; |
| 90 | clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>, |
| 91 | <&cru SCLK_SDMMC_DRV>, <&cru SCLK_SDMMC_SAMPLE>; |
| 92 | clock-names = "biu", "ciu", "ciu_drv", "ciu_sample"; |
| 93 | fifo-depth = <0x100>; |
| 94 | interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>; |
| 95 | reg = <0xff0c0000 0x4000>; |
| 96 | bus-width = <4>; |
| 97 | cap-mmc-highspeed; |
| 98 | cap-sd-highspeed; |
| 99 | card-detect-delay = <200>; |
| 100 | disable-wp; |
| 101 | num-slots = <1>; |
| 102 | pinctrl-names = "default"; |
| 103 | pinctrl-0 = <&sdmmc_clk>, <&sdmmc_cmd>, <&sdmmc_cd>, <&sdmmc_bus4>; |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 104 | vmmc-supply = <&vcc_sd>; |
| 105 | status = "okay"; |
| 106 | u-boot,dm-pre-reloc; |
| 107 | }; |
| 108 | |
| 109 | |
| 110 | Some of these properties are dropped by U-Boot under control of the |
| 111 | CONFIG_OF_SPL_REMOVE_PROPS option. The rest are processed. This will produce |
| 112 | the following C struct declaration: |
| 113 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 114 | .. code-block:: c |
| 115 | |
| 116 | struct dtd_rockchip_rk3288_dw_mshc { |
| 117 | fdt32_t bus_width; |
| 118 | bool cap_mmc_highspeed; |
| 119 | bool cap_sd_highspeed; |
| 120 | fdt32_t card_detect_delay; |
| 121 | fdt32_t clock_freq_min_max[2]; |
| 122 | struct phandle_1_arg clocks[4]; |
| 123 | bool disable_wp; |
| 124 | fdt32_t fifo_depth; |
| 125 | fdt32_t interrupts[3]; |
| 126 | fdt32_t num_slots; |
| 127 | fdt32_t reg[2]; |
| 128 | fdt32_t vmmc_supply; |
| 129 | }; |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 130 | |
Simon Glass | a772946 | 2020-10-03 11:31:42 -0600 | [diff] [blame] | 131 | and the following device declarations: |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 132 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 133 | .. code-block:: c |
| 134 | |
Simon Glass | a772946 | 2020-10-03 11:31:42 -0600 | [diff] [blame] | 135 | /* Node /clock-controller@ff760000 index 0 */ |
| 136 | ... |
| 137 | |
| 138 | /* Node /dwmmc@ff0c0000 index 2 */ |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 139 | static struct dtd_rockchip_rk3288_dw_mshc dtv_dwmmc_at_ff0c0000 = { |
| 140 | .fifo_depth = 0x100, |
| 141 | .cap_sd_highspeed = true, |
| 142 | .interrupts = {0x0, 0x20, 0x4}, |
| 143 | .clock_freq_min_max = {0x61a80, 0x8f0d180}, |
| 144 | .vmmc_supply = 0xb, |
| 145 | .num_slots = 0x1, |
Simon Glass | a772946 | 2020-10-03 11:31:42 -0600 | [diff] [blame] | 146 | .clocks = {{0, 456}, |
| 147 | {0, 68}, |
| 148 | {0, 114}, |
| 149 | {0, 118}}, |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 150 | .cap_mmc_highspeed = true, |
| 151 | .disable_wp = true, |
| 152 | .bus_width = 0x4, |
| 153 | .u_boot_dm_pre_reloc = true, |
| 154 | .reg = {0xff0c0000, 0x4000}, |
| 155 | .card_detect_delay = 0xc8, |
| 156 | }; |
| 157 | |
| 158 | U_BOOT_DEVICE(dwmmc_at_ff0c0000) = { |
| 159 | .name = "rockchip_rk3288_dw_mshc", |
Simon Glass | 71fa5b4 | 2020-12-03 16:55:18 -0700 | [diff] [blame] | 160 | .plat = &dtv_dwmmc_at_ff0c0000, |
| 161 | .plat_size = sizeof(dtv_dwmmc_at_ff0c0000), |
Simon Glass | a772946 | 2020-10-03 11:31:42 -0600 | [diff] [blame] | 162 | .parent_idx = -1, |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 163 | }; |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 164 | |
Walter Lozano | de707f4 | 2020-06-25 01:10:14 -0300 | [diff] [blame] | 165 | void dm_populate_phandle_data(void) { |
Walter Lozano | de707f4 | 2020-06-25 01:10:14 -0300 | [diff] [blame] | 166 | } |
| 167 | |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 168 | The device is then instantiated at run-time and the platform data can be |
| 169 | accessed using: |
| 170 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 171 | .. code-block:: c |
| 172 | |
| 173 | struct udevice *dev; |
Simon Glass | fa20e93 | 2020-12-03 16:55:20 -0700 | [diff] [blame] | 174 | struct dtd_rockchip_rk3288_dw_mshc *plat = dev_get_plat(dev); |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 175 | |
| 176 | This avoids the code overhead of converting the device tree data to |
Simon Glass | aad29ae | 2020-12-03 16:55:21 -0700 | [diff] [blame^] | 177 | platform data in the driver. The of_to_plat() method should |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 178 | therefore do nothing in such a driver. |
| 179 | |
Simon Goldschmidt | 49ce8ca | 2019-01-16 20:40:18 +0100 | [diff] [blame] | 180 | Note that for the platform data to be matched with a driver, the 'name' |
| 181 | property of the U_BOOT_DEVICE() declaration has to match a driver declared |
| 182 | via U_BOOT_DRIVER(). This effectively means that a U_BOOT_DRIVER() with a |
| 183 | 'name' corresponding to the devicetree 'compatible' string (after converting |
| 184 | it to a valid name for C) is needed, so a dedicated driver is required for |
| 185 | each 'compatible' string. |
| 186 | |
Walter Lozano | c38b491 | 2020-06-25 01:10:09 -0300 | [diff] [blame] | 187 | In order to make this a bit more flexible U_BOOT_DRIVER_ALIAS macro can be |
| 188 | used to declare an alias for a driver name, typically a 'compatible' string. |
| 189 | This macro produces no code, but it is by dtoc tool. |
| 190 | |
Simon Glass | a772946 | 2020-10-03 11:31:42 -0600 | [diff] [blame] | 191 | The parent_idx is the index of the parent driver_info structure within its |
| 192 | linker list (instantiated by the U_BOOT_DEVICE() macro). This is used to support |
| 193 | dev_get_parent(). The dm_populate_phandle_data() is included to allow for |
| 194 | fix-ups required by dtoc. It is not currently used. The values in 'clocks' are |
| 195 | the index of the driver_info for the target device followed by any phandle |
| 196 | arguments. This is used to support device_get_by_driver_info_idx(). |
| 197 | |
Walter Lozano | c38b491 | 2020-06-25 01:10:09 -0300 | [diff] [blame] | 198 | During the build process dtoc parses both U_BOOT_DRIVER and U_BOOT_DRIVER_ALIAS |
| 199 | to build a list of valid driver names and driver aliases. If the 'compatible' |
| 200 | string used for a device does not not match a valid driver name, it will be |
| 201 | checked against the list of driver aliases in order to get the right driver |
| 202 | name to use. If in this step there is no match found a warning is issued to |
| 203 | avoid run-time failures. |
| 204 | |
Simon Glass | 934be0b | 2017-06-13 21:10:06 -0600 | [diff] [blame] | 205 | Where a node has multiple compatible strings, a #define is used to make them |
| 206 | equivalent, e.g.: |
| 207 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 208 | .. code-block:: c |
Simon Glass | 934be0b | 2017-06-13 21:10:06 -0600 | [diff] [blame] | 209 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 210 | #define dtd_rockchip_rk3299_dw_mshc dtd_rockchip_rk3288_dw_mshc |
| 211 | |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 212 | |
| 213 | Converting of-platdata to a useful form |
| 214 | --------------------------------------- |
| 215 | |
Simon Goldschmidt | 49ce8ca | 2019-01-16 20:40:18 +0100 | [diff] [blame] | 216 | Of course it would be possible to use the of-platdata directly in your driver |
| 217 | whenever configuration information is required. However this means that the |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 218 | driver will not be able to support device tree, since the of-platdata |
| 219 | structure is not available when device tree is used. It would make no sense |
| 220 | to use this structure if device tree were available, since the structure has |
| 221 | all the limitations metioned in caveats above. |
| 222 | |
| 223 | Therefore it is recommended that the of-platdata structure should be used |
| 224 | only in the probe() method of your driver. It cannot be used in the |
Simon Glass | aad29ae | 2020-12-03 16:55:21 -0700 | [diff] [blame^] | 225 | of_to_plat() method since this is not called when platform data is |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 226 | already present. |
| 227 | |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 228 | |
| 229 | How to structure your driver |
| 230 | ---------------------------- |
| 231 | |
| 232 | Drivers should always support device tree as an option. The of-platdata |
| 233 | feature is intended as a add-on to existing drivers. |
| 234 | |
Simon Glass | 71fa5b4 | 2020-12-03 16:55:18 -0700 | [diff] [blame] | 235 | Your driver should convert the plat struct in its probe() method. The |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 236 | existing device tree decoding logic should be kept in the |
Simon Glass | aad29ae | 2020-12-03 16:55:21 -0700 | [diff] [blame^] | 237 | of_to_plat() method and wrapped with #if. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 238 | |
| 239 | For example: |
| 240 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 241 | .. code-block:: c |
| 242 | |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 243 | #include <dt-structs.h> |
| 244 | |
| 245 | struct mmc_platdata { |
Lukasz Majewski | fd54ab2 | 2019-09-03 15:43:19 +0200 | [diff] [blame] | 246 | #if CONFIG_IS_ENABLED(OF_PLATDATA) |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 247 | /* Put this first since driver model will copy the data here */ |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 248 | struct dtd_mmc dtplat; |
| 249 | #endif |
| 250 | /* |
| 251 | * Other fields can go here, to be filled in by decoding from |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 252 | * the device tree (or the C structures when of-platdata is used). |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 253 | */ |
| 254 | int fifo_depth; |
| 255 | }; |
| 256 | |
Simon Glass | aad29ae | 2020-12-03 16:55:21 -0700 | [diff] [blame^] | 257 | static int mmc_of_to_plat(struct udevice *dev) |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 258 | { |
Lukasz Majewski | fd54ab2 | 2019-09-03 15:43:19 +0200 | [diff] [blame] | 259 | #if !CONFIG_IS_ENABLED(OF_PLATDATA) |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 260 | /* Decode the device tree data */ |
Simon Glass | fa20e93 | 2020-12-03 16:55:20 -0700 | [diff] [blame] | 261 | struct mmc_platdata *plat = dev_get_plat(dev); |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 262 | const void *blob = gd->fdt_blob; |
Simon Glass | dd79d6e | 2017-01-17 16:52:55 -0700 | [diff] [blame] | 263 | int node = dev_of_offset(dev); |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 264 | |
| 265 | plat->fifo_depth = fdtdec_get_int(blob, node, "fifo-depth", 0); |
| 266 | #endif |
| 267 | |
| 268 | return 0; |
| 269 | } |
| 270 | |
| 271 | static int mmc_probe(struct udevice *dev) |
| 272 | { |
Simon Glass | fa20e93 | 2020-12-03 16:55:20 -0700 | [diff] [blame] | 273 | struct mmc_platdata *plat = dev_get_plat(dev); |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 274 | |
Lukasz Majewski | fd54ab2 | 2019-09-03 15:43:19 +0200 | [diff] [blame] | 275 | #if CONFIG_IS_ENABLED(OF_PLATDATA) |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 276 | /* Decode the of-platdata from the C structures */ |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 277 | struct dtd_mmc *dtplat = &plat->dtplat; |
| 278 | |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 279 | plat->fifo_depth = dtplat->fifo_depth; |
| 280 | #endif |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 281 | /* Set up the device from the plat data */ |
| 282 | writel(plat->fifo_depth, ...) |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 283 | } |
| 284 | |
| 285 | static const struct udevice_id mmc_ids[] = { |
| 286 | { .compatible = "vendor,mmc" }, |
| 287 | { } |
| 288 | }; |
| 289 | |
| 290 | U_BOOT_DRIVER(mmc_drv) = { |
Walter Lozano | c38b491 | 2020-06-25 01:10:09 -0300 | [diff] [blame] | 291 | .name = "mmc_drv", |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 292 | .id = UCLASS_MMC, |
| 293 | .of_match = mmc_ids, |
Simon Glass | aad29ae | 2020-12-03 16:55:21 -0700 | [diff] [blame^] | 294 | .of_to_plat = mmc_of_to_plat, |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 295 | .probe = mmc_probe, |
Simon Glass | 8a2b47f | 2020-12-03 16:55:17 -0700 | [diff] [blame] | 296 | .priv_auto = sizeof(struct mmc_priv), |
Simon Glass | 71fa5b4 | 2020-12-03 16:55:18 -0700 | [diff] [blame] | 297 | .plat_auto = sizeof(struct mmc_platdata), |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 298 | }; |
| 299 | |
Walter Lozano | c38b491 | 2020-06-25 01:10:09 -0300 | [diff] [blame] | 300 | U_BOOT_DRIVER_ALIAS(mmc_drv, vendor_mmc) /* matches compatible string */ |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 301 | |
Simon Glass | 63c19ed | 2019-12-06 21:42:43 -0700 | [diff] [blame] | 302 | Note that struct mmc_platdata is defined in the C file, not in a header. This |
| 303 | is to avoid needing to include dt-structs.h in a header file. The idea is to |
| 304 | keep the use of each of-platdata struct to the smallest possible code area. |
| 305 | There is just one driver C file for each struct, that can convert from the |
| 306 | of-platdata struct to the standard one used by the driver. |
| 307 | |
Simon Glass | 71fa5b4 | 2020-12-03 16:55:18 -0700 | [diff] [blame] | 308 | In the case where SPL_OF_PLATDATA is enabled, plat_auto is |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 309 | still used to allocate space for the platform data. This is different from |
| 310 | the normal behaviour and is triggered by the use of of-platdata (strictly |
Simon Glass | 39edb95 | 2020-12-03 16:55:19 -0700 | [diff] [blame] | 311 | speaking it is a non-zero plat_size which triggers this). |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 312 | |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 313 | The of-platdata struct contents is copied from the C structure data to the |
| 314 | start of the newly allocated area. In the case where device tree is used, |
| 315 | the platform data is allocated, and starts zeroed. In this case the |
Simon Glass | aad29ae | 2020-12-03 16:55:21 -0700 | [diff] [blame^] | 316 | of_to_plat() method should still set up the platform data (and the |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 317 | of-platdata struct will not be present). |
| 318 | |
| 319 | SPL must use either of-platdata or device tree. Drivers cannot use both at |
| 320 | the same time, but they must support device tree. Supporting of-platdata is |
| 321 | optional. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 322 | |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 323 | The device tree becomes in accessible when CONFIG_SPL_OF_PLATDATA is enabled, |
| 324 | since the device-tree access code is not compiled in. A corollary is that |
| 325 | a board can only move to using of-platdata if all the drivers it uses support |
| 326 | it. There would be little point in having some drivers require the device |
| 327 | tree data, since then libfdt would still be needed for those drivers and |
| 328 | there would be no code-size benefit. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 329 | |
| 330 | Internals |
| 331 | --------- |
| 332 | |
| 333 | The dt-structs.h file includes the generated file |
| 334 | (include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled. |
| 335 | Otherwise (such as in U-Boot proper) these structs are not available. This |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 336 | prevents them being used inadvertently. All usage must be bracketed with |
Lukasz Majewski | fd54ab2 | 2019-09-03 15:43:19 +0200 | [diff] [blame] | 337 | #if CONFIG_IS_ENABLED(OF_PLATDATA). |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 338 | |
Simon Glass | 71fa5b4 | 2020-12-03 16:55:18 -0700 | [diff] [blame] | 339 | The dt-plat.c file contains the device declarations and is is built in |
| 340 | spl/dt-plat.c. It additionally contains the definition of |
Walter Lozano | de707f4 | 2020-06-25 01:10:14 -0300 | [diff] [blame] | 341 | dm_populate_phandle_data() which is responsible of filling the phandle |
| 342 | information by adding references to U_BOOT_DEVICE by using DM_GET_DEVICE |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 343 | |
Simon Glass | a772946 | 2020-10-03 11:31:42 -0600 | [diff] [blame] | 344 | The pylibfdt Python module is used to access the devicetree. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 345 | |
Simon Glass | 946c723 | 2016-07-04 11:58:42 -0600 | [diff] [blame] | 346 | |
| 347 | Credits |
| 348 | ------- |
| 349 | |
| 350 | This is an implementation of an idea by Tom Rini <trini@konsulko.com>. |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 351 | |
| 352 | |
| 353 | Future work |
| 354 | ----------- |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 355 | - Consider programmatically reading binding files instead of device tree |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 356 | contents |
Simon Glass | 261ad28 | 2016-07-04 11:58:07 -0600 | [diff] [blame] | 357 | |
Bin Meng | ae25869 | 2019-07-18 00:33:55 -0700 | [diff] [blame] | 358 | |
| 359 | .. Simon Glass <sjg@chromium.org> |
| 360 | .. Google, Inc |
| 361 | .. 6/6/16 |
| 362 | .. Updated Independence Day 2016 |
Simon Glass | a772946 | 2020-10-03 11:31:42 -0600 | [diff] [blame] | 363 | .. Updated 1st October 2020 |