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