GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,231 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <devapc.h>
#include <drivers/console.h>
#include <lib/mmio.h>
static void set_master_transaction(uint32_t master_index,
enum TRANSACTION transaction_type)
{
uintptr_t base;
uint32_t master_register_index;
uint32_t master_set_index;
uint32_t set_bit;
master_register_index = master_index / (MOD_NO_IN_1_DEVAPC * 2);
master_set_index = master_index % (MOD_NO_IN_1_DEVAPC * 2);
base = DEVAPC_INFRA_MAS_SEC_0 + master_register_index * 4;
set_bit = 0x1 << master_set_index;
if (transaction_type == SECURE_TRANSACTION)
mmio_setbits_32(base, set_bit);
else
mmio_clrbits_32(base, set_bit);
}
static void set_master_domain(uint32_t master_index, enum MASK_DOM domain)
{
uintptr_t base;
uint32_t domain_reg;
uint32_t domain_index;
uint32_t clr_bit;
uint32_t set_bit;
domain_reg = master_index / MASTER_MOD_NO_IN_1_DEVAPC;
domain_index = master_index % MASTER_MOD_NO_IN_1_DEVAPC;
clr_bit = 0xF << (4 * domain_index);
set_bit = domain << (4 * domain_index);
base = DEVAPC_INFRA_MAS_DOM_0 + domain_reg * 4;
mmio_clrsetbits_32(base, clr_bit, set_bit);
}
static void set_master_domain_remap_infra(enum MASK_DOM domain_emi_view,
enum MASK_DOM domain_infra_view)
{
uintptr_t base;
uint32_t clr_bit;
uint32_t set_bit;
if (domain_emi_view < DOMAIN_10) {
base = DEVAPC_INFRA_DOM_RMP_0;
clr_bit = 0x7 << (domain_emi_view * 3);
set_bit = domain_infra_view << (domain_emi_view * 3);
mmio_clrsetbits_32(base, clr_bit, set_bit);
} else if (domain_emi_view > DOMAIN_10) {
base = DEVAPC_INFRA_DOM_RMP_1;
domain_emi_view = domain_emi_view - DOMAIN_11;
clr_bit = 0x7 << (domain_emi_view * 3 + 1);
set_bit = domain_infra_view << (domain_emi_view * 3 + 1);
mmio_clrsetbits_32(base, clr_bit, set_bit);
} else {
base = DEVAPC_INFRA_DOM_RMP_0;
clr_bit = 0x3 << (domain_emi_view * 3);
set_bit = domain_infra_view << (domain_emi_view * 3);
mmio_clrsetbits_32(base, clr_bit, set_bit);
base = DEVAPC_INFRA_DOM_RMP_1;
set_bit = (domain_infra_view & 0x4) >> 2;
mmio_clrsetbits_32(base, 0x1, set_bit);
}
}
static void set_master_domain_remap_mm(enum MASK_DOM domain_emi_view,
enum MASK_DOM domain_mm_view)
{
uintptr_t base;
uint32_t clr_bit;
uint32_t set_bit;
base = DEVAPC_MM_DOM_RMP_0;
clr_bit = 0x3 << (domain_emi_view * 2);
set_bit = domain_mm_view << (domain_emi_view * 2);
mmio_clrsetbits_32(base, clr_bit, set_bit);
}
static void set_module_apc(enum DAPC_SLAVE_TYPE slave_type, uint32_t module,
enum MASK_DOM domain_num,
enum APC_ATTR permission_control)
{
uintptr_t base;
uint32_t apc_index;
uint32_t apc_set_index;
uint32_t clr_bit;
uint32_t set_bit;
apc_index = module / MOD_NO_IN_1_DEVAPC;
apc_set_index = module % MOD_NO_IN_1_DEVAPC;
clr_bit = 0x3 << (apc_set_index * 2);
set_bit = permission_control << (apc_set_index * 2);
if (slave_type == DAPC_INFRA_SLAVE && module <= SLAVE_INFRA_MAX_INDEX)
base = DEVAPC_INFRA_D0_APC_0 + domain_num * 0x100 +
apc_index * 4;
else if (slave_type == DAPC_MM_SLAVE && module <= SLAVE_MM_MAX_INDEX)
base = DEVAPC_MM_D0_APC_0 + domain_num * 0x100 + apc_index * 4;
else
return;
mmio_clrsetbits_32(base, clr_bit, set_bit);
}
static void set_default_master_transaction(void)
{
set_master_transaction(MASTER_SSPM, SECURE_TRANSACTION);
}
static void set_default_master_domain(void)
{
set_master_domain(MASTER_SCP, DOMAIN_1);
set_master_domain_remap_infra(DOMAIN_1, DOMAIN_1);
set_master_domain_remap_mm(DOMAIN_1, DOMAIN_1);
set_master_domain(MASTER_SPM, DOMAIN_2);
set_master_domain_remap_infra(DOMAIN_2, DOMAIN_2);
set_master_domain_remap_mm(DOMAIN_2, DOMAIN_2);
set_master_domain(MASTER_SSPM, DOMAIN_2);
set_master_domain_remap_infra(DOMAIN_2, DOMAIN_2);
set_master_domain_remap_mm(DOMAIN_2, DOMAIN_2);
}
static void set_default_slave_permission(void)
{
uint32_t module_index;
uint32_t infra_size;
uint32_t mm_size;
infra_size = sizeof(D_APC_INFRA_Devices) / sizeof(struct DEVICE_INFO);
mm_size = sizeof(D_APC_MM_Devices) / sizeof(struct DEVICE_INFO);
for (module_index = 0; module_index < infra_size; module_index++) {
if (D_APC_INFRA_Devices[module_index].d0_permission > 0) {
set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_0,
D_APC_INFRA_Devices[module_index].d0_permission);
}
if (D_APC_INFRA_Devices[module_index].d1_permission > 0) {
set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_1,
D_APC_INFRA_Devices[module_index].d1_permission);
}
if (D_APC_INFRA_Devices[module_index].d2_permission > 0) {
set_module_apc(DAPC_INFRA_SLAVE, module_index, DOMAIN_2,
D_APC_INFRA_Devices[module_index].d2_permission);
}
}
for (module_index = 0; module_index < mm_size; module_index++) {
if (D_APC_MM_Devices[module_index].d0_permission > 0) {
set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_0,
D_APC_MM_Devices[module_index].d0_permission);
}
if (D_APC_MM_Devices[module_index].d1_permission > 0) {
set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_1,
D_APC_MM_Devices[module_index].d1_permission);
}
if (D_APC_MM_Devices[module_index].d2_permission > 0) {
set_module_apc(DAPC_MM_SLAVE, module_index, DOMAIN_2,
D_APC_MM_Devices[module_index].d2_permission);
}
}
}
static void dump_devapc(void)
{
int i;
INFO("[DEVAPC] dump DEVAPC registers:\n");
for (i = 0; i < 13; i++) {
INFO("[DEVAPC] (INFRA)D0_APC_%d = 0x%x, "
"(INFRA)D1_APC_%d = 0x%x, "
"(INFRA)D2_APC_%d = 0x%x\n",
i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + i * 4),
i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + 0x100 + i * 4),
i, mmio_read_32(DEVAPC_INFRA_D0_APC_0 + 0x200 + i * 4));
}
for (i = 0; i < 9; i++) {
INFO("[DEVAPC] (MM)D0_APC_%d = 0x%x, "
"(MM)D1_APC_%d = 0x%x, "
"(MM)D2_APC_%d = 0x%x\n",
i, mmio_read_32(DEVAPC_MM_D0_APC_0 + i * 4),
i, mmio_read_32(DEVAPC_MM_D0_APC_0 + 0x100 + i * 4),
i, mmio_read_32(DEVAPC_MM_D0_APC_0 + 0x200 + i * 4));
}
for (i = 0; i < 4; i++) {
INFO("[DEVAPC] MAS_DOM_%d = 0x%x\n", i,
mmio_read_32(DEVAPC_INFRA_MAS_DOM_0 + i * 4));
}
INFO("[DEVAPC] MAS_SEC_0 = 0x%x\n",
mmio_read_32(DEVAPC_INFRA_MAS_SEC_0));
INFO("[DEVAPC] (INFRA)MAS_DOMAIN_REMAP_0 = 0x%x, "
"(INFRA)MAS_DOMAIN_REMAP_1 = 0x%x\n",
mmio_read_32(DEVAPC_INFRA_DOM_RMP_0),
mmio_read_32(DEVAPC_INFRA_DOM_RMP_1));
INFO("[DEVAPC] (MM)MAS_DOMAIN_REMAP_0 = 0x%x\n",
mmio_read_32(DEVAPC_MM_DOM_RMP_0));
}
void devapc_init(void)
{
mmio_write_32(DEVAPC_INFRA_APC_CON, 0x80000001);
mmio_write_32(DEVAPC_MM_APC_CON, 0x80000001);
mmio_write_32(DEVAPC_MD_APC_CON, 0x80000001);
set_default_master_transaction();
set_default_master_domain();
set_default_slave_permission();
dump_devapc();
}
@@ -0,0 +1,499 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef DEVAPC_H
#define DEVAPC_H
#include <stdint.h>
#define DEVAPC_AO_INFRA_BASE 0x1000E000
#define DEVAPC_AO_MM_BASE 0x1001C000
#define DEVAPC_AO_MD_BASE 0x10019000
#define DEVAPC_INFRA_D0_APC_0 (DEVAPC_AO_INFRA_BASE + 0x0000)
#define DEVAPC_INFRA_MAS_DOM_0 (DEVAPC_AO_INFRA_BASE + 0x0A00)
#define DEVAPC_INFRA_MAS_SEC_0 (DEVAPC_AO_INFRA_BASE + 0x0B00)
#define DEVAPC_INFRA_DOM_RMP_0 (DEVAPC_AO_INFRA_BASE + 0x0D00)
#define DEVAPC_INFRA_DOM_RMP_1 (DEVAPC_AO_INFRA_BASE + 0x0D04)
#define DEVAPC_INFRA_APC_CON (DEVAPC_AO_INFRA_BASE + 0x0F00)
#define DEVAPC_MD_APC_CON (DEVAPC_AO_MD_BASE + 0x0F00)
#define DEVAPC_MM_D0_APC_0 (DEVAPC_AO_MM_BASE + 0x0000)
#define DEVAPC_MM_DOM_RMP_0 (DEVAPC_AO_MM_BASE + 0x0D00)
#define DEVAPC_MM_APC_CON (DEVAPC_AO_MM_BASE + 0x0F00)
#define MOD_NO_IN_1_DEVAPC 16
#define MASTER_MOD_NO_IN_1_DEVAPC 8
#define SLAVE_INFRA_MAX_INDEX 195
#define SLAVE_MM_MAX_INDEX 140
enum {
MASTER_SCP = 0,
MASTER_SPM = 10,
MASTER_SSPM = 27
};
enum MASK_DOM {
DOMAIN_0 = 0,
DOMAIN_1,
DOMAIN_2,
DOMAIN_3,
DOMAIN_4,
DOMAIN_5,
DOMAIN_6,
DOMAIN_7,
DOMAIN_8,
DOMAIN_9,
DOMAIN_10,
DOMAIN_11
};
enum TRANSACTION {
NON_SECURE_TRANSACTION = 0,
SECURE_TRANSACTION
};
enum DAPC_SLAVE_TYPE {
DAPC_INFRA_SLAVE = 0,
DAPC_MM_SLAVE
};
enum APC_ATTR {
NO_SEC = 0,
S_RW_ONLY,
S_RW_NS_R,
FORBID,
};
struct DEVICE_INFO {
uint8_t d0_permission;
uint8_t d1_permission;
uint8_t d2_permission;
};
#define PERMISSION(DEV_NAME, ATTR1, ATTR2, ATTR3) \
{(uint8_t)ATTR1, (uint8_t)ATTR2, (uint8_t)ATTR3}
static const struct DEVICE_INFO D_APC_INFRA_Devices[] = {
/* module, domain0, domain1, domain2 */
/* 0 */
PERMISSION("INFRA_AO_TOPCKGEN", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("INFRA_AO_INFRASYS_CONFIG_REGS", NO_SEC, FORBID, NO_SEC),
PERMISSION("IO_CFG", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_PERICFG", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_EFUSE_AO_DEBUG", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_GPIO", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_SLEEP_CONTROLLER", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_TOPRGU", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_APXGPT", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_RESERVE", NO_SEC, FORBID, NO_SEC),
/* 10 */
PERMISSION("INFRA_AO_SEJ", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_AP_CIRQ_EINT", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_APMIXEDSYS", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("INFRA_AO_PMIC_WRAP", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_DEVICE_APC_AO_INFRA_PERI", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_SLEEP_CONTROLLER_MD", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_KEYPAD", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_TOP_MISC", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_DVFS_CTRL_PROC", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_MBIST_AO_REG", NO_SEC, FORBID, NO_SEC),
/* 20 */
PERMISSION("INFRA_AO_CLDMA_AO_AP", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_DEVICE_MPU", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_AES_TOP_0", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_SYS_TIMER", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_MDEM_TEMP_SHARE", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_DEVICE_APC_AO_MD", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_SECURITY_AO", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_TOPCKGEN_REG", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_DEVICE_APC_AO_MM", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
/* 30 */
PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_SYS_CIRQ", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_MM_IOMMU", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_EFUSE_PDN_DEBUG", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DEVICE_APC", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DBG_TRACKER", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CCIF0_AP", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CCIF0_MD", NO_SEC, FORBID, NO_SEC),
/* 40 */
PERMISSION("INFRASYS_CCIF1_AP", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CCIF1_MD", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_MBIST", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_INFRA_PDN_REGISTER", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_TRNG", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DX_CC", NO_SEC, FORBID, NO_SEC),
PERMISSION("MD_CCIF_MD1", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CQ_DMA", NO_SEC, FORBID, NO_SEC),
PERMISSION("MD_CCIF_MD2", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_SRAMROM", NO_SEC, FORBID, NO_SEC),
/* 50 */
PERMISSION("ANA_MIPI_DSI0", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("ANA_MIPI_CSI0", NO_SEC, FORBID, NO_SEC),
PERMISSION("ANA_MIPI_CSI1", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_EMI", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CLDMA_PDN", NO_SEC, FORBID, NO_SEC),
PERMISSION("CLDMA_PDN_MD_MISC", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_MD", NO_SEC, FORBID, NO_SEC),
PERMISSION("BPI_BSI_SLV0", NO_SEC, FORBID, NO_SEC),
/* 60 */
PERMISSION("BPI_BSI_SLV1", NO_SEC, FORBID, NO_SEC),
PERMISSION("BPI_BSI_SLV2", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_EMI_MPU", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DVFS_PROC", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH0_TOP0", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH0_TOP1", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH0_TOP2", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH0_TOP3", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH0_TOP4", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH1_TOP0", NO_SEC, FORBID, NO_SEC),
/* 70 */
PERMISSION("INFRASYS_DRAMC_CH1_TOP1", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH1_TOP2", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH1_TOP3", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DRAMC_CH1_TOP4", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_GCE", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CCIF2_AP", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CCIF2_MD", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CCIF3_AP", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_CCIF3_MD", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRA_AO_PWRMCU Partition 1", S_RW_NS_R, FORBID, NO_SEC),
/* 80 */
PERMISSION("INFRA_AO_PWRMCU Partition 2", S_RW_NS_R, FORBID, NO_SEC),
PERMISSION("INFRA_AO_PWRMCU Partition 3", S_RW_NS_R, FORBID, NO_SEC),
PERMISSION("INFRA_AO_PWRMCU Partition 4", S_RW_NS_R, FORBID, NO_SEC),
PERMISSION("INFRA_AO_PWRMCU Partition 5", S_RW_NS_R, FORBID, NO_SEC),
PERMISSION("INFRA_AO_PWRMCU Partition 6", S_RW_NS_R, FORBID, NO_SEC),
PERMISSION("INFRA_AO_PWRMCU Partition 7", S_RW_NS_R, FORBID, NO_SEC),
PERMISSION("INFRA_AO_PWRMCU Partition 8", S_RW_NS_R, FORBID, NO_SEC),
PERMISSION("INFRA_AO_SCP", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("INFRA_AO_MCUCFG", NO_SEC, FORBID, NO_SEC),
PERMISSION("INFRASYS_DBUGSYS", NO_SEC, FORBID, NO_SEC),
/* 90 */
PERMISSION("PERISYS_APDMA", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_AUXADC", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_UART0", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("PERISYS_UART1", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_UART2", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C6", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_PWM", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C0", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C1", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C2", NO_SEC, FORBID, NO_SEC),
/* 100 */
PERMISSION("PERISYS_SPI0", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_PTP", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_BTIF", NO_SEC, FORBID, NO_SEC),
PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_DISP_PWM", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C3", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_SPI1", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C4", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_SPI2", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_SPI3", NO_SEC, FORBID, NO_SEC),
/* 110 */
PERMISSION("PERISYS_I2C1_IMM", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C2_IMM", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C5", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C5_IMM", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_SPI4", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_SPI5", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C7", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_I2C8", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_USB", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_USB_2_0_SUB", NO_SEC, FORBID, NO_SEC),
/* 120 */
PERMISSION("PERISYS_AUDIO", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_MSDC0", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_MSDC1", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_MSDC2", NO_SEC, FORBID, NO_SEC),
PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_UFS", NO_SEC, FORBID, NO_SEC),
PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_0", NO_SEC, FORBID, NO_SEC),
/* 130 */
PERMISSION("EAST_RESERVE_1", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_2", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_3", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_4", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_IO_CFG_RT", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_6", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_7", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_CSI0_TOP_AO", NO_SEC, FORBID, NO_SEC),
PERMISSION("RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_A", NO_SEC, FORBID, NO_SEC),
/* 140 */
PERMISSION("EAST_RESERVE_B", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_C", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_D", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_E", NO_SEC, FORBID, NO_SEC),
PERMISSION("EAST_RESERVE_F", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_0", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_1", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_IO_CFG_RM", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_IO_CFG_RB", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_EFUSE", NO_SEC, FORBID, NO_SEC),
/* 150 */
PERMISSION("SOUTH_RESERVE_5", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_6", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_7", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_8", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_9", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_A", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_B", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_C", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_D", NO_SEC, FORBID, NO_SEC),
PERMISSION("SOUTH_RESERVE_E", NO_SEC, FORBID, NO_SEC),
/* 160 */
PERMISSION("SOUTH_RESERVE_F", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_0", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_MSDC1_PAD_MACRO", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_2", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_3", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_4", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_MIPI_TX_CONFIG", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_6", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_IO_CFG_LB", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_IO_CFG_LM", NO_SEC, FORBID, NO_SEC),
/* 170 */
PERMISSION("WEST_IO_CFG_BL", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_A", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_B", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_C", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_D", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_E", NO_SEC, FORBID, NO_SEC),
PERMISSION("WEST_RESERVE_F", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_0", NO_SEC, FORBID, NO_SEC),
PERMISSION("EFUSE_TOP", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_IO_CFG_LT", NO_SEC, FORBID, NO_SEC),
/* 180 */
PERMISSION("NORTH_IO_CFG_TL", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_USB20 PHY", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_MSDC0 PAD MACRO", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_6", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_7", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_8", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_9", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_UFS_MPHY", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_B", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_C", NO_SEC, FORBID, NO_SEC),
/* 190 */
PERMISSION("NORTH_RESERVE_D", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_E", NO_SEC, FORBID, NO_SEC),
PERMISSION("NORTH_RESERVE_F", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_CONN", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_MD_VIOLATION", NO_SEC, FORBID, NO_SEC),
PERMISSION("PERISYS_RESERVE", NO_SEC, FORBID, NO_SEC)
};
static const struct DEVICE_INFO D_APC_MM_Devices[] = {
/* module, domain0, domain1, domain2 */
/* 0 */
PERMISSION("G3D_CONFIG", NO_SEC, FORBID, NO_SEC),
PERMISSION("MFG VAD", NO_SEC, FORBID, NO_SEC),
PERMISSION("SC0 VAD", NO_SEC, FORBID, NO_SEC),
PERMISSION("MFG_OTHERS", NO_SEC, FORBID, NO_SEC),
PERMISSION("MMSYS_CONFIG", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("MDP_RDMA0", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("MDP_RDMA1", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("MDP_RSZ0", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("MDP_RSZ1", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("MDP_WROT0", NO_SEC, NO_SEC, NO_SEC),
/* 10 */
PERMISSION("MDP_WDMA", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("MDP_TDSHP", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_OVL0", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_OVL0_2L", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_OVL1_2L", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_RDMA0", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_RDMA1", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_WDMA0", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_COLOR0", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_CCORR0", NO_SEC, FORBID, NO_SEC),
/* 20 */
PERMISSION("DISP_AAL0", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_GAMMA0", NO_SEC, FORBID, NO_SEC),
PERMISSION("DISP_DITHER0", NO_SEC, FORBID, NO_SEC),
PERMISSION("DSI_SPLIT", NO_SEC, FORBID, NO_SEC),
PERMISSION("DSI0", NO_SEC, FORBID, NO_SEC),
PERMISSION("DPI", NO_SEC, FORBID, NO_SEC),
PERMISSION("MM_MUTEX", NO_SEC, FORBID, NO_SEC),
PERMISSION("SMI_LARB0", NO_SEC, FORBID, NO_SEC),
PERMISSION("SMI_LARB1", NO_SEC, FORBID, NO_SEC),
PERMISSION("SMI_COMMON", NO_SEC, FORBID, NO_SEC),
/* 30 */
PERMISSION("DISP_RSZ", NO_SEC, FORBID, NO_SEC),
PERMISSION("MDP_AAL", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("MDP_CCORR", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("DBI", NO_SEC, FORBID, NO_SEC),
PERMISSION("MMSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_CONFIG", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("IMGSYS_SMI_LARB1", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_DISP_A0", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("IMGSYS_DISP_A1", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_DISP_A2", NO_SEC, FORBID, NO_SEC),
/* 40 */
PERMISSION("IMGSYS_DISP_A3", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_DISP_A4", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_DISP_A5", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_DPE", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_RSC", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_WPEA", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_FDVT", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("IMGSYS_OWE", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_WPEB", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_MFB", NO_SEC, FORBID, NO_SEC),
/* 50 */
PERMISSION("IMGSYS_SMI_LARB2", NO_SEC, FORBID, NO_SEC),
PERMISSION("IMGSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
PERMISSION("VENCSYS_GLOBAL_CON", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("VENCSYSSYS_SMI_LARB4", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("VENCSYS_VENC", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("VENCSYS_JPGENC", NO_SEC, FORBID, NO_SEC),
PERMISSION("VENCSYS_MBIST_CTRL", NO_SEC, FORBID, NO_SEC),
PERMISSION("VENCSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
PERMISSION("VDECSYS_GLOBAL_CON", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("VDECSYS_SMI_LARB1", NO_SEC, FORBID, NO_SEC),
/* 60 */
PERMISSION("VDECSYS_FULL_TOP", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("VDECSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAMSYS_TOP", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_LARB6", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("CAMSYS_LARB3", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("CAMSYS_CAM_TOP", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("CAMSYS_CAM_A", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("CAMSYS_CAM_A", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("CAMSYS_CAM_B", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("CAMSYS_CAM_B", NO_SEC, NO_SEC, NO_SEC),
/* 70 */
PERMISSION("CAMSYS_CAM_C", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("CAMSYS_CAM_C", NO_SEC, NO_SEC, NO_SEC),
PERMISSION("CAMSYS_CAM_TOP_SET", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_A_SET", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_A_SET", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_B_SET", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_B_SET", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_C_SET", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_C_SET", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_TOP_INNER", NO_SEC, FORBID, NO_SEC),
/* 80 */
PERMISSION("CAMSYS_CAM_A_INNER", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_A_INNER", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_B_INNER", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_B_INNER", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_C_INNER", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_C_INNER", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_A_EXT", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_B_EXT", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_C_EXT", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_TOP_CLR", NO_SEC, FORBID, NO_SEC),
/* 90 */
PERMISSION("CAMSYS_CAM_A_CLR", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_A_CLR", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_B_CLR", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_B_CLR", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_C_CLR", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_C_CLR", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_A_EXT", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_B_EXT", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_C_EXT", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAM_RESERVE", NO_SEC, FORBID, NO_SEC),
/* 100 */
PERMISSION("CAMSYS_SENINF_A", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_SENINF_B", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_SENINF_C", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_SENINF_D", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_SENINF_E", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_SENINF_F", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_SENINF_G", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_SENINF_H", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAMSV_A", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAMSV_B", NO_SEC, FORBID, NO_SEC),
/* 110 */
PERMISSION("CAMSYS_CAMSV_C", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CAMSV_D", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_MD32 DMEM_12", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_RESEVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CCU_CTL", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CCU_H2T_A", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CCU_T2H_A", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_RESERVE", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_CCU_DMA", NO_SEC, FORBID, NO_SEC),
/* 120 */
PERMISSION("CAMSYS_TSF", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_MD32_PMEM_24", NO_SEC, FORBID, NO_SEC),
PERMISSION("CAMSYS_OTHERS", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_CFG", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_ADL_CTRL", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREA_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREA_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREA_IMEM_256KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREA_CONTROL", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREA_DEBUG", NO_SEC, FORBID, NO_SEC),
/* 130 */
PERMISSION("VPUSYS_COREB_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREB_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREB_IMEM_256KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREB_CONTROL", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREB_DEBUG", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREC_DMEM_0_128KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREC_DMEM_128_256KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREC_IMEM_256KB", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREC_CONTROL", NO_SEC, FORBID, NO_SEC),
PERMISSION("VPUSYS_COREC_DEBUG", NO_SEC, FORBID, NO_SEC),
/* 140 */
PERMISSION("VPUSYS_OTHERS", NO_SEC, FORBID, NO_SEC)
};
void devapc_init(void);
#endif /* DEVAPC_H */
@@ -0,0 +1,147 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <lib/mmio.h>
#include <emi_mpu.h>
int is_4GB(void)
{
return 0; /* 8183 doesn't use 4GB */
}
/*
* emi_mpu_set_region_protection: protect a region.
* @start: start address of the region
* @end: end address of the region
* @region: EMI MPU region id
* @access_permission: EMI MPU access permission
* Return 0 for success, otherwise negative status code.
*/
int emi_mpu_set_region_protection(
unsigned long start, unsigned long end,
int region,
unsigned int access_permission)
{
int ret = 0;
if (end <= start) {
ERROR("[EMI][MTEE][MPU] Invalid address!.\n");
return -1;
}
if (is_4GB()) {
/* 4GB mode: emi_addr = phy_addr & 0xffff */
start = EMI_PHY_OFFSET & 0xffff;
end = EMI_PHY_OFFSET & 0xffff;
} else {
/* non-4GB mode: emi_addr = phy_addr - MEM_OFFSET */
start = start - EMI_PHY_OFFSET;
end = end - EMI_PHY_OFFSET;
}
/*Address 64KB alignment*/
start = start >> 16;
end = end >> 16;
switch (region) {
case 0:
mmio_write_32(EMI_MPU_APC0, 0);
mmio_write_32(EMI_MPU_SA0, start);
mmio_write_32(EMI_MPU_EA0, end);
mmio_write_32(EMI_MPU_APC0, access_permission);
break;
case 1:
mmio_write_32(EMI_MPU_APC1, 0);
mmio_write_32(EMI_MPU_SA1, start);
mmio_write_32(EMI_MPU_EA1, end);
mmio_write_32(EMI_MPU_APC1, access_permission);
break;
case 2:
mmio_write_32(EMI_MPU_APC2, 0);
mmio_write_32(EMI_MPU_SA2, start);
mmio_write_32(EMI_MPU_EA2, end);
mmio_write_32(EMI_MPU_APC2, access_permission);
break;
case 3:
mmio_write_32(EMI_MPU_APC3, 0);
mmio_write_32(EMI_MPU_SA3, start);
mmio_write_32(EMI_MPU_EA3, end);
mmio_write_32(EMI_MPU_APC3, access_permission);
break;
case 4:
mmio_write_32(EMI_MPU_APC4, 0);
mmio_write_32(EMI_MPU_SA4, start);
mmio_write_32(EMI_MPU_EA4, end);
mmio_write_32(EMI_MPU_APC4, access_permission);
break;
case 5:
mmio_write_32(EMI_MPU_APC5, 0);
mmio_write_32(EMI_MPU_SA5, start);
mmio_write_32(EMI_MPU_EA5, end);
mmio_write_32(EMI_MPU_APC5, access_permission);
break;
case 6:
mmio_write_32(EMI_MPU_APC6, 0);
mmio_write_32(EMI_MPU_SA6, start);
mmio_write_32(EMI_MPU_EA6, end);
mmio_write_32(EMI_MPU_APC6, access_permission);
break;
case 7:
mmio_write_32(EMI_MPU_APC7, 0);
mmio_write_32(EMI_MPU_SA7, start);
mmio_write_32(EMI_MPU_EA7, end);
mmio_write_32(EMI_MPU_APC7, access_permission);
break;
default:
ret = -1;
break;
}
return ret;
}
void dump_emi_mpu_regions(void)
{
unsigned int apc, sa, ea;
unsigned int apc_addr = EMI_MPU_APC0;
unsigned int sa_addr = EMI_MPU_SA0;
unsigned int ea_addr = EMI_MPU_EA0;
int i;
for (i = 0; i < 8; ++i) {
apc = mmio_read_32(apc_addr + i * 4);
sa = mmio_read_32(sa_addr + i * 4);
ea = mmio_read_32(ea_addr + i * 4);
WARN("region %d:\n", i);
WARN("\tapc:0x%x, sa:0x%x, ea:0x%x\n", apc, sa, ea);
}
}
void emi_mpu_init(void)
{
/* Set permission */
emi_mpu_set_region_protection(0x40000000UL, 0x4FFFFFFFUL, 0,
(FORBIDDEN << 3 | FORBIDDEN << 6));
emi_mpu_set_region_protection(0x50000000UL, 0x528FFFFFUL, 1,
(FORBIDDEN << 6));
emi_mpu_set_region_protection(0x52900000UL, 0x5FFFFFFFUL, 2,
(FORBIDDEN << 3 | FORBIDDEN << 6));
emi_mpu_set_region_protection(0x60000000UL, 0xFFFFFFFFUL, 3,
(FORBIDDEN << 3 | FORBIDDEN << 6));
emi_mpu_set_region_protection(0x100000000UL, 0x23FFFFFFFUL, 4,
(FORBIDDEN << 3 | FORBIDDEN << 6));
dump_emi_mpu_regions();
}
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __EMI_MPU_H
#define __EMI_MPU_H
#include <platform_def.h>
#define EMI_MPUP (EMI_BASE + 0x01D8)
#define EMI_MPUQ (EMI_BASE + 0x01E0)
#define EMI_MPUR (EMI_BASE + 0x01E8)
#define EMI_MPUS (EMI_BASE + 0x01F0)
#define EMI_MPUT (EMI_BASE + 0x01F8)
#define EMI_MPUY (EMI_BASE + 0x0220)
#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x0000)
#define EMI_MPUD0_ST (EMI_BASE + 0x0160)
#define EMI_MPUD1_ST (EMI_BASE + 0x0164)
#define EMI_MPUD2_ST (EMI_BASE + 0x0168)
#define EMI_MPUD3_ST (EMI_BASE + 0x016C)
#define EMI_MPUD0_ST2 (EMI_BASE + 0x0200)
#define EMI_MPUD1_ST2 (EMI_BASE + 0x0204)
#define EMI_MPUD2_ST2 (EMI_BASE + 0x0208)
#define EMI_MPUD3_ST2 (EMI_BASE + 0x020C)
#define EMI_PHY_OFFSET (0x40000000UL)
#define EIGHT_DOMAIN
#define NO_PROTECTION (0)
#define SEC_RW (1)
#define SEC_RW_NSEC_R (2)
#define SEC_RW_NSEC_W (3)
#define SEC_R_NSEC_R (4)
#define FORBIDDEN (5)
#define SEC_R_NSEC_RW (6)
#define SECURE_OS_MPU_REGION_ID (0)
#define ATF_MPU_REGION_ID (1)
#ifdef EIGHT_DOMAIN
#define SET_ACCESS_PERMISSON(d7, d6, d5, d4, d3, d2, d1, d0) \
(((d7) << 21) | ((d6) << 18) | ((d5) << 15) | ((d4) << 12) \
| ((d3) << 9) | ((d2) << 6) | ((d1) << 3) | (d0))
#else
#define SET_ACCESS_PERMISSON(d3, d2, d1, d0) \
(((d3) << 9) | ((d2) << 6) | ((d1) << 3) | (d0))
#endif
//#define EMI_MPU_BASE (0x1020E000U)
#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
#define EMI_MPU_SA1 (EMI_MPU_BASE + 0x104)
#define EMI_MPU_SA2 (EMI_MPU_BASE + 0x108)
#define EMI_MPU_SA3 (EMI_MPU_BASE + 0x10C)
#define EMI_MPU_SA4 (EMI_MPU_BASE + 0x110)
#define EMI_MPU_SA5 (EMI_MPU_BASE + 0x114)
#define EMI_MPU_SA6 (EMI_MPU_BASE + 0x118)
#define EMI_MPU_SA7 (EMI_MPU_BASE + 0x11C)
#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
#define EMI_MPU_EA1 (EMI_MPU_BASE + 0x204)
#define EMI_MPU_EA2 (EMI_MPU_BASE + 0x208)
#define EMI_MPU_EA3 (EMI_MPU_BASE + 0x20C)
#define EMI_MPU_EA4 (EMI_MPU_BASE + 0x210)
#define EMI_MPU_EA5 (EMI_MPU_BASE + 0x214)
#define EMI_MPU_EA6 (EMI_MPU_BASE + 0x218)
#define EMI_MPU_EA7 (EMI_MPU_BASE + 0x21C)
#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
#define EMI_MPU_APC1 (EMI_MPU_BASE + 0x304)
#define EMI_MPU_APC2 (EMI_MPU_BASE + 0x308)
#define EMI_MPU_APC3 (EMI_MPU_BASE + 0x30C)
#define EMI_MPU_APC4 (EMI_MPU_BASE + 0x310)
#define EMI_MPU_APC5 (EMI_MPU_BASE + 0x314)
#define EMI_MPU_APC6 (EMI_MPU_BASE + 0x318)
#define EMI_MPU_APC7 (EMI_MPU_BASE + 0x31C)
#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
#define EMI_MPU_CTRL_D1 (EMI_MPU_BASE + 0x804)
#define EMI_MPU_CTRL_D2 (EMI_MPU_BASE + 0x808)
#define EMI_MPU_CTRL_D3 (EMI_MPU_BASE + 0x80C)
#define EMI_MPU_CTRL_D4 (EMI_MPU_BASE + 0x810)
#define EMI_MPU_CTRL_D5 (EMI_MPU_BASE + 0x814)
#define EMI_MPU_CTRL_D6 (EMI_MPU_BASE + 0x818)
#define EMI_MPU_CTRL_D7 (EMI_MPU_BASE + 0x81C)
#define EMI_MPU_MASK_D0 (EMI_MPU_BASE + 0x900)
#define EMI_MPU_MASK_D1 (EMI_MPU_BASE + 0x904)
#define EMI_MPU_MASK_D2 (EMI_MPU_BASE + 0x908)
#define EMI_MPU_MASK_D3 (EMI_MPU_BASE + 0x90C)
#define EMI_MPU_MASK_D4 (EMI_MPU_BASE + 0x910)
#define EMI_MPU_MASK_D5 (EMI_MPU_BASE + 0x914)
#define EMI_MPU_MASK_D6 (EMI_MPU_BASE + 0x918)
#define EMI_MPU_MASK_D7 (EMI_MPU_BASE + 0x91C)
int emi_mpu_set_region_protection(
unsigned long start, unsigned long end,
int region,
unsigned int access_permission);
void dump_emi_mpu_regions(void);
void emi_mpu_init(void);
#endif /* __EMI_MPU_H */
@@ -0,0 +1,439 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <gpio/mtgpio.h>
#include <gpio/mtgpio_cfg.h>
#include <drivers/gpio.h>
#include <mcucfg.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include <spm.h>
#include <stdbool.h>
/******************************************************************************
*Macro Definition
******************************************************************************/
#define GPIO_MODE_BITS 4
#define MAX_GPIO_MODE_PER_REG 8
#define MAX_GPIO_REG_BITS 32
#define DIR_BASE (GPIO_BASE + 0x000)
#define DOUT_BASE (GPIO_BASE + 0x100)
#define DIN_BASE (GPIO_BASE + 0x200)
#define MODE_BASE (GPIO_BASE + 0x300)
#define SET 0x4
#define CLR 0x8
#define PULLEN_ADDR_OFFSET 0x060
#define PULLSEL_ADDR_OFFSET 0x080
void mt_set_gpio_dir_chip(uint32_t pin, int dir)
{
uint32_t pos, bit;
assert(pin < MAX_GPIO_PIN);
assert(dir < GPIO_DIR_MAX);
pos = pin / MAX_GPIO_REG_BITS;
bit = pin % MAX_GPIO_REG_BITS;
if (dir == GPIO_DIR_IN)
mmio_write_32(DIR_BASE + 0x10 * pos + CLR, 1U << bit);
else
mmio_write_32(DIR_BASE + 0x10 * pos + SET, 1U << bit);
}
int mt_get_gpio_dir_chip(uint32_t pin)
{
uint32_t pos, bit;
uint32_t reg;
assert(pin < MAX_GPIO_PIN);
pos = pin / MAX_GPIO_REG_BITS;
bit = pin % MAX_GPIO_REG_BITS;
reg = mmio_read_32(DIR_BASE + 0x10 * pos);
return (((reg & (1U << bit)) != 0) ? GPIO_DIR_OUT : GPIO_DIR_IN);
}
void mt_set_gpio_out_chip(uint32_t pin, int output)
{
uint32_t pos, bit;
assert(pin < MAX_GPIO_PIN);
assert(output < GPIO_OUT_MAX);
pos = pin / MAX_GPIO_REG_BITS;
bit = pin % MAX_GPIO_REG_BITS;
if (output == GPIO_OUT_ZERO)
mmio_write_32(DOUT_BASE + 0x10 * pos + CLR, 1U << bit);
else
mmio_write_32(DOUT_BASE + 0x10 * pos + SET, 1U << bit);
}
int mt_get_gpio_out_chip(uint32_t pin)
{
uint32_t pos, bit;
uint32_t reg;
assert(pin < MAX_GPIO_PIN);
pos = pin / MAX_GPIO_REG_BITS;
bit = pin % MAX_GPIO_REG_BITS;
reg = mmio_read_32(DOUT_BASE + 0x10 * pos);
return (((reg & (1U << bit)) != 0) ? 1 : 0);
}
int mt_get_gpio_in_chip(uint32_t pin)
{
uint32_t pos, bit;
uint32_t reg;
assert(pin < MAX_GPIO_PIN);
pos = pin / MAX_GPIO_REG_BITS;
bit = pin % MAX_GPIO_REG_BITS;
reg = mmio_read_32(DIN_BASE + 0x10 * pos);
return (((reg & (1U << bit)) != 0) ? 1 : 0);
}
void mt_set_gpio_mode_chip(uint32_t pin, int mode)
{
uint32_t pos, bit;
uint32_t data;
uint32_t mask;
assert(pin < MAX_GPIO_PIN);
assert(mode < GPIO_MODE_MAX);
mask = (1U << GPIO_MODE_BITS) - 1;
mode = mode & mask;
pos = pin / MAX_GPIO_MODE_PER_REG;
bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
data = mmio_read_32(MODE_BASE + 0x10 * pos);
data &= (~(mask << bit));
data |= (mode << bit);
mmio_write_32(MODE_BASE + 0x10 * pos, data);
}
int mt_get_gpio_mode_chip(uint32_t pin)
{
uint32_t pos, bit;
uint32_t data;
uint32_t mask;
assert(pin < MAX_GPIO_PIN);
mask = (1U << GPIO_MODE_BITS) - 1;
pos = pin / MAX_GPIO_MODE_PER_REG;
bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
data = mmio_read_32(MODE_BASE + 0x10 * pos);
return (data >> bit) & mask;
}
int32_t gpio_get_pull_iocfg(uint32_t pin)
{
switch (pin) {
case 0 ... 10:
return IOCFG_5_BASE;
case 11 ... 12:
return IOCFG_0_BASE;
case 13 ... 28:
return IOCFG_1_BASE;
case 43 ... 49:
return IOCFG_2_BASE;
case 50 ... 60:
return IOCFG_3_BASE;
case 61 ... 88:
return IOCFG_4_BASE;
case 89 ... 90:
return IOCFG_5_BASE;
case 95 ... 106:
return IOCFG_5_BASE;
case 107 ... 121:
return IOCFG_6_BASE;
case 134 ... 160:
return IOCFG_0_BASE;
case 161 ... 166:
return IOCFG_1_BASE;
case 167 ... 176:
return IOCFG_3_BASE;
case 177 ... 179:
return IOCFG_5_BASE;
default:
return -1;
}
}
int32_t gpio_get_pupd_iocfg(uint32_t pin)
{
const int32_t offset = 0x0c0;
switch (pin) {
case 29 ... 34:
return IOCFG_1_BASE + offset;
case 35 ... 42:
return IOCFG_2_BASE + offset;
case 91 ... 94:
return IOCFG_5_BASE + offset;
case 122 ... 133:
return IOCFG_7_BASE + offset;
default:
return -1;
}
}
int gpio_get_pupd_offset(uint32_t pin)
{
switch (pin) {
case 29 ... 34:
return (pin - 29) * 4 % 32;
case 35 ... 42:
return (pin - 35) * 4 % 32;
case 91 ... 94:
return (pin - 91) * 4 % 32;
case 122 ... 129:
return (pin - 122) * 4 % 32;
case 130 ... 133:
return (pin - 130) * 4 % 32;
default:
return -1;
}
}
void mt_set_gpio_pull_enable_chip(uint32_t pin, int en)
{
int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
int pupd_addr = gpio_get_pupd_iocfg(pin);
int pupd_offset = gpio_get_pupd_offset(pin);
assert(pin < MAX_GPIO_PIN);
assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
(pupd_offset == (int8_t)-1)));
if (en == GPIO_PULL_DISABLE) {
if (PULL_offset[pin].offset == (int8_t)-1)
mmio_clrbits_32(pupd_addr, 3U << pupd_offset);
else
mmio_clrbits_32(pullen_addr,
1U << PULL_offset[pin].offset);
} else if (en == GPIO_PULL_ENABLE) {
if (PULL_offset[pin].offset == (int8_t)-1) {
/* For PUPD+R0+R1 Type, mt_set_gpio_pull_enable
* does not know
* which one between PU and PD shall be enabled.
* Use R0 to guarantee at one resistor is set when lk
* apply default setting
*/
mmio_setbits_32(pupd_addr, 1U << pupd_offset);
mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
} else {
/* For PULLEN + PULLSEL Type */
mmio_setbits_32(pullen_addr,
1U << PULL_offset[pin].offset);
}
} else if (en == GPIO_PULL_ENABLE_R0) {
assert(!(pupd_offset == (int8_t)-1));
mmio_setbits_32(pupd_addr, 1U << pupd_offset);
mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
} else if (en == GPIO_PULL_ENABLE_R1) {
assert(!(pupd_offset == (int8_t)-1));
mmio_clrbits_32(pupd_addr, 1U << pupd_offset);
mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 1));
} else if (en == GPIO_PULL_ENABLE_R0R1) {
assert(!(pupd_offset == (int8_t)-1));
mmio_setbits_32(pupd_addr, 3U << pupd_offset);
}
}
int mt_get_gpio_pull_enable_chip(uint32_t pin)
{
uint32_t reg;
int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
int pupd_addr = gpio_get_pupd_iocfg(pin);
int pupd_offset = gpio_get_pupd_offset(pin);
assert(pin < MAX_GPIO_PIN);
assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
(pupd_offset == (int8_t)-1)));
if (PULL_offset[pin].offset == (int8_t)-1) {
reg = mmio_read_32(pupd_addr);
return ((reg & (3U << pupd_offset)) ? 1 : 0);
} else if (pupd_offset == (int8_t)-1) {
reg = mmio_read_32(pullen_addr);
return ((reg & (1U << PULL_offset[pin].offset)) ? 1 : 0);
}
return -ERINVAL;
}
void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
{
int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
int pupd_addr = gpio_get_pupd_iocfg(pin);
int pupd_offset = gpio_get_pupd_offset(pin);
assert(pin < MAX_GPIO_PIN);
assert(!((PULL_offset[pin].offset == (int8_t) -1) &&
(pupd_offset == (int8_t)-1)));
if (sel == GPIO_PULL_NONE) {
/* Regard No PULL as PULL disable + pull down */
mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_DISABLE);
if (PULL_offset[pin].offset == (int8_t)-1)
mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
else
mmio_clrbits_32(pullsel_addr,
1U << PULL_offset[pin].offset);
} else if (sel == GPIO_PULL_UP) {
mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
if (PULL_offset[pin].offset == (int8_t)-1)
mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 2));
else
mmio_setbits_32(pullsel_addr,
1U << PULL_offset[pin].offset);
} else if (sel == GPIO_PULL_DOWN) {
mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
if (PULL_offset[pin].offset == -1)
mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
else
mmio_clrbits_32(pullsel_addr,
1U << PULL_offset[pin].offset);
}
}
/* get pull-up or pull-down, regardless of resistor value */
int mt_get_gpio_pull_select_chip(uint32_t pin)
{
uint32_t reg;
int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
int pupd_addr = gpio_get_pupd_iocfg(pin);
int pupd_offset = gpio_get_pupd_offset(pin);
assert(pin < MAX_GPIO_PIN);
assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
(pupd_offset == (int8_t)-1)));
if (PULL_offset[pin].offset == (int8_t)-1) {
reg = mmio_read_32(pupd_addr);
if (reg & (3U << pupd_offset)) {
reg = mmio_read_32(pupd_addr);
/* Reg value: 0 for PU, 1 for PD -->
* reverse return value */
return ((reg & (1U << (pupd_offset + 2))) ?
GPIO_PULL_DOWN : GPIO_PULL_UP);
} else {
return GPIO_PULL_NONE;
}
} else if (pupd_offset == (int8_t)-1) {
reg = mmio_read_32(pullen_addr);
if ((reg & (1U << PULL_offset[pin].offset))) {
reg = mmio_read_32(pullsel_addr);
return ((reg & (1U << PULL_offset[pin].offset)) ?
GPIO_PULL_UP : GPIO_PULL_DOWN);
} else {
return GPIO_PULL_NONE;
}
}
return -ERINVAL;
}
void mt_set_gpio_dir(int gpio, int direction)
{
mt_set_gpio_dir_chip((uint32_t)gpio, direction);
}
int mt_get_gpio_dir(int gpio)
{
uint32_t pin;
pin = (uint32_t)gpio;
return mt_get_gpio_dir_chip(pin);
}
void mt_set_gpio_pull(int gpio, int pull)
{
uint32_t pin;
pin = (uint32_t)gpio;
mt_set_gpio_pull_select_chip(pin, pull);
}
int mt_get_gpio_pull(int gpio)
{
uint32_t pin;
pin = (uint32_t)gpio;
return mt_get_gpio_pull_select_chip(pin);
}
void mt_set_gpio_out(int gpio, int value)
{
uint32_t pin;
pin = (uint32_t)gpio;
mt_set_gpio_out_chip(pin, value);
}
int mt_get_gpio_out(int gpio)
{
uint32_t pin;
pin = (uint32_t)gpio;
return mt_get_gpio_out_chip(pin);
}
int mt_get_gpio_in(int gpio)
{
uint32_t pin;
pin = (uint32_t)gpio;
return mt_get_gpio_in_chip(pin);
}
void mt_set_gpio_mode(int gpio, int mode)
{
uint32_t pin;
pin = (uint32_t)gpio;
mt_set_gpio_mode_chip(pin, mode);
}
int mt_get_gpio_mode(int gpio)
{
uint32_t pin;
pin = (uint32_t)gpio;
return mt_get_gpio_mode_chip(pin);
}
const gpio_ops_t mtgpio_ops = {
.get_direction = mt_get_gpio_dir,
.set_direction = mt_set_gpio_dir,
.get_value = mt_get_gpio_in,
.set_value = mt_set_gpio_out,
.set_pull = mt_set_gpio_pull,
.get_pull = mt_get_gpio_pull,
};
@@ -0,0 +1,154 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_GPIO_H
#define MT_GPIO_H
#include <stdint.h>
#include <plat/common/common_def.h>
/* Error Code No. */
#define RSUCCESS 0
#define ERACCESS 1
#define ERINVAL 2
#define ERWRAPPER 3
#define MAX_GPIO_PIN MT_GPIO_BASE_MAX
/* Enumeration for GPIO pin */
typedef enum GPIO_PIN {
GPIO_UNSUPPORTED = -1,
GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7,
GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15,
GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23,
GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31,
GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39,
GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47,
GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55,
GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63,
GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71,
GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79,
GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87,
GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95,
GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103,
GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111,
GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119,
GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127,
GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135,
GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143,
GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151,
GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159,
GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167,
GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175,
GPIO176, GPIO177, GPIO178, GPIO179,
MT_GPIO_BASE_MAX
} GPIO_PIN;
/* GPIO MODE CONTROL VALUE*/
typedef enum {
GPIO_MODE_UNSUPPORTED = -1,
GPIO_MODE_GPIO = 0,
GPIO_MODE_00 = 0,
GPIO_MODE_01,
GPIO_MODE_02,
GPIO_MODE_03,
GPIO_MODE_04,
GPIO_MODE_05,
GPIO_MODE_06,
GPIO_MODE_07,
GPIO_MODE_MAX,
GPIO_MODE_DEFAULT = GPIO_MODE_00,
} GPIO_MODE;
/* GPIO DIRECTION */
typedef enum {
GPIO_DIR_UNSUPPORTED = -1,
GPIO_DIR_OUT = 0,
GPIO_DIR_IN = 1,
GPIO_DIR_MAX,
GPIO_DIR_DEFAULT = GPIO_DIR_IN,
} GPIO_DIR;
/* GPIO PULL ENABLE*/
typedef enum {
GPIO_PULL_EN_UNSUPPORTED = -1,
GPIO_PULL_DISABLE = 0,
GPIO_PULL_ENABLE = 1,
GPIO_PULL_ENABLE_R0 = 2,
GPIO_PULL_ENABLE_R1 = 3,
GPIO_PULL_ENABLE_R0R1 = 4,
GPIO_PULL_EN_MAX,
GPIO_PULL_EN_DEFAULT = GPIO_PULL_ENABLE,
} GPIO_PULL_EN;
/* GPIO PULL-UP/PULL-DOWN*/
typedef enum {
GPIO_PULL_UNSUPPORTED = -1,
GPIO_PULL_NONE = 0,
GPIO_PULL_UP = 1,
GPIO_PULL_DOWN = 2,
GPIO_PULL_MAX,
GPIO_PULL_DEFAULT = GPIO_PULL_DOWN
} GPIO_PULL;
/* GPIO OUTPUT */
typedef enum {
GPIO_OUT_UNSUPPORTED = -1,
GPIO_OUT_ZERO = 0,
GPIO_OUT_ONE = 1,
GPIO_OUT_MAX,
GPIO_OUT_DEFAULT = GPIO_OUT_ZERO,
GPIO_DATA_OUT_DEFAULT = GPIO_OUT_ZERO, /*compatible with DCT*/
} GPIO_OUT;
/* GPIO INPUT */
typedef enum {
GPIO_IN_UNSUPPORTED = -1,
GPIO_IN_ZERO = 0,
GPIO_IN_ONE = 1,
GPIO_IN_MAX,
} GPIO_IN;
typedef struct {
uint32_t val;
uint32_t set;
uint32_t rst;
uint32_t _align1;
} VAL_REGS;
typedef struct {
VAL_REGS dir[6]; /*0x0000 ~ 0x005F: 96 bytes */
uint8_t rsv00[160]; /*0x0060 ~ 0x00FF: 160 bytes */
VAL_REGS dout[6]; /*0x0100 ~ 0x015F: 96 bytes */
uint8_t rsv01[160]; /*0x0160 ~ 0x01FF: 160 bytes */
VAL_REGS din[6]; /*0x0200 ~ 0x025F: 96 bytes */
uint8_t rsv02[160]; /*0x0260 ~ 0x02FF: 160 bytes */
VAL_REGS mode[23]; /*0x0300 ~ 0x046F: 368 bytes */
} GPIO_REGS;
/* GPIO Driver interface */
/*direction*/
void mt_set_gpio_dir(int gpio, int direction);
int mt_get_gpio_dir(int gpio);
/*pull select*/
void mt_set_gpio_pull(int gpio, int pull);
int mt_get_gpio_pull(int gpio);
/*input/output*/
void mt_set_gpio_out(int gpio, int value);
int mt_get_gpio_out(int gpio);
int mt_get_gpio_in(int gpio);
/*mode control*/
void mt_set_gpio_mode(int gpio, int mode);
int mt_get_gpio_mode(int gpio);
#endif /* MT_GPIO_H */
@@ -0,0 +1,208 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_GPIO_CFG_H
#define MT_GPIO_CFG_H
#include <stdint.h>
#include <plat/common/common_def.h>
#define IOCFG_0_BASE 0x11F20000
#define IOCFG_1_BASE 0x11E80000
#define IOCFG_2_BASE 0x11E70000
#define IOCFG_3_BASE 0x11E90000
#define IOCFG_4_BASE 0x11D30000
#define IOCFG_5_BASE 0x11D20000
#define IOCFG_6_BASE 0x11C50000
#define IOCFG_7_BASE 0x11F30000
typedef struct {
int8_t offset;
} PIN_offset;
PIN_offset PULL_offset[] = {
/* 0 */ {6},
/* 1 */ {7},
/* 2 */ {8},
/* 3 */ {9},
/* 4 */ {11},
/* 5 */ {12},
/* 6 */ {13},
/* 7 */ {14},
/* 8 */ {0},
/* 9 */ {26},
/* 10 */ {27},
/* 11 */ {10},
/* 12 */ {17},
/* 13 */ {6},
/* 14 */ {7},
/* 15 */ {8},
/* 16 */ {9},
/* 17 */ {10},
/* 18 */ {11},
/* 19 */ {12},
/* 20 */ {13},
/* 21 */ {14},
/* 22 */ {15},
/* 23 */ {16},
/* 24 */ {17},
/* 25 */ {18},
/* 26 */ {19},
/* 27 */ {20},
/* 28 */ {21},
/* 29 */ {-1},
/* 30 */ {-1},
/* 31 */ {-1},
/* 32 */ {-1},
/* 33 */ {-1},
/* 34 */ {-1},
/* 35 */ {-1},
/* 36 */ {-1},
/* 37 */ {-1},
/* 38 */ {-1},
/* 39 */ {-1},
/* 40 */ {-1},
/* 41 */ {-1},
/* 42 */ {-1},
/* 43 */ {8},
/* 44 */ {9},
/* 45 */ {10},
/* 46 */ {11},
/* 47 */ {12},
/* 48 */ {13},
/* 49 */ {14},
/* 50 */ {0},
/* 51 */ {1},
/* 52 */ {2},
/* 53 */ {3},
/* 54 */ {4},
/* 55 */ {5},
/* 56 */ {6},
/* 57 */ {7},
/* 58 */ {8},
/* 59 */ {9},
/* 60 */ {10},
/* 61 */ {0},
/* 62 */ {1},
/* 63 */ {2},
/* 64 */ {3},
/* 65 */ {4},
/* 66 */ {5},
/* 67 */ {6},
/* 68 */ {7},
/* 69 */ {8},
/* 70 */ {9},
/* 71 */ {10},
/* 72 */ {11},
/* 73 */ {12},
/* 74 */ {13},
/* 75 */ {14},
/* 76 */ {15},
/* 77 */ {16},
/* 78 */ {17},
/* 79 */ {18},
/* 80 */ {19},
/* 81 */ {20},
/* 82 */ {21},
/* 83 */ {22},
/* 84 */ {23},
/* 85 */ {24},
/* 86 */ {25},
/* 87 */ {26},
/* 88 */ {27},
/* 89 */ {24},
/* 90 */ {1},
/* 91 */ {-1},
/* 92 */ {-1},
/* 93 */ {-1},
/* 94 */ {-1},
/* 95 */ {15},
/* 96 */ {17},
/* 97 */ {18},
/* 98 */ {19},
/* 99 */ {20},
/* 100 */ {21},
/* 101 */ {22},
/* 102 */ {23},
/* 103 */ {28},
/* 104 */ {29},
/* 105 */ {30},
/* 106 */ {31},
/* 107 */ {0},
/* 108 */ {1},
/* 109 */ {2},
/* 110 */ {3},
/* 111 */ {4},
/* 112 */ {5},
/* 113 */ {6},
/* 114 */ {7},
/* 115 */ {8},
/* 116 */ {9},
/* 117 */ {10},
/* 118 */ {11},
/* 119 */ {12},
/* 120 */ {13},
/* 121 */ {14},
/* 122 */ {-1},
/* 123 */ {-1},
/* 124 */ {-1},
/* 125 */ {-1},
/* 126 */ {-1},
/* 127 */ {-1},
/* 128 */ {-1},
/* 129 */ {-1},
/* 130 */ {-1},
/* 131 */ {-1},
/* 132 */ {-1},
/* 133 */ {-1},
/* 134 */ {0},
/* 135 */ {1},
/* 136 */ {2},
/* 137 */ {3},
/* 138 */ {4},
/* 139 */ {5},
/* 140 */ {6},
/* 141 */ {7},
/* 142 */ {8},
/* 143 */ {9},
/* 144 */ {11},
/* 145 */ {12},
/* 146 */ {13},
/* 147 */ {14},
/* 148 */ {15},
/* 149 */ {16},
/* 150 */ {18},
/* 151 */ {19},
/* 152 */ {20},
/* 153 */ {21},
/* 154 */ {22},
/* 155 */ {23},
/* 156 */ {24},
/* 157 */ {25},
/* 158 */ {26},
/* 159 */ {27},
/* 160 */ {28},
/* 161 */ {0},
/* 162 */ {1},
/* 163 */ {2},
/* 164 */ {3},
/* 165 */ {4},
/* 166 */ {5},
/* 167 */ {11},
/* 168 */ {12},
/* 169 */ {13},
/* 170 */ {14},
/* 171 */ {15},
/* 172 */ {16},
/* 173 */ {17},
/* 174 */ {18},
/* 175 */ {19},
/* 176 */ {20},
/* 177 */ {10},
/* 178 */ {16},
/* 179 */ {25}
};
#endif /* MT_GPIO_CFG_H */
@@ -0,0 +1,259 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <sspm_reg.h>
#include <mtk_mcdi.h>
static inline uint32_t mcdi_mbox_read(uint32_t id)
{
return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2));
}
static inline void mcdi_mbox_write(uint32_t id, uint32_t val)
{
mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val);
}
void sspm_set_bootaddr(uint32_t bootaddr)
{
mcdi_mbox_write(MCDI_MBOX_BOOTADDR, bootaddr);
}
void sspm_cluster_pwr_off_notify(uint32_t cluster)
{
mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 1);
}
void sspm_cluster_pwr_on_notify(uint32_t cluster)
{
mcdi_mbox_write(MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE + cluster, 0);
}
void sspm_standbywfi_irq_enable(uint32_t cpu_idx)
{
mmio_write_32(SSPM_CFGREG_ACAO_INT_SET, STANDBYWFI_EN(cpu_idx));
}
uint32_t mcdi_avail_cpu_mask_read(void)
{
return mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
}
uint32_t mcdi_avail_cpu_mask_write(uint32_t mask)
{
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, mask);
return mask;
}
uint32_t mcdi_avail_cpu_mask_set(uint32_t mask)
{
uint32_t m;
m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
m |= mask;
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m);
return m;
}
uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask)
{
uint32_t m;
m = mcdi_mbox_read(MCDI_MBOX_AVAIL_CPU_MASK);
m &= ~mask;
mcdi_mbox_write(MCDI_MBOX_AVAIL_CPU_MASK, m);
return m;
}
uint32_t mcdi_cpu_cluster_pwr_stat_read(void)
{
return mcdi_mbox_read(MCDI_MBOX_CPU_CLUSTER_PWR_STAT);
}
#define PAUSE_BIT 1
#define CLUSTER_OFF_OFS 20
#define CPU_OFF_OFS 24
#define CLUSTER_ON_OFS 4
#define CPU_ON_OFS 8
static uint32_t target_mask(int cluster, int cpu_idx, bool on)
{
uint32_t t = 0;
if (on) {
if (cluster >= 0)
t |= BIT(cluster + CLUSTER_ON_OFS);
if (cpu_idx >= 0)
t |= BIT(cpu_idx + CPU_ON_OFS);
} else {
if (cluster >= 0)
t |= BIT(cluster + CLUSTER_OFF_OFS);
if (cpu_idx >= 0)
t |= BIT(cpu_idx + CPU_OFF_OFS);
}
return t;
}
void mcdi_pause_clr(int cluster, int cpu_idx, bool on)
{
uint32_t tgt = target_mask(cluster, cpu_idx, on);
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION);
m &= ~tgt;
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
}
void mcdi_pause_set(int cluster, int cpu_idx, bool on)
{
uint32_t tgt = target_mask(cluster, cpu_idx, on);
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION);
uint32_t tgtn = target_mask(-1, cpu_idx, !on);
/* request on and off at the same time to ensure it can be paused */
m |= tgt | tgtn;
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
/* wait pause_ack */
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK))
;
/* clear non-requested operation */
m &= ~tgtn;
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
}
void mcdi_pause(void)
{
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT);
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
/* wait pause_ack */
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK))
;
}
void mcdi_unpause(void)
{
uint32_t m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT);
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
}
void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on)
{
uint32_t tgt = target_mask(cluster, cpu_idx, on);
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
/* wait until ack */
while (!(ack & tgt))
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
}
void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on)
{
uint32_t tgt = target_mask(cluster, cpu_idx, on);
uint32_t tgt_cpu = target_mask(-1, cpu_idx, on);
uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD);
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
if (!(cmd & tgt))
return;
/* wait until ack */
while (!(ack & tgt_cpu))
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
cmd &= ~tgt;
mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd);
}
void mcdi_hotplug_set(int cluster, int cpu_idx, bool on)
{
uint32_t tgt = target_mask(cluster, cpu_idx, on);
uint32_t tgt_cpu = target_mask(-1, cpu_idx, on);
uint32_t cmd = mcdi_mbox_read(MCDI_MBOX_HP_CMD);
uint32_t ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
if ((cmd & tgt) == tgt)
return;
/* wait until ack clear */
while (ack & tgt_cpu)
ack = mcdi_mbox_read(MCDI_MBOX_HP_ACK);
cmd |= tgt;
mcdi_mbox_write(MCDI_MBOX_HP_CMD, cmd);
}
bool check_mcdi_ctl_stat(void)
{
uint32_t clk_regs[] = {0x100010ac, 0x100010c8};
uint32_t clk_mask[] = {0x00028000, 0x00000018};
uint32_t tgt = target_mask(0, 0, true);
uint32_t m;
int i;
/* check clk status */
for (i = 0; i < ARRAY_SIZE(clk_regs); i++) {
if (mmio_read_32(clk_regs[i]) & clk_mask[i]) {
WARN("mcdi: clk check fail.\n");
return false;
}
}
/* check mcdi cmd handling */
m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) | BIT(PAUSE_BIT);
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
i = 500;
while (!mcdi_mbox_read(MCDI_MBOX_PAUSE_ACK) && --i > 0)
udelay(10);
m = mcdi_mbox_read(MCDI_MBOX_PAUSE_ACTION) & ~BIT(PAUSE_BIT);
mcdi_mbox_write(MCDI_MBOX_PAUSE_ACTION, m);
if (i == 0) {
WARN("mcdi: pause_action fail.\n");
return false;
}
/* check mcdi cmd handling */
if (mcdi_mbox_read(MCDI_MBOX_HP_CMD) ||
mcdi_mbox_read(MCDI_MBOX_HP_ACK)) {
WARN("mcdi: hp_cmd fail.\n");
return false;
}
mcdi_mbox_write(MCDI_MBOX_HP_CMD, tgt);
i = 500;
while ((mcdi_mbox_read(MCDI_MBOX_HP_ACK) & tgt) != tgt && --i > 0)
udelay(10);
mcdi_mbox_write(MCDI_MBOX_HP_CMD, 0);
if (i == 0) {
WARN("mcdi: hp_ack fail.\n");
return false;
}
return true;
}
void mcdi_init(void)
{
mcdi_avail_cpu_mask_write(0x01); /* cpu0 default on */
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __MTK_MCDI_H__
#define __MTK_MCDI_H__
#include <stdbool.h>
void sspm_set_bootaddr(uint32_t bootaddr);
void sspm_standbywfi_irq_enable(uint32_t cpu_idx);
void sspm_cluster_pwr_off_notify(uint32_t cluster);
void sspm_cluster_pwr_on_notify(uint32_t cluster);
uint32_t mcdi_avail_cpu_mask_read(void);
uint32_t mcdi_avail_cpu_mask_write(uint32_t mask);
uint32_t mcdi_avail_cpu_mask_set(uint32_t mask);
uint32_t mcdi_avail_cpu_mask_clr(uint32_t mask);
uint32_t mcdi_cpu_cluster_pwr_stat_read(void);
void mcdi_pause(void);
void mcdi_unpause(void);
void mcdi_pause_set(int cluster, int cpu_idx, bool on);
void mcdi_pause_clr(int cluster, int cpu_idx, bool on);
void mcdi_hotplug_set(int cluster, int cpu_idx, bool on);
void mcdi_hotplug_clr(int cluster, int cpu_idx, bool on);
void mcdi_hotplug_wait_ack(int cluster, int cpu_idx, bool on);
bool check_mcdi_ctl_stat(void);
void mcdi_init(void);
#endif /* __MTK_MCDI_H__ */
@@ -0,0 +1,211 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <scu.h>
#include <mcucfg.h>
#include <drivers/delay_timer.h>
#include <mcsi/mcsi.h>
#define MAX_CLUSTERS 5
static unsigned long cci_base_addr;
static unsigned int cci_cluster_ix_to_iface[MAX_CLUSTERS];
void mcsi_init(unsigned long cci_base,
unsigned int num_cci_masters)
{
int i;
assert(cci_base);
assert(num_cci_masters < MAX_CLUSTERS);
cci_base_addr = cci_base;
for (i = 0; i < num_cci_masters; i++)
cci_cluster_ix_to_iface[i] = SLAVE_IFACE_OFFSET(i);
}
void mcsi_cache_flush(void)
{
/* timeout is 10ms */
int timeout = 10000;
/* to make flush by SF safe, need to disable BIU DCM */
mmio_clrbits_32(CCI_CLK_CTRL, 1 << 8);
mmio_write_32(cci_base_addr + FLUSH_SF, 0x1);
for (; timeout; timeout--, udelay(1)) {
if ((mmio_read_32(cci_base_addr + FLUSH_SF) & 0x1) == 0x0)
break;
}
if (!timeout) {
INFO("SF lush timeout\n");
return;
}
/* enable BIU DCM as it was */
mmio_setbits_32(CCI_CLK_CTRL, 1 << 8);
}
static inline unsigned long get_slave_iface_base(unsigned long mpidr)
{
/*
* We assume the TF topology code allocates affinity instances
* consecutively from zero.
* It is a programming error if this is called without initializing
* the slave interface to use for this cluster.
*/
unsigned int cluster_id =
(mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK;
assert(cluster_id < MAX_CLUSTERS);
assert(cci_cluster_ix_to_iface[cluster_id] != 0);
return cci_base_addr + cci_cluster_ix_to_iface[cluster_id];
}
void cci_enable_cluster_coherency(unsigned long mpidr)
{
unsigned long slave_base;
unsigned int support_ability;
unsigned int config = 0;
unsigned int pending = 0;
assert(cci_base_addr);
slave_base = get_slave_iface_base(mpidr);
support_ability = mmio_read_32(slave_base);
pending = (mmio_read_32(
cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING;
while (pending) {
pending = (mmio_read_32(
cci_base_addr + SNP_PENDING_REG)) >> SNP_PENDING;
}
if (support_ability & SNP_SUPPORT)
config |= SNOOP_EN_BIT;
if (support_ability & DVM_SUPPORT)
config |= DVM_EN_BIT;
mmio_write_32(slave_base, support_ability | config);
/* Wait for the dust to settle down */
while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
;
}
#if ERRATA_MCSIB_SW
#pragma weak mcsib_sw_workaround_main
#endif
void cci_disable_cluster_coherency(unsigned long mpidr)
{
unsigned long slave_base;
unsigned int config = 0;
assert(cci_base_addr);
slave_base = get_slave_iface_base(mpidr);
while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
;
config = mmio_read_32(slave_base);
config &= ~(DVM_EN_BIT | SNOOP_EN_BIT);
/* Disable Snoops and DVM messages */
mmio_write_32(slave_base, config);
#if ERRATA_MCSIB_SW
mcsib_sw_workaround_main();
#endif
/* Wait for the dust to settle down */
while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
;
}
void cci_secure_switch(unsigned int status)
{
unsigned int config;
config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG);
if (status == NS_ACC)
config |= SECURE_ACC_EN;
else
config &= ~SECURE_ACC_EN;
mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config);
}
void cci_pmu_secure_switch(unsigned int status)
{
unsigned int config;
config = mmio_read_32(cci_base_addr + CENTRAL_CTRL_REG);
if (status == NS_ACC)
config |= PMU_SECURE_ACC_EN;
else
config &= ~PMU_SECURE_ACC_EN;
mmio_write_32(cci_base_addr + CENTRAL_CTRL_REG, config);
}
void cci_init_sf(void)
{
while (mmio_read_32(cci_base_addr + SNP_PENDING_REG) >> SNP_PENDING)
;
/* init sf1 */
mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF1_INIT);
while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF1_INIT)
;
while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF1_INIT_DONE))
;
/* init sf2 */
mmio_write_32(cci_base_addr + SF_INIT_REG, TRIG_SF2_INIT);
while (mmio_read_32(cci_base_addr + SF_INIT_REG) & TRIG_SF2_INIT)
;
while (!(mmio_read_32(cci_base_addr + SF_INIT_REG) & SF2_INIT_DONE))
;
}
void cci_interrupt_en(void)
{
mmio_setbits_32(cci_base_addr + CENTRAL_CTRL_REG, INT_EN);
}
unsigned long cci_reg_access(unsigned int op, unsigned long offset,
unsigned long val)
{
unsigned long ret = 0;
if ((cci_base_addr == 0) || (offset > MSCI_MEMORY_SZ))
panic();
switch (op) {
case MCSI_REG_ACCESS_READ:
ret = mmio_read_32(cci_base_addr + offset);
break;
case MCSI_REG_ACCESS_WRITE:
mmio_write_32(cci_base_addr + offset, val);
dsb();
break;
case MCSI_REG_ACCESS_SET_BITMASK:
mmio_setbits_32(cci_base_addr + offset, val);
dsb();
break;
case MCSI_REG_ACCESS_CLEAR_BITMASK:
mmio_clrbits_32(cci_base_addr + offset, val);
dsb();
break;
default:
break;
}
return ret;
}
@@ -0,0 +1,116 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MCSI_H
#define MCSI_H
#define SLAVE_IFACE7_OFFSET 0x1700
#define SLAVE_IFACE6_OFFSET 0x1600
#define SLAVE_IFACE5_OFFSET 0x1500
#define SLAVE_IFACE4_OFFSET 0x1400
#define SLAVE_IFACE3_OFFSET 0x1300
#define SLAVE_IFACE2_OFFSET 0x1200
#define SLAVE_IFACE1_OFFSET 0x1100
#define SLAVE_IFACE0_OFFSET 0x1000
#define SLAVE_IFACE_OFFSET(index) (SLAVE_IFACE0_OFFSET + \
(0x100 * (index)))
/* Control and ID register offsets */
#define CENTRAL_CTRL_REG 0x0
#define ERR_FLAG_REG 0x4
#define SF_INIT_REG 0x10
#define SF_CTRL_REG 0x14
#define DCM_CTRL_REG 0x18
#define ERR_FLAG2_REG 0x20
#define SNP_PENDING_REG 0x28
#define ACP_PENDING_REG 0x2c
#define FLUSH_SF 0x500
#define SYS_CCE_CTRL 0x2000
#define MST1_CTRL 0x2100
#define MTS2_CTRL 0x2200
#define XBAR_ARAW_ARB 0x3000
#define XBAR_R_ARB 0x3004
/* Slave interface register offsets */
#define SNOOP_CTRL_REG 0x0
#define QOS_CTRL_REG 0x4
#define QOS_OVERRIDE_REG 0x8
#define QOS_TARGET_REG 0xc
#define BD_CTRL_REG 0x40
/* Snoop Control register bit definitions */
#define DVM_SUPPORT (1U << 31)
#define SNP_SUPPORT (1 << 30)
#define SHAREABLE_OVWRT (1 << 2)
#define DVM_EN_BIT (1 << 1)
#define SNOOP_EN_BIT (1 << 0)
#define SF2_INIT_DONE (1 << 17)
#define SF1_INIT_DONE (1 << 16)
#define TRIG_SF2_INIT (1 << 1)
#define TRIG_SF1_INIT (1 << 0)
/* Status register bit definitions */
#define SNP_PENDING 31
/* Status bit */
#define NS_ACC 1
#define S_ACC 0
/* Central control register bit definitions */
#define PMU_SECURE_ACC_EN (1 << 4)
#define INT_EN (1 << 3)
#define SECURE_ACC_EN (1 << 2)
#define DVM_DIS (1 << 1)
#define SNOOP_DIS (1 << 0)
#define MSCI_MEMORY_SZ (0x10000)
#define MCSI_REG_ACCESS_READ (0x0)
#define MCSI_REG_ACCESS_WRITE (0x1)
#define MCSI_REG_ACCESS_SET_BITMASK (0x2)
#define MCSI_REG_ACCESS_CLEAR_BITMASK (0x3)
#define NR_MAX_SLV (7)
/* ICCS */
#define CACHE_INSTR_EN (1 << 2)
#define IDLE_CACHE (1 << 3)
#define USE_SHARED_CACHE (1 << 4)
#define CACHE_SHARED_PRE_EN (1 << 5)
#define CACHE_SHARED_POST_EN (1 << 6)
#define ACP_PENDING_MASK (0x1007f)
#define CCI_CLK_CTRL (MCUCFG_BASE + 0x660)
#ifndef __ASSEMBLER__
#include <plat/common/common_def.h>
#include <stdint.h>
/* Function declarations */
/*
* The MCSI driver must be initialized with the base address of the
* MCSI device in the platform memory map, and the cluster indices for
* the MCSI slave interfaces 3 and 4 respectively. These are the fully
* coherent ACE slave interfaces of MCSI.
* The cluster indices must either be 0 or 1, corresponding to the level 1
* affinity instance of the mpidr representing the cluster. A negative cluster
* index indicates that no cluster is present on that slave interface.
*/
void mcsi_init(unsigned long cci_base,
unsigned int num_cci_masters);
void mcsi_cache_flush(void);
void cci_enable_cluster_coherency(unsigned long mpidr);
void cci_disable_cluster_coherency(unsigned long mpidr);
void cci_secure_switch(unsigned int ns);
void cci_init_sf(void);
unsigned long cci_reg_access(unsigned int op, unsigned long offset, unsigned long val);
#endif /* __ASSEMBLER__ */
#endif /* MCSI_H */
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <pmic_wrap_init.h>
#include <pmic.h>
void bcpu_enable(uint32_t en)
{
pwrap_write(PMIC_VPROC11_OP_EN, 0x1);
if (en)
pwrap_write(PMIC_VPROC11_CON0, 1);
else
pwrap_write(PMIC_VPROC11_CON0, 0);
}
void bcpu_sram_enable(uint32_t en)
{
pwrap_write(PMIC_VSRAM_PROC11_OP_EN, 0x1);
if (en)
pwrap_write(PMIC_VSRAM_PROC11_CON0, 1);
else
pwrap_write(PMIC_VSRAM_PROC11_CON0, 0);
}
void wk_pmic_enable_sdn_delay(void)
{
uint32_t con;
pwrap_write(PMIC_TMA_KEY, 0x9CA7);
pwrap_read(PMIC_PSEQ_ELR11, &con);
con &= ~PMIC_RG_SDN_DLY_ENB;
pwrap_write(PMIC_PSEQ_ELR11, con);
pwrap_write(PMIC_TMA_KEY, 0);
}
void pmic_power_off(void)
{
pwrap_write(PMIC_PWRHOLD, 0x0);
}
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PMIC_H
#define PMIC_H
enum {
PMIC_TMA_KEY = 0x03a8,
PMIC_PWRHOLD = 0x0a08,
PMIC_PSEQ_ELR11 = 0x0a62,
PMIC_VPROC11_CON0 = 0x1388,
PMIC_VPROC11_OP_EN = 0x1390,
PMIC_VSRAM_PROC11_CON0 = 0x1b46,
PMIC_VSRAM_PROC11_OP_EN = 0x1b4e
};
enum {
PMIC_RG_SDN_DLY_ENB = 1U << 10
};
/* external API */
void bcpu_enable(uint32_t en);
void bcpu_sram_enable(uint32_t en);
void wk_pmic_enable_sdn_delay(void);
void pmic_power_off(void);
#endif /* PMIC_H */
@@ -0,0 +1,94 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PMIC_WRAP_INIT_H
#define PMIC_WRAP_INIT_H
#include <platform_def.h>
#include <stdint.h>
/* external API */
int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
int32_t pwrap_write(uint32_t adr, uint32_t wdata);
static struct mt8183_pmic_wrap_regs *const mtk_pwrap =
(void *)PMIC_WRAP_BASE;
/* timeout setting */
enum {
TIMEOUT_READ = 255, /* us */
TIMEOUT_WAIT_IDLE = 255 /* us */
};
/* PMIC_WRAP registers */
struct mt8183_pmic_wrap_regs {
uint32_t reserved[776];
uint32_t wacs2_cmd;
uint32_t wacs2_rdata;
uint32_t wacs2_vldclr;
uint32_t reserved1[4];
};
enum {
RDATA_WACS_RDATA_SHIFT = 0,
RDATA_WACS_FSM_SHIFT = 16,
RDATA_WACS_REQ_SHIFT = 19,
RDATA_SYNC_IDLE_SHIFT,
RDATA_INIT_DONE_SHIFT,
RDATA_SYS_IDLE_SHIFT,
};
enum {
RDATA_WACS_RDATA_MASK = 0xffff,
RDATA_WACS_FSM_MASK = 0x7,
RDATA_WACS_REQ_MASK = 0x1,
RDATA_SYNC_IDLE_MASK = 0x1,
RDATA_INIT_DONE_MASK = 0x1,
RDATA_SYS_IDLE_MASK = 0x1,
};
/* WACS_FSM */
enum {
WACS_FSM_IDLE = 0x00,
WACS_FSM_REQ = 0x02,
WACS_FSM_WFDLE = 0x04,
WACS_FSM_WFVLDCLR = 0x06,
WACS_INIT_DONE = 0x01,
WACS_SYNC_IDLE = 0x01,
WACS_SYNC_BUSY = 0x00
};
/* error information flag */
enum {
E_PWR_INVALID_ARG = 1,
E_PWR_INVALID_RW = 2,
E_PWR_INVALID_ADDR = 3,
E_PWR_INVALID_WDAT = 4,
E_PWR_INVALID_OP_MANUAL = 5,
E_PWR_NOT_IDLE_STATE = 6,
E_PWR_NOT_INIT_DONE = 7,
E_PWR_NOT_INIT_DONE_READ = 8,
E_PWR_WAIT_IDLE_TIMEOUT = 9,
E_PWR_WAIT_IDLE_TIMEOUT_READ = 10,
E_PWR_INIT_SIDLY_FAIL = 11,
E_PWR_RESET_TIMEOUT = 12,
E_PWR_TIMEOUT = 13,
E_PWR_INIT_RESET_SPI = 20,
E_PWR_INIT_SIDLY = 21,
E_PWR_INIT_REG_CLOCK = 22,
E_PWR_INIT_ENABLE_PMIC = 23,
E_PWR_INIT_DIO = 24,
E_PWR_INIT_CIPHER = 25,
E_PWR_INIT_WRITE_TEST = 26,
E_PWR_INIT_ENABLE_CRC = 27,
E_PWR_INIT_ENABLE_DEWRAP = 28,
E_PWR_INIT_ENABLE_EVENT = 29,
E_PWR_READ_TEST_FAIL = 30,
E_PWR_WRITE_TEST_FAIL = 31,
E_PWR_SWITCH_DIO = 32
};
#endif /* PMIC_WRAP_INIT_H */
@@ -0,0 +1,133 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <rtc.h>
static void RTC_Config_Interface(uint32_t addr, uint16_t data,
uint16_t MASK, uint16_t SHIFT)
{
uint16_t pmic_reg = 0;
pmic_reg = RTC_Read(addr);
pmic_reg &= ~(MASK << SHIFT);
pmic_reg |= (data << SHIFT);
RTC_Write(addr, pmic_reg);
}
static void rtc_disable_2sec_reboot(void)
{
uint16_t reboot;
reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
~RTC_BBPU_AUTO_PDN_SEL;
RTC_Write(RTC_AL_SEC, reboot);
RTC_Write_Trigger();
}
static void rtc_xosc_write(uint16_t val, bool reload)
{
uint16_t bbpu;
RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1);
rtc_busy_wait();
RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2);
rtc_busy_wait();
RTC_Write(RTC_OSC32CON, val);
rtc_busy_wait();
if (reload) {
bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
RTC_Write(RTC_BBPU, bbpu);
RTC_Write_Trigger();
}
}
static void rtc_enable_k_eosc(void)
{
uint16_t osc32;
uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */
/* Truning on eosc cali mode clock */
RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK,
PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT);
RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK,
PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT);
RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0,
PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
switch (rtc_eosc_cali_td) {
case 1:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
case 2:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
case 4:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
case 16:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
default:
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6,
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
break;
}
/* Switch the DCXO from 32k-less mode to RTC mode,
* otherwise, EOSC cali will fail
*/
/* RTC mode will have only OFF mode and FPM */
RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK,
PMIC_RG_XO_EN32K_MAN_SHIFT);
RTC_Write(RTC_BBPU,
RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
RTC_Write_Trigger();
/* Enable K EOSC mode for normal power off and then plug out battery */
RTC_Write(RTC_AL_YEA, ((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
& (~RTC_K_EOSC_RSV_1)) | RTC_K_EOSC_RSV_2);
RTC_Write_Trigger();
osc32 = RTC_Read(RTC_OSC32CON);
rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true);
INFO("[RTC] RTC_enable_k_eosc\n");
}
void rtc_power_off_sequence(void)
{
uint16_t bbpu;
rtc_disable_2sec_reboot();
rtc_enable_k_eosc();
/* clear alarm */
bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN;
if (Writeif_unlock()) {
RTC_Write(RTC_BBPU, bbpu);
RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
RTC_Write_Trigger();
mdelay(1);
bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
RTC_Write(RTC_BBPU, bbpu);
RTC_Write_Trigger();
INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n",
RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN),
RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC));
}
}
@@ -0,0 +1,147 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef RTC_H
#define RTC_H
/* RTC registers */
enum {
RTC_BBPU = 0x0588,
RTC_IRQ_STA = 0x058A,
RTC_IRQ_EN = 0x058C,
RTC_CII_EN = 0x058E
};
enum {
RTC_AL_SEC = 0x05A0,
RTC_AL_MIN = 0x05A2,
RTC_AL_HOU = 0x05A4,
RTC_AL_DOM = 0x05A6,
RTC_AL_DOW = 0x05A8,
RTC_AL_MTH = 0x05AA,
RTC_AL_YEA = 0x05AC,
RTC_AL_MASK = 0x0590
};
enum {
RTC_OSC32CON = 0x05AE,
RTC_CON = 0x05C4,
RTC_WRTGR = 0x05C2
};
enum {
RTC_PDN1 = 0x05B4,
RTC_PDN2 = 0x05B6,
RTC_SPAR0 = 0x05B8,
RTC_SPAR1 = 0x05BA,
RTC_PROT = 0x05BC,
RTC_DIFF = 0x05BE,
RTC_CALI = 0x05C0
};
enum {
RTC_OSC32CON_UNLOCK1 = 0x1A57,
RTC_OSC32CON_UNLOCK2 = 0x2B68
};
enum {
RTC_PROT_UNLOCK1 = 0x586A,
RTC_PROT_UNLOCK2 = 0x9136
};
enum {
RTC_BBPU_PWREN = 1U << 0,
RTC_BBPU_CLR = 1U << 1,
RTC_BBPU_INIT = 1U << 2,
RTC_BBPU_AUTO = 1U << 3,
RTC_BBPU_CLRPKY = 1U << 4,
RTC_BBPU_RELOAD = 1U << 5,
RTC_BBPU_CBUSY = 1U << 6
};
enum {
RTC_AL_MASK_SEC = 1U << 0,
RTC_AL_MASK_MIN = 1U << 1,
RTC_AL_MASK_HOU = 1U << 2,
RTC_AL_MASK_DOM = 1U << 3,
RTC_AL_MASK_DOW = 1U << 4,
RTC_AL_MASK_MTH = 1U << 5,
RTC_AL_MASK_YEA = 1U << 6
};
enum {
RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
RTC_BBPU_2SEC_CK_SEL = 1U << 7,
RTC_BBPU_2SEC_EN = 1U << 8,
RTC_BBPU_2SEC_MODE = 0x3 << 9,
RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
RTC_BBPU_2SEC_STAT_STA = 1U << 12
};
enum {
RTC_BBPU_KEY = 0x43 << 8
};
enum {
RTC_EMBCK_SRC_SEL = 1 << 8,
RTC_EMBCK_SEL_MODE = 3 << 6,
RTC_XOSC32_ENB = 1 << 5,
RTC_REG_XOSC32_ENB = 1 << 15
};
enum {
RTC_K_EOSC_RSV_0 = 1 << 8,
RTC_K_EOSC_RSV_1 = 1 << 9,
RTC_K_EOSC_RSV_2 = 1 << 10
};
/* PMIC TOP Register Definition */
enum {
PMIC_RG_TOP_CON = 0x001E,
PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
};
/* PMIC SCK Register Definition */
enum {
PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x051A,
PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x051C,
PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x051E,
PMIC_RG_EOSC_CALI_CON0 = 0x540
};
/* PMIC DCXO Register Definition */
enum {
PMIC_RG_DCXO_CW00 = 0x0788,
PMIC_RG_DCXO_CW02 = 0x0790
};
enum {
PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1,
PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1,
PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1,
PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3,
PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1,
PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2,
PMIC_RG_EOSC_CALI_TD_MASK = 0x7,
PMIC_RG_EOSC_CALI_TD_SHIFT = 5,
PMIC_RG_XO_EN32K_MAN_MASK = 0x1,
PMIC_RG_XO_EN32K_MAN_SHIFT = 0
};
/* external API */
uint16_t RTC_Read(uint32_t addr);
void RTC_Write(uint32_t addr, uint16_t data);
int32_t rtc_busy_wait(void);
int32_t RTC_Write_Trigger(void);
int32_t Writeif_unlock(void);
void rtc_power_off_sequence(void);
#endif /* RTC_H */
@@ -0,0 +1,363 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <lib/bakery_lock.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <spm.h>
#include <spm_pmic_wrap.h>
DEFINE_BAKERY_LOCK(spm_lock);
/* SPM_DVS_LEVEL */
#define SPM_VMODEM_LEVEL_MASK (0xff << 16)
#define SPM_VMODEM_LEVEL (1U << 18)
#define SPM_VCORE_LEVEL_MASK (0xff)
#define SPM_VCORE_LEVEL (1U << 1)
/* CLK_SCP_CFG_0 */
#define SPM_CK_OFF_CONTROL (0x3FF)
/* CLK_SCP_CFG_1 */
#define SPM_AXI_26M_SEL (0x1)
/* AP_PLL_CON3 */
#define SPM_PLL_CONTROL (0x7FAAAAF)
/* AP_PLL_CON4 */
#define SPM_PLL_OUT_OFF_CONTROL (0xFA0A)
/* AP_PLL_CON6 */
#define PLL_DLY (0x20000)
const char *wakeup_src_str[32] = {
[0] = "R12_PCM_TIMER",
[1] = "R12_SSPM_WDT_EVENT_B",
[2] = "R12_KP_IRQ_B",
[3] = "R12_APWDT_EVENT_B",
[4] = "R12_APXGPT1_EVENT_B",
[5] = "R12_CONN2AP_SPM_WAKEUP_B",
[6] = "R12_EINT_EVENT_B",
[7] = "R12_CONN_WDT_IRQ_B",
[8] = "R12_CCIF0_EVENT_B",
[9] = "R12_LOWBATTERY_IRQ_B",
[10] = "R12_SSPM_SPM_IRQ_B",
[11] = "R12_SCP_SPM_IRQ_B",
[12] = "R12_SCP_WDT_EVENT_B",
[13] = "R12_PCM_WDT_WAKEUP_B",
[14] = "R12_USB_CDSC_B ",
[15] = "R12_USB_POWERDWN_B",
[16] = "R12_SYS_TIMER_EVENT_B",
[17] = "R12_EINT_EVENT_SECURE_B",
[18] = "R12_CCIF1_EVENT_B",
[19] = "R12_UART0_IRQ_B",
[20] = "R12_AFE_IRQ_MCU_B",
[21] = "R12_THERM_CTRL_EVENT_B",
[22] = "R12_SYS_CIRQ_IRQ_B",
[23] = "R12_MD2AP_PEER_EVENT_B",
[24] = "R12_CSYSPWREQ_B",
[25] = "R12_MD1_WDT_B ",
[26] = "R12_CLDMA_EVENT_B",
[27] = "R12_SEJ_WDT_GPT_B",
[28] = "R12_ALL_SSPM_WAKEUP_B",
[29] = "R12_CPU_IRQ_B",
[30] = "R12_CPU_WFI_AND_B"
};
const char *spm_get_firmware_version(void)
{
return "DYNAMIC_SPM_FW_VERSION";
}
void spm_lock_init(void)
{
bakery_lock_init(&spm_lock);
}
void spm_lock_get(void)
{
bakery_lock_get(&spm_lock);
}
void spm_lock_release(void)
{
bakery_lock_release(&spm_lock);
}
void spm_set_bootaddr(unsigned long bootaddr)
{
/* initialize core4~7 boot entry address */
mmio_write_32(SW2SPM_MAILBOX_3, bootaddr);
}
void spm_set_cpu_status(int cpu)
{
if (cpu >= 0 && cpu < 4) {
mmio_write_32(ROOT_CPUTOP_ADDR, 0x10006204);
mmio_write_32(ROOT_CORE_ADDR, 0x10006208 + (cpu * 0x4));
} else if (cpu >= 4 && cpu < 8) {
mmio_write_32(ROOT_CPUTOP_ADDR, 0x10006218);
mmio_write_32(ROOT_CORE_ADDR, 0x1000621c + ((cpu - 4) * 0x4));
} else {
ERROR("%s: error cpu number %d\n", __func__, cpu);
}
}
void spm_set_power_control(const struct pwr_ctrl *pwrctrl)
{
mmio_write_32(SPM_AP_STANDBY_CON,
((pwrctrl->wfi_op & 0x1) << 0) |
((pwrctrl->mp0_cputop_idle_mask & 0x1) << 1) |
((pwrctrl->mp1_cputop_idle_mask & 0x1) << 2) |
((pwrctrl->mcusys_idle_mask & 0x1) << 4) |
((pwrctrl->mm_mask_b & 0x3) << 16) |
((pwrctrl->md_ddr_en_0_dbc_en & 0x1) << 18) |
((pwrctrl->md_ddr_en_1_dbc_en & 0x1) << 19) |
((pwrctrl->md_mask_b & 0x3) << 20) |
((pwrctrl->sspm_mask_b & 0x1) << 22) |
((pwrctrl->scp_mask_b & 0x1) << 23) |
((pwrctrl->srcclkeni_mask_b & 0x1) << 24) |
((pwrctrl->md_apsrc_1_sel & 0x1) << 25) |
((pwrctrl->md_apsrc_0_sel & 0x1) << 26) |
((pwrctrl->conn_ddr_en_dbc_en & 0x1) << 27) |
((pwrctrl->conn_mask_b & 0x1) << 28) |
((pwrctrl->conn_apsrc_sel & 0x1) << 29));
mmio_write_32(SPM_SRC_REQ,
((pwrctrl->spm_apsrc_req & 0x1) << 0) |
((pwrctrl->spm_f26m_req & 0x1) << 1) |
((pwrctrl->spm_infra_req & 0x1) << 3) |
((pwrctrl->spm_vrf18_req & 0x1) << 4) |
((pwrctrl->spm_ddren_req & 0x1) << 7) |
((pwrctrl->spm_rsv_src_req & 0x7) << 8) |
((pwrctrl->spm_ddren_2_req & 0x1) << 11) |
((pwrctrl->cpu_md_dvfs_sop_force_on & 0x1) << 16));
mmio_write_32(SPM_SRC_MASK,
((pwrctrl->csyspwreq_mask & 0x1) << 0) |
((pwrctrl->ccif0_md_event_mask_b & 0x1) << 1) |
((pwrctrl->ccif0_ap_event_mask_b & 0x1) << 2) |
((pwrctrl->ccif1_md_event_mask_b & 0x1) << 3) |
((pwrctrl->ccif1_ap_event_mask_b & 0x1) << 4) |
((pwrctrl->ccif2_md_event_mask_b & 0x1) << 5) |
((pwrctrl->ccif2_ap_event_mask_b & 0x1) << 6) |
((pwrctrl->ccif3_md_event_mask_b & 0x1) << 7) |
((pwrctrl->ccif3_ap_event_mask_b & 0x1) << 8) |
((pwrctrl->md_srcclkena_0_infra_mask_b & 0x1) << 9) |
((pwrctrl->md_srcclkena_1_infra_mask_b & 0x1) << 10) |
((pwrctrl->conn_srcclkena_infra_mask_b & 0x1) << 11) |
((pwrctrl->ufs_infra_req_mask_b & 0x1) << 12) |
((pwrctrl->srcclkeni_infra_mask_b & 0x1) << 13) |
((pwrctrl->md_apsrc_req_0_infra_mask_b & 0x1) << 14) |
((pwrctrl->md_apsrc_req_1_infra_mask_b & 0x1) << 15) |
((pwrctrl->conn_apsrcreq_infra_mask_b & 0x1) << 16) |
((pwrctrl->ufs_srcclkena_mask_b & 0x1) << 17) |
((pwrctrl->md_vrf18_req_0_mask_b & 0x1) << 18) |
((pwrctrl->md_vrf18_req_1_mask_b & 0x1) << 19) |
((pwrctrl->ufs_vrf18_req_mask_b & 0x1) << 20) |
((pwrctrl->gce_vrf18_req_mask_b & 0x1) << 21) |
((pwrctrl->conn_infra_req_mask_b & 0x1) << 22) |
((pwrctrl->gce_apsrc_req_mask_b & 0x1) << 23) |
((pwrctrl->disp0_apsrc_req_mask_b & 0x1) << 24) |
((pwrctrl->disp1_apsrc_req_mask_b & 0x1) << 25) |
((pwrctrl->mfg_req_mask_b & 0x1) << 26) |
((pwrctrl->vdec_req_mask_b & 0x1) << 27));
mmio_write_32(SPM_SRC2_MASK,
((pwrctrl->md_ddr_en_0_mask_b & 0x1) << 0) |
((pwrctrl->md_ddr_en_1_mask_b & 0x1) << 1) |
((pwrctrl->conn_ddr_en_mask_b & 0x1) << 2) |
((pwrctrl->ddren_sspm_apsrc_req_mask_b & 0x1) << 3) |
((pwrctrl->ddren_scp_apsrc_req_mask_b & 0x1) << 4) |
((pwrctrl->disp0_ddren_mask_b & 0x1) << 5) |
((pwrctrl->disp1_ddren_mask_b & 0x1) << 6) |
((pwrctrl->gce_ddren_mask_b & 0x1) << 7) |
((pwrctrl->ddren_emi_self_refresh_ch0_mask_b & 0x1)
<< 8) |
((pwrctrl->ddren_emi_self_refresh_ch1_mask_b & 0x1)
<< 9));
mmio_write_32(SPM_WAKEUP_EVENT_MASK,
((pwrctrl->spm_wakeup_event_mask & 0xffffffff) << 0));
mmio_write_32(SPM_WAKEUP_EVENT_EXT_MASK,
((pwrctrl->spm_wakeup_event_ext_mask & 0xffffffff)
<< 0));
mmio_write_32(SPM_SRC3_MASK,
((pwrctrl->md_ddr_en_2_0_mask_b & 0x1) << 0) |
((pwrctrl->md_ddr_en_2_1_mask_b & 0x1) << 1) |
((pwrctrl->conn_ddr_en_2_mask_b & 0x1) << 2) |
((pwrctrl->ddren2_sspm_apsrc_req_mask_b & 0x1) << 3) |
((pwrctrl->ddren2_scp_apsrc_req_mask_b & 0x1) << 4) |
((pwrctrl->disp0_ddren2_mask_b & 0x1) << 5) |
((pwrctrl->disp1_ddren2_mask_b & 0x1) << 6) |
((pwrctrl->gce_ddren2_mask_b & 0x1) << 7) |
((pwrctrl->ddren2_emi_self_refresh_ch0_mask_b & 0x1)
<< 8) |
((pwrctrl->ddren2_emi_self_refresh_ch1_mask_b & 0x1)
<< 9));
mmio_write_32(MP0_CPU0_WFI_EN,
((pwrctrl->mp0_cpu0_wfi_en & 0x1) << 0));
mmio_write_32(MP0_CPU1_WFI_EN,
((pwrctrl->mp0_cpu1_wfi_en & 0x1) << 0));
mmio_write_32(MP0_CPU2_WFI_EN,
((pwrctrl->mp0_cpu2_wfi_en & 0x1) << 0));
mmio_write_32(MP0_CPU3_WFI_EN,
((pwrctrl->mp0_cpu3_wfi_en & 0x1) << 0));
mmio_write_32(MP1_CPU0_WFI_EN,
((pwrctrl->mp1_cpu0_wfi_en & 0x1) << 0));
mmio_write_32(MP1_CPU1_WFI_EN,
((pwrctrl->mp1_cpu1_wfi_en & 0x1) << 0));
mmio_write_32(MP1_CPU2_WFI_EN,
((pwrctrl->mp1_cpu2_wfi_en & 0x1) << 0));
mmio_write_32(MP1_CPU3_WFI_EN,
((pwrctrl->mp1_cpu3_wfi_en & 0x1) << 0));
}
void spm_disable_pcm_timer(void)
{
mmio_clrsetbits_32(PCM_CON1, PCM_TIMER_EN_LSB, SPM_REGWR_CFG_KEY);
}
void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
{
uint32_t val, mask, isr;
val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX;
mmio_write_32(PCM_TIMER_VAL, val);
mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | PCM_TIMER_EN_LSB);
mask = pwrctrl->wake_src;
if (pwrctrl->csyspwreq_mask)
mask &= ~WAKE_SRC_R12_CSYSPWREQ_B;
mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~mask);
isr = mmio_read_32(SPM_IRQ_MASK) & SPM_TWAM_IRQ_MASK_LSB;
mmio_write_32(SPM_IRQ_MASK, isr | ISRM_RET_IRQ_AUX);
}
void spm_set_pcm_flags(const struct pwr_ctrl *pwrctrl)
{
mmio_write_32(SPM_SW_FLAG, pwrctrl->pcm_flags);
mmio_write_32(SPM_SW_RSV_2, pwrctrl->pcm_flags1);
}
void spm_set_pcm_wdt(int en)
{
if (en) {
mmio_clrsetbits_32(PCM_CON1, PCM_WDT_WAKE_MODE_LSB,
SPM_REGWR_CFG_KEY);
if (mmio_read_32(PCM_TIMER_VAL) > PCM_TIMER_MAX)
mmio_write_32(PCM_TIMER_VAL, PCM_TIMER_MAX);
mmio_write_32(PCM_WDT_VAL,
mmio_read_32(PCM_TIMER_VAL) + PCM_WDT_TIMEOUT);
mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | PCM_WDT_EN_LSB);
} else {
mmio_clrsetbits_32(PCM_CON1, PCM_WDT_EN_LSB,
SPM_REGWR_CFG_KEY);
}
}
void spm_send_cpu_wakeup_event(void)
{
mmio_write_32(PCM_REG_DATA_INI, 0);
mmio_write_32(SPM_CPU_WAKEUP_EVENT, 1);
}
void spm_get_wakeup_status(struct wake_status *wakesta)
{
wakesta->assert_pc = mmio_read_32(PCM_REG_DATA_INI);
wakesta->r12 = mmio_read_32(SPM_SW_RSV_0);
wakesta->r12_ext = mmio_read_32(PCM_REG12_EXT_DATA);
wakesta->raw_sta = mmio_read_32(SPM_WAKEUP_STA);
wakesta->raw_ext_sta = mmio_read_32(SPM_WAKEUP_EXT_STA);
wakesta->wake_misc = mmio_read_32(SPM_BSI_D0_SR);
wakesta->timer_out = mmio_read_32(SPM_BSI_D1_SR);
wakesta->r13 = mmio_read_32(PCM_REG13_DATA);
wakesta->idle_sta = mmio_read_32(SUBSYS_IDLE_STA);
wakesta->req_sta = mmio_read_32(SRC_REQ_STA);
wakesta->sw_flag = mmio_read_32(SPM_SW_FLAG);
wakesta->sw_flag1 = mmio_read_32(SPM_SW_RSV_2);
wakesta->r15 = mmio_read_32(PCM_REG15_DATA);
wakesta->debug_flag = mmio_read_32(SPM_SW_DEBUG);
wakesta->debug_flag1 = mmio_read_32(WDT_LATCH_SPARE0_FIX);
wakesta->event_reg = mmio_read_32(SPM_BSI_D2_SR);
wakesta->isr = mmio_read_32(SPM_IRQ_STA);
}
void spm_clean_after_wakeup(void)
{
mmio_write_32(SPM_SW_RSV_0,
mmio_read_32(SPM_WAKEUP_STA) |
mmio_read_32(SPM_SW_RSV_0));
mmio_write_32(SPM_CPU_WAKEUP_EVENT, 0);
mmio_write_32(SPM_WAKEUP_EVENT_MASK, ~0);
mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM);
mmio_write_32(SPM_IRQ_STA, ISRC_ALL_EXC_TWAM);
mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT_ALL);
}
void spm_output_wake_reason(struct wake_status *wakesta, const char *scenario)
{
uint32_t i;
if (wakesta->assert_pc != 0) {
INFO("%s: PCM ASSERT AT %u, ULPOSC_CON = 0x%x\n",
scenario, wakesta->assert_pc, mmio_read_32(ULPOSC_CON));
goto spm_debug_flags;
}
for (i = 0; i <= 31; i++) {
if (wakesta->r12 & (1U << i)) {
INFO("%s: wake up by %s, timer_out = %u\n",
scenario, wakeup_src_str[i], wakesta->timer_out);
break;
}
}
spm_debug_flags:
INFO("r15 = 0x%x, r13 = 0x%x, debug_flag = 0x%x 0x%x\n",
wakesta->r15, wakesta->r13, wakesta->debug_flag,
wakesta->debug_flag1);
INFO("sw_flag = 0x%x 0x%x, r12 = 0x%x, r12_ext = 0x%x\n",
wakesta->sw_flag, wakesta->sw_flag1, wakesta->r12,
wakesta->r12_ext);
INFO("idle_sta = 0x%x, req_sta = 0x%x, event_reg = 0x%x\n",
wakesta->idle_sta, wakesta->req_sta, wakesta->event_reg);
INFO("isr = 0x%x, raw_sta = 0x%x, raw_ext_sta = 0x%x\n",
wakesta->isr, wakesta->raw_sta, wakesta->raw_ext_sta);
INFO("wake_misc = 0x%x\n", wakesta->wake_misc);
}
void spm_boot_init(void)
{
NOTICE("%s() start\n", __func__);
spm_lock_init();
mt_spm_pmic_wrap_set_phase(PMIC_WRAP_PHASE_ALLINONE);
/* Set Vmodem / Vcore DVS init level */
mmio_clrsetbits_32(SPM_DVS_LEVEL,
SPM_VMODEM_LEVEL_MASK | SPM_VCORE_LEVEL_MASK,
SPM_VMODEM_LEVEL | SPM_VCORE_LEVEL);
/* switch ck_off/axi_26m control to SPM */
mmio_setbits_32(CLK_SCP_CFG_0, SPM_CK_OFF_CONTROL);
mmio_setbits_32(CLK_SCP_CFG_1, SPM_AXI_26M_SEL);
/* switch PLL/CLKSQ control to SPM */
mmio_clrbits_32(AP_PLL_CON3, SPM_PLL_CONTROL);
mmio_clrbits_32(AP_PLL_CON4, SPM_PLL_OUT_OFF_CONTROL);
mmio_clrbits_32(AP_PLL_CON6, PLL_DLY);
NOTICE("%s() end\n", __func__);
}
@@ -0,0 +1,170 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include <spm.h>
#include <spm_pmic_wrap.h>
#include <lib/libc/string.h>
#define SLEEP_REG_MD_SPM_DVFS_CMD20 (SLEEP_REG_MD_BASE + 0x010)
#define SLEEP_REG_MD_SPM_DVFS_CMD21 (SLEEP_REG_MD_BASE + 0x014)
#define SLEEP_REG_MD_SPM_DVFS_CMD22 (SLEEP_REG_MD_BASE + 0x018)
#define SLEEP_REG_MD_SPM_DVFS_CMD23 (SLEEP_REG_MD_BASE + 0x01C)
/* PMIC_WRAP -> PMIC MT6358 */
#define VCORE_BASE_UV 50000
#define VOLT_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625)
#define PMIC_VAL_TO_VOLT(pmic) (((pmic) * 625) + VCORE_BASE_UV)
#define DEFAULT_VOLT_VSRAM (100000)
#define DEFAULT_VOLT_VCORE (100000)
#define NR_PMIC_WRAP_CMD (NR_IDX_ALL)
#define MAX_RETRY_COUNT (100)
#define SPM_DATA_SHIFT (16)
#define BUCK_VCORE_ELR0 0x14AA
#define BUCK_VPROC12_CON0 0x1408
#define BUCK_VPROC11_CON0 0x1388
#define TOP_SPI_CON0 0x044C
#define LDO_VSRAM_PROC12_CON0 0x1B88
#define LDO_VSRAM_PROC11_CON0 0x1B46
#define BUCK_VMODEM_ELR0 0x15A6
struct pmic_wrap_cmd {
unsigned long cmd_addr;
unsigned long cmd_wdata;
};
struct pmic_wrap_setting {
enum pmic_wrap_phase_id phase;
struct pmic_wrap_cmd addr[NR_PMIC_WRAP_CMD];
struct {
struct {
unsigned long cmd_addr;
unsigned long cmd_wdata;
} _[NR_PMIC_WRAP_CMD];
const int nr_idx;
} set[NR_PMIC_WRAP_PHASE];
};
static struct pmic_wrap_setting pw = {
.phase = NR_PMIC_WRAP_PHASE,
.addr = {{0, 0} },
.set[PMIC_WRAP_PHASE_ALLINONE] = {
._[CMD_0] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(70000),},
._[CMD_1] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(80000),},
._[CMD_2] = {BUCK_VPROC12_CON0, 0x3,},
._[CMD_3] = {BUCK_VPROC12_CON0, 0x1,},
._[CMD_4] = {BUCK_VPROC11_CON0, 0x3,},
._[CMD_5] = {BUCK_VPROC11_CON0, 0x1,},
._[CMD_6] = {TOP_SPI_CON0, 0x1,},
._[CMD_7] = {TOP_SPI_CON0, 0x0,},
._[CMD_8] = {BUCK_VPROC12_CON0, 0x0,},
._[CMD_9] = {BUCK_VPROC12_CON0, 0x1,},
._[CMD_10] = {BUCK_VPROC11_CON0, 0x0,},
._[CMD_11] = {BUCK_VPROC11_CON0, 0x1,},
._[CMD_12] = {LDO_VSRAM_PROC12_CON0, 0x0,},
._[CMD_13] = {LDO_VSRAM_PROC12_CON0, 0x1,},
._[CMD_14] = {LDO_VSRAM_PROC11_CON0, 0x0,},
._[CMD_15] = {LDO_VSRAM_PROC11_CON0, 0x1,},
._[CMD_20] = {BUCK_VMODEM_ELR0, VOLT_TO_PMIC_VAL(55000),},
._[CMD_21] = {BUCK_VCORE_ELR0, VOLT_TO_PMIC_VAL(60000),},
._[CMD_22] = {LDO_VSRAM_PROC11_CON0, 0x3,},
._[CMD_23] = {LDO_VSRAM_PROC11_CON0, 0x1,},
.nr_idx = NR_IDX_ALL
}
};
void _mt_spm_pmic_table_init(void)
{
struct pmic_wrap_cmd pwrap_cmd_default[NR_PMIC_WRAP_CMD] = {
{(uint32_t)SPM_DVFS_CMD0, (uint32_t)SPM_DVFS_CMD0,},
{(uint32_t)SPM_DVFS_CMD1, (uint32_t)SPM_DVFS_CMD1,},
{(uint32_t)SPM_DVFS_CMD2, (uint32_t)SPM_DVFS_CMD2,},
{(uint32_t)SPM_DVFS_CMD3, (uint32_t)SPM_DVFS_CMD3,},
{(uint32_t)SPM_DVFS_CMD4, (uint32_t)SPM_DVFS_CMD4,},
{(uint32_t)SPM_DVFS_CMD5, (uint32_t)SPM_DVFS_CMD5,},
{(uint32_t)SPM_DVFS_CMD6, (uint32_t)SPM_DVFS_CMD6,},
{(uint32_t)SPM_DVFS_CMD7, (uint32_t)SPM_DVFS_CMD7,},
{(uint32_t)SPM_DVFS_CMD8, (uint32_t)SPM_DVFS_CMD8,},
{(uint32_t)SPM_DVFS_CMD9, (uint32_t)SPM_DVFS_CMD9,},
{(uint32_t)SPM_DVFS_CMD10, (uint32_t)SPM_DVFS_CMD10,},
{(uint32_t)SPM_DVFS_CMD11, (uint32_t)SPM_DVFS_CMD11,},
{(uint32_t)SPM_DVFS_CMD12, (uint32_t)SPM_DVFS_CMD12,},
{(uint32_t)SPM_DVFS_CMD13, (uint32_t)SPM_DVFS_CMD13,},
{(uint32_t)SPM_DVFS_CMD14, (uint32_t)SPM_DVFS_CMD14,},
{(uint32_t)SPM_DVFS_CMD15, (uint32_t)SPM_DVFS_CMD15,},
{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,
(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD20,},
{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,
(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD21,},
{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,
(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD22,},
{(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,
(uint32_t)SLEEP_REG_MD_SPM_DVFS_CMD23,}
};
memcpy(pw.addr, pwrap_cmd_default, sizeof(pwrap_cmd_default));
}
void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase)
{
uint32_t idx, addr, data;
if (phase >= NR_PMIC_WRAP_PHASE)
return;
if (pw.phase == phase)
return;
if (pw.addr[0].cmd_addr == 0)
_mt_spm_pmic_table_init();
pw.phase = phase;
mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY |
BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB);
for (idx = 0; idx < pw.set[phase].nr_idx; idx++) {
addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
data = pw.set[phase]._[idx].cmd_wdata;
mmio_write_32(pw.addr[idx].cmd_addr, addr | data);
}
}
void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase, uint32_t idx,
uint32_t cmd_wdata)
{
uint32_t addr;
if (phase >= NR_PMIC_WRAP_PHASE)
return;
if (idx >= pw.set[phase].nr_idx)
return;
pw.set[phase]._[idx].cmd_wdata = cmd_wdata;
mmio_write_32(POWERON_CONFIG_EN, SPM_REGWR_CFG_KEY |
BCLK_CG_EN_LSB | MD_BCLK_CG_EN_LSB);
if (pw.phase == phase) {
addr = pw.set[phase]._[idx].cmd_addr << SPM_DATA_SHIFT;
mmio_write_32(pw.addr[idx].cmd_addr, addr | cmd_wdata);
}
}
uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx)
{
if (phase >= NR_PMIC_WRAP_PHASE)
return 0;
if (idx >= pw.set[phase].nr_idx)
return 0;
return pw.set[phase]._[idx].cmd_wdata;
}
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/****************************************************************
* Auto generated by DE, please DO NOT modify this file directly.
*****************************************************************/
#ifndef SPM_PMIC_WRAP__H
#define SPM_PMIC_WRAP__H
enum pmic_wrap_phase_id {
PMIC_WRAP_PHASE_ALLINONE,
NR_PMIC_WRAP_PHASE
};
/* IDX mapping */
enum {
CMD_0, /* 0x0 *//* PMIC_WRAP_PHASE_ALLINONE */
CMD_1, /* 0x1 */
CMD_2, /* 0x2 */
CMD_3, /* 0x3 */
CMD_4, /* 0x4 */
CMD_5, /* 0x5 */
CMD_6, /* 0x6 */
CMD_7, /* 0x7 */
CMD_8, /* 0x8 */
CMD_9, /* 0x9 */
CMD_10, /* 0xA */
CMD_11, /* 0xB */
CMD_12, /* 0xC */
CMD_13, /* 0xD */
CMD_14, /* 0xE */
CMD_15, /* 0xF */
CMD_20, /* 0x14 */
CMD_21, /* 0x15 */
CMD_22, /* 0x16 */
CMD_23, /* 0x17 */
NR_IDX_ALL
};
/* APIs */
void mt_spm_pmic_wrap_set_phase(enum pmic_wrap_phase_id phase);
void mt_spm_pmic_wrap_set_cmd(enum pmic_wrap_phase_id phase,
uint32_t idx, uint32_t cmd_wdata);
uint64_t mt_spm_pmic_wrap_get_cmd(enum pmic_wrap_phase_id phase, uint32_t idx);
#endif /* SPM_PMIC_WRAP__H */
@@ -0,0 +1,255 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <mt_gic_v3.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include <pmic.h>
#include <spm.h>
#include <uart.h>
#define SPM_SYSCLK_SETTLE 99
#define WAKE_SRC_FOR_SUSPEND \
(WAKE_SRC_R12_PCM_TIMER | \
WAKE_SRC_R12_SSPM_WDT_EVENT_B | \
WAKE_SRC_R12_KP_IRQ_B | \
WAKE_SRC_R12_CONN2AP_SPM_WAKEUP_B | \
WAKE_SRC_R12_EINT_EVENT_B | \
WAKE_SRC_R12_CONN_WDT_IRQ_B | \
WAKE_SRC_R12_CCIF0_EVENT_B | \
WAKE_SRC_R12_SSPM_SPM_IRQ_B | \
WAKE_SRC_R12_SCP_SPM_IRQ_B | \
WAKE_SRC_R12_SCP_WDT_EVENT_B | \
WAKE_SRC_R12_USB_CDSC_B | \
WAKE_SRC_R12_USB_POWERDWN_B | \
WAKE_SRC_R12_SYS_TIMER_EVENT_B | \
WAKE_SRC_R12_EINT_EVENT_SECURE_B | \
WAKE_SRC_R12_CCIF1_EVENT_B | \
WAKE_SRC_R12_MD2AP_PEER_EVENT_B | \
WAKE_SRC_R12_MD1_WDT_B | \
WAKE_SRC_R12_CLDMA_EVENT_B | \
WAKE_SRC_R12_SEJ_WDT_GPT_B)
#define SLP_PCM_FLAGS \
(SPM_FLAG_DIS_VCORE_DVS | SPM_FLAG_DIS_VCORE_DFS | \
SPM_FLAG_DIS_ATF_ABORT | SPM_FLAG_DISABLE_MMSYS_DVFS | \
SPM_FLAG_DIS_INFRA_PDN | SPM_FLAG_SUSPEND_OPTION)
#define SLP_PCM_FLAGS1 \
(SPM_FLAG1_DISABLE_MCDSR)
static const struct pwr_ctrl suspend_ctrl = {
.wake_src = WAKE_SRC_FOR_SUSPEND,
.pcm_flags = SLP_PCM_FLAGS,
.pcm_flags1 = SLP_PCM_FLAGS1,
/* SPM_AP_STANDBY_CON */
.wfi_op = 0x1,
.mp0_cputop_idle_mask = 0,
.mp1_cputop_idle_mask = 0,
.mcusys_idle_mask = 0,
.mm_mask_b = 0,
.md_ddr_en_0_dbc_en = 0x1,
.md_ddr_en_1_dbc_en = 0,
.md_mask_b = 0x1,
.sspm_mask_b = 0x1,
.scp_mask_b = 0x1,
.srcclkeni_mask_b = 0x1,
.md_apsrc_1_sel = 0,
.md_apsrc_0_sel = 0,
.conn_ddr_en_dbc_en = 0x1,
.conn_mask_b = 0x1,
.conn_apsrc_sel = 0,
/* SPM_SRC_REQ */
.spm_apsrc_req = 0,
.spm_f26m_req = 0,
.spm_infra_req = 0,
.spm_vrf18_req = 0,
.spm_ddren_req = 0,
.spm_rsv_src_req = 0,
.spm_ddren_2_req = 0,
.cpu_md_dvfs_sop_force_on = 0,
/* SPM_SRC_MASK */
.csyspwreq_mask = 0x1,
.ccif0_md_event_mask_b = 0x1,
.ccif0_ap_event_mask_b = 0x1,
.ccif1_md_event_mask_b = 0x1,
.ccif1_ap_event_mask_b = 0x1,
.ccif2_md_event_mask_b = 0x1,
.ccif2_ap_event_mask_b = 0x1,
.ccif3_md_event_mask_b = 0x1,
.ccif3_ap_event_mask_b = 0x1,
.md_srcclkena_0_infra_mask_b = 0x1,
.md_srcclkena_1_infra_mask_b = 0,
.conn_srcclkena_infra_mask_b = 0,
.ufs_infra_req_mask_b = 0,
.srcclkeni_infra_mask_b = 0,
.md_apsrc_req_0_infra_mask_b = 0x1,
.md_apsrc_req_1_infra_mask_b = 0x1,
.conn_apsrcreq_infra_mask_b = 0x1,
.ufs_srcclkena_mask_b = 0,
.md_vrf18_req_0_mask_b = 0,
.md_vrf18_req_1_mask_b = 0,
.ufs_vrf18_req_mask_b = 0,
.gce_vrf18_req_mask_b = 0,
.conn_infra_req_mask_b = 0x1,
.gce_apsrc_req_mask_b = 0,
.disp0_apsrc_req_mask_b = 0,
.disp1_apsrc_req_mask_b = 0,
.mfg_req_mask_b = 0,
.vdec_req_mask_b = 0,
/* SPM_SRC2_MASK */
.md_ddr_en_0_mask_b = 0x1,
.md_ddr_en_1_mask_b = 0,
.conn_ddr_en_mask_b = 0x1,
.ddren_sspm_apsrc_req_mask_b = 0x1,
.ddren_scp_apsrc_req_mask_b = 0x1,
.disp0_ddren_mask_b = 0x1,
.disp1_ddren_mask_b = 0x1,
.gce_ddren_mask_b = 0x1,
.ddren_emi_self_refresh_ch0_mask_b = 0,
.ddren_emi_self_refresh_ch1_mask_b = 0,
/* SPM_WAKEUP_EVENT_MASK */
.spm_wakeup_event_mask = 0xF1782218,
/* SPM_WAKEUP_EVENT_EXT_MASK */
.spm_wakeup_event_ext_mask = 0xFFFFFFFF,
/* SPM_SRC3_MASK */
.md_ddr_en_2_0_mask_b = 0x1,
.md_ddr_en_2_1_mask_b = 0,
.conn_ddr_en_2_mask_b = 0x1,
.ddren2_sspm_apsrc_req_mask_b = 0x1,
.ddren2_scp_apsrc_req_mask_b = 0x1,
.disp0_ddren2_mask_b = 0,
.disp1_ddren2_mask_b = 0,
.gce_ddren2_mask_b = 0,
.ddren2_emi_self_refresh_ch0_mask_b = 0,
.ddren2_emi_self_refresh_ch1_mask_b = 0,
.mp0_cpu0_wfi_en = 0x1,
.mp0_cpu1_wfi_en = 0x1,
.mp0_cpu2_wfi_en = 0x1,
.mp0_cpu3_wfi_en = 0x1,
.mp1_cpu0_wfi_en = 0x1,
.mp1_cpu1_wfi_en = 0x1,
.mp1_cpu2_wfi_en = 0x1,
.mp1_cpu3_wfi_en = 0x1
};
static uint32_t spm_set_sysclk_settle(void)
{
mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE);
return mmio_read_32(SPM_CLK_SETTLE);
}
void go_to_sleep_before_wfi(void)
{
int cpu = MPIDR_AFFLVL0_VAL(read_mpidr());
uint32_t settle;
settle = spm_set_sysclk_settle();
spm_set_cpu_status(cpu);
spm_set_power_control(&suspend_ctrl);
spm_set_wakeup_event(&suspend_ctrl);
spm_set_pcm_flags(&suspend_ctrl);
spm_send_cpu_wakeup_event();
spm_set_pcm_wdt(0);
spm_disable_pcm_timer();
if (is_infra_pdn(suspend_ctrl.pcm_flags))
mt_uart_save();
if (!mt_console_uart_cg_status())
console_switch_state(CONSOLE_FLAG_BOOT);
INFO("cpu%d: \"%s\", wakesrc = 0x%x, pcm_con1 = 0x%x\n",
cpu, spm_get_firmware_version(), suspend_ctrl.wake_src,
mmio_read_32(PCM_CON1));
INFO("settle = %u, sec = %u, sw_flag = 0x%x 0x%x, src_req = 0x%x\n",
settle, mmio_read_32(PCM_TIMER_VAL) / 32768,
suspend_ctrl.pcm_flags, suspend_ctrl.pcm_flags1,
mmio_read_32(SPM_SRC_REQ));
if (!mt_console_uart_cg_status())
console_switch_state(CONSOLE_FLAG_RUNTIME);
}
static void go_to_sleep_after_wfi(void)
{
struct wake_status spm_wakesta;
if (is_infra_pdn(suspend_ctrl.pcm_flags))
mt_uart_restore();
spm_set_pcm_wdt(0);
spm_get_wakeup_status(&spm_wakesta);
spm_clean_after_wakeup();
if (!mt_console_uart_cg_status())
console_switch_state(CONSOLE_FLAG_BOOT);
spm_output_wake_reason(&spm_wakesta, "suspend");
if (!mt_console_uart_cg_status())
console_switch_state(CONSOLE_FLAG_RUNTIME);
}
static void spm_enable_armpll_l(void)
{
/* power on */
mmio_setbits_32(ARMPLL_L_PWR_CON0, 0x1);
/* clear isolation */
mmio_clrbits_32(ARMPLL_L_PWR_CON0, 0x2);
/* enable pll */
mmio_setbits_32(ARMPLL_L_CON0, 0x1);
/* Add 20us delay for turning on PLL */
udelay(20);
}
static void spm_disable_armpll_l(void)
{
/* disable pll */
mmio_clrbits_32(ARMPLL_L_CON0, 0x1);
/* isolation */
mmio_setbits_32(ARMPLL_L_PWR_CON0, 0x2);
/* power off */
mmio_clrbits_32(ARMPLL_L_PWR_CON0, 0x1);
}
void spm_system_suspend(void)
{
spm_disable_armpll_l();
bcpu_enable(0);
bcpu_sram_enable(0);
spm_lock_get();
go_to_sleep_before_wfi();
spm_lock_release();
}
void spm_system_suspend_finish(void)
{
spm_lock_get();
go_to_sleep_after_wfi();
spm_lock_release();
spm_enable_armpll_l();
bcpu_sram_enable(1);
bcpu_enable(1);
}
@@ -0,0 +1,13 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SPM_SUSPEND_H__
#define __SPM_SUSPEND_H__
void spm_system_suspend(void);
void spm_system_suspend_finish(void);
#endif /* __SPM_SUSPEND_H__*/
@@ -0,0 +1,366 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <arch_helpers.h>
#include <cortex_a53.h>
#include <cortex_a73.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <platform_def.h>
#include <mcucfg.h>
#include <spm.h>
#include <drivers/delay_timer.h>
#include <mtspmc.h>
#include "mtspmc_private.h"
static void set_retention(int cluster, int tick)
{
uint64_t cpuectlr;
if (cluster)
cpuectlr = read_a73_cpuectlr_el1();
else
cpuectlr = read_a53_cpuectlr_el1();
cpuectlr &= ~0x7ULL;
cpuectlr |= tick & 0x7;
if (cluster)
write_a73_cpuectlr_el1(cpuectlr);
else
write_a53_cpuectlr_el1(cpuectlr);
}
void spm_enable_cpu_auto_off(int cluster, int cpu)
{
uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK);
set_retention(cluster, 1);
mmio_clrbits_32(reg, SW_NO_WAIT_Q);
}
void spm_disable_cpu_auto_off(int cluster, int cpu)
{
uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK);
mmio_setbits_32(reg, SW_NO_WAIT_Q);
set_retention(cluster, 0);
}
void spm_set_cpu_power_off(int cluster, int cpu)
{
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
}
void spm_enable_cluster_auto_off(int cluster)
{
assert(cluster);
mmio_clrbits_32(MCUCFG_MP2_SPMC, SW_NO_WAIT_Q);
mmio_clrbits_32(MCUCFG_MP2_COQ, BIT(0));
mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, MP1_SPMC_SRAM_DORMANT_EN);
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
}
void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr)
{
uintptr_t reg;
const uintptr_t mp2_bootreg[] = {
MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1,
MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 };
if (cluster) {
assert(cpu >= 0 && cpu < 4);
reg = mp2_bootreg[cpu];
} else {
reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR);
}
mmio_write_32(reg, bootaddr);
}
uintptr_t mcucfg_get_bootaddr(int cluster, int cpu)
{
uintptr_t reg;
const uintptr_t mp2_bootreg[] = {
MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1,
MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 };
if (cluster) {
assert(cpu >= 0 && cpu < 4);
reg = mp2_bootreg[cpu];
} else {
reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR);
}
return mmio_read_32(reg);
}
void mcucfg_init_archstate(int cluster, int cpu, int arm64)
{
uintptr_t reg;
int i;
reg = per_cluster(cluster, MCUCFG_INITARCH);
i = cluster ? 16 : 12;
mmio_setbits_32(reg, (arm64 & 1) << (i + cpu));
}
/**
* Return power state of specified subsystem
*
* @mask: mask to SPM_PWR_STATUS to query the power state
* of one subsystem.
* RETURNS:
* 0 (the subsys was powered off)
* 1 (the subsys was powered on)
*/
int spm_get_powerstate(uint32_t mask)
{
return mmio_read_32(SPM_PWR_STATUS) & mask;
}
int spm_get_cluster_powerstate(int cluster)
{
uint32_t mask;
mask = cluster ? PWR_STATUS_MP1_CPUTOP : PWR_STATUS_MP0_CPUTOP;
return spm_get_powerstate(mask);
}
int spm_get_cpu_powerstate(int cluster, int cpu)
{
uint32_t i;
/*
* a quick way to specify the mask of cpu[0-3]/cpu[4-7] in PWR_STATUS
* register which are the BITS[9:12](MP0_CPU0~3) and
* BITS[16:19](MP1_CPU0~3)
*/
i = (cluster) ? 16 : 9;
i = 1 << (i + cpu);
return spm_get_powerstate(i);
}
int spmc_init(void)
{
/* enable SPM register control */
mmio_write_32(SPM_POWERON_CONFIG_EN,
PROJECT_CODE | MD_BCLK_CG_EN | BCLK_CG_EN);
#if SPMC_MODE == 1
INFO("SPM: enable SPMC mode\n");
/* 0: SPMC mode 1: Legacy mode */
mmio_write_32(SPM_BYPASS_SPMC, 0);
mmio_clrbits_32(per_cluster(0, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND);
mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
mmio_clrbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
mmio_clrbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
mmio_clrbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
#endif
mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND);
mmio_setbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_RST_B);
mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_CLK_DIS);
mmio_clrbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
mmio_clrbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
mmio_clrbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
mmio_clrbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
mmio_setbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
mmio_setbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
mmio_setbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
mmio_setbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
return 0;
}
/**
* Power on a core with specified cluster and core index
*
* @cluster: the cluster ID of the CPU which to be powered on
* @cpu: the CPU ID of the CPU which to be powered on
*/
void spm_poweron_cpu(int cluster, int cpu)
{
INFO("spmc: power on core %d.%d\n", cluster, cpu);
/* STA_POWER_ON */
/* Start to turn on MP0_CPU0 */
/* Set PWR_RST_B = 1 */
mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
/* Set PWR_ON = 1 */
mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
/* Wait until MP0_CPU0_PWR_STA_MASK = 1 */
while (!spm_get_cpu_powerstate(cluster, cpu))
;
/* Finish to turn on MP0_CPU0 */
INFO("spmc: power on core %d.%d successfully\n", cluster, cpu);
}
/**
* Power off a core with specified cluster and core index
*
* @cluster: the cluster ID of the CPU which to be powered off
* @cpu: the CPU ID of the CPU which to be powered off
*/
void spm_poweroff_cpu(int cluster, int cpu)
{
INFO("spmc: power off core %d.%d\n", cluster, cpu);
/* Start to turn off MP0_CPU0 */
/* Set PWR_ON_2ND = 0 */
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
/* Set PWR_ON = 0 */
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
/* Wait until MP0_CPU0_PWR_STA_MASK = 0 */
while (spm_get_cpu_powerstate(cluster, cpu))
;
/* Set PWR_RST_B = 0 */
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
/* Finish to turn off MP0_CPU0 */
INFO("spmc: power off core %d.%d successfully\n", cluster, cpu);
}
/**
* Power off a cluster with specified index
*
* @cluster: the cluster index which to be powered off
*/
void spm_poweroff_cluster(int cluster)
{
uint32_t mask;
uint32_t pwr_rst_ctl;
INFO("spmc: power off cluster %d\n", cluster);
/* Start to turn off MP0_CPUTOP */
/* Set bus protect - step1 : 0 */
mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK :
MP0_CPUTOP_PROT_STEP1_0_MASK;
mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_SET, mask);
while ((mmio_read_32(INFRA_TOPAXI_PROTECTEN_STA1_1) & mask) != mask)
;
/* Set PWR_ON_2ND = 0 */
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
PWRCTRL_PWR_ON_2ND);
/* SPMC_DORMANT_ENABLE[0]=0 */
mask = (cluster) ? MP1_SPMC_SRAM_DORMANT_EN : MP0_SPMC_SRAM_DORMANT_EN;
mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, mask);
/* Set PWR_ON = 0" */
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
/* Wait until MP0_CPUTOP_PWR_STA_MASK = 0 */
while (spm_get_cluster_powerstate(cluster))
;
/* NOTE
* Following flow only for BIG core cluster. It was from
* application note but not covered in mtcmos_ctrl.c
*/
if (cluster) {
pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL);
mmio_write_32(MCUCFG_MP2_PWR_RST_CTL,
(pwr_rst_ctl & ~SW_RST_B) | TOPAON_APB_MASK);
}
/* CPU_EXT_BUCK_ISO[0]=1 */
if (cluster)
mmio_setbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO);
/* Finish to turn off MP0_CPUTOP */
INFO("spmc: power off cluster %d successfully\n", cluster);
}
/**
* Power on a cluster with specified index
*
* @cluster: the cluster index which to be powered on
*/
void spm_poweron_cluster(int cluster)
{
uint32_t mask;
uint32_t pwr_rst_ctl;
INFO("spmc: power on cluster %d\n", cluster);
/* Start to turn on MP1_CPUTOP */
/* NOTE
* Following flow only for BIG core cluster. It was from
* application note but not covered in mtcmos_ctrl.c
*/
if (cluster) {
mmio_clrbits_32(MCUCFG_MP2_PWR_RST_CTL, SW_RST_B);
/* CPU_EXT_BUCK_ISO[1]=0 */
/* Set mp<n>_vproc_ext_off to 0 to release vproc isolation control */
mmio_clrbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO);
/* NOTE
* Following flow only for BIG core cluster. It was from
* application note but not covered in mtcmos_ctrl.c
*/
pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL);
mmio_write_32(MCUCFG_MP2_PWR_RST_CTL,
(pwr_rst_ctl | SW_RST_B) & ~TOPAON_APB_MASK);
}
/* Set PWR_ON_2ND = 0 */
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
PWRCTRL_PWR_ON_2ND);
/* Set PWR_RST_B = 1 */
mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
PWRCTRL_PWR_RST_B);
/* Set PWR_CLK_DIS = 0 */
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
PWRCTRL_PWR_CLK_DIS);
/* Set PWR_ON = 1 */
mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
/* Wait until MP1_CPUTOP_PWR_STA_MASK = 1 */
while (!spm_get_cluster_powerstate(cluster))
;
/* Release bus protect - step1 : 0 */
mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK :
MP0_CPUTOP_PROT_STEP1_0_MASK;
mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_CLR, mask);
/* Finish to turn on MP1_CPUTOP */
INFO("spmc: power on cluster %d successfully\n", cluster);
}
@@ -0,0 +1,42 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTSPMC_H
#define MTSPMC_H
/*
* CONFIG_SPMC_MODE: Select CPU power control mode.
*
* 0: Legacy
* Control power flow from SW through SPM register (MP*_PWR_CON).
* 1: HW
* Control power flow from SPMC. Most control flow and timing are handled
* by SPMC.
*/
#define SPMC_MODE 1
int spmc_init(void);
void spm_poweron_cpu(int cluster, int cpu);
void spm_poweroff_cpu(int cluster, int cpu);
void spm_poweroff_cluster(int cluster);
void spm_poweron_cluster(int cluster);
int spm_get_cpu_powerstate(int cluster, int cpu);
int spm_get_cluster_powerstate(int cluster);
int spm_get_powerstate(uint32_t mask);
void spm_enable_cpu_auto_off(int cluster, int cpu);
void spm_disable_cpu_auto_off(int cluster, int cpu);
void spm_set_cpu_power_off(int cluster, int cpu);
void spm_enable_cluster_auto_off(int cluster);
void mcucfg_init_archstate(int cluster, int cpu, int arm64);
void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr);
uintptr_t mcucfg_get_bootaddr(int cluster, int cpu);
#endif /* MTSPMC_H */
@@ -0,0 +1,233 @@
/*
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTSPMC_PRIVATE_H
#define MTSPMC_PRIVATE_H
/*
* per_cpu/cluster helper
*/
struct per_cpu_reg {
int cluster_addr;
int cpu_stride;
};
#define per_cpu(cluster, cpu, reg) (reg[cluster].cluster_addr + \
(cpu << reg[cluster].cpu_stride))
#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
/* SPMC related registers */
#define SPM_POWERON_CONFIG_EN (SPM_BASE + 0x000)
/* bit-fields of SPM_POWERON_CONFIG_EN */
#define BCLK_CG_EN (1 << 0)
#define MD_BCLK_CG_EN (1 << 1)
#define PROJECT_CODE (0xb16 << 16)
#define SPM_PWR_STATUS (SPM_BASE + 0x180)
#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x184)
#define SPM_BYPASS_SPMC (SPM_BASE + 0x2b4)
#define SPM_SPMC_DORMANT_ENABLE (SPM_BASE + 0x2b8)
#define SPM_MP0_CPUTOP_PWR_CON (SPM_BASE + 0x204)
#define SPM_MP0_CPU0_PWR_CON (SPM_BASE + 0x208)
#define SPM_MP0_CPU1_PWR_CON (SPM_BASE + 0x20C)
#define SPM_MP0_CPU2_PWR_CON (SPM_BASE + 0x210)
#define SPM_MP0_CPU3_PWR_CON (SPM_BASE + 0x214)
#define SPM_MP1_CPUTOP_PWR_CON (SPM_BASE + 0x218)
#define SPM_MP1_CPU0_PWR_CON (SPM_BASE + 0x21C)
#define SPM_MP1_CPU1_PWR_CON (SPM_BASE + 0x220)
#define SPM_MP1_CPU2_PWR_CON (SPM_BASE + 0x224)
#define SPM_MP1_CPU3_PWR_CON (SPM_BASE + 0x228)
#define SPM_MP0_CPUTOP_L2_PDN (SPM_BASE + 0x240)
#define SPM_MP0_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x244)
#define SPM_MP0_CPU0_L1_PDN (SPM_BASE + 0x248)
#define SPM_MP0_CPU1_L1_PDN (SPM_BASE + 0x24C)
#define SPM_MP0_CPU2_L1_PDN (SPM_BASE + 0x250)
#define SPM_MP0_CPU3_L1_PDN (SPM_BASE + 0x254)
#define SPM_MP1_CPUTOP_L2_PDN (SPM_BASE + 0x258)
#define SPM_MP1_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x25C)
#define SPM_MP1_CPU0_L1_PDN (SPM_BASE + 0x260)
#define SPM_MP1_CPU1_L1_PDN (SPM_BASE + 0x264)
#define SPM_MP1_CPU2_L1_PDN (SPM_BASE + 0x268)
#define SPM_MP1_CPU3_L1_PDN (SPM_BASE + 0x26C)
#define SPM_CPU_EXT_BUCK_ISO (SPM_BASE + 0x290)
/* bit-fields of SPM_CPU_EXT_BUCK_ISO */
#define MP0_EXT_BUCK_ISO (1 << 0)
#define MP1_EXT_BUCK_ISO (1 << 1)
#define MP_EXT_BUCK_ISO (1 << 2)
/* bit-fields of SPM_PWR_STATUS */
#define PWR_STATUS_MD (1 << 0)
#define PWR_STATUS_CONN (1 << 1)
#define PWR_STATUS_DDRPHY (1 << 2)
#define PWR_STATUS_DISP (1 << 3)
#define PWR_STATUS_MFG (1 << 4)
#define PWR_STATUS_ISP (1 << 5)
#define PWR_STATUS_INFRA (1 << 6)
#define PWR_STATUS_VDEC (1 << 7)
#define PWR_STATUS_MP0_CPUTOP (1 << 8)
#define PWR_STATUS_MP0_CPU0 (1 << 9)
#define PWR_STATUS_MP0_CPU1 (1 << 10)
#define PWR_STATUS_MP0_CPU2 (1 << 11)
#define PWR_STATUS_MP0_CPU3 (1 << 12)
#define PWR_STATUS_MCUSYS (1 << 14)
#define PWR_STATUS_MP1_CPUTOP (1 << 15)
#define PWR_STATUS_MP1_CPU0 (1 << 16)
#define PWR_STATUS_MP1_CPU1 (1 << 17)
#define PWR_STATUS_MP1_CPU2 (1 << 18)
#define PWR_STATUS_MP1_CPU3 (1 << 19)
#define PWR_STATUS_VEN (1 << 21)
#define PWR_STATUS_MFG_ASYNC (1 << 23)
#define PWR_STATUS_AUDIO (1 << 24)
#define PWR_STATUS_C2K (1 << 28)
#define PWR_STATUS_MD_INFRA (1 << 29)
/* bit-fields of SPM_*_PWR_CON */
#define PWRCTRL_PWR_RST_B (1 << 0)
#define PWRCTRL_PWR_ISO (1 << 1)
#define PWRCTRL_PWR_ON (1 << 2)
#define PWRCTRL_PWR_ON_2ND (1 << 3)
#define PWRCTRL_PWR_CLK_DIS (1 << 4)
#define PWRCTRL_PWR_SRAM_CKISO (1 << 5)
#define PWRCTRL_PWR_SRAM_ISOINT_B (1 << 6)
#define PWRCTRL_PWR_SRAM_PD_SLPB_CLAMP (1 << 7)
#define PWRCTRL_PWR_SRAM_PDN (1 << 8)
#define PWRCTRL_PWR_SRAM_SLEEP_B (1 << 12)
#define PWRCTRL_PWR_SRAM_PDN_ACK (1 << 24)
#define PWRCTRL_PWR_SRAM_SLEEP_B_ACK (1 << 28)
/* per_cpu registers for SPM_MP?_CPU?_PWR_CON */
static const struct per_cpu_reg SPM_CPU_PWR[] = {
[0] = { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2 },
[1] = { .cluster_addr = SPM_MP1_CPU0_PWR_CON, .cpu_stride = 2 },
};
/* per_cluster registers for SPM_MP?_CPUTOP_PWR_CON */
static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
[0] = { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON },
[1] = { .cluster_addr = SPM_MP1_CPUTOP_PWR_CON },
};
/* APB Module infracfg_ao */
#define INFRA_TOPAXI_PROTECTEN_1 (INFRACFG_AO_BASE + 0x250)
#define INFRA_TOPAXI_PROTECTEN_STA1_1 (INFRACFG_AO_BASE + 0x258)
#define INFRA_TOPAXI_PROTECTEN_1_SET (INFRACFG_AO_BASE + 0x2A8)
#define INFRA_TOPAXI_PROTECTEN_1_CLR (INFRACFG_AO_BASE + 0x2AC)
/* bit-fields of INFRA_TOPAXI_PROTECTEN_1_SET */
#define MP0_CPUTOP_PROT_STEP1_0_MASK ((1 << 10)|(1 << 12)| \
(1 << 13)|(1 << 26))
#define MP1_CPUTOP_PROT_STEP1_0_MASK ((1 << 11)|(1 << 14)| \
(1 << 15)|(1 << 27))
/* bit-fields of INFRA_TOPAXI_PROTECTEN_STA1_1 */
#define MP0_CPUTOP_PROT_STEP1_0_ACK_MASK ((1 << 10)|(1 << 12)| \
(1 << 13)|(1 << 26))
#define MP1_CPUTOP_PROT_STEP1_0_ACK_MASK ((1 << 11)|(1 << 14)| \
(1 << 15)|(1 << 27))
/*
* MCU configuration registers
*/
/* bit-fields of MCUCFG_MP?_AXI_CONFIG */
#define MCUCFG_AXI_CONFIG_BROADCASTINNER (1 << 0)
#define MCUCFG_AXI_CONFIG_BROADCASTOUTER (1 << 1)
#define MCUCFG_AXI_CONFIG_BROADCASTCACHEMAINT (1 << 2)
#define MCUCFG_AXI_CONFIG_SYSBARDISABLE (1 << 3)
#define MCUCFG_AXI_CONFIG_ACINACTM (1 << 4)
#define MCUCFG_AXI_CONFIG_AINACTS (1 << 5)
#define MCUCFG_MP0_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[2])
#define MCUCFG_MP0_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[3])
#define MCUCFG_MP1_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp1_misc_config[2])
#define MCUCFG_MP1_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp1_misc_config[3])
#define MCUCFG_CPUSYS0_SPARKVRETCNTRL (MCUCFG_BASE + 0x1c00)
/* bit-fields of MCUCFG_CPUSYS0_SPARKVRETCNTRL */
#define CPU0_SPARK_VRET_CTRL (0x3f << 0)
#define CPU1_SPARK_VRET_CTRL (0x3f << 8)
#define CPU2_SPARK_VRET_CTRL (0x3f << 16)
#define CPU3_SPARK_VRET_CTRL (0x3f << 24)
/* SPARK control in little cores */
#define MCUCFG_CPUSYS0_CPU0_SPMC_CTL (MCUCFG_BASE + 0x1c30)
#define MCUCFG_CPUSYS0_CPU1_SPMC_CTL (MCUCFG_BASE + 0x1c34)
#define MCUCFG_CPUSYS0_CPU2_SPMC_CTL (MCUCFG_BASE + 0x1c38)
#define MCUCFG_CPUSYS0_CPU3_SPMC_CTL (MCUCFG_BASE + 0x1c3c)
/* bit-fields of MCUCFG_CPUSYS0_CPU?_SPMC_CTL */
#define SW_SPARK_EN (1 << 0)
#define SW_NO_WAIT_Q (1 << 1)
/* the MCUCFG which BIG cores used is at (MCUCFG_BASE + 0x2000) */
#define MCUCFG_MP2_BASE (MCUCFG_BASE + 0x2000)
#define MCUCFG_MP2_PWR_RST_CTL (MCUCFG_MP2_BASE + 0x8)
/* bit-fields of MCUCFG_MP2_PWR_RST_CTL */
#define SW_RST_B (1 << 0)
#define TOPAON_APB_MASK (1 << 1)
#define MCUCFG_MP2_CPUCFG (MCUCFG_MP2_BASE + 0x208)
#define MCUCFG_MP2_RVADDR0 (MCUCFG_MP2_BASE + 0x290)
#define MCUCFG_MP2_RVADDR1 (MCUCFG_MP2_BASE + 0x298)
#define MCUCFG_MP2_RVADDR2 (MCUCFG_MP2_BASE + 0x2c0)
#define MCUCFG_MP2_RVADDR3 (MCUCFG_MP2_BASE + 0x2c8)
/* SPMC control */
#define MCUCFG_MP0_SPMC (MCUCFG_BASE + 0x788)
#define MCUCFG_MP2_SPMC (MCUCFG_MP2_BASE + 0x2a0)
#define MCUCFG_MP2_COQ (MCUCFG_MP2_BASE + 0x2bC)
/* per_cpu registers for MCUCFG_MP?_MISC_CONFIG2 */
static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
[0] = { .cluster_addr = MCUCFG_MP0_MISC_CONFIG2, .cpu_stride = 3 },
};
/* per_cpu registers for MCUCFG_MP?_MISC_CONFIG3 */
static const struct per_cpu_reg MCUCFG_INITARCH[] = {
[0] = { .cluster_addr = MCUCFG_MP0_MISC_CONFIG3 },
[1] = { .cluster_addr = MCUCFG_MP2_CPUCFG },
};
/* SPARK control in BIG cores */
#define MCUCFG_MP2_PTP3_CPU0_SPMC0 (MCUCFG_MP2_BASE + 0x430)
#define MCUCFG_MP2_PTP3_CPU0_SPMC1 (MCUCFG_MP2_BASE + 0x434)
#define MCUCFG_MP2_PTP3_CPU1_SPMC0 (MCUCFG_MP2_BASE + 0x438)
#define MCUCFG_MP2_PTP3_CPU1_SPMC1 (MCUCFG_MP2_BASE + 0x43c)
#define MCUCFG_MP2_PTP3_CPU2_SPMC0 (MCUCFG_MP2_BASE + 0x440)
#define MCUCFG_MP2_PTP3_CPU2_SPMC1 (MCUCFG_MP2_BASE + 0x444)
#define MCUCFG_MP2_PTP3_CPU3_SPMC0 (MCUCFG_MP2_BASE + 0x448)
#define MCUCFG_MP2_PTP3_CPU3_SPMC1 (MCUCFG_MP2_BASE + 0x44c)
/* bit-fields of MCUCFG_MP2_PTP3_CPU?_SPMC? */
#define SW_SPARK_EN (1 << 0)
#define SW_NO_WAIT_Q (1 << 1)
#define MCUCFG_MP2_SPARK2LDO (MCUCFG_MP2_BASE + 0x700)
/* bit-fields of MCUCFG_MP2_SPARK2LDO */
#define SPARK_VRET_CTRL (0x3f << 0)
#define CPU0_SPARK_LDO_AMUXSEL (0xf << 6)
#define CPU1_SPARK_LDO_AMUXSEL (0xf << 10)
#define CPU2_SPARK_LDO_AMUXSEL (0xf << 14)
#define CPU3_SPARK_LDO_AMUXSEL (0xf << 18)
/* per_cpu registers for SPARK */
static const struct per_cpu_reg MCUCFG_SPARK[] = {
[0] = { .cluster_addr = MCUCFG_CPUSYS0_CPU0_SPMC_CTL, .cpu_stride = 2 },
[1] = { .cluster_addr = MCUCFG_MP2_PTP3_CPU0_SPMC0, .cpu_stride = 3 },
};
/* per_cpu registers for SPARK2LDO */
static const struct per_cpu_reg MCUCFG_SPARK2LDO[] = {
[0] = { .cluster_addr = MCUCFG_CPUSYS0_SPARKVRETCNTRL },
[1] = { .cluster_addr = MCUCFG_MP2_SPARK2LDO },
};
#endif /* MTSPMC_PRIVATE_H */
@@ -0,0 +1,159 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <errno.h>
#include <lib/mmio.h>
#include <sspm.h>
static void memcpy_to_sspm(uint32_t dst, uint32_t *src, uint32_t len)
{
while (len--) {
mmio_write_32(dst, *src);
dst += sizeof(uint32_t);
src++;
}
}
static void memcpy_from_sspm(uint32_t *dst, uint32_t src, uint32_t len)
{
while (len--) {
*dst = mmio_read_32(src);
dst++;
src += sizeof(uint32_t);
}
}
int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len)
{
if (slot >= 32) {
ERROR("%s:slot = %d\n", __func__, slot);
return -EINVAL;
}
if (data)
memcpy_from_sspm(data,
MBOX3_BASE + slot * 4,
len);
return 0;
}
int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len)
{
if (slot >= 32) {
ERROR("%s:slot = %d\n", __func__, slot);
return -EINVAL;
}
if (data)
memcpy_to_sspm(MBOX3_BASE + slot * 4,
data,
len);
return 0;
}
static int sspm_ipi_check_ack(uint32_t id)
{
int ret = 0;
if (id == IPI_ID_PLATFORM) {
if ((mmio_read_32(MBOX0_BASE + MBOX_IN_IRQ_OFS) & 0x1) == 0x1)
ret = -EINPROGRESS;
} else if (id == IPI_ID_SUSPEND) {
if ((mmio_read_32(MBOX1_BASE + MBOX_IN_IRQ_OFS) & 0x2) == 0x2)
ret = -EINPROGRESS;
} else {
ERROR("%s: id = %d\n", __func__, id);
ret = -EINVAL;
}
return ret;
}
int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data)
{
int ret = 0;
ret = sspm_ipi_check_ack(id);
if (ret)
return ret;
if (id == IPI_ID_PLATFORM) {
memcpy_to_sspm(MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
data,
PINR_SIZE_PLATFORM);
dsb();
mmio_write_32(MBOX0_BASE + MBOX_OUT_IRQ_OFS, 0x1);
} else if (id == IPI_ID_SUSPEND) {
memcpy_to_sspm(MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
data,
PINR_SIZE_SUSPEND);
dsb();
mmio_write_32(MBOX1_BASE + MBOX_OUT_IRQ_OFS,
0x2);
}
return 0;
}
int sspm_ipi_recv_non_blocking(uint32_t id, uint32_t *data, uint32_t len)
{
int ret = 0;
ret = sspm_ipi_check_ack(id);
if (ret == -EINPROGRESS) {
if (id == IPI_ID_PLATFORM) {
memcpy_from_sspm(data,
MBOX0_BASE + PINR_OFFSET_PLATFORM * 4,
len);
dsb();
/* clear interrupt bit*/
mmio_write_32(MBOX0_BASE + MBOX_IN_IRQ_OFS,
0x1);
ret = 0;
} else if (id == IPI_ID_SUSPEND) {
memcpy_from_sspm(data,
MBOX1_BASE + PINR_OFFSET_SUSPEND * 4,
len);
dsb();
/* clear interrupt bit*/
mmio_write_32(MBOX1_BASE + MBOX_IN_IRQ_OFS,
0x2);
ret = 0;
}
} else if (ret == 0) {
ret = -EBUSY;
}
return ret;
}
int sspm_alive_show(void)
{
uint32_t ipi_data, count;
int ret = 0;
count = 5;
ipi_data = 0xdead;
if (sspm_ipi_send_non_blocking(IPI_ID_PLATFORM, &ipi_data) != 0) {
ERROR("sspm init send fail! ret=%d\n", ret);
return -1;
}
while (sspm_ipi_recv_non_blocking(IPI_ID_PLATFORM,
&ipi_data,
sizeof(ipi_data) / sizeof(uint32_t))
&& count) {
mdelay(100);
count--;
}
return (ipi_data == 1) ? 0 : -1;
}
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SSPM_H__
#define __SSPM_H__
/* These should sync with sspm.bin */
#define IPI_ID_PLATFORM 0
#define IPI_ID_SUSPEND 6
#define PINR_OFFSET_PLATFORM 0
#define PINR_SIZE_PLATFORM 3
#define PINR_OFFSET_SUSPEND 2
#define PINR_SIZE_SUSPEND 8
#define MBOX0_BASE 0x10450000
#define MBOX1_BASE 0x10460000
#define MBOX3_BASE 0x10480000
#define MBOX_OUT_IRQ_OFS 0x1000
#define MBOX_IN_IRQ_OFS 0x1004
#define SHAREMBOX_OFFSET_MCDI 0
#define SHAREMBOX_SIZE_MCDI 20
#define SHAREMBOX_OFFSET_SUSPEND 26
#define SHAREMBOX_SIZE_SUSPEND 6
int sspm_mbox_read(uint32_t slot, uint32_t *data, uint32_t len);
int sspm_mbox_write(uint32_t slot, uint32_t *data, uint32_t len);
int sspm_ipi_send_non_blocking(uint32_t id, uint32_t *data);
int sspm_ipi_recv_non_blocking(uint32_t slot, uint32_t *data, uint32_t len);
int sspm_alive_show(void);
#endif /* __SSPM_H__ */
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <mcucfg.h>
#include <mt_timer.h>
#include <platform_def.h>
static void enable_systimer_compensation(void)
{
unsigned int reg;
reg = mmio_read_32(CNTCR_REG);
reg &= ~COMP_15_EN;
reg |= COMP_20_EN;
mmio_write_32(CNTCR_REG, reg);
NOTICE("[systimer] CNTCR_REG(0x%x)\n", mmio_read_32(CNTCR_REG));
}
void mt_systimer_init(void)
{
/* systimer is default on, so we only enable systimer compensation */
enable_systimer_compensation();
}
@@ -0,0 +1,20 @@
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MT_TIMER_H
#define MT_TIMER_H
#define SYSTIMER_BASE (0x10017000)
#define CNTCR_REG (SYSTIMER_BASE + 0x0)
#define CNTSR_REG (SYSTIMER_BASE + 0x4)
#define COMP_15_EN (1 << 10)
#define COMP_20_EN (1 << 11)
void mt_systimer_init(void);
#endif /* MT_TIMER_H */