blob: 2ec5ef1b5cf28ad89dce55c3a0669a2744619403 [file] [log] [blame]
Simon Glass90469da2024-08-07 16:47:27 -06001/* SPDX-License-Identifier: GPL-2.0+ */
2/*
3 * UPL handoff generation
4 *
5 * Copyright 2024 Google LLC
6 * Written by Simon Glass <sjg@chromium.org>
7 */
8
9#ifndef __UPL_WRITE_H
10#define __UPL_WRITE_H
11
12#ifndef USE_HOSTCC
13
14#include <alist.h>
15#include <image.h>
16#include <dm/ofnode_decl.h>
17
18struct unit_test_state;
19
20#define UPLP_ADDRESS_CELLS "#address-cells"
21#define UPLP_SIZE_CELLS "#size-cells"
22
23#define UPLN_OPTIONS "options"
24#define UPLN_UPL_PARAMS "upl-params"
25#define UPLP_SMBIOS "smbios"
26#define UPLP_ACPI "acpi"
27#define UPLP_BOOTMODE "bootmode"
28#define UPLP_ADDR_WIDTH "addr-width"
29#define UPLP_ACPI_NVS_SIZE "acpi-nvs-size"
30
31#define UPLPATH_UPL_IMAGE "/options/upl-image"
32#define UPLN_UPL_IMAGE "upl-image"
33#define UPLN_IMAGE "image"
34#define UPLP_FIT "fit"
35#define UPLP_CONF_OFFSET "conf-offset"
36#define UPLP_LOAD "load"
37#define UPLP_SIZE "size"
38#define UPLP_OFFSET "offset"
39#define UPLP_DESCRIPTION "description"
40
41#define UPLN_MEMORY "memory"
42#define UPLP_HOTPLUGGABLE "hotpluggable"
43
44#define UPLPATH_MEMORY_MAP "/memory-map"
45#define UPLN_MEMORY_MAP "memory-map"
46#define UPLP_USAGE "usage"
47
48#define UPLN_MEMORY_RESERVED "reserved-memory"
49#define UPLPATH_MEMORY_RESERVED "/reserved-memory"
50#define UPLP_NO_MAP "no-map"
51
52#define UPLN_SERIAL "serial"
53#define UPLP_REG "reg"
54#define UPLP_COMPATIBLE "compatible"
55#define UPLP_CLOCK_FREQUENCY "clock-frequency"
56#define UPLP_CURRENT_SPEED "current-speed"
57#define UPLP_REG_IO_SHIFT "reg-io-shift"
58#define UPLP_REG_OFFSET "reg-offset"
59#define UPLP_REG_IO_WIDTH "reg-io-width"
60#define UPLP_VIRTUAL_REG "virtual-reg"
61#define UPLP_ACCESS_TYPE "access-type"
62
63#define UPLN_GRAPHICS "framebuffer"
64#define UPLC_GRAPHICS "simple-framebuffer"
65#define UPLP_WIDTH "width"
66#define UPLP_HEIGHT "height"
67#define UPLP_STRIDE "stride"
68#define UPLP_GRAPHICS_FORMAT "format"
69
70/**
71 * enum upl_boot_mode - Encodes the boot mode
72 *
73 * Each is a bit number from the boot_mode mask
74 */
75enum upl_boot_mode {
76 UPLBM_FULL,
77 UPLBM_MINIMAL,
78 UPLBM_FAST,
79 UPLBM_DIAG,
80 UPLBM_DEFAULT,
81 UPLBM_S2,
82 UPLBM_S3,
83 UPLBM_S4,
84 UPLBM_S5,
85 UPLBM_FACTORY,
86 UPLBM_FLASH,
87 UPLBM_RECOVERY,
88
89 UPLBM_COUNT,
90};
91
92/**
93 * struct upl_image - UPL image informaiton
94 *
95 * @load: Address image was loaded to
96 * @size: Size of image in bytes
97 * @offset: Offset of the image in the FIT (0=none)
98 * @desc: Description of the iamge (taken from the FIT)
99 */
100struct upl_image {
101 ulong load;
102 ulong size;
103 uint offset;
104 const char *description;
105};
106
107/**
108 * struct memregion - Information about a region of memory
109 *
110 * @base: Base address
111 * @size: Size in bytes
112 */
113struct memregion {
114 ulong base;
115 ulong size;
116};
117
118/**
119 * struct upl_mem - Information about physical-memory layout
120 *
121 * TODO: Figure out initial-mapped-area
122 *
123 * @region: Memory region list (struct memregion)
124 * @hotpluggable: true if hotpluggable
125 */
126struct upl_mem {
127 struct alist region;
128 bool hotpluggable;
129};
130
131/**
132 * enum upl_usage - Encodes the usage
133 *
134 * Each is a bit number from the usage mask
135 */
136enum upl_usage {
137 UPLUS_ACPI_RECLAIM,
138 UPLUS_ACPI_NVS,
139 UPLUS_BOOT_CODE,
140 UPLUS_BOOT_DATA,
141 UPLUS_RUNTIME_CODE,
142 UPLUS_RUNTIME_DATA,
143 UPLUS_COUNT
144};
145
146/**
147 * struct upl_memmap - Information about logical-memory layout
148 *
149 * @name: Node name to use
150 * @region: Memory region list (struct memregion)
151 * @usage: Memory-usage mask (enum upl_usage)
152 */
153struct upl_memmap {
154 const char *name;
155 struct alist region;
156 uint usage;
157};
158
159/**
160 * struct upl_memres - Reserved memory
161 *
162 * @name: Node name to use
163 * @region: Reserved memory region list (struct memregion)
164 * @no_map: true to indicate that a virtual mapping must not be created
165 */
166struct upl_memres {
167 const char *name;
168 struct alist region;
169 bool no_map;
170};
171
172enum upl_serial_access_type {
173 UPLSAT_MMIO,
174 UPLSAT_IO,
175};
176
177/* serial defaults */
178enum {
179 UPLD_REG_IO_SHIFT = 0,
180 UPLD_REG_OFFSET = 0,
181 UPLD_REG_IO_WIDTH = 1,
182};
183
184/**
185 * enum upl_access_type - Access types
186 *
187 * @UPLAT_MMIO: Memory-mapped I/O
188 * @UPLAT_IO: Separate I/O
189 */
190enum upl_access_type {
191 UPLAT_MMIO,
192 UPLAT_IO,
193};
194
195/**
196 * struct upl_serial - Serial console
197 *
198 * @compatible: Compatible string (NULL if there is no serial console)
199 * @clock_frequency: Input clock frequency of UART
200 * @current_speed: Current baud rate of UART
201 * @reg: List of base address and size of registers (struct memregion)
202 * @reg_shift_log2: log2 of distance between each register
203 * @reg_offset: Offset of registers from the base address
204 * @reg_width: Register width in bytes
205 * @virtual_reg: Virtual register access (0 for none)
206 * @access_type: Register access type to use
207 */
208struct upl_serial {
209 const char *compatible;
210 uint clock_frequency;
211 uint current_speed;
212 struct alist reg;
213 uint reg_io_shift;
214 uint reg_offset;
215 uint reg_io_width;
216 ulong virtual_reg;
217 enum upl_serial_access_type access_type;
218};
219
220/**
221 * enum upl_graphics_format - Graphics formats
222 *
223 * @UPLGF_ARGB32: 32bpp format using 0xaarrggbb
224 * @UPLGF_ABGR32: 32bpp format using 0xaabbggrr
225 * @UPLGF_ARGB64: 64bpp format using 0xaaaabbbbggggrrrr
226 */
227enum upl_graphics_format {
228 UPLGF_ARGB32,
229 UPLGF_ABGR32,
230 UPLGF_ABGR64,
231};
232
233/**
234 * @reg: List of base address and size of registers (struct memregion)
235 * @width: Width of display in pixels
236 * @height: Height of display in pixels
237 * @stride: Number of bytes from one line to the next
238 * @format: Pixel format
239 */
240struct upl_graphics {
241 struct alist reg;
242 uint width;
243 uint height;
244 uint stride;
245 enum upl_graphics_format format;
246};
247
248/*
249 * Information about the UPL state
250 *
251 * @addr_cells: Number of address cells used in the handoff
252 * @size_cells: Number of size cells used in the handoff
253 * @bootmode: Boot-mode mask (enum upl_boot_mode)
254 * @fit: Address of FIT image that was loaded
255 * @conf_offset: Offset in FIT of the configuration that was selected
256 * @addr_width: Adress-bus width of machine, e.g. 46 for 46 bits
257 * @acpi_nvs_size: Size of the ACPI non-volatile-storage area in bytes
258 * @image: Information about each image (struct upl_image)
259 * @mem: Information about physical-memory regions (struct upl_mem)
260 * @nennap: Information about logical-memory regions (struct upl_memmap)
261 * @nennap: Information about reserved-memory regions (struct upl_memres)
262 */
263struct upl {
264 int addr_cells;
265 int size_cells;
266
267 ulong smbios;
268 ulong acpi;
269 uint bootmode;
270 ulong fit;
271 uint conf_offset;
272 uint addr_width;
273 uint acpi_nvs_size;
274
275 struct alist image;
276 struct alist mem;
277 struct alist memmap;
278 struct alist memres;
279 struct upl_serial serial;
280 struct upl_graphics graphics;
281};
282
283/**
284 * upl_write_handoff() - Write a Unversal Payload handoff structure
285 *
286 * upl: UPL state to write
287 * @root: root node to write it to
288 * @skip_existing: Avoid recreating any nodes which already exist in the
289 * devicetree. For example, if there is a serial node, just leave it alone,
290 * since don't need to create a new one
291 * Return: 0 on success, -ve on error
292 */
293int upl_write_handoff(const struct upl *upl, ofnode root, bool skip_existing);
294
295/**
296 * upl_create_handoff_tree() - Write a Unversal Payload handoff structure
297 *
298 * upl: UPL state to write
299 * @treep: Returns a new tree containing the handoff
300 * Return: 0 on success, -ve on error
301 */
302int upl_create_handoff_tree(const struct upl *upl, oftree *treep);
303
304/**
305 * upl_read_handoff() - Read a Unversal Payload handoff structure
306 *
307 * upl: UPL state to read into
308 * @tree: Devicetree containing the data to read
309 * Return: 0 on success, -ve on error
310 */
311int upl_read_handoff(struct upl *upl, oftree tree);
Simon Glass637be2e2024-08-07 16:47:29 -0600312
313/**
314 * upl_get_test_data() - Fill a UPL with some test data
315 *
316 * @uts: Test state (can be uninited)
317 * @upl: Returns test data
318 * Return: 0 on success, 1 on error
319 */
320int upl_get_test_data(struct unit_test_state *uts, struct upl *upl);
Simon Glass90469da2024-08-07 16:47:27 -0600321#endif /* USE_HOSTCC */
322
323#if CONFIG_IS_ENABLED(UPL) && defined(CONFIG_SPL_BUILD)
324
325/**
326 * upl_set_fit_info() - Set up basic info about the FIT
327 *
328 * @fit: Address of FIT
329 * @conf_offset: Configuration node being used
330 * @entry_addr: Entry address for next phase
331 */
332void upl_set_fit_info(ulong fit, int conf_offset, ulong entry_addr);
333
334/**
335 * upl_set_fit_addr() - Set up the address of the FIT
336 *
337 * @fit: Address of FIT
338 */
339void upl_set_fit_addr(ulong fit);
340
341#else
342static inline void upl_set_fit_addr(ulong fit) {}
343static inline void upl_set_fit_info(ulong fit, int conf_offset,
344 ulong entry_addr) {}
345#endif /* UPL && SPL */
346
347/**
348 * _upl_add_image() - Internal function to add a new image to the UPL
349 *
350 * @node: Image node offset in FIT
351 * @load_addr: Address to which images was loaded
352 * @size: Image size in bytes
353 * @desc: Description of image
354 * Return: 0 if OK, -ENOMEM if out of memory
355 */
356int _upl_add_image(int node, ulong load_addr, ulong size, const char *desc);
357
358/**
359 * upl_add_image() - Add a new image to the UPL
360 *
361 * @fit: Pointer to FIT
362 * @node: Image node offset in FIT
363 * @load_addr: Address to which images was loaded
364 * @size: Image size in bytes
365 * Return: 0 if OK, -ENOMEM if out of memory
366 */
367static inline int upl_add_image(const void *fit, int node, ulong load_addr,
368 ulong size)
369{
370 if (CONFIG_IS_ENABLED(UPL) && IS_ENABLED(CONFIG_SPL_BUILD)) {
371 const char *desc = fdt_getprop(fit, node, FIT_DESC_PROP, NULL);
372
373 return _upl_add_image(node, load_addr, size, desc);
374 }
375
376 return 0;
377}
378
379/** upl_init() - Set up a UPL struct */
380void upl_init(struct upl *upl);
381
382#endif /* __UPL_WRITE_H */