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-amd8111.c (11896B)


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