brintos

brintos / linux-shallow public Read only

0
0
Text · 12.0 KiB · fab662e Raw
443 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3    SMBus driver for nVidia nForce2 MCP4 5    Added nForce3 Pro 150  Thomas Leibold <thomas@plx.com>,6	Ported to 2.5 Patrick Dreker <patrick@dreker.de>,7    Copyright (c) 2003  Hans-Frieder Vogt <hfvogt@arcor.de>,8    Based on9    SMBus 2.0 driver for AMD-8111 IO-Hub10    Copyright (c) 2002 Vojtech Pavlik11 12*/13 14/*15    SUPPORTED DEVICES		PCI ID16    nForce2 MCP			006417    nForce2 Ultra 400 MCP	008418    nForce3 Pro150 MCP		00D419    nForce3 250Gb MCP		00E420    nForce4 MCP			005221    nForce4 MCP-04		003422    nForce MCP51		026423    nForce MCP55		036824    nForce MCP61		03EB25    nForce MCP65		044626    nForce MCP67		054227    nForce MCP73		07D828    nForce MCP78S		075229    nForce MCP79		0AA230 31    This driver supports the 2 SMBuses that are included in the MCP of the32    nForce2/3/4/5xx chipsets.33*/34 35/* Note: we assume there can only be one nForce2, with two SMBus interfaces */36 37#include <linux/module.h>38#include <linux/pci.h>39#include <linux/kernel.h>40#include <linux/stddef.h>41#include <linux/ioport.h>42#include <linux/i2c.h>43#include <linux/delay.h>44#include <linux/dmi.h>45#include <linux/acpi.h>46#include <linux/slab.h>47#include <linux/io.h>48 49MODULE_LICENSE("GPL");50MODULE_AUTHOR("Hans-Frieder Vogt <hfvogt@gmx.net>");51MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver");52 53 54struct nforce2_smbus {55	struct i2c_adapter adapter;56	int base;57	int size;58	int blockops;59	int can_abort;60};61 62 63/*64 * nVidia nForce2 SMBus control register definitions65 * (Newer incarnations use standard BARs 4 and 5 instead)66 */67#define NFORCE_PCI_SMB1	0x5068#define NFORCE_PCI_SMB2	0x5469 70 71/*72 * ACPI 2.0 chapter 13 SMBus 2.0 EC register model73 */74#define NVIDIA_SMB_PRTCL	(smbus->base + 0x00)	/* protocol, PEC */75#define NVIDIA_SMB_STS		(smbus->base + 0x01)	/* status */76#define NVIDIA_SMB_ADDR		(smbus->base + 0x02)	/* address */77#define NVIDIA_SMB_CMD		(smbus->base + 0x03)	/* command */78#define NVIDIA_SMB_DATA		(smbus->base + 0x04)	/* 32 data registers */79#define NVIDIA_SMB_BCNT		(smbus->base + 0x24)	/* number of data80							   bytes */81#define NVIDIA_SMB_STATUS_ABRT	(smbus->base + 0x3c)	/* register used to82							   check the status of83							   the abort command */84#define NVIDIA_SMB_CTRL		(smbus->base + 0x3e)	/* control register */85 86#define NVIDIA_SMB_STATUS_ABRT_STS	0x01		/* Bit to notify that87							   abort succeeded */88#define NVIDIA_SMB_CTRL_ABORT	0x2089#define NVIDIA_SMB_STS_DONE	0x8090#define NVIDIA_SMB_STS_ALRM	0x4091#define NVIDIA_SMB_STS_RES	0x2092#define NVIDIA_SMB_STS_STATUS	0x1f93 94#define NVIDIA_SMB_PRTCL_WRITE			0x0095#define NVIDIA_SMB_PRTCL_READ			0x0196#define NVIDIA_SMB_PRTCL_QUICK			0x0297#define NVIDIA_SMB_PRTCL_BYTE			0x0498#define NVIDIA_SMB_PRTCL_BYTE_DATA		0x0699#define NVIDIA_SMB_PRTCL_WORD_DATA		0x08100#define NVIDIA_SMB_PRTCL_BLOCK_DATA		0x0a101#define NVIDIA_SMB_PRTCL_PEC			0x80102 103/* Misc definitions */104#define MAX_TIMEOUT	100105 106/* We disable the second SMBus channel on these boards */107static const struct dmi_system_id nforce2_dmi_blacklist2[] = {108	{109		.ident = "DFI Lanparty NF4 Expert",110		.matches = {111			DMI_MATCH(DMI_BOARD_VENDOR, "DFI Corp,LTD"),112			DMI_MATCH(DMI_BOARD_NAME, "LP UT NF4 Expert"),113		},114	},115	{ }116};117 118static struct pci_driver nforce2_driver;119 120/* For multiplexing support, we need a global reference to the 1st121   SMBus channel */122#if IS_ENABLED(CONFIG_I2C_NFORCE2_S4985)123struct i2c_adapter *nforce2_smbus;124EXPORT_SYMBOL_GPL(nforce2_smbus);125 126static void nforce2_set_reference(struct i2c_adapter *adap)127{128	nforce2_smbus = adap;129}130#else131static inline void nforce2_set_reference(struct i2c_adapter *adap) { }132#endif133 134static void nforce2_abort(struct i2c_adapter *adap)135{136	struct nforce2_smbus *smbus = adap->algo_data;137	int timeout = 0;138	unsigned char temp;139 140	dev_dbg(&adap->dev, "Aborting current transaction\n");141 142	outb_p(NVIDIA_SMB_CTRL_ABORT, NVIDIA_SMB_CTRL);143	do {144		msleep(1);145		temp = inb_p(NVIDIA_SMB_STATUS_ABRT);146	} while (!(temp & NVIDIA_SMB_STATUS_ABRT_STS) &&147			(timeout++ < MAX_TIMEOUT));148	if (!(temp & NVIDIA_SMB_STATUS_ABRT_STS))149		dev_err(&adap->dev, "Can't reset the smbus\n");150	outb_p(NVIDIA_SMB_STATUS_ABRT_STS, NVIDIA_SMB_STATUS_ABRT);151}152 153static int nforce2_check_status(struct i2c_adapter *adap)154{155	struct nforce2_smbus *smbus = adap->algo_data;156	int timeout = 0;157	unsigned char temp;158 159	do {160		msleep(1);161		temp = inb_p(NVIDIA_SMB_STS);162	} while ((!temp) && (timeout++ < MAX_TIMEOUT));163 164	if (timeout > MAX_TIMEOUT) {165		dev_dbg(&adap->dev, "SMBus Timeout!\n");166		if (smbus->can_abort)167			nforce2_abort(adap);168		return -ETIMEDOUT;169	}170	if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {171		dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp);172		return -EIO;173	}174	return 0;175}176 177/* Return negative errno on error */178static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,179		unsigned short flags, char read_write,180		u8 command, int size, union i2c_smbus_data *data)181{182	struct nforce2_smbus *smbus = adap->algo_data;183	unsigned char protocol, pec;184	u8 len;185	int i, status;186 187	protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :188		NVIDIA_SMB_PRTCL_WRITE;189	pec = (flags & I2C_CLIENT_PEC) ? NVIDIA_SMB_PRTCL_PEC : 0;190 191	switch (size) {192	case I2C_SMBUS_QUICK:193		protocol |= NVIDIA_SMB_PRTCL_QUICK;194		read_write = I2C_SMBUS_WRITE;195		break;196 197	case I2C_SMBUS_BYTE:198		if (read_write == I2C_SMBUS_WRITE)199			outb_p(command, NVIDIA_SMB_CMD);200		protocol |= NVIDIA_SMB_PRTCL_BYTE;201		break;202 203	case I2C_SMBUS_BYTE_DATA:204		outb_p(command, NVIDIA_SMB_CMD);205		if (read_write == I2C_SMBUS_WRITE)206			outb_p(data->byte, NVIDIA_SMB_DATA);207		protocol |= NVIDIA_SMB_PRTCL_BYTE_DATA;208		break;209 210	case I2C_SMBUS_WORD_DATA:211		outb_p(command, NVIDIA_SMB_CMD);212		if (read_write == I2C_SMBUS_WRITE) {213			outb_p(data->word, NVIDIA_SMB_DATA);214			outb_p(data->word >> 8, NVIDIA_SMB_DATA + 1);215		}216		protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec;217		break;218 219	case I2C_SMBUS_BLOCK_DATA:220		outb_p(command, NVIDIA_SMB_CMD);221		if (read_write == I2C_SMBUS_WRITE) {222			len = data->block[0];223			if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) {224				dev_err(&adap->dev,225					"Transaction failed (requested block size: %d)\n",226					len);227				return -EINVAL;228			}229			outb_p(len, NVIDIA_SMB_BCNT);230			for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)231				outb_p(data->block[i + 1],232				       NVIDIA_SMB_DATA + i);233		}234		protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec;235		break;236 237	default:238		dev_err(&adap->dev, "Unsupported transaction %d\n", size);239		return -EOPNOTSUPP;240	}241 242	outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);243	outb_p(protocol, NVIDIA_SMB_PRTCL);244 245	status = nforce2_check_status(adap);246	if (status)247		return status;248 249	if (read_write == I2C_SMBUS_WRITE)250		return 0;251 252	switch (size) {253	case I2C_SMBUS_BYTE:254	case I2C_SMBUS_BYTE_DATA:255		data->byte = inb_p(NVIDIA_SMB_DATA);256		break;257 258	case I2C_SMBUS_WORD_DATA:259		data->word = inb_p(NVIDIA_SMB_DATA) |260			     (inb_p(NVIDIA_SMB_DATA + 1) << 8);261		break;262 263	case I2C_SMBUS_BLOCK_DATA:264		len = inb_p(NVIDIA_SMB_BCNT);265		if ((len <= 0) || (len > I2C_SMBUS_BLOCK_MAX)) {266			dev_err(&adap->dev,267				"Transaction failed (received block size: 0x%02x)\n",268				len);269			return -EPROTO;270		}271		for (i = 0; i < len; i++)272			data->block[i + 1] = inb_p(NVIDIA_SMB_DATA + i);273		data->block[0] = len;274		break;275	}276 277	return 0;278}279 280 281static u32 nforce2_func(struct i2c_adapter *adapter)282{283	/* other functionality might be possible, but is not tested */284	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |285	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |286	       I2C_FUNC_SMBUS_PEC |287	       (((struct nforce2_smbus *)adapter->algo_data)->blockops ?288		I2C_FUNC_SMBUS_BLOCK_DATA : 0);289}290 291static const struct i2c_algorithm smbus_algorithm = {292	.smbus_xfer	= nforce2_access,293	.functionality	= nforce2_func,294};295 296 297static const struct pci_device_id nforce2_ids[] = {298	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) },299	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) },300	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },301	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },302	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) },303	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },304	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) },305	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },306	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) },307	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },308	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS) },309	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS) },310	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS) },311	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS) },312	{ 0 }313};314 315MODULE_DEVICE_TABLE(pci, nforce2_ids);316 317 318static int nforce2_probe_smb(struct pci_dev *dev, int bar, int alt_reg,319			     struct nforce2_smbus *smbus, const char *name)320{321	int error;322 323	smbus->base = pci_resource_start(dev, bar);324	if (smbus->base) {325		smbus->size = pci_resource_len(dev, bar);326	} else {327		/* Older incarnations of the device used non-standard BARs */328		u16 iobase;329 330		error = pci_read_config_word(dev, alt_reg, &iobase);331		if (error != PCIBIOS_SUCCESSFUL) {332			dev_err(&dev->dev, "Error reading PCI config for %s\n",333				name);334			return -EIO;335		}336 337		smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;338		smbus->size = 64;339	}340 341	error = acpi_check_region(smbus->base, smbus->size,342				  nforce2_driver.name);343	if (error)344		return error;345 346	if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {347		dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",348			smbus->base, smbus->base+smbus->size-1, name);349		return -EBUSY;350	}351	smbus->adapter.owner = THIS_MODULE;352	smbus->adapter.class = I2C_CLASS_HWMON;353	smbus->adapter.algo = &smbus_algorithm;354	smbus->adapter.algo_data = smbus;355	smbus->adapter.dev.parent = &dev->dev;356	snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),357		"SMBus nForce2 adapter at %04x", smbus->base);358 359	error = i2c_add_adapter(&smbus->adapter);360	if (error) {361		release_region(smbus->base, smbus->size);362		return error;363	}364	dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n",365		smbus->base);366	return 0;367}368 369 370static int nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id)371{372	struct nforce2_smbus *smbuses;373	int res1, res2;374 375	/* we support 2 SMBus adapters */376	smbuses = kcalloc(2, sizeof(struct nforce2_smbus), GFP_KERNEL);377	if (!smbuses)378		return -ENOMEM;379	pci_set_drvdata(dev, smbuses);380 381	switch (dev->device) {382	case PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS:383	case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS:384	case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS:385		smbuses[0].blockops = 1;386		smbuses[1].blockops = 1;387		smbuses[0].can_abort = 1;388		smbuses[1].can_abort = 1;389	}390 391	/* SMBus adapter 1 */392	res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1");393	if (res1 < 0)394		smbuses[0].base = 0;	/* to have a check value */395 396	/* SMBus adapter 2 */397	if (dmi_check_system(nforce2_dmi_blacklist2)) {398		dev_err(&dev->dev, "Disabling SMB2 for safety reasons.\n");399		res2 = -EPERM;400		smbuses[1].base = 0;401	} else {402		res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1],403					 "SMB2");404		if (res2 < 0)405			smbuses[1].base = 0;	/* to have a check value */406	}407 408	if ((res1 < 0) && (res2 < 0)) {409		/* we did not find even one of the SMBuses, so we give up */410		kfree(smbuses);411		return -ENODEV;412	}413 414	nforce2_set_reference(&smbuses[0].adapter);415	return 0;416}417 418 419static void nforce2_remove(struct pci_dev *dev)420{421	struct nforce2_smbus *smbuses = pci_get_drvdata(dev);422 423	nforce2_set_reference(NULL);424	if (smbuses[0].base) {425		i2c_del_adapter(&smbuses[0].adapter);426		release_region(smbuses[0].base, smbuses[0].size);427	}428	if (smbuses[1].base) {429		i2c_del_adapter(&smbuses[1].adapter);430		release_region(smbuses[1].base, smbuses[1].size);431	}432	kfree(smbuses);433}434 435static struct pci_driver nforce2_driver = {436	.name		= "nForce2_smbus",437	.id_table	= nforce2_ids,438	.probe		= nforce2_probe,439	.remove		= nforce2_remove,440};441 442module_pci_driver(nforce2_driver);443