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 #include <linux/kernel.h>
0032 #include <linux/module.h>
0033 #include <linux/delay.h>
0034 #include <linux/pci.h>
0035 #include <linux/ioport.h>
0036 #include <linux/i2c.h>
0037 #include <linux/acpi.h>
0038 #include <linux/io.h>
0039
0040
0041 #define PCI_DEVICE_ID_SI_964 0x0964
0042
0043
0044 #define SMB_STS 0x00
0045 #define SMB_CNT 0x02
0046 #define SMBHOST_CNT 0x03
0047 #define SMB_ADDR 0x04
0048 #define SMB_CMD 0x05
0049 #define SMB_COUNT 0x07
0050 #define SMB_BYTE 0x08
0051
0052
0053 #define BYTE_DONE_STS 0x10
0054 #define SMBCOL_STS 0x04
0055 #define SMBERR_STS 0x02
0056
0057
0058 #define MSTO_EN 0x40
0059 #define SMBCLK_SEL 0x20
0060 #define SMB_PROBE 0x02
0061 #define SMB_HOSTBUSY 0x01
0062
0063
0064 #define SMB_KILL 0x20
0065 #define SMB_START 0x10
0066
0067
0068
0069
0070 #define SIS630_SMB_IOREGION 20
0071
0072
0073
0074 #define SIS630_ACPI_BASE_REG 0x74
0075
0076 #define SIS630_BIOS_CTL_REG 0x40
0077
0078
0079 #define MAX_TIMEOUT 500
0080
0081
0082 #define SIS630_QUICK 0x00
0083 #define SIS630_BYTE 0x01
0084 #define SIS630_BYTE_DATA 0x02
0085 #define SIS630_WORD_DATA 0x03
0086 #define SIS630_PCALL 0x04
0087 #define SIS630_BLOCK_DATA 0x05
0088
0089 static struct pci_driver sis630_driver;
0090
0091
0092 static bool high_clock;
0093 static bool force;
0094 module_param(high_clock, bool, 0);
0095 MODULE_PARM_DESC(high_clock,
0096 "Set Host Master Clock to 56KHz (default 14KHz) (SIS630/730 only).");
0097 module_param(force, bool, 0);
0098 MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!");
0099
0100
0101 static unsigned short smbus_base;
0102
0103
0104 static int supported[] = {
0105 PCI_DEVICE_ID_SI_630,
0106 PCI_DEVICE_ID_SI_730,
0107 PCI_DEVICE_ID_SI_760,
0108 0
0109 };
0110
0111 static inline u8 sis630_read(u8 reg)
0112 {
0113 return inb(smbus_base + reg);
0114 }
0115
0116 static inline void sis630_write(u8 reg, u8 data)
0117 {
0118 outb(data, smbus_base + reg);
0119 }
0120
0121 static int sis630_transaction_start(struct i2c_adapter *adap, int size,
0122 u8 *oldclock)
0123 {
0124 int temp;
0125
0126
0127 temp = sis630_read(SMB_CNT);
0128 if ((temp & (SMB_PROBE | SMB_HOSTBUSY)) != 0x00) {
0129 dev_dbg(&adap->dev, "SMBus busy (%02x). Resetting...\n", temp);
0130
0131 sis630_write(SMBHOST_CNT, SMB_KILL);
0132
0133 temp = sis630_read(SMB_CNT);
0134 if (temp & (SMB_PROBE | SMB_HOSTBUSY)) {
0135 dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
0136 return -EBUSY;
0137 } else {
0138 dev_dbg(&adap->dev, "Successful!\n");
0139 }
0140 }
0141
0142
0143 *oldclock = sis630_read(SMB_CNT);
0144
0145 dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock);
0146
0147
0148
0149 if (high_clock)
0150 sis630_write(SMB_CNT, SMBCLK_SEL);
0151 else
0152 sis630_write(SMB_CNT, (*oldclock & ~MSTO_EN));
0153
0154
0155 temp = sis630_read(SMB_STS);
0156 sis630_write(SMB_STS, temp & 0x1e);
0157
0158
0159 sis630_write(SMBHOST_CNT, SMB_START | (size & 0x07));
0160
0161 return 0;
0162 }
0163
0164 static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
0165 {
0166 int temp, result = 0, timeout = 0;
0167
0168
0169 do {
0170 msleep(1);
0171 temp = sis630_read(SMB_STS);
0172
0173 if (size == SIS630_BLOCK_DATA && (temp & BYTE_DONE_STS))
0174 break;
0175 } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
0176
0177
0178 if (timeout > MAX_TIMEOUT) {
0179 dev_dbg(&adap->dev, "SMBus Timeout!\n");
0180 result = -ETIMEDOUT;
0181 }
0182
0183 if (temp & SMBERR_STS) {
0184 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
0185 result = -ENXIO;
0186 }
0187
0188 if (temp & SMBCOL_STS) {
0189 dev_err(&adap->dev, "Bus collision!\n");
0190 result = -EAGAIN;
0191 }
0192
0193 return result;
0194 }
0195
0196 static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock)
0197 {
0198
0199 sis630_write(SMB_STS, 0xFF);
0200
0201 dev_dbg(&adap->dev,
0202 "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT));
0203
0204
0205
0206
0207
0208 if (high_clock && !(oldclock & SMBCLK_SEL))
0209 sis630_write(SMB_CNT, sis630_read(SMB_CNT) & ~SMBCLK_SEL);
0210
0211 dev_dbg(&adap->dev,
0212 "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT));
0213 }
0214
0215 static int sis630_transaction(struct i2c_adapter *adap, int size)
0216 {
0217 int result = 0;
0218 u8 oldclock = 0;
0219
0220 result = sis630_transaction_start(adap, size, &oldclock);
0221 if (!result) {
0222 result = sis630_transaction_wait(adap, size);
0223 sis630_transaction_end(adap, oldclock);
0224 }
0225
0226 return result;
0227 }
0228
0229 static int sis630_block_data(struct i2c_adapter *adap,
0230 union i2c_smbus_data *data, int read_write)
0231 {
0232 int i, len = 0, rc = 0;
0233 u8 oldclock = 0;
0234
0235 if (read_write == I2C_SMBUS_WRITE) {
0236 len = data->block[0];
0237 if (len < 0)
0238 len = 0;
0239 else if (len > 32)
0240 len = 32;
0241 sis630_write(SMB_COUNT, len);
0242 for (i = 1; i <= len; i++) {
0243 dev_dbg(&adap->dev,
0244 "set data 0x%02x\n", data->block[i]);
0245
0246 sis630_write(SMB_BYTE + (i - 1) % 8, data->block[i]);
0247 if (i == 8 || (len < 8 && i == len)) {
0248 dev_dbg(&adap->dev,
0249 "start trans len=%d i=%d\n", len, i);
0250
0251 rc = sis630_transaction_start(adap,
0252 SIS630_BLOCK_DATA, &oldclock);
0253 if (rc)
0254 return rc;
0255 } else if ((i - 1) % 8 == 7 || i == len) {
0256 dev_dbg(&adap->dev,
0257 "trans_wait len=%d i=%d\n", len, i);
0258 if (i > 8) {
0259 dev_dbg(&adap->dev,
0260 "clear smbary_sts"
0261 " len=%d i=%d\n", len, i);
0262
0263
0264
0265
0266
0267 sis630_write(SMB_STS, BYTE_DONE_STS);
0268 }
0269 rc = sis630_transaction_wait(adap,
0270 SIS630_BLOCK_DATA);
0271 if (rc) {
0272 dev_dbg(&adap->dev,
0273 "trans_wait failed\n");
0274 break;
0275 }
0276 }
0277 }
0278 } else {
0279
0280 data->block[0] = len = 0;
0281 rc = sis630_transaction_start(adap,
0282 SIS630_BLOCK_DATA, &oldclock);
0283 if (rc)
0284 return rc;
0285 do {
0286 rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
0287 if (rc) {
0288 dev_dbg(&adap->dev, "trans_wait failed\n");
0289 break;
0290 }
0291
0292 if (len == 0)
0293 data->block[0] = sis630_read(SMB_COUNT);
0294
0295
0296 if (data->block[0] > 32)
0297 data->block[0] = 32;
0298
0299 dev_dbg(&adap->dev,
0300 "block data read len=0x%x\n", data->block[0]);
0301
0302 for (i = 0; i < 8 && len < data->block[0]; i++, len++) {
0303 dev_dbg(&adap->dev,
0304 "read i=%d len=%d\n", i, len);
0305 data->block[len + 1] = sis630_read(SMB_BYTE +
0306 i);
0307 }
0308
0309 dev_dbg(&adap->dev,
0310 "clear smbary_sts len=%d i=%d\n", len, i);
0311
0312
0313 sis630_write(SMB_STS, BYTE_DONE_STS);
0314 } while (len < data->block[0]);
0315 }
0316
0317 sis630_transaction_end(adap, oldclock);
0318
0319 return rc;
0320 }
0321
0322
0323 static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
0324 unsigned short flags, char read_write,
0325 u8 command, int size, union i2c_smbus_data *data)
0326 {
0327 int status;
0328
0329 switch (size) {
0330 case I2C_SMBUS_QUICK:
0331 sis630_write(SMB_ADDR,
0332 ((addr & 0x7f) << 1) | (read_write & 0x01));
0333 size = SIS630_QUICK;
0334 break;
0335 case I2C_SMBUS_BYTE:
0336 sis630_write(SMB_ADDR,
0337 ((addr & 0x7f) << 1) | (read_write & 0x01));
0338 if (read_write == I2C_SMBUS_WRITE)
0339 sis630_write(SMB_CMD, command);
0340 size = SIS630_BYTE;
0341 break;
0342 case I2C_SMBUS_BYTE_DATA:
0343 sis630_write(SMB_ADDR,
0344 ((addr & 0x7f) << 1) | (read_write & 0x01));
0345 sis630_write(SMB_CMD, command);
0346 if (read_write == I2C_SMBUS_WRITE)
0347 sis630_write(SMB_BYTE, data->byte);
0348 size = SIS630_BYTE_DATA;
0349 break;
0350 case I2C_SMBUS_PROC_CALL:
0351 case I2C_SMBUS_WORD_DATA:
0352 sis630_write(SMB_ADDR,
0353 ((addr & 0x7f) << 1) | (read_write & 0x01));
0354 sis630_write(SMB_CMD, command);
0355 if (read_write == I2C_SMBUS_WRITE) {
0356 sis630_write(SMB_BYTE, data->word & 0xff);
0357 sis630_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8);
0358 }
0359 size = (size == I2C_SMBUS_PROC_CALL ?
0360 SIS630_PCALL : SIS630_WORD_DATA);
0361 break;
0362 case I2C_SMBUS_BLOCK_DATA:
0363 sis630_write(SMB_ADDR,
0364 ((addr & 0x7f) << 1) | (read_write & 0x01));
0365 sis630_write(SMB_CMD, command);
0366 size = SIS630_BLOCK_DATA;
0367 return sis630_block_data(adap, data, read_write);
0368 default:
0369 dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
0370 return -EOPNOTSUPP;
0371 }
0372
0373 status = sis630_transaction(adap, size);
0374 if (status)
0375 return status;
0376
0377 if ((size != SIS630_PCALL) &&
0378 ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
0379 return 0;
0380 }
0381
0382 switch (size) {
0383 case SIS630_BYTE:
0384 case SIS630_BYTE_DATA:
0385 data->byte = sis630_read(SMB_BYTE);
0386 break;
0387 case SIS630_PCALL:
0388 case SIS630_WORD_DATA:
0389 data->word = sis630_read(SMB_BYTE) +
0390 (sis630_read(SMB_BYTE + 1) << 8);
0391 break;
0392 }
0393
0394 return 0;
0395 }
0396
0397 static u32 sis630_func(struct i2c_adapter *adapter)
0398 {
0399 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
0400 I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
0401 I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA;
0402 }
0403
0404 static int sis630_setup(struct pci_dev *sis630_dev)
0405 {
0406 unsigned char b;
0407 struct pci_dev *dummy = NULL;
0408 int retval, i;
0409
0410 unsigned short acpi_base;
0411
0412
0413 for (i = 0; supported[i] > 0; i++) {
0414 dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy);
0415 if (dummy)
0416 break;
0417 }
0418
0419 if (dummy) {
0420 pci_dev_put(dummy);
0421 } else if (force) {
0422 dev_err(&sis630_dev->dev,
0423 "WARNING: Can't detect SIS630 compatible device, but "
0424 "loading because of force option enabled\n");
0425 } else {
0426 return -ENODEV;
0427 }
0428
0429
0430
0431
0432
0433 if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, &b)) {
0434 dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n");
0435 retval = -ENODEV;
0436 goto exit;
0437 }
0438
0439 if (!(b & 0x80) &&
0440 pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) {
0441 dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n");
0442 retval = -ENODEV;
0443 goto exit;
0444 }
0445
0446
0447 if (pci_read_config_word(sis630_dev,
0448 SIS630_ACPI_BASE_REG, &acpi_base)) {
0449 dev_err(&sis630_dev->dev,
0450 "Error: Can't determine ACPI base address\n");
0451 retval = -ENODEV;
0452 goto exit;
0453 }
0454
0455 dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04hx\n", acpi_base);
0456
0457 if (supported[i] == PCI_DEVICE_ID_SI_760)
0458 smbus_base = acpi_base + 0xE0;
0459 else
0460 smbus_base = acpi_base + 0x80;
0461
0462 dev_dbg(&sis630_dev->dev, "SMBus base at 0x%04hx\n", smbus_base);
0463
0464 retval = acpi_check_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
0465 sis630_driver.name);
0466 if (retval)
0467 goto exit;
0468
0469
0470 if (!request_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION,
0471 sis630_driver.name)) {
0472 dev_err(&sis630_dev->dev,
0473 "I/O Region 0x%04x-0x%04x for SMBus already in use.\n",
0474 smbus_base + SMB_STS,
0475 smbus_base + SMB_STS + SIS630_SMB_IOREGION - 1);
0476 retval = -EBUSY;
0477 goto exit;
0478 }
0479
0480 retval = 0;
0481
0482 exit:
0483 if (retval)
0484 smbus_base = 0;
0485 return retval;
0486 }
0487
0488
0489 static const struct i2c_algorithm smbus_algorithm = {
0490 .smbus_xfer = sis630_access,
0491 .functionality = sis630_func,
0492 };
0493
0494 static struct i2c_adapter sis630_adapter = {
0495 .owner = THIS_MODULE,
0496 .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
0497 .algo = &smbus_algorithm,
0498 .retries = 3
0499 };
0500
0501 static const struct pci_device_id sis630_ids[] = {
0502 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
0503 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) },
0504 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_964) },
0505 { 0, }
0506 };
0507
0508 MODULE_DEVICE_TABLE(pci, sis630_ids);
0509
0510 static int sis630_probe(struct pci_dev *dev, const struct pci_device_id *id)
0511 {
0512 if (sis630_setup(dev)) {
0513 dev_err(&dev->dev,
0514 "SIS630 compatible bus not detected, "
0515 "module not inserted.\n");
0516 return -ENODEV;
0517 }
0518
0519
0520 sis630_adapter.dev.parent = &dev->dev;
0521
0522 snprintf(sis630_adapter.name, sizeof(sis630_adapter.name),
0523 "SMBus SIS630 adapter at %04x", smbus_base + SMB_STS);
0524
0525 return i2c_add_adapter(&sis630_adapter);
0526 }
0527
0528 static void sis630_remove(struct pci_dev *dev)
0529 {
0530 if (smbus_base) {
0531 i2c_del_adapter(&sis630_adapter);
0532 release_region(smbus_base + SMB_STS, SIS630_SMB_IOREGION);
0533 smbus_base = 0;
0534 }
0535 }
0536
0537
0538 static struct pci_driver sis630_driver = {
0539 .name = "sis630_smbus",
0540 .id_table = sis630_ids,
0541 .probe = sis630_probe,
0542 .remove = sis630_remove,
0543 };
0544
0545 module_pci_driver(sis630_driver);
0546
0547 MODULE_LICENSE("GPL");
0548 MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>");
0549 MODULE_DESCRIPTION("SIS630 SMBus driver");