2 * This file is part of the coreboot project.
4 * Copyright (C) 2004 Ronald G. Minnich
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.
22 #define PM_DEVFN PCI_DEVFN(0x1f,3)
24 void smbus_enable(void)
28 pcibios_write_config_dword(PM_BUS
, PM_DEVFN
, 0x20, SMBUS_IO_BASE
| 1);
30 pcibios_write_config_byte(PM_BUS
, PM_DEVFN
, 0x40, 1);
32 pcibios_write_config_word(PM_BUS
, PM_DEVFN
, 0x4, 1);
34 /* Disable interrupt generation */
35 outb(0, SMBUS_IO_BASE
+ SMBHSTCTL
);
39 void smbus_setup(void)
41 outb(0, SMBUS_IO_BASE
+ SMBHSTSTAT
);
44 static void smbus_wait_until_ready(void)
46 while ((inb(SMBUS_IO_BASE
+ SMBHSTSTAT
) & 1) == 1) {
51 static void smbus_wait_until_done(void)
55 byte
= inb(SMBUS_IO_BASE
+ SMBHSTSTAT
);
57 while ((byte
& 1) == 1);
58 while ((byte
& ~1) == 0) {
59 byte
= inb(SMBUS_IO_BASE
+ SMBHSTSTAT
);
63 int smbus_read_byte(unsigned device
, unsigned address
, unsigned char *result
)
65 unsigned char host_status_register
;
68 smbus_wait_until_ready();
70 /* setup transaction */
71 /* disable interrupts */
72 outb(inb(SMBUS_IO_BASE
+ SMBHSTCTL
) & (~1), SMBUS_IO_BASE
+ SMBHSTCTL
);
73 /* set the device I'm talking too */
74 outb(((device
& 0x7f) << 1) | 1, SMBUS_IO_BASE
+ SMBHSTADD
);
75 /* set the command/address... */
76 outb(address
& 0xFF, SMBUS_IO_BASE
+ SMBHSTCMD
);
77 /* set up for a byte data read */
78 outb((inb(SMBUS_IO_BASE
+ SMBHSTCTL
) & 0xE3) | (0x2 << 2),
79 SMBUS_IO_BASE
+ SMBHSTCTL
);
81 /* clear any lingering errors, so the transaction will run */
82 outb(inb(SMBUS_IO_BASE
+ SMBHSTSTAT
), SMBUS_IO_BASE
+ SMBHSTSTAT
);
84 /* clear the data byte... */
85 outb(0, SMBUS_IO_BASE
+ SMBHSTDAT0
);
87 /* start the command */
88 outb((inb(SMBUS_IO_BASE
+ SMBHSTCTL
) | 0x40),
89 SMBUS_IO_BASE
+ SMBHSTCTL
);
91 /* poll for transaction completion */
92 smbus_wait_until_done();
94 host_status_register
= inb(SMBUS_IO_BASE
+ SMBHSTSTAT
);
96 /* read results of transaction */
97 byte
= inb(SMBUS_IO_BASE
+ SMBHSTDAT0
);
100 return host_status_register
!= 0x02;