Merge changes I08cf22df,I535ee414,Ie84cfc96,I8c35ce4e,If7649764, ... into integration
* changes: mediatek: mt8183: Support coreboot configuration mediatek: mt8183: support system reset mediatek: mt8183: pass platform parameters mediatek: mt8183: add GPIO driver mediatek: mt8183: support system off mediatek: mt8183: support CPU hotplug mediatek: mt8183: refine GIC driver
This commit is contained in:
commit
76eac18647
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H
|
||||
#define ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H
|
||||
|
||||
/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */
|
||||
|
||||
#include "../../../lib/bl_aux_params/bl_aux_params_exp.h"
|
||||
|
||||
/* param type */
|
||||
enum bl_aux_mtk_param_type {
|
||||
BL_AUX_PARAM_MTK_RESET_GPIO = BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST,
|
||||
};
|
||||
|
||||
#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H */
|
|
@ -73,4 +73,11 @@
|
|||
******************************************************************************/
|
||||
#define CORTEX_A53_L2MERRSR_EL1 S3_1_C15_C2_3
|
||||
|
||||
/*******************************************************************************
|
||||
* Helper function to access a53_cpuectlr_el1 register on Cortex-A53 CPUs
|
||||
******************************************************************************/
|
||||
#ifndef __ASSEMBLY__
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(a53_cpuectlr_el1, CORTEX_A53_ECTLR_EL1)
|
||||
#endif
|
||||
|
||||
#endif /* CORTEX_A53_H */
|
||||
|
|
|
@ -35,4 +35,11 @@
|
|||
|
||||
#define CORTEX_A73_IMP_DEF_REG2 S3_0_C15_C0_2
|
||||
|
||||
/*******************************************************************************
|
||||
* Helper function to access a73_cpuectlr_el1 register on Cortex-A73 CPUs
|
||||
******************************************************************************/
|
||||
#ifndef __ASSEMBLY__
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(a73_cpuectlr_el1, CORTEX_A73_CPUECTLR_EL1)
|
||||
#endif
|
||||
|
||||
#endif /* CORTEX_A73_H */
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <pmic_wrap_init.h>
|
||||
|
||||
/* pmic wrap module wait_idle and read polling interval (in microseconds) */
|
||||
enum {
|
||||
WAIT_IDLE_POLLING_DELAY_US = 1,
|
||||
READ_POLLING_DELAY_US = 2
|
||||
};
|
||||
|
||||
static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
|
||||
void *wacs_register,
|
||||
void *wacs_vldclr_register,
|
||||
uint32_t *read_reg)
|
||||
{
|
||||
uint32_t reg_rdata;
|
||||
uint32_t retry;
|
||||
|
||||
retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
|
||||
WAIT_IDLE_POLLING_DELAY_US;
|
||||
|
||||
do {
|
||||
udelay(WAIT_IDLE_POLLING_DELAY_US);
|
||||
reg_rdata = mmio_read_32((uintptr_t)wacs_register);
|
||||
/* if last read command timeout,clear vldclr bit
|
||||
* read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
|
||||
* write:FSM_REQ-->idle
|
||||
*/
|
||||
switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
|
||||
RDATA_WACS_FSM_MASK)) {
|
||||
case WACS_FSM_WFVLDCLR:
|
||||
mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
|
||||
ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
|
||||
break;
|
||||
case WACS_FSM_WFDLE:
|
||||
ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
|
||||
break;
|
||||
case WACS_FSM_REQ:
|
||||
ERROR("WACS_FSM = WACS_FSM_REQ\n");
|
||||
break;
|
||||
case WACS_FSM_IDLE:
|
||||
goto done;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
done:
|
||||
if (!retry) /* timeout */
|
||||
return E_PWR_WAIT_IDLE_TIMEOUT;
|
||||
|
||||
if (read_reg)
|
||||
*read_reg = reg_rdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
|
||||
void *wacs_register,
|
||||
uint32_t *read_reg)
|
||||
{
|
||||
uint32_t reg_rdata;
|
||||
uint32_t retry;
|
||||
|
||||
retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
|
||||
|
||||
do {
|
||||
udelay(READ_POLLING_DELAY_US);
|
||||
reg_rdata = mmio_read_32((uintptr_t)wacs_register);
|
||||
|
||||
if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
|
||||
== WACS_FSM_WFVLDCLR)
|
||||
break;
|
||||
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
if (!retry) { /* timeout */
|
||||
ERROR("timeout when waiting for idle\n");
|
||||
return E_PWR_WAIT_IDLE_TIMEOUT_READ;
|
||||
}
|
||||
|
||||
if (read_reg)
|
||||
*read_reg = reg_rdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t pwrap_wacs2(uint32_t write,
|
||||
uint32_t adr,
|
||||
uint32_t wdata,
|
||||
uint32_t *rdata,
|
||||
uint32_t init_check)
|
||||
{
|
||||
uint32_t reg_rdata = 0;
|
||||
uint32_t wacs_write = 0;
|
||||
uint32_t wacs_adr = 0;
|
||||
uint32_t wacs_cmd = 0;
|
||||
uint32_t return_value = 0;
|
||||
|
||||
if (init_check) {
|
||||
reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
|
||||
/* Prevent someone to used pwrap before pwrap init */
|
||||
if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
|
||||
RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
|
||||
ERROR("initialization isn't finished\n");
|
||||
return E_PWR_NOT_INIT_DONE;
|
||||
}
|
||||
}
|
||||
reg_rdata = 0;
|
||||
/* Check IDLE in advance */
|
||||
return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
|
||||
&mtk_pwrap->wacs2_rdata,
|
||||
&mtk_pwrap->wacs2_vldclr,
|
||||
0);
|
||||
if (return_value != 0) {
|
||||
ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
|
||||
goto FAIL;
|
||||
}
|
||||
wacs_write = write << 31;
|
||||
wacs_adr = (adr >> 1) << 16;
|
||||
wacs_cmd = wacs_write | wacs_adr | wdata;
|
||||
|
||||
mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, wacs_cmd);
|
||||
if (write == 0) {
|
||||
if (rdata == NULL) {
|
||||
ERROR("rdata is a NULL pointer\n");
|
||||
return_value = E_PWR_INVALID_ARG;
|
||||
goto FAIL;
|
||||
}
|
||||
return_value = wait_for_state_ready(TIMEOUT_READ,
|
||||
&mtk_pwrap->wacs2_rdata,
|
||||
®_rdata);
|
||||
if (return_value != 0) {
|
||||
ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
|
||||
return_value);
|
||||
goto FAIL;
|
||||
}
|
||||
*rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
|
||||
& RDATA_WACS_RDATA_MASK);
|
||||
mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 1);
|
||||
}
|
||||
FAIL:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/* external API for pmic_wrap user */
|
||||
|
||||
int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
|
||||
{
|
||||
return pwrap_wacs2(0, adr, 0, rdata, 1);
|
||||
}
|
||||
|
||||
int32_t pwrap_write(uint32_t adr, uint32_t wdata)
|
||||
{
|
||||
return pwrap_wacs2(1, adr, wdata, 0, 1);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
|
||||
#include <pmic_wrap_init.h>
|
||||
#include <rtc.h>
|
||||
|
||||
/* RTC busy status polling interval and retry count */
|
||||
enum {
|
||||
RTC_WRTGR_POLLING_DELAY_MS = 10,
|
||||
RTC_WRTGR_POLLING_CNT = 100
|
||||
};
|
||||
|
||||
uint16_t RTC_Read(uint32_t addr)
|
||||
{
|
||||
uint32_t rdata = 0;
|
||||
|
||||
pwrap_read((uint32_t)addr, &rdata);
|
||||
return (uint16_t)rdata;
|
||||
}
|
||||
|
||||
void RTC_Write(uint32_t addr, uint16_t data)
|
||||
{
|
||||
pwrap_write((uint32_t)addr, (uint32_t)data);
|
||||
}
|
||||
|
||||
int32_t rtc_busy_wait(void)
|
||||
{
|
||||
uint64_t retry = RTC_WRTGR_POLLING_CNT;
|
||||
|
||||
do {
|
||||
mdelay(RTC_WRTGR_POLLING_DELAY_MS);
|
||||
if (!(RTC_Read(RTC_BBPU) & RTC_BBPU_CBUSY))
|
||||
return 1;
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
ERROR("[RTC] rtc cbusy time out!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t RTC_Write_Trigger(void)
|
||||
{
|
||||
RTC_Write(RTC_WRTGR, 1);
|
||||
return rtc_busy_wait();
|
||||
}
|
||||
|
||||
int32_t Writeif_unlock(void)
|
||||
{
|
||||
RTC_Write(RTC_PROT, RTC_PROT_UNLOCK1);
|
||||
if (!RTC_Write_Trigger())
|
||||
return 0;
|
||||
RTC_Write(RTC_PROT, RTC_PROT_UNLOCK2);
|
||||
if (!RTC_Write_Trigger())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/bl_aux_params/bl_aux_params.h>
|
||||
#include <common/debug.h>
|
||||
#include <plat_params.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct bl_aux_gpio_info rst_gpio;
|
||||
|
||||
struct bl_aux_gpio_info *plat_get_mtk_gpio_reset(void)
|
||||
{
|
||||
return &rst_gpio;
|
||||
}
|
||||
|
||||
static bool mtk_aux_param_handler(struct bl_aux_param_header *param)
|
||||
{
|
||||
/* Store platform parameters for later processing if needed. */
|
||||
switch (param->type) {
|
||||
case BL_AUX_PARAM_MTK_RESET_GPIO:
|
||||
rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void params_early_setup(u_register_t plat_param_from_bl2)
|
||||
{
|
||||
bl_aux_params_parse(plat_param_from_bl2, mtk_aux_param_handler);
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_PARAMS_H
|
||||
#define PLAT_PARAMS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <export/plat/mediatek/common/plat_params_exp.h>
|
||||
|
||||
struct bl_aux_gpio_info *plat_get_mtk_gpio_reset(void);
|
||||
void params_early_setup(u_register_t plat_param_from_bl2);
|
||||
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -14,9 +14,12 @@
|
|||
#include <drivers/generic_delay_timer.h>
|
||||
#include <mcucfg.h>
|
||||
#include <mt_gic_v3.h>
|
||||
#include <lib/coreboot.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <mtk_plat_common.h>
|
||||
#include <mtspmc.h>
|
||||
#include <plat_debug.h>
|
||||
#include <plat_params.h>
|
||||
#include <plat_private.h>
|
||||
#include <platform_def.h>
|
||||
#include <scu.h>
|
||||
|
@ -73,7 +76,17 @@ void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1,
|
|||
{
|
||||
static console_16550_t console;
|
||||
|
||||
params_early_setup(arg1);
|
||||
|
||||
#if COREBOOT
|
||||
if (coreboot_serial.type)
|
||||
console_16550_register(coreboot_serial.baseaddr,
|
||||
coreboot_serial.input_hertz,
|
||||
coreboot_serial.baud,
|
||||
&console);
|
||||
#else
|
||||
console_16550_register(UART0_BASE, UART_CLOCK, UART_BAUDRATE, &console);
|
||||
#endif
|
||||
|
||||
NOTICE("MT8183 bl31_setup\n");
|
||||
|
||||
|
@ -95,6 +108,10 @@ void bl31_platform_setup(void)
|
|||
|
||||
/* Init mcsi SF */
|
||||
plat_mtk_cci_init_sf();
|
||||
|
||||
#if SPMC_MODE == 1
|
||||
spmc_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <gpio/mtgpio.h>
|
||||
#include <gpio/mtgpio_cfg.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <mcucfg.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <spm.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
/******************************************************************************
|
||||
*Macro Definition
|
||||
******************************************************************************/
|
||||
#define GPIO_MODE_BITS 4
|
||||
#define MAX_GPIO_MODE_PER_REG 8
|
||||
#define MAX_GPIO_REG_BITS 32
|
||||
#define DIR_BASE (GPIO_BASE + 0x000)
|
||||
#define DOUT_BASE (GPIO_BASE + 0x100)
|
||||
#define DIN_BASE (GPIO_BASE + 0x200)
|
||||
#define MODE_BASE (GPIO_BASE + 0x300)
|
||||
#define SET 0x4
|
||||
#define CLR 0x8
|
||||
#define PULLEN_ADDR_OFFSET 0x060
|
||||
#define PULLSEL_ADDR_OFFSET 0x080
|
||||
|
||||
void mt_set_gpio_dir_chip(uint32_t pin, int dir)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
assert(dir < GPIO_DIR_MAX);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
if (dir == GPIO_DIR_IN)
|
||||
mmio_write_32(DIR_BASE + 0x10 * pos + CLR, 1U << bit);
|
||||
else
|
||||
mmio_write_32(DIR_BASE + 0x10 * pos + SET, 1U << bit);
|
||||
}
|
||||
|
||||
int mt_get_gpio_dir_chip(uint32_t pin)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
uint32_t reg;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
reg = mmio_read_32(DIR_BASE + 0x10 * pos);
|
||||
return (((reg & (1U << bit)) != 0) ? GPIO_DIR_OUT : GPIO_DIR_IN);
|
||||
}
|
||||
|
||||
void mt_set_gpio_out_chip(uint32_t pin, int output)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
assert(output < GPIO_OUT_MAX);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
if (output == GPIO_OUT_ZERO)
|
||||
mmio_write_32(DOUT_BASE + 0x10 * pos + CLR, 1U << bit);
|
||||
else
|
||||
mmio_write_32(DOUT_BASE + 0x10 * pos + SET, 1U << bit);
|
||||
}
|
||||
|
||||
int mt_get_gpio_out_chip(uint32_t pin)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
uint32_t reg;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
reg = mmio_read_32(DOUT_BASE + 0x10 * pos);
|
||||
return (((reg & (1U << bit)) != 0) ? 1 : 0);
|
||||
}
|
||||
|
||||
int mt_get_gpio_in_chip(uint32_t pin)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
uint32_t reg;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
reg = mmio_read_32(DIN_BASE + 0x10 * pos);
|
||||
return (((reg & (1U << bit)) != 0) ? 1 : 0);
|
||||
}
|
||||
|
||||
void mt_set_gpio_mode_chip(uint32_t pin, int mode)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
uint32_t data;
|
||||
uint32_t mask;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
assert(mode < GPIO_MODE_MAX);
|
||||
|
||||
mask = (1U << GPIO_MODE_BITS) - 1;
|
||||
|
||||
mode = mode & mask;
|
||||
pos = pin / MAX_GPIO_MODE_PER_REG;
|
||||
bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
|
||||
|
||||
data = mmio_read_32(MODE_BASE + 0x10 * pos);
|
||||
data &= (~(mask << bit));
|
||||
data |= (mode << bit);
|
||||
mmio_write_32(MODE_BASE + 0x10 * pos, data);
|
||||
}
|
||||
|
||||
int mt_get_gpio_mode_chip(uint32_t pin)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
uint32_t data;
|
||||
uint32_t mask;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
mask = (1U << GPIO_MODE_BITS) - 1;
|
||||
|
||||
pos = pin / MAX_GPIO_MODE_PER_REG;
|
||||
bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS;
|
||||
|
||||
data = mmio_read_32(MODE_BASE + 0x10 * pos);
|
||||
return (data >> bit) & mask;
|
||||
}
|
||||
|
||||
int32_t gpio_get_pull_iocfg(uint32_t pin)
|
||||
{
|
||||
switch (pin) {
|
||||
case 0 ... 10:
|
||||
return IOCFG_5_BASE;
|
||||
case 11 ... 12:
|
||||
return IOCFG_0_BASE;
|
||||
case 13 ... 28:
|
||||
return IOCFG_1_BASE;
|
||||
case 43 ... 49:
|
||||
return IOCFG_2_BASE;
|
||||
case 50 ... 60:
|
||||
return IOCFG_3_BASE;
|
||||
case 61 ... 88:
|
||||
return IOCFG_4_BASE;
|
||||
case 89 ... 90:
|
||||
return IOCFG_5_BASE;
|
||||
case 95 ... 106:
|
||||
return IOCFG_5_BASE;
|
||||
case 107 ... 121:
|
||||
return IOCFG_6_BASE;
|
||||
case 134 ... 160:
|
||||
return IOCFG_0_BASE;
|
||||
case 161 ... 166:
|
||||
return IOCFG_1_BASE;
|
||||
case 167 ... 176:
|
||||
return IOCFG_3_BASE;
|
||||
case 177 ... 179:
|
||||
return IOCFG_5_BASE;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t gpio_get_pupd_iocfg(uint32_t pin)
|
||||
{
|
||||
const int32_t offset = 0x0c0;
|
||||
|
||||
switch (pin) {
|
||||
case 29 ... 34:
|
||||
return IOCFG_1_BASE + offset;
|
||||
case 35 ... 42:
|
||||
return IOCFG_2_BASE + offset;
|
||||
case 91 ... 94:
|
||||
return IOCFG_5_BASE + offset;
|
||||
case 122 ... 133:
|
||||
return IOCFG_7_BASE + offset;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int gpio_get_pupd_offset(uint32_t pin)
|
||||
{
|
||||
switch (pin) {
|
||||
case 29 ... 34:
|
||||
return (pin - 29) * 4 % 32;
|
||||
case 35 ... 42:
|
||||
return (pin - 35) * 4 % 32;
|
||||
case 91 ... 94:
|
||||
return (pin - 91) * 4 % 32;
|
||||
case 122 ... 129:
|
||||
return (pin - 122) * 4 % 32;
|
||||
case 130 ... 133:
|
||||
return (pin - 130) * 4 % 32;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void mt_set_gpio_pull_enable_chip(uint32_t pin, int en)
|
||||
{
|
||||
int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
|
||||
int pupd_addr = gpio_get_pupd_iocfg(pin);
|
||||
int pupd_offset = gpio_get_pupd_offset(pin);
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
|
||||
(pupd_offset == (int8_t)-1)));
|
||||
|
||||
if (en == GPIO_PULL_DISABLE) {
|
||||
if (PULL_offset[pin].offset == (int8_t)-1)
|
||||
mmio_clrbits_32(pupd_addr, 3U << pupd_offset);
|
||||
else
|
||||
mmio_clrbits_32(pullen_addr,
|
||||
1U << PULL_offset[pin].offset);
|
||||
} else if (en == GPIO_PULL_ENABLE) {
|
||||
if (PULL_offset[pin].offset == (int8_t)-1) {
|
||||
/* For PUPD+R0+R1 Type, mt_set_gpio_pull_enable
|
||||
* does not know
|
||||
* which one between PU and PD shall be enabled.
|
||||
* Use R0 to guarantee at one resistor is set when lk
|
||||
* apply default setting
|
||||
*/
|
||||
mmio_setbits_32(pupd_addr, 1U << pupd_offset);
|
||||
mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
|
||||
} else {
|
||||
/* For PULLEN + PULLSEL Type */
|
||||
mmio_setbits_32(pullen_addr,
|
||||
1U << PULL_offset[pin].offset);
|
||||
}
|
||||
} else if (en == GPIO_PULL_ENABLE_R0) {
|
||||
assert(!(pupd_offset == (int8_t)-1));
|
||||
mmio_setbits_32(pupd_addr, 1U << pupd_offset);
|
||||
mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 1));
|
||||
} else if (en == GPIO_PULL_ENABLE_R1) {
|
||||
assert(!(pupd_offset == (int8_t)-1));
|
||||
|
||||
mmio_clrbits_32(pupd_addr, 1U << pupd_offset);
|
||||
mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 1));
|
||||
} else if (en == GPIO_PULL_ENABLE_R0R1) {
|
||||
assert(!(pupd_offset == (int8_t)-1));
|
||||
mmio_setbits_32(pupd_addr, 3U << pupd_offset);
|
||||
}
|
||||
}
|
||||
|
||||
int mt_get_gpio_pull_enable_chip(uint32_t pin)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
|
||||
int pupd_addr = gpio_get_pupd_iocfg(pin);
|
||||
int pupd_offset = gpio_get_pupd_offset(pin);
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
|
||||
(pupd_offset == (int8_t)-1)));
|
||||
|
||||
if (PULL_offset[pin].offset == (int8_t)-1) {
|
||||
reg = mmio_read_32(pupd_addr);
|
||||
return ((reg & (3U << pupd_offset)) ? 1 : 0);
|
||||
} else if (pupd_offset == (int8_t)-1) {
|
||||
reg = mmio_read_32(pullen_addr);
|
||||
return ((reg & (1U << PULL_offset[pin].offset)) ? 1 : 0);
|
||||
}
|
||||
|
||||
return -ERINVAL;
|
||||
}
|
||||
|
||||
void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
|
||||
{
|
||||
int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
|
||||
int pupd_addr = gpio_get_pupd_iocfg(pin);
|
||||
int pupd_offset = gpio_get_pupd_offset(pin);
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
assert(!((PULL_offset[pin].offset == (int8_t) -1) &&
|
||||
(pupd_offset == (int8_t)-1)));
|
||||
|
||||
if (sel == GPIO_PULL_NONE) {
|
||||
/* Regard No PULL as PULL disable + pull down */
|
||||
mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_DISABLE);
|
||||
if (PULL_offset[pin].offset == (int8_t)-1)
|
||||
mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
|
||||
else
|
||||
mmio_clrbits_32(pullsel_addr,
|
||||
1U << PULL_offset[pin].offset);
|
||||
} else if (sel == GPIO_PULL_UP) {
|
||||
mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
|
||||
if (PULL_offset[pin].offset == (int8_t)-1)
|
||||
mmio_clrbits_32(pupd_addr, 1U << (pupd_offset + 2));
|
||||
else
|
||||
mmio_setbits_32(pullsel_addr,
|
||||
1U << PULL_offset[pin].offset);
|
||||
} else if (sel == GPIO_PULL_DOWN) {
|
||||
mt_set_gpio_pull_enable_chip(pin, GPIO_PULL_ENABLE);
|
||||
if (PULL_offset[pin].offset == -1)
|
||||
mmio_setbits_32(pupd_addr, 1U << (pupd_offset + 2));
|
||||
else
|
||||
mmio_clrbits_32(pullsel_addr,
|
||||
1U << PULL_offset[pin].offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* get pull-up or pull-down, regardless of resistor value */
|
||||
int mt_get_gpio_pull_select_chip(uint32_t pin)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
int pullen_addr = gpio_get_pull_iocfg(pin) + PULLEN_ADDR_OFFSET;
|
||||
int pullsel_addr = gpio_get_pull_iocfg(pin) + PULLSEL_ADDR_OFFSET;
|
||||
int pupd_addr = gpio_get_pupd_iocfg(pin);
|
||||
int pupd_offset = gpio_get_pupd_offset(pin);
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
assert(!((PULL_offset[pin].offset == (int8_t)-1) &&
|
||||
(pupd_offset == (int8_t)-1)));
|
||||
|
||||
if (PULL_offset[pin].offset == (int8_t)-1) {
|
||||
reg = mmio_read_32(pupd_addr);
|
||||
if (reg & (3U << pupd_offset)) {
|
||||
reg = mmio_read_32(pupd_addr);
|
||||
/* Reg value: 0 for PU, 1 for PD -->
|
||||
* reverse return value */
|
||||
return ((reg & (1U << (pupd_offset + 2))) ?
|
||||
GPIO_PULL_DOWN : GPIO_PULL_UP);
|
||||
} else {
|
||||
return GPIO_PULL_NONE;
|
||||
}
|
||||
} else if (pupd_offset == (int8_t)-1) {
|
||||
reg = mmio_read_32(pullen_addr);
|
||||
if ((reg & (1U << PULL_offset[pin].offset))) {
|
||||
reg = mmio_read_32(pullsel_addr);
|
||||
return ((reg & (1U << PULL_offset[pin].offset)) ?
|
||||
GPIO_PULL_UP : GPIO_PULL_DOWN);
|
||||
} else {
|
||||
return GPIO_PULL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
return -ERINVAL;
|
||||
}
|
||||
|
||||
void mt_set_gpio_dir(int gpio, int direction)
|
||||
{
|
||||
mt_set_gpio_dir_chip((uint32_t)gpio, direction);
|
||||
}
|
||||
|
||||
int mt_get_gpio_dir(int gpio)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
return mt_get_gpio_dir_chip(pin);
|
||||
}
|
||||
|
||||
void mt_set_gpio_pull(int gpio, int pull)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
mt_set_gpio_pull_select_chip(pin, pull);
|
||||
}
|
||||
|
||||
int mt_get_gpio_pull(int gpio)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
return mt_get_gpio_pull_select_chip(pin);
|
||||
}
|
||||
|
||||
void mt_set_gpio_out(int gpio, int value)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
mt_set_gpio_out_chip(pin, value);
|
||||
}
|
||||
|
||||
int mt_get_gpio_out(int gpio)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
return mt_get_gpio_out_chip(pin);
|
||||
}
|
||||
|
||||
int mt_get_gpio_in(int gpio)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
return mt_get_gpio_in_chip(pin);
|
||||
}
|
||||
|
||||
void mt_set_gpio_mode(int gpio, int mode)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
mt_set_gpio_mode_chip(pin, mode);
|
||||
}
|
||||
|
||||
int mt_get_gpio_mode(int gpio)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
return mt_get_gpio_mode_chip(pin);
|
||||
}
|
||||
|
||||
const gpio_ops_t mtgpio_ops = {
|
||||
.get_direction = mt_get_gpio_dir,
|
||||
.set_direction = mt_set_gpio_dir,
|
||||
.get_value = mt_get_gpio_in,
|
||||
.set_value = mt_set_gpio_out,
|
||||
.set_pull = mt_set_gpio_pull,
|
||||
.get_pull = mt_get_gpio_pull,
|
||||
};
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_GPIO_H
|
||||
#define MT_GPIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
/* Error Code No. */
|
||||
#define RSUCCESS 0
|
||||
#define ERACCESS 1
|
||||
#define ERINVAL 2
|
||||
#define ERWRAPPER 3
|
||||
#define MAX_GPIO_PIN MT_GPIO_BASE_MAX
|
||||
|
||||
/* Enumeration for GPIO pin */
|
||||
typedef enum GPIO_PIN {
|
||||
GPIO_UNSUPPORTED = -1,
|
||||
|
||||
GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6, GPIO7,
|
||||
GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14, GPIO15,
|
||||
GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23,
|
||||
GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30, GPIO31,
|
||||
GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38, GPIO39,
|
||||
GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46, GPIO47,
|
||||
GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54, GPIO55,
|
||||
GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62, GPIO63,
|
||||
GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70, GPIO71,
|
||||
GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78, GPIO79,
|
||||
GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86, GPIO87,
|
||||
GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94, GPIO95,
|
||||
GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102, GPIO103,
|
||||
GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110, GPIO111,
|
||||
GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118, GPIO119,
|
||||
GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126, GPIO127,
|
||||
GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134, GPIO135,
|
||||
GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142, GPIO143,
|
||||
GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150, GPIO151,
|
||||
GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158, GPIO159,
|
||||
GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166, GPIO167,
|
||||
GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174, GPIO175,
|
||||
GPIO176, GPIO177, GPIO178, GPIO179,
|
||||
MT_GPIO_BASE_MAX
|
||||
} GPIO_PIN;
|
||||
|
||||
/* GPIO MODE CONTROL VALUE*/
|
||||
typedef enum {
|
||||
GPIO_MODE_UNSUPPORTED = -1,
|
||||
GPIO_MODE_GPIO = 0,
|
||||
GPIO_MODE_00 = 0,
|
||||
GPIO_MODE_01,
|
||||
GPIO_MODE_02,
|
||||
GPIO_MODE_03,
|
||||
GPIO_MODE_04,
|
||||
GPIO_MODE_05,
|
||||
GPIO_MODE_06,
|
||||
GPIO_MODE_07,
|
||||
|
||||
GPIO_MODE_MAX,
|
||||
GPIO_MODE_DEFAULT = GPIO_MODE_00,
|
||||
} GPIO_MODE;
|
||||
|
||||
/* GPIO DIRECTION */
|
||||
typedef enum {
|
||||
GPIO_DIR_UNSUPPORTED = -1,
|
||||
GPIO_DIR_OUT = 0,
|
||||
GPIO_DIR_IN = 1,
|
||||
GPIO_DIR_MAX,
|
||||
GPIO_DIR_DEFAULT = GPIO_DIR_IN,
|
||||
} GPIO_DIR;
|
||||
|
||||
/* GPIO PULL ENABLE*/
|
||||
typedef enum {
|
||||
GPIO_PULL_EN_UNSUPPORTED = -1,
|
||||
GPIO_PULL_DISABLE = 0,
|
||||
GPIO_PULL_ENABLE = 1,
|
||||
GPIO_PULL_ENABLE_R0 = 2,
|
||||
GPIO_PULL_ENABLE_R1 = 3,
|
||||
GPIO_PULL_ENABLE_R0R1 = 4,
|
||||
|
||||
GPIO_PULL_EN_MAX,
|
||||
GPIO_PULL_EN_DEFAULT = GPIO_PULL_ENABLE,
|
||||
} GPIO_PULL_EN;
|
||||
|
||||
/* GPIO PULL-UP/PULL-DOWN*/
|
||||
typedef enum {
|
||||
GPIO_PULL_UNSUPPORTED = -1,
|
||||
GPIO_PULL_NONE = 0,
|
||||
GPIO_PULL_UP = 1,
|
||||
GPIO_PULL_DOWN = 2,
|
||||
GPIO_PULL_MAX,
|
||||
GPIO_PULL_DEFAULT = GPIO_PULL_DOWN
|
||||
} GPIO_PULL;
|
||||
|
||||
/* GPIO OUTPUT */
|
||||
typedef enum {
|
||||
GPIO_OUT_UNSUPPORTED = -1,
|
||||
GPIO_OUT_ZERO = 0,
|
||||
GPIO_OUT_ONE = 1,
|
||||
|
||||
GPIO_OUT_MAX,
|
||||
GPIO_OUT_DEFAULT = GPIO_OUT_ZERO,
|
||||
GPIO_DATA_OUT_DEFAULT = GPIO_OUT_ZERO, /*compatible with DCT*/
|
||||
} GPIO_OUT;
|
||||
|
||||
/* GPIO INPUT */
|
||||
typedef enum {
|
||||
GPIO_IN_UNSUPPORTED = -1,
|
||||
GPIO_IN_ZERO = 0,
|
||||
GPIO_IN_ONE = 1,
|
||||
|
||||
GPIO_IN_MAX,
|
||||
} GPIO_IN;
|
||||
|
||||
typedef struct {
|
||||
uint32_t val;
|
||||
uint32_t set;
|
||||
uint32_t rst;
|
||||
uint32_t _align1;
|
||||
} VAL_REGS;
|
||||
|
||||
typedef struct {
|
||||
VAL_REGS dir[6]; /*0x0000 ~ 0x005F: 96 bytes */
|
||||
uint8_t rsv00[160]; /*0x0060 ~ 0x00FF: 160 bytes */
|
||||
VAL_REGS dout[6]; /*0x0100 ~ 0x015F: 96 bytes */
|
||||
uint8_t rsv01[160]; /*0x0160 ~ 0x01FF: 160 bytes */
|
||||
VAL_REGS din[6]; /*0x0200 ~ 0x025F: 96 bytes */
|
||||
uint8_t rsv02[160]; /*0x0260 ~ 0x02FF: 160 bytes */
|
||||
VAL_REGS mode[23]; /*0x0300 ~ 0x046F: 368 bytes */
|
||||
} GPIO_REGS;
|
||||
|
||||
/* GPIO Driver interface */
|
||||
/*direction*/
|
||||
void mt_set_gpio_dir(int gpio, int direction);
|
||||
int mt_get_gpio_dir(int gpio);
|
||||
|
||||
/*pull select*/
|
||||
void mt_set_gpio_pull(int gpio, int pull);
|
||||
int mt_get_gpio_pull(int gpio);
|
||||
|
||||
/*input/output*/
|
||||
void mt_set_gpio_out(int gpio, int value);
|
||||
int mt_get_gpio_out(int gpio);
|
||||
int mt_get_gpio_in(int gpio);
|
||||
|
||||
/*mode control*/
|
||||
void mt_set_gpio_mode(int gpio, int mode);
|
||||
int mt_get_gpio_mode(int gpio);
|
||||
|
||||
#endif /* MT_GPIO_H */
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_GPIO_CFG_H
|
||||
#define MT_GPIO_CFG_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
#define IOCFG_0_BASE 0x11F20000
|
||||
#define IOCFG_1_BASE 0x11E80000
|
||||
#define IOCFG_2_BASE 0x11E70000
|
||||
#define IOCFG_3_BASE 0x11E90000
|
||||
#define IOCFG_4_BASE 0x11D30000
|
||||
#define IOCFG_5_BASE 0x11D20000
|
||||
#define IOCFG_6_BASE 0x11C50000
|
||||
#define IOCFG_7_BASE 0x11F30000
|
||||
|
||||
typedef struct {
|
||||
int8_t offset;
|
||||
} PIN_offset;
|
||||
|
||||
PIN_offset PULL_offset[] = {
|
||||
/* 0 */ {6},
|
||||
/* 1 */ {7},
|
||||
/* 2 */ {8},
|
||||
/* 3 */ {9},
|
||||
/* 4 */ {11},
|
||||
/* 5 */ {12},
|
||||
/* 6 */ {13},
|
||||
/* 7 */ {14},
|
||||
/* 8 */ {0},
|
||||
/* 9 */ {26},
|
||||
/* 10 */ {27},
|
||||
/* 11 */ {10},
|
||||
/* 12 */ {17},
|
||||
/* 13 */ {6},
|
||||
/* 14 */ {7},
|
||||
/* 15 */ {8},
|
||||
/* 16 */ {9},
|
||||
/* 17 */ {10},
|
||||
/* 18 */ {11},
|
||||
/* 19 */ {12},
|
||||
/* 20 */ {13},
|
||||
/* 21 */ {14},
|
||||
/* 22 */ {15},
|
||||
/* 23 */ {16},
|
||||
/* 24 */ {17},
|
||||
/* 25 */ {18},
|
||||
/* 26 */ {19},
|
||||
/* 27 */ {20},
|
||||
/* 28 */ {21},
|
||||
/* 29 */ {-1},
|
||||
/* 30 */ {-1},
|
||||
/* 31 */ {-1},
|
||||
/* 32 */ {-1},
|
||||
/* 33 */ {-1},
|
||||
/* 34 */ {-1},
|
||||
/* 35 */ {-1},
|
||||
/* 36 */ {-1},
|
||||
/* 37 */ {-1},
|
||||
/* 38 */ {-1},
|
||||
/* 39 */ {-1},
|
||||
/* 40 */ {-1},
|
||||
/* 41 */ {-1},
|
||||
/* 42 */ {-1},
|
||||
/* 43 */ {8},
|
||||
/* 44 */ {9},
|
||||
/* 45 */ {10},
|
||||
/* 46 */ {11},
|
||||
/* 47 */ {12},
|
||||
/* 48 */ {13},
|
||||
/* 49 */ {14},
|
||||
/* 50 */ {0},
|
||||
/* 51 */ {1},
|
||||
/* 52 */ {2},
|
||||
/* 53 */ {3},
|
||||
/* 54 */ {4},
|
||||
/* 55 */ {5},
|
||||
/* 56 */ {6},
|
||||
/* 57 */ {7},
|
||||
/* 58 */ {8},
|
||||
/* 59 */ {9},
|
||||
/* 60 */ {10},
|
||||
/* 61 */ {0},
|
||||
/* 62 */ {1},
|
||||
/* 63 */ {2},
|
||||
/* 64 */ {3},
|
||||
/* 65 */ {4},
|
||||
/* 66 */ {5},
|
||||
/* 67 */ {6},
|
||||
/* 68 */ {7},
|
||||
/* 69 */ {8},
|
||||
/* 70 */ {9},
|
||||
/* 71 */ {10},
|
||||
/* 72 */ {11},
|
||||
/* 73 */ {12},
|
||||
/* 74 */ {13},
|
||||
/* 75 */ {14},
|
||||
/* 76 */ {15},
|
||||
/* 77 */ {16},
|
||||
/* 78 */ {17},
|
||||
/* 79 */ {18},
|
||||
/* 80 */ {19},
|
||||
/* 81 */ {20},
|
||||
/* 82 */ {21},
|
||||
/* 83 */ {22},
|
||||
/* 84 */ {23},
|
||||
/* 85 */ {24},
|
||||
/* 86 */ {25},
|
||||
/* 87 */ {26},
|
||||
/* 88 */ {27},
|
||||
/* 89 */ {24},
|
||||
/* 90 */ {1},
|
||||
/* 91 */ {-1},
|
||||
/* 92 */ {-1},
|
||||
/* 93 */ {-1},
|
||||
/* 94 */ {-1},
|
||||
/* 95 */ {15},
|
||||
/* 96 */ {17},
|
||||
/* 97 */ {18},
|
||||
/* 98 */ {19},
|
||||
/* 99 */ {20},
|
||||
/* 100 */ {21},
|
||||
/* 101 */ {22},
|
||||
/* 102 */ {23},
|
||||
/* 103 */ {28},
|
||||
/* 104 */ {29},
|
||||
/* 105 */ {30},
|
||||
/* 106 */ {31},
|
||||
/* 107 */ {0},
|
||||
/* 108 */ {1},
|
||||
/* 109 */ {2},
|
||||
/* 110 */ {3},
|
||||
/* 111 */ {4},
|
||||
/* 112 */ {5},
|
||||
/* 113 */ {6},
|
||||
/* 114 */ {7},
|
||||
/* 115 */ {8},
|
||||
/* 116 */ {9},
|
||||
/* 117 */ {10},
|
||||
/* 118 */ {11},
|
||||
/* 119 */ {12},
|
||||
/* 120 */ {13},
|
||||
/* 121 */ {14},
|
||||
/* 122 */ {-1},
|
||||
/* 123 */ {-1},
|
||||
/* 124 */ {-1},
|
||||
/* 125 */ {-1},
|
||||
/* 126 */ {-1},
|
||||
/* 127 */ {-1},
|
||||
/* 128 */ {-1},
|
||||
/* 129 */ {-1},
|
||||
/* 130 */ {-1},
|
||||
/* 131 */ {-1},
|
||||
/* 132 */ {-1},
|
||||
/* 133 */ {-1},
|
||||
/* 134 */ {0},
|
||||
/* 135 */ {1},
|
||||
/* 136 */ {2},
|
||||
/* 137 */ {3},
|
||||
/* 138 */ {4},
|
||||
/* 139 */ {5},
|
||||
/* 140 */ {6},
|
||||
/* 141 */ {7},
|
||||
/* 142 */ {8},
|
||||
/* 143 */ {9},
|
||||
/* 144 */ {11},
|
||||
/* 145 */ {12},
|
||||
/* 146 */ {13},
|
||||
/* 147 */ {14},
|
||||
/* 148 */ {15},
|
||||
/* 149 */ {16},
|
||||
/* 150 */ {18},
|
||||
/* 151 */ {19},
|
||||
/* 152 */ {20},
|
||||
/* 153 */ {21},
|
||||
/* 154 */ {22},
|
||||
/* 155 */ {23},
|
||||
/* 156 */ {24},
|
||||
/* 157 */ {25},
|
||||
/* 158 */ {26},
|
||||
/* 159 */ {27},
|
||||
/* 160 */ {28},
|
||||
/* 161 */ {0},
|
||||
/* 162 */ {1},
|
||||
/* 163 */ {2},
|
||||
/* 164 */ {3},
|
||||
/* 165 */ {4},
|
||||
/* 166 */ {5},
|
||||
/* 167 */ {11},
|
||||
/* 168 */ {12},
|
||||
/* 169 */ {13},
|
||||
/* 170 */ {14},
|
||||
/* 171 */ {15},
|
||||
/* 172 */ {16},
|
||||
/* 173 */ {17},
|
||||
/* 174 */ {18},
|
||||
/* 175 */ {19},
|
||||
/* 176 */ {20},
|
||||
/* 177 */ {10},
|
||||
/* 178 */ {16},
|
||||
/* 179 */ {25}
|
||||
};
|
||||
#endif /* MT_GPIO_CFG_H */
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <pmic_wrap_init.h>
|
||||
#include <pmic.h>
|
||||
|
||||
void wk_pmic_enable_sdn_delay(void)
|
||||
{
|
||||
uint32_t con;
|
||||
|
||||
pwrap_write(PMIC_TMA_KEY, 0x9CA7);
|
||||
pwrap_read(PMIC_PSEQ_ELR11, &con);
|
||||
con &= ~PMIC_RG_SDN_DLY_ENB;
|
||||
pwrap_write(PMIC_PSEQ_ELR11, con);
|
||||
pwrap_write(PMIC_TMA_KEY, 0);
|
||||
}
|
||||
|
||||
void pmic_power_off(void)
|
||||
{
|
||||
pwrap_write(PMIC_PWRHOLD, 0x0);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PMIC_H
|
||||
#define PMIC_H
|
||||
|
||||
enum {
|
||||
PMIC_TMA_KEY = 0x03a8,
|
||||
PMIC_PWRHOLD = 0x0a08,
|
||||
PMIC_PSEQ_ELR11 = 0x0a62
|
||||
};
|
||||
|
||||
enum {
|
||||
PMIC_RG_SDN_DLY_ENB = 1U << 10
|
||||
};
|
||||
|
||||
/* external API */
|
||||
void wk_pmic_enable_sdn_delay(void);
|
||||
void pmic_power_off(void);
|
||||
|
||||
#endif /* PMIC_H */
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PMIC_WRAP_INIT_H
|
||||
#define PMIC_WRAP_INIT_H
|
||||
|
||||
#include <platform_def.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* external API */
|
||||
int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
|
||||
int32_t pwrap_write(uint32_t adr, uint32_t wdata);
|
||||
|
||||
static struct mt8183_pmic_wrap_regs *const mtk_pwrap =
|
||||
(void *)PMIC_WRAP_BASE;
|
||||
|
||||
/* timeout setting */
|
||||
enum {
|
||||
TIMEOUT_READ = 255, /* us */
|
||||
TIMEOUT_WAIT_IDLE = 255 /* us */
|
||||
};
|
||||
|
||||
/* PMIC_WRAP registers */
|
||||
struct mt8183_pmic_wrap_regs {
|
||||
uint32_t reserved[776];
|
||||
uint32_t wacs2_cmd;
|
||||
uint32_t wacs2_rdata;
|
||||
uint32_t wacs2_vldclr;
|
||||
uint32_t reserved1[4];
|
||||
};
|
||||
|
||||
enum {
|
||||
RDATA_WACS_RDATA_SHIFT = 0,
|
||||
RDATA_WACS_FSM_SHIFT = 16,
|
||||
RDATA_WACS_REQ_SHIFT = 19,
|
||||
RDATA_SYNC_IDLE_SHIFT,
|
||||
RDATA_INIT_DONE_SHIFT,
|
||||
RDATA_SYS_IDLE_SHIFT,
|
||||
};
|
||||
|
||||
enum {
|
||||
RDATA_WACS_RDATA_MASK = 0xffff,
|
||||
RDATA_WACS_FSM_MASK = 0x7,
|
||||
RDATA_WACS_REQ_MASK = 0x1,
|
||||
RDATA_SYNC_IDLE_MASK = 0x1,
|
||||
RDATA_INIT_DONE_MASK = 0x1,
|
||||
RDATA_SYS_IDLE_MASK = 0x1,
|
||||
};
|
||||
|
||||
/* WACS_FSM */
|
||||
enum {
|
||||
WACS_FSM_IDLE = 0x00,
|
||||
WACS_FSM_REQ = 0x02,
|
||||
WACS_FSM_WFDLE = 0x04,
|
||||
WACS_FSM_WFVLDCLR = 0x06,
|
||||
WACS_INIT_DONE = 0x01,
|
||||
WACS_SYNC_IDLE = 0x01,
|
||||
WACS_SYNC_BUSY = 0x00
|
||||
};
|
||||
|
||||
/* error information flag */
|
||||
enum {
|
||||
E_PWR_INVALID_ARG = 1,
|
||||
E_PWR_INVALID_RW = 2,
|
||||
E_PWR_INVALID_ADDR = 3,
|
||||
E_PWR_INVALID_WDAT = 4,
|
||||
E_PWR_INVALID_OP_MANUAL = 5,
|
||||
E_PWR_NOT_IDLE_STATE = 6,
|
||||
E_PWR_NOT_INIT_DONE = 7,
|
||||
E_PWR_NOT_INIT_DONE_READ = 8,
|
||||
E_PWR_WAIT_IDLE_TIMEOUT = 9,
|
||||
E_PWR_WAIT_IDLE_TIMEOUT_READ = 10,
|
||||
E_PWR_INIT_SIDLY_FAIL = 11,
|
||||
E_PWR_RESET_TIMEOUT = 12,
|
||||
E_PWR_TIMEOUT = 13,
|
||||
E_PWR_INIT_RESET_SPI = 20,
|
||||
E_PWR_INIT_SIDLY = 21,
|
||||
E_PWR_INIT_REG_CLOCK = 22,
|
||||
E_PWR_INIT_ENABLE_PMIC = 23,
|
||||
E_PWR_INIT_DIO = 24,
|
||||
E_PWR_INIT_CIPHER = 25,
|
||||
E_PWR_INIT_WRITE_TEST = 26,
|
||||
E_PWR_INIT_ENABLE_CRC = 27,
|
||||
E_PWR_INIT_ENABLE_DEWRAP = 28,
|
||||
E_PWR_INIT_ENABLE_EVENT = 29,
|
||||
E_PWR_READ_TEST_FAIL = 30,
|
||||
E_PWR_WRITE_TEST_FAIL = 31,
|
||||
E_PWR_SWITCH_DIO = 32
|
||||
};
|
||||
|
||||
#endif /* PMIC_WRAP_INIT_H */
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <rtc.h>
|
||||
|
||||
static void RTC_Config_Interface(uint32_t addr, uint16_t data,
|
||||
uint16_t MASK, uint16_t SHIFT)
|
||||
{
|
||||
uint16_t pmic_reg = 0;
|
||||
|
||||
pmic_reg = RTC_Read(addr);
|
||||
|
||||
pmic_reg &= ~(MASK << SHIFT);
|
||||
pmic_reg |= (data << SHIFT);
|
||||
|
||||
RTC_Write(addr, pmic_reg);
|
||||
}
|
||||
|
||||
static void rtc_disable_2sec_reboot(void)
|
||||
{
|
||||
uint16_t reboot;
|
||||
|
||||
reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
|
||||
~RTC_BBPU_AUTO_PDN_SEL;
|
||||
RTC_Write(RTC_AL_SEC, reboot);
|
||||
RTC_Write_Trigger();
|
||||
}
|
||||
|
||||
static void rtc_xosc_write(uint16_t val, bool reload)
|
||||
{
|
||||
uint16_t bbpu;
|
||||
|
||||
RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1);
|
||||
rtc_busy_wait();
|
||||
RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2);
|
||||
rtc_busy_wait();
|
||||
|
||||
RTC_Write(RTC_OSC32CON, val);
|
||||
rtc_busy_wait();
|
||||
|
||||
if (reload) {
|
||||
bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
|
||||
RTC_Write(RTC_BBPU, bbpu);
|
||||
RTC_Write_Trigger();
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_enable_k_eosc(void)
|
||||
{
|
||||
uint16_t osc32;
|
||||
uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */
|
||||
|
||||
/* Truning on eosc cali mode clock */
|
||||
RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
|
||||
PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK,
|
||||
PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT);
|
||||
RTC_Config_Interface(PMIC_RG_TOP_CON, 1,
|
||||
PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK,
|
||||
PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT);
|
||||
RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0,
|
||||
PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
|
||||
PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
|
||||
|
||||
switch (rtc_eosc_cali_td) {
|
||||
case 1:
|
||||
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3,
|
||||
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
|
||||
break;
|
||||
case 2:
|
||||
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4,
|
||||
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
|
||||
break;
|
||||
case 4:
|
||||
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5,
|
||||
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
|
||||
break;
|
||||
case 16:
|
||||
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7,
|
||||
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
|
||||
break;
|
||||
default:
|
||||
RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6,
|
||||
PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT);
|
||||
break;
|
||||
}
|
||||
/* Switch the DCXO from 32k-less mode to RTC mode,
|
||||
* otherwise, EOSC cali will fail
|
||||
*/
|
||||
/* RTC mode will have only OFF mode and FPM */
|
||||
RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK,
|
||||
PMIC_RG_XO_EN32K_MAN_SHIFT);
|
||||
RTC_Write(RTC_BBPU,
|
||||
RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
|
||||
RTC_Write_Trigger();
|
||||
/* Enable K EOSC mode for normal power off and then plug out battery */
|
||||
RTC_Write(RTC_AL_YEA, ((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
|
||||
& (~RTC_K_EOSC_RSV_1)) | RTC_K_EOSC_RSV_2);
|
||||
RTC_Write_Trigger();
|
||||
|
||||
osc32 = RTC_Read(RTC_OSC32CON);
|
||||
rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true);
|
||||
INFO("[RTC] RTC_enable_k_eosc\n");
|
||||
}
|
||||
|
||||
void rtc_power_off_sequence(void)
|
||||
{
|
||||
uint16_t bbpu;
|
||||
|
||||
rtc_disable_2sec_reboot();
|
||||
rtc_enable_k_eosc();
|
||||
|
||||
/* clear alarm */
|
||||
bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN;
|
||||
if (Writeif_unlock()) {
|
||||
RTC_Write(RTC_BBPU, bbpu);
|
||||
|
||||
RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
|
||||
RTC_Write_Trigger();
|
||||
mdelay(1);
|
||||
|
||||
bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
|
||||
RTC_Write(RTC_BBPU, bbpu);
|
||||
RTC_Write_Trigger();
|
||||
INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n",
|
||||
RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN),
|
||||
RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef RTC_H
|
||||
#define RTC_H
|
||||
|
||||
/* RTC registers */
|
||||
enum {
|
||||
RTC_BBPU = 0x0588,
|
||||
RTC_IRQ_STA = 0x058A,
|
||||
RTC_IRQ_EN = 0x058C,
|
||||
RTC_CII_EN = 0x058E
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_AL_SEC = 0x05A0,
|
||||
RTC_AL_MIN = 0x05A2,
|
||||
RTC_AL_HOU = 0x05A4,
|
||||
RTC_AL_DOM = 0x05A6,
|
||||
RTC_AL_DOW = 0x05A8,
|
||||
RTC_AL_MTH = 0x05AA,
|
||||
RTC_AL_YEA = 0x05AC,
|
||||
RTC_AL_MASK = 0x0590
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_OSC32CON = 0x05AE,
|
||||
RTC_CON = 0x05C4,
|
||||
RTC_WRTGR = 0x05C2
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_PDN1 = 0x05B4,
|
||||
RTC_PDN2 = 0x05B6,
|
||||
RTC_SPAR0 = 0x05B8,
|
||||
RTC_SPAR1 = 0x05BA,
|
||||
RTC_PROT = 0x05BC,
|
||||
RTC_DIFF = 0x05BE,
|
||||
RTC_CALI = 0x05C0
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_OSC32CON_UNLOCK1 = 0x1A57,
|
||||
RTC_OSC32CON_UNLOCK2 = 0x2B68
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_PROT_UNLOCK1 = 0x586A,
|
||||
RTC_PROT_UNLOCK2 = 0x9136
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_BBPU_PWREN = 1U << 0,
|
||||
RTC_BBPU_CLR = 1U << 1,
|
||||
RTC_BBPU_INIT = 1U << 2,
|
||||
RTC_BBPU_AUTO = 1U << 3,
|
||||
RTC_BBPU_CLRPKY = 1U << 4,
|
||||
RTC_BBPU_RELOAD = 1U << 5,
|
||||
RTC_BBPU_CBUSY = 1U << 6
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_AL_MASK_SEC = 1U << 0,
|
||||
RTC_AL_MASK_MIN = 1U << 1,
|
||||
RTC_AL_MASK_HOU = 1U << 2,
|
||||
RTC_AL_MASK_DOM = 1U << 3,
|
||||
RTC_AL_MASK_DOW = 1U << 4,
|
||||
RTC_AL_MASK_MTH = 1U << 5,
|
||||
RTC_AL_MASK_YEA = 1U << 6
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
|
||||
RTC_BBPU_2SEC_CK_SEL = 1U << 7,
|
||||
RTC_BBPU_2SEC_EN = 1U << 8,
|
||||
RTC_BBPU_2SEC_MODE = 0x3 << 9,
|
||||
RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
|
||||
RTC_BBPU_2SEC_STAT_STA = 1U << 12
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_BBPU_KEY = 0x43 << 8
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_EMBCK_SRC_SEL = 1 << 8,
|
||||
RTC_EMBCK_SEL_MODE = 3 << 6,
|
||||
RTC_XOSC32_ENB = 1 << 5,
|
||||
RTC_REG_XOSC32_ENB = 1 << 15
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_K_EOSC_RSV_0 = 1 << 8,
|
||||
RTC_K_EOSC_RSV_1 = 1 << 9,
|
||||
RTC_K_EOSC_RSV_2 = 1 << 10
|
||||
};
|
||||
|
||||
/* PMIC TOP Register Definition */
|
||||
enum {
|
||||
PMIC_RG_TOP_CON = 0x001E,
|
||||
PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
|
||||
PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
|
||||
PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
|
||||
PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
|
||||
PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
|
||||
PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
|
||||
};
|
||||
|
||||
/* PMIC SCK Register Definition */
|
||||
enum {
|
||||
PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x051A,
|
||||
PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x051C,
|
||||
PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x051E,
|
||||
PMIC_RG_EOSC_CALI_CON0 = 0x540
|
||||
};
|
||||
|
||||
/* PMIC DCXO Register Definition */
|
||||
enum {
|
||||
PMIC_RG_DCXO_CW00 = 0x0788,
|
||||
PMIC_RG_DCXO_CW02 = 0x0790
|
||||
};
|
||||
|
||||
enum {
|
||||
PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1,
|
||||
PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1,
|
||||
PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1,
|
||||
PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3,
|
||||
PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1,
|
||||
PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2,
|
||||
PMIC_RG_EOSC_CALI_TD_MASK = 0x7,
|
||||
PMIC_RG_EOSC_CALI_TD_SHIFT = 5,
|
||||
PMIC_RG_XO_EN32K_MAN_MASK = 0x1,
|
||||
PMIC_RG_XO_EN32K_MAN_SHIFT = 0
|
||||
};
|
||||
|
||||
/* external API */
|
||||
uint16_t RTC_Read(uint32_t addr);
|
||||
void RTC_Write(uint32_t addr, uint16_t data);
|
||||
int32_t rtc_busy_wait(void);
|
||||
int32_t RTC_Write_Trigger(void);
|
||||
int32_t Writeif_unlock(void);
|
||||
void rtc_power_off_sequence(void);
|
||||
|
||||
#endif /* RTC_H */
|
|
@ -0,0 +1,366 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <cortex_a53.h>
|
||||
#include <cortex_a73.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <mcucfg.h>
|
||||
#include <spm.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <mtspmc.h>
|
||||
|
||||
#include "mtspmc_private.h"
|
||||
|
||||
|
||||
static void set_retention(int cluster, int tick)
|
||||
{
|
||||
uint64_t cpuectlr;
|
||||
|
||||
if (cluster)
|
||||
cpuectlr = read_a73_cpuectlr_el1();
|
||||
else
|
||||
cpuectlr = read_a53_cpuectlr_el1();
|
||||
|
||||
cpuectlr &= ~0x7ULL;
|
||||
cpuectlr |= tick & 0x7;
|
||||
|
||||
if (cluster)
|
||||
write_a73_cpuectlr_el1(cpuectlr);
|
||||
else
|
||||
write_a53_cpuectlr_el1(cpuectlr);
|
||||
}
|
||||
|
||||
void spm_enable_cpu_auto_off(int cluster, int cpu)
|
||||
{
|
||||
uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK);
|
||||
|
||||
set_retention(cluster, 1);
|
||||
mmio_clrbits_32(reg, SW_NO_WAIT_Q);
|
||||
}
|
||||
|
||||
void spm_disable_cpu_auto_off(int cluster, int cpu)
|
||||
{
|
||||
uintptr_t reg = per_cpu(cluster, cpu, MCUCFG_SPARK);
|
||||
|
||||
mmio_setbits_32(reg, SW_NO_WAIT_Q);
|
||||
set_retention(cluster, 0);
|
||||
}
|
||||
|
||||
void spm_set_cpu_power_off(int cluster, int cpu)
|
||||
{
|
||||
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
|
||||
}
|
||||
|
||||
void spm_enable_cluster_auto_off(int cluster)
|
||||
{
|
||||
assert(cluster);
|
||||
|
||||
mmio_clrbits_32(MCUCFG_MP2_SPMC, SW_NO_WAIT_Q);
|
||||
mmio_clrbits_32(MCUCFG_MP2_COQ, BIT(0));
|
||||
|
||||
mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, MP1_SPMC_SRAM_DORMANT_EN);
|
||||
|
||||
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
|
||||
}
|
||||
|
||||
void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr)
|
||||
{
|
||||
uintptr_t reg;
|
||||
const uintptr_t mp2_bootreg[] = {
|
||||
MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1,
|
||||
MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 };
|
||||
|
||||
if (cluster) {
|
||||
assert(cpu >= 0 && cpu < 4);
|
||||
reg = mp2_bootreg[cpu];
|
||||
} else {
|
||||
reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR);
|
||||
}
|
||||
|
||||
mmio_write_32(reg, bootaddr);
|
||||
}
|
||||
|
||||
uintptr_t mcucfg_get_bootaddr(int cluster, int cpu)
|
||||
{
|
||||
uintptr_t reg;
|
||||
const uintptr_t mp2_bootreg[] = {
|
||||
MCUCFG_MP2_RVADDR0, MCUCFG_MP2_RVADDR1,
|
||||
MCUCFG_MP2_RVADDR2, MCUCFG_MP2_RVADDR3 };
|
||||
|
||||
if (cluster) {
|
||||
assert(cpu >= 0 && cpu < 4);
|
||||
reg = mp2_bootreg[cpu];
|
||||
} else {
|
||||
reg = per_cpu(cluster, cpu, MCUCFG_BOOTADDR);
|
||||
}
|
||||
|
||||
return mmio_read_32(reg);
|
||||
}
|
||||
|
||||
void mcucfg_init_archstate(int cluster, int cpu, int arm64)
|
||||
{
|
||||
uintptr_t reg;
|
||||
int i;
|
||||
|
||||
reg = per_cluster(cluster, MCUCFG_INITARCH);
|
||||
i = cluster ? 16 : 12;
|
||||
|
||||
mmio_setbits_32(reg, (arm64 & 1) << (i + cpu));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return power state of specified subsystem
|
||||
*
|
||||
* @mask: mask to SPM_PWR_STATUS to query the power state
|
||||
* of one subsystem.
|
||||
* RETURNS:
|
||||
* 0 (the subsys was powered off)
|
||||
* 1 (the subsys was powered on)
|
||||
*/
|
||||
int spm_get_powerstate(uint32_t mask)
|
||||
{
|
||||
return mmio_read_32(SPM_PWR_STATUS) & mask;
|
||||
}
|
||||
|
||||
int spm_get_cluster_powerstate(int cluster)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
mask = cluster ? PWR_STATUS_MP1_CPUTOP : PWR_STATUS_MP0_CPUTOP;
|
||||
|
||||
return spm_get_powerstate(mask);
|
||||
}
|
||||
|
||||
int spm_get_cpu_powerstate(int cluster, int cpu)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/*
|
||||
* a quick way to specify the mask of cpu[0-3]/cpu[4-7] in PWR_STATUS
|
||||
* register which are the BITS[9:12](MP0_CPU0~3) and
|
||||
* BITS[16:19](MP1_CPU0~3)
|
||||
*/
|
||||
i = (cluster) ? 16 : 9;
|
||||
i = 1 << (i + cpu);
|
||||
|
||||
return spm_get_powerstate(i);
|
||||
}
|
||||
|
||||
int spmc_init(void)
|
||||
{
|
||||
/* enable SPM register control */
|
||||
mmio_write_32(SPM_POWERON_CONFIG_EN,
|
||||
PROJECT_CODE | MD_BCLK_CG_EN | BCLK_CG_EN);
|
||||
|
||||
#if SPMC_MODE == 1
|
||||
INFO("SPM: enable SPMC mode\n");
|
||||
|
||||
/* 0: SPMC mode 1: Legacy mode */
|
||||
mmio_write_32(SPM_BYPASS_SPMC, 0);
|
||||
|
||||
mmio_clrbits_32(per_cluster(0, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
|
||||
mmio_clrbits_32(per_cpu(0, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
mmio_clrbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
mmio_clrbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
mmio_clrbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
|
||||
mmio_setbits_32(per_cpu(0, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(0, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(0, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
#endif
|
||||
|
||||
mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
mmio_setbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_RST_B);
|
||||
mmio_clrbits_32(per_cluster(1, SPM_CLUSTER_PWR), PWRCTRL_PWR_CLK_DIS);
|
||||
|
||||
mmio_clrbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
mmio_clrbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
mmio_clrbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
mmio_clrbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
|
||||
mmio_setbits_32(per_cpu(1, 0, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(1, 1, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(1, 2, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
mmio_setbits_32(per_cpu(1, 3, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Power on a core with specified cluster and core index
|
||||
*
|
||||
* @cluster: the cluster ID of the CPU which to be powered on
|
||||
* @cpu: the CPU ID of the CPU which to be powered on
|
||||
*/
|
||||
void spm_poweron_cpu(int cluster, int cpu)
|
||||
{
|
||||
INFO("spmc: power on core %d.%d\n", cluster, cpu);
|
||||
|
||||
/* STA_POWER_ON */
|
||||
/* Start to turn on MP0_CPU0 */
|
||||
|
||||
/* Set PWR_RST_B = 1 */
|
||||
mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
|
||||
/* Set PWR_ON = 1 */
|
||||
mmio_setbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
|
||||
|
||||
/* Wait until MP0_CPU0_PWR_STA_MASK = 1 */
|
||||
while (!spm_get_cpu_powerstate(cluster, cpu))
|
||||
;
|
||||
|
||||
/* Finish to turn on MP0_CPU0 */
|
||||
INFO("spmc: power on core %d.%d successfully\n", cluster, cpu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Power off a core with specified cluster and core index
|
||||
*
|
||||
* @cluster: the cluster ID of the CPU which to be powered off
|
||||
* @cpu: the CPU ID of the CPU which to be powered off
|
||||
*/
|
||||
void spm_poweroff_cpu(int cluster, int cpu)
|
||||
{
|
||||
INFO("spmc: power off core %d.%d\n", cluster, cpu);
|
||||
|
||||
/* Start to turn off MP0_CPU0 */
|
||||
/* Set PWR_ON_2ND = 0 */
|
||||
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON_2ND);
|
||||
|
||||
/* Set PWR_ON = 0 */
|
||||
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_ON);
|
||||
|
||||
/* Wait until MP0_CPU0_PWR_STA_MASK = 0 */
|
||||
while (spm_get_cpu_powerstate(cluster, cpu))
|
||||
;
|
||||
|
||||
/* Set PWR_RST_B = 0 */
|
||||
mmio_clrbits_32(per_cpu(cluster, cpu, SPM_CPU_PWR), PWRCTRL_PWR_RST_B);
|
||||
|
||||
/* Finish to turn off MP0_CPU0 */
|
||||
INFO("spmc: power off core %d.%d successfully\n", cluster, cpu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Power off a cluster with specified index
|
||||
*
|
||||
* @cluster: the cluster index which to be powered off
|
||||
*/
|
||||
void spm_poweroff_cluster(int cluster)
|
||||
{
|
||||
uint32_t mask;
|
||||
uint32_t pwr_rst_ctl;
|
||||
|
||||
INFO("spmc: power off cluster %d\n", cluster);
|
||||
|
||||
/* Start to turn off MP0_CPUTOP */
|
||||
/* Set bus protect - step1 : 0 */
|
||||
mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK :
|
||||
MP0_CPUTOP_PROT_STEP1_0_MASK;
|
||||
mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_SET, mask);
|
||||
|
||||
while ((mmio_read_32(INFRA_TOPAXI_PROTECTEN_STA1_1) & mask) != mask)
|
||||
;
|
||||
|
||||
/* Set PWR_ON_2ND = 0 */
|
||||
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
|
||||
PWRCTRL_PWR_ON_2ND);
|
||||
|
||||
/* SPMC_DORMANT_ENABLE[0]=0 */
|
||||
mask = (cluster) ? MP1_SPMC_SRAM_DORMANT_EN : MP0_SPMC_SRAM_DORMANT_EN;
|
||||
mmio_clrbits_32(SPM_SPMC_DORMANT_ENABLE, mask);
|
||||
|
||||
/* Set PWR_ON = 0" */
|
||||
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
|
||||
|
||||
/* Wait until MP0_CPUTOP_PWR_STA_MASK = 0 */
|
||||
while (spm_get_cluster_powerstate(cluster))
|
||||
;
|
||||
|
||||
/* NOTE
|
||||
* Following flow only for BIG core cluster. It was from
|
||||
* application note but not covered in mtcmos_ctrl.c
|
||||
*/
|
||||
if (cluster) {
|
||||
pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL);
|
||||
mmio_write_32(MCUCFG_MP2_PWR_RST_CTL,
|
||||
(pwr_rst_ctl & ~SW_RST_B) | TOPAON_APB_MASK);
|
||||
}
|
||||
|
||||
/* CPU_EXT_BUCK_ISO[0]=1 */
|
||||
if (cluster)
|
||||
mmio_setbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO);
|
||||
|
||||
/* Finish to turn off MP0_CPUTOP */
|
||||
INFO("spmc: power off cluster %d successfully\n", cluster);
|
||||
}
|
||||
|
||||
/**
|
||||
* Power on a cluster with specified index
|
||||
*
|
||||
* @cluster: the cluster index which to be powered on
|
||||
*/
|
||||
void spm_poweron_cluster(int cluster)
|
||||
{
|
||||
uint32_t mask;
|
||||
uint32_t pwr_rst_ctl;
|
||||
|
||||
INFO("spmc: power on cluster %d\n", cluster);
|
||||
|
||||
/* Start to turn on MP1_CPUTOP */
|
||||
|
||||
/* NOTE
|
||||
* Following flow only for BIG core cluster. It was from
|
||||
* application note but not covered in mtcmos_ctrl.c
|
||||
*/
|
||||
if (cluster) {
|
||||
mmio_clrbits_32(MCUCFG_MP2_PWR_RST_CTL, SW_RST_B);
|
||||
|
||||
/* CPU_EXT_BUCK_ISO[1]=0 */
|
||||
/* Set mp<n>_vproc_ext_off to 0 to release vproc isolation control */
|
||||
mmio_clrbits_32(SPM_CPU_EXT_BUCK_ISO, MP1_EXT_BUCK_ISO);
|
||||
|
||||
/* NOTE
|
||||
* Following flow only for BIG core cluster. It was from
|
||||
* application note but not covered in mtcmos_ctrl.c
|
||||
*/
|
||||
pwr_rst_ctl = mmio_read_32(MCUCFG_MP2_PWR_RST_CTL);
|
||||
mmio_write_32(MCUCFG_MP2_PWR_RST_CTL,
|
||||
(pwr_rst_ctl | SW_RST_B) & ~TOPAON_APB_MASK);
|
||||
}
|
||||
|
||||
/* Set PWR_ON_2ND = 0 */
|
||||
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
|
||||
PWRCTRL_PWR_ON_2ND);
|
||||
|
||||
/* Set PWR_RST_B = 1 */
|
||||
mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
|
||||
PWRCTRL_PWR_RST_B);
|
||||
|
||||
/* Set PWR_CLK_DIS = 0 */
|
||||
mmio_clrbits_32(per_cluster(cluster, SPM_CLUSTER_PWR),
|
||||
PWRCTRL_PWR_CLK_DIS);
|
||||
|
||||
/* Set PWR_ON = 1 */
|
||||
mmio_setbits_32(per_cluster(cluster, SPM_CLUSTER_PWR), PWRCTRL_PWR_ON);
|
||||
|
||||
/* Wait until MP1_CPUTOP_PWR_STA_MASK = 1 */
|
||||
while (!spm_get_cluster_powerstate(cluster))
|
||||
;
|
||||
|
||||
/* Release bus protect - step1 : 0 */
|
||||
mask = (cluster) ? MP1_CPUTOP_PROT_STEP1_0_MASK :
|
||||
MP0_CPUTOP_PROT_STEP1_0_MASK;
|
||||
mmio_write_32(INFRA_TOPAXI_PROTECTEN_1_CLR, mask);
|
||||
|
||||
/* Finish to turn on MP1_CPUTOP */
|
||||
INFO("spmc: power on cluster %d successfully\n", cluster);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MTSPMC_H
|
||||
#define MTSPMC_H
|
||||
|
||||
/*
|
||||
* CONFIG_SPMC_MODE: Select CPU power control mode.
|
||||
*
|
||||
* 0: Legacy
|
||||
* Control power flow from SW through SPM register (MP*_PWR_CON).
|
||||
* 1: HW
|
||||
* Control power flow from SPMC. Most control flow and timing are handled
|
||||
* by SPMC.
|
||||
*/
|
||||
#define SPMC_MODE 1
|
||||
|
||||
int spmc_init(void);
|
||||
|
||||
void spm_poweron_cpu(int cluster, int cpu);
|
||||
void spm_poweroff_cpu(int cluster, int cpu);
|
||||
|
||||
void spm_poweroff_cluster(int cluster);
|
||||
void spm_poweron_cluster(int cluster);
|
||||
|
||||
int spm_get_cpu_powerstate(int cluster, int cpu);
|
||||
int spm_get_cluster_powerstate(int cluster);
|
||||
int spm_get_powerstate(uint32_t mask);
|
||||
|
||||
void spm_enable_cpu_auto_off(int cluster, int cpu);
|
||||
void spm_disable_cpu_auto_off(int cluster, int cpu);
|
||||
void spm_set_cpu_power_off(int cluster, int cpu);
|
||||
void spm_enable_cluster_auto_off(int cluster);
|
||||
|
||||
void mcucfg_init_archstate(int cluster, int cpu, int arm64);
|
||||
void mcucfg_set_bootaddr(int cluster, int cpu, uintptr_t bootaddr);
|
||||
uintptr_t mcucfg_get_bootaddr(int cluster, int cpu);
|
||||
|
||||
#endif /* MTSPMC_H */
|
|
@ -0,0 +1,239 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MTSPMC_PRIVATE_H
|
||||
#define MTSPMC_PRIVATE_H
|
||||
|
||||
/*
|
||||
* per_cpu/cluster helper
|
||||
*/
|
||||
struct per_cpu_reg {
|
||||
int cluster_addr;
|
||||
int cpu_stride;
|
||||
};
|
||||
|
||||
#define per_cpu(cluster, cpu, reg) (reg[cluster].cluster_addr + \
|
||||
(cpu << reg[cluster].cpu_stride))
|
||||
#define per_cluster(cluster, reg) (reg[cluster].cluster_addr)
|
||||
|
||||
/* SPMC related registers */
|
||||
#define SPM_POWERON_CONFIG_EN (SPM_BASE + 0x000)
|
||||
/* bit-fields of SPM_POWERON_CONFIG_EN */
|
||||
#define BCLK_CG_EN (1 << 0)
|
||||
#define MD_BCLK_CG_EN (1 << 1)
|
||||
#define PROJECT_CODE (0xb16 << 16)
|
||||
|
||||
#define SPM_PWR_STATUS (SPM_BASE + 0x180)
|
||||
#define SPM_PWR_STATUS_2ND (SPM_BASE + 0x184)
|
||||
|
||||
#define SPM_BYPASS_SPMC (SPM_BASE + 0x2b4)
|
||||
#define SPM_SPMC_DORMANT_ENABLE (SPM_BASE + 0x2b8)
|
||||
|
||||
#define SPM_MP0_CPUTOP_PWR_CON (SPM_BASE + 0x204)
|
||||
#define SPM_MP0_CPU0_PWR_CON (SPM_BASE + 0x208)
|
||||
#define SPM_MP0_CPU1_PWR_CON (SPM_BASE + 0x20C)
|
||||
#define SPM_MP0_CPU2_PWR_CON (SPM_BASE + 0x210)
|
||||
#define SPM_MP0_CPU3_PWR_CON (SPM_BASE + 0x214)
|
||||
#define SPM_MP1_CPUTOP_PWR_CON (SPM_BASE + 0x218)
|
||||
#define SPM_MP1_CPU0_PWR_CON (SPM_BASE + 0x21C)
|
||||
#define SPM_MP1_CPU1_PWR_CON (SPM_BASE + 0x220)
|
||||
#define SPM_MP1_CPU2_PWR_CON (SPM_BASE + 0x224)
|
||||
#define SPM_MP1_CPU3_PWR_CON (SPM_BASE + 0x228)
|
||||
#define SPM_MP0_CPUTOP_L2_PDN (SPM_BASE + 0x240)
|
||||
#define SPM_MP0_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x244)
|
||||
#define SPM_MP0_CPU0_L1_PDN (SPM_BASE + 0x248)
|
||||
#define SPM_MP0_CPU1_L1_PDN (SPM_BASE + 0x24C)
|
||||
#define SPM_MP0_CPU2_L1_PDN (SPM_BASE + 0x250)
|
||||
#define SPM_MP0_CPU3_L1_PDN (SPM_BASE + 0x254)
|
||||
#define SPM_MP1_CPUTOP_L2_PDN (SPM_BASE + 0x258)
|
||||
#define SPM_MP1_CPUTOP_L2_SLEEP_B (SPM_BASE + 0x25C)
|
||||
#define SPM_MP1_CPU0_L1_PDN (SPM_BASE + 0x260)
|
||||
#define SPM_MP1_CPU1_L1_PDN (SPM_BASE + 0x264)
|
||||
#define SPM_MP1_CPU2_L1_PDN (SPM_BASE + 0x268)
|
||||
#define SPM_MP1_CPU3_L1_PDN (SPM_BASE + 0x26C)
|
||||
|
||||
#define SPM_CPU_EXT_BUCK_ISO (SPM_BASE + 0x290)
|
||||
/* bit-fields of SPM_CPU_EXT_BUCK_ISO */
|
||||
#define MP0_EXT_BUCK_ISO (1 << 0)
|
||||
#define MP1_EXT_BUCK_ISO (1 << 1)
|
||||
#define MP_EXT_BUCK_ISO (1 << 2)
|
||||
|
||||
/* bit-fields of SPM_PWR_STATUS */
|
||||
#define PWR_STATUS_MD (1 << 0)
|
||||
#define PWR_STATUS_CONN (1 << 1)
|
||||
#define PWR_STATUS_DDRPHY (1 << 2)
|
||||
#define PWR_STATUS_DISP (1 << 3)
|
||||
#define PWR_STATUS_MFG (1 << 4)
|
||||
#define PWR_STATUS_ISP (1 << 5)
|
||||
#define PWR_STATUS_INFRA (1 << 6)
|
||||
#define PWR_STATUS_VDEC (1 << 7)
|
||||
#define PWR_STATUS_MP0_CPUTOP (1 << 8)
|
||||
#define PWR_STATUS_MP0_CPU0 (1 << 9)
|
||||
#define PWR_STATUS_MP0_CPU1 (1 << 10)
|
||||
#define PWR_STATUS_MP0_CPU2 (1 << 11)
|
||||
#define PWR_STATUS_MP0_CPU3 (1 << 12)
|
||||
#define PWR_STATUS_MCUSYS (1 << 14)
|
||||
#define PWR_STATUS_MP1_CPUTOP (1 << 15)
|
||||
#define PWR_STATUS_MP1_CPU0 (1 << 16)
|
||||
#define PWR_STATUS_MP1_CPU1 (1 << 17)
|
||||
#define PWR_STATUS_MP1_CPU2 (1 << 18)
|
||||
#define PWR_STATUS_MP1_CPU3 (1 << 19)
|
||||
#define PWR_STATUS_VEN (1 << 21)
|
||||
#define PWR_STATUS_MFG_ASYNC (1 << 23)
|
||||
#define PWR_STATUS_AUDIO (1 << 24)
|
||||
#define PWR_STATUS_C2K (1 << 28)
|
||||
#define PWR_STATUS_MD_INFRA (1 << 29)
|
||||
|
||||
|
||||
/* bit-fields of SPM_*_PWR_CON */
|
||||
#define PWRCTRL_PWR_RST_B (1 << 0)
|
||||
#define PWRCTRL_PWR_ISO (1 << 1)
|
||||
#define PWRCTRL_PWR_ON (1 << 2)
|
||||
#define PWRCTRL_PWR_ON_2ND (1 << 3)
|
||||
#define PWRCTRL_PWR_CLK_DIS (1 << 4)
|
||||
#define PWRCTRL_PWR_SRAM_CKISO (1 << 5)
|
||||
#define PWRCTRL_PWR_SRAM_ISOINT_B (1 << 6)
|
||||
#define PWRCTRL_PWR_SRAM_PD_SLPB_CLAMP (1 << 7)
|
||||
#define PWRCTRL_PWR_SRAM_PDN (1 << 8)
|
||||
#define PWRCTRL_PWR_SRAM_SLEEP_B (1 << 12)
|
||||
#define PWRCTRL_PWR_SRAM_PDN_ACK (1 << 24)
|
||||
#define PWRCTRL_PWR_SRAM_SLEEP_B_ACK (1 << 28)
|
||||
|
||||
/* per_cpu registers for SPM_MP?_CPU?_PWR_CON */
|
||||
static const struct per_cpu_reg SPM_CPU_PWR[] = {
|
||||
[0] = { .cluster_addr = SPM_MP0_CPU0_PWR_CON, .cpu_stride = 2 },
|
||||
[1] = { .cluster_addr = SPM_MP1_CPU0_PWR_CON, .cpu_stride = 2 },
|
||||
};
|
||||
|
||||
/* per_cluster registers for SPM_MP?_CPUTOP_PWR_CON */
|
||||
static const struct per_cpu_reg SPM_CLUSTER_PWR[] = {
|
||||
[0] = { .cluster_addr = SPM_MP0_CPUTOP_PWR_CON },
|
||||
[1] = { .cluster_addr = SPM_MP1_CPUTOP_PWR_CON },
|
||||
};
|
||||
|
||||
/* APB Module infracfg_ao */
|
||||
#define INFRA_TOPAXI_PROTECTEN_1 (INFRACFG_AO_BASE + 0x250)
|
||||
#define INFRA_TOPAXI_PROTECTEN_STA1_1 (INFRACFG_AO_BASE + 0x258)
|
||||
#define INFRA_TOPAXI_PROTECTEN_1_SET (INFRACFG_AO_BASE + 0x2A8)
|
||||
#define INFRA_TOPAXI_PROTECTEN_1_CLR (INFRACFG_AO_BASE + 0x2AC)
|
||||
|
||||
/* bit-fields of INFRA_TOPAXI_PROTECTEN_1_SET */
|
||||
#define MP0_CPUTOP_PROT_STEP1_0_MASK ((1 << 10)|(1 << 12)| \
|
||||
(1 << 13)|(1 << 26))
|
||||
#define MP1_CPUTOP_PROT_STEP1_0_MASK ((1 << 11)|(1 << 14)| \
|
||||
(1 << 15)|(1 << 27))
|
||||
|
||||
/* bit-fields of INFRA_TOPAXI_PROTECTEN_STA1_1 */
|
||||
#define MP0_CPUTOP_PROT_STEP1_0_ACK_MASK ((1 << 10)|(1 << 12)| \
|
||||
(1 << 13)|(1 << 26))
|
||||
#define MP1_CPUTOP_PROT_STEP1_0_ACK_MASK ((1 << 11)|(1 << 14)| \
|
||||
(1 << 15)|(1 << 27))
|
||||
|
||||
|
||||
/*
|
||||
* MCU configuration registers
|
||||
*/
|
||||
#define MCUCFG_MP0_AXI_CONFIG ((uintptr_t)&mt8183_mcucfg->mp0_axi_config)
|
||||
#define MCUCFG_MP1_AXI_CONFIG ((uintptr_t)&mt8183_mcucfg->mp1_axi_config)
|
||||
/* bit-fields of MCUCFG_MP?_AXI_CONFIG */
|
||||
#define MCUCFG_AXI_CONFIG_BROADCASTINNER (1 << 0)
|
||||
#define MCUCFG_AXI_CONFIG_BROADCASTOUTER (1 << 1)
|
||||
#define MCUCFG_AXI_CONFIG_BROADCASTCACHEMAINT (1 << 2)
|
||||
#define MCUCFG_AXI_CONFIG_SYSBARDISABLE (1 << 3)
|
||||
#define MCUCFG_AXI_CONFIG_ACINACTM (1 << 4)
|
||||
#define MCUCFG_AXI_CONFIG_AINACTS (1 << 5)
|
||||
|
||||
/* per_cpu registers for MCUCFG_MP?_AXI_CONFIG */
|
||||
static const struct per_cpu_reg MCUCFG_SCUCTRL[] = {
|
||||
[0] = { .cluster_addr = MCUCFG_MP0_AXI_CONFIG },
|
||||
[1] = { .cluster_addr = MCUCFG_MP1_AXI_CONFIG },
|
||||
};
|
||||
|
||||
#define MCUCFG_MP0_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[2])
|
||||
#define MCUCFG_MP0_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp0_misc_config[3])
|
||||
#define MCUCFG_MP1_MISC_CONFIG2 ((uintptr_t)&mt8183_mcucfg->mp1_misc_config[2])
|
||||
#define MCUCFG_MP1_MISC_CONFIG3 ((uintptr_t)&mt8183_mcucfg->mp1_misc_config[3])
|
||||
|
||||
#define MCUCFG_CPUSYS0_SPARKVRETCNTRL (MCUCFG_BASE + 0x1c00)
|
||||
/* bit-fields of MCUCFG_CPUSYS0_SPARKVRETCNTRL */
|
||||
#define CPU0_SPARK_VRET_CTRL (0x3f << 0)
|
||||
#define CPU1_SPARK_VRET_CTRL (0x3f << 8)
|
||||
#define CPU2_SPARK_VRET_CTRL (0x3f << 16)
|
||||
#define CPU3_SPARK_VRET_CTRL (0x3f << 24)
|
||||
|
||||
/* SPARK control in little cores */
|
||||
#define MCUCFG_CPUSYS0_CPU0_SPMC_CTL (MCUCFG_BASE + 0x1c30)
|
||||
#define MCUCFG_CPUSYS0_CPU1_SPMC_CTL (MCUCFG_BASE + 0x1c34)
|
||||
#define MCUCFG_CPUSYS0_CPU2_SPMC_CTL (MCUCFG_BASE + 0x1c38)
|
||||
#define MCUCFG_CPUSYS0_CPU3_SPMC_CTL (MCUCFG_BASE + 0x1c3c)
|
||||
/* bit-fields of MCUCFG_CPUSYS0_CPU?_SPMC_CTL */
|
||||
#define SW_SPARK_EN (1 << 0)
|
||||
#define SW_NO_WAIT_Q (1 << 1)
|
||||
|
||||
/* the MCUCFG which BIG cores used is at (MCUCFG_BASE + 0x2000) */
|
||||
#define MCUCFG_MP2_BASE (MCUCFG_BASE + 0x2000)
|
||||
#define MCUCFG_MP2_PWR_RST_CTL (MCUCFG_MP2_BASE + 0x8)
|
||||
/* bit-fields of MCUCFG_MP2_PWR_RST_CTL */
|
||||
#define SW_RST_B (1 << 0)
|
||||
#define TOPAON_APB_MASK (1 << 1)
|
||||
|
||||
#define MCUCFG_MP2_CPUCFG (MCUCFG_MP2_BASE + 0x208)
|
||||
|
||||
#define MCUCFG_MP2_RVADDR0 (MCUCFG_MP2_BASE + 0x290)
|
||||
#define MCUCFG_MP2_RVADDR1 (MCUCFG_MP2_BASE + 0x298)
|
||||
#define MCUCFG_MP2_RVADDR2 (MCUCFG_MP2_BASE + 0x2c0)
|
||||
#define MCUCFG_MP2_RVADDR3 (MCUCFG_MP2_BASE + 0x2c8)
|
||||
|
||||
/* SPMC control */
|
||||
#define MCUCFG_MP0_SPMC (MCUCFG_BASE + 0x788)
|
||||
#define MCUCFG_MP2_SPMC (MCUCFG_MP2_BASE + 0x2a0)
|
||||
#define MCUCFG_MP2_COQ (MCUCFG_MP2_BASE + 0x2bC)
|
||||
|
||||
/* per_cpu registers for MCUCFG_MP?_MISC_CONFIG2 */
|
||||
static const struct per_cpu_reg MCUCFG_BOOTADDR[] = {
|
||||
[0] = { .cluster_addr = MCUCFG_MP0_MISC_CONFIG2, .cpu_stride = 3 },
|
||||
};
|
||||
|
||||
/* per_cpu registers for MCUCFG_MP?_MISC_CONFIG3 */
|
||||
static const struct per_cpu_reg MCUCFG_INITARCH[] = {
|
||||
[0] = { .cluster_addr = MCUCFG_MP0_MISC_CONFIG3 },
|
||||
[1] = { .cluster_addr = MCUCFG_MP2_CPUCFG },
|
||||
};
|
||||
|
||||
/* SPARK control in BIG cores */
|
||||
#define MCUCFG_MP2_PTP3_CPU0_SPMC0 (MCUCFG_MP2_BASE + 0x430)
|
||||
#define MCUCFG_MP2_PTP3_CPU0_SPMC1 (MCUCFG_MP2_BASE + 0x434)
|
||||
#define MCUCFG_MP2_PTP3_CPU1_SPMC0 (MCUCFG_MP2_BASE + 0x438)
|
||||
#define MCUCFG_MP2_PTP3_CPU1_SPMC1 (MCUCFG_MP2_BASE + 0x43c)
|
||||
#define MCUCFG_MP2_PTP3_CPU2_SPMC0 (MCUCFG_MP2_BASE + 0x440)
|
||||
#define MCUCFG_MP2_PTP3_CPU2_SPMC1 (MCUCFG_MP2_BASE + 0x444)
|
||||
#define MCUCFG_MP2_PTP3_CPU3_SPMC0 (MCUCFG_MP2_BASE + 0x448)
|
||||
#define MCUCFG_MP2_PTP3_CPU3_SPMC1 (MCUCFG_MP2_BASE + 0x44c)
|
||||
/* bit-fields of MCUCFG_MP2_PTP3_CPU?_SPMC? */
|
||||
#define SW_SPARK_EN (1 << 0)
|
||||
#define SW_NO_WAIT_Q (1 << 1)
|
||||
|
||||
#define MCUCFG_MP2_SPARK2LDO (MCUCFG_MP2_BASE + 0x700)
|
||||
/* bit-fields of MCUCFG_MP2_SPARK2LDO */
|
||||
#define SPARK_VRET_CTRL (0x3f << 0)
|
||||
#define CPU0_SPARK_LDO_AMUXSEL (0xf << 6)
|
||||
#define CPU1_SPARK_LDO_AMUXSEL (0xf << 10)
|
||||
#define CPU2_SPARK_LDO_AMUXSEL (0xf << 14)
|
||||
#define CPU3_SPARK_LDO_AMUXSEL (0xf << 18)
|
||||
|
||||
/* per_cpu registers for SPARK */
|
||||
static const struct per_cpu_reg MCUCFG_SPARK[] = {
|
||||
[0] = { .cluster_addr = MCUCFG_CPUSYS0_CPU0_SPMC_CTL, .cpu_stride = 2 },
|
||||
[1] = { .cluster_addr = MCUCFG_MP2_PTP3_CPU0_SPMC0, .cpu_stride = 3 },
|
||||
};
|
||||
|
||||
/* per_cpu registers for SPARK2LDO */
|
||||
static const struct per_cpu_reg MCUCFG_SPARK2LDO[] = {
|
||||
[0] = { .cluster_addr = MCUCFG_CPUSYS0_SPARKVRETCNTRL },
|
||||
[1] = { .cluster_addr = MCUCFG_MP2_SPARK2LDO },
|
||||
};
|
||||
|
||||
#endif /* MTSPMC_PRIVATE_H */
|
|
@ -9,11 +9,6 @@
|
|||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
enum irq_schedule_mode {
|
||||
SW_MODE,
|
||||
HW_MODE
|
||||
};
|
||||
|
||||
#define GIC_INT_MASK (MCUCFG_BASE + 0x5e8)
|
||||
#define GIC500_ACTIVE_SEL_SHIFT 3
|
||||
#define GIC500_ACTIVE_SEL_MASK (0x7 << GIC500_ACTIVE_SEL_SHIFT)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_DCM_H
|
||||
#define PLAT_DCM_H
|
||||
|
||||
#define MP2_SYNC_DCM (MCUCFG_BASE + 0x2274)
|
||||
#define MP2_SYNC_DCM_MASK (0x1 << 0)
|
||||
#define MP2_SYNC_DCM_ON (0x1 << 0)
|
||||
#define MP2_SYNC_DCM_OFF (0x0 << 0)
|
||||
|
||||
extern uint64_t plat_dcm_mcsi_a_addr;
|
||||
extern uint32_t plat_dcm_mcsi_a_val;
|
||||
extern int plat_dcm_initiated;
|
||||
|
||||
extern void plat_dcm_mcsi_a_backup(void);
|
||||
extern void plat_dcm_mcsi_a_restore(void);
|
||||
extern void plat_dcm_rgu_enable(void);
|
||||
extern void plat_dcm_restore_cluster_on(unsigned long mpidr);
|
||||
extern void plat_dcm_msg_handler(uint64_t x1);
|
||||
extern unsigned long plat_dcm_get_enabled_cnt(uint64_t type);
|
||||
extern void plat_dcm_init(void);
|
||||
|
||||
#define ALL_DCM_TYPE (ARMCORE_DCM_TYPE | MCUSYS_DCM_TYPE \
|
||||
| STALL_DCM_TYPE | BIG_CORE_DCM_TYPE \
|
||||
| GIC_SYNC_DCM_TYPE | RGU_DCM_TYPE \
|
||||
| INFRA_DCM_TYPE \
|
||||
| DDRPHY_DCM_TYPE | EMI_DCM_TYPE | DRAMC_DCM_TYPE \
|
||||
| MCSI_DCM_TYPE)
|
||||
|
||||
enum {
|
||||
ARMCORE_DCM_TYPE = (1U << 0),
|
||||
MCUSYS_DCM_TYPE = (1U << 1),
|
||||
INFRA_DCM_TYPE = (1U << 2),
|
||||
PERI_DCM_TYPE = (1U << 3),
|
||||
EMI_DCM_TYPE = (1U << 4),
|
||||
DRAMC_DCM_TYPE = (1U << 5),
|
||||
DDRPHY_DCM_TYPE = (1U << 6),
|
||||
STALL_DCM_TYPE = (1U << 7),
|
||||
BIG_CORE_DCM_TYPE = (1U << 8),
|
||||
GIC_SYNC_DCM_TYPE = (1U << 9),
|
||||
LAST_CORE_DCM_TYPE = (1U << 10),
|
||||
RGU_DCM_TYPE = (1U << 11),
|
||||
TOPCKG_DCM_TYPE = (1U << 12),
|
||||
LPDMA_DCM_TYPE = (1U << 13),
|
||||
MCSI_DCM_TYPE = (1U << 14),
|
||||
NR_DCM_TYPE = 15,
|
||||
};
|
||||
|
||||
#endif /* PLAT_DCM_H */
|
|
@ -273,7 +273,7 @@ INTR_PROP_DESC(MT_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
|||
******************************************************************************/
|
||||
|
||||
#define TZRAM_BASE 0x54600000
|
||||
#define TZRAM_SIZE 0x00020000
|
||||
#define TZRAM_SIZE 0x00030000
|
||||
|
||||
/*******************************************************************************
|
||||
* BL31 specific defines.
|
||||
|
@ -291,7 +291,7 @@ INTR_PROP_DESC(MT_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, grp, \
|
|||
******************************************************************************/
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define MAX_XLAT_TABLES 4
|
||||
#define MAX_XLAT_TABLES 16
|
||||
#define MAX_MMAP_REGIONS 16
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <lib/bakery_lock.h>
|
||||
#include <drivers/console.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <plat_dcm.h>
|
||||
#include <plat_private.h>
|
||||
#include <plat_dcm.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <platform_def.h>
|
||||
#include <mtk_plat_common.h>
|
||||
|
||||
#define PWR_STATUS (SPM_BASE + 0x180)
|
||||
|
||||
uint64_t plat_dcm_mcsi_a_addr;
|
||||
uint32_t plat_dcm_mcsi_a_val;
|
||||
static int plat_dcm_init_type;
|
||||
static unsigned int dcm_big_core_cnt;
|
||||
int plat_dcm_initiated;
|
||||
|
||||
#define PWR_STA_BIG_MP_MASK (0x1 << 15)
|
||||
|
||||
DEFINE_BAKERY_LOCK(dcm_lock);
|
||||
|
||||
void dcm_lock_init(void)
|
||||
{
|
||||
bakery_lock_init(&dcm_lock);
|
||||
}
|
||||
|
||||
void dcm_lock_get(void)
|
||||
{
|
||||
bakery_lock_get(&dcm_lock);
|
||||
}
|
||||
|
||||
void dcm_lock_release(void)
|
||||
{
|
||||
bakery_lock_release(&dcm_lock);
|
||||
}
|
||||
|
||||
void plat_dcm_mcsi_a_backup(void)
|
||||
{
|
||||
}
|
||||
|
||||
void plat_dcm_mcsi_a_restore(void)
|
||||
{
|
||||
}
|
||||
|
||||
void plat_dcm_rgu_enable(void)
|
||||
{
|
||||
}
|
||||
|
||||
void plat_dcm_big_core_sync(short on)
|
||||
{
|
||||
/* Check if Big cluster power is existed */
|
||||
if (!(mmio_read_32(PWR_STATUS) & PWR_STA_BIG_MP_MASK))
|
||||
return;
|
||||
|
||||
if (on) {
|
||||
mmio_write_32(MP2_SYNC_DCM,
|
||||
(mmio_read_32(MP2_SYNC_DCM) & ~MP2_SYNC_DCM_MASK)
|
||||
| MP2_SYNC_DCM_ON);
|
||||
dcm_big_core_cnt++;
|
||||
} else
|
||||
mmio_write_32(MP2_SYNC_DCM,
|
||||
(mmio_read_32(MP2_SYNC_DCM) & ~MP2_SYNC_DCM_MASK)
|
||||
| MP2_SYNC_DCM_OFF);
|
||||
}
|
||||
|
||||
void plat_dcm_restore_cluster_on(unsigned long mpidr)
|
||||
{
|
||||
unsigned long cluster_id =
|
||||
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS;
|
||||
|
||||
switch (cluster_id) {
|
||||
case 0x1:
|
||||
dcm_lock_get();
|
||||
if (plat_dcm_init_type & BIG_CORE_DCM_TYPE)
|
||||
plat_dcm_big_core_sync(1);
|
||||
else
|
||||
plat_dcm_big_core_sync(0);
|
||||
dcm_lock_release();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void plat_dcm_msg_handler(uint64_t x1)
|
||||
{
|
||||
plat_dcm_init_type = x1 & ALL_DCM_TYPE;
|
||||
}
|
||||
|
||||
unsigned long plat_dcm_get_enabled_cnt(uint64_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case BIG_CORE_DCM_TYPE:
|
||||
return dcm_big_core_cnt;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void plat_dcm_init(void)
|
||||
{
|
||||
dcm_lock_init();
|
||||
}
|
|
@ -1,14 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <bl31/interrupt_mgmt.h>
|
||||
#include <../drivers/arm/gic/v3/gicv3_private.h>
|
||||
#include <mt_gic_v3.h>
|
||||
#include <mtk_plat_common.h>
|
||||
#include "plat_private.h"
|
||||
|
@ -21,13 +21,9 @@
|
|||
|
||||
uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
|
||||
|
||||
/*
|
||||
* We save and restore the GICv3 context on system suspend. Allocate the
|
||||
* data in the designated EL3 Secure carve-out memory
|
||||
*/
|
||||
gicv3_redist_ctx_t rdist_ctx __section("arm_el3_tzc_dram");
|
||||
gicv3_dist_ctx_t dist_ctx __section("arm_el3_tzc_dram");
|
||||
|
||||
/* we save and restore the GICv3 context on system suspend */
|
||||
gicv3_redist_ctx_t rdist_ctx;
|
||||
gicv3_dist_ctx_t dist_ctx;
|
||||
|
||||
static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr)
|
||||
{
|
||||
|
@ -42,27 +38,6 @@ gicv3_driver_data_t mt_gicv3_data = {
|
|||
.mpidr_to_core_pos = mt_mpidr_to_core_pos,
|
||||
};
|
||||
|
||||
void setup_int_schedule_mode(enum irq_schedule_mode mode,
|
||||
unsigned int active_cpu)
|
||||
{
|
||||
assert(mode <= HW_MODE);
|
||||
assert(active_cpu <= 0xFF);
|
||||
|
||||
if (mode == HW_MODE) {
|
||||
mmio_write_32(GIC_INT_MASK,
|
||||
(mmio_read_32(GIC_INT_MASK) & ~(GIC500_ACTIVE_SEL_MASK))
|
||||
| (0x1 << GIC500_ACTIVE_SEL_SHIFT));
|
||||
} else if (mode == SW_MODE) {
|
||||
mmio_write_32(GIC_INT_MASK,
|
||||
(mmio_read_32(GIC_INT_MASK) & ~(GIC500_ACTIVE_SEL_MASK)));
|
||||
}
|
||||
|
||||
mmio_write_32(GIC_INT_MASK,
|
||||
(mmio_read_32(GIC_INT_MASK) & ~(GIC500_ACTIVE_CPU_MASK))
|
||||
| (active_cpu << GIC500_ACTIVE_CPU_SHIFT));
|
||||
return;
|
||||
}
|
||||
|
||||
void clear_sec_pol_ctl_en(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
@ -85,7 +60,6 @@ void mt_gic_init(void)
|
|||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
|
||||
setup_int_schedule_mode(SW_MODE, 0xf);
|
||||
clear_sec_pol_ctl_en();
|
||||
}
|
||||
|
||||
|
@ -94,14 +68,6 @@ void mt_gic_set_pending(uint32_t irq)
|
|||
gicv3_set_interrupt_pending(irq, plat_my_core_pos());
|
||||
}
|
||||
|
||||
uint32_t mt_gic_get_pending(uint32_t irq)
|
||||
{
|
||||
uint32_t bit = 1 << (irq % 32);
|
||||
|
||||
return (mmio_read_32(gicv3_driver_data->gicd_base +
|
||||
GICD_ISPENDR + irq / 32 * 4) & bit) ? 1 : 0;
|
||||
}
|
||||
|
||||
void mt_gic_cpuif_enable(void)
|
||||
{
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -15,25 +15,151 @@
|
|||
/* mediatek platform specific headers */
|
||||
#include <platform_def.h>
|
||||
#include <scu.h>
|
||||
#include <mt_gic_v3.h>
|
||||
#include <mtk_plat_common.h>
|
||||
#include <power_tracer.h>
|
||||
#include <mtgpio.h>
|
||||
#include <mtspmc.h>
|
||||
#include <plat_dcm.h>
|
||||
#include <plat_debug.h>
|
||||
#include <plat_params.h>
|
||||
#include <plat_private.h>
|
||||
#include <power_tracer.h>
|
||||
#include <pmic.h>
|
||||
#include <rtc.h>
|
||||
|
||||
#define MTK_LOCAL_STATE_OFF 2
|
||||
|
||||
static uintptr_t secure_entrypoint;
|
||||
|
||||
static void mp1_L2_desel_config(void)
|
||||
{
|
||||
mmio_write_64(MCUCFG_BASE + 0x2200, 0x2092c820);
|
||||
|
||||
dsb();
|
||||
}
|
||||
|
||||
static int plat_mtk_power_domain_on(unsigned long mpidr)
|
||||
{
|
||||
int cpu = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
|
||||
INFO("%s():%d: mpidr: %lx, c.c: %d.%d\n",
|
||||
__func__, __LINE__, mpidr, 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 */
|
||||
mcucfg_init_archstate(cluster, cpu, 1);
|
||||
mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint);
|
||||
|
||||
spm_poweron_cpu(cluster, cpu);
|
||||
|
||||
return PSCI_E_SUCCESS;
|
||||
}
|
||||
|
||||
static void plat_mtk_power_domain_off(const psci_power_state_t *state)
|
||||
{
|
||||
uint64_t mpidr = read_mpidr();
|
||||
int cpu = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
|
||||
INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
|
||||
|
||||
/* Prevent interrupts from spuriously waking up this cpu */
|
||||
mt_gic_cpuif_disable();
|
||||
|
||||
spm_enable_cpu_auto_off(cluster, cpu);
|
||||
|
||||
if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
|
||||
if (cluster == 1)
|
||||
mt_gic_sync_dcm_enable();
|
||||
|
||||
plat_mtk_cci_disable();
|
||||
spm_enable_cluster_auto_off(cluster);
|
||||
}
|
||||
|
||||
spm_set_cpu_power_off(cluster, cpu);
|
||||
}
|
||||
|
||||
static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state)
|
||||
{
|
||||
uint64_t mpidr = read_mpidr();
|
||||
int cpu = MPIDR_AFFLVL0_VAL(mpidr);
|
||||
int cluster = MPIDR_AFFLVL1_VAL(mpidr);
|
||||
|
||||
INFO("%s():%d: c.c: %d.%d\n", __func__, __LINE__, cluster, cpu);
|
||||
|
||||
assert(state->pwr_domain_state[MPIDR_AFFLVL0] == MTK_LOCAL_STATE_OFF);
|
||||
|
||||
if (state->pwr_domain_state[MPIDR_AFFLVL1] == MTK_LOCAL_STATE_OFF) {
|
||||
enable_scu(mpidr);
|
||||
|
||||
/* Enable coherency if this cluster was off */
|
||||
plat_mtk_cci_enable();
|
||||
/* Enable big core dcm if this cluster was on */
|
||||
plat_dcm_restore_cluster_on(mpidr);
|
||||
/* Enable rgu dcm if this cluster was off */
|
||||
plat_dcm_rgu_enable();
|
||||
}
|
||||
|
||||
spm_disable_cpu_auto_off(cluster, cpu);
|
||||
|
||||
/* Enable the gic cpu interface */
|
||||
mt_gic_pcpu_init();
|
||||
mt_gic_cpuif_enable();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* MTK handlers to shutdown/reboot the system
|
||||
******************************************************************************/
|
||||
static void __dead2 plat_mtk_system_off(void)
|
||||
{
|
||||
INFO("MTK System Off\n");
|
||||
|
||||
rtc_power_off_sequence();
|
||||
wk_pmic_enable_sdn_delay();
|
||||
pmic_power_off();
|
||||
|
||||
wfi();
|
||||
ERROR("MTK System Off: operation not handled.\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
static void __dead2 plat_mtk_system_reset(void)
|
||||
{
|
||||
struct bl_aux_gpio_info *gpio_reset = plat_get_mtk_gpio_reset();
|
||||
|
||||
INFO("MTK System Reset\n");
|
||||
|
||||
mt_set_gpio_out(gpio_reset->index, gpio_reset->polarity);
|
||||
|
||||
wfi();
|
||||
ERROR("MTK System Reset: operation not handled.\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* MTK_platform handler called when an affinity instance is about to be turned
|
||||
* on. The level and mpidr determine the affinity instance.
|
||||
******************************************************************************/
|
||||
static uintptr_t secure_entrypoint;
|
||||
|
||||
static const plat_psci_ops_t plat_plat_pm_ops = {
|
||||
.cpu_standby = NULL,
|
||||
.pwr_domain_on = NULL,
|
||||
.pwr_domain_on_finish = NULL,
|
||||
.pwr_domain_off = NULL,
|
||||
.pwr_domain_on = plat_mtk_power_domain_on,
|
||||
.pwr_domain_on_finish = plat_mtk_power_domain_on_finish,
|
||||
.pwr_domain_off = plat_mtk_power_domain_off,
|
||||
.pwr_domain_suspend = NULL,
|
||||
.pwr_domain_suspend_finish = NULL,
|
||||
.system_off = NULL,
|
||||
.system_reset = NULL,
|
||||
.system_off = plat_mtk_system_off,
|
||||
.system_reset = plat_mtk_system_reset,
|
||||
.validate_power_state = NULL,
|
||||
.get_sys_suspend_power_state = NULL,
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#
|
||||
# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved.
|
||||
# Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
@ -9,6 +9,10 @@ MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT}
|
|||
|
||||
PLAT_INCLUDES := -I${MTK_PLAT}/common/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/spmc/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/gpio/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/pmic/ \
|
||||
-I${MTK_PLAT_SOC}/drivers/rtc/ \
|
||||
-I${MTK_PLAT_SOC}/include/
|
||||
|
||||
PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \
|
||||
|
@ -27,17 +31,26 @@ BL31_SOURCES += common/desc_image_load.c \
|
|||
drivers/delay_timer/generic_delay_timer.c \
|
||||
drivers/gpio/gpio.c \
|
||||
drivers/ti/uart/aarch64/16550_console.S \
|
||||
lib/bl_aux_params/bl_aux_params.c \
|
||||
lib/cpus/aarch64/aem_generic.S \
|
||||
lib/cpus/aarch64/cortex_a53.S \
|
||||
lib/cpus/aarch64/cortex_a73.S \
|
||||
plat/common/plat_gicv3.c \
|
||||
${MTK_PLAT}/common/mtk_plat_common.c \
|
||||
${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \
|
||||
${MTK_PLAT}/common/drivers/rtc/rtc_common.c \
|
||||
${MTK_PLAT}/common/params_setup.c \
|
||||
${MTK_PLAT_SOC}/aarch64/plat_helpers.S \
|
||||
${MTK_PLAT_SOC}/aarch64/platform_common.c \
|
||||
${MTK_PLAT_SOC}/drivers/mcsi/mcsi.c \
|
||||
${MTK_PLAT_SOC}/drivers/pmic/pmic.c \
|
||||
${MTK_PLAT_SOC}/drivers/rtc/rtc.c \
|
||||
${MTK_PLAT_SOC}/drivers/spmc/mtspmc.c \
|
||||
${MTK_PLAT_SOC}/drivers/gpio/mtgpio.c \
|
||||
${MTK_PLAT_SOC}/plat_pm.c \
|
||||
${MTK_PLAT_SOC}/plat_topology.c \
|
||||
${MTK_PLAT_SOC}/plat_mt_gic.c \
|
||||
${MTK_PLAT_SOC}/plat_dcm.c \
|
||||
${MTK_PLAT_SOC}/bl31_plat_setup.c \
|
||||
${MTK_PLAT_SOC}/plat_debug.c \
|
||||
${MTK_PLAT_SOC}/scu.c
|
||||
|
@ -57,3 +70,5 @@ MULTI_CONSOLE_API := 1
|
|||
MACH_MT8183 := 1
|
||||
$(eval $(call add_define,MACH_MT8183))
|
||||
|
||||
include lib/coreboot/coreboot.mk
|
||||
|
||||
|
|
Loading…
Reference in New Issue