Path: blob/master/drivers/i2c/busses/i2c-ali1563.c
15111 views
/**1* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge2*3* Copyright (C) 2004 Patrick Mochel4* 2005 Rudolf Marek <[email protected]>5*6* The 1563 southbridge is deceptively similar to the 1533, with a7* few notable exceptions. One of those happens to be the fact they8* upgraded the i2c core to be 2.0 compliant, and happens to be almost9* identical to the i2c controller found in the Intel 801 south10* bridges.11*12* This driver is based on a mix of the 15x3, 1535, and i801 drivers,13* with a little help from the ALi 1563 spec.14*15* This file is released under the GPLv216*/1718#include <linux/module.h>19#include <linux/delay.h>20#include <linux/i2c.h>21#include <linux/pci.h>22#include <linux/init.h>23#include <linux/acpi.h>2425#define ALI1563_MAX_TIMEOUT 50026#define ALI1563_SMBBA 0x8027#define ALI1563_SMB_IOEN 128#define ALI1563_SMB_HOSTEN 229#define ALI1563_SMB_IOSIZE 163031#define SMB_HST_STS (ali1563_smba + 0)32#define SMB_HST_CNTL1 (ali1563_smba + 1)33#define SMB_HST_CNTL2 (ali1563_smba + 2)34#define SMB_HST_CMD (ali1563_smba + 3)35#define SMB_HST_ADD (ali1563_smba + 4)36#define SMB_HST_DAT0 (ali1563_smba + 5)37#define SMB_HST_DAT1 (ali1563_smba + 6)38#define SMB_BLK_DAT (ali1563_smba + 7)3940#define HST_STS_BUSY 0x0141#define HST_STS_INTR 0x0242#define HST_STS_DEVERR 0x0443#define HST_STS_BUSERR 0x0844#define HST_STS_FAIL 0x1045#define HST_STS_DONE 0x8046#define HST_STS_BAD 0x1c474849#define HST_CNTL1_TIMEOUT 0x8050#define HST_CNTL1_LAST 0x405152#define HST_CNTL2_KILL 0x0453#define HST_CNTL2_START 0x4054#define HST_CNTL2_QUICK 0x0055#define HST_CNTL2_BYTE 0x0156#define HST_CNTL2_BYTE_DATA 0x0257#define HST_CNTL2_WORD_DATA 0x0358#define HST_CNTL2_BLOCK 0x05596061#define HST_CNTL2_SIZEMASK 0x386263static struct pci_driver ali1563_pci_driver;64static unsigned short ali1563_smba;6566static int ali1563_transaction(struct i2c_adapter * a, int size)67{68u32 data;69int timeout;70int status = -EIO;7172dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, "73"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",74inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),75inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),76inb_p(SMB_HST_DAT1));7778data = inb_p(SMB_HST_STS);79if (data & HST_STS_BAD) {80dev_err(&a->dev, "ali1563: Trying to reset busy device\n");81outb_p(data | HST_STS_BAD,SMB_HST_STS);82data = inb_p(SMB_HST_STS);83if (data & HST_STS_BAD)84return -EBUSY;85}86outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2);8788timeout = ALI1563_MAX_TIMEOUT;89do {90msleep(1);91} while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout);9293dev_dbg(&a->dev, "Transaction (post): STS=%02x, CNTL1=%02x, "94"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",95inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),96inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),97inb_p(SMB_HST_DAT1));9899if (timeout && !(data & HST_STS_BAD))100return 0;101102if (!timeout) {103dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n");104/* Issue 'kill' to host controller */105outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);106data = inb_p(SMB_HST_STS);107status = -ETIMEDOUT;108}109110/* device error - no response, ignore the autodetection case */111if (data & HST_STS_DEVERR) {112if (size != HST_CNTL2_QUICK)113dev_err(&a->dev, "Device error!\n");114status = -ENXIO;115}116/* bus collision */117if (data & HST_STS_BUSERR) {118dev_err(&a->dev, "Bus collision!\n");119/* Issue timeout, hoping it helps */120outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);121}122123if (data & HST_STS_FAIL) {124dev_err(&a->dev, "Cleaning fail after KILL!\n");125outb_p(0x0,SMB_HST_CNTL2);126}127128return status;129}130131static int ali1563_block_start(struct i2c_adapter * a)132{133u32 data;134int timeout;135int status = -EIO;136137dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, "138"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",139inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),140inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),141inb_p(SMB_HST_DAT1));142143data = inb_p(SMB_HST_STS);144if (data & HST_STS_BAD) {145dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");146outb_p(data | HST_STS_BAD,SMB_HST_STS);147data = inb_p(SMB_HST_STS);148if (data & HST_STS_BAD)149return -EBUSY;150}151152/* Clear byte-ready bit */153outb_p(data | HST_STS_DONE, SMB_HST_STS);154155/* Start transaction and wait for byte-ready bit to be set */156outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2);157158timeout = ALI1563_MAX_TIMEOUT;159do {160msleep(1);161} while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout);162163dev_dbg(&a->dev, "Block (post): STS=%02x, CNTL1=%02x, "164"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",165inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),166inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),167inb_p(SMB_HST_DAT1));168169if (timeout && !(data & HST_STS_BAD))170return 0;171172if (timeout == 0)173status = -ETIMEDOUT;174175if (data & HST_STS_DEVERR)176status = -ENXIO;177178dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",179timeout ? "" : "Timeout ",180data & HST_STS_FAIL ? "Transaction Failed " : "",181data & HST_STS_BUSERR ? "No response or Bus Collision " : "",182data & HST_STS_DEVERR ? "Device Error " : "",183!(data & HST_STS_DONE) ? "Transaction Never Finished " : "");184return status;185}186187static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)188{189int i, len;190int error = 0;191192/* Do we need this? */193outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);194195if (rw == I2C_SMBUS_WRITE) {196len = data->block[0];197if (len < 1)198len = 1;199else if (len > 32)200len = 32;201outb_p(len,SMB_HST_DAT0);202outb_p(data->block[1],SMB_BLK_DAT);203} else204len = 32;205206outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_BLOCK, SMB_HST_CNTL2);207208for (i = 0; i < len; i++) {209if (rw == I2C_SMBUS_WRITE) {210outb_p(data->block[i + 1], SMB_BLK_DAT);211if ((error = ali1563_block_start(a)))212break;213} else {214if ((error = ali1563_block_start(a)))215break;216if (i == 0) {217len = inb_p(SMB_HST_DAT0);218if (len < 1)219len = 1;220else if (len > 32)221len = 32;222}223data->block[i+1] = inb_p(SMB_BLK_DAT);224}225}226/* Do we need this? */227outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);228return error;229}230231static s32 ali1563_access(struct i2c_adapter * a, u16 addr,232unsigned short flags, char rw, u8 cmd,233int size, union i2c_smbus_data * data)234{235int error = 0;236int timeout;237u32 reg;238239for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) {240if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY))241break;242}243if (!timeout)244dev_warn(&a->dev,"SMBus not idle. HST_STS = %02x\n",reg);245outb_p(0xff,SMB_HST_STS);246247/* Map the size to what the chip understands */248switch (size) {249case I2C_SMBUS_QUICK:250size = HST_CNTL2_QUICK;251break;252case I2C_SMBUS_BYTE:253size = HST_CNTL2_BYTE;254break;255case I2C_SMBUS_BYTE_DATA:256size = HST_CNTL2_BYTE_DATA;257break;258case I2C_SMBUS_WORD_DATA:259size = HST_CNTL2_WORD_DATA;260break;261case I2C_SMBUS_BLOCK_DATA:262size = HST_CNTL2_BLOCK;263break;264default:265dev_warn(&a->dev, "Unsupported transaction %d\n", size);266error = -EOPNOTSUPP;267goto Done;268}269270outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);271outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2);272273/* Write the command register */274275switch(size) {276case HST_CNTL2_BYTE:277if (rw== I2C_SMBUS_WRITE)278/* Beware it uses DAT0 register and not CMD! */279outb_p(cmd, SMB_HST_DAT0);280break;281case HST_CNTL2_BYTE_DATA:282outb_p(cmd, SMB_HST_CMD);283if (rw == I2C_SMBUS_WRITE)284outb_p(data->byte, SMB_HST_DAT0);285break;286case HST_CNTL2_WORD_DATA:287outb_p(cmd, SMB_HST_CMD);288if (rw == I2C_SMBUS_WRITE) {289outb_p(data->word & 0xff, SMB_HST_DAT0);290outb_p((data->word & 0xff00) >> 8, SMB_HST_DAT1);291}292break;293case HST_CNTL2_BLOCK:294outb_p(cmd, SMB_HST_CMD);295error = ali1563_block(a,data,rw);296goto Done;297}298299if ((error = ali1563_transaction(a, size)))300goto Done;301302if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))303goto Done;304305switch (size) {306case HST_CNTL2_BYTE: /* Result put in SMBHSTDAT0 */307data->byte = inb_p(SMB_HST_DAT0);308break;309case HST_CNTL2_BYTE_DATA:310data->byte = inb_p(SMB_HST_DAT0);311break;312case HST_CNTL2_WORD_DATA:313data->word = inb_p(SMB_HST_DAT0) + (inb_p(SMB_HST_DAT1) << 8);314break;315}316Done:317return error;318}319320static u32 ali1563_func(struct i2c_adapter * a)321{322return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |323I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |324I2C_FUNC_SMBUS_BLOCK_DATA;325}326327328static int __devinit ali1563_setup(struct pci_dev * dev)329{330u16 ctrl;331332pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);333334/* SMB I/O Base in high 12 bits and must be aligned with the335* size of the I/O space. */336ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1);337if (!ali1563_smba) {338dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");339goto Err;340}341342/* Check if device is enabled */343if (!(ctrl & ALI1563_SMB_HOSTEN)) {344dev_warn(&dev->dev, "Host Controller not enabled\n");345goto Err;346}347if (!(ctrl & ALI1563_SMB_IOEN)) {348dev_warn(&dev->dev, "I/O space not enabled, trying manually\n");349pci_write_config_word(dev, ALI1563_SMBBA,350ctrl | ALI1563_SMB_IOEN);351pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);352if (!(ctrl & ALI1563_SMB_IOEN)) {353dev_err(&dev->dev, "I/O space still not enabled, "354"giving up\n");355goto Err;356}357}358359if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE,360ali1563_pci_driver.name))361goto Err;362363if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,364ali1563_pci_driver.name)) {365dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",366ali1563_smba);367goto Err;368}369dev_info(&dev->dev, "Found ALi1563 SMBus at 0x%04x\n", ali1563_smba);370371return 0;372Err:373return -ENODEV;374}375376static void ali1563_shutdown(struct pci_dev *dev)377{378release_region(ali1563_smba,ALI1563_SMB_IOSIZE);379}380381static const struct i2c_algorithm ali1563_algorithm = {382.smbus_xfer = ali1563_access,383.functionality = ali1563_func,384};385386static struct i2c_adapter ali1563_adapter = {387.owner = THIS_MODULE,388.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,389.algo = &ali1563_algorithm,390};391392static int __devinit ali1563_probe(struct pci_dev * dev,393const struct pci_device_id * id_table)394{395int error;396397if ((error = ali1563_setup(dev)))398goto exit;399ali1563_adapter.dev.parent = &dev->dev;400snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name),401"SMBus ALi 1563 Adapter @ %04x", ali1563_smba);402if ((error = i2c_add_adapter(&ali1563_adapter)))403goto exit_shutdown;404return 0;405406exit_shutdown:407ali1563_shutdown(dev);408exit:409dev_warn(&dev->dev, "ALi1563 SMBus probe failed (%d)\n", error);410return error;411}412413static void __devexit ali1563_remove(struct pci_dev * dev)414{415i2c_del_adapter(&ali1563_adapter);416ali1563_shutdown(dev);417}418419static const struct pci_device_id ali1563_id_table[] __devinitconst = {420{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) },421{},422};423424MODULE_DEVICE_TABLE (pci, ali1563_id_table);425426static struct pci_driver ali1563_pci_driver = {427.name = "ali1563_smbus",428.id_table = ali1563_id_table,429.probe = ali1563_probe,430.remove = __devexit_p(ali1563_remove),431};432433static int __init ali1563_init(void)434{435return pci_register_driver(&ali1563_pci_driver);436}437438module_init(ali1563_init);439440static void __exit ali1563_exit(void)441{442pci_unregister_driver(&ali1563_pci_driver);443}444445module_exit(ali1563_exit);446447MODULE_LICENSE("GPL");448449450