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