1 /*
2 * AXP-2XX PMU Emulation, supported lists:
3 * AXP209
4 * AXP221
5 *
6 * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
7 * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 *
27 * SPDX-License-Identifier: MIT
28 */
29
30 #include "qemu/osdep.h"
31 #include "qemu/log.h"
32 #include "qom/object.h"
33 #include "trace.h"
34 #include "hw/i2c/i2c.h"
35 #include "migration/vmstate.h"
36
37 #define TYPE_AXP2XX "axp2xx_pmu"
38 #define TYPE_AXP209_PMU "axp209_pmu"
39 #define TYPE_AXP221_PMU "axp221_pmu"
40
41 OBJECT_DECLARE_TYPE(AXP2xxI2CState, AXP2xxClass, AXP2XX)
42
43 #define NR_REGS (0xff)
44
45 /* A simple I2C slave which returns values of ID or CNT register. */
46 typedef struct AXP2xxI2CState {
47 /*< private >*/
48 I2CSlave i2c;
49 /*< public >*/
50 uint8_t regs[NR_REGS]; /* peripheral registers */
51 uint8_t ptr; /* current register index */
52 uint8_t count; /* counter used for tx/rx */
53 } AXP2xxI2CState;
54
55 typedef struct AXP2xxClass {
56 /*< private >*/
57 I2CSlaveClass parent_class;
58 /*< public >*/
59 void (*reset_enter)(AXP2xxI2CState *s, ResetType type);
60 } AXP2xxClass;
61
62 #define AXP209_CHIP_VERSION_ID (0x01)
63 #define AXP209_DC_DC2_OUT_V_CTRL_RESET (0x16)
64
65 /* Reset all counters and load ID register */
axp209_reset_enter(AXP2xxI2CState * s,ResetType type)66 static void axp209_reset_enter(AXP2xxI2CState *s, ResetType type)
67 {
68 memset(s->regs, 0, NR_REGS);
69 s->ptr = 0;
70 s->count = 0;
71
72 s->regs[0x03] = AXP209_CHIP_VERSION_ID;
73 s->regs[0x23] = AXP209_DC_DC2_OUT_V_CTRL_RESET;
74
75 s->regs[0x30] = 0x60;
76 s->regs[0x32] = 0x46;
77 s->regs[0x34] = 0x41;
78 s->regs[0x35] = 0x22;
79 s->regs[0x36] = 0x5d;
80 s->regs[0x37] = 0x08;
81 s->regs[0x38] = 0xa5;
82 s->regs[0x39] = 0x1f;
83 s->regs[0x3a] = 0x68;
84 s->regs[0x3b] = 0x5f;
85 s->regs[0x3c] = 0xfc;
86 s->regs[0x3d] = 0x16;
87 s->regs[0x40] = 0xd8;
88 s->regs[0x42] = 0xff;
89 s->regs[0x43] = 0x3b;
90 s->regs[0x80] = 0xe0;
91 s->regs[0x82] = 0x83;
92 s->regs[0x83] = 0x80;
93 s->regs[0x84] = 0x32;
94 s->regs[0x86] = 0xff;
95 s->regs[0x90] = 0x07;
96 s->regs[0x91] = 0xa0;
97 s->regs[0x92] = 0x07;
98 s->regs[0x93] = 0x07;
99 }
100
101 #define AXP221_PWR_STATUS_ACIN_PRESENT BIT(7)
102 #define AXP221_PWR_STATUS_ACIN_AVAIL BIT(6)
103 #define AXP221_PWR_STATUS_VBUS_PRESENT BIT(5)
104 #define AXP221_PWR_STATUS_VBUS_USED BIT(4)
105 #define AXP221_PWR_STATUS_BAT_CHARGING BIT(2)
106 #define AXP221_PWR_STATUS_ACIN_VBUS_POWERED BIT(1)
107
108 /* Reset all counters and load ID register */
axp221_reset_enter(AXP2xxI2CState * s,ResetType type)109 static void axp221_reset_enter(AXP2xxI2CState *s, ResetType type)
110 {
111 memset(s->regs, 0, NR_REGS);
112 s->ptr = 0;
113 s->count = 0;
114
115 /* input power status register */
116 s->regs[0x00] = AXP221_PWR_STATUS_ACIN_PRESENT
117 | AXP221_PWR_STATUS_ACIN_AVAIL
118 | AXP221_PWR_STATUS_ACIN_VBUS_POWERED;
119
120 s->regs[0x01] = 0x00; /* no battery is connected */
121
122 /*
123 * CHIPID register, no documented on datasheet, but it is checked in
124 * u-boot spl. I had read it from AXP221s and got 0x06 value.
125 * So leave 06h here.
126 */
127 s->regs[0x03] = 0x06;
128
129 s->regs[0x10] = 0xbf;
130 s->regs[0x13] = 0x01;
131 s->regs[0x30] = 0x60;
132 s->regs[0x31] = 0x03;
133 s->regs[0x32] = 0x43;
134 s->regs[0x33] = 0xc6;
135 s->regs[0x34] = 0x45;
136 s->regs[0x35] = 0x0e;
137 s->regs[0x36] = 0x5d;
138 s->regs[0x37] = 0x08;
139 s->regs[0x38] = 0xa5;
140 s->regs[0x39] = 0x1f;
141 s->regs[0x3c] = 0xfc;
142 s->regs[0x3d] = 0x16;
143 s->regs[0x80] = 0x80;
144 s->regs[0x82] = 0xe0;
145 s->regs[0x84] = 0x32;
146 s->regs[0x8f] = 0x01;
147
148 s->regs[0x90] = 0x07;
149 s->regs[0x91] = 0x1f;
150 s->regs[0x92] = 0x07;
151 s->regs[0x93] = 0x1f;
152
153 s->regs[0x40] = 0xd8;
154 s->regs[0x41] = 0xff;
155 s->regs[0x42] = 0x03;
156 s->regs[0x43] = 0x03;
157
158 s->regs[0xb8] = 0xc0;
159 s->regs[0xb9] = 0x64;
160 s->regs[0xe6] = 0xa0;
161 }
162
axp2xx_reset_enter(Object * obj,ResetType type)163 static void axp2xx_reset_enter(Object *obj, ResetType type)
164 {
165 AXP2xxI2CState *s = AXP2XX(obj);
166 AXP2xxClass *sc = AXP2XX_GET_CLASS(s);
167
168 sc->reset_enter(s, type);
169 }
170
171 /* Handle events from master. */
axp2xx_event(I2CSlave * i2c,enum i2c_event event)172 static int axp2xx_event(I2CSlave *i2c, enum i2c_event event)
173 {
174 AXP2xxI2CState *s = AXP2XX(i2c);
175
176 s->count = 0;
177
178 return 0;
179 }
180
181 /* Called when master requests read */
axp2xx_rx(I2CSlave * i2c)182 static uint8_t axp2xx_rx(I2CSlave *i2c)
183 {
184 AXP2xxI2CState *s = AXP2XX(i2c);
185 uint8_t ret = 0xff;
186
187 if (s->ptr < NR_REGS) {
188 ret = s->regs[s->ptr++];
189 }
190
191 trace_axp2xx_rx(s->ptr - 1, ret);
192
193 return ret;
194 }
195
196 /*
197 * Called when master sends write.
198 * Update ptr with byte 0, then perform write with second byte.
199 */
axp2xx_tx(I2CSlave * i2c,uint8_t data)200 static int axp2xx_tx(I2CSlave *i2c, uint8_t data)
201 {
202 AXP2xxI2CState *s = AXP2XX(i2c);
203
204 if (s->count == 0) {
205 /* Store register address */
206 s->ptr = data;
207 s->count++;
208 trace_axp2xx_select(data);
209 } else {
210 trace_axp2xx_tx(s->ptr, data);
211 s->regs[s->ptr++] = data;
212 }
213
214 return 0;
215 }
216
217 static const VMStateDescription vmstate_axp2xx = {
218 .name = TYPE_AXP2XX,
219 .version_id = 1,
220 .fields = (const VMStateField[]) {
221 VMSTATE_UINT8_ARRAY(regs, AXP2xxI2CState, NR_REGS),
222 VMSTATE_UINT8(ptr, AXP2xxI2CState),
223 VMSTATE_UINT8(count, AXP2xxI2CState),
224 VMSTATE_END_OF_LIST()
225 }
226 };
227
axp2xx_class_init(ObjectClass * oc,void * data)228 static void axp2xx_class_init(ObjectClass *oc, void *data)
229 {
230 DeviceClass *dc = DEVICE_CLASS(oc);
231 I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
232 ResettableClass *rc = RESETTABLE_CLASS(oc);
233
234 rc->phases.enter = axp2xx_reset_enter;
235 dc->vmsd = &vmstate_axp2xx;
236 isc->event = axp2xx_event;
237 isc->recv = axp2xx_rx;
238 isc->send = axp2xx_tx;
239 }
240
241 static const TypeInfo axp2xx_info = {
242 .name = TYPE_AXP2XX,
243 .parent = TYPE_I2C_SLAVE,
244 .instance_size = sizeof(AXP2xxI2CState),
245 .class_size = sizeof(AXP2xxClass),
246 .class_init = axp2xx_class_init,
247 .abstract = true,
248 };
249
axp209_class_init(ObjectClass * oc,void * data)250 static void axp209_class_init(ObjectClass *oc, void *data)
251 {
252 AXP2xxClass *sc = AXP2XX_CLASS(oc);
253
254 sc->reset_enter = axp209_reset_enter;
255 }
256
257 static const TypeInfo axp209_info = {
258 .name = TYPE_AXP209_PMU,
259 .parent = TYPE_AXP2XX,
260 .class_init = axp209_class_init
261 };
262
axp221_class_init(ObjectClass * oc,void * data)263 static void axp221_class_init(ObjectClass *oc, void *data)
264 {
265 AXP2xxClass *sc = AXP2XX_CLASS(oc);
266
267 sc->reset_enter = axp221_reset_enter;
268 }
269
270 static const TypeInfo axp221_info = {
271 .name = TYPE_AXP221_PMU,
272 .parent = TYPE_AXP2XX,
273 .class_init = axp221_class_init,
274 };
275
axp2xx_register_devices(void)276 static void axp2xx_register_devices(void)
277 {
278 type_register_static(&axp2xx_info);
279 type_register_static(&axp209_info);
280 type_register_static(&axp221_info);
281 }
282
283 type_init(axp2xx_register_devices);
284