Commit 77990838 authored by Manish Pandey's avatar Manish Pandey Committed by TrustedFirmware Code Review
Browse files

Merge changes Ibbee37c8,Ic3a13c83,Ib7f2380a,I83b477fd,I284956d4, ... into integration

* changes:
  mediatek: mt8192: dcm: Add mcusys related dcm drivers
  mediatek: mt8192: add ptp3 driver
  mediatek: mt8192: Add SiP service
  mediatek: mt8192: add uart save and restore api
  mediatek: mt8192: modify sys_cirq driver
  mediatek: mt8192: add power-off support
  mediatek: mt8192: add pmic mt6359p driver
  mediatek: mt8192: Initialize delay_timer
  mediatek: mt8192: enable NS access for systimer
  mediatek: mt8192: Add CPU hotplug and MCDI support
  mediatek: mt8192: Add MCDI drivers
  mediatek: mt8192: Add SPMC driver
parents 0b18d5a5 43d7bbcc
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTSPMC_H
#define MTSPMC_H
#include <stdint.h>
int spmc_init(void);
void spm_poweron_cpu(uint32_t cluster, uint32_t cpu);
void spm_poweroff_cpu(uint32_t cluster, uint32_t cpu);
void spm_poweroff_cluster(uint32_t cluster);
void spm_poweron_cluster(uint32_t cluster);
bool spm_get_cpu_powerstate(uint32_t cluster, uint32_t cpu);
bool spm_get_cluster_powerstate(uint32_t cluster);
bool spm_get_powerstate(uint32_t mask);
void mcucfg_init_archstate(uint32_t cluster, uint32_t cpu, bool arm64);
void mcucfg_set_bootaddr(uint32_t cluster, uint32_t cpu, uintptr_t bootaddr);
uintptr_t mcucfg_get_bootaddr(uint32_t cluster, uint32_t cpu);
void mcucfg_disable_gic_wakeup(uint32_t cluster, uint32_t cpu);
void mcucfg_enable_gic_wakeup(uint32_t cluster, uint32_t cpu);
#endif /* MTSPMC_H */
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MTSPMC_PRIVATE_H
#define MTSPMC_PRIVATE_H
#include <lib/utils_def.h>
#include <platform_def.h>
unsigned long read_cpuectlr(void);
void write_cpuectlr(unsigned long cpuectlr);
unsigned long read_cpupwrctlr_el1(void);
void write_cpupwrctlr_el1(unsigned long cpuectlr);
/*
* per_cpu/cluster helper
*/
struct per_cpu_reg {
unsigned int cluster_addr;
unsigned 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)
#define SPM_REG(ofs) (uint32_t)(SPM_BASE + (ofs))
#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
#define INFRACFG_AO_REG(ofs) (uint32_t)(INFRACFG_AO_BASE + (ofs))
/* === SPMC related registers */
#define SPM_POWERON_CONFIG_EN SPM_REG(0x000)
/* bit-fields of SPM_POWERON_CONFIG_EN */
#define PROJECT_CODE (U(0xb16) << 16)
#define BCLK_CG_EN BIT(0)
#define SPM_PWR_STATUS SPM_REG(0x16c)
#define SPM_PWR_STATUS_2ND SPM_REG(0x170)
#define SPM_CPU_PWR_STATUS SPM_REG(0x174)
/* bit-fields of SPM_PWR_STATUS */
#define MD BIT(0)
#define CONN BIT(1)
#define DDRPHY BIT(2)
#define DISP BIT(3)
#define MFG BIT(4)
#define ISP BIT(5)
#define INFRA BIT(6)
#define VDEC BIT(7)
#define MP0_CPUTOP BIT(8)
#define MP0_CPU0 BIT(9)
#define MP0_CPU1 BIT(10)
#define MP0_CPU2 BIT(11)
#define MP0_CPU3 BIT(12)
#define MCUSYS BIT(14)
#define MP0_CPU4 BIT(15)
#define MP0_CPU5 BIT(16)
#define MP0_CPU6 BIT(17)
#define MP0_CPU7 BIT(18)
#define VEN BIT(21)
/* === SPMC related registers */
#define SPM_MCUSYS_PWR_CON MCUCFG_REG(0xd200)
#define SPM_MP0_CPUTOP_PWR_CON MCUCFG_REG(0xd204)
#define SPM_MP0_CPU0_PWR_CON MCUCFG_REG(0xd208)
#define SPM_MP0_CPU1_PWR_CON MCUCFG_REG(0xd20c)
#define SPM_MP0_CPU2_PWR_CON MCUCFG_REG(0xd210)
#define SPM_MP0_CPU3_PWR_CON MCUCFG_REG(0xd214)
#define SPM_MP0_CPU4_PWR_CON MCUCFG_REG(0xd218)
#define SPM_MP0_CPU5_PWR_CON MCUCFG_REG(0xd21c)
#define SPM_MP0_CPU6_PWR_CON MCUCFG_REG(0xd220)
#define SPM_MP0_CPU7_PWR_CON MCUCFG_REG(0xd224)
/* bit fields of SPM_*_PWR_CON */
#define PWR_ON_ACK BIT(31)
#define VPROC_EXT_OFF BIT(7)
#define DORMANT_EN BIT(6)
#define RESETPWRON_CONFIG BIT(5)
#define PWR_CLK_DIS BIT(4)
#define PWR_ON BIT(2)
#define PWR_RST_B BIT(0)
/**** per_cpu registers for SPM_MP0_CPU?_PWR_CON */
static const struct per_cpu_reg SPM_CPU_PWR[] = {
{ .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2U }
};
/**** per_cluster registers for SPM_MP0_CPUTOP_PWR_CON */
static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
{ .cluster_addr = SPM_MP0_CPUTOP_PWR_CON, .cpu_stride = 0U }
};
/* === MCUCFG related registers */
/* aa64naa32 */
#define MCUCFG_MP0_CLUSTER_CFG5 MCUCFG_REG(0xc8e4)
/* reset vectors */
#define MCUCFG_MP0_CLUSTER_CFG8 MCUCFG_REG(0xc900)
#define MCUCFG_MP0_CLUSTER_CFG10 MCUCFG_REG(0xc908)
#define MCUCFG_MP0_CLUSTER_CFG12 MCUCFG_REG(0xc910)
#define MCUCFG_MP0_CLUSTER_CFG14 MCUCFG_REG(0xc918)
#define MCUCFG_MP0_CLUSTER_CFG16 MCUCFG_REG(0xc920)
#define MCUCFG_MP0_CLUSTER_CFG18 MCUCFG_REG(0xc928)
#define MCUCFG_MP0_CLUSTER_CFG20 MCUCFG_REG(0xc930)
#define MCUCFG_MP0_CLUSTER_CFG22 MCUCFG_REG(0xc938)
/* MCUSYS DREQ BIG VPROC ISO control */
#define DREQ20_BIG_VPROC_ISO MCUCFG_REG(0xad8c)
/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG? */
static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG8, .cpu_stride = 3U }
};
/**** per_cpu registers for MCUCFG_MP0_CLUSTER_CFG5 */
static const struct per_cpu_reg MCUCFG_INITARCH[] = {
{ .cluster_addr = MCUCFG_MP0_CLUSTER_CFG5, .cpu_stride = 0U }
};
#define MCUCFG_INITARCH_CPU_BIT(cpu) BIT(16U + cpu)
#define LAST_PC_REG(cpu) (MCUCFG_REG(0x308) + (cpu * 0x800))
/* === CPC control */
#define MCUCFG_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
#define MCUCFG_CPC_SPMC_PWR_STATUS MCUCFG_REG(0xa840)
/* bit fields of CPC_FLOW_CTRL_CFG */
#define CPC_CTRL_ENABLE BIT(16)
#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
/* bit fields of CPC_SPMC_PWR_STATUS */
#define CORE_SPMC_PWR_ON_ACK GENMASK(15, 0)
/* === APB Module infracfg_ao */
#define INFRA_TOPAXI_PROTECTEN INFRACFG_AO_REG(0x0220)
#define INFRA_TOPAXI_PROTECTEN_STA0 INFRACFG_AO_REG(0x0224)
#define INFRA_TOPAXI_PROTECTEN_STA1 INFRACFG_AO_REG(0x0228)
#define INFRA_TOPAXI_PROTECTEN_SET INFRACFG_AO_REG(0x02a0)
#define INFRA_TOPAXI_PROTECTEN_CLR INFRACFG_AO_REG(0x02a4)
#define INFRA_TOPAXI_PROTECTEN_1 INFRACFG_AO_REG(0x0250)
#define INFRA_TOPAXI_PROTECTEN_STA0_1 INFRACFG_AO_REG(0x0254)
#define INFRA_TOPAXI_PROTECTEN_STA1_1 INFRACFG_AO_REG(0x0258)
#define INFRA_TOPAXI_PROTECTEN_1_SET INFRACFG_AO_REG(0x02a8)
#define INFRA_TOPAXI_PROTECTEN_1_CLR INFRACFG_AO_REG(0x02ac)
/* bit fields of INFRA_TOPAXI_PROTECTEN */
#define MP0_SPMC_PROT_STEP1_0_MASK BIT(12)
#define MP0_SPMC_PROT_STEP1_1_MASK (BIT(26) | BIT(12))
/* === SPARK */
#define VOLTAGE_04 U(0x40)
#define VOLTAGE_05 U(0x60)
#define PTP3_CPU0_SPMC_SW_CFG MCUCFG_REG(0x200)
#define CPU0_ILDO_CONTROL5 MCUCFG_REG(0x334)
#define CPU0_ILDO_CONTROL8 MCUCFG_REG(0x340)
/* bit fields of CPU0_ILDO_CONTROL5 */
#define ILDO_RET_VOSEL GENMASK(7, 0)
/* bit fields of PTP3_CPU_SPMC_SW_CFG */
#define SW_SPARK_EN BIT(0)
/* bit fields of CPU0_ILDO_CONTROL8 */
#define ILDO_BYPASS_B BIT(0)
static const struct per_cpu_reg MCUCFG_SPARK[] = {
{ .cluster_addr = PTP3_CPU0_SPMC_SW_CFG, .cpu_stride = 11U }
};
static const struct per_cpu_reg ILDO_CONTROL5[] = {
{ .cluster_addr = CPU0_ILDO_CONTROL5, .cpu_stride = 11U }
};
static const struct per_cpu_reg ILDO_CONTROL8[] = {
{ .cluster_addr = CPU0_ILDO_CONTROL8, .cpu_stride = 11U }
};
#endif /* MTSPMC_PRIVATE_H */
......@@ -5,6 +5,7 @@
*/
#include <arch_helpers.h>
#include <lib/mmio.h>
#include <mt_timer.h>
#include <platform_def.h>
......@@ -28,3 +29,10 @@ uint64_t sched_clock(void)
- normal_time_base;
return cval;
}
void mt_systimer_init(void)
{
/* Enable access in NS mode */
mmio_write_32(CNTWACR_REG, CNT_WRITE_ACCESS_CTL_MASK);
mmio_write_32(CNTRACR_REG, CNT_READ_ACCESS_CTL_MASK);
}
......@@ -12,6 +12,8 @@
#define CNTSR_REG (SYSTIMER_BASE + 0x4)
#define CNTSYS_L_REG (SYSTIMER_BASE + 0x8)
#define CNTSYS_H_REG (SYSTIMER_BASE + 0xc)
#define CNTWACR_REG (SYSTIMER_BASE + 0x10)
#define CNTRACR_REG (SYSTIMER_BASE + 0x14)
#define TIEO_EN (1 << 3)
#define COMP_15_EN (1 << 10)
......@@ -23,8 +25,11 @@
#define COMP_20_MASK (COMP_20_EN | TIEO_EN)
#define COMP_25_MASK (COMP_20_EN | COMP_25_EN)
#define CNT_WRITE_ACCESS_CTL_MASK (0x3FFFFF0U)
#define CNT_READ_ACCESS_CTL_MASK (0x3FFFFFFU)
void sched_clock_init(uint64_t normal_base, uint64_t atf_base);
uint64_t sched_clock(void);
void mt_systimer_init(void);
#endif /* MT_TIMER_H */
/*
* Copyright (c) 2020, MediaTek Inc. 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 {
uint32_t dll;
uint32_t dlh;
uint32_t ier;
uint32_t lcr;
uint32_t mcr;
uint32_t fcr;
uint32_t lsr;
uint32_t scr;
uint32_t efr;
uint32_t highspeed;
uint32_t sample_count;
uint32_t sample_point;
uint32_t fracdiv_l;
uint32_t fracdiv_m;
uint32_t escape_en;
uint32_t guard;
uint32_t 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);
uint32_t mt_console_uart_cg_status(void);
#endif /* __UART_H__ */
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MCUCFG_H
#define MCUCFG_H
#ifndef __ASSEMBLER__
#include <stdint.h>
#endif /* __ASSEMBLER__ */
#include <platform_def.h>
#define MCUCFG_REG(ofs) (uint32_t)(MCUCFG_BASE + (ofs))
#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_REG(0x2290) + ((cpu) * 8))
#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_REG(0x2294) + ((cpu) * 8))
#define MP2_CPUCFG MCUCFG_REG(0x2208)
#define MP2_CPU0_STANDBYWFE BIT(4)
#define MP2_CPU1_STANDBYWFE BIT(5)
#define MP0_CPUTOP_SPMC_CTL MCUCFG_REG(0x788)
#define MP1_CPUTOP_SPMC_CTL MCUCFG_REG(0x78C)
#define MP1_CPUTOP_SPMC_SRAM_CTL MCUCFG_REG(0x790)
#define sw_spark_en BIT(0)
#define sw_no_wait_for_q_channel BIT(1)
#define sw_fsm_override BIT(2)
#define sw_logic_pre1_pdb BIT(3)
#define sw_logic_pre2_pdb BIT(4)
#define sw_logic_pdb BIT(5)
#define sw_iso BIT(6)
#define sw_sram_sleepb (U(0x3F) << 7)
#define sw_sram_isointb BIT(13)
#define sw_clk_dis BIT(14)
#define sw_ckiso BIT(15)
#define sw_pd (U(0x3F) << 16)
#define sw_hot_plug_reset BIT(22)
#define sw_pwr_on_override_en BIT(23)
#define sw_pwr_on BIT(24)
#define sw_coq_dis BIT(25)
#define logic_pdbo_all_off_ack BIT(26)
#define logic_pdbo_all_on_ack BIT(27)
#define logic_pre2_pdbo_all_on_ack BIT(28)
#define logic_pre1_pdbo_all_on_ack BIT(29)
#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) \
(MCUCFG_REG(0x1c30) + cluster * 0x2000 + cpu * 4)
#define CPUSYS0_CPU0_SPMC_CTL MCUCFG_REG(0x1c30)
#define CPUSYS0_CPU1_SPMC_CTL MCUCFG_REG(0x1c34)
#define CPUSYS0_CPU2_SPMC_CTL MCUCFG_REG(0x1c38)
#define CPUSYS0_CPU3_SPMC_CTL MCUCFG_REG(0x1c3C)
#define CPUSYS1_CPU0_SPMC_CTL MCUCFG_REG(0x3c30)
#define CPUSYS1_CPU1_SPMC_CTL MCUCFG_REG(0x3c34)
#define CPUSYS1_CPU2_SPMC_CTL MCUCFG_REG(0x3c38)
#define CPUSYS1_CPU3_SPMC_CTL MCUCFG_REG(0x3c3C)
#define cpu_sw_spark_en BIT(0)
#define cpu_sw_no_wait_for_q_channel BIT(1)
#define cpu_sw_fsm_override BIT(2)
#define cpu_sw_logic_pre1_pdb BIT(3)
#define cpu_sw_logic_pre2_pdb BIT(4)
#define cpu_sw_logic_pdb BIT(5)
#define cpu_sw_iso BIT(6)
#define cpu_sw_sram_sleepb BIT(7)
#define cpu_sw_sram_isointb BIT(8)
#define cpu_sw_clk_dis BIT(9)
#define cpu_sw_ckiso BIT(10)
#define cpu_sw_pd (U(0x1F) << 11)
#define cpu_sw_hot_plug_reset BIT(16)
#define cpu_sw_powr_on_override_en BIT(17)
#define cpu_sw_pwr_on BIT(18)
#define cpu_spark2ldo_allswoff BIT(19)
#define cpu_pdbo_all_on_ack BIT(20)
#define cpu_pre2_pdbo_allon_ack BIT(21)
#define cpu_pre1_pdbo_allon_ack BIT(22)
/* CPC related registers */
#define CPC_MCUSYS_CPC_OFF_THRES MCUCFG_REG(0xa714)
#define CPC_MCUSYS_PWR_CTRL MCUCFG_REG(0xa804)
#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG MCUCFG_REG(0xa814)
#define CPC_MCUSYS_LAST_CORE_REQ MCUCFG_REG(0xa818)
#define CPC_MCUSYS_MP_LAST_CORE_RESP MCUCFG_REG(0xa81c)
#define CPC_MCUSYS_LAST_CORE_RESP MCUCFG_REG(0xa824)
#define CPC_MCUSYS_PWR_ON_MASK MCUCFG_REG(0xa828)
#define CPC_MCUSYS_CPU_ON_SW_HINT_SET MCUCFG_REG(0xa8a8)
#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR MCUCFG_REG(0xa8ac)
#define CPC_MCUSYS_CPC_DBG_SETTING MCUCFG_REG(0xab00)
#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE MCUCFG_REG(0xab04)
#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE MCUCFG_REG(0xab08)
#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE MCUCFG_REG(0xab0c)
#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE MCUCFG_REG(0xab10)
#define CPC_MCUSYS_TRACE_SEL MCUCFG_REG(0xab14)
#define CPC_MCUSYS_TRACE_DATA MCUCFG_REG(0xab20)
#define CPC_MCUSYS_CLUSTER_COUNTER MCUCFG_REG(0xab70)
#define CPC_MCUSYS_CLUSTER_COUNTER_CLR MCUCFG_REG(0xab74)
#define SPARK2LDO MCUCFG_REG(0x2700)
/* APB Module mcucfg */
#define MP0_CA7_CACHE_CONFIG MCUCFG_REG(0x000)
#define MP0_AXI_CONFIG MCUCFG_REG(0x02C)
#define MP0_MISC_CONFIG0 MCUCFG_REG(0x030)
#define MP0_MISC_CONFIG1 MCUCFG_REG(0x034)
#define MP0_MISC_CONFIG2 MCUCFG_REG(0x038)
#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MP0_MISC_CONFIG2 + ((cpu) * 8))
#define MP0_MISC_CONFIG3 MCUCFG_REG(0x03C)
#define MP0_MISC_CONFIG9 MCUCFG_REG(0x054)
#define MP0_CA7_MISC_CONFIG MCUCFG_REG(0x064)
#define MP0_RW_RSVD0 MCUCFG_REG(0x06C)
#define MP1_CA7_CACHE_CONFIG MCUCFG_REG(0x200)
#define MP1_AXI_CONFIG MCUCFG_REG(0x22C)
#define MP1_MISC_CONFIG0 MCUCFG_REG(0x230)
#define MP1_MISC_CONFIG1 MCUCFG_REG(0x234)
#define MP1_MISC_CONFIG2 MCUCFG_REG(0x238)
#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MP1_MISC_CONFIG2 + ((cpu) * 8))
#define MP1_MISC_CONFIG3 MCUCFG_REG(0x23C)
#define MP1_MISC_CONFIG9 MCUCFG_REG(0x254)
#define MP1_CA7_MISC_CONFIG MCUCFG_REG(0x264)
#define CCI_ADB400_DCM_CONFIG MCUCFG_REG(0x740)
#define SYNC_DCM_CONFIG MCUCFG_REG(0x744)
#define MP0_CLUSTER_CFG0 MCUCFG_REG(0xC8D0)
#define MP0_SPMC MCUCFG_REG(0x788)
#define MP1_SPMC MCUCFG_REG(0x78C)
#define MP2_AXI_CONFIG MCUCFG_REG(0x220C)
#define MP2_AXI_CONFIG_ACINACTM BIT(0)
#define MP2_AXI_CONFIG_AINACTS BIT(4)
#define MPx_AXI_CONFIG_ACINACTM BIT(4)
#define MPx_AXI_CONFIG_AINACTS BIT(5)
#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
#define MP0_CPU0_STANDBYWFE BIT(20)
#define MP0_CPU1_STANDBYWFE BIT(21)
#define MP0_CPU2_STANDBYWFE BIT(22)
#define MP0_CPU3_STANDBYWFE BIT(23)
#define MP1_CPU0_STANDBYWFE BIT(20)
#define MP1_CPU1_STANDBYWFE BIT(21)
#define MP1_CPU2_STANDBYWFE BIT(22)
#define MP1_CPU3_STANDBYWFE BIT(23)
#define CPUSYS0_SPARKVRETCNTRL MCUCFG_REG(0x1c00)
#define CPUSYS0_SPARKEN MCUCFG_REG(0x1c04)
#define CPUSYS0_AMUXSEL MCUCFG_REG(0x1c08)
#define CPUSYS1_SPARKVRETCNTRL MCUCFG_REG(0x3c00)
#define CPUSYS1_SPARKEN MCUCFG_REG(0x3c04)
#define CPUSYS1_AMUXSEL MCUCFG_REG(0x3c08)
#define MP2_PWR_RST_CTL MCUCFG_REG(0x2008)
#define MP2_PTP3_CPUTOP_SPMC0 MCUCFG_REG(0x22A0)
#define MP2_PTP3_CPUTOP_SPMC1 MCUCFG_REG(0x22A4)
#define MP2_COQ MCUCFG_REG(0x22BC)
#define MP2_COQ_SW_DIS BIT(0)
#define MP2_CA15M_MON_SEL MCUCFG_REG(0x2400)
#define MP2_CA15M_MON_L MCUCFG_REG(0x2404)
#define CPUSYS2_CPU0_SPMC_CTL MCUCFG_REG(0x2430)
#define CPUSYS2_CPU1_SPMC_CTL MCUCFG_REG(0x2438)
#define CPUSYS2_CPU0_SPMC_STA MCUCFG_REG(0x2434)
#define CPUSYS2_CPU1_SPMC_STA MCUCFG_REG(0x243C)
#define MP0_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x068)
#define MP1_CA7L_DBG_PWR_CTRL MCUCFG_REG(0x268)
#define BIG_DBG_PWR_CTRL MCUCFG_REG(0x75C)
#define MP2_SW_RST_B BIT(0)
#define MP2_TOPAON_APB_MASK BIT(1)
#define B_SW_HOT_PLUG_RESET BIT(30)
#define B_SW_PD_OFFSET 18U
#define B_SW_PD (U(0x3f) << B_SW_PD_OFFSET)
#define B_SW_SRAM_SLEEPB_OFFSET 12U
#define B_SW_SRAM_SLEEPB (U(0x3f) << B_SW_SRAM_SLEEPB_OFFSET)
#define B_SW_SRAM_ISOINTB BIT(9)
#define B_SW_ISO BIT(8)
#define B_SW_LOGIC_PDB BIT(7)
#define B_SW_LOGIC_PRE2_PDB BIT(6)
#define B_SW_LOGIC_PRE1_PDB BIT(5)
#define B_SW_FSM_OVERRIDE BIT(4)
#define B_SW_PWR_ON BIT(3)
#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
#define B_FSM_STATE_OUT_OFFSET (6U)
#define B_FSM_STATE_OUT_MASK (U(0x1f) << B_FSM_STATE_OUT_OFFSET)
#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
#ifndef __ASSEMBLER__
/* cpu boot mode */
enum {
MP0_CPUCFG_64BIT_SHIFT = 12U,
MP1_CPUCFG_64BIT_SHIFT = 28U,
MP0_CPUCFG_64BIT = U(0xf) << MP0_CPUCFG_64BIT_SHIFT,
MP1_CPUCFG_64BIT = U(0xf) << MP1_CPUCFG_64BIT_SHIFT
};
enum {
MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0U,
MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4U,
MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8U,
MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12U,
MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16U,
MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK =
U(0xf) << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT
};
enum {
MP1_AINACTS_SHIFT = 4U,
MP1_AINACTS = 1U << MP1_AINACTS_SHIFT
};
enum {
MP1_SW_CG_GEN_SHIFT = 12U,
MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT
};
enum {
MP1_L2RSTDISABLE_SHIFT = 14U,
MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT
};
#endif /* __ASSEMBLER__ */
#endif /* MCUCFG_H */
......@@ -7,24 +7,53 @@
#ifndef PLAT_MT_CIRQ_H
#define PLAT_MT_CIRQ_H
#define SYS_CIRQ_BASE U(0x10204000)
#define CIRQ_IRQ_NUM U(439)
#define CIRQ_SPI_START U(96)
#include <stdint.h>
enum {
IRQ_MASK_HEADER = 0xF1F1F1F1,
IRQ_MASK_FOOTER = 0xF2F2F2F2
};
struct mtk_irq_mask {
uint32_t header; /* for error checking */
uint32_t mask0;
uint32_t mask1;
uint32_t mask2;
uint32_t mask3;
uint32_t mask4;
uint32_t mask5;
uint32_t mask6;
uint32_t mask7;
uint32_t mask8;
uint32_t mask9;
uint32_t mask10;
uint32_t mask11;
uint32_t mask12;
uint32_t footer; /* for error checking */
};
/*
* Define hardware register
*/
#define CIRQ_STA_BASE U(0x000)
#define CIRQ_ACK_BASE U(0x080)
#define CIRQ_MASK_BASE U(0x100)
#define CIRQ_MASK_SET_BASE U(0x180)
#define CIRQ_MASK_CLR_BASE U(0x200)
#define CIRQ_SENS_BASE U(0x280)
#define CIRQ_SENS_SET_BASE U(0x300)
#define CIRQ_SENS_CLR_BASE U(0x380)
#define CIRQ_POL_BASE U(0x400)
#define CIRQ_POL_SET_BASE U(0x480)
#define CIRQ_POL_CLR_BASE U(0x500)
#define CIRQ_CON U(0x600)
#define SYS_CIRQ_BASE U(0x10204000)
#define CIRQ_REG_NUM U(14)
#define CIRQ_IRQ_NUM U(439)
#define CIRQ_SPI_START U(64)
#define MD_WDT_IRQ_BIT_ID U(110)
#define CIRQ_STA_BASE (SYS_CIRQ_BASE + U(0x000))
#define CIRQ_ACK_BASE (SYS_CIRQ_BASE + U(0x080))
#define CIRQ_MASK_BASE (SYS_CIRQ_BASE + U(0x100))
#define CIRQ_MASK_SET_BASE (SYS_CIRQ_BASE + U(0x180))
#define CIRQ_MASK_CLR_BASE (SYS_CIRQ_BASE + U(0x200))
#define CIRQ_SENS_BASE (SYS_CIRQ_BASE + U(0x280))
#define CIRQ_SENS_SET_BASE (SYS_CIRQ_BASE + U(0x300))
#define CIRQ_SENS_CLR_BASE (SYS_CIRQ_BASE + U(0x380))
#define CIRQ_POL_BASE (SYS_CIRQ_BASE + U(0x400))
#define CIRQ_POL_SET_BASE (SYS_CIRQ_BASE + U(0x480))
#define CIRQ_POL_CLR_BASE (SYS_CIRQ_BASE + U(0x500))
#define CIRQ_CON (SYS_CIRQ_BASE + U(0x600))
/*
* Register placement
......@@ -32,8 +61,8 @@
#define CIRQ_CON_EN_BITS U(0)
#define CIRQ_CON_EDGE_ONLY_BITS U(1)
#define CIRQ_CON_FLUSH_BITS U(2)
#define CIRQ_CON_EVENT_BITS U(31)
#define CIRQ_CON_SW_RST_BITS U(20)
#define CIRQ_CON_EVENT_BITS U(31)
#define CIRQ_CON_BITS_MASK U(0x7)
/*
......@@ -41,42 +70,59 @@
*/
#define CIRQ_CON_EN U(0x1)
#define CIRQ_CON_EDGE_ONLY U(0x1)
#define CIRQ_SW_RESET U(0x1)
#define CIRQ_CON_FLUSH U(0x1)
#define CIRQ_SW_RESET U(0x1)
/*
* Define constant
*/
#define CIRQ_CTRL_REG_NUM ((CIRQ_IRQ_NUM + 31U) / 32U)
#define MT_CIRQ_POL_NEG U(0)
#define MT_CIRQ_POL_POS U(1)
#define MT_CIRQ_EDGE_SENSITIVE U(0)
#define MT_CIRQ_LEVEL_SENSITIVE U(1)
/*
* Define macro
*/
#define IRQ_TO_CIRQ_NUM(irq) ((irq) - (CIRQ_SPI_START))
#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (CIRQ_SPI_START))
#define IRQ_TO_CIRQ_NUM(irq) ((irq) - (32U + CIRQ_SPI_START))
#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (32U + CIRQ_SPI_START))
/* GIC sensitive */
#define SENS_EDGE U(0x2)
#define SENS_LEVEL U(0x1)
/*
* Define cirq events
*/
struct cirq_events {
uint32_t spi_start;
uint32_t num_of_events;
uint32_t *wakeup_events;
};
/*
* Define function prototypes.
*/
void mt_cirq_enable(void);
void mt_cirq_disable(void);
int mt_cirq_test(void);
void mt_cirq_dump_reg(void);
int mt_irq_mask_restore(struct mtk_irq_mask *mask);
int mt_irq_mask_all(struct mtk_irq_mask *mask);
void mt_cirq_clone_gic(void);
void mt_cirq_enable(void);
void mt_cirq_flush(void);
void mt_cirq_sw_reset(void);
void mt_cirq_disable(void);
void mt_irq_unmask_for_sleep_ex(uint32_t irq);
void set_wakeup_sources(uint32_t *list, uint32_t num_of_events);
void mt_cirq_dump_reg(void);
void mt_cirq_sw_reset(void);
struct cirq_reg {
uint32_t reg_num;
uint32_t used;
uint32_t mask;
uint32_t pol;
uint32_t sen;
uint32_t pending;
uint32_t the_link;
};
struct cirq_events {
uint32_t num_reg;
uint32_t spi_start;
uint32_t num_of_events;
uint32_t *wakeup_events;
struct cirq_reg table[CIRQ_REG_NUM];
uint32_t dist_base;
uint32_t cirq_base;
uint32_t used_reg_head;
};
#endif /* PLAT_MT_CIRQ_H */
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_MTK_LPM_H
#define PLAT_MTK_LPM_H
#include <lib/psci/psci.h>
#include <lib/utils_def.h>
#define MT_IRQ_REMAIN_MAX U(8)
#define MT_IRQ_REMAIN_CAT_LOG BIT(31)
struct mt_irqremain {
unsigned int count;
unsigned int irqs[MT_IRQ_REMAIN_MAX];
unsigned int wakeupsrc_cat[MT_IRQ_REMAIN_MAX];
unsigned int wakeupsrc[MT_IRQ_REMAIN_MAX];
};
#define PLAT_RC_STATUS_READY BIT(0)
#define PLAT_RC_STATUS_FEATURE_EN BIT(1)
#define PLAT_RC_STATUS_UART_NONSLEEP BIT(31)
struct mt_lpm_tz {
int (*pwr_prompt)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_reflect)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_cpu_on)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_cpu_dwn)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_cluster_on)(unsigned int cpu,
const psci_power_state_t *state);
int (*pwr_cluster_dwn)(unsigned int cpu,
const psci_power_state_t *state);
int (*pwr_mcusys_on)(unsigned int cpu, const psci_power_state_t *state);
int (*pwr_mcusys_on_finished)(unsigned int cpu,
const psci_power_state_t *state);
int (*pwr_mcusys_dwn)(unsigned int cpu,
const psci_power_state_t *state);
};
const struct mt_lpm_tz *mt_plat_cpu_pm_init(void);
#endif /* PLAT_MTK_LPM_H */
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_PM_H
#define PLAT_PM_H
#include <lib/utils_def.h>
#define MT_PLAT_PWR_STATE_CPU U(1)
#define MT_PLAT_PWR_STATE_CLUSTER U(2)
#define MT_PLAT_PWR_STATE_MCUSYS U(3)
#define MT_PLAT_PWR_STATE_SUSPEND2IDLE U(8)
#define MT_PLAT_PWR_STATE_SYSTEM_SUSPEND U(9)
#define MTK_LOCAL_STATE_RUN U(0)
#define MTK_LOCAL_STATE_RET U(1)
#define MTK_LOCAL_STATE_OFF U(2)
#define MTK_AFFLVL_CPU U(0)
#define MTK_AFFLVL_CLUSTER U(1)
#define MTK_AFFLVL_MCUSYS U(2)
#define MTK_AFFLVL_SYSTEM U(3)
#define IS_CLUSTER_OFF_STATE(s) \
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_CLUSTER])
#define IS_MCUSYS_OFF_STATE(s) \
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_MCUSYS])
#define IS_SYSTEM_SUSPEND_STATE(s) \
is_local_state_off(s->pwr_domain_state[MTK_AFFLVL_SYSTEM])
#define IS_PLAT_SUSPEND_ID(stateid)\
((stateid == MT_PLAT_PWR_STATE_SUSPEND2IDLE) \
|| (stateid == MT_PLAT_PWR_STATE_SYSTEM_SUSPEND))
#endif /* PLAT_PM_H */
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_SIP_CALLS_H
#define PLAT_SIP_CALLS_H
/*******************************************************************************
* Plat SiP function constants
******************************************************************************/
#define MTK_PLAT_SIP_NUM_CALLS 0
#endif /* PLAT_SIP_CALLS_H */
......@@ -23,8 +23,13 @@
#define MTK_DEV_RNG1_SIZE 0x10000000
#define MTK_DEV_RNG2_BASE 0x0c000000
#define MTK_DEV_RNG2_SIZE 0x600000
#define MTK_MCDI_SRAM_BASE 0x11B000
#define MTK_MCDI_SRAM_MAP_SIZE 0x1000
#define INFRACFG_AO_BASE (IO_PHYS + 0x00001000)
#define GPIO_BASE (IO_PHYS + 0x00005000)
#define SPM_BASE (IO_PHYS + 0x00006000)
#define PMIC_WRAP_BASE (IO_PHYS + 0x00026000)
#define IOCFG_RM_BASE (IO_PHYS + 0x01C20000)
#define IOCFG_BM_BASE (IO_PHYS + 0x01D10000)
#define IOCFG_BL_BASE (IO_PHYS + 0x01D30000)
......@@ -67,11 +72,12 @@
******************************************************************************/
#define PLATFORM_STACK_SIZE 0x800
#define PLAT_MAX_PWR_LVL U(2)
#define PLAT_MAX_PWR_LVL U(3)
#define PLAT_MAX_RET_STATE U(1)
#define PLAT_MAX_OFF_STATE U(2)
#define PLAT_MAX_OFF_STATE U(9)
#define PLATFORM_SYSTEM_COUNT U(1)
#define PLATFORM_MCUSYS_COUNT U(1)
#define PLATFORM_CLUSTER_COUNT U(1)
#define PLATFORM_CLUSTER0_CORE_COUNT U(8)
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
......
......@@ -7,137 +7,255 @@
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/arm/gic_common.h>
#include <drivers/console.h>
#include <lib/mmio.h>
#include <mt_gic_v3.h>
#include <mtk_plat_common.h>
#include <plat_mt_cirq.h>
#include <platform_def.h>
static struct cirq_events cirq_all_events = {
.spi_start = CIRQ_SPI_START
.spi_start = CIRQ_SPI_START,
};
static inline void mt_cirq_write32(uint32_t val, uint32_t addr)
{
mmio_write_32(addr + SYS_CIRQ_BASE, val);
}
static inline uint32_t mt_cirq_read32(uint32_t addr)
{
return mmio_read_32(addr + SYS_CIRQ_BASE);
}
static uint32_t already_cloned;
/*
* cirq_clone_flush_check_store:
* set 1 if we need to enable clone/flush value's check
* mt_irq_mask_restore: restore all interrupts
* @mask: pointer to struct mtk_irq_mask for storing the original mask value.
* Return 0 for success; return negative values for failure.
* (This is ONLY used for the idle current measurement by the factory mode.)
*/
static int32_t cirq_clone_flush_check_val;
int mt_irq_mask_restore(struct mtk_irq_mask *mask)
{
if (mask == NULL) {
return -1;
}
if (mask->header != IRQ_MASK_HEADER) {
return -1;
}
if (mask->footer != IRQ_MASK_FOOTER) {
return -1;
}
/*
* cirq_pattern_clone_flush_check_show: set 1 if we need to do pattern test.
*/
static int32_t cirq_pattern_clone_flush_check_val;
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x4),
mask->mask1);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x8),
mask->mask2);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0xc),
mask->mask3);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x10),
mask->mask4);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x14),
mask->mask5);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x18),
mask->mask6);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x1c),
mask->mask7);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x20),
mask->mask8);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x24),
mask->mask9);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x28),
mask->mask10);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x2c),
mask->mask11);
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x30),
mask->mask12);
/* make sure dist changes happen */
dsb();
/*
* cirq_pattern_clone_flush_check_show: set 1 if we need to do pattern test.
*/
static int32_t cirq_pattern_list;
return 0;
}
/*
* mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
* mt_irq_mask_all: disable all interrupts
* @mask: pointer to struct mtk_irq_mask for storing the original mask value.
* Return 0 for success; return negative values for failure.
* (This is ONLY used for the idle current measurement by the factory mode.)
*/
void mt_cirq_ack_all(void)
int mt_irq_mask_all(struct mtk_irq_mask *mask)
{
unsigned int i;
if (mask != NULL) {
/* for SPI */
mask->mask1 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x4));
mask->mask2 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x8));
mask->mask3 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0xc));
mask->mask4 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x10));
mask->mask5 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x14));
mask->mask6 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x18));
mask->mask7 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x1c));
mask->mask8 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x20));
mask->mask9 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x24));
mask->mask10 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x28));
mask->mask11 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x2c));
mask->mask12 = mmio_read_32((BASE_GICD_BASE +
GICD_ISENABLER + 0x30));
/* for SPI */
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x4),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x8),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0xC),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x10),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x14),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x18),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x1C),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x20),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x24),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x28),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x2c),
0xFFFFFFFF);
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x30),
0xFFFFFFFF);
/* make sure distributor changes happen */
dsb();
mask->header = IRQ_MASK_HEADER;
mask->footer = IRQ_MASK_FOOTER;
for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
mt_cirq_write32(0xFFFFFFFF, CIRQ_ACK_BASE + (i * 4U));
return 0;
} else {
return -1;
}
/* make sure all cirq setting take effect before doing other things */
dmbsy();
}
/*
* mt_cirq_enable: Enable SYS_CIRQ
*/
void mt_cirq_enable(void)
static uint32_t mt_irq_get_pol(uint32_t irq)
{
uint32_t st;
#ifdef CIRQ_WITH_POLARITY
uint32_t reg;
uint32_t base = INT_POL_CTL0;
mt_cirq_ack_all();
if (irq < 32U) {
return 0;
}
st = mt_cirq_read32(CIRQ_CON);
st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS) |
(CIRQ_CON_EDGE_ONLY << CIRQ_CON_EDGE_ONLY_BITS);
reg = ((irq - 32U) / 32U);
mt_cirq_write32((st & CIRQ_CON_BITS_MASK), CIRQ_CON);
return mmio_read_32(base + reg * 4U);
#else
return 0;
#endif
}
/*
* mt_cirq_disable: Disable SYS_CIRQ
*/
void mt_cirq_disable(void)
unsigned int mt_irq_get_sens(unsigned int irq)
{
uint32_t st;
unsigned int config;
st = mt_cirq_read32(CIRQ_CON);
st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
/*
* 2'b10 edge
* 2'b01 level
*/
config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U);
config = (config >> (irq % 16U) * 2U) & 0x3;
mt_cirq_write32((st & CIRQ_CON_BITS_MASK), CIRQ_CON);
return config;
}
/*
* mt_cirq_get_mask: Get the specified SYS_CIRQ mask
* @cirq_num: the SYS_CIRQ number to get
* @return:
* 1: this cirq is masked
* 0: this cirq is umasked
* 2: cirq num is out of range
*/
__attribute__((weak)) unsigned int mt_cirq_get_mask(uint32_t cirq_num)
static void collect_all_wakeup_events(void)
{
uint32_t st;
unsigned int val;
if (cirq_num >= CIRQ_IRQ_NUM) {
ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
return 2;
unsigned int i;
uint32_t gic_irq;
uint32_t cirq;
uint32_t cirq_reg;
uint32_t cirq_offset;
uint32_t mask;
uint32_t pol_mask;
uint32_t irq_offset;
uint32_t irq_mask;
if ((cirq_all_events.wakeup_events == NULL) ||
cirq_all_events.num_of_events == 0U) {
return;
}
st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_MASK_BASE);
val = (st >> (cirq_num % 32U)) & 1U;
return val;
}
/*
* mt_cirq_mask_all: Mask all interrupts on SYS_CIRQ.
for (i = 0U; i < cirq_all_events.num_of_events; i++) {
if (cirq_all_events.wakeup_events[i] > 0U) {
gic_irq = cirq_all_events.wakeup_events[i];
cirq = gic_irq - cirq_all_events.spi_start - 32U;
cirq_reg = cirq / 32U;
cirq_offset = cirq % 32U;
mask = 0x1 << cirq_offset;
irq_offset = gic_irq % 32U;
irq_mask = 0x1 << irq_offset;
/*
* CIRQ default masks all
*/
void mt_cirq_mask_all(void)
{
unsigned int i;
cirq_all_events.table[cirq_reg].mask |= mask;
/*
* CIRQ default pol is low
*/
pol_mask = mt_irq_get_pol(
cirq_all_events.wakeup_events[i])
& irq_mask;
/*
* 0 means rising
*/
if (pol_mask == 0U) {
cirq_all_events.table[cirq_reg].pol |= mask;
}
/*
* CIRQ could monitor edge/level trigger
* cirq register (0: edge, 1: level)
*/
if (mt_irq_get_sens(cirq_all_events.wakeup_events[i])
== SENS_EDGE) {
cirq_all_events.table[cirq_reg].sen |= mask;
}
for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
mt_cirq_write32(0xFFFFFFFF, CIRQ_MASK_SET_BASE + (i * 4U));
cirq_all_events.table[cirq_reg].used = 1U;
cirq_all_events.table[cirq_reg].reg_num = cirq_reg;
}
}
/* make sure all cirq setting take effect before doing other things */
dmbsy();
}
/*
* mt_cirq_unmask_all: Unmask all interrupts on SYS_CIRQ.
* mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
* @cirq_num: the SYS_CIRQ number to set
* @pol: polarity to set
* @return:
* 0: set pol success
* -1: cirq num is out of range
*/
void mt_cirq_unmask_all(void)
#ifdef CIRQ_WITH_POLARITY
static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
{
unsigned int i;
uint32_t base;
uint32_t bit = 1U << (cirq_num % 32U);
for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
mt_cirq_write32(0xFFFFFFFF, CIRQ_MASK_CLR_BASE + (i * 4U));
if (cirq_num >= CIRQ_IRQ_NUM) {
return -1;
}
if (pol == MT_CIRQ_POL_NEG) {
base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
} else if (pol == MT_CIRQ_POL_POS) {
base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
} else {
return -1;
}
/* make sure all cirq setting take effect before doing other things */
dmbsy();
mmio_write_32(base, bit);
return 0;
}
#endif
/*
* mt_cirq_mask: Mask the specified SYS_CIRQ.
......@@ -151,11 +269,11 @@ static int mt_cirq_mask(uint32_t cirq_num)
uint32_t bit = 1U << (cirq_num % 32U);
if (cirq_num >= CIRQ_IRQ_NUM) {
ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
return -1;
}
mt_cirq_write32(bit, (cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE);
mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit);
return 0;
}
......@@ -171,324 +289,264 @@ static int mt_cirq_unmask(uint32_t cirq_num)
uint32_t bit = 1U << (cirq_num % 32U);
if (cirq_num >= CIRQ_IRQ_NUM) {
ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
return -1;
}
mt_cirq_write32(bit, (cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE);
mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit);
return 0;
}
/*
* mt_cirq_set_sens: Set the sensitivity for the specified SYS_CIRQ number.
* @cirq_num: the SYS_CIRQ number to set
* @sens: sensitivity to set
* @return:
* 0: set sens success
* -1: cirq num is out of range
*/
static int mt_cirq_set_sens(uint32_t cirq_num, uint32_t sens)
uint32_t mt_irq_get_en(uint32_t irq)
{
uint32_t base;
uint32_t bit = 1U << (cirq_num % 32U);
uint32_t addr, st, val;
if (cirq_num >= CIRQ_IRQ_NUM) {
ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
return -1;
}
addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U;
st = mmio_read_32(addr);
if (sens == MT_CIRQ_EDGE_SENSITIVE) {
base = (cirq_num / 32U) * 4U + CIRQ_SENS_CLR_BASE;
} else if (sens == MT_CIRQ_LEVEL_SENSITIVE) {
base = (cirq_num / 32U) * 4U + CIRQ_SENS_SET_BASE;
} else {
ERROR("[CIRQ] set_sens invalid sen value %u\n", sens);
return -1;
}
val = (st >> (irq % 32U)) & 1U;
mt_cirq_write32(bit, base);
return 0;
return val;
}
/*
* mt_cirq_get_sens: Get the specified SYS_CIRQ sensitivity
* @cirq_num: the SYS_CIRQ number to get
* @return:
* 1: this cirq is MT_LEVEL_SENSITIVE
* 0: this cirq is MT_EDGE_SENSITIVE
* 2: cirq num is out of range
*/
__attribute__((weak)) unsigned int mt_cirq_get_sens(uint32_t cirq_num)
static void __cirq_fast_clone(void)
{
uint32_t st;
unsigned int val;
struct cirq_reg *reg;
unsigned int i;
if (cirq_num >= CIRQ_IRQ_NUM) {
ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
return 2;
for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
uint32_t cirq_bit;
reg = &cirq_all_events.table[i];
if (reg->used == 0U) {
continue;
}
st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_SENS_BASE);
val = (st >> (cirq_num % 32U)) & 1U;
return val;
}
mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U),
reg->sen);
/*
* mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
* @cirq_num: the SYS_CIRQ number to set
* @pol: polarity to set
* @return:
* 0: set pol success
* -1: cirq num is out of range
*/
static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
{
uint32_t base;
uint32_t bit = 1U << (cirq_num % 32U);
for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
uint32_t val, cirq_id;
uint32_t gic_id;
#ifdef CIRQ_WITH_POLARITY
uint32_t gic_bit, pol;
#endif
uint32_t en;
if (cirq_num >= CIRQ_IRQ_NUM) {
ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
return -1;
val = ((1U << cirq_bit) & reg->mask);
if (val == 0U) {
continue;
}
if (pol == MT_CIRQ_POL_NEG) {
base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
} else if (pol == MT_CIRQ_POL_POS) {
base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
cirq_id = (reg->reg_num << 5U) + cirq_bit;
gic_id = CIRQ_TO_IRQ_NUM(cirq_id);
#ifdef CIRQ_WITH_POLARITY
gic_bit = (0x1U << ((gic_id - 32U) % 32U));
pol = mt_irq_get_pol(gic_id) & gic_bit;
if (pol != 0U) {
mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_NEG);
} else {
ERROR("[CIRQ] set_pol invalid polarity value %u\n", pol);
return -1;
mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_POS);
}
#endif
en = mt_irq_get_en(gic_id);
if (en == 1U) {
mt_cirq_unmask(cirq_id);
} else {
mt_cirq_mask(cirq_id);
}
}
}
mt_cirq_write32(bit, base);
return 0;
}
/*
* mt_cirq_get_pol: Get the specified SYS_CIRQ polarity
* @cirq_num: the SYS_CIRQ number to get
* @return:
* 1: this cirq is MT_CIRQ_POL_POS
* 0: this cirq is MT_CIRQ_POL_NEG
* 2: cirq num is out of range
*/
__attribute__((weak)) unsigned int mt_cirq_get_pol(uint32_t cirq_num)
static void cirq_fast_clone(void)
{
uint32_t st;
unsigned int val;
if (cirq_num >= CIRQ_IRQ_NUM) {
ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
return 2;
if (already_cloned == 0U) {
collect_all_wakeup_events();
already_cloned = 1U;
}
st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_POL_BASE);
val = (st >> (cirq_num % 32U)) & 1U;
return val;
__cirq_fast_clone();
}
void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
{
cirq_all_events.num_of_events = num_of_events;
cirq_all_events.wakeup_events = list;
}
/*
* mt_cirq_get_pending: Get the specified SYS_CIRQ pending
* @cirq_num: the SYS_CIRQ number to get
* @return:
* 1: this cirq is pending
* 0: this cirq is not pending
* 2: cirq num is out of range
* mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
*/
static unsigned int mt_cirq_get_pending(uint32_t cirq_num)
void mt_cirq_clone_gic(void)
{
uint32_t st;
unsigned int val;
cirq_fast_clone();
}
if (cirq_num >= CIRQ_IRQ_NUM) {
ERROR("[CIRQ] %s: invalid cirq %u\n", __func__, cirq_num);
return 2;
uint32_t mt_irq_get_pending_vec(uint32_t start_irq)
{
uint32_t base = 0U;
uint32_t pending_vec = 0U;
uint32_t reg = start_irq / 32U;
uint32_t LSB_num, MSB_num;
uint32_t LSB_vec, MSB_vec;
base = BASE_GICD_BASE;
/* if start_irq is not aligned 32, do some assembling */
MSB_num = start_irq % 32U;
if (MSB_num != 0U) {
LSB_num = 32U - MSB_num;
LSB_vec = mmio_read_32(base + GICD_ISPENDR +
reg * 4U) >> MSB_num;
MSB_vec = mmio_read_32(base + GICD_ISPENDR +
(reg + 1U) * 4U) << LSB_num;
pending_vec = MSB_vec | LSB_vec;
} else {
pending_vec = mmio_read_32(base + GICD_ISPENDR + reg * 4);
}
st = mt_cirq_read32((cirq_num / 32U) * 4U + CIRQ_STA_BASE);
val = (st >> (cirq_num % 32U)) & 1U;
return val;
return pending_vec;
}
static int mt_cirq_get_mask_vec(unsigned int i)
{
return mmio_read_32((i * 4U) + CIRQ_MASK_BASE);
}
/*
* mt_cirq_clone_pol: Copy the polarity setting from GIC to SYS_CIRQ
* mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
*/
void mt_cirq_clone_pol(void)
void mt_cirq_ack_all(void)
{
uint32_t cirq_num;
uint32_t ack_vec, pend_vec, mask_vec;
unsigned int i;
for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) {
mt_cirq_set_pol(cirq_num, MT_CIRQ_POL_POS);
for (i = 0; i < CIRQ_CTRL_REG_NUM; i++) {
/*
* if a irq is pending & not masked, don't ack it
* , since cirq start irq might not be 32 aligned with gic,
* need an exotic API to get proper vector of pending irq
*/
pend_vec = mt_irq_get_pending_vec(CIRQ_SPI_START
+ (i + 1U) * 32U);
mask_vec = mt_cirq_get_mask_vec(i);
/* those should be acked are: "not (pending & not masked)",
*/
ack_vec = (~pend_vec) | mask_vec;
mmio_write_32(CIRQ_ACK_BASE + (i * 4U), ack_vec);
}
}
/*
* make sure all cirq setting take effect
* before doing other things
*/
dsb();
}
/*
* mt_cirq_clone_sens: Copy the sensitivity setting from GIC to SYS_CIRQ
* mt_cirq_enable: Enable SYS_CIRQ
*/
void mt_cirq_clone_sens(void)
void mt_cirq_enable(void)
{
uint32_t cirq_num, irq_num;
uint32_t st, val;
for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) {
irq_num = CIRQ_TO_IRQ_NUM(cirq_num);
uint32_t st;
if ((cirq_num == 0U) || (irq_num % 16U == 0U)) {
st = mmio_read_32(BASE_GICD_BASE + GICD_ICFGR +
(irq_num / 16U * 4U));
}
/* level only */
mt_cirq_ack_all();
val = (st >> ((irq_num % 16U) * 2U)) & 0x2U;
st = mmio_read_32(CIRQ_CON);
/*
* CIRQ could monitor edge/level trigger
*/
st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS);
if (val) {
mt_cirq_set_sens(cirq_num, MT_CIRQ_EDGE_SENSITIVE);
} else {
mt_cirq_set_sens(cirq_num, MT_CIRQ_LEVEL_SENSITIVE);
}
}
mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
}
/*
* mt_cirq_clone_mask: Copy the mask setting from GIC to SYS_CIRQ
* mt_cirq_disable: Disable SYS_CIRQ
*/
void mt_cirq_clone_mask(void)
void mt_cirq_disable(void)
{
uint32_t cirq_num, irq_num;
uint32_t st, val;
uint32_t st;
for (cirq_num = 0U; cirq_num < CIRQ_IRQ_NUM; cirq_num++) {
irq_num = CIRQ_TO_IRQ_NUM(cirq_num);
st = mmio_read_32(CIRQ_CON);
st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
}
if ((cirq_num == 0U) || (irq_num % 32U == 0U)) {
st = mmio_read_32(BASE_GICD_BASE +
GICD_ISENABLER + (irq_num / 32U * 4U));
}
void mt_irq_unmask_for_sleep_ex(uint32_t irq)
{
uint32_t mask;
val = (st >> (irq_num % 32)) & 1U;
mask = 1U << (irq % 32U);
if (val) {
mt_cirq_unmask(cirq_num);
} else {
mt_cirq_mask(cirq_num);
}
}
mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER +
((irq / 32U) * 4U), mask);
}
/*
* mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
*/
void mt_cirq_clone_gic(void)
void mt_cirq_mask_all(void)
{
mt_cirq_clone_sens();
mt_cirq_clone_mask();
unsigned int i;
for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF);
}
dsb();
}
/*
* mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
*/
void mt_cirq_flush(void)
static void cirq_fast_sw_flush(void)
{
struct cirq_reg *reg;
unsigned int i;
unsigned char cirq_p_val = 0U;
unsigned char irq_p_val = 0U;
uint32_t irq_p = 0U;
unsigned char pass = 1U;
uint32_t first_cirq_found = 0U;
uint32_t first_flushed_cirq;
uint32_t first_irq_flushedto;
uint32_t last_fluashed_cirq;
uint32_t last_irq_flushedto;
if (cirq_pattern_clone_flush_check_val == 1U) {
if (cirq_pattern_list < CIRQ_IRQ_NUM) {
mt_cirq_unmask(cirq_pattern_list);
mt_cirq_set_sens(cirq_pattern_list,
MT_CIRQ_EDGE_SENSITIVE);
mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_NEG);
mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_POS);
mt_cirq_set_pol(cirq_pattern_list, MT_CIRQ_POL_NEG);
} else {
ERROR("[CIRQ] no pattern to test,");
ERROR("input pattern first\n");
}
ERROR("[CIRQ] cirq_pattern %u, cirq_p %u,",
cirq_pattern_list,
mt_cirq_get_pending(cirq_pattern_list));
ERROR("cirq_s %u, cirq_con 0x%x\n",
mt_cirq_get_sens(cirq_pattern_list),
mt_cirq_read32(CIRQ_CON));
}
mt_cirq_unmask_all();
for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
uint32_t cirq_bit;
for (i = 0U; i < CIRQ_IRQ_NUM; i++) {
cirq_p_val = mt_cirq_get_pending(i);
if (cirq_p_val) {
mt_irq_set_pending(CIRQ_TO_IRQ_NUM(i));
}
reg = &cirq_all_events.table[i];
if (cirq_clone_flush_check_val == 1U) {
if (cirq_p_val == 0U) {
if (reg->used == 0U) {
continue;
}
irq_p = CIRQ_TO_IRQ_NUM(i);
irq_p_val = mt_irq_get_pending(irq_p);
if (cirq_p_val != irq_p_val) {
ERROR("[CIRQ] CIRQ Flush Failed ");
ERROR("%u(cirq %d)!= %u(gic %d)\n",
cirq_p_val, i, irq_p_val,
CIRQ_TO_IRQ_NUM(i));
pass = 0;
} else {
ERROR("[CIRQ] CIRQ Flush Pass ");
ERROR("%u(cirq %d) = %u(gic %d)\n",
cirq_p_val, i, irq_p_val,
CIRQ_TO_IRQ_NUM(i));
reg->pending = mmio_read_32(CIRQ_STA_BASE +
(reg->reg_num << 2U));
reg->pending &= reg->mask;
for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
uint32_t val, cirq_id;
val = (1U << cirq_bit) & reg->pending;
if (val == 0U) {
continue;
}
if (!first_cirq_found) {
first_flushed_cirq = i;
first_irq_flushedto = irq_p;
first_cirq_found = 1U;
cirq_id = (reg->reg_num << 5U) + cirq_bit;
mt_irq_set_pending(CIRQ_TO_IRQ_NUM(cirq_id));
if (CIRQ_TO_IRQ_NUM(cirq_id) == MD_WDT_IRQ_BIT_ID) {
INFO("Set MD_WDT_IRQ pending in %s\n",
__func__);
}
last_fluashed_cirq = i;
last_irq_flushedto = irq_p;
}
}
}
if (cirq_clone_flush_check_val == 1U) {
if (first_cirq_found) {
ERROR("[CIRQ] The first flush : CIRQ%u to IRQ%u\n",
first_flushed_cirq, first_irq_flushedto);
ERROR("[CIRQ] The last flush : CIRQ%u to IRQ%u\n",
last_fluashed_cirq, last_irq_flushedto);
} else {
ERROR("[CIRQ] There are no pending ");
ERROR("interrupt in CIRQ\n");
ERROR("[CIRQ] so no flush operation happened\n");
}
ERROR("[CIRQ] The Flush Max Range : CIRQ");
ERROR("%d to IRQ%d ~ CIRQ%d to IRQ%d\n", 0U,
CIRQ_TO_IRQ_NUM(0U), CIRQ_IRQ_NUM - 1U,
CIRQ_TO_IRQ_NUM(CIRQ_IRQ_NUM - 1U));
ERROR("[CIRQ] Flush Check %s, Confirm:SPI_START_OFFSET:%d\n",
pass == 1 ? "Pass" : "Failed", CIRQ_SPI_START);
}
/*
* mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
*/
void mt_cirq_flush(void)
{
cirq_fast_sw_flush();
mt_cirq_mask_all();
mt_cirq_ack_all();
}
void mt_cirq_sw_reset(void)
{
#ifdef CIRQ_NEED_SW_RESET
uint32_t st;
st = mt_cirq_read32(CIRQ_CON);
st = mmio_read_32(CIRQ_CON);
st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
mt_cirq_write32(st, CIRQ_CON);
}
void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
{
cirq_all_events.num_of_events = num_of_events;
cirq_all_events.wakeup_events = list;
mmio_write_32(CIRQ_CON, st);
#endif
}
......@@ -5,17 +5,353 @@
*/
/* common headers */
#include <assert.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/gpio.h>
#include <lib/psci/psci.h>
/* mediatek platform specific headers */
/* platform specific headers */
#include <mt_gic_v3.h>
#include <mtk_ptp3_common.h>
#include <mtspmc.h>
#include <plat/common/platform.h>
#include <plat_mtk_lpm.h>
#include <plat_params.h>
#include <plat_pm.h>
#include <pmic.h>
/*
* Cluster state request:
* [0] : The CPU requires cluster power down
* [1] : The CPU requires cluster power on
*/
#define coordinate_cluster(onoff) write_clusterpwrdn_el1(onoff)
#define coordinate_cluster_pwron() coordinate_cluster(1)
#define coordinate_cluster_pwroff() coordinate_cluster(0)
/* platform secure entry point */
static uintptr_t secure_entrypoint;
/* per-CPU power state */
static unsigned int plat_power_state[PLATFORM_CORE_COUNT];
/* platform CPU power domain - ops */
static const struct mt_lpm_tz *plat_mt_pm;
#define plat_mt_pm_invoke(_name, _cpu, _state) ({ \
int ret = -1; \
if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
ret = plat_mt_pm->_name(_cpu, _state); \
} \
ret; })
#define plat_mt_pm_invoke_no_check(_name, _cpu, _state) ({ \
if (plat_mt_pm != NULL && plat_mt_pm->_name != NULL) { \
(void) plat_mt_pm->_name(_cpu, _state); \
} \
})
/*
* Common MTK_platform operations to power on/off a
* CPU in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_cpu_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
plat_mt_pm_invoke_no_check(pwr_cpu_dwn, cpu, state);
if ((psci_get_pstate_pwrlvl(req_pstate) >= MTK_AFFLVL_CLUSTER) ||
(req_pstate == 0U)) { /* hotplug off */
coordinate_cluster_pwroff();
}
/* Prevent interrupts from spuriously waking up this CPU */
mt_gic_rdistif_save();
gicv3_cpuif_disable(cpu);
gicv3_rdistif_off(cpu);
/* PTP3 config */
ptp3_deinit(cpu);
}
static void plat_cpu_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
plat_mt_pm_invoke_no_check(pwr_cpu_on, cpu, state);
coordinate_cluster_pwron();
/* Enable the GIC CPU interface */
gicv3_rdistif_on(cpu);
gicv3_cpuif_enable(cpu);
mt_gic_rdistif_init();
/*
* If mcusys does power down before then restore
* all CPUs' GIC Redistributors
*/
if (IS_MCUSYS_OFF_STATE(state)) {
mt_gic_rdistif_restore_all();
} else {
mt_gic_rdistif_restore();
}
/* PTP3 config */
ptp3_init(cpu);
}
/*
* Common MTK_platform operations to power on/off a
* cluster in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_cluster_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
if (plat_mt_pm_invoke(pwr_cluster_dwn, cpu, state) != 0) {
coordinate_cluster_pwron();
/* TODO: return on fail.
* Add a 'return' here before adding any code following
* the if-block.
*/
}
}
static void plat_cluster_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
if (plat_mt_pm_invoke(pwr_cluster_on, cpu, state) != 0) {
/* TODO: return on fail.
* Add a 'return' here before adding any code following
* the if-block.
*/
}
}
/*
* Common MTK_platform operations to power on/off a
* mcusys in response to a CPU_ON, CPU_OFF or CPU_SUSPEND request.
*/
static void plat_mcusys_pwrdwn_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
if (plat_mt_pm_invoke(pwr_mcusys_dwn, cpu, state) != 0) {
return; /* return on fail */
}
mt_gic_distif_save();
gic_sgi_save_all();
}
static void plat_mcusys_pwron_common(unsigned int cpu,
const psci_power_state_t *state, unsigned int req_pstate)
{
assert(cpu == plat_my_core_pos());
if (plat_mt_pm_invoke(pwr_mcusys_on, cpu, state) != 0) {
return; /* return on fail */
}
mt_gic_init();
mt_gic_distif_restore();
gic_sgi_restore_all();
plat_mt_pm_invoke_no_check(pwr_mcusys_on_finished, cpu, state);
}
/*
* plat_psci_ops implementation
*/
static void plat_cpu_standby(plat_local_state_t cpu_state)
{
uint64_t scr;
scr = read_scr_el3();
write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
isb();
dsb();
wfi();
write_scr_el3(scr);
}
static int plat_power_domain_on(u_register_t mpidr)
{
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
unsigned int cluster = 0U;
if (cpu >= PLATFORM_CORE_COUNT) {
return PSCI_E_INVALID_PARAMS;
}
if (!spm_get_cluster_powerstate(cluster)) {
spm_poweron_cluster(cluster);
}
/* init CPU reset arch as AARCH64 */
mcucfg_init_archstate(cluster, cpu, true);
mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
spm_poweron_cpu(cluster, cpu);
return PSCI_E_SUCCESS;
}
static void plat_power_domain_on_finish(const psci_power_state_t *state)
{
unsigned long mpidr = read_mpidr_el1();
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
assert(cpu < PLATFORM_CORE_COUNT);
/* Allow IRQs to wakeup this core in IDLE flow */
mcucfg_enable_gic_wakeup(0U, cpu);
if (IS_CLUSTER_OFF_STATE(state)) {
plat_cluster_pwron_common(cpu, state, 0U);
}
plat_cpu_pwron_common(cpu, state, 0U);
}
static void plat_power_domain_off(const psci_power_state_t *state)
{
unsigned long mpidr = read_mpidr_el1();
unsigned int cpu = (unsigned int)plat_core_pos_by_mpidr(mpidr);
assert(cpu < PLATFORM_CORE_COUNT);
plat_cpu_pwrdwn_common(cpu, state, 0U);
spm_poweroff_cpu(0U, cpu);
/* prevent unintended IRQs from waking up the hot-unplugged core */
mcucfg_disable_gic_wakeup(0U, cpu);
if (IS_CLUSTER_OFF_STATE(state)) {
plat_cluster_pwrdwn_common(cpu, state, 0U);
}
}
static void plat_power_domain_suspend(const psci_power_state_t *state)
{
unsigned int cpu = plat_my_core_pos();
assert(cpu < PLATFORM_CORE_COUNT);
plat_mt_pm_invoke_no_check(pwr_prompt, cpu, state);
/* Perform the common CPU specific operations */
plat_cpu_pwrdwn_common(cpu, state, plat_power_state[cpu]);
if (IS_CLUSTER_OFF_STATE(state)) {
/* Perform the common cluster specific operations */
plat_cluster_pwrdwn_common(cpu, state, plat_power_state[cpu]);
}
if (IS_MCUSYS_OFF_STATE(state)) {
/* Perform the common mcusys specific operations */
plat_mcusys_pwrdwn_common(cpu, state, plat_power_state[cpu]);
}
}
static void plat_power_domain_suspend_finish(const psci_power_state_t *state)
{
unsigned int cpu = plat_my_core_pos();
assert(cpu < PLATFORM_CORE_COUNT);
if (IS_MCUSYS_OFF_STATE(state)) {
/* Perform the common mcusys specific operations */
plat_mcusys_pwron_common(cpu, state, plat_power_state[cpu]);
}
if (IS_CLUSTER_OFF_STATE(state)) {
/* Perform the common cluster specific operations */
plat_cluster_pwron_common(cpu, state, plat_power_state[cpu]);
}
/* Perform the common CPU specific operations */
plat_cpu_pwron_common(cpu, state, plat_power_state[cpu]);
plat_mt_pm_invoke_no_check(pwr_reflect, cpu, state);
}
static int plat_validate_power_state(unsigned int power_state,
psci_power_state_t *req_state)
{
unsigned int pstate = psci_get_pstate_type(power_state);
unsigned int aff_lvl = psci_get_pstate_pwrlvl(power_state);
unsigned int cpu = plat_my_core_pos();
if (aff_lvl > PLAT_MAX_PWR_LVL) {
return PSCI_E_INVALID_PARAMS;
}
if (pstate == PSTATE_TYPE_STANDBY) {
req_state->pwr_domain_state[0] = PLAT_MAX_RET_STATE;
} else {
unsigned int i;
unsigned int pstate_id = psci_get_pstate_id(power_state);
plat_local_state_t s = MTK_LOCAL_STATE_OFF;
/* Use pstate_id to be power domain state */
if (pstate_id > s) {
s = (plat_local_state_t)pstate_id;
}
for (i = 0U; i <= aff_lvl; i++) {
req_state->pwr_domain_state[i] = s;
}
}
plat_power_state[cpu] = power_state;
return PSCI_E_SUCCESS;
}
static void plat_get_sys_suspend_power_state(psci_power_state_t *req_state)
{
unsigned int lv;
unsigned int cpu = plat_my_core_pos();
for (lv = PSCI_CPU_PWR_LVL; lv <= PLAT_MAX_PWR_LVL; lv++) {
req_state->pwr_domain_state[lv] = PLAT_MAX_OFF_STATE;
}
plat_power_state[cpu] =
psci_make_powerstate(
MT_PLAT_PWR_STATE_SYSTEM_SUSPEND,
PSTATE_TYPE_POWERDOWN, PLAT_MAX_PWR_LVL);
flush_dcache_range((uintptr_t)
&plat_power_state[cpu],
sizeof(plat_power_state[cpu]));
}
static void __dead2 plat_mtk_system_off(void)
{
INFO("MTK System Off\n");
pmic_power_off();
wfi();
ERROR("MTK System Off: operation not handled.\n");
panic();
}
/*******************************************************************************
* MTK handlers to shutdown/reboot the system
******************************************************************************/
static void __dead2 plat_mtk_system_reset(void)
{
struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
......@@ -29,18 +365,35 @@ static void __dead2 plat_mtk_system_reset(void)
panic();
}
/*******************************************************************************
* MTK_platform handler called when an affinity instance is about to be turned
* 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_psci_ops = {
.system_reset = plat_mtk_system_reset,
.cpu_standby = plat_cpu_standby,
.pwr_domain_on = plat_power_domain_on,
.pwr_domain_on_finish = plat_power_domain_on_finish,
.pwr_domain_off = plat_power_domain_off,
.pwr_domain_suspend = plat_power_domain_suspend,
.pwr_domain_suspend_finish = plat_power_domain_suspend_finish,
.system_off = plat_mtk_system_off,
.validate_power_state = plat_validate_power_state,
.get_sys_suspend_power_state = plat_get_sys_suspend_power_state
};
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
*psci_ops = &plat_plat_pm_ops;
*psci_ops = &plat_psci_ops;
secure_entrypoint = sec_entrypoint;
/*
* init the warm reset config for boot CPU
* reset arch as AARCH64
* reset addr as function bl31_warm_entrypoint()
*/
mcucfg_init_archstate(0U, 0U, true);
mcucfg_set_bootaddr(0U, 0U, secure_entrypoint);
spmc_init();
plat_mt_pm = mt_plat_cpu_pm_init();
return 0;
}
/*
* Copyright (c) 2020, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <common/debug.h>
#include <common/runtime_svc.h>
uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
u_register_t x1,
u_register_t x2,
u_register_t x3,
u_register_t x4,
void *cookie,
void *handle,
u_register_t flags)
{
switch (smc_fid) {
default:
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
break;
}
SMC_RET1(handle, SMC_UNK);
}
......@@ -17,6 +17,8 @@ const unsigned char mtk_power_domain_tree_desc[] = {
/* Number of root nodes */
PLATFORM_SYSTEM_COUNT,
/* Number of children for the root node */
PLATFORM_MCUSYS_COUNT,
/* Number of children for the mcusys node */
PLATFORM_CLUSTER_COUNT,
/* Number of children for the first cluster node */
PLATFORM_CLUSTER0_CORE_COUNT,
......
......@@ -10,8 +10,14 @@ MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
-I${MTK_PLAT_SOC}/include/ \
-I${MTK_PLAT_SOC}/drivers/ \
-I${MTK_PLAT_SOC}/drivers/dcm \
-I${MTK_PLAT_SOC}/drivers/gpio/ \
-I${MTK_PLAT_SOC}/drivers/timer/
-I${MTK_PLAT_SOC}/drivers/mcdi/ \
-I${MTK_PLAT_SOC}/drivers/pmic/ \
-I${MTK_PLAT_SOC}/drivers/ptp3/ \
-I${MTK_PLAT_SOC}/drivers/spmc/ \
-I${MTK_PLAT_SOC}/drivers/timer/ \
-I${MTK_PLAT_SOC}/drivers/uart/
GICV3_SUPPORT_GIC600 := 1
include drivers/arm/gic/v3/gicv3.mk
......@@ -23,25 +29,38 @@ PLAT_BL_COMMON_SOURCES := ${GICV3_SOURCES} \
plat/common/plat_psci_common.c
BL31_SOURCES += common/desc_image_load.c \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
drivers/ti/uart/aarch64/16550_console.S \
drivers/gpio/gpio.c \
lib/bl_aux_params/bl_aux_params.c \
lib/cpus/aarch64/cortex_a55.S \
lib/cpus/aarch64/cortex_a76.S \
plat/common/plat_gicv3.c \
${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \
${MTK_PLAT}/common/drivers/uart/uart.c \
${MTK_PLAT}/common/mtk_plat_common.c \
${MTK_PLAT}/common/mtk_sip_svc.c \
${MTK_PLAT}/common/params_setup.c \
${MTK_PLAT_SOC}/aarch64/platform_common.c \
${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
${MTK_PLAT_SOC}/bl31_plat_setup.c \
${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
${MTK_PLAT_SOC}/plat_pm.c \
${MTK_PLAT_SOC}/plat_topology.c \
${MTK_PLAT_SOC}/plat_mt_gic.c \
${MTK_PLAT_SOC}/plat_mt_cirq.c \
${MTK_PLAT_SOC}/plat_sip_calls.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm.c \
${MTK_PLAT_SOC}/drivers/dcm/mtk_dcm_utils.c \
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm.c \
${MTK_PLAT_SOC}/drivers/mcdi/mt_cpu_pm_cpc.c \
${MTK_PLAT_SOC}/drivers/mcdi/mt_mcdi.c \
${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.c \
${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
${MTK_PLAT_SOC}/drivers/timer/mt_timer.c
# Configs for A76 and A55
HW_ASSISTED_COHERENCY := 1
USE_COHERENT_MEM := 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