feat(mediatek): add APU bootup control smc call
Add APU bootup control smc call.
The steps of bootup flow:
1. set up APU config.
2. reset APU.
3. set up APU boot config.
4. boot APU.
Change-Id: I9e930070a64c7c4dcaa3a8b3d28b897823e9f53c
diff --git a/plat/mediatek/drivers/apusys/apusys.c b/plat/mediatek/drivers/apusys/apusys.c
index 33cfe93..1aaf7cc 100644
--- a/plat/mediatek/drivers/apusys/apusys.c
+++ b/plat/mediatek/drivers/apusys/apusys.c
@@ -35,6 +35,21 @@
case MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_OFF:
ret = apusys_kernel_apusys_pwr_top_off();
break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_REVISER:
+ ret = apusys_kernel_apusys_rv_setup_reviser();
+ break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_RV_RESET_MP:
+ ret = apusys_kernel_apusys_rv_reset_mp();
+ break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_BOOT:
+ ret = apusys_kernel_apusys_rv_setup_boot();
+ break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_RV_START_MP:
+ ret = apusys_kernel_apusys_rv_start_mp();
+ break;
+ case MTK_APUSYS_KERNEL_OP_APUSYS_RV_STOP_MP:
+ ret = apusys_kernel_apusys_rv_stop_mp();
+ break;
default:
ERROR(MODULE_TAG "%s unknown request_ops = %x\n", MODULE_TAG, request_ops);
break;
diff --git a/plat/mediatek/drivers/apusys/apusys.h b/plat/mediatek/drivers/apusys/apusys.h
index 1592cff..93ed6a7 100644
--- a/plat/mediatek/drivers/apusys/apusys.h
+++ b/plat/mediatek/drivers/apusys/apusys.h
@@ -10,8 +10,13 @@
#define MODULE_TAG "[APUSYS]"
enum MTK_APUSYS_KERNEL_OP {
- MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_ON, /* 0 */
- MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_OFF,/* 1 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_ON, /* 0 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_OFF, /* 1 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_REVISER, /* 2 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_RESET_MP, /* 3 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_SETUP_BOOT, /* 4 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_START_MP, /* 5 */
+ MTK_APUSYS_KERNEL_OP_APUSYS_RV_STOP_MP, /* 6 */
MTK_APUSYS_KERNEL_OP_NUM,
};
diff --git a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c
index 42f3b3f..fef8661 100644
--- a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c
+++ b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.c
@@ -6,12 +6,17 @@
/* TF-A system header */
#include <common/debug.h>
+#include <drivers/delay_timer.h>
#include <lib/mmio.h>
+#include <lib/spinlock.h>
/* Vendor header */
+#include "apusys.h"
#include "apusys_rv.h"
#include "apusys_rv_mbox_mpu.h"
+static spinlock_t apusys_rv_lock;
+
void apusys_rv_mbox_mpu_init(void)
{
int i;
@@ -27,4 +32,152 @@
(mbox_mpu_setting_tab[i].tx_ns << MBOX_TX_NS_SHIFT) |
(mbox_mpu_setting_tab[i].tx_domain << MBOX_TX_DOMAIN_SHIFT)));
}
+}
+
+int apusys_kernel_apusys_rv_setup_reviser(void)
+{
+ static bool apusys_rv_setup_reviser_called;
+
+ spin_lock(&apusys_rv_lock);
+
+ if (apusys_rv_setup_reviser_called) {
+ WARN(MODULE_TAG "%s: already initialized\n", __func__);
+ spin_unlock(&apusys_rv_lock);
+ return -1;
+ }
+
+ apusys_rv_setup_reviser_called = true;
+
+ mmio_write_32(USERFW_CTXT, CFG_4GB_SEL_EN | CFG_4GB_SEL);
+ mmio_write_32(SECUREFW_CTXT, CFG_4GB_SEL_EN | CFG_4GB_SEL);
+
+ mmio_write_32(UP_IOMMU_CTRL, MMU_CTRL_LOCK | MMU_CTRL | MMU_EN);
+
+ mmio_write_32(UP_NORMAL_DOMAIN_NS,
+ (UP_NORMAL_DOMAIN << UP_DOMAIN_SHIFT) | (UP_NORMAL_NS << UP_NS_SHIFT));
+ mmio_write_32(UP_PRI_DOMAIN_NS,
+ (UP_PRI_DOMAIN << UP_DOMAIN_SHIFT) | (UP_PRI_NS << UP_NS_SHIFT));
+
+ mmio_write_32(UP_CORE0_VABASE0,
+ VLD | PARTIAL_ENABLE | (THREAD_NUM_PRI << THREAD_NUM_SHIFT));
+ mmio_write_32(UP_CORE0_MVABASE0, VASIZE_1MB | (APU_SEC_FW_IOVA >> MVA_34BIT_SHIFT));
+
+ mmio_write_32(UP_CORE0_VABASE1,
+ VLD | PARTIAL_ENABLE | (THREAD_NUM_NORMAL << THREAD_NUM_SHIFT));
+ mmio_write_32(UP_CORE0_MVABASE1, VASIZE_1MB | (APU_SEC_FW_IOVA >> MVA_34BIT_SHIFT));
+
+ spin_unlock(&apusys_rv_lock);
+
+ return 0;
+}
+
+int apusys_kernel_apusys_rv_reset_mp(void)
+{
+ static bool apusys_rv_reset_mp_called;
+
+ spin_lock(&apusys_rv_lock);
+
+ if (apusys_rv_reset_mp_called) {
+ WARN(MODULE_TAG "%s: already initialized\n", __func__);
+ spin_unlock(&apusys_rv_lock);
+ return -1;
+ }
+
+ apusys_rv_reset_mp_called = true;
+
+ mmio_write_32(MD32_SYS_CTRL, MD32_SYS_CTRL_RST);
+
+ udelay(RESET_DEALY_US);
+
+ mmio_write_32(MD32_SYS_CTRL, MD32_G2B_CG_EN | MD32_DBG_EN | MD32_DM_AWUSER_IOMMU_EN |
+ MD32_DM_ARUSER_IOMMU_EN | MD32_PM_AWUSER_IOMMU_EN | MD32_PM_ARUSER_IOMMU_EN |
+ MD32_SOFT_RSTN);
+
+ mmio_write_32(MD32_CLK_CTRL, MD32_CLK_EN);
+ mmio_write_32(UP_WAKE_HOST_MASK0, WDT_IRQ_EN);
+ mmio_write_32(UP_WAKE_HOST_MASK1, MBOX0_IRQ_EN | MBOX1_IRQ_EN | MBOX2_IRQ_EN);
+
+ spin_unlock(&apusys_rv_lock);
+
+ return 0;
+}
+
+int apusys_kernel_apusys_rv_setup_boot(void)
+{
+ static bool apusys_rv_setup_boot_called;
+
+ spin_lock(&apusys_rv_lock);
+
+ if (apusys_rv_setup_boot_called) {
+ WARN(MODULE_TAG "%s: already initialized\n", __func__);
+ spin_unlock(&apusys_rv_lock);
+ return -1;
+ }
+
+ apusys_rv_setup_boot_called = true;
+
+ mmio_write_32(MD32_BOOT_CTRL, APU_SEC_FW_IOVA);
+
+ mmio_write_32(MD32_PRE_DEFINE, (PREDEFINE_CACHE_TCM << PREDEF_1G_OFS) |
+ (PREDEFINE_CACHE << PREDEF_2G_OFS) | (PREDEFINE_CACHE << PREDEF_3G_OFS) |
+ (PREDEFINE_CACHE << PREDEF_4G_OFS));
+
+ spin_unlock(&apusys_rv_lock);
+ return 0;
+}
+
+int apusys_kernel_apusys_rv_start_mp(void)
+{
+ static bool apusys_rv_start_mp_called;
+
+ spin_lock(&apusys_rv_lock);
+
+ if (apusys_rv_start_mp_called) {
+ WARN(MODULE_TAG "%s: already initialized\n", __func__);
+ spin_unlock(&apusys_rv_lock);
+ return -1;
+ }
+
+ apusys_rv_start_mp_called = true;
+
+ mmio_write_32(MD32_RUNSTALL, MD32_RUN);
+
+ spin_unlock(&apusys_rv_lock);
+
+ return 0;
+}
+
+static bool watch_dog_is_timeout(void)
+{
+ if (mmio_read_32(WDT_INT) != WDT_INT_W1C) {
+ ERROR(MODULE_TAG "%s: WDT does not timeout\n", __func__);
+ return false;
+ }
+ return true;
+}
+
+int apusys_kernel_apusys_rv_stop_mp(void)
+{
+ static bool apusys_rv_stop_mp_called;
+
+ spin_lock(&apusys_rv_lock);
+
+ if (apusys_rv_stop_mp_called) {
+ WARN(MODULE_TAG "%s: already initialized\n", __func__);
+ spin_unlock(&apusys_rv_lock);
+ return -1;
+ }
+
+ if (watch_dog_is_timeout() == false) {
+ spin_unlock(&apusys_rv_lock);
+ return -1;
+ }
+
+ apusys_rv_stop_mp_called = true;
+
+ mmio_write_32(MD32_RUNSTALL, MD32_STALL);
+
+ spin_unlock(&apusys_rv_lock);
+
+ return 0;
}
diff --git a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.h b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.h
index f21835e..150f404 100644
--- a/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.h
+++ b/plat/mediatek/drivers/apusys/apusys_rv/2.0/apusys_rv.h
@@ -9,17 +9,87 @@
#include <platform_def.h>
+#define APU_SEC_FW_IOVA (0x200000UL)
+
+/* APU_SCTRL_REVISER */
+#define UP_NORMAL_DOMAIN_NS (APU_REVISER + 0x0000)
+#define UP_PRI_DOMAIN_NS (APU_REVISER + 0x0004)
+#define UP_IOMMU_CTRL (APU_REVISER + 0x0008)
+#define UP_CORE0_VABASE0 (APU_REVISER + 0x000c)
+#define UP_CORE0_MVABASE0 (APU_REVISER + 0x0010)
+#define UP_CORE0_VABASE1 (APU_REVISER + 0x0014)
+#define UP_CORE0_MVABASE1 (APU_REVISER + 0x0018)
+#define USERFW_CTXT (APU_REVISER + 0x1000)
+#define SECUREFW_CTXT (APU_REVISER + 0x1004)
+#define UP_NORMAL_DOMAIN (7)
+#define UP_NORMAL_NS (1)
+#define UP_PRI_DOMAIN (5)
+#define UP_PRI_NS (1)
+#define UP_DOMAIN_SHIFT (0)
+#define UP_NS_SHIFT (4)
+#define MMU_EN BIT(0)
+#define MMU_CTRL BIT(1)
+#define MMU_CTRL_LOCK BIT(2)
+#define VLD BIT(0)
+#define PARTIAL_ENABLE BIT(1)
+#define THREAD_NUM_PRI (1)
+#define THREAD_NUM_NORMAL (0)
+#define THREAD_NUM_SHIFT (2)
+#define VASIZE_1MB BIT(0)
+#define CFG_4GB_SEL_EN BIT(2)
+#define CFG_4GB_SEL (0)
+#define MVA_34BIT_SHIFT (2)
+
+/* APU_MD32_SYSCTRL */
+#define MD32_SYS_CTRL (APU_MD32_SYSCTRL + 0x0000)
+#define MD32_CLK_CTRL (APU_MD32_SYSCTRL + 0x00b8)
+#define UP_WAKE_HOST_MASK0 (APU_MD32_SYSCTRL + 0x00bc)
+#define UP_WAKE_HOST_MASK1 (APU_MD32_SYSCTRL + 0x00c0)
+#define MD32_SYS_CTRL_RST (0)
+#define MD32_G2B_CG_EN BIT(11)
+#define MD32_DBG_EN BIT(10)
+#define MD32_DM_AWUSER_IOMMU_EN BIT(9)
+#define MD32_DM_ARUSER_IOMMU_EN BIT(7)
+#define MD32_PM_AWUSER_IOMMU_EN BIT(5)
+#define MD32_PM_ARUSER_IOMMU_EN BIT(3)
+#define MD32_SOFT_RSTN BIT(0)
+#define MD32_CLK_EN (1)
+#define WDT_IRQ_EN BIT(0)
+#define MBOX0_IRQ_EN BIT(21)
+#define MBOX1_IRQ_EN BIT(22)
+#define MBOX2_IRQ_EN BIT(23)
+#define RESET_DEALY_US (10)
+
+/* APU_AO_CTRL */
+#define MD32_PRE_DEFINE (APU_AO_CTRL + 0x0000)
+#define MD32_BOOT_CTRL (APU_AO_CTRL + 0x0004)
+#define MD32_RUNSTALL (APU_AO_CTRL + 0x0008)
+#define PREDEFINE_NON_CACHE (0)
+#define PREDEFINE_TCM (1)
+#define PREDEFINE_CACHE (2)
+#define PREDEFINE_CACHE_TCM (3)
+#define PREDEF_1G_OFS (0)
+#define PREDEF_2G_OFS (2)
+#define PREDEF_3G_OFS (4)
+#define PREDEF_4G_OFS (6)
+#define MD32_RUN (0)
+#define MD32_STALL (1)
+
+/* APU_MD32_WDT */
+#define WDT_INT (APU_MD32_WDT + 0x0)
+#define WDT_INT_W1C (1)
+
/* APU MBOX */
-#define MBOX_FUNC_CFG (0xb0)
-#define MBOX_DOMAIN_CFG (0xe0)
-#define MBOX_CTRL_LOCK BIT(0)
-#define MBOX_NO_MPU_SHIFT (16)
-#define MBOX_RX_NS_SHIFT (16)
-#define MBOX_RX_DOMAIN_SHIFT (17)
-#define MBOX_TX_NS_SHIFT (24)
-#define MBOX_TX_DOMAIN_SHIFT (25)
-#define MBOX_SIZE (0x100)
-#define MBOX_NUM (8)
+#define MBOX_FUNC_CFG (0xb0)
+#define MBOX_DOMAIN_CFG (0xe0)
+#define MBOX_CTRL_LOCK BIT(0)
+#define MBOX_NO_MPU_SHIFT (16)
+#define MBOX_RX_NS_SHIFT (16)
+#define MBOX_RX_DOMAIN_SHIFT (17)
+#define MBOX_TX_NS_SHIFT (24)
+#define MBOX_TX_DOMAIN_SHIFT (25)
+#define MBOX_SIZE (0x100)
+#define MBOX_NUM (8)
#define APU_MBOX(i) (((i) < MBOX_NUM) ? (APU_MBOX0 + MBOX_SIZE * (i)) : \
(APU_MBOX1 + MBOX_SIZE * ((i) - MBOX_NUM)))
@@ -27,5 +97,10 @@
#define APU_MBOX_DOMAIN_CFG(i) (APU_MBOX(i) + MBOX_DOMAIN_CFG)
void apusys_rv_mbox_mpu_init(void);
+int apusys_kernel_apusys_rv_setup_reviser(void);
+int apusys_kernel_apusys_rv_reset_mp(void);
+int apusys_kernel_apusys_rv_setup_boot(void);
+int apusys_kernel_apusys_rv_start_mp(void);
+int apusys_kernel_apusys_rv_stop_mp(void);
#endif /* APUSYS_RV_H */