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/allwinner/axp.h>
14 #include <drivers/delay_timer.h>
15 #include <drivers/mentor/mi2cv.h>
16 #include <lib/mmio.h>
17
18 #include <sunxi_def.h>
19 #include <sunxi_mmap.h>
20 #include <sunxi_private.h>
21
22 #define AXP805_ADDR 0x36
23
24 static enum pmic_type {
25 UNKNOWN,
26 AXP805,
27 } pmic;
28
axp_read(uint8_t reg)29 int axp_read(uint8_t reg)
30 {
31 uint8_t val;
32 int ret;
33
34 ret = i2c_write(AXP805_ADDR, 0, 0, ®, 1);
35 if (ret == 0)
36 ret = i2c_read(AXP805_ADDR, 0, 0, &val, 1);
37 if (ret) {
38 ERROR("PMIC: Cannot read AXP805 register %02x\n", reg);
39 return ret;
40 }
41
42 return val;
43 }
44
axp_write(uint8_t reg,uint8_t val)45 int axp_write(uint8_t reg, uint8_t val)
46 {
47 int ret;
48
49 ret = i2c_write(AXP805_ADDR, reg, 1, &val, 1);
50 if (ret)
51 ERROR("PMIC: Cannot write AXP805 register %02x\n", reg);
52
53 return ret;
54 }
55
axp805_probe(void)56 static int axp805_probe(void)
57 {
58 int ret;
59
60 /* Switch the AXP805 to master/single-PMIC mode. */
61 ret = axp_write(0xff, 0x0);
62 if (ret)
63 return ret;
64
65 ret = axp_check_id();
66 if (ret)
67 return ret;
68
69 return 0;
70 }
71
sunxi_pmic_setup(uint16_t socid,const void * fdt)72 int sunxi_pmic_setup(uint16_t socid, const void *fdt)
73 {
74 int ret;
75
76 INFO("PMIC: Probing AXP805 on I2C\n");
77
78 ret = sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
79 if (ret)
80 return ret;
81
82 /* initialise mi2cv driver */
83 i2c_init((void *)SUNXI_R_I2C_BASE);
84
85 ret = axp805_probe();
86 if (ret)
87 return ret;
88
89 pmic = AXP805;
90 axp_setup_regulators(fdt);
91
92 return 0;
93 }
94
sunxi_power_down(void)95 void sunxi_power_down(void)
96 {
97 switch (pmic) {
98 case AXP805:
99 /* Re-initialise after rich OS might have used it. */
100 sunxi_init_platform_r_twi(SUNXI_SOC_H6, false);
101 /* initialise mi2cv driver */
102 i2c_init((void *)SUNXI_R_I2C_BASE);
103 axp_power_off();
104 break;
105 default:
106 break;
107 }
108 }
109