From d255fade66414271950ab605098439591a67f1ed Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Fri, 9 Feb 2018 10:56:23 +0800 Subject: [PATCH 1/9] core: add uclass_get_device_by_phandle_id() api Add api for who can not get phandle from a device property. Signed-off-by: Kever Yang Reviewed-by: Philipp Tomsich --- drivers/core/uclass.c | 26 ++++++++++++++++++++++++++ include/dm/uclass.h | 16 ++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 1aedaa08f0..628e2e13ff 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -457,6 +457,32 @@ int uclass_get_device_by_ofnode(enum uclass_id id, ofnode node, } #if CONFIG_IS_ENABLED(OF_CONTROL) +int uclass_get_device_by_phandle_id(enum uclass_id id, uint phandle_id, + struct udevice **devp) +{ + struct udevice *dev; + struct uclass *uc; + int ret; + + *devp = NULL; + ret = uclass_get(id, &uc); + if (ret) + return ret; + + list_for_each_entry(dev, &uc->dev_head, uclass_node) { + uint phandle; + + phandle = dev_read_phandle(dev); + + if (phandle == phandle_id) { + *devp = dev; + return uclass_get_device_tail(dev, ret, devp); + } + } + + return -ENODEV; +} + int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent, const char *name, struct udevice **devp) { diff --git a/include/dm/uclass.h b/include/dm/uclass.h index 3a01abc239..a5bf3eb831 100644 --- a/include/dm/uclass.h +++ b/include/dm/uclass.h @@ -210,6 +210,22 @@ int uclass_get_device_by_of_offset(enum uclass_id id, int node, int uclass_get_device_by_ofnode(enum uclass_id id, ofnode node, struct udevice **devp); +/** + * uclass_get_device_by_phandle_id() - Get a uclass device by phandle id + * + * This searches the devices in the uclass for one with the given phandle id. + * + * The device is probed to activate it ready for use. + * + * @id: uclass ID to look up + * @phandle_id: the phandle id to look up + * @devp: Returns pointer to device (there is only one for each node) + * @return 0 if OK, -ENODEV if there is no device match the phandle, other + * -ve on error + */ +int uclass_get_device_by_phandle_id(enum uclass_id id, uint phandle_id, + struct udevice **devp); + /** * uclass_get_device_by_phandle() - Get a uclass device by phandle * From 1e656ad08c92c7b9db86bcc16eeb64fe5679f7c9 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Fri, 9 Feb 2018 10:56:24 +0800 Subject: [PATCH 2/9] pinctrl-uclass: convert to use live dt Use live dt interface for pinctrl_select_state_full() Signed-off-by: Kever Yang Reviewed-by: Philipp Tomsich --- drivers/pinctrl/pinctrl-uclass.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/pinctrl/pinctrl-uclass.c b/drivers/pinctrl/pinctrl-uclass.c index 6a73a0679b..a0a326a142 100644 --- a/drivers/pinctrl/pinctrl-uclass.c +++ b/drivers/pinctrl/pinctrl-uclass.c @@ -12,6 +12,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -63,16 +64,13 @@ static int pinctrl_config_one(struct udevice *config) */ static int pinctrl_select_state_full(struct udevice *dev, const char *statename) { - const void *fdt = gd->fdt_blob; - int node = dev_of_offset(dev); char propname[32]; /* long enough */ const fdt32_t *list; uint32_t phandle; - int config_node; struct udevice *config; int state, size, i, ret; - state = fdt_stringlist_search(fdt, node, "pinctrl-names", statename); + state = dev_read_stringlist_search(dev, "pinctrl-names", statename); if (state < 0) { char *end; /* @@ -85,22 +83,15 @@ static int pinctrl_select_state_full(struct udevice *dev, const char *statename) } snprintf(propname, sizeof(propname), "pinctrl-%d", state); - list = fdt_getprop(fdt, node, propname, &size); + list = dev_read_prop(dev, propname, &size); if (!list) return -EINVAL; size /= sizeof(*list); for (i = 0; i < size; i++) { phandle = fdt32_to_cpu(*list++); - - config_node = fdt_node_offset_by_phandle(fdt, phandle); - if (config_node < 0) { - dev_err(dev, "prop %s index %d invalid phandle\n", - propname, i); - return -EINVAL; - } - ret = uclass_get_device_by_of_offset(UCLASS_PINCONFIG, - config_node, &config); + ret = uclass_get_device_by_phandle_id(UCLASS_PINCONFIG, phandle, + &config); if (ret) return ret; From 33222c8a2cef36d0651d85100d9e0eadbe73884c Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Thu, 15 Feb 2018 07:40:10 +0100 Subject: [PATCH 3/9] cmd: cbfs: fix reading the end_of_rom pointer for 64bit archs The cast breaks the pointer on 64bit archs, so lets get rid of it. Signed-off-by: Andre Heider Reviewed-by: Alexander Graf --- cmd/cbfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cbfs.c b/cmd/cbfs.c index 799ba01fcc..736f8c4527 100644 --- a/cmd/cbfs.c +++ b/cmd/cbfs.c @@ -22,7 +22,7 @@ static int do_cbfs_init(cmd_tbl_t *cmdtp, int flag, int argc, return 0; } if (argc == 2) { - end_of_rom = (int)simple_strtoul(argv[1], &ep, 16); + end_of_rom = simple_strtoul(argv[1], &ep, 16); if (*ep) { puts("\n** Invalid end of ROM **\n"); return 1; From 44683170f818ecaf914ea4c77d35021f60e38b04 Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Thu, 15 Feb 2018 07:40:11 +0100 Subject: [PATCH 4/9] fs: cbfs: fix locating the cbfs header The value at the end of the rom is not a pointer, it is an offset relative to the end of rom. Signed-off-by: Andre Heider --- fs/cbfs/cbfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/cbfs/cbfs.c b/fs/cbfs/cbfs.c index 6e1107d751..46da8f134f 100644 --- a/fs/cbfs/cbfs.c +++ b/fs/cbfs/cbfs.c @@ -168,9 +168,9 @@ static int file_cbfs_load_header(uintptr_t end_of_rom, struct cbfs_header *header) { struct cbfs_header *header_in_rom; + int32_t offset = *(u32 *)(end_of_rom - 3); - header_in_rom = (struct cbfs_header *)(uintptr_t) - *(u32 *)(end_of_rom - 3); + header_in_rom = (struct cbfs_header *)(end_of_rom + offset + 1); swap_header(header, header_in_rom); if (header->magic != good_magic || header->offset > From bcfdf055f8956b784085bafa14f1731cc141c414 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 1 Mar 2018 14:08:15 +0800 Subject: [PATCH 5/9] dm: core: make fixed-clock dt scan live dt compatible dm_scan_fdt_node can't work when live dt is active, we should use dm_scan_fdt_live instead. Signed-off-by: Andy Yan Reviewed-by: Simon Glass --- drivers/core/root.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/core/root.c b/drivers/core/root.c index 3a426ab4b7..9000ed55ca 100644 --- a/drivers/core/root.c +++ b/drivers/core/root.c @@ -333,7 +333,8 @@ static int dm_scan_fdt_node(struct udevice *parent, const void *blob, int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only) { - int node, ret; + int ret; + ofnode node; ret = dm_scan_fdt(gd->fdt_blob, pre_reloc_only); if (ret) { @@ -342,13 +343,18 @@ int dm_extended_scan_fdt(const void *blob, bool pre_reloc_only) } /* bind fixed-clock */ - node = ofnode_to_offset(ofnode_path("/clocks")); + node = ofnode_path("/clocks"); /* if no DT "clocks" node, no need to go further */ - if (node < 0) + if (!ofnode_valid(node)) return ret; - ret = dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node, - pre_reloc_only); +#if CONFIG_IS_ENABLED(OF_LIVE) + if (of_live_active()) + ret = dm_scan_fdt_live(gd->dm_root, node.np, pre_reloc_only); + else +#endif + ret = dm_scan_fdt_node(gd->dm_root, gd->fdt_blob, node.of_offset, + pre_reloc_only); if (ret) debug("dm_scan_fdt_node() failed: %d\n", ret); From e8d5291824e27575fe71222f683579325221e0cb Mon Sep 17 00:00:00 2001 From: Mario Six Date: Mon, 12 Mar 2018 14:53:33 +0100 Subject: [PATCH 6/9] core: ofnode: Fix translation for #size-cells == 0 Commit 286ede6 ("drivers: core: Add translation in live tree case") made dev_get_addr always use proper bus translations for addresses read from the device tree. But this leads to problems with certain busses, e.g. I2C busses, which run into an error during translation, and hence stop working. It turns out that of_translate_address() and fdt_translate_address() stop the address translation with an error when they're asked to translate addresses for busses where #size-cells == 0 (comment from drivers/core/of_addr.c): * Note: We consider that crossing any level with #size-cells == 0 to mean * that translation is impossible (that is we are not dealing with a value * that can be mapped to a cpu physical address). This is not really specified * that way, but this is traditionally the way IBM at least do things To fix this case, we check in both the live-tree and non-live tree-case, whether the bus of the device whose address is about to be translated has size-cell size zero. If this is the case, we just read the address as a plain integer and return it, and only apply bus translations if the size-cell size if greater than zero. Signed-off-by: Mario Six Signed-off-by: Martin Fuzzey Reported-by: Martin Fuzzey Fixes: 286ede6 ("drivers: core: Add translation in live tree case") Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 48 +++++++++++++++++++++++++++++++++++++++ drivers/core/fdtaddr.c | 17 +++++++++----- drivers/core/ofnode.c | 5 +++- include/dm/uclass-id.h | 1 + test/dm/test-fdt.c | 43 +++++++++++++++++++++++++++++++++++ 5 files changed, 107 insertions(+), 7 deletions(-) diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index b0f0ca8f19..06d0e8ce85 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -27,6 +27,10 @@ testfdt3 = "/b-test"; testfdt5 = "/some-bus/c-test@5"; testfdt8 = "/a-test"; + fdt_dummy0 = "/translation-test@8000/dev@0,0"; + fdt_dummy1 = "/translation-test@8000/dev@1,100"; + fdt_dummy2 = "/translation-test@8000/dev@2,200"; + fdt_dummy3 = "/translation-test@8000/noxlatebus@3,300/dev@42"; usb0 = &usb_0; usb1 = &usb_1; usb2 = &usb_2; @@ -487,6 +491,50 @@ reg = <9 1>; }; }; + + translation-test@8000 { + compatible = "simple-bus"; + reg = <0x8000 0x4000>; + + #address-cells = <0x2>; + #size-cells = <0x1>; + + ranges = <0 0x0 0x8000 0x1000 + 1 0x100 0x9000 0x1000 + 2 0x200 0xA000 0x1000 + 3 0x300 0xB000 0x1000 + >; + + dev@0,0 { + compatible = "denx,u-boot-fdt-dummy"; + reg = <0 0x0 0x1000>; + }; + + dev@1,100 { + compatible = "denx,u-boot-fdt-dummy"; + reg = <1 0x100 0x1000>; + + }; + + dev@2,200 { + compatible = "denx,u-boot-fdt-dummy"; + reg = <2 0x200 0x1000>; + }; + + + noxlatebus@3,300 { + compatible = "simple-bus"; + reg = <3 0x300 0x1000>; + + #address-cells = <0x1>; + #size-cells = <0x0>; + + dev@42 { + compatible = "denx,u-boot-fdt-dummy"; + reg = <0x42>; + }; + }; + }; }; #include "sandbox_pmic.dtsi" diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index 3847dd836e..9a3b4c312a 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -49,12 +49,17 @@ fdt_addr_t devfdt_get_addr_index(struct udevice *dev, int index) reg += index * (na + ns); - /* - * Use the full-fledged translate function for complex - * bus setups. - */ - addr = fdt_translate_address((void *)gd->fdt_blob, - dev_of_offset(dev), reg); + if (ns) { + /* + * Use the full-fledged translate function for complex + * bus setups. + */ + addr = fdt_translate_address((void *)gd->fdt_blob, + dev_of_offset(dev), reg); + } else { + /* Non translatable if #size-cells == 0 */ + addr = fdt_read_number(reg, na); + } } else { /* * Use the "simple" translate function for less complex diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 4e4532651f..5909a25f85 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -227,13 +227,16 @@ fdt_addr_t ofnode_get_addr_index(ofnode node, int index) uint flags; u64 size; int na; + int ns; prop_val = of_get_address(ofnode_to_np(node), index, &size, &flags); if (!prop_val) return FDT_ADDR_T_NONE; - if (IS_ENABLED(CONFIG_OF_TRANSLATE)) { + ns = of_n_size_cells(ofnode_to_np(node)); + + if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) { return of_translate_address(ofnode_to_np(node), prop_val); } else { na = of_n_addr_cells(ofnode_to_np(node)); diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 07fabc3ce6..d28fb3e23f 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -19,6 +19,7 @@ enum uclass_id { UCLASS_TEST_FDT, UCLASS_TEST_BUS, UCLASS_TEST_PROBE, + UCLASS_TEST_DUMMY, UCLASS_SPI_EMUL, /* sandbox SPI device emulator */ UCLASS_I2C_EMUL, /* sandbox I2C device emulator */ UCLASS_PCI_EMUL, /* sandbox PCI device emulator */ diff --git a/test/dm/test-fdt.c b/test/dm/test-fdt.c index 920ccbf016..0d11bfdb2f 100644 --- a/test/dm/test-fdt.c +++ b/test/dm/test-fdt.c @@ -419,3 +419,46 @@ static int dm_test_first_next_ok_device(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_first_next_ok_device, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +static const struct udevice_id fdt_dummy_ids[] = { + { .compatible = "denx,u-boot-fdt-dummy", }, + { } +}; + +UCLASS_DRIVER(fdt_dummy) = { + .name = "fdt_dummy", + .id = UCLASS_TEST_DUMMY, + .flags = DM_UC_FLAG_SEQ_ALIAS, +}; + +U_BOOT_DRIVER(fdt_dummy_drv) = { + .name = "fdt_dummy_drv", + .of_match = fdt_dummy_ids, + .id = UCLASS_TEST_DUMMY, +}; + +static int dm_test_fdt_translation(struct unit_test_state *uts) +{ + struct udevice *dev; + + /* Some simple translations */ + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 0, true, &dev)); + ut_asserteq_str("dev@0,0", dev->name); + ut_asserteq(0x8000, dev_read_addr(dev)); + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 1, true, &dev)); + ut_asserteq_str("dev@1,100", dev->name); + ut_asserteq(0x9000, dev_read_addr(dev)); + + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 2, true, &dev)); + ut_asserteq_str("dev@2,200", dev->name); + ut_asserteq(0xA000, dev_read_addr(dev)); + + /* No translation for busses with #size-cells == 0 */ + ut_assertok(uclass_find_device_by_seq(UCLASS_TEST_DUMMY, 3, true, &dev)); + ut_asserteq_str("dev@42", dev->name); + ut_asserteq(0x42, dev_read_addr(dev)); + + return 0; +} +DM_TEST(dm_test_fdt_translation, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); From c960a68e200057b0e8b3aa627aa4b0c9b31ca2d8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 21 Mar 2018 18:03:33 +0900 Subject: [PATCH 7/9] libfdt: move FDT_RAMDISK_OVERHEAD to image-fdt.c This macro is locally referenced in common/image-fdt.c Signed-off-by: Masahiro Yamada Reviewed-by: Simon Glass --- common/image-fdt.c | 3 +++ include/linux/libfdt.h | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/image-fdt.c b/common/image-fdt.c index 25103ba3b5..3dc02a1219 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -21,6 +21,9 @@ #define CONFIG_SYS_FDT_PAD 0x3000 #endif +/* adding a ramdisk needs 0x44 bytes in version 2008.10 */ +#define FDT_RAMDISK_OVERHEAD 0x80 + DECLARE_GLOBAL_DATA_PTR; static void fdt_error(const char *msg) diff --git a/include/linux/libfdt.h b/include/linux/libfdt.h index 9e6eeadc40..eeb2344971 100644 --- a/include/linux/libfdt.h +++ b/include/linux/libfdt.h @@ -309,7 +309,4 @@ int fdt_add_alias_regions(const void *fdt, struct fdt_region *region, int count, extern struct fdt_header *working_fdt; /* Pointer to the working fdt */ -/* adding a ramdisk needs 0x44 bytes in version 2008.10 */ -#define FDT_RAMDISK_OVERHEAD 0x80 - #endif /* _INCLUDE_LIBFDT_H_ */ From 414e2dbbf2725f6d7e929e3b4957b38ee46535c2 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 21 Mar 2018 18:03:34 +0900 Subject: [PATCH 8/9] fdt_region: remove unneeded fdt_internal.h inclusion fdt_region.c does not depend on anything in libfdt_internal.h Signed-off-by: Masahiro Yamada Reviewed-by: Simon Glass --- lib/libfdt/fdt_region.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/libfdt/fdt_region.c b/lib/libfdt/fdt_region.c index 70914a4e9b..054c4b302f 100644 --- a/lib/libfdt/fdt_region.c +++ b/lib/libfdt/fdt_region.c @@ -14,8 +14,6 @@ #include "fdt_host.h" #endif -#include "libfdt_internal.h" - #define FDT_MAX_DEPTH 32 static int str_in_list(const char *str, char * const list[], int count) From 641599a63df258c3e3cb259c75cdada0cc009d56 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 21 Mar 2018 18:03:35 +0900 Subject: [PATCH 9/9] image.h: add forward declaration of struct fdt_region This header needs to know 'fdt_region' is a struct for the fit_region_make_list() prototype. Signed-off-by: Masahiro Yamada Reviewed-by: Simon Glass --- include/image.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/image.h b/include/image.h index 621abf647f..a6f82aebfe 100644 --- a/include/image.h +++ b/include/image.h @@ -21,6 +21,7 @@ /* Define this to avoid #ifdefs later on */ struct lmb; +struct fdt_region; #ifdef USE_HOSTCC #include