e56a67c1e00eda2a6129c672ae23d70e4c3a6cc0
[coreboot.git] / src / southbridge / intel / i82801dx / i82801dx_smbus.c
1 #include "i82801dx.h"
2 #include <smbus.h>
3 #include <pci.h>
4 #include <arch/io.h>
5
6 #define PM_BUS 0
7 #define PM_DEVFN PCI_DEVFN(0x1f,3)
8
9 #if 0
10 #define SMBUS_IO_BASE 0x1000
11 #define SMBHSTSTAT 0
12 #define SMBHSTCTL  2
13 #define SMBHSTCMD  3
14 #define SMBHSTADD  4
15 #define SMBHSTDAT0 5
16 #define SMBHSTDAT1 6
17 #define SMBBLKDAT  7
18 #endif
19
20 void smbus_enable(void)
21 {
22         unsigned char byte;
23         /* iobase addr */
24         pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x20, SMBUS_IO_BASE | 1);
25         /* smbus enable */
26         pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0x40,  1);
27         /* iospace enable */
28         pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1);
29
30         /* Disable interrupt generation */
31         outb(0, SMBUS_IO_BASE + SMBHSTCTL);
32
33 }
34
35 void smbus_setup(void)
36 {
37         outb(0, SMBUS_IO_BASE + SMBHSTSTAT);
38 }
39
40 static void smbus_wait_until_ready(void)
41 {
42         while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
43                 /* nop */
44         }
45 }
46
47 static void smbus_wait_until_done(void)
48 {
49         unsigned char byte;
50         do {
51                 byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
52         }
53         while((byte &1) == 1);
54         while( (byte & ~1) == 0) {
55                 byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
56         }
57 }
58
59 int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
60 {
61         unsigned char host_status_register;
62         unsigned char byte;
63
64         smbus_wait_until_ready();
65
66         /* setup transaction */
67         /* disable interrupts */
68         outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
69         /* set the device I'm talking too */
70         outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADD);
71         /* set the command/address... */
72         outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
73         /* set up for a byte data read */
74         outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2), SMBUS_IO_BASE + SMBHSTCTL);
75
76         /* clear any lingering errors, so the transaction will run */
77         outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
78
79         /* clear the data byte...*/
80         outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
81
82         /* start the command */
83         outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL);
84
85         /* poll for transaction completion */
86         smbus_wait_until_done();
87
88         host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
89
90         /* read results of transaction */
91         byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
92
93         *result = byte;
94         return host_status_register != 0x02;
95 }