From 91a8c95623af3aad1c9579f6ae9eff274d4c1b0a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 11 Oct 2019 16:16:46 -0600 Subject: [PATCH 01/18] sandbox: test: Show hex values on failure Quite a few tests use addresses or hex values for comparisons. Add hex output for test failures, e.g.: 0x55ca22fa == reg: Expected 0x55ca22fa (1439310586), got 0x55ea22fb (1441407739) Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- include/test/ut.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/test/ut.h b/include/test/ut.h index 19bcb8c3748..fbfde10719f 100644 --- a/include/test/ut.h +++ b/include/test/ut.h @@ -61,7 +61,8 @@ void ut_failf(struct unit_test_state *uts, const char *fname, int line, if (val1 != val2) { \ ut_failf(uts, __FILE__, __LINE__, __func__, \ #expr1 " == " #expr2, \ - "Expected %d, got %d", val1, val2); \ + "Expected %#x (%d), got %#x (%d)", val1, val1, \ + val2, val2); \ return CMD_RET_FAILURE; \ } \ } From 8417385dc911f9ad049ae610b4e23557e890b353 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 11 Oct 2019 16:16:47 -0600 Subject: [PATCH 02/18] sandbox: Drop 'const' from sandbox_write() This function writes to its address so the address should not be declared as const. Fix it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/sandbox/cpu/cpu.c | 3 +-- arch/sandbox/include/asm/io.h | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index 2046cb53c4a..f3af88d79e9 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c @@ -246,8 +246,7 @@ unsigned int sandbox_read(const void *addr, enum sandboxio_size_t size) return 0; } -void sandbox_write(const void *addr, unsigned int val, - enum sandboxio_size_t size) +void sandbox_write(void *addr, unsigned int val, enum sandboxio_size_t size) { struct sandbox_state *state = state_get_current(); diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h index 4a35c419723..ad6c29a4e26 100644 --- a/arch/sandbox/include/asm/io.h +++ b/arch/sandbox/include/asm/io.h @@ -46,8 +46,7 @@ static inline void unmap_sysmem(const void *vaddr) phys_addr_t map_to_sysmem(const void *ptr); unsigned int sandbox_read(const void *addr, enum sandboxio_size_t size); -void sandbox_write(const void *addr, unsigned int val, - enum sandboxio_size_t size); +void sandbox_write(void *addr, unsigned int val, enum sandboxio_size_t size); #define readb(addr) sandbox_read((const void *)addr, SB_SIZE_8) #define readw(addr) sandbox_read((const void *)addr, SB_SIZE_16) @@ -55,11 +54,11 @@ void sandbox_write(const void *addr, unsigned int val, #ifdef CONFIG_SANDBOX64 #define readq(addr) sandbox_read((const void *)addr, SB_SIZE_64) #endif -#define writeb(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_8) -#define writew(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_16) -#define writel(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_32) +#define writeb(v, addr) sandbox_write((void *)addr, v, SB_SIZE_8) +#define writew(v, addr) sandbox_write((void *)addr, v, SB_SIZE_16) +#define writel(v, addr) sandbox_write((void *)addr, v, SB_SIZE_32) #ifdef CONFIG_SANDBOX64 -#define writeq(v, addr) sandbox_write((const void *)addr, v, SB_SIZE_64) +#define writeq(v, addr) sandbox_write((void *)addr, v, SB_SIZE_64) #endif /* From 619025b8d68b346442430b8a412852b63960bedb Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 11 Oct 2019 16:16:48 -0600 Subject: [PATCH 03/18] sandbox: test: Add a prototype for sandbox_set_enable_memio() This function needs a prototype so that tests can use it. Add one. Signed-off-by: Simon Glass Reviewed-by: Bin Meng --- arch/sandbox/include/asm/test.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/sandbox/include/asm/test.h b/arch/sandbox/include/asm/test.h index cd2b9e3155d..b885e1a14f1 100644 --- a/arch/sandbox/include/asm/test.h +++ b/arch/sandbox/include/asm/test.h @@ -213,4 +213,15 @@ int sandbox_get_pci_ep_irq_count(struct udevice *dev); */ uint sandbox_pci_read_bar(u32 barval, int type, uint size); +/** + * sandbox_set_enable_memio() - Enable readl/writel() for sandbox + * + * Normally these I/O functions do nothing with sandbox. Certain tests need them + * to work as for other architectures, so this function can be used to enable + * them. + * + * @enable: true to enable, false to disable + */ +void sandbox_set_enable_memio(bool enable); + #endif From 5ca5ec1e3272f40a7ad26a15e3df3bb18e0b11d8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Fri, 11 Oct 2019 16:16:49 -0600 Subject: [PATCH 04/18] dm: regmap: Fix mask in regmap_update_bits() This function assumes that the 'val' parameter has no masked bits set. This is not defined by the function prototype though. Fix the function to mask the value and update the documentation. Signed-off-by: Simon Glass Reviewed-by: Bin Meng Reviewed-by: Jean-Jacques Hiblot --- drivers/core/regmap.c | 2 +- include/regmap.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/core/regmap.c b/drivers/core/regmap.c index d1d12eef385..e9e55c9d165 100644 --- a/drivers/core/regmap.c +++ b/drivers/core/regmap.c @@ -462,5 +462,5 @@ int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val) reg &= ~mask; - return regmap_write(map, offset, reg | val); + return regmap_write(map, offset, reg | (val & mask)); } diff --git a/include/regmap.h b/include/regmap.h index 0854200a9c1..9ada1af5ef0 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -295,7 +295,8 @@ int regmap_raw_read_range(struct regmap *map, uint range_num, uint offset, * @map: The map returned by regmap_init_mem*() * @offset: Offset of the memory * @mask: Mask to apply to the read value - * @val: Value to apply to the value to write + * @val: Value to OR with the read value after masking. Note that any + * bits set in @val which are not set in @mask are ignored * Return: 0 if OK, -ve on error */ int regmap_update_bits(struct regmap *map, uint offset, uint mask, uint val); From 2333dc47b891d169f97b57b0f687a5843acc7d8c Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Fri, 11 Oct 2019 16:16:50 -0600 Subject: [PATCH 05/18] test: regmap: check the values read from the regmap The test did reads after writes but didn't check the value. It probably was because the sandbox didn't implement the writeX/readX functions. Signed-off-by: Jean-Jacques Hiblot Updated to use sandbox_set_enable_memio(): Signed-off-by: Simon Glass Reviewed-by: Bin Meng Tested-by: Bin Meng --- test/dm/regmap.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/test/dm/regmap.c b/test/dm/regmap.c index 82de295cb8f..6fd1f20656b 100644 --- a/test/dm/regmap.c +++ b/test/dm/regmap.c @@ -99,18 +99,27 @@ static int dm_test_regmap_rw(struct unit_test_state *uts) struct regmap *map; uint reg; + sandbox_set_enable_memio(true); ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); map = syscon_get_regmap(dev); ut_assertok_ptr(map); ut_assertok(regmap_write(map, 0, 0xcacafafa)); - ut_assertok(regmap_write(map, 3, 0x55aa2211)); + ut_assertok(regmap_write(map, 5, 0x55aa2211)); ut_assertok(regmap_read(map, 0, ®)); - ut_assertok(regmap_read(map, 3, ®)); + ut_asserteq(0xcacafafa, reg); + ut_assertok(regmap_read(map, 5, ®)); + ut_asserteq(0x55aa2211, reg); + ut_assertok(regmap_read(map, 0, ®)); + ut_asserteq(0xcacafafa, reg); ut_assertok(regmap_update_bits(map, 0, 0xff00ff00, 0x55aa2211)); - ut_assertok(regmap_update_bits(map, 3, 0x00ff00ff, 0xcacafada)); + ut_assertok(regmap_read(map, 0, ®)); + ut_asserteq(0x55ca22fa, reg); + ut_assertok(regmap_update_bits(map, 5, 0x00ff00ff, 0xcacafada)); + ut_assertok(regmap_read(map, 5, ®)); + ut_asserteq(0x55ca22da, reg); return 0; } @@ -130,6 +139,7 @@ static int dm_test_regmap_getset(struct unit_test_state *uts) u32 val3; }; + sandbox_set_enable_memio(true); ut_assertok(uclass_get_device(UCLASS_SYSCON, 0, &dev)); map = syscon_get_regmap(dev); ut_assertok_ptr(map); @@ -138,7 +148,9 @@ static int dm_test_regmap_getset(struct unit_test_state *uts) regmap_set(map, struct layout, val3, 0x55aa2211); ut_assertok(regmap_get(map, struct layout, val0, ®)); + ut_asserteq(0xcacafafa, reg); ut_assertok(regmap_get(map, struct layout, val3, ®)); + ut_asserteq(0x55aa2211, reg); return 0; } @@ -159,6 +171,7 @@ static int dm_test_regmap_poll(struct unit_test_state *uts) start = get_timer(0); + ut_assertok(regmap_write(map, 0, 0x0)); ut_asserteq(-ETIMEDOUT, regmap_read_poll_timeout_test(map, 0, reg, (reg == 0xcacafafa), From 1c1c8a3a990742a73a75b091c35213b0a50f0c45 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:43 -0600 Subject: [PATCH 06/18] tiny-printf: Reduce size by removing ctype The ctype array is brought into the image, adding 256 bytes, when it is unlikely to be needed. The extra code for %p is only present when DEBUG is defined, so let's drop ctype as well unless DEBUG is defined. Signed-off-by: Simon Glass --- lib/tiny-printf.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index ebef92fc9f6..632b4249142 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -289,8 +289,15 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) break; case 'p': pointer(info, fmt, va_arg(va, void *)); + /* + * Skip this because it pulls in _ctype which is + * 256 bytes, and we don't generally implement + * pointer anyway + */ +#ifdef DEBUG while (isalnum(fmt[0])) fmt++; +#endif break; case '%': out(info, '%'); From dee74e6cc4a94da19b99309ad1c99eb5bddfe217 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:44 -0600 Subject: [PATCH 07/18] tiny-printf: Add print_grouped_ull() This function is used in the bootstage report which may be trigged in TPL or TPL. Add a very basic implication of this function so that it builds. There is no attempt to get the formatting right, since this would add too much code size. Signed-off-by: Simon Glass Reviewed-by: Stefan Roese --- lib/tiny-printf.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index 632b4249142..d46d206873f 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -389,3 +389,9 @@ int snprintf(char *buf, size_t size, const char *fmt, ...) return ret; } + +void print_grouped_ull(unsigned long long int_val, int digits) +{ + /* Don't try to print the upper 32-bits */ + printf("%ld ", (ulong)int_val); +} From 831c1611195961bf79ac55a8deaac9034112ef5f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:45 -0600 Subject: [PATCH 08/18] tiny-printf: Reorder code to support %p With a bit of code reordering we can support %p using the existing code for ulong. Move the %p code up and adjust the logic accordingly. Signed-off-by: Simon Glass --- lib/tiny-printf.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/lib/tiny-printf.c b/lib/tiny-printf.c index d46d206873f..4f7fc239ae9 100644 --- a/lib/tiny-printf.c +++ b/lib/tiny-printf.c @@ -157,7 +157,8 @@ static void ip4_addr_string(struct printf_info *info, u8 *addr) * decimal). */ -static void pointer(struct printf_info *info, const char *fmt, void *ptr) +static void __maybe_unused pointer(struct printf_info *info, const char *fmt, + void *ptr) { #ifdef DEBUG unsigned long num = (uintptr_t)ptr; @@ -266,6 +267,21 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) div_out(info, &num, div); } break; + case 'p': +#ifdef DEBUG + pointer(info, fmt, va_arg(va, void *)); + /* + * Skip this because it pulls in _ctype which is + * 256 bytes, and we don't generally implement + * pointer anyway + */ + while (isalnum(fmt[0])) + fmt++; + break; +#else + islong = true; + /* no break */ +#endif case 'x': if (islong) { num = va_arg(va, unsigned long); @@ -287,18 +303,6 @@ static int _vprintf(struct printf_info *info, const char *fmt, va_list va) case 's': p = va_arg(va, char*); break; - case 'p': - pointer(info, fmt, va_arg(va, void *)); - /* - * Skip this because it pulls in _ctype which is - * 256 bytes, and we don't generally implement - * pointer anyway - */ -#ifdef DEBUG - while (isalnum(fmt[0])) - fmt++; -#endif - break; case '%': out(info, '%'); default: From 5074a8a3c0d0d1e11a1d51a7fb0ce8746668046f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:46 -0600 Subject: [PATCH 09/18] bloblist: Reserve an aligned base Make sure that the bloblist starts on an aligned boundary. This protects against one of the early allocating causing the alignment to be lost. Signed-off-by: Simon Glass --- common/board_f.c | 1 + 1 file changed, 1 insertion(+) diff --git a/common/board_f.c b/common/board_f.c index 591f18f391e..4852a3b0d84 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -588,6 +588,7 @@ static int reserve_stacks(void) static int reserve_bloblist(void) { #ifdef CONFIG_BLOBLIST + gd->start_addr_sp &= ~0xf; gd->start_addr_sp -= CONFIG_BLOBLIST_SIZE; gd->new_bloblist = map_sysmem(gd->start_addr_sp, CONFIG_BLOBLIST_SIZE); #endif From 53a4f253f129926bb5398634c8bae43ab788342d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:47 -0600 Subject: [PATCH 10/18] bootstage: Store the next ID in the stash When stashing bootstage info, store the next ID so that it can be used when the stash is restored. This avoids the ID starting at zero and potentially overwriting existing entries. Signed-off-by: Simon Glass --- common/bootstage.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/common/bootstage.c b/common/bootstage.c index 56ef91ad859..257dc5d402f 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -41,10 +41,11 @@ enum { }; struct bootstage_hdr { - uint32_t version; /* BOOTSTAGE_VERSION */ - uint32_t count; /* Number of records */ - uint32_t size; /* Total data size (non-zero if valid) */ - uint32_t magic; /* Unused */ + u32 version; /* BOOTSTAGE_VERSION */ + u32 count; /* Number of records */ + u32 size; /* Total data size (non-zero if valid) */ + u32 magic; /* Magic number */ + u32 next_id; /* Next ID to use for bootstage */ }; int bootstage_relocate(void) @@ -392,6 +393,7 @@ int bootstage_stash(void *base, int size) hdr->count = count; hdr->size = 0; hdr->magic = BOOTSTAGE_MAGIC; + hdr->next_id = data->next_id; ptr += sizeof(*hdr); /* Write the records, silently stopping when we run out of space */ @@ -485,6 +487,7 @@ int bootstage_unstash(const void *base, int size) /* Mark the records as read */ data->rec_count += hdr->count; + data->next_id = hdr->next_id; debug("Unstashed %d records\n", hdr->count); return 0; From ed54bdaf88758854905b5d8ca5036a078b9ef168 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:48 -0600 Subject: [PATCH 11/18] bootstage: Fix counting of entries in stash The current code searches for empty records but these not existing with bootstage now. This used to be needed when bootstage records were stored in a spare array. Drop the unnecessary code and fix a code-style nit at the same time. Signed-off-by: Simon Glass --- common/bootstage.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/common/bootstage.c b/common/bootstage.c index 257dc5d402f..fe36bac0474 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -373,7 +373,6 @@ int bootstage_stash(void *base, int size) const struct bootstage_record *rec; char buf[20]; char *ptr = base, *end = ptr + size; - uint32_t count; int i; if (hdr + 1 > (struct bootstage_hdr *)end) { @@ -384,22 +383,15 @@ int bootstage_stash(void *base, int size) /* Write an arbitrary version number */ hdr->version = BOOTSTAGE_VERSION; - /* Count the number of records, and write that value first */ - for (rec = data->record, i = count = 0; i < data->rec_count; - i++, rec++) { - if (rec->id != 0) - count++; - } - hdr->count = count; + hdr->count = data->rec_count; hdr->size = 0; hdr->magic = BOOTSTAGE_MAGIC; hdr->next_id = data->next_id; ptr += sizeof(*hdr); /* Write the records, silently stopping when we run out of space */ - for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) { + for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) append_data(&ptr, end, rec, sizeof(*rec)); - } /* Write the name strings */ for (rec = data->record, i = 0; i < data->rec_count; i++, rec++) { From 65b2d96f4c5e3f9084bc04cf5a5d7fc7a2285a72 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:49 -0600 Subject: [PATCH 12/18] bootstage: Avoid conflicts between stash/unstash At present there is a single shared address for bootstage data in both TPL and SPL. If SPL unstashs TPL bootstage info and then stashes it again to pass it to U-Boot, the new stash overwrites the strings of the old stash. Fix this by duplicating the strings into the malloc() region. This should be a small code. Fix the header-file order at the same time. This problem doesn't happen at the next stage (SPL->U-Boot) since U-Boot relocates the boostage data. Signed-off-by: Simon Glass --- common/bootstage.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/common/bootstage.c b/common/bootstage.c index fe36bac0474..4557ed4508c 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -10,9 +10,10 @@ */ #include -#include #include +#include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -472,6 +473,8 @@ int bootstage_unstash(const void *base, int size) for (rec = data->record + data->next_id, i = 0; i < hdr->count; i++, rec++) { rec->name = ptr; + if (spl_phase() == PHASE_SPL) + rec->name = strdup(ptr); /* Assume no data corruption here */ ptr += strlen(ptr) + 1; From ac9cd4805c8b11f529b508921c2275b889265313 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:50 -0600 Subject: [PATCH 13/18] bootstage: Correct relocation algorithm At present bootstage relocation assumes that it is possible to point back to memory available before relocation, so it does not relocate the strings. However this is not the case on some platforms, such as x86 which uses the cache as RAM and loses access to this when the cache is enabled. Move the relocation step to before U-Boot relocates, expand the allocated region to include space for the strings and relocate the strings at the same time as the bootstage records. This ensures that bootstage data can remain accessible from TPL through SPL to U-Boot before/after relocation. Signed-off-by: Simon Glass --- common/board_f.c | 1 + common/board_r.c | 1 - common/bootstage.c | 25 ++++++++++++++++++++++--- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/common/board_f.c b/common/board_f.c index 4852a3b0d84..e3591cbaebd 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -696,6 +696,7 @@ static int reloc_bootstage(void) gd->bootstage, gd->new_bootstage, size); memcpy(gd->new_bootstage, gd->bootstage, size); gd->bootstage = gd->new_bootstage; + bootstage_relocate(); } #endif diff --git a/common/board_r.c b/common/board_r.c index d6fb5047a26..c1ecb06b743 100644 --- a/common/board_r.c +++ b/common/board_r.c @@ -670,7 +670,6 @@ static init_fnc_t init_sequence_r[] = { #ifdef CONFIG_SYS_NONCACHED_MEMORY initr_noncached, #endif - bootstage_relocate, #ifdef CONFIG_OF_LIVE initr_of_live, #endif diff --git a/common/bootstage.c b/common/bootstage.c index 4557ed4508c..e8b7bbf81a6 100644 --- a/common/bootstage.c +++ b/common/bootstage.c @@ -53,14 +53,23 @@ int bootstage_relocate(void) { struct bootstage_data *data = gd->bootstage; int i; + char *ptr; + + /* Figure out where to relocate the strings to */ + ptr = (char *)(data + 1); /* * Duplicate all strings. They may point to an old location in the * program .text section that can eventually get trashed. */ debug("Relocating %d records\n", data->rec_count); - for (i = 0; i < data->rec_count; i++) - data->record[i].name = strdup(data->record[i].name); + for (i = 0; i < data->rec_count; i++) { + const char *from = data->record[i].name; + + strcpy(ptr, from); + data->record[i].name = ptr; + ptr += strlen(ptr) + 1; + } return 0; } @@ -490,7 +499,17 @@ int bootstage_unstash(const void *base, int size) int bootstage_get_size(void) { - return sizeof(struct bootstage_data); + struct bootstage_data *data = gd->bootstage; + struct bootstage_record *rec; + int size; + int i; + + size = sizeof(struct bootstage_data); + for (rec = data->record, i = 0; i < data->rec_count; + i++, rec++) + size += strlen(rec->name) + 1; + + return size; } int bootstage_init(bool first) From 5256beecb8a14efba805a2f3f14afb33752ac71a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:51 -0600 Subject: [PATCH 14/18] bootstage: Mark the start/end of TPL and SPL separately At present bootstage in TPL and SPL use the same ID so it is not possible to see the timing of each. Separate out the IDs and use the correct one depending on which phase we are at. Example output: Timer summary in microseconds (14 records): Mark Elapsed Stage 0 0 reset 224,787 224,787 TPL 282,248 57,461 end TPL 341,067 58,819 SPL 925,436 584,369 end SPL 931,710 6,274 board_init_f 1,035,482 103,772 board_init_r 1,387,852 352,370 main_loop 1,387,911 59 id=175 Accumulated time: 196 dm_r 8,300 dm_spl 14,139 dm_f 229,121 fsp-m 262,992 fsp-s Signed-off-by: Simon Glass --- common/spl/spl.c | 9 ++++++--- include/bootstage.h | 2 ++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index a9d3e847af5..eabb1fbc138 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -402,7 +402,8 @@ static int spl_common_init(bool setup_malloc) ret); return ret; } - bootstage_mark_name(BOOTSTAGE_ID_START_SPL, "spl"); + bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL : + BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME); #if CONFIG_IS_ENABLED(LOG) ret = log_init(); if (ret) { @@ -418,7 +419,8 @@ static int spl_common_init(bool setup_malloc) } } if (CONFIG_IS_ENABLED(DM)) { - bootstage_start(BOOTSTATE_ID_ACCUM_DM_SPL, "dm_spl"); + bootstage_start(BOOTSTATE_ID_ACCUM_DM_SPL, + spl_phase() == PHASE_TPL ? "dm tpl" : "dm_spl"); /* With CONFIG_SPL_OF_PLATDATA, bring in all devices */ ret = dm_init_and_scan(!CONFIG_IS_ENABLED(OF_PLATDATA)); bootstage_accum(BOOTSTATE_ID_ACCUM_DM_SPL); @@ -704,8 +706,9 @@ void board_init_r(gd_t *dummy1, ulong dummy2) debug("SPL malloc() used 0x%lx bytes (%ld KB)\n", gd->malloc_ptr, gd->malloc_ptr / 1024); #endif + bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_END_TPL : + BOOTSTAGE_ID_END_SPL, "end " SPL_TPL_NAME); #ifdef CONFIG_BOOTSTAGE_STASH - bootstage_mark_name(BOOTSTAGE_ID_END_SPL, "end_spl"); ret = bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, CONFIG_BOOTSTAGE_STASH_SIZE); if (ret) diff --git a/include/bootstage.h b/include/bootstage.h index 5e7e242b834..d105ae01813 100644 --- a/include/bootstage.h +++ b/include/bootstage.h @@ -170,6 +170,8 @@ enum bootstage_id { * rough boot timing information. */ BOOTSTAGE_ID_AWAKE, + BOOTSTAGE_ID_START_TPL, + BOOTSTAGE_ID_END_TPL, BOOTSTAGE_ID_START_SPL, BOOTSTAGE_ID_END_SPL, BOOTSTAGE_ID_START_UBOOT_F, From 31f9f0ea571c12e914eda400b242d4a0a4b39f43 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 21 Oct 2019 17:26:52 -0600 Subject: [PATCH 15/18] bootstage: Allow SPL to obtain bootstage info from TPL It is possible to enable bootstage in TPL. TPL can stash the info for SPL. But at present this information is then lost because SPL does not read from the stash. Add support for SPL not being the first phase to enable bootstage. Signed-off-by: Simon Glass --- common/spl/spl.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/common/spl/spl.c b/common/spl/spl.c index eabb1fbc138..f1ad8dc9dab 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -396,12 +397,23 @@ static int spl_common_init(bool setup_malloc) gd->malloc_ptr = 0; } #endif - ret = bootstage_init(true); + ret = bootstage_init(u_boot_first_phase()); if (ret) { debug("%s: Failed to set up bootstage: ret=%d\n", __func__, ret); return ret; } +#ifdef CONFIG_BOOTSTAGE_STASH + if (!u_boot_first_phase()) { + const void *stash = map_sysmem(CONFIG_BOOTSTAGE_STASH_ADDR, + CONFIG_BOOTSTAGE_STASH_SIZE); + + ret = bootstage_unstash(stash, CONFIG_BOOTSTAGE_STASH_SIZE); + if (ret) + debug("%s: Failed to unstash bootstage: ret=%d\n", + __func__, ret); + } +#endif /* CONFIG_BOOTSTAGE_STASH */ bootstage_mark_name(spl_phase() == PHASE_TPL ? BOOTSTAGE_ID_START_TPL : BOOTSTAGE_ID_START_SPL, SPL_TPL_NAME); #if CONFIG_IS_ENABLED(LOG) From 8ab452d5877638a97e5bdd521d119403b70b45f5 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 21 Oct 2019 20:09:56 -0700 Subject: [PATCH 16/18] patman: separate emails in CC list with NULs There is a contributor in Linux kernel with a comma in their name, which confuses patman and results in invalid to- or cc- addresses on some patches. To avoid this, let's use \0 as a separator when generating cc file. Signed-off-by: Dmitry Torokhov Reviewed-by: Simon Glass --- tools/patman/func_test.py | 4 ++-- tools/patman/patman.py | 2 +- tools/patman/series.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/patman/func_test.py b/tools/patman/func_test.py index 50a2741439e..2321f9e028b 100644 --- a/tools/patman/func_test.py +++ b/tools/patman/func_test.py @@ -198,9 +198,9 @@ class TestFunctional(unittest.TestCase): line += 4 self.assertEqual(expected, tools.ToUnicode(lines[line])) - self.assertEqual(('%s %s, %s' % (args[0], rick, stefan)), + self.assertEqual(('%s %s\0%s' % (args[0], rick, stefan)), tools.ToUnicode(cc_lines[0])) - self.assertEqual(('%s %s, %s, %s, %s' % (args[1], fred, ed, rick, + self.assertEqual(('%s %s\0%s\0%s\0%s' % (args[1], fred, ed, rick, stefan)), tools.ToUnicode(cc_lines[1])) expected = ''' diff --git a/tools/patman/patman.py b/tools/patman/patman.py index 9605a36eff2..0187ebe1d4b 100755 --- a/tools/patman/patman.py +++ b/tools/patman/patman.py @@ -112,7 +112,7 @@ elif options.cc_cmd: for line in fd.readlines(): match = re_line.match(line) if match and match.group(1) == args[0]: - for cc in match.group(2).split(', '): + for cc in match.group(2).split('\0'): cc = cc.strip() if cc: print(cc) diff --git a/tools/patman/series.py b/tools/patman/series.py index 67103f03e69..d667d9b6d61 100644 --- a/tools/patman/series.py +++ b/tools/patman/series.py @@ -243,13 +243,13 @@ class Series(dict): if limit is not None: cc = cc[:limit] all_ccs += cc - print(commit.patch, ', '.join(sorted(set(cc))), file=fd) + print(commit.patch, '\0'.join(sorted(set(cc))), file=fd) self._generated_cc[commit.patch] = cc if cover_fname: cover_cc = gitutil.BuildEmailList(self.get('cover_cc', '')) cover_cc = [tools.FromUnicode(m) for m in cover_cc] - cc_list = ', '.join([tools.ToUnicode(x) + cc_list = '\0'.join([tools.ToUnicode(x) for x in sorted(set(cover_cc + all_ccs))]) print(cover_fname, cc_list.encode('utf-8'), file=fd) From 97b5f9d1a0dcae66cf7fe5e892f6dc56d14b0c21 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Tue, 22 Oct 2019 15:39:47 +0800 Subject: [PATCH 17/18] dm: core: Update log method for uclass_find_device_by_seq Use log() insted of debug() for uclass_find_device_by_seq function, since this print is very much and we can filter it out with log() interface. Signed-off-by: Kever Yang Reviewed-by: Simon Glass Move #define to top of file as per docs: Signed-off-by: Simon Glass --- drivers/core/uclass.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index 36f4d1c289d..c520ef113a2 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -6,6 +6,8 @@ * Pavel Herrmann */ +#define LOG_CATEGORY LOGC_DM + #include #include #include @@ -303,7 +305,7 @@ int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq, int ret; *devp = NULL; - debug("%s: %d %d\n", __func__, find_req_seq, seq_or_req_seq); + log_debug("%d %d\n", find_req_seq, seq_or_req_seq); if (seq_or_req_seq == -1) return -ENODEV; ret = uclass_get(id, &uc); @@ -311,15 +313,16 @@ int uclass_find_device_by_seq(enum uclass_id id, int seq_or_req_seq, return ret; uclass_foreach_dev(dev, uc) { - debug(" - %d %d '%s'\n", dev->req_seq, dev->seq, dev->name); + log_debug(" - %d %d '%s'\n", + dev->req_seq, dev->seq, dev->name); if ((find_req_seq ? dev->req_seq : dev->seq) == seq_or_req_seq) { *devp = dev; - debug(" - found\n"); + log_debug(" - found\n"); return 0; } } - debug(" - not found\n"); + log_debug(" - not found\n"); return -ENODEV; } From d60ae4c59df55c08dc96202ff58fed21ab3afb7d Mon Sep 17 00:00:00 2001 From: Jean-Jacques Hiblot Date: Tue, 22 Oct 2019 10:05:22 +0200 Subject: [PATCH 18/18] fdt: Fix alignment issue when reading 64-bits properties from fdt The FDT specification [0] gives a requirement of aligning properties on 32-bits. Make sure that the compiler is aware of this constraint when accessing 64-bits properties. [0]: https://github.com/devicetree-org/devicetree-specification/blob/master/source/flattened-format.rst Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Simon Glass --- common/fdt_support.c | 2 +- drivers/core/ofnode.c | 2 +- include/linux/libfdt_env.h | 1 + lib/fdtdec.c | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/common/fdt_support.c b/common/fdt_support.c index baf7924ff61..68343990395 100644 --- a/common/fdt_support.c +++ b/common/fdt_support.c @@ -1566,7 +1566,7 @@ static int fdt_read_prop(const fdt32_t *prop, int prop_len, int cell_off, uint64_t *val, int cells) { const fdt32_t *prop32 = &prop[cell_off]; - const fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off]; + const unaligned_fdt64_t *prop64 = (const fdt64_t *)&prop[cell_off]; if ((cell_off + cells) > prop_len) return -FDT_ERR_NOSPACE; diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index 297f0a0c7cc..8f0eab2ca62 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -57,7 +57,7 @@ int ofnode_read_s32_default(ofnode node, const char *propname, s32 def) int ofnode_read_u64(ofnode node, const char *propname, u64 *outp) { - const fdt64_t *cell; + const unaligned_fdt64_t *cell; int len; assert(ofnode_valid(node)); diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h index e2bf79c7ee8..e49fcd72bd6 100644 --- a/include/linux/libfdt_env.h +++ b/include/linux/libfdt_env.h @@ -16,6 +16,7 @@ typedef __be16 fdt16_t; typedef __be32 fdt32_t; typedef __be64 fdt64_t; +typedef __be64 unaligned_fdt64_t __aligned(4); #define fdt32_to_cpu(x) be32_to_cpu(x) #define cpu_to_fdt32(x) cpu_to_be32(x) diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 17736ce6655..125d9dbf263 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -242,7 +242,7 @@ int fdtdec_get_pci_bar32(struct udevice *dev, struct fdt_pci_addr *addr, uint64_t fdtdec_get_uint64(const void *blob, int node, const char *prop_name, uint64_t default_val) { - const uint64_t *cell64; + const unaligned_fdt64_t *cell64; int length; cell64 = fdt_getprop(blob, node, prop_name, &length);