qemu

Форк
0
/
axp2xx.c 
283 строки · 7.5 Кб
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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.