Move MMCONF resource into the domain for fam10 for the resource allocator.
[coreboot.git] / src / southbridge / intel / i3100 / i3100_smbus.h
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2008 Arastra, Inc.
5  *
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.
9  *
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.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 /* This code is based on src/southbridge/intel/esb6300/esb6300_smbus.h */
21
22 #include <device/smbus_def.h>
23
24 #define SMBHSTSTAT 0x0
25 #define SMBHSTCTL  0x2
26 #define SMBHSTCMD  0x3
27 #define SMBXMITADD 0x4
28 #define SMBHSTDAT0 0x5
29 #define SMBHSTDAT1 0x6
30 #define SMBBLKDAT  0x7
31 #define SMBTRNSADD 0x9
32 #define SMBSLVDATA 0xa
33 #define SMLINK_PIN_CTL 0xe
34 #define SMBUS_PIN_CTL  0xf
35 #define SMBSLVCMD  0x11
36
37 #define SMBUS_TIMEOUT (100*1000*10)
38
39 static void smbus_delay(void)
40 {
41         outb(0x80, 0x80);
42 }
43
44 static int smbus_wait_until_ready(u32 smbus_io_base)
45 {
46         u32 loops = SMBUS_TIMEOUT;
47         u8 byte;
48         do {
49                 smbus_delay();
50                 if (--loops == 0)
51                         break;
52                 byte = inb(smbus_io_base + SMBHSTSTAT);
53         } while (byte & 1);
54         return loops ? 0 : -1;
55 }
56
57 static int smbus_wait_until_done(u32 smbus_io_base)
58 {
59         u32 loops = SMBUS_TIMEOUT;
60         u8 byte;
61         do {
62                 smbus_delay();
63                 if (--loops == 0)
64                         break;
65                 byte = inb(smbus_io_base + SMBHSTSTAT);
66         } while ((byte & 1) || (byte & ~((1 << 6)|(1 << 0))) == 0);
67         return loops ? 0 : -1;
68 }
69
70 static int do_smbus_read_byte(u32 smbus_io_base, u16 device, u8 address)
71 {
72         u8 global_status_register;
73         u8 byte;
74
75         if (smbus_wait_until_ready(smbus_io_base) < 0) {
76                 return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
77         }
78         /* setup transaction */
79         /* disable interrupts */
80         outb(inb(smbus_io_base + SMBHSTCTL) & (~1), smbus_io_base + SMBHSTCTL);
81         /* set the device I'm talking too */
82         outb(((device & 0x7f) << 1) | 1, smbus_io_base + SMBXMITADD);
83         /* set the command/address... */
84         outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
85         /* set up for a byte data read */
86         outb((inb(smbus_io_base + SMBHSTCTL) & 0xE3) | (0x2 << 2), smbus_io_base + SMBHSTCTL);
87         /* clear any lingering errors, so the transaction will run */
88         outb(inb(smbus_io_base + SMBHSTSTAT), smbus_io_base + SMBHSTSTAT);
89
90         /* clear the data byte...*/
91         outb(0, smbus_io_base + SMBHSTDAT0);
92
93         /* start the command */
94         outb((inb(smbus_io_base + SMBHSTCTL) | 0x40), smbus_io_base + SMBHSTCTL);
95
96         /* poll for transaction completion */
97         if (smbus_wait_until_done(smbus_io_base) < 0) {
98                 return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
99         }
100
101         global_status_register = inb(smbus_io_base + SMBHSTSTAT);
102
103         /* Ignore the In Use Status... */
104         global_status_register &= ~(3 << 5);
105
106         /* read results of transaction */
107         byte = inb(smbus_io_base + SMBHSTDAT0);
108         if (global_status_register != (1 << 1)) {
109                 return SMBUS_ERROR;
110         }
111         return byte;
112 }