summaryrefslogtreecommitdiff
path: root/board
diff options
context:
space:
mode:
Diffstat (limited to 'board')
-rw-r--r--board/st/u8500/itp.c159
-rw-r--r--board/st/u8500/itp.h4
-rw-r--r--board/st/u8500/mmc_host.c2
3 files changed, 151 insertions, 14 deletions
diff --git a/board/st/u8500/itp.c b/board/st/u8500/itp.c
index e7ef4fa7e..033d3d03c 100644
--- a/board/st/u8500/itp.c
+++ b/board/st/u8500/itp.c
@@ -13,7 +13,116 @@
#include "itp.h"
#include "cspsa_fp.h"
+#define SEC_ROM_FORCE_CLEAN_MASK 0x0020
+#define SEC_ROM_RET_OK 0x01
+#define ISSWAPI_SECURE_LOAD 0x10000002
+#define ISSWAPI_FLUSH_BOOT_CODE 0x11000003
+#define IPL_ITEM_ID 0x02
+typedef u32 (*boot_rom_bridge_func_t)(const u32 , const u32, const va_list);
+
+static boot_rom_bridge_func_t hw_sec_rom_pub_bridge;
+
+struct sec_rom_cut_desc {
+ u32 cutid_addr;
+ u32 cutid;
+ u32 bridge_func;
+};
+
+static const struct sec_rom_cut_desc cuttable[] = {
+ { 0x9001FFF4, 0x008500A0, 0x90018300 },
+ { 0x9001FFF4, 0x008500A1, 0x90018300 },
+ { 0x9001FFF4, 0x005500A0, 0x90018300 },
+ { 0x9001DBF4, 0x008500B0, 0x90017300 },
+};
+
+static u32 itp_call_secure_service(const u32 serviceid,
+ const u32 secureconfig,
+ ...)
+{
+ va_list ap;
+ u32 returnvalue;
+
+ va_start(ap, secureconfig);
+
+ returnvalue = hw_sec_rom_pub_bridge(serviceid,
+ secureconfig,
+ ap);
+
+ va_end(ap);
+ return returnvalue;
+}
+
+static int itp_init_bridge(void)
+{
+ u8 cutnb = 0;
+
+ hw_sec_rom_pub_bridge = NULL;
+
+ while ((cutnb < ARRAY_SIZE(cuttable)) &&
+ (cuttable[cutnb].cutid != *(u32 *)(cuttable[cutnb].cutid_addr)))
+ cutnb++;
+
+ if (cutnb < ARRAY_SIZE(cuttable)) {
+ hw_sec_rom_pub_bridge =
+ (boot_rom_bridge_func_t)cuttable[cutnb].bridge_func;
+ return 0;
+ }
+
+ printf("itp_init_bridge: cutid not found\n");
+ return 1;
+}
+
+static int itp_flush_issw(void)
+{
+ u32 ret;
+
+ ret = itp_call_secure_service(ISSWAPI_FLUSH_BOOT_CODE,
+ SEC_ROM_FORCE_CLEAN_MASK,
+ 0,
+ 0);
+
+ if (ret != SEC_ROM_RET_OK) {
+ printf("itp_flush_issw: ISSWAPI_FLUSH_BOOT_CODE failed: %d\n",
+ ret);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int itp_load_ipl(block_dev_desc_t *block_dev)
+{
+ u32 offset;
+ u32 size;
+ u32 loadaddr;
+ u32 returnvalue;
+ int ab8500_cutid;
+
+ debug("loadipl\n");
+
+ /* Check if IPL partition is present */
+ if (get_entry_info_toc(block_dev, ITP_TOC_IPL_NAME, &offset,
+ &size, &loadaddr)) {
+ printf("itp_load_ipl: get_entry_info_toc failed\n");
+ return 1;
+ }
+
+ /* Get CutID */
+ ab8500_cutid = ab8500_read(AB8500_MISC, AB8500_REV_REG);
+
+ returnvalue = itp_call_secure_service((u32)ISSWAPI_SECURE_LOAD,
+ SEC_ROM_FORCE_CLEAN_MASK,
+ IPL_ITEM_ID,
+ ab8500_cutid);
+ if (returnvalue != SEC_ROM_RET_OK) {
+ printf("itp_load_ipl: ISSWAPI_SECURE_LOAD failed: %d\n",
+ returnvalue);
+ return 1;
+ }
+
+ return 0;
+}
static int itp_load_toc_entry(block_dev_desc_t *block_dev,
const char *partname,
u32 *loadaddress)
@@ -47,36 +156,62 @@ static int itp_load_toc_entry(block_dev_desc_t *block_dev,
}
/*
- * itp_load_itp - Loads itp depending on config.
+ * itp_load_itp_and_modem - Loads itp and modem depending on config.
* If itp is loaded ok it will be executed and u-boot execution will stop
*/
-int itp_load_itp(block_dev_desc_t *block_dev)
+int itp_load_itp_and_modem(block_dev_desc_t *block_dev)
{
+ int retval = 0;
u32 cspsa_key;
void (*loadaddress)(void) = NULL;
- debug("\nitp_load_itp\n");
+ debug("\nitp_load_itp_and_modem\n");
+
+ if (itp_init_bridge()) {
+ retval = 1;
+ goto exit;
+ }
if (cspsa_fp_read(block_dev,
ITP_CSPSA_KEY,
&cspsa_key)) {
- printf("itp_load_itp: cspsa_fp_read failed\n");
- return 1;
+ printf("itp_load_itp_and_modem: cspsa_fp_read failed\n");
+ retval = 1;
+ goto exit;
+ }
+
+ if (cspsa_key & ITP_LOAD_MODEM) {
+ if (itp_load_toc_entry(block_dev,
+ ITP_TOC_MODEM_NAME,
+ (u32 *)loadaddress)) {
+ retval = 1;
+ goto exit;
+ }
+
+ if (itp_load_ipl(block_dev)) {
+ retval = 1;
+ goto exit;
+ }
}
if (cspsa_key & ITP_LOAD_ITP) {
if (itp_load_toc_entry(block_dev,
ITP_TOC_ITP_NAME,
(u32 *)loadaddress)) {
- printf("itp_load_itp: itp_load_partition failed\n");
- return 1;
+ retval = 1;
+ goto exit;
}
- loadaddress(); /* U-boot execution will end here*/
-
- printf("itp_load_itp: itp execution failed\n");
- return 1;
}
- return 0;
+exit:
+ /* Always Flush */
+ if (hw_sec_rom_pub_bridge != NULL)
+ itp_flush_issw();
+
+ if ((cspsa_key & ITP_LOAD_ITP) && !retval)
+ loadaddress(); /* U-boot execution will end here*/
+
+ /* Return on error */
+ return retval;
}
diff --git a/board/st/u8500/itp.h b/board/st/u8500/itp.h
index 74dc6b65b..13d039eed 100644
--- a/board/st/u8500/itp.h
+++ b/board/st/u8500/itp.h
@@ -16,9 +16,11 @@
#define ITP_LOAD_ITP 0x04
#define ITP_TOC_ITP_NAME "ITP"
+#define ITP_TOC_MODEM_NAME "MODEM"
+#define ITP_TOC_IPL_NAME "IPL"
#define ITP_CSPSA_KEY 0
-int itp_load_itp(block_dev_desc_t *block_dev);
+int itp_load_itp_and_modem(block_dev_desc_t *block_dev);
#endif /* __ITP_H__ */
diff --git a/board/st/u8500/mmc_host.c b/board/st/u8500/mmc_host.c
index a77793620..79be58acd 100644
--- a/board/st/u8500/mmc_host.c
+++ b/board/st/u8500/mmc_host.c
@@ -625,7 +625,7 @@ int board_mmc_init(bd_t *bis)
*/
#ifdef CONFIG_ITP_LOAD
- itp_load_itp(&dev->block_dev);
+ itp_load_itp_and_modem(&dev->block_dev);
#endif
dev = alloc_mmc_struct();