2 * This file is part of the coreboot project.
4 * Copyright (C) 2012 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.
19 #include <console/console.h> /* printk */
21 static int smbus_wait_until_ready(u32 smbus_io_base
)
25 loops
= SMBUS_TIMEOUT
;
28 val
= inb(smbus_io_base
+ SMBHSTSTAT
);
30 if (val
== 0) { /* ready now */
33 outb(val
, smbus_io_base
+ SMBHSTSTAT
);
36 return -2; /* time out */
39 static int smbus_wait_until_done(u32 smbus_io_base
)
43 loops
= SMBUS_TIMEOUT
;
47 val
= inb(smbus_io_base
+ SMBHSTSTAT
);
48 val
&= 0x1f; /* mask off reserved bits */
50 return -5; /* error */
53 outb(val
, smbus_io_base
+ SMBHSTSTAT
); /* clear status */
58 return -3; /* timeout */
61 int do_smbus_recv_byte(u32 smbus_io_base
, u32 device
)
65 if (smbus_wait_until_ready(smbus_io_base
) < 0) {
66 return -2; /* not ready */
69 printk(BIOS_SPEW
, "SB700 - Smbus.c - do_smbus_recv_byte - Start.\n");
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 printk(BIOS_SPEW
, "SB700 - Smbus.c - do_smbus_recv_byte - End.\n");
90 int do_smbus_send_byte(u32 smbus_io_base
, u32 device
, u8 val
)
94 if (smbus_wait_until_ready(smbus_io_base
) < 0) {
95 return -2; /* not ready */
98 printk(BIOS_SPEW
, "SB700 - Smbus.c - do_smbus_send_byte - Start.\n");
99 /* set the command... */
100 outb(val
, smbus_io_base
+ SMBHSTCMD
);
102 /* set the device I'm talking too */
103 outb(((device
& 0x7f) << 1) | 0, smbus_io_base
+ SMBHSTADDR
);
105 byte
= inb(smbus_io_base
+ SMBHSTCTRL
);
106 byte
&= 0xe3; /* Clear [4:2] */
107 byte
|= (1 << 2) | (1 << 6); /* Byte data read/write command, start the command */
108 outb(byte
, smbus_io_base
+ SMBHSTCTRL
);
110 /* poll for transaction completion */
111 if (smbus_wait_until_done(smbus_io_base
) < 0) {
112 return -3; /* timeout or error */
115 printk(BIOS_SPEW
, "SB700 - Smbus.c - do_smbus_send_byte - End.\n");
119 int do_smbus_read_byte(u32 smbus_io_base
, u32 device
, u32 address
)
123 if (smbus_wait_until_ready(smbus_io_base
) < 0) {
124 return -2; /* not ready */
127 printk(BIOS_SPEW
, "SB700 - Smbus.c - do_smbus_read_byte - Start.\n");
128 /* set the command/address... */
129 outb(address
& 0xff, smbus_io_base
+ SMBHSTCMD
);
131 /* set the device I'm talking too */
132 outb(((device
& 0x7f) << 1) | 1, smbus_io_base
+ SMBHSTADDR
);
134 byte
= inb(smbus_io_base
+ SMBHSTCTRL
);
135 byte
&= 0xe3; /* Clear [4:2] */
136 byte
|= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
137 outb(byte
, smbus_io_base
+ SMBHSTCTRL
);
139 /* poll for transaction completion */
140 if (smbus_wait_until_done(smbus_io_base
) < 0) {
141 return -3; /* timeout or error */
144 /* read results of transaction */
145 byte
= inb(smbus_io_base
+ SMBHSTDAT0
);
147 printk(BIOS_SPEW
, "SB700 - Smbus.c - do_smbus_read_byte - End.\n");
151 int do_smbus_write_byte(u32 smbus_io_base
, u32 device
, u32 address
, u8 val
)
155 if (smbus_wait_until_ready(smbus_io_base
) < 0) {
156 return -2; /* not ready */
159 printk(BIOS_SPEW
, "SB700 - Smbus.c - do_smbus_write_byte - Start.\n");
160 /* set the command/address... */
161 outb(address
& 0xff, smbus_io_base
+ SMBHSTCMD
);
163 /* set the device I'm talking too */
164 outb(((device
& 0x7f) << 1) | 0, smbus_io_base
+ SMBHSTADDR
);
167 outb(val
, smbus_io_base
+ SMBHSTDAT0
);
169 byte
= inb(smbus_io_base
+ SMBHSTCTRL
);
170 byte
&= 0xe3; /* Clear [4:2] */
171 byte
|= (1 << 3) | (1 << 6); /* Byte data read/write command, start the command */
172 outb(byte
, smbus_io_base
+ SMBHSTCTRL
);
174 /* poll for transaction completion */
175 if (smbus_wait_until_done(smbus_io_base
) < 0) {
176 return -3; /* timeout or error */
179 printk(BIOS_SPEW
, "SB700 - Smbus.c - do_smbus_write_byte - End.\n");
183 void alink_ab_indx(u32 reg_space
, u32 reg_addr
, u32 mask
, u32 val
)
187 printk(BIOS_SPEW
, "SB700 - Smbus.c - alink_ab_indx - Start.\n");
188 outl((reg_space
& 0x7) << 29 | reg_addr
, AB_INDX
);
191 * For certain revisions of the chip, the ABCFG registers,
192 * with an address of 0x100NN (where 'N' is any hexadecimal
193 * number), require an extra programming step.*/
199 /* printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | reg_addr); */
200 outl((reg_space
& 0x7) << 29 | reg_addr
, AB_INDX
); /* probably we don't have to do it again. */
203 printk(BIOS_SPEW
, "SB700 - Smbus.c - alink_ab_indx - End.\n");
206 void alink_rc_indx(u32 reg_space
, u32 reg_addr
, u32 port
, u32 mask
, u32 val
)
210 printk(BIOS_SPEW
, "SB700 - Smbus.c - alink_rc_indx - Start.\n");
211 outl((reg_space
& 0x7) << 29 | (port
& 3) << 24 | reg_addr
, AB_INDX
);
214 * For certain revisions of the chip, the ABCFG registers,
215 * with an address of 0x100NN (where 'N' is any hexadecimal
216 * number), require an extra programming step.*/
222 //printk(BIOS_DEBUG, "about write %x, index=%x", tmp, (reg_space&0x3)<<29 | (port&3) << 24 | reg_addr);
223 outl((reg_space
& 0x7) << 29 | (port
& 3) << 24 | reg_addr
, AB_INDX
); /* probably we don't have to do it again. */
226 printk(BIOS_SPEW
, "SB700 - Smbus.c - alink_rc_indx - End.\n");
229 /* space = 0: AX_INDXC, AX_DATAC
230 * space = 1: AX_INDXP, AX_DATAP
232 void alink_ax_indx(u32 space
/*c or p? */ , u32 axindc
, u32 mask
, u32 val
)
236 printk(BIOS_SPEW
, "SB700 - Smbus.c - alink_ax_indx - Start.\n");
237 /* read axindc to tmp */
238 outl(space
<< 29 | space
<< 3 | 0x30, AB_INDX
);
239 outl(axindc
, AB_DATA
);
241 outl(space
<< 29 | space
<< 3 | 0x34, AB_INDX
);
249 outl(space
<< 29 | space
<< 3 | 0x30, AB_INDX
);
250 outl(axindc
, AB_DATA
);
252 outl(space
<< 29 | space
<< 3 | 0x34, AB_INDX
);
255 printk(BIOS_SPEW
, "SB700 - Smbus.c - alink_ax_indx - End.\n");