Remove *.aml
[qemu/ar7.git] / hw / i2c / pm_smbus.c
blob0d26e0f6b5fec90df7a255f70dc67bf399dfa370
1 /*
2 * PC SMBus implementation
3 * splitted from acpi.c
5 * Copyright (c) 2006 Fabrice Bellard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License version 2 as published by the Free Software Foundation.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see
18 * <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
21 #include "hw/hw.h"
22 #include "hw/i2c/pm_smbus.h"
23 #include "hw/i2c/smbus.h"
25 /* no save/load? */
27 #define SMBHSTSTS 0x00
28 #define SMBHSTCNT 0x02
29 #define SMBHSTCMD 0x03
30 #define SMBHSTADD 0x04
31 #define SMBHSTDAT0 0x05
32 #define SMBHSTDAT1 0x06
33 #define SMBBLKDAT 0x07
35 #define STS_HOST_BUSY (1)
36 #define STS_INTR (1<<1)
37 #define STS_DEV_ERR (1<<2)
38 #define STS_BUS_ERR (1<<3)
39 #define STS_FAILED (1<<4)
40 #define STS_SMBALERT (1<<5)
41 #define STS_INUSE_STS (1<<6)
42 #define STS_BYTE_DONE (1<<7)
43 /* Signs of successfully transaction end :
44 * ByteDoneStatus = 1 (STS_BYTE_DONE) and INTR = 1 (STS_INTR )
47 //#define DEBUG
49 #ifdef DEBUG
50 # define SMBUS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
51 #else
52 # define SMBUS_DPRINTF(format, ...) do { } while (0)
53 #endif
56 static void smb_transaction(PMSMBus *s)
58 uint8_t prot = (s->smb_ctl >> 2) & 0x07;
59 uint8_t read = s->smb_addr & 0x01;
60 uint8_t cmd = s->smb_cmd;
61 uint8_t addr = s->smb_addr >> 1;
62 I2CBus *bus = s->smbus;
63 int ret;
65 assert(s->smb_stat & STS_HOST_BUSY);
66 s->smb_stat &= ~STS_HOST_BUSY;
68 SMBUS_DPRINTF("SMBus trans addr=0x%02x prot=0x%02x\n", addr, prot);
69 /* Transaction isn't exec if STS_DEV_ERR bit set */
70 if ((s->smb_stat & STS_DEV_ERR) != 0) {
71 goto error;
73 switch(prot) {
74 case 0x0:
75 ret = smbus_quick_command(bus, addr, read);
76 goto done;
77 case 0x1:
78 if (read) {
79 ret = smbus_receive_byte(bus, addr);
80 goto data8;
81 } else {
82 ret = smbus_send_byte(bus, addr, cmd);
83 goto done;
85 case 0x2:
86 if (read) {
87 ret = smbus_read_byte(bus, addr, cmd);
88 goto data8;
89 } else {
90 ret = smbus_write_byte(bus, addr, cmd, s->smb_data0);
91 goto done;
93 break;
94 case 0x3:
95 if (read) {
96 ret = smbus_read_word(bus, addr, cmd);
97 goto data16;
98 } else {
99 ret = smbus_write_word(bus, addr, cmd, (s->smb_data1 << 8) | s->smb_data0);
100 goto done;
102 break;
103 case 0x5:
104 if (read) {
105 ret = smbus_read_block(bus, addr, cmd, s->smb_data);
106 goto data8;
107 } else {
108 ret = smbus_write_block(bus, addr, cmd, s->smb_data, s->smb_data0);
109 goto done;
111 break;
112 default:
113 goto error;
115 abort();
117 data16:
118 if (ret < 0) {
119 goto error;
121 s->smb_data1 = ret >> 8;
122 data8:
123 if (ret < 0) {
124 goto error;
126 s->smb_data0 = ret;
127 done:
128 if (ret < 0) {
129 goto error;
131 s->smb_stat |= STS_BYTE_DONE | STS_INTR;
132 return;
134 error:
135 s->smb_stat |= STS_DEV_ERR;
136 return;
140 static void smb_transaction_start(PMSMBus *s)
142 /* Do not execute immediately the command ; it will be
143 * executed when guest will read SMB_STAT register */
144 s->smb_stat |= STS_HOST_BUSY;
147 static void smb_ioport_writeb(void *opaque, hwaddr addr, uint64_t val,
148 unsigned width)
150 PMSMBus *s = opaque;
152 SMBUS_DPRINTF("SMB writeb port=0x%04" HWADDR_PRIx
153 " val=0x%02" PRIx64 "\n", addr, val);
154 switch(addr) {
155 case SMBHSTSTS:
156 s->smb_stat = (~(val & 0xff)) & s->smb_stat;
157 s->smb_index = 0;
158 break;
159 case SMBHSTCNT:
160 s->smb_ctl = val;
161 if (val & 0x40)
162 smb_transaction_start(s);
163 break;
164 case SMBHSTCMD:
165 s->smb_cmd = val;
166 break;
167 case SMBHSTADD:
168 s->smb_addr = val;
169 break;
170 case SMBHSTDAT0:
171 s->smb_data0 = val;
172 break;
173 case SMBHSTDAT1:
174 s->smb_data1 = val;
175 break;
176 case SMBBLKDAT:
177 s->smb_data[s->smb_index++] = val;
178 if (s->smb_index > 31)
179 s->smb_index = 0;
180 break;
181 default:
182 break;
186 static uint64_t smb_ioport_readb(void *opaque, hwaddr addr, unsigned width)
188 PMSMBus *s = opaque;
189 uint32_t val;
191 switch(addr) {
192 case SMBHSTSTS:
193 val = s->smb_stat;
194 if (s->smb_stat & STS_HOST_BUSY) {
195 /* execute command now */
196 smb_transaction(s);
198 break;
199 case SMBHSTCNT:
200 s->smb_index = 0;
201 val = s->smb_ctl & 0x1f;
202 break;
203 case SMBHSTCMD:
204 val = s->smb_cmd;
205 break;
206 case SMBHSTADD:
207 val = s->smb_addr;
208 break;
209 case SMBHSTDAT0:
210 val = s->smb_data0;
211 break;
212 case SMBHSTDAT1:
213 val = s->smb_data1;
214 break;
215 case SMBBLKDAT:
216 val = s->smb_data[s->smb_index++];
217 if (s->smb_index > 31)
218 s->smb_index = 0;
219 break;
220 default:
221 val = 0;
222 break;
224 SMBUS_DPRINTF("SMB readb port=0x%04" HWADDR_PRIx " val=0x%02x\n", addr, val);
225 return val;
228 static const MemoryRegionOps pm_smbus_ops = {
229 .read = smb_ioport_readb,
230 .write = smb_ioport_writeb,
231 .valid.min_access_size = 1,
232 .valid.max_access_size = 1,
233 .endianness = DEVICE_LITTLE_ENDIAN,
236 void pm_smbus_init(DeviceState *parent, PMSMBus *smb)
238 smb->smbus = i2c_init_bus(parent, "i2c");
239 memory_region_init_io(&smb->io, OBJECT(parent), &pm_smbus_ops, smb,
240 "pm-smbus", 64);