4 * Copyright (c) 2012 Andreas Färber
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
14 #include "qemu/osdep.h"
15 #include "qemu/bswap.h"
18 enum OMAPI2CRegisters
{
27 enum OMAPI2CSTATBits
{
28 OMAP_I2C_STAT_NACK
= 1 << 1,
29 OMAP_I2C_STAT_ARDY
= 1 << 2,
30 OMAP_I2C_STAT_RRDY
= 1 << 3,
31 OMAP_I2C_STAT_XRDY
= 1 << 4,
32 OMAP_I2C_STAT_ROVR
= 1 << 11,
33 OMAP_I2C_STAT_SBD
= 1 << 15,
37 OMAP_I2C_CON_STT
= 1 << 0,
38 OMAP_I2C_CON_STP
= 1 << 1,
39 OMAP_I2C_CON_TRX
= 1 << 9,
40 OMAP_I2C_CON_MST
= 1 << 10,
41 OMAP_I2C_CON_BE
= 1 << 14,
42 OMAP_I2C_CON_I2C_EN
= 1 << 15,
45 typedef struct OMAPI2C
{
52 /* FIXME Use TBD readw qtest API */
53 static inline uint16_t readw(uint64_t addr
)
57 memread(addr
, &data
, 2);
58 return le16_to_cpu(data
);
61 /* FIXME Use TBD writew qtest API */
62 static inline void writew(uint64_t addr
, uint16_t data
)
64 data
= cpu_to_le16(data
);
65 memwrite(addr
, &data
, 2);
71 #pragma GCC poison memread
72 #pragma GCC poison memwrite
75 static void omap_i2c_set_slave_addr(OMAPI2C
*s
, uint8_t addr
)
79 writew(s
->addr
+ OMAP_I2C_SA
, data
);
80 data
= readw(s
->addr
+ OMAP_I2C_SA
);
81 g_assert_cmphex(data
, ==, addr
);
84 static void omap_i2c_send(I2CAdapter
*i2c
, uint8_t addr
,
85 const uint8_t *buf
, uint16_t len
)
87 OMAPI2C
*s
= (OMAPI2C
*)i2c
;
90 omap_i2c_set_slave_addr(s
, addr
);
93 writew(s
->addr
+ OMAP_I2C_CNT
, data
);
95 data
= OMAP_I2C_CON_I2C_EN
|
100 writew(s
->addr
+ OMAP_I2C_CON
, data
);
101 data
= readw(s
->addr
+ OMAP_I2C_CON
);
102 g_assert((data
& OMAP_I2C_CON_STP
) != 0);
104 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
105 g_assert((data
& OMAP_I2C_STAT_NACK
) == 0);
108 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
109 g_assert((data
& OMAP_I2C_STAT_XRDY
) != 0);
111 data
= buf
[0] | ((uint16_t)buf
[1] << 8);
112 writew(s
->addr
+ OMAP_I2C_DATA
, data
);
113 buf
= (uint8_t *)buf
+ 2;
117 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
118 g_assert((data
& OMAP_I2C_STAT_XRDY
) != 0);
121 writew(s
->addr
+ OMAP_I2C_DATA
, data
);
124 data
= readw(s
->addr
+ OMAP_I2C_CON
);
125 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
128 static void omap_i2c_recv(I2CAdapter
*i2c
, uint8_t addr
,
129 uint8_t *buf
, uint16_t len
)
131 OMAPI2C
*s
= (OMAPI2C
*)i2c
;
134 omap_i2c_set_slave_addr(s
, addr
);
137 writew(s
->addr
+ OMAP_I2C_CNT
, data
);
139 data
= OMAP_I2C_CON_I2C_EN
|
143 writew(s
->addr
+ OMAP_I2C_CON
, data
);
144 data
= readw(s
->addr
+ OMAP_I2C_CON
);
145 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
147 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
148 g_assert((data
& OMAP_I2C_STAT_NACK
) == 0);
150 data
= readw(s
->addr
+ OMAP_I2C_CNT
);
151 g_assert_cmpuint(data
, ==, len
);
154 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
155 g_assert((data
& OMAP_I2C_STAT_RRDY
) != 0);
156 g_assert((data
& OMAP_I2C_STAT_ROVR
) == 0);
158 data
= readw(s
->addr
+ OMAP_I2C_DATA
);
160 stat
= readw(s
->addr
+ OMAP_I2C_STAT
);
162 if (unlikely(len
== 1)) {
163 g_assert((stat
& OMAP_I2C_STAT_SBD
) != 0);
165 buf
[0] = data
& 0xff;
169 buf
[0] = data
& 0xff;
176 data
= readw(s
->addr
+ OMAP_I2C_CON
);
177 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
180 I2CAdapter
*omap_i2c_create(uint64_t addr
)
182 OMAPI2C
*s
= g_malloc0(sizeof(*s
));
183 I2CAdapter
*i2c
= (I2CAdapter
*)s
;
188 i2c
->send
= omap_i2c_send
;
189 i2c
->recv
= omap_i2c_recv
;
191 /* verify the mmio address by looking for a known signature */
192 data
= readw(addr
+ OMAP_I2C_REV
);
193 g_assert_cmphex(data
, ==, 0x34);