diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2024-03-13 12:01:36 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2024-03-13 12:01:36 +0100 |
commit | a72dbcb0c695c3927f713464c2a71fc915a81032 (patch) | |
tree | 356c743ca5b7bc2546a1afa6a342afb94ca6549d | |
parent | 373953beb32b517c8166b1d32a651460a9ca9a33 (diff) | |
parent | 3c8d123593cc7ad4070dc9f0631bd30d1d733225 (diff) | |
download | barebox-next.tar.gz barebox-next.tar.xz |
Merge branch 'for-next/misc' into nextnext
-rw-r--r-- | arch/mips/Kconfig | 10 | ||||
-rw-r--r-- | arch/mips/boards/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/boards/board-dt-2nd.S | 35 | ||||
-rw-r--r-- | arch/mips/boot/main_entry-pbl.c | 4 | ||||
-rw-r--r-- | arch/mips/lib/bootm.c | 13 | ||||
-rw-r--r-- | commands/dmesg.c | 6 | ||||
-rw-r--r-- | common/bbu.c | 18 | ||||
-rw-r--r-- | common/blspec.c | 16 | ||||
-rw-r--r-- | common/console_common.c | 17 | ||||
-rw-r--r-- | common/ddr_spd.c | 556 | ||||
-rw-r--r-- | common/image-fit.c | 39 | ||||
-rw-r--r-- | drivers/dma/debug.c | 22 | ||||
-rw-r--r-- | drivers/gpio/gpio-pca953x.c | 2 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 11 | ||||
-rw-r--r-- | drivers/input/gpio_keys.c | 27 | ||||
-rw-r--r-- | drivers/mci/arasan-sdhci.c | 16 | ||||
-rw-r--r-- | drivers/mci/dwcmshc-sdhci.c | 47 | ||||
-rw-r--r-- | drivers/mci/mci-core.c | 1 | ||||
-rw-r--r-- | drivers/mci/sdhci.h | 2 | ||||
-rw-r--r-- | drivers/of/fdt.c | 182 | ||||
-rw-r--r-- | drivers/of/partition.c | 6 | ||||
-rw-r--r-- | fs/fs.c | 2 | ||||
-rw-r--r-- | include/ddr_spd.h | 34 | ||||
-rw-r--r-- | include/driver.h | 1 | ||||
-rw-r--r-- | include/gpio.h | 15 | ||||
-rw-r--r-- | include/linux/printk.h | 2 | ||||
-rw-r--r-- | include/of.h | 8 | ||||
-rw-r--r-- | lib/cmdlinepart.c | 2 | ||||
-rw-r--r-- | net/rarp.h | 23 |
29 files changed, 1001 insertions, 118 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/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/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/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/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/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/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 7ff65d6394..100b6d10fd 100644 --- a/include/driver.h +++ b/include/driver.h @@ -647,6 +647,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/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/of.h b/include/of.h index 19b8e7c038..9cd2c9aee2 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; @@ -1216,6 +1219,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); 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__ */ |