coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
spm.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <console/console.h>
5 #include <delay.h>
6 #include <device/mmio.h>
7 #include <soc/mcu_common.h>
8 #include <soc/spm.h>
9 #include <soc/spm_common.h>
10 #include <soc/symbols.h>
11 #include <timer.h>
12 
13 #define SPM_SYSTEM_BASE_OFFSET 0x40000000
14 
15 static const struct pwr_ctrl spm_init_ctrl = {
18 
19  /* SPM_AP_STANDBY_CON */
20  /* [0] */
21  .reg_wfi_op = 0,
22  /* [1] */
23  .reg_wfi_type = 0,
24  /* [2] */
25  .reg_mp0_cputop_idle_mask = 0,
26  /* [3] */
27  .reg_mp1_cputop_idle_mask = 0,
28  /* [4] */
29  .reg_mcusys_idle_mask = 0,
30  /* [25] */
31  .reg_md_apsrc_1_sel = 0,
32  /* [26] */
33  .reg_md_apsrc_0_sel = 0,
34  /* [29] */
35  .reg_conn_apsrc_sel = 0,
36 
37  /* SPM_SRC_REQ */
38  /* [0] */
39  .reg_spm_apsrc_req = 0,
40  /* [1] */
41  .reg_spm_f26m_req = 0,
42  /* [3] */
43  .reg_spm_infra_req = 0,
44  /* [4] */
45  .reg_spm_vrf18_req = 0,
46  /* [7] FIXME: default disable HW Auto S1*/
47  .reg_spm_ddr_en_req = 1,
48  /* [8] */
49  .reg_spm_dvfs_req = 0,
50  /* [9] */
51  .reg_spm_sw_mailbox_req = 0,
52  /* [10] */
53  .reg_spm_sspm_mailbox_req = 0,
54  /* [11] */
55  .reg_spm_adsp_mailbox_req = 0,
56  /* [12] */
57  .reg_spm_scp_mailbox_req = 0,
58 
59  /* SPM_SRC_MASK */
60  /* [0] */
61  .reg_sspm_srcclkena_0_mask_b = 1,
62  /* [1] */
63  .reg_sspm_infra_req_0_mask_b = 1,
64  /* [2] */
65  .reg_sspm_apsrc_req_0_mask_b = 1,
66  /* [3] */
67  .reg_sspm_vrf18_req_0_mask_b = 1,
68  /* [4] */
69  .reg_sspm_ddr_en_0_mask_b = 1,
70  /* [5] */
71  .reg_scp_srcclkena_mask_b = 1,
72  /* [6] */
73  .reg_scp_infra_req_mask_b = 1,
74  /* [7] */
75  .reg_scp_apsrc_req_mask_b = 1,
76  /* [8] */
77  .reg_scp_vrf18_req_mask_b = 1,
78  /* [9] */
79  .reg_scp_ddr_en_mask_b = 1,
80  /* [10] */
81  .reg_audio_dsp_srcclkena_mask_b = 1,
82  /* [11] */
83  .reg_audio_dsp_infra_req_mask_b = 1,
84  /* [12] */
85  .reg_audio_dsp_apsrc_req_mask_b = 1,
86  /* [13] */
87  .reg_audio_dsp_vrf18_req_mask_b = 1,
88  /* [14] */
89  .reg_audio_dsp_ddr_en_mask_b = 1,
90  /* [15] */
91  .reg_apu_srcclkena_mask_b = 1,
92  /* [16] */
93  .reg_apu_infra_req_mask_b = 1,
94  /* [17] */
95  .reg_apu_apsrc_req_mask_b = 1,
96  /* [18] */
97  .reg_apu_vrf18_req_mask_b = 1,
98  /* [19] */
99  .reg_apu_ddr_en_mask_b = 1,
100  /* [20] */
101  .reg_cpueb_srcclkena_mask_b = 1,
102  /* [21] */
103  .reg_cpueb_infra_req_mask_b = 1,
104  /* [22] */
105  .reg_cpueb_apsrc_req_mask_b = 1,
106  /* [23] */
107  .reg_cpueb_vrf18_req_mask_b = 1,
108  /* [24] */
109  .reg_cpueb_ddr_en_mask_b = 1,
110  /* [25] */
111  .reg_bak_psri_srcclkena_mask_b = 0,
112  /* [26] */
113  .reg_bak_psri_infra_req_mask_b = 0,
114  /* [27] */
115  .reg_bak_psri_apsrc_req_mask_b = 0,
116  /* [28] */
117  .reg_bak_psri_vrf18_req_mask_b = 0,
118  /* [29] */
119  .reg_bak_psri_ddr_en_mask_b = 0,
120 
121  /* SPM_SRC2_MASK */
122  /* [0] */
123  .reg_msdc0_srcclkena_mask_b = 1,
124  /* [1] */
125  .reg_msdc0_infra_req_mask_b = 1,
126  /* [2] */
127  .reg_msdc0_apsrc_req_mask_b = 1,
128  /* [3] */
129  .reg_msdc0_vrf18_req_mask_b = 1,
130  /* [4] */
131  .reg_msdc0_ddr_en_mask_b = 1,
132  /* [5] */
133  .reg_msdc1_srcclkena_mask_b = 1,
134  /* [6] */
135  .reg_msdc1_infra_req_mask_b = 1,
136  /* [7] */
137  .reg_msdc1_apsrc_req_mask_b = 1,
138  /* [8] */
139  .reg_msdc1_vrf18_req_mask_b = 1,
140  /* [9] */
141  .reg_msdc1_ddr_en_mask_b = 1,
142  /* [10] */
143  .reg_msdc2_srcclkena_mask_b = 1,
144  /* [11] */
145  .reg_msdc2_infra_req_mask_b = 1,
146  /* [12] */
147  .reg_msdc2_apsrc_req_mask_b = 1,
148  /* [13] */
149  .reg_msdc2_vrf18_req_mask_b = 1,
150  /* [14] */
151  .reg_msdc2_ddr_en_mask_b = 1,
152  /* [15] */
153  .reg_ufs_srcclkena_mask_b = 1,
154  /* [16] */
155  .reg_ufs_infra_req_mask_b = 1,
156  /* [17] */
157  .reg_ufs_apsrc_req_mask_b = 1,
158  /* [18] */
159  .reg_ufs_vrf18_req_mask_b = 1,
160  /* [19] */
161  .reg_ufs_ddr_en_mask_b = 1,
162  /* [20] */
163  .reg_usb_srcclkena_mask_b = 1,
164  /* [21] */
165  .reg_usb_infra_req_mask_b = 1,
166  /* [22] */
167  .reg_usb_apsrc_req_mask_b = 1,
168  /* [23] */
169  .reg_usb_vrf18_req_mask_b = 1,
170  /* [24] */
171  .reg_usb_ddr_en_mask_b = 1,
172  /* [25] */
173  .reg_pextp_p0_srcclkena_mask_b = 1,
174  /* [26] */
175  .reg_pextp_p0_infra_req_mask_b = 1,
176  /* [27] */
177  .reg_pextp_p0_apsrc_req_mask_b = 1,
178  /* [28] */
179  .reg_pextp_p0_vrf18_req_mask_b = 1,
180  /* [29] */
181  .reg_pextp_p0_ddr_en_mask_b = 1,
182 
183  /* SPM_SRC3_MASK */
184  /* [0] */
185  .reg_pextp_p1_srcclkena_mask_b = 1,
186  /* [1] */
187  .reg_pextp_p1_infra_req_mask_b = 1,
188  /* [2] */
189  .reg_pextp_p1_apsrc_req_mask_b = 1,
190  /* [3] */
191  .reg_pextp_p1_vrf18_req_mask_b = 1,
192  /* [4] */
193  .reg_pextp_p1_ddr_en_mask_b = 1,
194  /* [5] */
195  .reg_gce0_infra_req_mask_b = 1,
196  /* [6] */
197  .reg_gce0_apsrc_req_mask_b = 1,
198  /* [7] */
199  .reg_gce0_vrf18_req_mask_b = 1,
200  /* [8] */
201  .reg_gce0_ddr_en_mask_b = 1,
202  /* [9] */
203  .reg_gce1_infra_req_mask_b = 1,
204  /* [10] */
205  .reg_gce1_apsrc_req_mask_b = 1,
206  /* [11] */
207  .reg_gce1_vrf18_req_mask_b = 1,
208  /* [12] */
209  .reg_gce1_ddr_en_mask_b = 1,
210  /* [13] */
211  .reg_spm_srcclkena_reserved_mask_b = 1,
212  /* [14] */
213  .reg_spm_infra_req_reserved_mask_b = 1,
214  /* [15] */
215  .reg_spm_apsrc_req_reserved_mask_b = 1,
216  /* [16] */
217  .reg_spm_vrf18_req_reserved_mask_b = 1,
218  /* [17] */
219  .reg_spm_ddr_en_reserved_mask_b = 1,
220  /* [18] */
221  .reg_disp0_apsrc_req_mask_b = 1,
222  /* [19] */
223  .reg_disp0_ddr_en_mask_b = 1,
224  /* [20] */
225  .reg_disp1_apsrc_req_mask_b = 1,
226  /* [21] */
227  .reg_disp1_ddr_en_mask_b = 1,
228  /* [22] */
229  .reg_disp2_apsrc_req_mask_b = 1,
230  /* [23] */
231  .reg_disp2_ddr_en_mask_b = 1,
232  /* [24] */
233  .reg_disp3_apsrc_req_mask_b = 1,
234  /* [25] */
235  .reg_disp3_ddr_en_mask_b = 1,
236  /* [26] */
237  .reg_infrasys_apsrc_req_mask_b = 0,
238  /* [27] */
239  .reg_infrasys_ddr_en_mask_b = 1,
240 
241  /* [28] */
242  .reg_cg_check_srcclkena_mask_b = 1,
243  /* [29] */
244  .reg_cg_check_apsrc_req_mask_b = 1,
245  /* [30] */
246  .reg_cg_check_vrf18_req_mask_b = 1,
247  /* [31] */
248  .reg_cg_check_ddr_en_mask_b = 1,
249 
250  /* SPM_SRC4_MASK */
251  /* [8:0] */
252  .reg_mcusys_merge_apsrc_req_mask_b = 0x17,
253  /* [17:9] */
254  .reg_mcusys_merge_ddr_en_mask_b = 0x17,
255  /* [19:18] */
256  .reg_dramc_md32_infra_req_mask_b = 0,
257  /* [21:20] */
258  .reg_dramc_md32_vrf18_req_mask_b = 0,
259  /* [23:22] */
260  .reg_dramc_md32_ddr_en_mask_b = 0,
261  /* [24] */
262  .reg_dvfsrc_event_trigger_mask_b = 1,
263 
264  /* SPM_WAKEUP_EVENT_MASK2 */
265  /* [3:0] */
266  .reg_sc_sw2spm_wakeup_mask_b = 0,
267  /* [4] */
268  .reg_sc_adsp2spm_wakeup_mask_b = 0,
269  /* [8:5] */
270  .reg_sc_sspm2spm_wakeup_mask_b = 0,
271  /* [9] */
272  .reg_sc_scp2spm_wakeup_mask_b = 0,
273  /* [10] */
274  .reg_csyspwrup_ack_mask = 0,
275  /* [11] */
276  .reg_csyspwrup_req_mask = 1,
277 
278  /* SPM_WAKEUP_EVENT_MASK */
279  /* [31:0] */
280  .reg_wakeup_event_mask = 0xC1382213,
281 
282  /* SPM_WAKEUP_EVENT_EXT_MASK */
283  /* [31:0] */
284  .reg_ext_wakeup_event_mask = 0xFFFFFFFF,
285 };
286 
287 static void spm_set_power_control(const struct pwr_ctrl *pwrctrl)
288 {
289  /* Auto-gen Start */
290 
291  /* SPM_AP_STANDBY_CON */
293  ((pwrctrl->reg_wfi_op & 0x1) << 0) |
294  ((pwrctrl->reg_wfi_type & 0x1) << 1) |
295  ((pwrctrl->reg_mp0_cputop_idle_mask & 0x1) << 2) |
296  ((pwrctrl->reg_mp1_cputop_idle_mask & 0x1) << 3) |
297  ((pwrctrl->reg_mcusys_idle_mask & 0x1) << 4) |
298  ((pwrctrl->reg_md_apsrc_1_sel & 0x1) << 25) |
299  ((pwrctrl->reg_md_apsrc_0_sel & 0x1) << 26) |
300  ((pwrctrl->reg_conn_apsrc_sel & 0x1) << 29));
301 
302  /* SPM_SRC_REQ */
304  ((pwrctrl->reg_spm_apsrc_req & 0x1) << 0) |
305  ((pwrctrl->reg_spm_f26m_req & 0x1) << 1) |
306  ((pwrctrl->reg_spm_infra_req & 0x1) << 3) |
307  ((pwrctrl->reg_spm_vrf18_req & 0x1) << 4) |
308  ((pwrctrl->reg_spm_ddr_en_req & 0x1) << 7) |
309  ((pwrctrl->reg_spm_dvfs_req & 0x1) << 8) |
310  ((pwrctrl->reg_spm_sw_mailbox_req & 0x1) << 9) |
311  ((pwrctrl->reg_spm_sspm_mailbox_req & 0x1) << 10) |
312  ((pwrctrl->reg_spm_adsp_mailbox_req & 0x1) << 11) |
313  ((pwrctrl->reg_spm_scp_mailbox_req & 0x1) << 12));
314 
315  /* SPM_SRC_MASK */
317  ((pwrctrl->reg_sspm_srcclkena_0_mask_b & 0x1) << 0) |
318  ((pwrctrl->reg_sspm_infra_req_0_mask_b & 0x1) << 1) |
319  ((pwrctrl->reg_sspm_apsrc_req_0_mask_b & 0x1) << 2) |
320  ((pwrctrl->reg_sspm_vrf18_req_0_mask_b & 0x1) << 3) |
321  ((pwrctrl->reg_sspm_ddr_en_0_mask_b & 0x1) << 4) |
322  ((pwrctrl->reg_scp_srcclkena_mask_b & 0x1) << 5) |
323  ((pwrctrl->reg_scp_infra_req_mask_b & 0x1) << 6) |
324  ((pwrctrl->reg_scp_apsrc_req_mask_b & 0x1) << 7) |
325  ((pwrctrl->reg_scp_vrf18_req_mask_b & 0x1) << 8) |
326  ((pwrctrl->reg_scp_ddr_en_mask_b & 0x1) << 9) |
327  ((pwrctrl->reg_audio_dsp_srcclkena_mask_b & 0x1) << 10) |
328  ((pwrctrl->reg_audio_dsp_infra_req_mask_b & 0x1) << 11) |
329  ((pwrctrl->reg_audio_dsp_apsrc_req_mask_b & 0x1) << 12) |
330  ((pwrctrl->reg_audio_dsp_vrf18_req_mask_b & 0x1) << 13) |
331  ((pwrctrl->reg_audio_dsp_ddr_en_mask_b & 0x1) << 14) |
332  ((pwrctrl->reg_apu_srcclkena_mask_b & 0x1) << 15) |
333  ((pwrctrl->reg_apu_infra_req_mask_b & 0x1) << 16) |
334  ((pwrctrl->reg_apu_apsrc_req_mask_b & 0x1) << 17) |
335  ((pwrctrl->reg_apu_vrf18_req_mask_b & 0x1) << 18) |
336  ((pwrctrl->reg_apu_ddr_en_mask_b & 0x1) << 19) |
337  ((pwrctrl->reg_cpueb_srcclkena_mask_b & 0x1) << 20) |
338  ((pwrctrl->reg_cpueb_infra_req_mask_b & 0x1) << 21) |
339  ((pwrctrl->reg_cpueb_apsrc_req_mask_b & 0x1) << 22) |
340  ((pwrctrl->reg_cpueb_vrf18_req_mask_b & 0x1) << 23) |
341  ((pwrctrl->reg_cpueb_ddr_en_mask_b & 0x1) << 24) |
342  ((pwrctrl->reg_bak_psri_srcclkena_mask_b & 0x1) << 25) |
343  ((pwrctrl->reg_bak_psri_infra_req_mask_b & 0x1) << 26) |
344  ((pwrctrl->reg_bak_psri_apsrc_req_mask_b & 0x1) << 27) |
345  ((pwrctrl->reg_bak_psri_vrf18_req_mask_b & 0x1) << 28) |
346  ((pwrctrl->reg_bak_psri_ddr_en_mask_b & 0x1) << 29));
347 
348  /* SPM_SRC2_MASK */
350  ((pwrctrl->reg_msdc0_srcclkena_mask_b & 0x1) << 0) |
351  ((pwrctrl->reg_msdc0_infra_req_mask_b & 0x1) << 1) |
352  ((pwrctrl->reg_msdc0_apsrc_req_mask_b & 0x1) << 2) |
353  ((pwrctrl->reg_msdc0_vrf18_req_mask_b & 0x1) << 3) |
354  ((pwrctrl->reg_msdc0_ddr_en_mask_b & 0x1) << 4) |
355  ((pwrctrl->reg_msdc1_srcclkena_mask_b & 0x1) << 5) |
356  ((pwrctrl->reg_msdc1_infra_req_mask_b & 0x1) << 6) |
357  ((pwrctrl->reg_msdc1_apsrc_req_mask_b & 0x1) << 7) |
358  ((pwrctrl->reg_msdc1_vrf18_req_mask_b & 0x1) << 8) |
359  ((pwrctrl->reg_msdc1_ddr_en_mask_b & 0x1) << 9) |
360  ((pwrctrl->reg_msdc2_srcclkena_mask_b & 0x1) << 10) |
361  ((pwrctrl->reg_msdc2_infra_req_mask_b & 0x1) << 11) |
362  ((pwrctrl->reg_msdc2_apsrc_req_mask_b & 0x1) << 12) |
363  ((pwrctrl->reg_msdc2_vrf18_req_mask_b & 0x1) << 13) |
364  ((pwrctrl->reg_msdc2_ddr_en_mask_b & 0x1) << 14) |
365  ((pwrctrl->reg_ufs_srcclkena_mask_b & 0x1) << 15) |
366  ((pwrctrl->reg_ufs_infra_req_mask_b & 0x1) << 16) |
367  ((pwrctrl->reg_ufs_apsrc_req_mask_b & 0x1) << 17) |
368  ((pwrctrl->reg_ufs_vrf18_req_mask_b & 0x1) << 18) |
369  ((pwrctrl->reg_ufs_ddr_en_mask_b & 0x1) << 19) |
370  ((pwrctrl->reg_usb_srcclkena_mask_b & 0x1) << 20) |
371  ((pwrctrl->reg_usb_infra_req_mask_b & 0x1) << 21) |
372  ((pwrctrl->reg_usb_apsrc_req_mask_b & 0x1) << 22) |
373  ((pwrctrl->reg_usb_vrf18_req_mask_b & 0x1) << 23) |
374  ((pwrctrl->reg_usb_ddr_en_mask_b & 0x1) << 24) |
375  ((pwrctrl->reg_pextp_p0_srcclkena_mask_b & 0x1) << 25) |
376  ((pwrctrl->reg_pextp_p0_infra_req_mask_b & 0x1) << 26) |
377  ((pwrctrl->reg_pextp_p0_apsrc_req_mask_b & 0x1) << 27) |
378  ((pwrctrl->reg_pextp_p0_vrf18_req_mask_b & 0x1) << 28) |
379  ((pwrctrl->reg_pextp_p0_ddr_en_mask_b & 0x1) << 29));
380 
381  /* SPM_SRC3_MASK */
383  ((pwrctrl->reg_pextp_p1_srcclkena_mask_b & 0x1) << 0) |
384  ((pwrctrl->reg_pextp_p1_infra_req_mask_b & 0x1) << 1) |
385  ((pwrctrl->reg_pextp_p1_apsrc_req_mask_b & 0x1) << 2) |
386  ((pwrctrl->reg_pextp_p1_vrf18_req_mask_b & 0x1) << 3) |
387  ((pwrctrl->reg_pextp_p1_ddr_en_mask_b & 0x1) << 4) |
388  ((pwrctrl->reg_gce0_infra_req_mask_b & 0x1) << 5) |
389  ((pwrctrl->reg_gce0_apsrc_req_mask_b & 0x1) << 6) |
390  ((pwrctrl->reg_gce0_vrf18_req_mask_b & 0x1) << 7) |
391  ((pwrctrl->reg_gce0_ddr_en_mask_b & 0x1) << 8) |
392  ((pwrctrl->reg_gce1_infra_req_mask_b & 0x1) << 9) |
393  ((pwrctrl->reg_gce1_apsrc_req_mask_b & 0x1) << 10) |
394  ((pwrctrl->reg_gce1_vrf18_req_mask_b & 0x1) << 11) |
395  ((pwrctrl->reg_gce1_ddr_en_mask_b & 0x1) << 12) |
396  ((pwrctrl->reg_spm_srcclkena_reserved_mask_b & 0x1) << 13) |
397  ((pwrctrl->reg_spm_infra_req_reserved_mask_b & 0x1) << 14) |
398  ((pwrctrl->reg_spm_apsrc_req_reserved_mask_b & 0x1) << 15) |
399  ((pwrctrl->reg_spm_vrf18_req_reserved_mask_b & 0x1) << 16) |
400  ((pwrctrl->reg_spm_ddr_en_reserved_mask_b & 0x1) << 17) |
401  ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 18) |
402  ((pwrctrl->reg_disp0_ddr_en_mask_b & 0x1) << 19) |
403  ((pwrctrl->reg_disp1_apsrc_req_mask_b & 0x1) << 20) |
404  ((pwrctrl->reg_disp1_ddr_en_mask_b & 0x1) << 21) |
405  ((pwrctrl->reg_disp2_apsrc_req_mask_b & 0x1) << 22) |
406  ((pwrctrl->reg_disp2_ddr_en_mask_b & 0x1) << 23) |
407  ((pwrctrl->reg_disp3_apsrc_req_mask_b & 0x1) << 24) |
408  ((pwrctrl->reg_disp3_ddr_en_mask_b & 0x1) << 25) |
409  ((pwrctrl->reg_infrasys_apsrc_req_mask_b & 0x1) << 26) |
410  ((pwrctrl->reg_infrasys_ddr_en_mask_b & 0x1) << 27));
411 
412  /* SPM_SRC4_MASK */
413  write32(&mtk_spm->spm_src4_mask, 0x1fc0000);
414 
415  /* SPM_WAKEUP_EVENT_MASK */
417  ((pwrctrl->reg_wakeup_event_mask & 0xffffffff) << 0));
418 
419  /* SPM_WAKEUP_EVENT_EXT_MASK */
421  ((pwrctrl->reg_ext_wakeup_event_mask & 0xffffffff) << 0));
422 
423  /* Auto-gen End */
424 }
425 
426 static void spm_register_init(void)
427 {
428  /* Enable register control */
431 
432  /* Init power control register */
435 
436  /* Reset PCM */
444 
445  /* Initial SPM CLK control register */
448 
449  /* Clean wakeup event raw status */
451 
452  /* Clean ISR status */
456 
457  /* Init r7 with POWER_ON_VAL1 */
462 
463  /* Configure ARMPLL Control Mode for MCDI */
465 
466  /* Init for SPM Resource ACK */
471 
472  /* Init VCORE DVFS Status */
478 
479 }
480 
481 static void spm_set_sysclk_settle(void)
482 {
484 }
485 
486 static void spm_code_swapping(void)
487 {
488  u32 mask;
489 
496 }
497 
498 static void spm_reset_and_init_pcm(void)
499 {
500  bool first_load_fw = true;
501 
502  /* Check the SPM FW is run or not */
505  first_load_fw = false;
506 
507  if (!first_load_fw) {
509  /* Backup PCM r0 -> SPM_POWER_ON_VAL0 before reset PCM */
512  }
513 
514  /* Disable r0 and r7 to control power */
516 
517  /* Disable pcm timer after leaving FW */
520 
521  /* Reset PCM */
525 
526  /* Init PCM_CON1 (disable PCM timer but keep PCM WDT setting) */
531 }
532 
533 static void spm_kick_im_to_fetch(const struct dyna_load_pcm *pcm)
534 {
535  uintptr_t ptr;
536  u32 dmem_words;
537  u32 pmem_words;
538  u32 total_words;
539  u32 pmem_start;
540  u32 dmem_start;
541 
542  ptr = (uintptr_t)pcm->buf + SPM_SYSTEM_BASE_OFFSET;
543  pmem_words = pcm->desc.pmem_words;
544  total_words = pcm->desc.total_words;
545  dmem_words = total_words - pmem_words;
546  pmem_start = pcm->desc.pmem_start;
547  dmem_start = pcm->desc.dmem_start;
548 
549  printk(BIOS_DEBUG, "%s: ptr = %#lx, pmem/dmem words = %#x/%#x\n",
550  __func__, (long)ptr, pmem_words, dmem_words);
551 
552  /* DMA needs 16-byte aligned source data. */
553  assert(ptr % 16 == 0);
554 
556  write32(&mtk_spm->md32pcm_dma0_dst, pmem_start);
557  write32(&mtk_spm->md32pcm_dma0_wppt, pmem_words);
558  write32(&mtk_spm->md32pcm_dma0_wpto, dmem_start);
559  write32(&mtk_spm->md32pcm_dma0_count, total_words);
562 
564 }
565 
566 static void spm_init_pcm_register(void)
567 {
568  /* Init r0 with POWER_ON_VAL0 */
573 
574  /* Init r7 with POWER_ON_VAL1 */
579 }
580 
581 static void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
582 {
583  u32 val, mask;
584 
585  /* Toggle event counter clear */
588 
589  /* Toggle for reset SYS TIMER start point */
592 
593  if (pwrctrl->timer_val_cust == 0)
594  val = pwrctrl->timer_val ? pwrctrl->timer_val : PCM_TIMER_MAX;
595  else
596  val = pwrctrl->timer_val_cust;
597 
599 
600  /* Disable pcm timer */
603 
604  /* Unmask AP wakeup source */
605  if (pwrctrl->wake_src_cust == 0)
606  mask = pwrctrl->wake_src;
607  else
608  mask = pwrctrl->wake_src_cust;
609 
611 
612  /* Unmask SPM ISR */
614  ISRM_TWAM_BF, 1,
615  ISRM_RET_IRQ_AUX_BF, 0x3ff);
616 
617  /* Toggle event counter clear */
620 
621  /* Toggle for reset SYS TIMER start point */
624 }
625 
626 static void spm_set_pcm_flags(const struct pwr_ctrl *pwrctrl)
627 {
628  u32 pcm_flags = pwrctrl->pcm_flags, pcm_flags1 = pwrctrl->pcm_flags1;
629 
630  /* Set PCM flags and data */
631  if (pwrctrl->pcm_flags_cust_clr != 0)
632  pcm_flags &= ~pwrctrl->pcm_flags_cust_clr;
633  if (pwrctrl->pcm_flags_cust_set != 0)
634  pcm_flags |= pwrctrl->pcm_flags_cust_set;
635  if (pwrctrl->pcm_flags1_cust_clr != 0)
636  pcm_flags1 &= ~pwrctrl->pcm_flags1_cust_clr;
637  if (pwrctrl->pcm_flags1_cust_set != 0)
638  pcm_flags1 |= pwrctrl->pcm_flags1_cust_set;
639 
644 }
645 
646 static void spm_kick_pcm_to_run(const struct pwr_ctrl *pwrctrl)
647 {
648  /* Waiting for loading SPMFW done*/
649  while (read32(&mtk_spm->md32pcm_dma0_rlct) != 0x0)
650  ;
651 
652  /* Init register to match PCM expectation */
657 
658  spm_set_pcm_flags(pwrctrl);
659 
660  /* Kick PCM to run (only toggle PCM_KICK) */
662 
663  /* Reset md32pcm */
666 
667  /* Waiting for SPM init done */
669 }
670 
671 static void reset_spm(struct mtk_mcu *mcu)
672 {
673  struct dyna_load_pcm *pcm = (struct dyna_load_pcm *)mcu->priv;
674 
675  spm_parse_firmware(mcu);
681 }
682 
683 static struct mtk_mcu spm = {
684  .firmware_name = CONFIG_SPM_FIRMWARE,
685  .reset = reset_spm,
686 };
687 
688 int spm_init(void)
689 {
690  struct dyna_load_pcm pcm;
691  struct stopwatch sw;
692 
693  stopwatch_init(&sw);
694 
698 
699  spm.load_buffer = _dram_dma;
700  spm.buffer_size = REGION_SIZE(dram_dma);
701  spm.priv = (void *)&pcm;
702 
703  if (mtk_init_mcu(&spm)) {
704  printk(BIOS_ERR, "SPM: %s: failed in mtk_init_mcu\n", __func__);
705  return -1;
706  }
707 
708  printk(BIOS_INFO, "SPM: %s done in %ld msecs, spm pc = %#x\n",
709  __func__, stopwatch_duration_msecs(&sw),
711 
712  return 0;
713 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define assert(statement)
Definition: assert.h:74
void spm_parse_firmware(struct mtk_mcu *mcu)
Definition: spm.c:12
#define printk(level,...)
Definition: stdlib.h:16
#define setbits32(addr, set)
Definition: mmio.h:21
#define SET32_BITFIELDS(addr,...)
Definition: mmio.h:201
#define clrsetbits32(addr, clear, set)
Definition: mmio.h:16
#define REGION_SIZE(name)
Definition: symbols.h:10
static void stopwatch_init(struct stopwatch *sw)
Definition: timer.h:117
static long stopwatch_duration_msecs(struct stopwatch *sw)
Definition: timer.h:182
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
int mtk_init_mcu(struct mtk_mcu *mcu)
Definition: mcu.c:10
static struct mtk_spm_regs *const mtk_spm
Definition: spm.h:154
#define PCM_CK_EN_LSB
Definition: spm.h:32
#define SPM_WAKEUP_EVENT_MASK_DEF
Definition: spm.h:88
#define ISRM_ALL
Definition: spm.h:100
#define PCM_SW_RESET_LSB
Definition: spm.h:35
#define PCM_SW_INT_ALL
Definition: spm.h:118
#define BCLK_CG_EN_LSB
Definition: spm.h:15
#define SPM_REGWR_CFG_KEY
Definition: spm.h:12
#define PCM_RF_SYNC_R0
Definition: spm.h:113
#define PCM_RF_SYNC_R7
Definition: spm.h:115
#define POWER_ON_VAL1_DEF
Definition: spm.h:82
#define ISRC_ALL
Definition: spm.h:108
int spm_init(void)
Definition: spm.c:298
#define SPM_FLAG_DISABLE_VCORE_DVS
Definition: spm.h:92
#define REG_MD32_APB_INTERNAL_EN_LSB
Definition: spm.h:47
#define ARMPLL_CLK_SEL_DEF
Definition: spm.h:69
#define RG_PCM_WDT_WAKE_LSB
Definition: spm.h:85
#define MD32PCM_DMA0_START_VAL
Definition: spm.h:40
#define SPM_RESOURCE_ACK_CON0_DEF
Definition: spm.h:70
#define SPM_INIT_DONE_US
Definition: spm.h:16
#define SPM_BUS_PROTECT2_MASK_B_DEF
Definition: spm.h:90
#define MD32PCM_DMA0_CON_VAL
Definition: spm.h:39
#define SPM_FLAG_DISABLE_VCORE_DFS
Definition: spm.h:93
#define SPM_RESOURCE_ACK_CON2_DEF
Definition: spm.h:72
#define MD32PCM_CFGREG_SW_RSTN_RUN
Definition: spm.h:38
#define PCM_TIMER_MAX
Definition: spm.h:99
#define SPM_RESOURCE_ACK_CON1_DEF
Definition: spm.h:71
#define SPM_RESOURCE_ACK_CON3_DEF
Definition: spm.h:73
#define SPM_WAKEUP_EVENT_MASK_BIT0
Definition: spm.h:83
#define SPM_SYSCLK_SETTLE
Definition: spm.h:82
#define SPM_BUS_PROTECT_MASK_B_DEF
Definition: spm.h:89
#define RG_PCM_TIMER_EN_LSB
Definition: spm.h:84
#define RG_AHBMIF_APBEN_LSB
Definition: spm.h:46
#define SPM_DVS_DFS_LEVEL_DEF
Definition: spm.h:79
#define SPM_FLAG_RUN_COMMON_SCENARIO
Definition: spm.h:94
#define SPM_DVFS_LEVEL_DEF
Definition: spm.h:78
#define SYS_TIMER_START_EN_LSB
Definition: spm.h:51
#define REG_EVENT_LOCK_EN_LSB
Definition: spm.h:31
#define REG_SPM_SRAM_ISOINT_B_LSB
Definition: spm.h:30
#define SPM_EVENT_COUNTER_CLR_LSB
Definition: spm.h:28
#define SPM_DVFSRC_ENABLE_LSB
Definition: spm.h:43
#define SPM_DVFS_FORCE_ENABLE_LSB
Definition: spm.h:42
#define MD32PCM_CFGREG_SW_RSTN_RESET
Definition: spm.h:54
#define REG_SYSCLK1_SRC_MD2_SRCCLKENA
Definition: spm.h:18
static void spm_code_swapping(void)
Definition: spm.c:486
static void spm_set_wakeup_event(const struct pwr_ctrl *pwrctrl)
Definition: spm.c:581
static void reset_spm(struct mtk_mcu *mcu)
Definition: spm.c:671
static void spm_set_pcm_flags(const struct pwr_ctrl *pwrctrl)
Definition: spm.c:626
static void spm_kick_im_to_fetch(const struct dyna_load_pcm *pcm)
Definition: spm.c:533
static void spm_kick_pcm_to_run(const struct pwr_ctrl *pwrctrl)
Definition: spm.c:646
static void spm_init_pcm_register(void)
Definition: spm.c:566
static void spm_reset_and_init_pcm(void)
Definition: spm.c:498
static void spm_set_sysclk_settle(void)
Definition: spm.c:481
static void spm_register_init(void)
Definition: spm.c:426
static void spm_set_power_control(const struct pwr_ctrl *pwrctrl)
Definition: spm.c:287
static struct mtk_mcu spm
Definition: spm.c:683
#define SPM_SYSTEM_BASE_OFFSET
Definition: spm.c:13
static const struct pwr_ctrl spm_init_ctrl
Definition: spm.c:15
static const int mask[4]
Definition: gpio.c:308
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
u32 * buf
Definition: spm.h:578
struct pcm_desc desc
Definition: spm.h:579
size_t buffer_size
Definition: mcu_common.h:11
const char * firmware_name
Definition: mcu_common.h:7
void * priv
Definition: mcu_common.h:12
void * load_buffer
Definition: mcu_common.h:10
uint32_t armpll_clk_sel
Definition: spm.h:269
u32 spm_clk_settle
Definition: spm.h:136
u32 spm_cpu_wakeup_event
Definition: spm.h:161
u32 md32pcm_dma0_count
Definition: spm.h:621
u32 pcm_con1
Definition: spm.h:71
uint32_t spm_bus_protect_mask_b
Definition: spm.h:361
u32 pcm_pwr_io_en
Definition: spm.h:82
uint32_t spm_resource_ack_con2
Definition: spm.h:193
uint32_t spm_resource_ack_con1
Definition: spm.h:192
u32 md32pcm_cfgreg_sw_rstn
Definition: spm.h:615
u32 spm_power_on_val1
Definition: spm.h:134
uint32_t spm_bus_protect2_mask_b
Definition: spm.h:363
u32 md32pcm_dma0_wppt
Definition: spm.h:619
u32 spm_irq_mask
Definition: spm.h:162
u32 spm_swint_clr
Definition: spm.h:154
uint32_t spm_dvs_dfs_level
Definition: spm.h:422
u32 spm_src_req
Definition: spm.h:163
uint32_t spm_src4_mask
Definition: spm.h:181
u32 md32pcm_dma0_rlct
Definition: spm.h:625
u32 md32pcm_dma0_wpto
Definition: spm.h:620
u32 pcm_reg_data_ini
Definition: spm.h:74
u32 spm_wakeup_event_ext_mask
Definition: spm.h:167
u32 spm_src3_mask
Definition: spm.h:173
u32 spm_irq_sta
Definition: spm.h:199
u32 spm_sw_rsv_7
Definition: spm.h:428
uint32_t sys_timer_con
Definition: spm.h:615
u32 spm_sw_rsv_8
Definition: spm.h:429
u32 spm_clk_con
Definition: spm.h:135
u32 spm_power_on_val0
Definition: spm.h:133
u32 md32pcm_dma0_dst
Definition: spm.h:618
u32 pcm_timer_val
Definition: spm.h:83
uint32_t spm_resource_ack_con0
Definition: spm.h:191
u32 md32pcm_dma0_con
Definition: spm.h:622
uint32_t spm_sw_flag_1
Definition: spm.h:427
uint32_t md32pcm_pc
Definition: spm.h:231
uint32_t spm_sw_flag_0
Definition: spm.h:425
u32 md32pcm_dma0_src
Definition: spm.h:617
u32 spm_src_mask
Definition: spm.h:164
u32 spm_wakeup_event_mask
Definition: spm.h:166
u32 poweron_config_set
Definition: spm.h:24
u32 spm_dvfs_misc
Definition: spm.h:446
u32 spm_dvfs_level
Definition: spm.h:441
uint32_t spm_resource_ack_con3
Definition: spm.h:194
u32 spm_src2_mask
Definition: spm.h:165
u32 spm_ap_standby_con
Definition: spm.h:137
u32 md32pcm_dma0_start
Definition: spm.h:623
u32 pcm_con0
Definition: spm.h:70
u32 pcm_reg0_data
Definition: spm.h:177
uint32_t dmem_start
Definition: spm.h:850
uint32_t total_words
Definition: spm.h:848
uint32_t pmem_words
Definition: spm.h:847
uint32_t pmem_start
Definition: spm.h:849
Definition: spm.h:654
u8 reg_infrasys_ddr_en_mask_b
Definition: spm.h:201
uint8_t reg_pextp_p1_ddr_en_mask_b
Definition: spm.h:311
uint8_t reg_bak_psri_apsrc_req_mask_b
Definition: spm.h:794
uint8_t reg_msdc1_infra_req_mask_b
Definition: spm.h:785
uint8_t reg_apu_vrf18_req_mask_b
Definition: spm.h:755
uint8_t reg_apu_infra_req_mask_b
Definition: spm.h:753
uint8_t reg_gce0_infra_req_mask_b
Definition: spm.h:313
uint32_t wake_src
Definition: spm.h:668
uint8_t reg_ufs_infra_req_mask_b
Definition: spm.h:740
uint8_t reg_msdc0_vrf18_req_mask_b
Definition: spm.h:782
uint8_t reg_ufs_srcclkena_mask_b
Definition: spm.h:739
uint8_t reg_sspm_srcclkena_0_mask_b
Definition: spm.h:179
uint32_t pcm_flags
Definition: spm.h:656
uint8_t reg_msdc2_srcclkena_mask_b
Definition: spm.h:810
uint8_t reg_disp3_apsrc_req_mask_b
Definition: spm.h:351
uint8_t reg_wfi_op
Definition: spm.h:675
uint8_t reg_disp1_apsrc_req_mask_b
Definition: spm.h:746
uint8_t reg_pextp_p1_apsrc_req_mask_b
Definition: spm.h:307
uint8_t reg_ufs_apsrc_req_mask_b
Definition: spm.h:741
uint32_t wake_src_cust
Definition: spm.h:669
uint8_t reg_gce1_apsrc_req_mask_b
Definition: spm.h:323
uint8_t reg_scp_infra_req_mask_b
Definition: spm.h:730
uint8_t reg_msdc0_srcclkena_mask_b
Definition: spm.h:779
uint8_t reg_disp2_apsrc_req_mask_b
Definition: spm.h:347
uint32_t pcm_flags_cust_set
Definition: spm.h:658
uint8_t reg_msdc2_apsrc_req_mask_b
Definition: spm.h:812
uint8_t reg_audio_dsp_apsrc_req_mask_b
Definition: spm.h:736
uint32_t pcm_flags1
Definition: spm.h:660
u8 reg_ufs_ddr_en_mask_b
Definition: spm.h:223
uint8_t reg_spm_vrf18_req
Definition: spm.h:692
u8 reg_apu_ddr_en_mask_b
Definition: spm.h:236
u8 reg_msdc2_ddr_en_mask_b
Definition: spm.h:295
uint8_t reg_msdc2_vrf18_req_mask_b
Definition: spm.h:813
uint8_t reg_pextp_p1_vrf18_req_mask_b
Definition: spm.h:309
uint8_t reg_msdc0_infra_req_mask_b
Definition: spm.h:780
uint8_t reg_disp3_ddr_en_mask_b
Definition: spm.h:353
u8 reg_disp0_ddr_en_mask_b
Definition: spm.h:225
uint8_t reg_gce0_apsrc_req_mask_b
Definition: spm.h:315
uint32_t reg_wakeup_event_mask
Definition: spm.h:817
uint8_t reg_scp_vrf18_req_mask_b
Definition: spm.h:732
uint8_t reg_gce1_ddr_en_mask_b
Definition: spm.h:327
uint8_t reg_apu_srcclkena_mask_b
Definition: spm.h:752
u8 reg_spm_apsrc_req_reserved_mask_b
Definition: spm.h:254
uint8_t reg_md_apsrc_1_sel
Definition: spm.h:680
uint8_t reg_msdc2_infra_req_mask_b
Definition: spm.h:811
uint8_t reg_cpueb_ddr_en_mask_b
Definition: spm.h:227
uint8_t reg_sspm_infra_req_0_mask_b
Definition: spm.h:181
u8 reg_disp1_ddr_en_mask_b
Definition: spm.h:227
uint8_t reg_bak_psri_vrf18_req_mask_b
Definition: spm.h:795
uint8_t reg_apu_apsrc_req_mask_b
Definition: spm.h:754
u8 reg_scp_ddr_en_mask_b
Definition: spm.h:213
uint8_t reg_usb_ddr_en_mask_b
Definition: spm.h:289
uint8_t reg_gce1_vrf18_req_mask_b
Definition: spm.h:325
uint8_t reg_cpueb_infra_req_mask_b
Definition: spm.h:221
uint32_t pcm_flags_cust_clr
Definition: spm.h:659
uint8_t reg_spm_dvfs_req
Definition: spm.h:694
uint8_t reg_conn_apsrc_sel
Definition: spm.h:682
uint8_t reg_spm_adsp_mailbox_req
Definition: spm.h:697
uint8_t reg_audio_dsp_infra_req_mask_b
Definition: spm.h:735
uint8_t reg_wfi_type
Definition: spm.h:676
uint8_t reg_cpueb_vrf18_req_mask_b
Definition: spm.h:225
uint8_t reg_pextp_p1_srcclkena_mask_b
Definition: spm.h:303
uint8_t reg_infrasys_apsrc_req_mask_b
Definition: spm.h:720
uint8_t reg_mp1_cputop_idle_mask
Definition: spm.h:678
uint8_t reg_audio_dsp_vrf18_req_mask_b
Definition: spm.h:737
uint8_t reg_usb_infra_req_mask_b
Definition: spm.h:283
u8 reg_msdc0_ddr_en_mask_b
Definition: spm.h:266
uint8_t reg_pextp_p1_infra_req_mask_b
Definition: spm.h:305
uint8_t reg_bak_psri_srcclkena_mask_b
Definition: spm.h:792
u8 reg_bak_psri_ddr_en_mask_b
Definition: spm.h:279
uint8_t reg_pextp_p0_srcclkena_mask_b
Definition: spm.h:291
uint8_t reg_usb_apsrc_req_mask_b
Definition: spm.h:285
uint8_t reg_msdc1_vrf18_req_mask_b
Definition: spm.h:787
uint8_t reg_pextp_p0_ddr_en_mask_b
Definition: spm.h:299
u8 reg_spm_vrf18_req_reserved_mask_b
Definition: spm.h:255
uint8_t reg_msdc1_apsrc_req_mask_b
Definition: spm.h:786
uint8_t reg_md_apsrc_0_sel
Definition: spm.h:681
uint8_t reg_mcusys_idle_mask
Definition: spm.h:679
uint8_t reg_usb_vrf18_req_mask_b
Definition: spm.h:287
uint8_t reg_spm_sspm_mailbox_req
Definition: spm.h:696
uint8_t reg_scp_apsrc_req_mask_b
Definition: spm.h:731
uint8_t reg_usb_srcclkena_mask_b
Definition: spm.h:281
uint8_t reg_gce0_vrf18_req_mask_b
Definition: spm.h:317
uint8_t reg_pextp_p0_infra_req_mask_b
Definition: spm.h:293
uint8_t reg_sspm_vrf18_req_0_mask_b
Definition: spm.h:185
uint8_t reg_gce1_infra_req_mask_b
Definition: spm.h:321
u8 reg_spm_ddr_en_reserved_mask_b
Definition: spm.h:256
u8 reg_spm_ddr_en_req
Definition: spm.h:167
uint8_t reg_ufs_vrf18_req_mask_b
Definition: spm.h:742
u8 reg_spm_srcclkena_reserved_mask_b
Definition: spm.h:252
u8 reg_spm_infra_req_reserved_mask_b
Definition: spm.h:253
uint32_t pcm_flags1_cust_set
Definition: spm.h:662
uint32_t timer_val
Definition: spm.h:664
uint32_t timer_val_cust
Definition: spm.h:665
uint32_t pcm_flags1_cust_clr
Definition: spm.h:663
uint8_t reg_disp2_ddr_en_mask_b
Definition: spm.h:349
uint8_t reg_msdc1_srcclkena_mask_b
Definition: spm.h:784
u8 reg_audio_dsp_ddr_en_mask_b
Definition: spm.h:218
uint8_t reg_pextp_p0_vrf18_req_mask_b
Definition: spm.h:297
uint32_t reg_ext_wakeup_event_mask
Definition: spm.h:820
uint8_t reg_cpueb_apsrc_req_mask_b
Definition: spm.h:223
uint8_t reg_msdc0_apsrc_req_mask_b
Definition: spm.h:781
uint8_t reg_sspm_apsrc_req_0_mask_b
Definition: spm.h:183
uint8_t reg_spm_f26m_req
Definition: spm.h:690
uint8_t reg_scp_srcclkena_mask_b
Definition: spm.h:729
uint8_t reg_bak_psri_infra_req_mask_b
Definition: spm.h:793
uint8_t reg_spm_sw_mailbox_req
Definition: spm.h:695
uint8_t reg_spm_infra_req
Definition: spm.h:691
uint8_t reg_spm_apsrc_req
Definition: spm.h:689
uint8_t reg_sspm_ddr_en_0_mask_b
Definition: spm.h:187
u8 reg_msdc1_ddr_en_mask_b
Definition: spm.h:271
uint8_t reg_cpueb_srcclkena_mask_b
Definition: spm.h:219
uint8_t reg_gce0_ddr_en_mask_b
Definition: spm.h:319
uint8_t reg_audio_dsp_srcclkena_mask_b
Definition: spm.h:734
uint8_t reg_pextp_p0_apsrc_req_mask_b
Definition: spm.h:295
uint8_t reg_spm_scp_mailbox_req
Definition: spm.h:698
uint8_t reg_mp0_cputop_idle_mask
Definition: spm.h:677
u8 val
Definition: sys.c:300
void udelay(uint32_t us)
Definition: udelay.c:15