summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/mips/Kconfig10
-rw-r--r--arch/mips/boards/Makefile2
-rw-r--r--arch/mips/boards/board-dt-2nd.S35
-rw-r--r--arch/mips/boot/main_entry-pbl.c4
-rw-r--r--arch/mips/lib/bootm.c13
-rw-r--r--commands/dmesg.c6
-rw-r--r--common/bbu.c18
-rw-r--r--common/blspec.c16
-rw-r--r--common/console_common.c17
-rw-r--r--common/ddr_spd.c556
-rw-r--r--common/image-fit.c39
-rw-r--r--drivers/dma/debug.c22
-rw-r--r--drivers/gpio/gpio-pca953x.c2
-rw-r--r--drivers/gpio/gpiolib.c11
-rw-r--r--drivers/input/gpio_keys.c27
-rw-r--r--drivers/mci/arasan-sdhci.c16
-rw-r--r--drivers/mci/dwcmshc-sdhci.c47
-rw-r--r--drivers/mci/mci-core.c1
-rw-r--r--drivers/mci/sdhci.h2
-rw-r--r--drivers/of/fdt.c182
-rw-r--r--drivers/of/partition.c6
-rw-r--r--fs/fs.c2
-rw-r--r--include/ddr_spd.h34
-rw-r--r--include/driver.h1
-rw-r--r--include/gpio.h15
-rw-r--r--include/linux/printk.h2
-rw-r--r--include/of.h8
-rw-r--r--lib/cmdlinepart.c2
-rw-r--r--net/rarp.h23
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)
diff --git a/fs/fs.c b/fs/fs.c
index 341cf62bbc..3a5298649c 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -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__ */