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