From: kenny liang Date: Thu, 2 May 2019 12:02:05 +0000 (+0800) Subject: mediatek: mt8183: support system off X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=e977b4db2a96f3587f1eb1b82efa90d80def4605;p=project%2Fbcm63xx%2Fatf.git mediatek: mt8183: support system off - Add PMIC driver - Add RTC drvier - Refactor PMIC and RTC to mediatek/common - Implement system off handler Change-Id: If76497646ace1b78bc9a5fa0110b652fe512281a Signed-off-by: kenny liang --- diff --git a/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c b/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c new file mode 100644 index 00000000..e3cfd46a --- /dev/null +++ b/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* 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); +} diff --git a/plat/mediatek/common/drivers/rtc/rtc_common.c b/plat/mediatek/common/drivers/rtc/rtc_common.c new file mode 100644 index 00000000..cad12a03 --- /dev/null +++ b/plat/mediatek/common/drivers/rtc/rtc_common.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +/* 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; +} + diff --git a/plat/mediatek/mt8183/drivers/pmic/pmic.c b/plat/mediatek/mt8183/drivers/pmic/pmic.c new file mode 100644 index 00000000..818c1493 --- /dev/null +++ b/plat/mediatek/mt8183/drivers/pmic/pmic.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +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); +} diff --git a/plat/mediatek/mt8183/drivers/pmic/pmic.h b/plat/mediatek/mt8183/drivers/pmic/pmic.h new file mode 100644 index 00000000..d62c6daf --- /dev/null +++ b/plat/mediatek/mt8183/drivers/pmic/pmic.h @@ -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 */ diff --git a/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h b/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 00000000..679c5e4c --- /dev/null +++ b/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.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 +#include + +/* 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 */ diff --git a/plat/mediatek/mt8183/drivers/rtc/rtc.c b/plat/mediatek/mt8183/drivers/rtc/rtc.c new file mode 100644 index 00000000..a821c1bc --- /dev/null +++ b/plat/mediatek/mt8183/drivers/rtc/rtc.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +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)); + } +} diff --git a/plat/mediatek/mt8183/drivers/rtc/rtc.h b/plat/mediatek/mt8183/drivers/rtc/rtc.h new file mode 100644 index 00000000..66686b40 --- /dev/null +++ b/plat/mediatek/mt8183/drivers/rtc/rtc.h @@ -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 */ diff --git a/plat/mediatek/mt8183/plat_pm.c b/plat/mediatek/mt8183/plat_pm.c index fa24e2e0..e2aa2b9e 100644 --- a/plat/mediatek/mt8183/plat_pm.c +++ b/plat/mediatek/mt8183/plat_pm.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #define MTK_LOCAL_STATE_OFF 2 @@ -114,6 +116,22 @@ static void plat_mtk_power_domain_on_finish(const psci_power_state_t *state) 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(); +} + /******************************************************************************* * MTK_platform handler called when an affinity instance is about to be turned * on. The level and mpidr determine the affinity instance. @@ -125,7 +143,7 @@ static const plat_psci_ops_t plat_plat_pm_ops = { .pwr_domain_off = plat_mtk_power_domain_off, .pwr_domain_suspend = NULL, .pwr_domain_suspend_finish = NULL, - .system_off = NULL, + .system_off = plat_mtk_system_off, .system_reset = NULL, .validate_power_state = NULL, .get_sys_suspend_power_state = NULL, diff --git a/plat/mediatek/mt8183/platform.mk b/plat/mediatek/mt8183/platform.mk index ae466b0f..f2e15e38 100644 --- a/plat/mediatek/mt8183/platform.mk +++ b/plat/mediatek/mt8183/platform.mk @@ -10,6 +10,8 @@ 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/pmic/ \ + -I${MTK_PLAT_SOC}/drivers/rtc/ \ -I${MTK_PLAT_SOC}/include/ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ @@ -33,9 +35,13 @@ BL31_SOURCES += common/desc_image_load.c \ 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_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}/plat_pm.c \ ${MTK_PLAT_SOC}/plat_topology.c \