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