1 /* 2 * QTest testcase for Broadcom Serial Controller (BSC) 3 * 4 * Copyright (c) 2024 Rayhan Faizel <rayhan.faizel@gmail.com> 5 * 6 * SPDX-License-Identifier: MIT 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a copy 9 * of this software and associated documentation files (the "Software"), to deal 10 * in the Software without restriction, including without limitation the rights 11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 * copies of the Software, and to permit persons to whom the Software is 13 * furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included in 16 * all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 * THE SOFTWARE. 25 */ 26 27 #include "qemu/osdep.h" 28 #include "libqtest-single.h" 29 30 #include "hw/i2c/bcm2835_i2c.h" 31 #include "hw/sensor/tmp105_regs.h" 32 33 static const uint32_t bsc_base_addrs[] = { 34 0x3f205000, /* I2C0 */ 35 0x3f804000, /* I2C1 */ 36 0x3f805000, /* I2C2 */ 37 }; 38 39 static void bcm2835_i2c_init_transfer(uint32_t base_addr, bool read) 40 { 41 /* read flag is bit 0 so we can write it directly */ 42 int interrupt = read ? BCM2835_I2C_C_INTR : BCM2835_I2C_C_INTT; 43 44 writel(base_addr + BCM2835_I2C_C, 45 BCM2835_I2C_C_I2CEN | BCM2835_I2C_C_INTD | 46 BCM2835_I2C_C_ST | BCM2835_I2C_C_CLEAR | interrupt | read); 47 } 48 49 static void test_i2c_read_write(gconstpointer data) 50 { 51 uint32_t i2cdata; 52 intptr_t index = (intptr_t) data; 53 uint32_t base_addr = bsc_base_addrs[index]; 54 55 /* Write to TMP105 register */ 56 writel(base_addr + BCM2835_I2C_A, 0x50); 57 writel(base_addr + BCM2835_I2C_DLEN, 3); 58 59 bcm2835_i2c_init_transfer(base_addr, 0); 60 61 writel(base_addr + BCM2835_I2C_FIFO, TMP105_REG_T_HIGH); 62 writel(base_addr + BCM2835_I2C_FIFO, 0xde); 63 writel(base_addr + BCM2835_I2C_FIFO, 0xad); 64 65 /* Clear flags */ 66 writel(base_addr + BCM2835_I2C_S, BCM2835_I2C_S_DONE | BCM2835_I2C_S_ERR | 67 BCM2835_I2C_S_CLKT); 68 69 /* Read from TMP105 register */ 70 writel(base_addr + BCM2835_I2C_A, 0x50); 71 writel(base_addr + BCM2835_I2C_DLEN, 1); 72 73 bcm2835_i2c_init_transfer(base_addr, 0); 74 75 writel(base_addr + BCM2835_I2C_FIFO, TMP105_REG_T_HIGH); 76 77 writel(base_addr + BCM2835_I2C_DLEN, 2); 78 bcm2835_i2c_init_transfer(base_addr, 1); 79 80 i2cdata = readl(base_addr + BCM2835_I2C_FIFO); 81 g_assert_cmpint(i2cdata, ==, 0xde); 82 83 i2cdata = readl(base_addr + BCM2835_I2C_FIFO); 84 g_assert_cmpint(i2cdata, ==, 0xa0); 85 86 /* Clear flags */ 87 writel(base_addr + BCM2835_I2C_S, BCM2835_I2C_S_DONE | BCM2835_I2C_S_ERR | 88 BCM2835_I2C_S_CLKT); 89 90 } 91 92 int main(int argc, char **argv) 93 { 94 int ret; 95 int i; 96 97 g_test_init(&argc, &argv, NULL); 98 99 for (i = 0; i < 3; i++) { 100 g_autofree char *test_name = 101 g_strdup_printf("/bcm2835/bcm2835-i2c%d/read_write", i); 102 qtest_add_data_func(test_name, (void *)(intptr_t) i, 103 test_i2c_read_write); 104 } 105 106 /* Run I2C tests with TMP105 slaves on all three buses */ 107 qtest_start("-M raspi3b " 108 "-device tmp105,address=0x50,bus=i2c-bus.0 " 109 "-device tmp105,address=0x50,bus=i2c-bus.1 " 110 "-device tmp105,address=0x50,bus=i2c-bus.2"); 111 ret = g_test_run(); 112 qtest_end(); 113 114 return ret; 115 } 116