[U-Boot] FW: [PATCH] u_qe: add u_qe_upload_firmware for u_qe
qiang.zhao at freescale.com
qiang.zhao at freescale.com
Thu Oct 30 03:35:25 CET 2014
Hi York,
This patch depends on the patch http://patchwork.ozlabs.org/patch/393256/
Best Regards
Zhao Qiang
> -----Original Message-----
> From: Zhao Qiang [mailto:B45475 at freescale.com]
> Sent: Thursday, October 30, 2014 10:24 AM
> To: u-boot at lists.denx.de; Sun York-R58495
> Cc: Xie Xiaobo-R63061; Zhao Qiang-B45475
> Subject: [PATCH] u_qe: add u_qe_upload_firmware for u_qe
>
> Signed-off-by: Zhao Qiang <B45475 at freescale.com>
> ---
> drivers/qe/qe.c | 125
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> drivers/qe/qe.h | 1 +
> 2 files changed, 125 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index 4de1881..5485672
> 100644
> --- a/drivers/qe/qe.c
> +++ b/drivers/qe/qe.c
> @@ -187,7 +187,7 @@ void u_qe_init(void)
> uint qe_base = CONFIG_SYS_IMMR + 0x01400000; /* QE immr base */
> qe_immr = (qe_map_t *)qe_base;
>
> - qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
> + u_qe_upload_firmware((const void *)CONFIG_SYS_QE_FW_ADDR);
> out_be32(&qe_immr->iram.iready, QE_IRAM_READY); }
>
> @@ -442,6 +442,129 @@ int qe_upload_firmware(const struct qe_firmware
> *firmware)
> return 0;
> }
>
> +/*
> + * Upload a microcode to the I-RAM at a specific address.
> + *
> + * See docs/README.qe_firmware for information on QE microcode uploading.
> + *
> + * Currently, only version 1 is supported, so the 'version' field must
> +be
> + * set to 1.
> + *
> + * The SOC model and revision are not validated, they are only
> +displayed for
> + * informational purposes.
> + *
> + * 'calc_size' is the calculated size, in bytes, of the firmware
> +structure and
> + * all of the microcode structures, minus the CRC.
> + *
> + * 'length' is the size that the structure says it is, including the CRC.
> + */
> +int u_qe_upload_firmware(const struct qe_firmware *firmware) {
> + unsigned int i;
> + unsigned int j;
> + u32 crc;
> + size_t calc_size = sizeof(struct qe_firmware);
> + size_t length;
> + const struct qe_header *hdr;
> +#ifdef CONFIG_DEEP_SLEEP
> + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); #endif
> + if (!firmware) {
> + printf("Invalid address\n");
> + return -EINVAL;
> + }
> +
> + hdr = &firmware->header;
> + length = be32_to_cpu(hdr->length);
> +
> + /* Check the magic */
> + if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
> + (hdr->magic[2] != 'F')) {
> + printf("Not a microcode\n");
> +#ifdef CONFIG_DEEP_SLEEP
> + setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE);
> #endif
> + return -EPERM;
> + }
> +
> + /* Check the version */
> + if (hdr->version != 1) {
> + printf("Unsupported version\n");
> + return -EPERM;
> + }
> +
> + /* Validate some of the fields */
> + if ((firmware->count < 1) || (firmware->count > MAX_QE_RISC)) {
> + printf("Invalid data\n");
> + return -EINVAL;
> + }
> +
> + /* Validate the length and check if there's a CRC */
> + calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
> +
> + for (i = 0; i < firmware->count; i++)
> + /*
> + * For situations where the second RISC uses the same
> microcode
> + * as the first, the 'code_offset' and 'count' fields will be
> + * zero, so it's okay to add those.
> + */
> + calc_size += sizeof(u32) *
> + be32_to_cpu(firmware->microcode[i].count);
> +
> + /* Validate the length */
> + if (length != calc_size + sizeof(u32)) {
> + printf("Invalid length\n");
> + return -EPERM;
> + }
> +
> + /*
> + * Validate the CRC. We would normally call crc32_no_comp(), but
> that
> + * function isn't available unless you turn on JFFS support.
> + */
> + crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
> + if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
> + printf("Firmware CRC is invalid\n");
> + return -EIO;
> + }
> +
> + /*
> + * If the microcode calls for it, split the I-RAM.
> + */
> + if (!firmware->split) {
> + out_be16(&qe_immr->cp.cercr,
> + in_be16(&qe_immr->cp.cercr) | QE_CP_CERCR_CIR);
> + }
> +
> + if (firmware->soc.model)
> + printf("Firmware '%s' for %u V%u.%u\n",
> + firmware->id, be16_to_cpu(firmware->soc.model),
> + firmware->soc.major, firmware->soc.minor);
> + else
> + printf("Firmware '%s'\n", firmware->id);
> +
> + /* Loop through each microcode. */
> + for (i = 0; i < firmware->count; i++) {
> + const struct qe_microcode *ucode = &firmware->microcode[i];
> +
> + /* Upload a microcode if it's present */
> + if (ucode->code_offset)
> + qe_upload_microcode(firmware, ucode);
> +
> + /* Program the traps for this processor */
> + for (j = 0; j < 16; j++) {
> + u32 trap = be32_to_cpu(ucode->traps[j]);
> +
> + if (trap)
> + out_be32(&qe_immr->rsp[i].tibcr[j], trap);
> + }
> +
> + /* Enable traps */
> + out_be32(&qe_immr->rsp[i].eccr, be32_to_cpu(ucode->eccr));
> + }
> +
> + return 0;
> +}
> +
> struct qe_firmware_info *qe_get_firmware_info(void) {
> return qe_firmware_uploaded ? &qe_firmware_info : NULL; diff --git
> a/drivers/qe/qe.h b/drivers/qe/qe.h index 30484b8..4c09748 100644
> --- a/drivers/qe/qe.h
> +++ b/drivers/qe/qe.h
> @@ -281,6 +281,7 @@ void qe_assign_page(uint snum, uint para_ram_base);
> int qe_set_brg(uint brg, uint rate); int qe_set_mii_clk_src(int ucc_num);
> int qe_upload_firmware(const struct qe_firmware *firmware);
> +int u_qe_upload_firmware(const struct qe_firmware *firmware);
> struct qe_firmware_info *qe_get_firmware_info(void); void
> ft_qe_setup(void *blob); void qe_init(uint qe_base);
> --
> 2.1.0.27.g96db324
More information about the U-Boot
mailing list