Browse Source

Merge "feat(mt8188): add apu power on/off control" into integration

pull/1994/merge
Manish Pandey 2 years ago
committed by TrustedFirmware Code Review
parent
commit
c629e8d8a2
  1. 29
      plat/mediatek/drivers/apusys/apusys.c
  2. 6
      plat/mediatek/drivers/apusys/apusys.h
  3. 133
      plat/mediatek/drivers/apusys/mt8188/apusys_power.c
  4. 45
      plat/mediatek/drivers/apusys/mt8188/apusys_power.h
  5. 3
      plat/mediatek/mt8188/include/platform_def.h

29
plat/mediatek/drivers/apusys/apusys.c

@ -11,6 +11,35 @@
#include "apusys.h"
#include "apusys_power.h"
#include <lib/mtk_init/mtk_init.h>
#include <mtk_sip_svc.h>
static u_register_t apusys_kernel_handler(u_register_t x1,
u_register_t x2,
u_register_t x3,
u_register_t x4,
void *handle,
struct smccc_res *smccc_ret)
{
uint32_t request_ops;
int32_t ret = -1;
request_ops = (uint32_t)x1;
switch (request_ops) {
case MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_ON:
ret = apusys_kernel_apusys_pwr_top_on();
break;
case MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_OFF:
ret = apusys_kernel_apusys_pwr_top_off();
break;
default:
ERROR(MODULE_TAG "%s unknown request_ops = %x\n", MODULE_TAG, request_ops);
break;
}
return ret;
}
DECLARE_SMC_HANDLER(MTK_SIP_APUSYS_CONTROL, apusys_kernel_handler);
int apusys_init(void)
{

6
plat/mediatek/drivers/apusys/apusys.h

@ -9,4 +9,10 @@
#define MODULE_TAG "[APUSYS]"
enum MTK_APUSYS_KERNEL_OP {
MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_ON, /* 0 */
MTK_APUSYS_KERNEL_OP_APUSYS_PWR_TOP_OFF,/* 1 */
MTK_APUSYS_KERNEL_OP_NUM,
};
#endif

133
plat/mediatek/drivers/apusys/mt8188/apusys_power.c

@ -10,6 +10,7 @@
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <lib/spinlock.h>
#include <lib/utils_def.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
@ -18,6 +19,9 @@
#include "apusys_power.h"
#include <mtk_mmap_pool.h>
static spinlock_t apu_lock;
static bool apusys_top_on;
static int apu_poll(uintptr_t reg, uint32_t mask, uint32_t value, uint32_t timeout_us)
{
uint32_t reg_val, count;
@ -43,6 +47,135 @@ static int apu_poll(uintptr_t reg, uint32_t mask, uint32_t value, uint32_t timeo
return -1;
}
static void apu_xpu2apusys_d4_slv_en(enum APU_D4_SLV_CTRL en)
{
switch (en) {
case D4_SLV_OFF:
mmio_setbits_32(BCRM_FMEM_PDN_BASE + INFRA_FMEM_BUS_u_SI21_CTRL_0,
INFRA_FMEM_BUS_u_SI21_CTRL_EN);
mmio_setbits_32(BCRM_FMEM_PDN_BASE + INFRA_FMEM_BUS_u_SI22_CTRL_0,
INFRA_FMEM_BUS_u_SI22_CTRL_EN);
mmio_setbits_32(BCRM_FMEM_PDN_BASE + INFRA_FMEM_BUS_u_SI11_CTRL_0,
INFRA_FMEM_BUS_u_SI11_CTRL_EN);
mmio_setbits_32(BCRM_FMEM_PDN_BASE + INFRA_FMEM_M6M7_BUS_u_SI24_CTRL_0,
INFRA_FMEM_M6M7_BUS_u_SI24_CTRL_EN);
break;
case D4_SLV_ON:
mmio_clrbits_32(BCRM_FMEM_PDN_BASE + INFRA_FMEM_BUS_u_SI21_CTRL_0,
INFRA_FMEM_BUS_u_SI21_CTRL_EN);
mmio_clrbits_32(BCRM_FMEM_PDN_BASE + INFRA_FMEM_BUS_u_SI22_CTRL_0,
INFRA_FMEM_BUS_u_SI22_CTRL_EN);
mmio_clrbits_32(BCRM_FMEM_PDN_BASE + INFRA_FMEM_BUS_u_SI11_CTRL_0,
INFRA_FMEM_BUS_u_SI11_CTRL_EN);
mmio_clrbits_32(BCRM_FMEM_PDN_BASE + INFRA_FMEM_M6M7_BUS_u_SI24_CTRL_0,
INFRA_FMEM_M6M7_BUS_u_SI24_CTRL_EN);
break;
default:
ERROR(MODULE_TAG "%s invalid op: %d\n", __func__, en);
break;
}
}
static void apu_pwr_flow_remote_sync(uint32_t cfg)
{
mmio_write_32(APU_MBOX0_BASE + PWR_FLOW_SYNC_REG, (cfg & 0x1));
}
int apusys_kernel_apusys_pwr_top_on(void)
{
int ret;
spin_lock(&apu_lock);
if (apusys_top_on == true) {
INFO(MODULE_TAG "%s: APUSYS already powered on!\n", __func__);
spin_unlock(&apu_lock);
return 0;
}
apu_pwr_flow_remote_sync(1);
mmio_setbits_32(APU_RPC_BASE + APU_RPC_TOP_SEL_1, AFC_ENA);
mmio_write_32(APU_RPC_BASE + APU_RPC_TOP_CON, REG_WAKEUP_SET);
ret = apu_poll(APU_RPC_BASE + APU_RPC_INTF_PWR_RDY,
PWR_RDY, PWR_RDY, APU_TOP_ON_POLLING_TIMEOUT_US);
if (ret != 0) {
ERROR(MODULE_TAG "%s polling RPC RDY timeout, ret %d\n", __func__, ret);
spin_unlock(&apu_lock);
return ret;
}
ret = apu_poll(APU_RPC_BASE + APU_RPC_STATUS,
RPC_STATUS_RDY, RPC_STATUS_RDY, APU_TOP_ON_POLLING_TIMEOUT_US);
if (ret != 0) {
ERROR(MODULE_TAG "%s polling ARE FSM timeout, ret %d\n", __func__, ret);
spin_unlock(&apu_lock);
return ret;
}
mmio_write_32(APU_VCORE_BASE + APUSYS_VCORE_CG_CLR, CG_CLR);
mmio_write_32(APU_RCX_BASE + APU_RCX_CG_CLR, CG_CLR);
apu_xpu2apusys_d4_slv_en(D4_SLV_OFF);
apusys_top_on = true;
spin_unlock(&apu_lock);
return ret;
}
static void apu_sleep_rpc_rcx(void)
{
mmio_write_32(APU_RPC_BASE + APU_RPC_TOP_CON, REG_WAKEUP_CLR);
udelay(10);
mmio_setbits_32(APU_RPC_BASE + APU_RPC_TOP_SEL, (RPC_CTRL | RSV10));
udelay(10);
mmio_setbits_32(APU_RPC_BASE + APU_RPC_TOP_CON, CLR_IRQ);
udelay(10);
mmio_setbits_32(APU_RPC_BASE + APU_RPC_TOP_CON, SLEEP_REQ);
udelay(100);
}
int apusys_kernel_apusys_pwr_top_off(void)
{
int ret;
spin_lock(&apu_lock);
if (apusys_top_on == false) {
INFO(MODULE_TAG "%s: APUSYS already powered off!\n", __func__);
spin_unlock(&apu_lock);
return 0;
}
apu_xpu2apusys_d4_slv_en(D4_SLV_ON);
if (mmio_read_32(APU_MBOX0_BASE + PWR_FLOW_SYNC_REG) == 0) {
apu_pwr_flow_remote_sync(1);
} else {
apu_sleep_rpc_rcx();
}
ret = apu_poll(APU_RPC_BASE + APU_RPC_INTF_PWR_RDY,
PWR_RDY, PWR_OFF, APU_TOP_OFF_POLLING_TIMEOUT_US);
if (ret != 0) {
ERROR(MODULE_TAG "%s timeout to wait RPC sleep (val:%d), ret %d\n",
__func__, APU_TOP_OFF_POLLING_TIMEOUT_US, ret);
spin_unlock(&apu_lock);
return ret;
}
apusys_top_on = false;
spin_unlock(&apu_lock);
return ret;
}
static void get_pll_pcw(const uint32_t clk_rate, uint32_t *r1, uint32_t *r2)
{
unsigned int fvco = clk_rate;

45
plat/mediatek/drivers/apusys/mt8188/apusys_power.h

@ -24,6 +24,11 @@ enum APU_ARE_ID {
APU_ARE_NUM,
};
enum APU_D4_SLV_CTRL {
D4_SLV_OFF = 0,
D4_SLV_ON,
};
#define APU_POLL_STEP_US (5)
#define OUT_CLK_FREQ_MIN (1500)
@ -40,20 +45,26 @@ enum APU_ARE_ID {
#define APU_ARE_POLLING_TIMEOUT_US (10000)
/* APU related reg */
#define APU_VCORE_BASE (APU_RCX_VCORE_CONFIG)
#define APU_RCX_BASE (APU_RCX_CONFIG)
#define APU_RPC_BASE (APU_RPCTOP)
#define APU_PCU_BASE (APU_PCUTOP)
#define APU_ARE0_BASE (APU_ARETOP_ARE0)
#define APU_ARE1_BASE (APU_ARETOP_ARE1)
#define APU_ARE2_BASE (APU_ARETOP_ARE2)
#define APU_MBOX0_BASE (APU_MBOX0)
#define APU_AO_CTL_BASE (APU_AO_CTRL)
#define APU_PLL_BASE (APU_PLL)
#define APU_ACC_BASE (APU_ACC)
#define APU_ACX0_RPC_LITE_BASE (APU_ACX0_RPC_LITE)
/* RPC offset define */
#define APU_RPC_TOP_CON (0x0000)
#define APU_RPC_TOP_SEL (0x0004)
#define APU_RPC_STATUS (0x0014)
#define APU_RPC_TOP_SEL_1 (0x0018)
#define APU_RPC_HW_CON (0x001c)
#define APU_RPC_INTF_PWR_RDY (0x0044)
#define APU_RPC_SW_TYPE0 (0x0200)
/* RPC control */
@ -68,6 +79,15 @@ enum APU_ARE_ID {
#define RPC_CTRL (0x0000009e)
#define RPC_TOP_CTRL (0x0800501e)
#define RPC_TOP_CTRL1 BIT(20)
#define AFC_ENA BIT(16)
#define REG_WAKEUP_SET BIT(8)
#define REG_WAKEUP_CLR BIT(12)
#define PWR_RDY BIT(0)
#define PWR_OFF (0)
#define RPC_STATUS_RDY BIT(29)
#define RSV10 BIT(10)
#define CLR_IRQ (0x6)
#define SLEEP_REQ BIT(0)
/* PLL offset define */
#define PLL4H_PLL1_CON1 (0x000c)
@ -137,6 +157,12 @@ enum APU_ARE_ID {
#define ARE_ENTRY1_SRAM_L_INIT (0x76543210)
#define ARE_CONFG_INI BIT(2)
/* VCORE offset define */
#define APUSYS_VCORE_CG_CLR (0x0008)
/* RCX offset define */
#define APU_RCX_CG_CLR (0x0008)
/* SPM offset define */
#define APUSYS_BUCK_ISOLATION (0x03ec)
@ -149,6 +175,18 @@ enum APU_ARE_ID {
/* apu_rcx_ao_ctrl control */
#define VCORE_ARE_REQ BIT(2)
/* xpu2apusys */
#define INFRA_FMEM_BUS_u_SI21_CTRL_0 (0x002c)
#define INFRA_FMEM_BUS_u_SI22_CTRL_0 (0x0044)
#define INFRA_FMEM_BUS_u_SI11_CTRL_0 (0x0048)
#define INFRA_FMEM_M6M7_BUS_u_SI24_CTRL_0 (0x01d0)
/* xpu2apusys */
#define INFRA_FMEM_BUS_u_SI21_CTRL_EN BIT(12)
#define INFRA_FMEM_BUS_u_SI22_CTRL_EN BIT(13)
#define INFRA_FMEM_BUS_u_SI11_CTRL_EN BIT(11)
#define INFRA_FMEM_M6M7_BUS_u_SI24_CTRL_EN BIT(15)
/* PCU offset define */
#define APU_PCU_CTRL_SET (0x0000)
#define APU_PCU_BUCK_STEP_SEL (0x0030)
@ -188,6 +226,13 @@ enum APU_ARE_ID {
#define APU_RPC_SW_TYPE8 (0x0220)
#define APU_RPC_SW_TYPE9 (0x0224)
/* power flow sync */
#define PWR_FLOW_SYNC_REG (0x0440)
#define CG_CLR (0xffffffff)
int apusys_power_init(void);
int apusys_kernel_apusys_pwr_top_on(void);
int apusys_kernel_apusys_pwr_top_off(void);
#endif /* APUSYS_POWER_H */

3
plat/mediatek/mt8188/include/platform_def.h

@ -28,6 +28,9 @@
* APUSYS related constants
******************************************************************************/
#define BCRM_FMEM_PDN_BASE (IO_PHYS + 0x00276000)
#define APU_RCX_CONFIG (IO_PHYS + 0x09020000)
#define APU_RCX_VCORE_CONFIG (IO_PHYS + 0x090e0000)
#define APU_MBOX0 (IO_PHYS + 0x090e1000)
#define APU_RPCTOP (IO_PHYS + 0x090f0000)
#define APU_PCUTOP (IO_PHYS + 0x090f1000)
#define APU_AO_CTRL (IO_PHYS + 0x090f2000)

Loading…
Cancel
Save