From 17651dcf23fd4e5654b191d6d706091d5a3faf17 Mon Sep 17 00:00:00 2001 From: Paer-Olof Haakansson Date: Fri, 28 Oct 2011 13:38:57 +0200 Subject: Add support for AP9500 in same binary as for U8500 Checks ASIC ID and skips trying to load ITP and modem in case the ASIC belongs to the AP9500 family. Copies tee functionality from U5500 board and uses secure world call to retrieve the ASIC ID. ST-Ericsson ID: 363927 ST-Ericsson FOSS-OUT ID: NA Change-Id: I37aed523679e62286e2ac023ce75e928afe3fcf1 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35765 Reviewed-by: QATOOLS Reviewed-by: Daniel FLINK Reviewed-by: QATEST Reviewed-by: Par-Olof HAKANSSON Tested-by: Par-Olof HAKANSSON --- board/st-ericsson/u8500/u8500.c | 21 ++++--- cpu/arm_cortexa9/db8500/Makefile | 1 + cpu/arm_cortexa9/db8500/cpu.c | 53 ++++++++++------- cpu/arm_cortexa9/db8500/tee.c | 121 ++++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-db8500/cpu.h | 25 ++++++++ include/asm-arm/arch-db8500/tee.h | 39 ++++++++++++ include/asm-arm/mach-types.h | 13 ++++ 7 files changed, 243 insertions(+), 30 deletions(-) create mode 100644 cpu/arm_cortexa9/db8500/tee.c create mode 100644 include/asm-arm/arch-db8500/tee.h diff --git a/board/st-ericsson/u8500/u8500.c b/board/st-ericsson/u8500/u8500.c index 3ad998dda..776eba791 100644 --- a/board/st-ericsson/u8500/u8500.c +++ b/board/st-ericsson/u8500/u8500.c @@ -30,9 +30,6 @@ #ifdef CONFIG_VIDEO_LOGO #include "mcde_display.h" #endif -#define NOMADIK_PER4_BASE (0x80150000) -#define NOMADIK_BACKUPRAM0_BASE (NOMADIK_PER4_BASE + 0x00000) -#define NOMADIK_BACKUPRAM1_BASE (NOMADIK_PER4_BASE + 0x01000) /* * Memory controller register @@ -208,7 +205,10 @@ int board_init(void) * Linux startup code and is the machine_id. * bi_boot_params: Where this board expects params. */ - gd->bd->bi_arch_number = MACH_TYPE_U8500; + if (cpu_is_a9500_generic()) + gd->bd->bi_arch_number = MACH_TYPE_A9500; + else + gd->bd->bi_arch_number = MACH_TYPE_U8500; gd->bd->bi_boot_params = 0x00000100; /* Configure GPIO pins needed by U-boot */ @@ -434,7 +434,8 @@ static void probe_href(void) * */ - if (gd->bd->bi_arch_number == MACH_TYPE_U8500) { + if (gd->bd->bi_arch_number == MACH_TYPE_U8500 || + gd->bd->bi_arch_number == MACH_TYPE_A9500) { (void) i2c_set_bus_num(0); if (!i2c_read(CONFIG_SYS_I2C_GPIOE_ADDR, 0x80, 1, &byte, 1)) { if (byte == 0x01) @@ -493,14 +494,17 @@ int board_early_access(block_dev_desc_t *block_dev) * Don't load itp, modem and splash if restarted (eg crashdump). */ if (!(data_init_flag > 0)) { + #ifdef CONFIG_ITP_LOAD - itp_read_config(block_dev); + if (!cpu_is_a9500_generic()) + itp_read_config(block_dev); #endif #ifdef CONFIG_VIDEO_LOGO /* only load splash if not itp */ #ifdef CONFIG_ITP_LOAD - if (!itp_is_itp_in_config()) + if (!itp_is_itp_in_config() || + cpu_is_a9500_generic()) mcde_error = dss_init(); #else mcde_error = dss_init(); @@ -508,7 +512,8 @@ int board_early_access(block_dev_desc_t *block_dev) #endif #ifdef CONFIG_ITP_LOAD - if (itp_load_itp_and_modem(block_dev)) + if (!cpu_is_a9500_generic() && + itp_load_itp_and_modem(block_dev)) return 1; #endif } diff --git a/cpu/arm_cortexa9/db8500/Makefile b/cpu/arm_cortexa9/db8500/Makefile index 964343a8e..20064e3e3 100644 --- a/cpu/arm_cortexa9/db8500/Makefile +++ b/cpu/arm_cortexa9/db8500/Makefile @@ -35,6 +35,7 @@ COBJS += cpu.o COBJS += interrupts.o COBJS += prcmu.o COBJS += timer.o +COBJS += tee.o COBJS-$(CONFIG_ITP_LOAD) += itp.o sec_bridge.o COBJS += $(COBJS-y) diff --git a/cpu/arm_cortexa9/db8500/cpu.c b/cpu/arm_cortexa9/db8500/cpu.c index fb9ed974f..8b531c90c 100644 --- a/cpu/arm_cortexa9/db8500/cpu.c +++ b/cpu/arm_cortexa9/db8500/cpu.c @@ -79,30 +79,39 @@ int arch_cpu_init(void) #ifdef CONFIG_DISPLAY_CPUINFO int print_cpuinfo(void) { - char *version, *clock; + char *cpu, *version, *clock; char clockbuf[24]; uint32_t arm_khz; - /* CPU version: Match most likely CPU first */ - if (cpu_is_u8500v2()) { - if (cpu_is_u8500v22()) - version = "v2.2"; - else if (cpu_is_u8500v21()) - version = "v2.1"; - else if (cpu_is_u8500v20()) - version = "v2.0"; - else if (cpu_is_u8520v22()) - version = "u8520v2.2"; + if (cpu_is_a9500_generic()) { + cpu = "a9500"; + if (cpu_is_a9500v1()) + version = "v1.0"; else - version = "v2.x"; - } else if (cpu_is_u8500v11()) - version = "v1.1"; - else if (cpu_is_u8500v1()) - version = "v1.0"; - else if (u8500_is_earlydrop()) - version = "ED"; - else - version = "Unknown"; + version = "Unknown"; + } else { + cpu = "db8500"; + /* CPU version: Match most likely CPU first */ + if (cpu_is_u8500v2()) { + if (cpu_is_u8500v22()) + version = "v2.2"; + else if (cpu_is_u8500v21()) + version = "v2.1"; + else if (cpu_is_u8500v20()) + version = "v2.0"; + else if (cpu_is_u8520v22()) + version = "u8520v2.2"; + else + version = "v2.x"; + } else if (cpu_is_u8500v11()) + version = "v1.1"; + else if (cpu_is_u8500v1()) + version = "v1.0"; + else if (u8500_is_earlydrop()) + version = "ED"; + else + version = "Unknown"; + } /* CPU clock speed */ arm_khz = db8500_clock_cpu_khz(); @@ -114,8 +123,8 @@ int print_cpuinfo(void) clock = clockbuf; } - printf("CPU:\tST-Ericsson db8500 %s (Dual ARM Cortex A9) " - "currently at %s\n", version, clock); + printf("CPU:\tST-Ericsson %s %s (Dual ARM Cortex A9) " + "currently at %s\n", cpu, version, clock); return 0; } diff --git a/cpu/arm_cortexa9/db8500/tee.c b/cpu/arm_cortexa9/db8500/tee.c new file mode 100644 index 000000000..c74ebf786 --- /dev/null +++ b/cpu/arm_cortexa9/db8500/tee.c @@ -0,0 +1,121 @@ +/* + * Code ported from tee in ST-Ericsson Linux kernel. + * + * Original Linux authors: + * Copyright (C) ST-Ericsson SA 2010 + * Authors: Shujuan Chen + * Martin Hovang + * + * Ported to U-boot by: + * Copyright (C) ST-Ericsson SA 2010 + * Author: Mikael Larsson for ST-Ericsson. + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#include +#include + +/* + * Defines the number of available memory references in an open session or + * invoke command operation payload. + */ +#define TEEC_CONFIG_PAYLOAD_REF_COUNT 4 + +/* + * Flag constants indicating which of the memory references in an open session + * or invoke command operation payload (TEEC_Operation) that are used. Type is + * u32. + */ +#define TEEC_MEMREF_0_USED 0x00000001 +#define TEEC_MEMREF_1_USED 0x00000002 +#define TEEC_MEMREF_2_USED 0x00000004 +#define TEEC_MEMREF_3_USED 0x00000008 + +/* + * Flag constants indicating the data transfer direction of memory in + * TEEC_SharedMemory and TEEC_MemoryReference. TEEC_MEM_INPUT signifies data + * transfer direction from the client application to the TEE. TEEC_MEM_OUTPUT + * signifies data transfer direction from the TEE to the client application. + * Type is u32. + */ +#define TEEC_MEM_INPUT 0x00000001 +#define TEEC_MEM_OUTPUT 0x00000002 + +#define BASS_APP_ISSWAPI_EXECUTE_TA 0x11000001 +#define BASS_APP_ISSWAPI_CLOSE_TA 0x11000002 + + +#define BASS_APP_GET_PRODUCT_ID 9 + +#define SEC_ROM_FORCE_CLEAN_MASK 0x0020 + +typedef struct { + u32 timeLow; + u16 timeMid; + u16 timeHiAndVersion; + u8 clockSeqAndNode[8]; +} TEEC_UUID; + +typedef struct { + void *buffer; + size_t size; + u32 flags; +} TEEC_SharedMemory; + +typedef struct { + TEEC_SharedMemory memRefs[TEEC_CONFIG_PAYLOAD_REF_COUNT]; + u32 flags; +} TEEC_Operation; + +int get_productid(u32 *const product_id) +{ + int ret = 0; + u32 org; + u32 id = 0; + TEEC_SharedMemory shm; + TEEC_Operation operation; + + /* UUID for static TA */ + TEEC_UUID uuid = { + 0xBC765EDE, + 0x6724, + 0x11DF, + {0x8E, 0x12, 0xEC, 0xDB, 0xDF, 0xD7, 0x20, 0x85} + }; + + sec_bridge_init_bridge(); + + shm.flags = TEEC_MEM_INPUT; + + memset((void *)(&operation), 0, sizeof(TEEC_Operation)); + + *product_id = 0; + + operation.memRefs[0].buffer = product_id; + operation.memRefs[0].size = sizeof(product_id); + operation.memRefs[0].flags = TEEC_MEM_OUTPUT; + + operation.flags = TEEC_MEMREF_0_USED; + + /* Call ISSW to verify and start modem */ + sec_bridge_call_secure_service(BASS_APP_ISSWAPI_EXECUTE_TA, + SEC_ROM_FORCE_CLEAN_MASK, + &id, + &uuid, + NULL, + BASS_APP_GET_PRODUCT_ID, + &operation, + &ret, + &org); + + /* Call ISSW to stop TA*/ + sec_bridge_call_secure_service(BASS_APP_ISSWAPI_CLOSE_TA, + SEC_ROM_FORCE_CLEAN_MASK, + &id, + &uuid, + NULL, + NULL); + + return ret; +} diff --git a/include/asm-arm/arch-db8500/cpu.h b/include/asm-arm/arch-db8500/cpu.h index d1fb4f20f..43f9211a1 100644 --- a/include/asm-arm/arch-db8500/cpu.h +++ b/include/asm-arm/arch-db8500/cpu.h @@ -14,6 +14,7 @@ #include #include +#include #define CPUID_DB8500ED 0x410fc090 #define CPUID_DB8500V1 0x411fc091 @@ -24,6 +25,7 @@ #define ASICID_DB8500V21 0x008500B1 #define ASICID_DB8500V22 0x008500B2 #define ASICID_DB8520V22 0x008520B2 + /* * Keep these CPU identity functions inline here because they are short * and used by many. Will make for fast optimized compiled code. @@ -57,6 +59,29 @@ static inline int cpu_is_u8500v2(void) return read_cpuid() == CPUID_DB8500V2; } +static inline int cpu_is_a9500_generic(void) +{ + unsigned int product_id; + int ret_val; + + ret_val = get_productid(&product_id); + + /* Only one version exists so far (Nov 2011) */ + return (!ret_val && + product_id == PRODUCT_ID_9500); +} + +static inline int cpu_is_a9500v1(void) +{ + unsigned int product_id; + int ret_val; + + ret_val = get_productid(&product_id); + + return (!ret_val && + product_id == PRODUCT_ID_9500); +} + static inline unsigned int read_asicid(void) { unsigned int *address; diff --git a/include/asm-arm/arch-db8500/tee.h b/include/asm-arm/arch-db8500/tee.h new file mode 100644 index 000000000..54be80c46 --- /dev/null +++ b/include/asm-arm/arch-db8500/tee.h @@ -0,0 +1,39 @@ +/* + * Code ported from tee in ST-Ericsson Linux kernel. + * + * Original Linux authors: + * Copyright (C) ST-Ericsson SA 2010 + * Authors: Shujuan Chen + * Martin Hovang + * + * Ported to U-boot by: + * Copyright (C) ST-Ericsson SA 2011 + * Author: Paer-Olof Haakansson + * for ST-Ericsson. + * + * License terms: GNU General Public License (GPL) version 2 + */ + +#ifndef _TEE_H +#define _TEE_H + +#include + +/** + * Product id numbers, copied from bass_app.h + * Note: Needs to be replicated from isswapi_types.h + */ +enum tee_product_id { + PRODUCT_ID_UNKNOWN = 0, + PRODUCT_ID_8400 = 1, /* Obsolete */ + PRODUCT_ID_8500B = 2, /* 1080p/1GHz/400MHz */ + PRODUCT_ID_9500 = 3, + PRODUCT_ID_5500 = 4, + PRODUCT_ID_7400 = 5, + PRODUCT_ID_8500C = 6, /* 720p/1GHz/400MHz */ + PRODUCT_ID_8500A = 7, /* 720p/800MHz/320MHz */ +}; + +int get_productid(u32 *const product_id); + +#endif diff --git a/include/asm-arm/mach-types.h b/include/asm-arm/mach-types.h index 28ef1e9f2..65a35fe43 100644 --- a/include/asm-arm/mach-types.h +++ b/include/asm-arm/mach-types.h @@ -3166,6 +3166,7 @@ extern unsigned int __machine_arch_type; #define MACH_TYPE_SPADE_LTE 3183 #define MACH_TYPE_PHILHWANI 3184 #define MACH_TYPE_GSNCOMM 3185 +#define MACH_TYPE_A9500 3867 /* manually added, but official value */ #define MACH_TYPE_HREFV60 3293 /* 0x0cdd */ @@ -31226,6 +31227,18 @@ extern unsigned int __machine_arch_type; # define machine_is_u8500() (0) #endif +#ifdef CONFIG_MACH_A9500 +# ifdef machine_arch_type +# undef machine_arch_type +# define machine_arch_type __machine_arch_type +# else +# define machine_arch_type MACH_TYPE_A9500 +# endif +# define machine_is_a9500() (machine_arch_type == MACH_TYPE_A9500) +#else +# define machine_is_a9500() (0) +#endif + #ifdef CONFIG_MACH_HUQIU # ifdef machine_arch_type # undef machine_arch_type -- cgit v1.2.3