1 /*
2  * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
3  * Copyright (c) 2018, Icenowy Zheng <[email protected]>
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <errno.h>
9 
10 #include <platform_def.h>
11 
12 #include <common/debug.h>
13 #include <drivers/allwinner/axp.h>
14 #include <drivers/allwinner/sunxi_rsb.h>
15 #include <lib/mmio.h>
16 
17 #include <core_off_arisc.h>
18 #include <sunxi_def.h>
19 #include <sunxi_mmap.h>
20 #include <sunxi_private.h>
21 
22 static enum pmic_type {
23 	UNKNOWN,
24 	GENERIC_H5,
25 	GENERIC_A64,
26 	REF_DESIGN_H5,	/* regulators controlled by GPIO pins on port L */
27 	AXP803_RSB,	/* PMIC connected via RSB on most A64 boards */
28 } pmic;
29 
30 #define AXP803_HW_ADDR	0x3a3
31 #define AXP803_RT_ADDR	0x2d
32 
33 /*
34  * On boards without a proper PMIC we struggle to turn off the system properly.
35  * Try to turn off as much off the system as we can, to reduce power
36  * consumption. This should be entered with only one core running and SMP
37  * disabled.
38  * This function only cares about peripherals.
39  */
sunxi_turn_off_soc(uint16_t socid)40 static void sunxi_turn_off_soc(uint16_t socid)
41 {
42 	int i;
43 
44 	/** Turn off most peripherals, most importantly DRAM users. **/
45 	/* Keep DRAM controller running for now. */
46 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, ~BIT_32(14));
47 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, ~BIT_32(14));
48 	/* Contains msgbox (bit 21) and spinlock (bit 22) */
49 	mmio_write_32(SUNXI_CCU_BASE + 0x2c4, 0);
50 	mmio_write_32(SUNXI_CCU_BASE + 0x64, 0);
51 	mmio_write_32(SUNXI_CCU_BASE + 0x2c8, 0);
52 	/* Keep PIO controller running for now. */
53 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x68, ~(BIT_32(5)));
54 	mmio_write_32(SUNXI_CCU_BASE + 0x2d0, 0);
55 	/* Contains UART0 (bit 16) */
56 	mmio_write_32(SUNXI_CCU_BASE + 0x2d8, 0);
57 	mmio_write_32(SUNXI_CCU_BASE + 0x6c, 0);
58 	mmio_write_32(SUNXI_CCU_BASE + 0x70, 0);
59 
60 	/** Turn off DRAM controller. **/
61 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c0, BIT_32(14));
62 	mmio_clrbits_32(SUNXI_CCU_BASE + 0x60, BIT_32(14));
63 
64 	/** Migrate CPU and bus clocks away from the PLLs. **/
65 	/* AHB1: use OSC24M/1, APB1 = AHB1 / 2 */
66 	mmio_write_32(SUNXI_CCU_BASE + 0x54, 0x1000);
67 	/* APB2: use OSC24M */
68 	mmio_write_32(SUNXI_CCU_BASE + 0x58, 0x1000000);
69 	/* AHB2: use AHB1 clock */
70 	mmio_write_32(SUNXI_CCU_BASE + 0x5c, 0);
71 	/* CPU: use OSC24M */
72 	mmio_write_32(SUNXI_CCU_BASE + 0x50, 0x10000);
73 
74 	/** Turn off PLLs. **/
75 	for (i = 0; i < 6; i++)
76 		mmio_clrbits_32(SUNXI_CCU_BASE + i * 8, BIT(31));
77 	switch (socid) {
78 	case SUNXI_SOC_H5:
79 		mmio_clrbits_32(SUNXI_CCU_BASE + 0x44, BIT(31));
80 		break;
81 	case SUNXI_SOC_A64:
82 		mmio_clrbits_32(SUNXI_CCU_BASE + 0x2c, BIT(31));
83 		mmio_clrbits_32(SUNXI_CCU_BASE + 0x4c, BIT(31));
84 		break;
85 	}
86 }
87 
rsb_init(void)88 static int rsb_init(void)
89 {
90 	int ret;
91 
92 	ret = rsb_init_controller();
93 	if (ret)
94 		return ret;
95 
96 	/* Switch to the recommended 3 MHz bus clock. */
97 	ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000);
98 	if (ret)
99 		return ret;
100 
101 	/* Initiate an I2C transaction to switch the PMIC to RSB mode. */
102 	ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8);
103 	if (ret)
104 		return ret;
105 
106 	/* Associate the 8-bit runtime address with the 12-bit bus address. */
107 	ret = rsb_assign_runtime_address(AXP803_HW_ADDR,
108 					 AXP803_RT_ADDR);
109 	if (ret)
110 		return ret;
111 
112 	return axp_check_id();
113 }
114 
axp_read(uint8_t reg)115 int axp_read(uint8_t reg)
116 {
117 	return rsb_read(AXP803_RT_ADDR, reg);
118 }
119 
axp_write(uint8_t reg,uint8_t val)120 int axp_write(uint8_t reg, uint8_t val)
121 {
122 	return rsb_write(AXP803_RT_ADDR, reg, val);
123 }
124 
sunxi_pmic_setup(uint16_t socid,const void * fdt)125 int sunxi_pmic_setup(uint16_t socid, const void *fdt)
126 {
127 	int ret;
128 
129 	switch (socid) {
130 	case SUNXI_SOC_H5:
131 		NOTICE("PMIC: Assuming H5 reference regulator design\n");
132 
133 		pmic = REF_DESIGN_H5;
134 
135 		break;
136 	case SUNXI_SOC_A64:
137 		pmic = GENERIC_A64;
138 
139 		INFO("PMIC: Probing AXP803 on RSB\n");
140 
141 		ret = sunxi_init_platform_r_twi(socid, true);
142 		if (ret)
143 			return ret;
144 
145 		ret = rsb_init();
146 		if (ret)
147 			return ret;
148 
149 		pmic = AXP803_RSB;
150 		axp_setup_regulators(fdt);
151 
152 		/* Switch the PMIC back to I2C mode. */
153 		ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C);
154 		if (ret)
155 			return ret;
156 
157 		break;
158 	default:
159 		return -ENODEV;
160 	}
161 	return 0;
162 }
163 
sunxi_power_down(void)164 void sunxi_power_down(void)
165 {
166 	switch (pmic) {
167 	case GENERIC_H5:
168 		/* Turn off as many peripherals and clocks as we can. */
169 		sunxi_turn_off_soc(SUNXI_SOC_H5);
170 		/* Turn off the pin controller now. */
171 		mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
172 		break;
173 	case GENERIC_A64:
174 		/* Turn off as many peripherals and clocks as we can. */
175 		sunxi_turn_off_soc(SUNXI_SOC_A64);
176 		/* Turn off the pin controller now. */
177 		mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
178 		break;
179 	case REF_DESIGN_H5:
180 		sunxi_turn_off_soc(SUNXI_SOC_H5);
181 
182 		/*
183 		 * Switch PL pins to power off the board:
184 		 * - PL5 (VCC_IO) -> high
185 		 * - PL8 (PWR-STB = CPU power supply) -> low
186 		 * - PL9 (PWR-DRAM) ->low
187 		 * - PL10 (power LED) -> low
188 		 * Note: Clearing PL8 will reset the board, so keep it up.
189 		 */
190 		sunxi_set_gpio_out('L', 5, 1);
191 		sunxi_set_gpio_out('L', 9, 0);
192 		sunxi_set_gpio_out('L', 10, 0);
193 
194 		/* Turn off pin controller now. */
195 		mmio_write_32(SUNXI_CCU_BASE + 0x68, 0);
196 
197 		break;
198 	case AXP803_RSB:
199 		/* (Re-)init RSB in case the rich OS has disabled it. */
200 		sunxi_init_platform_r_twi(SUNXI_SOC_A64, true);
201 		rsb_init();
202 		axp_power_off();
203 		break;
204 	default:
205 		break;
206 	}
207 
208 }
209 
210 /* This lock synchronises access to the arisc management processor. */
211 static DEFINE_BAKERY_LOCK(arisc_lock);
212 
213 /*
214  * If we are supposed to turn ourself off, tell the arisc SCP to do that
215  * work for us. Without any SCPI provider running there, we place some
216  * OpenRISC code into SRAM, put the address of that into the reset vector
217  * and release the arisc reset line. The SCP will wait for the core to enter
218  * WFI, then execute that code and pull the line up again.
219  * The code expects the core mask to be patched into the first instruction.
220  */
sunxi_cpu_power_off_self(void)221 void sunxi_cpu_power_off_self(void)
222 {
223 	u_register_t mpidr = read_mpidr();
224 	unsigned int core  = MPIDR_AFFLVL0_VAL(mpidr);
225 	uintptr_t arisc_reset_vec = SUNXI_SRAM_A2_BASE + 0x100;
226 	uint32_t *code = arisc_core_off;
227 
228 	do {
229 		bakery_lock_get(&arisc_lock);
230 		/* Wait until the arisc is in reset state. */
231 		if (!(mmio_read_32(SUNXI_R_CPUCFG_BASE) & BIT(0)))
232 			break;
233 
234 		bakery_lock_release(&arisc_lock);
235 	} while (1);
236 
237 	/* Patch up the code to feed in an input parameter. */
238 	code[0] = (code[0] & ~0xffff) | BIT_32(core);
239 	clean_dcache_range((uintptr_t)code, sizeof(arisc_core_off));
240 
241 	/*
242 	 * The OpenRISC unconditional branch has opcode 0, the branch offset
243 	 * is in the lower 26 bits, containing the distance to the target,
244 	 * in instruction granularity (32 bits).
245 	 */
246 	mmio_write_32(arisc_reset_vec, ((uintptr_t)code - arisc_reset_vec) / 4);
247 
248 	/* De-assert the arisc reset line to let it run. */
249 	mmio_setbits_32(SUNXI_R_CPUCFG_BASE, BIT(0));
250 
251 	/*
252 	 * We release the lock here, although the arisc is still busy.
253 	 * But as long as it runs, the reset line is high, so other users
254 	 * won't leave the loop above.
255 	 * Once it has finished, the code is supposed to clear the reset line,
256 	 * to signal this to other users.
257 	 */
258 	bakery_lock_release(&arisc_lock);
259 }
260