diff --git a/plat/mediatek/common/mtk_sip_svc.c b/plat/mediatek/common/mtk_sip_svc.c index 65916599f..021511e0d 100644 --- a/plat/mediatek/common/mtk_sip_svc.c +++ b/plat/mediatek/common/mtk_sip_svc.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -117,7 +118,8 @@ uint64_t sip_smc_handler(uint32_t smc_fid, switch (smc_fid) { case SIP_SVC_CALL_COUNT: /* Return the number of Mediatek SiP Service Calls. */ - SMC_RET1(handle, MTK_SIP_NUM_CALLS); + SMC_RET1(handle, + MTK_COMMON_SIP_NUM_CALLS + MTK_PLAT_SIP_NUM_CALLS); case SIP_SVC_UID: /* Return UID to the caller */ diff --git a/plat/mediatek/common/mtk_sip_svc.h b/plat/mediatek/common/mtk_sip_svc.h index 91252d16f..703e49aff 100644 --- a/plat/mediatek/common/mtk_sip_svc.h +++ b/plat/mediatek/common/mtk_sip_svc.h @@ -45,13 +45,10 @@ #define SMC_AARCH64_BIT 0x40000000 /* Number of Mediatek SiP Calls implemented */ -#define MTK_SIP_NUM_CALLS 4 +#define MTK_COMMON_SIP_NUM_CALLS 4 /* Mediatek SiP Service Calls function IDs */ #define MTK_SIP_SET_AUTHORIZED_SECURE_REG 0x82000001 -#define MTK_SIP_PWR_ON_MTCMOS 0x82000402 -#define MTK_SIP_PWR_OFF_MTCMOS 0x82000403 -#define MTK_SIP_PWR_MTCMOS_SUPPORT 0x82000404 /* For MTK SMC from Secure OS */ /* 0x82000000 - 0x820000FF & 0xC2000000 - 0xC20000FF */ @@ -76,7 +73,5 @@ enum { * Return MTK_SIP_E_SUCCESS on success, and MTK_SIP_E_INVALID_PARAM on failure. */ uint64_t mt_sip_set_authorized_sreg(uint32_t sreg, uint32_t val); -uint64_t mt_sip_pwr_on_mtcmos(uint32_t val); -uint64_t mt_sip_pwr_off_mtcmos(uint32_t val); -uint64_t mt_sip_pwr_mtcmos_support(void); + #endif /* __PLAT_SIP_SVC_H__ */ diff --git a/plat/mediatek/mt8173/drivers/crypt/crypt.c b/plat/mediatek/mt8173/drivers/crypt/crypt.c new file mode 100644 index 000000000..2fca0f5ea --- /dev/null +++ b/plat/mediatek/mt8173/drivers/crypt/crypt.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define crypt_read32(offset) \ + mmio_read_32((uintptr_t)(CRYPT_BASE+((offset) * 4))) + +#define crypt_write32(offset, value) \ + mmio_write_32((uintptr_t)(CRYPT_BASE + ((offset) * 4)), (uint32_t)value) + +#define GET_L32(x) ((uint32_t)(x & 0xffffffff)) +#define GET_H32(x) ((uint32_t)((x >> 32) & 0xffffffff)) + +#define REG_INIT 0 +#define REG_MSC 4 +#define REG_TRIG 256 +#define REG_STAT 512 +#define REG_CLR 513 +#define REG_INT 514 +#define REG_P68 768 +#define REG_P69 769 +#define REG_P70 770 +#define REG_P71 771 +#define REG_P72 772 +#define REG_D20 820 +#define KEY_SIZE 160 +#define KEY_LEN 40 + +/* Wait until crypt is completed */ +uint64_t crypt_wait(void) +{ + crypt_write32(REG_TRIG, 0); + while (crypt_read32(REG_STAT) == 0) + ; + udelay(100); + crypt_write32(REG_CLR, crypt_read32(REG_STAT)); + crypt_write32(REG_INT, 0); + return MTK_SIP_E_SUCCESS; +} + +static uint32_t record[4]; +/* Copy encrypted key to crypt engine */ +uint64_t crypt_set_hdcp_key_ex(uint64_t x1, uint64_t x2, uint64_t x3) +{ + uint32_t i = (uint32_t)x1; + uint32_t j = 0; + + if (i > KEY_LEN) + return MTK_SIP_E_INVALID_PARAM; + + if (i < KEY_LEN) { + crypt_write32(REG_MSC, 0x80ff3800); + crypt_write32(REG_INIT, 0); + crypt_write32(REG_INIT, 0xF); + crypt_write32(REG_CLR, 1); + crypt_write32(REG_INT, 0); + + crypt_write32(REG_P68, 0x70); + crypt_write32(REG_P69, 0x1C0); + crypt_write32(REG_P70, 0x30); + crypt_write32(REG_P71, 0x4); + crypt_wait(); + + crypt_write32(REG_D20 + 4 * i, GET_L32(x2)); + crypt_write32(REG_D20 + 4 * i + 1, GET_H32(x2)); + crypt_write32(REG_D20 + 4 * i + 2, GET_L32(x3)); + crypt_write32(REG_D20 + 4 * i + 3, GET_H32(x3)); + + crypt_write32(REG_P69, 0); + crypt_write32(REG_P68, 0x20); + crypt_write32(REG_P71, 0x34 + 4 * i); + crypt_write32(REG_P72, 0x34 + 4 * i); + crypt_wait(); + + for (j = 0; j < 4; j++) { + crypt_write32(REG_P68, 0x71); + crypt_write32(REG_P69, 0x34 + 4 * i + j); + crypt_write32(REG_P70, record[j]); + crypt_wait(); + } + } + /* Prepare data for next iteration */ + record[0] = GET_L32(x2); + record[1] = GET_H32(x2); + record[2] = GET_L32(x3); + record[3] = GET_H32(x3); + return MTK_SIP_E_SUCCESS; +} + +/* Set key to hdcp */ +uint64_t crypt_set_hdcp_key_num(uint32_t num) +{ + if (num > KEY_LEN) + return MTK_SIP_E_INVALID_PARAM; + + crypt_write32(REG_P68, 0x6A); + crypt_write32(REG_P69, 0x34 + 4 * num); + crypt_wait(); + return MTK_SIP_E_SUCCESS; +} + +/* Clear key in crypt engine */ +uint64_t crypt_clear_hdcp_key(void) +{ + uint32_t i; + + for (i = 0; i < KEY_SIZE; i++) + crypt_write32(REG_D20 + i, 0); + return MTK_SIP_E_SUCCESS; +} diff --git a/plat/mediatek/mt8173/drivers/crypt/crypt.h b/plat/mediatek/mt8173/drivers/crypt/crypt.h new file mode 100644 index 000000000..25e3077fc --- /dev/null +++ b/plat/mediatek/mt8173/drivers/crypt/crypt.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __CRYPT_H__ +#define __CRYPT_H__ + +#include + +/* crypt function prototype */ +uint64_t crypt_set_hdcp_key_ex(uint64_t x1, uint64_t x2, uint64_t x3); +uint64_t crypt_set_hdcp_key_num(uint32_t num); +uint64_t crypt_clear_hdcp_key(void); + +#endif /* __CRYPT_H__ */ diff --git a/plat/mediatek/mt8173/include/mt8173_def.h b/plat/mediatek/mt8173/include/mt8173_def.h index 0113d6099..360be6c86 100644 --- a/plat/mediatek/mt8173/include/mt8173_def.h +++ b/plat/mediatek/mt8173/include/mt8173_def.h @@ -50,6 +50,7 @@ #define MCUCFG_BASE (IO_PHYS + 0x200000) #define APMIXED_BASE (IO_PHYS + 0x209000) #define TRNG_BASE (IO_PHYS + 0x20F000) +#define CRYPT_BASE (IO_PHYS + 0x210000) #define MT_GIC_BASE (IO_PHYS + 0x220000) #define PLAT_MT_CCI_BASE (IO_PHYS + 0x390000) diff --git a/plat/mediatek/mt8173/include/plat_sip_calls.h b/plat/mediatek/mt8173/include/plat_sip_calls.h new file mode 100644 index 000000000..0fd84b24b --- /dev/null +++ b/plat/mediatek/mt8173/include/plat_sip_calls.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __PLAT_SIP_CALLS_H__ +#define __PLAT_SIP_CALLS_H__ + +/******************************************************************************* + * Plat SiP function constants + ******************************************************************************/ +#define MTK_PLAT_SIP_NUM_CALLS 6 + +#define MTK_SIP_PWR_ON_MTCMOS 0x82000402 +#define MTK_SIP_PWR_OFF_MTCMOS 0x82000403 +#define MTK_SIP_PWR_MTCMOS_SUPPORT 0x82000404 +#define MTK_SIP_SET_HDCP_KEY_NUM 0x82000405 +#define MTK_SIP_CLR_HDCP_KEY 0x82000406 +#define MTK_SIP_SET_HDCP_KEY_EX 0x82000407 + +#endif /* __PLAT_SIP_CALLS_H__ */ diff --git a/plat/mediatek/mt8173/plat_sip_calls.c b/plat/mediatek/mt8173/plat_sip_calls.c index e12892f01..6969ee3a7 100644 --- a/plat/mediatek/mt8173/plat_sip_calls.c +++ b/plat/mediatek/mt8173/plat_sip_calls.c @@ -27,9 +27,13 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include #include #include #include +#include +#include /* Authorized secure register list */ enum { @@ -57,7 +61,7 @@ uint64_t mt_sip_set_authorized_sreg(uint32_t sreg, uint32_t val) return MTK_SIP_E_INVALID_PARAM; } -uint64_t mt_sip_pwr_on_mtcmos(uint32_t val) +static uint64_t mt_sip_pwr_on_mtcmos(uint32_t val) { uint32_t ret; @@ -68,7 +72,7 @@ uint64_t mt_sip_pwr_on_mtcmos(uint32_t val) return MTK_SIP_E_SUCCESS; } -uint64_t mt_sip_pwr_off_mtcmos(uint32_t val) +static uint64_t mt_sip_pwr_off_mtcmos(uint32_t val) { uint32_t ret; @@ -79,7 +83,51 @@ uint64_t mt_sip_pwr_off_mtcmos(uint32_t val) return MTK_SIP_E_SUCCESS; } -uint64_t mt_sip_pwr_mtcmos_support(void) +static uint64_t mt_sip_pwr_mtcmos_support(void) { return MTK_SIP_E_SUCCESS; } + +uint64_t mediatek_plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + uint64_t ret; + + switch (smc_fid) { + case MTK_SIP_PWR_ON_MTCMOS: + ret = mt_sip_pwr_on_mtcmos((uint32_t)x1); + SMC_RET1(handle, ret); + + case MTK_SIP_PWR_OFF_MTCMOS: + ret = mt_sip_pwr_off_mtcmos((uint32_t)x1); + SMC_RET1(handle, ret); + + case MTK_SIP_PWR_MTCMOS_SUPPORT: + ret = mt_sip_pwr_mtcmos_support(); + SMC_RET1(handle, ret); + + case MTK_SIP_SET_HDCP_KEY_EX: + ret = crypt_set_hdcp_key_ex(x1, x2, x3); + SMC_RET1(handle, ret); + + case MTK_SIP_SET_HDCP_KEY_NUM: + ret = crypt_set_hdcp_key_num((uint32_t)x1); + SMC_RET1(handle, ret); + + case MTK_SIP_CLR_HDCP_KEY: + ret = crypt_clear_hdcp_key(); + SMC_RET1(handle, ret); + + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk index ab1d5d78c..1c550f35a 100644 --- a/plat/mediatek/mt8173/platform.mk +++ b/plat/mediatek/mt8173/platform.mk @@ -32,6 +32,7 @@ MTK_PLAT := plat/mediatek MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT_SOC}/drivers/crypt/ \ -I${MTK_PLAT_SOC}/drivers/mtcmos/ \ -I${MTK_PLAT_SOC}/drivers/pmic/ \ -I${MTK_PLAT_SOC}/drivers/rtc/ \ @@ -61,6 +62,7 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ ${MTK_PLAT_SOC}/aarch64/platform_common.c \ ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/drivers/crypt/crypt.c \ ${MTK_PLAT_SOC}/drivers/mtcmos/mtcmos.c \ ${MTK_PLAT_SOC}/drivers/pmic/pmic_wrap_init.c \ ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \