qemu

Форк
0
/
dps310.c 
224 строки · 5.8 Кб
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * Copyright 2017-2021 Joel Stanley <joel@jms.id.au>, IBM Corporation
4
 *
5
 * Infineon DPS310 temperature and humidity sensor
6
 *
7
 * https://www.infineon.com/cms/en/product/sensor/pressure-sensors/pressure-sensors-for-iot/dps310/
8
 */
9

10
#include "qemu/osdep.h"
11
#include "qemu/log.h"
12
#include "hw/i2c/i2c.h"
13
#include "qapi/error.h"
14
#include "qapi/visitor.h"
15
#include "migration/vmstate.h"
16

17
#define NUM_REGISTERS   0x33
18

19
typedef struct DPS310State {
20
    /*< private >*/
21
    I2CSlave i2c;
22

23
    /*< public >*/
24
    uint8_t regs[NUM_REGISTERS];
25

26
    uint8_t len;
27
    uint8_t pointer;
28

29
} DPS310State;
30

31
#define TYPE_DPS310 "dps310"
32
#define DPS310(obj) OBJECT_CHECK(DPS310State, (obj), TYPE_DPS310)
33

34
#define DPS310_PRS_B2           0x00
35
#define DPS310_PRS_B1           0x01
36
#define DPS310_PRS_B0           0x02
37
#define DPS310_TMP_B2           0x03
38
#define DPS310_TMP_B1           0x04
39
#define DPS310_TMP_B0           0x05
40
#define DPS310_PRS_CFG          0x06
41
#define DPS310_TMP_CFG          0x07
42
#define  DPS310_TMP_RATE_BITS   (0x70)
43
#define DPS310_MEAS_CFG         0x08
44
#define  DPS310_MEAS_CTRL_BITS  (0x07)
45
#define   DPS310_PRESSURE_EN    BIT(0)
46
#define   DPS310_TEMP_EN        BIT(1)
47
#define   DPS310_BACKGROUND     BIT(2)
48
#define  DPS310_PRS_RDY         BIT(4)
49
#define  DPS310_TMP_RDY         BIT(5)
50
#define  DPS310_SENSOR_RDY      BIT(6)
51
#define  DPS310_COEF_RDY        BIT(7)
52
#define DPS310_CFG_REG          0x09
53
#define DPS310_RESET            0x0c
54
#define  DPS310_RESET_MAGIC     (BIT(0) | BIT(3))
55
#define DPS310_COEF_BASE        0x10
56
#define DPS310_COEF_LAST        0x21
57
#define DPS310_COEF_SRC         0x28
58

59
static void dps310_reset(DeviceState *dev)
60
{
61
    DPS310State *s = DPS310(dev);
62

63
    static const uint8_t regs_reset_state[sizeof(s->regs)] = {
64
        0xfe, 0x2f, 0xee, 0x02, 0x69, 0xa6, 0x00, 0x80, 0xc7, 0x00, 0x00, 0x00,
65
        0x00, 0x10, 0x00, 0x00, 0x0e, 0x1e, 0xdd, 0x13, 0xca, 0x5f, 0x21, 0x52,
66
        0xf9, 0xc6, 0x04, 0xd1, 0xdb, 0x47, 0x00, 0x5b, 0xfb, 0x3a, 0x00, 0x00,
67
        0x20, 0x49, 0x4e, 0xa5, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68
        0x60, 0x15, 0x02
69
    };
70

71
    memcpy(s->regs, regs_reset_state, sizeof(s->regs));
72
    s->pointer = 0;
73

74
    /* TODO: assert these after some timeout ? */
75
    s->regs[DPS310_MEAS_CFG] = DPS310_COEF_RDY | DPS310_SENSOR_RDY
76
        | DPS310_TMP_RDY | DPS310_PRS_RDY;
77
}
78

79
static uint8_t dps310_read(DPS310State *s, uint8_t reg)
80
{
81
    if (reg >= sizeof(s->regs)) {
82
        qemu_log_mask(LOG_GUEST_ERROR, "%s: register 0x%02x out of bounds\n",
83
                      __func__, s->pointer);
84
        return 0xFF;
85
    }
86

87
    switch (reg) {
88
    case DPS310_PRS_B2:
89
    case DPS310_PRS_B1:
90
    case DPS310_PRS_B0:
91
    case DPS310_TMP_B2:
92
    case DPS310_TMP_B1:
93
    case DPS310_TMP_B0:
94
    case DPS310_PRS_CFG:
95
    case DPS310_TMP_CFG:
96
    case DPS310_MEAS_CFG:
97
    case DPS310_CFG_REG:
98
    case DPS310_COEF_BASE...DPS310_COEF_LAST:
99
    case DPS310_COEF_SRC:
100
    case 0x32: /* Undocumented register to indicate workaround not required */
101
        return s->regs[reg];
102
    default:
103
        qemu_log_mask(LOG_UNIMP, "%s: register 0x%02x unimplemented\n",
104
                      __func__, reg);
105
        return 0xFF;
106
    }
107
}
108

109
static void dps310_write(DPS310State *s, uint8_t reg, uint8_t data)
110
{
111
    if (reg >= sizeof(s->regs)) {
112
        qemu_log_mask(LOG_GUEST_ERROR, "%s: register %d out of bounds\n",
113
                      __func__, s->pointer);
114
        return;
115
    }
116

117
    switch (reg) {
118
    case DPS310_RESET:
119
        if (data == DPS310_RESET_MAGIC) {
120
            device_cold_reset(DEVICE(s));
121
        }
122
        break;
123
    case DPS310_PRS_CFG:
124
    case DPS310_TMP_CFG:
125
    case DPS310_MEAS_CFG:
126
    case DPS310_CFG_REG:
127
        s->regs[reg] = data;
128
        break;
129
    default:
130
        qemu_log_mask(LOG_UNIMP, "%s: register 0x%02x unimplemented\n",
131
                      __func__, reg);
132
        return;
133
    }
134
}
135

136
static uint8_t dps310_rx(I2CSlave *i2c)
137
{
138
    DPS310State *s = DPS310(i2c);
139

140
    if (s->len == 1) {
141
        return dps310_read(s, s->pointer++);
142
    } else {
143
        return 0xFF;
144
    }
145
}
146

147
static int dps310_tx(I2CSlave *i2c, uint8_t data)
148
{
149
    DPS310State *s = DPS310(i2c);
150

151
    if (s->len == 0) {
152
        /*
153
         * first byte is the register pointer for a read or write
154
         * operation
155
         */
156
        s->pointer = data;
157
        s->len++;
158
    } else if (s->len == 1) {
159
        dps310_write(s, s->pointer++, data);
160
    }
161

162
    return 0;
163
}
164

165
static int dps310_event(I2CSlave *i2c, enum i2c_event event)
166
{
167
    DPS310State *s = DPS310(i2c);
168

169
    switch (event) {
170
    case I2C_START_SEND:
171
        s->pointer = 0xFF;
172
        s->len = 0;
173
        break;
174
    case I2C_START_RECV:
175
        if (s->len != 1) {
176
            qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid recv sequence\n",
177
                          __func__);
178
        }
179
        break;
180
    default:
181
        break;
182
    }
183

184
    return 0;
185
}
186

187
static const VMStateDescription vmstate_dps310 = {
188
    .name = "DPS310",
189
    .version_id = 0,
190
    .minimum_version_id = 0,
191
    .fields = (const VMStateField[]) {
192
        VMSTATE_UINT8(len, DPS310State),
193
        VMSTATE_UINT8_ARRAY(regs, DPS310State, NUM_REGISTERS),
194
        VMSTATE_UINT8(pointer, DPS310State),
195
        VMSTATE_I2C_SLAVE(i2c, DPS310State),
196
        VMSTATE_END_OF_LIST()
197
    }
198
};
199

200
static void dps310_class_init(ObjectClass *klass, void *data)
201
{
202
    DeviceClass *dc = DEVICE_CLASS(klass);
203
    I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
204

205
    k->event = dps310_event;
206
    k->recv = dps310_rx;
207
    k->send = dps310_tx;
208
    dc->reset = dps310_reset;
209
    dc->vmsd = &vmstate_dps310;
210
}
211

212
static const TypeInfo dps310_info = {
213
    .name          = TYPE_DPS310,
214
    .parent        = TYPE_I2C_SLAVE,
215
    .instance_size = sizeof(DPS310State),
216
    .class_init    = dps310_class_init,
217
};
218

219
static void dps310_register_types(void)
220
{
221
    type_register_static(&dps310_info);
222
}
223

224
type_init(dps310_register_types)
225

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

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

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

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