linux/drivers/i2c/busses/i2c-amd8111.c
<<
>>
Prefs
   1/*
   2 * SMBus 2.0 driver for AMD-8111 IO-Hub.
   3 *
   4 * Copyright (c) 2002 Vojtech Pavlik
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License as published by
   8 * the Free Software Foundation version 2.
   9 */
  10
  11#include <linux/module.h>
  12#include <linux/pci.h>
  13#include <linux/kernel.h>
  14#include <linux/stddef.h>
  15#include <linux/ioport.h>
  16#include <linux/init.h>
  17#include <linux/i2c.h>
  18#include <linux/delay.h>
  19#include <linux/acpi.h>
  20#include <linux/slab.h>
  21#include <linux/io.h>
  22
  23MODULE_LICENSE("GPL");
  24MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>");
  25MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver");
  26
  27struct amd_smbus {
  28        struct pci_dev *dev;
  29        struct i2c_adapter adapter;
  30        int base;
  31        int size;
  32};
  33
  34static struct pci_driver amd8111_driver;
  35
  36/*
  37 * AMD PCI control registers definitions.
  38 */
  39
  40#define AMD_PCI_MISC    0x48
  41
  42#define AMD_PCI_MISC_SCI        0x04    /* deliver SCI */
  43#define AMD_PCI_MISC_INT        0x02    /* deliver PCI IRQ */
  44#define AMD_PCI_MISC_SPEEDUP    0x01    /* 16x clock speedup */
  45
  46/*
  47 * ACPI 2.0 chapter 13 PCI interface definitions.
  48 */
  49
  50#define AMD_EC_DATA     0x00    /* data register */
  51#define AMD_EC_SC       0x04    /* status of controller */
  52#define AMD_EC_CMD      0x04    /* command register */
  53#define AMD_EC_ICR      0x08    /* interrupt control register */
  54
  55#define AMD_EC_SC_SMI   0x04    /* smi event pending */
  56#define AMD_EC_SC_SCI   0x02    /* sci event pending */
  57#define AMD_EC_SC_BURST 0x01    /* burst mode enabled */
  58#define AMD_EC_SC_CMD   0x08    /* byte in data reg is command */
  59#define AMD_EC_SC_IBF   0x02    /* data ready for embedded controller */
  60#define AMD_EC_SC_OBF   0x01    /* data ready for host */
  61
  62#define AMD_EC_CMD_RD   0x80    /* read EC */
  63#define AMD_EC_CMD_WR   0x81    /* write EC */
  64#define AMD_EC_CMD_BE   0x82    /* enable burst mode */
  65#define AMD_EC_CMD_BD   0x83    /* disable burst mode */
  66#define AMD_EC_CMD_QR   0x84    /* query EC */
  67
  68/*
  69 * ACPI 2.0 chapter 13 access of registers of the EC
  70 */
  71
  72static int amd_ec_wait_write(struct amd_smbus *smbus)
  73{
  74        int timeout = 500;
  75
  76        while ((inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout)
  77                udelay(1);
  78
  79        if (!timeout) {
  80                dev_warn(&smbus->dev->dev,
  81                         "Timeout while waiting for IBF to clear\n");
  82                return -ETIMEDOUT;
  83        }
  84
  85        return 0;
  86}
  87
  88static int amd_ec_wait_read(struct amd_smbus *smbus)
  89{
  90        int timeout = 500;
  91
  92        while ((~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout)
  93                udelay(1);
  94
  95        if (!timeout) {
  96                dev_warn(&smbus->dev->dev,
  97                         "Timeout while waiting for OBF to set\n");
  98                return -ETIMEDOUT;
  99        }
 100
 101        return 0;
 102}
 103
 104static int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
 105                unsigned char *data)
 106{
 107        int status;
 108
 109        status = amd_ec_wait_write(smbus);
 110        if (status)
 111                return status;
 112        outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
 113
 114        status = amd_ec_wait_write(smbus);
 115        if (status)
 116                return status;
 117        outb(address, smbus->base + AMD_EC_DATA);
 118
 119        status = amd_ec_wait_read(smbus);
 120        if (status)
 121                return status;
 122        *data = inb(smbus->base + AMD_EC_DATA);
 123
 124        return 0;
 125}
 126
 127static int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
 128                unsigned char data)
 129{
 130        int status;
 131
 132        status = amd_ec_wait_write(smbus);
 133        if (status)
 134                return status;
 135        outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
 136
 137        status = amd_ec_wait_write(smbus);
 138        if (status)
 139                return status;
 140        outb(address, smbus->base + AMD_EC_DATA);
 141
 142        status = amd_ec_wait_write(smbus);
 143        if (status)
 144                return status;
 145        outb(data, smbus->base + AMD_EC_DATA);
 146
 147        return 0;
 148}
 149
 150/*
 151 * ACPI 2.0 chapter 13 SMBus 2.0 EC register model
 152 */
 153
 154#define AMD_SMB_PRTCL   0x00    /* protocol, PEC */
 155#define AMD_SMB_STS     0x01    /* status */
 156#define AMD_SMB_ADDR    0x02    /* address */
 157#define AMD_SMB_CMD     0x03    /* command */
 158#define AMD_SMB_DATA    0x04    /* 32 data registers */
 159#define AMD_SMB_BCNT    0x24    /* number of data bytes */
 160#define AMD_SMB_ALRM_A  0x25    /* alarm address */
 161#define AMD_SMB_ALRM_D  0x26    /* 2 bytes alarm data */
 162
 163#define AMD_SMB_STS_DONE        0x80
 164#define AMD_SMB_STS_ALRM        0x40
 165#define AMD_SMB_STS_RES         0x20
 166#define AMD_SMB_STS_STATUS      0x1f
 167
 168#define AMD_SMB_STATUS_OK       0x00
 169#define AMD_SMB_STATUS_FAIL     0x07
 170#define AMD_SMB_STATUS_DNAK     0x10
 171#define AMD_SMB_STATUS_DERR     0x11
 172#define AMD_SMB_STATUS_CMD_DENY 0x12
 173#define AMD_SMB_STATUS_UNKNOWN  0x13
 174#define AMD_SMB_STATUS_ACC_DENY 0x17
 175#define AMD_SMB_STATUS_TIMEOUT  0x18
 176#define AMD_SMB_STATUS_NOTSUP   0x19
 177#define AMD_SMB_STATUS_BUSY     0x1A
 178#define AMD_SMB_STATUS_PEC      0x1F
 179
 180#define AMD_SMB_PRTCL_WRITE             0x00
 181#define AMD_SMB_PRTCL_READ              0x01
 182#define AMD_SMB_PRTCL_QUICK             0x02
 183#define AMD_SMB_PRTCL_BYTE              0x04
 184#define AMD_SMB_PRTCL_BYTE_DATA         0x06
 185#define AMD_SMB_PRTCL_WORD_DATA         0x08
 186#define AMD_SMB_PRTCL_BLOCK_DATA        0x0a
 187#define AMD_SMB_PRTCL_PROC_CALL         0x0c
 188#define AMD_SMB_PRTCL_BLOCK_PROC_CALL   0x0d
 189#define AMD_SMB_PRTCL_I2C_BLOCK_DATA    0x4a
 190#define AMD_SMB_PRTCL_PEC               0x80
 191
 192
 193static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
 194                unsigned short flags, char read_write, u8 command, int size,
 195                union i2c_smbus_data * data)
 196{
 197        struct amd_smbus *smbus = adap->algo_data;
 198        unsigned char protocol, len, pec, temp[2];
 199        int i, status;
 200
 201        protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ
 202                                                  : AMD_SMB_PRTCL_WRITE;
 203        pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0;
 204
 205        switch (size) {
 206                case I2C_SMBUS_QUICK:
 207                        protocol |= AMD_SMB_PRTCL_QUICK;
 208                        read_write = I2C_SMBUS_WRITE;
 209                        break;
 210
 211                case I2C_SMBUS_BYTE:
 212                        if (read_write == I2C_SMBUS_WRITE) {
 213                                status = amd_ec_write(smbus, AMD_SMB_CMD,
 214                                                      command);
 215                                if (status)
 216                                        return status;
 217                        }
 218                        protocol |= AMD_SMB_PRTCL_BYTE;
 219                        break;
 220
 221                case I2C_SMBUS_BYTE_DATA:
 222                        status = amd_ec_write(smbus, AMD_SMB_CMD, command);
 223                        if (status)
 224                                return status;
 225                        if (read_write == I2C_SMBUS_WRITE) {
 226                                status = amd_ec_write(smbus, AMD_SMB_DATA,
 227                                                      data->byte);
 228                                if (status)
 229                                        return status;
 230                        }
 231                        protocol |= AMD_SMB_PRTCL_BYTE_DATA;
 232                        break;
 233
 234                case I2C_SMBUS_WORD_DATA:
 235                        status = amd_ec_write(smbus, AMD_SMB_CMD, command);
 236                        if (status)
 237                                return status;
 238                        if (read_write == I2C_SMBUS_WRITE) {
 239                                status = amd_ec_write(smbus, AMD_SMB_DATA,
 240                                                      data->word & 0xff);
 241                                if (status)
 242                                        return status;
 243                                status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
 244                                                      data->word >> 8);
 245                                if (status)
 246                                        return status;
 247                        }
 248                        protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
 249                        break;
 250
 251                case I2C_SMBUS_BLOCK_DATA:
 252                        status = amd_ec_write(smbus, AMD_SMB_CMD, command);
 253                        if (status)
 254                                return status;
 255                        if (read_write == I2C_SMBUS_WRITE) {
 256                                len = min_t(u8, data->block[0],
 257                                            I2C_SMBUS_BLOCK_MAX);
 258                                status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
 259                                if (status)
 260                                        return status;
 261                                for (i = 0; i < len; i++) {
 262                                        status =
 263                                          amd_ec_write(smbus, AMD_SMB_DATA + i,
 264                                                       data->block[i + 1]);
 265                                        if (status)
 266                                                return status;
 267                                }
 268                        }
 269                        protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
 270                        break;
 271
 272                case I2C_SMBUS_I2C_BLOCK_DATA:
 273                        len = min_t(u8, data->block[0],
 274                                    I2C_SMBUS_BLOCK_MAX);
 275                        status = amd_ec_write(smbus, AMD_SMB_CMD, command);
 276                        if (status)
 277                                return status;
 278                        status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
 279                        if (status)
 280                                return status;
 281                        if (read_write == I2C_SMBUS_WRITE)
 282                                for (i = 0; i < len; i++) {
 283                                        status =
 284                                          amd_ec_write(smbus, AMD_SMB_DATA + i,
 285                                                       data->block[i + 1]);
 286                                        if (status)
 287                                                return status;
 288                                }
 289                        protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
 290                        break;
 291
 292                case I2C_SMBUS_PROC_CALL:
 293                        status = amd_ec_write(smbus, AMD_SMB_CMD, command);
 294                        if (status)
 295                                return status;
 296                        status = amd_ec_write(smbus, AMD_SMB_DATA,
 297                                              data->word & 0xff);
 298                        if (status)
 299                                return status;
 300                        status = amd_ec_write(smbus, AMD_SMB_DATA + 1,
 301                                              data->word >> 8);
 302                        if (status)
 303                                return status;
 304                        protocol = AMD_SMB_PRTCL_PROC_CALL | pec;
 305                        read_write = I2C_SMBUS_READ;
 306                        break;
 307
 308                case I2C_SMBUS_BLOCK_PROC_CALL:
 309                        len = min_t(u8, data->block[0],
 310                                    I2C_SMBUS_BLOCK_MAX - 1);
 311                        status = amd_ec_write(smbus, AMD_SMB_CMD, command);
 312                        if (status)
 313                                return status;
 314                        status = amd_ec_write(smbus, AMD_SMB_BCNT, len);
 315                        if (status)
 316                                return status;
 317                        for (i = 0; i < len; i++) {
 318                                status = amd_ec_write(smbus, AMD_SMB_DATA + i,
 319                                                      data->block[i + 1]);
 320                                if (status)
 321                                        return status;
 322                        }
 323                        protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;
 324                        read_write = I2C_SMBUS_READ;
 325                        break;
 326
 327                default:
 328                        dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
 329                        return -EOPNOTSUPP;
 330        }
 331
 332        status = amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
 333        if (status)
 334                return status;
 335        status = amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
 336        if (status)
 337                return status;
 338
 339        status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
 340        if (status)
 341                return status;
 342
 343        if (~temp[0] & AMD_SMB_STS_DONE) {
 344                udelay(500);
 345                status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
 346                if (status)
 347                        return status;
 348        }
 349
 350        if (~temp[0] & AMD_SMB_STS_DONE) {
 351                msleep(1);
 352                status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
 353                if (status)
 354                        return status;
 355        }
 356
 357        if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
 358                return -EIO;
 359
 360        if (read_write == I2C_SMBUS_WRITE)
 361                return 0;
 362
 363        switch (size) {
 364                case I2C_SMBUS_BYTE:
 365                case I2C_SMBUS_BYTE_DATA:
 366                        status = amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
 367                        if (status)
 368                                return status;
 369                        break;
 370
 371                case I2C_SMBUS_WORD_DATA:
 372                case I2C_SMBUS_PROC_CALL:
 373                        status = amd_ec_read(smbus, AMD_SMB_DATA, temp + 0);
 374                        if (status)
 375                                return status;
 376                        status = amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1);
 377                        if (status)
 378                                return status;
 379                        data->word = (temp[1] << 8) | temp[0];
 380                        break;
 381
 382                case I2C_SMBUS_BLOCK_DATA:
 383                case I2C_SMBUS_BLOCK_PROC_CALL:
 384                        status = amd_ec_read(smbus, AMD_SMB_BCNT, &len);
 385                        if (status)
 386                                return status;
 387                        len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
 388                case I2C_SMBUS_I2C_BLOCK_DATA:
 389                        for (i = 0; i < len; i++) {
 390                                status = amd_ec_read(smbus, AMD_SMB_DATA + i,
 391                                                     data->block + i + 1);
 392                                if (status)
 393                                        return status;
 394                        }
 395                        data->block[0] = len;
 396                        break;
 397        }
 398
 399        return 0;
 400}
 401
 402
 403static u32 amd8111_func(struct i2c_adapter *adapter)
 404{
 405        return  I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 406                I2C_FUNC_SMBUS_BYTE_DATA |
 407                I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA |
 408                I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
 409                I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC;
 410}
 411
 412static const struct i2c_algorithm smbus_algorithm = {
 413        .smbus_xfer = amd8111_access,
 414        .functionality = amd8111_func,
 415};
 416
 417
 418static const struct pci_device_id amd8111_ids[] = {
 419        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) },
 420        { 0, }
 421};
 422
 423MODULE_DEVICE_TABLE (pci, amd8111_ids);
 424
 425static int __devinit amd8111_probe(struct pci_dev *dev,
 426                const struct pci_device_id *id)
 427{
 428        struct amd_smbus *smbus;
 429        int error;
 430
 431        if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
 432                return -ENODEV;
 433
 434        smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL);
 435        if (!smbus)
 436                return -ENOMEM;
 437
 438        smbus->dev = dev;
 439        smbus->base = pci_resource_start(dev, 0);
 440        smbus->size = pci_resource_len(dev, 0);
 441
 442        error = acpi_check_resource_conflict(&dev->resource[0]);
 443        if (error) {
 444                error = -ENODEV;
 445                goto out_kfree;
 446        }
 447
 448        if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
 449                error = -EBUSY;
 450                goto out_kfree;
 451        }
 452
 453        smbus->adapter.owner = THIS_MODULE;
 454        snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
 455                "SMBus2 AMD8111 adapter at %04x", smbus->base);
 456        smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
 457        smbus->adapter.algo = &smbus_algorithm;
 458        smbus->adapter.algo_data = smbus;
 459
 460        /* set up the sysfs linkage to our parent device */
 461        smbus->adapter.dev.parent = &dev->dev;
 462
 463        pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
 464        error = i2c_add_adapter(&smbus->adapter);
 465        if (error)
 466                goto out_release_region;
 467
 468        pci_set_drvdata(dev, smbus);
 469        return 0;
 470
 471 out_release_region:
 472        release_region(smbus->base, smbus->size);
 473 out_kfree:
 474        kfree(smbus);
 475        return error;
 476}
 477
 478static void __devexit amd8111_remove(struct pci_dev *dev)
 479{
 480        struct amd_smbus *smbus = pci_get_drvdata(dev);
 481
 482        i2c_del_adapter(&smbus->adapter);
 483        release_region(smbus->base, smbus->size);
 484        kfree(smbus);
 485}
 486
 487static struct pci_driver amd8111_driver = {
 488        .name           = "amd8111_smbus2",
 489        .id_table       = amd8111_ids,
 490        .probe          = amd8111_probe,
 491        .remove         = __devexit_p(amd8111_remove),
 492};
 493
 494static int __init i2c_amd8111_init(void)
 495{
 496        return pci_register_driver(&amd8111_driver);
 497}
 498
 499static void __exit i2c_amd8111_exit(void)
 500{
 501        pci_unregister_driver(&amd8111_driver);
 502}
 503
 504module_init(i2c_amd8111_init);
 505module_exit(i2c_amd8111_exit);
 506