1 /*
2  * Copyright (c) 2022, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 
9 #include <lib/mmio.h>
10 
11 #include "mt_cpu_pm_mbox.h"
12 #include <platform_def.h>
13 
14 #ifdef __GNUC__
15 #define MCDI_LIKELY(x)		__builtin_expect(!!(x), 1)
16 #define MCDI_UNLIKELY(x)	__builtin_expect(!!(x), 0)
17 #else
18 #define MCDI_LIKELY(x)		(x)
19 #define MCDI_UNLIKELY(x)	(x)
20 #endif
21 
22 #define MCUPM_MBOX_3_BASE		(CPU_EB_TCM_BASE + CPU_EB_MBOX3_OFFSET)
23 #define MCUPM_MBOX_WRITE(id, val)	mmio_write_32(MCUPM_MBOX_3_BASE + 4 * (id), val)
24 #define MCUPM_MBOX_READ(id)		mmio_read_32(MCUPM_MBOX_3_BASE + 4 * (id))
25 
mtk_set_mcupm_pll_mode(unsigned int mode)26 void mtk_set_mcupm_pll_mode(unsigned int mode)
27 {
28 	if (mode < NF_MCUPM_ARMPLL_MODE) {
29 		MCUPM_MBOX_WRITE(MCUPM_MBOX_ARMPLL_MODE, mode);
30 	}
31 }
32 
mtk_get_mcupm_pll_mode(void)33 int mtk_get_mcupm_pll_mode(void)
34 {
35 	return MCUPM_MBOX_READ(MCUPM_MBOX_ARMPLL_MODE);
36 }
37 
mtk_set_mcupm_buck_mode(unsigned int mode)38 void mtk_set_mcupm_buck_mode(unsigned int mode)
39 {
40 	if (mode < NF_MCUPM_BUCK_MODE) {
41 		MCUPM_MBOX_WRITE(MCUPM_MBOX_BUCK_MODE, mode);
42 	}
43 }
44 
mtk_get_mcupm_buck_mode(void)45 int mtk_get_mcupm_buck_mode(void)
46 {
47 	return MCUPM_MBOX_READ(MCUPM_MBOX_BUCK_MODE);
48 }
49 
mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid)50 void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid)
51 {
52 	return MCUPM_MBOX_WRITE(MCUPM_MBOX_WAKEUP_CPU, cpuid);
53 }
54 
mtk_get_cpu_pm_preffered_cpu(void)55 unsigned int mtk_get_cpu_pm_preffered_cpu(void)
56 {
57 	return MCUPM_MBOX_READ(MCUPM_MBOX_WAKEUP_CPU);
58 }
59 
mtk_wait_mbox_init_done(void)60 static int mtk_wait_mbox_init_done(void)
61 {
62 	int status = MCUPM_MBOX_READ(MCUPM_MBOX_TASK_STA);
63 
64 	if (status != MCUPM_TASK_INIT) {
65 		return status;
66 	}
67 
68 	mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
69 	mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
70 
71 	MCUPM_MBOX_WRITE(MCUPM_MBOX_PWR_CTRL_EN, (MCUPM_MCUSYS_CTRL | MCUPM_CM_CTRL |
72 						 MCUPM_BUCK_CTRL | MCUPM_ARMPLL_CTRL));
73 
74 	return status;
75 }
76 
mtk_lp_depd_condition(enum cpupm_mbox_depd_type type)77 int mtk_lp_depd_condition(enum cpupm_mbox_depd_type type)
78 {
79 	int status;
80 
81 	if (type == CPUPM_MBOX_WAIT_DEV_INIT) {
82 		status = mtk_wait_mbox_init_done();
83 		if (MCDI_UNLIKELY(status != MCUPM_TASK_INIT)) {
84 			return -ENXIO;
85 		}
86 		MCUPM_MBOX_WRITE(MCUPM_MBOX_AP_READY, 1);
87 	} else if (type == CPUPM_MBOX_WAIT_TASK_READY) {
88 		status = MCUPM_MBOX_READ(MCUPM_MBOX_TASK_STA);
89 		if (MCDI_UNLIKELY((status != MCUPM_TASK_WAIT) &&
90 				  (status != MCUPM_TASK_INIT_FINISH))) {
91 			return -ENXIO;
92 		}
93 	}
94 	return 0;
95 }
96