xref: /rk3399_ARM-atf/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c (revision 06cb65ef079941d0525dca75dd0e110e9330906d)
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