Commit 3bf2f15351e9533c9c99ebbdd93cafca30558b0d

Authored by Thierry Reding
Committed by Simon Glass
1 parent 089ff8eb66

fdtdec: Remove fdt_{addr,size}_unpack()

U-Boot already defines the {upper,lower}_32_bits() macros that have the
same purpose. Use the existing macros instead of defining new APIs.

Signed-off-by: Thierry Reding <treding@nvidia.com>

Showing 3 changed files with 12 additions and 28 deletions Inline Diff

1 /* SPDX-License-Identifier: GPL-2.0+ */ 1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /* 2 /*
3 * Copyright (c) 2011 The Chromium OS Authors. 3 * Copyright (c) 2011 The Chromium OS Authors.
4 */ 4 */
5 5
6 #ifndef __fdtdec_h 6 #ifndef __fdtdec_h
7 #define __fdtdec_h 7 #define __fdtdec_h
8 8
9 /* 9 /*
10 * This file contains convenience functions for decoding useful and 10 * This file contains convenience functions for decoding useful and
11 * enlightening information from FDTs. It is intended to be used by device 11 * enlightening information from FDTs. It is intended to be used by device
12 * drivers and board-specific code within U-Boot. It aims to reduce the 12 * drivers and board-specific code within U-Boot. It aims to reduce the
13 * amount of FDT munging required within U-Boot itself, so that driver code 13 * amount of FDT munging required within U-Boot itself, so that driver code
14 * changes to support FDT are minimized. 14 * changes to support FDT are minimized.
15 */ 15 */
16 16
17 #include <linux/libfdt.h> 17 #include <linux/libfdt.h>
18 #include <pci.h> 18 #include <pci.h>
19 19
20 /* 20 /*
21 * A typedef for a physical address. Note that fdt data is always big 21 * A typedef for a physical address. Note that fdt data is always big
22 * endian even on a litle endian machine. 22 * endian even on a litle endian machine.
23 */ 23 */
24 typedef phys_addr_t fdt_addr_t; 24 typedef phys_addr_t fdt_addr_t;
25 typedef phys_size_t fdt_size_t; 25 typedef phys_size_t fdt_size_t;
26 26
27 static inline fdt32_t fdt_addr_unpack(fdt_addr_t addr, fdt32_t *upper)
28 {
29 if (upper)
30 #ifdef CONFIG_PHYS_64BIT
31 *upper = addr >> 32;
32 #else
33 *upper = 0;
34 #endif
35
36 return addr;
37 }
38
39 static inline fdt32_t fdt_size_unpack(fdt_size_t size, fdt32_t *upper)
40 {
41 if (upper)
42 #ifdef CONFIG_PHYS_64BIT
43 *upper = size >> 32;
44 #else
45 *upper = 0;
46 #endif
47
48 return size;
49 }
50
51 #ifdef CONFIG_PHYS_64BIT 27 #ifdef CONFIG_PHYS_64BIT
52 #define FDT_ADDR_T_NONE (-1U) 28 #define FDT_ADDR_T_NONE (-1U)
53 #define fdt_addr_to_cpu(reg) be64_to_cpu(reg) 29 #define fdt_addr_to_cpu(reg) be64_to_cpu(reg)
54 #define fdt_size_to_cpu(reg) be64_to_cpu(reg) 30 #define fdt_size_to_cpu(reg) be64_to_cpu(reg)
55 #define cpu_to_fdt_addr(reg) cpu_to_be64(reg) 31 #define cpu_to_fdt_addr(reg) cpu_to_be64(reg)
56 #define cpu_to_fdt_size(reg) cpu_to_be64(reg) 32 #define cpu_to_fdt_size(reg) cpu_to_be64(reg)
57 typedef fdt64_t fdt_val_t; 33 typedef fdt64_t fdt_val_t;
58 #else 34 #else
59 #define FDT_ADDR_T_NONE (-1U) 35 #define FDT_ADDR_T_NONE (-1U)
60 #define fdt_addr_to_cpu(reg) be32_to_cpu(reg) 36 #define fdt_addr_to_cpu(reg) be32_to_cpu(reg)
61 #define fdt_size_to_cpu(reg) be32_to_cpu(reg) 37 #define fdt_size_to_cpu(reg) be32_to_cpu(reg)
62 #define cpu_to_fdt_addr(reg) cpu_to_be32(reg) 38 #define cpu_to_fdt_addr(reg) cpu_to_be32(reg)
63 #define cpu_to_fdt_size(reg) cpu_to_be32(reg) 39 #define cpu_to_fdt_size(reg) cpu_to_be32(reg)
64 typedef fdt32_t fdt_val_t; 40 typedef fdt32_t fdt_val_t;
65 #endif 41 #endif
66 42
67 /* Information obtained about memory from the FDT */ 43 /* Information obtained about memory from the FDT */
68 struct fdt_memory { 44 struct fdt_memory {
69 fdt_addr_t start; 45 fdt_addr_t start;
70 fdt_addr_t end; 46 fdt_addr_t end;
71 }; 47 };
72 48
73 struct bd_info; 49 struct bd_info;
74 50
75 #ifdef CONFIG_SPL_BUILD 51 #ifdef CONFIG_SPL_BUILD
76 #define SPL_BUILD 1 52 #define SPL_BUILD 1
77 #else 53 #else
78 #define SPL_BUILD 0 54 #define SPL_BUILD 0
79 #endif 55 #endif
80 56
81 #if CONFIG_IS_ENABLED(OF_PRIOR_STAGE) 57 #if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
82 extern phys_addr_t prior_stage_fdt_address; 58 extern phys_addr_t prior_stage_fdt_address;
83 #endif 59 #endif
84 60
85 /* 61 /*
86 * Information about a resource. start is the first address of the resource 62 * Information about a resource. start is the first address of the resource
87 * and end is the last address (inclusive). The length of the resource will 63 * and end is the last address (inclusive). The length of the resource will
88 * be equal to: end - start + 1. 64 * be equal to: end - start + 1.
89 */ 65 */
90 struct fdt_resource { 66 struct fdt_resource {
91 fdt_addr_t start; 67 fdt_addr_t start;
92 fdt_addr_t end; 68 fdt_addr_t end;
93 }; 69 };
94 70
95 enum fdt_pci_space { 71 enum fdt_pci_space {
96 FDT_PCI_SPACE_CONFIG = 0, 72 FDT_PCI_SPACE_CONFIG = 0,
97 FDT_PCI_SPACE_IO = 0x01000000, 73 FDT_PCI_SPACE_IO = 0x01000000,
98 FDT_PCI_SPACE_MEM32 = 0x02000000, 74 FDT_PCI_SPACE_MEM32 = 0x02000000,
99 FDT_PCI_SPACE_MEM64 = 0x03000000, 75 FDT_PCI_SPACE_MEM64 = 0x03000000,
100 FDT_PCI_SPACE_MEM32_PREF = 0x42000000, 76 FDT_PCI_SPACE_MEM32_PREF = 0x42000000,
101 FDT_PCI_SPACE_MEM64_PREF = 0x43000000, 77 FDT_PCI_SPACE_MEM64_PREF = 0x43000000,
102 }; 78 };
103 79
104 #define FDT_PCI_ADDR_CELLS 3 80 #define FDT_PCI_ADDR_CELLS 3
105 #define FDT_PCI_SIZE_CELLS 2 81 #define FDT_PCI_SIZE_CELLS 2
106 #define FDT_PCI_REG_SIZE \ 82 #define FDT_PCI_REG_SIZE \
107 ((FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS) * sizeof(u32)) 83 ((FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS) * sizeof(u32))
108 84
109 /* 85 /*
110 * The Open Firmware spec defines PCI physical address as follows: 86 * The Open Firmware spec defines PCI physical address as follows:
111 * 87 *
112 * bits# 31 .... 24 23 .... 16 15 .... 08 07 .... 00 88 * bits# 31 .... 24 23 .... 16 15 .... 08 07 .... 00
113 * 89 *
114 * phys.hi cell: npt000ss bbbbbbbb dddddfff rrrrrrrr 90 * phys.hi cell: npt000ss bbbbbbbb dddddfff rrrrrrrr
115 * phys.mid cell: hhhhhhhh hhhhhhhh hhhhhhhh hhhhhhhh 91 * phys.mid cell: hhhhhhhh hhhhhhhh hhhhhhhh hhhhhhhh
116 * phys.lo cell: llllllll llllllll llllllll llllllll 92 * phys.lo cell: llllllll llllllll llllllll llllllll
117 * 93 *
118 * where: 94 * where:
119 * 95 *
120 * n: is 0 if the address is relocatable, 1 otherwise 96 * n: is 0 if the address is relocatable, 1 otherwise
121 * p: is 1 if addressable region is prefetchable, 0 otherwise 97 * p: is 1 if addressable region is prefetchable, 0 otherwise
122 * t: is 1 if the address is aliased (for non-relocatable I/O) below 1MB 98 * t: is 1 if the address is aliased (for non-relocatable I/O) below 1MB
123 * (for Memory), or below 64KB (for relocatable I/O) 99 * (for Memory), or below 64KB (for relocatable I/O)
124 * ss: is the space code, denoting the address space 100 * ss: is the space code, denoting the address space
125 * bbbbbbbb: is the 8-bit Bus Number 101 * bbbbbbbb: is the 8-bit Bus Number
126 * ddddd: is the 5-bit Device Number 102 * ddddd: is the 5-bit Device Number
127 * fff: is the 3-bit Function Number 103 * fff: is the 3-bit Function Number
128 * rrrrrrrr: is the 8-bit Register Number 104 * rrrrrrrr: is the 8-bit Register Number
129 * hhhhhhhh: is a 32-bit unsigned number 105 * hhhhhhhh: is a 32-bit unsigned number
130 * llllllll: is a 32-bit unsigned number 106 * llllllll: is a 32-bit unsigned number
131 */ 107 */
132 struct fdt_pci_addr { 108 struct fdt_pci_addr {
133 u32 phys_hi; 109 u32 phys_hi;
134 u32 phys_mid; 110 u32 phys_mid;
135 u32 phys_lo; 111 u32 phys_lo;
136 }; 112 };
137 113
138 /** 114 /**
139 * Compute the size of a resource. 115 * Compute the size of a resource.
140 * 116 *
141 * @param res the resource to operate on 117 * @param res the resource to operate on
142 * @return the size of the resource 118 * @return the size of the resource
143 */ 119 */
144 static inline fdt_size_t fdt_resource_size(const struct fdt_resource *res) 120 static inline fdt_size_t fdt_resource_size(const struct fdt_resource *res)
145 { 121 {
146 return res->end - res->start + 1; 122 return res->end - res->start + 1;
147 } 123 }
148 124
149 /** 125 /**
150 * Compat types that we know about and for which we might have drivers. 126 * Compat types that we know about and for which we might have drivers.
151 * Each is named COMPAT_<dir>_<filename> where <dir> is the directory 127 * Each is named COMPAT_<dir>_<filename> where <dir> is the directory
152 * within drivers. 128 * within drivers.
153 */ 129 */
154 enum fdt_compat_id { 130 enum fdt_compat_id {
155 COMPAT_UNKNOWN, 131 COMPAT_UNKNOWN,
156 COMPAT_NVIDIA_TEGRA20_EMC, /* Tegra20 memory controller */ 132 COMPAT_NVIDIA_TEGRA20_EMC, /* Tegra20 memory controller */
157 COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */ 133 COMPAT_NVIDIA_TEGRA20_EMC_TABLE, /* Tegra20 memory timing table */
158 COMPAT_NVIDIA_TEGRA20_NAND, /* Tegra2 NAND controller */ 134 COMPAT_NVIDIA_TEGRA20_NAND, /* Tegra2 NAND controller */
159 COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL, 135 COMPAT_NVIDIA_TEGRA124_XUSB_PADCTL,
160 /* Tegra124 XUSB pad controller */ 136 /* Tegra124 XUSB pad controller */
161 COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL, 137 COMPAT_NVIDIA_TEGRA210_XUSB_PADCTL,
162 /* Tegra210 XUSB pad controller */ 138 /* Tegra210 XUSB pad controller */
163 COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet LAN9215 */ 139 COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet LAN9215 */
164 COMPAT_SAMSUNG_EXYNOS5_SROMC, /* Exynos5 SROMC */ 140 COMPAT_SAMSUNG_EXYNOS5_SROMC, /* Exynos5 SROMC */
165 COMPAT_SAMSUNG_EXYNOS_USB_PHY, /* Exynos phy controller for usb2.0 */ 141 COMPAT_SAMSUNG_EXYNOS_USB_PHY, /* Exynos phy controller for usb2.0 */
166 COMPAT_SAMSUNG_EXYNOS5_USB3_PHY,/* Exynos phy controller for usb3.0 */ 142 COMPAT_SAMSUNG_EXYNOS5_USB3_PHY,/* Exynos phy controller for usb3.0 */
167 COMPAT_SAMSUNG_EXYNOS_TMU, /* Exynos TMU */ 143 COMPAT_SAMSUNG_EXYNOS_TMU, /* Exynos TMU */
168 COMPAT_SAMSUNG_EXYNOS_MIPI_DSI, /* Exynos mipi dsi */ 144 COMPAT_SAMSUNG_EXYNOS_MIPI_DSI, /* Exynos mipi dsi */
169 COMPAT_SAMSUNG_EXYNOS_DWMMC, /* Exynos DWMMC controller */ 145 COMPAT_SAMSUNG_EXYNOS_DWMMC, /* Exynos DWMMC controller */
170 COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ 146 COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */
171 COMPAT_SAMSUNG_EXYNOS_SYSMMU, /* Exynos sysmmu */ 147 COMPAT_SAMSUNG_EXYNOS_SYSMMU, /* Exynos sysmmu */
172 COMPAT_INTEL_MICROCODE, /* Intel microcode update */ 148 COMPAT_INTEL_MICROCODE, /* Intel microcode update */
173 COMPAT_INTEL_QRK_MRC, /* Intel Quark MRC */ 149 COMPAT_INTEL_QRK_MRC, /* Intel Quark MRC */
174 COMPAT_ALTERA_SOCFPGA_DWMAC, /* SoCFPGA Ethernet controller */ 150 COMPAT_ALTERA_SOCFPGA_DWMAC, /* SoCFPGA Ethernet controller */
175 COMPAT_ALTERA_SOCFPGA_DWMMC, /* SoCFPGA DWMMC controller */ 151 COMPAT_ALTERA_SOCFPGA_DWMMC, /* SoCFPGA DWMMC controller */
176 COMPAT_ALTERA_SOCFPGA_DWC2USB, /* SoCFPGA DWC2 USB controller */ 152 COMPAT_ALTERA_SOCFPGA_DWC2USB, /* SoCFPGA DWC2 USB controller */
177 COMPAT_INTEL_BAYTRAIL_FSP, /* Intel Bay Trail FSP */ 153 COMPAT_INTEL_BAYTRAIL_FSP, /* Intel Bay Trail FSP */
178 COMPAT_INTEL_BAYTRAIL_FSP_MDP, /* Intel FSP memory-down params */ 154 COMPAT_INTEL_BAYTRAIL_FSP_MDP, /* Intel FSP memory-down params */
179 COMPAT_INTEL_IVYBRIDGE_FSP, /* Intel Ivy Bridge FSP */ 155 COMPAT_INTEL_IVYBRIDGE_FSP, /* Intel Ivy Bridge FSP */
180 COMPAT_SUNXI_NAND, /* SUNXI NAND controller */ 156 COMPAT_SUNXI_NAND, /* SUNXI NAND controller */
181 COMPAT_ALTERA_SOCFPGA_CLK, /* SoCFPGA Clock initialization */ 157 COMPAT_ALTERA_SOCFPGA_CLK, /* SoCFPGA Clock initialization */
182 COMPAT_ALTERA_SOCFPGA_PINCTRL_SINGLE, /* SoCFPGA pinctrl-single */ 158 COMPAT_ALTERA_SOCFPGA_PINCTRL_SINGLE, /* SoCFPGA pinctrl-single */
183 COMPAT_ALTERA_SOCFPGA_H2F_BRG, /* SoCFPGA hps2fpga bridge */ 159 COMPAT_ALTERA_SOCFPGA_H2F_BRG, /* SoCFPGA hps2fpga bridge */
184 COMPAT_ALTERA_SOCFPGA_LWH2F_BRG, /* SoCFPGA lwhps2fpga bridge */ 160 COMPAT_ALTERA_SOCFPGA_LWH2F_BRG, /* SoCFPGA lwhps2fpga bridge */
185 COMPAT_ALTERA_SOCFPGA_F2H_BRG, /* SoCFPGA fpga2hps bridge */ 161 COMPAT_ALTERA_SOCFPGA_F2H_BRG, /* SoCFPGA fpga2hps bridge */
186 COMPAT_ALTERA_SOCFPGA_F2SDR0, /* SoCFPGA fpga2SDRAM0 bridge */ 162 COMPAT_ALTERA_SOCFPGA_F2SDR0, /* SoCFPGA fpga2SDRAM0 bridge */
187 COMPAT_ALTERA_SOCFPGA_F2SDR1, /* SoCFPGA fpga2SDRAM1 bridge */ 163 COMPAT_ALTERA_SOCFPGA_F2SDR1, /* SoCFPGA fpga2SDRAM1 bridge */
188 COMPAT_ALTERA_SOCFPGA_F2SDR2, /* SoCFPGA fpga2SDRAM2 bridge */ 164 COMPAT_ALTERA_SOCFPGA_F2SDR2, /* SoCFPGA fpga2SDRAM2 bridge */
189 COMPAT_ALTERA_SOCFPGA_FPGA0, /* SOCFPGA FPGA manager */ 165 COMPAT_ALTERA_SOCFPGA_FPGA0, /* SOCFPGA FPGA manager */
190 COMPAT_ALTERA_SOCFPGA_NOC, /* SOCFPGA Arria 10 NOC */ 166 COMPAT_ALTERA_SOCFPGA_NOC, /* SOCFPGA Arria 10 NOC */
191 COMPAT_ALTERA_SOCFPGA_CLK_INIT, /* SOCFPGA Arria 10 clk init */ 167 COMPAT_ALTERA_SOCFPGA_CLK_INIT, /* SOCFPGA Arria 10 clk init */
192 168
193 COMPAT_COUNT, 169 COMPAT_COUNT,
194 }; 170 };
195 171
196 #define MAX_PHANDLE_ARGS 16 172 #define MAX_PHANDLE_ARGS 16
197 struct fdtdec_phandle_args { 173 struct fdtdec_phandle_args {
198 int node; 174 int node;
199 int args_count; 175 int args_count;
200 uint32_t args[MAX_PHANDLE_ARGS]; 176 uint32_t args[MAX_PHANDLE_ARGS];
201 }; 177 };
202 178
203 /** 179 /**
204 * fdtdec_parse_phandle_with_args() - Find a node pointed by phandle in a list 180 * fdtdec_parse_phandle_with_args() - Find a node pointed by phandle in a list
205 * 181 *
206 * This function is useful to parse lists of phandles and their arguments. 182 * This function is useful to parse lists of phandles and their arguments.
207 * 183 *
208 * Example: 184 * Example:
209 * 185 *
210 * phandle1: node1 { 186 * phandle1: node1 {
211 * #list-cells = <2>; 187 * #list-cells = <2>;
212 * } 188 * }
213 * 189 *
214 * phandle2: node2 { 190 * phandle2: node2 {
215 * #list-cells = <1>; 191 * #list-cells = <1>;
216 * } 192 * }
217 * 193 *
218 * node3 { 194 * node3 {
219 * list = <&phandle1 1 2 &phandle2 3>; 195 * list = <&phandle1 1 2 &phandle2 3>;
220 * } 196 * }
221 * 197 *
222 * To get a device_node of the `node2' node you may call this: 198 * To get a device_node of the `node2' node you may call this:
223 * fdtdec_parse_phandle_with_args(blob, node3, "list", "#list-cells", 0, 1, 199 * fdtdec_parse_phandle_with_args(blob, node3, "list", "#list-cells", 0, 1,
224 * &args); 200 * &args);
225 * 201 *
226 * (This function is a modified version of __of_parse_phandle_with_args() from 202 * (This function is a modified version of __of_parse_phandle_with_args() from
227 * Linux 3.18) 203 * Linux 3.18)
228 * 204 *
229 * @blob: Pointer to device tree 205 * @blob: Pointer to device tree
230 * @src_node: Offset of device tree node containing a list 206 * @src_node: Offset of device tree node containing a list
231 * @list_name: property name that contains a list 207 * @list_name: property name that contains a list
232 * @cells_name: property name that specifies the phandles' arguments count, 208 * @cells_name: property name that specifies the phandles' arguments count,
233 * or NULL to use @cells_count 209 * or NULL to use @cells_count
234 * @cells_count: Cell count to use if @cells_name is NULL 210 * @cells_count: Cell count to use if @cells_name is NULL
235 * @index: index of a phandle to parse out 211 * @index: index of a phandle to parse out
236 * @out_args: optional pointer to output arguments structure (will be filled) 212 * @out_args: optional pointer to output arguments structure (will be filled)
237 * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if 213 * @return 0 on success (with @out_args filled out if not NULL), -ENOENT if
238 * @list_name does not exist, a phandle was not found, @cells_name 214 * @list_name does not exist, a phandle was not found, @cells_name
239 * could not be found, the arguments were truncated or there were too 215 * could not be found, the arguments were truncated or there were too
240 * many arguments. 216 * many arguments.
241 * 217 *
242 */ 218 */
243 int fdtdec_parse_phandle_with_args(const void *blob, int src_node, 219 int fdtdec_parse_phandle_with_args(const void *blob, int src_node,
244 const char *list_name, 220 const char *list_name,
245 const char *cells_name, 221 const char *cells_name,
246 int cell_count, int index, 222 int cell_count, int index,
247 struct fdtdec_phandle_args *out_args); 223 struct fdtdec_phandle_args *out_args);
248 224
249 /** 225 /**
250 * Find the next numbered alias for a peripheral. This is used to enumerate 226 * Find the next numbered alias for a peripheral. This is used to enumerate
251 * all the peripherals of a certain type. 227 * all the peripherals of a certain type.
252 * 228 *
253 * Do the first call with *upto = 0. Assuming /aliases/<name>0 exists then 229 * Do the first call with *upto = 0. Assuming /aliases/<name>0 exists then
254 * this function will return a pointer to the node the alias points to, and 230 * this function will return a pointer to the node the alias points to, and
255 * then update *upto to 1. Next time you call this function, the next node 231 * then update *upto to 1. Next time you call this function, the next node
256 * will be returned. 232 * will be returned.
257 * 233 *
258 * All nodes returned will match the compatible ID, as it is assumed that 234 * All nodes returned will match the compatible ID, as it is assumed that
259 * all peripherals use the same driver. 235 * all peripherals use the same driver.
260 * 236 *
261 * @param blob FDT blob to use 237 * @param blob FDT blob to use
262 * @param name Root name of alias to search for 238 * @param name Root name of alias to search for
263 * @param id Compatible ID to look for 239 * @param id Compatible ID to look for
264 * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more 240 * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more
265 */ 241 */
266 int fdtdec_next_alias(const void *blob, const char *name, 242 int fdtdec_next_alias(const void *blob, const char *name,
267 enum fdt_compat_id id, int *upto); 243 enum fdt_compat_id id, int *upto);
268 244
269 /** 245 /**
270 * Find the compatible ID for a given node. 246 * Find the compatible ID for a given node.
271 * 247 *
272 * Generally each node has at least one compatible string attached to it. 248 * Generally each node has at least one compatible string attached to it.
273 * This function looks through our list of known compatible strings and 249 * This function looks through our list of known compatible strings and
274 * returns the corresponding ID which matches the compatible string. 250 * returns the corresponding ID which matches the compatible string.
275 * 251 *
276 * @param blob FDT blob to use 252 * @param blob FDT blob to use
277 * @param node Node containing compatible string to find 253 * @param node Node containing compatible string to find
278 * @return compatible ID, or COMPAT_UNKNOWN if we cannot find a match 254 * @return compatible ID, or COMPAT_UNKNOWN if we cannot find a match
279 */ 255 */
280 enum fdt_compat_id fdtdec_lookup(const void *blob, int node); 256 enum fdt_compat_id fdtdec_lookup(const void *blob, int node);
281 257
282 /** 258 /**
283 * Find the next compatible node for a peripheral. 259 * Find the next compatible node for a peripheral.
284 * 260 *
285 * Do the first call with node = 0. This function will return a pointer to 261 * Do the first call with node = 0. This function will return a pointer to
286 * the next compatible node. Next time you call this function, pass the 262 * the next compatible node. Next time you call this function, pass the
287 * value returned, and the next node will be provided. 263 * value returned, and the next node will be provided.
288 * 264 *
289 * @param blob FDT blob to use 265 * @param blob FDT blob to use
290 * @param node Start node for search 266 * @param node Start node for search
291 * @param id Compatible ID to look for (enum fdt_compat_id) 267 * @param id Compatible ID to look for (enum fdt_compat_id)
292 * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more 268 * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more
293 */ 269 */
294 int fdtdec_next_compatible(const void *blob, int node, 270 int fdtdec_next_compatible(const void *blob, int node,
295 enum fdt_compat_id id); 271 enum fdt_compat_id id);
296 272
297 /** 273 /**
298 * Find the next compatible subnode for a peripheral. 274 * Find the next compatible subnode for a peripheral.
299 * 275 *
300 * Do the first call with node set to the parent and depth = 0. This 276 * Do the first call with node set to the parent and depth = 0. This
301 * function will return the offset of the next compatible node. Next time 277 * function will return the offset of the next compatible node. Next time
302 * you call this function, pass the node value returned last time, with 278 * you call this function, pass the node value returned last time, with
303 * depth unchanged, and the next node will be provided. 279 * depth unchanged, and the next node will be provided.
304 * 280 *
305 * @param blob FDT blob to use 281 * @param blob FDT blob to use
306 * @param node Start node for search 282 * @param node Start node for search
307 * @param id Compatible ID to look for (enum fdt_compat_id) 283 * @param id Compatible ID to look for (enum fdt_compat_id)
308 * @param depthp Current depth (set to 0 before first call) 284 * @param depthp Current depth (set to 0 before first call)
309 * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more 285 * @return offset of next compatible node, or -FDT_ERR_NOTFOUND if no more
310 */ 286 */
311 int fdtdec_next_compatible_subnode(const void *blob, int node, 287 int fdtdec_next_compatible_subnode(const void *blob, int node,
312 enum fdt_compat_id id, int *depthp); 288 enum fdt_compat_id id, int *depthp);
313 289
314 /* 290 /*
315 * Look up an address property in a node and return the parsed address, and 291 * Look up an address property in a node and return the parsed address, and
316 * optionally the parsed size. 292 * optionally the parsed size.
317 * 293 *
318 * This variant assumes a known and fixed number of cells are used to 294 * This variant assumes a known and fixed number of cells are used to
319 * represent the address and size. 295 * represent the address and size.
320 * 296 *
321 * You probably don't want to use this function directly except to parse 297 * You probably don't want to use this function directly except to parse
322 * non-standard properties, and never to parse the "reg" property. Instead, 298 * non-standard properties, and never to parse the "reg" property. Instead,
323 * use one of the "auto" variants below, which automatically honor the 299 * use one of the "auto" variants below, which automatically honor the
324 * #address-cells and #size-cells properties in the parent node. 300 * #address-cells and #size-cells properties in the parent node.
325 * 301 *
326 * @param blob FDT blob 302 * @param blob FDT blob
327 * @param node node to examine 303 * @param node node to examine
328 * @param prop_name name of property to find 304 * @param prop_name name of property to find
329 * @param index which address to retrieve from a list of addresses. Often 0. 305 * @param index which address to retrieve from a list of addresses. Often 0.
330 * @param na the number of cells used to represent an address 306 * @param na the number of cells used to represent an address
331 * @param ns the number of cells used to represent a size 307 * @param ns the number of cells used to represent a size
332 * @param sizep a pointer to store the size into. Use NULL if not required 308 * @param sizep a pointer to store the size into. Use NULL if not required
333 * @param translate Indicates whether to translate the returned value 309 * @param translate Indicates whether to translate the returned value
334 * using the parent node's ranges property. 310 * using the parent node's ranges property.
335 * @return address, if found, or FDT_ADDR_T_NONE if not 311 * @return address, if found, or FDT_ADDR_T_NONE if not
336 */ 312 */
337 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node, 313 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
338 const char *prop_name, int index, int na, int ns, 314 const char *prop_name, int index, int na, int ns,
339 fdt_size_t *sizep, bool translate); 315 fdt_size_t *sizep, bool translate);
340 316
341 /* 317 /*
342 * Look up an address property in a node and return the parsed address, and 318 * Look up an address property in a node and return the parsed address, and
343 * optionally the parsed size. 319 * optionally the parsed size.
344 * 320 *
345 * This variant automatically determines the number of cells used to represent 321 * This variant automatically determines the number of cells used to represent
346 * the address and size by parsing the provided parent node's #address-cells 322 * the address and size by parsing the provided parent node's #address-cells
347 * and #size-cells properties. 323 * and #size-cells properties.
348 * 324 *
349 * @param blob FDT blob 325 * @param blob FDT blob
350 * @param parent parent node of @node 326 * @param parent parent node of @node
351 * @param node node to examine 327 * @param node node to examine
352 * @param prop_name name of property to find 328 * @param prop_name name of property to find
353 * @param index which address to retrieve from a list of addresses. Often 0. 329 * @param index which address to retrieve from a list of addresses. Often 0.
354 * @param sizep a pointer to store the size into. Use NULL if not required 330 * @param sizep a pointer to store the size into. Use NULL if not required
355 * @param translate Indicates whether to translate the returned value 331 * @param translate Indicates whether to translate the returned value
356 * using the parent node's ranges property. 332 * using the parent node's ranges property.
357 * @return address, if found, or FDT_ADDR_T_NONE if not 333 * @return address, if found, or FDT_ADDR_T_NONE if not
358 */ 334 */
359 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent, 335 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
360 int node, const char *prop_name, int index, fdt_size_t *sizep, 336 int node, const char *prop_name, int index, fdt_size_t *sizep,
361 bool translate); 337 bool translate);
362 338
363 /* 339 /*
364 * Look up an address property in a node and return the parsed address, and 340 * Look up an address property in a node and return the parsed address, and
365 * optionally the parsed size. 341 * optionally the parsed size.
366 * 342 *
367 * This variant automatically determines the number of cells used to represent 343 * This variant automatically determines the number of cells used to represent
368 * the address and size by parsing the parent node's #address-cells 344 * the address and size by parsing the parent node's #address-cells
369 * and #size-cells properties. The parent node is automatically found. 345 * and #size-cells properties. The parent node is automatically found.
370 * 346 *
371 * The automatic parent lookup implemented by this function is slow. 347 * The automatic parent lookup implemented by this function is slow.
372 * Consequently, fdtdec_get_addr_size_auto_parent() should be used where 348 * Consequently, fdtdec_get_addr_size_auto_parent() should be used where
373 * possible. 349 * possible.
374 * 350 *
375 * @param blob FDT blob 351 * @param blob FDT blob
376 * @param parent parent node of @node 352 * @param parent parent node of @node
377 * @param node node to examine 353 * @param node node to examine
378 * @param prop_name name of property to find 354 * @param prop_name name of property to find
379 * @param index which address to retrieve from a list of addresses. Often 0. 355 * @param index which address to retrieve from a list of addresses. Often 0.
380 * @param sizep a pointer to store the size into. Use NULL if not required 356 * @param sizep a pointer to store the size into. Use NULL if not required
381 * @param translate Indicates whether to translate the returned value 357 * @param translate Indicates whether to translate the returned value
382 * using the parent node's ranges property. 358 * using the parent node's ranges property.
383 * @return address, if found, or FDT_ADDR_T_NONE if not 359 * @return address, if found, or FDT_ADDR_T_NONE if not
384 */ 360 */
385 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node, 361 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
386 const char *prop_name, int index, fdt_size_t *sizep, 362 const char *prop_name, int index, fdt_size_t *sizep,
387 bool translate); 363 bool translate);
388 364
389 /* 365 /*
390 * Look up an address property in a node and return the parsed address. 366 * Look up an address property in a node and return the parsed address.
391 * 367 *
392 * This variant hard-codes the number of cells used to represent the address 368 * This variant hard-codes the number of cells used to represent the address
393 * and size based on sizeof(fdt_addr_t) and sizeof(fdt_size_t). It also 369 * and size based on sizeof(fdt_addr_t) and sizeof(fdt_size_t). It also
394 * always returns the first address value in the property (index 0). 370 * always returns the first address value in the property (index 0).
395 * 371 *
396 * Use of this function is not recommended due to the hard-coding of cell 372 * Use of this function is not recommended due to the hard-coding of cell
397 * counts. There is no programmatic validation that these hard-coded values 373 * counts. There is no programmatic validation that these hard-coded values
398 * actually match the device tree content in any way at all. This assumption 374 * actually match the device tree content in any way at all. This assumption
399 * can be satisfied by manually ensuring CONFIG_PHYS_64BIT is appropriately 375 * can be satisfied by manually ensuring CONFIG_PHYS_64BIT is appropriately
400 * set in the U-Boot build and exercising strict control over DT content to 376 * set in the U-Boot build and exercising strict control over DT content to
401 * ensure use of matching #address-cells/#size-cells properties. However, this 377 * ensure use of matching #address-cells/#size-cells properties. However, this
402 * approach is error-prone; those familiar with DT will not expect the 378 * approach is error-prone; those familiar with DT will not expect the
403 * assumption to exist, and could easily invalidate it. If the assumption is 379 * assumption to exist, and could easily invalidate it. If the assumption is
404 * invalidated, this function will not report the issue, and debugging will 380 * invalidated, this function will not report the issue, and debugging will
405 * be required. Instead, use fdtdec_get_addr_size_auto_parent(). 381 * be required. Instead, use fdtdec_get_addr_size_auto_parent().
406 * 382 *
407 * @param blob FDT blob 383 * @param blob FDT blob
408 * @param node node to examine 384 * @param node node to examine
409 * @param prop_name name of property to find 385 * @param prop_name name of property to find
410 * @return address, if found, or FDT_ADDR_T_NONE if not 386 * @return address, if found, or FDT_ADDR_T_NONE if not
411 */ 387 */
412 fdt_addr_t fdtdec_get_addr(const void *blob, int node, 388 fdt_addr_t fdtdec_get_addr(const void *blob, int node,
413 const char *prop_name); 389 const char *prop_name);
414 390
415 /* 391 /*
416 * Look up an address property in a node and return the parsed address, and 392 * Look up an address property in a node and return the parsed address, and
417 * optionally the parsed size. 393 * optionally the parsed size.
418 * 394 *
419 * This variant hard-codes the number of cells used to represent the address 395 * This variant hard-codes the number of cells used to represent the address
420 * and size based on sizeof(fdt_addr_t) and sizeof(fdt_size_t). It also 396 * and size based on sizeof(fdt_addr_t) and sizeof(fdt_size_t). It also
421 * always returns the first address value in the property (index 0). 397 * always returns the first address value in the property (index 0).
422 * 398 *
423 * Use of this function is not recommended due to the hard-coding of cell 399 * Use of this function is not recommended due to the hard-coding of cell
424 * counts. There is no programmatic validation that these hard-coded values 400 * counts. There is no programmatic validation that these hard-coded values
425 * actually match the device tree content in any way at all. This assumption 401 * actually match the device tree content in any way at all. This assumption
426 * can be satisfied by manually ensuring CONFIG_PHYS_64BIT is appropriately 402 * can be satisfied by manually ensuring CONFIG_PHYS_64BIT is appropriately
427 * set in the U-Boot build and exercising strict control over DT content to 403 * set in the U-Boot build and exercising strict control over DT content to
428 * ensure use of matching #address-cells/#size-cells properties. However, this 404 * ensure use of matching #address-cells/#size-cells properties. However, this
429 * approach is error-prone; those familiar with DT will not expect the 405 * approach is error-prone; those familiar with DT will not expect the
430 * assumption to exist, and could easily invalidate it. If the assumption is 406 * assumption to exist, and could easily invalidate it. If the assumption is
431 * invalidated, this function will not report the issue, and debugging will 407 * invalidated, this function will not report the issue, and debugging will
432 * be required. Instead, use fdtdec_get_addr_size_auto_parent(). 408 * be required. Instead, use fdtdec_get_addr_size_auto_parent().
433 * 409 *
434 * @param blob FDT blob 410 * @param blob FDT blob
435 * @param node node to examine 411 * @param node node to examine
436 * @param prop_name name of property to find 412 * @param prop_name name of property to find
437 * @param sizep a pointer to store the size into. Use NULL if not required 413 * @param sizep a pointer to store the size into. Use NULL if not required
438 * @return address, if found, or FDT_ADDR_T_NONE if not 414 * @return address, if found, or FDT_ADDR_T_NONE if not
439 */ 415 */
440 fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, 416 fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
441 const char *prop_name, fdt_size_t *sizep); 417 const char *prop_name, fdt_size_t *sizep);
442 418
443 /** 419 /**
444 * Look at an address property in a node and return the pci address which 420 * Look at an address property in a node and return the pci address which
445 * corresponds to the given type in the form of fdt_pci_addr. 421 * corresponds to the given type in the form of fdt_pci_addr.
446 * The property must hold one fdt_pci_addr with a lengh. 422 * The property must hold one fdt_pci_addr with a lengh.
447 * 423 *
448 * @param blob FDT blob 424 * @param blob FDT blob
449 * @param node node to examine 425 * @param node node to examine
450 * @param type pci address type (FDT_PCI_SPACE_xxx) 426 * @param type pci address type (FDT_PCI_SPACE_xxx)
451 * @param prop_name name of property to find 427 * @param prop_name name of property to find
452 * @param addr returns pci address in the form of fdt_pci_addr 428 * @param addr returns pci address in the form of fdt_pci_addr
453 * @return 0 if ok, -ENOENT if the property did not exist, -EINVAL if the 429 * @return 0 if ok, -ENOENT if the property did not exist, -EINVAL if the
454 * format of the property was invalid, -ENXIO if the requested 430 * format of the property was invalid, -ENXIO if the requested
455 * address type was not found 431 * address type was not found
456 */ 432 */
457 int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, 433 int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
458 const char *prop_name, struct fdt_pci_addr *addr); 434 const char *prop_name, struct fdt_pci_addr *addr);
459 435
460 /** 436 /**
461 * Look at the compatible property of a device node that represents a PCI 437 * Look at the compatible property of a device node that represents a PCI
462 * device and extract pci vendor id and device id from it. 438 * device and extract pci vendor id and device id from it.
463 * 439 *
464 * @param blob FDT blob 440 * @param blob FDT blob
465 * @param node node to examine 441 * @param node node to examine
466 * @param vendor vendor id of the pci device 442 * @param vendor vendor id of the pci device
467 * @param device device id of the pci device 443 * @param device device id of the pci device
468 * @return 0 if ok, negative on error 444 * @return 0 if ok, negative on error
469 */ 445 */
470 int fdtdec_get_pci_vendev(const void *blob, int node, 446 int fdtdec_get_pci_vendev(const void *blob, int node,
471 u16 *vendor, u16 *device); 447 u16 *vendor, u16 *device);
472 448
473 /** 449 /**
474 * Look at the pci address of a device node that represents a PCI device 450 * Look at the pci address of a device node that represents a PCI device
475 * and return base address of the pci device's registers. 451 * and return base address of the pci device's registers.
476 * 452 *
477 * @param dev device to examine 453 * @param dev device to examine
478 * @param addr pci address in the form of fdt_pci_addr 454 * @param addr pci address in the form of fdt_pci_addr
479 * @param bar returns base address of the pci device's registers 455 * @param bar returns base address of the pci device's registers
480 * @return 0 if ok, negative on error 456 * @return 0 if ok, negative on error
481 */ 457 */
482 int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr, 458 int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr,
483 u32 *bar); 459 u32 *bar);
484 460
485 /** 461 /**
486 * Look up a 32-bit integer property in a node and return it. The property 462 * Look up a 32-bit integer property in a node and return it. The property
487 * must have at least 4 bytes of data. The value of the first cell is 463 * must have at least 4 bytes of data. The value of the first cell is
488 * returned. 464 * returned.
489 * 465 *
490 * @param blob FDT blob 466 * @param blob FDT blob
491 * @param node node to examine 467 * @param node node to examine
492 * @param prop_name name of property to find 468 * @param prop_name name of property to find
493 * @param default_val default value to return if the property is not found 469 * @param default_val default value to return if the property is not found
494 * @return integer value, if found, or default_val if not 470 * @return integer value, if found, or default_val if not
495 */ 471 */
496 s32 fdtdec_get_int(const void *blob, int node, const char *prop_name, 472 s32 fdtdec_get_int(const void *blob, int node, const char *prop_name,
497 s32 default_val); 473 s32 default_val);
498 474
499 /** 475 /**
500 * Unsigned version of fdtdec_get_int. The property must have at least 476 * Unsigned version of fdtdec_get_int. The property must have at least
501 * 4 bytes of data. The value of the first cell is returned. 477 * 4 bytes of data. The value of the first cell is returned.
502 * 478 *
503 * @param blob FDT blob 479 * @param blob FDT blob
504 * @param node node to examine 480 * @param node node to examine
505 * @param prop_name name of property to find 481 * @param prop_name name of property to find
506 * @param default_val default value to return if the property is not found 482 * @param default_val default value to return if the property is not found
507 * @return unsigned integer value, if found, or default_val if not 483 * @return unsigned integer value, if found, or default_val if not
508 */ 484 */
509 unsigned int fdtdec_get_uint(const void *blob, int node, const char *prop_name, 485 unsigned int fdtdec_get_uint(const void *blob, int node, const char *prop_name,
510 unsigned int default_val); 486 unsigned int default_val);
511 487
512 /** 488 /**
513 * Get a variable-sized number from a property 489 * Get a variable-sized number from a property
514 * 490 *
515 * This reads a number from one or more cells. 491 * This reads a number from one or more cells.
516 * 492 *
517 * @param ptr Pointer to property 493 * @param ptr Pointer to property
518 * @param cells Number of cells containing the number 494 * @param cells Number of cells containing the number
519 * @return the value in the cells 495 * @return the value in the cells
520 */ 496 */
521 u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells); 497 u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells);
522 498
523 /** 499 /**
524 * Look up a 64-bit integer property in a node and return it. The property 500 * Look up a 64-bit integer property in a node and return it. The property
525 * must have at least 8 bytes of data (2 cells). The first two cells are 501 * must have at least 8 bytes of data (2 cells). The first two cells are
526 * concatenated to form a 8 bytes value, where the first cell is top half and 502 * concatenated to form a 8 bytes value, where the first cell is top half and
527 * the second cell is bottom half. 503 * the second cell is bottom half.
528 * 504 *
529 * @param blob FDT blob 505 * @param blob FDT blob
530 * @param node node to examine 506 * @param node node to examine
531 * @param prop_name name of property to find 507 * @param prop_name name of property to find
532 * @param default_val default value to return if the property is not found 508 * @param default_val default value to return if the property is not found
533 * @return integer value, if found, or default_val if not 509 * @return integer value, if found, or default_val if not
534 */ 510 */
535 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name, 511 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
536 uint64_t default_val); 512 uint64_t default_val);
537 513
538 /** 514 /**
539 * Checks whether a node is enabled. 515 * Checks whether a node is enabled.
540 * This looks for a 'status' property. If this exists, then returns 1 if 516 * This looks for a 'status' property. If this exists, then returns 1 if
541 * the status is 'ok' and 0 otherwise. If there is no status property, 517 * the status is 'ok' and 0 otherwise. If there is no status property,
542 * it returns 1 on the assumption that anything mentioned should be enabled 518 * it returns 1 on the assumption that anything mentioned should be enabled
543 * by default. 519 * by default.
544 * 520 *
545 * @param blob FDT blob 521 * @param blob FDT blob
546 * @param node node to examine 522 * @param node node to examine
547 * @return integer value 0 (not enabled) or 1 (enabled) 523 * @return integer value 0 (not enabled) or 1 (enabled)
548 */ 524 */
549 int fdtdec_get_is_enabled(const void *blob, int node); 525 int fdtdec_get_is_enabled(const void *blob, int node);
550 526
551 /** 527 /**
552 * Make sure we have a valid fdt available to control U-Boot. 528 * Make sure we have a valid fdt available to control U-Boot.
553 * 529 *
554 * If not, a message is printed to the console if the console is ready. 530 * If not, a message is printed to the console if the console is ready.
555 * 531 *
556 * @return 0 if all ok, -1 if not 532 * @return 0 if all ok, -1 if not
557 */ 533 */
558 int fdtdec_prepare_fdt(void); 534 int fdtdec_prepare_fdt(void);
559 535
560 /** 536 /**
561 * Checks that we have a valid fdt available to control U-Boot. 537 * Checks that we have a valid fdt available to control U-Boot.
562 538
563 * However, if not then for the moment nothing is done, since this function 539 * However, if not then for the moment nothing is done, since this function
564 * is called too early to panic(). 540 * is called too early to panic().
565 * 541 *
566 * @returns 0 542 * @returns 0
567 */ 543 */
568 int fdtdec_check_fdt(void); 544 int fdtdec_check_fdt(void);
569 545
570 /** 546 /**
571 * Find the nodes for a peripheral and return a list of them in the correct 547 * Find the nodes for a peripheral and return a list of them in the correct
572 * order. This is used to enumerate all the peripherals of a certain type. 548 * order. This is used to enumerate all the peripherals of a certain type.
573 * 549 *
574 * To use this, optionally set up a /aliases node with alias properties for 550 * To use this, optionally set up a /aliases node with alias properties for
575 * a peripheral. For example, for usb you could have: 551 * a peripheral. For example, for usb you could have:
576 * 552 *
577 * aliases { 553 * aliases {
578 * usb0 = "/ehci@c5008000"; 554 * usb0 = "/ehci@c5008000";
579 * usb1 = "/ehci@c5000000"; 555 * usb1 = "/ehci@c5000000";
580 * }; 556 * };
581 * 557 *
582 * Pass "usb" as the name to this function and will return a list of two 558 * Pass "usb" as the name to this function and will return a list of two
583 * nodes offsets: /ehci@c5008000 and ehci@c5000000. 559 * nodes offsets: /ehci@c5008000 and ehci@c5000000.
584 * 560 *
585 * All nodes returned will match the compatible ID, as it is assumed that 561 * All nodes returned will match the compatible ID, as it is assumed that
586 * all peripherals use the same driver. 562 * all peripherals use the same driver.
587 * 563 *
588 * If no alias node is found, then the node list will be returned in the 564 * If no alias node is found, then the node list will be returned in the
589 * order found in the fdt. If the aliases mention a node which doesn't 565 * order found in the fdt. If the aliases mention a node which doesn't
590 * exist, then this will be ignored. If nodes are found with no aliases, 566 * exist, then this will be ignored. If nodes are found with no aliases,
591 * they will be added in any order. 567 * they will be added in any order.
592 * 568 *
593 * If there is a gap in the aliases, then this function return a 0 node at 569 * If there is a gap in the aliases, then this function return a 0 node at
594 * that position. The return value will also count these gaps. 570 * that position. The return value will also count these gaps.
595 * 571 *
596 * This function checks node properties and will not return nodes which are 572 * This function checks node properties and will not return nodes which are
597 * marked disabled (status = "disabled"). 573 * marked disabled (status = "disabled").
598 * 574 *
599 * @param blob FDT blob to use 575 * @param blob FDT blob to use
600 * @param name Root name of alias to search for 576 * @param name Root name of alias to search for
601 * @param id Compatible ID to look for 577 * @param id Compatible ID to look for
602 * @param node_list Place to put list of found nodes 578 * @param node_list Place to put list of found nodes
603 * @param maxcount Maximum number of nodes to find 579 * @param maxcount Maximum number of nodes to find
604 * @return number of nodes found on success, FDT_ERR_... on error 580 * @return number of nodes found on success, FDT_ERR_... on error
605 */ 581 */
606 int fdtdec_find_aliases_for_id(const void *blob, const char *name, 582 int fdtdec_find_aliases_for_id(const void *blob, const char *name,
607 enum fdt_compat_id id, int *node_list, int maxcount); 583 enum fdt_compat_id id, int *node_list, int maxcount);
608 584
609 /* 585 /*
610 * This function is similar to fdtdec_find_aliases_for_id() except that it 586 * This function is similar to fdtdec_find_aliases_for_id() except that it
611 * adds to the node_list that is passed in. Any 0 elements are considered 587 * adds to the node_list that is passed in. Any 0 elements are considered
612 * available for allocation - others are considered already used and are 588 * available for allocation - others are considered already used and are
613 * skipped. 589 * skipped.
614 * 590 *
615 * You can use this by calling fdtdec_find_aliases_for_id() with an 591 * You can use this by calling fdtdec_find_aliases_for_id() with an
616 * uninitialised array, then setting the elements that are returned to -1, 592 * uninitialised array, then setting the elements that are returned to -1,
617 * say, then calling this function, perhaps with a different compat id. 593 * say, then calling this function, perhaps with a different compat id.
618 * Any elements you get back that are >0 are new nodes added by the call 594 * Any elements you get back that are >0 are new nodes added by the call
619 * to this function. 595 * to this function.
620 * 596 *
621 * Note that if you have some nodes with aliases and some without, you are 597 * Note that if you have some nodes with aliases and some without, you are
622 * sailing close to the wind. The call to fdtdec_find_aliases_for_id() with 598 * sailing close to the wind. The call to fdtdec_find_aliases_for_id() with
623 * one compat_id may fill in positions for which you have aliases defined 599 * one compat_id may fill in positions for which you have aliases defined
624 * for another compat_id. When you later call *this* function with the second 600 * for another compat_id. When you later call *this* function with the second
625 * compat_id, the alias positions may already be used. A debug warning may 601 * compat_id, the alias positions may already be used. A debug warning may
626 * be generated in this case, but it is safest to define aliases for all 602 * be generated in this case, but it is safest to define aliases for all
627 * nodes when you care about the ordering. 603 * nodes when you care about the ordering.
628 */ 604 */
629 int fdtdec_add_aliases_for_id(const void *blob, const char *name, 605 int fdtdec_add_aliases_for_id(const void *blob, const char *name,
630 enum fdt_compat_id id, int *node_list, int maxcount); 606 enum fdt_compat_id id, int *node_list, int maxcount);
631 607
632 /** 608 /**
633 * Get the alias sequence number of a node 609 * Get the alias sequence number of a node
634 * 610 *
635 * This works out whether a node is pointed to by an alias, and if so, the 611 * This works out whether a node is pointed to by an alias, and if so, the
636 * sequence number of that alias. Aliases are of the form <base><num> where 612 * sequence number of that alias. Aliases are of the form <base><num> where
637 * <num> is the sequence number. For example spi2 would be sequence number 613 * <num> is the sequence number. For example spi2 would be sequence number
638 * 2. 614 * 2.
639 * 615 *
640 * @param blob Device tree blob (if NULL, then error is returned) 616 * @param blob Device tree blob (if NULL, then error is returned)
641 * @param base Base name for alias (before the underscore) 617 * @param base Base name for alias (before the underscore)
642 * @param node Node to look up 618 * @param node Node to look up
643 * @param seqp This is set to the sequence number if one is found, 619 * @param seqp This is set to the sequence number if one is found,
644 * but otherwise the value is left alone 620 * but otherwise the value is left alone
645 * @return 0 if a sequence was found, -ve if not 621 * @return 0 if a sequence was found, -ve if not
646 */ 622 */
647 int fdtdec_get_alias_seq(const void *blob, const char *base, int node, 623 int fdtdec_get_alias_seq(const void *blob, const char *base, int node,
648 int *seqp); 624 int *seqp);
649 625
650 /** 626 /**
651 * Get the highest alias number for susbystem. 627 * Get the highest alias number for susbystem.
652 * 628 *
653 * It parses all aliases and find out highest recorded alias for subsystem. 629 * It parses all aliases and find out highest recorded alias for subsystem.
654 * Aliases are of the form <base><num> where <num> is the sequence number. 630 * Aliases are of the form <base><num> where <num> is the sequence number.
655 * 631 *
656 * @param blob Device tree blob (if NULL, then error is returned) 632 * @param blob Device tree blob (if NULL, then error is returned)
657 * @param base Base name for alias susbystem (before the number) 633 * @param base Base name for alias susbystem (before the number)
658 * 634 *
659 * @return 0 highest alias ID, -1 if not found 635 * @return 0 highest alias ID, -1 if not found
660 */ 636 */
661 int fdtdec_get_alias_highest_id(const void *blob, const char *base); 637 int fdtdec_get_alias_highest_id(const void *blob, const char *base);
662 638
663 /** 639 /**
664 * Get a property from the /chosen node 640 * Get a property from the /chosen node
665 * 641 *
666 * @param blob Device tree blob (if NULL, then NULL is returned) 642 * @param blob Device tree blob (if NULL, then NULL is returned)
667 * @param name Property name to look up 643 * @param name Property name to look up
668 * @return Value of property, or NULL if it does not exist 644 * @return Value of property, or NULL if it does not exist
669 */ 645 */
670 const char *fdtdec_get_chosen_prop(const void *blob, const char *name); 646 const char *fdtdec_get_chosen_prop(const void *blob, const char *name);
671 647
672 /** 648 /**
673 * Get the offset of the given /chosen node 649 * Get the offset of the given /chosen node
674 * 650 *
675 * This looks up a property in /chosen containing the path to another node, 651 * This looks up a property in /chosen containing the path to another node,
676 * then finds the offset of that node. 652 * then finds the offset of that node.
677 * 653 *
678 * @param blob Device tree blob (if NULL, then error is returned) 654 * @param blob Device tree blob (if NULL, then error is returned)
679 * @param name Property name, e.g. "stdout-path" 655 * @param name Property name, e.g. "stdout-path"
680 * @return Node offset referred to by that chosen node, or -ve FDT_ERR_... 656 * @return Node offset referred to by that chosen node, or -ve FDT_ERR_...
681 */ 657 */
682 int fdtdec_get_chosen_node(const void *blob, const char *name); 658 int fdtdec_get_chosen_node(const void *blob, const char *name);
683 659
684 /* 660 /*
685 * Get the name for a compatible ID 661 * Get the name for a compatible ID
686 * 662 *
687 * @param id Compatible ID to look for 663 * @param id Compatible ID to look for
688 * @return compatible string for that id 664 * @return compatible string for that id
689 */ 665 */
690 const char *fdtdec_get_compatible(enum fdt_compat_id id); 666 const char *fdtdec_get_compatible(enum fdt_compat_id id);
691 667
692 /* Look up a phandle and follow it to its node. Then return the offset 668 /* Look up a phandle and follow it to its node. Then return the offset
693 * of that node. 669 * of that node.
694 * 670 *
695 * @param blob FDT blob 671 * @param blob FDT blob
696 * @param node node to examine 672 * @param node node to examine
697 * @param prop_name name of property to find 673 * @param prop_name name of property to find
698 * @return node offset if found, -ve error code on error 674 * @return node offset if found, -ve error code on error
699 */ 675 */
700 int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name); 676 int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name);
701 677
702 /** 678 /**
703 * Look up a property in a node and return its contents in an integer 679 * Look up a property in a node and return its contents in an integer
704 * array of given length. The property must have at least enough data for 680 * array of given length. The property must have at least enough data for
705 * the array (4*count bytes). It may have more, but this will be ignored. 681 * the array (4*count bytes). It may have more, but this will be ignored.
706 * 682 *
707 * @param blob FDT blob 683 * @param blob FDT blob
708 * @param node node to examine 684 * @param node node to examine
709 * @param prop_name name of property to find 685 * @param prop_name name of property to find
710 * @param array array to fill with data 686 * @param array array to fill with data
711 * @param count number of array elements 687 * @param count number of array elements
712 * @return 0 if ok, or -FDT_ERR_NOTFOUND if the property is not found, 688 * @return 0 if ok, or -FDT_ERR_NOTFOUND if the property is not found,
713 * or -FDT_ERR_BADLAYOUT if not enough data 689 * or -FDT_ERR_BADLAYOUT if not enough data
714 */ 690 */
715 int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, 691 int fdtdec_get_int_array(const void *blob, int node, const char *prop_name,
716 u32 *array, int count); 692 u32 *array, int count);
717 693
718 /** 694 /**
719 * Look up a property in a node and return its contents in an integer 695 * Look up a property in a node and return its contents in an integer
720 * array of given length. The property must exist but may have less data that 696 * array of given length. The property must exist but may have less data that
721 * expected (4*count bytes). It may have more, but this will be ignored. 697 * expected (4*count bytes). It may have more, but this will be ignored.
722 * 698 *
723 * @param blob FDT blob 699 * @param blob FDT blob
724 * @param node node to examine 700 * @param node node to examine
725 * @param prop_name name of property to find 701 * @param prop_name name of property to find
726 * @param array array to fill with data 702 * @param array array to fill with data
727 * @param count number of array elements 703 * @param count number of array elements
728 * @return number of array elements if ok, or -FDT_ERR_NOTFOUND if the 704 * @return number of array elements if ok, or -FDT_ERR_NOTFOUND if the
729 * property is not found 705 * property is not found
730 */ 706 */
731 int fdtdec_get_int_array_count(const void *blob, int node, 707 int fdtdec_get_int_array_count(const void *blob, int node,
732 const char *prop_name, u32 *array, int count); 708 const char *prop_name, u32 *array, int count);
733 709
734 /** 710 /**
735 * Look up a property in a node and return a pointer to its contents as a 711 * Look up a property in a node and return a pointer to its contents as a
736 * unsigned int array of given length. The property must have at least enough 712 * unsigned int array of given length. The property must have at least enough
737 * data for the array ('count' cells). It may have more, but this will be 713 * data for the array ('count' cells). It may have more, but this will be
738 * ignored. The data is not copied. 714 * ignored. The data is not copied.
739 * 715 *
740 * Note that you must access elements of the array with fdt32_to_cpu(), 716 * Note that you must access elements of the array with fdt32_to_cpu(),
741 * since the elements will be big endian even on a little endian machine. 717 * since the elements will be big endian even on a little endian machine.
742 * 718 *
743 * @param blob FDT blob 719 * @param blob FDT blob
744 * @param node node to examine 720 * @param node node to examine
745 * @param prop_name name of property to find 721 * @param prop_name name of property to find
746 * @param count number of array elements 722 * @param count number of array elements
747 * @return pointer to array if found, or NULL if the property is not 723 * @return pointer to array if found, or NULL if the property is not
748 * found or there is not enough data 724 * found or there is not enough data
749 */ 725 */
750 const u32 *fdtdec_locate_array(const void *blob, int node, 726 const u32 *fdtdec_locate_array(const void *blob, int node,
751 const char *prop_name, int count); 727 const char *prop_name, int count);
752 728
753 /** 729 /**
754 * Look up a boolean property in a node and return it. 730 * Look up a boolean property in a node and return it.
755 * 731 *
756 * A boolean properly is true if present in the device tree and false if not 732 * A boolean properly is true if present in the device tree and false if not
757 * present, regardless of its value. 733 * present, regardless of its value.
758 * 734 *
759 * @param blob FDT blob 735 * @param blob FDT blob
760 * @param node node to examine 736 * @param node node to examine
761 * @param prop_name name of property to find 737 * @param prop_name name of property to find
762 * @return 1 if the properly is present; 0 if it isn't present 738 * @return 1 if the properly is present; 0 if it isn't present
763 */ 739 */
764 int fdtdec_get_bool(const void *blob, int node, const char *prop_name); 740 int fdtdec_get_bool(const void *blob, int node, const char *prop_name);
765 741
766 /* 742 /*
767 * Count child nodes of one parent node. 743 * Count child nodes of one parent node.
768 * 744 *
769 * @param blob FDT blob 745 * @param blob FDT blob
770 * @param node parent node 746 * @param node parent node
771 * @return number of child node; 0 if there is not child node 747 * @return number of child node; 0 if there is not child node
772 */ 748 */
773 int fdtdec_get_child_count(const void *blob, int node); 749 int fdtdec_get_child_count(const void *blob, int node);
774 750
775 /** 751 /**
776 * Look in the FDT for a config item with the given name and return its value 752 * Look in the FDT for a config item with the given name and return its value
777 * as a 32-bit integer. The property must have at least 4 bytes of data. The 753 * as a 32-bit integer. The property must have at least 4 bytes of data. The
778 * value of the first cell is returned. 754 * value of the first cell is returned.
779 * 755 *
780 * @param blob FDT blob to use 756 * @param blob FDT blob to use
781 * @param prop_name Node property name 757 * @param prop_name Node property name
782 * @param default_val default value to return if the property is not found 758 * @param default_val default value to return if the property is not found
783 * @return integer value, if found, or default_val if not 759 * @return integer value, if found, or default_val if not
784 */ 760 */
785 int fdtdec_get_config_int(const void *blob, const char *prop_name, 761 int fdtdec_get_config_int(const void *blob, const char *prop_name,
786 int default_val); 762 int default_val);
787 763
788 /** 764 /**
789 * Look in the FDT for a config item with the given name 765 * Look in the FDT for a config item with the given name
790 * and return whether it exists. 766 * and return whether it exists.
791 * 767 *
792 * @param blob FDT blob 768 * @param blob FDT blob
793 * @param prop_name property name to look up 769 * @param prop_name property name to look up
794 * @return 1, if it exists, or 0 if not 770 * @return 1, if it exists, or 0 if not
795 */ 771 */
796 int fdtdec_get_config_bool(const void *blob, const char *prop_name); 772 int fdtdec_get_config_bool(const void *blob, const char *prop_name);
797 773
798 /** 774 /**
799 * Look in the FDT for a config item with the given name and return its value 775 * Look in the FDT for a config item with the given name and return its value
800 * as a string. 776 * as a string.
801 * 777 *
802 * @param blob FDT blob 778 * @param blob FDT blob
803 * @param prop_name property name to look up 779 * @param prop_name property name to look up
804 * @returns property string, NULL on error. 780 * @returns property string, NULL on error.
805 */ 781 */
806 char *fdtdec_get_config_string(const void *blob, const char *prop_name); 782 char *fdtdec_get_config_string(const void *blob, const char *prop_name);
807 783
808 /* 784 /*
809 * Look up a property in a node and return its contents in a byte 785 * Look up a property in a node and return its contents in a byte
810 * array of given length. The property must have at least enough data for 786 * array of given length. The property must have at least enough data for
811 * the array (count bytes). It may have more, but this will be ignored. 787 * the array (count bytes). It may have more, but this will be ignored.
812 * 788 *
813 * @param blob FDT blob 789 * @param blob FDT blob
814 * @param node node to examine 790 * @param node node to examine
815 * @param prop_name name of property to find 791 * @param prop_name name of property to find
816 * @param array array to fill with data 792 * @param array array to fill with data
817 * @param count number of array elements 793 * @param count number of array elements
818 * @return 0 if ok, or -FDT_ERR_MISSING if the property is not found, 794 * @return 0 if ok, or -FDT_ERR_MISSING if the property is not found,
819 * or -FDT_ERR_BADLAYOUT if not enough data 795 * or -FDT_ERR_BADLAYOUT if not enough data
820 */ 796 */
821 int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name, 797 int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name,
822 u8 *array, int count); 798 u8 *array, int count);
823 799
824 /** 800 /**
825 * Look up a property in a node and return a pointer to its contents as a 801 * Look up a property in a node and return a pointer to its contents as a
826 * byte array of given length. The property must have at least enough data 802 * byte array of given length. The property must have at least enough data
827 * for the array (count bytes). It may have more, but this will be ignored. 803 * for the array (count bytes). It may have more, but this will be ignored.
828 * The data is not copied. 804 * The data is not copied.
829 * 805 *
830 * @param blob FDT blob 806 * @param blob FDT blob
831 * @param node node to examine 807 * @param node node to examine
832 * @param prop_name name of property to find 808 * @param prop_name name of property to find
833 * @param count number of array elements 809 * @param count number of array elements
834 * @return pointer to byte array if found, or NULL if the property is not 810 * @return pointer to byte array if found, or NULL if the property is not
835 * found or there is not enough data 811 * found or there is not enough data
836 */ 812 */
837 const u8 *fdtdec_locate_byte_array(const void *blob, int node, 813 const u8 *fdtdec_locate_byte_array(const void *blob, int node,
838 const char *prop_name, int count); 814 const char *prop_name, int count);
839 815
840 /** 816 /**
841 * Obtain an indexed resource from a device property. 817 * Obtain an indexed resource from a device property.
842 * 818 *
843 * @param fdt FDT blob 819 * @param fdt FDT blob
844 * @param node node to examine 820 * @param node node to examine
845 * @param property name of the property to parse 821 * @param property name of the property to parse
846 * @param index index of the resource to retrieve 822 * @param index index of the resource to retrieve
847 * @param res returns the resource 823 * @param res returns the resource
848 * @return 0 if ok, negative on error 824 * @return 0 if ok, negative on error
849 */ 825 */
850 int fdt_get_resource(const void *fdt, int node, const char *property, 826 int fdt_get_resource(const void *fdt, int node, const char *property,
851 unsigned int index, struct fdt_resource *res); 827 unsigned int index, struct fdt_resource *res);
852 828
853 /** 829 /**
854 * Obtain a named resource from a device property. 830 * Obtain a named resource from a device property.
855 * 831 *
856 * Look up the index of the name in a list of strings and return the resource 832 * Look up the index of the name in a list of strings and return the resource
857 * at that index. 833 * at that index.
858 * 834 *
859 * @param fdt FDT blob 835 * @param fdt FDT blob
860 * @param node node to examine 836 * @param node node to examine
861 * @param property name of the property to parse 837 * @param property name of the property to parse
862 * @param prop_names name of the property containing the list of names 838 * @param prop_names name of the property containing the list of names
863 * @param name the name of the entry to look up 839 * @param name the name of the entry to look up
864 * @param res returns the resource 840 * @param res returns the resource
865 */ 841 */
866 int fdt_get_named_resource(const void *fdt, int node, const char *property, 842 int fdt_get_named_resource(const void *fdt, int node, const char *property,
867 const char *prop_names, const char *name, 843 const char *prop_names, const char *name,
868 struct fdt_resource *res); 844 struct fdt_resource *res);
869 845
870 /* Display timings from linux include/video/display_timing.h */ 846 /* Display timings from linux include/video/display_timing.h */
871 enum display_flags { 847 enum display_flags {
872 DISPLAY_FLAGS_HSYNC_LOW = 1 << 0, 848 DISPLAY_FLAGS_HSYNC_LOW = 1 << 0,
873 DISPLAY_FLAGS_HSYNC_HIGH = 1 << 1, 849 DISPLAY_FLAGS_HSYNC_HIGH = 1 << 1,
874 DISPLAY_FLAGS_VSYNC_LOW = 1 << 2, 850 DISPLAY_FLAGS_VSYNC_LOW = 1 << 2,
875 DISPLAY_FLAGS_VSYNC_HIGH = 1 << 3, 851 DISPLAY_FLAGS_VSYNC_HIGH = 1 << 3,
876 852
877 /* data enable flag */ 853 /* data enable flag */
878 DISPLAY_FLAGS_DE_LOW = 1 << 4, 854 DISPLAY_FLAGS_DE_LOW = 1 << 4,
879 DISPLAY_FLAGS_DE_HIGH = 1 << 5, 855 DISPLAY_FLAGS_DE_HIGH = 1 << 5,
880 /* drive data on pos. edge */ 856 /* drive data on pos. edge */
881 DISPLAY_FLAGS_PIXDATA_POSEDGE = 1 << 6, 857 DISPLAY_FLAGS_PIXDATA_POSEDGE = 1 << 6,
882 /* drive data on neg. edge */ 858 /* drive data on neg. edge */
883 DISPLAY_FLAGS_PIXDATA_NEGEDGE = 1 << 7, 859 DISPLAY_FLAGS_PIXDATA_NEGEDGE = 1 << 7,
884 DISPLAY_FLAGS_INTERLACED = 1 << 8, 860 DISPLAY_FLAGS_INTERLACED = 1 << 8,
885 DISPLAY_FLAGS_DOUBLESCAN = 1 << 9, 861 DISPLAY_FLAGS_DOUBLESCAN = 1 << 9,
886 DISPLAY_FLAGS_DOUBLECLK = 1 << 10, 862 DISPLAY_FLAGS_DOUBLECLK = 1 << 10,
887 }; 863 };
888 864
889 /* 865 /*
890 * A single signal can be specified via a range of minimal and maximal values 866 * A single signal can be specified via a range of minimal and maximal values
891 * with a typical value, that lies somewhere inbetween. 867 * with a typical value, that lies somewhere inbetween.
892 */ 868 */
893 struct timing_entry { 869 struct timing_entry {
894 u32 min; 870 u32 min;
895 u32 typ; 871 u32 typ;
896 u32 max; 872 u32 max;
897 }; 873 };
898 874
899 /* 875 /*
900 * Single "mode" entry. This describes one set of signal timings a display can 876 * Single "mode" entry. This describes one set of signal timings a display can
901 * have in one setting. This struct can later be converted to struct videomode 877 * have in one setting. This struct can later be converted to struct videomode
902 * (see include/video/videomode.h). As each timing_entry can be defined as a 878 * (see include/video/videomode.h). As each timing_entry can be defined as a
903 * range, one struct display_timing may become multiple struct videomodes. 879 * range, one struct display_timing may become multiple struct videomodes.
904 * 880 *
905 * Example: hsync active high, vsync active low 881 * Example: hsync active high, vsync active low
906 * 882 *
907 * Active Video 883 * Active Video
908 * Video ______________________XXXXXXXXXXXXXXXXXXXXXX_____________________ 884 * Video ______________________XXXXXXXXXXXXXXXXXXXXXX_____________________
909 * |<- sync ->|<- back ->|<----- active ----->|<- front ->|<- sync.. 885 * |<- sync ->|<- back ->|<----- active ----->|<- front ->|<- sync..
910 * | | porch | | porch | 886 * | | porch | | porch |
911 * 887 *
912 * HSync _|ยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏ|___________________________________________|ยฏยฏยฏยฏยฏยฏยฏยฏยฏ 888 * HSync _|ยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏ|___________________________________________|ยฏยฏยฏยฏยฏยฏยฏยฏยฏ
913 * 889 *
914 * VSync ยฏ|__________|ยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏ|_________ 890 * VSync ยฏ|__________|ยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏยฏ|_________
915 */ 891 */
916 struct display_timing { 892 struct display_timing {
917 struct timing_entry pixelclock; 893 struct timing_entry pixelclock;
918 894
919 struct timing_entry hactive; /* hor. active video */ 895 struct timing_entry hactive; /* hor. active video */
920 struct timing_entry hfront_porch; /* hor. front porch */ 896 struct timing_entry hfront_porch; /* hor. front porch */
921 struct timing_entry hback_porch; /* hor. back porch */ 897 struct timing_entry hback_porch; /* hor. back porch */
922 struct timing_entry hsync_len; /* hor. sync len */ 898 struct timing_entry hsync_len; /* hor. sync len */
923 899
924 struct timing_entry vactive; /* ver. active video */ 900 struct timing_entry vactive; /* ver. active video */
925 struct timing_entry vfront_porch; /* ver. front porch */ 901 struct timing_entry vfront_porch; /* ver. front porch */
926 struct timing_entry vback_porch; /* ver. back porch */ 902 struct timing_entry vback_porch; /* ver. back porch */
927 struct timing_entry vsync_len; /* ver. sync len */ 903 struct timing_entry vsync_len; /* ver. sync len */
928 904
929 enum display_flags flags; /* display flags */ 905 enum display_flags flags; /* display flags */
930 bool hdmi_monitor; /* is hdmi monitor? */ 906 bool hdmi_monitor; /* is hdmi monitor? */
931 }; 907 };
932 908
933 /** 909 /**
934 * fdtdec_decode_display_timing() - decode display timings 910 * fdtdec_decode_display_timing() - decode display timings
935 * 911 *
936 * Decode display timings from the supplied 'display-timings' node. 912 * Decode display timings from the supplied 'display-timings' node.
937 * See doc/device-tree-bindings/video/display-timing.txt for binding 913 * See doc/device-tree-bindings/video/display-timing.txt for binding
938 * information. 914 * information.
939 * 915 *
940 * @param blob FDT blob 916 * @param blob FDT blob
941 * @param node 'display-timing' node containing the timing subnodes 917 * @param node 'display-timing' node containing the timing subnodes
942 * @param index Index number to read (0=first timing subnode) 918 * @param index Index number to read (0=first timing subnode)
943 * @param config Place to put timings 919 * @param config Place to put timings
944 * @return 0 if OK, -FDT_ERR_NOTFOUND if not found 920 * @return 0 if OK, -FDT_ERR_NOTFOUND if not found
945 */ 921 */
946 int fdtdec_decode_display_timing(const void *blob, int node, int index, 922 int fdtdec_decode_display_timing(const void *blob, int node, int index,
947 struct display_timing *config); 923 struct display_timing *config);
948 924
949 /** 925 /**
950 * fdtdec_setup_mem_size_base_fdt() - decode and setup gd->ram_size and 926 * fdtdec_setup_mem_size_base_fdt() - decode and setup gd->ram_size and
951 * gd->ram_start 927 * gd->ram_start
952 * 928 *
953 * Decode the /memory 'reg' property to determine the size and start of the 929 * Decode the /memory 'reg' property to determine the size and start of the
954 * first memory bank, populate the global data with the size and start of the 930 * first memory bank, populate the global data with the size and start of the
955 * first bank of memory. 931 * first bank of memory.
956 * 932 *
957 * This function should be called from a boards dram_init(). This helper 933 * This function should be called from a boards dram_init(). This helper
958 * function allows for boards to query the device tree for DRAM size and start 934 * function allows for boards to query the device tree for DRAM size and start
959 * address instead of hard coding the value in the case where the memory size 935 * address instead of hard coding the value in the case where the memory size
960 * and start address cannot be detected automatically. 936 * and start address cannot be detected automatically.
961 * 937 *
962 * @param blob FDT blob 938 * @param blob FDT blob
963 * 939 *
964 * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or 940 * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
965 * invalid 941 * invalid
966 */ 942 */
967 int fdtdec_setup_mem_size_base_fdt(const void *blob); 943 int fdtdec_setup_mem_size_base_fdt(const void *blob);
968 944
969 /** 945 /**
970 * fdtdec_setup_mem_size_base() - decode and setup gd->ram_size and 946 * fdtdec_setup_mem_size_base() - decode and setup gd->ram_size and
971 * gd->ram_start 947 * gd->ram_start
972 * 948 *
973 * Decode the /memory 'reg' property to determine the size and start of the 949 * Decode the /memory 'reg' property to determine the size and start of the
974 * first memory bank, populate the global data with the size and start of the 950 * first memory bank, populate the global data with the size and start of the
975 * first bank of memory. 951 * first bank of memory.
976 * 952 *
977 * This function should be called from a boards dram_init(). This helper 953 * This function should be called from a boards dram_init(). This helper
978 * function allows for boards to query the device tree for DRAM size and start 954 * function allows for boards to query the device tree for DRAM size and start
979 * address instead of hard coding the value in the case where the memory size 955 * address instead of hard coding the value in the case where the memory size
980 * and start address cannot be detected automatically. 956 * and start address cannot be detected automatically.
981 * 957 *
982 * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or 958 * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
983 * invalid 959 * invalid
984 */ 960 */
985 int fdtdec_setup_mem_size_base(void); 961 int fdtdec_setup_mem_size_base(void);
986 962
987 /** 963 /**
988 * fdtdec_setup_memory_banksize_fdt() - decode and populate gd->bd->bi_dram 964 * fdtdec_setup_memory_banksize_fdt() - decode and populate gd->bd->bi_dram
989 * 965 *
990 * Decode the /memory 'reg' property to determine the address and size of the 966 * Decode the /memory 'reg' property to determine the address and size of the
991 * memory banks. Use this data to populate the global data board info with the 967 * memory banks. Use this data to populate the global data board info with the
992 * phys address and size of memory banks. 968 * phys address and size of memory banks.
993 * 969 *
994 * This function should be called from a boards dram_init_banksize(). This 970 * This function should be called from a boards dram_init_banksize(). This
995 * helper function allows for boards to query the device tree for memory bank 971 * helper function allows for boards to query the device tree for memory bank
996 * information instead of hard coding the information in cases where it cannot 972 * information instead of hard coding the information in cases where it cannot
997 * be detected automatically. 973 * be detected automatically.
998 * 974 *
999 * @param blob FDT blob 975 * @param blob FDT blob
1000 * 976 *
1001 * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or 977 * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
1002 * invalid 978 * invalid
1003 */ 979 */
1004 int fdtdec_setup_memory_banksize_fdt(const void *blob); 980 int fdtdec_setup_memory_banksize_fdt(const void *blob);
1005 981
1006 /** 982 /**
1007 * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram 983 * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram
1008 * 984 *
1009 * Decode the /memory 'reg' property to determine the address and size of the 985 * Decode the /memory 'reg' property to determine the address and size of the
1010 * memory banks. Use this data to populate the global data board info with the 986 * memory banks. Use this data to populate the global data board info with the
1011 * phys address and size of memory banks. 987 * phys address and size of memory banks.
1012 * 988 *
1013 * This function should be called from a boards dram_init_banksize(). This 989 * This function should be called from a boards dram_init_banksize(). This
1014 * helper function allows for boards to query the device tree for memory bank 990 * helper function allows for boards to query the device tree for memory bank
1015 * information instead of hard coding the information in cases where it cannot 991 * information instead of hard coding the information in cases where it cannot
1016 * be detected automatically. 992 * be detected automatically.
1017 * 993 *
1018 * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or 994 * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or
1019 * invalid 995 * invalid
1020 */ 996 */
1021 int fdtdec_setup_memory_banksize(void); 997 int fdtdec_setup_memory_banksize(void);
1022 998
1023 /** 999 /**
1024 * fdtdec_set_phandle() - sets the phandle of a given node 1000 * fdtdec_set_phandle() - sets the phandle of a given node
1025 * 1001 *
1026 * @param blob FDT blob 1002 * @param blob FDT blob
1027 * @param node offset in the FDT blob of the node whose phandle is to 1003 * @param node offset in the FDT blob of the node whose phandle is to
1028 * be set 1004 * be set
1029 * @param phandle phandle to set for the given node 1005 * @param phandle phandle to set for the given node
1030 * @return 0 on success or a negative error code on failure 1006 * @return 0 on success or a negative error code on failure
1031 */ 1007 */
1032 static inline int fdtdec_set_phandle(void *blob, int node, uint32_t phandle) 1008 static inline int fdtdec_set_phandle(void *blob, int node, uint32_t phandle)
1033 { 1009 {
1034 return fdt_setprop_u32(blob, node, "phandle", phandle); 1010 return fdt_setprop_u32(blob, node, "phandle", phandle);
1035 } 1011 }
1036 1012
1037 /** 1013 /**
1038 * fdtdec_add_reserved_memory() - add or find a reserved-memory node 1014 * fdtdec_add_reserved_memory() - add or find a reserved-memory node
1039 * 1015 *
1040 * If a reserved-memory node already exists for the given carveout, a phandle 1016 * If a reserved-memory node already exists for the given carveout, a phandle
1041 * for that node will be returned. Otherwise a new node will be created and a 1017 * for that node will be returned. Otherwise a new node will be created and a
1042 * phandle corresponding to it will be returned. 1018 * phandle corresponding to it will be returned.
1043 * 1019 *
1044 * See Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt 1020 * See Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
1045 * for details on how to use reserved memory regions. 1021 * for details on how to use reserved memory regions.
1046 * 1022 *
1047 * As an example, consider the following code snippet: 1023 * As an example, consider the following code snippet:
1048 * 1024 *
1049 * struct fdt_memory fb = { 1025 * struct fdt_memory fb = {
1050 * .start = 0x92cb3000, 1026 * .start = 0x92cb3000,
1051 * .end = 0x934b2fff, 1027 * .end = 0x934b2fff,
1052 * }; 1028 * };
1053 * uint32_t phandle; 1029 * uint32_t phandle;
1054 * 1030 *
1055 * fdtdec_add_reserved_memory(fdt, "framebuffer", &fb, &phandle); 1031 * fdtdec_add_reserved_memory(fdt, "framebuffer", &fb, &phandle);
1056 * 1032 *
1057 * This results in the following subnode being added to the top-level 1033 * This results in the following subnode being added to the top-level
1058 * /reserved-memory node: 1034 * /reserved-memory node:
1059 * 1035 *
1060 * reserved-memory { 1036 * reserved-memory {
1061 * #address-cells = <0x00000002>; 1037 * #address-cells = <0x00000002>;
1062 * #size-cells = <0x00000002>; 1038 * #size-cells = <0x00000002>;
1063 * ranges; 1039 * ranges;
1064 * 1040 *
1065 * framebuffer@92cb3000 { 1041 * framebuffer@92cb3000 {
1066 * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>; 1042 * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>;
1067 * phandle = <0x0000004d>; 1043 * phandle = <0x0000004d>;
1068 * }; 1044 * };
1069 * }; 1045 * };
1070 * 1046 *
1071 * If the top-level /reserved-memory node does not exist, it will be created. 1047 * If the top-level /reserved-memory node does not exist, it will be created.
1072 * The phandle returned from the function call can be used to reference this 1048 * The phandle returned from the function call can be used to reference this
1073 * reserved memory region from other nodes. 1049 * reserved memory region from other nodes.
1074 * 1050 *
1075 * See fdtdec_set_carveout() for a more elaborate example. 1051 * See fdtdec_set_carveout() for a more elaborate example.
1076 * 1052 *
1077 * @param blob FDT blob 1053 * @param blob FDT blob
1078 * @param basename base name of the node to create 1054 * @param basename base name of the node to create
1079 * @param carveout information about the carveout region 1055 * @param carveout information about the carveout region
1080 * @param phandlep return location for the phandle of the carveout region 1056 * @param phandlep return location for the phandle of the carveout region
1081 * @return 0 on success or a negative error code on failure 1057 * @return 0 on success or a negative error code on failure
1082 */ 1058 */
1083 int fdtdec_add_reserved_memory(void *blob, const char *basename, 1059 int fdtdec_add_reserved_memory(void *blob, const char *basename,
1084 const struct fdt_memory *carveout, 1060 const struct fdt_memory *carveout,
1085 uint32_t *phandlep); 1061 uint32_t *phandlep);
1086 1062
1087 /** 1063 /**
1088 * fdtdec_get_carveout() - reads a carveout from an FDT 1064 * fdtdec_get_carveout() - reads a carveout from an FDT
1089 * 1065 *
1090 * Reads information about a carveout region from an FDT. The carveout is a 1066 * Reads information about a carveout region from an FDT. The carveout is a
1091 * referenced by its phandle that is read from a given property in a given 1067 * referenced by its phandle that is read from a given property in a given
1092 * node. 1068 * node.
1093 * 1069 *
1094 * @param blob FDT blob 1070 * @param blob FDT blob
1095 * @param node name of a node 1071 * @param node name of a node
1096 * @param name name of the property in the given node that contains 1072 * @param name name of the property in the given node that contains
1097 * the phandle for the carveout 1073 * the phandle for the carveout
1098 * @param index index of the phandle for which to read the carveout 1074 * @param index index of the phandle for which to read the carveout
1099 * @param carveout return location for the carveout information 1075 * @param carveout return location for the carveout information
1100 * @return 0 on success or a negative error code on failure 1076 * @return 0 on success or a negative error code on failure
1101 */ 1077 */
1102 int fdtdec_get_carveout(const void *blob, const char *node, const char *name, 1078 int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
1103 unsigned int index, struct fdt_memory *carveout); 1079 unsigned int index, struct fdt_memory *carveout);
1104 1080
1105 /** 1081 /**
1106 * fdtdec_set_carveout() - sets a carveout region for a given node 1082 * fdtdec_set_carveout() - sets a carveout region for a given node
1107 * 1083 *
1108 * Sets a carveout region for a given node. If a reserved-memory node already 1084 * Sets a carveout region for a given node. If a reserved-memory node already
1109 * exists for the carveout, the phandle for that node will be reused. If no 1085 * exists for the carveout, the phandle for that node will be reused. If no
1110 * such node exists, a new one will be created and a phandle to it stored in 1086 * such node exists, a new one will be created and a phandle to it stored in
1111 * a specified property of the given node. 1087 * a specified property of the given node.
1112 * 1088 *
1113 * As an example, consider the following code snippet: 1089 * As an example, consider the following code snippet:
1114 * 1090 *
1115 * const char *node = "/host1x@50000000/dc@54240000"; 1091 * const char *node = "/host1x@50000000/dc@54240000";
1116 * struct fdt_memory fb = { 1092 * struct fdt_memory fb = {
1117 * .start = 0x92cb3000, 1093 * .start = 0x92cb3000,
1118 * .end = 0x934b2fff, 1094 * .end = 0x934b2fff,
1119 * }; 1095 * };
1120 * 1096 *
1121 * fdtdec_set_carveout(fdt, node, "memory-region", 0, "framebuffer", &fb); 1097 * fdtdec_set_carveout(fdt, node, "memory-region", 0, "framebuffer", &fb);
1122 * 1098 *
1123 * dc@54200000 is a display controller and was set up by the bootloader to 1099 * dc@54200000 is a display controller and was set up by the bootloader to
1124 * scan out the framebuffer specified by "fb". This would cause the following 1100 * scan out the framebuffer specified by "fb". This would cause the following
1125 * reserved memory region to be added: 1101 * reserved memory region to be added:
1126 * 1102 *
1127 * reserved-memory { 1103 * reserved-memory {
1128 * #address-cells = <0x00000002>; 1104 * #address-cells = <0x00000002>;
1129 * #size-cells = <0x00000002>; 1105 * #size-cells = <0x00000002>;
1130 * ranges; 1106 * ranges;
1131 * 1107 *
1132 * framebuffer@92cb3000 { 1108 * framebuffer@92cb3000 {
1133 * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>; 1109 * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>;
1134 * phandle = <0x0000004d>; 1110 * phandle = <0x0000004d>;
1135 * }; 1111 * };
1136 * }; 1112 * };
1137 * 1113 *
1138 * A "memory-region" property will also be added to the node referenced by the 1114 * A "memory-region" property will also be added to the node referenced by the
1139 * offset parameter. 1115 * offset parameter.
1140 * 1116 *
1141 * host1x@50000000 { 1117 * host1x@50000000 {
1142 * ... 1118 * ...
1143 * 1119 *
1144 * dc@54240000 { 1120 * dc@54240000 {
1145 * ... 1121 * ...
1146 * memory-region = <0x0000004d>; 1122 * memory-region = <0x0000004d>;
1147 * ... 1123 * ...
1148 * }; 1124 * };
1149 * 1125 *
1150 * ... 1126 * ...
1151 * }; 1127 * };
1152 * 1128 *
1153 * @param blob FDT blob 1129 * @param blob FDT blob
1154 * @param node name of the node to add the carveout to 1130 * @param node name of the node to add the carveout to
1155 * @param prop_name name of the property in which to store the phandle of 1131 * @param prop_name name of the property in which to store the phandle of
1156 * the carveout 1132 * the carveout
1157 * @param index index of the phandle to store 1133 * @param index index of the phandle to store
1158 * @param name base name of the reserved-memory node to create 1134 * @param name base name of the reserved-memory node to create
1159 * @param carveout information about the carveout to add 1135 * @param carveout information about the carveout to add
1160 * @return 0 on success or a negative error code on failure 1136 * @return 0 on success or a negative error code on failure
1161 */ 1137 */
1162 int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name, 1138 int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
1163 unsigned int index, const char *name, 1139 unsigned int index, const char *name,
1164 const struct fdt_memory *carveout); 1140 const struct fdt_memory *carveout);
1165 1141
1166 /** 1142 /**
1167 * Set up the device tree ready for use 1143 * Set up the device tree ready for use
1168 */ 1144 */
1169 int fdtdec_setup(void); 1145 int fdtdec_setup(void);
1170 1146
1171 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) 1147 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
1172 /** 1148 /**
1173 * fdtdec_resetup() - Set up the device tree again 1149 * fdtdec_resetup() - Set up the device tree again
1174 * 1150 *
1175 * The main difference with fdtdec_setup() is that it returns if the fdt has 1151 * The main difference with fdtdec_setup() is that it returns if the fdt has
1176 * changed because a better match has been found. 1152 * changed because a better match has been found.
1177 * This is typically used for boards that rely on a DM driver to detect the 1153 * This is typically used for boards that rely on a DM driver to detect the
1178 * board type. This function sould be called by the board code after the stuff 1154 * board type. This function sould be called by the board code after the stuff
1179 * needed by board_fit_config_name_match() to operate porperly is available. 1155 * needed by board_fit_config_name_match() to operate porperly is available.
1180 * If this functions signals that a rescan is necessary, the board code must 1156 * If this functions signals that a rescan is necessary, the board code must
1181 * unbind all the drivers using dm_uninit() and then rescan the DT with 1157 * unbind all the drivers using dm_uninit() and then rescan the DT with
1182 * dm_init_and_scan(). 1158 * dm_init_and_scan().
1183 * 1159 *
1184 * @param rescan Returns a flag indicating that fdt has changed and rescanning 1160 * @param rescan Returns a flag indicating that fdt has changed and rescanning
1185 * the fdt is required 1161 * the fdt is required
1186 * 1162 *
1187 * @return 0 if OK, -ve on error 1163 * @return 0 if OK, -ve on error
1188 */ 1164 */
1189 int fdtdec_resetup(int *rescan); 1165 int fdtdec_resetup(int *rescan);
1190 #endif 1166 #endif
1191 1167
1192 /** 1168 /**
1193 * Board-specific FDT initialization. Returns the address to a device tree blob. 1169 * Board-specific FDT initialization. Returns the address to a device tree blob.
1194 * Called when CONFIG_OF_BOARD is defined, or if CONFIG_OF_SEPARATE is defined 1170 * Called when CONFIG_OF_BOARD is defined, or if CONFIG_OF_SEPARATE is defined
1195 * and the board implements it. 1171 * and the board implements it.
1196 */ 1172 */
1197 void *board_fdt_blob_setup(void); 1173 void *board_fdt_blob_setup(void);
1198 1174
1199 /* 1175 /*
1200 * Decode the size of memory 1176 * Decode the size of memory
1201 * 1177 *
1202 * RAM size is normally set in a /memory node and consists of a list of 1178 * RAM size is normally set in a /memory node and consists of a list of
1203 * (base, size) cells in the 'reg' property. This information is used to 1179 * (base, size) cells in the 'reg' property. This information is used to
1204 * determine the total available memory as well as the address and size 1180 * determine the total available memory as well as the address and size
1205 * of each bank. 1181 * of each bank.
1206 * 1182 *
1207 * Optionally the memory configuration can vary depending on a board id, 1183 * Optionally the memory configuration can vary depending on a board id,
1208 * typically read from strapping resistors or an EEPROM on the board. 1184 * typically read from strapping resistors or an EEPROM on the board.
1209 * 1185 *
1210 * Finally, memory size can be detected (within certain limits) by probing 1186 * Finally, memory size can be detected (within certain limits) by probing
1211 * the available memory. It is safe to do so within the limits provides by 1187 * the available memory. It is safe to do so within the limits provides by
1212 * the board's device tree information. This makes it possible to produce 1188 * the board's device tree information. This makes it possible to produce
1213 * boards with different memory sizes, where the device tree specifies the 1189 * boards with different memory sizes, where the device tree specifies the
1214 * maximum memory configuration, and the smaller memory configuration is 1190 * maximum memory configuration, and the smaller memory configuration is
1215 * probed. 1191 * probed.
1216 * 1192 *
1217 * This function decodes that information, returning the memory base address, 1193 * This function decodes that information, returning the memory base address,
1218 * size and bank information. See the memory.txt binding for full 1194 * size and bank information. See the memory.txt binding for full
1219 * documentation. 1195 * documentation.
1220 * 1196 *
1221 * @param blob Device tree blob 1197 * @param blob Device tree blob
1222 * @param area Name of node to check (NULL means "/memory") 1198 * @param area Name of node to check (NULL means "/memory")
1223 * @param board_id Board ID to look up 1199 * @param board_id Board ID to look up
1224 * @param basep Returns base address of first memory bank (NULL to 1200 * @param basep Returns base address of first memory bank (NULL to
1225 * ignore) 1201 * ignore)
1226 * @param sizep Returns total memory size (NULL to ignore) 1202 * @param sizep Returns total memory size (NULL to ignore)
1227 * @param bd Updated with the memory bank information (NULL to skip) 1203 * @param bd Updated with the memory bank information (NULL to skip)
1228 * @return 0 if OK, -ve on error 1204 * @return 0 if OK, -ve on error
1229 */ 1205 */
1230 int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id, 1206 int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id,
1231 phys_addr_t *basep, phys_size_t *sizep, 1207 phys_addr_t *basep, phys_size_t *sizep,
1232 struct bd_info *bd); 1208 struct bd_info *bd);
1233 1209
1234 #endif 1210 #endif
1235 1211
1 // SPDX-License-Identifier: GPL-2.0+ 1 // SPDX-License-Identifier: GPL-2.0+
2 /* 2 /*
3 * Copyright (c) 2011 The Chromium OS Authors. 3 * Copyright (c) 2011 The Chromium OS Authors.
4 */ 4 */
5 5
6 #ifndef USE_HOSTCC 6 #ifndef USE_HOSTCC
7 #include <common.h> 7 #include <common.h>
8 #include <boot_fit.h> 8 #include <boot_fit.h>
9 #include <dm.h> 9 #include <dm.h>
10 #include <dm/of_extra.h> 10 #include <dm/of_extra.h>
11 #include <errno.h> 11 #include <errno.h>
12 #include <fdtdec.h> 12 #include <fdtdec.h>
13 #include <fdt_support.h> 13 #include <fdt_support.h>
14 #include <mapmem.h> 14 #include <mapmem.h>
15 #include <linux/libfdt.h> 15 #include <linux/libfdt.h>
16 #include <serial.h> 16 #include <serial.h>
17 #include <asm/sections.h> 17 #include <asm/sections.h>
18 #include <linux/ctype.h> 18 #include <linux/ctype.h>
19 #include <linux/lzo.h> 19 #include <linux/lzo.h>
20 20
21 DECLARE_GLOBAL_DATA_PTR; 21 DECLARE_GLOBAL_DATA_PTR;
22 22
23 /* 23 /*
24 * Here are the type we know about. One day we might allow drivers to 24 * Here are the type we know about. One day we might allow drivers to
25 * register. For now we just put them here. The COMPAT macro allows us to 25 * register. For now we just put them here. The COMPAT macro allows us to
26 * turn this into a sparse list later, and keeps the ID with the name. 26 * turn this into a sparse list later, and keeps the ID with the name.
27 * 27 *
28 * NOTE: This list is basically a TODO list for things that need to be 28 * NOTE: This list is basically a TODO list for things that need to be
29 * converted to driver model. So don't add new things here unless there is a 29 * converted to driver model. So don't add new things here unless there is a
30 * good reason why driver-model conversion is infeasible. Examples include 30 * good reason why driver-model conversion is infeasible. Examples include
31 * things which are used before driver model is available. 31 * things which are used before driver model is available.
32 */ 32 */
33 #define COMPAT(id, name) name 33 #define COMPAT(id, name) name
34 static const char * const compat_names[COMPAT_COUNT] = { 34 static const char * const compat_names[COMPAT_COUNT] = {
35 COMPAT(UNKNOWN, "<none>"), 35 COMPAT(UNKNOWN, "<none>"),
36 COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"), 36 COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"),
37 COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"), 37 COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"),
38 COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"), 38 COMPAT(NVIDIA_TEGRA20_NAND, "nvidia,tegra20-nand"),
39 COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"), 39 COMPAT(NVIDIA_TEGRA124_XUSB_PADCTL, "nvidia,tegra124-xusb-padctl"),
40 COMPAT(NVIDIA_TEGRA210_XUSB_PADCTL, "nvidia,tegra210-xusb-padctl"), 40 COMPAT(NVIDIA_TEGRA210_XUSB_PADCTL, "nvidia,tegra210-xusb-padctl"),
41 COMPAT(SMSC_LAN9215, "smsc,lan9215"), 41 COMPAT(SMSC_LAN9215, "smsc,lan9215"),
42 COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"), 42 COMPAT(SAMSUNG_EXYNOS5_SROMC, "samsung,exynos-sromc"),
43 COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"), 43 COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
44 COMPAT(SAMSUNG_EXYNOS5_USB3_PHY, "samsung,exynos5250-usb3-phy"), 44 COMPAT(SAMSUNG_EXYNOS5_USB3_PHY, "samsung,exynos5250-usb3-phy"),
45 COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"), 45 COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
46 COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"), 46 COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"),
47 COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"), 47 COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"),
48 COMPAT(GENERIC_SPI_FLASH, "jedec,spi-nor"), 48 COMPAT(GENERIC_SPI_FLASH, "jedec,spi-nor"),
49 COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"), 49 COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
50 COMPAT(INTEL_MICROCODE, "intel,microcode"), 50 COMPAT(INTEL_MICROCODE, "intel,microcode"),
51 COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"), 51 COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
52 COMPAT(ALTERA_SOCFPGA_DWMAC, "altr,socfpga-stmmac"), 52 COMPAT(ALTERA_SOCFPGA_DWMAC, "altr,socfpga-stmmac"),
53 COMPAT(ALTERA_SOCFPGA_DWMMC, "altr,socfpga-dw-mshc"), 53 COMPAT(ALTERA_SOCFPGA_DWMMC, "altr,socfpga-dw-mshc"),
54 COMPAT(ALTERA_SOCFPGA_DWC2USB, "snps,dwc2"), 54 COMPAT(ALTERA_SOCFPGA_DWC2USB, "snps,dwc2"),
55 COMPAT(INTEL_BAYTRAIL_FSP, "intel,baytrail-fsp"), 55 COMPAT(INTEL_BAYTRAIL_FSP, "intel,baytrail-fsp"),
56 COMPAT(INTEL_BAYTRAIL_FSP_MDP, "intel,baytrail-fsp-mdp"), 56 COMPAT(INTEL_BAYTRAIL_FSP_MDP, "intel,baytrail-fsp-mdp"),
57 COMPAT(INTEL_IVYBRIDGE_FSP, "intel,ivybridge-fsp"), 57 COMPAT(INTEL_IVYBRIDGE_FSP, "intel,ivybridge-fsp"),
58 COMPAT(COMPAT_SUNXI_NAND, "allwinner,sun4i-a10-nand"), 58 COMPAT(COMPAT_SUNXI_NAND, "allwinner,sun4i-a10-nand"),
59 COMPAT(ALTERA_SOCFPGA_CLK, "altr,clk-mgr"), 59 COMPAT(ALTERA_SOCFPGA_CLK, "altr,clk-mgr"),
60 COMPAT(ALTERA_SOCFPGA_PINCTRL_SINGLE, "pinctrl-single"), 60 COMPAT(ALTERA_SOCFPGA_PINCTRL_SINGLE, "pinctrl-single"),
61 COMPAT(ALTERA_SOCFPGA_H2F_BRG, "altr,socfpga-hps2fpga-bridge"), 61 COMPAT(ALTERA_SOCFPGA_H2F_BRG, "altr,socfpga-hps2fpga-bridge"),
62 COMPAT(ALTERA_SOCFPGA_LWH2F_BRG, "altr,socfpga-lwhps2fpga-bridge"), 62 COMPAT(ALTERA_SOCFPGA_LWH2F_BRG, "altr,socfpga-lwhps2fpga-bridge"),
63 COMPAT(ALTERA_SOCFPGA_F2H_BRG, "altr,socfpga-fpga2hps-bridge"), 63 COMPAT(ALTERA_SOCFPGA_F2H_BRG, "altr,socfpga-fpga2hps-bridge"),
64 COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"), 64 COMPAT(ALTERA_SOCFPGA_F2SDR0, "altr,socfpga-fpga2sdram0-bridge"),
65 COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"), 65 COMPAT(ALTERA_SOCFPGA_F2SDR1, "altr,socfpga-fpga2sdram1-bridge"),
66 COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"), 66 COMPAT(ALTERA_SOCFPGA_F2SDR2, "altr,socfpga-fpga2sdram2-bridge"),
67 COMPAT(ALTERA_SOCFPGA_FPGA0, "altr,socfpga-a10-fpga-mgr"), 67 COMPAT(ALTERA_SOCFPGA_FPGA0, "altr,socfpga-a10-fpga-mgr"),
68 COMPAT(ALTERA_SOCFPGA_NOC, "altr,socfpga-a10-noc"), 68 COMPAT(ALTERA_SOCFPGA_NOC, "altr,socfpga-a10-noc"),
69 COMPAT(ALTERA_SOCFPGA_CLK_INIT, "altr,socfpga-a10-clk-init") 69 COMPAT(ALTERA_SOCFPGA_CLK_INIT, "altr,socfpga-a10-clk-init")
70 }; 70 };
71 71
72 const char *fdtdec_get_compatible(enum fdt_compat_id id) 72 const char *fdtdec_get_compatible(enum fdt_compat_id id)
73 { 73 {
74 /* We allow reading of the 'unknown' ID for testing purposes */ 74 /* We allow reading of the 'unknown' ID for testing purposes */
75 assert(id >= 0 && id < COMPAT_COUNT); 75 assert(id >= 0 && id < COMPAT_COUNT);
76 return compat_names[id]; 76 return compat_names[id];
77 } 77 }
78 78
79 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node, 79 fdt_addr_t fdtdec_get_addr_size_fixed(const void *blob, int node,
80 const char *prop_name, int index, int na, 80 const char *prop_name, int index, int na,
81 int ns, fdt_size_t *sizep, 81 int ns, fdt_size_t *sizep,
82 bool translate) 82 bool translate)
83 { 83 {
84 const fdt32_t *prop, *prop_end; 84 const fdt32_t *prop, *prop_end;
85 const fdt32_t *prop_addr, *prop_size, *prop_after_size; 85 const fdt32_t *prop_addr, *prop_size, *prop_after_size;
86 int len; 86 int len;
87 fdt_addr_t addr; 87 fdt_addr_t addr;
88 88
89 debug("%s: %s: ", __func__, prop_name); 89 debug("%s: %s: ", __func__, prop_name);
90 90
91 prop = fdt_getprop(blob, node, prop_name, &len); 91 prop = fdt_getprop(blob, node, prop_name, &len);
92 if (!prop) { 92 if (!prop) {
93 debug("(not found)\n"); 93 debug("(not found)\n");
94 return FDT_ADDR_T_NONE; 94 return FDT_ADDR_T_NONE;
95 } 95 }
96 prop_end = prop + (len / sizeof(*prop)); 96 prop_end = prop + (len / sizeof(*prop));
97 97
98 prop_addr = prop + (index * (na + ns)); 98 prop_addr = prop + (index * (na + ns));
99 prop_size = prop_addr + na; 99 prop_size = prop_addr + na;
100 prop_after_size = prop_size + ns; 100 prop_after_size = prop_size + ns;
101 if (prop_after_size > prop_end) { 101 if (prop_after_size > prop_end) {
102 debug("(not enough data: expected >= %d cells, got %d cells)\n", 102 debug("(not enough data: expected >= %d cells, got %d cells)\n",
103 (u32)(prop_after_size - prop), ((u32)(prop_end - prop))); 103 (u32)(prop_after_size - prop), ((u32)(prop_end - prop)));
104 return FDT_ADDR_T_NONE; 104 return FDT_ADDR_T_NONE;
105 } 105 }
106 106
107 #if CONFIG_IS_ENABLED(OF_TRANSLATE) 107 #if CONFIG_IS_ENABLED(OF_TRANSLATE)
108 if (translate) 108 if (translate)
109 addr = fdt_translate_address(blob, node, prop_addr); 109 addr = fdt_translate_address(blob, node, prop_addr);
110 else 110 else
111 #endif 111 #endif
112 addr = fdtdec_get_number(prop_addr, na); 112 addr = fdtdec_get_number(prop_addr, na);
113 113
114 if (sizep) { 114 if (sizep) {
115 *sizep = fdtdec_get_number(prop_size, ns); 115 *sizep = fdtdec_get_number(prop_size, ns);
116 debug("addr=%08llx, size=%llx\n", (unsigned long long)addr, 116 debug("addr=%08llx, size=%llx\n", (unsigned long long)addr,
117 (unsigned long long)*sizep); 117 (unsigned long long)*sizep);
118 } else { 118 } else {
119 debug("addr=%08llx\n", (unsigned long long)addr); 119 debug("addr=%08llx\n", (unsigned long long)addr);
120 } 120 }
121 121
122 return addr; 122 return addr;
123 } 123 }
124 124
125 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent, 125 fdt_addr_t fdtdec_get_addr_size_auto_parent(const void *blob, int parent,
126 int node, const char *prop_name, 126 int node, const char *prop_name,
127 int index, fdt_size_t *sizep, 127 int index, fdt_size_t *sizep,
128 bool translate) 128 bool translate)
129 { 129 {
130 int na, ns; 130 int na, ns;
131 131
132 debug("%s: ", __func__); 132 debug("%s: ", __func__);
133 133
134 na = fdt_address_cells(blob, parent); 134 na = fdt_address_cells(blob, parent);
135 if (na < 1) { 135 if (na < 1) {
136 debug("(bad #address-cells)\n"); 136 debug("(bad #address-cells)\n");
137 return FDT_ADDR_T_NONE; 137 return FDT_ADDR_T_NONE;
138 } 138 }
139 139
140 ns = fdt_size_cells(blob, parent); 140 ns = fdt_size_cells(blob, parent);
141 if (ns < 0) { 141 if (ns < 0) {
142 debug("(bad #size-cells)\n"); 142 debug("(bad #size-cells)\n");
143 return FDT_ADDR_T_NONE; 143 return FDT_ADDR_T_NONE;
144 } 144 }
145 145
146 debug("na=%d, ns=%d, ", na, ns); 146 debug("na=%d, ns=%d, ", na, ns);
147 147
148 return fdtdec_get_addr_size_fixed(blob, node, prop_name, index, na, 148 return fdtdec_get_addr_size_fixed(blob, node, prop_name, index, na,
149 ns, sizep, translate); 149 ns, sizep, translate);
150 } 150 }
151 151
152 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node, 152 fdt_addr_t fdtdec_get_addr_size_auto_noparent(const void *blob, int node,
153 const char *prop_name, int index, 153 const char *prop_name, int index,
154 fdt_size_t *sizep, 154 fdt_size_t *sizep,
155 bool translate) 155 bool translate)
156 { 156 {
157 int parent; 157 int parent;
158 158
159 debug("%s: ", __func__); 159 debug("%s: ", __func__);
160 160
161 parent = fdt_parent_offset(blob, node); 161 parent = fdt_parent_offset(blob, node);
162 if (parent < 0) { 162 if (parent < 0) {
163 debug("(no parent found)\n"); 163 debug("(no parent found)\n");
164 return FDT_ADDR_T_NONE; 164 return FDT_ADDR_T_NONE;
165 } 165 }
166 166
167 return fdtdec_get_addr_size_auto_parent(blob, parent, node, prop_name, 167 return fdtdec_get_addr_size_auto_parent(blob, parent, node, prop_name,
168 index, sizep, translate); 168 index, sizep, translate);
169 } 169 }
170 170
171 fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, 171 fdt_addr_t fdtdec_get_addr_size(const void *blob, int node,
172 const char *prop_name, fdt_size_t *sizep) 172 const char *prop_name, fdt_size_t *sizep)
173 { 173 {
174 int ns = sizep ? (sizeof(fdt_size_t) / sizeof(fdt32_t)) : 0; 174 int ns = sizep ? (sizeof(fdt_size_t) / sizeof(fdt32_t)) : 0;
175 175
176 return fdtdec_get_addr_size_fixed(blob, node, prop_name, 0, 176 return fdtdec_get_addr_size_fixed(blob, node, prop_name, 0,
177 sizeof(fdt_addr_t) / sizeof(fdt32_t), 177 sizeof(fdt_addr_t) / sizeof(fdt32_t),
178 ns, sizep, false); 178 ns, sizep, false);
179 } 179 }
180 180
181 fdt_addr_t fdtdec_get_addr(const void *blob, int node, const char *prop_name) 181 fdt_addr_t fdtdec_get_addr(const void *blob, int node, const char *prop_name)
182 { 182 {
183 return fdtdec_get_addr_size(blob, node, prop_name, NULL); 183 return fdtdec_get_addr_size(blob, node, prop_name, NULL);
184 } 184 }
185 185
186 #if CONFIG_IS_ENABLED(PCI) && defined(CONFIG_DM_PCI) 186 #if CONFIG_IS_ENABLED(PCI) && defined(CONFIG_DM_PCI)
187 int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, 187 int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type,
188 const char *prop_name, struct fdt_pci_addr *addr) 188 const char *prop_name, struct fdt_pci_addr *addr)
189 { 189 {
190 const u32 *cell; 190 const u32 *cell;
191 int len; 191 int len;
192 int ret = -ENOENT; 192 int ret = -ENOENT;
193 193
194 debug("%s: %s: ", __func__, prop_name); 194 debug("%s: %s: ", __func__, prop_name);
195 195
196 /* 196 /*
197 * If we follow the pci bus bindings strictly, we should check 197 * If we follow the pci bus bindings strictly, we should check
198 * the value of the node's parent node's #address-cells and 198 * the value of the node's parent node's #address-cells and
199 * #size-cells. They need to be 3 and 2 accordingly. However, 199 * #size-cells. They need to be 3 and 2 accordingly. However,
200 * for simplicity we skip the check here. 200 * for simplicity we skip the check here.
201 */ 201 */
202 cell = fdt_getprop(blob, node, prop_name, &len); 202 cell = fdt_getprop(blob, node, prop_name, &len);
203 if (!cell) 203 if (!cell)
204 goto fail; 204 goto fail;
205 205
206 if ((len % FDT_PCI_REG_SIZE) == 0) { 206 if ((len % FDT_PCI_REG_SIZE) == 0) {
207 int num = len / FDT_PCI_REG_SIZE; 207 int num = len / FDT_PCI_REG_SIZE;
208 int i; 208 int i;
209 209
210 for (i = 0; i < num; i++) { 210 for (i = 0; i < num; i++) {
211 debug("pci address #%d: %08lx %08lx %08lx\n", i, 211 debug("pci address #%d: %08lx %08lx %08lx\n", i,
212 (ulong)fdt32_to_cpu(cell[0]), 212 (ulong)fdt32_to_cpu(cell[0]),
213 (ulong)fdt32_to_cpu(cell[1]), 213 (ulong)fdt32_to_cpu(cell[1]),
214 (ulong)fdt32_to_cpu(cell[2])); 214 (ulong)fdt32_to_cpu(cell[2]));
215 if ((fdt32_to_cpu(*cell) & type) == type) { 215 if ((fdt32_to_cpu(*cell) & type) == type) {
216 addr->phys_hi = fdt32_to_cpu(cell[0]); 216 addr->phys_hi = fdt32_to_cpu(cell[0]);
217 addr->phys_mid = fdt32_to_cpu(cell[1]); 217 addr->phys_mid = fdt32_to_cpu(cell[1]);
218 addr->phys_lo = fdt32_to_cpu(cell[1]); 218 addr->phys_lo = fdt32_to_cpu(cell[1]);
219 break; 219 break;
220 } 220 }
221 221
222 cell += (FDT_PCI_ADDR_CELLS + 222 cell += (FDT_PCI_ADDR_CELLS +
223 FDT_PCI_SIZE_CELLS); 223 FDT_PCI_SIZE_CELLS);
224 } 224 }
225 225
226 if (i == num) { 226 if (i == num) {
227 ret = -ENXIO; 227 ret = -ENXIO;
228 goto fail; 228 goto fail;
229 } 229 }
230 230
231 return 0; 231 return 0;
232 } 232 }
233 233
234 ret = -EINVAL; 234 ret = -EINVAL;
235 235
236 fail: 236 fail:
237 debug("(not found)\n"); 237 debug("(not found)\n");
238 return ret; 238 return ret;
239 } 239 }
240 240
241 int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device) 241 int fdtdec_get_pci_vendev(const void *blob, int node, u16 *vendor, u16 *device)
242 { 242 {
243 const char *list, *end; 243 const char *list, *end;
244 int len; 244 int len;
245 245
246 list = fdt_getprop(blob, node, "compatible", &len); 246 list = fdt_getprop(blob, node, "compatible", &len);
247 if (!list) 247 if (!list)
248 return -ENOENT; 248 return -ENOENT;
249 249
250 end = list + len; 250 end = list + len;
251 while (list < end) { 251 while (list < end) {
252 len = strlen(list); 252 len = strlen(list);
253 if (len >= strlen("pciVVVV,DDDD")) { 253 if (len >= strlen("pciVVVV,DDDD")) {
254 char *s = strstr(list, "pci"); 254 char *s = strstr(list, "pci");
255 255
256 /* 256 /*
257 * check if the string is something like pciVVVV,DDDD.RR 257 * check if the string is something like pciVVVV,DDDD.RR
258 * or just pciVVVV,DDDD 258 * or just pciVVVV,DDDD
259 */ 259 */
260 if (s && s[7] == ',' && 260 if (s && s[7] == ',' &&
261 (s[12] == '.' || s[12] == 0)) { 261 (s[12] == '.' || s[12] == 0)) {
262 s += 3; 262 s += 3;
263 *vendor = simple_strtol(s, NULL, 16); 263 *vendor = simple_strtol(s, NULL, 16);
264 264
265 s += 5; 265 s += 5;
266 *device = simple_strtol(s, NULL, 16); 266 *device = simple_strtol(s, NULL, 16);
267 267
268 return 0; 268 return 0;
269 } 269 }
270 } 270 }
271 list += (len + 1); 271 list += (len + 1);
272 } 272 }
273 273
274 return -ENOENT; 274 return -ENOENT;
275 } 275 }
276 276
277 int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr, 277 int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr,
278 u32 *bar) 278 u32 *bar)
279 { 279 {
280 int barnum; 280 int barnum;
281 281
282 /* extract the bar number from fdt_pci_addr */ 282 /* extract the bar number from fdt_pci_addr */
283 barnum = addr->phys_hi & 0xff; 283 barnum = addr->phys_hi & 0xff;
284 if (barnum < PCI_BASE_ADDRESS_0 || barnum > PCI_CARDBUS_CIS) 284 if (barnum < PCI_BASE_ADDRESS_0 || barnum > PCI_CARDBUS_CIS)
285 return -EINVAL; 285 return -EINVAL;
286 286
287 barnum = (barnum - PCI_BASE_ADDRESS_0) / 4; 287 barnum = (barnum - PCI_BASE_ADDRESS_0) / 4;
288 *bar = dm_pci_read_bar32(dev, barnum); 288 *bar = dm_pci_read_bar32(dev, barnum);
289 289
290 return 0; 290 return 0;
291 } 291 }
292 #endif 292 #endif
293 293
294 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name, 294 uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name,
295 uint64_t default_val) 295 uint64_t default_val)
296 { 296 {
297 const uint64_t *cell64; 297 const uint64_t *cell64;
298 int length; 298 int length;
299 299
300 cell64 = fdt_getprop(blob, node, prop_name, &length); 300 cell64 = fdt_getprop(blob, node, prop_name, &length);
301 if (!cell64 || length < sizeof(*cell64)) 301 if (!cell64 || length < sizeof(*cell64))
302 return default_val; 302 return default_val;
303 303
304 return fdt64_to_cpu(*cell64); 304 return fdt64_to_cpu(*cell64);
305 } 305 }
306 306
307 int fdtdec_get_is_enabled(const void *blob, int node) 307 int fdtdec_get_is_enabled(const void *blob, int node)
308 { 308 {
309 const char *cell; 309 const char *cell;
310 310
311 /* 311 /*
312 * It should say "okay", so only allow that. Some fdts use "ok" but 312 * It should say "okay", so only allow that. Some fdts use "ok" but
313 * this is a bug. Please fix your device tree source file. See here 313 * this is a bug. Please fix your device tree source file. See here
314 * for discussion: 314 * for discussion:
315 * 315 *
316 * http://www.mail-archive.com/u-boot@lists.denx.de/msg71598.html 316 * http://www.mail-archive.com/u-boot@lists.denx.de/msg71598.html
317 */ 317 */
318 cell = fdt_getprop(blob, node, "status", NULL); 318 cell = fdt_getprop(blob, node, "status", NULL);
319 if (cell) 319 if (cell)
320 return strcmp(cell, "okay") == 0; 320 return strcmp(cell, "okay") == 0;
321 return 1; 321 return 1;
322 } 322 }
323 323
324 enum fdt_compat_id fdtdec_lookup(const void *blob, int node) 324 enum fdt_compat_id fdtdec_lookup(const void *blob, int node)
325 { 325 {
326 enum fdt_compat_id id; 326 enum fdt_compat_id id;
327 327
328 /* Search our drivers */ 328 /* Search our drivers */
329 for (id = COMPAT_UNKNOWN; id < COMPAT_COUNT; id++) 329 for (id = COMPAT_UNKNOWN; id < COMPAT_COUNT; id++)
330 if (fdt_node_check_compatible(blob, node, 330 if (fdt_node_check_compatible(blob, node,
331 compat_names[id]) == 0) 331 compat_names[id]) == 0)
332 return id; 332 return id;
333 return COMPAT_UNKNOWN; 333 return COMPAT_UNKNOWN;
334 } 334 }
335 335
336 int fdtdec_next_compatible(const void *blob, int node, enum fdt_compat_id id) 336 int fdtdec_next_compatible(const void *blob, int node, enum fdt_compat_id id)
337 { 337 {
338 return fdt_node_offset_by_compatible(blob, node, compat_names[id]); 338 return fdt_node_offset_by_compatible(blob, node, compat_names[id]);
339 } 339 }
340 340
341 int fdtdec_next_compatible_subnode(const void *blob, int node, 341 int fdtdec_next_compatible_subnode(const void *blob, int node,
342 enum fdt_compat_id id, int *depthp) 342 enum fdt_compat_id id, int *depthp)
343 { 343 {
344 do { 344 do {
345 node = fdt_next_node(blob, node, depthp); 345 node = fdt_next_node(blob, node, depthp);
346 } while (*depthp > 1); 346 } while (*depthp > 1);
347 347
348 /* If this is a direct subnode, and compatible, return it */ 348 /* If this is a direct subnode, and compatible, return it */
349 if (*depthp == 1 && 0 == fdt_node_check_compatible( 349 if (*depthp == 1 && 0 == fdt_node_check_compatible(
350 blob, node, compat_names[id])) 350 blob, node, compat_names[id]))
351 return node; 351 return node;
352 352
353 return -FDT_ERR_NOTFOUND; 353 return -FDT_ERR_NOTFOUND;
354 } 354 }
355 355
356 int fdtdec_next_alias(const void *blob, const char *name, enum fdt_compat_id id, 356 int fdtdec_next_alias(const void *blob, const char *name, enum fdt_compat_id id,
357 int *upto) 357 int *upto)
358 { 358 {
359 #define MAX_STR_LEN 20 359 #define MAX_STR_LEN 20
360 char str[MAX_STR_LEN + 20]; 360 char str[MAX_STR_LEN + 20];
361 int node, err; 361 int node, err;
362 362
363 /* snprintf() is not available */ 363 /* snprintf() is not available */
364 assert(strlen(name) < MAX_STR_LEN); 364 assert(strlen(name) < MAX_STR_LEN);
365 sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto); 365 sprintf(str, "%.*s%d", MAX_STR_LEN, name, *upto);
366 node = fdt_path_offset(blob, str); 366 node = fdt_path_offset(blob, str);
367 if (node < 0) 367 if (node < 0)
368 return node; 368 return node;
369 err = fdt_node_check_compatible(blob, node, compat_names[id]); 369 err = fdt_node_check_compatible(blob, node, compat_names[id]);
370 if (err < 0) 370 if (err < 0)
371 return err; 371 return err;
372 if (err) 372 if (err)
373 return -FDT_ERR_NOTFOUND; 373 return -FDT_ERR_NOTFOUND;
374 (*upto)++; 374 (*upto)++;
375 return node; 375 return node;
376 } 376 }
377 377
378 int fdtdec_find_aliases_for_id(const void *blob, const char *name, 378 int fdtdec_find_aliases_for_id(const void *blob, const char *name,
379 enum fdt_compat_id id, int *node_list, 379 enum fdt_compat_id id, int *node_list,
380 int maxcount) 380 int maxcount)
381 { 381 {
382 memset(node_list, '\0', sizeof(*node_list) * maxcount); 382 memset(node_list, '\0', sizeof(*node_list) * maxcount);
383 383
384 return fdtdec_add_aliases_for_id(blob, name, id, node_list, maxcount); 384 return fdtdec_add_aliases_for_id(blob, name, id, node_list, maxcount);
385 } 385 }
386 386
387 /* TODO: Can we tighten this code up a little? */ 387 /* TODO: Can we tighten this code up a little? */
388 int fdtdec_add_aliases_for_id(const void *blob, const char *name, 388 int fdtdec_add_aliases_for_id(const void *blob, const char *name,
389 enum fdt_compat_id id, int *node_list, 389 enum fdt_compat_id id, int *node_list,
390 int maxcount) 390 int maxcount)
391 { 391 {
392 int name_len = strlen(name); 392 int name_len = strlen(name);
393 int nodes[maxcount]; 393 int nodes[maxcount];
394 int num_found = 0; 394 int num_found = 0;
395 int offset, node; 395 int offset, node;
396 int alias_node; 396 int alias_node;
397 int count; 397 int count;
398 int i, j; 398 int i, j;
399 399
400 /* find the alias node if present */ 400 /* find the alias node if present */
401 alias_node = fdt_path_offset(blob, "/aliases"); 401 alias_node = fdt_path_offset(blob, "/aliases");
402 402
403 /* 403 /*
404 * start with nothing, and we can assume that the root node can't 404 * start with nothing, and we can assume that the root node can't
405 * match 405 * match
406 */ 406 */
407 memset(nodes, '\0', sizeof(nodes)); 407 memset(nodes, '\0', sizeof(nodes));
408 408
409 /* First find all the compatible nodes */ 409 /* First find all the compatible nodes */
410 for (node = count = 0; node >= 0 && count < maxcount;) { 410 for (node = count = 0; node >= 0 && count < maxcount;) {
411 node = fdtdec_next_compatible(blob, node, id); 411 node = fdtdec_next_compatible(blob, node, id);
412 if (node >= 0) 412 if (node >= 0)
413 nodes[count++] = node; 413 nodes[count++] = node;
414 } 414 }
415 if (node >= 0) 415 if (node >= 0)
416 debug("%s: warning: maxcount exceeded with alias '%s'\n", 416 debug("%s: warning: maxcount exceeded with alias '%s'\n",
417 __func__, name); 417 __func__, name);
418 418
419 /* Now find all the aliases */ 419 /* Now find all the aliases */
420 for (offset = fdt_first_property_offset(blob, alias_node); 420 for (offset = fdt_first_property_offset(blob, alias_node);
421 offset > 0; 421 offset > 0;
422 offset = fdt_next_property_offset(blob, offset)) { 422 offset = fdt_next_property_offset(blob, offset)) {
423 const struct fdt_property *prop; 423 const struct fdt_property *prop;
424 const char *path; 424 const char *path;
425 int number; 425 int number;
426 int found; 426 int found;
427 427
428 node = 0; 428 node = 0;
429 prop = fdt_get_property_by_offset(blob, offset, NULL); 429 prop = fdt_get_property_by_offset(blob, offset, NULL);
430 path = fdt_string(blob, fdt32_to_cpu(prop->nameoff)); 430 path = fdt_string(blob, fdt32_to_cpu(prop->nameoff));
431 if (prop->len && 0 == strncmp(path, name, name_len)) 431 if (prop->len && 0 == strncmp(path, name, name_len))
432 node = fdt_path_offset(blob, prop->data); 432 node = fdt_path_offset(blob, prop->data);
433 if (node <= 0) 433 if (node <= 0)
434 continue; 434 continue;
435 435
436 /* Get the alias number */ 436 /* Get the alias number */
437 number = simple_strtoul(path + name_len, NULL, 10); 437 number = simple_strtoul(path + name_len, NULL, 10);
438 if (number < 0 || number >= maxcount) { 438 if (number < 0 || number >= maxcount) {
439 debug("%s: warning: alias '%s' is out of range\n", 439 debug("%s: warning: alias '%s' is out of range\n",
440 __func__, path); 440 __func__, path);
441 continue; 441 continue;
442 } 442 }
443 443
444 /* Make sure the node we found is actually in our list! */ 444 /* Make sure the node we found is actually in our list! */
445 found = -1; 445 found = -1;
446 for (j = 0; j < count; j++) 446 for (j = 0; j < count; j++)
447 if (nodes[j] == node) { 447 if (nodes[j] == node) {
448 found = j; 448 found = j;
449 break; 449 break;
450 } 450 }
451 451
452 if (found == -1) { 452 if (found == -1) {
453 debug("%s: warning: alias '%s' points to a node " 453 debug("%s: warning: alias '%s' points to a node "
454 "'%s' that is missing or is not compatible " 454 "'%s' that is missing or is not compatible "
455 " with '%s'\n", __func__, path, 455 " with '%s'\n", __func__, path,
456 fdt_get_name(blob, node, NULL), 456 fdt_get_name(blob, node, NULL),
457 compat_names[id]); 457 compat_names[id]);
458 continue; 458 continue;
459 } 459 }
460 460
461 /* 461 /*
462 * Add this node to our list in the right place, and mark 462 * Add this node to our list in the right place, and mark
463 * it as done. 463 * it as done.
464 */ 464 */
465 if (fdtdec_get_is_enabled(blob, node)) { 465 if (fdtdec_get_is_enabled(blob, node)) {
466 if (node_list[number]) { 466 if (node_list[number]) {
467 debug("%s: warning: alias '%s' requires that " 467 debug("%s: warning: alias '%s' requires that "
468 "a node be placed in the list in a " 468 "a node be placed in the list in a "
469 "position which is already filled by " 469 "position which is already filled by "
470 "node '%s'\n", __func__, path, 470 "node '%s'\n", __func__, path,
471 fdt_get_name(blob, node, NULL)); 471 fdt_get_name(blob, node, NULL));
472 continue; 472 continue;
473 } 473 }
474 node_list[number] = node; 474 node_list[number] = node;
475 if (number >= num_found) 475 if (number >= num_found)
476 num_found = number + 1; 476 num_found = number + 1;
477 } 477 }
478 nodes[found] = 0; 478 nodes[found] = 0;
479 } 479 }
480 480
481 /* Add any nodes not mentioned by an alias */ 481 /* Add any nodes not mentioned by an alias */
482 for (i = j = 0; i < maxcount; i++) { 482 for (i = j = 0; i < maxcount; i++) {
483 if (!node_list[i]) { 483 if (!node_list[i]) {
484 for (; j < maxcount; j++) 484 for (; j < maxcount; j++)
485 if (nodes[j] && 485 if (nodes[j] &&
486 fdtdec_get_is_enabled(blob, nodes[j])) 486 fdtdec_get_is_enabled(blob, nodes[j]))
487 break; 487 break;
488 488
489 /* Have we run out of nodes to add? */ 489 /* Have we run out of nodes to add? */
490 if (j == maxcount) 490 if (j == maxcount)
491 break; 491 break;
492 492
493 assert(!node_list[i]); 493 assert(!node_list[i]);
494 node_list[i] = nodes[j++]; 494 node_list[i] = nodes[j++];
495 if (i >= num_found) 495 if (i >= num_found)
496 num_found = i + 1; 496 num_found = i + 1;
497 } 497 }
498 } 498 }
499 499
500 return num_found; 500 return num_found;
501 } 501 }
502 502
503 int fdtdec_get_alias_seq(const void *blob, const char *base, int offset, 503 int fdtdec_get_alias_seq(const void *blob, const char *base, int offset,
504 int *seqp) 504 int *seqp)
505 { 505 {
506 int base_len = strlen(base); 506 int base_len = strlen(base);
507 const char *find_name; 507 const char *find_name;
508 int find_namelen; 508 int find_namelen;
509 int prop_offset; 509 int prop_offset;
510 int aliases; 510 int aliases;
511 511
512 find_name = fdt_get_name(blob, offset, &find_namelen); 512 find_name = fdt_get_name(blob, offset, &find_namelen);
513 debug("Looking for '%s' at %d, name %s\n", base, offset, find_name); 513 debug("Looking for '%s' at %d, name %s\n", base, offset, find_name);
514 514
515 aliases = fdt_path_offset(blob, "/aliases"); 515 aliases = fdt_path_offset(blob, "/aliases");
516 for (prop_offset = fdt_first_property_offset(blob, aliases); 516 for (prop_offset = fdt_first_property_offset(blob, aliases);
517 prop_offset > 0; 517 prop_offset > 0;
518 prop_offset = fdt_next_property_offset(blob, prop_offset)) { 518 prop_offset = fdt_next_property_offset(blob, prop_offset)) {
519 const char *prop; 519 const char *prop;
520 const char *name; 520 const char *name;
521 const char *slash; 521 const char *slash;
522 int len, val; 522 int len, val;
523 523
524 prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len); 524 prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len);
525 debug(" - %s, %s\n", name, prop); 525 debug(" - %s, %s\n", name, prop);
526 if (len < find_namelen || *prop != '/' || prop[len - 1] || 526 if (len < find_namelen || *prop != '/' || prop[len - 1] ||
527 strncmp(name, base, base_len)) 527 strncmp(name, base, base_len))
528 continue; 528 continue;
529 529
530 slash = strrchr(prop, '/'); 530 slash = strrchr(prop, '/');
531 if (strcmp(slash + 1, find_name)) 531 if (strcmp(slash + 1, find_name))
532 continue; 532 continue;
533 val = trailing_strtol(name); 533 val = trailing_strtol(name);
534 if (val != -1) { 534 if (val != -1) {
535 *seqp = val; 535 *seqp = val;
536 debug("Found seq %d\n", *seqp); 536 debug("Found seq %d\n", *seqp);
537 return 0; 537 return 0;
538 } 538 }
539 } 539 }
540 540
541 debug("Not found\n"); 541 debug("Not found\n");
542 return -ENOENT; 542 return -ENOENT;
543 } 543 }
544 544
545 int fdtdec_get_alias_highest_id(const void *blob, const char *base) 545 int fdtdec_get_alias_highest_id(const void *blob, const char *base)
546 { 546 {
547 int base_len = strlen(base); 547 int base_len = strlen(base);
548 int prop_offset; 548 int prop_offset;
549 int aliases; 549 int aliases;
550 int max = -1; 550 int max = -1;
551 551
552 debug("Looking for highest alias id for '%s'\n", base); 552 debug("Looking for highest alias id for '%s'\n", base);
553 553
554 aliases = fdt_path_offset(blob, "/aliases"); 554 aliases = fdt_path_offset(blob, "/aliases");
555 for (prop_offset = fdt_first_property_offset(blob, aliases); 555 for (prop_offset = fdt_first_property_offset(blob, aliases);
556 prop_offset > 0; 556 prop_offset > 0;
557 prop_offset = fdt_next_property_offset(blob, prop_offset)) { 557 prop_offset = fdt_next_property_offset(blob, prop_offset)) {
558 const char *prop; 558 const char *prop;
559 const char *name; 559 const char *name;
560 int len, val; 560 int len, val;
561 561
562 prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len); 562 prop = fdt_getprop_by_offset(blob, prop_offset, &name, &len);
563 debug(" - %s, %s\n", name, prop); 563 debug(" - %s, %s\n", name, prop);
564 if (*prop != '/' || prop[len - 1] || 564 if (*prop != '/' || prop[len - 1] ||
565 strncmp(name, base, base_len)) 565 strncmp(name, base, base_len))
566 continue; 566 continue;
567 567
568 val = trailing_strtol(name); 568 val = trailing_strtol(name);
569 if (val > max) { 569 if (val > max) {
570 debug("Found seq %d\n", val); 570 debug("Found seq %d\n", val);
571 max = val; 571 max = val;
572 } 572 }
573 } 573 }
574 574
575 return max; 575 return max;
576 } 576 }
577 577
578 const char *fdtdec_get_chosen_prop(const void *blob, const char *name) 578 const char *fdtdec_get_chosen_prop(const void *blob, const char *name)
579 { 579 {
580 int chosen_node; 580 int chosen_node;
581 581
582 if (!blob) 582 if (!blob)
583 return NULL; 583 return NULL;
584 chosen_node = fdt_path_offset(blob, "/chosen"); 584 chosen_node = fdt_path_offset(blob, "/chosen");
585 return fdt_getprop(blob, chosen_node, name, NULL); 585 return fdt_getprop(blob, chosen_node, name, NULL);
586 } 586 }
587 587
588 int fdtdec_get_chosen_node(const void *blob, const char *name) 588 int fdtdec_get_chosen_node(const void *blob, const char *name)
589 { 589 {
590 const char *prop; 590 const char *prop;
591 591
592 prop = fdtdec_get_chosen_prop(blob, name); 592 prop = fdtdec_get_chosen_prop(blob, name);
593 if (!prop) 593 if (!prop)
594 return -FDT_ERR_NOTFOUND; 594 return -FDT_ERR_NOTFOUND;
595 return fdt_path_offset(blob, prop); 595 return fdt_path_offset(blob, prop);
596 } 596 }
597 597
598 int fdtdec_check_fdt(void) 598 int fdtdec_check_fdt(void)
599 { 599 {
600 /* 600 /*
601 * We must have an FDT, but we cannot panic() yet since the console 601 * We must have an FDT, but we cannot panic() yet since the console
602 * is not ready. So for now, just assert(). Boards which need an early 602 * is not ready. So for now, just assert(). Boards which need an early
603 * FDT (prior to console ready) will need to make their own 603 * FDT (prior to console ready) will need to make their own
604 * arrangements and do their own checks. 604 * arrangements and do their own checks.
605 */ 605 */
606 assert(!fdtdec_prepare_fdt()); 606 assert(!fdtdec_prepare_fdt());
607 return 0; 607 return 0;
608 } 608 }
609 609
610 /* 610 /*
611 * This function is a little odd in that it accesses global data. At some 611 * This function is a little odd in that it accesses global data. At some
612 * point if the architecture board.c files merge this will make more sense. 612 * point if the architecture board.c files merge this will make more sense.
613 * Even now, it is common code. 613 * Even now, it is common code.
614 */ 614 */
615 int fdtdec_prepare_fdt(void) 615 int fdtdec_prepare_fdt(void)
616 { 616 {
617 if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) || 617 if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
618 fdt_check_header(gd->fdt_blob)) { 618 fdt_check_header(gd->fdt_blob)) {
619 #ifdef CONFIG_SPL_BUILD 619 #ifdef CONFIG_SPL_BUILD
620 puts("Missing DTB\n"); 620 puts("Missing DTB\n");
621 #else 621 #else
622 puts("No valid device tree binary found - please append one to U-Boot binary, use u-boot-dtb.bin or define CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n"); 622 puts("No valid device tree binary found - please append one to U-Boot binary, use u-boot-dtb.bin or define CONFIG_OF_EMBED. For sandbox, use -d <file.dtb>\n");
623 # ifdef DEBUG 623 # ifdef DEBUG
624 if (gd->fdt_blob) { 624 if (gd->fdt_blob) {
625 printf("fdt_blob=%p\n", gd->fdt_blob); 625 printf("fdt_blob=%p\n", gd->fdt_blob);
626 print_buffer((ulong)gd->fdt_blob, gd->fdt_blob, 4, 626 print_buffer((ulong)gd->fdt_blob, gd->fdt_blob, 4,
627 32, 0); 627 32, 0);
628 } 628 }
629 # endif 629 # endif
630 #endif 630 #endif
631 return -1; 631 return -1;
632 } 632 }
633 return 0; 633 return 0;
634 } 634 }
635 635
636 int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name) 636 int fdtdec_lookup_phandle(const void *blob, int node, const char *prop_name)
637 { 637 {
638 const u32 *phandle; 638 const u32 *phandle;
639 int lookup; 639 int lookup;
640 640
641 debug("%s: %s\n", __func__, prop_name); 641 debug("%s: %s\n", __func__, prop_name);
642 phandle = fdt_getprop(blob, node, prop_name, NULL); 642 phandle = fdt_getprop(blob, node, prop_name, NULL);
643 if (!phandle) 643 if (!phandle)
644 return -FDT_ERR_NOTFOUND; 644 return -FDT_ERR_NOTFOUND;
645 645
646 lookup = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*phandle)); 646 lookup = fdt_node_offset_by_phandle(blob, fdt32_to_cpu(*phandle));
647 return lookup; 647 return lookup;
648 } 648 }
649 649
650 /** 650 /**
651 * Look up a property in a node and check that it has a minimum length. 651 * Look up a property in a node and check that it has a minimum length.
652 * 652 *
653 * @param blob FDT blob 653 * @param blob FDT blob
654 * @param node node to examine 654 * @param node node to examine
655 * @param prop_name name of property to find 655 * @param prop_name name of property to find
656 * @param min_len minimum property length in bytes 656 * @param min_len minimum property length in bytes
657 * @param err 0 if ok, or -FDT_ERR_NOTFOUND if the property is not 657 * @param err 0 if ok, or -FDT_ERR_NOTFOUND if the property is not
658 found, or -FDT_ERR_BADLAYOUT if not enough data 658 found, or -FDT_ERR_BADLAYOUT if not enough data
659 * @return pointer to cell, which is only valid if err == 0 659 * @return pointer to cell, which is only valid if err == 0
660 */ 660 */
661 static const void *get_prop_check_min_len(const void *blob, int node, 661 static const void *get_prop_check_min_len(const void *blob, int node,
662 const char *prop_name, int min_len, 662 const char *prop_name, int min_len,
663 int *err) 663 int *err)
664 { 664 {
665 const void *cell; 665 const void *cell;
666 int len; 666 int len;
667 667
668 debug("%s: %s\n", __func__, prop_name); 668 debug("%s: %s\n", __func__, prop_name);
669 cell = fdt_getprop(blob, node, prop_name, &len); 669 cell = fdt_getprop(blob, node, prop_name, &len);
670 if (!cell) 670 if (!cell)
671 *err = -FDT_ERR_NOTFOUND; 671 *err = -FDT_ERR_NOTFOUND;
672 else if (len < min_len) 672 else if (len < min_len)
673 *err = -FDT_ERR_BADLAYOUT; 673 *err = -FDT_ERR_BADLAYOUT;
674 else 674 else
675 *err = 0; 675 *err = 0;
676 return cell; 676 return cell;
677 } 677 }
678 678
679 int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, 679 int fdtdec_get_int_array(const void *blob, int node, const char *prop_name,
680 u32 *array, int count) 680 u32 *array, int count)
681 { 681 {
682 const u32 *cell; 682 const u32 *cell;
683 int err = 0; 683 int err = 0;
684 684
685 debug("%s: %s\n", __func__, prop_name); 685 debug("%s: %s\n", __func__, prop_name);
686 cell = get_prop_check_min_len(blob, node, prop_name, 686 cell = get_prop_check_min_len(blob, node, prop_name,
687 sizeof(u32) * count, &err); 687 sizeof(u32) * count, &err);
688 if (!err) { 688 if (!err) {
689 int i; 689 int i;
690 690
691 for (i = 0; i < count; i++) 691 for (i = 0; i < count; i++)
692 array[i] = fdt32_to_cpu(cell[i]); 692 array[i] = fdt32_to_cpu(cell[i]);
693 } 693 }
694 return err; 694 return err;
695 } 695 }
696 696
697 int fdtdec_get_int_array_count(const void *blob, int node, 697 int fdtdec_get_int_array_count(const void *blob, int node,
698 const char *prop_name, u32 *array, int count) 698 const char *prop_name, u32 *array, int count)
699 { 699 {
700 const u32 *cell; 700 const u32 *cell;
701 int len, elems; 701 int len, elems;
702 int i; 702 int i;
703 703
704 debug("%s: %s\n", __func__, prop_name); 704 debug("%s: %s\n", __func__, prop_name);
705 cell = fdt_getprop(blob, node, prop_name, &len); 705 cell = fdt_getprop(blob, node, prop_name, &len);
706 if (!cell) 706 if (!cell)
707 return -FDT_ERR_NOTFOUND; 707 return -FDT_ERR_NOTFOUND;
708 elems = len / sizeof(u32); 708 elems = len / sizeof(u32);
709 if (count > elems) 709 if (count > elems)
710 count = elems; 710 count = elems;
711 for (i = 0; i < count; i++) 711 for (i = 0; i < count; i++)
712 array[i] = fdt32_to_cpu(cell[i]); 712 array[i] = fdt32_to_cpu(cell[i]);
713 713
714 return count; 714 return count;
715 } 715 }
716 716
717 const u32 *fdtdec_locate_array(const void *blob, int node, 717 const u32 *fdtdec_locate_array(const void *blob, int node,
718 const char *prop_name, int count) 718 const char *prop_name, int count)
719 { 719 {
720 const u32 *cell; 720 const u32 *cell;
721 int err; 721 int err;
722 722
723 cell = get_prop_check_min_len(blob, node, prop_name, 723 cell = get_prop_check_min_len(blob, node, prop_name,
724 sizeof(u32) * count, &err); 724 sizeof(u32) * count, &err);
725 return err ? NULL : cell; 725 return err ? NULL : cell;
726 } 726 }
727 727
728 int fdtdec_get_bool(const void *blob, int node, const char *prop_name) 728 int fdtdec_get_bool(const void *blob, int node, const char *prop_name)
729 { 729 {
730 const s32 *cell; 730 const s32 *cell;
731 int len; 731 int len;
732 732
733 debug("%s: %s\n", __func__, prop_name); 733 debug("%s: %s\n", __func__, prop_name);
734 cell = fdt_getprop(blob, node, prop_name, &len); 734 cell = fdt_getprop(blob, node, prop_name, &len);
735 return cell != NULL; 735 return cell != NULL;
736 } 736 }
737 737
738 int fdtdec_parse_phandle_with_args(const void *blob, int src_node, 738 int fdtdec_parse_phandle_with_args(const void *blob, int src_node,
739 const char *list_name, 739 const char *list_name,
740 const char *cells_name, 740 const char *cells_name,
741 int cell_count, int index, 741 int cell_count, int index,
742 struct fdtdec_phandle_args *out_args) 742 struct fdtdec_phandle_args *out_args)
743 { 743 {
744 const __be32 *list, *list_end; 744 const __be32 *list, *list_end;
745 int rc = 0, size, cur_index = 0; 745 int rc = 0, size, cur_index = 0;
746 uint32_t count = 0; 746 uint32_t count = 0;
747 int node = -1; 747 int node = -1;
748 int phandle; 748 int phandle;
749 749
750 /* Retrieve the phandle list property */ 750 /* Retrieve the phandle list property */
751 list = fdt_getprop(blob, src_node, list_name, &size); 751 list = fdt_getprop(blob, src_node, list_name, &size);
752 if (!list) 752 if (!list)
753 return -ENOENT; 753 return -ENOENT;
754 list_end = list + size / sizeof(*list); 754 list_end = list + size / sizeof(*list);
755 755
756 /* Loop over the phandles until all the requested entry is found */ 756 /* Loop over the phandles until all the requested entry is found */
757 while (list < list_end) { 757 while (list < list_end) {
758 rc = -EINVAL; 758 rc = -EINVAL;
759 count = 0; 759 count = 0;
760 760
761 /* 761 /*
762 * If phandle is 0, then it is an empty entry with no 762 * If phandle is 0, then it is an empty entry with no
763 * arguments. Skip forward to the next entry. 763 * arguments. Skip forward to the next entry.
764 */ 764 */
765 phandle = be32_to_cpup(list++); 765 phandle = be32_to_cpup(list++);
766 if (phandle) { 766 if (phandle) {
767 /* 767 /*
768 * Find the provider node and parse the #*-cells 768 * Find the provider node and parse the #*-cells
769 * property to determine the argument length. 769 * property to determine the argument length.
770 * 770 *
771 * This is not needed if the cell count is hard-coded 771 * This is not needed if the cell count is hard-coded
772 * (i.e. cells_name not set, but cell_count is set), 772 * (i.e. cells_name not set, but cell_count is set),
773 * except when we're going to return the found node 773 * except when we're going to return the found node
774 * below. 774 * below.
775 */ 775 */
776 if (cells_name || cur_index == index) { 776 if (cells_name || cur_index == index) {
777 node = fdt_node_offset_by_phandle(blob, 777 node = fdt_node_offset_by_phandle(blob,
778 phandle); 778 phandle);
779 if (!node) { 779 if (!node) {
780 debug("%s: could not find phandle\n", 780 debug("%s: could not find phandle\n",
781 fdt_get_name(blob, src_node, 781 fdt_get_name(blob, src_node,
782 NULL)); 782 NULL));
783 goto err; 783 goto err;
784 } 784 }
785 } 785 }
786 786
787 if (cells_name) { 787 if (cells_name) {
788 count = fdtdec_get_int(blob, node, cells_name, 788 count = fdtdec_get_int(blob, node, cells_name,
789 -1); 789 -1);
790 if (count == -1) { 790 if (count == -1) {
791 debug("%s: could not get %s for %s\n", 791 debug("%s: could not get %s for %s\n",
792 fdt_get_name(blob, src_node, 792 fdt_get_name(blob, src_node,
793 NULL), 793 NULL),
794 cells_name, 794 cells_name,
795 fdt_get_name(blob, node, 795 fdt_get_name(blob, node,
796 NULL)); 796 NULL));
797 goto err; 797 goto err;
798 } 798 }
799 } else { 799 } else {
800 count = cell_count; 800 count = cell_count;
801 } 801 }
802 802
803 /* 803 /*
804 * Make sure that the arguments actually fit in the 804 * Make sure that the arguments actually fit in the
805 * remaining property data length 805 * remaining property data length
806 */ 806 */
807 if (list + count > list_end) { 807 if (list + count > list_end) {
808 debug("%s: arguments longer than property\n", 808 debug("%s: arguments longer than property\n",
809 fdt_get_name(blob, src_node, NULL)); 809 fdt_get_name(blob, src_node, NULL));
810 goto err; 810 goto err;
811 } 811 }
812 } 812 }
813 813
814 /* 814 /*
815 * All of the error cases above bail out of the loop, so at 815 * All of the error cases above bail out of the loop, so at
816 * this point, the parsing is successful. If the requested 816 * this point, the parsing is successful. If the requested
817 * index matches, then fill the out_args structure and return, 817 * index matches, then fill the out_args structure and return,
818 * or return -ENOENT for an empty entry. 818 * or return -ENOENT for an empty entry.
819 */ 819 */
820 rc = -ENOENT; 820 rc = -ENOENT;
821 if (cur_index == index) { 821 if (cur_index == index) {
822 if (!phandle) 822 if (!phandle)
823 goto err; 823 goto err;
824 824
825 if (out_args) { 825 if (out_args) {
826 int i; 826 int i;
827 827
828 if (count > MAX_PHANDLE_ARGS) { 828 if (count > MAX_PHANDLE_ARGS) {
829 debug("%s: too many arguments %d\n", 829 debug("%s: too many arguments %d\n",
830 fdt_get_name(blob, src_node, 830 fdt_get_name(blob, src_node,
831 NULL), count); 831 NULL), count);
832 count = MAX_PHANDLE_ARGS; 832 count = MAX_PHANDLE_ARGS;
833 } 833 }
834 out_args->node = node; 834 out_args->node = node;
835 out_args->args_count = count; 835 out_args->args_count = count;
836 for (i = 0; i < count; i++) { 836 for (i = 0; i < count; i++) {
837 out_args->args[i] = 837 out_args->args[i] =
838 be32_to_cpup(list++); 838 be32_to_cpup(list++);
839 } 839 }
840 } 840 }
841 841
842 /* Found it! return success */ 842 /* Found it! return success */
843 return 0; 843 return 0;
844 } 844 }
845 845
846 node = -1; 846 node = -1;
847 list += count; 847 list += count;
848 cur_index++; 848 cur_index++;
849 } 849 }
850 850
851 /* 851 /*
852 * Result will be one of: 852 * Result will be one of:
853 * -ENOENT : index is for empty phandle 853 * -ENOENT : index is for empty phandle
854 * -EINVAL : parsing error on data 854 * -EINVAL : parsing error on data
855 * [1..n] : Number of phandle (count mode; when index = -1) 855 * [1..n] : Number of phandle (count mode; when index = -1)
856 */ 856 */
857 rc = index < 0 ? cur_index : -ENOENT; 857 rc = index < 0 ? cur_index : -ENOENT;
858 err: 858 err:
859 return rc; 859 return rc;
860 } 860 }
861 861
862 int fdtdec_get_child_count(const void *blob, int node) 862 int fdtdec_get_child_count(const void *blob, int node)
863 { 863 {
864 int subnode; 864 int subnode;
865 int num = 0; 865 int num = 0;
866 866
867 fdt_for_each_subnode(subnode, blob, node) 867 fdt_for_each_subnode(subnode, blob, node)
868 num++; 868 num++;
869 869
870 return num; 870 return num;
871 } 871 }
872 872
873 int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name, 873 int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name,
874 u8 *array, int count) 874 u8 *array, int count)
875 { 875 {
876 const u8 *cell; 876 const u8 *cell;
877 int err; 877 int err;
878 878
879 cell = get_prop_check_min_len(blob, node, prop_name, count, &err); 879 cell = get_prop_check_min_len(blob, node, prop_name, count, &err);
880 if (!err) 880 if (!err)
881 memcpy(array, cell, count); 881 memcpy(array, cell, count);
882 return err; 882 return err;
883 } 883 }
884 884
885 const u8 *fdtdec_locate_byte_array(const void *blob, int node, 885 const u8 *fdtdec_locate_byte_array(const void *blob, int node,
886 const char *prop_name, int count) 886 const char *prop_name, int count)
887 { 887 {
888 const u8 *cell; 888 const u8 *cell;
889 int err; 889 int err;
890 890
891 cell = get_prop_check_min_len(blob, node, prop_name, count, &err); 891 cell = get_prop_check_min_len(blob, node, prop_name, count, &err);
892 if (err) 892 if (err)
893 return NULL; 893 return NULL;
894 return cell; 894 return cell;
895 } 895 }
896 896
897 int fdtdec_get_config_int(const void *blob, const char *prop_name, 897 int fdtdec_get_config_int(const void *blob, const char *prop_name,
898 int default_val) 898 int default_val)
899 { 899 {
900 int config_node; 900 int config_node;
901 901
902 debug("%s: %s\n", __func__, prop_name); 902 debug("%s: %s\n", __func__, prop_name);
903 config_node = fdt_path_offset(blob, "/config"); 903 config_node = fdt_path_offset(blob, "/config");
904 if (config_node < 0) 904 if (config_node < 0)
905 return default_val; 905 return default_val;
906 return fdtdec_get_int(blob, config_node, prop_name, default_val); 906 return fdtdec_get_int(blob, config_node, prop_name, default_val);
907 } 907 }
908 908
909 int fdtdec_get_config_bool(const void *blob, const char *prop_name) 909 int fdtdec_get_config_bool(const void *blob, const char *prop_name)
910 { 910 {
911 int config_node; 911 int config_node;
912 const void *prop; 912 const void *prop;
913 913
914 debug("%s: %s\n", __func__, prop_name); 914 debug("%s: %s\n", __func__, prop_name);
915 config_node = fdt_path_offset(blob, "/config"); 915 config_node = fdt_path_offset(blob, "/config");
916 if (config_node < 0) 916 if (config_node < 0)
917 return 0; 917 return 0;
918 prop = fdt_get_property(blob, config_node, prop_name, NULL); 918 prop = fdt_get_property(blob, config_node, prop_name, NULL);
919 919
920 return prop != NULL; 920 return prop != NULL;
921 } 921 }
922 922
923 char *fdtdec_get_config_string(const void *blob, const char *prop_name) 923 char *fdtdec_get_config_string(const void *blob, const char *prop_name)
924 { 924 {
925 const char *nodep; 925 const char *nodep;
926 int nodeoffset; 926 int nodeoffset;
927 int len; 927 int len;
928 928
929 debug("%s: %s\n", __func__, prop_name); 929 debug("%s: %s\n", __func__, prop_name);
930 nodeoffset = fdt_path_offset(blob, "/config"); 930 nodeoffset = fdt_path_offset(blob, "/config");
931 if (nodeoffset < 0) 931 if (nodeoffset < 0)
932 return NULL; 932 return NULL;
933 933
934 nodep = fdt_getprop(blob, nodeoffset, prop_name, &len); 934 nodep = fdt_getprop(blob, nodeoffset, prop_name, &len);
935 if (!nodep) 935 if (!nodep)
936 return NULL; 936 return NULL;
937 937
938 return (char *)nodep; 938 return (char *)nodep;
939 } 939 }
940 940
941 u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells) 941 u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells)
942 { 942 {
943 u64 number = 0; 943 u64 number = 0;
944 944
945 while (cells--) 945 while (cells--)
946 number = (number << 32) | fdt32_to_cpu(*ptr++); 946 number = (number << 32) | fdt32_to_cpu(*ptr++);
947 947
948 return number; 948 return number;
949 } 949 }
950 950
951 int fdt_get_resource(const void *fdt, int node, const char *property, 951 int fdt_get_resource(const void *fdt, int node, const char *property,
952 unsigned int index, struct fdt_resource *res) 952 unsigned int index, struct fdt_resource *res)
953 { 953 {
954 const fdt32_t *ptr, *end; 954 const fdt32_t *ptr, *end;
955 int na, ns, len, parent; 955 int na, ns, len, parent;
956 unsigned int i = 0; 956 unsigned int i = 0;
957 957
958 parent = fdt_parent_offset(fdt, node); 958 parent = fdt_parent_offset(fdt, node);
959 if (parent < 0) 959 if (parent < 0)
960 return parent; 960 return parent;
961 961
962 na = fdt_address_cells(fdt, parent); 962 na = fdt_address_cells(fdt, parent);
963 ns = fdt_size_cells(fdt, parent); 963 ns = fdt_size_cells(fdt, parent);
964 964
965 ptr = fdt_getprop(fdt, node, property, &len); 965 ptr = fdt_getprop(fdt, node, property, &len);
966 if (!ptr) 966 if (!ptr)
967 return len; 967 return len;
968 968
969 end = ptr + len / sizeof(*ptr); 969 end = ptr + len / sizeof(*ptr);
970 970
971 while (ptr + na + ns <= end) { 971 while (ptr + na + ns <= end) {
972 if (i == index) { 972 if (i == index) {
973 res->start = fdtdec_get_number(ptr, na); 973 res->start = fdtdec_get_number(ptr, na);
974 res->end = res->start; 974 res->end = res->start;
975 res->end += fdtdec_get_number(&ptr[na], ns) - 1; 975 res->end += fdtdec_get_number(&ptr[na], ns) - 1;
976 return 0; 976 return 0;
977 } 977 }
978 978
979 ptr += na + ns; 979 ptr += na + ns;
980 i++; 980 i++;
981 } 981 }
982 982
983 return -FDT_ERR_NOTFOUND; 983 return -FDT_ERR_NOTFOUND;
984 } 984 }
985 985
986 int fdt_get_named_resource(const void *fdt, int node, const char *property, 986 int fdt_get_named_resource(const void *fdt, int node, const char *property,
987 const char *prop_names, const char *name, 987 const char *prop_names, const char *name,
988 struct fdt_resource *res) 988 struct fdt_resource *res)
989 { 989 {
990 int index; 990 int index;
991 991
992 index = fdt_stringlist_search(fdt, node, prop_names, name); 992 index = fdt_stringlist_search(fdt, node, prop_names, name);
993 if (index < 0) 993 if (index < 0)
994 return index; 994 return index;
995 995
996 return fdt_get_resource(fdt, node, property, index, res); 996 return fdt_get_resource(fdt, node, property, index, res);
997 } 997 }
998 998
999 static int decode_timing_property(const void *blob, int node, const char *name, 999 static int decode_timing_property(const void *blob, int node, const char *name,
1000 struct timing_entry *result) 1000 struct timing_entry *result)
1001 { 1001 {
1002 int length, ret = 0; 1002 int length, ret = 0;
1003 const u32 *prop; 1003 const u32 *prop;
1004 1004
1005 prop = fdt_getprop(blob, node, name, &length); 1005 prop = fdt_getprop(blob, node, name, &length);
1006 if (!prop) { 1006 if (!prop) {
1007 debug("%s: could not find property %s\n", 1007 debug("%s: could not find property %s\n",
1008 fdt_get_name(blob, node, NULL), name); 1008 fdt_get_name(blob, node, NULL), name);
1009 return length; 1009 return length;
1010 } 1010 }
1011 1011
1012 if (length == sizeof(u32)) { 1012 if (length == sizeof(u32)) {
1013 result->typ = fdtdec_get_int(blob, node, name, 0); 1013 result->typ = fdtdec_get_int(blob, node, name, 0);
1014 result->min = result->typ; 1014 result->min = result->typ;
1015 result->max = result->typ; 1015 result->max = result->typ;
1016 } else { 1016 } else {
1017 ret = fdtdec_get_int_array(blob, node, name, &result->min, 3); 1017 ret = fdtdec_get_int_array(blob, node, name, &result->min, 3);
1018 } 1018 }
1019 1019
1020 return ret; 1020 return ret;
1021 } 1021 }
1022 1022
1023 int fdtdec_decode_display_timing(const void *blob, int parent, int index, 1023 int fdtdec_decode_display_timing(const void *blob, int parent, int index,
1024 struct display_timing *dt) 1024 struct display_timing *dt)
1025 { 1025 {
1026 int i, node, timings_node; 1026 int i, node, timings_node;
1027 u32 val = 0; 1027 u32 val = 0;
1028 int ret = 0; 1028 int ret = 0;
1029 1029
1030 timings_node = fdt_subnode_offset(blob, parent, "display-timings"); 1030 timings_node = fdt_subnode_offset(blob, parent, "display-timings");
1031 if (timings_node < 0) 1031 if (timings_node < 0)
1032 return timings_node; 1032 return timings_node;
1033 1033
1034 for (i = 0, node = fdt_first_subnode(blob, timings_node); 1034 for (i = 0, node = fdt_first_subnode(blob, timings_node);
1035 node > 0 && i != index; 1035 node > 0 && i != index;
1036 node = fdt_next_subnode(blob, node)) 1036 node = fdt_next_subnode(blob, node))
1037 i++; 1037 i++;
1038 1038
1039 if (node < 0) 1039 if (node < 0)
1040 return node; 1040 return node;
1041 1041
1042 memset(dt, 0, sizeof(*dt)); 1042 memset(dt, 0, sizeof(*dt));
1043 1043
1044 ret |= decode_timing_property(blob, node, "hback-porch", 1044 ret |= decode_timing_property(blob, node, "hback-porch",
1045 &dt->hback_porch); 1045 &dt->hback_porch);
1046 ret |= decode_timing_property(blob, node, "hfront-porch", 1046 ret |= decode_timing_property(blob, node, "hfront-porch",
1047 &dt->hfront_porch); 1047 &dt->hfront_porch);
1048 ret |= decode_timing_property(blob, node, "hactive", &dt->hactive); 1048 ret |= decode_timing_property(blob, node, "hactive", &dt->hactive);
1049 ret |= decode_timing_property(blob, node, "hsync-len", &dt->hsync_len); 1049 ret |= decode_timing_property(blob, node, "hsync-len", &dt->hsync_len);
1050 ret |= decode_timing_property(blob, node, "vback-porch", 1050 ret |= decode_timing_property(blob, node, "vback-porch",
1051 &dt->vback_porch); 1051 &dt->vback_porch);
1052 ret |= decode_timing_property(blob, node, "vfront-porch", 1052 ret |= decode_timing_property(blob, node, "vfront-porch",
1053 &dt->vfront_porch); 1053 &dt->vfront_porch);
1054 ret |= decode_timing_property(blob, node, "vactive", &dt->vactive); 1054 ret |= decode_timing_property(blob, node, "vactive", &dt->vactive);
1055 ret |= decode_timing_property(blob, node, "vsync-len", &dt->vsync_len); 1055 ret |= decode_timing_property(blob, node, "vsync-len", &dt->vsync_len);
1056 ret |= decode_timing_property(blob, node, "clock-frequency", 1056 ret |= decode_timing_property(blob, node, "clock-frequency",
1057 &dt->pixelclock); 1057 &dt->pixelclock);
1058 1058
1059 dt->flags = 0; 1059 dt->flags = 0;
1060 val = fdtdec_get_int(blob, node, "vsync-active", -1); 1060 val = fdtdec_get_int(blob, node, "vsync-active", -1);
1061 if (val != -1) { 1061 if (val != -1) {
1062 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH : 1062 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
1063 DISPLAY_FLAGS_VSYNC_LOW; 1063 DISPLAY_FLAGS_VSYNC_LOW;
1064 } 1064 }
1065 val = fdtdec_get_int(blob, node, "hsync-active", -1); 1065 val = fdtdec_get_int(blob, node, "hsync-active", -1);
1066 if (val != -1) { 1066 if (val != -1) {
1067 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH : 1067 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
1068 DISPLAY_FLAGS_HSYNC_LOW; 1068 DISPLAY_FLAGS_HSYNC_LOW;
1069 } 1069 }
1070 val = fdtdec_get_int(blob, node, "de-active", -1); 1070 val = fdtdec_get_int(blob, node, "de-active", -1);
1071 if (val != -1) { 1071 if (val != -1) {
1072 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH : 1072 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
1073 DISPLAY_FLAGS_DE_LOW; 1073 DISPLAY_FLAGS_DE_LOW;
1074 } 1074 }
1075 val = fdtdec_get_int(blob, node, "pixelclk-active", -1); 1075 val = fdtdec_get_int(blob, node, "pixelclk-active", -1);
1076 if (val != -1) { 1076 if (val != -1) {
1077 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE : 1077 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
1078 DISPLAY_FLAGS_PIXDATA_NEGEDGE; 1078 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
1079 } 1079 }
1080 1080
1081 if (fdtdec_get_bool(blob, node, "interlaced")) 1081 if (fdtdec_get_bool(blob, node, "interlaced"))
1082 dt->flags |= DISPLAY_FLAGS_INTERLACED; 1082 dt->flags |= DISPLAY_FLAGS_INTERLACED;
1083 if (fdtdec_get_bool(blob, node, "doublescan")) 1083 if (fdtdec_get_bool(blob, node, "doublescan"))
1084 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN; 1084 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
1085 if (fdtdec_get_bool(blob, node, "doubleclk")) 1085 if (fdtdec_get_bool(blob, node, "doubleclk"))
1086 dt->flags |= DISPLAY_FLAGS_DOUBLECLK; 1086 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
1087 1087
1088 return ret; 1088 return ret;
1089 } 1089 }
1090 1090
1091 int fdtdec_setup_mem_size_base_fdt(const void *blob) 1091 int fdtdec_setup_mem_size_base_fdt(const void *blob)
1092 { 1092 {
1093 int ret, mem; 1093 int ret, mem;
1094 struct fdt_resource res; 1094 struct fdt_resource res;
1095 1095
1096 mem = fdt_path_offset(blob, "/memory"); 1096 mem = fdt_path_offset(blob, "/memory");
1097 if (mem < 0) { 1097 if (mem < 0) {
1098 debug("%s: Missing /memory node\n", __func__); 1098 debug("%s: Missing /memory node\n", __func__);
1099 return -EINVAL; 1099 return -EINVAL;
1100 } 1100 }
1101 1101
1102 ret = fdt_get_resource(blob, mem, "reg", 0, &res); 1102 ret = fdt_get_resource(blob, mem, "reg", 0, &res);
1103 if (ret != 0) { 1103 if (ret != 0) {
1104 debug("%s: Unable to decode first memory bank\n", __func__); 1104 debug("%s: Unable to decode first memory bank\n", __func__);
1105 return -EINVAL; 1105 return -EINVAL;
1106 } 1106 }
1107 1107
1108 gd->ram_size = (phys_size_t)(res.end - res.start + 1); 1108 gd->ram_size = (phys_size_t)(res.end - res.start + 1);
1109 gd->ram_base = (unsigned long)res.start; 1109 gd->ram_base = (unsigned long)res.start;
1110 debug("%s: Initial DRAM size %llx\n", __func__, 1110 debug("%s: Initial DRAM size %llx\n", __func__,
1111 (unsigned long long)gd->ram_size); 1111 (unsigned long long)gd->ram_size);
1112 1112
1113 return 0; 1113 return 0;
1114 } 1114 }
1115 1115
1116 int fdtdec_setup_mem_size_base(void) 1116 int fdtdec_setup_mem_size_base(void)
1117 { 1117 {
1118 return fdtdec_setup_mem_size_base_fdt(gd->fdt_blob); 1118 return fdtdec_setup_mem_size_base_fdt(gd->fdt_blob);
1119 } 1119 }
1120 1120
1121 #if defined(CONFIG_NR_DRAM_BANKS) 1121 #if defined(CONFIG_NR_DRAM_BANKS)
1122 1122
1123 static int get_next_memory_node(const void *blob, int mem) 1123 static int get_next_memory_node(const void *blob, int mem)
1124 { 1124 {
1125 do { 1125 do {
1126 mem = fdt_node_offset_by_prop_value(blob, mem, 1126 mem = fdt_node_offset_by_prop_value(blob, mem,
1127 "device_type", "memory", 7); 1127 "device_type", "memory", 7);
1128 } while (!fdtdec_get_is_enabled(blob, mem)); 1128 } while (!fdtdec_get_is_enabled(blob, mem));
1129 1129
1130 return mem; 1130 return mem;
1131 } 1131 }
1132 1132
1133 int fdtdec_setup_memory_banksize_fdt(const void *blob) 1133 int fdtdec_setup_memory_banksize_fdt(const void *blob)
1134 { 1134 {
1135 int bank, ret, mem, reg = 0; 1135 int bank, ret, mem, reg = 0;
1136 struct fdt_resource res; 1136 struct fdt_resource res;
1137 1137
1138 mem = get_next_memory_node(blob, -1); 1138 mem = get_next_memory_node(blob, -1);
1139 if (mem < 0) { 1139 if (mem < 0) {
1140 debug("%s: Missing /memory node\n", __func__); 1140 debug("%s: Missing /memory node\n", __func__);
1141 return -EINVAL; 1141 return -EINVAL;
1142 } 1142 }
1143 1143
1144 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { 1144 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
1145 ret = fdt_get_resource(blob, mem, "reg", reg++, &res); 1145 ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
1146 if (ret == -FDT_ERR_NOTFOUND) { 1146 if (ret == -FDT_ERR_NOTFOUND) {
1147 reg = 0; 1147 reg = 0;
1148 mem = get_next_memory_node(blob, mem); 1148 mem = get_next_memory_node(blob, mem);
1149 if (mem == -FDT_ERR_NOTFOUND) 1149 if (mem == -FDT_ERR_NOTFOUND)
1150 break; 1150 break;
1151 1151
1152 ret = fdt_get_resource(blob, mem, "reg", reg++, &res); 1152 ret = fdt_get_resource(blob, mem, "reg", reg++, &res);
1153 if (ret == -FDT_ERR_NOTFOUND) 1153 if (ret == -FDT_ERR_NOTFOUND)
1154 break; 1154 break;
1155 } 1155 }
1156 if (ret != 0) { 1156 if (ret != 0) {
1157 return -EINVAL; 1157 return -EINVAL;
1158 } 1158 }
1159 1159
1160 gd->bd->bi_dram[bank].start = (phys_addr_t)res.start; 1160 gd->bd->bi_dram[bank].start = (phys_addr_t)res.start;
1161 gd->bd->bi_dram[bank].size = 1161 gd->bd->bi_dram[bank].size =
1162 (phys_size_t)(res.end - res.start + 1); 1162 (phys_size_t)(res.end - res.start + 1);
1163 1163
1164 debug("%s: DRAM Bank #%d: start = 0x%llx, size = 0x%llx\n", 1164 debug("%s: DRAM Bank #%d: start = 0x%llx, size = 0x%llx\n",
1165 __func__, bank, 1165 __func__, bank,
1166 (unsigned long long)gd->bd->bi_dram[bank].start, 1166 (unsigned long long)gd->bd->bi_dram[bank].start,
1167 (unsigned long long)gd->bd->bi_dram[bank].size); 1167 (unsigned long long)gd->bd->bi_dram[bank].size);
1168 } 1168 }
1169 1169
1170 return 0; 1170 return 0;
1171 } 1171 }
1172 1172
1173 int fdtdec_setup_memory_banksize(void) 1173 int fdtdec_setup_memory_banksize(void)
1174 { 1174 {
1175 return fdtdec_setup_memory_banksize_fdt(gd->fdt_blob); 1175 return fdtdec_setup_memory_banksize_fdt(gd->fdt_blob);
1176 1176
1177 } 1177 }
1178 #endif 1178 #endif
1179 1179
1180 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) 1180 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
1181 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT_GZIP) ||\ 1181 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT_GZIP) ||\
1182 CONFIG_IS_ENABLED(MULTI_DTB_FIT_LZO) 1182 CONFIG_IS_ENABLED(MULTI_DTB_FIT_LZO)
1183 static int uncompress_blob(const void *src, ulong sz_src, void **dstp) 1183 static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
1184 { 1184 {
1185 size_t sz_out = CONFIG_VAL(MULTI_DTB_FIT_UNCOMPRESS_SZ); 1185 size_t sz_out = CONFIG_VAL(MULTI_DTB_FIT_UNCOMPRESS_SZ);
1186 bool gzip = 0, lzo = 0; 1186 bool gzip = 0, lzo = 0;
1187 ulong sz_in = sz_src; 1187 ulong sz_in = sz_src;
1188 void *dst; 1188 void *dst;
1189 int rc; 1189 int rc;
1190 1190
1191 if (CONFIG_IS_ENABLED(GZIP)) 1191 if (CONFIG_IS_ENABLED(GZIP))
1192 if (gzip_parse_header(src, sz_in) >= 0) 1192 if (gzip_parse_header(src, sz_in) >= 0)
1193 gzip = 1; 1193 gzip = 1;
1194 if (CONFIG_IS_ENABLED(LZO)) 1194 if (CONFIG_IS_ENABLED(LZO))
1195 if (!gzip && lzop_is_valid_header(src)) 1195 if (!gzip && lzop_is_valid_header(src))
1196 lzo = 1; 1196 lzo = 1;
1197 1197
1198 if (!gzip && !lzo) 1198 if (!gzip && !lzo)
1199 return -EBADMSG; 1199 return -EBADMSG;
1200 1200
1201 1201
1202 if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)) { 1202 if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)) {
1203 dst = malloc(sz_out); 1203 dst = malloc(sz_out);
1204 if (!dst) { 1204 if (!dst) {
1205 puts("uncompress_blob: Unable to allocate memory\n"); 1205 puts("uncompress_blob: Unable to allocate memory\n");
1206 return -ENOMEM; 1206 return -ENOMEM;
1207 } 1207 }
1208 } else { 1208 } else {
1209 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT_USER_DEFINED_AREA) 1209 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT_USER_DEFINED_AREA)
1210 dst = (void *)CONFIG_VAL(MULTI_DTB_FIT_USER_DEF_ADDR); 1210 dst = (void *)CONFIG_VAL(MULTI_DTB_FIT_USER_DEF_ADDR);
1211 # else 1211 # else
1212 return -ENOTSUPP; 1212 return -ENOTSUPP;
1213 # endif 1213 # endif
1214 } 1214 }
1215 1215
1216 if (CONFIG_IS_ENABLED(GZIP) && gzip) 1216 if (CONFIG_IS_ENABLED(GZIP) && gzip)
1217 rc = gunzip(dst, sz_out, (u8 *)src, &sz_in); 1217 rc = gunzip(dst, sz_out, (u8 *)src, &sz_in);
1218 else if (CONFIG_IS_ENABLED(LZO) && lzo) 1218 else if (CONFIG_IS_ENABLED(LZO) && lzo)
1219 rc = lzop_decompress(src, sz_in, dst, &sz_out); 1219 rc = lzop_decompress(src, sz_in, dst, &sz_out);
1220 else 1220 else
1221 hang(); 1221 hang();
1222 1222
1223 if (rc < 0) { 1223 if (rc < 0) {
1224 /* not a valid compressed blob */ 1224 /* not a valid compressed blob */
1225 puts("uncompress_blob: Unable to uncompress\n"); 1225 puts("uncompress_blob: Unable to uncompress\n");
1226 if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC)) 1226 if (CONFIG_IS_ENABLED(MULTI_DTB_FIT_DYN_ALLOC))
1227 free(dst); 1227 free(dst);
1228 return -EBADMSG; 1228 return -EBADMSG;
1229 } 1229 }
1230 *dstp = dst; 1230 *dstp = dst;
1231 return 0; 1231 return 0;
1232 } 1232 }
1233 # else 1233 # else
1234 static int uncompress_blob(const void *src, ulong sz_src, void **dstp) 1234 static int uncompress_blob(const void *src, ulong sz_src, void **dstp)
1235 { 1235 {
1236 *dstp = (void *)src; 1236 *dstp = (void *)src;
1237 return 0; 1237 return 0;
1238 } 1238 }
1239 # endif 1239 # endif
1240 #endif 1240 #endif
1241 1241
1242 #if defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE) 1242 #if defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE)
1243 /* 1243 /*
1244 * For CONFIG_OF_SEPARATE, the board may optionally implement this to 1244 * For CONFIG_OF_SEPARATE, the board may optionally implement this to
1245 * provide and/or fixup the fdt. 1245 * provide and/or fixup the fdt.
1246 */ 1246 */
1247 __weak void *board_fdt_blob_setup(void) 1247 __weak void *board_fdt_blob_setup(void)
1248 { 1248 {
1249 void *fdt_blob = NULL; 1249 void *fdt_blob = NULL;
1250 #ifdef CONFIG_SPL_BUILD 1250 #ifdef CONFIG_SPL_BUILD
1251 /* FDT is at end of BSS unless it is in a different memory region */ 1251 /* FDT is at end of BSS unless it is in a different memory region */
1252 if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS)) 1252 if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS))
1253 fdt_blob = (ulong *)&_image_binary_end; 1253 fdt_blob = (ulong *)&_image_binary_end;
1254 else 1254 else
1255 fdt_blob = (ulong *)&__bss_end; 1255 fdt_blob = (ulong *)&__bss_end;
1256 #else 1256 #else
1257 /* FDT is at end of image */ 1257 /* FDT is at end of image */
1258 fdt_blob = (ulong *)&_end; 1258 fdt_blob = (ulong *)&_end;
1259 #endif 1259 #endif
1260 return fdt_blob; 1260 return fdt_blob;
1261 } 1261 }
1262 #endif 1262 #endif
1263 1263
1264 static int fdtdec_init_reserved_memory(void *blob) 1264 static int fdtdec_init_reserved_memory(void *blob)
1265 { 1265 {
1266 int na, ns, node, err; 1266 int na, ns, node, err;
1267 fdt32_t value; 1267 fdt32_t value;
1268 1268
1269 /* inherit #address-cells and #size-cells from the root node */ 1269 /* inherit #address-cells and #size-cells from the root node */
1270 na = fdt_address_cells(blob, 0); 1270 na = fdt_address_cells(blob, 0);
1271 ns = fdt_size_cells(blob, 0); 1271 ns = fdt_size_cells(blob, 0);
1272 1272
1273 node = fdt_add_subnode(blob, 0, "reserved-memory"); 1273 node = fdt_add_subnode(blob, 0, "reserved-memory");
1274 if (node < 0) 1274 if (node < 0)
1275 return node; 1275 return node;
1276 1276
1277 err = fdt_setprop(blob, node, "ranges", NULL, 0); 1277 err = fdt_setprop(blob, node, "ranges", NULL, 0);
1278 if (err < 0) 1278 if (err < 0)
1279 return err; 1279 return err;
1280 1280
1281 value = cpu_to_fdt32(ns); 1281 value = cpu_to_fdt32(ns);
1282 1282
1283 err = fdt_setprop(blob, node, "#size-cells", &value, sizeof(value)); 1283 err = fdt_setprop(blob, node, "#size-cells", &value, sizeof(value));
1284 if (err < 0) 1284 if (err < 0)
1285 return err; 1285 return err;
1286 1286
1287 value = cpu_to_fdt32(na); 1287 value = cpu_to_fdt32(na);
1288 1288
1289 err = fdt_setprop(blob, node, "#address-cells", &value, sizeof(value)); 1289 err = fdt_setprop(blob, node, "#address-cells", &value, sizeof(value));
1290 if (err < 0) 1290 if (err < 0)
1291 return err; 1291 return err;
1292 1292
1293 return node; 1293 return node;
1294 } 1294 }
1295 1295
1296 int fdtdec_add_reserved_memory(void *blob, const char *basename, 1296 int fdtdec_add_reserved_memory(void *blob, const char *basename,
1297 const struct fdt_memory *carveout, 1297 const struct fdt_memory *carveout,
1298 uint32_t *phandlep) 1298 uint32_t *phandlep)
1299 { 1299 {
1300 fdt32_t cells[4] = {}, *ptr = cells; 1300 fdt32_t cells[4] = {}, *ptr = cells;
1301 uint32_t upper, lower, phandle; 1301 uint32_t upper, lower, phandle;
1302 int parent, node, na, ns, err; 1302 int parent, node, na, ns, err;
1303 fdt_size_t size;
1303 char name[64]; 1304 char name[64];
1304 1305
1305 /* create an empty /reserved-memory node if one doesn't exist */ 1306 /* create an empty /reserved-memory node if one doesn't exist */
1306 parent = fdt_path_offset(blob, "/reserved-memory"); 1307 parent = fdt_path_offset(blob, "/reserved-memory");
1307 if (parent < 0) { 1308 if (parent < 0) {
1308 parent = fdtdec_init_reserved_memory(blob); 1309 parent = fdtdec_init_reserved_memory(blob);
1309 if (parent < 0) 1310 if (parent < 0)
1310 return parent; 1311 return parent;
1311 } 1312 }
1312 1313
1313 /* only 1 or 2 #address-cells and #size-cells are supported */ 1314 /* only 1 or 2 #address-cells and #size-cells are supported */
1314 na = fdt_address_cells(blob, parent); 1315 na = fdt_address_cells(blob, parent);
1315 if (na < 1 || na > 2) 1316 if (na < 1 || na > 2)
1316 return -FDT_ERR_BADNCELLS; 1317 return -FDT_ERR_BADNCELLS;
1317 1318
1318 ns = fdt_size_cells(blob, parent); 1319 ns = fdt_size_cells(blob, parent);
1319 if (ns < 1 || ns > 2) 1320 if (ns < 1 || ns > 2)
1320 return -FDT_ERR_BADNCELLS; 1321 return -FDT_ERR_BADNCELLS;
1321 1322
1322 /* find a matching node and return the phandle to that */ 1323 /* find a matching node and return the phandle to that */
1323 fdt_for_each_subnode(node, blob, parent) { 1324 fdt_for_each_subnode(node, blob, parent) {
1324 const char *name = fdt_get_name(blob, node, NULL); 1325 const char *name = fdt_get_name(blob, node, NULL);
1325 phys_addr_t addr, size; 1326 phys_addr_t addr, size;
1326 1327
1327 addr = fdtdec_get_addr_size(blob, node, "reg", &size); 1328 addr = fdtdec_get_addr_size(blob, node, "reg", &size);
1328 if (addr == FDT_ADDR_T_NONE) { 1329 if (addr == FDT_ADDR_T_NONE) {
1329 debug("failed to read address/size for %s\n", name); 1330 debug("failed to read address/size for %s\n", name);
1330 continue; 1331 continue;
1331 } 1332 }
1332 1333
1333 if (addr == carveout->start && (addr + size) == carveout->end) { 1334 if (addr == carveout->start && (addr + size) == carveout->end) {
1334 *phandlep = fdt_get_phandle(blob, node); 1335 *phandlep = fdt_get_phandle(blob, node);
1335 return 0; 1336 return 0;
1336 } 1337 }
1337 } 1338 }
1338 1339
1339 /* 1340 /*
1340 * Unpack the start address and generate the name of the new node 1341 * Unpack the start address and generate the name of the new node
1341 * base on the basename and the unit-address. 1342 * base on the basename and the unit-address.
1342 */ 1343 */
1343 lower = fdt_addr_unpack(carveout->start, &upper); 1344 upper = upper_32_bits(carveout->start);
1345 lower = lower_32_bits(carveout->start);
1344 1346
1345 if (na > 1 && upper > 0) 1347 if (na > 1 && upper > 0)
1346 snprintf(name, sizeof(name), "%s@%x,%x", basename, upper, 1348 snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
1347 lower); 1349 lower);
1348 else { 1350 else {
1349 if (upper > 0) { 1351 if (upper > 0) {
1350 debug("address %08x:%08x exceeds addressable space\n", 1352 debug("address %08x:%08x exceeds addressable space\n",
1351 upper, lower); 1353 upper, lower);
1352 return -FDT_ERR_BADVALUE; 1354 return -FDT_ERR_BADVALUE;
1353 } 1355 }
1354 1356
1355 snprintf(name, sizeof(name), "%s@%x", basename, lower); 1357 snprintf(name, sizeof(name), "%s@%x", basename, lower);
1356 } 1358 }
1357 1359
1358 node = fdt_add_subnode(blob, parent, name); 1360 node = fdt_add_subnode(blob, parent, name);
1359 if (node < 0) 1361 if (node < 0)
1360 return node; 1362 return node;
1361 1363
1362 err = fdt_generate_phandle(blob, &phandle); 1364 err = fdt_generate_phandle(blob, &phandle);
1363 if (err < 0) 1365 if (err < 0)
1364 return err; 1366 return err;
1365 1367
1366 err = fdtdec_set_phandle(blob, node, phandle); 1368 err = fdtdec_set_phandle(blob, node, phandle);
1367 if (err < 0) 1369 if (err < 0)
1368 return err; 1370 return err;
1369 1371
1370 /* store one or two address cells */ 1372 /* store one or two address cells */
1371 if (na > 1) 1373 if (na > 1)
1372 *ptr++ = cpu_to_fdt32(upper); 1374 *ptr++ = cpu_to_fdt32(upper);
1373 1375
1374 *ptr++ = cpu_to_fdt32(lower); 1376 *ptr++ = cpu_to_fdt32(lower);
1375 1377
1376 /* store one or two size cells */ 1378 /* store one or two size cells */
1377 lower = fdt_size_unpack(carveout->end - carveout->start + 1, &upper); 1379 size = carveout->end - carveout->start + 1;
1380 upper = upper_32_bits(size);
1381 lower = lower_32_bits(size);
1378 1382
1379 if (ns > 1) 1383 if (ns > 1)
1380 *ptr++ = cpu_to_fdt32(upper); 1384 *ptr++ = cpu_to_fdt32(upper);
1381 1385
1382 *ptr++ = cpu_to_fdt32(lower); 1386 *ptr++ = cpu_to_fdt32(lower);
1383 1387
1384 err = fdt_setprop(blob, node, "reg", cells, (na + ns) * sizeof(*cells)); 1388 err = fdt_setprop(blob, node, "reg", cells, (na + ns) * sizeof(*cells));
1385 if (err < 0) 1389 if (err < 0)
1386 return err; 1390 return err;
1387 1391
1388 /* return the phandle for the new node for the caller to use */ 1392 /* return the phandle for the new node for the caller to use */
1389 if (phandlep) 1393 if (phandlep)
1390 *phandlep = phandle; 1394 *phandlep = phandle;
1391 1395
1392 return 0; 1396 return 0;
1393 } 1397 }
1394 1398
1395 int fdtdec_get_carveout(const void *blob, const char *node, const char *name, 1399 int fdtdec_get_carveout(const void *blob, const char *node, const char *name,
1396 unsigned int index, struct fdt_memory *carveout) 1400 unsigned int index, struct fdt_memory *carveout)
1397 { 1401 {
1398 const fdt32_t *prop; 1402 const fdt32_t *prop;
1399 uint32_t phandle; 1403 uint32_t phandle;
1400 int offset, len; 1404 int offset, len;
1401 fdt_size_t size; 1405 fdt_size_t size;
1402 1406
1403 offset = fdt_path_offset(blob, node); 1407 offset = fdt_path_offset(blob, node);
1404 if (offset < 0) 1408 if (offset < 0)
1405 return offset; 1409 return offset;
1406 1410
1407 prop = fdt_getprop(blob, offset, name, &len); 1411 prop = fdt_getprop(blob, offset, name, &len);
1408 if (!prop) { 1412 if (!prop) {
1409 debug("failed to get %s for %s\n", name, node); 1413 debug("failed to get %s for %s\n", name, node);
1410 return -FDT_ERR_NOTFOUND; 1414 return -FDT_ERR_NOTFOUND;
1411 } 1415 }
1412 1416
1413 if ((len % sizeof(phandle)) != 0) { 1417 if ((len % sizeof(phandle)) != 0) {
1414 debug("invalid phandle property\n"); 1418 debug("invalid phandle property\n");
1415 return -FDT_ERR_BADPHANDLE; 1419 return -FDT_ERR_BADPHANDLE;
1416 } 1420 }
1417 1421
1418 if (len < (sizeof(phandle) * (index + 1))) { 1422 if (len < (sizeof(phandle) * (index + 1))) {
1419 debug("invalid phandle index\n"); 1423 debug("invalid phandle index\n");
1420 return -FDT_ERR_BADPHANDLE; 1424 return -FDT_ERR_BADPHANDLE;
1421 } 1425 }
1422 1426
1423 phandle = fdt32_to_cpu(prop[index]); 1427 phandle = fdt32_to_cpu(prop[index]);
1424 1428
1425 offset = fdt_node_offset_by_phandle(blob, phandle); 1429 offset = fdt_node_offset_by_phandle(blob, phandle);
1426 if (offset < 0) { 1430 if (offset < 0) {
1427 debug("failed to find node for phandle %u\n", phandle); 1431 debug("failed to find node for phandle %u\n", phandle);
1428 return offset; 1432 return offset;
1429 } 1433 }
1430 1434
1431 carveout->start = fdtdec_get_addr_size_auto_noparent(blob, offset, 1435 carveout->start = fdtdec_get_addr_size_auto_noparent(blob, offset,
1432 "reg", 0, &size, 1436 "reg", 0, &size,
1433 true); 1437 true);
1434 if (carveout->start == FDT_ADDR_T_NONE) { 1438 if (carveout->start == FDT_ADDR_T_NONE) {
1435 debug("failed to read address/size from \"reg\" property\n"); 1439 debug("failed to read address/size from \"reg\" property\n");
1436 return -FDT_ERR_NOTFOUND; 1440 return -FDT_ERR_NOTFOUND;
1437 } 1441 }
1438 1442
1439 carveout->end = carveout->start + size - 1; 1443 carveout->end = carveout->start + size - 1;
1440 1444
1441 return 0; 1445 return 0;
1442 } 1446 }
1443 1447
1444 int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name, 1448 int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name,
1445 unsigned int index, const char *name, 1449 unsigned int index, const char *name,
1446 const struct fdt_memory *carveout) 1450 const struct fdt_memory *carveout)
1447 { 1451 {
1448 uint32_t phandle; 1452 uint32_t phandle;
1449 int err, offset; 1453 int err, offset;
1450 fdt32_t value; 1454 fdt32_t value;
1451 1455
1452 /* XXX implement support for multiple phandles */ 1456 /* XXX implement support for multiple phandles */
1453 if (index > 0) { 1457 if (index > 0) {
1454 debug("invalid index %u\n", index); 1458 debug("invalid index %u\n", index);
1455 return -FDT_ERR_BADOFFSET; 1459 return -FDT_ERR_BADOFFSET;
1456 } 1460 }
1457 1461
1458 err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle); 1462 err = fdtdec_add_reserved_memory(blob, name, carveout, &phandle);
1459 if (err < 0) { 1463 if (err < 0) {
1460 debug("failed to add reserved memory: %d\n", err); 1464 debug("failed to add reserved memory: %d\n", err);
1461 return err; 1465 return err;
1462 } 1466 }
1463 1467
1464 offset = fdt_path_offset(blob, node); 1468 offset = fdt_path_offset(blob, node);
1465 if (offset < 0) { 1469 if (offset < 0) {
1466 debug("failed to find offset for node %s: %d\n", node, offset); 1470 debug("failed to find offset for node %s: %d\n", node, offset);
1467 return offset; 1471 return offset;
1468 } 1472 }
1469 1473
1470 value = cpu_to_fdt32(phandle); 1474 value = cpu_to_fdt32(phandle);
1471 1475
1472 err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value)); 1476 err = fdt_setprop(blob, offset, prop_name, &value, sizeof(value));
1473 if (err < 0) { 1477 if (err < 0) {
1474 debug("failed to set %s property for node %s: %d\n", prop_name, 1478 debug("failed to set %s property for node %s: %d\n", prop_name,
1475 node, err); 1479 node, err);
1476 return err; 1480 return err;
1477 } 1481 }
1478 1482
1479 return 0; 1483 return 0;
1480 } 1484 }
1481 1485
1482 int fdtdec_setup(void) 1486 int fdtdec_setup(void)
1483 { 1487 {
1484 #if CONFIG_IS_ENABLED(OF_CONTROL) 1488 #if CONFIG_IS_ENABLED(OF_CONTROL)
1485 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT) 1489 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
1486 void *fdt_blob; 1490 void *fdt_blob;
1487 # endif 1491 # endif
1488 # ifdef CONFIG_OF_EMBED 1492 # ifdef CONFIG_OF_EMBED
1489 /* Get a pointer to the FDT */ 1493 /* Get a pointer to the FDT */
1490 # ifdef CONFIG_SPL_BUILD 1494 # ifdef CONFIG_SPL_BUILD
1491 gd->fdt_blob = __dtb_dt_spl_begin; 1495 gd->fdt_blob = __dtb_dt_spl_begin;
1492 # else 1496 # else
1493 gd->fdt_blob = __dtb_dt_begin; 1497 gd->fdt_blob = __dtb_dt_begin;
1494 # endif 1498 # endif
1495 # elif defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE) 1499 # elif defined(CONFIG_OF_BOARD) || defined(CONFIG_OF_SEPARATE)
1496 /* Allow the board to override the fdt address. */ 1500 /* Allow the board to override the fdt address. */
1497 gd->fdt_blob = board_fdt_blob_setup(); 1501 gd->fdt_blob = board_fdt_blob_setup();
1498 # elif defined(CONFIG_OF_HOSTFILE) 1502 # elif defined(CONFIG_OF_HOSTFILE)
1499 if (sandbox_read_fdt_from_file()) { 1503 if (sandbox_read_fdt_from_file()) {
1500 puts("Failed to read control FDT\n"); 1504 puts("Failed to read control FDT\n");
1501 return -1; 1505 return -1;
1502 } 1506 }
1503 # endif 1507 # endif
1504 # ifndef CONFIG_SPL_BUILD 1508 # ifndef CONFIG_SPL_BUILD
1505 /* Allow the early environment to override the fdt address */ 1509 /* Allow the early environment to override the fdt address */
1506 # if CONFIG_IS_ENABLED(OF_PRIOR_STAGE) 1510 # if CONFIG_IS_ENABLED(OF_PRIOR_STAGE)
1507 gd->fdt_blob = (void *)prior_stage_fdt_address; 1511 gd->fdt_blob = (void *)prior_stage_fdt_address;
1508 # else 1512 # else
1509 gd->fdt_blob = map_sysmem 1513 gd->fdt_blob = map_sysmem
1510 (env_get_ulong("fdtcontroladdr", 16, 1514 (env_get_ulong("fdtcontroladdr", 16,
1511 (unsigned long)map_to_sysmem(gd->fdt_blob)), 0); 1515 (unsigned long)map_to_sysmem(gd->fdt_blob)), 0);
1512 # endif 1516 # endif
1513 # endif 1517 # endif
1514 1518
1515 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT) 1519 # if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
1516 /* 1520 /*
1517 * Try and uncompress the blob. 1521 * Try and uncompress the blob.
1518 * Unfortunately there is no way to know how big the input blob really 1522 * Unfortunately there is no way to know how big the input blob really
1519 * is. So let us set the maximum input size arbitrarily high. 16MB 1523 * is. So let us set the maximum input size arbitrarily high. 16MB
1520 * ought to be more than enough for packed DTBs. 1524 * ought to be more than enough for packed DTBs.
1521 */ 1525 */
1522 if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0) 1526 if (uncompress_blob(gd->fdt_blob, 0x1000000, &fdt_blob) == 0)
1523 gd->fdt_blob = fdt_blob; 1527 gd->fdt_blob = fdt_blob;
1524 1528
1525 /* 1529 /*
1526 * Check if blob is a FIT images containings DTBs. 1530 * Check if blob is a FIT images containings DTBs.
1527 * If so, pick the most relevant 1531 * If so, pick the most relevant
1528 */ 1532 */
1529 fdt_blob = locate_dtb_in_fit(gd->fdt_blob); 1533 fdt_blob = locate_dtb_in_fit(gd->fdt_blob);
1530 if (fdt_blob) { 1534 if (fdt_blob) {
1531 gd->multi_dtb_fit = gd->fdt_blob; 1535 gd->multi_dtb_fit = gd->fdt_blob;
1532 gd->fdt_blob = fdt_blob; 1536 gd->fdt_blob = fdt_blob;
1533 } 1537 }
1534 1538
1535 # endif 1539 # endif
1536 #endif 1540 #endif
1537 1541
1538 return fdtdec_prepare_fdt(); 1542 return fdtdec_prepare_fdt();
1539 } 1543 }
1540 1544
1541 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT) 1545 #if CONFIG_IS_ENABLED(MULTI_DTB_FIT)
1542 int fdtdec_resetup(int *rescan) 1546 int fdtdec_resetup(int *rescan)
1543 { 1547 {
1544 void *fdt_blob; 1548 void *fdt_blob;
1545 1549
1546 /* 1550 /*
1547 * If the current DTB is part of a compressed FIT image, 1551 * If the current DTB is part of a compressed FIT image,
1548 * try to locate the best match from the uncompressed 1552 * try to locate the best match from the uncompressed
1549 * FIT image stillpresent there. Save the time and space 1553 * FIT image stillpresent there. Save the time and space
1550 * required to uncompress it again. 1554 * required to uncompress it again.
1551 */ 1555 */
1552 if (gd->multi_dtb_fit) { 1556 if (gd->multi_dtb_fit) {
1553 fdt_blob = locate_dtb_in_fit(gd->multi_dtb_fit); 1557 fdt_blob = locate_dtb_in_fit(gd->multi_dtb_fit);
1554 1558
1555 if (fdt_blob == gd->fdt_blob) { 1559 if (fdt_blob == gd->fdt_blob) {
1556 /* 1560 /*
1557 * The best match did not change. no need to tear down 1561 * The best match did not change. no need to tear down
1558 * the DM and rescan the fdt. 1562 * the DM and rescan the fdt.
1559 */ 1563 */
1560 *rescan = 0; 1564 *rescan = 0;
1561 return 0; 1565 return 0;
1562 } 1566 }
1563 1567
1564 *rescan = 1; 1568 *rescan = 1;
1565 gd->fdt_blob = fdt_blob; 1569 gd->fdt_blob = fdt_blob;
1566 return fdtdec_prepare_fdt(); 1570 return fdtdec_prepare_fdt();
1567 } 1571 }
1568 1572
1569 /* 1573 /*
1570 * If multi_dtb_fit is NULL, it means that blob appended to u-boot is 1574 * If multi_dtb_fit is NULL, it means that blob appended to u-boot is
1571 * not a FIT image containings DTB, but a single DTB. There is no need 1575 * not a FIT image containings DTB, but a single DTB. There is no need
1572 * to teard down DM and rescan the DT in this case. 1576 * to teard down DM and rescan the DT in this case.
1573 */ 1577 */
1574 *rescan = 0; 1578 *rescan = 0;
1575 return 0; 1579 return 0;
1576 } 1580 }
1577 #endif 1581 #endif
1578 1582
1579 #ifdef CONFIG_NR_DRAM_BANKS 1583 #ifdef CONFIG_NR_DRAM_BANKS
1580 int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id, 1584 int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id,
1581 phys_addr_t *basep, phys_size_t *sizep, bd_t *bd) 1585 phys_addr_t *basep, phys_size_t *sizep, bd_t *bd)
1582 { 1586 {
1583 int addr_cells, size_cells; 1587 int addr_cells, size_cells;
1584 const u32 *cell, *end; 1588 const u32 *cell, *end;
1585 u64 total_size, size, addr; 1589 u64 total_size, size, addr;
1586 int node, child; 1590 int node, child;
1587 bool auto_size; 1591 bool auto_size;
1588 int bank; 1592 int bank;
1589 int len; 1593 int len;
1590 1594
1591 debug("%s: board_id=%d\n", __func__, board_id); 1595 debug("%s: board_id=%d\n", __func__, board_id);
1592 if (!area) 1596 if (!area)
1593 area = "/memory"; 1597 area = "/memory";
1594 node = fdt_path_offset(blob, area); 1598 node = fdt_path_offset(blob, area);
1595 if (node < 0) { 1599 if (node < 0) {
1596 debug("No %s node found\n", area); 1600 debug("No %s node found\n", area);
1597 return -ENOENT; 1601 return -ENOENT;
1598 } 1602 }
1599 1603
1600 cell = fdt_getprop(blob, node, "reg", &len); 1604 cell = fdt_getprop(blob, node, "reg", &len);
1601 if (!cell) { 1605 if (!cell) {
1602 debug("No reg property found\n"); 1606 debug("No reg property found\n");
1603 return -ENOENT; 1607 return -ENOENT;
1604 } 1608 }
1605 1609
1606 addr_cells = fdt_address_cells(blob, node); 1610 addr_cells = fdt_address_cells(blob, node);
1607 size_cells = fdt_size_cells(blob, node); 1611 size_cells = fdt_size_cells(blob, node);
1608 1612
1609 /* Check the board id and mask */ 1613 /* Check the board id and mask */
1610 for (child = fdt_first_subnode(blob, node); 1614 for (child = fdt_first_subnode(blob, node);
1611 child >= 0; 1615 child >= 0;
1612 child = fdt_next_subnode(blob, child)) { 1616 child = fdt_next_subnode(blob, child)) {
1613 int match_mask, match_value; 1617 int match_mask, match_value;
1614 1618
1615 match_mask = fdtdec_get_int(blob, child, "match-mask", -1); 1619 match_mask = fdtdec_get_int(blob, child, "match-mask", -1);
1616 match_value = fdtdec_get_int(blob, child, "match-value", -1); 1620 match_value = fdtdec_get_int(blob, child, "match-value", -1);
1617 1621
1618 if (match_value >= 0 && 1622 if (match_value >= 0 &&
1619 ((board_id & match_mask) == match_value)) { 1623 ((board_id & match_mask) == match_value)) {
1620 /* Found matching mask */ 1624 /* Found matching mask */
1621 debug("Found matching mask %d\n", match_mask); 1625 debug("Found matching mask %d\n", match_mask);
1622 node = child; 1626 node = child;
1623 cell = fdt_getprop(blob, node, "reg", &len); 1627 cell = fdt_getprop(blob, node, "reg", &len);
1624 if (!cell) { 1628 if (!cell) {
1625 debug("No memory-banks property found\n"); 1629 debug("No memory-banks property found\n");
1626 return -EINVAL; 1630 return -EINVAL;
1627 } 1631 }
1628 break; 1632 break;
1629 } 1633 }
1630 } 1634 }
1631 /* Note: if no matching subnode was found we use the parent node */ 1635 /* Note: if no matching subnode was found we use the parent node */
1632 1636
1633 if (bd) { 1637 if (bd) {
1634 memset(bd->bi_dram, '\0', sizeof(bd->bi_dram[0]) * 1638 memset(bd->bi_dram, '\0', sizeof(bd->bi_dram[0]) *
1635 CONFIG_NR_DRAM_BANKS); 1639 CONFIG_NR_DRAM_BANKS);
1636 } 1640 }
1637 1641
1638 auto_size = fdtdec_get_bool(blob, node, "auto-size"); 1642 auto_size = fdtdec_get_bool(blob, node, "auto-size");
1639 1643
1640 total_size = 0; 1644 total_size = 0;
1641 end = cell + len / 4 - addr_cells - size_cells; 1645 end = cell + len / 4 - addr_cells - size_cells;
1642 debug("cell at %p, end %p\n", cell, end); 1646 debug("cell at %p, end %p\n", cell, end);
1643 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { 1647 for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) {
1644 if (cell > end) 1648 if (cell > end)
1645 break; 1649 break;
1646 addr = 0; 1650 addr = 0;
1647 if (addr_cells == 2) 1651 if (addr_cells == 2)
1648 addr += (u64)fdt32_to_cpu(*cell++) << 32UL; 1652 addr += (u64)fdt32_to_cpu(*cell++) << 32UL;
1649 addr += fdt32_to_cpu(*cell++); 1653 addr += fdt32_to_cpu(*cell++);
1650 if (bd) 1654 if (bd)
1651 bd->bi_dram[bank].start = addr; 1655 bd->bi_dram[bank].start = addr;
1652 if (basep && !bank) 1656 if (basep && !bank)
1653 *basep = (phys_addr_t)addr; 1657 *basep = (phys_addr_t)addr;
1654 1658
1655 size = 0; 1659 size = 0;
1656 if (size_cells == 2) 1660 if (size_cells == 2)
1657 size += (u64)fdt32_to_cpu(*cell++) << 32UL; 1661 size += (u64)fdt32_to_cpu(*cell++) << 32UL;
1658 size += fdt32_to_cpu(*cell++); 1662 size += fdt32_to_cpu(*cell++);
1659 1663
1660 if (auto_size) { 1664 if (auto_size) {
1661 u64 new_size; 1665 u64 new_size;
1662 1666
1663 debug("Auto-sizing %llx, size %llx: ", addr, size); 1667 debug("Auto-sizing %llx, size %llx: ", addr, size);
1664 new_size = get_ram_size((long *)(uintptr_t)addr, size); 1668 new_size = get_ram_size((long *)(uintptr_t)addr, size);
1665 if (new_size == size) { 1669 if (new_size == size) {
1666 debug("OK\n"); 1670 debug("OK\n");
1667 } else { 1671 } else {
1668 debug("sized to %llx\n", new_size); 1672 debug("sized to %llx\n", new_size);
1669 size = new_size; 1673 size = new_size;
1670 } 1674 }
1671 } 1675 }
1672 1676
1673 if (bd) 1677 if (bd)
1674 bd->bi_dram[bank].size = size; 1678 bd->bi_dram[bank].size = size;
1675 total_size += size; 1679 total_size += size;
1676 } 1680 }
1677 1681
1678 debug("Memory size %llu\n", total_size); 1682 debug("Memory size %llu\n", total_size);
1679 if (sizep) 1683 if (sizep)
1680 *sizep = (phys_size_t)total_size; 1684 *sizep = (phys_size_t)total_size;
1681 1685
1682 return 0; 1686 return 0;
1683 } 1687 }
1684 #endif /* CONFIG_NR_DRAM_BANKS */ 1688 #endif /* CONFIG_NR_DRAM_BANKS */
1685 1689
1686 #endif /* !USE_HOSTCC */ 1690 #endif /* !USE_HOSTCC */
1687 1691
1 // SPDX-License-Identifier: GPL-2.0+ 1 // SPDX-License-Identifier: GPL-2.0+
2 /* 2 /*
3 * Some very basic tests for fdtdec, accessed through test_fdtdec command. 3 * Some very basic tests for fdtdec, accessed through test_fdtdec command.
4 * They are easiest to use with sandbox. 4 * They are easiest to use with sandbox.
5 * 5 *
6 * Copyright (c) 2011 The Chromium OS Authors. 6 * Copyright (c) 2011 The Chromium OS Authors.
7 */ 7 */
8 8
9 #include <common.h> 9 #include <common.h>
10 #include <fdtdec.h> 10 #include <fdtdec.h>
11 #include <linux/libfdt.h> 11 #include <linux/libfdt.h>
12 #include <malloc.h> 12 #include <malloc.h>
13 #include <os.h> 13 #include <os.h>
14 14
15 /* The size of our test fdt blob */ 15 /* The size of our test fdt blob */
16 #define FDT_SIZE (16 * 1024) 16 #define FDT_SIZE (16 * 1024)
17 17
18 #define CHECK(op) ({ \ 18 #define CHECK(op) ({ \
19 int err = op; \ 19 int err = op; \
20 if (err < 0) { \ 20 if (err < 0) { \
21 printf("%s: %s: %s\n", __func__, #op, \ 21 printf("%s: %s: %s\n", __func__, #op, \
22 fdt_strerror(err)); \ 22 fdt_strerror(err)); \
23 return err; \ 23 return err; \
24 } \ 24 } \
25 \ 25 \
26 err; \ 26 err; \
27 }) 27 })
28 28
29 #define CHECKVAL(op, expected) ({ \ 29 #define CHECKVAL(op, expected) ({ \
30 int err = op; \ 30 int err = op; \
31 if (err != expected) { \ 31 if (err != expected) { \
32 printf("%s: %s: expected %d, but returned %d\n",\ 32 printf("%s: %s: expected %d, but returned %d\n",\
33 __func__, #op, expected, err); \ 33 __func__, #op, expected, err); \
34 return err; \ 34 return err; \
35 } \ 35 } \
36 \ 36 \
37 err; \ 37 err; \
38 }) 38 })
39 39
40 #define CHECKOK(op) CHECKVAL(op, 0) 40 #define CHECKOK(op) CHECKVAL(op, 0)
41 41
42 /* maximum number of nodes / aliases to generate */ 42 /* maximum number of nodes / aliases to generate */
43 #define MAX_NODES 20 43 #define MAX_NODES 20
44 44
45 /* 45 /*
46 * Make a test fdt 46 * Make a test fdt
47 * 47 *
48 * @param fdt Device tree pointer 48 * @param fdt Device tree pointer
49 * @param size Size of device tree blob 49 * @param size Size of device tree blob
50 * @param aliases Specifies alias assignments. Format is a list of items 50 * @param aliases Specifies alias assignments. Format is a list of items
51 * separated by space. Items are #a where 51 * separated by space. Items are #a where
52 * # is the alias number 52 * # is the alias number
53 * a is the node to point to 53 * a is the node to point to
54 * @param nodes Specifies nodes to generate (a=0, b=1), upper case 54 * @param nodes Specifies nodes to generate (a=0, b=1), upper case
55 * means to create a disabled node 55 * means to create a disabled node
56 */ 56 */
57 static int make_fdt(void *fdt, int size, const char *aliases, 57 static int make_fdt(void *fdt, int size, const char *aliases,
58 const char *nodes) 58 const char *nodes)
59 { 59 {
60 char name[20], value[20]; 60 char name[20], value[20];
61 const char *s; 61 const char *s;
62 #if defined(DEBUG) && defined(CONFIG_SANDBOX) 62 #if defined(DEBUG) && defined(CONFIG_SANDBOX)
63 int fd; 63 int fd;
64 #endif 64 #endif
65 65
66 CHECK(fdt_create(fdt, size)); 66 CHECK(fdt_create(fdt, size));
67 CHECK(fdt_finish_reservemap(fdt)); 67 CHECK(fdt_finish_reservemap(fdt));
68 CHECK(fdt_begin_node(fdt, "")); 68 CHECK(fdt_begin_node(fdt, ""));
69 69
70 CHECK(fdt_begin_node(fdt, "aliases")); 70 CHECK(fdt_begin_node(fdt, "aliases"));
71 for (s = aliases; *s;) { 71 for (s = aliases; *s;) {
72 sprintf(name, "i2c%c", *s); 72 sprintf(name, "i2c%c", *s);
73 sprintf(value, "/i2c%d@0", s[1] - 'a'); 73 sprintf(value, "/i2c%d@0", s[1] - 'a');
74 CHECK(fdt_property_string(fdt, name, value)); 74 CHECK(fdt_property_string(fdt, name, value));
75 s += 2 + (s[2] != '\0'); 75 s += 2 + (s[2] != '\0');
76 } 76 }
77 CHECK(fdt_end_node(fdt)); 77 CHECK(fdt_end_node(fdt));
78 78
79 for (s = nodes; *s; s++) { 79 for (s = nodes; *s; s++) {
80 sprintf(value, "i2c%d@0", (*s & 0xdf) - 'A'); 80 sprintf(value, "i2c%d@0", (*s & 0xdf) - 'A');
81 CHECK(fdt_begin_node(fdt, value)); 81 CHECK(fdt_begin_node(fdt, value));
82 CHECK(fdt_property_string(fdt, "compatible", 82 CHECK(fdt_property_string(fdt, "compatible",
83 fdtdec_get_compatible(COMPAT_UNKNOWN))); 83 fdtdec_get_compatible(COMPAT_UNKNOWN)));
84 if (*s <= 'Z') 84 if (*s <= 'Z')
85 CHECK(fdt_property_string(fdt, "status", "disabled")); 85 CHECK(fdt_property_string(fdt, "status", "disabled"));
86 CHECK(fdt_end_node(fdt)); 86 CHECK(fdt_end_node(fdt));
87 } 87 }
88 88
89 CHECK(fdt_end_node(fdt)); 89 CHECK(fdt_end_node(fdt));
90 CHECK(fdt_finish(fdt)); 90 CHECK(fdt_finish(fdt));
91 CHECK(fdt_pack(fdt)); 91 CHECK(fdt_pack(fdt));
92 #if defined(DEBUG) && defined(CONFIG_SANDBOX) 92 #if defined(DEBUG) && defined(CONFIG_SANDBOX)
93 fd = os_open("/tmp/fdtdec-text.dtb", OS_O_CREAT | OS_O_WRONLY); 93 fd = os_open("/tmp/fdtdec-text.dtb", OS_O_CREAT | OS_O_WRONLY);
94 if (fd == -1) { 94 if (fd == -1) {
95 printf("Could not open .dtb file to write\n"); 95 printf("Could not open .dtb file to write\n");
96 return -1; 96 return -1;
97 } 97 }
98 os_write(fd, fdt, size); 98 os_write(fd, fdt, size);
99 os_close(fd); 99 os_close(fd);
100 #endif 100 #endif
101 return 0; 101 return 0;
102 } 102 }
103 103
104 static int run_test(const char *aliases, const char *nodes, const char *expect) 104 static int run_test(const char *aliases, const char *nodes, const char *expect)
105 { 105 {
106 int list[MAX_NODES]; 106 int list[MAX_NODES];
107 const char *s; 107 const char *s;
108 void *blob; 108 void *blob;
109 int i; 109 int i;
110 110
111 blob = malloc(FDT_SIZE); 111 blob = malloc(FDT_SIZE);
112 if (!blob) { 112 if (!blob) {
113 printf("%s: out of memory\n", __func__); 113 printf("%s: out of memory\n", __func__);
114 return 1; 114 return 1;
115 } 115 }
116 116
117 printf("aliases=%s, nodes=%s, expect=%s: ", aliases, nodes, expect); 117 printf("aliases=%s, nodes=%s, expect=%s: ", aliases, nodes, expect);
118 CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0); 118 CHECKVAL(make_fdt(blob, FDT_SIZE, aliases, nodes), 0);
119 CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c", 119 CHECKVAL(fdtdec_find_aliases_for_id(blob, "i2c",
120 COMPAT_UNKNOWN, 120 COMPAT_UNKNOWN,
121 list, ARRAY_SIZE(list)), (int)strlen(expect)); 121 list, ARRAY_SIZE(list)), (int)strlen(expect));
122 122
123 /* Check we got the right ones */ 123 /* Check we got the right ones */
124 for (i = 0, s = expect; *s; s++, i++) { 124 for (i = 0, s = expect; *s; s++, i++) {
125 int want = *s; 125 int want = *s;
126 const char *name; 126 const char *name;
127 int got = ' '; 127 int got = ' ';
128 128
129 name = list[i] ? fdt_get_name(blob, list[i], NULL) : NULL; 129 name = list[i] ? fdt_get_name(blob, list[i], NULL) : NULL;
130 if (name) 130 if (name)
131 got = name[3] + 'a' - '0'; 131 got = name[3] + 'a' - '0';
132 132
133 if (got != want) { 133 if (got != want) {
134 printf("Position %d: Expected '%c', got '%c' ('%s')\n", 134 printf("Position %d: Expected '%c', got '%c' ('%s')\n",
135 i, want, got, name); 135 i, want, got, name);
136 return 1; 136 return 1;
137 } 137 }
138 } 138 }
139 139
140 printf("pass\n"); 140 printf("pass\n");
141 return 0; 141 return 0;
142 } 142 }
143 143
144 static int make_fdt_carveout_device(void *fdt, uint32_t na, uint32_t ns) 144 static int make_fdt_carveout_device(void *fdt, uint32_t na, uint32_t ns)
145 { 145 {
146 const char *basename = "/display"; 146 const char *basename = "/display";
147 struct fdt_memory carveout = { 147 struct fdt_memory carveout = {
148 #ifdef CONFIG_PHYS_64BIT 148 #ifdef CONFIG_PHYS_64BIT
149 .start = 0x180000000, 149 .start = 0x180000000,
150 .end = 0x18fffffff, 150 .end = 0x18fffffff,
151 #else 151 #else
152 .start = 0x80000000, 152 .start = 0x80000000,
153 .end = 0x8fffffff, 153 .end = 0x8fffffff,
154 #endif 154 #endif
155 }; 155 };
156 fdt32_t cells[4], *ptr = cells; 156 fdt32_t cells[4], *ptr = cells;
157 uint32_t upper, lower; 157 uint32_t upper, lower;
158 fdt_size_t size;
158 char name[32]; 159 char name[32];
159 int offset; 160 int offset;
160 161
161 /* store one or two address cells */ 162 /* store one or two address cells */
162 lower = fdt_addr_unpack(carveout.start, &upper); 163 upper = upper_32_bits(carveout.start);
164 lower = lower_32_bits(carveout.start);
163 165
164 if (na > 1 && upper > 0) 166 if (na > 1 && upper > 0)
165 snprintf(name, sizeof(name), "%s@%x,%x", basename, upper, 167 snprintf(name, sizeof(name), "%s@%x,%x", basename, upper,
166 lower); 168 lower);
167 else 169 else
168 snprintf(name, sizeof(name), "%s@%x", basename, lower); 170 snprintf(name, sizeof(name), "%s@%x", basename, lower);
169 171
170 if (na > 1) 172 if (na > 1)
171 *ptr++ = cpu_to_fdt32(upper); 173 *ptr++ = cpu_to_fdt32(upper);
172 174
173 *ptr++ = cpu_to_fdt32(lower); 175 *ptr++ = cpu_to_fdt32(lower);
174 176
175 /* store one or two size cells */ 177 /* store one or two size cells */
176 lower = fdt_size_unpack(carveout.end - carveout.start + 1, &upper); 178 size = carveout.end - carveout.start + 1;
179 upper = upper_32_bits(size);
180 lower = lower_32_bits(size);
177 181
178 if (ns > 1) 182 if (ns > 1)
179 *ptr++ = cpu_to_fdt32(upper); 183 *ptr++ = cpu_to_fdt32(upper);
180 184
181 *ptr++ = cpu_to_fdt32(lower); 185 *ptr++ = cpu_to_fdt32(lower);
182 186
183 offset = CHECK(fdt_add_subnode(fdt, 0, name + 1)); 187 offset = CHECK(fdt_add_subnode(fdt, 0, name + 1));
184 CHECK(fdt_setprop(fdt, offset, "reg", cells, (na + ns) * sizeof(*cells))); 188 CHECK(fdt_setprop(fdt, offset, "reg", cells, (na + ns) * sizeof(*cells)));
185 189
186 return fdtdec_set_carveout(fdt, name, "memory-region", 0, 190 return fdtdec_set_carveout(fdt, name, "memory-region", 0,
187 "framebuffer", &carveout); 191 "framebuffer", &carveout);
188 } 192 }
189 193
190 static int check_fdt_carveout(void *fdt, uint32_t address_cells, 194 static int check_fdt_carveout(void *fdt, uint32_t address_cells,
191 uint32_t size_cells) 195 uint32_t size_cells)
192 { 196 {
193 #ifdef CONFIG_PHYS_64BIT 197 #ifdef CONFIG_PHYS_64BIT
194 const char *name = "/display@1,80000000"; 198 const char *name = "/display@1,80000000";
195 const struct fdt_memory expected = { 199 const struct fdt_memory expected = {
196 .start = 0x180000000, 200 .start = 0x180000000,
197 .end = 0x18fffffff, 201 .end = 0x18fffffff,
198 }; 202 };
199 #else 203 #else
200 const char *name = "/display@80000000"; 204 const char *name = "/display@80000000";
201 const struct fdt_memory expected = { 205 const struct fdt_memory expected = {
202 .start = 0x80000000, 206 .start = 0x80000000,
203 .end = 0x8fffffff, 207 .end = 0x8fffffff,
204 }; 208 };
205 #endif 209 #endif
206 struct fdt_memory carveout; 210 struct fdt_memory carveout;
207 211
208 printf("carveout: %pap-%pap na=%u ns=%u: ", &expected.start, 212 printf("carveout: %pap-%pap na=%u ns=%u: ", &expected.start,
209 &expected.end, address_cells, size_cells); 213 &expected.end, address_cells, size_cells);
210 214
211 CHECK(fdtdec_get_carveout(fdt, name, "memory-region", 0, &carveout)); 215 CHECK(fdtdec_get_carveout(fdt, name, "memory-region", 0, &carveout));
212 216
213 if ((carveout.start != expected.start) || 217 if ((carveout.start != expected.start) ||
214 (carveout.end != expected.end)) { 218 (carveout.end != expected.end)) {
215 printf("carveout: %pap-%pap, expected %pap-%pap\n", 219 printf("carveout: %pap-%pap, expected %pap-%pap\n",
216 &carveout.start, &carveout.end, 220 &carveout.start, &carveout.end,
217 &expected.start, &expected.end); 221 &expected.start, &expected.end);
218 return 1; 222 return 1;
219 } 223 }
220 224
221 printf("pass\n"); 225 printf("pass\n");
222 return 0; 226 return 0;
223 } 227 }
224 228
225 static int make_fdt_carveout(void *fdt, int size, uint32_t address_cells, 229 static int make_fdt_carveout(void *fdt, int size, uint32_t address_cells,
226 uint32_t size_cells) 230 uint32_t size_cells)
227 { 231 {
228 fdt32_t na = cpu_to_fdt32(address_cells); 232 fdt32_t na = cpu_to_fdt32(address_cells);
229 fdt32_t ns = cpu_to_fdt32(size_cells); 233 fdt32_t ns = cpu_to_fdt32(size_cells);
230 #if defined(DEBUG) && defined(CONFIG_SANDBOX) 234 #if defined(DEBUG) && defined(CONFIG_SANDBOX)
231 char filename[512]; 235 char filename[512];
232 int fd; 236 int fd;
233 #endif 237 #endif
234 int err; 238 int err;
235 239
236 CHECK(fdt_create(fdt, size)); 240 CHECK(fdt_create(fdt, size));
237 CHECK(fdt_finish_reservemap(fdt)); 241 CHECK(fdt_finish_reservemap(fdt));
238 CHECK(fdt_begin_node(fdt, "")); 242 CHECK(fdt_begin_node(fdt, ""));
239 CHECK(fdt_property(fdt, "#address-cells", &na, sizeof(na))); 243 CHECK(fdt_property(fdt, "#address-cells", &na, sizeof(na)));
240 CHECK(fdt_property(fdt, "#size-cells", &ns, sizeof(ns))); 244 CHECK(fdt_property(fdt, "#size-cells", &ns, sizeof(ns)));
241 CHECK(fdt_end_node(fdt)); 245 CHECK(fdt_end_node(fdt));
242 CHECK(fdt_finish(fdt)); 246 CHECK(fdt_finish(fdt));
243 CHECK(fdt_pack(fdt)); 247 CHECK(fdt_pack(fdt));
244 248
245 CHECK(fdt_open_into(fdt, fdt, FDT_SIZE)); 249 CHECK(fdt_open_into(fdt, fdt, FDT_SIZE));
246 250
247 err = make_fdt_carveout_device(fdt, address_cells, size_cells); 251 err = make_fdt_carveout_device(fdt, address_cells, size_cells);
248 252
249 #if defined(DEBUG) && defined(CONFIG_SANDBOX) 253 #if defined(DEBUG) && defined(CONFIG_SANDBOX)
250 snprintf(filename, sizeof(filename), "/tmp/fdtdec-carveout-%u-%u.dtb", 254 snprintf(filename, sizeof(filename), "/tmp/fdtdec-carveout-%u-%u.dtb",
251 address_cells, size_cells); 255 address_cells, size_cells);
252 256
253 fd = os_open(filename, OS_O_CREAT | OS_O_WRONLY); 257 fd = os_open(filename, OS_O_CREAT | OS_O_WRONLY);
254 if (fd < 0) { 258 if (fd < 0) {
255 printf("could not open .dtb file to write\n"); 259 printf("could not open .dtb file to write\n");
256 goto out; 260 goto out;
257 } 261 }
258 262
259 os_write(fd, fdt, size); 263 os_write(fd, fdt, size);
260 os_close(fd); 264 os_close(fd);
261 265
262 out: 266 out:
263 #endif 267 #endif
264 return err; 268 return err;
265 } 269 }
266 270
267 static int check_carveout(void) 271 static int check_carveout(void)
268 { 272 {
269 void *fdt; 273 void *fdt;
270 274
271 fdt = malloc(FDT_SIZE); 275 fdt = malloc(FDT_SIZE);
272 if (!fdt) { 276 if (!fdt) {
273 printf("%s: out of memory\n", __func__); 277 printf("%s: out of memory\n", __func__);
274 return 1; 278 return 1;
275 } 279 }
276 280
277 #ifndef CONFIG_PHYS_64BIT 281 #ifndef CONFIG_PHYS_64BIT
278 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), 0); 282 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), 0);
279 CHECKOK(check_fdt_carveout(fdt, 1, 1)); 283 CHECKOK(check_fdt_carveout(fdt, 1, 1));
280 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), 0); 284 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), 0);
281 CHECKOK(check_fdt_carveout(fdt, 1, 2)); 285 CHECKOK(check_fdt_carveout(fdt, 1, 2));
282 #else 286 #else
283 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), -FDT_ERR_BADVALUE); 287 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 1), -FDT_ERR_BADVALUE);
284 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), -FDT_ERR_BADVALUE); 288 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 1, 2), -FDT_ERR_BADVALUE);
285 #endif 289 #endif
286 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 1), 0); 290 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 1), 0);
287 CHECKOK(check_fdt_carveout(fdt, 2, 1)); 291 CHECKOK(check_fdt_carveout(fdt, 2, 1));
288 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 2), 0); 292 CHECKVAL(make_fdt_carveout(fdt, FDT_SIZE, 2, 2), 0);
289 CHECKOK(check_fdt_carveout(fdt, 2, 2)); 293 CHECKOK(check_fdt_carveout(fdt, 2, 2));
290 294
291 return 0; 295 return 0;
292 } 296 }
293 297
294 static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc, 298 static int do_test_fdtdec(cmd_tbl_t *cmdtp, int flag, int argc,
295 char * const argv[]) 299 char * const argv[])
296 { 300 {
297 /* basic tests */ 301 /* basic tests */
298 CHECKOK(run_test("", "", "")); 302 CHECKOK(run_test("", "", ""));
299 CHECKOK(run_test("1e 3d", "", "")); 303 CHECKOK(run_test("1e 3d", "", ""));
300 304
301 /* 305 /*
302 * 'a' represents 0, 'b' represents 1, etc. 306 * 'a' represents 0, 'b' represents 1, etc.
303 * The first character is the alias number, the second is the node 307 * The first character is the alias number, the second is the node
304 * number. So the params mean: 308 * number. So the params mean:
305 * 0a 1b : point alias 0 to node 0 (a), alias 1 to node 1(b) 309 * 0a 1b : point alias 0 to node 0 (a), alias 1 to node 1(b)
306 * ab : to create nodes 0 and 1 (a and b) 310 * ab : to create nodes 0 and 1 (a and b)
307 * ab : we expect the function to return two nodes, in 311 * ab : we expect the function to return two nodes, in
308 * the order 0, 1 312 * the order 0, 1
309 */ 313 */
310 CHECKOK(run_test("0a 1b", "ab", "ab")); 314 CHECKOK(run_test("0a 1b", "ab", "ab"));
311 315
312 CHECKOK(run_test("0a 1c", "ab", "ab")); 316 CHECKOK(run_test("0a 1c", "ab", "ab"));
313 CHECKOK(run_test("1c", "ab", "ab")); 317 CHECKOK(run_test("1c", "ab", "ab"));
314 CHECKOK(run_test("1b", "ab", "ab")); 318 CHECKOK(run_test("1b", "ab", "ab"));
315 CHECKOK(run_test("0b", "ab", "ba")); 319 CHECKOK(run_test("0b", "ab", "ba"));
316 CHECKOK(run_test("0b 2d", "dbc", "bcd")); 320 CHECKOK(run_test("0b 2d", "dbc", "bcd"));
317 CHECKOK(run_test("0d 3a 1c 2b", "dbac", "dcba")); 321 CHECKOK(run_test("0d 3a 1c 2b", "dbac", "dcba"));
318 322
319 /* things with holes */ 323 /* things with holes */
320 CHECKOK(run_test("1b 3d", "dbc", "cb d")); 324 CHECKOK(run_test("1b 3d", "dbc", "cb d"));
321 CHECKOK(run_test("1e 3d", "dbc", "bc d")); 325 CHECKOK(run_test("1e 3d", "dbc", "bc d"));
322 326
323 /* no aliases */ 327 /* no aliases */
324 CHECKOK(run_test("", "dbac", "dbac")); 328 CHECKOK(run_test("", "dbac", "dbac"));
325 329
326 /* disabled nodes */ 330 /* disabled nodes */
327 CHECKOK(run_test("0d 3a 1c 2b", "dBac", "dc a")); 331 CHECKOK(run_test("0d 3a 1c 2b", "dBac", "dc a"));
328 CHECKOK(run_test("0b 2d", "DBc", "c")); 332 CHECKOK(run_test("0b 2d", "DBc", "c"));
329 CHECKOK(run_test("0b 4d 2c", "DBc", " c")); 333 CHECKOK(run_test("0b 4d 2c", "DBc", " c"));
330 334
331 /* conflicting aliases - first one gets it */ 335 /* conflicting aliases - first one gets it */
332 CHECKOK(run_test("2a 1a 0a", "a", " a")); 336 CHECKOK(run_test("2a 1a 0a", "a", " a"));
333 CHECKOK(run_test("0a 1a 2a", "a", "a")); 337 CHECKOK(run_test("0a 1a 2a", "a", "a"));
334 338
335 CHECKOK(check_carveout()); 339 CHECKOK(check_carveout());
336 340
337 printf("Test passed\n"); 341 printf("Test passed\n");
338 return 0; 342 return 0;
339 } 343 }
340 344
341 U_BOOT_CMD( 345 U_BOOT_CMD(
342 test_fdtdec, 3, 1, do_test_fdtdec, 346 test_fdtdec, 3, 1, do_test_fdtdec,
343 "test_fdtdec", 347 "test_fdtdec",
344 "Run tests for fdtdec library"); 348 "Run tests for fdtdec library");
345 349