diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2024-03-15 13:15:24 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2024-03-15 13:15:24 +0100 |
commit | 4ddf024563216c284c7375a485a167c73e2eaed4 (patch) | |
tree | 0cf1fe711bbd95cb3488c9a40ada5e14e71ca43d | |
parent | 46149a0260cbe7ec86e7fabd83c6e68f1b900e54 (diff) | |
parent | dc82ff225a9bf1e601b7091664769908aa78dcba (diff) | |
download | barebox-4ddf024563216c284c7375a485a167c73e2eaed4.tar.gz barebox-4ddf024563216c284c7375a485a167c73e2eaed4.tar.xz |
Merge branch 'for-next/misc'
45 files changed, 1142 insertions, 159 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 63ba6aa9d5..14062dee34 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -319,6 +319,16 @@ config 64BIT endchoice +config BOARD_MIPS_GENERIC_DT + select BOARD_GENERIC_DT + depends on OFDEVICE + bool "Build generic MIPS device tree 2nd stage image" + help + This enables compilation of a generic image that can be started 2nd + stage from barebox or from qemu. It picks up a device tree passed + in a1 like the Kernel does. + The image will be called images/barebox-dt-2nd.img + menu "MIPS specific settings" config CMD_MIPS_CPUINFO diff --git a/arch/mips/boards/Makefile b/arch/mips/boards/Makefile index 9402035856..c4ce599c93 100644 --- a/arch/mips/boards/Makefile +++ b/arch/mips/boards/Makefile @@ -13,3 +13,5 @@ obj-$(CONFIG_BOARD_QEMU_MALTA) += qemu-malta/ obj-$(CONFIG_BOARD_RZX50) += ritmix-rzx50/ obj-$(CONFIG_BOARD_TPLINK_MR3020) += tplink-mr3020/ obj-$(CONFIG_BOARD_TPLINK_WDR4300) += tplink-wdr4300/ + +pbl-$(CONFIG_BOARD_MIPS_GENERIC_DT) += board-dt-2nd.o diff --git a/arch/mips/boards/board-dt-2nd.S b/arch/mips/boards/board-dt-2nd.S new file mode 100644 index 0000000000..a1465f09e3 --- /dev/null +++ b/arch/mips/boards/board-dt-2nd.S @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Startup Code for generic MIPS device tree 2nd stage image + * + * Copyright (C) 2024 Antony Pavlov <antonynpavlov@gmail.com> + */ + +#include <asm/asm.h> +#include <asm/pbl_macros.h> +#include <linux/sizes.h> + +ENTRY_FUNCTION(start_dt_2nd) + + /* save device tree address in v1 */ + move v1, a1 + + mips_cpu_setup + + copy_to_link_location start_dt_2nd + + stack_setup + + /* pbl_main_entry() computes fdt_len by itself + * if fdt == fdt_end */ + move a0, v1 /* fdt */ + move a1, v1 /* fdt_end */ + PTR_LI a2, SZ_256M /* ram_size */ + PTR_LA v0, pbl_main_entry + jal v0 + nop + + /* No return */ +1: + b 1b + nop diff --git a/arch/mips/boot/main_entry-pbl.c b/arch/mips/boot/main_entry-pbl.c index 78982fd995..389dc94f37 100644 --- a/arch/mips/boot/main_entry-pbl.c +++ b/arch/mips/boot/main_entry-pbl.c @@ -11,6 +11,7 @@ #include <asm/sections.h> #include <asm-generic/memory_layout.h> #include <debug_ll.h> +#include <asm/unaligned.h> extern void *input_data; extern void *input_data_end; @@ -45,6 +46,9 @@ void __section(.text_entry) pbl_main_entry(void *fdt, void *fdt_end, barebox_uncompress(&input_data, piggy_len); fdt_len = (unsigned long)fdt_end - (unsigned long)fdt; + if (!fdt_len) { + fdt_len = get_unaligned_be32((void *)((unsigned long)fdt + 4)); + } fdt_new = (void *)PAGE_ALIGN_DOWN(TEXT_BASE - MALLOC_SIZE - STACK_SIZE - fdt_len); memcpy(fdt_new, fdt, fdt_len); diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c index 643ad57e4d..86573dec7f 100644 --- a/arch/mips/lib/bootm.c +++ b/arch/mips/lib/bootm.c @@ -16,12 +16,21 @@ static int do_bootm_barebox(struct image_data *data) { - void (*barebox)(void); + void (*barebox)(int, void *); + void *fdt = NULL; barebox = read_file(data->os_file, NULL); if (!barebox) return -EINVAL; + if (data->oftree_file) { + fdt = bootm_get_devicetree(data); + if (IS_ERR(fdt)) { + pr_err("Failed to load dtb\n"); + return PTR_ERR(fdt); + } + } + if (data->dryrun) { free(barebox); return 0; @@ -29,7 +38,7 @@ static int do_bootm_barebox(struct image_data *data) shutdown_barebox(); - barebox(); + barebox(-2, fdt); restart_machine(); } diff --git a/commands/dmesg.c b/commands/dmesg.c index 83410234e1..8a60f07507 100644 --- a/commands/dmesg.c +++ b/commands/dmesg.c @@ -76,7 +76,7 @@ static unsigned dmesg_get_levels(const char *__args) static int do_dmesg(int argc, char *argv[]) { - int opt, i; + int opt, ret, i; int delete_buf = 0, emit = 0; unsigned flags = 0, levels = 0; char *set = NULL; @@ -148,7 +148,9 @@ static int do_dmesg(int argc, char *argv[]) return 0; } - log_print(flags, levels); + ret = log_print(flags, levels); + if (ret) + return 1; if (delete_buf) log_clean(10); diff --git a/common/Kconfig b/common/Kconfig index 33903aa249..0000dac874 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -840,6 +840,16 @@ config CONSOLE_ALLOW_COLOR compile time default for colored console output. After boot it can be controlled using global.allow_color. +config CONSOLE_FLUSH_LINE_BREAK + bool "Flush consoles on new line" if COMPILE_TEST + help + Many serial drivers configure and use hardware FIFOs as not to + delay the boot. When debuging some king of bugs, such as clock + issues that hang the SoC, this can falsify debugging output, + because the UART doesn't output a submitted message fully, before + the SoC hangs. This option will flush serial FIFOs when processing + the new line feed characters. + config CONSOLE_DISABLE_INPUT prompt "Disable input on all consoles by default (non-interactive)" def_bool CONSOLE_NONE @@ -1705,6 +1715,7 @@ config DEBUG_AT91_UART_BASE config DEBUG_INITCALLS bool "Trace initcalls" + select CONSOLE_FLUSH_LINE_BREAK help If enabled this will print initcall traces. @@ -1719,6 +1730,7 @@ config DEBUG_PBL config DEBUG_PROBES bool "Trace driver probes/removes" + select CONSOLE_FLUSH_LINE_BREAK help If enabled this will log driver probe and remove traces. If DEBUG_LL is enabled, probes will be printed even before registering consoles. If it's disabled, they diff --git a/common/bbu.c b/common/bbu.c index f08ce7e0d5..ba2566acdf 100644 --- a/common/bbu.c +++ b/common/bbu.c @@ -95,17 +95,23 @@ out: int bbu_confirm(struct bbu_data *data) { int key; + const char *prompt; if (data->flags & BBU_FLAG_YES) - return 0; + prompt = "."; + else + prompt = " (y/n)?"; if (data->imagefile) - printf("update barebox from %s using handler %s to %s (y/n)?\n", - data->imagefile, data->handler_name, - data->devicefile); + printf("update barebox on %s from %s using handler %s%s\n", + data->devicefile, data->imagefile, + data->handler_name, prompt); else - printf("Refresh barebox on %s using handler %s (y/n)?\n", - data->devicefile, data->handler_name); + printf("Refresh barebox on %s using handler %s%s\n", + data->devicefile, data->handler_name, prompt); + + if (data->flags & BBU_FLAG_YES) + return 0; key = read_key(); diff --git a/common/blspec.c b/common/blspec.c index b70332a54c..23a24c63db 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -427,7 +427,9 @@ static bool entry_is_of_compatible(struct blspec_entry *entry) const char *devicetree; const char *abspath; int ret; - struct device_node *root = NULL, *barebox_root; + struct device_node *barebox_root; + size_t size; + void *fdt; const char *compat; char *filename; @@ -455,25 +457,23 @@ static bool entry_is_of_compatible(struct blspec_entry *entry) filename = basprintf("%s/%s", abspath, devicetree); - root = of_read_file(filename); - if (IS_ERR(root)) { + fdt = read_file(filename, &size); + if (!fdt) { ret = false; - root = NULL; goto out; } - if (of_device_is_compatible(root, compat)) { + if (fdt_machine_is_compatible(fdt, size, compat)) { ret = true; goto out; } - pr_info("ignoring entry with incompatible devicetree \"%s\"\n", - (char *)of_get_property(root, "compatible", NULL)); + pr_info("ignoring entry with incompatible devicetree: %s\n", devicetree); ret = false; out: - of_delete_node(root); + free(fdt); free(filename); return ret; diff --git a/common/boot.c b/common/boot.c index 28bb459883..cbfe6649b3 100644 --- a/common/boot.c +++ b/common/boot.c @@ -115,11 +115,18 @@ struct watchdog *boot_get_enabled_watchdog(void) } static char *global_boot_default; + +void boot_set_default(const char *boot_default) +{ + free(global_boot_default); + global_boot_default = xstrdup(boot_default); +} + static char *global_user; static int init_boot(void) { - global_boot_default = xstrdup("net"); + global_boot_default = global_boot_default ? : xstrdup("net"); globalvar_add_simple_string("boot.default", &global_boot_default); globalvar_add_simple_int("boot.watchdog_timeout", &boot_watchdog_timeout, "%u"); diff --git a/common/console.c b/common/console.c index 03b76b122b..5a0fd66ab3 100644 --- a/common/console.c +++ b/common/console.c @@ -277,8 +277,11 @@ static int __console_puts(struct console_device *cdev, const char *s, size_t i; for (i = 0; i < nbytes; i++) { - if (*s == '\n') + if (*s == '\n') { cdev->putc(cdev, '\r'); + if (IS_ENABLED(CONFIG_CONSOLE_FLUSH_LINE_BREAK) && cdev->flush) + cdev->flush(cdev); + } cdev->putc(cdev, *s); s++; diff --git a/common/console_common.c b/common/console_common.c index 65c339cfae..0113a64138 100644 --- a/common/console_common.c +++ b/common/console_common.c @@ -14,12 +14,14 @@ #include <environment.h> #include <globalvar.h> #include <magicvar.h> +#include <memory.h> #include <of.h> #include <password.h> #include <clock.h> #include <malloc.h> #include <linux/pstore.h> #include <linux/math64.h> +#include <linux/sizes.h> #include <linux/overflow.h> #ifndef CONFIG_CONSOLE_NONE @@ -37,7 +39,7 @@ int barebox_loglevel = CONFIG_DEFAULT_LOGLEVEL; LIST_HEAD(barebox_logbuf); static int barebox_logbuf_num_messages; -static int barebox_log_max_messages = 1000; +static int barebox_log_max_messages; static void log_del(struct log_entry *log) { @@ -173,15 +175,18 @@ bool console_allow_color(void) static int console_common_init(void) { - if (IS_ENABLED(CONFIG_LOGBUF)) + if (IS_ENABLED(CONFIG_LOGBUF)) { + barebox_log_max_messages + = clamp(mem_malloc_size() / SZ_32K, 1000UL, 100000UL); globalvar_add_simple_int("log_max_messages", &barebox_log_max_messages, "%d"); + } globalvar_add_simple_bool("allow_color", &__console_allow_color); return globalvar_add_simple_int("loglevel", &barebox_loglevel, "%d"); } -device_initcall(console_common_init); +core_initcall(console_common_init); int log_writefile(const char *filepath) { @@ -203,7 +208,7 @@ int log_writefile(const char *filepath) return ret < 0 ? ret : nbytes; } -void log_print(unsigned flags, unsigned levels) +int log_print(unsigned flags, unsigned levels) { struct log_entry *log; unsigned long last = 0; @@ -214,6 +219,8 @@ void log_print(unsigned flags, unsigned levels) if (levels && !(levels & (1 << log->level))) continue; + if (ctrlc()) + return -EINTR; if (!(flags & (BAREBOX_LOG_PRINT_RAW | BAREBOX_LOG_PRINT_TIME | BAREBOX_LOG_DIFF_TIME))) @@ -242,6 +249,8 @@ void log_print(unsigned flags, unsigned levels) printf("%s", log->msg); } + + return 0; } int printf(const char *fmt, ...) diff --git a/common/ddr_spd.c b/common/ddr_spd.c index 1c1d5826e0..b7693f3fd2 100644 --- a/common/ddr_spd.c +++ b/common/ddr_spd.c @@ -231,11 +231,31 @@ static int ddr2_sdram_ctime(uint8_t byte) return ctime; } +static void spd_print_manufacturing_date(uint8_t year, uint8_t week) +{ + /* + * According to JEDEC Standard the year/week bytes must be in BCD + * format. However, that is not always true for actual DIMMs out + * there, so fall back to binary format if it makes more sense. + */ + + printf("%-48s ", "Manufacturing Date"); + if ((year & 0xf0) <= 0x90 && (year & 0xf) <= 0x9 + && (week & 0xf0) <= 0x90 && (week & 0xf) <= 0x9) { + printf("20%02X-W%02X", year, week); + } else if (year <= 99 && week >= 1 && week <= 53) { + printf("20%02d-W%02d", year, week); + } else { + printf("0x%02X%02X", year, week); + } + printf("\n"); +} + /* * Based on * https://github.com/groeck/i2c-tools/blob/master/eeprom/decode-dimms */ -void ddr_spd_print(uint8_t *record) +static void ddr2_spd_print(uint8_t *record) { int highestCAS = 0; int i, i_i, k, x, y; @@ -246,11 +266,6 @@ void ddr_spd_print(uint8_t *record) char *ref, *sum; struct ddr2_spd_eeprom *s = (struct ddr2_spd_eeprom *)record; - if (s->mem_type != SPD_MEMTYPE_DDR2) { - printf("Can't dump information for non-DDR2 memory\n"); - return; - } - ctime = ddr2_sdram_ctime(s->clk_cycle); ddrclk = 2 * (100000 / ctime); tbits = (s->res_7 << 8) + (s->dataw); @@ -420,14 +435,539 @@ void ddr_spd_print(uint8_t *record) printf("%d", record[i]); } printf("\n"); - printf("%-48s 20%d-W%d\n", "Manufacturing Date", record[93], - record[94]); + spd_print_manufacturing_date(record[93], record[94]); printf("%-48s 0x", "Assembly Serial Number"); for (i = 95; i < 99; i++) printf("%02X", record[i]); printf("\n"); } +static const char * const ddr3_spd_moduletypes[] = { + "Undefined", + "RDIMM", + "UDIMM", + "SO-DIMM", + "Micro-DIMM", + "Mini-RDIMM", + "Mini-UDIMM", + "Mini-CDIMM", + "72b-SO-UDIMM", + "72b-SO-RDIMM", + "72b-SO-CDIMM", + "LRDIMM", + "16b-SO-DIMM", + "32b-SO-DIMM" +}; + +static const char * const ddr3_spd_moduletypes_width[] = { + "Unknown", + "133.35 mm", + "133.35 mm", + "67.6 mm", + "TBD", + "82.0 mm", + "82.0 mm", + "67.6 mm", + "67.6 mm", + "67.6 mm", + "67.6 mm", + "133.35 mm", + "67.6 mm", + "67.6 mm" +}; + +#define DDR3_UNBUFFERED 1 +#define DDR3_REGISTERED 2 +#define DDR3_CLOCKED 3 +#define DDR3_LOAD_REDUCED 4 + +static const uint8_t ddr3_spd_moduletypes_family[] = { + 0, + DDR3_REGISTERED, + DDR3_UNBUFFERED, + DDR3_UNBUFFERED, + DDR3_UNBUFFERED, + DDR3_REGISTERED, + DDR3_UNBUFFERED, + DDR3_CLOCKED, + DDR3_UNBUFFERED, + DDR3_REGISTERED, + DDR3_CLOCKED, + DDR3_LOAD_REDUCED, + DDR3_UNBUFFERED, + DDR3_UNBUFFERED +}; + +static const int ddr3_std_speeds[] = { + 1000 * 7.5 / 8, + 1000 * 7.5 / 7, + 1000 * 1.25, + 1000 * 1.5, + 1000 * 1.875, + 1000 * 2.5 +}; + +static const char * const ddr3_maximum_activated_counts[] = { + "Untested", + "700 K", + "600 K", + "500 K", + "400 K", + "300 K", + "200 K", + "Reserved", + "Unlimited", +}; + +static int ddr3_timing_from_mtb_ftb(uint16_t txx, int8_t fine_txx, + uint8_t mtb_dividend, uint8_t mtb_divisor, + uint8_t ftb_div) +{ + /* + * Given mtb in ns and ftb in ps, return the result in ps, + * carefully rounding to the nearest picosecond. + */ + int result = txx * 10000 * mtb_dividend / mtb_divisor + + fine_txx * (ftb_div >> 4) / (ftb_div & 0xf); + return DIV_ROUND_CLOSEST(result, 10); +} + +static int ddr3_adjust_ctime(int ctime, uint8_t ftb_div) +{ + uint8_t ftb_divisor = ftb_div >> 4; + uint8_t ftb_dividend = ftb_div & 0xf; + int i; + + /* + * Starting with DDR3-1866, vendors may start approximating the + * minimum cycle time. Try to guess what they really meant so + * that the reported speed matches the standard. + */ + for (i = 7; i < 15; i++) { + int test = ctime * ftb_divisor - (int)(1000 * 7.5) * ftb_divisor / i; + + if (test > -(int)ftb_dividend && test < ftb_dividend) + return (int)(1000 * 7.5) / i; + } + + return ctime; +} + +static void ddr3_print_reference_card(uint8_t ref_raw_card, uint8_t mod_height) +{ + const char alphabet[] = "ABCDEFGHJKLMNPRTUVWY"; + uint8_t ref = ref_raw_card & 0x1f; + uint8_t revision = mod_height >> 5; + char ref_card[3] = { 0 }; + + if (ref == 0x1f) { + printf("%-48s %s\n", "Module Reference Card", "ZZ"); + return; + } + + if (ref_raw_card & 0x80) + ref += 0x1f; + if (!revision) + revision = ((ref_raw_card >> 5) & 0x3); + + if (ref < ARRAY_SIZE(alphabet) - 1) { + /* One letter reference card */ + ref_card[0] = alphabet[ref]; + } else { + /* Two letter reference card */ + uint8_t ref1 = ref / (ARRAY_SIZE(alphabet) - 1); + + ref -= (ARRAY_SIZE(alphabet) - 1) * ref1; + ref_card[0] = alphabet[ref1]; + ref_card[1] = alphabet[ref]; + } + + printf("%-48s %s revision %u\n", "Module Reference Card", ref_card, revision); +} + +static void ddr3_print_revision_number(const char *name, uint8_t rev) +{ + uint8_t h = rev >> 4; + uint8_t l = rev & 0xf; + + /* Decode as suggested by JEDEC Standard 21-C */ + if (!h) + printf("%-48s %d\n", name, l); + if (h < 0xa) + printf("%-48s %d.%d\n", name, h, l); + else + printf("%-48s %c%d\n", name, 'A' + h - 0xa, l); +} + +static void ddr3_spd_print(uint8_t *record) +{ + struct ddr3_spd_eeprom *s = (struct ddr3_spd_eeprom *)record; + const char *sum; + uint8_t spd_len; + int size, bytes_written; + int ctime, ddrclk; + uint8_t tbits; + int pcclk; + uint8_t cap, k; + int taa, trcd, trp, tras; + uint16_t cas_sup; + int twr, trrd, trc, trfc, twtr, trtp, tfaw; + uint8_t die_count, loading; + uint8_t mac; + uint8_t family; + int i; + + sum = ddr3_spd_check(s) ? "ERR" : "OK"; + + printf("\n---=== SPD EEPROM Information ===---\n"); + + printf("EEPROM CRC of bytes 0-%3d %22s %s (0x%02X%02X)\n", + (s->info_size_crc & 0x80) ? 116 : 125, "", sum, s->crc[1], s->crc[0]); + + spd_len = (s->info_size_crc >> 4) & 0x7; + size = 64 << (s->info_size_crc & 0xf); + if (spd_len == 0) { + bytes_written = 128; + } else if (spd_len == 1) { + bytes_written = 176; + } else if (spd_len == 2) { + bytes_written = 256; + } else { + size = 64; + bytes_written = 64; + } + printf("%-48s %d\n", "# of bytes written to SDRAM EEPROM", bytes_written); + printf("%-48s %d\n", "Total number of bytes in EEPROM", size); + printf("%-48s %s\n", "Fundamental Memory type", type_list[s->mem_type]); + + if (s->spd_rev != 0xff) + printf("%-48s %x.%x\n", "SPD Revision", s->spd_rev >> 4, + s->spd_rev & 0xf); + + printf("%-48s ", "Module Type"); + if (s->module_type <= ARRAY_SIZE(ddr3_spd_moduletypes)) + printf("%s\n", ddr3_spd_moduletypes[s->module_type]); + else + printf("Reserved (0x%02x)\n", s->module_type); + + if ((s->ftb_div & 0x0f) == 0 || s->mtb_divisor == 0) { + printf("Invalid time base divisor, can't decode\n"); + return; + } + + printf("\n---=== Memory Characteristics ===---\n"); + + ctime = ddr3_timing_from_mtb_ftb(s->tck_min, s->fine_tck_min, + s->mtb_dividend, s->mtb_divisor, s->ftb_div); + ctime = ddr3_adjust_ctime(ctime, s->ftb_div); + + ddrclk = 2 * 1000 * 1000 / ctime; + tbits = 1 << ((s->bus_width & 0x7) + 3); + pcclk = ddrclk * tbits / 8; + pcclk = pcclk - (pcclk % 100); /* Round down to comply with JEDEC */ + printf("%-48s %d MT/s (PC3-%d)\n", "Maximum module speed", ddrclk, pcclk); + + cap = (s->density_banks & 0xf) + 28 + (s->bus_width & 0x7) + 3 + - ((s->organization & 0x7) + 2) - (20 + 3); + k = (s->organization >> 3) + 1; + printf("%-48s %d MB\n", "Size", (1 << cap) * k); + + printf("%-48s %d x %d x %d x %d\n", "Banks x Rows x Columns x Bits", + 1 << (((s->density_banks >> 4) & 0x7) + 3), + (((s->addressing >> 3) & 0x1f) + 12), + ((s->addressing & 7) + 9), + (1 << ((s->bus_width & 0x7) + 3))); + + printf("%-48s %d\n", "Ranks", k); + + printf("%-48s %d bits\n", "SDRAM Device Width", + (1 << ((s->organization & 0x7) + 2))); + + printf("%-48s %d bits\n", "Primary Bus Width", + (8 << (s->bus_width & 0x7))); + if (s->bus_width & 0x18) + printf("%-48s %d bits\n", "Bus Width Extension", s->bus_width & 0x18); + + taa = ddr3_timing_from_mtb_ftb(s->taa_min, s->fine_taa_min, + s->mtb_dividend, s->mtb_divisor, s->ftb_div); + trcd = ddr3_timing_from_mtb_ftb(s->trcd_min, s->fine_trcd_min, + s->mtb_dividend, s->mtb_divisor, s->ftb_div); + trp = ddr3_timing_from_mtb_ftb(s->trp_min, s->fine_trp_min, + s->mtb_dividend, s->mtb_divisor, s->ftb_div); + tras = (((s->tras_trc_ext & 0xf) << 8) + s->tras_min_lsb) + * 1000 * s->mtb_dividend / s->mtb_divisor; + + printf("%-48s %d-%d-%d-%d\n", "tCL-tRCD-tRP-tRAS", + DIV_ROUND_UP(taa, ctime), DIV_ROUND_UP(trcd, ctime), + DIV_ROUND_UP(trp, ctime), DIV_ROUND_UP(tras, ctime)); + + printf("%-48s", "Supported CAS Latencies (tCL)"); + cas_sup = (s->caslat_msb << 8) + s->caslat_lsb; + for (i = 14; i >= 0; i--) { + if (cas_sup & (1 << i)) + printf(" %dT", i + 4); + } + printf("\n"); + + printf("\n---=== Timings at Standard Speeds ===---\n"); + + for (i = 0; i < ARRAY_SIZE(ddr3_std_speeds); i++) { + int ctime_at_speed = ddr3_std_speeds[i]; + int best_cas = 0; + int j; + + /* Find min CAS latency at this speed */ + for (j = 14; j >= 0; j--) { + if (!(cas_sup & (1 << j))) + continue; + if (DIV_ROUND_UP(taa, ctime_at_speed) <= j + 4) { + best_cas = j + 4; + } + } + + if (!best_cas || ctime_at_speed < ctime) + continue; + + printf("tCL-tRCD-tRP-tRAS as DDR3-%-4d %17s %d-%d-%d-%d\n", + 2000 * 1000 / ctime_at_speed, "", best_cas, + DIV_ROUND_UP(trcd, ctime_at_speed), + DIV_ROUND_UP(trp, ctime_at_speed), + DIV_ROUND_UP(tras, ctime_at_speed)); + } + + printf("\n---=== Timing Parameters ===---\n"); + + printf("%-48s %d.%03d ns\n", "Minimum Cycle Time (tCK)", + ctime / 1000, ctime % 1000); + printf("%-48s %d.%03d ns\n", "Minimum CAS Latency Time (tAA)", + taa / 1000, taa % 1000); + twr = s->twr_min * 1000 * s->mtb_dividend / s->mtb_divisor; + printf("%-48s %d.%03d ns\n", "Minimum Write Recovery time (tWR)", + twr / 1000, twr % 1000); + printf("%-48s %d.%03d ns\n", "Minimum RAS# to CAS# Delay (tRCD)", + trcd / 1000, trcd % 1000); + trrd = s->trrd_min * 1000 * s->mtb_dividend / s->mtb_divisor; + printf("%-48s %d.%03d ns\n", "Minimum Row Active to Row Active Delay (tRRD)", + trrd / 1000, trrd % 1000); + printf("%-48s %d.%03d ns\n", "Minimum Row Precharge Delay (tRP)", + trp / 1000, trp % 1000); + printf("%-48s %d.%03d ns\n", "Minimum Active to Precharge Delay (tRAS)", + tras / 1000, tras % 1000); + trc = ddr3_timing_from_mtb_ftb(((s->tras_trc_ext & 0xf0) << 4) + s->trc_min_lsb, + s->fine_trc_min, s->mtb_dividend, s->mtb_divisor, + s->ftb_div); + printf("%-48s %d.%03d ns\n", "Minimum Active to Auto-Refresh Delay (tRC)", + trc / 1000, trc % 1000); + trfc = ((s->trfc_min_msb << 8) + s->trfc_min_lsb) * 1000 + * s->mtb_dividend / s->mtb_divisor; + printf("%-48s %d.%03d ns\n", "Minimum Recovery Delay (tRFC)", + trfc / 1000, trfc % 1000); + twtr = s->twtr_min * 1000 * s->mtb_dividend / s->mtb_divisor; + printf("%-48s %d.%03d ns\n", "Minimum Write to Read CMD Delay (tWTR)", + twtr / 1000, twtr % 1000); + trtp = s->trtp_min * 1000 * s->mtb_dividend / s->mtb_divisor; + printf("%-48s %d.%03d ns\n", "Minimum Read to Pre-charge CMD Delay (tRTP)", + trtp / 1000, trtp % 1000); + tfaw = (((s->tfaw_msb & 0xf) << 8) + s->tfaw_min) * 1000 + * s->mtb_dividend / s->mtb_divisor; + printf("%-48s %d.%03d ns\n", "Minimum Four Activate Window Delay (tFAW)", + tfaw / 1000, tfaw % 1000); + + printf("\n---=== Optional Features ===---\n"); + + printf("%-48s 1.5V%s%s%s\n", "Operable voltages", + (s->module_vdd & 0x1) ? " tolerant" : "", + (s->module_vdd & 0x2) ? ", 1.35V" : "", + (s->module_vdd & 0x4) ? ", 1.2X V" : ""); + printf("%-48s %s\n", "RZQ/6 supported?", + (s->opt_features & 1) ? "Yes" : "No"); + printf("%-48s %s\n", "RZQ/7 supported?", + (s->opt_features & 2) ? "Yes" : "No"); + printf("%-48s %s\n", "DLL-Off Mode supported?", + (s->opt_features & 0x80) ? "Yes" : "No"); + printf("%-48s 0-%d degrees C\n", "Operating temperature range", + (s->therm_ref_opt & 0x1) ? 95 : 85); + if (s->therm_ref_opt & 0x1) + printf("%-48s %s\n", "Refresh Rate in extended temp range", + (s->therm_ref_opt & 0x2) ? "1X" : "2X"); + printf("%-48s %s\n", "Auto Self-Refresh?", + (s->therm_ref_opt & 0x4) ? "Yes" : "No"); + printf("%-48s %s\n", "On-Die Thermal Sensor readout?", + (s->therm_ref_opt & 0x8) ? "Yes" : "No"); + printf("%-48s %s\n", "Partial Array Self-Refresh?", + (s->therm_ref_opt & 0x80) ? "Yes" : "No"); + printf("%-48s %s\n", "Module Thermal Sensor", + (s->therm_sensor & 0x80) ? "Yes" : "No"); + + printf("%-48s %s\n", "SDRAM Device Type", + (s->device_type & 0x80) ? "Non-Standard" : "Standard Monolithic"); + + die_count = (s->device_type >> 4) & 0x7; + if (die_count == 1) + printf("%-48s Single die\n", ""); + else if (die_count == 2) + printf("%-48s 2 die\n", ""); + else if (die_count == 3) + printf("%-48s 4 die\n", ""); + else if (die_count == 4) + printf("%-48s 8 die\n", ""); + + loading = (s->device_type >> 2) & 0x3; + if (loading == 1) + printf("%-48s Multi load stack\n", ""); + else if (loading == 2) + printf("%-48s Single load stack\n", ""); + + mac = s->res_39_59[2] & 0xf; + if (mac < ARRAY_SIZE(ddr3_maximum_activated_counts)) + printf("%-48s %s\n", "Maximum Activate Count (MAC)", + ddr3_maximum_activated_counts[mac]); + + /* + * The following bytes are type-specific, so don't continue if the type + * is unknown. + */ + if (!s->module_type || s->module_type > ARRAY_SIZE(ddr3_spd_moduletypes)) + return; + + family = ddr3_spd_moduletypes_family[s->module_type]; + if (family == DDR3_UNBUFFERED || family == DDR3_REGISTERED + || family == DDR3_CLOCKED || family == DDR3_LOAD_REDUCED) { + printf("\n---=== Physical Characteristics ===---\n"); + printf("%-48s %d mm\n", "Module Height", + ((s->mod_section.unbuffered.mod_height & 0x1f) + 15)); + printf("%-48s %d mm front, %d mm back\n", "Module Thickness", + (s->mod_section.unbuffered.mod_thickness & 0xf) + 1, + ((s->mod_section.unbuffered.mod_thickness >> 4) & 0xf) + 1); + printf("%-48s %s\n", "Module Width", + ddr3_spd_moduletypes_width[s->module_type]); + ddr3_print_reference_card(s->mod_section.unbuffered.ref_raw_card, + s->mod_section.unbuffered.mod_height); + } + + if (family == DDR3_UNBUFFERED) + printf("%-48s %s\n", "Rank 1 Mapping", + (s->mod_section.unbuffered.addr_mapping) ? "Mirrored" : "Standard"); + + if (family == DDR3_REGISTERED) { + uint8_t rows = (s->mod_section.registered.modu_attr >> 2) & 0x3; + uint8_t registers = s->mod_section.registered.modu_attr & 0x3; + + printf("\n---=== Registered DIMM ===---\n"); + + if (!rows) + printf("%-48s Undefined\n", "# DRAM Rows"); + else + printf("%-48s %u\n", "# DRAM Rows", 1 << (rows - 1)); + + if (!registers) + printf("%-48s Undefined\n", "# Registers"); + else + printf("%-48s %u\n", "# Registers", 1 << (registers - 1)); + printf("%-48s 0x%02x%02x\n", "Register manufacturer ID", + s->mod_section.registered.reg_id_hi, + s->mod_section.registered.reg_id_lo); + printf("%-48s %s\n", "Register device type", + (!s->mod_section.registered.reg_type) ? "SSTE32882" : "Undefined"); + if (s->mod_section.registered.reg_rev != 0xff) + ddr3_print_revision_number("Register revision", + s->mod_section.registered.reg_rev); + printf("%-48s %s\n", "Heat spreader", + (s->mod_section.registered.thermal & 0x80) ? "Yes" : "No"); + } + + if (family == DDR3_LOAD_REDUCED) { + uint8_t modu_attr = s->mod_section.loadreduced.modu_attr; + uint8_t rows = (modu_attr >> 2) & 0x3; + static const char *mirroring[] = { + "None", "Odd ranks", "Reserved", "Reserved" + }; + + printf("\n---=== Load Reduced DIMM ===---\n"); + + if (!rows) + printf("%-48s Undefined\n", "# DRAM Rows"); + else if (rows == 0x3) + printf("%-48s Reserved\n", "# DRAM Rows"); + else + printf("%-48s %u\n", "# DRAM Rows", 1 << (rows - 1)); + + printf("%-48s %s\n", "Mirroring", + mirroring[modu_attr & 0x3]); + + printf("%-48s %s\n", "Rank Numbering", + (modu_attr & 0x20) ? "Even only" : "Contiguous"); + printf("%-48s %s\n", "Buffer Orientation", + (modu_attr & 0x10) ? "Horizontal" : "Vertical"); + printf("%-48s 0x%02x%02x\n", "Register Manufacturer ID", + s->mod_section.loadreduced.buf_id_hi, + s->mod_section.loadreduced.buf_id_lo); + if (s->mod_section.loadreduced.buf_rev_id != 0xff) + ddr3_print_revision_number("Buffer Revision", + s->mod_section.loadreduced.buf_rev_id); + printf("%-48s %s\n", "Heat spreader", + (s->mod_section.loadreduced.modu_attr & 0x80) ? "Yes" : "No"); + } + + printf("\n---=== Manufacturer Data ===---\n"); + + printf("%-48s 0x%02x%02x\n", "Module Manufacturer ID", + s->mmid_msb, s->mmid_lsb); + + if (!((s->dmid_lsb == 0xff) && (s->dmid_msb == 0xff)) + && !((s->dmid_lsb == 0x0) && (s->dmid_msb == 0x0))) + printf("%-48s 0x%02x%02x\n", "DRAM Manufacturer ID", + s->dmid_msb, s->dmid_lsb); + + if (!(s->mloc == 0xff) && !(s->mloc == 0x0)) + printf("%-48s 0x%02x\n", "Manufacturing Location Code", + s->mloc); + + if (!((s->mdate[0] == 0xff) && (s->mdate[1] == 0xff)) + && !((s->mdate[0] == 0x0) && (s->mdate[1] == 0x0))) + spd_print_manufacturing_date(s->mdate[0], s->mdate[1]); + + if ((s->sernum[0] != s->sernum[1]) + && (s->sernum[0] != s->sernum[2]) + && (s->sernum[1] != s->sernum[3]) + && ((s->sernum[0] != 0xff) || (s->sernum[0] != 0x0))) + printf("%-48s 0x%02X%02X%02X%02X\n", "Assembly Serial Number", + s->sernum[0], s->sernum[1], s->sernum[2], s->sernum[3]); + + printf("%-48s ", "Part Number"); + if (!(s->mpart[0] >= 32 && s->mpart[0] < 127)) { + printf("Undefined\n"); + } else { + for (i = 0; i < ARRAY_SIZE(s->mpart); i++) { + if (s->mpart[i] >= 32 && s->mpart[i] < 127) + printf("%c", s->mpart[i]); + else + break; + } + printf("\n"); + } + + if (!((s->mrev[0] == 0xff) && (s->mrev[1] == 0xff)) + && !((s->mrev[0] == 0x0) && (s->mrev[1] == 0x0))) + printf("%-48s 0x%02X%02X\n", "Revision Code", s->mrev[0], s->mrev[1]); +} + +void ddr_spd_print(uint8_t *record) +{ + uint8_t mem_type = record[2]; + + switch (mem_type) { + case SPD_MEMTYPE_DDR2: + ddr2_spd_print(record); + break; + case SPD_MEMTYPE_DDR3: + ddr3_spd_print(record); + break; + default: + printf("Can only dump SPD information for DDR2 and DDR3 memory types\n"); + } +} + #define SPD_SPA0_ADDRESS 0x36 #define SPD_SPA1_ADDRESS 0x37 diff --git a/common/fastboot.c b/common/fastboot.c index f5a275d8bf..d8dabd89ab 100644 --- a/common/fastboot.c +++ b/common/fastboot.c @@ -955,6 +955,11 @@ bool get_fastboot_bbu(void) return fastboot_bbu; } +void set_fastboot_bbu(unsigned int enable) +{ + fastboot_bbu = enable; +} + struct file_list *get_fastboot_partitions(void) { if (fastboot_partitions && *fastboot_partitions) diff --git a/common/image-fit.c b/common/image-fit.c index b16752de05..251fda97b3 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -715,7 +715,8 @@ static int fit_config_verify_signature(struct fit_handle *handle, struct device_ return ret; } -static int fit_find_compatible_unit(struct device_node *conf_node, +static int fit_find_compatible_unit(struct fit_handle *handle, + struct device_node *conf_node, const char **unit) { struct device_node *child = NULL; @@ -734,6 +735,40 @@ static int fit_find_compatible_unit(struct device_node *conf_node, for_each_child_of_node(conf_node, child) { int score = of_device_is_compatible(child, machine); + + if (!score && !of_property_present(child, "compatible") && + of_property_present(child, "fdt")) { + struct device_node *image; + const char *unit = "fdt"; + int data_len; + const void *data; + int ret; + + ret = fit_get_image(handle, child, &unit, &image); + if (ret) + goto next; + + data = of_get_property(image, "data", &data_len); + if (!data) { + ret = -EINVAL; + goto next; + } + + ret = fit_handle_decompression(image, "fdt", &data, &data_len); + if (ret) { + ret = -EILSEQ; + goto next; + } + + score = fdt_machine_is_compatible(data, data_len, machine); + + of_delete_property_by_name(image, "uncompressed-data"); +next: + if (ret) + pr_warn("skipping malformed configuration: %pOF (%pe)\n", + child, ERR_PTR(ret)); + } + if (score > best_score) { best_score = score; *unit = child->name; @@ -779,7 +814,7 @@ void *fit_open_configuration(struct fit_handle *handle, const char *name) if (name) { unit = name; } else { - ret = fit_find_compatible_unit(conf_node, &unit); + ret = fit_find_compatible_unit(handle, conf_node, &unit); if (ret) { pr_info("Couldn't get a valid configuration. Aborting.\n"); return ERR_PTR(ret); diff --git a/common/startup.c b/common/startup.c index 522e2de755..47b70a7756 100644 --- a/common/startup.c +++ b/common/startup.c @@ -175,7 +175,8 @@ enum autoboot_state do_autoboot_countdown(void) if (autoboot_state != AUTOBOOT_UNKNOWN) return autoboot_state; - if (!console_get_first_active()) { + if (!console_get_first_active() && + global_autoboot_state != AUTOBOOT_ABORT) { printf("\nNon-interactive console, booting system\n"); return autoboot_state = AUTOBOOT_BOOT; } diff --git a/common/version.c b/common/version.c index 465e22c7f5..0cac5ee609 100644 --- a/common/version.c +++ b/common/version.c @@ -22,7 +22,7 @@ void barebox_banner (void) printf("\n\n"); pr_info("%s\n", version_string); if (strlen(buildsystem_version_string) > 0) - pr_info("Buildsystem version: %s", buildsystem_version_string); + pr_info("Buildsystem version: %s\n", buildsystem_version_string); printf("\n\n"); pr_info("Board: %s\n", barebox_get_model()); } diff --git a/drivers/dma/debug.c b/drivers/dma/debug.c index b3bfbff9b2..e524dc4127 100644 --- a/drivers/dma/debug.c +++ b/drivers/dma/debug.c @@ -12,6 +12,7 @@ struct dma_debug_entry { dma_addr_t dev_addr; size_t size; int direction; + bool dev_owned; }; static const char *dir2name[] = { @@ -121,6 +122,7 @@ void debug_dma_map(struct device *dev, void *addr, entry->dev_addr = dev_addr; entry->size = size; entry->direction = direction; + entry->dev_owned = true; list_add(&entry->list, &dma_mappings); @@ -159,9 +161,17 @@ void debug_dma_sync_single_for_cpu(struct device *dev, struct dma_debug_entry *entry; entry = dma_debug_entry_find(dev, dma_handle, size); - if (!entry) + if (!entry) { dma_dev_warn(dev, "sync for CPU of never-mapped %s buffer 0x%llx+0x%zx!\n", dir2name[direction], (u64)dma_handle, size); + return; + } + + if (!entry->dev_owned) + dma_dev_warn(dev, "unexpected sync for CPU of already CPU-mapped %s buffer 0x%llx+0x%zx!\n", + dir2name[direction], (u64)dma_handle, size); + + entry->dev_owned = false; } void debug_dma_sync_single_for_device(struct device *dev, @@ -177,7 +187,15 @@ void debug_dma_sync_single_for_device(struct device *dev, * corruption */ entry = dma_debug_entry_find(dev, dma_handle, size); - if (!entry) + if (!entry) { dma_dev_warn(dev, "Syncing for device of never-mapped %s buffer 0x%llx+0x%zx!\n", dir2name[direction], (u64)dma_handle, size); + return; + } + + if (entry->dev_owned) + dma_dev_warn(dev, "unexpected sync for device of already device-mapped %s buffer 0x%llx+0x%zx!\n", + dir2name[direction], (u64)dma_handle, size); + + entry->dev_owned = true; } diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index cee60f7a65..e303f6b21f 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -475,6 +475,8 @@ static int pca953x_probe(struct device *dev) if (ret) return ret; + slice_depends_on(gpiochip_slice(&chip->gpio_chip), i2c_client_slice(client)); + if (pdata && pdata->setup) { ret = pdata->setup(client, chip->gpio_chip.base, chip->gpio_chip.ngpio, pdata->context); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index bcfdd5a0dd..5bc261a010 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -172,6 +172,16 @@ int gpio_request(unsigned gpio, const char *label) return gpiodesc_request(desc, label); } +bool gpio_slice_acquired(unsigned gpio) +{ + struct gpio_desc *desc = gpio_to_desc(gpio); + + if (!desc) + return false; + + return slice_acquired(&desc->chip->slice); +} + static void gpiodesc_free(struct gpio_desc *desc) { if (!desc->requested) @@ -1013,6 +1023,7 @@ int gpiochip_add(struct gpio_chip *chip) return -ENOSPC; } + slice_init(&chip->slice, dev_name(chip->dev)); list_add_tail(&chip->list, &chip_list); diff --git a/drivers/input/gpio_keys.c b/drivers/input/gpio_keys.c index 77013be133..c23d20563c 100644 --- a/drivers/input/gpio_keys.c +++ b/drivers/input/gpio_keys.c @@ -29,24 +29,25 @@ struct gpio_keys { struct gpio_key *buttons; int nbuttons; - struct poller_struct poller; + struct poller_async poller; struct input_device input; struct device *dev; }; -static inline struct gpio_keys * -poller_to_gk_pdata(struct poller_struct *poller) +static void gpio_key_poller(void *data) { - return container_of(poller, struct gpio_keys, poller); -} - -static void gpio_key_poller(struct poller_struct *poller) -{ - struct gpio_keys *gk = poller_to_gk_pdata(poller); + struct gpio_keys *gk = data; struct gpio_key *gb; int i, val; for (i = 0; i < gk->nbuttons; i++) { + gb = &gk->buttons[i]; + + if (gpio_slice_acquired(gb->gpio)) + goto out; + } + + for (i = 0; i < gk->nbuttons; i++) { gb = &gk->buttons[i]; val = gpio_get_value(gb->gpio); @@ -64,6 +65,8 @@ static void gpio_key_poller(struct poller_struct *poller) gb->previous_state = val; } } +out: + poller_call_async(&gk->poller, 10 * MSECOND, gpio_key_poller, gk); } static int gpio_keys_probe_pdata(struct gpio_keys *gk, struct device *dev) @@ -159,16 +162,16 @@ static int __init gpio_keys_probe(struct device *dev) gk->buttons[i].previous_state = gk->buttons[i].active_low; } - gk->poller.func = gpio_key_poller; - ret = input_device_register(&gk->input); if (ret) return ret; - ret = poller_register(&gk->poller, dev_name(dev)); + ret = poller_async_register(&gk->poller, dev_name(dev)); if (ret) return ret; + poller_call_async(&gk->poller, 10 * MSECOND, gpio_key_poller, gk); + return 0; } diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c index 59afac7372..973e08779d 100644 --- a/drivers/mci/arasan-sdhci.c +++ b/drivers/mci/arasan-sdhci.c @@ -147,6 +147,7 @@ static int arasan_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, { struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); u32 mask, command, xfer; + dma_addr_t dma; int ret; ret = sdhci_wait_idle(&host->sdhci, cmd); @@ -156,13 +157,14 @@ static int arasan_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); mask = SDHCI_INT_CMD_COMPLETE; - if (data && data->flags == MMC_DATA_READ) - mask |= SDHCI_INT_DATA_AVAIL; if (cmd->resp_type & MMC_RSP_BUSY) mask |= SDHCI_INT_XFER_COMPLETE; - sdhci_set_cmd_xfer_mode(&host->sdhci, - cmd, data, false, &command, &xfer); + sdhci_setup_data_dma(&host->sdhci, data, &dma); + + sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, + dma == SDHCI_NO_DMA ? false : true, + &command, &xfer); sdhci_write8(&host->sdhci, SDHCI_TIMEOUT_CONTROL, TIMEOUT_VAL); if (data) { @@ -174,15 +176,15 @@ static int arasan_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); sdhci_write16(&host->sdhci, SDHCI_COMMAND, command); - ret = sdhci_wait_for_done(&host->sdhci, mask); + ret = sdhci_wait_for_done(&host->sdhci, SDHCI_INT_CMD_COMPLETE); if (ret) goto error; sdhci_read_response(&host->sdhci, cmd); - sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, mask); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, SDHCI_INT_CMD_COMPLETE); if (data) - ret = sdhci_transfer_data_pio(&host->sdhci, data); + ret = sdhci_transfer_data_dma(&host->sdhci, data, dma); error: if (ret) { diff --git a/drivers/mci/dwcmshc-sdhci.c b/drivers/mci/dwcmshc-sdhci.c index 0251a83a02..7b367e02ee 100644 --- a/drivers/mci/dwcmshc-sdhci.c +++ b/drivers/mci/dwcmshc-sdhci.c @@ -9,11 +9,16 @@ #include <dma.h> #include <malloc.h> #include <mci.h> +#include <of_device.h> #include <linux/err.h> #include <linux/clk.h> #include "sdhci.h" +#define tx_delay_static_cfg(delay) (delay << 5) +#define tx_tuning_clk_sel(delay) (delay) + +#define DWCMSHC_GPIO_OUT 0x34 /* offset from vendor specific area */ #define CARD_STATUS_MASK (0x1e00) #define CARD_STATUS_TRAN (4 << 9) @@ -22,6 +27,12 @@ static int do_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_dat struct dwcmshc_host { struct mci_host mci; struct sdhci sdhci; + int vendor_specific_area; + const struct dwcmshc_callbacks *cb; +}; + +struct dwcmshc_callbacks { + void (*init)(struct mci_host *mci, struct device *dev); }; static inline struct dwcmshc_host *priv_from_mci_host(struct mci_host *h) @@ -252,6 +263,9 @@ static int dwcmshc_mci_init(struct mci_host *mci, struct device *dev) dev_dbg(host->mci.hw_dev, "host version4: %s\n", ctrl2 & SDHCI_CTRL_V4_MODE ? "enabled" : "disabled"); + if (host->cb && host->cb->init) + host->cb->init(mci, dev); + return 0; } @@ -283,6 +297,8 @@ static void dwcmshc_set_dma_mask(struct device *dev) static int dwcmshc_probe(struct device *dev) { + const struct dwcmshc_callbacks *dwcmshc_cb = + of_device_get_match_data(dev); struct dwcmshc_host *host; struct resource *iores; struct mci_host *mci; @@ -308,6 +324,7 @@ static int dwcmshc_probe(struct device *dev) host->sdhci.base = IOMEM(iores->start); host->sdhci.mci = mci; host->sdhci.max_clk = clk_get_rate(clk); + host->cb = dwcmshc_cb; mci->hw_dev = dev; mci->init = dwcmshc_mci_init; @@ -315,14 +332,17 @@ static int dwcmshc_probe(struct device *dev) mci->send_cmd = dwcmshc_mci_send_cmd; mci->card_present = dwcmshc_mci_card_present; - mci_of_parse(&host->mci); - - /* Enable host_version4 */ - sdhci_enable_v4_mode(&host->sdhci); sdhci_setup_host(&host->sdhci); mci->max_req_size = 0x8000; + /* + * Let's first initialize f_max to the DT clock freq + * Then mci_of_parse can override if with the content + * of the 'max-frequency' DT property if it is present. + * Then we can finish by computing the f_min. + */ mci->f_max = clk_get_rate(clk); + mci_of_parse(&host->mci); mci->f_min = mci->f_max / SDHCI_MAX_DIV_SPEC_300; dev->priv = host; @@ -333,6 +353,10 @@ static int dwcmshc_probe(struct device *dev) dev_dbg(host->mci.hw_dev, "host controller version: %u\n", host->sdhci.version); + host->vendor_specific_area = sdhci_read32(&host->sdhci, + SDHCI_P_VENDOR_SPEC_AREA); + host->vendor_specific_area &= SDHCI_P_VENDOR_SPEC_AREA_MASK; + ret = mci_register(&host->mci); if (ret) goto err_register; @@ -350,8 +374,23 @@ err_mem_req: return ret; } +static void dwcmshc_coolidgev2_init(struct mci_host *mci, struct device *dev) +{ + struct dwcmshc_host *host = priv_from_mci_host(mci); + + /* configure TX delay to set correct setup/hold for Coolidge V2 */ + sdhci_write32(&host->sdhci, + host->vendor_specific_area + DWCMSHC_GPIO_OUT, + tx_delay_static_cfg(0xf) | tx_tuning_clk_sel(4)); +} + +struct dwcmshc_callbacks kalray_coolidgev2_callbacks = { + .init = dwcmshc_coolidgev2_init, +}; + static struct of_device_id dwcmshc_dt_ids[] = { { .compatible = "snps,dwcmshc-sdhci", }, + { .compatible = "kalray,coolidge-v2-dwcmshc-sdhci", .data = &kalray_coolidgev2_callbacks }, { } }; diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index bd9083b9f7..aa222ea1bc 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -1295,6 +1295,7 @@ static int mci_mmc_select_hs_ddr(struct mci *mci) if (ret < 0) return mci_mmc_try_bus_width(mci, host->bus_width, MMC_TIMING_MMC_HS); + /* Block length is fixed to 512 bytes while in DDR mode */ mci->read_bl_len = SECTOR_SIZE; mci->write_bl_len = SECTOR_SIZE; diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index 2139498855..73d1b35274 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -165,6 +165,8 @@ #define SDHCI_PRESET_CLKGEN_SEL BIT(10) #define SDHCI_PRESET_SDCLK_FREQ_MASK GENMASK(9, 0) +#define SDHCI_P_VENDOR_SPEC_AREA 0xE8 +#define SDHCI_P_VENDOR_SPEC_AREA_MASK GENMASK(11, 0) #define SDHCI_HOST_VERSION 0xFE #define SDHCI_VENDOR_VER_MASK 0xFF00 #define SDHCI_VENDOR_VER_SHIFT 8 diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c index 42fb32bde2..31ca61a230 100644 --- a/drivers/net/cpsw.c +++ b/drivers/net/cpsw.c @@ -215,6 +215,8 @@ struct cpsw_priv { unsigned int slave_size; unsigned int sliver_ofs; + void *rx_buffer[PKTBUFSRX - 2]; + struct cpdma_desc *descs; struct cpdma_desc *desc_free; struct cpdma_chan rx_chan, tx_chan; @@ -802,7 +804,8 @@ static void cpdma_desc_free(struct cpsw_priv *priv, struct cpdma_desc *desc) } static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan, - void *buffer, int len, int port) + void *sw_buffer, dma_addr_t hw_buffer, + int len, int port) { struct cpdma_desc *desc, *prev; u32 mode; @@ -821,10 +824,10 @@ static int cpdma_submit(struct cpsw_priv *priv, struct cpdma_chan *chan, (port << CPDMA_FROM_TO_PORT_SHIFT); writel(0, &desc->hw_next); - writel((u32)buffer, &desc->hw_buffer); + writel(hw_buffer, &desc->hw_buffer); writel(len, &desc->hw_len); writel(mode | len, &desc->hw_mode); - writel((u32)buffer, &desc->sw_buffer); + writel((u32)sw_buffer, &desc->sw_buffer); writel((u32)len, &desc->sw_len); if (!chan->head) { @@ -851,7 +854,7 @@ done: } static int cpdma_process(struct cpsw_slave *slave, struct cpdma_chan *chan, - void **buffer, int *len) + void **buffer, dma_addr_t *dma, int *len) { struct cpdma_desc *desc = chan->head; struct cpsw_priv *priv = slave->cpsw; @@ -865,6 +868,8 @@ static int cpdma_process(struct cpsw_slave *slave, struct cpdma_chan *chan, if (len) *len = status & 0x7ff; + if (dma) + *dma = readl(&desc->hw_buffer); if (buffer) *buffer = (void *)readl(&desc->sw_buffer); @@ -980,8 +985,15 @@ static int cpsw_setup(struct device *dev) /* submit rx descs */ for (i = 0; i < PKTBUFSRX - 2; i++) { - ret = cpdma_submit(priv, &priv->rx_chan, NetRxPackets[i], - PKTSIZE, 0); + void *buffer = priv->rx_buffer[i]; + unsigned len = PKTSIZE; + dma_addr_t dma; + + dma = dma_map_single(priv->dev, buffer, len, DMA_FROM_DEVICE); + if (dma_mapping_error(priv->dev, dma)) + return -EFAULT; + + ret = cpdma_submit(priv, &priv->rx_chan, buffer, dma, len, 0); if (ret < 0) { dev_err(dev, "error %d submitting rx desc\n", ret); break; @@ -1012,20 +1024,21 @@ static int cpsw_send(struct eth_device *edev, void *packet, int length) { struct cpsw_slave *slave = edev->priv; struct cpsw_priv *priv = slave->cpsw; - void *buffer; - int ret, len; + dma_addr_t dma; + int ret; dev_dbg(&slave->dev, "* %s slave %d\n", __func__, slave->slave_num); /* first reap completed packets */ - while (cpdma_process(slave, &priv->tx_chan, &buffer, &len) >= 0); + while (cpdma_process(slave, &priv->tx_chan, NULL, NULL, NULL) >= 0) + ; dev_dbg(&slave->dev, "%s: %i bytes @ 0x%p\n", __func__, length, packet); - dma_sync_single_for_device(priv->dev, (unsigned long)packet, length, DMA_TO_DEVICE); - ret = cpdma_submit(priv, &priv->tx_chan, packet, + dma = dma_map_single(priv->dev, packet, length, DMA_TO_DEVICE); + ret = cpdma_submit(priv, &priv->tx_chan, packet, dma, length, BIT(slave->slave_num)); - dma_sync_single_for_cpu(priv->dev, (unsigned long)packet, length, DMA_TO_DEVICE); + dma_unmap_single(priv->dev, dma, length, DMA_TO_DEVICE); return ret; } @@ -1034,16 +1047,15 @@ static int cpsw_recv(struct eth_device *edev) { struct cpsw_slave *slave = edev->priv; struct cpsw_priv *priv = slave->cpsw; + dma_addr_t dma; void *buffer; int len; - while (cpdma_process(slave, &priv->rx_chan, &buffer, &len) >= 0) { - dma_sync_single_for_cpu(priv->dev, (unsigned long)buffer, len, - DMA_FROM_DEVICE); + while (cpdma_process(slave, &priv->rx_chan, &buffer, &dma, &len) >= 0) { + dma_sync_single_for_cpu(priv->dev, dma, len, DMA_FROM_DEVICE); net_receive(edev, buffer, len); - dma_sync_single_for_device(priv->dev, (unsigned long)buffer, len, - DMA_FROM_DEVICE); - cpdma_submit(priv, &priv->rx_chan, buffer, PKTSIZE, 0); + dma_sync_single_for_device(priv->dev, dma, len, DMA_FROM_DEVICE); + cpdma_submit(priv, &priv->rx_chan, buffer, dma, PKTSIZE, 0); } return 0; @@ -1350,6 +1362,10 @@ static int cpsw_probe(struct device *dev) priv = xzalloc(sizeof(*priv)); priv->dev = dev; + ret = net_alloc_packets(priv->rx_buffer, ARRAY_SIZE(priv->rx_buffer)); + if (ret) + goto out; + if (dev->of_node) { ret = cpsw_probe_dt(priv); if (ret) diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index 51556ae013..9455c6f5ea 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c @@ -46,6 +46,7 @@ struct enc28j60_net { /* store MAC address here while hardware is in the reset state */ u8 hwaddr[ETH_ALEN]; struct mii_bus miibus; + void *rx_buffer; }; /* @@ -793,9 +794,9 @@ static void enc28j60_hw_rx(struct eth_device *edev) /* copy the packet from the receive buffer */ enc28j60_mem_read(priv, rx_packet_start(priv->next_pk_ptr), - len, NetRxPackets[0]); + len, priv->rx_buffer); - net_receive(edev, NetRxPackets[0], len); + net_receive(edev, priv->rx_buffer, len); } /* @@ -931,6 +932,7 @@ static int enc28j60_probe(struct device *dev) priv = xzalloc(sizeof(*priv)); priv->spi = (struct spi_device *)dev->type_data; + priv->rx_buffer = net_alloc_packet(); edev = &priv->edev; edev->priv = priv; diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c index 77f8aa63db..bd954e7a17 100644 --- a/drivers/net/ep93xx.c +++ b/drivers/net/ep93xx.c @@ -62,7 +62,7 @@ static void dump_dev(struct eth_device *edev) printf(" rx_sq.end %p\n", priv->rx_sq.end); for (i = 0; i < NUMRXDESC; i++) - printf(" rx_buffer[%2.d] %p\n", i, NetRxPackets[i]); + printf(" rx_buffer[%2.d] %p\n", i, priv->rx_buffer[i]); printf(" tx_dq.base %p\n", priv->tx_dq.base); printf(" tx_dq.current %p\n", priv->tx_dq.current); @@ -258,7 +258,7 @@ static int ep93xx_eth_open(struct eth_device *edev) */ for (i = 0; i < NUMRXDESC; i++) { /* set buffer address */ - (priv->rx_dq.base + i)->word1 = (uint32_t)NetRxPackets[i]; + (priv->rx_dq.base + i)->word1 = (uint32_t)priv->rx_buffer[i]; /* set buffer length, clear buffer index and NSOF */ (priv->rx_dq.base + i)->word2 = EP93XX_MAX_PKT_SIZE; @@ -324,7 +324,7 @@ static int ep93xx_eth_rcv_packet(struct eth_device *edev) /* * We have a good frame. Extract the frame's length * from the current rx_status_queue entry, and copy - * the frame's data into NetRxPackets[] of the + * the frame's data into priv->rx_buffer of the * protocol stack. We track the total number of * bytes in the frame (nbytes_frame) which will be * used when we pass the data off to the protocol @@ -532,6 +532,12 @@ static int ep93xx_eth_probe(struct device *dev) goto eth_probe_failed_3; } + ret = net_alloc_packets(priv->rx_buffer, NUMRXDESC); + if (ret) { + pr_err("net_alloc_packet() failed: rx_buffer"); + goto eth_probe_failed_4; + } + mdiobus_register(&priv->miibus); eth_register(edev); @@ -539,6 +545,10 @@ static int ep93xx_eth_probe(struct device *dev) goto eth_probe_done; +eth_probe_failed_4: + free(priv->rx_sq.base); + /* Fall through */ + eth_probe_failed_3: free(priv->rx_dq.base); /* Fall through */ diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index c878f498a4..a31d3bb521 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -178,6 +178,8 @@ struct ethoc { u32 cur_rx; struct mii_bus miibus; + + void *rx_buffer[PKTBUFSRX]; }; /** @@ -266,7 +268,7 @@ static int ethoc_init_ring(struct ethoc *dev) if (i == dev->num_rx - 1) bd.stat |= RX_BD_WRAP; - bd.addr = (u32)NetRxPackets[i]; + bd.addr = (u32)dev->rx_buffer[i]; ethoc_write_bd(dev, dev->num_tx + i, &bd); flush_dcache_range(bd.addr, bd.addr + PKTSIZE); @@ -534,12 +536,18 @@ static int ethoc_probe(struct device *dev) struct resource *iores; struct eth_device *edev; struct ethoc *priv; + int ret; edev = xzalloc(sizeof(struct eth_device) + sizeof(struct ethoc)); edev->priv = (struct ethoc *)(edev + 1); priv = edev->priv; + + ret = net_alloc_packets(priv->rx_buffer, ARRAY_SIZE(priv->rx_buffer)); + if (ret) + return ret; + iores = dev_request_mem_resource(dev, 0); if (IS_ERR(iores)) return PTR_ERR(iores); diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 1a07059db4..21ffe822e1 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -21,11 +21,6 @@ #include <linux/err.h> #include "gianfar.h" -/* 2 seems to be the minimum number of TX descriptors to make it work. */ -#define TX_BUF_CNT 2 -#define RX_BUF_CNT PKTBUFSRX -#define BUF_ALIGN 8 - /* * Initialize required registers to appropriate values, zeroing * those we don't care about (unless zero is bad, in which case, @@ -199,7 +194,7 @@ static int gfar_open(struct eth_device *edev) for (ix = 0; ix < RX_BUF_CNT; ix++) { out_be16(&priv->rxbd[ix].status, RXBD_EMPTY); out_be16(&priv->rxbd[ix].length, 0); - out_be32(&priv->rxbd[ix].bufPtr, (uint) NetRxPackets[ix]); + out_be32(&priv->rxbd[ix].bufPtr, (uint) priv->rx_buffer[ix]); } out_be16(&priv->rxbd[RX_BUF_CNT - 1].status, RXBD_EMPTY | RXBD_WRAP); @@ -407,7 +402,7 @@ static int gfar_recv(struct eth_device *edev) /* Send the packet up if there were no errors */ status = in_be16(&priv->rxbd[priv->rxidx].status); if (!(status & RXBD_STATS)) - net_receive(edev, NetRxPackets[priv->rxidx], length - 4); + net_receive(edev, priv->rx_buffer[priv->rxidx], length - 4); else dev_err(dev, "Got error %x\n", status & RXBD_STATS); @@ -471,9 +466,14 @@ static int gfar_probe(struct device *dev) size_t size; char devname[16]; char *p; + int ret; priv = xzalloc(sizeof(struct gfar_private)); + ret = net_alloc_packets(priv->rx_buffer, ARRAY_SIZE(priv->rx_buffer)); + if (ret) + return ret; + edev = &priv->edev; priv->mdiobus_tbi = gfar_info->mdiobus_tbi; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index cea41218a7..8a60c7f38e 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -265,6 +265,11 @@ struct gfar_phy { struct mii_bus miibus; }; +/* 2 seems to be the minimum number of TX descriptors to make it work. */ +#define TX_BUF_CNT 2 +#define RX_BUF_CNT PKTBUFSRX +#define BUF_ALIGN 8 + struct gfar_private { struct eth_device edev; void __iomem *regs; @@ -282,5 +287,6 @@ struct gfar_private { uint link; uint duplexity; uint speed; + void *rx_buffer[PKTBUFSRX]; }; #endif /* __GIANFAR_H */ diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index cf08fa1cfd..8dca41990c 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -43,9 +43,9 @@ static inline uint32_t dt_struct_advance(struct fdt_header *f, uint32_t dt, int return dt; } -static inline char *dt_string(struct fdt_header *f, char *strstart, uint32_t ofs) +static inline const char *dt_string(struct fdt_header *f, const char *strstart, uint32_t ofs) { - char *str; + const char *str; if (ofs > f->size_dt_strings) return NULL; @@ -115,6 +115,44 @@ static int of_unflatten_reservemap(struct device_node *root, return 0; } +static int fdt_parse_header(const struct fdt_header *fdt, size_t fdt_size, + struct fdt_header *out) +{ + if (fdt_size < sizeof(struct fdt_header)) + return -EINVAL; + + if (fdt->magic != cpu_to_fdt32(FDT_MAGIC)) { + pr_err("bad magic: 0x%08x\n", fdt32_to_cpu(fdt->magic)); + return -EINVAL; + } + + if (fdt->version != cpu_to_fdt32(17)) { + pr_err("bad dt version: 0x%08x\n", fdt32_to_cpu(fdt->version)); + return -EINVAL; + } + + out->totalsize = fdt32_to_cpu(fdt->totalsize); + out->off_dt_struct = fdt32_to_cpu(fdt->off_dt_struct); + out->size_dt_struct = fdt32_to_cpu(fdt->size_dt_struct); + out->off_dt_strings = fdt32_to_cpu(fdt->off_dt_strings); + out->size_dt_strings = fdt32_to_cpu(fdt->size_dt_strings); + + if (out->totalsize > fdt_size) + return -EINVAL; + + if (size_add(out->off_dt_struct, out->size_dt_struct) > out->totalsize) { + pr_err("unflatten: dt size exceeds total size\n"); + return -ESPIPE; + } + + if (size_add(out->off_dt_strings, out->size_dt_strings) > out->totalsize) { + pr_err("unflatten: string size exceeds total size\n"); + return -ESPIPE; + } + + return 0; +} + /** * of_unflatten_dtb - unflatten a dtb binary blob * @infdt - the fdt blob to unflatten @@ -140,37 +178,9 @@ static struct device_node *__of_unflatten_dtb(const void *infdt, int size, unsigned int maxlen; const struct fdt_header *fdt = infdt; - if (size < sizeof(struct fdt_header)) - return ERR_PTR(-EINVAL); - - if (fdt->magic != cpu_to_fdt32(FDT_MAGIC)) { - pr_err("bad magic: 0x%08x\n", fdt32_to_cpu(fdt->magic)); - return ERR_PTR(-EINVAL); - } - - if (fdt->version != cpu_to_fdt32(17)) { - pr_err("bad dt version: 0x%08x\n", fdt32_to_cpu(fdt->version)); - return ERR_PTR(-EINVAL); - } - - f.totalsize = fdt32_to_cpu(fdt->totalsize); - f.off_dt_struct = fdt32_to_cpu(fdt->off_dt_struct); - f.size_dt_struct = fdt32_to_cpu(fdt->size_dt_struct); - f.off_dt_strings = fdt32_to_cpu(fdt->off_dt_strings); - f.size_dt_strings = fdt32_to_cpu(fdt->size_dt_strings); - - if (f.totalsize > size) - return ERR_PTR(-EINVAL); - - if (size_add(f.off_dt_struct, f.size_dt_struct) > f.totalsize) { - pr_err("unflatten: dt size exceeds total size\n"); - return ERR_PTR(-ESPIPE); - } - - if (size_add(f.off_dt_strings, f.size_dt_strings) > f.totalsize) { - pr_err("unflatten: string size exceeds total size\n"); - return ERR_PTR(-ESPIPE); - } + ret = fdt_parse_header(infdt, size, &f); + if (ret < 0) + return ERR_PTR(ret); dt_struct = f.off_dt_struct; dt_strings = (void *)fdt + f.off_dt_strings; @@ -658,3 +668,109 @@ void fdt_print_reserve_map(const void *__fdt) return; } } + +static int fdt_string_is_compatible(const char *haystack, int haystack_len, + const char *needle, int needle_len) +{ + const char *p; + int index = 0; + + while (haystack_len >= needle_len) { + if (memcmp(needle, haystack, needle_len + 1) == 0) + return OF_DEVICE_COMPATIBLE_MAX_SCORE - (index << 2); + + p = memchr(haystack, '\0', haystack_len); + if (!p) + return 0; + haystack_len -= (p - haystack) + 1; + haystack = p + 1; + index++; + } + + return 0; +} + +int fdt_machine_is_compatible(const struct fdt_header *fdt, size_t fdt_size, const char *compat) +{ + uint32_t tag; + const struct fdt_property *fdt_prop; + const char *name; + uint32_t dt_struct; + const struct fdt_node_header *fnh; + const void *dt_strings; + struct fdt_header f; + int ret, len; + int expect = FDT_BEGIN_NODE; + int compat_len = strlen(compat); + + ret = fdt_parse_header(fdt, fdt_size, &f); + if (ret < 0) + return 0; + + dt_struct = f.off_dt_struct; + dt_strings = (const void *)fdt + f.off_dt_strings; + + while (1) { + const __be32 *tagp = (const void *)fdt + dt_struct; + if (!dt_ptr_ok(fdt, tagp)) + return 0; + + tag = be32_to_cpu(*tagp); + if (tag != FDT_NOP && tag != expect) + return 0; + + switch (tag) { + case FDT_BEGIN_NODE: + fnh = (const void *)fdt + dt_struct; + + /* The root node must have an empty name */ + if (fnh->name[0] != '\0') + return 0; + + dt_struct = dt_struct_advance(&f, dt_struct, + sizeof(struct fdt_node_header) + 1); + + /* + * Quoting Device Tree Specification v0.4 ยง5.4.2: + * + * [T]his process requires that all property definitions for + * a particular node precede any subnode definitions for that + * node. Although the structure would not be ambiguous if + * properties and subnodes were intermingled, the code needed + * to process a flat tree is simplified by this requirement. + * + * So let's make use of this simplification. + */ + expect = FDT_PROP; + break; + + case FDT_PROP: + fdt_prop = (const void *)fdt + dt_struct; + len = fdt32_to_cpu(fdt_prop->len); + + name = dt_string(&f, dt_strings, fdt32_to_cpu(fdt_prop->nameoff)); + if (!name) + return 0; + + if (strcmp(name, "compatible")) { + dt_struct = dt_struct_advance(&f, dt_struct, + sizeof(struct fdt_property) + len); + break; + } + + return fdt_string_is_compatible(fdt_prop->data, len, compat, compat_len); + + case FDT_NOP: + dt_struct = dt_struct_advance(&f, dt_struct, FDT_TAGSIZE); + break; + + default: + return 0; + } + + if (!dt_struct) + return 0; + } + + return 0; +} diff --git a/drivers/of/partition.c b/drivers/of/partition.c index 729ea238b9..df66751fe9 100644 --- a/drivers/of/partition.c +++ b/drivers/of/partition.c @@ -74,7 +74,7 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node) } new->device_node = node; - new->flags |= DEVFS_PARTITION_FROM_OF; + new->flags |= DEVFS_PARTITION_FROM_OF | DEVFS_PARTITION_FOR_FIXUP; if (IS_ENABLED(CONFIG_NVMEM) && of_device_is_compatible(node, "nvmem-cells")) { struct nvmem_device *nvmem = nvmem_partition_register(new); @@ -178,7 +178,7 @@ int of_fixup_partitions(struct device_node *np, struct cdev *cdev) return 0; list_for_each_entry(partcdev, &cdev->partitions, partition_entry) { - if (!(partcdev->flags & DEVFS_PARTITION_FROM_OF)) + if (!(partcdev->flags & DEVFS_PARTITION_FOR_FIXUP)) continue; n_parts++; } @@ -229,7 +229,7 @@ int of_fixup_partitions(struct device_node *np, struct cdev *cdev) u8 tmp[16 * 16]; /* Up to 64-bit address + 64-bit size */ loff_t partoffset; - if (!(partcdev->flags & DEVFS_PARTITION_FROM_OF)) + if (!(partcdev->flags & DEVFS_PARTITION_FOR_FIXUP)) continue; if (partcdev->mtd) @@ -93,6 +93,8 @@ void cdev_print(const struct cdev *cdev) printf(" of-partition"); if (cdev->flags & DEVFS_PARTITION_FROM_TABLE) printf(" table-partition"); + if (cdev->flags & DEVFS_PARTITION_FOR_FIXUP) + printf(" fixup"); if (cdev->flags & DEVFS_IS_MCI_MAIN_PART_DEV) printf(" mci-main-partition"); if (cdev->flags & DEVFS_IS_MBR_PARTITIONED) diff --git a/include/boot.h b/include/boot.h index c9e8c0fd0d..0f97901a9a 100644 --- a/include/boot.h +++ b/include/boot.h @@ -44,6 +44,7 @@ int bootentry_register_provider(int (*fn)(struct bootentries *bootentries, const struct watchdog; +void boot_set_default(const char *boot_default); void boot_set_watchdog_timeout(unsigned int timeout); struct watchdog *boot_get_enabled_watchdog(void); struct bootentries *bootentries_alloc(void); diff --git a/include/ddr_spd.h b/include/ddr_spd.h index a96d01df85..415fc88f63 100644 --- a/include/ddr_spd.h +++ b/include/ddr_spd.h @@ -264,6 +264,40 @@ struct ddr3_spd_eeprom { /* 69-76 RC1,3,5...15 (MS Nibble) / RC0,2,4...14 (LS Nibble) */ unsigned char rcw[8]; } registered; + struct { + /* 60 (Load Reduced) Module Nominal Height */ + unsigned char mod_height; + /* 61 (Load Reduced) Module Maximum Thickness */ + unsigned char mod_thickness; + /* 62 (Load Reduced) Reference Raw Card Used */ + unsigned char ref_raw_card; + /* 63 Module Attributes */ + unsigned char modu_attr; + /* 64 Memory Buffer Revision ID */ + unsigned char buf_rev_id; + /* 65 Memory Buffer Manufacturer ID Code, Least Significant Byte */ + unsigned char buf_id_lo; + /* 66 Memory Buffer Manufacturer ID Code, Most Significant Byte */ + unsigned char buf_id_hi; + /* 67-89 FxRCy and MR1,2 Registers */ + unsigned char fxrcy_mr1_2[23]; + /* 90 Minimum Module Delay Time for 1.5 V */ + unsigned char min_delay_1_5; + /* 91 Maximum Module Delay Time for 1.5 V */ + unsigned char max_delay_1_5; + /* 92 Minimum Module Delay Time for 1.35 V */ + unsigned char min_delay_1_35; + /* 93 Maximum Module Delay Time for 1.35 V */ + unsigned char max_delay_1_35; + /* 94 Minimum Module Delay Time for 1.25 V */ + unsigned char min_delay_1_25; + /* 95 Maximum Module Delay Time for 1.25 V */ + unsigned char max_delay_1_25; + /* 96-101 Reserved */ + unsigned char reserved[6]; + /* 102-116 Memory Buffer Personality Bytes */ + unsigned char mem_buf_personality[15]; + } loadreduced; unsigned char uc[57]; /* 60-116 Module-Specific Section */ } mod_section; diff --git a/include/driver.h b/include/driver.h index a61b9dca22..e02815d09b 100644 --- a/include/driver.h +++ b/include/driver.h @@ -651,6 +651,7 @@ extern struct list_head cdev_list; #define DEVFS_PARTITION_NO_EXPORT (1U << 10) #define DEVFS_PARTITION_BOOTABLE_LEGACY (1U << 11) #define DEVFS_PARTITION_BOOTABLE_ESP (1U << 12) +#define DEVFS_PARTITION_FOR_FIXUP (1U << 13) static inline bool cdev_is_mbr_partitioned(const struct cdev *master) { diff --git a/include/fastboot.h b/include/fastboot.h index 8a98b482fe..cd415847e3 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -60,6 +60,7 @@ enum fastboot_msg_type { #ifdef CONFIG_FASTBOOT_BASE bool get_fastboot_bbu(void); +void set_fastboot_bbu(unsigned int enable); struct file_list *get_fastboot_partitions(void); #else static inline int get_fastboot_bbu(void) @@ -67,6 +68,10 @@ static inline int get_fastboot_bbu(void) return false; } +static inline void set_fastboot_bbu(unsigned int enable) +{ +} + static inline struct file_list *get_fastboot_partitions(void) { return file_list_parse(""); diff --git a/include/gpio.h b/include/gpio.h index 9951532084..adc1eb39ac 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -2,6 +2,7 @@ #ifndef __GPIO_H #define __GPIO_H +#include <slice.h> #include <linux/types.h> #include <linux/list.h> #include <linux/iopoll.h> @@ -156,6 +157,12 @@ static inline int gpio_array_to_id(const struct gpio *array, size_t num, u32 *va { return -EINVAL; } + +static inline bool gpio_slice_acquired(unsigned gpio) +{ + return false; +} + #else int gpio_request(unsigned gpio, const char *label); int gpio_find_by_name(const char *name); @@ -165,6 +172,7 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); int gpio_request_array(const struct gpio *array, size_t num); void gpio_free_array(const struct gpio *array, size_t num); int gpio_array_to_id(const struct gpio *array, size_t num, u32 *val); +bool gpio_slice_acquired(unsigned gpio); #endif struct gpio_chip; @@ -213,9 +221,16 @@ struct gpio_chip { struct gpio_ops *ops; + struct slice slice; + struct list_head list; }; +static inline struct slice *gpiochip_slice(struct gpio_chip *chip) +{ + return &chip->slice; +} + int gpiochip_add(struct gpio_chip *chip); void gpiochip_remove(struct gpio_chip *chip); diff --git a/include/linux/printk.h b/include/linux/printk.h index 0e9604bbe9..07403ea60c 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -189,7 +189,7 @@ extern void log_clean(unsigned int limit); #define BAREBOX_LOG_PRINT_TIME BIT(0) int log_writefile(const char *filepath); -void log_print(unsigned flags, unsigned levels); +int log_print(unsigned flags, unsigned levels); struct va_format { const char *fmt; diff --git a/include/net.h b/include/net.h index ffc1093ae6..5a6dd9ca7b 100644 --- a/include/net.h +++ b/include/net.h @@ -249,8 +249,6 @@ struct icmphdr { * (big endian). */ -extern unsigned char *NetRxPackets[PKTBUFSRX];/* Receive packets */ - void net_set_ip(struct eth_device *edev, IPaddr_t ip); void net_set_serverip(IPaddr_t ip); const char *net_get_server(void); @@ -551,6 +549,14 @@ static inline char *net_alloc_packet(void) return dma_alloc(PKTSIZE); } +static inline void net_free_packet(char *pkt) +{ + return dma_free(pkt); +} + +int net_alloc_packets(void **packets, int count); +void net_free_packets(void **packets, unsigned count); + struct net_connection *net_udp_new(IPaddr_t dest, uint16_t dport, rx_handler_f *handler, void *ctx); diff --git a/include/of.h b/include/of.h index 3391403a34..9eef6d7f13 100644 --- a/include/of.h +++ b/include/of.h @@ -64,6 +64,9 @@ void of_clean_reserve_map(void); void fdt_add_reserve_map(void *fdt); void fdt_print_reserve_map(const void *fdt); +int fdt_machine_is_compatible(const struct fdt_header *fdt, size_t fdt_size, const char *compat); + + struct device; struct driver; struct resource; @@ -1223,6 +1226,11 @@ static inline int of_property_write_u64(struct device_node *np, return of_property_write_u64_array(np, propname, &value, 1); } +static inline void of_delete_property_by_name(struct device_node *np, const char *name) +{ + of_delete_property(of_find_property(np, name, NULL)); +} + extern const struct of_device_id of_default_bus_match_table[]; int of_device_enable(struct device_node *node); diff --git a/lib/cmdlinepart.c b/lib/cmdlinepart.c index 5e95760bae..f1bfda641c 100644 --- a/lib/cmdlinepart.c +++ b/lib/cmdlinepart.c @@ -29,7 +29,7 @@ int cmdlinepart_do_parse_one(const char *devname, const char *partstr, loff_t size; char *end; char buf[PATH_MAX] = {}; - unsigned long flags = 0; + unsigned long flags = DEVFS_PARTITION_FOR_FIXUP; struct cdev *cdev; memset(buf, 0, PATH_MAX); @@ -29,7 +29,6 @@ #include <linux/ctype.h> #include <linux/err.h> -unsigned char *NetRxPackets[PKTBUFSRX]; /* Receive packets */ static unsigned int net_ip_id; char *net_server; @@ -789,13 +788,32 @@ out: return ret; } -static int net_init(void) +void net_free_packets(void **packets, unsigned count) { + while (count-- > 0) + net_free_packet(packets[count]); +} + +int net_alloc_packets(void **packets, int count) +{ + void *packet; int i; - for (i = 0; i < PKTBUFSRX; i++) - NetRxPackets[i] = net_alloc_packet(); + for (i = 0; i < count; i++) { + packet = net_alloc_packet(); + if (!packet) + goto free; + packets[i] = packet; + } + + return 0; +free: + net_free_packets(packets, i); + return -ENOMEM; +} +static int net_init(void) +{ globalvar_add_simple_ip("net.nameserver", &net_nameserver); globalvar_add_simple_string("net.domainname", &net_domainname); globalvar_add_simple_string("net.server", &net_server); diff --git a/net/rarp.h b/net/rarp.h deleted file mode 100644 index 0986b02513..0000000000 --- a/net/rarp.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* SPDX-FileCopyrightText: 2000 Wolfgang Denk <wd@denx.de>, DENX Software Engineering */ - -#ifndef __RARP_H__ -#define __RARP_H__ - -#ifndef __NET_H__ -#include <net.h> -#endif /* __NET_H__ */ - - -/**********************************************************************/ -/* - * Global functions and variables. - */ - -extern int RarpTry; - -extern void RarpRequest (void); /* Send a RARP request */ - -/**********************************************************************/ - -#endif /* __RARP_H__ */ |