Hi York, This patch depends on the patch http://patchwork.ozlabs.org/patch/393256/
Best Regards Zhao Qiang > -----Original Message----- > From: Zhao Qiang [mailto:b45...@freescale.com] > Sent: Thursday, October 30, 2014 10:24 AM > To: u-boot@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 <b45...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot