xref: /qemu/hw/i2c/smbus_master.c (revision 93198b6cad8af03996373584284a1673ad6000cb)
1*93198b6cSCorey Minyard /*
2*93198b6cSCorey Minyard  * QEMU SMBus host (master) emulation.
3*93198b6cSCorey Minyard  *
4*93198b6cSCorey Minyard  * This code emulates SMBus transactions from the master point of view,
5*93198b6cSCorey Minyard  * it runs the individual I2C transaction to do the SMBus protocol
6*93198b6cSCorey Minyard  * over I2C.
7*93198b6cSCorey Minyard  *
8*93198b6cSCorey Minyard  * Copyright (c) 2007 CodeSourcery.
9*93198b6cSCorey Minyard  * Written by Paul Brook
10*93198b6cSCorey Minyard  *
11*93198b6cSCorey Minyard  * This code is licensed under the LGPL.
12*93198b6cSCorey Minyard  */
13*93198b6cSCorey Minyard 
14*93198b6cSCorey Minyard #include "qemu/osdep.h"
15*93198b6cSCorey Minyard #include "hw/hw.h"
16*93198b6cSCorey Minyard #include "hw/i2c/i2c.h"
17*93198b6cSCorey Minyard #include "hw/i2c/smbus_master.h"
18*93198b6cSCorey Minyard 
19*93198b6cSCorey Minyard /* Master device commands.  */
20*93198b6cSCorey Minyard int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
21*93198b6cSCorey Minyard {
22*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, read)) {
23*93198b6cSCorey Minyard         return -1;
24*93198b6cSCorey Minyard     }
25*93198b6cSCorey Minyard     i2c_end_transfer(bus);
26*93198b6cSCorey Minyard     return 0;
27*93198b6cSCorey Minyard }
28*93198b6cSCorey Minyard 
29*93198b6cSCorey Minyard int smbus_receive_byte(I2CBus *bus, uint8_t addr)
30*93198b6cSCorey Minyard {
31*93198b6cSCorey Minyard     uint8_t data;
32*93198b6cSCorey Minyard 
33*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 1)) {
34*93198b6cSCorey Minyard         return -1;
35*93198b6cSCorey Minyard     }
36*93198b6cSCorey Minyard     data = i2c_recv(bus);
37*93198b6cSCorey Minyard     i2c_nack(bus);
38*93198b6cSCorey Minyard     i2c_end_transfer(bus);
39*93198b6cSCorey Minyard     return data;
40*93198b6cSCorey Minyard }
41*93198b6cSCorey Minyard 
42*93198b6cSCorey Minyard int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
43*93198b6cSCorey Minyard {
44*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 0)) {
45*93198b6cSCorey Minyard         return -1;
46*93198b6cSCorey Minyard     }
47*93198b6cSCorey Minyard     i2c_send(bus, data);
48*93198b6cSCorey Minyard     i2c_end_transfer(bus);
49*93198b6cSCorey Minyard     return 0;
50*93198b6cSCorey Minyard }
51*93198b6cSCorey Minyard 
52*93198b6cSCorey Minyard int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
53*93198b6cSCorey Minyard {
54*93198b6cSCorey Minyard     uint8_t data;
55*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 0)) {
56*93198b6cSCorey Minyard         return -1;
57*93198b6cSCorey Minyard     }
58*93198b6cSCorey Minyard     i2c_send(bus, command);
59*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 1)) {
60*93198b6cSCorey Minyard         i2c_end_transfer(bus);
61*93198b6cSCorey Minyard         return -1;
62*93198b6cSCorey Minyard     }
63*93198b6cSCorey Minyard     data = i2c_recv(bus);
64*93198b6cSCorey Minyard     i2c_nack(bus);
65*93198b6cSCorey Minyard     i2c_end_transfer(bus);
66*93198b6cSCorey Minyard     return data;
67*93198b6cSCorey Minyard }
68*93198b6cSCorey Minyard 
69*93198b6cSCorey Minyard int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
70*93198b6cSCorey Minyard {
71*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 0)) {
72*93198b6cSCorey Minyard         return -1;
73*93198b6cSCorey Minyard     }
74*93198b6cSCorey Minyard     i2c_send(bus, command);
75*93198b6cSCorey Minyard     i2c_send(bus, data);
76*93198b6cSCorey Minyard     i2c_end_transfer(bus);
77*93198b6cSCorey Minyard     return 0;
78*93198b6cSCorey Minyard }
79*93198b6cSCorey Minyard 
80*93198b6cSCorey Minyard int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
81*93198b6cSCorey Minyard {
82*93198b6cSCorey Minyard     uint16_t data;
83*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 0)) {
84*93198b6cSCorey Minyard         return -1;
85*93198b6cSCorey Minyard     }
86*93198b6cSCorey Minyard     i2c_send(bus, command);
87*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 1)) {
88*93198b6cSCorey Minyard         i2c_end_transfer(bus);
89*93198b6cSCorey Minyard         return -1;
90*93198b6cSCorey Minyard     }
91*93198b6cSCorey Minyard     data = i2c_recv(bus);
92*93198b6cSCorey Minyard     data |= i2c_recv(bus) << 8;
93*93198b6cSCorey Minyard     i2c_nack(bus);
94*93198b6cSCorey Minyard     i2c_end_transfer(bus);
95*93198b6cSCorey Minyard     return data;
96*93198b6cSCorey Minyard }
97*93198b6cSCorey Minyard 
98*93198b6cSCorey Minyard int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
99*93198b6cSCorey Minyard {
100*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 0)) {
101*93198b6cSCorey Minyard         return -1;
102*93198b6cSCorey Minyard     }
103*93198b6cSCorey Minyard     i2c_send(bus, command);
104*93198b6cSCorey Minyard     i2c_send(bus, data & 0xff);
105*93198b6cSCorey Minyard     i2c_send(bus, data >> 8);
106*93198b6cSCorey Minyard     i2c_end_transfer(bus);
107*93198b6cSCorey Minyard     return 0;
108*93198b6cSCorey Minyard }
109*93198b6cSCorey Minyard 
110*93198b6cSCorey Minyard int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
111*93198b6cSCorey Minyard                      int len, bool recv_len, bool send_cmd)
112*93198b6cSCorey Minyard {
113*93198b6cSCorey Minyard     int rlen;
114*93198b6cSCorey Minyard     int i;
115*93198b6cSCorey Minyard 
116*93198b6cSCorey Minyard     if (send_cmd) {
117*93198b6cSCorey Minyard         if (i2c_start_transfer(bus, addr, 0)) {
118*93198b6cSCorey Minyard             return -1;
119*93198b6cSCorey Minyard         }
120*93198b6cSCorey Minyard         i2c_send(bus, command);
121*93198b6cSCorey Minyard     }
122*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 1)) {
123*93198b6cSCorey Minyard         if (send_cmd) {
124*93198b6cSCorey Minyard             i2c_end_transfer(bus);
125*93198b6cSCorey Minyard         }
126*93198b6cSCorey Minyard         return -1;
127*93198b6cSCorey Minyard     }
128*93198b6cSCorey Minyard     if (recv_len) {
129*93198b6cSCorey Minyard         rlen = i2c_recv(bus);
130*93198b6cSCorey Minyard     } else {
131*93198b6cSCorey Minyard         rlen = len;
132*93198b6cSCorey Minyard     }
133*93198b6cSCorey Minyard     if (rlen > len) {
134*93198b6cSCorey Minyard         rlen = 0;
135*93198b6cSCorey Minyard     }
136*93198b6cSCorey Minyard     for (i = 0; i < rlen; i++) {
137*93198b6cSCorey Minyard         data[i] = i2c_recv(bus);
138*93198b6cSCorey Minyard     }
139*93198b6cSCorey Minyard     i2c_nack(bus);
140*93198b6cSCorey Minyard     i2c_end_transfer(bus);
141*93198b6cSCorey Minyard     return rlen;
142*93198b6cSCorey Minyard }
143*93198b6cSCorey Minyard 
144*93198b6cSCorey Minyard int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
145*93198b6cSCorey Minyard                       int len, bool send_len)
146*93198b6cSCorey Minyard {
147*93198b6cSCorey Minyard     int i;
148*93198b6cSCorey Minyard 
149*93198b6cSCorey Minyard     if (len > 32) {
150*93198b6cSCorey Minyard         len = 32;
151*93198b6cSCorey Minyard     }
152*93198b6cSCorey Minyard 
153*93198b6cSCorey Minyard     if (i2c_start_transfer(bus, addr, 0)) {
154*93198b6cSCorey Minyard         return -1;
155*93198b6cSCorey Minyard     }
156*93198b6cSCorey Minyard     i2c_send(bus, command);
157*93198b6cSCorey Minyard     if (send_len) {
158*93198b6cSCorey Minyard         i2c_send(bus, len);
159*93198b6cSCorey Minyard     }
160*93198b6cSCorey Minyard     for (i = 0; i < len; i++) {
161*93198b6cSCorey Minyard         i2c_send(bus, data[i]);
162*93198b6cSCorey Minyard     }
163*93198b6cSCorey Minyard     i2c_end_transfer(bus);
164*93198b6cSCorey Minyard     return 0;
165*93198b6cSCorey Minyard }
166