xref: /rk3399_ARM-atf/plat/allwinner/sun50i_a64/sunxi_power.c (revision f953c30fe58dcd7f924c5df63d631c5c4ca0517d)
17c26b6ecSIcenowy Zheng /*
27c26b6ecSIcenowy Zheng  * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
37c26b6ecSIcenowy Zheng  * Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
47c26b6ecSIcenowy Zheng  *
57c26b6ecSIcenowy Zheng  * SPDX-License-Identifier: BSD-3-Clause
67c26b6ecSIcenowy Zheng  */
77c26b6ecSIcenowy Zheng 
85069c1cfSIcenowy Zheng #include <arch_helpers.h>
97c26b6ecSIcenowy Zheng #include <debug.h>
10*f953c30fSAndre Przywara #include <delay_timer.h>
11*f953c30fSAndre Przywara #include <errno.h>
12*f953c30fSAndre Przywara #include <mmio.h>
13*f953c30fSAndre Przywara #include <platform_def.h>
14*f953c30fSAndre Przywara #include <sunxi_def.h>
15*f953c30fSAndre Przywara #include <sunxi_mmap.h>
16*f953c30fSAndre Przywara 
17*f953c30fSAndre Przywara static enum pmic_type {
18*f953c30fSAndre Przywara 	GENERIC_H5,
19*f953c30fSAndre Przywara 	GENERIC_A64,
20*f953c30fSAndre Przywara } pmic;
21*f953c30fSAndre Przywara 
22*f953c30fSAndre Przywara /*
23*f953c30fSAndre Przywara  * On boards without a proper PMIC we struggle to turn off the system properly.
24*f953c30fSAndre Przywara  * Try to turn off as much off the system as we can, to reduce power
25*f953c30fSAndre Przywara  * consumption. This should be entered with only one core running and SMP
26*f953c30fSAndre Przywara  * disabled.
27*f953c30fSAndre Przywara  * This function only cares about peripherals.
28*f953c30fSAndre Przywara  */
29*f953c30fSAndre Przywara void sunxi_turn_off_soc(uint16_t socid)
30*f953c30fSAndre Przywara {
31*f953c30fSAndre Przywara 	int i;
32*f953c30fSAndre Przywara 
33*f953c30fSAndre Przywara 	/** Turn off most peripherals, most importantly DRAM users. **/
34*f953c30fSAndre Przywara 	/* Keep DRAM controller running for now. */
35*f953c30fSAndre Przywara 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, ~BIT_32(14));
36*f953c30fSAndre Przywara 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, ~BIT_32(14));
37*f953c30fSAndre Przywara 	/* Contains msgbox (bit 21) and spinlock (bit 22) */
38*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x2c4, 0);
39*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x64, 0);
40*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x2c8, 0);
41*f953c30fSAndre Przywara 	/* Keep PIO controller running for now. */
42*f953c30fSAndre Przywara 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x68, ~(BIT_32(5)));
43*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x2d0, 0);
44*f953c30fSAndre Przywara 	/* Contains UART0 (bit 16) */
45*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x2d8, 0);
46*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x6c, 0);
47*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x70, 0);
48*f953c30fSAndre Przywara 
49*f953c30fSAndre Przywara 	/** Turn off DRAM controller. **/
50*f953c30fSAndre Przywara 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, BIT_32(14));
51*f953c30fSAndre Przywara 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, BIT_32(14));
52*f953c30fSAndre Przywara 
53*f953c30fSAndre Przywara 	/** Migrate CPU and bus clocks away from the PLLs. **/
54*f953c30fSAndre Przywara 	/* AHB1: use OSC24M/1, APB1 = AHB1 / 2 */
55*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x1000);
56*f953c30fSAndre Przywara 	/* APB2: use OSC24M */
57*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x58, 0x1000000);
58*f953c30fSAndre Przywara 	/* AHB2: use AHB1 clock */
59*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0);
60*f953c30fSAndre Przywara 	/* CPU: use OSC24M */
61*f953c30fSAndre Przywara 	mmio_write_32(SUNXI_CCU_BASE + 0x50, 0x10000);
62*f953c30fSAndre Przywara 
63*f953c30fSAndre Przywara 	/** Turn off PLLs. **/
64*f953c30fSAndre Przywara 	for (i = 0; i < 6; i++)
65*f953c30fSAndre Przywara 		mmio_clrbits_32(SUNXI_CCU_BASE + i * 8, BIT(31));
66*f953c30fSAndre Przywara 	switch (socid) {
67*f953c30fSAndre Przywara 	case SUNXI_SOC_H5:
68*f953c30fSAndre Przywara 		mmio_clrbits_32(SUNXI_CCU_BASE + 0x44, BIT(31));
69*f953c30fSAndre Przywara 		break;
70*f953c30fSAndre Przywara 	case SUNXI_SOC_A64:
71*f953c30fSAndre Przywara 		mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c, BIT(31));
72*f953c30fSAndre Przywara 		mmio_clrbits_32(SUNXI_CCU_BASE + 0x4c, BIT(31));
73*f953c30fSAndre Przywara 		break;
74*f953c30fSAndre Przywara 	}
75*f953c30fSAndre Przywara }
767c26b6ecSIcenowy Zheng 
77fe57c7d4SAndre Przywara int sunxi_pmic_setup(uint16_t socid)
787c26b6ecSIcenowy Zheng {
79*f953c30fSAndre Przywara 	switch (socid) {
80*f953c30fSAndre Przywara 	case SUNXI_SOC_H5:
81*f953c30fSAndre Przywara 		pmic = GENERIC_H5;
82*f953c30fSAndre Przywara 		break;
83*f953c30fSAndre Przywara 	case SUNXI_SOC_A64:
84*f953c30fSAndre Przywara 		pmic = GENERIC_A64;
85*f953c30fSAndre Przywara 		break;
86*f953c30fSAndre Przywara 	default:
87*f953c30fSAndre Przywara 		NOTICE("BL31: PMIC: No support for Allwinner %x SoC.\n", socid);
88*f953c30fSAndre Przywara 		return -ENODEV;
89*f953c30fSAndre Przywara 	}
907c26b6ecSIcenowy Zheng 	return 0;
917c26b6ecSIcenowy Zheng }
925069c1cfSIcenowy Zheng 
935069c1cfSIcenowy Zheng void __dead2 sunxi_power_down(void)
945069c1cfSIcenowy Zheng {
95*f953c30fSAndre Przywara 	switch (pmic) {
96*f953c30fSAndre Przywara 	case GENERIC_H5:
97*f953c30fSAndre Przywara 		/* Turn off as many peripherals and clocks as we can. */
98*f953c30fSAndre Przywara 		sunxi_turn_off_soc(SUNXI_SOC_H5);
99*f953c30fSAndre Przywara 		/* Turn off the pin controller now. */
100*f953c30fSAndre Przywara 		mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
101*f953c30fSAndre Przywara 		break;
102*f953c30fSAndre Przywara 	case GENERIC_A64:
103*f953c30fSAndre Przywara 		/* Turn off as many peripherals and clocks as we can. */
104*f953c30fSAndre Przywara 		sunxi_turn_off_soc(SUNXI_SOC_A64);
105*f953c30fSAndre Przywara 		/* Turn off the pin controller now. */
106*f953c30fSAndre Przywara 		mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
107*f953c30fSAndre Przywara 		break;
108*f953c30fSAndre Przywara 	default:
109*f953c30fSAndre Przywara 		break;
110*f953c30fSAndre Przywara 	}
111*f953c30fSAndre Przywara 
112*f953c30fSAndre Przywara 	udelay(1000);
113*f953c30fSAndre Przywara 	ERROR("PSCI: Cannot turn off system, halting.\n");
1145069c1cfSIcenowy Zheng 	wfi();
1155069c1cfSIcenowy Zheng 	panic();
1165069c1cfSIcenowy Zheng }
117