Merge remote-tracking branch 'remotes/amarkovic/tags/mips-queue-jun-26-2019' into...
[qemu/ar7.git] / hw / i2c / smbus_master.c
blob0a6223744c6a99f357aec085c28eed69810bfcce
1 /*
2 * QEMU SMBus host (master) emulation.
4 * This code emulates SMBus transactions from the master point of view,
5 * it runs the individual I2C transaction to do the SMBus protocol
6 * over I2C.
8 * Copyright (c) 2007 CodeSourcery.
9 * Written by Paul Brook
11 * This code is licensed under the LGPL.
14 #include "qemu/osdep.h"
15 #include "hw/hw.h"
16 #include "hw/i2c/i2c.h"
17 #include "hw/i2c/smbus_master.h"
19 /* Master device commands. */
20 int smbus_quick_command(I2CBus *bus, uint8_t addr, int read)
22 if (i2c_start_transfer(bus, addr, read)) {
23 return -1;
25 i2c_end_transfer(bus);
26 return 0;
29 int smbus_receive_byte(I2CBus *bus, uint8_t addr)
31 uint8_t data;
33 if (i2c_start_transfer(bus, addr, 1)) {
34 return -1;
36 data = i2c_recv(bus);
37 i2c_nack(bus);
38 i2c_end_transfer(bus);
39 return data;
42 int smbus_send_byte(I2CBus *bus, uint8_t addr, uint8_t data)
44 if (i2c_start_transfer(bus, addr, 0)) {
45 return -1;
47 i2c_send(bus, data);
48 i2c_end_transfer(bus);
49 return 0;
52 int smbus_read_byte(I2CBus *bus, uint8_t addr, uint8_t command)
54 uint8_t data;
55 if (i2c_start_transfer(bus, addr, 0)) {
56 return -1;
58 i2c_send(bus, command);
59 if (i2c_start_transfer(bus, addr, 1)) {
60 i2c_end_transfer(bus);
61 return -1;
63 data = i2c_recv(bus);
64 i2c_nack(bus);
65 i2c_end_transfer(bus);
66 return data;
69 int smbus_write_byte(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t data)
71 if (i2c_start_transfer(bus, addr, 0)) {
72 return -1;
74 i2c_send(bus, command);
75 i2c_send(bus, data);
76 i2c_end_transfer(bus);
77 return 0;
80 int smbus_read_word(I2CBus *bus, uint8_t addr, uint8_t command)
82 uint16_t data;
83 if (i2c_start_transfer(bus, addr, 0)) {
84 return -1;
86 i2c_send(bus, command);
87 if (i2c_start_transfer(bus, addr, 1)) {
88 i2c_end_transfer(bus);
89 return -1;
91 data = i2c_recv(bus);
92 data |= i2c_recv(bus) << 8;
93 i2c_nack(bus);
94 i2c_end_transfer(bus);
95 return data;
98 int smbus_write_word(I2CBus *bus, uint8_t addr, uint8_t command, uint16_t data)
100 if (i2c_start_transfer(bus, addr, 0)) {
101 return -1;
103 i2c_send(bus, command);
104 i2c_send(bus, data & 0xff);
105 i2c_send(bus, data >> 8);
106 i2c_end_transfer(bus);
107 return 0;
110 int smbus_read_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
111 int len, bool recv_len, bool send_cmd)
113 int rlen;
114 int i;
116 if (send_cmd) {
117 if (i2c_start_transfer(bus, addr, 0)) {
118 return -1;
120 i2c_send(bus, command);
122 if (i2c_start_transfer(bus, addr, 1)) {
123 if (send_cmd) {
124 i2c_end_transfer(bus);
126 return -1;
128 if (recv_len) {
129 rlen = i2c_recv(bus);
130 } else {
131 rlen = len;
133 if (rlen > len) {
134 rlen = 0;
136 for (i = 0; i < rlen; i++) {
137 data[i] = i2c_recv(bus);
139 i2c_nack(bus);
140 i2c_end_transfer(bus);
141 return rlen;
144 int smbus_write_block(I2CBus *bus, uint8_t addr, uint8_t command, uint8_t *data,
145 int len, bool send_len)
147 int i;
149 if (len > 32) {
150 len = 32;
153 if (i2c_start_transfer(bus, addr, 0)) {
154 return -1;
156 i2c_send(bus, command);
157 if (send_len) {
158 i2c_send(bus, len);
160 for (i = 0; i < len; i++) {
161 i2c_send(bus, data[i]);
163 i2c_end_transfer(bus);
164 return 0;