xref: /openbmc/qemu/tests/qtest/qtest_aspeed.c (revision 39920a04)
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