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