blob: b5625231d0b575eebd6617b4c6298bf3bfc1fee4 [file] [log] [blame]
Icenowy Zheng7508bef2018-07-21 20:41:12 +08001/*
2 * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
3 * Copyright (c) 2018, Icenowy Zheng <icenowy@aosc.io>
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
Icenowy Zhengbd57eb52018-07-22 21:52:50 +08008#include <arch_helpers.h>
Icenowy Zheng7508bef2018-07-21 20:41:12 +08009#include <debug.h>
Andre Przywaraa920a772018-10-02 00:21:49 +010010#include <delay_timer.h>
11#include <errno.h>
12#include <mmio.h>
13#include <platform_def.h>
14#include <sunxi_def.h>
15#include <sunxi_mmap.h>
Andre Przywara456208a2018-10-14 12:02:02 +010016#include <sunxi_private.h>
Icenowy Zheng7508bef2018-07-21 20:41:12 +080017
Andre Przywaraa920a772018-10-02 00:21:49 +010018static enum pmic_type {
19 GENERIC_H5,
20 GENERIC_A64,
21} pmic;
22
23/*
24 * On boards without a proper PMIC we struggle to turn off the system properly.
25 * Try to turn off as much off the system as we can, to reduce power
26 * consumption. This should be entered with only one core running and SMP
27 * disabled.
28 * This function only cares about peripherals.
29 */
30void sunxi_turn_off_soc(uint16_t socid)
Icenowy Zheng7508bef2018-07-21 20:41:12 +080031{
Andre Przywaraa920a772018-10-02 00:21:49 +010032 int i;
33
34 /** Turn off most peripherals, most importantly DRAM users. **/
35 /* Keep DRAM controller running for now. */
36 mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, ~BIT_32(14));
37 mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, ~BIT_32(14));
38 /* Contains msgbox (bit 21) and spinlock (bit 22) */
39 mmio_write_32(SUNXI_CCU_BASE + 0x2c4, 0);
40 mmio_write_32(SUNXI_CCU_BASE + 0x64, 0);
41 mmio_write_32(SUNXI_CCU_BASE + 0x2c8, 0);
42 /* Keep PIO controller running for now. */
43 mmio_clrbits_32(SUNXI_CCU_BASE + 0x68, ~(BIT_32(5)));
44 mmio_write_32(SUNXI_CCU_BASE + 0x2d0, 0);
45 /* Contains UART0 (bit 16) */
46 mmio_write_32(SUNXI_CCU_BASE + 0x2d8, 0);
47 mmio_write_32(SUNXI_CCU_BASE + 0x6c, 0);
48 mmio_write_32(SUNXI_CCU_BASE + 0x70, 0);
49
50 /** Turn off DRAM controller. **/
51 mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, BIT_32(14));
52 mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, BIT_32(14));
53
54 /** Migrate CPU and bus clocks away from the PLLs. **/
55 /* AHB1: use OSC24M/1, APB1 = AHB1 / 2 */
56 mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x1000);
57 /* APB2: use OSC24M */
58 mmio_write_32(SUNXI_CCU_BASE + 0x58, 0x1000000);
59 /* AHB2: use AHB1 clock */
60 mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0);
61 /* CPU: use OSC24M */
62 mmio_write_32(SUNXI_CCU_BASE + 0x50, 0x10000);
Icenowy Zheng7508bef2018-07-21 20:41:12 +080063
Andre Przywaraa920a772018-10-02 00:21:49 +010064 /** Turn off PLLs. **/
65 for (i = 0; i < 6; i++)
66 mmio_clrbits_32(SUNXI_CCU_BASE + i * 8, BIT(31));
67 switch (socid) {
68 case SUNXI_SOC_H5:
69 mmio_clrbits_32(SUNXI_CCU_BASE + 0x44, BIT(31));
70 break;
71 case SUNXI_SOC_A64:
72 mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c, BIT(31));
73 mmio_clrbits_32(SUNXI_CCU_BASE + 0x4c, BIT(31));
74 break;
75 }
76}
77
78int sunxi_pmic_setup(uint16_t socid)
79{
80 switch (socid) {
81 case SUNXI_SOC_H5:
82 pmic = GENERIC_H5;
83 break;
84 case SUNXI_SOC_A64:
85 pmic = GENERIC_A64;
86 break;
87 default:
88 NOTICE("BL31: PMIC: No support for Allwinner %x SoC.\n", socid);
89 return -ENODEV;
90 }
Icenowy Zheng7508bef2018-07-21 20:41:12 +080091 return 0;
92}
Icenowy Zhengbd57eb52018-07-22 21:52:50 +080093
94void __dead2 sunxi_power_down(void)
95{
Andre Przywaraa920a772018-10-02 00:21:49 +010096 switch (pmic) {
97 case GENERIC_H5:
98 /* Turn off as many peripherals and clocks as we can. */
99 sunxi_turn_off_soc(SUNXI_SOC_H5);
100 /* Turn off the pin controller now. */
101 mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
102 break;
103 case GENERIC_A64:
104 /* Turn off as many peripherals and clocks as we can. */
105 sunxi_turn_off_soc(SUNXI_SOC_A64);
106 /* Turn off the pin controller now. */
107 mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
108 break;
109 default:
110 break;
111 }
112
113 udelay(1000);
114 ERROR("PSCI: Cannot turn off system, halting.\n");
Icenowy Zhengbd57eb52018-07-22 21:52:50 +0800115 wfi();
116 panic();
117}