xref: /rk3399_ARM-atf/plat/allwinner/sun50i_h6/sunxi_power.c (revision 6d37282807c8540319777cb50f411a2e56607438)
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 <debug.h>
9 #include <delay_timer.h>
10 #include <errno.h>
11 #include <mmio.h>
12 #include <mentor/mi2cv.h>
13 #include <string.h>
14 #include <sunxi_mmap.h>
15 
16 #define AXP805_ADDR	0x36
17 #define AXP805_ID	0x03
18 
19 enum pmic_type {
20 	NO_PMIC,
21 	AXP805,
22 };
23 
24 enum pmic_type pmic;
25 
26 static int sunxi_init_r_i2c(void)
27 {
28 	uint32_t reg;
29 
30 	/* get currently configured function for pins PL0 and PL1 */
31 	reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x00);
32 	if ((reg & 0xff) == 0x33) {
33 		NOTICE("PMIC: already configured for TWI\n");
34 	}
35 
36 	/* switch pins PL0 and PL1 to I2C */
37 	mmio_write_32(SUNXI_R_PIO_BASE + 0x00, (reg & ~0xff) | 0x33);
38 
39 	/* level 2 drive strength */
40 	reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x14);
41 	mmio_write_32(SUNXI_R_PIO_BASE + 0x14, (reg & ~0x0f) | 0xa);
42 
43 	/* set both ports to pull-up */
44 	reg = mmio_read_32(SUNXI_R_PIO_BASE + 0x1c);
45 	mmio_write_32(SUNXI_R_PIO_BASE + 0x1c, (reg & ~0x0f) | 0x5);
46 
47 	/* assert & de-assert reset of R_I2C */
48 	reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c);
49 	mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, 0);
50 	reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c);
51 	mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | 0x00010000);
52 
53 	/* un-gate R_I2C clock */
54 	reg = mmio_read_32(SUNXI_R_PRCM_BASE + 0x19c);
55 	mmio_write_32(SUNXI_R_PRCM_BASE + 0x19c, reg | 0x00000001);
56 
57 	/* call mi2cv driver */
58 	i2c_init((void *)SUNXI_R_I2C_BASE);
59 
60 	return 0;
61 }
62 
63 int axp_i2c_read(uint8_t chip, uint8_t reg, uint8_t *val)
64 {
65 	int ret;
66 
67 	ret = i2c_write(chip, 0, 0, &reg, 1);
68 	if (ret)
69 		return ret;
70 
71 	return i2c_read(chip, 0, 0, val, 1);
72 }
73 
74 int axp_i2c_write(uint8_t chip, uint8_t reg, uint8_t val)
75 {
76 	return i2c_write(chip, reg, 1, &val, 1);
77 }
78 
79 static int axp805_probe(void)
80 {
81 	int ret;
82 	uint8_t val;
83 
84 	ret = axp_i2c_write(AXP805_ADDR, 0xff, 0x0);
85 	if (ret) {
86 		ERROR("PMIC: Cannot put AXP805 to master mode.\n");
87 		return -EPERM;
88 	}
89 
90 	ret = axp_i2c_read(AXP805_ADDR, AXP805_ID, &val);
91 
92 	if (!ret && ((val & 0xcf) == 0x40))
93 		NOTICE("PMIC: AXP805 detected\n");
94 	else if (ret) {
95 		ERROR("PMIC: Cannot communicate with AXP805.\n");
96 		return -EPERM;
97 	} else {
98 		ERROR("PMIC: Non-AXP805 chip attached at AXP805's address.\n");
99 		return -EINVAL;
100 	}
101 
102 	return 0;
103 }
104 
105 int sunxi_pmic_setup(void)
106 {
107 	int ret;
108 
109 	sunxi_init_r_i2c();
110 
111 	NOTICE("PMIC: Probing AXP805\n");
112 	pmic = AXP805;
113 
114 	ret = axp805_probe();
115 	if (ret)
116 		pmic = NO_PMIC;
117 	else
118 		pmic = AXP805;
119 
120 	return 0;
121 }
122