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