1 /* 2 * Aspeed i2c bus interface for reading from and writing to i2c device registers 3 * 4 * Copyright (c) 2023 IBM Corporation 5 * 6 * Authors: 7 * Stefan Berger <stefanb@linux.ibm.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #include "qemu/osdep.h" 14 15 #include "qtest_aspeed.h" 16 #include "hw/i2c/aspeed_i2c.h" 17 18 static void aspeed_i2c_startup(QTestState *s, uint32_t baseaddr, 19 uint8_t slave_addr, uint8_t reg) 20 { 21 uint32_t v; 22 static int once; 23 24 if (!once) { 25 /* one time: enable master */ 26 qtest_writel(s, baseaddr + A_I2CC_FUN_CTRL, 0); 27 v = qtest_readl(s, baseaddr + A_I2CC_FUN_CTRL) | A_I2CD_MASTER_EN; 28 qtest_writel(s, baseaddr + A_I2CC_FUN_CTRL, v); 29 once = 1; 30 } 31 32 /* select device */ 33 qtest_writel(s, baseaddr + A_I2CD_BYTE_BUF, slave_addr << 1); 34 qtest_writel(s, baseaddr + A_I2CD_CMD, 35 A_I2CD_M_START_CMD | A_I2CD_M_RX_CMD); 36 37 /* select the register to write to */ 38 qtest_writel(s, baseaddr + A_I2CD_BYTE_BUF, reg); 39 qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_TX_CMD); 40 } 41 42 static uint32_t aspeed_i2c_read_n(QTestState *s, 43 uint32_t baseaddr, uint8_t slave_addr, 44 uint8_t reg, size_t nbytes) 45 { 46 uint32_t res = 0; 47 uint32_t v; 48 size_t i; 49 50 aspeed_i2c_startup(s, baseaddr, slave_addr, reg); 51 52 for (i = 0; i < nbytes; i++) { 53 qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_RX_CMD); 54 v = qtest_readl(s, baseaddr + A_I2CD_BYTE_BUF) >> 8; 55 res |= (v & 0xff) << (i * 8); 56 } 57 58 qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_STOP_CMD); 59 60 return res; 61 } 62 63 uint32_t aspeed_i2c_readl(QTestState *s, 64 uint32_t baseaddr, uint8_t slave_addr, uint8_t reg) 65 { 66 return aspeed_i2c_read_n(s, baseaddr, slave_addr, reg, sizeof(uint32_t)); 67 } 68 69 uint16_t aspeed_i2c_readw(QTestState *s, 70 uint32_t baseaddr, uint8_t slave_addr, uint8_t reg) 71 { 72 return aspeed_i2c_read_n(s, baseaddr, slave_addr, reg, sizeof(uint16_t)); 73 } 74 75 uint8_t aspeed_i2c_readb(QTestState *s, 76 uint32_t baseaddr, uint8_t slave_addr, uint8_t reg) 77 { 78 return aspeed_i2c_read_n(s, baseaddr, slave_addr, reg, sizeof(uint8_t)); 79 } 80 81 static void aspeed_i2c_write_n(QTestState *s, 82 uint32_t baseaddr, uint8_t slave_addr, 83 uint8_t reg, uint32_t v, size_t nbytes) 84 { 85 size_t i; 86 87 aspeed_i2c_startup(s, baseaddr, slave_addr, reg); 88 89 for (i = 0; i < nbytes; i++) { 90 qtest_writel(s, baseaddr + A_I2CD_BYTE_BUF, v & 0xff); 91 v >>= 8; 92 qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_TX_CMD); 93 } 94 95 qtest_writel(s, baseaddr + A_I2CD_CMD, A_I2CD_M_STOP_CMD); 96 } 97 98 void aspeed_i2c_writel(QTestState *s, 99 uint32_t baseaddr, uint8_t slave_addr, 100 uint8_t reg, uint32_t v) 101 { 102 aspeed_i2c_write_n(s, baseaddr, slave_addr, reg, v, sizeof(v)); 103 } 104 105 void aspeed_i2c_writew(QTestState *s, 106 uint32_t baseaddr, uint8_t slave_addr, 107 uint8_t reg, uint16_t v) 108 { 109 aspeed_i2c_write_n(s, baseaddr, slave_addr, reg, v, sizeof(v)); 110 } 111 112 void aspeed_i2c_writeb(QTestState *s, 113 uint32_t baseaddr, uint8_t slave_addr, 114 uint8_t reg, uint8_t v) 115 { 116 aspeed_i2c_write_n(s, baseaddr, slave_addr, reg, v, sizeof(v)); 117 } 118