Merge branch 'master' of http://git.denx.de/u-boot-sunxi
[oweals/u-boot.git] / arch / arm / cpu / armv7 / sunxi / pmic_bus.c
1 /*
2  * (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
3  *
4  * Sunxi PMIC bus access helpers
5  *
6  * The axp152 & axp209 use an i2c bus, the axp221 uses the p2wi bus and the
7  * axp223 uses the rsb bus, these functions abstract this.
8  *
9  * SPDX-License-Identifier:     GPL-2.0+
10  */
11
12 #include <common.h>
13 #include <asm/arch/p2wi.h>
14 #include <asm/arch/rsb.h>
15 #include <i2c.h>
16 #include <asm/arch/pmic_bus.h>
17
18 #define AXP152_I2C_ADDR                 0x30
19
20 #define AXP209_I2C_ADDR                 0x34
21
22 #define AXP221_CHIP_ADDR                0x68
23 #define AXP221_CTRL_ADDR                0x3e
24 #define AXP221_INIT_DATA                0x3e
25
26 #define AXP223_DEVICE_ADDR              0x3a3
27 #define AXP223_RUNTIME_ADDR             0x2d
28
29 int pmic_bus_init(void)
30 {
31         /* This cannot be 0 because it is used in SPL before BSS is ready */
32         static int needs_init = 1;
33         __maybe_unused int ret;
34
35         if (!needs_init)
36                 return 0;
37
38 #ifdef CONFIG_AXP221_POWER
39 # ifdef CONFIG_MACH_SUN6I
40         p2wi_init();
41         ret = p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR,
42                                        AXP221_INIT_DATA);
43 # else
44         ret = rsb_init();
45         if (ret)
46                 return ret;
47
48         ret = rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR);
49 # endif
50         if (ret)
51                 return ret;
52 #endif
53
54         needs_init = 0;
55         return 0;
56 }
57
58 int pmic_bus_read(u8 reg, u8 *data)
59 {
60 #ifdef CONFIG_AXP152_POWER
61         return i2c_read(AXP152_I2C_ADDR, reg, 1, data, 1);
62 #elif defined CONFIG_AXP209_POWER
63         return i2c_read(AXP209_I2C_ADDR, reg, 1, data, 1);
64 #elif defined CONFIG_AXP221_POWER
65 # ifdef CONFIG_MACH_SUN6I
66         return p2wi_read(reg, data);
67 # else
68         return rsb_read(AXP223_RUNTIME_ADDR, reg, data);
69 # endif
70 #endif
71 }
72
73 int pmic_bus_write(u8 reg, u8 data)
74 {
75 #ifdef CONFIG_AXP152_POWER
76         return i2c_write(AXP152_I2C_ADDR, reg, 1, &data, 1);
77 #elif defined CONFIG_AXP209_POWER
78         return i2c_write(AXP209_I2C_ADDR, reg, 1, &data, 1);
79 #elif defined CONFIG_AXP221_POWER
80 # ifdef CONFIG_MACH_SUN6I
81         return p2wi_write(reg, data);
82 # else
83         return rsb_write(AXP223_RUNTIME_ADDR, reg, data);
84 # endif
85 #endif
86 }
87
88 int pmic_bus_setbits(u8 reg, u8 bits)
89 {
90         int ret;
91         u8 val;
92
93         ret = pmic_bus_read(reg, &val);
94         if (ret)
95                 return ret;
96
97         val |= bits;
98         return pmic_bus_write(reg, val);
99 }
100
101 int pmic_bus_clrbits(u8 reg, u8 bits)
102 {
103         int ret;
104         u8 val;
105
106         ret = pmic_bus_read(reg, &val);
107         if (ret)
108                 return ret;
109
110         val &= ~bits;
111         return pmic_bus_write(reg, val);
112 }