xref: /qemu/tests/qtest/pnv-host-i2c-test.c (revision 019fbfa4bcd2d3a835c241295e22ab2b5b56129b)
1 /*
2  * QTest testcase for PowerNV 10 Host I2C Communications
3  *
4  * Copyright (c) 2023, IBM Corporation.
5  *
6  * This work is licensed under the terms of the GNU GPL, version 2 or
7  * later. See the COPYING file in the top-level directory.
8  */
9 #include "qemu/osdep.h"
10 #include "libqtest.h"
11 #include "hw/gpio/pca9554_regs.h"
12 #include "hw/gpio/pca9552_regs.h"
13 #include "pnv-xscom.h"
14 
15 #define PPC_BIT(bit)            (0x8000000000000000ULL >> (bit))
16 #define PPC_BIT32(bit)          (0x80000000 >> (bit))
17 #define PPC_BIT8(bit)           (0x80 >> (bit))
18 #define PPC_BITMASK(bs, be)     ((PPC_BIT(bs) - PPC_BIT(be)) | PPC_BIT(bs))
19 #define PPC_BITMASK32(bs, be)   ((PPC_BIT32(bs) - PPC_BIT32(be)) | \
20                                  PPC_BIT32(bs))
21 
22 #define MASK_TO_LSH(m)          (__builtin_ffsll(m) - 1)
23 #define GETFIELD(m, v)          (((v) & (m)) >> MASK_TO_LSH(m))
24 #define SETFIELD(m, v, val) \
25         (((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m)))
26 
27 #define PNV10_XSCOM_I2CM_BASE   0xa0000
28 #define PNV10_XSCOM_I2CM_SIZE   0x1000
29 
30 #include "hw/i2c/pnv_i2c_regs.h"
31 
32 typedef struct {
33     QTestState    *qts;
34     const PnvChip *chip;
35     int           engine;
36 } PnvI2cCtlr;
37 
38 typedef struct {
39     PnvI2cCtlr  *ctlr;
40     int         port;
41     uint8_t     addr;
42 } PnvI2cDev;
43 
44 
pnv_i2c_xscom_addr(PnvI2cCtlr * ctlr,uint32_t reg)45 static uint64_t pnv_i2c_xscom_addr(PnvI2cCtlr *ctlr, uint32_t reg)
46 {
47     return pnv_xscom_addr(ctlr->chip, PNV10_XSCOM_I2CM_BASE +
48                           (PNV10_XSCOM_I2CM_SIZE * ctlr->engine) + reg);
49 }
50 
pnv_i2c_xscom_read(PnvI2cCtlr * ctlr,uint32_t reg)51 static uint64_t pnv_i2c_xscom_read(PnvI2cCtlr *ctlr, uint32_t reg)
52 {
53     return qtest_readq(ctlr->qts, pnv_i2c_xscom_addr(ctlr, reg));
54 }
55 
pnv_i2c_xscom_write(PnvI2cCtlr * ctlr,uint32_t reg,uint64_t val)56 static void pnv_i2c_xscom_write(PnvI2cCtlr *ctlr, uint32_t reg, uint64_t val)
57 {
58     qtest_writeq(ctlr->qts, pnv_i2c_xscom_addr(ctlr, reg), val);
59 }
60 
61 /* Write len bytes from buf to i2c device with given addr and port */
pnv_i2c_send(PnvI2cDev * dev,const uint8_t * buf,uint16_t len)62 static void pnv_i2c_send(PnvI2cDev *dev, const uint8_t *buf, uint16_t len)
63 {
64     int byte_num;
65     uint64_t reg64;
66 
67     /* select requested port */
68     reg64 = SETFIELD(I2C_MODE_BIT_RATE_DIV, 0ull, 0x2be);
69     reg64 = SETFIELD(I2C_MODE_PORT_NUM, reg64, dev->port);
70     pnv_i2c_xscom_write(dev->ctlr, I2C_MODE_REG, reg64);
71 
72     /* check status for cmd complete and bus idle */
73     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_EXTD_STAT_REG);
74     g_assert_cmphex(reg64 & I2C_EXTD_STAT_I2C_BUSY, ==, 0);
75     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_STAT_REG);
76     g_assert_cmphex(reg64 & (I2C_STAT_ANY_ERR | I2C_STAT_CMD_COMP), ==,
77                     I2C_STAT_CMD_COMP);
78 
79     /* Send start, with stop, with address and len bytes of data */
80     reg64 = I2C_CMD_WITH_START | I2C_CMD_WITH_ADDR | I2C_CMD_WITH_STOP;
81     reg64 = SETFIELD(I2C_CMD_DEV_ADDR, reg64, dev->addr);
82     reg64 = SETFIELD(I2C_CMD_LEN_BYTES, reg64, len);
83     pnv_i2c_xscom_write(dev->ctlr, I2C_CMD_REG, reg64);
84 
85     /* check status for errors */
86     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_STAT_REG);
87     g_assert_cmphex(reg64 & I2C_STAT_ANY_ERR, ==, 0);
88 
89     /* write data bytes to fifo register */
90     for (byte_num = 0; byte_num < len; byte_num++) {
91         reg64 = SETFIELD(I2C_FIFO, 0ull, buf[byte_num]);
92         pnv_i2c_xscom_write(dev->ctlr, I2C_FIFO_REG, reg64);
93     }
94 
95     /* check status for cmd complete and bus idle */
96     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_EXTD_STAT_REG);
97     g_assert_cmphex(reg64 & I2C_EXTD_STAT_I2C_BUSY, ==, 0);
98     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_STAT_REG);
99     g_assert_cmphex(reg64 & (I2C_STAT_ANY_ERR | I2C_STAT_CMD_COMP), ==,
100                     I2C_STAT_CMD_COMP);
101 }
102 
103 /* Recieve len bytes into buf from i2c device with given addr and port */
pnv_i2c_recv(PnvI2cDev * dev,uint8_t * buf,uint16_t len)104 static void pnv_i2c_recv(PnvI2cDev *dev, uint8_t *buf, uint16_t len)
105 {
106     int byte_num;
107     uint64_t reg64;
108 
109     /* select requested port */
110     reg64 = SETFIELD(I2C_MODE_BIT_RATE_DIV, 0ull, 0x2be);
111     reg64 = SETFIELD(I2C_MODE_PORT_NUM, reg64, dev->port);
112     pnv_i2c_xscom_write(dev->ctlr, I2C_MODE_REG, reg64);
113 
114     /* check status for cmd complete and bus idle */
115     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_EXTD_STAT_REG);
116     g_assert_cmphex(reg64 & I2C_EXTD_STAT_I2C_BUSY, ==, 0);
117     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_STAT_REG);
118     g_assert_cmphex(reg64 & (I2C_STAT_ANY_ERR | I2C_STAT_CMD_COMP), ==,
119                     I2C_STAT_CMD_COMP);
120 
121     /* Send start, with stop, with address and len bytes of data */
122     reg64 = I2C_CMD_WITH_START | I2C_CMD_WITH_ADDR |
123             I2C_CMD_WITH_STOP | I2C_CMD_READ_NOT_WRITE;
124     reg64 = SETFIELD(I2C_CMD_DEV_ADDR, reg64, dev->addr);
125     reg64 = SETFIELD(I2C_CMD_LEN_BYTES, reg64, len);
126     pnv_i2c_xscom_write(dev->ctlr, I2C_CMD_REG, reg64);
127 
128     /* check status for errors */
129     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_STAT_REG);
130     g_assert_cmphex(reg64 & I2C_STAT_ANY_ERR, ==, 0);
131 
132     /* Read data bytes from fifo register */
133     for (byte_num = 0; byte_num < len; byte_num++) {
134         reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_FIFO_REG);
135         buf[byte_num] = GETFIELD(I2C_FIFO, reg64);
136     }
137 
138     /* check status for cmd complete and bus idle */
139     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_EXTD_STAT_REG);
140     g_assert_cmphex(reg64 & I2C_EXTD_STAT_I2C_BUSY, ==, 0);
141     reg64 = pnv_i2c_xscom_read(dev->ctlr, I2C_STAT_REG);
142     g_assert_cmphex(reg64 & (I2C_STAT_ANY_ERR | I2C_STAT_CMD_COMP), ==,
143                     I2C_STAT_CMD_COMP);
144 }
145 
pnv_i2c_pca9554_default_cfg(PnvI2cDev * dev)146 static void pnv_i2c_pca9554_default_cfg(PnvI2cDev *dev)
147 {
148     uint8_t buf[2];
149 
150     /* input register bits are not inverted */
151     buf[0] = PCA9554_POLARITY;
152     buf[1] = 0;
153     pnv_i2c_send(dev, buf, 2);
154 
155     /* All pins are inputs */
156     buf[0] = PCA9554_CONFIG;
157     buf[1] = 0xff;
158     pnv_i2c_send(dev, buf, 2);
159 
160     /* Output value for when pins are outputs */
161     buf[0] = PCA9554_OUTPUT;
162     buf[1] = 0xff;
163     pnv_i2c_send(dev, buf, 2);
164 }
165 
pnv_i2c_pca9554_set_pin(PnvI2cDev * dev,int pin,bool high)166 static void pnv_i2c_pca9554_set_pin(PnvI2cDev *dev, int pin, bool high)
167 {
168     uint8_t send_buf[2];
169     uint8_t recv_buf[2];
170     uint8_t mask = 0x1 << pin;
171     uint8_t new_value = ((high) ? 1 : 0) << pin;
172 
173     /* read current OUTPUT value */
174     send_buf[0] = PCA9554_OUTPUT;
175     pnv_i2c_send(dev, send_buf, 1);
176     pnv_i2c_recv(dev, recv_buf, 1);
177 
178     /* write new OUTPUT value */
179     send_buf[1] = (recv_buf[0] & ~mask) | new_value;
180     pnv_i2c_send(dev, send_buf, 2);
181 
182     /* Update config bit for output */
183     send_buf[0] = PCA9554_CONFIG;
184     pnv_i2c_send(dev, send_buf, 1);
185     pnv_i2c_recv(dev, recv_buf, 1);
186     send_buf[1] = recv_buf[0] & ~mask;
187     pnv_i2c_send(dev, send_buf, 2);
188 }
189 
pnv_i2c_pca9554_read_pins(PnvI2cDev * dev)190 static uint8_t pnv_i2c_pca9554_read_pins(PnvI2cDev *dev)
191 {
192     uint8_t send_buf[1];
193     uint8_t recv_buf[1];
194     send_buf[0] = PCA9554_INPUT;
195     pnv_i2c_send(dev, send_buf, 1);
196     pnv_i2c_recv(dev, recv_buf, 1);
197     return recv_buf[0];
198 }
199 
pnv_i2c_pca9554_flip_polarity(PnvI2cDev * dev)200 static void pnv_i2c_pca9554_flip_polarity(PnvI2cDev *dev)
201 {
202     uint8_t recv_buf[1];
203     uint8_t send_buf[2];
204 
205     send_buf[0] = PCA9554_POLARITY;
206     pnv_i2c_send(dev, send_buf, 1);
207     pnv_i2c_recv(dev, recv_buf, 1);
208     send_buf[1] = recv_buf[0] ^ 0xff;
209     pnv_i2c_send(dev, send_buf, 2);
210 }
211 
pnv_i2c_pca9554_default_inputs(PnvI2cDev * dev)212 static void pnv_i2c_pca9554_default_inputs(PnvI2cDev *dev)
213 {
214     uint8_t pin_values = pnv_i2c_pca9554_read_pins(dev);
215     g_assert_cmphex(pin_values, ==, 0xff);
216 }
217 
218 /* Check that setting pin values and polarity changes inputs as expected */
pnv_i2c_pca554_set_pins(PnvI2cDev * dev)219 static void pnv_i2c_pca554_set_pins(PnvI2cDev *dev)
220 {
221     uint8_t pin_values;
222     pnv_i2c_pca9554_set_pin(dev, 0, 0);
223     pin_values = pnv_i2c_pca9554_read_pins(dev);
224     g_assert_cmphex(pin_values, ==, 0xfe);
225     pnv_i2c_pca9554_flip_polarity(dev);
226     pin_values = pnv_i2c_pca9554_read_pins(dev);
227     g_assert_cmphex(pin_values, ==, 0x01);
228     pnv_i2c_pca9554_set_pin(dev, 2, 0);
229     pin_values = pnv_i2c_pca9554_read_pins(dev);
230     g_assert_cmphex(pin_values, ==, 0x05);
231     pnv_i2c_pca9554_flip_polarity(dev);
232     pin_values = pnv_i2c_pca9554_read_pins(dev);
233     g_assert_cmphex(pin_values, ==, 0xfa);
234     pnv_i2c_pca9554_default_cfg(dev);
235     pin_values = pnv_i2c_pca9554_read_pins(dev);
236     g_assert_cmphex(pin_values, ==, 0xff);
237 }
238 
pnv_i2c_pca9552_default_cfg(PnvI2cDev * dev)239 static void pnv_i2c_pca9552_default_cfg(PnvI2cDev *dev)
240 {
241     uint8_t buf[2];
242     /* configure pwm/psc regs */
243     buf[0] = PCA9552_PSC0;
244     buf[1] = 0xff;
245     pnv_i2c_send(dev, buf, 2);
246     buf[0] = PCA9552_PWM0;
247     buf[1] = 0x80;
248     pnv_i2c_send(dev, buf, 2);
249     buf[0] = PCA9552_PSC1;
250     buf[1] = 0xff;
251     pnv_i2c_send(dev, buf, 2);
252     buf[0] = PCA9552_PWM1;
253     buf[1] = 0x80;
254     pnv_i2c_send(dev, buf, 2);
255 
256     /* configure all pins as inputs */
257     buf[0] = PCA9552_LS0;
258     buf[1] = 0x55;
259     pnv_i2c_send(dev, buf, 2);
260     buf[0] = PCA9552_LS1;
261     buf[1] = 0x55;
262     pnv_i2c_send(dev, buf, 2);
263     buf[0] = PCA9552_LS2;
264     buf[1] = 0x55;
265     pnv_i2c_send(dev, buf, 2);
266     buf[0] = PCA9552_LS3;
267     buf[1] = 0x55;
268     pnv_i2c_send(dev, buf, 2);
269 }
270 
pnv_i2c_pca9552_set_pin(PnvI2cDev * dev,int pin,bool high)271 static void pnv_i2c_pca9552_set_pin(PnvI2cDev *dev, int pin, bool high)
272 {
273     uint8_t send_buf[2];
274     uint8_t recv_buf[2];
275     uint8_t reg = PCA9552_LS0 + (pin / 4);
276     uint8_t shift = (pin % 4) * 2;
277     uint8_t mask = ~(0x3 << shift);
278     uint8_t new_value = ((high) ? 1 : 0) << shift;
279 
280     /* read current LSx value */
281     send_buf[0] = reg;
282     pnv_i2c_send(dev, send_buf, 1);
283     pnv_i2c_recv(dev, recv_buf, 1);
284 
285     /* write new value to LSx */
286     send_buf[1] = (recv_buf[0] & mask) | new_value;
287     pnv_i2c_send(dev, send_buf, 2);
288 }
289 
pnv_i2c_pca9552_read_pins(PnvI2cDev * dev)290 static uint16_t pnv_i2c_pca9552_read_pins(PnvI2cDev *dev)
291 {
292     uint8_t send_buf[2];
293     uint8_t recv_buf[2];
294     uint16_t inputs;
295     send_buf[0] = PCA9552_INPUT0;
296     pnv_i2c_send(dev, send_buf, 1);
297     pnv_i2c_recv(dev, recv_buf, 1);
298     inputs = recv_buf[0];
299     send_buf[0] = PCA9552_INPUT1;
300     pnv_i2c_send(dev, send_buf, 1);
301     pnv_i2c_recv(dev, recv_buf, 1);
302     inputs |= recv_buf[0] << 8;
303     return inputs;
304 }
305 
pnv_i2c_pca9552_default_inputs(PnvI2cDev * dev)306 static void pnv_i2c_pca9552_default_inputs(PnvI2cDev *dev)
307 {
308     uint16_t pin_values = pnv_i2c_pca9552_read_pins(dev);
309     g_assert_cmphex(pin_values, ==, 0xffff);
310 }
311 
312 /*
313  * Set pins 0-4 one at a time and verify that pins 5-9 are
314  * set to the same value
315  */
pnv_i2c_pca552_set_pins(PnvI2cDev * dev)316 static void pnv_i2c_pca552_set_pins(PnvI2cDev *dev)
317 {
318     uint16_t pin_values;
319 
320     /* set pin 0 low */
321     pnv_i2c_pca9552_set_pin(dev, 0, 0);
322     pin_values = pnv_i2c_pca9552_read_pins(dev);
323 
324     /* pins 0 and 5 should be low */
325     g_assert_cmphex(pin_values, ==, 0xffde);
326 
327     /* set pin 1 low */
328     pnv_i2c_pca9552_set_pin(dev, 1, 0);
329     pin_values = pnv_i2c_pca9552_read_pins(dev);
330 
331     /* pins 0, 1, 5 and 6 should be low */
332     g_assert_cmphex(pin_values, ==, 0xff9c);
333 
334     /* set pin 2 low */
335     pnv_i2c_pca9552_set_pin(dev, 2, 0);
336     pin_values = pnv_i2c_pca9552_read_pins(dev);
337 
338     /* pins 0, 1, 2, 5, 6 and 7 should be low */
339     g_assert_cmphex(pin_values, ==, 0xff18);
340 
341     /* set pin 3 low */
342     pnv_i2c_pca9552_set_pin(dev, 3, 0);
343     pin_values = pnv_i2c_pca9552_read_pins(dev);
344 
345     /* pins 0, 1, 2, 3, 5, 6, 7 and 8 should be low */
346     g_assert_cmphex(pin_values, ==, 0xfe10);
347 
348     /* set pin 4 low */
349     pnv_i2c_pca9552_set_pin(dev, 4, 0);
350     pin_values = pnv_i2c_pca9552_read_pins(dev);
351 
352     /* pins 0, 1, 2, 3, 5, 6, 7, 8 and 9 should be low */
353     g_assert_cmphex(pin_values, ==, 0xfc00);
354 
355     /* reset all pins to the high state */
356     pnv_i2c_pca9552_default_cfg(dev);
357     pin_values = pnv_i2c_pca9552_read_pins(dev);
358 
359     /* verify all pins went back to the high state */
360     g_assert_cmphex(pin_values, ==, 0xffff);
361 }
362 
reset_engine(PnvI2cCtlr * ctlr)363 static void reset_engine(PnvI2cCtlr *ctlr)
364 {
365     pnv_i2c_xscom_write(ctlr, I2C_RESET_I2C_REG, 0);
366 }
367 
check_i2cm_por_regs(QTestState * qts,const PnvChip * chip)368 static void check_i2cm_por_regs(QTestState *qts, const PnvChip *chip)
369 {
370     int engine;
371     for (engine = 0; engine < chip->num_i2c; engine++) {
372         PnvI2cCtlr ctlr;
373         ctlr.qts = qts;
374         ctlr.chip = chip;
375         ctlr.engine = engine;
376 
377         /* Check version in Extended Status Register */
378         uint64_t value = pnv_i2c_xscom_read(&ctlr, I2C_EXTD_STAT_REG);
379         g_assert_cmphex(value & I2C_EXTD_STAT_I2C_VERSION, ==, 0x1700000000);
380 
381         /* Check for command complete and bus idle in Status Register */
382         value = pnv_i2c_xscom_read(&ctlr, I2C_STAT_REG);
383         g_assert_cmphex(value & (I2C_STAT_ANY_ERR | I2C_STAT_CMD_COMP),
384                         ==,
385                         I2C_STAT_CMD_COMP);
386     }
387 }
388 
reset_all(QTestState * qts,const PnvChip * chip)389 static void reset_all(QTestState *qts, const PnvChip *chip)
390 {
391     int engine;
392     for (engine = 0; engine < chip->num_i2c; engine++) {
393         PnvI2cCtlr ctlr;
394         ctlr.qts = qts;
395         ctlr.chip = chip;
396         ctlr.engine = engine;
397         reset_engine(&ctlr);
398         pnv_i2c_xscom_write(&ctlr, I2C_MODE_REG, 0x02be040000000000);
399     }
400 }
401 
test_host_i2c(const void * data)402 static void test_host_i2c(const void *data)
403 {
404     const PnvChip *chip = data;
405     QTestState *qts;
406     const char *machine = "powernv8";
407     PnvI2cCtlr ctlr;
408     PnvI2cDev pca9552;
409     PnvI2cDev pca9554;
410 
411     if (chip->chip_type == PNV_CHIP_POWER9) {
412         machine = "powernv9";
413     } else if (chip->chip_type == PNV_CHIP_POWER10) {
414         machine = "powernv10-rainier";
415     }
416 
417     qts = qtest_initf("-M %s -smp %d,cores=1,threads=%d -nographic "
418                       "-nodefaults -serial mon:stdio -S "
419                       "-d guest_errors",
420                       machine, SMT, SMT);
421 
422     /* Check the I2C master status registers after POR */
423     check_i2cm_por_regs(qts, chip);
424 
425     /* Now do a forced "immediate" reset on all engines */
426     reset_all(qts, chip);
427 
428     /* Check that the status values are still good */
429     check_i2cm_por_regs(qts, chip);
430 
431     /* P9 doesn't have any i2c devices attached at this time */
432     if (chip->chip_type != PNV_CHIP_POWER10) {
433         qtest_quit(qts);
434         return;
435     }
436 
437     /* Initialize for a P10 pca9552 hotplug device */
438     ctlr.qts = qts;
439     ctlr.chip = chip;
440     ctlr.engine = 2;
441     pca9552.ctlr = &ctlr;
442     pca9552.port = 1;
443     pca9552.addr = 0x63;
444 
445     /* Set all pca9552 pins as inputs */
446     pnv_i2c_pca9552_default_cfg(&pca9552);
447 
448     /* Check that all pins of the pca9552 are high */
449     pnv_i2c_pca9552_default_inputs(&pca9552);
450 
451     /* perform individual pin tests */
452     pnv_i2c_pca552_set_pins(&pca9552);
453 
454     /* Initialize for a P10 pca9554 CableCard Presence detection device */
455     pca9554.ctlr = &ctlr;
456     pca9554.port = 1;
457     pca9554.addr = 0x25;
458 
459     /* Set all pca9554 pins as inputs */
460     pnv_i2c_pca9554_default_cfg(&pca9554);
461 
462     /* Check that all pins of the pca9554 are high */
463     pnv_i2c_pca9554_default_inputs(&pca9554);
464 
465     /* perform individual pin tests */
466     pnv_i2c_pca554_set_pins(&pca9554);
467 
468     qtest_quit(qts);
469 }
470 
add_test(const char * name,void (* test)(const void * data))471 static void add_test(const char *name, void (*test)(const void *data))
472 {
473     int i;
474 
475     for (i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
476         char *tname = g_strdup_printf("pnv-xscom/%s/%s", name,
477                                       pnv_chips[i].cpu_model);
478         qtest_add_data_func(tname, &pnv_chips[i], test);
479         g_free(tname);
480     }
481 }
482 
main(int argc,char ** argv)483 int main(int argc, char **argv)
484 {
485     g_test_init(&argc, &argv, NULL);
486 
487     add_test("host-i2c", test_host_i2c);
488     return g_test_run();
489 }
490