From 57be1825cb6bf4b2652844a113333267f9d8a3da Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Wed, 15 Jan 2020 14:39:53 +0800 Subject: [PATCH] rockchip: clean kernel dtb code to kernel_dtb.c Since there is a lot of code for kernel dtb feature, let's move them into a individual file to make board.c clean. Signed-off-by: Joseph Chen Change-Id: I4e01627c265807b1c0e26b432f0b4fc1db0d889e --- arch/arm/mach-rockchip/Makefile | 1 + arch/arm/mach-rockchip/board.c | 282 ---------------------------- arch/arm/mach-rockchip/kernel_dtb.c | 279 +++++++++++++++++++++++++++ include/boot_rkimg.h | 1 + 4 files changed, 281 insertions(+), 282 deletions(-) create mode 100644 arch/arm/mach-rockchip/kernel_dtb.c diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 897818cf41..15f314add0 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -28,6 +28,7 @@ obj-y += iomem.o obj-y += memblk.o obj-y += hotkey.o +obj-$(CONFIG_USING_KERNEL_DTB) += kernel_dtb.o obj-$(CONFIG_ROCKCHIP_SMCCC) += rockchip_smccc.o obj-$(CONFIG_ROCKCHIP_VENDOR_PARTITION) += vendor.o obj-$(CONFIG_ROCKCHIP_RESOURCE_IMAGE) += resource_img.o diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c index aa33d4ffb4..a7bc733a1e 100644 --- a/arch/arm/mach-rockchip/board.c +++ b/arch/arm/mach-rockchip/board.c @@ -280,288 +280,6 @@ int board_late_init(void) return rk_board_late_init(); } -#ifdef CONFIG_USING_KERNEL_DTB -/* Here, only fixup cru phandle, pmucru is not included */ -static int phandles_fixup_cru(void *fdt) -{ - const char *props[] = { "clocks", "assigned-clocks" }; - struct udevice *dev; - struct uclass *uc; - const char *comp; - u32 id, nclocks; - u32 *clocks; - int phandle, ncells; - int off, offset; - int ret, length; - int i, j; - int first_phandle = -1; - - phandle = -ENODATA; - ncells = -ENODATA; - - /* fdt points to kernel dtb, getting cru phandle and "#clock-cells" */ - for (offset = fdt_next_node(fdt, 0, NULL); - offset >= 0; - offset = fdt_next_node(fdt, offset, NULL)) { - comp = fdt_getprop(fdt, offset, "compatible", NULL); - if (!comp) - continue; - - /* Actually, this is not a good method to get cru node */ - off = strlen(comp) - strlen("-cru"); - if (off > 0 && !strncmp(comp + off, "-cru", 4)) { - phandle = fdt_get_phandle(fdt, offset); - ncells = fdtdec_get_int(fdt, offset, - "#clock-cells", -ENODATA); - break; - } - } - - if (phandle == -ENODATA || ncells == -ENODATA) - return 0; - - debug("%s: target cru: clock-cells:%d, phandle:0x%x\n", - __func__, ncells, fdt32_to_cpu(phandle)); - - /* Try to fixup all cru phandle from U-Boot dtb nodes */ - for (id = 0; id < UCLASS_COUNT; id++) { - ret = uclass_get(id, &uc); - if (ret) - continue; - - if (list_empty(&uc->dev_head)) - continue; - - list_for_each_entry(dev, &uc->dev_head, uclass_node) { - /* Only U-Boot node go further */ - if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") && - !dev_read_bool(dev, "u-boot,dm-spl")) - continue; - - for (i = 0; i < ARRAY_SIZE(props); i++) { - if (!dev_read_prop(dev, props[i], &length)) - continue; - - clocks = malloc(length); - if (!clocks) - return -ENOMEM; - - /* Read "props[]" which contains cru phandle */ - nclocks = length / sizeof(u32); - if (dev_read_u32_array(dev, props[i], - clocks, nclocks)) { - free(clocks); - continue; - } - - /* Fixup with kernel cru phandle */ - for (j = 0; j < nclocks; j += (ncells + 1)) { - /* - * Check: update pmucru phandle with cru - * phandle by mistake. - */ - if (first_phandle == -1) - first_phandle = clocks[j]; - - if (clocks[j] != first_phandle) { - debug("WARN: %s: first cru phandle=%d, this=%d\n", - dev_read_name(dev), - first_phandle, clocks[j]); - continue; - } - - clocks[j] = phandle; - } - - /* - * Override live dt nodes but not fdt nodes, - * because all U-Boot nodes has been imported - * to live dt nodes, should use "dev_xxx()". - */ - dev_write_u32_array(dev, props[i], - clocks, nclocks); - free(clocks); - } - } - } - - return 0; -} - -static int phandles_fixup_gpio(void *fdt, void *ufdt) -{ - struct udevice *dev; - struct uclass *uc; - const char *prop = "gpios"; - const char *comp; - char *gpio_name[10]; - int gpio_off[10]; - int pinctrl; - int offset; - int i = 0; - int n = 0; - - pinctrl = fdt_path_offset(fdt, "/pinctrl"); - if (pinctrl < 0) - return 0; - - memset(gpio_name, 0, sizeof(gpio_name)); - for (offset = fdt_first_subnode(fdt, pinctrl); - offset >= 0; - offset = fdt_next_subnode(fdt, offset)) { - /* assume the font nodes are gpio node */ - if (++i >= ARRAY_SIZE(gpio_name)) - break; - - comp = fdt_getprop(fdt, offset, "compatible", NULL); - if (!comp) - continue; - - if (!strcmp(comp, "rockchip,gpio-bank")) { - gpio_name[n] = (char *)fdt_get_name(fdt, offset, NULL); - gpio_off[n] = offset; - n++; - } - } - - if (!gpio_name[0]) - return 0; - - if (uclass_get(UCLASS_KEY, &uc) || list_empty(&uc->dev_head)) - return 0; - - list_for_each_entry(dev, &uc->dev_head, uclass_node) { - u32 new_phd, phd_old; - char *name; - ofnode ofn; - - if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") && - !dev_read_bool(dev, "u-boot,dm-spl")) - continue; - - if (dev_read_u32_array(dev, prop, &phd_old, 1)) - continue; - - ofn = ofnode_get_by_phandle(phd_old); - if (!ofnode_valid(ofn)) - continue; - - name = (char *)ofnode_get_name(ofn); - if (!name) - continue; - - for (i = 0; i < ARRAY_SIZE(gpio_name[i]); i++) { - if (gpio_name[i] && !strcmp(name, gpio_name[i])) { - new_phd = fdt_get_phandle(fdt, gpio_off[i]); - dev_write_u32_array(dev, prop, &new_phd, 1); - break; - } - } - } - - return 0; -} - -__weak int board_mmc_dm_reinit(struct udevice *dev) -{ - return 0; -} - -static int mmc_dm_reinit(void) -{ - struct udevice *dev; - struct uclass *uc; - int ret; - - if (uclass_get(UCLASS_MMC, &uc) || list_empty(&uc->dev_head)) - return 0; - - list_for_each_entry(dev, &uc->dev_head, uclass_node) { - ret = board_mmc_dm_reinit(dev); - if (ret) - return ret; - } - - return 0; -} - -static void env_fixup_fdt_addr(void) -{ -#ifdef ENV_MEM_LAYOUT_SETTINGS1 - char *addr_r; - - if (gd->ram_size <= SZ_128M) { - addr_r = env_get("fdt_addr1_r"); - if (addr_r) - env_set("fdt_addr_r", addr_r); - } -#endif -} - -int init_kernel_dtb(void) -{ - ulong fdt_addr; - void *ufdt_blob; - int ret; - - env_fixup_fdt_addr(); - - fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); - if (!fdt_addr) { - printf("No Found FDT Load Address.\n"); - return -1; - } - - ret = rockchip_read_dtb_file((void *)fdt_addr); - if (ret < 0) { - if (!fdt_check_header(gd->fdt_blob_kern)) { - fdt_addr = (ulong)memalign(ARCH_DMA_MINALIGN, - fdt_totalsize(gd->fdt_blob_kern)); - if (!fdt_addr) - return -ENOMEM; - - memcpy((void *)fdt_addr, gd->fdt_blob_kern, - fdt_totalsize(gd->fdt_blob_kern)); - printf("DTB: embedded kern.dtb\n"); - } else { - printf("Failed to get kernel dtb, ret=%d\n", ret); - return ret; - } - } - - ufdt_blob = (void *)gd->fdt_blob; - gd->fdt_blob = (void *)fdt_addr; - - hotkey_run(HK_FDT); - - /* - * There is a phandle miss match between U-Boot and kernel dtb node, - * we fixup it in U-Boot live dt nodes. - * - * CRU: all nodes. - * GPIO: key nodes. - */ - phandles_fixup_cru((void *)gd->fdt_blob); - phandles_fixup_gpio((void *)gd->fdt_blob, (void *)ufdt_blob); - - of_live_build((void *)gd->fdt_blob, (struct device_node **)&gd->of_root); - dm_scan_fdt((void *)gd->fdt_blob, false); - - /* - * There maybe something for the mmc devices to do after kernel dtb - * dm setup, eg: regain the clock device binding from kernel dtb. - */ - mmc_dm_reinit(); - - /* Reserve 'reserved-memory' */ - ret = boot_fdt_add_sysmem_rsv_regions((void *)gd->fdt_blob); - if (ret) - return ret; - - return 0; -} -#endif - static void early_download(void) { #if defined(CONFIG_PWRKEY_DNL_TRIGGER_NUM) && \ diff --git a/arch/arm/mach-rockchip/kernel_dtb.c b/arch/arm/mach-rockchip/kernel_dtb.c new file mode 100644 index 0000000000..445b7ee43c --- /dev/null +++ b/arch/arm/mach-rockchip/kernel_dtb.c @@ -0,0 +1,279 @@ +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* Here, only fixup cru phandle, pmucru is not included */ +static int phandles_fixup_cru(const void *fdt) +{ + const char *props[] = { "clocks", "assigned-clocks" }; + struct udevice *dev; + struct uclass *uc; + const char *comp; + u32 id, nclocks; + u32 *clocks; + int phandle, ncells; + int off, offset; + int ret, length; + int i, j; + int first_phandle = -1; + + phandle = -ENODATA; + ncells = -ENODATA; + + /* fdt points to kernel dtb, getting cru phandle and "#clock-cells" */ + for (offset = fdt_next_node(fdt, 0, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + comp = fdt_getprop(fdt, offset, "compatible", NULL); + if (!comp) + continue; + + /* Actually, this is not a good method to get cru node */ + off = strlen(comp) - strlen("-cru"); + if (off > 0 && !strncmp(comp + off, "-cru", 4)) { + phandle = fdt_get_phandle(fdt, offset); + ncells = fdtdec_get_int(fdt, offset, + "#clock-cells", -ENODATA); + break; + } + } + + if (phandle == -ENODATA || ncells == -ENODATA) + return 0; + + debug("%s: target cru: clock-cells:%d, phandle:0x%x\n", + __func__, ncells, fdt32_to_cpu(phandle)); + + /* Try to fixup all cru phandle from U-Boot dtb nodes */ + for (id = 0; id < UCLASS_COUNT; id++) { + ret = uclass_get(id, &uc); + if (ret) + continue; + + if (list_empty(&uc->dev_head)) + continue; + + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + /* Only U-Boot node go further */ + if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") && + !dev_read_bool(dev, "u-boot,dm-spl")) + continue; + + for (i = 0; i < ARRAY_SIZE(props); i++) { + if (!dev_read_prop(dev, props[i], &length)) + continue; + + clocks = malloc(length); + if (!clocks) + return -ENOMEM; + + /* Read "props[]" which contains cru phandle */ + nclocks = length / sizeof(u32); + if (dev_read_u32_array(dev, props[i], + clocks, nclocks)) { + free(clocks); + continue; + } + + /* Fixup with kernel cru phandle */ + for (j = 0; j < nclocks; j += (ncells + 1)) { + /* + * Check: update pmucru phandle with cru + * phandle by mistake. + */ + if (first_phandle == -1) + first_phandle = clocks[j]; + + if (clocks[j] != first_phandle) { + debug("WARN: %s: first cru phandle=%d, this=%d\n", + dev_read_name(dev), + first_phandle, clocks[j]); + continue; + } + + clocks[j] = phandle; + } + + /* + * Override live dt nodes but not fdt nodes, + * because all U-Boot nodes has been imported + * to live dt nodes, should use "dev_xxx()". + */ + dev_write_u32_array(dev, props[i], + clocks, nclocks); + free(clocks); + } + } + } + + return 0; +} + +static int phandles_fixup_gpio(const void *fdt, void *ufdt) +{ + struct udevice *dev; + struct uclass *uc; + const char *prop = "gpios"; + const char *comp; + char *gpio_name[10]; + int gpio_off[10]; + int pinctrl; + int offset; + int i = 0; + int n = 0; + + pinctrl = fdt_path_offset(fdt, "/pinctrl"); + if (pinctrl < 0) + return 0; + + memset(gpio_name, 0, sizeof(gpio_name)); + for (offset = fdt_first_subnode(fdt, pinctrl); + offset >= 0; + offset = fdt_next_subnode(fdt, offset)) { + /* assume the font nodes are gpio node */ + if (++i >= ARRAY_SIZE(gpio_name)) + break; + + comp = fdt_getprop(fdt, offset, "compatible", NULL); + if (!comp) + continue; + + if (!strcmp(comp, "rockchip,gpio-bank")) { + gpio_name[n] = (char *)fdt_get_name(fdt, offset, NULL); + gpio_off[n] = offset; + n++; + } + } + + if (!gpio_name[0]) + return 0; + + if (uclass_get(UCLASS_KEY, &uc) || list_empty(&uc->dev_head)) + return 0; + + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + u32 new_phd, phd_old; + char *name; + ofnode ofn; + + if (!dev_read_bool(dev, "u-boot,dm-pre-reloc") && + !dev_read_bool(dev, "u-boot,dm-spl")) + continue; + + if (dev_read_u32_array(dev, prop, &phd_old, 1)) + continue; + + ofn = ofnode_get_by_phandle(phd_old); + if (!ofnode_valid(ofn)) + continue; + + name = (char *)ofnode_get_name(ofn); + if (!name) + continue; + + for (i = 0; i < ARRAY_SIZE(gpio_name[i]); i++) { + if (gpio_name[i] && !strcmp(name, gpio_name[i])) { + new_phd = fdt_get_phandle(fdt, gpio_off[i]); + dev_write_u32_array(dev, prop, &new_phd, 1); + break; + } + } + } + + return 0; +} + +__weak int board_mmc_dm_reinit(struct udevice *dev) +{ + return 0; +} + +static int mmc_dm_reinit(void) +{ + struct udevice *dev; + struct uclass *uc; + int ret; + + if (uclass_get(UCLASS_MMC, &uc) || list_empty(&uc->dev_head)) + return 0; + + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + ret = board_mmc_dm_reinit(dev); + if (ret) + return ret; + } + + return 0; +} + +int init_kernel_dtb(void) +{ + ulong fdt_addr; + void *ufdt_blob; + int ret; + + fdt_addr = env_get_ulong("fdt_addr_r", 16, 0); + if (!fdt_addr) { + printf("No Found FDT Load Address.\n"); + return -1; + } + + ret = rockchip_read_dtb_file((void *)fdt_addr); + if (ret < 0) { + if (!fdt_check_header(gd->fdt_blob_kern)) { + fdt_addr = (ulong)memalign(ARCH_DMA_MINALIGN, + fdt_totalsize(gd->fdt_blob_kern)); + if (!fdt_addr) + return -ENOMEM; + + memcpy((void *)fdt_addr, gd->fdt_blob_kern, + fdt_totalsize(gd->fdt_blob_kern)); + printf("DTB: embedded kern.dtb\n"); + } else { + printf("Failed to get kernel dtb, ret=%d\n", ret); + return ret; + } + } + + ufdt_blob = (void *)gd->fdt_blob; + gd->fdt_blob = (void *)fdt_addr; + + hotkey_run(HK_FDT); + + /* + * There is a phandle miss match between U-Boot and kernel dtb node, + * we fixup it in U-Boot live dt nodes. + * + * CRU: all nodes. + * GPIO: key nodes. + */ + phandles_fixup_cru((void *)gd->fdt_blob); + phandles_fixup_gpio((void *)gd->fdt_blob, (void *)ufdt_blob); + + of_live_build((void *)gd->fdt_blob, (struct device_node **)&gd->of_root); + dm_scan_fdt((void *)gd->fdt_blob, false); + + /* + * There maybe something for the mmc devices to do after kernel dtb + * dm setup, eg: regain the clock device binding from kernel dtb. + */ + mmc_dm_reinit(); + + /* Reserve 'reserved-memory' */ + ret = boot_fdt_add_sysmem_rsv_regions((void *)gd->fdt_blob); + if (ret) + return ret; + + return 0; +} diff --git a/include/boot_rkimg.h b/include/boot_rkimg.h index 62040e75a4..db826e7357 100644 --- a/include/boot_rkimg.h +++ b/include/boot_rkimg.h @@ -62,5 +62,6 @@ void board_run_recovery_wipe_data(void); void setup_download_mode(void); int rockchip_get_boot_mode(void); int rockchip_read_dtb_file(void *fdt_addr); +int init_kernel_dtb(void); #endif