Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
0004     Philip Edelbrock <phil@netroedge.com>
0005 
0006 */
0007 
0008 /* Note: we assume there can only be one SIS5595 with one SMBus interface */
0009 
0010 /*
0011    Note: all have mfr. ID 0x1039.
0012    SUPPORTED        PCI ID      
0013     5595        0008
0014 
0015    Note: these chips contain a 0008 device which is incompatible with the
0016          5595. We recognize these by the presence of the listed
0017          "blacklist" PCI ID and refuse to load.
0018 
0019    NOT SUPPORTED    PCI ID      BLACKLIST PCI ID    
0020      540        0008        0540
0021      550        0008        0550
0022     5513        0008        5511
0023     5581        0008        5597
0024     5582        0008        5597
0025     5597        0008        5597
0026     5598        0008        5597/5598
0027      630        0008        0630
0028      645        0008        0645
0029      646        0008        0646
0030      648        0008        0648
0031      650        0008        0650
0032      651        0008        0651
0033      730        0008        0730
0034      735        0008        0735
0035      745        0008        0745
0036      746        0008        0746
0037 */
0038 
0039 /* TO DO: 
0040  * Add Block Transfers (ugly, but supported by the adapter)
0041  * Add adapter resets
0042  */
0043 
0044 #include <linux/kernel.h>
0045 #include <linux/module.h>
0046 #include <linux/delay.h>
0047 #include <linux/pci.h>
0048 #include <linux/ioport.h>
0049 #include <linux/init.h>
0050 #include <linux/i2c.h>
0051 #include <linux/acpi.h>
0052 #include <linux/io.h>
0053 
0054 static int blacklist[] = {
0055     PCI_DEVICE_ID_SI_540,
0056     PCI_DEVICE_ID_SI_550,
0057     PCI_DEVICE_ID_SI_630,
0058     PCI_DEVICE_ID_SI_645,
0059     PCI_DEVICE_ID_SI_646,
0060     PCI_DEVICE_ID_SI_648,
0061     PCI_DEVICE_ID_SI_650,
0062     PCI_DEVICE_ID_SI_651,
0063     PCI_DEVICE_ID_SI_730,
0064     PCI_DEVICE_ID_SI_735,
0065     PCI_DEVICE_ID_SI_745,
0066     PCI_DEVICE_ID_SI_746,
0067     PCI_DEVICE_ID_SI_5511,  /* 5513 chip has the 0008 device but that ID
0068                    shows up in other chips so we use the 5511
0069                    ID for recognition */
0070     PCI_DEVICE_ID_SI_5597,
0071     PCI_DEVICE_ID_SI_5598,
0072     0,          /* terminates the list */
0073 };
0074 
0075 /* Length of ISA address segment */
0076 #define SIS5595_EXTENT      8
0077 /* SIS5595 SMBus registers */
0078 #define SMB_STS_LO      0x00
0079 #define SMB_STS_HI      0x01
0080 #define SMB_CTL_LO      0x02
0081 #define SMB_CTL_HI      0x03
0082 #define SMB_ADDR        0x04
0083 #define SMB_CMD         0x05
0084 #define SMB_PCNT        0x06
0085 #define SMB_CNT         0x07
0086 #define SMB_BYTE        0x08
0087 #define SMB_DEV         0x10
0088 #define SMB_DB0         0x11
0089 #define SMB_DB1         0x12
0090 #define SMB_HAA         0x13
0091 
0092 /* PCI Address Constants */
0093 #define SMB_INDEX       0x38
0094 #define SMB_DAT         0x39
0095 #define SIS5595_ENABLE_REG  0x40
0096 #define ACPI_BASE       0x90
0097 
0098 /* Other settings */
0099 #define MAX_TIMEOUT     500
0100 
0101 /* SIS5595 constants */
0102 #define SIS5595_QUICK       0x00
0103 #define SIS5595_BYTE        0x02
0104 #define SIS5595_BYTE_DATA   0x04
0105 #define SIS5595_WORD_DATA   0x06
0106 #define SIS5595_PROC_CALL   0x08
0107 #define SIS5595_BLOCK_DATA  0x0A
0108 
0109 /* insmod parameters */
0110 
0111 /* If force_addr is set to anything different from 0, we forcibly enable
0112    the device at the given address. */
0113 static u16 force_addr;
0114 module_param_hw(force_addr, ushort, ioport, 0);
0115 MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
0116 
0117 static struct pci_driver sis5595_driver;
0118 static unsigned short sis5595_base;
0119 static struct pci_dev *sis5595_pdev;
0120 
0121 static u8 sis5595_read(u8 reg)
0122 {
0123     outb(reg, sis5595_base + SMB_INDEX);
0124     return inb(sis5595_base + SMB_DAT);
0125 }
0126 
0127 static void sis5595_write(u8 reg, u8 data)
0128 {
0129     outb(reg, sis5595_base + SMB_INDEX);
0130     outb(data, sis5595_base + SMB_DAT);
0131 }
0132 
0133 static int sis5595_setup(struct pci_dev *SIS5595_dev)
0134 {
0135     u16 a;
0136     u8 val;
0137     int *i;
0138     int retval;
0139 
0140     /* Look for imposters */
0141     for (i = blacklist; *i != 0; i++) {
0142         struct pci_dev *dev;
0143         dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
0144         if (dev) {
0145             dev_err(&SIS5595_dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
0146             pci_dev_put(dev);
0147             return -ENODEV;
0148         }
0149     }
0150 
0151     /* Determine the address of the SMBus areas */
0152     pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base);
0153     if (sis5595_base == 0 && force_addr == 0) {
0154         dev_err(&SIS5595_dev->dev, "ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
0155         return -ENODEV;
0156     }
0157 
0158     if (force_addr)
0159         sis5595_base = force_addr & ~(SIS5595_EXTENT - 1);
0160     dev_dbg(&SIS5595_dev->dev, "ACPI Base address: %04x\n", sis5595_base);
0161 
0162     /* NB: We grab just the two SMBus registers here, but this may still
0163      * interfere with ACPI :-(  */
0164     retval = acpi_check_region(sis5595_base + SMB_INDEX, 2,
0165                    sis5595_driver.name);
0166     if (retval)
0167         return retval;
0168 
0169     if (!request_region(sis5595_base + SMB_INDEX, 2,
0170                 sis5595_driver.name)) {
0171         dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
0172             sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1);
0173         return -ENODEV;
0174     }
0175 
0176     if (force_addr) {
0177         dev_info(&SIS5595_dev->dev, "forcing ISA address 0x%04X\n", sis5595_base);
0178         if (pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base)
0179             != PCIBIOS_SUCCESSFUL)
0180             goto error;
0181         if (pci_read_config_word(SIS5595_dev, ACPI_BASE, &a)
0182             != PCIBIOS_SUCCESSFUL)
0183             goto error;
0184         if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) {
0185             /* doesn't work for some chips! */
0186             dev_err(&SIS5595_dev->dev, "force address failed - not supported?\n");
0187             goto error;
0188         }
0189     }
0190 
0191     if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)
0192         != PCIBIOS_SUCCESSFUL)
0193         goto error;
0194     if ((val & 0x80) == 0) {
0195         dev_info(&SIS5595_dev->dev, "enabling ACPI\n");
0196         if (pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80)
0197             != PCIBIOS_SUCCESSFUL)
0198             goto error;
0199         if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val)
0200             != PCIBIOS_SUCCESSFUL)
0201             goto error;
0202         if ((val & 0x80) == 0) {
0203             /* doesn't work for some chips? */
0204             dev_err(&SIS5595_dev->dev, "ACPI enable failed - not supported?\n");
0205             goto error;
0206         }
0207     }
0208 
0209     /* Everything is happy */
0210     return 0;
0211 
0212 error:
0213     release_region(sis5595_base + SMB_INDEX, 2);
0214     return -ENODEV;
0215 }
0216 
0217 static int sis5595_transaction(struct i2c_adapter *adap)
0218 {
0219     int temp;
0220     int result = 0;
0221     int timeout = 0;
0222 
0223     /* Make sure the SMBus host is ready to start transmitting */
0224     temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
0225     if (temp != 0x00) {
0226         dev_dbg(&adap->dev, "SMBus busy (%04x). Resetting...\n", temp);
0227         sis5595_write(SMB_STS_LO, temp & 0xff);
0228         sis5595_write(SMB_STS_HI, temp >> 8);
0229         if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
0230             dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
0231             return -EBUSY;
0232         } else {
0233             dev_dbg(&adap->dev, "Successful!\n");
0234         }
0235     }
0236 
0237     /* start the transaction by setting bit 4 */
0238     sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
0239 
0240     /* We will always wait for a fraction of a second! */
0241     do {
0242         msleep(1);
0243         temp = sis5595_read(SMB_STS_LO);
0244     } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
0245 
0246     /* If the SMBus is still busy, we give up */
0247     if (timeout > MAX_TIMEOUT) {
0248         dev_dbg(&adap->dev, "SMBus Timeout!\n");
0249         result = -ETIMEDOUT;
0250     }
0251 
0252     if (temp & 0x10) {
0253         dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
0254         result = -ENXIO;
0255     }
0256 
0257     if (temp & 0x20) {
0258         dev_err(&adap->dev, "Bus collision! SMBus may be locked until "
0259             "next hard reset (or not...)\n");
0260         /* Clock stops and slave is stuck in mid-transmission */
0261         result = -EIO;
0262     }
0263 
0264     temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
0265     if (temp != 0x00) {
0266         sis5595_write(SMB_STS_LO, temp & 0xff);
0267         sis5595_write(SMB_STS_HI, temp >> 8);
0268     }
0269 
0270     temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
0271     if (temp != 0x00)
0272         dev_dbg(&adap->dev, "Failed reset at end of transaction (%02x)\n", temp);
0273 
0274     return result;
0275 }
0276 
0277 /* Return negative errno on error. */
0278 static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
0279               unsigned short flags, char read_write,
0280               u8 command, int size, union i2c_smbus_data *data)
0281 {
0282     int status;
0283 
0284     switch (size) {
0285     case I2C_SMBUS_QUICK:
0286         sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
0287         size = SIS5595_QUICK;
0288         break;
0289     case I2C_SMBUS_BYTE:
0290         sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
0291         if (read_write == I2C_SMBUS_WRITE)
0292             sis5595_write(SMB_CMD, command);
0293         size = SIS5595_BYTE;
0294         break;
0295     case I2C_SMBUS_BYTE_DATA:
0296         sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
0297         sis5595_write(SMB_CMD, command);
0298         if (read_write == I2C_SMBUS_WRITE)
0299             sis5595_write(SMB_BYTE, data->byte);
0300         size = SIS5595_BYTE_DATA;
0301         break;
0302     case I2C_SMBUS_PROC_CALL:
0303     case I2C_SMBUS_WORD_DATA:
0304         sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
0305         sis5595_write(SMB_CMD, command);
0306         if (read_write == I2C_SMBUS_WRITE) {
0307             sis5595_write(SMB_BYTE, data->word & 0xff);
0308             sis5595_write(SMB_BYTE + 1,
0309                       (data->word & 0xff00) >> 8);
0310         }
0311         size = (size == I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : SIS5595_WORD_DATA;
0312         break;
0313     default:
0314         dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
0315         return -EOPNOTSUPP;
0316     }
0317 
0318     sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
0319 
0320     status = sis5595_transaction(adap);
0321     if (status)
0322         return status;
0323 
0324     if ((size != SIS5595_PROC_CALL) &&
0325         ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
0326         return 0;
0327 
0328 
0329     switch (size) {
0330     case SIS5595_BYTE:
0331     case SIS5595_BYTE_DATA:
0332         data->byte = sis5595_read(SMB_BYTE);
0333         break;
0334     case SIS5595_WORD_DATA:
0335     case SIS5595_PROC_CALL:
0336         data->word = sis5595_read(SMB_BYTE) + (sis5595_read(SMB_BYTE + 1) << 8);
0337         break;
0338     }
0339     return 0;
0340 }
0341 
0342 static u32 sis5595_func(struct i2c_adapter *adapter)
0343 {
0344     return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
0345         I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
0346         I2C_FUNC_SMBUS_PROC_CALL;
0347 }
0348 
0349 static const struct i2c_algorithm smbus_algorithm = {
0350     .smbus_xfer = sis5595_access,
0351     .functionality  = sis5595_func,
0352 };
0353 
0354 static struct i2c_adapter sis5595_adapter = {
0355     .owner      = THIS_MODULE,
0356     .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
0357     .algo       = &smbus_algorithm,
0358 };
0359 
0360 static const struct pci_device_id sis5595_ids[] = {
0361     { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, 
0362     { 0, }
0363 };
0364 
0365 MODULE_DEVICE_TABLE (pci, sis5595_ids);
0366 
0367 static int sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id)
0368 {
0369     int err;
0370 
0371     if (sis5595_setup(dev)) {
0372         dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n");
0373         return -ENODEV;
0374     }
0375 
0376     /* set up the sysfs linkage to our parent device */
0377     sis5595_adapter.dev.parent = &dev->dev;
0378 
0379     snprintf(sis5595_adapter.name, sizeof(sis5595_adapter.name),
0380          "SMBus SIS5595 adapter at %04x", sis5595_base + SMB_INDEX);
0381     err = i2c_add_adapter(&sis5595_adapter);
0382     if (err) {
0383         release_region(sis5595_base + SMB_INDEX, 2);
0384         return err;
0385     }
0386 
0387     /* Always return failure here.  This is to allow other drivers to bind
0388      * to this pci device.  We don't really want to have control over the
0389      * pci device, we only wanted to read as few register values from it.
0390      */
0391     sis5595_pdev =  pci_dev_get(dev);
0392     return -ENODEV;
0393 }
0394 
0395 static struct pci_driver sis5595_driver = {
0396     .name       = "sis5595_smbus",
0397     .id_table   = sis5595_ids,
0398     .probe      = sis5595_probe,
0399 };
0400 
0401 static int __init i2c_sis5595_init(void)
0402 {
0403     return pci_register_driver(&sis5595_driver);
0404 }
0405 
0406 static void __exit i2c_sis5595_exit(void)
0407 {
0408     pci_unregister_driver(&sis5595_driver);
0409     if (sis5595_pdev) {
0410         i2c_del_adapter(&sis5595_adapter);
0411         release_region(sis5595_base + SMB_INDEX, 2);
0412         pci_dev_put(sis5595_pdev);
0413         sis5595_pdev = NULL;
0414     }
0415 }
0416 
0417 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
0418 MODULE_DESCRIPTION("SIS5595 SMBus driver");
0419 MODULE_LICENSE("GPL");
0420 
0421 module_init(i2c_sis5595_init);
0422 module_exit(i2c_sis5595_exit);