Fix a few whitespace and coding style issues.
[coreboot.git] / src / southbridge / intel / sch / smbus.h
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2005 Yinghai Lu <yinghailu@gmail.com>
5  * Copyright (C) 2009 coresystems GmbH
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * This program 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <device/smbus_def.h>
22
23 static void smbus_delay(void)
24 {
25         inb(0x80);
26 }
27
28 static int smbus_wait_until_ready(u16 smbus_base)
29 {
30         unsigned loops = SMBUS_TIMEOUT;
31         unsigned char byte;
32         do {
33                 smbus_delay();
34                 if (--loops == 0)
35                         break;
36                 byte = inb(smbus_base + SMBHSTSTAT);
37         } while (byte & 1);
38         return loops ? 0 : -1;
39 }
40
41 static int smbus_wait_until_done(u16 smbus_base)
42 {
43         unsigned loops = SMBUS_TIMEOUT;
44         unsigned char byte;
45         do {
46                 smbus_delay();
47                 if (--loops == 0)
48                         break;
49                 byte = inb(smbus_base + SMBHSTSTAT);
50         } while ((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0);
51         return loops ? 0 : -1;
52 }
53
54 static int do_smbus_read_byte(unsigned smbus_base, unsigned device,
55                               unsigned address)
56 {
57         unsigned char global_status_register;
58         unsigned char byte;
59
60         if (smbus_wait_until_ready(smbus_base) < 0) {
61                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
62         }
63         /* Setup transaction */
64         /* Disable interrupts */
65         outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
66         /* Set the device I'm talking too */
67         outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
68         /* Set the command/address... */
69         outb(address & 0xff, smbus_base + SMBHSTCMD);
70         /* Set up for a byte data read */
71         outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
72              (smbus_base + SMBHSTCTL));
73         /* Clear any lingering errors, so the transaction will run */
74         outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
75
76         /* Clear the data byte... */
77         outb(0, smbus_base + SMBHSTDAT0);
78
79         /* Start the command */
80         outb((inb(smbus_base + SMBHSTCTL) | 0x40), smbus_base + SMBHSTCTL);
81
82         /* Poll for transaction completion */
83         if (smbus_wait_until_done(smbus_base) < 0) {
84                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
85         }
86
87         global_status_register = inb(smbus_base + SMBHSTSTAT);
88
89         /* Ignore the "In Use" status... */
90         global_status_register &= ~(3 << 5);
91
92         /* Read results of transaction */
93         byte = inb(smbus_base + SMBHSTDAT0);
94         if (global_status_register != (1 << 1)) {
95                 return SMBUS_ERROR;
96         }
97         return byte;
98 }