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 "qemu/osdep.h"
10 #include "libqos/i2c.h"
13 #include "qemu/bswap.h"
16 enum OMAPI2CRegisters
{
25 enum OMAPI2CSTATBits
{
26 OMAP_I2C_STAT_NACK
= 1 << 1,
27 OMAP_I2C_STAT_ARDY
= 1 << 2,
28 OMAP_I2C_STAT_RRDY
= 1 << 3,
29 OMAP_I2C_STAT_XRDY
= 1 << 4,
30 OMAP_I2C_STAT_ROVR
= 1 << 11,
31 OMAP_I2C_STAT_SBD
= 1 << 15,
35 OMAP_I2C_CON_STT
= 1 << 0,
36 OMAP_I2C_CON_STP
= 1 << 1,
37 OMAP_I2C_CON_TRX
= 1 << 9,
38 OMAP_I2C_CON_MST
= 1 << 10,
39 OMAP_I2C_CON_BE
= 1 << 14,
40 OMAP_I2C_CON_I2C_EN
= 1 << 15,
43 typedef struct OMAPI2C
{
50 static void omap_i2c_set_slave_addr(OMAPI2C
*s
, uint8_t addr
)
54 writew(s
->addr
+ OMAP_I2C_SA
, data
);
55 data
= readw(s
->addr
+ OMAP_I2C_SA
);
56 g_assert_cmphex(data
, ==, addr
);
59 static void omap_i2c_send(I2CAdapter
*i2c
, uint8_t addr
,
60 const uint8_t *buf
, uint16_t len
)
62 OMAPI2C
*s
= (OMAPI2C
*)i2c
;
65 omap_i2c_set_slave_addr(s
, addr
);
68 writew(s
->addr
+ OMAP_I2C_CNT
, data
);
70 data
= OMAP_I2C_CON_I2C_EN
|
75 writew(s
->addr
+ OMAP_I2C_CON
, data
);
76 data
= readw(s
->addr
+ OMAP_I2C_CON
);
77 g_assert((data
& OMAP_I2C_CON_STP
) != 0);
79 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
80 g_assert((data
& OMAP_I2C_STAT_NACK
) == 0);
83 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
84 g_assert((data
& OMAP_I2C_STAT_XRDY
) != 0);
86 data
= buf
[0] | ((uint16_t)buf
[1] << 8);
87 writew(s
->addr
+ OMAP_I2C_DATA
, data
);
88 buf
= (uint8_t *)buf
+ 2;
92 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
93 g_assert((data
& OMAP_I2C_STAT_XRDY
) != 0);
96 writew(s
->addr
+ OMAP_I2C_DATA
, data
);
99 data
= readw(s
->addr
+ OMAP_I2C_CON
);
100 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
103 static void omap_i2c_recv(I2CAdapter
*i2c
, uint8_t addr
,
104 uint8_t *buf
, uint16_t len
)
106 OMAPI2C
*s
= (OMAPI2C
*)i2c
;
109 omap_i2c_set_slave_addr(s
, addr
);
112 writew(s
->addr
+ OMAP_I2C_CNT
, data
);
114 data
= OMAP_I2C_CON_I2C_EN
|
118 writew(s
->addr
+ OMAP_I2C_CON
, data
);
119 data
= readw(s
->addr
+ OMAP_I2C_CON
);
120 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
122 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
123 g_assert((data
& OMAP_I2C_STAT_NACK
) == 0);
125 data
= readw(s
->addr
+ OMAP_I2C_CNT
);
126 g_assert_cmpuint(data
, ==, len
);
129 data
= readw(s
->addr
+ OMAP_I2C_STAT
);
130 g_assert((data
& OMAP_I2C_STAT_RRDY
) != 0);
131 g_assert((data
& OMAP_I2C_STAT_ROVR
) == 0);
133 data
= readw(s
->addr
+ OMAP_I2C_DATA
);
135 stat
= readw(s
->addr
+ OMAP_I2C_STAT
);
137 if (unlikely(len
== 1)) {
138 g_assert((stat
& OMAP_I2C_STAT_SBD
) != 0);
140 buf
[0] = data
& 0xff;
144 buf
[0] = data
& 0xff;
151 data
= readw(s
->addr
+ OMAP_I2C_CON
);
152 g_assert((data
& OMAP_I2C_CON_STP
) == 0);
155 I2CAdapter
*omap_i2c_create(uint64_t addr
)
157 OMAPI2C
*s
= g_malloc0(sizeof(*s
));
158 I2CAdapter
*i2c
= (I2CAdapter
*)s
;
163 i2c
->send
= omap_i2c_send
;
164 i2c
->recv
= omap_i2c_recv
;
166 /* verify the mmio address by looking for a known signature */
167 data
= readw(addr
+ OMAP_I2C_REV
);
168 g_assert_cmphex(data
, ==, 0x34);