Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 1 | #define SMBUS_IO_BASE 0x5000 |
| 2 | |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 3 | #define SMBHSTSTAT 0x0 |
| 4 | #define SMBSLVSTAT 0x1 |
| 5 | #define SMBHSTCTL 0x2 |
| 6 | #define SMBHSTCMD 0x3 |
| 7 | #define SMBXMITADD 0x4 |
| 8 | #define SMBHSTDAT0 0x5 |
| 9 | #define SMBHSTDAT1 0x6 |
| 10 | #define SMBBLKDAT 0x7 |
| 11 | #define SMBSLVCTL 0x8 |
| 12 | #define SMBTRNSADD 0x9 |
| 13 | #define SMBSLVDATA 0xa |
| 14 | #define SMLINK_PIN_CTL 0xe |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 15 | #define SMBUS_PIN_CTL 0xf |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 16 | |
| 17 | /* Define register settings */ |
| 18 | #define HOST_RESET 0xff |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 19 | #define READ_CMD 0x01 // 1 in the 0 bit of SMBHSTADD states to READ |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 20 | |
Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 21 | |
| 22 | #define SMBUS_TIMEOUT (100*1000*10) |
| 23 | |
| 24 | static void enable_smbus(void) |
| 25 | { |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 26 | device_t dev; |
| 27 | unsigned char c; |
| 28 | /* Power management controller */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 29 | dev = pci_locate_device(PCI_ID(0x1106, 0x8235), 0); |
| 30 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 31 | if (dev == PCI_DEV_INVALID) { |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 32 | die("SMBUS controller not found\n"); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 33 | } |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 34 | // set IO base address to SMBUS_IO_BASE |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 35 | pci_write_config32(dev, 0x90, SMBUS_IO_BASE | 1); |
| 36 | |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 37 | // Enable SMBus |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 38 | c = pci_read_config8(dev, 0xd2); |
| 39 | c |= 5; |
| 40 | pci_write_config8(dev, 0xd2, c); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 41 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 42 | /* make it work for I/O ... |
| 43 | */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 44 | dev = pci_locate_device(PCI_ID(0x1106, 0x8231), 0); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 45 | c = pci_read_config8(dev, 4); |
| 46 | c |= 1; |
| 47 | pci_write_config8(dev, 4, c); |
Ronald G. Minnich | 88fbae2 | 2003-10-22 21:54:19 +0000 | [diff] [blame] | 48 | print_debug_hex8(c); |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 49 | print_debug(" is the comm register\n"); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 50 | |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 51 | print_debug("SMBus controller enabled\n"); |
Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | |
| 55 | static inline void smbus_delay(void) |
| 56 | { |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 57 | outb(0x80, 0x80); |
Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 58 | } |
| 59 | |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 60 | static int smbus_wait_until_active(void) |
| 61 | { |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 62 | unsigned long loops; |
| 63 | loops = SMBUS_TIMEOUT; |
| 64 | do { |
| 65 | unsigned char val; |
| 66 | smbus_delay(); |
| 67 | val = inb(SMBUS_IO_BASE + SMBHSTSTAT); |
| 68 | if ((val & 1)) { |
| 69 | break; |
| 70 | } |
| 71 | } while (--loops); |
| 72 | return loops ? 0 : -4; |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 73 | } |
| 74 | |
Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 75 | static int smbus_wait_until_ready(void) |
| 76 | { |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 77 | unsigned long loops; |
| 78 | loops = SMBUS_TIMEOUT; |
| 79 | do { |
| 80 | unsigned char val; |
| 81 | smbus_delay(); |
| 82 | val = inb(SMBUS_IO_BASE + SMBHSTSTAT); |
| 83 | if ((val & 1) == 0) { |
| 84 | break; |
| 85 | } |
| 86 | if (loops == (SMBUS_TIMEOUT / 2)) { |
| 87 | outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); |
| 88 | } |
| 89 | } while (--loops); |
| 90 | return loops ? 0 : -2; |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 91 | } |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 92 | |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 93 | static int smbus_wait_until_done(void) |
| 94 | { |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 95 | unsigned long loops; |
| 96 | loops = SMBUS_TIMEOUT; |
| 97 | do { |
| 98 | unsigned char val; |
| 99 | smbus_delay(); |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 100 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 101 | val = inb(SMBUS_IO_BASE + SMBHSTSTAT); |
| 102 | if ((val & 1) == 0) { |
| 103 | break; |
| 104 | } |
| 105 | } while (--loops); |
| 106 | return loops ? 0 : -3; |
Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 107 | } |
| 108 | |
Stefan Reinauer | 8a926845 | 2010-04-07 03:40:37 +0000 | [diff] [blame] | 109 | #if 0 |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 110 | void smbus_reset(void) |
| 111 | { |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 112 | outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT); |
| 113 | outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT); |
| 114 | outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT); |
| 115 | outb(HOST_RESET, SMBUS_IO_BASE + SMBHSTSTAT); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 116 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 117 | smbus_wait_until_ready(); |
Ronald G. Minnich | 88fbae2 | 2003-10-22 21:54:19 +0000 | [diff] [blame] | 118 | print_debug("After reset status "); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 119 | print_debug_hex8(inb(SMBUS_IO_BASE + SMBHSTSTAT)); |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 120 | print_debug("\n"); |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 121 | } |
Stefan Reinauer | 8a926845 | 2010-04-07 03:40:37 +0000 | [diff] [blame] | 122 | #endif |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 123 | |
Stefan Reinauer | 8a926845 | 2010-04-07 03:40:37 +0000 | [diff] [blame] | 124 | #if CONFIG_DEBUG_SMBUS |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 125 | static void smbus_print_error(unsigned char host_status_register) |
Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 126 | { |
Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 127 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 128 | print_err("smbus_error: "); |
| 129 | print_err_hex8(host_status_register); |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 130 | print_err("\n"); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 131 | if (host_status_register & (1 << 4)) { |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 132 | print_err("Interrup/SMI# was Failed Bus Transaction\n"); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 133 | } |
| 134 | if (host_status_register & (1 << 3)) { |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 135 | print_err("Bus Error\n"); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 136 | } |
| 137 | if (host_status_register & (1 << 2)) { |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 138 | print_err("Device Error\n"); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 139 | } |
| 140 | if (host_status_register & (1 << 1)) { |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 141 | print_err("Interrupt/SMI# was Successful Completion\n"); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 142 | } |
| 143 | if (host_status_register & (1 << 0)) { |
Stefan Reinauer | 64ed2b7 | 2010-03-31 14:47:43 +0000 | [diff] [blame] | 144 | print_err("Host Busy\n"); |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 145 | } |
Ronald G. Minnich | c817926 | 2003-09-26 04:45:52 +0000 | [diff] [blame] | 146 | } |
Stefan Reinauer | 8a926845 | 2010-04-07 03:40:37 +0000 | [diff] [blame] | 147 | #endif |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 148 | |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 149 | /* |
| 150 | * Copied from intel/i82801dbm early smbus code - suggested by rgm. |
| 151 | * Modifications/check against i2c-viapro driver code from linux-2.4.22 |
| 152 | * and VT8231 Reference Docs - mw. |
| 153 | */ |
| 154 | static int smbus_read_byte(unsigned device, unsigned address) |
| 155 | { |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 156 | unsigned char global_status_register; |
| 157 | unsigned char byte; |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 158 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 159 | if (smbus_wait_until_ready() < 0) { |
| 160 | outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); |
| 161 | if (smbus_wait_until_ready() < 0) { |
| 162 | return -2; |
| 163 | } |
| 164 | } |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 165 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 166 | /* setup transaction */ |
| 167 | /* disable interrupts */ |
| 168 | outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xfe, SMBUS_IO_BASE + SMBHSTCTL); |
| 169 | /* set the device I'm talking too */ |
| 170 | outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD); |
| 171 | /* set the command/address... */ |
| 172 | outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD); |
| 173 | /* set up for a byte data read */ |
| 174 | outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xe3) | (0x2 << 2), SMBUS_IO_BASE + SMBHSTCTL); |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 175 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 176 | /* clear any lingering errors, so the transaction will run */ |
| 177 | outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 178 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 179 | /* clear the data byte... */ |
| 180 | outb(0, SMBUS_IO_BASE + SMBHSTDAT0); |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 181 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 182 | /* start a byte read, with interrupts disabled */ |
| 183 | outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL); |
| 184 | /* poll for it to start */ |
| 185 | if (smbus_wait_until_active() < 0) { |
| 186 | return -4; |
| 187 | } |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 188 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 189 | /* poll for transaction completion */ |
| 190 | if (smbus_wait_until_done() < 0) { |
| 191 | return -3; |
| 192 | } |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 193 | |
| 194 | /* Ignore the Host Busy & Command Complete ? */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 195 | global_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT) & ~((1 << 1) | (1 << 0)); |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 196 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 197 | /* read results of transaction */ |
| 198 | byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 199 | |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 200 | if (global_status_register != 0) { |
| 201 | return -1; |
| 202 | } |
| 203 | return byte; |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 204 | } |
| 205 | |
| 206 | #if 0 |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 207 | /* SMBus routines borrowed from VIA's Trident Driver */ |
| 208 | /* this works, so I am not going to touch it for now -- rgm */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 209 | static unsigned char smbus_read_byte(unsigned char devAdr, unsigned char bIndex) |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 210 | { |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 211 | unsigned int i; |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 212 | unsigned char bData; |
| 213 | unsigned char sts = 0; |
| 214 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 215 | /* clear host status */ |
| 216 | outb(0xff, SMBUS_IO_BASE); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 217 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 218 | /* check SMBUS ready */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 219 | for (i = 0; i < SMBUS_TIMEOUT; i++) |
| 220 | if ((inb(SMBUS_IO_BASE) & 0x01) == 0) |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 221 | break; |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 222 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 223 | /* set host command */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 224 | outb(bIndex, SMBUS_IO_BASE + 3); |
| 225 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 226 | /* set slave address */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 227 | outb(devAdr | 0x01, SMBUS_IO_BASE + 4); |
| 228 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 229 | /* start */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 230 | outb(0x48, SMBUS_IO_BASE + 2); |
| 231 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 232 | /* SMBUS Wait Ready */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 233 | for (i = 0; i < SMBUS_TIMEOUT; i++) |
| 234 | if (((sts = inb(SMBUS_IO_BASE)) & 0x01) == 0) |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 235 | break; |
| 236 | if ((sts & ~3) != 0) { |
| 237 | smbus_print_error(sts); |
| 238 | return 0; |
| 239 | } |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 240 | bData = inb(SMBUS_IO_BASE + 5); |
| 241 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 242 | return bData; |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 243 | |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 244 | } |
Mark Wilkinson | e1bc97b | 2004-12-01 16:57:37 +0000 | [diff] [blame] | 245 | #endif |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 246 | /* for reference, here is the fancier version which we will use at some |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 247 | * point |
| 248 | */ |
| 249 | # if 0 |
| 250 | int smbus_read_byte(unsigned device, unsigned address, unsigned char *result) |
| 251 | { |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 252 | unsigned char host_status_register; |
| 253 | unsigned char byte; |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 254 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 255 | reset(); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 256 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 257 | smbus_wait_until_ready(); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 258 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 259 | /* setup transaction */ |
| 260 | /* disable interrupts */ |
| 261 | outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL); |
| 262 | /* set the device I'm talking too */ |
| 263 | outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD); |
| 264 | /* set the command/address... */ |
| 265 | outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD); |
| 266 | /* set up for a byte data read */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 267 | outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2), SMBUS_IO_BASE + SMBHSTCTL); |
| 268 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 269 | /* clear any lingering errors, so the transaction will run */ |
| 270 | outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 271 | |
| 272 | /* clear the data byte... */ |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 273 | outb(0, SMBUS_IO_BASE + SMBHSTDAT0); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 274 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 275 | /* start the command */ |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 276 | outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL); |
| 277 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 278 | /* poll for transaction completion */ |
| 279 | smbus_wait_until_done(); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 280 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 281 | host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 282 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 283 | /* Ignore the In Use Status... */ |
| 284 | host_status_register &= ~(1 << 6); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 285 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 286 | /* read results of transaction */ |
| 287 | byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); |
| 288 | smbus_print_error(byte); |
arch import user (historical) | 80e3d96 | 2005-07-06 18:17:33 +0000 | [diff] [blame] | 289 | |
Eric Biederman | 83b991a | 2003-10-11 06:20:25 +0000 | [diff] [blame] | 290 | *result = byte; |
| 291 | return host_status_register != 0x02; |
Ronald G. Minnich | 320c6a0 | 2003-10-01 01:45:43 +0000 | [diff] [blame] | 292 | } |
| 293 | |
| 294 | |
| 295 | #endif |