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