This source file includes following definitions.
- ali15x3_setup
- ali15x3_transaction
- ali15x3_access
- ali15x3_func
- ali15x3_probe
- ali15x3_remove
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 #include <linux/module.h>
  50 #include <linux/pci.h>
  51 #include <linux/kernel.h>
  52 #include <linux/stddef.h>
  53 #include <linux/ioport.h>
  54 #include <linux/delay.h>
  55 #include <linux/i2c.h>
  56 #include <linux/acpi.h>
  57 #include <linux/io.h>
  58 
  59 
  60 #define SMBHSTSTS       (0 + ali15x3_smba)
  61 #define SMBHSTCNT       (1 + ali15x3_smba)
  62 #define SMBHSTSTART     (2 + ali15x3_smba)
  63 #define SMBHSTCMD       (7 + ali15x3_smba)
  64 #define SMBHSTADD       (3 + ali15x3_smba)
  65 #define SMBHSTDAT0      (4 + ali15x3_smba)
  66 #define SMBHSTDAT1      (5 + ali15x3_smba)
  67 #define SMBBLKDAT       (6 + ali15x3_smba)
  68 
  69 
  70 #define SMBCOM          0x004
  71 #define SMBBA           0x014
  72 #define SMBATPC         0x05B   
  73 #define SMBHSTCFG       0x0E0
  74 #define SMBSLVC         0x0E1
  75 #define SMBCLK          0x0E2
  76 #define SMBREV          0x008
  77 
  78 
  79 #define MAX_TIMEOUT             200     
  80 #define ALI15X3_SMB_IOSIZE      32
  81 
  82 
  83 
  84 
  85 
  86 #define ALI15X3_SMB_DEFAULTBASE 0xE800
  87 
  88 
  89 #define ALI15X3_LOCK            0x06
  90 
  91 
  92 #define ALI15X3_ABORT           0x02
  93 #define ALI15X3_T_OUT           0x04
  94 #define ALI15X3_QUICK           0x00
  95 #define ALI15X3_BYTE            0x10
  96 #define ALI15X3_BYTE_DATA       0x20
  97 #define ALI15X3_WORD_DATA       0x30
  98 #define ALI15X3_BLOCK_DATA      0x40
  99 #define ALI15X3_BLOCK_CLR       0x80
 100 
 101 
 102 #define ALI15X3_STS_IDLE        0x04
 103 #define ALI15X3_STS_BUSY        0x08
 104 #define ALI15X3_STS_DONE        0x10
 105 #define ALI15X3_STS_DEV         0x20    
 106 #define ALI15X3_STS_COLL        0x40    
 107 #define ALI15X3_STS_TERM        0x80    
 108 #define ALI15X3_STS_ERR         0xE0    
 109 
 110 
 111 
 112 
 113 static u16 force_addr;
 114 module_param_hw(force_addr, ushort, ioport, 0);
 115 MODULE_PARM_DESC(force_addr,
 116                  "Initialize the base address of the i2c controller");
 117 
 118 static struct pci_driver ali15x3_driver;
 119 static unsigned short ali15x3_smba;
 120 
 121 static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
 122 {
 123         u16 a;
 124         unsigned char temp;
 125 
 126         
 127 
 128 
 129 
 130 
 131 
 132         
 133 
 134 
 135 
 136 
 137         pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
 138         if (temp & ALI15X3_LOCK) {
 139                 temp &= ~ALI15X3_LOCK;
 140                 pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
 141         }
 142 
 143         
 144         pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);
 145         ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));
 146         if (ali15x3_smba == 0 && force_addr == 0) {
 147                 dev_err(&ALI15X3_dev->dev, "ALI15X3_smb region uninitialized "
 148                         "- upgrade BIOS or use force_addr=0xaddr\n");
 149                 return -ENODEV;
 150         }
 151 
 152         if(force_addr)
 153                 ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
 154 
 155         if (acpi_check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
 156                               ali15x3_driver.name))
 157                 return -EBUSY;
 158 
 159         if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
 160                             ali15x3_driver.name)) {
 161                 dev_err(&ALI15X3_dev->dev,
 162                         "ALI15X3_smb region 0x%x already in use!\n",
 163                         ali15x3_smba);
 164                 return -ENODEV;
 165         }
 166 
 167         if(force_addr) {
 168                 dev_info(&ALI15X3_dev->dev, "forcing ISA address 0x%04X\n",
 169                         ali15x3_smba);
 170                 if (PCIBIOS_SUCCESSFUL != pci_write_config_word(ALI15X3_dev,
 171                                                                 SMBBA,
 172                                                                 ali15x3_smba))
 173                         goto error;
 174                 if (PCIBIOS_SUCCESSFUL != pci_read_config_word(ALI15X3_dev,
 175                                                                 SMBBA, &a))
 176                         goto error;
 177                 if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) {
 178                         
 179                         dev_err(&ALI15X3_dev->dev,
 180                                 "force address failed - not supported?\n");
 181                         goto error;
 182                 }
 183         }
 184         
 185         pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
 186         if ((temp & 1) == 0) {
 187                 dev_info(&ALI15X3_dev->dev, "enabling SMBus device\n");
 188                 pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01);
 189         }
 190 
 191         
 192         pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
 193         if ((temp & 1) == 0) {
 194                 dev_info(&ALI15X3_dev->dev, "enabling SMBus controller\n");
 195                 pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01);
 196         }
 197 
 198         
 199         pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
 200 
 201         
 202 
 203 
 204 
 205 
 206 
 207 
 208         pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
 209         dev_dbg(&ALI15X3_dev->dev, "SMBREV = 0x%X\n", temp);
 210         dev_dbg(&ALI15X3_dev->dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba);
 211 
 212         return 0;
 213 error:
 214         release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
 215         return -ENODEV;
 216 }
 217 
 218 
 219 static int ali15x3_transaction(struct i2c_adapter *adap)
 220 {
 221         int temp;
 222         int result = 0;
 223         int timeout = 0;
 224 
 225         dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, "
 226                 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),
 227                 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
 228                 inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
 229 
 230         
 231         temp = inb_p(SMBHSTSTS);
 232 
 233         
 234         
 235         if (temp & ALI15X3_STS_BUSY) {
 236         
 237 
 238 
 239 
 240 
 241 
 242 
 243 
 244 
 245 
 246 
 247 
 248 
 249 
 250         
 251         
 252 
 253 
 254 
 255 
 256 
 257                 dev_info(&adap->dev, "Resetting entire SMB Bus to "
 258                         "clear busy condition (%02x)\n", temp);
 259                 outb_p(ALI15X3_T_OUT, SMBHSTCNT);
 260                 temp = inb_p(SMBHSTSTS);
 261         }
 262 
 263         
 264         if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
 265                 
 266                 outb_p(0xFF, SMBHSTSTS);
 267                 if ((temp = inb_p(SMBHSTSTS)) &
 268                     (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
 269                         
 270 
 271                         
 272                         dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - "
 273                                 "controller or device on bus is probably hung\n",
 274                                 temp);
 275                         return -EBUSY;
 276                 }
 277         } else {
 278                 
 279                 if (temp & ALI15X3_STS_DONE) {
 280                         outb_p(temp, SMBHSTSTS);
 281                 }
 282         }
 283 
 284         
 285         outb_p(0xFF, SMBHSTSTART);
 286 
 287         
 288         timeout = 0;
 289         do {
 290                 msleep(1);
 291                 temp = inb_p(SMBHSTSTS);
 292         } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))
 293                  && (timeout++ < MAX_TIMEOUT));
 294 
 295         
 296         if (timeout > MAX_TIMEOUT) {
 297                 result = -ETIMEDOUT;
 298                 dev_err(&adap->dev, "SMBus Timeout!\n");
 299         }
 300 
 301         if (temp & ALI15X3_STS_TERM) {
 302                 result = -EIO;
 303                 dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
 304         }
 305 
 306         
 307 
 308 
 309 
 310 
 311 
 312         if (temp & ALI15X3_STS_COLL) {
 313                 result = -ENXIO;
 314                 dev_dbg(&adap->dev,
 315                         "Error: no response or bus collision ADD=%02x\n",
 316                         inb_p(SMBHSTADD));
 317         }
 318 
 319         
 320         if (temp & ALI15X3_STS_DEV) {
 321                 result = -EIO;
 322                 dev_err(&adap->dev, "Error: device error\n");
 323         }
 324         dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, "
 325                 "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS),
 326                 inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
 327                 inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
 328         return result;
 329 }
 330 
 331 
 332 static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
 333                    unsigned short flags, char read_write, u8 command,
 334                    int size, union i2c_smbus_data * data)
 335 {
 336         int i, len;
 337         int temp;
 338         int timeout;
 339 
 340         
 341         outb_p(0xFF, SMBHSTSTS);
 342         
 343         temp = inb_p(SMBHSTSTS);
 344         for (timeout = 0;
 345              (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
 346              timeout++) {
 347                 msleep(1);
 348                 temp = inb_p(SMBHSTSTS);
 349         }
 350         if (timeout >= MAX_TIMEOUT) {
 351                 dev_err(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp);
 352         }
 353 
 354         switch (size) {
 355         case I2C_SMBUS_QUICK:
 356                 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
 357                        SMBHSTADD);
 358                 size = ALI15X3_QUICK;
 359                 break;
 360         case I2C_SMBUS_BYTE:
 361                 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
 362                        SMBHSTADD);
 363                 if (read_write == I2C_SMBUS_WRITE)
 364                         outb_p(command, SMBHSTCMD);
 365                 size = ALI15X3_BYTE;
 366                 break;
 367         case I2C_SMBUS_BYTE_DATA:
 368                 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
 369                        SMBHSTADD);
 370                 outb_p(command, SMBHSTCMD);
 371                 if (read_write == I2C_SMBUS_WRITE)
 372                         outb_p(data->byte, SMBHSTDAT0);
 373                 size = ALI15X3_BYTE_DATA;
 374                 break;
 375         case I2C_SMBUS_WORD_DATA:
 376                 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
 377                        SMBHSTADD);
 378                 outb_p(command, SMBHSTCMD);
 379                 if (read_write == I2C_SMBUS_WRITE) {
 380                         outb_p(data->word & 0xff, SMBHSTDAT0);
 381                         outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
 382                 }
 383                 size = ALI15X3_WORD_DATA;
 384                 break;
 385         case I2C_SMBUS_BLOCK_DATA:
 386                 outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
 387                        SMBHSTADD);
 388                 outb_p(command, SMBHSTCMD);
 389                 if (read_write == I2C_SMBUS_WRITE) {
 390                         len = data->block[0];
 391                         if (len < 0) {
 392                                 len = 0;
 393                                 data->block[0] = len;
 394                         }
 395                         if (len > 32) {
 396                                 len = 32;
 397                                 data->block[0] = len;
 398                         }
 399                         outb_p(len, SMBHSTDAT0);
 400                         
 401                         outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);
 402                         for (i = 1; i <= len; i++)
 403                                 outb_p(data->block[i], SMBBLKDAT);
 404                 }
 405                 size = ALI15X3_BLOCK_DATA;
 406                 break;
 407         default:
 408                 dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
 409                 return -EOPNOTSUPP;
 410         }
 411 
 412         outb_p(size, SMBHSTCNT);        
 413 
 414         temp = ali15x3_transaction(adap);
 415         if (temp)
 416                 return temp;
 417 
 418         if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
 419                 return 0;
 420 
 421 
 422         switch (size) {
 423         case ALI15X3_BYTE:      
 424                 data->byte = inb_p(SMBHSTDAT0);
 425                 break;
 426         case ALI15X3_BYTE_DATA:
 427                 data->byte = inb_p(SMBHSTDAT0);
 428                 break;
 429         case ALI15X3_WORD_DATA:
 430                 data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
 431                 break;
 432         case ALI15X3_BLOCK_DATA:
 433                 len = inb_p(SMBHSTDAT0);
 434                 if (len > 32)
 435                         len = 32;
 436                 data->block[0] = len;
 437                 
 438                 outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);
 439                 for (i = 1; i <= data->block[0]; i++) {
 440                         data->block[i] = inb_p(SMBBLKDAT);
 441                         dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n",
 442                                 len, i, data->block[i]);
 443                 }
 444                 break;
 445         }
 446         return 0;
 447 }
 448 
 449 static u32 ali15x3_func(struct i2c_adapter *adapter)
 450 {
 451         return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 452             I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
 453             I2C_FUNC_SMBUS_BLOCK_DATA;
 454 }
 455 
 456 static const struct i2c_algorithm smbus_algorithm = {
 457         .smbus_xfer     = ali15x3_access,
 458         .functionality  = ali15x3_func,
 459 };
 460 
 461 static struct i2c_adapter ali15x3_adapter = {
 462         .owner          = THIS_MODULE,
 463         .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
 464         .algo           = &smbus_algorithm,
 465 };
 466 
 467 static const struct pci_device_id ali15x3_ids[] = {
 468         { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
 469         { 0, }
 470 };
 471 
 472 MODULE_DEVICE_TABLE (pci, ali15x3_ids);
 473 
 474 static int ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
 475 {
 476         if (ali15x3_setup(dev)) {
 477                 dev_err(&dev->dev,
 478                         "ALI15X3 not detected, module not inserted.\n");
 479                 return -ENODEV;
 480         }
 481 
 482         
 483         ali15x3_adapter.dev.parent = &dev->dev;
 484 
 485         snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
 486                 "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
 487         return i2c_add_adapter(&ali15x3_adapter);
 488 }
 489 
 490 static void ali15x3_remove(struct pci_dev *dev)
 491 {
 492         i2c_del_adapter(&ali15x3_adapter);
 493         release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
 494 }
 495 
 496 static struct pci_driver ali15x3_driver = {
 497         .name           = "ali15x3_smbus",
 498         .id_table       = ali15x3_ids,
 499         .probe          = ali15x3_probe,
 500         .remove         = ali15x3_remove,
 501 };
 502 
 503 module_pci_driver(ali15x3_driver);
 504 
 505 MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, "
 506                 "Philip Edelbrock <phil@netroedge.com>, "
 507                 "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
 508 MODULE_DESCRIPTION("ALI15X3 SMBus driver");
 509 MODULE_LICENSE("GPL");