0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
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,
0068
0069
0070 PCI_DEVICE_ID_SI_5597,
0071 PCI_DEVICE_ID_SI_5598,
0072 0,
0073 };
0074
0075
0076 #define SIS5595_EXTENT 8
0077
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
0093 #define SMB_INDEX 0x38
0094 #define SMB_DAT 0x39
0095 #define SIS5595_ENABLE_REG 0x40
0096 #define ACPI_BASE 0x90
0097
0098
0099 #define MAX_TIMEOUT 500
0100
0101
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
0110
0111
0112
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
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
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
0163
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
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
0204 dev_err(&SIS5595_dev->dev, "ACPI enable failed - not supported?\n");
0205 goto error;
0206 }
0207 }
0208
0209
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
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
0238 sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10);
0239
0240
0241 do {
0242 msleep(1);
0243 temp = sis5595_read(SMB_STS_LO);
0244 } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
0245
0246
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
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
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
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
0388
0389
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);