uboot/drivers/net/fm/fdt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2016 Freescale Semiconductor, Inc.
   4 */
   5#include <asm/io.h>
   6#include <env.h>
   7#include <fdt_support.h>
   8#include <fsl_qe.h>     /* For struct qe_firmware */
   9#include <u-boot/crc.h>
  10
  11#ifdef CONFIG_SYS_DPAA_FMAN
  12/**
  13 * fdt_fixup_fman_firmware -- insert the Fman firmware into the device tree
  14 *
  15 * The binding for an Fman firmware node is documented in
  16 * Documentation/powerpc/dts-bindings/fsl/dpaa/fman.txt.  This node contains
  17 * the actual Fman firmware binary data.  The operating system is expected to
  18 * be able to parse the binary data to determine any attributes it needs.
  19 */
  20void fdt_fixup_fman_firmware(void *blob)
  21{
  22        int rc, fmnode, fwnode = -1;
  23        uint32_t phandle;
  24        struct qe_firmware *fmanfw;
  25        const struct qe_header *hdr;
  26        unsigned int length;
  27        uint32_t crc;
  28        const char *p;
  29
  30        /* The first Fman we find will contain the actual firmware. */
  31        fmnode = fdt_node_offset_by_compatible(blob, -1, "fsl,fman");
  32        if (fmnode < 0)
  33                /* Exit silently if there are no Fman devices */
  34                return;
  35
  36        /* If we already have a firmware node, then also exit silently. */
  37        if (fdt_node_offset_by_compatible(blob, -1, "fsl,fman-firmware") > 0)
  38                return;
  39
  40        /* If the environment variable is not set, then exit silently */
  41        p = env_get("fman_ucode");
  42        if (!p)
  43                return;
  44
  45        fmanfw = (struct qe_firmware *)simple_strtoul(p, NULL, 16);
  46        if (!fmanfw)
  47                return;
  48
  49        hdr = &fmanfw->header;
  50        length = fdt32_to_cpu(hdr->length);
  51
  52        /* Verify the firmware. */
  53        if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
  54            (hdr->magic[2] != 'F')) {
  55                printf("Data at %p is not an Fman firmware\n", fmanfw);
  56                return;
  57        }
  58
  59        if (length > CONFIG_SYS_QE_FMAN_FW_LENGTH) {
  60                printf("Fman firmware at %p is too large (size=%u)\n",
  61                       fmanfw, length);
  62                return;
  63        }
  64
  65        length -= sizeof(u32);  /* Subtract the size of the CRC */
  66        crc = fdt32_to_cpu(*(u32 *)((void *)fmanfw + length));
  67        if (crc != crc32_no_comp(0, (void *)fmanfw, length)) {
  68                printf("Fman firmware at %p has invalid CRC\n", fmanfw);
  69                return;
  70        }
  71
  72        length += sizeof(u32);
  73
  74        /* Increase the size of the fdt to make room for the node. */
  75        rc = fdt_increase_size(blob, length);
  76        if (rc < 0) {
  77                printf("Unable to make room for Fman firmware: %s\n",
  78                       fdt_strerror(rc));
  79                return;
  80        }
  81
  82        /* Create the firmware node. */
  83        fwnode = fdt_add_subnode(blob, fmnode, "fman-firmware");
  84        if (fwnode < 0) {
  85                char s[64];
  86                fdt_get_path(blob, fmnode, s, sizeof(s));
  87                printf("Could not add firmware node to %s: %s\n", s,
  88                       fdt_strerror(fwnode));
  89                return;
  90        }
  91        rc = fdt_setprop_string(blob, fwnode, "compatible",
  92                                        "fsl,fman-firmware");
  93        if (rc < 0) {
  94                char s[64];
  95                fdt_get_path(blob, fwnode, s, sizeof(s));
  96                printf("Could not add compatible property to node %s: %s\n", s,
  97                       fdt_strerror(rc));
  98                return;
  99        }
 100        phandle = fdt_create_phandle(blob, fwnode);
 101        if (!phandle) {
 102                char s[64];
 103                fdt_get_path(blob, fwnode, s, sizeof(s));
 104                printf("Could not add phandle property to node %s: %s\n", s,
 105                       fdt_strerror(rc));
 106                return;
 107        }
 108        rc = fdt_setprop(blob, fwnode, "fsl,firmware", fmanfw, length);
 109        if (rc < 0) {
 110                char s[64];
 111                fdt_get_path(blob, fwnode, s, sizeof(s));
 112                printf("Could not add firmware property to node %s: %s\n", s,
 113                       fdt_strerror(rc));
 114                return;
 115        }
 116
 117        /* Find all other Fman nodes and point them to the firmware node. */
 118        while ((fmnode = fdt_node_offset_by_compatible(blob, fmnode,
 119                "fsl,fman")) > 0) {
 120                rc = fdt_setprop_cell(blob, fmnode, "fsl,firmware-phandle",
 121                                      phandle);
 122                if (rc < 0) {
 123                        char s[64];
 124                        fdt_get_path(blob, fmnode, s, sizeof(s));
 125                        printf("Could not add pointer property to node %s: %s\n",
 126                               s, fdt_strerror(rc));
 127                        return;
 128                }
 129        }
 130}
 131#endif
 132