]>
Commit | Line | Data |
---|---|---|
4d2cd2d8 GM |
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" | |
6328d8ff CLG |
11 | #include "hw/gpio/pca9554_regs.h" |
12 | #include "hw/gpio/pca9552_regs.h" | |
4d2cd2d8 GM |
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 | } |