linux/drivers/i2c/busses/i2c-ali1563.c
<<
>>
Prefs
   1/**
   2 *      i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
   3 *
   4 *      Copyright (C) 2004 Patrick Mochel
   5 *                    2005 Rudolf Marek <r.marek@assembler.cz>
   6 *
   7 *      The 1563 southbridge is deceptively similar to the 1533, with a
   8 *      few notable exceptions. One of those happens to be the fact they
   9 *      upgraded the i2c core to be 2.0 compliant, and happens to be almost
  10 *      identical to the i2c controller found in the Intel 801 south
  11 *      bridges.
  12 *
  13 *      This driver is based on a mix of the 15x3, 1535, and i801 drivers,
  14 *      with a little help from the ALi 1563 spec.
  15 *
  16 *      This file is released under the GPLv2
  17 */
  18
  19#include <linux/module.h>
  20#include <linux/delay.h>
  21#include <linux/i2c.h>
  22#include <linux/pci.h>
  23#include <linux/init.h>
  24#include <linux/acpi.h>
  25
  26#define ALI1563_MAX_TIMEOUT     500
  27#define ALI1563_SMBBA           0x80
  28#define ALI1563_SMB_IOEN        1
  29#define ALI1563_SMB_HOSTEN      2
  30#define ALI1563_SMB_IOSIZE      16
  31
  32#define SMB_HST_STS     (ali1563_smba + 0)
  33#define SMB_HST_CNTL1   (ali1563_smba + 1)
  34#define SMB_HST_CNTL2   (ali1563_smba + 2)
  35#define SMB_HST_CMD     (ali1563_smba + 3)
  36#define SMB_HST_ADD     (ali1563_smba + 4)
  37#define SMB_HST_DAT0    (ali1563_smba + 5)
  38#define SMB_HST_DAT1    (ali1563_smba + 6)
  39#define SMB_BLK_DAT     (ali1563_smba + 7)
  40
  41#define HST_STS_BUSY    0x01
  42#define HST_STS_INTR    0x02
  43#define HST_STS_DEVERR  0x04
  44#define HST_STS_BUSERR  0x08
  45#define HST_STS_FAIL    0x10
  46#define HST_STS_DONE    0x80
  47#define HST_STS_BAD     0x1c
  48
  49
  50#define HST_CNTL1_TIMEOUT       0x80
  51#define HST_CNTL1_LAST          0x40
  52
  53#define HST_CNTL2_KILL          0x04
  54#define HST_CNTL2_START         0x40
  55#define HST_CNTL2_QUICK         0x00
  56#define HST_CNTL2_BYTE          0x01
  57#define HST_CNTL2_BYTE_DATA     0x02
  58#define HST_CNTL2_WORD_DATA     0x03
  59#define HST_CNTL2_BLOCK         0x05
  60
  61
  62#define HST_CNTL2_SIZEMASK      0x38
  63
  64static struct pci_driver ali1563_pci_driver;
  65static unsigned short ali1563_smba;
  66
  67static int ali1563_transaction(struct i2c_adapter * a, int size)
  68{
  69        u32 data;
  70        int timeout;
  71        int status = -EIO;
  72
  73        dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, "
  74                "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
  75                inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),
  76                inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),
  77                inb_p(SMB_HST_DAT1));
  78
  79        data = inb_p(SMB_HST_STS);
  80        if (data & HST_STS_BAD) {
  81                dev_err(&a->dev, "ali1563: Trying to reset busy device\n");
  82                outb_p(data | HST_STS_BAD,SMB_HST_STS);
  83                data = inb_p(SMB_HST_STS);
  84                if (data & HST_STS_BAD)
  85                        return -EBUSY;
  86        }
  87        outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2);
  88
  89        timeout = ALI1563_MAX_TIMEOUT;
  90        do {
  91                msleep(1);
  92        } while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout);
  93
  94        dev_dbg(&a->dev, "Transaction (post): STS=%02x, CNTL1=%02x, "
  95                "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
  96                inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),
  97                inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),
  98                inb_p(SMB_HST_DAT1));
  99
 100        if (timeout && !(data & HST_STS_BAD))
 101                return 0;
 102
 103        if (!timeout) {
 104                dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n");
 105                /* Issue 'kill' to host controller */
 106                outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
 107                data = inb_p(SMB_HST_STS);
 108                status = -ETIMEDOUT;
 109        }
 110
 111        /* device error - no response, ignore the autodetection case */
 112        if (data & HST_STS_DEVERR) {
 113                if (size != HST_CNTL2_QUICK)
 114                        dev_err(&a->dev, "Device error!\n");
 115                status = -ENXIO;
 116        }
 117        /* bus collision */
 118        if (data & HST_STS_BUSERR) {
 119                dev_err(&a->dev, "Bus collision!\n");
 120                /* Issue timeout, hoping it helps */
 121                outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
 122        }
 123
 124        if (data & HST_STS_FAIL) {
 125                dev_err(&a->dev, "Cleaning fail after KILL!\n");
 126                outb_p(0x0,SMB_HST_CNTL2);
 127        }
 128
 129        return status;
 130}
 131
 132static int ali1563_block_start(struct i2c_adapter * a)
 133{
 134        u32 data;
 135        int timeout;
 136        int status = -EIO;
 137
 138        dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, "
 139                "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
 140                inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),
 141                inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),
 142                inb_p(SMB_HST_DAT1));
 143
 144        data = inb_p(SMB_HST_STS);
 145        if (data & HST_STS_BAD) {
 146                dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");
 147                outb_p(data | HST_STS_BAD,SMB_HST_STS);
 148                data = inb_p(SMB_HST_STS);
 149                if (data & HST_STS_BAD)
 150                        return -EBUSY;
 151        }
 152
 153        /* Clear byte-ready bit */
 154        outb_p(data | HST_STS_DONE, SMB_HST_STS);
 155
 156        /* Start transaction and wait for byte-ready bit to be set */
 157        outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2);
 158
 159        timeout = ALI1563_MAX_TIMEOUT;
 160        do {
 161                msleep(1);
 162        } while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout);
 163
 164        dev_dbg(&a->dev, "Block (post): STS=%02x, CNTL1=%02x, "
 165                "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
 166                inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),
 167                inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),
 168                inb_p(SMB_HST_DAT1));
 169
 170        if (timeout && !(data & HST_STS_BAD))
 171                return 0;
 172
 173        if (timeout == 0)
 174                status = -ETIMEDOUT;
 175
 176        if (data & HST_STS_DEVERR)
 177                status = -ENXIO;
 178
 179        dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",
 180                timeout ? "" : "Timeout ",
 181                data & HST_STS_FAIL ? "Transaction Failed " : "",
 182                data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
 183                data & HST_STS_DEVERR ? "Device Error " : "",
 184                !(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
 185        return status;
 186}
 187
 188static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)
 189{
 190        int i, len;
 191        int error = 0;
 192
 193        /* Do we need this? */
 194        outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);
 195
 196        if (rw == I2C_SMBUS_WRITE) {
 197                len = data->block[0];
 198                if (len < 1)
 199                        len = 1;
 200                else if (len > 32)
 201                        len = 32;
 202                outb_p(len,SMB_HST_DAT0);
 203                outb_p(data->block[1],SMB_BLK_DAT);
 204        } else
 205                len = 32;
 206
 207        outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_BLOCK, SMB_HST_CNTL2);
 208
 209        for (i = 0; i < len; i++) {
 210                if (rw == I2C_SMBUS_WRITE) {
 211                        outb_p(data->block[i + 1], SMB_BLK_DAT);
 212                        if ((error = ali1563_block_start(a)))
 213                                break;
 214                } else {
 215                        if ((error = ali1563_block_start(a)))
 216                                break;
 217                        if (i == 0) {
 218                                len = inb_p(SMB_HST_DAT0);
 219                                if (len < 1)
 220                                        len = 1;
 221                                else if (len > 32)
 222                                        len = 32;
 223                        }
 224                        data->block[i+1] = inb_p(SMB_BLK_DAT);
 225                }
 226        }
 227        /* Do we need this? */
 228        outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);
 229        return error;
 230}
 231
 232static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
 233                          unsigned short flags, char rw, u8 cmd,
 234                          int size, union i2c_smbus_data * data)
 235{
 236        int error = 0;
 237        int timeout;
 238        u32 reg;
 239
 240        for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) {
 241                if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY))
 242                        break;
 243        }
 244        if (!timeout)
 245                dev_warn(&a->dev,"SMBus not idle. HST_STS = %02x\n",reg);
 246        outb_p(0xff,SMB_HST_STS);
 247
 248        /* Map the size to what the chip understands */
 249        switch (size) {
 250        case I2C_SMBUS_QUICK:
 251                size = HST_CNTL2_QUICK;
 252                break;
 253        case I2C_SMBUS_BYTE:
 254                size = HST_CNTL2_BYTE;
 255                break;
 256        case I2C_SMBUS_BYTE_DATA:
 257                size = HST_CNTL2_BYTE_DATA;
 258                break;
 259        case I2C_SMBUS_WORD_DATA:
 260                size = HST_CNTL2_WORD_DATA;
 261                break;
 262        case I2C_SMBUS_BLOCK_DATA:
 263                size = HST_CNTL2_BLOCK;
 264                break;
 265        default:
 266                dev_warn(&a->dev, "Unsupported transaction %d\n", size);
 267                error = -EOPNOTSUPP;
 268                goto Done;
 269        }
 270
 271        outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
 272        outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2);
 273
 274        /* Write the command register */
 275
 276        switch(size) {
 277        case HST_CNTL2_BYTE:
 278                if (rw== I2C_SMBUS_WRITE)
 279                        /* Beware it uses DAT0 register and not CMD! */
 280                        outb_p(cmd, SMB_HST_DAT0);
 281                break;
 282        case HST_CNTL2_BYTE_DATA:
 283                outb_p(cmd, SMB_HST_CMD);
 284                if (rw == I2C_SMBUS_WRITE)
 285                        outb_p(data->byte, SMB_HST_DAT0);
 286                break;
 287        case HST_CNTL2_WORD_DATA:
 288                outb_p(cmd, SMB_HST_CMD);
 289                if (rw == I2C_SMBUS_WRITE) {
 290                        outb_p(data->word & 0xff, SMB_HST_DAT0);
 291                        outb_p((data->word & 0xff00) >> 8, SMB_HST_DAT1);
 292                }
 293                break;
 294        case HST_CNTL2_BLOCK:
 295                outb_p(cmd, SMB_HST_CMD);
 296                error = ali1563_block(a,data,rw);
 297                goto Done;
 298        }
 299
 300        if ((error = ali1563_transaction(a, size)))
 301                goto Done;
 302
 303        if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
 304                goto Done;
 305
 306        switch (size) {
 307        case HST_CNTL2_BYTE:    /* Result put in SMBHSTDAT0 */
 308                data->byte = inb_p(SMB_HST_DAT0);
 309                break;
 310        case HST_CNTL2_BYTE_DATA:
 311                data->byte = inb_p(SMB_HST_DAT0);
 312                break;
 313        case HST_CNTL2_WORD_DATA:
 314                data->word = inb_p(SMB_HST_DAT0) + (inb_p(SMB_HST_DAT1) << 8);
 315                break;
 316        }
 317Done:
 318        return error;
 319}
 320
 321static u32 ali1563_func(struct i2c_adapter * a)
 322{
 323        return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 324            I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
 325            I2C_FUNC_SMBUS_BLOCK_DATA;
 326}
 327
 328
 329static int ali1563_setup(struct pci_dev *dev)
 330{
 331        u16 ctrl;
 332
 333        pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
 334
 335        /* SMB I/O Base in high 12 bits and must be aligned with the
 336         * size of the I/O space. */
 337        ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1);
 338        if (!ali1563_smba) {
 339                dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
 340                goto Err;
 341        }
 342
 343        /* Check if device is enabled */
 344        if (!(ctrl & ALI1563_SMB_HOSTEN)) {
 345                dev_warn(&dev->dev, "Host Controller not enabled\n");
 346                goto Err;
 347        }
 348        if (!(ctrl & ALI1563_SMB_IOEN)) {
 349                dev_warn(&dev->dev, "I/O space not enabled, trying manually\n");
 350                pci_write_config_word(dev, ALI1563_SMBBA,
 351                                      ctrl | ALI1563_SMB_IOEN);
 352                pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);
 353                if (!(ctrl & ALI1563_SMB_IOEN)) {
 354                        dev_err(&dev->dev, "I/O space still not enabled, "
 355                                "giving up\n");
 356                        goto Err;
 357                }
 358        }
 359
 360        if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE,
 361                              ali1563_pci_driver.name))
 362                goto Err;
 363
 364        if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
 365                            ali1563_pci_driver.name)) {
 366                dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",
 367                        ali1563_smba);
 368                goto Err;
 369        }
 370        dev_info(&dev->dev, "Found ALi1563 SMBus at 0x%04x\n", ali1563_smba);
 371
 372        return 0;
 373Err:
 374        return -ENODEV;
 375}
 376
 377static void ali1563_shutdown(struct pci_dev *dev)
 378{
 379        release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
 380}
 381
 382static const struct i2c_algorithm ali1563_algorithm = {
 383        .smbus_xfer     = ali1563_access,
 384        .functionality  = ali1563_func,
 385};
 386
 387static struct i2c_adapter ali1563_adapter = {
 388        .owner  = THIS_MODULE,
 389        .class  = I2C_CLASS_HWMON | I2C_CLASS_SPD,
 390        .algo   = &ali1563_algorithm,
 391};
 392
 393static int ali1563_probe(struct pci_dev *dev,
 394                         const struct pci_device_id *id_table)
 395{
 396        int error;
 397
 398        if ((error = ali1563_setup(dev)))
 399                goto exit;
 400        ali1563_adapter.dev.parent = &dev->dev;
 401        snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name),
 402                 "SMBus ALi 1563 Adapter @ %04x", ali1563_smba);
 403        if ((error = i2c_add_adapter(&ali1563_adapter)))
 404                goto exit_shutdown;
 405        return 0;
 406
 407exit_shutdown:
 408        ali1563_shutdown(dev);
 409exit:
 410        dev_warn(&dev->dev, "ALi1563 SMBus probe failed (%d)\n", error);
 411        return error;
 412}
 413
 414static void ali1563_remove(struct pci_dev *dev)
 415{
 416        i2c_del_adapter(&ali1563_adapter);
 417        ali1563_shutdown(dev);
 418}
 419
 420static DEFINE_PCI_DEVICE_TABLE(ali1563_id_table) = {
 421        { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) },
 422        {},
 423};
 424
 425MODULE_DEVICE_TABLE (pci, ali1563_id_table);
 426
 427static struct pci_driver ali1563_pci_driver = {
 428        .name           = "ali1563_smbus",
 429        .id_table       = ali1563_id_table,
 430        .probe          = ali1563_probe,
 431        .remove         = ali1563_remove,
 432};
 433
 434module_pci_driver(ali1563_pci_driver);
 435
 436MODULE_LICENSE("GPL");
 437