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