| /* SPDX-License-Identifier: GPL-2.0+ */ |
| /* |
| * UPL handoff generation |
| * |
| * Copyright 2024 Google LLC |
| * Written by Simon Glass <sjg@chromium.org> |
| */ |
| |
| #ifndef __UPL_WRITE_H |
| #define __UPL_WRITE_H |
| |
| #ifndef USE_HOSTCC |
| |
| #include <alist.h> |
| #include <image.h> |
| #include <dm/ofnode_decl.h> |
| |
| struct unit_test_state; |
| |
| #define UPLP_ADDRESS_CELLS "#address-cells" |
| #define UPLP_SIZE_CELLS "#size-cells" |
| |
| #define UPLN_OPTIONS "options" |
| #define UPLN_UPL_PARAMS "upl-params" |
| #define UPLP_SMBIOS "smbios" |
| #define UPLP_ACPI "acpi" |
| #define UPLP_BOOTMODE "bootmode" |
| #define UPLP_ADDR_WIDTH "addr-width" |
| #define UPLP_ACPI_NVS_SIZE "acpi-nvs-size" |
| |
| #define UPLPATH_UPL_IMAGE "/options/upl-image" |
| #define UPLN_UPL_IMAGE "upl-image" |
| #define UPLN_IMAGE "image" |
| #define UPLP_FIT "fit" |
| #define UPLP_CONF_OFFSET "conf-offset" |
| #define UPLP_LOAD "load" |
| #define UPLP_SIZE "size" |
| #define UPLP_OFFSET "offset" |
| #define UPLP_DESCRIPTION "description" |
| |
| #define UPLN_MEMORY "memory" |
| #define UPLP_HOTPLUGGABLE "hotpluggable" |
| |
| #define UPLPATH_MEMORY_MAP "/memory-map" |
| #define UPLN_MEMORY_MAP "memory-map" |
| #define UPLP_USAGE "usage" |
| |
| #define UPLN_MEMORY_RESERVED "reserved-memory" |
| #define UPLPATH_MEMORY_RESERVED "/reserved-memory" |
| #define UPLP_NO_MAP "no-map" |
| |
| #define UPLN_SERIAL "serial" |
| #define UPLP_REG "reg" |
| #define UPLP_COMPATIBLE "compatible" |
| #define UPLP_CLOCK_FREQUENCY "clock-frequency" |
| #define UPLP_CURRENT_SPEED "current-speed" |
| #define UPLP_REG_IO_SHIFT "reg-io-shift" |
| #define UPLP_REG_OFFSET "reg-offset" |
| #define UPLP_REG_IO_WIDTH "reg-io-width" |
| #define UPLP_VIRTUAL_REG "virtual-reg" |
| #define UPLP_ACCESS_TYPE "access-type" |
| |
| #define UPLN_GRAPHICS "framebuffer" |
| #define UPLC_GRAPHICS "simple-framebuffer" |
| #define UPLP_WIDTH "width" |
| #define UPLP_HEIGHT "height" |
| #define UPLP_STRIDE "stride" |
| #define UPLP_GRAPHICS_FORMAT "format" |
| |
| /** |
| * enum upl_boot_mode - Encodes the boot mode |
| * |
| * Each is a bit number from the boot_mode mask |
| */ |
| enum upl_boot_mode { |
| UPLBM_FULL, |
| UPLBM_MINIMAL, |
| UPLBM_FAST, |
| UPLBM_DIAG, |
| UPLBM_DEFAULT, |
| UPLBM_S2, |
| UPLBM_S3, |
| UPLBM_S4, |
| UPLBM_S5, |
| UPLBM_FACTORY, |
| UPLBM_FLASH, |
| UPLBM_RECOVERY, |
| |
| UPLBM_COUNT, |
| }; |
| |
| /** |
| * struct upl_image - UPL image informaiton |
| * |
| * @load: Address image was loaded to |
| * @size: Size of image in bytes |
| * @offset: Offset of the image in the FIT (0=none) |
| * @desc: Description of the iamge (taken from the FIT) |
| */ |
| struct upl_image { |
| ulong load; |
| ulong size; |
| uint offset; |
| const char *description; |
| }; |
| |
| /** |
| * struct memregion - Information about a region of memory |
| * |
| * @base: Base address |
| * @size: Size in bytes |
| */ |
| struct memregion { |
| ulong base; |
| ulong size; |
| }; |
| |
| /** |
| * struct upl_mem - Information about physical-memory layout |
| * |
| * TODO: Figure out initial-mapped-area |
| * |
| * @region: Memory region list (struct memregion) |
| * @hotpluggable: true if hotpluggable |
| */ |
| struct upl_mem { |
| struct alist region; |
| bool hotpluggable; |
| }; |
| |
| /** |
| * enum upl_usage - Encodes the usage |
| * |
| * Each is a bit number from the usage mask |
| */ |
| enum upl_usage { |
| UPLUS_ACPI_RECLAIM, |
| UPLUS_ACPI_NVS, |
| UPLUS_BOOT_CODE, |
| UPLUS_BOOT_DATA, |
| UPLUS_RUNTIME_CODE, |
| UPLUS_RUNTIME_DATA, |
| UPLUS_COUNT |
| }; |
| |
| /** |
| * struct upl_memmap - Information about logical-memory layout |
| * |
| * @name: Node name to use |
| * @region: Memory region list (struct memregion) |
| * @usage: Memory-usage mask (enum upl_usage) |
| */ |
| struct upl_memmap { |
| const char *name; |
| struct alist region; |
| uint usage; |
| }; |
| |
| /** |
| * struct upl_memres - Reserved memory |
| * |
| * @name: Node name to use |
| * @region: Reserved memory region list (struct memregion) |
| * @no_map: true to indicate that a virtual mapping must not be created |
| */ |
| struct upl_memres { |
| const char *name; |
| struct alist region; |
| bool no_map; |
| }; |
| |
| enum upl_serial_access_type { |
| UPLSAT_MMIO, |
| UPLSAT_IO, |
| }; |
| |
| /* serial defaults */ |
| enum { |
| UPLD_REG_IO_SHIFT = 0, |
| UPLD_REG_OFFSET = 0, |
| UPLD_REG_IO_WIDTH = 1, |
| }; |
| |
| /** |
| * enum upl_access_type - Access types |
| * |
| * @UPLAT_MMIO: Memory-mapped I/O |
| * @UPLAT_IO: Separate I/O |
| */ |
| enum upl_access_type { |
| UPLAT_MMIO, |
| UPLAT_IO, |
| }; |
| |
| /** |
| * struct upl_serial - Serial console |
| * |
| * @compatible: Compatible string (NULL if there is no serial console) |
| * @clock_frequency: Input clock frequency of UART |
| * @current_speed: Current baud rate of UART |
| * @reg: List of base address and size of registers (struct memregion) |
| * @reg_shift_log2: log2 of distance between each register |
| * @reg_offset: Offset of registers from the base address |
| * @reg_width: Register width in bytes |
| * @virtual_reg: Virtual register access (0 for none) |
| * @access_type: Register access type to use |
| */ |
| struct upl_serial { |
| const char *compatible; |
| uint clock_frequency; |
| uint current_speed; |
| struct alist reg; |
| uint reg_io_shift; |
| uint reg_offset; |
| uint reg_io_width; |
| ulong virtual_reg; |
| enum upl_serial_access_type access_type; |
| }; |
| |
| /** |
| * enum upl_graphics_format - Graphics formats |
| * |
| * @UPLGF_ARGB32: 32bpp format using 0xaarrggbb |
| * @UPLGF_ABGR32: 32bpp format using 0xaabbggrr |
| * @UPLGF_ARGB64: 64bpp format using 0xaaaabbbbggggrrrr |
| */ |
| enum upl_graphics_format { |
| UPLGF_ARGB32, |
| UPLGF_ABGR32, |
| UPLGF_ABGR64, |
| }; |
| |
| /** |
| * @reg: List of base address and size of registers (struct memregion) |
| * @width: Width of display in pixels |
| * @height: Height of display in pixels |
| * @stride: Number of bytes from one line to the next |
| * @format: Pixel format |
| */ |
| struct upl_graphics { |
| struct alist reg; |
| uint width; |
| uint height; |
| uint stride; |
| enum upl_graphics_format format; |
| }; |
| |
| /* |
| * Information about the UPL state |
| * |
| * @addr_cells: Number of address cells used in the handoff |
| * @size_cells: Number of size cells used in the handoff |
| * @bootmode: Boot-mode mask (enum upl_boot_mode) |
| * @fit: Address of FIT image that was loaded |
| * @conf_offset: Offset in FIT of the configuration that was selected |
| * @addr_width: Adress-bus width of machine, e.g. 46 for 46 bits |
| * @acpi_nvs_size: Size of the ACPI non-volatile-storage area in bytes |
| * @image: Information about each image (struct upl_image) |
| * @mem: Information about physical-memory regions (struct upl_mem) |
| * @nennap: Information about logical-memory regions (struct upl_memmap) |
| * @nennap: Information about reserved-memory regions (struct upl_memres) |
| */ |
| struct upl { |
| int addr_cells; |
| int size_cells; |
| |
| ulong smbios; |
| ulong acpi; |
| uint bootmode; |
| ulong fit; |
| uint conf_offset; |
| uint addr_width; |
| uint acpi_nvs_size; |
| |
| struct alist image; |
| struct alist mem; |
| struct alist memmap; |
| struct alist memres; |
| struct upl_serial serial; |
| struct upl_graphics graphics; |
| }; |
| |
| /** |
| * upl_write_handoff() - Write a Unversal Payload handoff structure |
| * |
| * upl: UPL state to write |
| * @root: root node to write it to |
| * @skip_existing: Avoid recreating any nodes which already exist in the |
| * devicetree. For example, if there is a serial node, just leave it alone, |
| * since don't need to create a new one |
| * Return: 0 on success, -ve on error |
| */ |
| int upl_write_handoff(const struct upl *upl, ofnode root, bool skip_existing); |
| |
| /** |
| * upl_create_handoff_tree() - Write a Unversal Payload handoff structure |
| * |
| * upl: UPL state to write |
| * @treep: Returns a new tree containing the handoff |
| * Return: 0 on success, -ve on error |
| */ |
| int upl_create_handoff_tree(const struct upl *upl, oftree *treep); |
| |
| /** |
| * upl_read_handoff() - Read a Unversal Payload handoff structure |
| * |
| * upl: UPL state to read into |
| * @tree: Devicetree containing the data to read |
| * Return: 0 on success, -ve on error |
| */ |
| int upl_read_handoff(struct upl *upl, oftree tree); |
| |
| /** |
| * upl_get_test_data() - Fill a UPL with some test data |
| * |
| * @uts: Test state (can be uninited) |
| * @upl: Returns test data |
| * Return: 0 on success, 1 on error |
| */ |
| int upl_get_test_data(struct unit_test_state *uts, struct upl *upl); |
| #endif /* USE_HOSTCC */ |
| |
| #if CONFIG_IS_ENABLED(UPL) && defined(CONFIG_SPL_BUILD) |
| |
| /** |
| * upl_set_fit_info() - Set up basic info about the FIT |
| * |
| * @fit: Address of FIT |
| * @conf_offset: Configuration node being used |
| * @entry_addr: Entry address for next phase |
| */ |
| void upl_set_fit_info(ulong fit, int conf_offset, ulong entry_addr); |
| |
| /** |
| * upl_set_fit_addr() - Set up the address of the FIT |
| * |
| * @fit: Address of FIT |
| */ |
| void upl_set_fit_addr(ulong fit); |
| |
| #else |
| static inline void upl_set_fit_addr(ulong fit) {} |
| static inline void upl_set_fit_info(ulong fit, int conf_offset, |
| ulong entry_addr) {} |
| #endif /* UPL && SPL */ |
| |
| /** |
| * _upl_add_image() - Internal function to add a new image to the UPL |
| * |
| * @node: Image node offset in FIT |
| * @load_addr: Address to which images was loaded |
| * @size: Image size in bytes |
| * @desc: Description of image |
| * Return: 0 if OK, -ENOMEM if out of memory |
| */ |
| int _upl_add_image(int node, ulong load_addr, ulong size, const char *desc); |
| |
| /** |
| * upl_add_image() - Add a new image to the UPL |
| * |
| * @fit: Pointer to FIT |
| * @node: Image node offset in FIT |
| * @load_addr: Address to which images was loaded |
| * @size: Image size in bytes |
| * Return: 0 if OK, -ENOMEM if out of memory |
| */ |
| static inline int upl_add_image(const void *fit, int node, ulong load_addr, |
| ulong size) |
| { |
| if (CONFIG_IS_ENABLED(UPL) && IS_ENABLED(CONFIG_SPL_BUILD)) { |
| const char *desc = fdt_getprop(fit, node, FIT_DESC_PROP, NULL); |
| |
| return _upl_add_image(node, load_addr, size, desc); |
| } |
| |
| return 0; |
| } |
| |
| /** upl_init() - Set up a UPL struct */ |
| void upl_init(struct upl *upl); |
| |
| #endif /* __UPL_WRITE_H */ |