xref: /rk3399_ARM-atf/plat/allwinner/sun50i_h6/sunxi_power.c (revision c0e109f2feb4fb40c9b345684ab18b8afd9e94cb)
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)
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 
81 	ret = axp805_probe();
82 	if (ret)
83 		return ret;
84 
85 	pmic = AXP805;
86 
87 	return 0;
88 }
89 
90 void __dead2 sunxi_power_down(void)
91 {
92 	uint8_t val;
93 
94 	switch (pmic) {
95 	case AXP805:
96 		/* Re-initialise after rich OS might have used it. */
97 		sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
98 		/* initialise mi2cv driver */
99 		i2c_init((void *)SUNXI_R_I2C_BASE);
100 		axp_i2c_read(AXP805_ADDR, 0x32, &val);
101 		axp_i2c_write(AXP805_ADDR, 0x32, val | 0x80);
102 		break;
103 	default:
104 		break;
105 	}
106 
107 	udelay(1000);
108 	ERROR("PSCI: Cannot communicate with PMIC, halting\n");
109 	wfi();
110 	panic();
111 }
112