2 * AXP-2XX PMU Emulation, supported lists:
6 * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
7 * Copyright (C) 2023 qianfan Zhao <qianfanguijin@163.com>
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:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
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.
27 * SPDX-License-Identifier: MIT
30 #include "qemu/osdep.h"
32 #include "qom/object.h"
34 #include "hw/i2c/i2c.h"
35 #include "migration/vmstate.h"
37 #define TYPE_AXP2XX "axp2xx_pmu"
38 #define TYPE_AXP209_PMU "axp209_pmu"
39 #define TYPE_AXP221_PMU "axp221_pmu"
41 OBJECT_DECLARE_TYPE(AXP2xxI2CState
, AXP2xxClass
, AXP2XX
)
43 #define NR_REGS (0xff)
45 /* A simple I2C slave which returns values of ID or CNT register. */
46 typedef struct AXP2xxI2CState
{
50 uint8_t regs
[NR_REGS
]; /* peripheral registers */
51 uint8_t ptr
; /* current register index */
52 uint8_t count
; /* counter used for tx/rx */
55 typedef struct AXP2xxClass
{
57 I2CSlaveClass parent_class
;
59 void (*reset_enter
)(AXP2xxI2CState
*s
, ResetType type
);
62 #define AXP209_CHIP_VERSION_ID (0x01)
63 #define AXP209_DC_DC2_OUT_V_CTRL_RESET (0x16)
65 /* Reset all counters and load ID register */
66 static void axp209_reset_enter(AXP2xxI2CState
*s
, ResetType type
)
68 memset(s
->regs
, 0, NR_REGS
);
72 s
->regs
[0x03] = AXP209_CHIP_VERSION_ID
;
73 s
->regs
[0x23] = AXP209_DC_DC2_OUT_V_CTRL_RESET
;
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)
108 /* Reset all counters and load ID register */
109 static void axp221_reset_enter(AXP2xxI2CState
*s
, ResetType type
)
111 memset(s
->regs
, 0, NR_REGS
);
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
;
120 s
->regs
[0x01] = 0x00; /* no battery is connected */
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.
127 s
->regs
[0x03] = 0x06;
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;
148 s
->regs
[0x90] = 0x07;
149 s
->regs
[0x91] = 0x1f;
150 s
->regs
[0x92] = 0x07;
151 s
->regs
[0x93] = 0x1f;
153 s
->regs
[0x40] = 0xd8;
154 s
->regs
[0x41] = 0xff;
155 s
->regs
[0x42] = 0x03;
156 s
->regs
[0x43] = 0x03;
158 s
->regs
[0xb8] = 0xc0;
159 s
->regs
[0xb9] = 0x64;
160 s
->regs
[0xe6] = 0xa0;
163 static void axp2xx_reset_enter(Object
*obj
, ResetType type
)
165 AXP2xxI2CState
*s
= AXP2XX(obj
);
166 AXP2xxClass
*sc
= AXP2XX_GET_CLASS(s
);
168 sc
->reset_enter(s
, type
);
171 /* Handle events from master. */
172 static int axp2xx_event(I2CSlave
*i2c
, enum i2c_event event
)
174 AXP2xxI2CState
*s
= AXP2XX(i2c
);
181 /* Called when master requests read */
182 static uint8_t axp2xx_rx(I2CSlave
*i2c
)
184 AXP2xxI2CState
*s
= AXP2XX(i2c
);
187 if (s
->ptr
< NR_REGS
) {
188 ret
= s
->regs
[s
->ptr
++];
191 trace_axp2xx_rx(s
->ptr
- 1, ret
);
197 * Called when master sends write.
198 * Update ptr with byte 0, then perform write with second byte.
200 static int axp2xx_tx(I2CSlave
*i2c
, uint8_t data
)
202 AXP2xxI2CState
*s
= AXP2XX(i2c
);
205 /* Store register address */
208 trace_axp2xx_select(data
);
210 trace_axp2xx_tx(s
->ptr
, data
);
211 s
->regs
[s
->ptr
++] = data
;
217 static const VMStateDescription vmstate_axp2xx
= {
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()
228 static void axp2xx_class_init(ObjectClass
*oc
, void *data
)
230 DeviceClass
*dc
= DEVICE_CLASS(oc
);
231 I2CSlaveClass
*isc
= I2C_SLAVE_CLASS(oc
);
232 ResettableClass
*rc
= RESETTABLE_CLASS(oc
);
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
;
241 static const TypeInfo axp2xx_info
= {
243 .parent
= TYPE_I2C_SLAVE
,
244 .instance_size
= sizeof(AXP2xxI2CState
),
245 .class_size
= sizeof(AXP2xxClass
),
246 .class_init
= axp2xx_class_init
,
250 static void axp209_class_init(ObjectClass
*oc
, void *data
)
252 AXP2xxClass
*sc
= AXP2XX_CLASS(oc
);
254 sc
->reset_enter
= axp209_reset_enter
;
257 static const TypeInfo axp209_info
= {
258 .name
= TYPE_AXP209_PMU
,
259 .parent
= TYPE_AXP2XX
,
260 .class_init
= axp209_class_init
263 static void axp221_class_init(ObjectClass
*oc
, void *data
)
265 AXP2xxClass
*sc
= AXP2XX_CLASS(oc
);
267 sc
->reset_enter
= axp221_reset_enter
;
270 static const TypeInfo axp221_info
= {
271 .name
= TYPE_AXP221_PMU
,
272 .parent
= TYPE_AXP2XX
,
273 .class_init
= axp221_class_init
,
276 static void axp2xx_register_devices(void)
278 type_register_static(&axp2xx_info
);
279 type_register_static(&axp209_info
);
280 type_register_static(&axp221_info
);
283 type_init(axp2xx_register_devices
);