aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-i801.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-i801.c')
-rw-r--r--drivers/i2c/busses/i2c-i801.c200
1 files changed, 102 insertions, 98 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 73bd8552734c..46aa41f73fdd 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -4,7 +4,7 @@
4 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, 4 Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
5 Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker 5 Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
6 <mdsxyz123@yahoo.com> 6 <mdsxyz123@yahoo.com>
7 Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> 7 Copyright (C) 2007, 2008 Jean Delvare <khali@linux-fr.org>
8 8
9 This program is free software; you can redistribute it and/or modify 9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by 10 it under the terms of the GNU General Public License as published by
@@ -121,6 +121,10 @@
121#define SMBHSTSTS_INTR 0x02 121#define SMBHSTSTS_INTR 0x02
122#define SMBHSTSTS_HOST_BUSY 0x01 122#define SMBHSTSTS_HOST_BUSY 0x01
123 123
124#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \
125 SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
126 SMBHSTSTS_INTR)
127
124static unsigned long i801_smba; 128static unsigned long i801_smba;
125static unsigned char i801_original_hstcfg; 129static unsigned char i801_original_hstcfg;
126static struct pci_driver i801_driver; 130static struct pci_driver i801_driver;
@@ -132,72 +136,114 @@ static struct pci_dev *I801_dev;
132#define FEATURE_I2C_BLOCK_READ (1 << 3) 136#define FEATURE_I2C_BLOCK_READ (1 << 3)
133static unsigned int i801_features; 137static unsigned int i801_features;
134 138
135static int i801_transaction(int xact) 139/* Make sure the SMBus host is ready to start transmitting.
140 Return 0 if it is, -EBUSY if it is not. */
141static int i801_check_pre(void)
136{ 142{
137 int status; 143 int status;
138 int result = 0;
139 int timeout = 0;
140 144
141 /* Make sure the SMBus host is ready to start transmitting */ 145 status = inb_p(SMBHSTSTS);
142 /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ 146 if (status & SMBHSTSTS_HOST_BUSY) {
143 if ((status = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { 147 dev_err(&I801_dev->dev, "SMBus is busy, can't use it!\n");
144 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n", 148 return -EBUSY;
149 }
150
151 status &= STATUS_FLAGS;
152 if (status) {
153 dev_dbg(&I801_dev->dev, "Clearing status flags (%02x)\n",
145 status); 154 status);
146 outb_p(status, SMBHSTSTS); 155 outb_p(status, SMBHSTSTS);
147 if ((status = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { 156 status = inb_p(SMBHSTSTS) & STATUS_FLAGS;
148 dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", status); 157 if (status) {
158 dev_err(&I801_dev->dev,
159 "Failed clearing status flags (%02x)\n",
160 status);
149 return -EBUSY; 161 return -EBUSY;
150 } else {
151 dev_dbg(&I801_dev->dev, "Successful!\n");
152 } 162 }
153 } 163 }
154 164
155 /* the current contents of SMBHSTCNT can be overwritten, since PEC, 165 return 0;
156 * INTREN, SMBSCMD are passed in xact */ 166}
157 outb_p(xact | I801_START, SMBHSTCNT);
158 167
159 /* We will always wait for a fraction of a second! */ 168/* Convert the status register to an error code, and clear it. */
160 do { 169static int i801_check_post(int status, int timeout)
161 msleep(1); 170{
162 status = inb_p(SMBHSTSTS); 171 int result = 0;
163 } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
164 172
165 /* If the SMBus is still busy, we give up */ 173 /* If the SMBus is still busy, we give up */
166 if (timeout >= MAX_TIMEOUT) { 174 if (timeout) {
167 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); 175 dev_err(&I801_dev->dev, "Transaction timeout\n");
168 result = -ETIMEDOUT;
169 /* try to stop the current command */ 176 /* try to stop the current command */
170 dev_dbg(&I801_dev->dev, "Terminating the current operation\n"); 177 dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
171 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT); 178 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
172 msleep(1); 179 msleep(1);
173 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT); 180 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
181
182 /* Check if it worked */
183 status = inb_p(SMBHSTSTS);
184 if ((status & SMBHSTSTS_HOST_BUSY) ||
185 !(status & SMBHSTSTS_FAILED))
186 dev_err(&I801_dev->dev,
187 "Failed terminating the transaction\n");
188 outb_p(STATUS_FLAGS, SMBHSTSTS);
189 return -ETIMEDOUT;
174 } 190 }
175 191
176 if (status & SMBHSTSTS_FAILED) { 192 if (status & SMBHSTSTS_FAILED) {
177 result = -EIO; 193 result = -EIO;
178 dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); 194 dev_err(&I801_dev->dev, "Transaction failed\n");
195 }
196 if (status & SMBHSTSTS_DEV_ERR) {
197 result = -ENXIO;
198 dev_dbg(&I801_dev->dev, "No response\n");
179 } 199 }
180
181 if (status & SMBHSTSTS_BUS_ERR) { 200 if (status & SMBHSTSTS_BUS_ERR) {
182 result = -EAGAIN; 201 result = -EAGAIN;
183 dev_dbg(&I801_dev->dev, "Lost arbitration\n"); 202 dev_dbg(&I801_dev->dev, "Lost arbitration\n");
184 } 203 }
185 204
186 if (status & SMBHSTSTS_DEV_ERR) { 205 if (result) {
187 result = -ENXIO; 206 /* Clear error flags */
188 dev_dbg(&I801_dev->dev, "Error: no response!\n"); 207 outb_p(status & STATUS_FLAGS, SMBHSTSTS);
208 status = inb_p(SMBHSTSTS) & STATUS_FLAGS;
209 if (status) {
210 dev_warn(&I801_dev->dev, "Failed clearing status "
211 "flags at end of transaction (%02x)\n",
212 status);
213 }
189 } 214 }
190 215
191 if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
192 outb_p(inb(SMBHSTSTS), SMBHSTSTS);
193
194 if ((status = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
195 dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
196 "(%02x)\n", status);
197 }
198 return result; 216 return result;
199} 217}
200 218
219static int i801_transaction(int xact)
220{
221 int status;
222 int result;
223 int timeout = 0;
224
225 result = i801_check_pre();
226 if (result < 0)
227 return result;
228
229 /* the current contents of SMBHSTCNT can be overwritten, since PEC,
230 * INTREN, SMBSCMD are passed in xact */
231 outb_p(xact | I801_START, SMBHSTCNT);
232
233 /* We will always wait for a fraction of a second! */
234 do {
235 msleep(1);
236 status = inb_p(SMBHSTSTS);
237 } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
238
239 result = i801_check_post(status, timeout >= MAX_TIMEOUT);
240 if (result < 0)
241 return result;
242
243 outb_p(SMBHSTSTS_INTR, SMBHSTSTS);
244 return 0;
245}
246
201/* wait for INTR bit as advised by Intel */ 247/* wait for INTR bit as advised by Intel */
202static void i801_wait_hwpec(void) 248static void i801_wait_hwpec(void)
203{ 249{
@@ -256,9 +302,12 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
256 int i, len; 302 int i, len;
257 int smbcmd; 303 int smbcmd;
258 int status; 304 int status;
259 int result = 0; 305 int result;
260 int timeout; 306 int timeout;
261 unsigned char errmask; 307
308 result = i801_check_pre();
309 if (result < 0)
310 return result;
262 311
263 len = data->block[0]; 312 len = data->block[0];
264 313
@@ -282,31 +331,6 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
282 } 331 }
283 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); 332 outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
284 333
285 /* Make sure the SMBus host is ready to start transmitting */
286 status = inb_p(SMBHSTSTS);
287 if (i == 1) {
288 /* Erroneous conditions before transaction:
289 * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
290 errmask = 0x9f;
291 } else {
292 /* Erroneous conditions during transaction:
293 * Failed, Bus_Err, Dev_Err, Intr */
294 errmask = 0x1e;
295 }
296 if (status & errmask) {
297 dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
298 "Resetting...\n", status);
299 outb_p(status, SMBHSTSTS);
300 if (((status = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
301 dev_err(&I801_dev->dev,
302 "Reset failed! (%02x)\n", status);
303 return -EBUSY;
304 }
305 if (i != 1)
306 /* if die in middle of block transaction, fail */
307 return -EIO;
308 }
309
310 if (i == 1) 334 if (i == 1)
311 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); 335 outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
312 336
@@ -319,36 +343,23 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
319 while ((!(status & SMBHSTSTS_BYTE_DONE)) 343 while ((!(status & SMBHSTSTS_BYTE_DONE))
320 && (timeout++ < MAX_TIMEOUT)); 344 && (timeout++ < MAX_TIMEOUT));
321 345
322 /* If the SMBus is still busy, we give up */ 346 result = i801_check_post(status, timeout >= MAX_TIMEOUT);
323 if (timeout >= MAX_TIMEOUT) { 347 if (result < 0)
324 /* try to stop the current command */ 348 return result;
325 dev_dbg(&I801_dev->dev, "Terminating the current "
326 "operation\n");
327 outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
328 msleep(1);
329 outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
330 SMBHSTCNT);
331 result = -ETIMEDOUT;
332 dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
333 }
334
335 if (status & SMBHSTSTS_FAILED) {
336 result = -EIO;
337 dev_dbg(&I801_dev->dev,
338 "Error: Failed bus transaction\n");
339 } else if (status & SMBHSTSTS_BUS_ERR) {
340 result = -EAGAIN;
341 dev_dbg(&I801_dev->dev, "Lost arbitration\n");
342 } else if (status & SMBHSTSTS_DEV_ERR) {
343 result = -ENXIO;
344 dev_dbg(&I801_dev->dev, "Error: no response!\n");
345 }
346 349
347 if (i == 1 && read_write == I2C_SMBUS_READ 350 if (i == 1 && read_write == I2C_SMBUS_READ
348 && command != I2C_SMBUS_I2C_BLOCK_DATA) { 351 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
349 len = inb_p(SMBHSTDAT0); 352 len = inb_p(SMBHSTDAT0);
350 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) 353 if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
354 dev_err(&I801_dev->dev,
355 "Illegal SMBus block read size %d\n",
356 len);
357 /* Recover */
358 while (inb_p(SMBHSTSTS) & SMBHSTSTS_HOST_BUSY)
359 outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS);
360 outb_p(SMBHSTSTS_INTR, SMBHSTSTS);
351 return -EPROTO; 361 return -EPROTO;
362 }
352 data->block[0] = len; 363 data->block[0] = len;
353 } 364 }
354 365
@@ -357,19 +368,12 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
357 data->block[i] = inb_p(SMBBLKDAT); 368 data->block[i] = inb_p(SMBBLKDAT);
358 if (read_write == I2C_SMBUS_WRITE && i+1 <= len) 369 if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
359 outb_p(data->block[i+1], SMBBLKDAT); 370 outb_p(data->block[i+1], SMBBLKDAT);
360 if ((status & 0x9e) != 0x00)
361 outb_p(status, SMBHSTSTS); /* signals SMBBLKDAT ready */
362 371
363 if ((status = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { 372 /* signals SMBBLKDAT ready */
364 dev_dbg(&I801_dev->dev, 373 outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS);
365 "Bad status (%02x) at end of transaction\n",
366 status);
367 }
368
369 if (result < 0)
370 return result;
371 } 374 }
372 return result; 375
376 return 0;
373} 377}
374 378
375static int i801_set_block_buffer_mode(void) 379static int i801_set_block_buffer_mode(void)