1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021, MediaTek Inc. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <cdefs.h> 8*91f16700Schasinglulu #include <common/debug.h> 9*91f16700Schasinglulu 10*91f16700Schasinglulu #include <lib/mmio.h> 11*91f16700Schasinglulu #include <lib/utils_def.h> 12*91f16700Schasinglulu #include <mt_mcdi.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu /* Read/Write */ 15*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_AP_READY U(0) 16*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_RESERVED_1 U(1) 17*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_RESERVED_2 U(2) 18*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_RESERVED_3 U(3) 19*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_PWR_CTRL_EN U(4) 20*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_L3_CACHE_MODE U(5) 21*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_BUCK_MODE U(6) 22*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_ARMPLL_MODE U(7) 23*91f16700Schasinglulu /* Read only */ 24*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_TASK_STA U(8) 25*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_RESERVED_9 U(9) 26*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_RESERVED_10 U(10) 27*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_RESERVED_11 U(11) 28*91f16700Schasinglulu 29*91f16700Schasinglulu /* CPC mode - Read/Write */ 30*91f16700Schasinglulu #define APMCU_MCUPM_MBOX_WAKEUP_CPU U(12) 31*91f16700Schasinglulu 32*91f16700Schasinglulu /* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN */ 33*91f16700Schasinglulu #define MCUPM_MCUSYS_CTRL BIT(0) 34*91f16700Schasinglulu #define MCUPM_BUCK_CTRL BIT(1) 35*91f16700Schasinglulu #define MCUPM_ARMPLL_CTRL BIT(2) 36*91f16700Schasinglulu #define MCUPM_CM_CTRL BIT(3) 37*91f16700Schasinglulu #define MCUPM_PWR_CTRL_MASK GENMASK(3, 0) 38*91f16700Schasinglulu 39*91f16700Schasinglulu /* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE */ 40*91f16700Schasinglulu #define MCUPM_BUCK_NORMAL_MODE U(0) /* default */ 41*91f16700Schasinglulu #define MCUPM_BUCK_LP_MODE U(1) 42*91f16700Schasinglulu #define MCUPM_BUCK_OFF_MODE U(2) 43*91f16700Schasinglulu #define NF_MCUPM_BUCK_MODE U(3) 44*91f16700Schasinglulu 45*91f16700Schasinglulu /* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE */ 46*91f16700Schasinglulu #define MCUPM_ARMPLL_ON U(0) /* default */ 47*91f16700Schasinglulu #define MCUPM_ARMPLL_GATING U(1) 48*91f16700Schasinglulu #define MCUPM_ARMPLL_OFF U(2) 49*91f16700Schasinglulu #define NF_MCUPM_ARMPLL_MODE U(3) 50*91f16700Schasinglulu 51*91f16700Schasinglulu /* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA */ 52*91f16700Schasinglulu #define MCUPM_TASK_UNINIT U(0) 53*91f16700Schasinglulu #define MCUPM_TASK_INIT U(1) 54*91f16700Schasinglulu #define MCUPM_TASK_INIT_FINISH U(2) 55*91f16700Schasinglulu #define MCUPM_TASK_WAIT U(3) 56*91f16700Schasinglulu #define MCUPM_TASK_RUN U(4) 57*91f16700Schasinglulu #define MCUPM_TASK_PAUSE U(5) 58*91f16700Schasinglulu 59*91f16700Schasinglulu #define SSPM_MBOX_3_BASE U(0x0c55fce0) 60*91f16700Schasinglulu 61*91f16700Schasinglulu #define MCDI_NOT_INIT 0 62*91f16700Schasinglulu #define MCDI_INIT_1 1 63*91f16700Schasinglulu #define MCDI_INIT_2 2 64*91f16700Schasinglulu #define MCDI_INIT_DONE 3 65*91f16700Schasinglulu 66*91f16700Schasinglulu static int mcdi_init_status __section(".tzfw_coherent_mem"); 67*91f16700Schasinglulu 68*91f16700Schasinglulu static inline uint32_t mcdi_mbox_read(uint32_t id) 69*91f16700Schasinglulu { 70*91f16700Schasinglulu return mmio_read_32(SSPM_MBOX_3_BASE + (id << 2)); 71*91f16700Schasinglulu } 72*91f16700Schasinglulu 73*91f16700Schasinglulu static inline void mcdi_mbox_write(uint32_t id, uint32_t val) 74*91f16700Schasinglulu { 75*91f16700Schasinglulu mmio_write_32(SSPM_MBOX_3_BASE + (id << 2), val); 76*91f16700Schasinglulu } 77*91f16700Schasinglulu 78*91f16700Schasinglulu static void mtk_mcupm_pwr_ctrl_setting(uint32_t dev) 79*91f16700Schasinglulu { 80*91f16700Schasinglulu mcdi_mbox_write(APMCU_MCUPM_MBOX_PWR_CTRL_EN, dev); 81*91f16700Schasinglulu } 82*91f16700Schasinglulu 83*91f16700Schasinglulu static void mtk_set_mcupm_pll_mode(uint32_t mode) 84*91f16700Schasinglulu { 85*91f16700Schasinglulu if (mode < NF_MCUPM_ARMPLL_MODE) { 86*91f16700Schasinglulu mcdi_mbox_write(APMCU_MCUPM_MBOX_ARMPLL_MODE, mode); 87*91f16700Schasinglulu } 88*91f16700Schasinglulu } 89*91f16700Schasinglulu 90*91f16700Schasinglulu static void mtk_set_mcupm_buck_mode(uint32_t mode) 91*91f16700Schasinglulu { 92*91f16700Schasinglulu if (mode < NF_MCUPM_BUCK_MODE) { 93*91f16700Schasinglulu mcdi_mbox_write(APMCU_MCUPM_MBOX_BUCK_MODE, mode); 94*91f16700Schasinglulu } 95*91f16700Schasinglulu } 96*91f16700Schasinglulu 97*91f16700Schasinglulu static int mtk_mcupm_is_ready(void) 98*91f16700Schasinglulu { 99*91f16700Schasinglulu unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); 100*91f16700Schasinglulu 101*91f16700Schasinglulu return (sta == MCUPM_TASK_WAIT) || (sta == MCUPM_TASK_INIT_FINISH); 102*91f16700Schasinglulu } 103*91f16700Schasinglulu 104*91f16700Schasinglulu static int mcdi_init_1(void) 105*91f16700Schasinglulu { 106*91f16700Schasinglulu unsigned int sta = mcdi_mbox_read(APMCU_MCUPM_MBOX_TASK_STA); 107*91f16700Schasinglulu 108*91f16700Schasinglulu if (sta != MCUPM_TASK_INIT) { 109*91f16700Schasinglulu return -1; 110*91f16700Schasinglulu } 111*91f16700Schasinglulu 112*91f16700Schasinglulu mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF); 113*91f16700Schasinglulu mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE); 114*91f16700Schasinglulu 115*91f16700Schasinglulu mtk_mcupm_pwr_ctrl_setting( 116*91f16700Schasinglulu MCUPM_MCUSYS_CTRL | 117*91f16700Schasinglulu MCUPM_BUCK_CTRL | 118*91f16700Schasinglulu MCUPM_ARMPLL_CTRL); 119*91f16700Schasinglulu 120*91f16700Schasinglulu mcdi_mbox_write(APMCU_MCUPM_MBOX_AP_READY, 1); 121*91f16700Schasinglulu 122*91f16700Schasinglulu return 0; 123*91f16700Schasinglulu } 124*91f16700Schasinglulu 125*91f16700Schasinglulu static int mcdi_init_2(void) 126*91f16700Schasinglulu { 127*91f16700Schasinglulu return mtk_mcupm_is_ready() ? 0 : -1; 128*91f16700Schasinglulu } 129*91f16700Schasinglulu 130*91f16700Schasinglulu int mcdi_try_init(void) 131*91f16700Schasinglulu { 132*91f16700Schasinglulu if (mcdi_init_status == MCDI_INIT_DONE) { 133*91f16700Schasinglulu return 0; 134*91f16700Schasinglulu } 135*91f16700Schasinglulu 136*91f16700Schasinglulu if (mcdi_init_status == MCDI_NOT_INIT) { 137*91f16700Schasinglulu mcdi_init_status = MCDI_INIT_1; 138*91f16700Schasinglulu } 139*91f16700Schasinglulu 140*91f16700Schasinglulu if (mcdi_init_status == MCDI_INIT_1 && mcdi_init_1() == 0) { 141*91f16700Schasinglulu mcdi_init_status = MCDI_INIT_2; 142*91f16700Schasinglulu } 143*91f16700Schasinglulu 144*91f16700Schasinglulu if (mcdi_init_status == MCDI_INIT_2 && mcdi_init_2() == 0) { 145*91f16700Schasinglulu mcdi_init_status = MCDI_INIT_DONE; 146*91f16700Schasinglulu } 147*91f16700Schasinglulu 148*91f16700Schasinglulu INFO("mcdi ready for mcusys-off-idle and system suspend\n"); 149*91f16700Schasinglulu 150*91f16700Schasinglulu return (mcdi_init_status == MCDI_INIT_DONE) ? 0 : mcdi_init_status; 151*91f16700Schasinglulu } 152