Xiang Wang has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/31047
Change subject: src/mb/sifive/hifive-unleashed: replace fdt in maskrom ......................................................................
src/mb/sifive/hifive-unleashed: replace fdt in maskrom
The fdt in the maskrom cannot be used to start linux. The correct fdt is dumped by replacing the bbl of the original firmware and used in coreboot.
Correct the mac address in fdt by reading otp
Change-Id: Ic29f0e590311360b85fafd12ebc36cd189fbbc38 Signed-off-by: Xiang Wang wxjstz@126.com --- M src/arch/riscv/Makefile.inc A src/arch/riscv/fdt.c A src/arch/riscv/include/fdt.h M src/commonlib/include/commonlib/cbmem_id.h M src/mainboard/sifive/hifive-unleashed/Makefile.inc A src/mainboard/sifive/hifive-unleashed/hifive-unleashed.dts M src/mainboard/sifive/hifive-unleashed/romstage.c 7 files changed, 1,054 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/47/31047/1
diff --git a/src/arch/riscv/Makefile.inc b/src/arch/riscv/Makefile.inc index aee4b3b..a27b3e8 100644 --- a/src/arch/riscv/Makefile.inc +++ b/src/arch/riscv/Makefile.inc @@ -57,6 +57,7 @@ bootblock-y += smp.c bootblock-y += misc.c bootblock-y += pmp.c +bootblock-y += fdt.c bootblock-y += \ $(top)/src/lib/memchr.c \ $(top)/src/lib/memcmp.c \ @@ -87,6 +88,7 @@ romstage-y += misc.c romstage-y += pmp.c romstage-y += smp.c +romstage-y += fdt.c romstage-y += \ $(top)/src/lib/memchr.c \ $(top)/src/lib/memcmp.c \ @@ -128,6 +130,7 @@ ramstage-y += tables.c ramstage-y += payload.S ramstage-y += pmp.c +ramstage-y += fdt.c ramstage-y += \ $(top)/src/lib/memchr.c \ $(top)/src/lib/memcmp.c \ diff --git a/src/arch/riscv/fdt.c b/src/arch/riscv/fdt.c new file mode 100644 index 0000000..a3815b6 --- /dev/null +++ b/src/arch/riscv/fdt.c @@ -0,0 +1,276 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 SiFive, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <stdint.h> +#include <string.h> +#include "fdt.h" + +static inline uint32_t bswap(uint32_t x) +{ + uint32_t y = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >> 8; + uint32_t z = (y & 0x0000FFFF) << 16 | (y & 0xFFFF0000) >> 16; + return z; +} + +static inline int isstring(char c) +{ + if (c >= 'A' && c <= 'Z') + return 1; + if (c >= 'a' && c <= 'z') + return 1; + if (c >= '0' && c <= '9') + return 1; + if (c == '\0' || c == ' ' || c == ',' || c == '-') + return 1; + return 0; +} + +static uint32_t *fdt_scan_helper( + uint32_t *lex, + const char *strings, + struct fdt_scan_node *node, + const struct fdt_cb *cb) +{ + struct fdt_scan_node child; + struct fdt_scan_prop prop; + int last = 0; + + child.parent = node; + // these are the default cell counts, as per the FDT spec + child.address_cells = 2; + child.size_cells = 1; + prop.node = node; + + while (1) { + switch (bswap(lex[0])) { + case FDT_NOP: { + lex += 1; + break; + } + case FDT_PROP: { + // assert (!last); + prop.name = strings + bswap(lex[2]); + prop.len = bswap(lex[1]); + prop.value = lex + 3; + if (node && !strcmp(prop.name, "#address-cells")) + node->address_cells = bswap(lex[3]); + if (node && !strcmp(prop.name, "#size-cells")) + node->size_cells = bswap(lex[3]); + lex += 3 + (prop.len+3)/4; + cb->prop(&prop, cb->extra); + break; + } + case FDT_BEGIN_NODE: { + uint32_t *lex_next; + if (!last && node && cb->done) + cb->done(node, cb->extra); + last = 1; + child.name = (const char *)(lex+1); + if (cb->open) + cb->open(&child, cb->extra); + lex_next = fdt_scan_helper( + lex + 2 + strlen(child.name)/4, + strings, &child, cb); + if (cb->close && + cb->close(&child, cb->extra) == -1) + while (lex != lex_next) + *lex++ = bswap(FDT_NOP); + lex = lex_next; + break; + } + case FDT_END_NODE: { + if (!last && node && cb->done) + cb->done(node, cb->extra); + return lex + 1; + } + default: { // FDT_END + if (!last && node && cb->done) + cb->done(node, cb->extra); + return lex; + } + } + } +} + +void fdt_scan(uintptr_t fdt, const struct fdt_cb *cb) +{ + struct fdt_header *header = (struct fdt_header *)fdt; + + // Only process FDT that we understand + if (bswap(header->magic) != FDT_MAGIC || + bswap(header->last_comp_version) > FDT_VERSION) + return; + + const char *strings = + (const char *)(fdt + bswap(header->off_dt_strings)); + uint32_t *lex = (uint32_t *)(fdt + bswap(header->off_dt_struct)); + + fdt_scan_helper(lex, strings, 0, cb); +} + +uint32_t fdt_size(uintptr_t fdt) +{ + struct fdt_header *header = (struct fdt_header *)fdt; + + // Only process FDT that we understand + if (bswap(header->magic) != FDT_MAGIC || + bswap(header->last_comp_version) > FDT_VERSION) + return 0; + return bswap(header->totalsize); +} + +const uint32_t *fdt_get_address( + const struct fdt_scan_node *node, + const uint32_t *value, + uint64_t *result) +{ + *result = 0; + for (int cells = node->address_cells; cells > 0; --cells) + *result = (*result << 32) + bswap(*value++); + return value; +} + +const uint32_t *fdt_get_size( + const struct fdt_scan_node *node, + const uint32_t *value, + uint64_t *result) +{ + *result = 0; + for (int cells = node->size_cells; cells > 0; --cells) + *result = (*result << 32) + bswap(*value++); + return value; +} + +void fdt_set_size( + const struct fdt_scan_node *node, + uint32_t *value, + uint64_t set) +{ + for (int cells = node->size_cells; cells > 0; --cells) { + value[cells-1] = bswap(set); + set >>= 32; + } +} + +int fdt_string_list_index(const struct fdt_scan_prop *prop, const char *str) +{ + const char *list = (const char *)prop->value; + const char *end = list + prop->len; + int index = 0; + while (end - list > 0) { + if (!strcmp(list, str)) + return index; + ++index; + list += strlen(list) + 1; + } + return -1; +} + +//////////////////////////// MEMORY REDUCE ///////////////////////////////////// + +struct mem_scan { + uint64_t size; + int memory; + const uint32_t *reg_value; + int reg_len; +}; + +static void mem_open(const struct fdt_scan_node *node, void *extra) +{ + struct mem_scan *scan = (struct mem_scan *)extra; + scan->memory = 0; +} + +static void mem_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct mem_scan *scan = (struct mem_scan *)extra; + if (!strcmp(prop->name, "device_type") && + !strcmp((const char *)prop->value, "memory")) { + scan->memory = 1; + } else if (!strcmp(prop->name, "reg")) { + scan->reg_value = prop->value; + scan->reg_len = prop->len; + } +} + +static void mem_done(const struct fdt_scan_node *node, void *extra) +{ + struct mem_scan *scan = (struct mem_scan *)extra; + const uint32_t *value = scan->reg_value; + const uint32_t *end = value + scan->reg_len/4; + uint32_t *size_ptr; + + if (!scan->memory) + return; + // assert (scan->reg_value && scan->reg_len % 4 == 0); + + while (end - value > 0) { + uint64_t base, size; + value = fdt_get_address(node->parent, value, &base); + size_ptr = (uint32_t *)value; + value = fdt_get_size(node->parent, value, &size); + if (size > scan->size) { + fdt_set_size(node->parent, size_ptr, scan->size); + scan->size = 0; + } else { + scan->size -= size; + } + } + // assert (end == value); +} + +void fdt_reduce_mem(uintptr_t fdt, uintptr_t size) +{ + struct fdt_cb cb; + struct mem_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.open = mem_open; + cb.prop = mem_prop; + cb.done = mem_done; + cb.extra = &scan; + scan.size = size; + + fdt_scan(fdt, &cb); +} + +//////////////////////////// MAC ADDRESS SET /////////////////////////////////// + +struct prop_scan { + const char *prop; + uint8_t *value; +}; + +static void set_prop(const struct fdt_scan_prop *prop, void *extra) +{ + struct prop_scan *scan = (struct prop_scan *)extra; + if (!strcmp(prop->name, scan->prop)) + memcpy(prop->value, scan->value, prop->len); +} + +void fdt_set_prop(uintptr_t fdt, const char *prop, uint8_t *value) +{ + struct fdt_cb cb; + struct prop_scan scan; + + memset(&cb, 0, sizeof(cb)); + cb.prop = set_prop; + cb.extra = &scan; + scan.value = value; + scan.prop = prop; + + fdt_scan(fdt, &cb); +} + diff --git a/src/arch/riscv/include/fdt.h b/src/arch/riscv/include/fdt.h new file mode 100644 index 0000000..1b8d498 --- /dev/null +++ b/src/arch/riscv/include/fdt.h @@ -0,0 +1,89 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 SiFive, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +#ifndef FDT_H +#define FDT_H + +#define FDT_MAGIC 0xd00dfeed +#define FDT_VERSION 17 + +struct fdt_header { + uint32_t magic; + uint32_t totalsize; + uint32_t off_dt_struct; + uint32_t off_dt_strings; + uint32_t off_mem_rsvmap; + uint32_t version; + uint32_t last_comp_version; /* <= 17 */ + uint32_t boot_cpuid_phys; + uint32_t size_dt_strings; + uint32_t size_dt_struct; +}; + +#define FDT_BEGIN_NODE 1 +#define FDT_END_NODE 2 +#define FDT_PROP 3 +#define FDT_NOP 4 +#define FDT_END 9 + +struct fdt_scan_node { + const struct fdt_scan_node *parent; + const char *name; + int address_cells; + int size_cells; +}; + +struct fdt_scan_prop { + const struct fdt_scan_node *node; + const char *name; + uint32_t *value; + int len; // in bytes of value +}; + +struct fdt_cb { + void (*open)(const struct fdt_scan_node *node, void *extra); + void (*prop)(const struct fdt_scan_prop *prop, void *extra); + // last property was seen + void (*done)(const struct fdt_scan_node *node, void *extra); + // -1 => delete the node + children + int (*close)(const struct fdt_scan_node *node, void *extra); + void *extra; +}; + +// Scan the contents of FDT +void fdt_scan(uintptr_t fdt, const struct fdt_cb *cb); +uint32_t fdt_size(uintptr_t fdt); + +// Extract fields +const uint32_t *fdt_get_address( + const struct fdt_scan_node *node, + const uint32_t *base, + uint64_t *value); +const uint32_t *fdt_get_size( + const struct fdt_scan_node *node, + const uint32_t *base, + uint64_t *value); +void fdt_set_size( + const struct fdt_scan_node *node, + uint32_t *value, + uint64_t set); +// -1 if not found +int fdt_string_list_index( + const struct fdt_scan_prop *prop, + const char *str); + +void fdt_reduce_mem(uintptr_t fdt, uintptr_t size); +void fdt_set_prop(uintptr_t fdt, const char *prop, uint8_t *value); + +#endif diff --git a/src/commonlib/include/commonlib/cbmem_id.h b/src/commonlib/include/commonlib/cbmem_id.h index 2e0eeb6..f410b14 100644 --- a/src/commonlib/include/commonlib/cbmem_id.h +++ b/src/commonlib/include/commonlib/cbmem_id.h @@ -77,6 +77,7 @@ #define CBMEM_ID_ROM1 0x524f4d31 #define CBMEM_ID_ROM2 0x524f4d32 #define CBMEM_ID_ROM3 0x524f4d33 +#define CBMEM_ID_DEVICETREE 0x44544220
#define CBMEM_ID_TO_NAME_TABLE \ { CBMEM_ID_ACPI, "ACPI " }, \ @@ -133,5 +134,6 @@ { CBMEM_ID_ROM0, "VGA ROM #0 "}, \ { CBMEM_ID_ROM1, "VGA ROM #1 "}, \ { CBMEM_ID_ROM2, "VGA ROM #2 "}, \ - { CBMEM_ID_ROM3, "VGA ROM #3 "}, + { CBMEM_ID_ROM3, "VGA ROM #3 "}, \ + { CBMEM_ID_DEVICETREE, "Device Tree"}, #endif /* _CBMEM_ID_H_ */ diff --git a/src/mainboard/sifive/hifive-unleashed/Makefile.inc b/src/mainboard/sifive/hifive-unleashed/Makefile.inc index 37d9804..1366038 100644 --- a/src/mainboard/sifive/hifive-unleashed/Makefile.inc +++ b/src/mainboard/sifive/hifive-unleashed/Makefile.inc @@ -23,3 +23,13 @@ ramstage-y += memlayout.ld ramstage-y += flash.c ramstage-y += media.c + + +DTB=build/hifive-unleashed.dtb +DTS=src/mainboard/sifive/hifive-unleashed/hifive-unleashed.dts +$(DTB): $(DTS) + dtc -I dts -O dtb -o $(DTB) $(DTS) + +cbfs-files-y += fallback/DTB +fallback/DTB-file := $(DTB) +fallback/DTB-type := raw diff --git a/src/mainboard/sifive/hifive-unleashed/hifive-unleashed.dts b/src/mainboard/sifive/hifive-unleashed/hifive-unleashed.dts new file mode 100644 index 0000000..6b9bbaa --- /dev/null +++ b/src/mainboard/sifive/hifive-unleashed/hifive-unleashed.dts @@ -0,0 +1,640 @@ +/* + * This file is part of the coreboot project. + * + * Copyright 2018 SiFive, Inc + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ +/dts-v1/; + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,fu540g", "sifive,fu500"; + model = "sifive,hifive-unleashed-a00"; + + aliases { + serial0 = &L28; + serial1 = &L29; + }; + + chosen { + }; +/* + firmware { + sifive,fsbl = "YYYY-MM-DD"; + }; +*/ + L3: cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <1000000>; + L9: cpu@0 { + clock-frequency = <0>; + compatible = "sifive,rocket0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <16384>; + next-level-cache = <&L24 &L0>; + reg = <0>; + riscv,isa = "rv64imac"; + sifive,dtim = <&L8>; + sifive,itim = <&L7>; + status = "okay"; + L10: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + L12: cpu@1 { + clock-frequency = <0>; + compatible = "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + next-level-cache = <&L24 &L0>; + reg = <1>; + riscv,isa = "rv64imafdc"; + sifive,itim = <&L11>; + status = "okay"; + tlb-split; + L13: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + L15: cpu@2 { + clock-frequency = <0>; + compatible = "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + next-level-cache = <&L24 &L0>; + reg = <2>; + riscv,isa = "rv64imafdc"; + sifive,itim = <&L14>; + status = "okay"; + tlb-split; + L16: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + L18: cpu@3 { + clock-frequency = <0>; + compatible = "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + next-level-cache = <&L24 &L0>; + reg = <3>; + riscv,isa = "rv64imafdc"; + sifive,itim = <&L17>; + status = "okay"; + tlb-split; + L19: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + L21: cpu@4 { + clock-frequency = <0>; + compatible = "sifive,rocket0", "riscv"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <32>; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <64>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <32>; + mmu-type = "riscv,sv39"; + next-level-cache = <&L24 &L0>; + reg = <4>; + riscv,isa = "rv64imafdc"; + sifive,itim = <&L20>; + status = "okay"; + tlb-split; + L22: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + L36: memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x2 0x00000000>; + }; + L2: soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "SiFive,FU540G-soc", "fu500-soc", "sifive-soc", "simple-bus"; + ranges; + refclk: refclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <33333333>; + clock-output-names = "xtal"; + }; + prci: prci@10000000 { + /* compatible = "sifive,ux00prci0"; */ + compatible = "sifive,aloeprci0"; + reg = <0x0 0x10000000 0x0 0x1000>; + reg-names = "control"; + clocks = <&refclk>; + #clock-cells = <1>; + }; + tlclk: tlclk { + compatible = "fixed-factor-clock"; + clocks = <&prci 0>; + #clock-cells = <0>; + clock-div = <2>; + clock-mult = <1>; + }; + L51: cadence-gemgxl-mgmt@100a0000 { + compatible = "sifive,cadencegemgxlmgmt0"; + reg = <0x0 0x100a0000 0x0 0x1000>; + reg-names = "control"; + #clock-cells = <0>; + }; + L35: bus-blocker@100b8000 { + compatible = "sifive,bus-blocker0"; + reg = <0x0 0x100b8000 0x0 0x1000>; + reg-names = "control"; + }; + L0: cache-controller@2010000 { + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <2048>; + cache-size = <2097152>; + cache-unified; + compatible = "sifive,ccache0", "cache"; + interrupt-parent = <&L4>; + interrupts = <1 2 3>; + next-level-cache = <&L25 &L40 &L36>; + reg = <0x0 0x2010000 0x0 0x1000 0x0 0x8000000 0x0 0x2000000>; + reg-names = "control", "sideband"; + }; + L33: cadence-ddr-mgmt@100c0000 { + compatible = "sifive,cadenceddrmgmt0"; + reg = <0x0 0x100c0000 0x0 0x1000>; + reg-names = "control"; + }; + L40: chiplink@40000000 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,chiplink", "simple-bus"; + ranges = <0x0 0x60000000 0x0 0x60000000 0x0 0x20000000 0x30 0x0 0x30 0x0 0x10 0x0 0x0 0x40000000 0x0 0x40000000 0x0 0x20000000 0x20 0x0 0x20 0x0 0x10 0x0>; + }; + L5: clint@2000000 { + compatible = "riscv,clint0"; + interrupts-extended = <&L10 3 &L10 7 &L13 3 &L13 7 &L16 3 &L16 7 &L19 3 &L19 7 &L22 3 &L22 7>; + reg = <0x0 0x2000000 0x0 0x10000>; + reg-names = "control"; + }; + L6: debug-controller@0 { + compatible = "sifive,debug-013", "riscv,debug-013"; + interrupts-extended = <&L10 65535 &L13 65535 &L16 65535 &L19 65535 &L22 65535>; + reg = <0x0 0x0 0x0 0x1000>; + reg-names = "control"; + }; + L32: dma@3000000 { + #dma-cells = <1>; + compatible = "riscv,dma0"; + dma-channels = <4>; + dma-requests = <0>; + interrupt-parent = <&L4>; + interrupts = <23 24 25 26 27 28 29 30>; + reg = <0x0 0x3000000 0x0 0x100000>; + reg-names = "control"; + riscv,dma-pools = <1>; + }; + L8: dtim@1000000 { + compatible = "sifive,dtim0"; + reg = <0x0 0x1000000 0x0 0x2000>; + reg-names = "mem"; + }; + L44: ememoryotp@10070000 { + compatible = "sifive,ememoryotp0"; + reg = <0x0 0x10070000 0x0 0x1000>; + reg-names = "control"; + }; + L24: error-device@18000000 { + compatible = "sifive,error0"; + reg = <0x0 0x18000000 0x0 0x8000000>; + reg-names = "mem"; + }; + L52: ethernet@10090000 { + compatible = "cdns,macb"; + interrupt-parent = <&L4>; + interrupts = <53>; + reg = <0x0 0x10090000 0x0 0x2000>; + reg-names = "control"; + + local-mac-address = [00 00 00 00 00 00]; + phy-mode = "gmii"; + clock-names = "pclk", "hclk", "tx_clk"; + clocks = <&prci 1>, <&prci 1>, <&L51>; + + #address-cells = <1>; + #size-cells = <0>; + phy1: ethernet-phy@0 { + reg = <0>; + reset-gpios = <&L31 12 1>; + }; + }; + L31: gpio@10060000 { + compatible = "sifive,gpio0"; + interrupt-parent = <&L4>; + interrupts = <7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22>; + reg = <0x0 0x10060000 0x0 0x1000>; + reg-names = "control"; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + gpio-restart { + compatible = "gpio-restart"; + gpios = <&L31 10 1>; + }; + L47: i2c@10030000 { + compatible = "sifive,i2c0", "opencores,i2c-ocores"; + reg = <0x0 0x10030000 0x0 0x1000>; + reg-names = "control"; + clocks = <&tlclk>; + + reg-shift = <2>; + reg-io-width = <1>; + + #address-cells = <1>; + #size-cells = <0>; + + /* On pre-production boards only */ +/* + ina233-vdd_soc_core@40 { + compatible = "ti,pmbus"; + reg = <0x40>; + }; + ina233-vdd_ddr_soc@44 { + compatible = "ti,pmbus"; + reg = <0x44>; + }; + ina233-vdd_ddr_mem@45 { + compatible = "ti,pmbus"; + reg = <0x45>; + }; + ina233-vdd_corepll@47 { + compatible = "ti,pmbus"; + reg = <0x47>; + }; + ina233-vdd_otp@4a { + compatible = "ti,pmbus"; + reg = <0x4a>; + }; + ina233-vdd_io@4b { + compatible = "ti,pmbus"; + reg = <0x4b>; + }; + ina233-vdd_ddrpll@48 { + compatible = "ti,pmbus"; + reg = <0x48>; + }; + ina233-avdd_ddrpll@49 { + compatible = "ti,pmbus"; + reg = <0x49>; + }; + ina233-vdd_givdd@4c { + compatible = "ti,pmbus"; + reg = <0x4c>; + }; + ina233vdd_gemgxlpll@4d { + compatible = "ti,pmbus"; + reg = <0x4d>; + }; +*/ + /* On the tester board */ +/* + m24c02 { + compatible = "st,24c02"; + reg = <0x51>; + }; +*/ + }; + L4: interrupt-controller@c000000 { + #interrupt-cells = <1>; + compatible = "riscv,plic0"; + interrupt-controller; + interrupts-extended = <&L10 11 &L13 11 &L13 9 &L16 11 &L16 9 &L19 11 &L19 9 &L22 11 &L22 9>; + reg = <0x0 0xc000000 0x0 0x4000000>; + reg-names = "control"; + riscv,max-priority = <7>; + riscv,ndev = <53>; + }; + L7: itim@1800000 { + compatible = "sifive,itim0"; + reg = <0x0 0x1800000 0x0 0x4000>; + reg-names = "mem"; + }; + L11: itim@1808000 { + compatible = "sifive,itim0"; + reg = <0x0 0x1808000 0x0 0x8000>; + reg-names = "mem"; + }; + L14: itim@1810000 { + compatible = "sifive,itim0"; + reg = <0x0 0x1810000 0x0 0x8000>; + reg-names = "mem"; + }; + L17: itim@1818000 { + compatible = "sifive,itim0"; + reg = <0x0 0x1818000 0x0 0x8000>; + reg-names = "mem"; + }; + L20: itim@1820000 { + compatible = "sifive,itim0"; + reg = <0x0 0x1820000 0x0 0x8000>; + reg-names = "mem"; + }; + L37: memory-controller@100b0000 { + /* compatible = "sifive,ux00ddr0"; */ + compatible = "sifive,aloeddr0"; + interrupt-parent = <&L4>; + interrupts = <31>; + reg = <0x0 0x100b0000 0x0 0x4000>; + reg-names = "control"; + }; + pci@2000000000 { + #address-cells = <3>; + #interrupt-cells = <1>; + #size-cells = <2>; + compatible = "xlnx,axi-pcie-host-1.00.a"; + device_type = "pci"; + interrupt-map = <0 0 0 1 &xil_pcie_intc 1 0 0 0 2 &xil_pcie_intc 2 0 0 0 3 &xil_pcie_intc 3 0 0 0 4 &xil_pcie_intc 4>; + interrupt-map-mask = <0 0 0 7>; + interrupt-parent = <&L4>; + interrupts = <32>; + ranges = <0x2000000 0x0 0x40000000 0x0 0x40000000 0x0 0x20000000>; + reg = <0x020 0x0 0x0 0x4000000>; + reg-names = "control"; + xil_pcie_intc: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; +/* + pci@2030000000 { + #address-cells = <3>; + #interrupt-cells = <1>; + #size-cells = <2>; + compatible = "ms-pf,axi-pcie-host"; + device_type = "pci"; + bus-range = <0x01 0x7f>; + interrupt-map = <0 0 0 1 &ms_pcie_intc 1 0 0 0 2 &ms_pcie_intc 2 0 0 0 3 &ms_pcie_intc 3 0 0 0 4 &ms_pcie_intc 4>; + interrupt-map-mask = <0 0 0 7>; + interrupt-parent = <&L4>; + interrupts = <32>; + ranges = <0x2000000 0x0 0x40000000 0x0 0x40000000 0x0 0x20000000>; + reg = <0x20 0x30000000 0x0 0x4000000 0x20 0x0 0x0 0x100000>; + reg-names = "control", "apb"; + ms_pcie_intc: interrupt-controller { + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + }; + }; +*/ + L53: pinctrl@10080000 { + compatible = "sifive,pinctrl0"; + reg = <0x0 0x10080000 0x0 0x1000>; + reg-names = "control"; + }; + L45: pwm@10020000 { + compatible = "sifive,pwm0"; + interrupt-parent = <&L4>; + interrupts = <42 43 44 45>; + reg = <0x0 0x10020000 0x0 0x1000>; + reg-names = "control"; + clocks = <&tlclk>; + sifive,approx-period = <1000000>; + #pwm-cells = <2>; + }; + L46: pwm@10021000 { + compatible = "sifive,pwm0"; + interrupt-parent = <&L4>; + interrupts = <46 47 48 49>; + reg = <0x0 0x10021000 0x0 0x1000>; + reg-names = "control"; + clocks = <&tlclk>; + sifive,approx-period = <1000000>; + #pwm-cells = <2>; + }; + pwmleds { + compatible = "pwm-leds"; + heartbeat { + pwms = <&L45 0 0>; + max-brightness = <255>; + linux,default-trigger = "heartbeat"; + }; + mtd { + pwms = <&L45 1 0>; + max-brightness = <255>; + linux,default-trigger = "mtd"; + }; + netdev { + pwms = <&L45 2 0>; + max-brightness = <255>; + linux,default-trigger = "netdev"; + }; + panic { + pwms = <&L45 3 0>; + max-brightness = <255>; + linux,default-trigger = "panic"; + }; + /* These LEDs are on the tester board */ +/* + testled { + pwms = <&L46 0 0>; + max-brightness = <255>; + }; + green { + pwms = <&L46 1 0>; + max-brightness = <255>; + }; + red { + pwms = <&L46 2 0>; + max-brightness = <255>; + }; + blue { + pwms = <&L46 3 0>; + max-brightness = <255>; + }; +*/ + }; + L27: rom@1000 { + compatible = "sifive,modeselect0"; + reg = <0x0 0x1000 0x0 0x1000>; + reg-names = "mem"; + }; + L26: rom@10000 { + compatible = "sifive,maskrom0"; + reg = <0x0 0x10000 0x0 0x8000>; + reg-names = "mem"; + }; + L25: rom@a000000 { + compatible = "ucbbar,cacheable-zero0"; + reg = <0x0 0xa000000 0x0 0x2000000>; + reg-names = "mem"; + }; + L28: serial@10010000 { + compatible = "sifive,uart0"; + interrupt-parent = <&L4>; + interrupts = <4>; + reg = <0x0 0x10010000 0x0 0x1000>; + reg-names = "control"; + clocks = <&tlclk>; + }; + L29: serial@10011000 { + compatible = "sifive,uart0"; + interrupt-parent = <&L4>; + interrupts = <5>; + reg = <0x0 0x10011000 0x0 0x1000>; + reg-names = "control"; + clocks = <&tlclk>; + }; + L49: spi@10040000 { + compatible = "sifive,spi0"; + interrupt-parent = <&L4>; + interrupts = <51>; + reg = <0x0 0x10040000 0x0 0x1000 0x0 0x20000000 0x0 0x10000000>; + reg-names = "control", "mem"; + clocks = <&tlclk>; + + #address-cells = <1>; + #size-cells = <0>; + flash@0 { + compatible = "issi,is25wp256d", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <50000000>; + m25p,fast-read; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; + }; + L50: spi@10041000 { + compatible = "sifive,spi0"; + interrupt-parent = <&L4>; + interrupts = <52>; + reg = <0x0 0x10041000 0x0 0x1000 0x0 0x30000000 0x0 0x10000000>; + reg-names = "control", "mem"; + clocks = <&tlclk>; + + #address-cells = <1>; + #size-cells = <0>; + + /* These flash chips are on the tester board */ +/* + flash@0 { + compatible = "issi,is25wp032", "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <25000000>; + m25p,fast-read; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; + flash@1 { + compatible = "issi,is25wp032", "jedec,spi-nor"; + reg = <1>; + spi-max-frequency = <25000000>; + m25p,fast-read; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; + flash@2 { + compatible = "issi,is25wp032", "jedec,spi-nor"; + reg = <2>; + spi-max-frequency = <25000000>; + m25p,fast-read; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; + flash@3 { + compatible = "issi,is25wp032", "jedec,spi-nor"; + reg = <3>; + spi-max-frequency = <25000000>; + m25p,fast-read; + spi-tx-bus-width = <4>; + spi-rx-bus-width = <4>; + }; +*/ + }; + L30: spi@10050000 { + compatible = "sifive,spi0"; + interrupt-parent = <&L4>; + interrupts = <6>; + reg = <0x0 0x10050000 0x0 0x1000>; + reg-names = "control"; + clocks = <&tlclk>; + + #address-cells = <1>; + #size-cells = <0>; + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0>; + spi-max-frequency = <20000000>; + voltage-ranges = <3300 3300>; + disable-wp; + gpios = <&L31 11 1>; + }; + }; + L23: teststatus@4000 { + compatible = "sifive,test0"; + reg = <0x0 0x4000 0x0 0x1000>; + reg-names = "control"; + }; + }; +}; diff --git a/src/mainboard/sifive/hifive-unleashed/romstage.c b/src/mainboard/sifive/hifive-unleashed/romstage.c index 8277141..17d1aef 100644 --- a/src/mainboard/sifive/hifive-unleashed/romstage.c +++ b/src/mainboard/sifive/hifive-unleashed/romstage.c @@ -2,6 +2,7 @@ * This file is part of the coreboot project. * * Copyright (C) 2013 Google, Inc. + * Copyright (C) 2019 HardenedLinux * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +21,36 @@ #include <program_loading.h> #include <soc/clock.h> #include <soc/sdram.h> +#include <mcall.h> +#include <fdt.h> +#include <string.h> +#include <symbols.h> +#include <cbfs.h> +#include <soc/otp.h> + +static void update_dtb(void) +{ + uintptr_t dtb_maskrom = (uintptr_t)cbfs_boot_map_with_leak( + "fallback/DTB", CBFS_TYPE_RAW, NULL); + uint32_t dtb_size = fdt_size(dtb_maskrom); + uintptr_t dtb_target = (uintptr_t)cbmem_add(CBMEM_ID_DEVICETREE, + dtb_size); + + memcpy((void *)dtb_target, (void *)dtb_maskrom, dtb_size); + fdt_reduce_mem(dtb_target, sdram_size_mb() * 1024 * 1024); + + uint32_t serial = otp_read_serial(); + unsigned char mac[6] = { 0x70, 0xb3, 0xd5, 0x92, 0xf0, 0x00 }; + if (serial != ~0) { + mac[5] |= (serial >> 0) & 0xff; + mac[4] |= (serial >> 8) & 0xff; + mac[3] |= (serial >> 16) & 0xff; + } + fdt_set_prop(dtb_target, "local-mac-address", &mac[0]); + + for (int i = 0; i < CONFIG_MAX_CPUS; i++) + OTHER_HLS(i)->fdt = (void *)dtb_target; +}
void main(void) { @@ -43,5 +74,7 @@
cbmem_initialize_empty();
+ update_dtb(); + run_ramstage(); }