summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/cpu/mpc85xx/fdt.c123
-rw-r--r--include/configs/corenet_ds.h26
2 files changed, 143 insertions, 6 deletions
diff --git a/arch/powerpc/cpu/mpc85xx/fdt.c b/arch/powerpc/cpu/mpc85xx/fdt.c
index 97d3928..812bb3f 100644
--- a/arch/powerpc/cpu/mpc85xx/fdt.c
+++ b/arch/powerpc/cpu/mpc85xx/fdt.c
@@ -33,6 +33,7 @@
#ifdef CONFIG_FSL_ESDHC
#include <fsl_esdhc.h>
#endif
+#include "../../../../drivers/qe/qe.h" /* For struct qe_firmware */
DECLARE_GLOBAL_DATA_PTR;
@@ -406,6 +407,126 @@ static void ft_fixup_qe_snum(void *blob)
}
#endif
+/**
+ * fdt_fixup_fman_firmware -- insert the Fman firmware into the device tree
+ *
+ * The binding for an Fman firmware node is documented in
+ * Documentation/powerpc/dts-bindings/fsl/dpaa/fman.txt. This node contains
+ * the actual Fman firmware binary data. The operating system is expected to
+ * be able to parse the binary data to determine any attributes it needs.
+ */
+#ifdef CONFIG_SYS_DPAA_FMAN
+void fdt_fixup_fman_firmware(void *blob)
+{
+ int rc, fmnode, fwnode = -1;
+ uint32_t phandle;
+ struct qe_firmware *fmanfw;
+ const struct qe_header *hdr;
+ unsigned int length;
+ uint32_t crc;
+ const char *p;
+
+ /* The first Fman we find will contain the actual firmware. */
+ fmnode = fdt_node_offset_by_compatible(blob, -1, "fsl,fman");
+ if (fmnode < 0)
+ /* Exit silently if there are no Fman devices */
+ return;
+
+ /* If we already have a firmware node, then also exit silently. */
+ if (fdt_node_offset_by_compatible(blob, -1, "fsl,fman-firmware") > 0)
+ return;
+
+ /* If the environment variable is not set, then exit silently */
+ p = getenv("fman_ucode");
+ if (!p)
+ return;
+
+ fmanfw = (struct qe_firmware *) simple_strtoul(p, NULL, 0);
+ if (!fmanfw)
+ return;
+
+ hdr = &fmanfw->header;
+ length = be32_to_cpu(hdr->length);
+
+ /* Verify the firmware. */
+ if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
+ (hdr->magic[2] != 'F')) {
+ printf("Data at %p is not an Fman firmware\n", fmanfw);
+ return;
+ }
+
+ if (length > CONFIG_SYS_FMAN_FW_LENGTH) {
+ printf("Fman firmware at %p is too large (size=%u)\n",
+ fmanfw, length);
+ return;
+ }
+
+ length -= sizeof(u32); /* Subtract the size of the CRC */
+ crc = be32_to_cpu(*(u32 *)((void *)fmanfw + length));
+ if (crc != crc32_no_comp(0, (void *)fmanfw, length)) {
+ printf("Fman firmware at %p has invalid CRC\n", fmanfw);
+ return;
+ }
+
+ /* Increase the size of the fdt to make room for the node. */
+ rc = fdt_increase_size(blob, fmanfw->header.length);
+ if (rc < 0) {
+ printf("Unable to make room for Fman firmware: %s\n",
+ fdt_strerror(rc));
+ return;
+ }
+
+ /* Create the firmware node. */
+ fwnode = fdt_add_subnode(blob, fmnode, "fman-firmware");
+ if (fwnode < 0) {
+ char s[64];
+ fdt_get_path(blob, fmnode, s, sizeof(s));
+ printf("Could not add firmware node to %s: %s\n", s,
+ fdt_strerror(fwnode));
+ return;
+ }
+ rc = fdt_setprop_string(blob, fwnode, "compatible", "fsl,fman-firmware");
+ if (rc < 0) {
+ char s[64];
+ fdt_get_path(blob, fwnode, s, sizeof(s));
+ printf("Could not add compatible property to node %s: %s\n", s,
+ fdt_strerror(rc));
+ return;
+ }
+ phandle = fdt_alloc_phandle(blob);
+ rc = fdt_setprop_cell(blob, fwnode, "linux,phandle", phandle);
+ if (rc < 0) {
+ char s[64];
+ fdt_get_path(blob, fwnode, s, sizeof(s));
+ printf("Could not add phandle property to node %s: %s\n", s,
+ fdt_strerror(rc));
+ return;
+ }
+ rc = fdt_setprop(blob, fwnode, "fsl,firmware", fmanfw, fmanfw->header.length);
+ if (rc < 0) {
+ char s[64];
+ fdt_get_path(blob, fwnode, s, sizeof(s));
+ printf("Could not add firmware property to node %s: %s\n", s,
+ fdt_strerror(rc));
+ return;
+ }
+
+ /* Find all other Fman nodes and point them to the firmware node. */
+ while ((fmnode = fdt_node_offset_by_compatible(blob, fmnode, "fsl,fman")) > 0) {
+ rc = fdt_setprop_cell(blob, fmnode, "fsl,firmware-phandle", phandle);
+ if (rc < 0) {
+ char s[64];
+ fdt_get_path(blob, fmnode, s, sizeof(s));
+ printf("Could not add pointer property to node %s: %s\n",
+ s, fdt_strerror(rc));
+ return;
+ }
+ }
+}
+#else
+#define fdt_fixup_fman_firmware(x)
+#endif
+
void ft_cpu_setup(void *blob, bd_t *bd)
{
int off;
@@ -445,6 +566,8 @@ void ft_cpu_setup(void *blob, bd_t *bd)
ft_fixup_qe_snum(blob);
#endif
+ fdt_fixup_fman_firmware(blob);
+
#ifdef CONFIG_SYS_NS16550
do_fixup_by_compat_u32(blob, "ns16550",
"clock-frequency", CONFIG_SYS_NS16550_CLK, 1);
diff --git a/include/configs/corenet_ds.h b/include/configs/corenet_ds.h
index c9cc22a..0b7becb 100644
--- a/include/configs/corenet_ds.h
+++ b/include/configs/corenet_ds.h
@@ -487,12 +487,27 @@
#define CONFIG_SYS_DPAA_FMAN
#define CONFIG_SYS_DPAA_PME
/* Default address of microcode for the Linux Fman driver */
-#define CONFIG_SYS_FMAN_FW_ADDR 0xEF000000
-#ifdef CONFIG_PHYS_64BIT
-#define CONFIG_SYS_FMAN_FW_ADDR_PHYS 0xFEF000000ULL
+#define CONFIG_SYS_FMAN_FW
+#if defined(CONFIG_SPIFLASH)
+/*
+ * env is stored at 0x100000, sector size is 0x10000, ucode is stored after
+ * env, so we got 0x110000.
+ */
+#define CONFIG_SYS_QE_FW_IN_SPIFLASH 0x110000
+#elif defined(CONFIG_SDCARD)
+/*
+ * PBL SD boot image should stored at 0x1000(8 blocks), the size of the image is
+ * about 545KB (1089 blocks), Env is stored after the image, and the env size is
+ * 0x2000 (16 blocks), 8 + 1089 + 16 = 1113, enlarge it to 1130.
+ */
+#define CONFIG_SYS_QE_FW_IN_MMC (512 * 1130)
+#elif defined(CONFIG_NAND)
+#define CONFIG_SYS_QE_FW_IN_NAND (6 * CONFIG_SYS_NAND_BLOCK_SIZE)
#else
-#define CONFIG_SYS_FMAN_FW_ADDR_PHYS CONFIG_SYS_FMAN_FW_ADDR
+#define CONFIG_SYS_FMAN_FW_ADDR 0xEF000000
#endif
+#define CONFIG_SYS_FMAN_FW_LENGTH 0x10000
+#define CONFIG_SYS_FDT_PAD (0x3000 + CONFIG_SYS_FMAN_FW_LENGTH)
#ifdef CONFIG_SYS_DPAA_FMAN
#define CONFIG_FMAN_ENET
@@ -664,8 +679,7 @@
"fdtaddr=c00000\0" \
"fdtfile=p4080ds/p4080ds.dtb\0" \
"bdev=sda3\0" \
- "c=ffe\0" \
- "fman_ucode="MK_STR(CONFIG_SYS_FMAN_FW_ADDR_PHYS)"\0"
+ "c=ffe\0"
#define CONFIG_HDBOOT \
"setenv bootargs root=/dev/$bdev rw " \