X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=include%2Ffdtdec.h;h=696e0fd024d5d1ca972401e9aa651e30da439742;hb=ca5655d8006cfbaa4ff8ff450e4a5931e57fe050;hp=2941a2ea718356061f7279b05db12eea121b8df8;hpb=b08c8c4870831c9315dcae237772238e80035bd5;p=oweals%2Fu-boot.git diff --git a/include/fdtdec.h b/include/fdtdec.h index 2941a2ea71..696e0fd024 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -1,6 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (c) 2011 The Chromium OS Authors. - * SPDX-License-Identifier: GPL-2.0+ */ #ifndef __fdtdec_h @@ -23,15 +23,20 @@ */ typedef phys_addr_t fdt_addr_t; typedef phys_size_t fdt_size_t; + #ifdef CONFIG_PHYS_64BIT #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be64_to_cpu(reg) #define fdt_size_to_cpu(reg) be64_to_cpu(reg) +#define cpu_to_fdt_addr(reg) cpu_to_be64(reg) +#define cpu_to_fdt_size(reg) cpu_to_be64(reg) typedef fdt64_t fdt_val_t; #else #define FDT_ADDR_T_NONE (-1U) #define fdt_addr_to_cpu(reg) be32_to_cpu(reg) #define fdt_size_to_cpu(reg) be32_to_cpu(reg) +#define cpu_to_fdt_addr(reg) cpu_to_be32(reg) +#define cpu_to_fdt_size(reg) cpu_to_be32(reg) typedef fdt32_t fdt_val_t; #endif @@ -41,12 +46,18 @@ struct fdt_memory { fdt_addr_t end; }; +struct bd_info; + #ifdef CONFIG_SPL_BUILD #define SPL_BUILD 1 #else #define SPL_BUILD 0 #endif +#ifdef CONFIG_OF_PRIOR_STAGE +extern phys_addr_t prior_stage_fdt_address; +#endif + /* * Information about a resource. start is the first address of the resource * and end is the last address (inclusive). The length of the resource will @@ -127,22 +138,14 @@ enum fdt_compat_id { /* Tegra210 XUSB pad controller */ COMPAT_SMSC_LAN9215, /* SMSC 10/100 Ethernet LAN9215 */ COMPAT_SAMSUNG_EXYNOS5_SROMC, /* Exynos5 SROMC */ - COMPAT_SAMSUNG_S3C2440_I2C, /* Exynos I2C Controller */ - COMPAT_SAMSUNG_EXYNOS5_SOUND, /* Exynos Sound */ - COMPAT_WOLFSON_WM8994_CODEC, /* Wolfson WM8994 Sound Codec */ COMPAT_SAMSUNG_EXYNOS_USB_PHY, /* Exynos phy controller for usb2.0 */ COMPAT_SAMSUNG_EXYNOS5_USB3_PHY,/* Exynos phy controller for usb3.0 */ COMPAT_SAMSUNG_EXYNOS_TMU, /* Exynos TMU */ COMPAT_SAMSUNG_EXYNOS_MIPI_DSI, /* Exynos mipi dsi */ COMPAT_SAMSUNG_EXYNOS_DWMMC, /* Exynos DWMMC controller */ - COMPAT_SAMSUNG_EXYNOS_MMC, /* Exynos MMC controller */ - COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */ COMPAT_GENERIC_SPI_FLASH, /* Generic SPI Flash chip */ - COMPAT_MAXIM_98095_CODEC, /* MAX98095 Codec */ - COMPAT_SAMSUNG_EXYNOS5_I2C, /* Exynos5 High Speed I2C Controller */ COMPAT_SAMSUNG_EXYNOS_SYSMMU, /* Exynos sysmmu */ COMPAT_INTEL_MICROCODE, /* Intel microcode update */ - COMPAT_AMS_AS3722, /* AMS AS3722 PMIC */ COMPAT_INTEL_QRK_MRC, /* Intel Quark MRC */ COMPAT_ALTERA_SOCFPGA_DWMAC, /* SoCFPGA Ethernet controller */ COMPAT_ALTERA_SOCFPGA_DWMMC, /* SoCFPGA DWMMC controller */ @@ -161,6 +164,7 @@ enum fdt_compat_id { COMPAT_ALTERA_SOCFPGA_F2SDR2, /* SoCFPGA fpga2SDRAM2 bridge */ COMPAT_ALTERA_SOCFPGA_FPGA0, /* SOCFPGA FPGA manager */ COMPAT_ALTERA_SOCFPGA_NOC, /* SOCFPGA Arria 10 NOC */ + COMPAT_ALTERA_SOCFPGA_CLK_INIT, /* SOCFPGA Arria 10 clk init */ COMPAT_COUNT, }; @@ -412,23 +416,6 @@ fdt_addr_t fdtdec_get_addr(const void *blob, int node, fdt_addr_t fdtdec_get_addr_size(const void *blob, int node, const char *prop_name, fdt_size_t *sizep); -/** - * Look at an address property in a node and return the pci address which - * corresponds to the given type in the form of fdt_pci_addr. - * The property must hold one fdt_pci_addr with a lengh. - * - * @param blob FDT blob - * @param node node to examine - * @param type pci address type (FDT_PCI_SPACE_xxx) - * @param prop_name name of property to find - * @param addr returns pci address in the form of fdt_pci_addr - * @return 0 if ok, -ENOENT if the property did not exist, -EINVAL if the - * format of the property was invalid, -ENXIO if the requested - * address type was not found - */ -int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, - const char *prop_name, struct fdt_pci_addr *addr); - /** * Look at the compatible property of a device node that represents a PCI * device and extract pci vendor id and device id from it. @@ -619,6 +606,19 @@ int fdtdec_add_aliases_for_id(const void *blob, const char *name, int fdtdec_get_alias_seq(const void *blob, const char *base, int node, int *seqp); +/** + * Get the highest alias number for susbystem. + * + * It parses all aliases and find out highest recorded alias for subsystem. + * Aliases are of the form where is the sequence number. + * + * @param blob Device tree blob (if NULL, then error is returned) + * @param base Base name for alias susbystem (before the number) + * + * @return 0 highest alias ID, -1 if not found + */ +int fdtdec_get_alias_highest_id(const void *blob, const char *base); + /** * Get a property from the /chosen node * @@ -796,23 +796,6 @@ int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name, const u8 *fdtdec_locate_byte_array(const void *blob, int node, const char *prop_name, int count); -/** - * Look up a property in a node which contains a memory region address and - * size. Then return a pointer to this address. - * - * The property must hold one address with a length. This is only tested on - * 32-bit machines. - * - * @param blob FDT blob - * @param node node to examine - * @param prop_name name of property to find - * @param basep Returns base address of region - * @param size Returns size of region - * @return 0 if ok, -1 on error (property not found) - */ -int fdtdec_decode_region(const void *blob, int node, const char *prop_name, - fdt_addr_t *basep, fdt_size_t *sizep); - /** * Obtain an indexed resource from a device property. * @@ -843,34 +826,6 @@ int fdt_get_named_resource(const void *fdt, int node, const char *property, const char *prop_names, const char *name, struct fdt_resource *res); -/** - * Decode a named region within a memory bank of a given type. - * - * This function handles selection of a memory region. The region is - * specified as an offset/size within a particular type of memory. - * - * The properties used are: - * - * -memory for the name of the memory bank - * -offset for the offset in that bank - * - * The property value must have an offset and a size. The function checks - * that the region is entirely within the memory bank.5 - * - * @param blob FDT blob - * @param node Node containing the properties (-1 for /config) - * @param mem_type Type of memory to use, which is a name, such as - * "u-boot" or "kernel". - * @param suffix String to append to the memory/offset - * property names - * @param basep Returns base of region - * @param sizep Returns size of region - * @return 0 if OK, -ive on error - */ -int fdtdec_decode_memory_region(const void *blob, int node, - const char *mem_type, const char *suffix, - fdt_addr_t *basep, fdt_size_t *sizep); - /* Display timings from linux include/video/display_timing.h */ enum display_flags { DISPLAY_FLAGS_HSYNC_LOW = 1 << 0, @@ -951,20 +906,61 @@ int fdtdec_decode_display_timing(const void *blob, int node, int index, struct display_timing *config); /** - * fdtdec_setup_memory_size() - decode and setup gd->ram_size + * fdtdec_setup_mem_size_base_fdt() - decode and setup gd->ram_size and + * gd->ram_start + * + * Decode the /memory 'reg' property to determine the size and start of the + * first memory bank, populate the global data with the size and start of the + * first bank of memory. + * + * This function should be called from a boards dram_init(). This helper + * function allows for boards to query the device tree for DRAM size and start + * address instead of hard coding the value in the case where the memory size + * and start address cannot be detected automatically. + * + * @param blob FDT blob + * + * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or + * invalid + */ +int fdtdec_setup_mem_size_base_fdt(const void *blob); + +/** + * fdtdec_setup_mem_size_base() - decode and setup gd->ram_size and + * gd->ram_start * - * Decode the /memory 'reg' property to determine the size of the first memory - * bank, populate the global data with the size of the first bank of memory. + * Decode the /memory 'reg' property to determine the size and start of the + * first memory bank, populate the global data with the size and start of the + * first bank of memory. * * This function should be called from a boards dram_init(). This helper - * function allows for boards to query the device tree for DRAM size instead of - * hard coding the value in the case where the memory size cannot be detected - * automatically. + * function allows for boards to query the device tree for DRAM size and start + * address instead of hard coding the value in the case where the memory size + * and start address cannot be detected automatically. * * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or * invalid */ -int fdtdec_setup_memory_size(void); +int fdtdec_setup_mem_size_base(void); + +/** + * fdtdec_setup_memory_banksize_fdt() - decode and populate gd->bd->bi_dram + * + * Decode the /memory 'reg' property to determine the address and size of the + * memory banks. Use this data to populate the global data board info with the + * phys address and size of memory banks. + * + * This function should be called from a boards dram_init_banksize(). This + * helper function allows for boards to query the device tree for memory bank + * information instead of hard coding the information in cases where it cannot + * be detected automatically. + * + * @param blob FDT blob + * + * @return 0 if OK, -EINVAL if the /memory node or reg property is missing or + * invalid + */ +int fdtdec_setup_memory_banksize_fdt(const void *blob); /** * fdtdec_setup_memory_banksize() - decode and populate gd->bd->bi_dram @@ -983,11 +979,200 @@ int fdtdec_setup_memory_size(void); */ int fdtdec_setup_memory_banksize(void); +/** + * fdtdec_set_ethernet_mac_address() - set MAC address for default interface + * + * Looks up the default interface via the "ethernet" alias (in the /aliases + * node) and stores the given MAC in its "local-mac-address" property. This + * is useful on platforms that store the MAC address in a custom location. + * Board code can call this in the late init stage to make sure that the + * interface device tree node has the right MAC address configured for the + * Ethernet uclass to pick it up. + * + * Typically the FDT passed into this function will be U-Boot's control DTB. + * Given that a lot of code may be holding offsets to various nodes in that + * tree, this code will only set the "local-mac-address" property in-place, + * which means that it needs to exist and have space for the 6-byte address. + * This ensures that the operation is non-destructive and does not invalidate + * offsets that other drivers may be using. + * + * @param fdt FDT blob + * @param mac buffer containing the MAC address to set + * @param size size of MAC address + * @return 0 on success or a negative error code on failure + */ +int fdtdec_set_ethernet_mac_address(void *fdt, const u8 *mac, size_t size); + +/** + * fdtdec_set_phandle() - sets the phandle of a given node + * + * @param blob FDT blob + * @param node offset in the FDT blob of the node whose phandle is to + * be set + * @param phandle phandle to set for the given node + * @return 0 on success or a negative error code on failure + */ +static inline int fdtdec_set_phandle(void *blob, int node, uint32_t phandle) +{ + return fdt_setprop_u32(blob, node, "phandle", phandle); +} + +/** + * fdtdec_add_reserved_memory() - add or find a reserved-memory node + * + * If a reserved-memory node already exists for the given carveout, a phandle + * for that node will be returned. Otherwise a new node will be created and a + * phandle corresponding to it will be returned. + * + * See Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt + * for details on how to use reserved memory regions. + * + * As an example, consider the following code snippet: + * + * struct fdt_memory fb = { + * .start = 0x92cb3000, + * .end = 0x934b2fff, + * }; + * uint32_t phandle; + * + * fdtdec_add_reserved_memory(fdt, "framebuffer", &fb, &phandle); + * + * This results in the following subnode being added to the top-level + * /reserved-memory node: + * + * reserved-memory { + * #address-cells = <0x00000002>; + * #size-cells = <0x00000002>; + * ranges; + * + * framebuffer@92cb3000 { + * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>; + * phandle = <0x0000004d>; + * }; + * }; + * + * If the top-level /reserved-memory node does not exist, it will be created. + * The phandle returned from the function call can be used to reference this + * reserved memory region from other nodes. + * + * See fdtdec_set_carveout() for a more elaborate example. + * + * @param blob FDT blob + * @param basename base name of the node to create + * @param carveout information about the carveout region + * @param phandlep return location for the phandle of the carveout region + * can be NULL if no phandle should be added + * @return 0 on success or a negative error code on failure + */ +int fdtdec_add_reserved_memory(void *blob, const char *basename, + const struct fdt_memory *carveout, + uint32_t *phandlep); + +/** + * fdtdec_get_carveout() - reads a carveout from an FDT + * + * Reads information about a carveout region from an FDT. The carveout is a + * referenced by its phandle that is read from a given property in a given + * node. + * + * @param blob FDT blob + * @param node name of a node + * @param name name of the property in the given node that contains + * the phandle for the carveout + * @param index index of the phandle for which to read the carveout + * @param carveout return location for the carveout information + * @return 0 on success or a negative error code on failure + */ +int fdtdec_get_carveout(const void *blob, const char *node, const char *name, + unsigned int index, struct fdt_memory *carveout); + +/** + * fdtdec_set_carveout() - sets a carveout region for a given node + * + * Sets a carveout region for a given node. If a reserved-memory node already + * exists for the carveout, the phandle for that node will be reused. If no + * such node exists, a new one will be created and a phandle to it stored in + * a specified property of the given node. + * + * As an example, consider the following code snippet: + * + * const char *node = "/host1x@50000000/dc@54240000"; + * struct fdt_memory fb = { + * .start = 0x92cb3000, + * .end = 0x934b2fff, + * }; + * + * fdtdec_set_carveout(fdt, node, "memory-region", 0, "framebuffer", &fb); + * + * dc@54200000 is a display controller and was set up by the bootloader to + * scan out the framebuffer specified by "fb". This would cause the following + * reserved memory region to be added: + * + * reserved-memory { + * #address-cells = <0x00000002>; + * #size-cells = <0x00000002>; + * ranges; + * + * framebuffer@92cb3000 { + * reg = <0x00000000 0x92cb3000 0x00000000 0x00800000>; + * phandle = <0x0000004d>; + * }; + * }; + * + * A "memory-region" property will also be added to the node referenced by the + * offset parameter. + * + * host1x@50000000 { + * ... + * + * dc@54240000 { + * ... + * memory-region = <0x0000004d>; + * ... + * }; + * + * ... + * }; + * + * @param blob FDT blob + * @param node name of the node to add the carveout to + * @param prop_name name of the property in which to store the phandle of + * the carveout + * @param index index of the phandle to store + * @param name base name of the reserved-memory node to create + * @param carveout information about the carveout to add + * @return 0 on success or a negative error code on failure + */ +int fdtdec_set_carveout(void *blob, const char *node, const char *prop_name, + unsigned int index, const char *name, + const struct fdt_memory *carveout); + /** * Set up the device tree ready for use */ int fdtdec_setup(void); +#if CONFIG_IS_ENABLED(MULTI_DTB_FIT) +/** + * fdtdec_resetup() - Set up the device tree again + * + * The main difference with fdtdec_setup() is that it returns if the fdt has + * changed because a better match has been found. + * This is typically used for boards that rely on a DM driver to detect the + * board type. This function sould be called by the board code after the stuff + * needed by board_fit_config_name_match() to operate porperly is available. + * If this functions signals that a rescan is necessary, the board code must + * unbind all the drivers using dm_uninit() and then rescan the DT with + * dm_init_and_scan(). + * + * @param rescan Returns a flag indicating that fdt has changed and rescanning + * the fdt is required + * + * @return 0 if OK, -ve on error + */ +int fdtdec_resetup(int *rescan); +#endif + /** * Board-specific FDT initialization. Returns the address to a device tree blob. * Called when CONFIG_OF_BOARD is defined, or if CONFIG_OF_SEPARATE is defined @@ -995,4 +1180,39 @@ int fdtdec_setup(void); */ void *board_fdt_blob_setup(void); +/* + * Decode the size of memory + * + * RAM size is normally set in a /memory node and consists of a list of + * (base, size) cells in the 'reg' property. This information is used to + * determine the total available memory as well as the address and size + * of each bank. + * + * Optionally the memory configuration can vary depending on a board id, + * typically read from strapping resistors or an EEPROM on the board. + * + * Finally, memory size can be detected (within certain limits) by probing + * the available memory. It is safe to do so within the limits provides by + * the board's device tree information. This makes it possible to produce + * boards with different memory sizes, where the device tree specifies the + * maximum memory configuration, and the smaller memory configuration is + * probed. + * + * This function decodes that information, returning the memory base address, + * size and bank information. See the memory.txt binding for full + * documentation. + * + * @param blob Device tree blob + * @param area Name of node to check (NULL means "/memory") + * @param board_id Board ID to look up + * @param basep Returns base address of first memory bank (NULL to + * ignore) + * @param sizep Returns total memory size (NULL to ignore) + * @param bd Updated with the memory bank information (NULL to skip) + * @return 0 if OK, -ve on error + */ +int fdtdec_decode_ram_size(const void *blob, const char *area, int board_id, + phys_addr_t *basep, phys_size_t *sizep, + struct bd_info *bd); + #endif