1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017-2020, ARM Limited. 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 #include <string.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch_helpers.h> 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 <sunxi_cpucfg.h> 18*91f16700Schasinglulu #include <sunxi_def.h> 19*91f16700Schasinglulu #include <sunxi_mmap.h> 20*91f16700Schasinglulu #include <sunxi_private.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu #define AXP305_I2C_ADDR 0x36 23*91f16700Schasinglulu #define AXP305_HW_ADDR 0x745 24*91f16700Schasinglulu #define AXP305_RT_ADDR 0x3a 25*91f16700Schasinglulu 26*91f16700Schasinglulu static enum pmic_type { 27*91f16700Schasinglulu UNKNOWN, 28*91f16700Schasinglulu AXP305, 29*91f16700Schasinglulu } pmic; 30*91f16700Schasinglulu 31*91f16700Schasinglulu int axp_read(uint8_t reg) 32*91f16700Schasinglulu { 33*91f16700Schasinglulu return rsb_read(AXP305_RT_ADDR, reg); 34*91f16700Schasinglulu } 35*91f16700Schasinglulu 36*91f16700Schasinglulu int axp_write(uint8_t reg, uint8_t val) 37*91f16700Schasinglulu { 38*91f16700Schasinglulu return rsb_write(AXP305_RT_ADDR, reg, val); 39*91f16700Schasinglulu } 40*91f16700Schasinglulu 41*91f16700Schasinglulu static int rsb_init(void) 42*91f16700Schasinglulu { 43*91f16700Schasinglulu int ret; 44*91f16700Schasinglulu 45*91f16700Schasinglulu ret = rsb_init_controller(); 46*91f16700Schasinglulu if (ret) 47*91f16700Schasinglulu return ret; 48*91f16700Schasinglulu 49*91f16700Schasinglulu /* Switch to the recommended 3 MHz bus clock. */ 50*91f16700Schasinglulu ret = rsb_set_bus_speed(SUNXI_OSC24M_CLK_IN_HZ, 3000000); 51*91f16700Schasinglulu if (ret) 52*91f16700Schasinglulu return ret; 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* Initiate an I2C transaction to switch the PMIC to RSB mode. */ 55*91f16700Schasinglulu ret = rsb_set_device_mode(AXP20X_MODE_RSB << 16 | AXP20X_MODE_REG << 8); 56*91f16700Schasinglulu if (ret) 57*91f16700Schasinglulu return ret; 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* Associate the 8-bit runtime address with the 12-bit bus address. */ 60*91f16700Schasinglulu ret = rsb_assign_runtime_address(AXP305_HW_ADDR, AXP305_RT_ADDR); 61*91f16700Schasinglulu if (ret) 62*91f16700Schasinglulu return ret; 63*91f16700Schasinglulu 64*91f16700Schasinglulu return axp_check_id(); 65*91f16700Schasinglulu } 66*91f16700Schasinglulu 67*91f16700Schasinglulu int sunxi_pmic_setup(uint16_t socid, const void *fdt) 68*91f16700Schasinglulu { 69*91f16700Schasinglulu int ret; 70*91f16700Schasinglulu 71*91f16700Schasinglulu INFO("PMIC: Probing AXP305 on RSB\n"); 72*91f16700Schasinglulu 73*91f16700Schasinglulu ret = sunxi_init_platform_r_twi(socid, true); 74*91f16700Schasinglulu if (ret) { 75*91f16700Schasinglulu INFO("Could not init platform bus: %d\n", ret); 76*91f16700Schasinglulu return ret; 77*91f16700Schasinglulu } 78*91f16700Schasinglulu 79*91f16700Schasinglulu ret = rsb_init(); 80*91f16700Schasinglulu if (ret) { 81*91f16700Schasinglulu INFO("Could not init RSB: %d\n", ret); 82*91f16700Schasinglulu return ret; 83*91f16700Schasinglulu } 84*91f16700Schasinglulu 85*91f16700Schasinglulu pmic = AXP305; 86*91f16700Schasinglulu axp_setup_regulators(fdt); 87*91f16700Schasinglulu 88*91f16700Schasinglulu /* Switch the PMIC back to I2C mode. */ 89*91f16700Schasinglulu ret = axp_write(AXP20X_MODE_REG, AXP20X_MODE_I2C); 90*91f16700Schasinglulu if (ret) 91*91f16700Schasinglulu return ret; 92*91f16700Schasinglulu 93*91f16700Schasinglulu return 0; 94*91f16700Schasinglulu } 95*91f16700Schasinglulu 96*91f16700Schasinglulu void sunxi_power_down(void) 97*91f16700Schasinglulu { 98*91f16700Schasinglulu switch (pmic) { 99*91f16700Schasinglulu case AXP305: 100*91f16700Schasinglulu /* Re-initialise after rich OS might have used it. */ 101*91f16700Schasinglulu sunxi_init_platform_r_twi(SUNXI_SOC_H616, true); 102*91f16700Schasinglulu rsb_init(); 103*91f16700Schasinglulu axp_power_off(); 104*91f16700Schasinglulu break; 105*91f16700Schasinglulu default: 106*91f16700Schasinglulu break; 107*91f16700Schasinglulu } 108*91f16700Schasinglulu } 109*91f16700Schasinglulu 110*91f16700Schasinglulu void sunxi_cpu_power_off_self(void) 111*91f16700Schasinglulu { 112*91f16700Schasinglulu u_register_t mpidr = read_mpidr(); 113*91f16700Schasinglulu unsigned int core = MPIDR_AFFLVL0_VAL(mpidr); 114*91f16700Schasinglulu 115*91f16700Schasinglulu /* Enable the CPUIDLE hardware (only really needs to be done once). */ 116*91f16700Schasinglulu mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0x16aa0000); 117*91f16700Schasinglulu mmio_write_32(SUNXI_CPUIDLE_EN_REG, 0xaa160001); 118*91f16700Schasinglulu 119*91f16700Schasinglulu /* Trigger power off for this core. */ 120*91f16700Schasinglulu mmio_write_32(SUNXI_CORE_CLOSE_REG, BIT_32(core)); 121*91f16700Schasinglulu } 122