xref: /arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu 
9*91f16700Schasinglulu #include <arch_helpers.h>
10*91f16700Schasinglulu #include <common/debug.h>
11*91f16700Schasinglulu #include <drivers/delay_timer.h>
12*91f16700Schasinglulu #include <lib/mmio.h>
13*91f16700Schasinglulu 
14*91f16700Schasinglulu #include <m0_ctl.h>
15*91f16700Schasinglulu #include <plat_private.h>
16*91f16700Schasinglulu #include <rk3399_def.h>
17*91f16700Schasinglulu #include <secure.h>
18*91f16700Schasinglulu #include <soc.h>
19*91f16700Schasinglulu 
20*91f16700Schasinglulu void m0_init(void)
21*91f16700Schasinglulu {
22*91f16700Schasinglulu 	/* secure config for M0 */
23*91f16700Schasinglulu 	mmio_write_32(SGRF_BASE + SGRF_PMU_CON(0), WMSK_BIT(7));
24*91f16700Schasinglulu 	mmio_write_32(SGRF_BASE + SGRF_SOC_CON(6), WMSK_BIT(12));
25*91f16700Schasinglulu 
26*91f16700Schasinglulu 	/* document is wrong, PMU_CRU_GATEDIS_CON0 do not need set MASK BIT */
27*91f16700Schasinglulu 	mmio_setbits_32(PMUCRU_BASE + PMUCRU_GATEDIS_CON0, 0x02);
28*91f16700Schasinglulu 
29*91f16700Schasinglulu 	/*
30*91f16700Schasinglulu 	 * To switch the parent to xin24M and div == 1,
31*91f16700Schasinglulu 	 *
32*91f16700Schasinglulu 	 * We need to close most of the PLLs and clocks except the OSC 24MHz
33*91f16700Schasinglulu 	 * durning suspend, and this should be enough to supplies the ddrfreq,
34*91f16700Schasinglulu 	 * For the simple handle, we just keep the fixed 24MHz to supply the
35*91f16700Schasinglulu 	 * suspend and ddrfreq directly.
36*91f16700Schasinglulu 	 */
37*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + PMUCRU_CLKSEL_CON0,
38*91f16700Schasinglulu 		      BIT_WITH_WMSK(15) | BITS_WITH_WMASK(0x0, 0x1f, 8));
39*91f16700Schasinglulu 
40*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2, WMSK_BIT(5));
41*91f16700Schasinglulu }
42*91f16700Schasinglulu 
43*91f16700Schasinglulu void m0_configure_execute_addr(uintptr_t addr)
44*91f16700Schasinglulu {
45*91f16700Schasinglulu 	/* set the execute address for M0 */
46*91f16700Schasinglulu 	mmio_write_32(SGRF_BASE + SGRF_PMU_CON(3),
47*91f16700Schasinglulu 		      BITS_WITH_WMASK((addr >> 12) & 0xffff,
48*91f16700Schasinglulu 				      0xffffu, 0));
49*91f16700Schasinglulu 	mmio_write_32(SGRF_BASE + SGRF_PMU_CON(7),
50*91f16700Schasinglulu 		      BITS_WITH_WMASK((addr >> 28) & 0xf,
51*91f16700Schasinglulu 				      0xfu, 0));
52*91f16700Schasinglulu }
53*91f16700Schasinglulu 
54*91f16700Schasinglulu void m0_start(void)
55*91f16700Schasinglulu {
56*91f16700Schasinglulu 	/* enable clocks for M0 */
57*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2,
58*91f16700Schasinglulu 		      BITS_WITH_WMASK(0x0, 0xf, 0));
59*91f16700Schasinglulu 
60*91f16700Schasinglulu 	/* clean the PARAM_M0_DONE flag, mean that M0 will start working */
61*91f16700Schasinglulu 	mmio_write_32(M0_PARAM_ADDR + PARAM_M0_DONE, 0);
62*91f16700Schasinglulu 	dmbst();
63*91f16700Schasinglulu 
64*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
65*91f16700Schasinglulu 		      BITS_WITH_WMASK(0x0, 0x4, 0));
66*91f16700Schasinglulu 
67*91f16700Schasinglulu 	udelay(5);
68*91f16700Schasinglulu 	/* start M0 */
69*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
70*91f16700Schasinglulu 		      BITS_WITH_WMASK(0x0, 0x20, 0));
71*91f16700Schasinglulu 	dmbst();
72*91f16700Schasinglulu }
73*91f16700Schasinglulu 
74*91f16700Schasinglulu void m0_stop(void)
75*91f16700Schasinglulu {
76*91f16700Schasinglulu 	/* stop M0 */
77*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + PMUCRU_SOFTRST_CON0,
78*91f16700Schasinglulu 		      BITS_WITH_WMASK(0x24, 0x24, 0));
79*91f16700Schasinglulu 
80*91f16700Schasinglulu 	/* disable clocks for M0 */
81*91f16700Schasinglulu 	mmio_write_32(PMUCRU_BASE + PMUCRU_CLKGATE_CON2,
82*91f16700Schasinglulu 		      BITS_WITH_WMASK(0xf, 0xf, 0));
83*91f16700Schasinglulu }
84*91f16700Schasinglulu 
85*91f16700Schasinglulu void m0_wait_done(void)
86*91f16700Schasinglulu {
87*91f16700Schasinglulu 	do {
88*91f16700Schasinglulu 		/*
89*91f16700Schasinglulu 		 * Don't starve the M0 for access to SRAM, so delay before
90*91f16700Schasinglulu 		 * reading the PARAM_M0_DONE value again.
91*91f16700Schasinglulu 		 */
92*91f16700Schasinglulu 		udelay(5);
93*91f16700Schasinglulu 		dsb();
94*91f16700Schasinglulu 	} while (mmio_read_32(M0_PARAM_ADDR + PARAM_M0_DONE) != M0_DONE_FLAG);
95*91f16700Schasinglulu 
96*91f16700Schasinglulu 	/*
97*91f16700Schasinglulu 	 * Let the M0 settle into WFI before we leave. This is so we don't reset
98*91f16700Schasinglulu 	 * the M0 in a bad spot which can cause problems with the M0.
99*91f16700Schasinglulu 	 */
100*91f16700Schasinglulu 	udelay(10);
101*91f16700Schasinglulu 	dsb();
102*91f16700Schasinglulu }
103