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:
Soby Mathew 2019-09-13 11:51:49 +00:00 committed by TrustedFirmware Code Review
commit 76eac18647
27 changed files with 4240 additions and 57 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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,
&reg_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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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
}
/*******************************************************************************

View File

@ -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,
};

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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));
}
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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 */

View File

@ -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

View File

@ -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();
}

View File

@ -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());

View File

@ -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,
};

View File

@ -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