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