[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