1 /* 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 8 #include <arch_helpers.h> 9 #include <debug.h> 10 #include <delay_timer.h> 11 #include <errno.h> 12 #include <mmio.h> 13 #include <mentor/mi2cv.h> 14 #include <string.h> 15 #include <sunxi_def.h> 16 #include <sunxi_mmap.h> 17 #include <sunxi_private.h> 18 19 #define AXP805_ADDR 0x36 20 #define AXP805_ID 0x03 21 22 enum pmic_type { 23 NO_PMIC, 24 AXP805, 25 }; 26 27 enum pmic_type pmic; 28 29 int axp_i2c_read(uint8_t chip, uint8_t reg, uint8_t *val) 30 { 31 int ret; 32 33 ret = i2c_write(chip, 0, 0, ®, 1); 34 if (ret) 35 return ret; 36 37 return i2c_read(chip, 0, 0, val, 1); 38 } 39 40 int axp_i2c_write(uint8_t chip, uint8_t reg, uint8_t val) 41 { 42 return i2c_write(chip, reg, 1, &val, 1); 43 } 44 45 static int axp805_probe(void) 46 { 47 int ret; 48 uint8_t val; 49 50 ret = axp_i2c_write(AXP805_ADDR, 0xff, 0x0); 51 if (ret) { 52 ERROR("PMIC: Cannot put AXP805 to master mode.\n"); 53 return -EPERM; 54 } 55 56 ret = axp_i2c_read(AXP805_ADDR, AXP805_ID, &val); 57 58 if (!ret && ((val & 0xcf) == 0x40)) 59 NOTICE("PMIC: AXP805 detected\n"); 60 else if (ret) { 61 ERROR("PMIC: Cannot communicate with AXP805.\n"); 62 return -EPERM; 63 } else { 64 ERROR("PMIC: Non-AXP805 chip attached at AXP805's address.\n"); 65 return -EINVAL; 66 } 67 68 return 0; 69 } 70 71 int sunxi_pmic_setup(uint16_t socid, const void *fdt) 72 { 73 int ret; 74 75 sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); 76 /* initialise mi2cv driver */ 77 i2c_init((void *)SUNXI_R_I2C_BASE); 78 79 NOTICE("PMIC: Probing AXP805\n"); 80 pmic = AXP805; 81 82 ret = axp805_probe(); 83 if (ret) 84 pmic = NO_PMIC; 85 else 86 pmic = AXP805; 87 88 return 0; 89 } 90 91 void __dead2 sunxi_power_down(void) 92 { 93 uint8_t val; 94 95 switch (pmic) { 96 case AXP805: 97 /* Re-initialise after rich OS might have used it. */ 98 sunxi_init_platform_r_twi(SUNXI_SOC_H6, false); 99 /* initialise mi2cv driver */ 100 i2c_init((void *)SUNXI_R_I2C_BASE); 101 axp_i2c_read(AXP805_ADDR, 0x32, &val); 102 axp_i2c_write(AXP805_ADDR, 0x32, val | 0x80); 103 break; 104 default: 105 break; 106 } 107 108 udelay(1000); 109 ERROR("PSCI: Cannot communicate with PMIC, halting\n"); 110 wfi(); 111 panic(); 112 } 113