xref: /rk3399_ARM-atf/plat/allwinner/sun50i_h6/sunxi_power.c (revision 4e0d14f218bd361e0373c9851b65e1106c11e61e)
1 /*
2  * Copyright (c) 2017-2019, 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 <errno.h>
9 #include <string.h>
10 
11 #include <arch_helpers.h>
12 #include <common/debug.h>
13 #include <drivers/delay_timer.h>
14 #include <drivers/mentor/mi2cv.h>
15 #include <lib/mmio.h>
16 
17 #include <sunxi_def.h>
18 #include <sunxi_mmap.h>
19 #include <sunxi_private.h>
20 
21 #define AXP805_ADDR	0x36
22 #define AXP805_ID	0x03
23 
24 static enum pmic_type {
25 	UNKNOWN,
26 	AXP805,
27 } 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, &reg, 1);
34 	if (ret == 0)
35 		ret = i2c_read(chip, 0, 0, val, 1);
36 	if (ret)
37 		ERROR("PMIC: Cannot read AXP805 register %02x\n", reg);
38 
39 	return ret;
40 }
41 
42 int axp_i2c_write(uint8_t chip, uint8_t reg, uint8_t val)
43 {
44 	int ret;
45 
46 	ret = i2c_write(chip, reg, 1, &val, 1);
47 	if (ret)
48 		ERROR("PMIC: Cannot write AXP805 register %02x\n", reg);
49 
50 	return ret;
51 }
52 
53 static int axp805_probe(void)
54 {
55 	int ret;
56 	uint8_t val;
57 
58 	/* Switch the AXP805 to master/single-PMIC mode. */
59 	ret = axp_i2c_write(AXP805_ADDR, 0xff, 0x0);
60 	if (ret)
61 		return ret;
62 
63 	ret = axp_i2c_read(AXP805_ADDR, AXP805_ID, &val);
64 	if (ret)
65 		return ret;
66 
67 	val &= 0xcf;
68 	if (val != 0x40) {
69 		ERROR("PMIC: Found unknown PMIC %02x\n", val);
70 		return -EINVAL;
71 	}
72 
73 	return 0;
74 }
75 
76 int sunxi_pmic_setup(uint16_t socid, const void *fdt)
77 {
78 	int ret;
79 
80 	INFO("PMIC: Probing AXP805 on I2C\n");
81 
82 	ret = sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
83 	if (ret)
84 		return ret;
85 
86 	/* initialise mi2cv driver */
87 	i2c_init((void *)SUNXI_R_I2C_BASE);
88 
89 	ret = axp805_probe();
90 	if (ret)
91 		return ret;
92 
93 	pmic = AXP805;
94 
95 	return 0;
96 }
97 
98 void sunxi_power_down(void)
99 {
100 	uint8_t val;
101 
102 	switch (pmic) {
103 	case AXP805:
104 		/* Re-initialise after rich OS might have used it. */
105 		sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
106 		/* initialise mi2cv driver */
107 		i2c_init((void *)SUNXI_R_I2C_BASE);
108 		axp_i2c_read(AXP805_ADDR, 0x32, &val);
109 		axp_i2c_write(AXP805_ADDR, 0x32, val | 0x80);
110 		break;
111 	default:
112 		break;
113 	}
114 }
115