aboutsummaryrefslogtreecommitdiff
path: root/src/mainboard/sifive/hifive-unleashed/fixup_fdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mainboard/sifive/hifive-unleashed/fixup_fdt.c')
-rw-r--r--src/mainboard/sifive/hifive-unleashed/fixup_fdt.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/mainboard/sifive/hifive-unleashed/fixup_fdt.c b/src/mainboard/sifive/hifive-unleashed/fixup_fdt.c
new file mode 100644
index 0000000000..ea58e02b2e
--- /dev/null
+++ b/src/mainboard/sifive/hifive-unleashed/fixup_fdt.c
@@ -0,0 +1,105 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * 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
+ * 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 <soc/otp.h>
+#include <soc/sdram.h>
+#include <cbfs.h>
+#include <device_tree.h>
+#include <bootstate.h>
+#include <mcall.h>
+
+static void do_fixup_mac(struct device_tree_node *node)
+{
+ uint32_t serial = otp_read_serial();
+ static 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;
+ }
+ dt_add_bin_prop(node, "local-mac-address", mac, 6);
+}
+
+static void fixup_mac(struct device_tree_node *parent)
+{
+ struct device_tree_property *prop;
+ const char *name = "local-mac-address";
+
+ list_for_each(prop, parent->properties, list_node) {
+ if (!strcmp(name, prop->prop.name))
+ do_fixup_mac(parent);
+ }
+
+ struct device_tree_node *child;
+ list_for_each(child, parent->children, list_node) {
+ fixup_mac(child);
+ }
+}
+
+static void do_fixup_memory(struct device_tree_node *node)
+{
+ u64 addrs[1], sizes[1];
+ addrs[0] = 0x80000000;
+ sizes[0] = sdram_size_mb() * 1024 * 1024;
+ dt_add_reg_prop(node, addrs, sizes, 1, 2, 2);
+}
+
+
+static void fixup_memory(struct device_tree_node *parent)
+{
+ struct device_tree_property *prop;
+ const char *name = "device_type";
+ const char *value = "memory";
+
+ list_for_each(prop, parent->properties, list_node) {
+ if (!strcmp(name, prop->prop.name)) {
+ if (!strcmp(value, (char *)prop->prop.data))
+ do_fixup_memory(parent);
+ }
+ }
+
+ struct device_tree_node *child;
+ list_for_each(child, parent->children, list_node) {
+ fixup_memory(child);
+ }
+}
+
+static void fixup_fdt(void *unused)
+{
+ void *fdt_rom;
+ struct device_tree *tree;
+
+ /* load flat dt from cbfs */
+ fdt_rom = cbfs_boot_map_with_leak("fallback/DTB", CBFS_TYPE_RAW, NULL);
+
+ /* Expand DT into a tree */
+ tree = fdt_unflatten(fdt_rom);
+
+ /* fixup tree */
+ fixup_mac(tree->root);
+ fixup_memory(tree->root);
+
+ /* convert the tree to a flat dt */
+ void *dt = malloc(dt_flat_size(tree));
+ dt_flatten(tree, dt);
+
+ /* update HLS */
+ for (int i = 0; i < CONFIG_MAX_CPUS; i++)
+ OTHER_HLS(i)->fdt = dt;
+}
+
+BOOT_STATE_INIT_ENTRY(BS_WRITE_TABLES, BS_ON_EXIT, fixup_fdt, NULL);