2 * QTests for Nuvoton NPCM7xx SMBus Modules.
4 * Copyright 2020 Google LLC
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 #include "qemu/osdep.h"
18 #include "qemu/bitops.h"
19 #include "libqos/i2c.h"
21 #include "hw/sensor/tmp105_regs.h"
23 #define NR_SMBUS_DEVICES 16
24 #define SMBUS_ADDR(x) (0xf0080000 + 0x1000 * (x))
25 #define SMBUS_IRQ(x) (64 + (x))
27 #define EVB_DEVICE_ADDR 0x48
28 #define INVALID_DEVICE_ADDR 0x01
30 const int evb_bus_list
[] = {0, 1, 2, 6};
46 enum NPCM7xxSMBusBank0Register
{
58 OFFSET_FIF_CTL
= 0x1d,
62 enum NPCM7xxSMBusBank1Register
{
63 OFFSET_FIF_CTS
= 0x10,
64 OFFSET_FAIR_PER
= 0x11,
65 OFFSET_TXF_CTL
= 0x12,
67 OFFSET_TXF_STS
= 0x1a,
68 OFFSET_RXF_STS
= 0x1c,
69 OFFSET_RXF_CTL
= 0x1e,
74 #define ST_SDAST BIT(6)
76 #define ST_NEGACK BIT(4)
77 #define ST_STASTR BIT(3)
78 #define ST_NMATCH BIT(2)
79 #define ST_MODE BIT(1)
80 #define ST_XMIT BIT(0)
83 #define CST_ARPMATCH BIT(7)
84 #define CST_MATCHAF BIT(6)
85 #define CST_TGSCL BIT(5)
86 #define CST_TSDA BIT(4)
87 #define CST_GCMATCH BIT(3)
88 #define CST_MATCH BIT(2)
90 #define CST_BUSY BIT(0)
93 #define CST2_INSTTS BIT(7)
94 #define CST2_MATCH7F BIT(6)
95 #define CST2_MATCH6F BIT(5)
96 #define CST2_MATCH5F BIT(4)
97 #define CST2_MATCH4F BIT(3)
98 #define CST2_MATCH3F BIT(2)
99 #define CST2_MATCH2F BIT(1)
100 #define CST2_MATCH1F BIT(0)
103 #define CST3_EO_BUSY BIT(7)
104 #define CST3_MATCH10F BIT(2)
105 #define CST3_MATCH9F BIT(1)
106 #define CST3_MATCH8F BIT(0)
109 #define CTL1_STASTRE BIT(7)
110 #define CTL1_NMINTE BIT(6)
111 #define CTL1_GCMEN BIT(5)
112 #define CTL1_ACK BIT(4)
113 #define CTL1_EOBINTE BIT(3)
114 #define CTL1_INTEN BIT(2)
115 #define CTL1_STOP BIT(1)
116 #define CTL1_START BIT(0)
119 #define CTL2_SCLFRQ(rv) extract8((rv), 1, 6)
120 #define CTL2_ENABLE BIT(0)
123 #define CTL3_SCL_LVL BIT(7)
124 #define CTL3_SDA_LVL BIT(6)
125 #define CTL3_BNK_SEL BIT(5)
126 #define CTL3_400K_MODE BIT(4)
127 #define CTL3_IDL_START BIT(3)
128 #define CTL3_ARPMEN BIT(2)
129 #define CTL3_SCLFRQ(rv) extract8((rv), 0, 2)
132 #define ADDR_EN BIT(7)
133 #define ADDR_A(rv) extract8((rv), 0, 6)
136 #define FIF_CTL_FIFO_EN BIT(4)
139 #define FIF_CTS_CLR_FIFO BIT(6)
140 #define FIF_CTS_RFTE_IE BIT(3)
141 #define FIF_CTS_RXF_TXE BIT(1)
144 #define TXF_CTL_THR_TXIE BIT(6)
145 #define TXF_CTL_TX_THR(rv) extract8((rv), 0, 5)
148 #define TXF_STS_TX_THST BIT(6)
149 #define TXF_STS_TX_BYTES(rv) extract8((rv), 0, 5)
152 #define RXF_CTL_THR_RXIE BIT(6)
153 #define RXF_CTL_LAST BIT(5)
154 #define RXF_CTL_RX_THR(rv) extract8((rv), 0, 5)
157 #define RXF_STS_RX_THST BIT(6)
158 #define RXF_STS_RX_BYTES(rv) extract8((rv), 0, 5)
161 static void choose_bank(QTestState
*qts
, uint64_t base_addr
, uint8_t bank
)
163 uint8_t ctl3
= qtest_readb(qts
, base_addr
+ OFFSET_CTL3
);
166 ctl3
|= CTL3_BNK_SEL
;
168 ctl3
&= ~CTL3_BNK_SEL
;
171 qtest_writeb(qts
, base_addr
+ OFFSET_CTL3
, ctl3
);
174 static void check_running(QTestState
*qts
, uint64_t base_addr
)
176 g_assert_true(qtest_readb(qts
, base_addr
+ OFFSET_CST
) & CST_BUSY
);
177 g_assert_true(qtest_readb(qts
, base_addr
+ OFFSET_CST
) & CST_BB
);
180 static void check_stopped(QTestState
*qts
, uint64_t base_addr
)
184 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_ST
), ==, 0);
185 g_assert_false(qtest_readb(qts
, base_addr
+ OFFSET_CST
) & CST_BUSY
);
186 g_assert_false(qtest_readb(qts
, base_addr
+ OFFSET_CST
) & CST_BB
);
188 cst3
= qtest_readb(qts
, base_addr
+ OFFSET_CST3
);
189 g_assert_true(cst3
& CST3_EO_BUSY
);
190 qtest_writeb(qts
, base_addr
+ OFFSET_CST3
, cst3
);
191 cst3
= qtest_readb(qts
, base_addr
+ OFFSET_CST3
);
192 g_assert_false(cst3
& CST3_EO_BUSY
);
195 static void enable_bus(QTestState
*qts
, uint64_t base_addr
)
197 uint8_t ctl2
= qtest_readb(qts
, base_addr
+ OFFSET_CTL2
);
200 qtest_writeb(qts
, base_addr
+ OFFSET_CTL2
, ctl2
);
201 g_assert_true(qtest_readb(qts
, base_addr
+ OFFSET_CTL2
) & CTL2_ENABLE
);
204 static void disable_bus(QTestState
*qts
, uint64_t base_addr
)
206 uint8_t ctl2
= qtest_readb(qts
, base_addr
+ OFFSET_CTL2
);
208 ctl2
&= ~CTL2_ENABLE
;
209 qtest_writeb(qts
, base_addr
+ OFFSET_CTL2
, ctl2
);
210 g_assert_false(qtest_readb(qts
, base_addr
+ OFFSET_CTL2
) & CTL2_ENABLE
);
213 static void start_transfer(QTestState
*qts
, uint64_t base_addr
)
217 ctl1
= CTL1_START
| CTL1_INTEN
| CTL1_STASTRE
;
218 qtest_writeb(qts
, base_addr
+ OFFSET_CTL1
, ctl1
);
219 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_CTL1
), ==,
220 CTL1_INTEN
| CTL1_STASTRE
| CTL1_INTEN
);
221 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_ST
), ==,
222 ST_MODE
| ST_XMIT
| ST_SDAST
);
223 check_running(qts
, base_addr
);
226 static void stop_transfer(QTestState
*qts
, uint64_t base_addr
)
228 uint8_t ctl1
= qtest_readb(qts
, base_addr
+ OFFSET_CTL1
);
230 ctl1
&= ~(CTL1_START
| CTL1_ACK
);
231 ctl1
|= CTL1_STOP
| CTL1_INTEN
| CTL1_EOBINTE
;
232 qtest_writeb(qts
, base_addr
+ OFFSET_CTL1
, ctl1
);
233 ctl1
= qtest_readb(qts
, base_addr
+ OFFSET_CTL1
);
234 g_assert_false(ctl1
& CTL1_STOP
);
237 static void send_byte(QTestState
*qts
, uint64_t base_addr
, uint8_t byte
)
239 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_ST
), ==,
240 ST_MODE
| ST_XMIT
| ST_SDAST
);
241 qtest_writeb(qts
, base_addr
+ OFFSET_SDA
, byte
);
244 static bool check_recv(QTestState
*qts
, uint64_t base_addr
)
246 uint8_t st
, fif_ctl
, rxf_ctl
, rxf_sts
;
249 st
= qtest_readb(qts
, base_addr
+ OFFSET_ST
);
250 choose_bank(qts
, base_addr
, 0);
251 fif_ctl
= qtest_readb(qts
, base_addr
+ OFFSET_FIF_CTL
);
252 fifo
= fif_ctl
& FIF_CTL_FIFO_EN
;
254 return st
== (ST_MODE
| ST_SDAST
);
257 choose_bank(qts
, base_addr
, 1);
258 rxf_ctl
= qtest_readb(qts
, base_addr
+ OFFSET_RXF_CTL
);
259 rxf_sts
= qtest_readb(qts
, base_addr
+ OFFSET_RXF_STS
);
261 if ((rxf_ctl
& RXF_CTL_THR_RXIE
) && RXF_STS_RX_BYTES(rxf_sts
) < 16) {
262 return st
== ST_MODE
;
264 return st
== (ST_MODE
| ST_SDAST
);
268 static uint8_t recv_byte(QTestState
*qts
, uint64_t base_addr
)
270 g_assert_true(check_recv(qts
, base_addr
));
271 return qtest_readb(qts
, base_addr
+ OFFSET_SDA
);
274 static void send_address(QTestState
*qts
, uint64_t base_addr
, uint8_t addr
,
275 bool recv
, bool valid
)
277 uint8_t encoded_addr
= (addr
<< 1) | (recv
? 1 : 0);
280 qtest_writeb(qts
, base_addr
+ OFFSET_SDA
, encoded_addr
);
281 st
= qtest_readb(qts
, base_addr
+ OFFSET_ST
);
285 g_assert_cmphex(st
, ==, ST_MODE
| ST_SDAST
| ST_STASTR
);
287 g_assert_cmphex(st
, ==, ST_MODE
| ST_XMIT
| ST_SDAST
| ST_STASTR
);
290 qtest_writeb(qts
, base_addr
+ OFFSET_ST
, ST_STASTR
);
291 st
= qtest_readb(qts
, base_addr
+ OFFSET_ST
);
293 g_assert_true(check_recv(qts
, base_addr
));
295 g_assert_cmphex(st
, ==, ST_MODE
| ST_XMIT
| ST_SDAST
);
299 g_assert_cmphex(st
, ==, ST_MODE
| ST_NEGACK
);
301 g_assert_cmphex(st
, ==, ST_MODE
| ST_XMIT
| ST_NEGACK
);
306 static void send_nack(QTestState
*qts
, uint64_t base_addr
)
308 uint8_t ctl1
= qtest_readb(qts
, base_addr
+ OFFSET_CTL1
);
310 ctl1
&= ~(CTL1_START
| CTL1_STOP
);
311 ctl1
|= CTL1_ACK
| CTL1_INTEN
;
312 qtest_writeb(qts
, base_addr
+ OFFSET_CTL1
, ctl1
);
315 static void start_fifo_mode(QTestState
*qts
, uint64_t base_addr
)
317 choose_bank(qts
, base_addr
, 0);
318 qtest_writeb(qts
, base_addr
+ OFFSET_FIF_CTL
, FIF_CTL_FIFO_EN
);
319 g_assert_true(qtest_readb(qts
, base_addr
+ OFFSET_FIF_CTL
) &
321 choose_bank(qts
, base_addr
, 1);
322 qtest_writeb(qts
, base_addr
+ OFFSET_FIF_CTS
,
323 FIF_CTS_CLR_FIFO
| FIF_CTS_RFTE_IE
);
324 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_FIF_CTS
), ==,
326 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_TXF_STS
), ==, 0);
327 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_RXF_STS
), ==, 0);
330 static void start_recv_fifo(QTestState
*qts
, uint64_t base_addr
, uint8_t bytes
)
332 choose_bank(qts
, base_addr
, 1);
333 qtest_writeb(qts
, base_addr
+ OFFSET_TXF_CTL
, 0);
334 qtest_writeb(qts
, base_addr
+ OFFSET_RXF_CTL
,
335 RXF_CTL_THR_RXIE
| RXF_CTL_LAST
| bytes
);
338 /* Check the SMBus's status is set correctly when disabled. */
339 static void test_disable_bus(gconstpointer data
)
341 intptr_t index
= (intptr_t)data
;
342 uint64_t base_addr
= SMBUS_ADDR(index
);
343 QTestState
*qts
= qtest_init("-machine npcm750-evb");
345 disable_bus(qts
, base_addr
);
346 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_CTL1
), ==, 0);
347 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_ST
), ==, 0);
348 g_assert_false(qtest_readb(qts
, base_addr
+ OFFSET_CST3
) & CST3_EO_BUSY
);
349 g_assert_cmphex(qtest_readb(qts
, base_addr
+ OFFSET_CST
), ==, 0);
353 /* Check the SMBus returns a NACK for an invalid address. */
354 static void test_invalid_addr(gconstpointer data
)
356 intptr_t index
= (intptr_t)data
;
357 uint64_t base_addr
= SMBUS_ADDR(index
);
358 int irq
= SMBUS_IRQ(index
);
359 QTestState
*qts
= qtest_init("-machine npcm750-evb");
361 qtest_irq_intercept_in(qts
, "/machine/soc/a9mpcore/gic");
362 enable_bus(qts
, base_addr
);
363 g_assert_false(qtest_get_irq(qts
, irq
));
364 start_transfer(qts
, base_addr
);
365 send_address(qts
, base_addr
, INVALID_DEVICE_ADDR
, false, false);
366 g_assert_true(qtest_get_irq(qts
, irq
));
367 stop_transfer(qts
, base_addr
);
368 check_running(qts
, base_addr
);
369 qtest_writeb(qts
, base_addr
+ OFFSET_ST
, ST_NEGACK
);
370 g_assert_false(qtest_readb(qts
, base_addr
+ OFFSET_ST
) & ST_NEGACK
);
371 check_stopped(qts
, base_addr
);
375 /* Check the SMBus can send and receive bytes to a device in single mode. */
376 static void test_single_mode(gconstpointer data
)
378 intptr_t index
= (intptr_t)data
;
379 uint64_t base_addr
= SMBUS_ADDR(index
);
380 int irq
= SMBUS_IRQ(index
);
381 uint8_t value
= 0x60;
382 QTestState
*qts
= qtest_init("-machine npcm750-evb");
384 qtest_irq_intercept_in(qts
, "/machine/soc/a9mpcore/gic");
385 enable_bus(qts
, base_addr
);
388 g_assert_false(qtest_get_irq(qts
, irq
));
389 start_transfer(qts
, base_addr
);
390 g_assert_true(qtest_get_irq(qts
, irq
));
391 send_address(qts
, base_addr
, EVB_DEVICE_ADDR
, false, true);
392 send_byte(qts
, base_addr
, TMP105_REG_CONFIG
);
393 send_byte(qts
, base_addr
, value
);
394 stop_transfer(qts
, base_addr
);
395 check_stopped(qts
, base_addr
);
398 start_transfer(qts
, base_addr
);
399 send_address(qts
, base_addr
, EVB_DEVICE_ADDR
, false, true);
400 send_byte(qts
, base_addr
, TMP105_REG_CONFIG
);
401 start_transfer(qts
, base_addr
);
402 send_address(qts
, base_addr
, EVB_DEVICE_ADDR
, true, true);
403 send_nack(qts
, base_addr
);
404 stop_transfer(qts
, base_addr
);
405 check_running(qts
, base_addr
);
406 g_assert_cmphex(recv_byte(qts
, base_addr
), ==, value
);
407 check_stopped(qts
, base_addr
);
411 /* Check the SMBus can send and receive bytes in FIFO mode. */
412 static void test_fifo_mode(gconstpointer data
)
414 intptr_t index
= (intptr_t)data
;
415 uint64_t base_addr
= SMBUS_ADDR(index
);
416 int irq
= SMBUS_IRQ(index
);
417 uint8_t value
= 0x60;
418 QTestState
*qts
= qtest_init("-machine npcm750-evb");
420 qtest_irq_intercept_in(qts
, "/machine/soc/a9mpcore/gic");
421 enable_bus(qts
, base_addr
);
422 start_fifo_mode(qts
, base_addr
);
423 g_assert_false(qtest_get_irq(qts
, irq
));
426 start_transfer(qts
, base_addr
);
427 send_address(qts
, base_addr
, EVB_DEVICE_ADDR
, false, true);
428 choose_bank(qts
, base_addr
, 1);
429 g_assert_true(qtest_readb(qts
, base_addr
+ OFFSET_FIF_CTS
) &
431 qtest_writeb(qts
, base_addr
+ OFFSET_TXF_CTL
, TXF_CTL_THR_TXIE
);
432 send_byte(qts
, base_addr
, TMP105_REG_CONFIG
);
433 send_byte(qts
, base_addr
, value
);
434 g_assert_true(qtest_readb(qts
, base_addr
+ OFFSET_FIF_CTS
) &
436 g_assert_true(qtest_readb(qts
, base_addr
+ OFFSET_TXF_STS
) &
438 g_assert_cmpuint(TXF_STS_TX_BYTES(
439 qtest_readb(qts
, base_addr
+ OFFSET_TXF_STS
)), ==, 0);
440 g_assert_true(qtest_get_irq(qts
, irq
));
441 stop_transfer(qts
, base_addr
);
442 check_stopped(qts
, base_addr
);
445 start_fifo_mode(qts
, base_addr
);
446 start_transfer(qts
, base_addr
);
447 send_address(qts
, base_addr
, EVB_DEVICE_ADDR
, false, true);
448 send_byte(qts
, base_addr
, TMP105_REG_CONFIG
);
449 start_transfer(qts
, base_addr
);
450 qtest_writeb(qts
, base_addr
+ OFFSET_FIF_CTS
, FIF_CTS_RXF_TXE
);
451 start_recv_fifo(qts
, base_addr
, 1);
452 send_address(qts
, base_addr
, EVB_DEVICE_ADDR
, true, true);
453 g_assert_false(qtest_readb(qts
, base_addr
+ OFFSET_FIF_CTS
) &
455 g_assert_true(qtest_readb(qts
, base_addr
+ OFFSET_RXF_STS
) &
457 g_assert_cmpuint(RXF_STS_RX_BYTES(
458 qtest_readb(qts
, base_addr
+ OFFSET_RXF_STS
)), ==, 1);
459 send_nack(qts
, base_addr
);
460 stop_transfer(qts
, base_addr
);
461 check_running(qts
, base_addr
);
462 g_assert_cmphex(recv_byte(qts
, base_addr
), ==, value
);
463 g_assert_cmpuint(RXF_STS_RX_BYTES(
464 qtest_readb(qts
, base_addr
+ OFFSET_RXF_STS
)), ==, 0);
465 check_stopped(qts
, base_addr
);
469 static void smbus_add_test(const char *name
, int index
, GTestDataFunc fn
)
471 g_autofree
char *full_name
= g_strdup_printf(
472 "npcm7xx_smbus[%d]/%s", index
, name
);
473 qtest_add_data_func(full_name
, (void *)(intptr_t)index
, fn
);
475 #define add_test(name, td) smbus_add_test(#name, td, test_##name)
477 int main(int argc
, char **argv
)
481 g_test_init(&argc
, &argv
, NULL
);
482 g_test_set_nonfatal_assertions();
484 for (i
= 0; i
< NR_SMBUS_DEVICES
; ++i
) {
485 add_test(disable_bus
, i
);
486 add_test(invalid_addr
, i
);
489 for (i
= 0; i
< ARRAY_SIZE(evb_bus_list
); ++i
) {
490 add_test(single_mode
, evb_bus_list
[i
]);
491 add_test(fifo_mode
, evb_bus_list
[i
]);