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