X-Git-Url: https://git.kernelconcepts.de/?a=blobdiff_plain;f=lib%2Ffdtdec.c;h=80b897a21cd69a88ce5d3fe1398d23da11339f67;hb=c44e9a99e38819c1f61b350e316b52aa8c85320e;hp=487122eebcf64c9129abb60c91e91d328f207f29;hpb=a62e84d7b1824a202dd6a9e9c7b1bc350c7b33b7;p=karo-tx-uboot.git diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 487122eebc..80b897a21c 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -9,10 +9,9 @@ #include #include #include +#include #include -#include - DECLARE_GLOBAL_DATA_PTR; /* @@ -26,9 +25,6 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(NVIDIA_TEGRA20_USB, "nvidia,tegra20-ehci"), COMPAT(NVIDIA_TEGRA30_USB, "nvidia,tegra30-ehci"), COMPAT(NVIDIA_TEGRA114_USB, "nvidia,tegra114-ehci"), - COMPAT(NVIDIA_TEGRA114_I2C, "nvidia,tegra114-i2c"), - COMPAT(NVIDIA_TEGRA20_I2C, "nvidia,tegra20-i2c"), - COMPAT(NVIDIA_TEGRA20_DVC, "nvidia,tegra20-i2c-dvc"), COMPAT(NVIDIA_TEGRA20_EMC, "nvidia,tegra20-emc"), COMPAT(NVIDIA_TEGRA20_EMC_TABLE, "nvidia,tegra20-emc-table"), COMPAT(NVIDIA_TEGRA20_KBC, "nvidia,tegra20-kbc"), @@ -38,9 +34,6 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(NVIDIA_TEGRA124_SDMMC, "nvidia,tegra124-sdhci"), COMPAT(NVIDIA_TEGRA30_SDMMC, "nvidia,tegra30-sdhci"), COMPAT(NVIDIA_TEGRA20_SDMMC, "nvidia,tegra20-sdhci"), - COMPAT(NVIDIA_TEGRA20_SFLASH, "nvidia,tegra20-sflash"), - COMPAT(NVIDIA_TEGRA20_SLINK, "nvidia,tegra20-slink"), - COMPAT(NVIDIA_TEGRA114_SPI, "nvidia,tegra114-spi"), COMPAT(NVIDIA_TEGRA124_PCIE, "nvidia,tegra124-pcie"), COMPAT(NVIDIA_TEGRA30_PCIE, "nvidia,tegra30-pcie"), COMPAT(NVIDIA_TEGRA20_PCIE, "nvidia,tegra20-pcie"), @@ -50,8 +43,6 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"), COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"), COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"), - COMPAT(SAMSUNG_EXYNOS_SPI, "samsung,exynos-spi"), - COMPAT(GOOGLE_CROS_EC, "google,cros-ec"), COMPAT(GOOGLE_CROS_EC_KEYB, "google,cros-ec-keyb"), COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"), COMPAT(SAMSUNG_EXYNOS5_XHCI, "samsung,exynos5250-xhci"), @@ -70,19 +61,21 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(INFINEON_SLB9635_TPM, "infineon,slb9635-tpm"), COMPAT(INFINEON_SLB9645_TPM, "infineon,slb9645-tpm"), COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"), - COMPAT(SANDBOX_HOST_EMULATION, "sandbox,host-emulation"), COMPAT(SANDBOX_LCD_SDL, "sandbox,lcd-sdl"), COMPAT(TI_TPS65090, "ti,tps65090"), COMPAT(COMPAT_NXP_PTN3460, "nxp,ptn3460"), COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"), COMPAT(PARADE_PS8625, "parade,ps8625"), - COMPAT(COMPAT_INTEL_LPC, "intel,lpc"), COMPAT(INTEL_MICROCODE, "intel,microcode"), COMPAT(MEMORY_SPD, "memory-spd"), COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"), COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"), COMPAT(INTEL_GMA, "intel,gma"), COMPAT(AMS_AS3722, "ams,as3722"), + COMPAT(INTEL_ICH_SPI, "intel,ich-spi"), + COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"), + COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"), + COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) @@ -166,8 +159,10 @@ int fdtdec_get_pci_addr(const void *blob, int node, enum fdt_pci_space type, } } - if (i == num) + if (i == num) { + ret = -ENXIO; goto fail; + } return 0; } else { @@ -571,9 +566,11 @@ int fdtdec_prepare_fdt(void) { if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) || fdt_check_header(gd->fdt_blob)) { - printf("No valid FDT found - please append one to U-Boot " - "binary, use u-boot-dtb.bin or define " - "CONFIG_OF_EMBED. For sandbox, use -d \n"); +#ifdef CONFIG_SPL_BUILD + puts("Missing DTB\n"); +#else + 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 \n"); +#endif return -1; } return 0; @@ -678,99 +675,128 @@ int fdtdec_get_bool(const void *blob, int node, const char *prop_name) return cell != NULL; } -/** - * Decode a list of GPIOs from an FDT. This creates a list of GPIOs with no - * terminating item. - * - * @param blob FDT blob to use - * @param node Node to look at - * @param prop_name Node property name - * @param gpio Array of gpio elements to fill from FDT. This will be - * untouched if either 0 or an error is returned - * @param max_count Maximum number of elements allowed - * @return number of GPIOs read if ok, -FDT_ERR_BADLAYOUT if max_count would - * be exceeded, or -FDT_ERR_NOTFOUND if the property is missing. - */ -int fdtdec_decode_gpios(const void *blob, int node, const char *prop_name, - struct fdt_gpio_state *gpio, int max_count) +int fdtdec_parse_phandle_with_args(const void *blob, int src_node, + const char *list_name, + const char *cells_name, + int cell_count, int index, + struct fdtdec_phandle_args *out_args) { - const struct fdt_property *prop; - const u32 *cell; - const char *name; - int len, i; - - debug("%s: %s\n", __func__, prop_name); - assert(max_count > 0); - prop = fdt_get_property(blob, node, prop_name, &len); - if (!prop) { - debug("%s: property '%s' missing\n", __func__, prop_name); - return -FDT_ERR_NOTFOUND; - } - - /* We will use the name to tag the GPIO */ - name = fdt_string(blob, fdt32_to_cpu(prop->nameoff)); - cell = (u32 *)prop->data; - len /= sizeof(u32) * 3; /* 3 cells per GPIO record */ - if (len > max_count) { - debug(" %s: too many GPIOs / cells for " - "property '%s'\n", __func__, prop_name); - return -FDT_ERR_BADLAYOUT; - } - - /* Read out the GPIO data from the cells */ - for (i = 0; i < len; i++, cell += 3) { - gpio[i].gpio = fdt32_to_cpu(cell[1]); - gpio[i].flags = fdt32_to_cpu(cell[2]); - gpio[i].name = name; - } + const __be32 *list, *list_end; + int rc = 0, size, cur_index = 0; + uint32_t count = 0; + int node = -1; + int phandle; + + /* Retrieve the phandle list property */ + list = fdt_getprop(blob, src_node, list_name, &size); + if (!list) + return -ENOENT; + list_end = list + size / sizeof(*list); - return len; -} + /* Loop over the phandles until all the requested entry is found */ + while (list < list_end) { + rc = -EINVAL; + count = 0; -int fdtdec_decode_gpio(const void *blob, int node, const char *prop_name, - struct fdt_gpio_state *gpio) -{ - int err; - - debug("%s: %s\n", __func__, prop_name); - gpio->gpio = FDT_GPIO_NONE; - gpio->name = NULL; - err = fdtdec_decode_gpios(blob, node, prop_name, gpio, 1); - return err == 1 ? 0 : err; -} + /* + * If phandle is 0, then it is an empty entry with no + * arguments. Skip forward to the next entry. + */ + phandle = be32_to_cpup(list++); + if (phandle) { + /* + * Find the provider node and parse the #*-cells + * property to determine the argument length. + * + * This is not needed if the cell count is hard-coded + * (i.e. cells_name not set, but cell_count is set), + * except when we're going to return the found node + * below. + */ + if (cells_name || cur_index == index) { + node = fdt_node_offset_by_phandle(blob, + phandle); + if (!node) { + debug("%s: could not find phandle\n", + fdt_get_name(blob, src_node, + NULL)); + goto err; + } + } -int fdtdec_get_gpio(struct fdt_gpio_state *gpio) -{ - int val; + if (cells_name) { + count = fdtdec_get_int(blob, node, cells_name, + -1); + if (count == -1) { + debug("%s: could not get %s for %s\n", + fdt_get_name(blob, src_node, + NULL), + cells_name, + fdt_get_name(blob, node, + NULL)); + goto err; + } + } else { + count = cell_count; + } - if (!fdt_gpio_isvalid(gpio)) - return -1; + /* + * Make sure that the arguments actually fit in the + * remaining property data length + */ + if (list + count > list_end) { + debug("%s: arguments longer than property\n", + fdt_get_name(blob, src_node, NULL)); + goto err; + } + } - val = gpio_get_value(gpio->gpio); - return gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val; -} + /* + * All of the error cases above bail out of the loop, so at + * this point, the parsing is successful. If the requested + * index matches, then fill the out_args structure and return, + * or return -ENOENT for an empty entry. + */ + rc = -ENOENT; + if (cur_index == index) { + if (!phandle) + goto err; + + if (out_args) { + int i; + + if (count > MAX_PHANDLE_ARGS) { + debug("%s: too many arguments %d\n", + fdt_get_name(blob, src_node, + NULL), count); + count = MAX_PHANDLE_ARGS; + } + out_args->node = node; + out_args->args_count = count; + for (i = 0; i < count; i++) { + out_args->args[i] = + be32_to_cpup(list++); + } + } -int fdtdec_set_gpio(struct fdt_gpio_state *gpio, int val) -{ - if (!fdt_gpio_isvalid(gpio)) - return -1; + /* Found it! return success */ + return 0; + } - val = gpio->flags & FDT_GPIO_ACTIVE_LOW ? val ^ 1 : val; - return gpio_set_value(gpio->gpio, val); -} + node = -1; + list += count; + cur_index++; + } -int fdtdec_setup_gpio(struct fdt_gpio_state *gpio) -{ /* - * Return success if there is no GPIO defined. This is used for - * optional GPIOs) + * Result will be one of: + * -ENOENT : index is for empty phandle + * -EINVAL : parsing error on data + * [1..n] : Number of phandle (count mode; when index = -1) */ - if (!fdt_gpio_isvalid(gpio)) - return 0; - - if (gpio_request(gpio->gpio, gpio->name)) - return -1; - return 0; + rc = index < 0 ? cur_index : -ENOENT; + err: + return rc; } int fdtdec_get_byte_array(const void *blob, int node, const char *prop_name, @@ -895,7 +921,7 @@ int fdtdec_read_fmap_entry(const void *blob, int node, const char *name, return 0; } -static u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells) +u64 fdtdec_get_number(const fdt32_t *ptr, unsigned int cells) { u64 number = 0; @@ -1012,4 +1038,34 @@ int fdtdec_decode_memory_region(const void *blob, int config_node, return 0; } + +int fdtdec_setup(void) +{ +#ifdef CONFIG_OF_CONTROL +# ifdef CONFIG_OF_EMBED + /* Get a pointer to the FDT */ + gd->fdt_blob = __dtb_dt_begin; +# elif defined CONFIG_OF_SEPARATE +# ifdef CONFIG_SPL_BUILD + /* FDT is at end of BSS */ + gd->fdt_blob = (ulong *)&__bss_end; +# else + /* FDT is at end of image */ + gd->fdt_blob = (ulong *)&_end; #endif +# elif defined(CONFIG_OF_HOSTFILE) + if (sandbox_read_fdt_from_file()) { + puts("Failed to read control FDT\n"); + return -1; + } +# endif +# ifndef CONFIG_SPL_BUILD + /* Allow the early environment to override the fdt address */ + gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, + (uintptr_t)gd->fdt_blob); +# endif +#endif + return fdtdec_prepare_fdt(); +} + +#endif /* !USE_HOSTCC */