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