1 /* Copyright 2023 The ChromiumOS Authors
2  * SPDX-License-Identifier: Apache-2.0
3  */
4 #include <zephyr/devicetree.h>
5 #include <zephyr/sys/util.h>
6 
7 /* Be warned: the interface here is poorly understood.  I did the best
8  * I could to transcribe it (with a little clarification and
9  * optimization) from the SOF mt8195 source, but without docs this
10  * needs to be treated with great care.
11  *
12  * Notes:
13  * * power-on default is 26Mhz, confirmed with a hacked SOF that
14  *   loads but stubs out the clk code.
15  * * The original driver has a 13Mhz mode too, but it doesn't work (it
16  *   hits all the same code and data paths as 26MHz and acts as a
17  *   duplicate.
18  * * The magic numbers in the pll_con2 field are from the original
19  *   source.  No docs on the PLL register interface are provided.
20  */
21 
22 struct mtk_pll_control {
23 	uint32_t con0;
24 	uint32_t con1;
25 	uint32_t con2;
26 	uint32_t con3;
27 	uint32_t con4;
28 };
29 
30 #define MTK_PLL_CTRL (*(volatile struct mtk_pll_control *)		\
31 		      DT_PROP(DT_NODELABEL(cpuclk), pll_ctrl_reg))
32 
33 #define MTK_PLL_CON0_BASE_EN BIT(0)
34 #define MTK_PLL_CON0_EN      BIT(9)
35 #define MTK_PLL_CON4_ISO_EN  BIT(1)
36 #define MTK_PLL_CON4_PWR_ON  BIT(0)
37 
38 struct mtk_clk_gen {
39 	uint32_t mode;
40 	uint32_t update[4];
41 	uint32_t _unused[3];
42 	struct {
43 		uint32_t cur;
44 		uint32_t set;
45 		uint32_t clr;
46 	} clk_cfg[29];
47 };
48 
49 #define MTK_CLK_GEN (*(volatile struct mtk_clk_gen *) \
50 		     DT_REG_ADDR(DT_NODELABEL(cpuclk)))
51 
52 #define MTK_CLK22_SEL_PLL 8
53 #define MTK_CLK22_SEL_26M 0
54 
55 #define MTK_CLK28_SEL_PLL 7
56 #define MTK_CLK28_SEL_26M 0
57 
58 #define MTK_CK_CG (*(volatile uint32_t *)			\
59 		   DT_PROP(DT_NODELABEL(cpuclk), cg_reg))
60 
61 #define MTK_CK_CG_SW 1
62 
63 const struct { uint16_t mhz; bool pll; uint32_t pll_con2; } freqs[] = {
64 	{  26, false, 0 },
65 	{ 370,  true, 0x831c7628 },
66 	{ 540,  true, 0x8214c4ed },
67 	{ 720,  true, 0x821bb13c },
68 };
69 
70 static int cur_idx;
71 
72 /* Can't use CPU-counted loops when changing CPU speed, and don't have
73  * an OS timer driver yet.  Use the 13 MHz timer hardware directly.
74  * (The ostimer is always running AFAICT, there's not even an
75  * interface for a disable bit defined)
76  */
77 #define TIMER (((volatile uint32_t *)DT_REG_ADDR(DT_NODELABEL(ostimer64)))[3])
delay_us(int us)78 static inline void delay_us(int us)
79 {
80 	uint32_t t0 = TIMER;
81 
82 	while (TIMER - t0 < (us * 13)) {
83 	}
84 }
85 
set_pll_power(bool on)86 static void set_pll_power(bool on)
87 {
88 	if (on) {
89 		MTK_CK_CG &= ~MTK_CK_CG_SW;
90 		MTK_PLL_CTRL.con4 |= MTK_PLL_CON4_PWR_ON;
91 		delay_us(1);
92 		MTK_PLL_CTRL.con4 &= ~MTK_PLL_CON4_ISO_EN;
93 		delay_us(1);
94 		MTK_PLL_CTRL.con0 |= MTK_PLL_CON0_EN;
95 		delay_us(20);
96 	} else {
97 		MTK_PLL_CTRL.con0 &= ~MTK_PLL_CON0_EN;
98 		delay_us(1);
99 		MTK_PLL_CTRL.con4 |= MTK_PLL_CON4_ISO_EN;
100 		delay_us(1);
101 		MTK_PLL_CTRL.con4 &= ~MTK_PLL_CON4_PWR_ON;
102 	}
103 }
104 
105 /* Oddball utility.  There is a giant array of clocks (of which SOF
106  * only touches two), each with "clear" and "set" registers which are
107  * used to set 4-bit fields at a specific offset.  After that, a
108  * particular bit in one of the "update" registers must be written,
109  * presumably to latch the input.
110  */
setclk(int clk,int shift,int updreg,int ubit,int val)111 static void setclk(int clk, int shift, int updreg, int ubit, int val)
112 {
113 	MTK_CLK_GEN.clk_cfg[clk].clr = (0xf << shift);
114 	if (val) {
115 		MTK_CLK_GEN.clk_cfg[clk].set = (val << shift);
116 	}
117 	MTK_CLK_GEN.update[updreg] = BIT(ubit);
118 }
119 
120 #define SETCLK22(val) setclk(22, 0, 2, 24, (val))
121 #define SETCLK28(val) setclk(28, 16, 3, 18, (val))
122 
mtk_adsp_set_cpu_freq(int mhz)123 void mtk_adsp_set_cpu_freq(int mhz)
124 {
125 	int idx;
126 
127 	for (idx = 0; idx < ARRAY_SIZE(freqs); idx++) {
128 		if (freqs[idx].mhz == mhz) {
129 			break;
130 		}
131 	}
132 
133 	if (idx == cur_idx || freqs[idx].mhz != mhz) {
134 		return;
135 	}
136 
137 	if (freqs[idx].pll) {
138 		/* Switch to PLL from 26Mhz */
139 		set_pll_power(true);
140 		SETCLK22(MTK_CLK22_SEL_PLL);
141 		SETCLK28(MTK_CLK28_SEL_PLL);
142 		MTK_PLL_CTRL.con2 = freqs[idx].pll_con2;
143 	} else {
144 		/* Switch to 26Mhz from PLL */
145 		SETCLK28(MTK_CLK28_SEL_26M);
146 		SETCLK22(MTK_CLK22_SEL_26M);
147 		set_pll_power(false);
148 	}
149 
150 	cur_idx = idx;
151 }
152 
153 /* The CPU clock is not affected (!) by device reset, so we don't know
154  * the speed we're at (on MT8195, hardware powers up at 26 Mhz, but
155  * production SOF firmware sets it to 720 at load time and leaves it
156  * there).  Set the lowest, then the highest speed unconditionally to
157  * force the transition.
158  */
mtk_adsp_cpu_freq_init(void)159 void mtk_adsp_cpu_freq_init(void)
160 {
161 	mtk_adsp_set_cpu_freq(freqs[0].mhz);
162 	mtk_adsp_set_cpu_freq(freqs[ARRAY_SIZE(freqs) - 1].mhz);
163 }
164