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