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.
9 #include "libqos/i2c.h"
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 static void omap_i2c_set_slave_addr(OMAPI2C
*s
, uint8_t addr
)
56 writew(s
->addr
+ OMAP_I2C_SA
, data
);
57 data
= readw(s
->addr
+ OMAP_I2C_SA
);
58 g_assert_cmphex(data
, ==, addr
);
61 static void omap_i2c_send(I2CAdapter
*i2c
, uint8_t addr
,
62 const uint8_t *buf
, uint16_t len
)
64 OMAPI2C
*s
= (OMAPI2C
*)i2c
;
67 omap_i2c_set_slave_addr(s
, addr
);
70 writew(s
->addr
+ OMAP_I2C_CNT
, data
);
72 data
= OMAP_I2C_CON_I2C_EN
|
77 writew(s
->addr
+ OMAP_I2C_CON
, data
);
78 data
= readw(s
->addr
+ OMAP_I2C_CON
);
79 g_assert((data
& OMAP_I2C_CON_STP
) != 0);
81 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
82 g_assert((data
& OMAP_I2C_STAT_NACK
) == 0);
85 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
86 g_assert((data
& OMAP_I2C_STAT_XRDY
) != 0);
88 data
= buf
[0] | ((uint16_t)buf
[1] << 8);
89 writew(s
->addr
+ OMAP_I2C_DATA
, data
);
90 buf
= (uint8_t *)buf
+ 2;
94 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
95 g_assert((data
& OMAP_I2C_STAT_XRDY
) != 0);
98 writew(s
->addr
+ OMAP_I2C_DATA
, data
);
101 data
= readw(s
->addr
+ OMAP_I2C_CON
);
102 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
105 static void omap_i2c_recv(I2CAdapter
*i2c
, uint8_t addr
,
106 uint8_t *buf
, uint16_t len
)
108 OMAPI2C
*s
= (OMAPI2C
*)i2c
;
111 omap_i2c_set_slave_addr(s
, addr
);
114 writew(s
->addr
+ OMAP_I2C_CNT
, data
);
116 data
= OMAP_I2C_CON_I2C_EN
|
120 writew(s
->addr
+ OMAP_I2C_CON
, data
);
121 data
= readw(s
->addr
+ OMAP_I2C_CON
);
122 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
124 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
125 g_assert((data
& OMAP_I2C_STAT_NACK
) == 0);
127 data
= readw(s
->addr
+ OMAP_I2C_CNT
);
128 g_assert_cmpuint(data
, ==, len
);
131 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
132 g_assert((data
& OMAP_I2C_STAT_RRDY
) != 0);
133 g_assert((data
& OMAP_I2C_STAT_ROVR
) == 0);
135 data
= readw(s
->addr
+ OMAP_I2C_DATA
);
137 stat
= readw(s
->addr
+ OMAP_I2C_STAT
);
139 if (unlikely(len
== 1)) {
140 g_assert((stat
& OMAP_I2C_STAT_SBD
) != 0);
142 buf
[0] = data
& 0xff;
146 buf
[0] = data
& 0xff;
153 data
= readw(s
->addr
+ OMAP_I2C_CON
);
154 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
157 I2CAdapter
*omap_i2c_create(uint64_t addr
)
159 OMAPI2C
*s
= g_malloc0(sizeof(*s
));
160 I2CAdapter
*i2c
= (I2CAdapter
*)s
;
165 i2c
->send
= omap_i2c_send
;
166 i2c
->recv
= omap_i2c_recv
;
168 /* verify the mmio address by looking for a known signature */
169 data
= readw(addr
+ OMAP_I2C_REV
);
170 g_assert_cmphex(data
, ==, 0x34);