From b22da3d8526a935aa31e086e63f60ff3246cb61c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 09 Dec 2023 07:24:11 +0000 Subject: [PATCH] add stmac read mac form eeprom --- kernel/drivers/of/fdt.c | 354 ++++++++++++++++++---------------------------------------- 1 files changed, 113 insertions(+), 241 deletions(-) diff --git a/kernel/drivers/of/fdt.c b/kernel/drivers/of/fdt.c index 3315e02..93ec936 100644 --- a/kernel/drivers/of/fdt.c +++ b/kernel/drivers/of/fdt.c @@ -11,7 +11,6 @@ #include <linux/crc32.h> #include <linux/kernel.h> #include <linux/initrd.h> -#include <linux/bootmem.h> #include <linux/memblock.h> #include <linux/mutex.h> #include <linux/of.h> @@ -40,7 +39,7 @@ * memory entries in the /memory node. This function may be called * any time after initial_boot_param is set. */ -void of_fdt_limit_memory(int limit) +void __init of_fdt_limit_memory(int limit) { int memory; int len; @@ -80,149 +79,6 @@ } } -/** - * of_fdt_get_ddrhbb - Return the highest bank bit of ddr on the current device - * - * On match, returns a non-zero positive value which matches the highest bank - * bit. - * Otherwise returns -ENOENT. - */ -int of_fdt_get_ddrhbb(int channel, int rank) -{ - int memory; - int len; - int ret; - /* Single spaces reserved for channel(0-9), rank(0-9) */ - char pname[] = "ddr_device_hbb_ch _rank "; - fdt32_t *prop = NULL; - - memory = fdt_path_offset(initial_boot_params, "/memory"); - if (memory > 0) { - snprintf(pname, sizeof(pname), - "ddr_device_hbb_ch%d_rank%d", channel, rank); - prop = fdt_getprop_w(initial_boot_params, memory, - pname, &len); - } - - if (!prop || len != sizeof(u32)) - return -ENOENT; - - ret = fdt32_to_cpu(*prop); - - return ret; -} -EXPORT_SYMBOL_GPL(of_fdt_get_ddrhbb); - -/** - * of_fdt_get_ddrrank - Return the rank of ddr on the current device - * - * On match, returns a non-zero positive value which matches the ddr rank. - * Otherwise returns -ENOENT. - */ -int of_fdt_get_ddrrank(int channel) -{ - int memory; - int len; - int ret; - /* Single space reserved for channel(0-9) */ - char pname[] = "ddr_device_rank_ch "; - fdt32_t *prop = NULL; - - memory = fdt_path_offset(initial_boot_params, "/memory"); - if (memory > 0) { - snprintf(pname, sizeof(pname), - "ddr_device_rank_ch%d", channel); - prop = fdt_getprop_w(initial_boot_params, memory, - pname, &len); - } - - if (!prop || len != sizeof(u32)) - return -ENOENT; - - ret = fdt32_to_cpu(*prop); - - return ret; -} -EXPORT_SYMBOL_GPL(of_fdt_get_ddrrank); - -/** - * of_fdt_get_ddrtype - Return the type of ddr (4/5) on the current device - * - * On match, returns a non-zero positive value which matches the ddr type. - * Otherwise returns -ENOENT. - */ -int of_fdt_get_ddrtype(void) -{ - int memory; - int len; - int ret; - fdt32_t *prop = NULL; - - memory = fdt_path_offset(initial_boot_params, "/memory"); - if (memory > 0) - prop = fdt_getprop_w(initial_boot_params, memory, - "ddr_device_type", &len); - - if (!prop || len != sizeof(u32)) - return -ENOENT; - - ret = fdt32_to_cpu(*prop); - - return ret; -} -EXPORT_SYMBOL_GPL(of_fdt_get_ddrtype); - -/** - * of_fdt_is_compatible - Return true if given node from the given blob has - * compat in its compatible list - * @blob: A device tree blob - * @node: node to test - * @compat: compatible string to compare with compatible list. - * - * On match, returns a non-zero value with smaller values returned for more - * specific compatible values. - */ -static int of_fdt_is_compatible(const void *blob, - unsigned long node, const char *compat) -{ - const char *cp; - int cplen; - unsigned long l, score = 0; - - cp = fdt_getprop(blob, node, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - score++; - if (of_compat_cmp(cp, compat, strlen(compat)) == 0) - return score; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} - -/** - * of_fdt_is_big_endian - Return true if given node needs BE MMIO accesses - * @blob: A device tree blob - * @node: node to test - * - * Returns true if the node has a "big-endian" property, or if the kernel - * was compiled for BE *and* the node has a "native-endian" property. - * Returns false otherwise. - */ -bool of_fdt_is_big_endian(const void *blob, unsigned long node) -{ - if (fdt_getprop(blob, node, "big-endian", NULL)) - return true; - if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && - fdt_getprop(blob, node, "native-endian", NULL)) - return true; - return false; -} - static bool of_fdt_device_is_available(const void *blob, unsigned long node) { const char *status = fdt_getprop(blob, node, "status", NULL); @@ -234,27 +90,6 @@ return true; return false; -} - -/** - * of_fdt_match - Return true if node matches a list of compatible values - */ -int of_fdt_match(const void *blob, unsigned long node, - const char *const *compat) -{ - unsigned int tmp, score = 0; - - if (!compat) - return 0; - - while (*compat) { - tmp = of_fdt_is_compatible(blob, node, *compat); - if (tmp && (score == 0 || (tmp < score))) - score = tmp; - compat++; - } - - return score; } static void *unflatten_dt_alloc(void **mem, unsigned long size, @@ -408,12 +243,8 @@ populate_properties(blob, offset, mem, np, pathp, dryrun); if (!dryrun) { np->name = of_get_property(np, "name", NULL); - np->type = of_get_property(np, "device_type", NULL); - if (!np->name) np->name = "<NULL>"; - if (!np->type) - np->type = "<NULL>"; } *pnp = np; @@ -484,7 +315,7 @@ for (offset = 0; offset >= 0 && depth >= initial_depth; offset = fdt_next_node(blob, offset, &depth)) { - if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH)) + if (WARN_ON_ONCE(depth >= FDT_MAX_DEPTH - 1)) continue; if (!IS_ENABLED(CONFIG_OF_KOBJ) && @@ -581,8 +412,8 @@ /* Second pass, do actual unflattening */ unflatten_dt_nodes(blob, mem, dad, mynodes); if (be32_to_cpup(mem + size) != 0xdeadbeef) - pr_warning("End of tree marker overwritten: %08x\n", - be32_to_cpup(mem + size)); + pr_warn("End of tree marker overwritten: %08x\n", + be32_to_cpup(mem + size)); if (detached && mynodes) { of_node_set_flag(*mynodes, OF_DETACHED); @@ -633,14 +464,14 @@ int __initdata dt_root_addr_cells; int __initdata dt_root_size_cells; -void *initial_boot_params; +void *initial_boot_params __ro_after_init; #ifdef CONFIG_OF_EARLY_FLATTREE static u32 of_fdt_crc32; /** - * res_mem_reserve_reg() - reserve all memory described in 'reg' property + * __reserved_mem_reserve_reg() - reserve all memory described in 'reg' property */ static int __init __reserved_mem_reserve_reg(unsigned long node, const char *uname) @@ -649,7 +480,8 @@ phys_addr_t base, size; int len; const __be32 *prop; - int nomap, first = 1; + int first = 1; + bool nomap; prop = of_get_flat_dt_prop(node, "reg", &len); if (!prop) @@ -764,7 +596,7 @@ fdt_get_mem_rsv(initial_boot_params, n, &base, &size); if (!size) break; - early_init_dt_reserve_memory_arch(base, size, 0); + early_init_dt_reserve_memory_arch(base, size, false); } of_scan_flat_dt(__fdt_scan_reserved_mem, NULL); @@ -782,7 +614,7 @@ /* Reserve the dtb region */ early_init_dt_reserve_memory_arch(__pa(initial_boot_params), fdt_totalsize(initial_boot_params), - 0); + false); } /** @@ -811,8 +643,6 @@ offset = fdt_next_node(blob, offset, &depth)) { pathp = fdt_get_name(blob, offset, NULL); - if (*pathp == '/') - pathp = kbasename(pathp); rc = it(offset, pathp, depth, data); } return rc; @@ -839,8 +669,6 @@ int rc; pathp = fdt_get_name(blob, node, NULL); - if (*pathp == '/') - pathp = kbasename(pathp); rc = it(node, pathp, data); if (rc) return rc; @@ -856,7 +684,7 @@ * @return offset of the subnode, or -FDT_ERR_NOTFOUND if there is none */ -int of_get_flat_dt_subnode_by_name(unsigned long node, const char *uname) +int __init of_get_flat_dt_subnode_by_name(unsigned long node, const char *uname) { return fdt_subnode_offset(initial_boot_params, node, uname); } @@ -867,14 +695,6 @@ unsigned long __init of_get_flat_dt_root(void) { return 0; -} - -/** - * of_get_flat_dt_size - Return the total size of the FDT - */ -int __init of_get_flat_dt_size(void) -{ - return fdt_totalsize(initial_boot_params); } /** @@ -890,6 +710,38 @@ } /** + * of_fdt_is_compatible - Return true if given node from the given blob has + * compat in its compatible list + * @blob: A device tree blob + * @node: node to test + * @compat: compatible string to compare with compatible list. + * + * On match, returns a non-zero value with smaller values returned for more + * specific compatible values. + */ +static int of_fdt_is_compatible(const void *blob, + unsigned long node, const char *compat) +{ + const char *cp; + int cplen; + unsigned long l, score = 0; + + cp = fdt_getprop(blob, node, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + score++; + if (of_compat_cmp(cp, compat, strlen(compat)) == 0) + return score; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} + +/** * of_flat_dt_is_compatible - Return true if given node has compat in compatible list * @node: node to test * @compat: compatible string to compare with compatible list. @@ -902,9 +754,21 @@ /** * of_flat_dt_match - Return true if node matches a list of compatible values */ -int __init of_flat_dt_match(unsigned long node, const char *const *compat) +static int __init of_flat_dt_match(unsigned long node, const char *const *compat) { - return of_fdt_match(initial_boot_params, node, compat); + unsigned int tmp, score = 0; + + if (!compat) + return 0; + + while (*compat) { + tmp = of_fdt_is_compatible(initial_boot_params, node, *compat); + if (tmp && (score == 0 || (tmp < score))) + score = tmp; + compat++; + } + + return score; } /** @@ -985,15 +849,20 @@ } #ifdef CONFIG_BLK_DEV_INITRD -#ifndef __early_init_dt_declare_initrd static void __early_init_dt_declare_initrd(unsigned long start, unsigned long end) { - initrd_start = (unsigned long)__va(start); - initrd_end = (unsigned long)__va(end); - initrd_below_start_ok = 1; + /* ARM64 would cause a BUG to occur here when CONFIG_DEBUG_VM is + * enabled since __va() is called too early. ARM64 does make use + * of phys_initrd_start/phys_initrd_size so we can skip this + * conversion. + */ + if (!IS_ENABLED(CONFIG_ARM64)) { + initrd_start = (unsigned long)__va(start); + initrd_end = (unsigned long)__va(end); + initrd_below_start_ok = 1; + } } -#endif /** * early_init_dt_check_for_initrd - Decode initrd location from flat tree @@ -1018,6 +887,8 @@ end = of_read_number(prop, len/4); __early_init_dt_declare_initrd(start, end); + phys_initrd_start = start; + phys_initrd_size = end - start; pr_debug("initrd_start=0x%llx initrd_end=0x%llx\n", (unsigned long long)start, (unsigned long long)end); @@ -1072,8 +943,8 @@ if (fdt_node_check_compatible(fdt, offset, match->compatible)) continue; - of_setup_earlycon(match, offset, options); - return 0; + if (of_setup_earlycon(match, offset, options) == 0) + return 0; } return -ENODEV; } @@ -1193,8 +1064,8 @@ { int l = 0; const char *p = NULL; - char *cmdline = data; const void *rng_seed; + char *cmdline = data; pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); @@ -1223,11 +1094,11 @@ strncpy(cmdline + cmdline_len, p, copy_len); cmdline[cmdline_len + copy_len] = '\0'; } else { - strlcpy(cmdline, p, min((int)l, COMMAND_LINE_SIZE)); + strlcpy(cmdline, p, min(l, COMMAND_LINE_SIZE)); } } - pr_debug("Command line is: %s\n", (char*)data); + pr_debug("Command line is: %s\n", (char *)data); rng_seed = of_get_flat_dt_prop(node, "rng-seed", &l); if (rng_seed && l > 0) { @@ -1245,7 +1116,6 @@ return 1; } -#ifdef CONFIG_HAVE_MEMBLOCK #ifndef MIN_MEMBLOCK_ADDR #define MIN_MEMBLOCK_ADDR __pa(PAGE_OFFSET) #endif @@ -1257,37 +1127,38 @@ { const u64 phys_offset = MIN_MEMBLOCK_ADDR; + if (size < PAGE_SIZE - (base & ~PAGE_MASK)) { + pr_warn("Ignoring memory block 0x%llx - 0x%llx\n", + base, base + size); + return; + } + if (!PAGE_ALIGNED(base)) { - if (size < PAGE_SIZE - (base & ~PAGE_MASK)) { - pr_warn("Ignoring memory block 0x%llx - 0x%llx\n", - base, base + size); - return; - } size -= PAGE_SIZE - (base & ~PAGE_MASK); base = PAGE_ALIGN(base); } size &= PAGE_MASK; if (base > MAX_MEMBLOCK_ADDR) { - pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", - base, base + size); + pr_warn("Ignoring memory block 0x%llx - 0x%llx\n", + base, base + size); return; } if (base + size - 1 > MAX_MEMBLOCK_ADDR) { - pr_warning("Ignoring memory range 0x%llx - 0x%llx\n", - ((u64)MAX_MEMBLOCK_ADDR) + 1, base + size); + pr_warn("Ignoring memory range 0x%llx - 0x%llx\n", + ((u64)MAX_MEMBLOCK_ADDR) + 1, base + size); size = MAX_MEMBLOCK_ADDR - base + 1; } if (base + size < phys_offset) { - pr_warning("Ignoring memory block 0x%llx - 0x%llx\n", - base, base + size); + pr_warn("Ignoring memory block 0x%llx - 0x%llx\n", + base, base + size); return; } if (base < phys_offset) { - pr_warning("Ignoring memory range 0x%llx - 0x%llx\n", - base, phys_offset); + pr_warn("Ignoring memory range 0x%llx - 0x%llx\n", + base, phys_offset); size -= phys_offset - base; base = phys_offset; } @@ -1302,34 +1173,31 @@ int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, phys_addr_t size, bool nomap) { - if (nomap) - return memblock_remove(base, size); + if (nomap) { + /* + * If the memory is already reserved (by another region), we + * should not allow it to be marked nomap. + */ + if (memblock_is_region_reserved(base, size)) + return -EBUSY; + + if (memblock_is_nomap_remove()) + return memblock_remove(base, size); + + return memblock_mark_nomap(base, size); + } return memblock_reserve(base, size); } -#else -void __init __weak early_init_dt_add_memory_arch(u64 base, u64 size) -{ - WARN_ON(1); -} - -int __init __weak early_init_dt_mark_hotplug_memory_arch(u64 base, u64 size) -{ - return -ENOSYS; -} - -int __init __weak early_init_dt_reserve_memory_arch(phys_addr_t base, - phys_addr_t size, bool nomap) -{ - pr_err("Reserved memory not supported, ignoring range %pa - %pa%s\n", - &base, &size, nomap ? " (nomap)" : ""); - return -ENOSYS; -} -#endif - static void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align) { - return memblock_virt_alloc(size, align); + void *ptr = memblock_alloc(size, align); + + if (!ptr) + panic("%s: Failed to allocate %llu bytes align=0x%llx\n", + __func__, size, align); + + return ptr; } bool __init early_init_dt_verify(void *params) @@ -1351,8 +1219,12 @@ void __init early_init_dt_scan_nodes(void) { + int rc = 0; + /* Retrieve various information from the /chosen node */ - of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); + rc = of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line); + if (!rc) + pr_warn("No chosen node found, continuing without\n"); /* Initialize {size,address}-cells info */ of_scan_flat_dt(early_init_dt_scan_root, NULL); -- Gitblit v1.6.2