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