IRAM will power off and microcode will lost when system go into deepsleep, so upload it when resume deepsleep.
Signed-off-by: Zhao Qiang <b45...@freescale.com> --- board/freescale/ls1021aqds/ls1021aqds.c | 4 +- drivers/qe/qe.c | 76 +++++++++++++++++++++++++++++++++ drivers/qe/qe.h | 8 ++++ include/linux/immap_qe.h | 6 +++ 4 files changed, 93 insertions(+), 1 deletion(-) diff --git a/board/freescale/ls1021aqds/ls1021aqds.c b/board/freescale/ls1021aqds/ls1021aqds.c index 1796789..cee7e37 100644 --- a/board/freescale/ls1021aqds/ls1021aqds.c +++ b/board/freescale/ls1021aqds/ls1021aqds.c @@ -309,8 +309,10 @@ int fsl_dp_resume(void) if (!is_warm_boot()) return 0; - enable_devices_ns_access(ns_dev, ARRAY_SIZE(ns_dev)); +#ifdef CONFIG_U_QE + u_qe_resume(); +#endif armv7_init_nonsec(); cleanup_before_linux(); diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index 4358a91..6a10d66 100644 --- a/drivers/qe/qe.c +++ b/drivers/qe/qe.c @@ -429,6 +429,82 @@ int qe_upload_firmware(const struct qe_firmware *firmware) return 0; } +#ifdef CONFIG_U_QE +void u_qe_resume(void) +{ + qe_map_t *qe_immrr; + uint qe_base = CONFIG_SYS_IMMR + 0x01400000; /* QE immr base */ + qe_immrr = (qe_map_t *)qe_base; + + u_qe_firmware_resume((const void *)CONFIG_SYS_QE_FW_ADDR, qe_immrr); + out_be32(&qe_immrr->iram.iready, QE_IRAM_READY); +} + +int u_qe_firmware_resume(const struct qe_firmware *firmware, qe_map_t *qe_immrr) +{ + unsigned int i; + unsigned int j; + const struct qe_header *hdr; + const u32 *code; +#ifdef CONFIG_DEEP_SLEEP + ccsr_gur_t __iomem *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); +#endif + + if (!firmware) + return -EINVAL; + + hdr = &firmware->header; + + /* Check the magic */ + if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') || + (hdr->magic[2] != 'F')) { +#ifdef CONFIG_DEEP_SLEEP + setbits_be32(&gur->devdisr, MPC85xx_DEVDISR_QE_DISABLE); +#endif + return -EPERM; + } + + /* + * If the microcode calls for it, split the I-RAM. + */ + if (!firmware->split) { + out_be16(&qe_immrr->cp.cercr, + in_be16(&qe_immrr->cp.cercr) | QE_CP_CERCR_CIR); + } + + /* 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) + return 0; + + code = (const void *)firmware + be32_to_cpu(ucode->code_offset); + + /* Use auto-increment */ + out_be32(&qe_immrr->iram.iadd, be32_to_cpu(ucode->iram_offset) | + QE_IRAM_IADD_AIE | QE_IRAM_IADD_BADDR); + + for (i = 0; i < be32_to_cpu(ucode->count); i++) + out_be32(&qe_immrr->iram.idata, be32_to_cpu(code[i])); + + /* 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_immrr->rsp[i].tibcr[j], trap); + } + + /* Enable traps */ + out_be32(&qe_immrr->rsp[i].eccr, be32_to_cpu(ucode->eccr)); + } + + return 0; +} +#endif + 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 ebb7c5f..d631e5b 100644 --- a/drivers/qe/qe.h +++ b/drivers/qe/qe.h @@ -11,6 +11,9 @@ #define __QE_H__ #include "common.h" +#ifdef CONFIG_U_QE +#include <linux/immap_qe.h> +#endif #define QE_NUM_OF_BRGS 16 #define UCC_MAX_NUM 8 @@ -285,4 +288,9 @@ void ft_qe_setup(void *blob); void qe_init(uint qe_base); void qe_reset(void); +#ifdef CONFIG_U_QE +void u_qe_resume(void); +int u_qe_firmware_resume(const struct qe_firmware *firmware, + qe_map_t *qe_immrr); +#endif #endif /* __QE_H__ */ diff --git a/include/linux/immap_qe.h b/include/linux/immap_qe.h index b317dcb..bbe3c85 100644 --- a/include/linux/immap_qe.h +++ b/include/linux/immap_qe.h @@ -24,6 +24,12 @@ #endif #endif +#ifdef CONFIG_LS102XA +#define QE_MURAM_SIZE 0x6000UL +#define MAX_QE_RISC 1 +#define QE_NUM_OF_SNUM 28 +#endif + /* QE I-RAM */ typedef struct qe_iram { u32 iadd; /* I-RAM Address Register */ -- 2.1.0.27.g96db324 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot