xref: /qemu/tests/qtest/pnv-host-i2c-test.c (revision d884e272)
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/misc/pca9554_regs.h"
12 #include "hw/misc/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 
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 
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 
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 */
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 */
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 
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 
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 
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     uint8_t inputs;
195     send_buf[0] = PCA9554_INPUT;
196     pnv_i2c_send(dev, send_buf, 1);
197     pnv_i2c_recv(dev, recv_buf, 1);
198     inputs = recv_buf[0];
199     return inputs;
200 }
201 
202 static void pnv_i2c_pca9554_flip_polarity(PnvI2cDev *dev)
203 {
204     uint8_t recv_buf[1];
205     uint8_t send_buf[2];
206 
207     send_buf[0] = PCA9554_POLARITY;
208     pnv_i2c_send(dev, send_buf, 1);
209     pnv_i2c_recv(dev, recv_buf, 1);
210     send_buf[1] = recv_buf[0] ^ 0xff;
211     pnv_i2c_send(dev, send_buf, 2);
212 }
213 
214 static void pnv_i2c_pca9554_default_inputs(PnvI2cDev *dev)
215 {
216     uint8_t pin_values = pnv_i2c_pca9554_read_pins(dev);
217     g_assert_cmphex(pin_values, ==, 0xff);
218 }
219 
220 /* Check that setting pin values and polarity changes inputs as expected */
221 static void pnv_i2c_pca554_set_pins(PnvI2cDev *dev)
222 {
223     uint8_t pin_values;
224     pnv_i2c_pca9554_set_pin(dev, 0, 0);
225     pin_values = pnv_i2c_pca9554_read_pins(dev);
226     g_assert_cmphex(pin_values, ==, 0xfe);
227     pnv_i2c_pca9554_flip_polarity(dev);
228     pin_values = pnv_i2c_pca9554_read_pins(dev);
229     g_assert_cmphex(pin_values, ==, 0x01);
230     pnv_i2c_pca9554_set_pin(dev, 2, 0);
231     pin_values = pnv_i2c_pca9554_read_pins(dev);
232     g_assert_cmphex(pin_values, ==, 0x05);
233     pnv_i2c_pca9554_flip_polarity(dev);
234     pin_values = pnv_i2c_pca9554_read_pins(dev);
235     g_assert_cmphex(pin_values, ==, 0xfa);
236     pnv_i2c_pca9554_default_cfg(dev);
237     pin_values = pnv_i2c_pca9554_read_pins(dev);
238     g_assert_cmphex(pin_values, ==, 0xff);
239 }
240 
241 static void pnv_i2c_pca9552_default_cfg(PnvI2cDev *dev)
242 {
243     uint8_t buf[2];
244     /* configure pwm/psc regs */
245     buf[0] = PCA9552_PSC0;
246     buf[1] = 0xff;
247     pnv_i2c_send(dev, buf, 2);
248     buf[0] = PCA9552_PWM0;
249     buf[1] = 0x80;
250     pnv_i2c_send(dev, buf, 2);
251     buf[0] = PCA9552_PSC1;
252     buf[1] = 0xff;
253     pnv_i2c_send(dev, buf, 2);
254     buf[0] = PCA9552_PWM1;
255     buf[1] = 0x80;
256     pnv_i2c_send(dev, buf, 2);
257 
258     /* configure all pins as inputs */
259     buf[0] = PCA9552_LS0;
260     buf[1] = 0x55;
261     pnv_i2c_send(dev, buf, 2);
262     buf[0] = PCA9552_LS1;
263     buf[1] = 0x55;
264     pnv_i2c_send(dev, buf, 2);
265     buf[0] = PCA9552_LS2;
266     buf[1] = 0x55;
267     pnv_i2c_send(dev, buf, 2);
268     buf[0] = PCA9552_LS3;
269     buf[1] = 0x55;
270     pnv_i2c_send(dev, buf, 2);
271 }
272 
273 static void pnv_i2c_pca9552_set_pin(PnvI2cDev *dev, int pin, bool high)
274 {
275     uint8_t send_buf[2];
276     uint8_t recv_buf[2];
277     uint8_t reg = PCA9552_LS0 + (pin / 4);
278     uint8_t shift = (pin % 4) * 2;
279     uint8_t mask = ~(0x3 << shift);
280     uint8_t new_value = ((high) ? 1 : 0) << shift;
281 
282     /* read current LSx value */
283     send_buf[0] = reg;
284     pnv_i2c_send(dev, send_buf, 1);
285     pnv_i2c_recv(dev, recv_buf, 1);
286 
287     /* write new value to LSx */
288     send_buf[1] = (recv_buf[0] & mask) | new_value;
289     pnv_i2c_send(dev, send_buf, 2);
290 }
291 
292 static uint16_t pnv_i2c_pca9552_read_pins(PnvI2cDev *dev)
293 {
294     uint8_t send_buf[2];
295     uint8_t recv_buf[2];
296     uint16_t inputs;
297     send_buf[0] = PCA9552_INPUT0;
298     pnv_i2c_send(dev, send_buf, 1);
299     pnv_i2c_recv(dev, recv_buf, 1);
300     inputs = recv_buf[0];
301     send_buf[0] = PCA9552_INPUT1;
302     pnv_i2c_send(dev, send_buf, 1);
303     pnv_i2c_recv(dev, recv_buf, 1);
304     inputs |= recv_buf[0] << 8;
305     return inputs;
306 }
307 
308 static void pnv_i2c_pca9552_default_inputs(PnvI2cDev *dev)
309 {
310     uint16_t pin_values = pnv_i2c_pca9552_read_pins(dev);
311     g_assert_cmphex(pin_values, ==, 0xffff);
312 }
313 
314 /*
315  * Set pins 0-4 one at a time and verify that pins 5-9 are
316  * set to the same value
317  */
318 static void pnv_i2c_pca552_set_pins(PnvI2cDev *dev)
319 {
320     uint16_t pin_values;
321 
322     /* set pin 0 low */
323     pnv_i2c_pca9552_set_pin(dev, 0, 0);
324     pin_values = pnv_i2c_pca9552_read_pins(dev);
325 
326     /* pins 0 and 5 should be low */
327     g_assert_cmphex(pin_values, ==, 0xffde);
328 
329     /* set pin 1 low */
330     pnv_i2c_pca9552_set_pin(dev, 1, 0);
331     pin_values = pnv_i2c_pca9552_read_pins(dev);
332 
333     /* pins 0, 1, 5 and 6 should be low */
334     g_assert_cmphex(pin_values, ==, 0xff9c);
335 
336     /* set pin 2 low */
337     pnv_i2c_pca9552_set_pin(dev, 2, 0);
338     pin_values = pnv_i2c_pca9552_read_pins(dev);
339 
340     /* pins 0, 1, 2, 5, 6 and 7 should be low */
341     g_assert_cmphex(pin_values, ==, 0xff18);
342 
343     /* set pin 3 low */
344     pnv_i2c_pca9552_set_pin(dev, 3, 0);
345     pin_values = pnv_i2c_pca9552_read_pins(dev);
346 
347     /* pins 0, 1, 2, 3, 5, 6, 7 and 8 should be low */
348     g_assert_cmphex(pin_values, ==, 0xfe10);
349 
350     /* set pin 4 low */
351     pnv_i2c_pca9552_set_pin(dev, 4, 0);
352     pin_values = pnv_i2c_pca9552_read_pins(dev);
353 
354     /* pins 0, 1, 2, 3, 5, 6, 7, 8 and 9 should be low */
355     g_assert_cmphex(pin_values, ==, 0xfc00);
356 
357     /* reset all pins to the high state */
358     pnv_i2c_pca9552_default_cfg(dev);
359     pin_values = pnv_i2c_pca9552_read_pins(dev);
360 
361     /* verify all pins went back to the high state */
362     g_assert_cmphex(pin_values, ==, 0xffff);
363 }
364 
365 static void reset_engine(PnvI2cCtlr *ctlr)
366 {
367     pnv_i2c_xscom_write(ctlr, I2C_RESET_I2C_REG, 0);
368 }
369 
370 static void check_i2cm_por_regs(QTestState *qts, const PnvChip *chip)
371 {
372     int engine;
373     for (engine = 0; engine < chip->num_i2c; engine++) {
374         PnvI2cCtlr ctlr;
375         ctlr.qts = qts;
376         ctlr.chip = chip;
377         ctlr.engine = engine;
378 
379         /* Check version in Extended Status Register */
380         uint64_t value = pnv_i2c_xscom_read(&ctlr, I2C_EXTD_STAT_REG);
381         g_assert_cmphex(value & I2C_EXTD_STAT_I2C_VERSION, ==, 0x1700000000);
382 
383         /* Check for command complete and bus idle in Status Register */
384         value = pnv_i2c_xscom_read(&ctlr, I2C_STAT_REG);
385         g_assert_cmphex(value & (I2C_STAT_ANY_ERR | I2C_STAT_CMD_COMP),
386                         ==,
387                         I2C_STAT_CMD_COMP);
388     }
389 }
390 
391 static void reset_all(QTestState *qts, const PnvChip *chip)
392 {
393     int engine;
394     for (engine = 0; engine < chip->num_i2c; engine++) {
395         PnvI2cCtlr ctlr;
396         ctlr.qts = qts;
397         ctlr.chip = chip;
398         ctlr.engine = engine;
399         reset_engine(&ctlr);
400         pnv_i2c_xscom_write(&ctlr, I2C_MODE_REG, 0x02be040000000000);
401     }
402 }
403 
404 static void test_host_i2c(const void *data)
405 {
406     const PnvChip *chip = data;
407     QTestState *qts;
408     const char *machine = "powernv8";
409     PnvI2cCtlr ctlr;
410     PnvI2cDev pca9552;
411     PnvI2cDev pca9554;
412 
413     if (chip->chip_type == PNV_CHIP_POWER9) {
414         machine = "powernv9";
415     } else if (chip->chip_type == PNV_CHIP_POWER10) {
416         machine = "powernv10-rainier";
417     }
418 
419     qts = qtest_initf("-M %s -smp %d,cores=1,threads=%d -nographic "
420                       "-nodefaults -serial mon:stdio -S "
421                       "-d guest_errors",
422                       machine, SMT, SMT);
423 
424     /* Check the I2C master status registers after POR */
425     check_i2cm_por_regs(qts, chip);
426 
427     /* Now do a forced "immediate" reset on all engines */
428     reset_all(qts, chip);
429 
430     /* Check that the status values are still good */
431     check_i2cm_por_regs(qts, chip);
432 
433     /* P9 doesn't have any i2c devices attached at this time */
434     if (chip->chip_type != PNV_CHIP_POWER10) {
435         qtest_quit(qts);
436         return;
437     }
438 
439     /* Initialize for a P10 pca9552 hotplug device */
440     ctlr.qts = qts;
441     ctlr.chip = chip;
442     ctlr.engine = 2;
443     pca9552.ctlr = &ctlr;
444     pca9552.port = 1;
445     pca9552.addr = 0x63;
446 
447     /* Set all pca9552 pins as inputs */
448     pnv_i2c_pca9552_default_cfg(&pca9552);
449 
450     /* Check that all pins of the pca9552 are high */
451     pnv_i2c_pca9552_default_inputs(&pca9552);
452 
453     /* perform individual pin tests */
454     pnv_i2c_pca552_set_pins(&pca9552);
455 
456     /* Initialize for a P10 pca9554 CableCard Presence detection device */
457     pca9554.ctlr = &ctlr;
458     pca9554.port = 1;
459     pca9554.addr = 0x25;
460 
461     /* Set all pca9554 pins as inputs */
462     pnv_i2c_pca9554_default_cfg(&pca9554);
463 
464     /* Check that all pins of the pca9554 are high */
465     pnv_i2c_pca9554_default_inputs(&pca9554);
466 
467     /* perform individual pin tests */
468     pnv_i2c_pca554_set_pins(&pca9554);
469 
470     qtest_quit(qts);
471 }
472 
473 static void add_test(const char *name, void (*test)(const void *data))
474 {
475     int i;
476 
477     for (i = 0; i < ARRAY_SIZE(pnv_chips); i++) {
478         char *tname = g_strdup_printf("pnv-xscom/%s/%s", name,
479                                       pnv_chips[i].cpu_model);
480         qtest_add_data_func(tname, &pnv_chips[i], test);
481         g_free(tname);
482     }
483 }
484 
485 int main(int argc, char **argv)
486 {
487     g_test_init(&argc, &argv, NULL);
488 
489     add_test("host-i2c", test_host_i2c);
490     return g_test_run();
491 }
492