xref: /openbmc/qemu/hw/misc/axp2xx.c (revision 2df1eb27)
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 */
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 */
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 
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. */
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 */
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  */
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 
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 
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 
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 
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