2     i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware
 
   5     Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
 
   7     This program is free software; you can redistribute it and/or modify
 
   8     it under the terms of the GNU General Public License as published by
 
   9     the Free Software Foundation; either version 2 of the License, or
 
  10     (at your option) any later version.
 
  12     This program is distributed in the hope that it will be useful,
 
  13     but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  15     GNU General Public License for more details.
 
  17     You should have received a copy of the GNU General Public License
 
  18     along with this program; if not, write to the Free Software
 
  19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
  25         Fixed the typo in sis630_access (Thanks to Mark M. Hoffman)
 
  26         Changed sis630_transaction.(Thanks to Mark M. Hoffman)
 
  28         Added SIS730 as supported.
 
  30         Added high_clock module option.If this option is set
 
  31         used Host Master Clock 56KHz (default 14KHz).For now we save old Host
 
  32         Master Clock and after transaction completed restore (otherwise
 
  33         it's confuse BIOS and hung Machine).
 
  35         Fixed typo in sis630_access
 
  36         Fixed logical error by restoring of Host Master Clock
 
  38         Added block data read/write support.
 
  48    Note: we assume there can only be one device, with one SMBus interface.
 
  51 #include <linux/kernel.h>
 
  52 #include <linux/module.h>
 
  53 #include <linux/delay.h>
 
  54 #include <linux/pci.h>
 
  55 #include <linux/ioport.h>
 
  56 #include <linux/init.h>
 
  57 #include <linux/i2c.h>
 
  60 /* SIS630 SMBus registers */
 
  61 #define SMB_STS                 0x80    /* status */
 
  62 #define SMB_EN                  0x81    /* status enable */
 
  64 #define SMBHOST_CNT             0x83
 
  67 #define SMB_PCOUNT              0x86    /* processed count */
 
  68 #define SMB_COUNT               0x87
 
  69 #define SMB_BYTE                0x88    /* ~0x8F data byte field */
 
  70 #define SMBDEV_ADDR             0x90
 
  75 /* register count for request_region */
 
  76 #define SIS630_SMB_IOREGION     20
 
  78 /* PCI address constants */
 
  79 /* acpi base address register  */
 
  80 #define SIS630_ACPI_BASE_REG    0x74
 
  81 /* bios control register */
 
  82 #define SIS630_BIOS_CTL_REG     0x40
 
  85 #define MAX_TIMEOUT             500
 
  87 /* SIS630 constants */
 
  88 #define SIS630_QUICK            0x00
 
  89 #define SIS630_BYTE             0x01
 
  90 #define SIS630_BYTE_DATA        0x02
 
  91 #define SIS630_WORD_DATA        0x03
 
  92 #define SIS630_PCALL            0x04
 
  93 #define SIS630_BLOCK_DATA       0x05
 
  95 /* insmod parameters */
 
  96 static int high_clock;
 
  98 module_param(high_clock, bool, 0);
 
  99 MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz).");
 
 100 module_param(force, bool, 0);
 
 101 MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
 
 103 /* acpi base address */
 
 104 static unsigned short acpi_base = 0;
 
 106 /* supported chips */
 
 107 static int supported[] = {
 
 108         PCI_DEVICE_ID_SI_630,
 
 109         PCI_DEVICE_ID_SI_730,
 
 110         0 /* terminates the list */
 
 113 static inline u8 sis630_read(u8 reg)
 
 115         return inb(acpi_base + reg);
 
 118 static inline void sis630_write(u8 reg, u8 data)
 
 120         outb(data, acpi_base + reg);
 
 123 static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldclock)
 
 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);
 
 133                 if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
 
 134                         dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
 
 137                         dev_dbg(&adap->dev, "Successfull!\n");
 
 141         /* save old clock, so we can prevent machine for hung */
 
 142         *oldclock = sis630_read(SMB_CNT);
 
 144         dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
 
 146         /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */
 
 148                 sis630_write(SMB_CNT, 0x20);
 
 150                 sis630_write(SMB_CNT, (*oldclock & ~0x40));
 
 152         /* clear all sticky bits */
 
 153         temp = sis630_read(SMB_STS);
 
 154         sis630_write(SMB_STS, temp & 0x1e);
 
 156         /* start the transaction by setting bit 4 and size */
 
 157         sis630_write(SMBHOST_CNT,0x10 | (size & 0x07));
 
 162 static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
 
 164         int temp, result = 0, timeout = 0;
 
 166         /* We will always wait for a fraction of a second! */
 
 169                 temp = sis630_read(SMB_STS);
 
 170                 /* check if block transmitted */
 
 171                 if (size == SIS630_BLOCK_DATA && (temp & 0x10))
 
 173         } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
 
 175         /* If the SMBus is still busy, we give up */
 
 176         if (timeout >= MAX_TIMEOUT) {
 
 177                 dev_dbg(&adap->dev, "SMBus Timeout!\n");
 
 182                 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
 
 187                 dev_err(&adap->dev, "Bus collision!\n");
 
 191                   the software should clear this bit and restart SMBUS operation.
 
 192                   Should we do it or user start request again?
 
 199 static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
 
 203         /* clear all status "sticky" bits */
 
 204         sis630_write(SMB_STS, temp);
 
 206         dev_dbg(&adap->dev, "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
 
 209          * restore old Host Master Clock if high_clock is set
 
 210          * and oldclock was not 56KHz
 
 212         if (high_clock && !(oldclock & 0x20))
 
 213                 sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20));
 
 215         dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
 
 218 static int sis630_transaction(struct i2c_adapter *adap, int size)
 
 223         result = sis630_transaction_start(adap, size, &oldclock);
 
 225                 result = sis630_transaction_wait(adap, size);
 
 226                 sis630_transaction_end(adap, oldclock);
 
 232 static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *data, int read_write)
 
 234         int i, len = 0, rc = 0;
 
 237         if (read_write == I2C_SMBUS_WRITE) {
 
 238                 len = data->block[0];
 
 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]);
 
 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                                 if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock))
 
 254                         else if ((i-1)%8 == 7 || i==len) {
 
 255                                 dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i);
 
 257                                         dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
 
 259                                            If this is not first transaction,
 
 260                                            we must clear sticky bit.
 
 263                                         sis630_write(SMB_STS,0x10);
 
 265                                 if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
 
 266                                         dev_dbg(&adap->dev, "trans_wait failed\n");
 
 275                 data->block[0] = len = 0;
 
 276                 if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) {
 
 280                         if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
 
 281                                 dev_dbg(&adap->dev, "trans_wait failed\n");
 
 285                         /* if this first transaction then read byte count */
 
 287                                 data->block[0] = sis630_read(SMB_COUNT);
 
 289                         /* just to be sure */
 
 290                         if (data->block[0] > 32)
 
 293                         dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]);
 
 295                         for (i=0; i < 8 && len < data->block[0]; i++,len++) {
 
 296                                 dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len);
 
 297                                 data->block[len+1] = sis630_read(SMB_BYTE+i);
 
 300                         dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i);
 
 302                         /* clear SMBARY_STS */
 
 303                         sis630_write(SMB_STS,0x10);
 
 304                 } while(len < data->block[0]);
 
 307         sis630_transaction_end(adap, oldclock);
 
 312 /* Return -1 on error. */
 
 313 static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
 
 314                          unsigned short flags, char read_write,
 
 315                          u8 command, int size, union i2c_smbus_data *data)
 
 318                 case I2C_SMBUS_QUICK:
 
 319                         sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
 
 323                         sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
 
 324                         if (read_write == I2C_SMBUS_WRITE)
 
 325                                 sis630_write(SMB_CMD, command);
 
 328                 case I2C_SMBUS_BYTE_DATA:
 
 329                         sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
 
 330                         sis630_write(SMB_CMD, command);
 
 331                         if (read_write == I2C_SMBUS_WRITE)
 
 332                                 sis630_write(SMB_BYTE, data->byte);
 
 333                         size = SIS630_BYTE_DATA;
 
 335                 case I2C_SMBUS_PROC_CALL:
 
 336                 case I2C_SMBUS_WORD_DATA:
 
 337                         sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
 
 338                         sis630_write(SMB_CMD, command);
 
 339                         if (read_write == I2C_SMBUS_WRITE) {
 
 340                                 sis630_write(SMB_BYTE, data->word & 0xff);
 
 341                                 sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8);
 
 343                         size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA);
 
 345                 case I2C_SMBUS_BLOCK_DATA:
 
 346                         sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01));
 
 347                         sis630_write(SMB_CMD, command);
 
 348                         size = SIS630_BLOCK_DATA;
 
 349                         return sis630_block_data(adap, data, read_write);
 
 351                         printk("Unsupported I2C size\n");
 
 356         if (sis630_transaction(adap, size))
 
 359         if ((size != SIS630_PCALL) &&
 
 360                 ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
 
 366                 case SIS630_BYTE_DATA:
 
 367                         data->byte = sis630_read(SMB_BYTE);
 
 370                 case SIS630_WORD_DATA:
 
 371                         data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
 
 381 static u32 sis630_func(struct i2c_adapter *adapter)
 
 383         return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
 
 384                 I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL |
 
 385                 I2C_FUNC_SMBUS_BLOCK_DATA;
 
 388 static int sis630_setup(struct pci_dev *sis630_dev)
 
 391         struct pci_dev *dummy = NULL;
 
 392         int retval = -ENODEV, i;
 
 394         /* check for supported SiS devices */
 
 395         for (i=0; supported[i] > 0 ; i++) {
 
 396                 if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy)))
 
 404                 dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but "
 
 405                         "loading because of force option enabled\n");
 
 412            Enable ACPI first , so we can accsess reg 74-75
 
 413            in acpi io space and read acpi base addr
 
 415         if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) {
 
 416                 dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
 
 419         /* if ACPI already enabled , do nothing */
 
 421             pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
 
 422                 dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
 
 426         /* Determine the ACPI base address */
 
 427         if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) {
 
 428                 dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n");
 
 432         dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
 
 434         /* Everything is happy, let's grab the memory and set things up. */
 
 435         if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, "sis630-smbus")) {
 
 436                 dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already "
 
 437                         "in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA);
 
 450 static struct i2c_algorithm smbus_algorithm = {
 
 451         .name           = "Non-I2C SMBus adapter",
 
 452         .id             = I2C_ALGO_SMBUS,
 
 453         .smbus_xfer     = sis630_access,
 
 454         .functionality  = sis630_func,
 
 457 static struct i2c_adapter sis630_adapter = {
 
 458         .owner          = THIS_MODULE,
 
 459         .class          = I2C_CLASS_HWMON,
 
 461         .algo           = &smbus_algorithm,
 
 464 static struct pci_device_id sis630_ids[] __devinitdata = {
 
 465         { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
 
 466         { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
 
 470 MODULE_DEVICE_TABLE (pci, sis630_ids);
 
 472 static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 474         if (sis630_setup(dev)) {
 
 475                 dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n");
 
 479         /* set up the driverfs linkage to our parent device */
 
 480         sis630_adapter.dev.parent = &dev->dev;
 
 482         sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x",
 
 483                 acpi_base + SMB_STS);
 
 485         return i2c_add_adapter(&sis630_adapter);
 
 488 static void __devexit sis630_remove(struct pci_dev *dev)
 
 491                 i2c_del_adapter(&sis630_adapter);
 
 492                 release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION);
 
 498 static struct pci_driver sis630_driver = {
 
 499         .name           = "sis630_smbus",
 
 500         .id_table       = sis630_ids,
 
 501         .probe          = sis630_probe,
 
 502         .remove         = __devexit_p(sis630_remove),
 
 505 static int __init i2c_sis630_init(void)
 
 507         return pci_register_driver(&sis630_driver);
 
 511 static void __exit i2c_sis630_exit(void)
 
 513         pci_unregister_driver(&sis630_driver);
 
 517 MODULE_LICENSE("GPL");
 
 518 MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
 
 519 MODULE_DESCRIPTION("SIS630 SMBus driver");
 
 521 module_init(i2c_sis630_init);
 
 522 module_exit(i2c_sis630_exit);