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_
21 static inline void smbus_delay(void)
23 outb(inb(0x80), 0x80);
26 static int smbus_wait_until_ready(u32 smbus_io_base
)
29 loops
= SMBUS_TIMEOUT
;
32 val
= inb(smbus_io_base
+ SMBHSTSTAT
);
34 if (val
== 0) { /* ready now */
37 outb(val
, smbus_io_base
+ SMBHSTSTAT
);
39 return -2; /* time out */
42 static int smbus_wait_until_done(u32 smbus_io_base
)
45 loops
= SMBUS_TIMEOUT
;
49 val
= inb(smbus_io_base
+ SMBHSTSTAT
);
50 val
&= 0x1f; /* mask off reserved bits */
52 return -5; /* error */
55 outb(val
, smbus_io_base
+ SMBHSTSTAT
); /* clear status */
59 return -3; /* timeout */
62 int do_smbus_recv_byte(u32 smbus_io_base
, u32 device
)
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
);
89 int do_smbus_send_byte(u32 smbus_io_base
, u32 device
, u8 val
)
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 */
116 int do_smbus_read_byte(u32 smbus_io_base
, u32 device
,
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
);
147 int do_smbus_write_byte(u32 smbus_io_base
, u32 device
,
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
);
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 */
178 void alink_ab_indx(u32 reg_space
, u32 reg_addr
,
183 outl((reg_space
& 0x7) << 29 | reg_addr
, AB_INDX
);
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.*/
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. */
200 void alink_rc_indx(u32 reg_space
, u32 reg_addr
, u32 port
,
205 outl((reg_space
& 0x7) << 29 | (port
& 3) << 24 | reg_addr
, AB_INDX
);
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.*/
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. */
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
,
230 /* read axindc to tmp */
231 outl(space
<< 29 | space
<< 3 | 0x30, AB_INDX
);
232 outl(axindc
, AB_DATA
);
234 outl(space
<< 29 | space
<< 3 | 0x34, AB_INDX
);
242 outl(space
<< 29 | space
<< 3 | 0x30, AB_INDX
);
243 outl(axindc
, AB_DATA
);
245 outl(space
<< 29 | space
<< 3 | 0x34, AB_INDX
);