xref: /openbmc/qemu/hw/misc/ir35221.c (revision 7ac65cd7d11e5c9f7fb42c1fc4eb991d26cbcabd)
1*7ac65cd7SCédric Le Goater /*
2*7ac65cd7SCédric Le Goater  * IBM CFF power supplies device
3*7ac65cd7SCédric Le Goater  *
4*7ac65cd7SCédric Le Goater  * Copyright (c) 2019 IBM Corporation.
5*7ac65cd7SCédric Le Goater  *
6*7ac65cd7SCédric Le Goater  * This code is licensed under the GPL version 2 or later. See the
7*7ac65cd7SCédric Le Goater  * COPYING file in the top-level directory.
8*7ac65cd7SCédric Le Goater  */
9*7ac65cd7SCédric Le Goater 
10*7ac65cd7SCédric Le Goater #include "qemu/osdep.h"
11*7ac65cd7SCédric Le Goater #include "hw/hw.h"
12*7ac65cd7SCédric Le Goater #include "hw/i2c/i2c.h"
13*7ac65cd7SCédric Le Goater #include "qapi/error.h"
14*7ac65cd7SCédric Le Goater #include "qapi/visitor.h"
15*7ac65cd7SCédric Le Goater #include "hw/misc/pmbus_regs.h"
16*7ac65cd7SCédric Le Goater #include "migration/vmstate.h"
17*7ac65cd7SCédric Le Goater 
18*7ac65cd7SCédric Le Goater #define IR35221_MFR_VIN_PEAK            0xc5
19*7ac65cd7SCédric Le Goater #define IR35221_MFR_VOUT_PEAK           0xc6
20*7ac65cd7SCédric Le Goater #define IR35221_MFR_IOUT_PEAK           0xc7
21*7ac65cd7SCédric Le Goater #define IR35221_MFR_TEMP_PEAK           0xc8
22*7ac65cd7SCédric Le Goater #define IR35221_MFR_VIN_VALLEY          0xc9
23*7ac65cd7SCédric Le Goater #define IR35221_MFR_VOUT_VALLEY         0xca
24*7ac65cd7SCédric Le Goater #define IR35221_MFR_IOUT_VALLEY         0xcb
25*7ac65cd7SCédric Le Goater #define IR35221_MFR_TEMP_VALLEY         0xcc
26*7ac65cd7SCédric Le Goater 
27*7ac65cd7SCédric Le Goater typedef struct Ir35221State {
28*7ac65cd7SCédric Le Goater     /*< private >*/
29*7ac65cd7SCédric Le Goater     I2CSlave i2c;
30*7ac65cd7SCédric Le Goater     /*< public >*/
31*7ac65cd7SCédric Le Goater 
32*7ac65cd7SCédric Le Goater     uint8_t regs[0x100];
33*7ac65cd7SCédric Le Goater 
34*7ac65cd7SCédric Le Goater     uint8_t len;
35*7ac65cd7SCédric Le Goater     uint8_t buf[32];
36*7ac65cd7SCédric Le Goater     uint8_t pointer;
37*7ac65cd7SCédric Le Goater 
38*7ac65cd7SCédric Le Goater } Ir35221State;
39*7ac65cd7SCédric Le Goater 
40*7ac65cd7SCédric Le Goater #define TYPE_IR35221 "ir35221"
41*7ac65cd7SCédric Le Goater #define IR35221(obj) OBJECT_CHECK(Ir35221State, (obj), TYPE_IR35221)
42*7ac65cd7SCédric Le Goater 
ir35221_read(Ir35221State * s)43*7ac65cd7SCédric Le Goater static void ir35221_read(Ir35221State *s)
44*7ac65cd7SCédric Le Goater {
45*7ac65cd7SCédric Le Goater     s->len = 0;
46*7ac65cd7SCédric Le Goater 
47*7ac65cd7SCédric Le Goater     switch (s->pointer) {
48*7ac65cd7SCédric Le Goater     case PMBUS_MFR_ID:
49*7ac65cd7SCédric Le Goater         s->buf[s->len++] = 2;  /* Byte count */
50*7ac65cd7SCédric Le Goater         s->buf[s->len++] = 'R';
51*7ac65cd7SCédric Le Goater         s->buf[s->len++] = 'I';
52*7ac65cd7SCédric Le Goater         break;
53*7ac65cd7SCédric Le Goater     case PMBUS_MFR_MODEL:
54*7ac65cd7SCédric Le Goater         s->buf[s->len++] = 2;   /* Byte count */
55*7ac65cd7SCédric Le Goater         s->buf[s->len++] = 0x6c;
56*7ac65cd7SCédric Le Goater         s->buf[s->len++] = 0x00;
57*7ac65cd7SCédric Le Goater         break;
58*7ac65cd7SCédric Le Goater     default:
59*7ac65cd7SCédric Le Goater         s->buf[s->len++] = s->regs[s->pointer];
60*7ac65cd7SCédric Le Goater         break;
61*7ac65cd7SCédric Le Goater     }
62*7ac65cd7SCédric Le Goater }
63*7ac65cd7SCédric Le Goater 
ir35221_write(Ir35221State * s)64*7ac65cd7SCédric Le Goater static void ir35221_write(Ir35221State *s)
65*7ac65cd7SCédric Le Goater {
66*7ac65cd7SCédric Le Goater     /* No writes */
67*7ac65cd7SCédric Le Goater }
68*7ac65cd7SCédric Le Goater 
ir35221_recv(I2CSlave * i2c)69*7ac65cd7SCédric Le Goater static uint8_t ir35221_recv(I2CSlave *i2c)
70*7ac65cd7SCédric Le Goater {
71*7ac65cd7SCédric Le Goater     Ir35221State *s = IR35221(i2c);
72*7ac65cd7SCédric Le Goater 
73*7ac65cd7SCédric Le Goater     if (s->len < sizeof(s->buf)) {
74*7ac65cd7SCédric Le Goater         return s->buf[s->len++];
75*7ac65cd7SCédric Le Goater     } else {
76*7ac65cd7SCédric Le Goater         return 0xff;
77*7ac65cd7SCédric Le Goater     }
78*7ac65cd7SCédric Le Goater }
79*7ac65cd7SCédric Le Goater 
ir35221_send(I2CSlave * i2c,uint8_t data)80*7ac65cd7SCédric Le Goater static int ir35221_send(I2CSlave *i2c, uint8_t data)
81*7ac65cd7SCédric Le Goater {
82*7ac65cd7SCédric Le Goater     Ir35221State *s = IR35221(i2c);
83*7ac65cd7SCédric Le Goater 
84*7ac65cd7SCédric Le Goater     if (s->len == 0) {
85*7ac65cd7SCédric Le Goater         /*
86*7ac65cd7SCédric Le Goater          * first byte is the register pointer for a read or write
87*7ac65cd7SCédric Le Goater          * operation
88*7ac65cd7SCédric Le Goater          */
89*7ac65cd7SCédric Le Goater         s->pointer = data;
90*7ac65cd7SCédric Le Goater         s->len++;
91*7ac65cd7SCédric Le Goater     } else {
92*7ac65cd7SCédric Le Goater         /*
93*7ac65cd7SCédric Le Goater          * next bytes are data to write.
94*7ac65cd7SCédric Le Goater          */
95*7ac65cd7SCédric Le Goater         if (s->len <= sizeof(s->buf)) {
96*7ac65cd7SCédric Le Goater             s->buf[s->len - 1] = data;
97*7ac65cd7SCédric Le Goater         }
98*7ac65cd7SCédric Le Goater         s->len++;
99*7ac65cd7SCédric Le Goater         ir35221_write(s);
100*7ac65cd7SCédric Le Goater     }
101*7ac65cd7SCédric Le Goater 
102*7ac65cd7SCédric Le Goater     return 0;
103*7ac65cd7SCédric Le Goater }
104*7ac65cd7SCédric Le Goater 
ir35221_event(I2CSlave * i2c,enum i2c_event event)105*7ac65cd7SCédric Le Goater static int ir35221_event(I2CSlave *i2c, enum i2c_event event)
106*7ac65cd7SCédric Le Goater {
107*7ac65cd7SCédric Le Goater     Ir35221State *s = IR35221(i2c);
108*7ac65cd7SCédric Le Goater 
109*7ac65cd7SCédric Le Goater     /* TODO: handle SMBus "block read" */
110*7ac65cd7SCédric Le Goater 
111*7ac65cd7SCédric Le Goater     switch (event) {
112*7ac65cd7SCédric Le Goater     case I2C_START_RECV:
113*7ac65cd7SCédric Le Goater         ir35221_read(s);
114*7ac65cd7SCédric Le Goater         break;
115*7ac65cd7SCédric Le Goater     case I2C_START_SEND:
116*7ac65cd7SCédric Le Goater     case I2C_NACK:
117*7ac65cd7SCédric Le Goater     case I2C_FINISH:
118*7ac65cd7SCédric Le Goater          s->pointer = 0xFF;
119*7ac65cd7SCédric Le Goater         break;
120*7ac65cd7SCédric Le Goater     default:
121*7ac65cd7SCédric Le Goater         return -1;
122*7ac65cd7SCédric Le Goater     }
123*7ac65cd7SCédric Le Goater 
124*7ac65cd7SCédric Le Goater     s->len = 0;
125*7ac65cd7SCédric Le Goater     return 0;
126*7ac65cd7SCédric Le Goater }
127*7ac65cd7SCédric Le Goater 
128*7ac65cd7SCédric Le Goater static const VMStateDescription vmstate_ir35221 = {
129*7ac65cd7SCédric Le Goater     .name = TYPE_IR35221,
130*7ac65cd7SCédric Le Goater     .version_id = 0,
131*7ac65cd7SCédric Le Goater     .minimum_version_id = 0,
132*7ac65cd7SCédric Le Goater     .fields = (VMStateField[]) {
133*7ac65cd7SCédric Le Goater         VMSTATE_UINT8(len, Ir35221State),
134*7ac65cd7SCédric Le Goater         VMSTATE_UINT8_ARRAY(buf, Ir35221State, 32),
135*7ac65cd7SCédric Le Goater         VMSTATE_UINT8(pointer, Ir35221State),
136*7ac65cd7SCédric Le Goater         VMSTATE_UINT8_ARRAY(regs, Ir35221State, 0x100),
137*7ac65cd7SCédric Le Goater         VMSTATE_I2C_SLAVE(i2c, Ir35221State),
138*7ac65cd7SCédric Le Goater         VMSTATE_END_OF_LIST()
139*7ac65cd7SCédric Le Goater     }
140*7ac65cd7SCédric Le Goater };
141*7ac65cd7SCédric Le Goater 
ir35221_reset(DeviceState * dev)142*7ac65cd7SCédric Le Goater static void ir35221_reset(DeviceState *dev)
143*7ac65cd7SCédric Le Goater {
144*7ac65cd7SCédric Le Goater     Ir35221State *s = IR35221(dev);
145*7ac65cd7SCédric Le Goater 
146*7ac65cd7SCédric Le Goater     memset(s->regs, 0, sizeof(s->regs));
147*7ac65cd7SCédric Le Goater     s->pointer = 0xFF;
148*7ac65cd7SCédric Le Goater }
149*7ac65cd7SCédric Le Goater 
ir35221_realize(DeviceState * dev,Error ** errp)150*7ac65cd7SCédric Le Goater static void ir35221_realize(DeviceState *dev, Error **errp)
151*7ac65cd7SCédric Le Goater {
152*7ac65cd7SCédric Le Goater     ;
153*7ac65cd7SCédric Le Goater }
154*7ac65cd7SCédric Le Goater 
ir35221_class_init(ObjectClass * klass,void * data)155*7ac65cd7SCédric Le Goater static void ir35221_class_init(ObjectClass *klass, void *data)
156*7ac65cd7SCédric Le Goater {
157*7ac65cd7SCédric Le Goater     DeviceClass *dc = DEVICE_CLASS(klass);
158*7ac65cd7SCédric Le Goater     I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
159*7ac65cd7SCédric Le Goater 
160*7ac65cd7SCédric Le Goater     dc->realize = ir35221_realize;
161*7ac65cd7SCédric Le Goater     device_class_set_legacy_reset(dc, ir35221_reset);
162*7ac65cd7SCédric Le Goater     k->event = ir35221_event;
163*7ac65cd7SCédric Le Goater     k->recv = ir35221_recv;
164*7ac65cd7SCédric Le Goater     k->send = ir35221_send;
165*7ac65cd7SCédric Le Goater     dc->vmsd = &vmstate_ir35221;
166*7ac65cd7SCédric Le Goater }
167*7ac65cd7SCédric Le Goater 
168*7ac65cd7SCédric Le Goater static const TypeInfo ir35221_info = {
169*7ac65cd7SCédric Le Goater     .name          = TYPE_IR35221,
170*7ac65cd7SCédric Le Goater     .parent        = TYPE_I2C_SLAVE,
171*7ac65cd7SCédric Le Goater     .instance_size = sizeof(Ir35221State),
172*7ac65cd7SCédric Le Goater     .class_init    = ir35221_class_init,
173*7ac65cd7SCédric Le Goater };
174*7ac65cd7SCédric Le Goater 
ir35221_register_types(void)175*7ac65cd7SCédric Le Goater static void ir35221_register_types(void)
176*7ac65cd7SCédric Le Goater {
177*7ac65cd7SCédric Le Goater     type_register_static(&ir35221_info);
178*7ac65cd7SCédric Le Goater }
179*7ac65cd7SCédric Le Goater 
180*7ac65cd7SCédric Le Goater type_init(ir35221_register_types)
181