1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61#include <linux/module.h>
62#include <linux/pci.h>
63#include <linux/kernel.h>
64#include <linux/stddef.h>
65#include <linux/ioport.h>
66#include <linux/delay.h>
67#include <linux/i2c.h>
68#include <linux/init.h>
69#include <linux/acpi.h>
70#include <linux/io.h>
71
72
73#define SMBHSTSTS (0 + ali15x3_smba)
74#define SMBHSTCNT (1 + ali15x3_smba)
75#define SMBHSTSTART (2 + ali15x3_smba)
76#define SMBHSTCMD (7 + ali15x3_smba)
77#define SMBHSTADD (3 + ali15x3_smba)
78#define SMBHSTDAT0 (4 + ali15x3_smba)
79#define SMBHSTDAT1 (5 + ali15x3_smba)
80#define SMBBLKDAT (6 + ali15x3_smba)
81
82
83#define SMBCOM 0x004
84#define SMBBA 0x014
85#define SMBATPC 0x05B
86#define SMBHSTCFG 0x0E0
87#define SMBSLVC 0x0E1
88#define SMBCLK 0x0E2
89#define SMBREV 0x008
90
91
92#define MAX_TIMEOUT 200
93#define ALI15X3_SMB_IOSIZE 32
94
95
96
97
98
99#define ALI15X3_SMB_DEFAULTBASE 0xE800
100
101
102#define ALI15X3_LOCK 0x06
103
104
105#define ALI15X3_ABORT 0x02
106#define ALI15X3_T_OUT 0x04
107#define ALI15X3_QUICK 0x00
108#define ALI15X3_BYTE 0x10
109#define ALI15X3_BYTE_DATA 0x20
110#define ALI15X3_WORD_DATA 0x30
111#define ALI15X3_BLOCK_DATA 0x40
112#define ALI15X3_BLOCK_CLR 0x80
113
114
115#define ALI15X3_STS_IDLE 0x04
116#define ALI15X3_STS_BUSY 0x08
117#define ALI15X3_STS_DONE 0x10
118#define ALI15X3_STS_DEV 0x20
119#define ALI15X3_STS_COLL 0x40
120#define ALI15X3_STS_TERM 0x80
121#define ALI15X3_STS_ERR 0xE0
122
123
124
125
126static u16 force_addr;
127module_param(force_addr, ushort, 0);
128MODULE_PARM_DESC(force_addr,
129 "Initialize the base address of the i2c controller");
130
131static struct pci_driver ali15x3_driver;
132static unsigned short ali15x3_smba;
133
134static int __devinit ali15x3_setup(struct pci_dev *ALI15X3_dev)
135{
136 u16 a;
137 unsigned char temp;
138
139
140
141
142
143
144
145
146
147
148
149
150 pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
151 if (temp & ALI15X3_LOCK) {
152 temp &= ~ALI15X3_LOCK;
153 pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
154 }
155
156
157 pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);
158 ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));
159 if (ali15x3_smba == 0 && force_addr == 0) {
160 dev_err(&ALI15X3_dev->dev, "ALI15X3_smb region uninitialized "
161 "- upgrade BIOS or use force_addr=0xaddr\n");
162 return -ENODEV;
163 }
164
165 if(force_addr)
166 ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
167
168 if (acpi_check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
169 ali15x3_driver.name))
170 return -EBUSY;
171
172 if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
173 ali15x3_driver.name)) {
174 dev_err(&ALI15X3_dev->dev,
175 "ALI15X3_smb region 0x%x already in use!\n",
176 ali15x3_smba);
177 return -ENODEV;
178 }
179
180 if(force_addr) {
181 dev_info(&ALI15X3_dev->dev, "forcing ISA address 0x%04X\n",
182 ali15x3_smba);
183 if (PCIBIOS_SUCCESSFUL != pci_write_config_word(ALI15X3_dev,
184 SMBBA,
185 ali15x3_smba))
186 goto error;
187 if (PCIBIOS_SUCCESSFUL != pci_read_config_word(ALI15X3_dev,
188 SMBBA, &a))
189 goto error;
190 if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) {
191
192 dev_err(&ALI15X3_dev->dev,
193 "force address failed - not supported?\n");
194 goto error;
195 }
196 }
197
198 pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
199 if ((temp & 1) == 0) {
200 dev_info(&ALI15X3_dev->dev, "enabling SMBus device\n");
201 pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01);
202 }
203
204
205 pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
206 if ((temp & 1) == 0) {
207 dev_info(&ALI15X3_dev->dev, "enabling SMBus controller\n");
208 pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01);
209 }
210
211
212 pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
213
214
215
216
217
218
219
220
221 pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
222 dev_dbg(&ALI15X3_dev->dev, "SMBREV = 0x%X\n", temp);
223 dev_dbg(&ALI15X3_dev->dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba);
224
225 return 0;
226error:
227 release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
228 return -ENODEV;
229}
230
231
232static int ali15x3_transaction(struct i2c_adapter *adap)
233{
234 int temp;
235 int result = 0;
236 int timeout = 0;
237
238 dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, "
239 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),
240 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
241 inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
242
243
244 temp = inb_p(SMBHSTSTS);
245
246
247
248 if (temp & ALI15X3_STS_BUSY) {
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270 dev_info(&adap->dev, "Resetting entire SMB Bus to "
271 "clear busy condition (%02x)\n", temp);
272 outb_p(ALI15X3_T_OUT, SMBHSTCNT);
273 temp = inb_p(SMBHSTSTS);
274 }
275
276
277 if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
278
279 outb_p(0xFF, SMBHSTSTS);
280 if ((temp = inb_p(SMBHSTSTS)) &
281 (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
282
283
284
285 dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - "
286 "controller or device on bus is probably hung\n",
287 temp);
288 return -EBUSY;
289 }
290 } else {
291
292 if (temp & ALI15X3_STS_DONE) {
293 outb_p(temp, SMBHSTSTS);
294 }
295 }
296
297
298 outb_p(0xFF, SMBHSTSTART);
299
300
301 timeout = 0;
302 do {
303 msleep(1);
304 temp = inb_p(SMBHSTSTS);
305 } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))
306 && (timeout++ < MAX_TIMEOUT));
307
308
309 if (timeout > MAX_TIMEOUT) {
310 result = -ETIMEDOUT;
311 dev_err(&adap->dev, "SMBus Timeout!\n");
312 }
313
314 if (temp & ALI15X3_STS_TERM) {
315 result = -EIO;
316 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
317 }
318
319
320
321
322
323
324
325 if (temp & ALI15X3_STS_COLL) {
326 result = -ENXIO;
327 dev_dbg(&adap->dev,
328 "Error: no response or bus collision ADD=%02x\n",
329 inb_p(SMBHSTADD));
330 }
331
332
333 if (temp & ALI15X3_STS_DEV) {
334 result = -EIO;
335 dev_err(&adap->dev, "Error: device error\n");
336 }
337 dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, "
338 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),
339 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
340 inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
341 return result;
342}
343
344
345static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
346 unsigned short flags, char read_write, u8 command,
347 int size, union i2c_smbus_data * data)
348{
349 int i, len;
350 int temp;
351 int timeout;
352
353
354 outb_p(0xFF, SMBHSTSTS);
355
356 temp = inb_p(SMBHSTSTS);
357 for (timeout = 0;
358 (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
359 timeout++) {
360 msleep(1);
361 temp = inb_p(SMBHSTSTS);
362 }
363 if (timeout >= MAX_TIMEOUT) {
364 dev_err(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp);
365 }
366
367 switch (size) {
368 case I2C_SMBUS_QUICK:
369 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
370 SMBHSTADD);
371 size = ALI15X3_QUICK;
372 break;
373 case I2C_SMBUS_BYTE:
374 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
375 SMBHSTADD);
376 if (read_write == I2C_SMBUS_WRITE)
377 outb_p(command, SMBHSTCMD);
378 size = ALI15X3_BYTE;
379 break;
380 case I2C_SMBUS_BYTE_DATA:
381 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
382 SMBHSTADD);
383 outb_p(command, SMBHSTCMD);
384 if (read_write == I2C_SMBUS_WRITE)
385 outb_p(data->byte, SMBHSTDAT0);
386 size = ALI15X3_BYTE_DATA;
387 break;
388 case I2C_SMBUS_WORD_DATA:
389 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
390 SMBHSTADD);
391 outb_p(command, SMBHSTCMD);
392 if (read_write == I2C_SMBUS_WRITE) {
393 outb_p(data->word & 0xff, SMBHSTDAT0);
394 outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
395 }
396 size = ALI15X3_WORD_DATA;
397 break;
398 case I2C_SMBUS_BLOCK_DATA:
399 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
400 SMBHSTADD);
401 outb_p(command, SMBHSTCMD);
402 if (read_write == I2C_SMBUS_WRITE) {
403 len = data->block[0];
404 if (len < 0) {
405 len = 0;
406 data->block[0] = len;
407 }
408 if (len > 32) {
409 len = 32;
410 data->block[0] = len;
411 }
412 outb_p(len, SMBHSTDAT0);
413
414 outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);
415 for (i = 1; i <= len; i++)
416 outb_p(data->block[i], SMBBLKDAT);
417 }
418 size = ALI15X3_BLOCK_DATA;
419 break;
420 default:
421 dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
422 return -EOPNOTSUPP;
423 }
424
425 outb_p(size, SMBHSTCNT);
426
427 temp = ali15x3_transaction(adap);
428 if (temp)
429 return temp;
430
431 if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
432 return 0;
433
434
435 switch (size) {
436 case ALI15X3_BYTE:
437 data->byte = inb_p(SMBHSTDAT0);
438 break;
439 case ALI15X3_BYTE_DATA:
440 data->byte = inb_p(SMBHSTDAT0);
441 break;
442 case ALI15X3_WORD_DATA:
443 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
444 break;
445 case ALI15X3_BLOCK_DATA:
446 len = inb_p(SMBHSTDAT0);
447 if (len > 32)
448 len = 32;
449 data->block[0] = len;
450
451 outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);
452 for (i = 1; i <= data->block[0]; i++) {
453 data->block[i] = inb_p(SMBBLKDAT);
454 dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n",
455 len, i, data->block[i]);
456 }
457 break;
458 }
459 return 0;
460}
461
462static u32 ali15x3_func(struct i2c_adapter *adapter)
463{
464 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
465 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
466 I2C_FUNC_SMBUS_BLOCK_DATA;
467}
468
469static const struct i2c_algorithm smbus_algorithm = {
470 .smbus_xfer = ali15x3_access,
471 .functionality = ali15x3_func,
472};
473
474static struct i2c_adapter ali15x3_adapter = {
475 .owner = THIS_MODULE,
476 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
477 .algo = &smbus_algorithm,
478};
479
480static DEFINE_PCI_DEVICE_TABLE(ali15x3_ids) = {
481 { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
482 { 0, }
483};
484
485MODULE_DEVICE_TABLE (pci, ali15x3_ids);
486
487static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
488{
489 if (ali15x3_setup(dev)) {
490 dev_err(&dev->dev,
491 "ALI15X3 not detected, module not inserted.\n");
492 return -ENODEV;
493 }
494
495
496 ali15x3_adapter.dev.parent = &dev->dev;
497
498 snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
499 "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
500 return i2c_add_adapter(&ali15x3_adapter);
501}
502
503static void __devexit ali15x3_remove(struct pci_dev *dev)
504{
505 i2c_del_adapter(&ali15x3_adapter);
506 release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
507}
508
509static struct pci_driver ali15x3_driver = {
510 .name = "ali15x3_smbus",
511 .id_table = ali15x3_ids,
512 .probe = ali15x3_probe,
513 .remove = __devexit_p(ali15x3_remove),
514};
515
516static int __init i2c_ali15x3_init(void)
517{
518 return pci_register_driver(&ali15x3_driver);
519}
520
521static void __exit i2c_ali15x3_exit(void)
522{
523 pci_unregister_driver(&ali15x3_driver);
524}
525
526MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
527 "Philip Edelbrock <phil@netroedge.com>, "
528 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
529MODULE_DESCRIPTION("ALI15X3 SMBus driver");
530MODULE_LICENSE("GPL");
531
532module_init(i2c_ali15x3_init);
533module_exit(i2c_ali15x3_exit);
534