1 /* 2 i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware 3 monitoring 4 5 Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de> 6 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. 11 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. 16 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. 20 */ 21 22 /* 23 Changes: 24 24.08.2002 25 Fixed the typo in sis630_access (Thanks to Mark M. Hoffman) 26 Changed sis630_transaction.(Thanks to Mark M. Hoffman) 27 18.09.2002 28 Added SIS730 as supported. 29 21.09.2002 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). 34 24.09.2002 35 Fixed typo in sis630_access 36 Fixed logical error by restoring of Host Master Clock 37 31.07.2003 38 Added block data read/write support. 39 */ 40 41 /* 42 Status: beta 43 44 Supports: 45 SIS 630 46 SIS 730 47 48 Note: we assume there can only be one device, with one SMBus interface. 49 */ 50 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> 58 #include <asm/io.h> 59 60 /* SIS630 SMBus registers */ 61 #define SMB_STS 0x80 /* status */ 62 #define SMB_EN 0x81 /* status enable */ 63 #define SMB_CNT 0x82 64 #define SMBHOST_CNT 0x83 65 #define SMB_ADDR 0x84 66 #define SMB_CMD 0x85 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 71 #define SMB_DB0 0x91 72 #define SMB_DB1 0x92 73 #define SMB_SAA 0x93 74 75 /* register count for request_region */ 76 #define SIS630_SMB_IOREGION 20 77 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 83 84 /* Other settings */ 85 #define MAX_TIMEOUT 500 86 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 94 95 static struct pci_driver sis630_driver; 96 97 /* insmod parameters */ 98 static int high_clock; 99 static int force; 100 module_param(high_clock, bool, 0); 101 MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz)."); 102 module_param(force, bool, 0); 103 MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!"); 104 105 /* acpi base address */ 106 static unsigned short acpi_base; 107 108 /* supported chips */ 109 static int supported[] = { 110 PCI_DEVICE_ID_SI_630, 111 PCI_DEVICE_ID_SI_730, 112 0 /* terminates the list */ 113 }; 114 115 static inline u8 sis630_read(u8 reg) 116 { 117 return inb(acpi_base + reg); 118 } 119 120 static inline void sis630_write(u8 reg, u8 data) 121 { 122 outb(data, acpi_base + reg); 123 } 124 125 static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldclock) 126 { 127 int temp; 128 129 /* Make sure the SMBus host is ready to start transmitting. */ 130 if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { 131 dev_dbg(&adap->dev, "SMBus busy (%02x).Resetting...\n",temp); 132 /* kill smbus transaction */ 133 sis630_write(SMBHOST_CNT, 0x20); 134 135 if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { 136 dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); 137 return -1; 138 } else { 139 dev_dbg(&adap->dev, "Successfull!\n"); 140 } 141 } 142 143 /* save old clock, so we can prevent machine for hung */ 144 *oldclock = sis630_read(SMB_CNT); 145 146 dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock); 147 148 /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */ 149 if (high_clock) 150 sis630_write(SMB_CNT, 0x20); 151 else 152 sis630_write(SMB_CNT, (*oldclock & ~0x40)); 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,0x10 | (size & 0x07)); 160 161 return 0; 162 } 163 164 static 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 & 0x10)) 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 = -1; 181 } 182 183 if (temp & 0x02) { 184 dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); 185 result = -1; 186 } 187 188 if (temp & 0x04) { 189 dev_err(&adap->dev, "Bus collision!\n"); 190 result = -1; 191 /* 192 TBD: Datasheet say: 193 the software should clear this bit and restart SMBUS operation. 194 Should we do it or user start request again? 195 */ 196 } 197 198 return result; 199 } 200 201 static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock) 202 { 203 int temp = 0; 204 205 /* clear all status "sticky" bits */ 206 sis630_write(SMB_STS, temp); 207 208 dev_dbg(&adap->dev, "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT)); 209 210 /* 211 * restore old Host Master Clock if high_clock is set 212 * and oldclock was not 56KHz 213 */ 214 if (high_clock && !(oldclock & 0x20)) 215 sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20)); 216 217 dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT)); 218 } 219 220 static int sis630_transaction(struct i2c_adapter *adap, int size) 221 { 222 int result = 0; 223 u8 oldclock = 0; 224 225 result = sis630_transaction_start(adap, size, &oldclock); 226 if (!result) { 227 result = sis630_transaction_wait(adap, size); 228 sis630_transaction_end(adap, oldclock); 229 } 230 231 return result; 232 } 233 234 static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *data, int read_write) 235 { 236 int i, len = 0, rc = 0; 237 u8 oldclock = 0; 238 239 if (read_write == I2C_SMBUS_WRITE) { 240 len = data->block[0]; 241 if (len < 0) 242 len = 0; 243 else if (len > 32) 244 len = 32; 245 sis630_write(SMB_COUNT, len); 246 for (i=1; i <= len; i++) { 247 dev_dbg(&adap->dev, "set data 0x%02x\n", data->block[i]); 248 /* set data */ 249 sis630_write(SMB_BYTE+(i-1)%8, data->block[i]); 250 if (i==8 || (len<8 && i==len)) { 251 dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i); 252 /* first transaction */ 253 if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) 254 return -1; 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 if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { 268 dev_dbg(&adap->dev, "trans_wait failed\n"); 269 rc = -1; 270 break; 271 } 272 } 273 } 274 } 275 else { 276 /* read request */ 277 data->block[0] = len = 0; 278 if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) { 279 return -1; 280 } 281 do { 282 if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) { 283 dev_dbg(&adap->dev, "trans_wait failed\n"); 284 rc = -1; 285 break; 286 } 287 /* if this first transaction then read byte count */ 288 if (len == 0) 289 data->block[0] = sis630_read(SMB_COUNT); 290 291 /* just to be sure */ 292 if (data->block[0] > 32) 293 data->block[0] = 32; 294 295 dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]); 296 297 for (i=0; i < 8 && len < data->block[0]; i++,len++) { 298 dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len); 299 data->block[len+1] = sis630_read(SMB_BYTE+i); 300 } 301 302 dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i); 303 304 /* clear SMBARY_STS */ 305 sis630_write(SMB_STS,0x10); 306 } while(len < data->block[0]); 307 } 308 309 sis630_transaction_end(adap, oldclock); 310 311 return rc; 312 } 313 314 /* Return -1 on error. */ 315 static s32 sis630_access(struct i2c_adapter *adap, u16 addr, 316 unsigned short flags, char read_write, 317 u8 command, int size, union i2c_smbus_data *data) 318 { 319 switch (size) { 320 case I2C_SMBUS_QUICK: 321 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); 322 size = SIS630_QUICK; 323 break; 324 case I2C_SMBUS_BYTE: 325 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); 326 if (read_write == I2C_SMBUS_WRITE) 327 sis630_write(SMB_CMD, command); 328 size = SIS630_BYTE; 329 break; 330 case I2C_SMBUS_BYTE_DATA: 331 sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); 332 sis630_write(SMB_CMD, command); 333 if (read_write == I2C_SMBUS_WRITE) 334 sis630_write(SMB_BYTE, data->byte); 335 size = SIS630_BYTE_DATA; 336 break; 337 case I2C_SMBUS_PROC_CALL: 338 case I2C_SMBUS_WORD_DATA: 339 sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01)); 340 sis630_write(SMB_CMD, command); 341 if (read_write == I2C_SMBUS_WRITE) { 342 sis630_write(SMB_BYTE, data->word & 0xff); 343 sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8); 344 } 345 size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA); 346 break; 347 case I2C_SMBUS_BLOCK_DATA: 348 sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01)); 349 sis630_write(SMB_CMD, command); 350 size = SIS630_BLOCK_DATA; 351 return sis630_block_data(adap, data, read_write); 352 default: 353 printk("Unsupported I2C size\n"); 354 return -1; 355 break; 356 } 357 358 if (sis630_transaction(adap, size)) 359 return -1; 360 361 if ((size != SIS630_PCALL) && 362 ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) { 363 return 0; 364 } 365 366 switch(size) { 367 case SIS630_BYTE: 368 case SIS630_BYTE_DATA: 369 data->byte = sis630_read(SMB_BYTE); 370 break; 371 case SIS630_PCALL: 372 case SIS630_WORD_DATA: 373 data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8); 374 break; 375 default: 376 return -1; 377 break; 378 } 379 380 return 0; 381 } 382 383 static u32 sis630_func(struct i2c_adapter *adapter) 384 { 385 return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | 386 I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL | 387 I2C_FUNC_SMBUS_BLOCK_DATA; 388 } 389 390 static int sis630_setup(struct pci_dev *sis630_dev) 391 { 392 unsigned char b; 393 struct pci_dev *dummy = NULL; 394 int retval = -ENODEV, i; 395 396 /* check for supported SiS devices */ 397 for (i=0; supported[i] > 0 ; i++) { 398 if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy))) 399 break; /* found */ 400 } 401 402 if (dummy) { 403 pci_dev_put(dummy); 404 } 405 else if (force) { 406 dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but " 407 "loading because of force option enabled\n"); 408 } 409 else { 410 return -ENODEV; 411 } 412 413 /* 414 Enable ACPI first , so we can accsess reg 74-75 415 in acpi io space and read acpi base addr 416 */ 417 if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) { 418 dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n"); 419 goto exit; 420 } 421 /* if ACPI already enabled , do nothing */ 422 if (!(b & 0x80) && 423 pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) { 424 dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n"); 425 goto exit; 426 } 427 428 /* Determine the ACPI base address */ 429 if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) { 430 dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n"); 431 goto exit; 432 } 433 434 dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base); 435 436 /* Everything is happy, let's grab the memory and set things up. */ 437 if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, 438 sis630_driver.name)) { 439 dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already " 440 "in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA); 441 goto exit; 442 } 443 444 retval = 0; 445 446 exit: 447 if (retval) 448 acpi_base = 0; 449 return retval; 450 } 451 452 453 static const struct i2c_algorithm smbus_algorithm = { 454 .smbus_xfer = sis630_access, 455 .functionality = sis630_func, 456 }; 457 458 static struct i2c_adapter sis630_adapter = { 459 .owner = THIS_MODULE, 460 .id = I2C_HW_SMBUS_SIS630, 461 .class = I2C_CLASS_HWMON, 462 .algo = &smbus_algorithm, 463 }; 464 465 static struct pci_device_id sis630_ids[] __devinitdata = { 466 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, 467 { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) }, 468 { 0, } 469 }; 470 471 MODULE_DEVICE_TABLE (pci, sis630_ids); 472 473 static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) 474 { 475 if (sis630_setup(dev)) { 476 dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n"); 477 return -ENODEV; 478 } 479 480 /* set up the sysfs linkage to our parent device */ 481 sis630_adapter.dev.parent = &dev->dev; 482 483 sprintf(sis630_adapter.name, "SMBus SIS630 adapter at %04x", 484 acpi_base + SMB_STS); 485 486 return i2c_add_adapter(&sis630_adapter); 487 } 488 489 static void __devexit sis630_remove(struct pci_dev *dev) 490 { 491 if (acpi_base) { 492 i2c_del_adapter(&sis630_adapter); 493 release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION); 494 acpi_base = 0; 495 } 496 } 497 498 499 static struct pci_driver sis630_driver = { 500 .name = "sis630_smbus", 501 .id_table = sis630_ids, 502 .probe = sis630_probe, 503 .remove = __devexit_p(sis630_remove), 504 }; 505 506 static int __init i2c_sis630_init(void) 507 { 508 return pci_register_driver(&sis630_driver); 509 } 510 511 512 static void __exit i2c_sis630_exit(void) 513 { 514 pci_unregister_driver(&sis630_driver); 515 } 516 517 518 MODULE_LICENSE("GPL"); 519 MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>"); 520 MODULE_DESCRIPTION("SIS630 SMBus driver"); 521 522 module_init(i2c_sis630_init); 523 module_exit(i2c_sis630_exit); 524