Commit 3ea2cc00 authored by Sandrine Bailleux's avatar Sandrine Bailleux Committed by TrustedFirmware Code Review
Browse files

Merge changes I93ecff4d,I30dd9a95,I8207eea9,Id4197b07,Ib810125b, ... into integration

* changes:
  mediatek: mt8183: add MTK MCDI driver
  mediatek: mt8183: add MTK SSPM driver
  mediatek: mt8183: add MTK SPM driver
  mediatek: mt8183: add MTK uart driver for controlling clock gate
  mediatek: mt8183: configure MCUSYS DCM
  mediatek: mt8173: refactor RTC and PMIC drivers
Showing with 940 additions and 80 deletions
+940 -80
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __UART_H__
#define __UART_H__
#include <platform_def.h>
/* UART HW information */
#define HW_SUPPORT_UART_PORTS 2
#define DRV_SUPPORT_UART_PORTS 2
/* console UART clock cg */
#define UART_CLOCK_GATE_SET (INFRACFG_AO_BASE + 0x80)
#define UART_CLOCK_GATE_CLR (INFRACFG_AO_BASE + 0x84)
#define UART_CLOCK_GATE_STA (INFRACFG_AO_BASE + 0x90)
#define UART0_CLOCK_GATE_BIT (1U<<22)
#define UART1_CLOCK_GATE_BIT (1U<<23)
/* UART registers */
#define UART_RBR(_baseaddr) (_baseaddr + 0x0)
#define UART_THR(_baseaddr) (_baseaddr + 0x0)
#define UART_IER(_baseaddr) (_baseaddr + 0x4)
#define UART_IIR(_baseaddr) (_baseaddr + 0x8)
#define UART_FCR(_baseaddr) (_baseaddr + 0x8)
#define UART_LCR(_baseaddr) (_baseaddr + 0xc)
#define UART_MCR(_baseaddr) (_baseaddr + 0x10)
#define UART_LSR(_baseaddr) (_baseaddr + 0x14)
#define UART_MSR(_baseaddr) (_baseaddr + 0x18)
#define UART_SCR(_baseaddr) (_baseaddr + 0x1c)
#define UART_DLL(_baseaddr) (_baseaddr + 0x0)
#define UART_DLH(_baseaddr) (_baseaddr + 0x4)
#define UART_EFR(_baseaddr) (_baseaddr + 0x8)
#define UART_XON1(_baseaddr) (_baseaddr + 0x10)
#define UART_XON2(_baseaddr) (_baseaddr + 0x14)
#define UART_XOFF1(_baseaddr) (_baseaddr + 0x18)
#define UART_XOFF2(_baseaddr) (_baseaddr + 0x1c)
#define UART_AUTOBAUD(_baseaddr) (_baseaddr + 0x20)
#define UART_HIGHSPEED(_baseaddr) (_baseaddr + 0x24)
#define UART_SAMPLE_COUNT(_baseaddr) (_baseaddr + 0x28)
#define UART_SAMPLE_POINT(_baseaddr) (_baseaddr + 0x2c)
#define UART_AUTOBAUD_REG(_baseaddr) (_baseaddr + 0x30)
#define UART_RATE_FIX_REG(_baseaddr) (_baseaddr + 0x34)
#define UART_AUTO_BAUDSAMPLE(_baseaddr) (_baseaddr + 0x38)
#define UART_GUARD(_baseaddr) (_baseaddr + 0x3c)
#define UART_ESCAPE_DAT(_baseaddr) (_baseaddr + 0x40)
#define UART_ESCAPE_EN(_baseaddr) (_baseaddr + 0x44)
#define UART_SLEEP_EN(_baseaddr) (_baseaddr + 0x48)
#define UART_DMA_EN(_baseaddr) (_baseaddr + 0x4c)
#define UART_RXTRI_AD(_baseaddr) (_baseaddr + 0x50)
#define UART_FRACDIV_L(_baseaddr) (_baseaddr + 0x54)
#define UART_FRACDIV_M(_baseaddr) (_baseaddr + 0x58)
#define UART_FCR_RD(_baseaddr) (_baseaddr + 0x5C)
#define UART_USB_RX_SEL(_baseaddr) (_baseaddr + 0xB0)
#define UART_SLEEP_REQ(_baseaddr) (_baseaddr + 0xB4)
#define UART_SLEEP_ACK(_baseaddr) (_baseaddr + 0xB8)
#define UART_SPM_SEL(_baseaddr) (_baseaddr + 0xBC)
#define UART_LCR_DLAB 0x0080
#define UART_LCR_MODE_B 0x00bf
enum uart_port_ID {
UART_PORT0 = 0,
UART_PORT1
};
struct mt_uart_register {
unsigned int dll;
unsigned int dlh;
unsigned int ier;
unsigned int lcr;
unsigned int mcr;
unsigned int fcr;
unsigned int lsr;
unsigned int scr;
unsigned int efr;
unsigned int highspeed;
unsigned int sample_count;
unsigned int sample_point;
unsigned int fracdiv_l;
unsigned int fracdiv_m;
unsigned int escape_en;
unsigned int guard;
unsigned int rx_sel;
};
struct mt_uart {
unsigned long base;
struct mt_uart_register registers;
};
/* external API */
void mt_uart_save(void);
void mt_uart_restore(void);
void mt_console_uart_cg(int on);
int mt_console_uart_cg_status(void);
#endif /* __UART_H__ */
...@@ -28,51 +28,141 @@ struct mt8183_mcucfg_regs { ...@@ -28,51 +28,141 @@ struct mt8183_mcucfg_regs {
uint32_t mp0_rw_rsvd0; /* 0x6C */ uint32_t mp0_rw_rsvd0; /* 0x6C */
uint32_t mp0_rw_rsvd1; /* 0x70 */ uint32_t mp0_rw_rsvd1; /* 0x70 */
uint32_t mp0_ro_rsvd; /* 0x74 */ uint32_t mp0_ro_rsvd; /* 0x74 */
uint32_t reserved0_0[98]; /* 0x78 */ uint32_t reserved0_0; /* 0x78 */
uint32_t mp1_ca7l_cache_config; /* 0x200 */ uint32_t mp0_l2_cache_parity1_rdata; /* 0x7C */
uint32_t mp1_miscdbg; /* 0x204 */ uint32_t mp0_l2_cache_parity2_rdata; /* 0x80 */
uint32_t reserved0_1[9]; /* 0x208 */ uint32_t reserved0_1; /* 0x84 */
uint32_t mp1_axi_config; /* 0x22C */ uint32_t mp0_rgu_dcm_config; /* 0x88 */
uint32_t mp1_misc_config[10]; /* 0x230 */ uint32_t mp0_ca53_specific_ctrl; /* 0x8C */
uint32_t reserved0_2[3]; /* 0x258 */ uint32_t mp0_esr_case; /* 0x90 */
uint32_t mp1_ca7l_misc_config; /* 0x264 */ uint32_t mp0_esr_mask; /* 0x94 */
uint32_t reserved0_3[310]; /* 0x268 */ uint32_t mp0_esr_trig_en; /* 0x98 */
uint32_t reserved_0_2; /* 0x9C */
uint32_t mp0_ses_cg_en; /* 0xA0 */
uint32_t reserved0_3[216]; /* 0xA4 */
uint32_t mp_dbg_ctrl; /* 0x404 */
uint32_t reserved0_4[34]; /* 0x408 */
uint32_t mp_dfd_ctrl; /* 0x490 */
uint32_t dfd_cnt_l; /* 0x494 */
uint32_t dfd_cnt_h; /* 0x498 */
uint32_t misccfg_ro_rsvd; /* 0x49C */
uint32_t reserved0_5[24]; /* 0x4A0 */
uint32_t mp1_rst_status; /* 0x500 */
uint32_t mp1_dbg_ctrl; /* 0x504 */
uint32_t mp1_dbg_flag; /* 0x508 */
uint32_t mp1_ca7l_ir_mon; /* 0x50C */
uint32_t reserved0_6[32]; /* 0x510 */
uint32_t mcusys_dbg_mon_sel_a; /* 0x590 */
uint32_t mcucys_dbg_mon; /* 0x594 */
uint32_t misccfg_sec_voi_status0; /* 0x598 */
uint32_t misccfg_sec_vio_status1; /* 0x59C */
uint32_t reserved0_7[18]; /* 0x5A0 */
uint32_t gic500_int_mask; /* 0x5E8 */
uint32_t core_rst_en_latch; /* 0x5EC */
uint32_t reserved0_8[3]; /* 0x5F0 */
uint32_t dbg_core_ret; /* 0x5FC */
uint32_t mcusys_config_a; /* 0x600 */
uint32_t mcusys_config1_a; /* 0x604 */
uint32_t mcusys_gic_prebase_a; /* 0x608 */
uint32_t mcusys_pinmux; /* 0x60C */
uint32_t sec_range0_start; /* 0x610 */
uint32_t sec_range0_end; /* 0x614 */
uint32_t sec_range_enable; /* 0x618 */
uint32_t l2c_mm_base; /* 0x61C */
uint32_t reserved0_9[8]; /* 0x620 */
uint32_t aclken_div; /* 0x640 */
uint32_t pclken_div; /* 0x644 */
uint32_t l2c_sram_ctrl; /* 0x648 */
uint32_t armpll_jit_ctrl; /* 0x64C */
uint32_t cci_addrmap; /* 0x650 */
uint32_t cci_config; /* 0x654 */
uint32_t cci_periphbase; /* 0x658 */
uint32_t cci_nevntcntovfl; /* 0x65C */
uint32_t cci_clk_ctrl; /* 0x660 */
uint32_t cci_acel_s1_ctrl; /* 0x664 */
uint32_t mcusys_bus_fabric_dcm_ctrl; /* 0x668 */
uint32_t mcu_misc_dcm_ctrl; /* 0x66C */
uint32_t xgpt_ctl; /* 0x670 */
uint32_t xgpt_idx; /* 0x674 */
uint32_t reserved0_10[3]; /* 0x678 */
uint32_t mcusys_rw_rsvd0; /* 0x684 */
uint32_t mcusys_rw_rsvd1; /* 0x688 */
uint32_t reserved0_11[13]; /* 0x68C */
uint32_t gic_500_delsel_ctl; /* 0x6C0 */
uint32_t etb_delsel_ctl; /* 0x6C4 */
uint32_t etb_rst_ctl; /* 0x6C8 */
uint32_t reserved0_12[29]; /* 0x6CC */
uint32_t cci_adb400_dcm_config; /* 0x740 */ uint32_t cci_adb400_dcm_config; /* 0x740 */
uint32_t sync_dcm_config; /* 0x744 */ uint32_t sync_dcm_config; /* 0x744 */
uint32_t reserved0_4[16]; /* 0x748 */ uint32_t reserved0_13; /* 0x748 */
uint32_t mp0_cputop_spmc_ctl; /* 0x788 */ uint32_t sync_dcm_cluster_config; /* 0x74C */
uint32_t mp1_cputop_spmc_ctl; /* 0x78C */ uint32_t sw_udi; /* 0x750 */
uint32_t mp1_cputop_spmc_sram_ctl; /* 0x790 */ uint32_t reserved0_14; /* 0x754 */
uint32_t reserved0_5[23]; /* 0x794 */ uint32_t gic_sync_dcm; /* 0x758 */
uint32_t big_dbg_pwr_ctrl; /* 0x75C */
uint32_t gic_cpu_periphbase; /* 0x760 */
uint32_t axi_cpu_config; /* 0x764 */
uint32_t reserved0_15[2]; /* 0x768 */
uint32_t mcsib_sys_ctrl1; /* 0x770 */
uint32_t mcsib_sys_ctrl2; /* 0x774 */
uint32_t mcsib_sys_ctrl3; /* 0x778 */
uint32_t mcsib_sys_ctrl4; /* 0x77C */
uint32_t mcsib_dbg_ctrl1; /* 0x780 */
uint32_t pwrmcu_apb2to1; /* 0x784 */
uint32_t mp0_spmc; /* 0x788 */
uint32_t reserved0_16; /* 0x78C */
uint32_t mp0_spmc_sram_ctl; /* 0x790 */
uint32_t reserved0_17; /* 0x794 */
uint32_t mp0_sw_rst_wait_cycle; /* 0x798 */
uint32_t reserved0_18; /* 0x79C */
uint32_t mp0_pll_divider_cfg; /* 0x7A0 */
uint32_t reserved0_19; /* 0x7A4 */
uint32_t mp2_pll_divider_cfg; /* 0x7A8 */
uint32_t reserved0_20[5]; /* 0x7AC */
uint32_t bus_pll_divider_cfg; /* 0x7C0 */
uint32_t reserved0_21[7]; /* 0x7C4 */
uint32_t clusterid_aff1; /* 0x7E0 */
uint32_t clusterid_aff2; /* 0x7E4 */
uint32_t reserved0_22[2]; /* 0x7E8 */
uint32_t l2_cfg_mp0; /* 0x7F0 */ uint32_t l2_cfg_mp0; /* 0x7F0 */
uint32_t l2_cfg_mp1; /* 0x7F4 */ uint32_t l2_cfg_mp1; /* 0x7F4 */
uint32_t reserved0_6[1282]; /* 0x7F8 */ uint32_t reserved0_23[218]; /* 0x7F8 */
uint32_t mscib_dcm_en; /* 0xB60 */
uint32_t reserved0_24[1063]; /* 0xB64 */
uint32_t cpusys0_sparkvretcntrl; /* 0x1C00 */ uint32_t cpusys0_sparkvretcntrl; /* 0x1C00 */
uint32_t cpusys0_sparken; /* 0x1C04 */ uint32_t cpusys0_sparken; /* 0x1C04 */
uint32_t cpusys0_amuxsel; /* 0x1C08 */ uint32_t cpusys0_amuxsel; /* 0x1C08 */
uint32_t reserved0_7[9]; /* 0x1C0C */ uint32_t reserved0_25[9]; /* 0x1C0C */
uint32_t cpusys0_cpu0_spmc_ctl; /* 0x1C30 */ uint32_t cpusys0_cpu0_spmc_ctl; /* 0x1C30 */
uint32_t cpusys0_cpu1_spmc_ctl; /* 0x1C34 */ uint32_t cpusys0_cpu1_spmc_ctl; /* 0x1C34 */
uint32_t cpusys0_cpu2_spmc_ctl; /* 0x1C38 */ uint32_t cpusys0_cpu2_spmc_ctl; /* 0x1C38 */
uint32_t cpusys0_cpu3_spmc_ctl; /* 0x1C3C */ uint32_t cpusys0_cpu3_spmc_ctl; /* 0x1C3C */
uint32_t reserved0_8[370]; /* 0x1C40 */ uint32_t reserved0_26[8]; /* 0x1C40 */
uint32_t mp0_sync_dcm_cgavg_ctrl; /* 0x1C60 */
uint32_t mp0_sync_dcm_cgavg_fact; /* 0x1C64 */
uint32_t mp0_sync_dcm_cgavg_rfact; /* 0x1C68 */
uint32_t mp0_sync_dcm_cgavg; /* 0x1C6C */
uint32_t mp0_l2_parity_clr; /* 0x1C70 */
uint32_t reserved0_27[357]; /* 0x1C74 */
uint32_t mp2_cpucfg; /* 0x2208 */ uint32_t mp2_cpucfg; /* 0x2208 */
uint32_t mp2_axi_config; /* 0x220C */ uint32_t mp2_axi_config; /* 0x220C */
uint32_t reserved0_9[36]; /* 0x2210 */ uint32_t reserved0_28[25]; /* 0x2210 */
uint32_t mp2_cputop_spm_ctl; /* 0x22A0 */ uint32_t mp2_sync_dcm; /* 0x2274 */
uint32_t mp2_cputop_spm_sta; /* 0x22A4 */ uint32_t reserved0_29[10]; /* 0x2278 */
uint32_t reserved0_10[98]; /* 0x22A8 */ uint32_t ptp3_cputop_spmc0; /* 0x22A0 */
uint32_t cpusys2_cpu0_spmc_ctl; /* 0x2430 */ uint32_t ptp3_cputop_spmc1; /* 0x22A4 */
uint32_t cpusys2_cpu0_spmc_sta; /* 0x2434 */ uint32_t reserved0_30[98]; /* 0x22A8 */
uint32_t cpusys2_cpu1_spmc_ctl; /* 0x2438 */ uint32_t ptp3_cpu0_spmc0; /* 0x2430 */
uint32_t cpusys2_cpu1_spmc_sta; /* 0x243C */ uint32_t ptp3_cpu0_spmc1; /* 0x2434 */
uint32_t reserved0_11[176]; /* 0x2440 */ uint32_t ptp3_cpu1_spmc0; /* 0x2438 */
uint32_t ptp3_cpu1_spmc1; /* 0x243C */
uint32_t ptp3_cpu2_spmc0; /* 0x2440 */
uint32_t ptp3_cpu2_spmc1; /* 0x2444 */
uint32_t ptp3_cpu3_spmc0; /* 0x2448 */
uint32_t ptp3_cpu3_spmc1; /* 0x244C */
uint32_t ptp3_cpux_spmc; /* 0x2450 */
uint32_t reserved0_31[171]; /* 0x2454 */
uint32_t spark2ld0; /* 0x2700 */ uint32_t spark2ld0; /* 0x2700 */
uint32_t reserved0_12[1355]; /* 0x2704 */
uint32_t cpusys1_cpu0_spmc_ctl; /* 0x3C30 */
uint32_t cpusys1_cpu1_spmc_ctl; /* 0x3C34 */
uint32_t cpusys1_cpu2_spmc_ctl; /* 0x3C38 */
uint32_t cpusys1_cpu3_spmc_ctl; /* 0x3C3C */
}; };
static struct mt8183_mcucfg_regs *const mt8183_mcucfg = (void *)MCUCFG_BASE; static struct mt8183_mcucfg_regs *const mt8183_mcucfg = (void *)MCUCFG_BASE;
...@@ -244,4 +334,235 @@ enum { ...@@ -244,4 +334,235 @@ enum {
MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT MP1_L2RSTDISABLE = 1 << MP1_L2RSTDISABLE_SHIFT
}; };
/* bus pll divider dcm related */
enum {
BUS_PLLDIVIDER_DCM_DBC_CNT_0_SHIFT = 11,
BUS_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
BUS_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
BUS_PLLDIV_DCM = (1 << BUS_PLLDIVIDER_DCM_DBC_CNT_0_SHIFT) |
(1 << BUS_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
(1 << BUS_PLLDIV_ARMWFE_DCM_EN_SHIFT)
};
/* mp0 pll divider dcm related */
enum {
MP0_PLLDIV_DCM_DBC_CNT_0_SHIFT = 11,
MP0_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
MP0_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
MP0_PLLDIV_LASTCORE_IDLE_EN_SHIFT = 31,
MP0_PLLDIV_DCM = (1 << MP0_PLLDIV_DCM_DBC_CNT_0_SHIFT) |
(1 << MP0_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
(1 << MP0_PLLDIV_ARMWFE_DCM_EN_SHIFT) |
(1u << MP0_PLLDIV_LASTCORE_IDLE_EN_SHIFT)
};
/* mp2 pll divider dcm related */
enum {
MP2_PLLDIV_DCM_DBC_CNT_0_SHIFT = 11,
MP2_PLLDIV_ARMWFI_DCM_EN_SHIFT = 24,
MP2_PLLDIV_ARMWFE_DCM_EN_SHIFT = 25,
MP2_PLLDIV_LASTCORE_IDLE_EN_SHIFT = 31,
MP2_PLLDIV_DCM = (1 << MP2_PLLDIV_DCM_DBC_CNT_0_SHIFT) |
(1 << MP2_PLLDIV_ARMWFI_DCM_EN_SHIFT) |
(1 << MP2_PLLDIV_ARMWFE_DCM_EN_SHIFT) |
(1u << MP2_PLLDIV_LASTCORE_IDLE_EN_SHIFT)
};
/* mcsib dcm related */
enum {
MCSIB_CACTIVE_SEL_SHIFT = 0,
MCSIB_DCM_EN_SHIFT = 16,
MCSIB_CACTIVE_SEL_MASK = 0xffff << MCSIB_CACTIVE_SEL_SHIFT,
MCSIB_CACTIVE_SEL = 0xffff << MCSIB_CACTIVE_SEL_SHIFT,
MCSIB_DCM_MASK = 0xffffu << MCSIB_DCM_EN_SHIFT,
MCSIB_DCM = 0xffffu << MCSIB_DCM_EN_SHIFT,
};
/* cci adb400 dcm related */
enum {
CCI_M0_ADB400_DCM_EN_SHIFT = 0,
CCI_M1_ADB400_DCM_EN_SHIFT = 1,
CCI_M2_ADB400_DCM_EN_SHIFT = 2,
CCI_S2_ADB400_DCM_EN_SHIFT = 3,
CCI_S3_ADB400_DCM_EN_SHIFT = 4,
CCI_S4_ADB400_DCM_EN_SHIFT = 5,
CCI_S5_ADB400_DCM_EN_SHIFT = 6,
ACP_S3_ADB400_DCM_EN_SHIFT = 11,
CCI_ADB400_DCM_MASK = (1 << CCI_M0_ADB400_DCM_EN_SHIFT) |
(1 << CCI_M1_ADB400_DCM_EN_SHIFT) |
(1 << CCI_M2_ADB400_DCM_EN_SHIFT) |
(1 << CCI_S2_ADB400_DCM_EN_SHIFT) |
(1 << CCI_S4_ADB400_DCM_EN_SHIFT) |
(1 << CCI_S4_ADB400_DCM_EN_SHIFT) |
(1 << CCI_S5_ADB400_DCM_EN_SHIFT) |
(1 << ACP_S3_ADB400_DCM_EN_SHIFT),
CCI_ADB400_DCM = (1 << CCI_M0_ADB400_DCM_EN_SHIFT) |
(1 << CCI_M1_ADB400_DCM_EN_SHIFT) |
(1 << CCI_M2_ADB400_DCM_EN_SHIFT) |
(0 << CCI_S2_ADB400_DCM_EN_SHIFT) |
(0 << CCI_S4_ADB400_DCM_EN_SHIFT) |
(0 << CCI_S4_ADB400_DCM_EN_SHIFT) |
(0 << CCI_S5_ADB400_DCM_EN_SHIFT) |
(1 << ACP_S3_ADB400_DCM_EN_SHIFT)
};
/* sync dcm related */
enum {
CCI_SYNC_DCM_DIV_EN_SHIFT = 0,
CCI_SYNC_DCM_UPDATE_TOG_SHIFT = 1,
CCI_SYNC_DCM_DIV_SEL_SHIFT = 2,
MP0_SYNC_DCM_DIV_EN_SHIFT = 10,
MP0_SYNC_DCM_UPDATE_TOG_SHIFT = 11,
MP0_SYNC_DCM_DIV_SEL_SHIFT = 12,
SYNC_DCM_MASK = (1 << CCI_SYNC_DCM_DIV_EN_SHIFT) |
(1 << CCI_SYNC_DCM_UPDATE_TOG_SHIFT) |
(0x7f << CCI_SYNC_DCM_DIV_SEL_SHIFT) |
(1 << MP0_SYNC_DCM_DIV_EN_SHIFT) |
(1 << MP0_SYNC_DCM_UPDATE_TOG_SHIFT) |
(0x7f << MP0_SYNC_DCM_DIV_SEL_SHIFT),
SYNC_DCM = (1 << CCI_SYNC_DCM_DIV_EN_SHIFT) |
(1 << CCI_SYNC_DCM_UPDATE_TOG_SHIFT) |
(0 << CCI_SYNC_DCM_DIV_SEL_SHIFT) |
(1 << MP0_SYNC_DCM_DIV_EN_SHIFT) |
(1 << MP0_SYNC_DCM_UPDATE_TOG_SHIFT) |
(0 << MP0_SYNC_DCM_DIV_SEL_SHIFT)
};
/* mcu bus dcm related */
enum {
MCU_BUS_DCM_EN_SHIFT = 8,
MCU_BUS_DCM = 1 << MCU_BUS_DCM_EN_SHIFT
};
/* mcusys bus fabric dcm related */
enum {
ACLK_INFRA_DYNAMIC_CG_EN_SHIFT = 0,
EMI2_ADB400_S_DCM_CTRL_SHIFT = 1,
ACLK_GPU_DYNAMIC_CG_EN_SHIFT = 2,
ACLK_PSYS_DYNAMIC_CG_EN_SHIFT = 3,
MP0_ADB400_S_DCM_CTRL_SHIFT = 4,
MP0_ADB400_M_DCM_CTRL_SHIFT = 5,
MP1_ADB400_S_DCM_CTRL_SHIFT = 6,
MP1_ADB400_M_DCM_CTRL_SHIFT = 7,
EMICLK_EMI_DYNAMIC_CG_EN_SHIFT = 8,
INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT = 9,
EMICLK_GPU_DYNAMIC_CG_EN_SHIFT = 10,
INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT = 11,
EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT = 12,
EMI1_ADB400_S_DCM_CTRL_SHIFT = 16,
MP2_ADB400_M_DCM_CTRL_SHIFT = 17,
MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT = 18,
MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT = 19,
MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT = 20,
L2_SHARE_ADB400_DCM_CTRL_SHIFT = 21,
MP1_AGGRESS_DCM_CTRL_SHIFT = 22,
MP0_AGGRESS_DCM_CTRL_SHIFT = 23,
MP0_ADB400_ACP_S_DCM_CTRL_SHIFT = 24,
MP0_ADB400_ACP_M_DCM_CTRL_SHIFT = 25,
MP1_ADB400_ACP_S_DCM_CTRL_SHIFT = 26,
MP1_ADB400_ACP_M_DCM_CTRL_SHIFT = 27,
MP3_ADB400_M_DCM_CTRL_SHIFT = 28,
MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT = 29,
MCUSYS_BUS_FABRIC_DCM_MASK = (1 << ACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
(1 << EMI2_ADB400_S_DCM_CTRL_SHIFT) |
(1 << ACLK_GPU_DYNAMIC_CG_EN_SHIFT) |
(1 << ACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
(1 << MP0_ADB400_S_DCM_CTRL_SHIFT) |
(1 << MP0_ADB400_M_DCM_CTRL_SHIFT) |
(1 << MP1_ADB400_S_DCM_CTRL_SHIFT) |
(1 << MP1_ADB400_M_DCM_CTRL_SHIFT) |
(1 << EMICLK_EMI_DYNAMIC_CG_EN_SHIFT) |
(1 << INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
(1 << EMICLK_GPU_DYNAMIC_CG_EN_SHIFT) |
(1 << INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
(1 << EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT) |
(1 << EMI1_ADB400_S_DCM_CTRL_SHIFT) |
(1 << MP2_ADB400_M_DCM_CTRL_SHIFT) |
(1 << MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
(1 << MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
(1 << MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
(1 << L2_SHARE_ADB400_DCM_CTRL_SHIFT) |
(1 << MP1_AGGRESS_DCM_CTRL_SHIFT) |
(1 << MP0_AGGRESS_DCM_CTRL_SHIFT) |
(1 << MP0_ADB400_ACP_S_DCM_CTRL_SHIFT) |
(1 << MP0_ADB400_ACP_M_DCM_CTRL_SHIFT) |
(1 << MP1_ADB400_ACP_S_DCM_CTRL_SHIFT) |
(1 << MP1_ADB400_ACP_M_DCM_CTRL_SHIFT) |
(1 << MP3_ADB400_M_DCM_CTRL_SHIFT) |
(1 << MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT),
MCUSYS_BUS_FABRIC_DCM = (1 << ACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
(1 << EMI2_ADB400_S_DCM_CTRL_SHIFT) |
(1 << ACLK_GPU_DYNAMIC_CG_EN_SHIFT) |
(1 << ACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
(0 << MP0_ADB400_S_DCM_CTRL_SHIFT) |
(0 << MP0_ADB400_M_DCM_CTRL_SHIFT) |
(1 << MP1_ADB400_S_DCM_CTRL_SHIFT) |
(1 << MP1_ADB400_M_DCM_CTRL_SHIFT) |
(1 << EMICLK_EMI_DYNAMIC_CG_EN_SHIFT) |
(1 << INFRACLK_INFRA_DYNAMIC_CG_EN_SHIFT) |
(1 << EMICLK_GPU_DYNAMIC_CG_EN_SHIFT) |
(1 << INFRACLK_PSYS_DYNAMIC_CG_EN_SHIFT) |
(1 << EMICLK_EMI1_DYNAMIC_CG_EN_SHIFT) |
(1 << EMI1_ADB400_S_DCM_CTRL_SHIFT) |
(0 << MP2_ADB400_M_DCM_CTRL_SHIFT) |
(1 << MP0_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
(1 << MP1_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
(1 << MP2_ICC_AXI_STREAM_ARCH_CG_SHIFT) |
(1 << L2_SHARE_ADB400_DCM_CTRL_SHIFT) |
(1 << MP1_AGGRESS_DCM_CTRL_SHIFT) |
(1 << MP0_AGGRESS_DCM_CTRL_SHIFT) |
(1 << MP0_ADB400_ACP_S_DCM_CTRL_SHIFT) |
(1 << MP0_ADB400_ACP_M_DCM_CTRL_SHIFT) |
(1 << MP1_ADB400_ACP_S_DCM_CTRL_SHIFT) |
(1 << MP1_ADB400_ACP_M_DCM_CTRL_SHIFT) |
(1 << MP3_ADB400_M_DCM_CTRL_SHIFT) |
(1 << MP3_ICC_AXI_STREAM_ARCH_CG_SHIFT)
};
/* l2c_sram dcm related */
enum {
L2C_SRAM_DCM_EN_SHIFT = 0,
L2C_SRAM_DCM = 1 << L2C_SRAM_DCM_EN_SHIFT
};
/* mcu misc dcm related */
enum {
MP0_CNTVALUEB_DCM_EN_SHIFT = 0,
MP_CNTVALUEB_DCM_EN = 8,
CNTVALUEB_DCM = (1 << MP0_CNTVALUEB_DCM_EN_SHIFT) |
(1 << MP_CNTVALUEB_DCM_EN)
};
/* sync dcm cluster config related */
enum {
MP0_SYNC_DCM_STALL_WR_EN_SHIFT = 7,
MCUSYS_MAX_ACCESS_LATENCY_SHIFT = 24,
MCU0_SYNC_DCM_STALL_WR_EN = 1 << MP0_SYNC_DCM_STALL_WR_EN_SHIFT,
MCUSYS_MAX_ACCESS_LATENCY_MASK = 0xf << MCUSYS_MAX_ACCESS_LATENCY_SHIFT,
MCUSYS_MAX_ACCESS_LATENCY = 0x5 << MCUSYS_MAX_ACCESS_LATENCY_SHIFT
};
/* cpusys rgu dcm related */
enum {
CPUSYS_RGU_DCM_CONFIG_SHIFT = 0,
CPUSYS_RGU_DCM_CINFIG = 1 << CPUSYS_RGU_DCM_CONFIG_SHIFT
};
/* mp2 sync dcm related */
enum {
MP2_DCM_EN_SHIFT = 0,
MP2_DCM_EN = 1 << MP2_DCM_EN_SHIFT
};
#endif /* MT8183_MCUCFG_H */ #endif /* MT8183_MCUCFG_H */
...@@ -24,8 +24,6 @@ ...@@ -24,8 +24,6 @@
#define BIT_CA15M_L2PARITY_EN (1 << 1) #define BIT_CA15M_L2PARITY_EN (1 << 1)
#define BIT_CA15M_LASTPC_DIS (1 << 8) #define BIT_CA15M_LASTPC_DIS (1 << 8)
#define MP1_CPUTOP_PWR_CON 0x10006218
#define MCU_ALL_PWR_ON_CTRL 0x0c530b58 #define MCU_ALL_PWR_ON_CTRL 0x0c530b58
#define PLAT_MTK_CIRCULAR_BUFFER_UNLOCK 0xefab4133 #define PLAT_MTK_CIRCULAR_BUFFER_UNLOCK 0xefab4133
#define PLAT_MTK_CIRCULAR_BUFFER_LOCK 0xefab4134 #define PLAT_MTK_CIRCULAR_BUFFER_LOCK 0xefab4134
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#define APMIXEDSYS (IO_PHYS + 0xC000) #define APMIXEDSYS (IO_PHYS + 0xC000)
#define ARMPLL_LL_CON0 (APMIXEDSYS + 0x200) #define ARMPLL_LL_CON0 (APMIXEDSYS + 0x200)
#define ARMPLL_L_CON0 (APMIXEDSYS + 0x210) #define ARMPLL_L_CON0 (APMIXEDSYS + 0x210)
#define ARMPLL_L_PWR_CON0 (APMIXEDSYS + 0x21c)
#define MAINPLL_CON0 (APMIXEDSYS + 0x220) #define MAINPLL_CON0 (APMIXEDSYS + 0x220)
#define CCIPLL_CON0 (APMIXEDSYS + 0x290) #define CCIPLL_CON0 (APMIXEDSYS + 0x290)
...@@ -74,6 +75,7 @@ ...@@ -74,6 +75,7 @@
#define MT_L2_WRITE_ACCESS_RATE (MCUCFG_BASE + 0x604) #define MT_L2_WRITE_ACCESS_RATE (MCUCFG_BASE + 0x604)
#define MP0_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f0) #define MP0_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f0)
#define MP1_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f4) #define MP1_CA7L_CACHE_CONFIG (MCUCFG_BASE + 0x7f4)
#define EMI_WFIFO (MCUCFG_BASE + 0x0b5c)
/******************************************************************************* /*******************************************************************************
* GIC related constants * GIC related constants
...@@ -87,6 +89,7 @@ ...@@ -87,6 +89,7 @@
* UART related constants * UART related constants
******************************************************************************/ ******************************************************************************/
#define UART0_BASE (IO_PHYS + 0x01002000) #define UART0_BASE (IO_PHYS + 0x01002000)
#define UART1_BASE (IO_PHYS + 0x01003000)
#define UART_BAUDRATE 115200 #define UART_BAUDRATE 115200
#define UART_CLOCK 26000000 #define UART_CLOCK 26000000
......
/*
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __SSPM_REG_H__
#define __SSPM_REG_H__
#include "platform_def.h"
#define SSPM_CFGREG_RSV_RW_REG0 (SSPM_CFGREG_BASE + 0x0100)
#define SSPM_CFGREG_ACAO_INT_SET (SSPM_CFGREG_BASE + 0x00D8)
#define SSPM_CFGREG_ACAO_INT_CLR (SSPM_CFGREG_BASE + 0x00DC)
#define SSPM_CFGREG_ACAO_WAKEUP_EN (SSPM_CFGREG_BASE + 0x0204)
#define STANDBYWFI_EN(n) (1 << (n + 8))
#define GIC_IRQOUT_EN(n) (1 << (n + 0))
#define NF_MCDI_MBOX 19
#define MCDI_MBOX_CLUSTER_0_CAN_POWER_OFF 0
#define MCDI_MBOX_CLUSTER_1_CAN_POWER_OFF 1
#define MCDI_MBOX_BUCK_POWER_OFF_MASK 2
#define MCDI_MBOX_CLUSTER_0_ATF_ACTION_DONE 3
#define MCDI_MBOX_CLUSTER_1_ATF_ACTION_DONE 4
#define MCDI_MBOX_BOOTADDR 5
#define MCDI_MBOX_PAUSE_ACTION 6
#define MCDI_MBOX_AVAIL_CPU_MASK 7
#define MCDI_MBOX_CPU_CLUSTER_PWR_STAT 8
#define MCDI_MBOX_ACTION_STAT 9
#define MCDI_MBOX_CLUSTER_0_CNT 10
#define MCDI_MBOX_CLUSTER_1_CNT 11
#define MCDI_MBOX_CPU_ISOLATION_MASK 12
#define MCDI_MBOX_PAUSE_ACK 13
#define MCDI_MBOX_PENDING_ON_EVENT 14
#define MCDI_MBOX_PROF_CMD 15
#define MCDI_MBOX_DRCC_CALI_DONE 16
#define MCDI_MBOX_HP_CMD 17
#define MCDI_MBOX_HP_ACK 18
#endif /* __SSPM_REG_H__ */
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <lib/mmio.h> #include <lib/mmio.h>
#include <plat_debug.h> #include <plat_debug.h>
#include <platform_def.h> #include <platform_def.h>
#include <spm.h>
void circular_buffer_setup(void) void circular_buffer_setup(void)
{ {
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <platform_def.h> #include <platform_def.h>
#include <scu.h> #include <scu.h>
#include <mt_gic_v3.h> #include <mt_gic_v3.h>
#include <mtk_mcdi.h>
#include <mtk_plat_common.h> #include <mtk_plat_common.h>
#include <mtgpio.h> #include <mtgpio.h>
#include <mtspmc.h> #include <mtspmc.h>
...@@ -25,9 +26,103 @@ ...@@ -25,9 +26,103 @@
#include <plat_private.h> #include <plat_private.h>
#include <power_tracer.h> #include <power_tracer.h>
#include <pmic.h> #include <pmic.h>
#include <spm.h>
#include <spm_suspend.h>
#include <sspm.h>
#include <rtc.h> #include <rtc.h>
#define MTK_LOCAL_STATE_OFF 2 /* Local power state for power domains in Run state. */
#define MTK_LOCAL_STATE_RUN 0
/* Local power state for retention. */
#define MTK_LOCAL_STATE_RET 1
/* Local power state for OFF/power-down. */
#define MTK_LOCAL_STATE_OFF 2
#if PSCI_EXTENDED_STATE_ID
/*
* Macros used to parse state information from State-ID if it is using the
* recommended encoding for State-ID.
*/
#define MTK_LOCAL_PSTATE_WIDTH 4
#define MTK_LOCAL_PSTATE_MASK ((1 << MTK_LOCAL_PSTATE_WIDTH) - 1)
/* Macros to construct the composite power state */
/* Make composite power state parameter till power level 0 */
#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
(((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT))
#else /* !PSCI_EXTENDED_STATE_ID */
#define mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \
(((lvl0_state) << PSTATE_ID_SHIFT) | \
((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \
((type) << PSTATE_TYPE_SHIFT))
#endif /* PSCI_EXTENDED_STATE_ID */
/* Make composite power state parameter till power level 1 */
#define mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \
(((lvl1_state) << MTK_LOCAL_PSTATE_WIDTH) | \
mtk_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type))
/* Make composite power state parameter till power level 2 */
#define mtk_make_pwrstate_lvl2( \
lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \
(((lvl2_state) << (MTK_LOCAL_PSTATE_WIDTH * 2)) | \
mtk_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type))
#define MTK_PWR_LVL0 0
#define MTK_PWR_LVL1 1
#define MTK_PWR_LVL2 2
/* Macros to read the MTK power domain state */
#define MTK_CORE_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL0]
#define MTK_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[MTK_PWR_LVL1]
#define MTK_SYSTEM_PWR_STATE(state) ((PLAT_MAX_PWR_LVL > MTK_PWR_LVL1) ? \
(state)->pwr_domain_state[MTK_PWR_LVL2] : 0)
#if PSCI_EXTENDED_STATE_ID
/*
* The table storing the valid idle power states. Ensure that the
* array entries are populated in ascending order of state-id to
* enable us to use binary search during power state validation.
* The table must be terminated by a NULL entry.
*/
const unsigned int mtk_pm_idle_states[] = {
/* State-id - 0x001 */
mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
MTK_LOCAL_STATE_RET, MTK_PWR_LVL0, PSTATE_TYPE_STANDBY),
/* State-id - 0x002 */
mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_RUN,
MTK_LOCAL_STATE_OFF, MTK_PWR_LVL0, PSTATE_TYPE_POWERDOWN),
/* State-id - 0x022 */
mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_RUN, MTK_LOCAL_STATE_OFF,
MTK_LOCAL_STATE_OFF, MTK_PWR_LVL1, PSTATE_TYPE_POWERDOWN),
#if PLAT_MAX_PWR_LVL > MTK_PWR_LVL1
/* State-id - 0x222 */
mtk_make_pwrstate_lvl2(MTK_LOCAL_STATE_OFF, MTK_LOCAL_STATE_OFF,
MTK_LOCAL_STATE_OFF, MTK_PWR_LVL2, PSTATE_TYPE_POWERDOWN),
#endif
0,
};
#endif
#define CPU_IDX(cluster, cpu) ((cluster << 2) + cpu)
#define ON true
#define OFF false
/* Pause MCDI when CPU hotplug */
static bool HP_SSPM_PAUSE;
/* CPU Hotplug by SSPM */
static bool HP_SSPM_CTRL = true;
/* Turn off cluster when CPU hotplug off */
static bool HP_CLUSTER_OFF = true;
/* Turn off cluster when CPU MCDI off */
static bool MCDI_C2 = true;
/* Enable MCDI */
static bool MCDI_SSPM = true;
static uintptr_t secure_entrypoint; static uintptr_t secure_entrypoint;
...@@ -38,30 +133,171 @@ static void mp1_L2_desel_config(void) ...@@ -38,30 +133,171 @@ static void mp1_L2_desel_config(void)
dsb(); dsb();
} }
static bool clst_single_pwr(int cluster, int cpu)
{
uint32_t cpu_mask[2] = {0x00001e00, 0x000f0000};
uint32_t cpu_pwr_bit[] = {9, 10, 11, 12, 16, 17, 18, 19};
int my_idx = (cluster << 2) + cpu;
uint32_t pwr_stat = mmio_read_32(0x10006180);
return !(pwr_stat & (cpu_mask[cluster] & ~BIT(cpu_pwr_bit[my_idx])));
}
static bool clst_single_on(int cluster, int cpu)
{
uint32_t cpu_mask[2] = {0x0f, 0xf0};
int my_idx = (cluster << 2) + cpu;
uint32_t on_stat = mcdi_avail_cpu_mask_read();
return !(on_stat & (cpu_mask[cluster] & ~BIT(my_idx)));
}
static void plat_cluster_pwrdwn_common(uint64_t mpidr, int cluster)
{
if (cluster > 0)
mt_gic_sync_dcm_enable();
/* Disable coherency */
plat_mtk_cci_disable();
disable_scu(mpidr);
}
static void plat_cluster_pwron_common(uint64_t mpidr, int cluster)
{
if (cluster > 0) {
l2c_parity_check_setup();
circular_buffer_setup();
mp1_L2_desel_config();
mt_gic_sync_dcm_disable();
}
/* Enable coherency */
enable_scu(mpidr);
plat_mtk_cci_enable();
/* Enable big core dcm */
plat_dcm_restore_cluster_on(mpidr);
/* Enable rgu dcm */
plat_dcm_rgu_enable();
}
static void plat_cpu_standby(plat_local_state_t cpu_state)
{
unsigned int scr;
scr = read_scr_el3();
write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
isb();
dsb();
wfi();
write_scr_el3(scr);
}
static void mcdi_ctrl_before_hotplug_on(int cluster, int cpu)
{
if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM) {
mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), OFF);
mcdi_pause_set(cluster, CPU_IDX(cluster, cpu), ON);
}
}
static void mcdi_ctrl_before_hotplug_off(int cluster, int cpu, bool cluster_off)
{
if (!HP_SSPM_CTRL && HP_SSPM_PAUSE && MCDI_SSPM)
mcdi_pause_set(cluster_off ? cluster : -1,
CPU_IDX(cluster, cpu), OFF);
}
static void mcdi_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off)
{
if (MCDI_SSPM) {
sspm_set_bootaddr(secure_entrypoint);
sspm_standbywfi_irq_enable(CPU_IDX(cluster, cpu));
if (cluster_off)
sspm_cluster_pwr_off_notify(cluster);
else
sspm_cluster_pwr_on_notify(cluster);
}
}
static void mcdi_ctrl_suspend(void)
{
if (MCDI_SSPM)
mcdi_pause();
}
static void mcdi_ctrl_resume(void)
{
if (MCDI_SSPM)
mcdi_unpause();
}
static void hotplug_ctrl_cluster_on(int cluster, int cpu)
{
if (HP_SSPM_CTRL && MCDI_SSPM) {
mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), OFF);
mcdi_hotplug_set(cluster, -1, ON);
mcdi_hotplug_wait_ack(cluster, -1, ON);
} else {
/* power on cluster */
if (!spm_get_cluster_powerstate(cluster))
spm_poweron_cluster(cluster);
}
}
static void hotplug_ctrl_cpu_on(int cluster, int cpu)
{
if (HP_SSPM_CTRL && MCDI_SSPM)
mcdi_hotplug_set(cluster, CPU_IDX(cluster, cpu), ON);
else
spm_poweron_cpu(cluster, cpu);
}
static void hotplug_ctrl_cpu_on_finish(int cluster, int cpu)
{
spm_disable_cpu_auto_off(cluster, cpu);
if (HP_SSPM_CTRL && MCDI_SSPM)
mcdi_hotplug_clr(cluster, CPU_IDX(cluster, cpu), ON);
else if (HP_SSPM_PAUSE && MCDI_SSPM)
mcdi_pause_clr(cluster, CPU_IDX(cluster, cpu), ON);
mcdi_avail_cpu_mask_set(BIT(CPU_IDX(cluster, cpu)));
}
static void hotplug_ctrl_cluster_cpu_off(int cluster, int cpu, bool cluster_off)
{
mcdi_avail_cpu_mask_clr(BIT(CPU_IDX(cluster, cpu)));
if (HP_SSPM_CTRL && MCDI_SSPM) {
mcdi_hotplug_set(cluster_off ? cluster : -1,
CPU_IDX(cluster, cpu), OFF);
} else {
spm_enable_cpu_auto_off(cluster, cpu);
if (cluster_off)
spm_enable_cluster_auto_off(cluster);
spm_set_cpu_power_off(cluster, cpu);
}
}
static int plat_mtk_power_domain_on(unsigned long mpidr) static int plat_mtk_power_domain_on(unsigned long mpidr)
{ {
int cpu = MPIDR_AFFLVL0_VAL(mpidr); int cpu = MPIDR_AFFLVL0_VAL(mpidr);
int cluster = MPIDR_AFFLVL1_VAL(mpidr); int cluster = MPIDR_AFFLVL1_VAL(mpidr);
INFO("%s():%d: mpidr: %lx, c.c: %d.%d\n", mcdi_ctrl_before_hotplug_on(cluster, cpu);
__func__, __LINE__, mpidr, cluster, cpu); hotplug_ctrl_cluster_on(cluster, cpu);
/* power on cluster */
if (!spm_get_cluster_powerstate(cluster)) {
spm_poweron_cluster(cluster);
if (cluster == 1) {
l2c_parity_check_setup();
circular_buffer_setup();
mp1_L2_desel_config();
mt_gic_sync_dcm_disable();
}
}
/* init cpu reset arch as AARCH64 */ /* init cpu reset arch as AARCH64 */
mcucfg_init_archstate(cluster, cpu, 1); mcucfg_init_archstate(cluster, cpu, 1);
mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint); mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
spm_poweron_cpu(cluster, cpu); hotplug_ctrl_cpu_on(cluster, cpu);
return PSCI_E_SUCCESS; return PSCI_E_SUCCESS;
} }
...@@ -71,53 +307,189 @@ static void plat_mtk_power_domain_off(const psci_power_state_t *state) ...@@ -71,53 +307,189 @@ static void plat_mtk_power_domain_off(const psci_power_state_t *state)
uint64_t mpidr = read_mpidr(); uint64_t mpidr = read_mpidr();
int cpu = MPIDR_AFFLVL0_VAL(mpidr); int cpu = MPIDR_AFFLVL0_VAL(mpidr);
int cluster = MPIDR_AFFLVL1_VAL(mpidr); int cluster = MPIDR_AFFLVL1_VAL(mpidr);
const plat_local_state_t *pds = state->pwr_domain_state;
bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
bool cluster_off = (HP_CLUSTER_OFF && afflvl1 &&
clst_single_on(cluster, cpu));
INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
/* Prevent interrupts from spuriously waking up this cpu */
mt_gic_cpuif_disable(); mt_gic_cpuif_disable();
spm_enable_cpu_auto_off(cluster, cpu); if (cluster_off)
plat_cluster_pwrdwn_common(mpidr, cluster);
if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) { mcdi_ctrl_before_hotplug_off(cluster, cpu, cluster_off);
if (cluster == 1) hotplug_ctrl_cluster_cpu_off(cluster, cpu, cluster_off);
mt_gic_sync_dcm_enable(); }
plat_mtk_cci_disable(); static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state)
spm_enable_cluster_auto_off(cluster); {
} uint64_t mpidr = read_mpidr();
int cpu = MPIDR_AFFLVL0_VAL(mpidr);
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
const plat_local_state_t *pds = state->pwr_domain_state;
bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
if (afflvl1)
plat_cluster_pwron_common(mpidr, cluster);
spm_set_cpu_power_off(cluster, cpu); mt_gic_pcpu_init();
mt_gic_cpuif_enable();
hotplug_ctrl_cpu_on_finish(cluster, cpu);
} }
static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state) static void plat_mtk_power_domain_suspend(const psci_power_state_t *state)
{ {
uint64_t mpidr = read_mpidr(); uint64_t mpidr = read_mpidr();
int cpu = MPIDR_AFFLVL0_VAL(mpidr); int cpu = MPIDR_AFFLVL0_VAL(mpidr);
int cluster = MPIDR_AFFLVL1_VAL(mpidr); int cluster = MPIDR_AFFLVL1_VAL(mpidr);
const plat_local_state_t *pds = state->pwr_domain_state;
bool afflvl1 = (pds[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF);
bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF);
bool cluster_off = MCDI_C2 && afflvl1 && clst_single_pwr(cluster, cpu);
/* init cpu reset arch as AARCH64 */
mcucfg_init_archstate(cluster, cpu, 1);
mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
mt_gic_cpuif_disable();
mt_gic_irq_save();
plat_dcm_mcsi_a_backup();
if (cluster_off || afflvl2)
plat_cluster_pwrdwn_common(mpidr, cluster);
if (afflvl2) {
spm_data_t spm_d = { .cmd = SPM_SUSPEND };
uint32_t *d = (uint32_t *)&spm_d;
uint32_t l = sizeof(spm_d) / sizeof(uint32_t);
INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu); mcdi_ctrl_suspend();
assert(state->pwr_domain_state[MPIDR_AFFLVL0] == MTK_LOCAL_STATE_OFF); spm_set_bootaddr(secure_entrypoint);
if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) { if (MCDI_SSPM)
enable_scu(mpidr); sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d);
/* Enable coherency if this cluster was off */ spm_system_suspend();
plat_mtk_cci_enable();
/* Enable big core dcm if this cluster was on */ if (MCDI_SSPM)
plat_dcm_restore_cluster_on(mpidr); while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l))
/* Enable rgu dcm if this cluster was off */ ;
plat_dcm_rgu_enable(); } else {
mcdi_ctrl_cluster_cpu_off(cluster, cpu, cluster_off);
} }
}
spm_disable_cpu_auto_off(cluster, cpu); static void plat_mtk_power_domain_suspend_finish(const psci_power_state_t *state)
{
uint64_t mpidr = read_mpidr();
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
const plat_local_state_t *pds = state->pwr_domain_state;
bool afflvl2 = (pds[MPIDR_AFFLVL2] == MTK_LOCAL_STATE_OFF);
/* Enable the gic cpu interface */ if (afflvl2) {
mt_gic_pcpu_init(); spm_data_t spm_d = { .cmd = SPM_RESUME };
mt_gic_cpuif_enable(); uint32_t *d = (uint32_t *)&spm_d;
uint32_t l = sizeof(spm_d) / sizeof(uint32_t);
mt_gic_init();
mt_gic_irq_restore();
mmio_write_32(EMI_WFIFO, 0xf);
if (MCDI_SSPM)
sspm_ipi_send_non_blocking(IPI_ID_SUSPEND, d);
spm_system_suspend_finish();
if (MCDI_SSPM)
while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l))
;
mcdi_ctrl_resume();
}
plat_cluster_pwron_common(mpidr, cluster);
plat_dcm_mcsi_a_restore();
}
#if PSCI_EXTENDED_STATE_ID
static int plat_mtk_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
unsigned int state_id;
int i;
assert(req_state);
if (!MCDI_SSPM)
return PSCI_E_INVALID_PARAMS;
/*
* Currently we are using a linear search for finding the matching
* entry in the idle power state array. This can be made a binary
* search if the number of entries justify the additional complexity.
*/
for (i = 0; !!mtk_pm_idle_states[i]; i++) {
if (power_state == mtk_pm_idle_states[i])
break;
}
/* Return error if entry not found in the idle state array */
if (!mtk_pm_idle_states[i])
return PSCI_E_INVALID_PARAMS;
i = 0;
state_id = psci_get_pstate_id(power_state);
/* Parse the State ID and populate the state info parameter */
while (state_id) {
req_state->pwr_domain_state[i++] = state_id &
MTK_LOCAL_PSTATE_MASK;
state_id >>= MTK_LOCAL_PSTATE_WIDTH;
}
return PSCI_E_SUCCESS;
}
#else /* if !PSCI_EXTENDED_STATE_ID */
static int plat_mtk_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
int pstate = psci_get_pstate_type(power_state);
int pwr_lvl = psci_get_pstate_pwrlvl(power_state);
int i;
assert(req_state);
if (pwr_lvl > PLAT_MAX_PWR_LVL)
return PSCI_E_INVALID_PARAMS;
/* Sanity check the requested state */
if (pstate == PSTATE_TYPE_STANDBY) {
/*
* It's possible to enter standby only on power level 0
* Ignore any other power level.
*/
if (pwr_lvl != 0)
return PSCI_E_INVALID_PARAMS;
req_state->pwr_domain_state[MTK_PWR_LVL0] = MTK_LOCAL_STATE_RET;
} else if (!MCDI_SSPM) {
return PSCI_E_INVALID_PARAMS;
} else {
for (i = 0; i <= pwr_lvl; i++)
req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
}
return PSCI_E_SUCCESS;
} }
#endif /* PSCI_EXTENDED_STATE_ID */
/******************************************************************************* /*******************************************************************************
* MTK handlers to shutdown/reboot the system * MTK handlers to shutdown/reboot the system
******************************************************************************/ ******************************************************************************/
...@@ -147,21 +519,29 @@ static void __dead2 plat_mtk_system_reset(void) ...@@ -147,21 +519,29 @@ static void __dead2 plat_mtk_system_reset(void)
panic(); panic();
} }
static void plat_mtk_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
assert(PLAT_MAX_PWR_LVL >= 2);
for (int i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++)
req_state->pwr_domain_state[i] = MTK_LOCAL_STATE_OFF;
}
/******************************************************************************* /*******************************************************************************
* MTK_platform handler called when an affinity instance is about to be turned * MTK_platform handler called when an affinity instance is about to be turned
* on. The level and mpidr determine the affinity instance. * on. The level and mpidr determine the affinity instance.
******************************************************************************/ ******************************************************************************/
static const plat_psci_ops_t plat_plat_pm_ops = { static const plat_psci_ops_t plat_plat_pm_ops = {
.cpu_standby = NULL, .cpu_standby = plat_cpu_standby,
.pwr_domain_on = plat_mtk_power_domain_on, .pwr_domain_on = plat_mtk_power_domain_on,
.pwr_domain_on_finish = plat_mtk_power_domain_on_finish, .pwr_domain_on_finish = plat_mtk_power_domain_on_finish,
.pwr_domain_off = plat_mtk_power_domain_off, .pwr_domain_off = plat_mtk_power_domain_off,
.pwr_domain_suspend = NULL, .pwr_domain_suspend = plat_mtk_power_domain_suspend,
.pwr_domain_suspend_finish = NULL, .pwr_domain_suspend_finish = plat_mtk_power_domain_suspend_finish,
.system_off = plat_mtk_system_off, .system_off = plat_mtk_system_off,
.system_reset = plat_mtk_system_reset, .system_reset = plat_mtk_system_reset,
.validate_power_state = NULL, .validate_power_state = plat_mtk_validate_power_state,
.get_sys_suspend_power_state = NULL, .get_sys_suspend_power_state = plat_mtk_get_sys_suspend_power_state,
}; };
int plat_setup_psci_ops(uintptr_t sec_entrypoint, int plat_setup_psci_ops(uintptr_t sec_entrypoint,
...@@ -169,5 +549,11 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint, ...@@ -169,5 +549,11 @@ int plat_setup_psci_ops(uintptr_t sec_entrypoint,
{ {
*psci_ops = &plat_plat_pm_ops; *psci_ops = &plat_plat_pm_ops;
secure_entrypoint = sec_entrypoint; secure_entrypoint = sec_entrypoint;
if (!check_mcdi_ctl_stat()) {
HP_SSPM_CTRL = false;
MCDI_SSPM = false;
}
return 0; return 0;
} }
...@@ -9,10 +9,14 @@ MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} ...@@ -9,10 +9,14 @@ MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
-I${MTK_PLAT_SOC}/drivers/ \ -I${MTK_PLAT_SOC}/drivers/ \
-I${MTK_PLAT_SOC}/drivers/mcdi/ \
-I${MTK_PLAT_SOC}/drivers/spmc/ \ -I${MTK_PLAT_SOC}/drivers/spmc/ \
-I${MTK_PLAT_SOC}/drivers/gpio/ \ -I${MTK_PLAT_SOC}/drivers/gpio/ \
-I${MTK_PLAT_SOC}/drivers/pmic/ \ -I${MTK_PLAT_SOC}/drivers/pmic/ \
-I${MTK_PLAT_SOC}/drivers/spm/ \
-I${MTK_PLAT_SOC}/drivers/sspm/ \
-I${MTK_PLAT_SOC}/drivers/rtc/ \ -I${MTK_PLAT_SOC}/drivers/rtc/ \
-I${MTK_PLAT_SOC}/drivers/uart/ \
-I${MTK_PLAT_SOC}/include/ -I${MTK_PLAT_SOC}/include/
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \
...@@ -45,15 +49,21 @@ BL31_SOURCES += common/desc_image_load.c \ ...@@ -45,15 +49,21 @@ BL31_SOURCES += common/desc_image_load.c \
${MTK_PLAT_SOC}/drivers/mcsi/mcsi.c \ ${MTK_PLAT_SOC}/drivers/mcsi/mcsi.c \
${MTK_PLAT_SOC}/drivers/pmic/pmic.c \ ${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
${MTK_PLAT_SOC}/drivers/rtc/rtc.c \ ${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
${MTK_PLAT_SOC}/drivers/mcdi/mtk_mcdi.c \
${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \ ${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
${MTK_PLAT_SOC}/drivers/spm/spm.c \
${MTK_PLAT_SOC}/drivers/spm/spm_pmic_wrap.c \
${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \ ${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
${MTK_PLAT_SOC}/drivers/uart/uart.c \
${MTK_PLAT_SOC}/plat_pm.c \ ${MTK_PLAT_SOC}/plat_pm.c \
${MTK_PLAT_SOC}/plat_topology.c \ ${MTK_PLAT_SOC}/plat_topology.c \
${MTK_PLAT_SOC}/plat_mt_gic.c \ ${MTK_PLAT_SOC}/plat_mt_gic.c \
${MTK_PLAT_SOC}/plat_dcm.c \ ${MTK_PLAT_SOC}/plat_dcm.c \
${MTK_PLAT_SOC}/bl31_plat_setup.c \ ${MTK_PLAT_SOC}/bl31_plat_setup.c \
${MTK_PLAT_SOC}/plat_debug.c \ ${MTK_PLAT_SOC}/plat_debug.c \
${MTK_PLAT_SOC}/scu.c ${MTK_PLAT_SOC}/scu.c \
${MTK_PLAT_SOC}/drivers/sspm/sspm.c
# Enable workarounds for selected Cortex-A53 erratas. # Enable workarounds for selected Cortex-A53 erratas.
ERRATA_A53_826319 := 0 ERRATA_A53_826319 := 0
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment