tree: drop last paragraph of GPL copyright header
[coreboot.git] / src / southbridge / amd / sb800 / smbus.c
blobd9bb746f46fc93293d16e61522fba0d41334235d
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2010 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #ifndef _SB800_SMBUS_C_
17 #define _SB800_SMBUS_C_
19 #include "smbus.h"
21 static inline void smbus_delay(void)
23 outb(inb(0x80), 0x80);
26 static int smbus_wait_until_ready(u32 smbus_io_base)
28 u32 loops;
29 loops = SMBUS_TIMEOUT;
30 do {
31 u8 val;
32 val = inb(smbus_io_base + SMBHSTSTAT);
33 val &= 0x1f;
34 if (val == 0) { /* ready now */
35 return 0;
37 outb(val, smbus_io_base + SMBHSTSTAT);
38 } while (--loops);
39 return -2; /* time out */
42 static int smbus_wait_until_done(u32 smbus_io_base)
44 u32 loops;
45 loops = SMBUS_TIMEOUT;
46 do {
47 u8 val;
49 val = inb(smbus_io_base + SMBHSTSTAT);
50 val &= 0x1f; /* mask off reserved bits */
51 if (val & 0x1c) {
52 return -5; /* error */
54 if (val == 0x02) {
55 outb(val, smbus_io_base + SMBHSTSTAT); /* clear status */
56 return 0;
58 } while (--loops);
59 return -3; /* timeout */
62 int do_smbus_recv_byte(u32 smbus_io_base, u32 device)
64 u8 byte;
66 if (smbus_wait_until_ready(smbus_io_base) < 0) {
67 return -2; /* not ready */
70 /* set the device I'm talking too */
71 outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
73 byte = inb(smbus_io_base + SMBHSTCTRL);
74 byte &= 0xe3; /* Clear [4:2] */
75 byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
76 outb(byte, smbus_io_base + SMBHSTCTRL);
78 /* poll for transaction completion */
79 if (smbus_wait_until_done(smbus_io_base) < 0) {
80 return -3; /* timeout or error */
83 /* read results of transaction */
84 byte = inb(smbus_io_base + SMBHSTCMD);
86 return byte;
89 int do_smbus_send_byte(u32 smbus_io_base, u32 device, u8 val)
91 u8 byte;
93 if (smbus_wait_until_ready(smbus_io_base) < 0) {
94 return -2; /* not ready */
97 /* set the command... */
98 outb(val, smbus_io_base + SMBHSTCMD);
100 /* set the device I'm talking too */
101 outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
103 byte = inb(smbus_io_base + SMBHSTCTRL);
104 byte &= 0xe3; /* Clear [4:2] */
105 byte |= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
106 outb(byte, smbus_io_base + SMBHSTCTRL);
108 /* poll for transaction completion */
109 if (smbus_wait_until_done(smbus_io_base) < 0) {
110 return -3; /* timeout or error */
113 return 0;
116 int do_smbus_read_byte(u32 smbus_io_base, u32 device,
117 u32 address)
119 u8 byte;
121 if (smbus_wait_until_ready(smbus_io_base) < 0) {
122 return -2; /* not ready */
125 /* set the command/address... */
126 outb(address & 0xff, smbus_io_base + SMBHSTCMD);
128 /* set the device I'm talking too */
129 outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
131 byte = inb(smbus_io_base + SMBHSTCTRL);
132 byte &= 0xe3; /* Clear [4:2] */
133 byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
134 outb(byte, smbus_io_base + SMBHSTCTRL);
136 /* poll for transaction completion */
137 if (smbus_wait_until_done(smbus_io_base) < 0) {
138 return -3; /* timeout or error */
141 /* read results of transaction */
142 byte = inb(smbus_io_base + SMBHSTDAT0);
144 return byte;
147 int do_smbus_write_byte(u32 smbus_io_base, u32 device,
148 u32 address, u8 val)
150 u8 byte;
152 if (smbus_wait_until_ready(smbus_io_base) < 0) {
153 return -2; /* not ready */
156 /* set the command/address... */
157 outb(address & 0xff, smbus_io_base + SMBHSTCMD);
159 /* set the device I'm talking too */
160 outb(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
162 /* output value */
163 outb(val, smbus_io_base + SMBHSTDAT0);
165 byte = inb(smbus_io_base + SMBHSTCTRL);
166 byte &= 0xe3; /* Clear [4:2] */
167 byte |= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
168 outb(byte, smbus_io_base + SMBHSTCTRL);
170 /* poll for transaction completion */
171 if (smbus_wait_until_done(smbus_io_base) < 0) {
172 return -3; /* timeout or error */
175 return 0;
178 void alink_ab_indx(u32 reg_space, u32 reg_addr,
179 u32 mask, u32 val)
181 u32 tmp;
183 outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX);
184 tmp = inl(AB_DATA);
185 /* rpr 4.2
186 * For certain revisions of the chip, the ABCFG registers,
187 * with an address of 0x100NN (where 'N' is any hexadecimal
188 * number), require an extra programming step.*/
189 outl(0, AB_INDX);
191 tmp &= ~mask;
192 tmp |= val;
194 /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | reg_addr); */
195 outl((reg_space & 0x7) << 29 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
196 outl(tmp, AB_DATA);
197 outl(0, AB_INDX);
200 void alink_rc_indx(u32 reg_space, u32 reg_addr, u32 port,
201 u32 mask, u32 val)
203 u32 tmp;
205 outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX);
206 tmp = inl(AB_DATA);
207 /* rpr 4.2
208 * For certain revisions of the chip, the ABCFG registers,
209 * with an address of 0x100NN (where 'N' is any hexadecimal
210 * number), require an extra programming step.*/
211 outl(0, AB_INDX);
213 tmp &= ~mask;
214 tmp |= val;
216 //printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | (port&3) << 24 | reg_addr);
217 outl((reg_space & 0x7) << 29 | (port & 3) << 24 | reg_addr, AB_INDX); /* probably we don't have to do it again. */
218 outl(tmp, AB_DATA);
219 outl(0, AB_INDX);
222 /* space = 0: AX_INDXC, AX_DATAC
223 * space = 1: AX_INDXP, AX_DATAP
225 void alink_ax_indx(u32 space /*c or p? */ , u32 axindc,
226 u32 mask, u32 val)
228 u32 tmp;
230 /* read axindc to tmp */
231 outl(space << 29 | space << 3 | 0x30, AB_INDX);
232 outl(axindc, AB_DATA);
233 outl(0, AB_INDX);
234 outl(space << 29 | space << 3 | 0x34, AB_INDX);
235 tmp = inl(AB_DATA);
236 outl(0, AB_INDX);
238 tmp &= ~mask;
239 tmp |= val;
241 /* write tmp */
242 outl(space << 29 | space << 3 | 0x30, AB_INDX);
243 outl(axindc, AB_DATA);
244 outl(0, AB_INDX);
245 outl(space << 29 | space << 3 | 0x34, AB_INDX);
246 outl(tmp, AB_DATA);
247 outl(0, AB_INDX);
249 #endif