summaryrefslogtreecommitdiff
path: root/arch/powerpc/cpu
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2011-05-03 13:24:08 -0500
committerKumar Gala <galak@kernel.crashing.org>2011-07-29 08:53:39 -0500
commit90f89f099d0741ed5557adbce4a2dde96887a824 (patch)
treee0fcc251d49ee7742d02bfd28a4d1d4a5d40dcc7 /arch/powerpc/cpu
parent21cd5815a7e956e689ac78be2ade05e61fd5dce7 (diff)
powerpc/85xx: verify the device tree before booting Linux
Introduce ft_verify_fdt(), a function that is called after the device tree has been fixed up, that displays warning messages if there is a mismatch between the physical addresses of some devices that U-Boot has configured with what the device tree says the addresses are. This is a particular problem when booting a 36-bit device tree from a 32-bit U-Boot (or vice versa), because the physical address of CCSR is wrong in the device tree. When the operating system boots, no messages are displayed, so the user generally has no idea what's wrong. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/cpu')
-rw-r--r--arch/powerpc/cpu/mpc85xx/fdt.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
index c62b12fb1d..8f13cd8ebf 100644
--- a/arch/powerpc/cpu/mpc85xx/fdt.c
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -639,3 +639,75 @@ void ft_cpu_setup(void *blob, bd_t *bd)
do_fixup_by_compat_u32(blob, "fsl,flexcan-v1.0",
"clock_freq", gd->bus_clk, 1);
}
+
+/*
+ * For some CCSR devices, we only have the virtual address, not the physical
+ * address. This is because we map CCSR as a whole, so we typically don't need
+ * a macro for the physical address of any device within CCSR. In this case,
+ * we calculate the physical address of that device using it's the difference
+ * between the virtual address of the device and the virtual address of the
+ * beginning of CCSR.
+ */
+#define CCSR_VIRT_TO_PHYS(x) \
+ (CONFIG_SYS_CCSRBAR_PHYS + ((x) - CONFIG_SYS_CCSRBAR))
+
+/*
+ * Verify the device tree
+ *
+ * This function compares several CONFIG_xxx macros that contain physical
+ * addresses with the corresponding nodes in the device tree, to see if
+ * the physical addresses are all correct. For example, if
+ * CONFIG_SYS_NS16550_COM1 is defined, then it contains the virtual address
+ * of the first UART. We convert this to a physical address and compare
+ * that with the physical address of the first ns16550-compatible node
+ * in the device tree. If they don't match, then we display a warning.
+ *
+ * Returns 1 on success, 0 on failure
+ */
+int ft_verify_fdt(void *fdt)
+{
+ uint64_t ccsr = 0;
+ int aliases;
+ int off;
+
+ /* First check the CCSR base address */
+ off = fdt_node_offset_by_prop_value(fdt, -1, "device_type", "soc", 4);
+ if (off > 0)
+ ccsr = fdt_get_base_address(fdt, off);
+
+ if (!ccsr) {
+ printf("Warning: could not determine base CCSR address in "
+ "device tree\n");
+ /* No point in checking anything else */
+ return 0;
+ }
+
+ if (ccsr != CONFIG_SYS_CCSRBAR_PHYS) {
+ printf("Warning: U-Boot configured CCSR at address %llx,\n"
+ "but the device tree has it at %llx\n",
+ (uint64_t) CONFIG_SYS_CCSRBAR_PHYS, ccsr);
+ /* No point in checking anything else */
+ return 0;
+ }
+
+ /*
+ * Get the 'aliases' node. If there isn't one, then there's nothing
+ * left to do.
+ */
+ aliases = fdt_path_offset(fdt, "/aliases");
+ if (aliases > 0) {
+#ifdef CONFIG_SYS_NS16550_COM1
+ if (!fdt_verify_alias_address(fdt, aliases, "serial0",
+ CCSR_VIRT_TO_PHYS(CONFIG_SYS_NS16550_COM1)))
+ return 0;
+#endif
+
+#ifdef CONFIG_SYS_NS16550_COM2
+ if (!fdt_verify_alias_address(fdt, aliases, "serial1",
+ CCSR_VIRT_TO_PHYS(CONFIG_SYS_NS16550_COM2)))
+ return 0;
+#endif
+ }
+
+ return 1;
+}