Loading...
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
4
5*/
6
7/*
8 Status: beta
9
10 Supports:
11 SIS 630
12 SIS 730
13 SIS 964
14
15 Notable differences between chips:
16 +------------------------+--------------------+-------------------+
17 | | SIS630/730 | SIS964 |
18 +------------------------+--------------------+-------------------+
19 | Clock | 14kHz/56kHz | 55.56kHz/27.78kHz |
20 | SMBus registers offset | 0x80 | 0xE0 |
21 | SMB_CNT | Bit 1 = Slave Busy | Bit 1 = Bus probe |
22 | (not used yet) | Bit 3 is reserved | Bit 3 = Last byte |
23 | SMB_PCOUNT | Offset + 0x06 | Offset + 0x14 |
24 | SMB_COUNT | 4:0 bits | 5:0 bits |
25 +------------------------+--------------------+-------------------+
26 (Other differences don't affect the functions provided by the driver)
27
28 Note: we assume there can only be one device, with one SMBus interface.
29*/
30
31#include <linux/kernel.h>
32#include <linux/module.h>
33#include <linux/delay.h>
34#include <linux/pci.h>
35#include <linux/ioport.h>
36#include <linux/i2c.h>
37#include <linux/acpi.h>
38#include <linux/io.h>
39
40/* SIS964 id is defined here as we are the only file using it */
41#define PCI_DEVICE_ID_SI_964 0x0964
42
43/* SIS630/730/964 SMBus registers */
44#define SMB_STS 0x00 /* status */
45#define SMB_CNT 0x02 /* control */
46#define SMBHOST_CNT 0x03 /* host control */
47#define SMB_ADDR 0x04 /* address */
48#define SMB_CMD 0x05 /* command */
49#define SMB_COUNT 0x07 /* byte count */
50#define SMB_BYTE 0x08 /* ~0x8F data byte field */
51
52/* SMB_STS register */
53#define BYTE_DONE_STS 0x10 /* Byte Done Status / Block Array */
54#define SMBCOL_STS 0x04 /* Collision */
55#define SMBERR_STS 0x02 /* Device error */
56
57/* SMB_CNT register */
58#define MSTO_EN 0x40 /* Host Master Timeout Enable */
59#define SMBCLK_SEL 0x20 /* Host master clock selection */
60#define SMB_PROBE 0x02 /* Bus Probe/Slave busy */
61#define SMB_HOSTBUSY 0x01 /* Host Busy */
62
63/* SMBHOST_CNT register */
64#define SMB_KILL 0x20 /* Kill */
65#define SMB_START 0x10 /* Start */
66
67/* register count for request_region
68 * As we don't use SMB_PCOUNT, 20 is ok for SiS630 and SiS964
69 */
70#define SIS630_SMB_IOREGION 20
71
72/* PCI address constants */
73/* acpi base address register */
74#define SIS630_ACPI_BASE_REG 0x74
75/* bios control register */
76#define SIS630_BIOS_CTL_REG 0x40
77
78/* Other settings */
79#define MAX_TIMEOUT 500
80
81/* SIS630 constants */
82#define SIS630_QUICK 0x00
83#define SIS630_BYTE 0x01
84#define SIS630_BYTE_DATA 0x02
85#define SIS630_WORD_DATA 0x03
86#define SIS630_PCALL 0x04
87#define SIS630_BLOCK_DATA 0x05
88
89static struct pci_driver sis630_driver;
90
91/* insmod parameters */
92static bool high_clock;
93static bool force;
94module_param(high_clock, bool, 0);
95MODULE_PARM_DESC(high_clock,
96 "Set Host Master Clock to 56KHz (default 14KHz) (SIS630/730 only).");
97module_param(force, bool, 0);
98MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
99
100/* SMBus base address */
101static unsigned short smbus_base;
102
103/* supported chips */
104static int supported[] = {
105 PCI_DEVICE_ID_SI_630,
106 PCI_DEVICE_ID_SI_730,
107 PCI_DEVICE_ID_SI_760,
108 0 /* terminates the list */
109};
110
111static inline u8 sis630_read(u8 reg)
112{
113 return inb(smbus_base + reg);
114}
115
116static inline void sis630_write(u8 reg, u8 data)
117{
118 outb(data, smbus_base + reg);
119}
120
121static int sis630_transaction_start(struct i2c_adapter *adap, int size,
122 u8 *oldclock)
123{
124 int temp;
125
126 /* Make sure the SMBus host is ready to start transmitting. */
127 temp = sis630_read(SMB_CNT);
128 if ((temp & (SMB_PROBE | SMB_HOSTBUSY)) != 0x00) {
129 dev_dbg(&adap->dev, "SMBus busy (%02x). Resetting...\n", temp);
130 /* kill smbus transaction */
131 sis630_write(SMBHOST_CNT, SMB_KILL);
132
133 temp = sis630_read(SMB_CNT);
134 if (temp & (SMB_PROBE | SMB_HOSTBUSY)) {
135 dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
136 return -EBUSY;
137 } else {
138 dev_dbg(&adap->dev, "Successful!\n");
139 }
140 }
141
142 /* save old clock, so we can prevent machine for hung */
143 *oldclock = sis630_read(SMB_CNT);
144
145 dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
146
147 /* disable timeout interrupt,
148 * set Host Master Clock to 56KHz if requested */
149 if (high_clock)
150 sis630_write(SMB_CNT, SMBCLK_SEL);
151 else
152 sis630_write(SMB_CNT, (*oldclock & ~MSTO_EN));
153
154 /* clear all sticky bits */
155 temp = sis630_read(SMB_STS);
156 sis630_write(SMB_STS, temp & 0x1e);
157
158 /* start the transaction by setting bit 4 and size */
159 sis630_write(SMBHOST_CNT, SMB_START | (size & 0x07));
160
161 return 0;
162}
163
164static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
165{
166 int temp, result = 0, timeout = 0;
167
168 /* We will always wait for a fraction of a second! */
169 do {
170 msleep(1);
171 temp = sis630_read(SMB_STS);
172 /* check if block transmitted */
173 if (size == SIS630_BLOCK_DATA && (temp & BYTE_DONE_STS))
174 break;
175 } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
176
177 /* If the SMBus is still busy, we give up */
178 if (timeout > MAX_TIMEOUT) {
179 dev_dbg(&adap->dev, "SMBus Timeout!\n");
180 result = -ETIMEDOUT;
181 }
182
183 if (temp & SMBERR_STS) {
184 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
185 result = -ENXIO;
186 }
187
188 if (temp & SMBCOL_STS) {
189 dev_err(&adap->dev, "Bus collision!\n");
190 result = -EAGAIN;
191 }
192
193 return result;
194}
195
196static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
197{
198 /* clear all status "sticky" bits */
199 sis630_write(SMB_STS, 0xFF);
200
201 dev_dbg(&adap->dev,
202 "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
203
204 /*
205 * restore old Host Master Clock if high_clock is set
206 * and oldclock was not 56KHz
207 */
208 if (high_clock && !(oldclock & SMBCLK_SEL))
209 sis630_write(SMB_CNT, sis630_read(SMB_CNT) & ~SMBCLK_SEL);
210
211 dev_dbg(&adap->dev,
212 "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
213}
214
215static int sis630_transaction(struct i2c_adapter *adap, int size)
216{
217 int result = 0;
218 u8 oldclock = 0;
219
220 result = sis630_transaction_start(adap, size, &oldclock);
221 if (!result) {
222 result = sis630_transaction_wait(adap, size);
223 sis630_transaction_end(adap, oldclock);
224 }
225
226 return result;
227}
228
229static int sis630_block_data(struct i2c_adapter *adap,
230 union i2c_smbus_data *data, int read_write)
231{
232 int i, len = 0, rc = 0;
233 u8 oldclock = 0;
234
235 if (read_write == I2C_SMBUS_WRITE) {
236 len = data->block[0];
237 if (len < 0)
238 len = 0;
239 else if (len > 32)
240 len = 32;
241 sis630_write(SMB_COUNT, len);
242 for (i = 1; i <= len; i++) {
243 dev_dbg(&adap->dev,
244 "set data 0x%02x\n", data->block[i]);
245 /* set data */
246 sis630_write(SMB_BYTE + (i - 1) % 8, data->block[i]);
247 if (i == 8 || (len < 8 && i == len)) {
248 dev_dbg(&adap->dev,
249 "start trans len=%d i=%d\n", len, i);
250 /* first transaction */
251 rc = sis630_transaction_start(adap,
252 SIS630_BLOCK_DATA, &oldclock);
253 if (rc)
254 return rc;
255 } else if ((i - 1) % 8 == 7 || i == len) {
256 dev_dbg(&adap->dev,
257 "trans_wait len=%d i=%d\n", len, i);
258 if (i > 8) {
259 dev_dbg(&adap->dev,
260 "clear smbary_sts"
261 " len=%d i=%d\n", len, i);
262 /*
263 If this is not first transaction,
264 we must clear sticky bit.
265 clear SMBARY_STS
266 */
267 sis630_write(SMB_STS, BYTE_DONE_STS);
268 }
269 rc = sis630_transaction_wait(adap,
270 SIS630_BLOCK_DATA);
271 if (rc) {
272 dev_dbg(&adap->dev,
273 "trans_wait failed\n");
274 break;
275 }
276 }
277 }
278 } else {
279 /* read request */
280 data->block[0] = len = 0;
281 rc = sis630_transaction_start(adap,
282 SIS630_BLOCK_DATA, &oldclock);
283 if (rc)
284 return rc;
285 do {
286 rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
287 if (rc) {
288 dev_dbg(&adap->dev, "trans_wait failed\n");
289 break;
290 }
291 /* if this first transaction then read byte count */
292 if (len == 0)
293 data->block[0] = sis630_read(SMB_COUNT);
294
295 /* just to be sure */
296 if (data->block[0] > 32)
297 data->block[0] = 32;
298
299 dev_dbg(&adap->dev,
300 "block data read len=0x%x\n", data->block[0]);
301
302 for (i = 0; i < 8 && len < data->block[0]; i++, len++) {
303 dev_dbg(&adap->dev,
304 "read i=%d len=%d\n", i, len);
305 data->block[len + 1] = sis630_read(SMB_BYTE +
306 i);
307 }
308
309 dev_dbg(&adap->dev,
310 "clear smbary_sts len=%d i=%d\n", len, i);
311
312 /* clear SMBARY_STS */
313 sis630_write(SMB_STS, BYTE_DONE_STS);
314 } while (len < data->block[0]);
315 }
316
317 sis630_transaction_end(adap, oldclock);
318
319 return rc;
320}
321
322/* Return negative errno on error. */
323static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
324 unsigned short flags, char read_write,
325 u8 command, int size, union i2c_smbus_data *data)
326{
327 int status;
328
329 switch (size) {
330 case I2C_SMBUS_QUICK:
331 sis630_write(SMB_ADDR,
332 ((addr & 0x7f) << 1) | (read_write & 0x01));
333 size = SIS630_QUICK;
334 break;
335 case I2C_SMBUS_BYTE:
336 sis630_write(SMB_ADDR,
337 ((addr & 0x7f) << 1) | (read_write & 0x01));
338 if (read_write == I2C_SMBUS_WRITE)
339 sis630_write(SMB_CMD, command);
340 size = SIS630_BYTE;
341 break;
342 case I2C_SMBUS_BYTE_DATA:
343 sis630_write(SMB_ADDR,
344 ((addr & 0x7f) << 1) | (read_write & 0x01));
345 sis630_write(SMB_CMD, command);
346 if (read_write == I2C_SMBUS_WRITE)
347 sis630_write(SMB_BYTE, data->byte);
348 size = SIS630_BYTE_DATA;
349 break;
350 case I2C_SMBUS_PROC_CALL:
351 case I2C_SMBUS_WORD_DATA:
352 sis630_write(SMB_ADDR,
353 ((addr & 0x7f) << 1) | (read_write & 0x01));
354 sis630_write(SMB_CMD, command);
355 if (read_write == I2C_SMBUS_WRITE) {
356 sis630_write(SMB_BYTE, data->word & 0xff);
357 sis630_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8);
358 }
359 size = (size == I2C_SMBUS_PROC_CALL ?
360 SIS630_PCALL : SIS630_WORD_DATA);
361 break;
362 case I2C_SMBUS_BLOCK_DATA:
363 sis630_write(SMB_ADDR,
364 ((addr & 0x7f) << 1) | (read_write & 0x01));
365 sis630_write(SMB_CMD, command);
366 size = SIS630_BLOCK_DATA;
367 return sis630_block_data(adap, data, read_write);
368 default:
369 dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
370 return -EOPNOTSUPP;
371 }
372
373 status = sis630_transaction(adap, size);
374 if (status)
375 return status;
376
377 if ((size != SIS630_PCALL) &&
378 ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
379 return 0;
380 }
381
382 switch (size) {
383 case SIS630_BYTE:
384 case SIS630_BYTE_DATA:
385 data->byte = sis630_read(SMB_BYTE);
386 break;
387 case SIS630_PCALL:
388 case SIS630_WORD_DATA:
389 data->word = sis630_read(SMB_BYTE) +
390 (sis630_read(SMB_BYTE + 1) << 8);
391 break;
392 }
393
394 return 0;
395}
396
397static u32 sis630_func(struct i2c_adapter *adapter)
398{
399 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
400 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
401 I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA;
402}
403
404static int sis630_setup(struct pci_dev *sis630_dev)
405{
406 unsigned char b;
407 struct pci_dev *dummy = NULL;
408 int retval, i;
409 /* acpi base address */
410 unsigned short acpi_base;
411
412 /* check for supported SiS devices */
413 for (i = 0; supported[i] > 0; i++) {
414 dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy);
415 if (dummy)
416 break; /* found */
417 }
418
419 if (dummy) {
420 pci_dev_put(dummy);
421 } else if (force) {
422 dev_err(&sis630_dev->dev,
423 "WARNING: Can't detect SIS630 compatible device, but "
424 "loading because of force option enabled\n");
425 } else {
426 return -ENODEV;
427 }
428
429 /*
430 Enable ACPI first , so we can accsess reg 74-75
431 in acpi io space and read acpi base addr
432 */
433 if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, &b)) {
434 dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
435 retval = -ENODEV;
436 goto exit;
437 }
438 /* if ACPI already enabled , do nothing */
439 if (!(b & 0x80) &&
440 pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
441 dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
442 retval = -ENODEV;
443 goto exit;
444 }
445
446 /* Determine the ACPI base address */
447 if (pci_read_config_word(sis630_dev,
448 SIS630_ACPI_BASE_REG, &acpi_base)) {
449 dev_err(&sis630_dev->dev,
450 "Error: Can't determine ACPI base address\n");
451 retval = -ENODEV;
452 goto exit;
453 }
454
455 dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04hx\n", acpi_base);
456
457 if (supported[i] == PCI_DEVICE_ID_SI_760)
458 smbus_base = acpi_base + 0xE0;
459 else
460 smbus_base = acpi_base + 0x80;
461
462 dev_dbg(&sis630_dev->dev, "SMBus base at 0x%04hx\n", smbus_base);
463
464 retval = acpi_check_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
465 sis630_driver.name);
466 if (retval)
467 goto exit;
468
469 /* Everything is happy, let's grab the memory and set things up. */
470 if (!request_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
471 sis630_driver.name)) {
472 dev_err(&sis630_dev->dev,
473 "I/O Region 0x%04x-0x%04x for SMBus already in use.\n",
474 smbus_base + SMB_STS,
475 smbus_base + SMB_STS + SIS630_SMB_IOREGION - 1);
476 retval = -EBUSY;
477 goto exit;
478 }
479
480 retval = 0;
481
482exit:
483 if (retval)
484 smbus_base = 0;
485 return retval;
486}
487
488
489static const struct i2c_algorithm smbus_algorithm = {
490 .smbus_xfer = sis630_access,
491 .functionality = sis630_func,
492};
493
494static struct i2c_adapter sis630_adapter = {
495 .owner = THIS_MODULE,
496 .class = I2C_CLASS_HWMON,
497 .algo = &smbus_algorithm,
498 .retries = 3
499};
500
501static const struct pci_device_id sis630_ids[] = {
502 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
503 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
504 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_964) },
505 { 0, }
506};
507
508MODULE_DEVICE_TABLE(pci, sis630_ids);
509
510static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
511{
512 if (sis630_setup(dev)) {
513 dev_err(&dev->dev,
514 "SIS630 compatible bus not detected, "
515 "module not inserted.\n");
516 return -ENODEV;
517 }
518
519 /* set up the sysfs linkage to our parent device */
520 sis630_adapter.dev.parent = &dev->dev;
521
522 snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
523 "SMBus SIS630 adapter at %04x", smbus_base + SMB_STS);
524
525 return i2c_add_adapter(&sis630_adapter);
526}
527
528static void sis630_remove(struct pci_dev *dev)
529{
530 if (smbus_base) {
531 i2c_del_adapter(&sis630_adapter);
532 release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION);
533 smbus_base = 0;
534 }
535}
536
537
538static struct pci_driver sis630_driver = {
539 .name = "sis630_smbus",
540 .id_table = sis630_ids,
541 .probe = sis630_probe,
542 .remove = sis630_remove,
543};
544
545module_pci_driver(sis630_driver);
546
547MODULE_LICENSE("GPL");
548MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
549MODULE_DESCRIPTION("SIS630 SMBus driver");
1/*
2 Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17*/
18
19/*
20 Changes:
21 24.08.2002
22 Fixed the typo in sis630_access (Thanks to Mark M. Hoffman)
23 Changed sis630_transaction.(Thanks to Mark M. Hoffman)
24 18.09.2002
25 Added SIS730 as supported.
26 21.09.2002
27 Added high_clock module option.If this option is set
28 used Host Master Clock 56KHz (default 14KHz).For now we save old Host
29 Master Clock and after transaction completed restore (otherwise
30 it's confuse BIOS and hung Machine).
31 24.09.2002
32 Fixed typo in sis630_access
33 Fixed logical error by restoring of Host Master Clock
34 31.07.2003
35 Added block data read/write support.
36*/
37
38/*
39 Status: beta
40
41 Supports:
42 SIS 630
43 SIS 730
44
45 Note: we assume there can only be one device, with one SMBus interface.
46*/
47
48#include <linux/kernel.h>
49#include <linux/module.h>
50#include <linux/delay.h>
51#include <linux/pci.h>
52#include <linux/ioport.h>
53#include <linux/init.h>
54#include <linux/i2c.h>
55#include <linux/acpi.h>
56#include <linux/io.h>
57
58/* SIS630 SMBus registers */
59#define SMB_STS 0x80 /* status */
60#define SMB_EN 0x81 /* status enable */
61#define SMB_CNT 0x82
62#define SMBHOST_CNT 0x83
63#define SMB_ADDR 0x84
64#define SMB_CMD 0x85
65#define SMB_PCOUNT 0x86 /* processed count */
66#define SMB_COUNT 0x87
67#define SMB_BYTE 0x88 /* ~0x8F data byte field */
68#define SMBDEV_ADDR 0x90
69#define SMB_DB0 0x91
70#define SMB_DB1 0x92
71#define SMB_SAA 0x93
72
73/* register count for request_region */
74#define SIS630_SMB_IOREGION 20
75
76/* PCI address constants */
77/* acpi base address register */
78#define SIS630_ACPI_BASE_REG 0x74
79/* bios control register */
80#define SIS630_BIOS_CTL_REG 0x40
81
82/* Other settings */
83#define MAX_TIMEOUT 500
84
85/* SIS630 constants */
86#define SIS630_QUICK 0x00
87#define SIS630_BYTE 0x01
88#define SIS630_BYTE_DATA 0x02
89#define SIS630_WORD_DATA 0x03
90#define SIS630_PCALL 0x04
91#define SIS630_BLOCK_DATA 0x05
92
93static struct pci_driver sis630_driver;
94
95/* insmod parameters */
96static bool high_clock;
97static bool force;
98module_param(high_clock, bool, 0);
99MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
100module_param(force, bool, 0);
101MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
102
103/* acpi base address */
104static unsigned short acpi_base;
105
106/* supported chips */
107static int supported[] = {
108 PCI_DEVICE_ID_SI_630,
109 PCI_DEVICE_ID_SI_730,
110 0 /* terminates the list */
111};
112
113static inline u8 sis630_read(u8 reg)
114{
115 return inb(acpi_base + reg);
116}
117
118static inline void sis630_write(u8 reg, u8 data)
119{
120 outb(data, acpi_base + reg);
121}
122
123static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldclock)
124{
125 int temp;
126
127 /* Make sure the SMBus host is ready to start transmitting. */
128 if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
129 dev_dbg(&adap->dev, "SMBus busy (%02x).Resetting...\n",temp);
130 /* kill smbus transaction */
131 sis630_write(SMBHOST_CNT, 0x20);
132
133 if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
134 dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
135 return -EBUSY;
136 } else {
137 dev_dbg(&adap->dev, "Successful!\n");
138 }
139 }
140
141 /* save old clock, so we can prevent machine for hung */
142 *oldclock = sis630_read(SMB_CNT);
143
144 dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
145
146 /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */
147 if (high_clock)
148 sis630_write(SMB_CNT, 0x20);
149 else
150 sis630_write(SMB_CNT, (*oldclock & ~0x40));
151
152 /* clear all sticky bits */
153 temp = sis630_read(SMB_STS);
154 sis630_write(SMB_STS, temp & 0x1e);
155
156 /* start the transaction by setting bit 4 and size */
157 sis630_write(SMBHOST_CNT,0x10 | (size & 0x07));
158
159 return 0;
160}
161
162static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
163{
164 int temp, result = 0, timeout = 0;
165
166 /* We will always wait for a fraction of a second! */
167 do {
168 msleep(1);
169 temp = sis630_read(SMB_STS);
170 /* check if block transmitted */
171 if (size == SIS630_BLOCK_DATA && (temp & 0x10))
172 break;
173 } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
174
175 /* If the SMBus is still busy, we give up */
176 if (timeout > MAX_TIMEOUT) {
177 dev_dbg(&adap->dev, "SMBus Timeout!\n");
178 result = -ETIMEDOUT;
179 }
180
181 if (temp & 0x02) {
182 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
183 result = -ENXIO;
184 }
185
186 if (temp & 0x04) {
187 dev_err(&adap->dev, "Bus collision!\n");
188 result = -EIO;
189 /*
190 TBD: Datasheet say:
191 the software should clear this bit and restart SMBUS operation.
192 Should we do it or user start request again?
193 */
194 }
195
196 return result;
197}
198
199static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
200{
201 int temp = 0;
202
203 /* clear all status "sticky" bits */
204 sis630_write(SMB_STS, temp);
205
206 dev_dbg(&adap->dev, "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
207
208 /*
209 * restore old Host Master Clock if high_clock is set
210 * and oldclock was not 56KHz
211 */
212 if (high_clock && !(oldclock & 0x20))
213 sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20));
214
215 dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
216}
217
218static int sis630_transaction(struct i2c_adapter *adap, int size)
219{
220 int result = 0;
221 u8 oldclock = 0;
222
223 result = sis630_transaction_start(adap, size, &oldclock);
224 if (!result) {
225 result = sis630_transaction_wait(adap, size);
226 sis630_transaction_end(adap, oldclock);
227 }
228
229 return result;
230}
231
232static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *data, int read_write)
233{
234 int i, len = 0, rc = 0;
235 u8 oldclock = 0;
236
237 if (read_write == I2C_SMBUS_WRITE) {
238 len = data->block[0];
239 if (len < 0)
240 len = 0;
241 else if (len > 32)
242 len = 32;
243 sis630_write(SMB_COUNT, len);
244 for (i=1; i <= len; i++) {
245 dev_dbg(&adap->dev, "set data 0x%02x\n", data->block[i]);
246 /* set data */
247 sis630_write(SMB_BYTE+(i-1)%8, data->block[i]);
248 if (i==8 || (len<8 && i==len)) {
249 dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i);
250 /* first transaction */
251 rc = sis630_transaction_start(adap,
252 SIS630_BLOCK_DATA, &oldclock);
253 if (rc)
254 return rc;
255 }
256 else if ((i-1)%8 == 7 || i==len) {
257 dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i);
258 if (i>8) {
259 dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
260 /*
261 If this is not first transaction,
262 we must clear sticky bit.
263 clear SMBARY_STS
264 */
265 sis630_write(SMB_STS,0x10);
266 }
267 rc = sis630_transaction_wait(adap,
268 SIS630_BLOCK_DATA);
269 if (rc) {
270 dev_dbg(&adap->dev, "trans_wait failed\n");
271 break;
272 }
273 }
274 }
275 }
276 else {
277 /* read request */
278 data->block[0] = len = 0;
279 rc = sis630_transaction_start(adap,
280 SIS630_BLOCK_DATA, &oldclock);
281 if (rc)
282 return rc;
283 do {
284 rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
285 if (rc) {
286 dev_dbg(&adap->dev, "trans_wait failed\n");
287 break;
288 }
289 /* if this first transaction then read byte count */
290 if (len == 0)
291 data->block[0] = sis630_read(SMB_COUNT);
292
293 /* just to be sure */
294 if (data->block[0] > 32)
295 data->block[0] = 32;
296
297 dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]);
298
299 for (i=0; i < 8 && len < data->block[0]; i++,len++) {
300 dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len);
301 data->block[len+1] = sis630_read(SMB_BYTE+i);
302 }
303
304 dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
305
306 /* clear SMBARY_STS */
307 sis630_write(SMB_STS,0x10);
308 } while(len < data->block[0]);
309 }
310
311 sis630_transaction_end(adap, oldclock);
312
313 return rc;
314}
315
316/* Return negative errno on error. */
317static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
318 unsigned short flags, char read_write,
319 u8 command, int size, union i2c_smbus_data *data)
320{
321 int status;
322
323 switch (size) {
324 case I2C_SMBUS_QUICK:
325 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
326 size = SIS630_QUICK;
327 break;
328 case I2C_SMBUS_BYTE:
329 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
330 if (read_write == I2C_SMBUS_WRITE)
331 sis630_write(SMB_CMD, command);
332 size = SIS630_BYTE;
333 break;
334 case I2C_SMBUS_BYTE_DATA:
335 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
336 sis630_write(SMB_CMD, command);
337 if (read_write == I2C_SMBUS_WRITE)
338 sis630_write(SMB_BYTE, data->byte);
339 size = SIS630_BYTE_DATA;
340 break;
341 case I2C_SMBUS_PROC_CALL:
342 case I2C_SMBUS_WORD_DATA:
343 sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
344 sis630_write(SMB_CMD, command);
345 if (read_write == I2C_SMBUS_WRITE) {
346 sis630_write(SMB_BYTE, data->word & 0xff);
347 sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8);
348 }
349 size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA);
350 break;
351 case I2C_SMBUS_BLOCK_DATA:
352 sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
353 sis630_write(SMB_CMD, command);
354 size = SIS630_BLOCK_DATA;
355 return sis630_block_data(adap, data, read_write);
356 default:
357 dev_warn(&adap->dev, "Unsupported transaction %d\n",
358 size);
359 return -EOPNOTSUPP;
360 }
361
362 status = sis630_transaction(adap, size);
363 if (status)
364 return status;
365
366 if ((size != SIS630_PCALL) &&
367 ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
368 return 0;
369 }
370
371 switch(size) {
372 case SIS630_BYTE:
373 case SIS630_BYTE_DATA:
374 data->byte = sis630_read(SMB_BYTE);
375 break;
376 case SIS630_PCALL:
377 case SIS630_WORD_DATA:
378 data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
379 break;
380 }
381
382 return 0;
383}
384
385static u32 sis630_func(struct i2c_adapter *adapter)
386{
387 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
388 I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL |
389 I2C_FUNC_SMBUS_BLOCK_DATA;
390}
391
392static int __devinit sis630_setup(struct pci_dev *sis630_dev)
393{
394 unsigned char b;
395 struct pci_dev *dummy = NULL;
396 int retval, i;
397
398 /* check for supported SiS devices */
399 for (i=0; supported[i] > 0 ; i++) {
400 if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy)))
401 break; /* found */
402 }
403
404 if (dummy) {
405 pci_dev_put(dummy);
406 }
407 else if (force) {
408 dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but "
409 "loading because of force option enabled\n");
410 }
411 else {
412 return -ENODEV;
413 }
414
415 /*
416 Enable ACPI first , so we can accsess reg 74-75
417 in acpi io space and read acpi base addr
418 */
419 if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
420 dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
421 retval = -ENODEV;
422 goto exit;
423 }
424 /* if ACPI already enabled , do nothing */
425 if (!(b & 0x80) &&
426 pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
427 dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
428 retval = -ENODEV;
429 goto exit;
430 }
431
432 /* Determine the ACPI base address */
433 if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
434 dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
435 retval = -ENODEV;
436 goto exit;
437 }
438
439 dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
440
441 retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
442 sis630_driver.name);
443 if (retval)
444 goto exit;
445
446 /* Everything is happy, let's grab the memory and set things up. */
447 if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
448 sis630_driver.name)) {
449 dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
450 "in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
451 retval = -EBUSY;
452 goto exit;
453 }
454
455 retval = 0;
456
457exit:
458 if (retval)
459 acpi_base = 0;
460 return retval;
461}
462
463
464static const struct i2c_algorithm smbus_algorithm = {
465 .smbus_xfer = sis630_access,
466 .functionality = sis630_func,
467};
468
469static struct i2c_adapter sis630_adapter = {
470 .owner = THIS_MODULE,
471 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
472 .algo = &smbus_algorithm,
473};
474
475static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = {
476 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
477 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
478 { 0, }
479};
480
481MODULE_DEVICE_TABLE (pci, sis630_ids);
482
483static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
484{
485 if (sis630_setup(dev)) {
486 dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
487 return -ENODEV;
488 }
489
490 /* set up the sysfs linkage to our parent device */
491 sis630_adapter.dev.parent = &dev->dev;
492
493 snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
494 "SMBus SIS630 adapter at %04x", acpi_base + SMB_STS);
495
496 return i2c_add_adapter(&sis630_adapter);
497}
498
499static void __devexit sis630_remove(struct pci_dev *dev)
500{
501 if (acpi_base) {
502 i2c_del_adapter(&sis630_adapter);
503 release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
504 acpi_base = 0;
505 }
506}
507
508
509static struct pci_driver sis630_driver = {
510 .name = "sis630_smbus",
511 .id_table = sis630_ids,
512 .probe = sis630_probe,
513 .remove = __devexit_p(sis630_remove),
514};
515
516static int __init i2c_sis630_init(void)
517{
518 return pci_register_driver(&sis630_driver);
519}
520
521
522static void __exit i2c_sis630_exit(void)
523{
524 pci_unregister_driver(&sis630_driver);
525}
526
527
528MODULE_LICENSE("GPL");
529MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
530MODULE_DESCRIPTION("SIS630 SMBus driver");
531
532module_init(i2c_sis630_init);
533module_exit(i2c_sis630_exit);