cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

i2c-ali1563.c (11234B)


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