Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3    Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
  4
  5    Shamelessly ripped from i2c-piix4.c:
  6
  7    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
  8    Philip Edelbrock <phil@netroedge.com>
  9
 10*/
 11
 12/*
 13    2002-04-08: Added nForce support. (Csaba Halasz)
 14    2002-10-03: Fixed nForce PnP I/O port. (Michael Steil)
 15    2002-12-28: Rewritten into something that resembles a Linux driver (hch)
 16    2003-11-29: Added back AMD8111 removed by the previous rewrite.
 17                (Philip Pokorny)
 18*/
 19
 20/*
 21   Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce
 22   Note: we assume there can only be one device, with one SMBus interface.
 23*/
 24
 25#include <linux/module.h>
 26#include <linux/pci.h>
 27#include <linux/kernel.h>
 28#include <linux/delay.h>
 29#include <linux/stddef.h>
 30#include <linux/ioport.h>
 31#include <linux/i2c.h>
 32#include <linux/acpi.h>
 33#include <linux/io.h>
 34
 35/* AMD756 SMBus address offsets */
 36#define SMB_ADDR_OFFSET		0xE0
 37#define SMB_IOSIZE		16
 38#define SMB_GLOBAL_STATUS	(0x0 + amd756_ioport)
 39#define SMB_GLOBAL_ENABLE	(0x2 + amd756_ioport)
 40#define SMB_HOST_ADDRESS	(0x4 + amd756_ioport)
 41#define SMB_HOST_DATA		(0x6 + amd756_ioport)
 42#define SMB_HOST_COMMAND	(0x8 + amd756_ioport)
 43#define SMB_HOST_BLOCK_DATA	(0x9 + amd756_ioport)
 44#define SMB_HAS_DATA		(0xA + amd756_ioport)
 45#define SMB_HAS_DEVICE_ADDRESS	(0xC + amd756_ioport)
 46#define SMB_HAS_HOST_ADDRESS	(0xE + amd756_ioport)
 47#define SMB_SNOOP_ADDRESS	(0xF + amd756_ioport)
 48
 49/* PCI Address Constants */
 50
 51/* address of I/O space */
 52#define SMBBA		0x058		/* mh */
 53#define SMBBANFORCE	0x014
 54
 55/* general configuration */
 56#define SMBGCFG		0x041		/* mh */
 57
 58/* silicon revision code */
 59#define SMBREV		0x008
 60
 61/* Other settings */
 62#define MAX_TIMEOUT	500
 63
 64/* AMD756 constants */
 65#define AMD756_QUICK		0x00
 66#define AMD756_BYTE		0x01
 67#define AMD756_BYTE_DATA	0x02
 68#define AMD756_WORD_DATA	0x03
 69#define AMD756_PROCESS_CALL	0x04
 70#define AMD756_BLOCK_DATA	0x05
 71
 72static struct pci_driver amd756_driver;
 73static unsigned short amd756_ioport;
 74
 75/* 
 76  SMBUS event = I/O 28-29 bit 11
 77     see E0 for the status bits and enabled in E2
 78     
 79*/
 80#define GS_ABRT_STS	(1 << 0)
 81#define GS_COL_STS	(1 << 1)
 82#define GS_PRERR_STS	(1 << 2)
 83#define GS_HST_STS	(1 << 3)
 84#define GS_HCYC_STS	(1 << 4)
 85#define GS_TO_STS	(1 << 5)
 86#define GS_SMB_STS	(1 << 11)
 87
 88#define GS_CLEAR_STS	(GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \
 89			 GS_HCYC_STS | GS_TO_STS )
 90
 91#define GE_CYC_TYPE_MASK	(7)
 92#define GE_HOST_STC		(1 << 3)
 93#define GE_ABORT		(1 << 5)
 94
 95
 96static int amd756_transaction(struct i2c_adapter *adap)
 97{
 98	int temp;
 99	int result = 0;
100	int timeout = 0;
101
102	dev_dbg(&adap->dev, "Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, "
103		"DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS),
104		inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS),
105		inb_p(SMB_HOST_DATA));
106
107	/* Make sure the SMBus host is ready to start transmitting */
108	if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) {
109		dev_dbg(&adap->dev, "SMBus busy (%04x). Waiting...\n", temp);
110		do {
111			msleep(1);
112			temp = inw_p(SMB_GLOBAL_STATUS);
113		} while ((temp & (GS_HST_STS | GS_SMB_STS)) &&
114		         (timeout++ < MAX_TIMEOUT));
115		/* If the SMBus is still busy, we give up */
116		if (timeout > MAX_TIMEOUT) {
117			dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp);
118			goto abort;
119		}
120		timeout = 0;
121	}
122
123	/* start the transaction by setting the start bit */
124	outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE);
125
126	/* We will always wait for a fraction of a second! */
127	do {
128		msleep(1);
129		temp = inw_p(SMB_GLOBAL_STATUS);
130	} while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
131
132	/* If the SMBus is still busy, we give up */
133	if (timeout > MAX_TIMEOUT) {
134		dev_dbg(&adap->dev, "Completion timeout!\n");
135		goto abort;
136	}
137
138	if (temp & GS_PRERR_STS) {
139		result = -ENXIO;
140		dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n");
141	}
142
143	if (temp & GS_COL_STS) {
144		result = -EIO;
145		dev_warn(&adap->dev, "SMBus collision!\n");
146	}
147
148	if (temp & GS_TO_STS) {
149		result = -ETIMEDOUT;
150		dev_dbg(&adap->dev, "SMBus protocol timeout!\n");
151	}
152
153	if (temp & GS_HCYC_STS)
154		dev_dbg(&adap->dev, "SMBus protocol success!\n");
155
156	outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
157
158#ifdef DEBUG
159	if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
160		dev_dbg(&adap->dev,
161			"Failed reset at end of transaction (%04x)\n", temp);
162	}
163#endif
164
165	dev_dbg(&adap->dev,
166		"Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
167		inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
168		inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
169
170	return result;
171
172 abort:
173	dev_warn(&adap->dev, "Sending abort\n");
174	outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
175	msleep(100);
176	outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
177	return -EIO;
178}
179
180/* Return negative errno on error. */
181static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
182		  unsigned short flags, char read_write,
183		  u8 command, int size, union i2c_smbus_data * data)
184{
185	int i, len;
186	int status;
187
188	switch (size) {
189	case I2C_SMBUS_QUICK:
190		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
191		       SMB_HOST_ADDRESS);
192		size = AMD756_QUICK;
193		break;
194	case I2C_SMBUS_BYTE:
195		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
196		       SMB_HOST_ADDRESS);
197		if (read_write == I2C_SMBUS_WRITE)
198			outb_p(command, SMB_HOST_DATA);
199		size = AMD756_BYTE;
200		break;
201	case I2C_SMBUS_BYTE_DATA:
202		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
203		       SMB_HOST_ADDRESS);
204		outb_p(command, SMB_HOST_COMMAND);
205		if (read_write == I2C_SMBUS_WRITE)
206			outw_p(data->byte, SMB_HOST_DATA);
207		size = AMD756_BYTE_DATA;
208		break;
209	case I2C_SMBUS_WORD_DATA:
210		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
211		       SMB_HOST_ADDRESS);
212		outb_p(command, SMB_HOST_COMMAND);
213		if (read_write == I2C_SMBUS_WRITE)
214			outw_p(data->word, SMB_HOST_DATA);	/* TODO: endian???? */
215		size = AMD756_WORD_DATA;
216		break;
217	case I2C_SMBUS_BLOCK_DATA:
218		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
219		       SMB_HOST_ADDRESS);
220		outb_p(command, SMB_HOST_COMMAND);
221		if (read_write == I2C_SMBUS_WRITE) {
222			len = data->block[0];
223			if (len < 0)
224				len = 0;
225			if (len > 32)
226				len = 32;
227			outw_p(len, SMB_HOST_DATA);
228			/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
229			for (i = 1; i <= len; i++)
230				outb_p(data->block[i],
231				       SMB_HOST_BLOCK_DATA);
232		}
233		size = AMD756_BLOCK_DATA;
234		break;
235	default:
236		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
237		return -EOPNOTSUPP;
238	}
239
240	/* How about enabling interrupts... */
241	outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
242
243	status = amd756_transaction(adap);
244	if (status)
245		return status;
246
247	if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
248		return 0;
249
250
251	switch (size) {
252	case AMD756_BYTE:
253		data->byte = inw_p(SMB_HOST_DATA);
254		break;
255	case AMD756_BYTE_DATA:
256		data->byte = inw_p(SMB_HOST_DATA);
257		break;
258	case AMD756_WORD_DATA:
259		data->word = inw_p(SMB_HOST_DATA);	/* TODO: endian???? */
260		break;
261	case AMD756_BLOCK_DATA:
262		data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f;
263		if(data->block[0] > 32)
264			data->block[0] = 32;
265		/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
266		for (i = 1; i <= data->block[0]; i++)
267			data->block[i] = inb_p(SMB_HOST_BLOCK_DATA);
268		break;
269	}
270
271	return 0;
272}
273
274static u32 amd756_func(struct i2c_adapter *adapter)
275{
276	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
277	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
278	    I2C_FUNC_SMBUS_BLOCK_DATA;
279}
280
281static const struct i2c_algorithm smbus_algorithm = {
282	.smbus_xfer	= amd756_access,
283	.functionality	= amd756_func,
284};
285
286struct i2c_adapter amd756_smbus = {
287	.owner		= THIS_MODULE,
288	.class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
289	.algo		= &smbus_algorithm,
290};
291
292enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
293static const char* chipname[] = {
294	"AMD756", "AMD766", "AMD768",
295	"nVidia nForce", "AMD8111",
296};
297
298static const struct pci_device_id amd756_ids[] = {
299	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B),
300	  .driver_data = AMD756 },
301	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413),
302	  .driver_data = AMD766 },
303	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443),
304	  .driver_data = AMD768 },
305	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS),
306	  .driver_data = AMD8111 },
307	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS),
308	  .driver_data = NFORCE },
309	{ 0, }
310};
311
312MODULE_DEVICE_TABLE (pci, amd756_ids);
313
314static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
315{
316	int nforce = (id->driver_data == NFORCE);
317	int error;
318	u8 temp;
319	
320	if (amd756_ioport) {
321		dev_err(&pdev->dev, "Only one device supported "
322		       "(you have a strange motherboard, btw)\n");
323		return -ENODEV;
324	}
325
326	if (nforce) {
327		if (PCI_FUNC(pdev->devfn) != 1)
328			return -ENODEV;
329
330		pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport);
331		amd756_ioport &= 0xfffc;
332	} else { /* amd */
333		if (PCI_FUNC(pdev->devfn) != 3)
334			return -ENODEV;
335
336		pci_read_config_byte(pdev, SMBGCFG, &temp);
337		if ((temp & 128) == 0) {
338			dev_err(&pdev->dev,
339				"Error: SMBus controller I/O not enabled!\n");
340			return -ENODEV;
341		}
342
343		/* Determine the address of the SMBus areas */
344		/* Technically it is a dword but... */
345		pci_read_config_word(pdev, SMBBA, &amd756_ioport);
346		amd756_ioport &= 0xff00;
347		amd756_ioport += SMB_ADDR_OFFSET;
348	}
349
350	error = acpi_check_region(amd756_ioport, SMB_IOSIZE,
351				  amd756_driver.name);
352	if (error)
353		return -ENODEV;
354
355	if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
356		dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
357			amd756_ioport);
358		return -ENODEV;
359	}
360
361	pci_read_config_byte(pdev, SMBREV, &temp);
362	dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
363	dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport);
364
365	/* set up the sysfs linkage to our parent device */
366	amd756_smbus.dev.parent = &pdev->dev;
367
368	snprintf(amd756_smbus.name, sizeof(amd756_smbus.name),
369		 "SMBus %s adapter at %04x", chipname[id->driver_data],
370		 amd756_ioport);
371
372	error = i2c_add_adapter(&amd756_smbus);
373	if (error)
374		goto out_err;
375
376	return 0;
377
378 out_err:
379	release_region(amd756_ioport, SMB_IOSIZE);
380	return error;
381}
382
383static void amd756_remove(struct pci_dev *dev)
384{
385	i2c_del_adapter(&amd756_smbus);
386	release_region(amd756_ioport, SMB_IOSIZE);
387}
388
389static struct pci_driver amd756_driver = {
390	.name		= "amd756_smbus",
391	.id_table	= amd756_ids,
392	.probe		= amd756_probe,
393	.remove		= amd756_remove,
394};
395
396module_pci_driver(amd756_driver);
397
398MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>");
399MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver");
400MODULE_LICENSE("GPL");
401
402EXPORT_SYMBOL(amd756_smbus);
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3    Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
  4
  5    Shamelessly ripped from i2c-piix4.c:
  6
  7    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
  8    Philip Edelbrock <phil@netroedge.com>
  9
 10*/
 11
 12/*
 13    2002-04-08: Added nForce support. (Csaba Halasz)
 14    2002-10-03: Fixed nForce PnP I/O port. (Michael Steil)
 15    2002-12-28: Rewritten into something that resembles a Linux driver (hch)
 16    2003-11-29: Added back AMD8111 removed by the previous rewrite.
 17                (Philip Pokorny)
 18*/
 19
 20/*
 21   Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce
 22   Note: we assume there can only be one device, with one SMBus interface.
 23*/
 24
 25#include <linux/module.h>
 26#include <linux/pci.h>
 27#include <linux/kernel.h>
 28#include <linux/delay.h>
 29#include <linux/stddef.h>
 30#include <linux/ioport.h>
 31#include <linux/i2c.h>
 32#include <linux/acpi.h>
 33#include <linux/io.h>
 34
 35/* AMD756 SMBus address offsets */
 36#define SMB_ADDR_OFFSET		0xE0
 37#define SMB_IOSIZE		16
 38#define SMB_GLOBAL_STATUS	(0x0 + amd756_ioport)
 39#define SMB_GLOBAL_ENABLE	(0x2 + amd756_ioport)
 40#define SMB_HOST_ADDRESS	(0x4 + amd756_ioport)
 41#define SMB_HOST_DATA		(0x6 + amd756_ioport)
 42#define SMB_HOST_COMMAND	(0x8 + amd756_ioport)
 43#define SMB_HOST_BLOCK_DATA	(0x9 + amd756_ioport)
 44#define SMB_HAS_DATA		(0xA + amd756_ioport)
 45#define SMB_HAS_DEVICE_ADDRESS	(0xC + amd756_ioport)
 46#define SMB_HAS_HOST_ADDRESS	(0xE + amd756_ioport)
 47#define SMB_SNOOP_ADDRESS	(0xF + amd756_ioport)
 48
 49/* PCI Address Constants */
 50
 51/* address of I/O space */
 52#define SMBBA		0x058		/* mh */
 53#define SMBBANFORCE	0x014
 54
 55/* general configuration */
 56#define SMBGCFG		0x041		/* mh */
 57
 58/* silicon revision code */
 59#define SMBREV		0x008
 60
 61/* Other settings */
 62#define MAX_TIMEOUT	500
 63
 64/* AMD756 constants */
 65#define AMD756_QUICK		0x00
 66#define AMD756_BYTE		0x01
 67#define AMD756_BYTE_DATA	0x02
 68#define AMD756_WORD_DATA	0x03
 69#define AMD756_PROCESS_CALL	0x04
 70#define AMD756_BLOCK_DATA	0x05
 71
 72static struct pci_driver amd756_driver;
 73static unsigned short amd756_ioport;
 74
 75/* 
 76  SMBUS event = I/O 28-29 bit 11
 77     see E0 for the status bits and enabled in E2
 78     
 79*/
 80#define GS_ABRT_STS	(1 << 0)
 81#define GS_COL_STS	(1 << 1)
 82#define GS_PRERR_STS	(1 << 2)
 83#define GS_HST_STS	(1 << 3)
 84#define GS_HCYC_STS	(1 << 4)
 85#define GS_TO_STS	(1 << 5)
 86#define GS_SMB_STS	(1 << 11)
 87
 88#define GS_CLEAR_STS	(GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \
 89			 GS_HCYC_STS | GS_TO_STS )
 90
 91#define GE_CYC_TYPE_MASK	(7)
 92#define GE_HOST_STC		(1 << 3)
 93#define GE_ABORT		(1 << 5)
 94
 95
 96static int amd756_transaction(struct i2c_adapter *adap)
 97{
 98	int temp;
 99	int result = 0;
100	int timeout = 0;
101
102	dev_dbg(&adap->dev, "Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, "
103		"DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS),
104		inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS),
105		inb_p(SMB_HOST_DATA));
106
107	/* Make sure the SMBus host is ready to start transmitting */
108	if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) {
109		dev_dbg(&adap->dev, "SMBus busy (%04x). Waiting...\n", temp);
110		do {
111			msleep(1);
112			temp = inw_p(SMB_GLOBAL_STATUS);
113		} while ((temp & (GS_HST_STS | GS_SMB_STS)) &&
114		         (timeout++ < MAX_TIMEOUT));
115		/* If the SMBus is still busy, we give up */
116		if (timeout > MAX_TIMEOUT) {
117			dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp);
118			goto abort;
119		}
120		timeout = 0;
121	}
122
123	/* start the transaction by setting the start bit */
124	outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE);
125
126	/* We will always wait for a fraction of a second! */
127	do {
128		msleep(1);
129		temp = inw_p(SMB_GLOBAL_STATUS);
130	} while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
131
132	/* If the SMBus is still busy, we give up */
133	if (timeout > MAX_TIMEOUT) {
134		dev_dbg(&adap->dev, "Completion timeout!\n");
135		goto abort;
136	}
137
138	if (temp & GS_PRERR_STS) {
139		result = -ENXIO;
140		dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n");
141	}
142
143	if (temp & GS_COL_STS) {
144		result = -EIO;
145		dev_warn(&adap->dev, "SMBus collision!\n");
146	}
147
148	if (temp & GS_TO_STS) {
149		result = -ETIMEDOUT;
150		dev_dbg(&adap->dev, "SMBus protocol timeout!\n");
151	}
152
153	if (temp & GS_HCYC_STS)
154		dev_dbg(&adap->dev, "SMBus protocol success!\n");
155
156	outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
157
158#ifdef DEBUG
159	if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) {
160		dev_dbg(&adap->dev,
161			"Failed reset at end of transaction (%04x)\n", temp);
162	}
163#endif
164
165	dev_dbg(&adap->dev,
166		"Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n",
167		inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE),
168		inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA));
169
170	return result;
171
172 abort:
173	dev_warn(&adap->dev, "Sending abort\n");
174	outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
175	msleep(100);
176	outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
177	return -EIO;
178}
179
180/* Return negative errno on error. */
181static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
182		  unsigned short flags, char read_write,
183		  u8 command, int size, union i2c_smbus_data * data)
184{
185	int i, len;
186	int status;
187
188	switch (size) {
189	case I2C_SMBUS_QUICK:
190		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
191		       SMB_HOST_ADDRESS);
192		size = AMD756_QUICK;
193		break;
194	case I2C_SMBUS_BYTE:
195		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
196		       SMB_HOST_ADDRESS);
197		if (read_write == I2C_SMBUS_WRITE)
198			outb_p(command, SMB_HOST_DATA);
199		size = AMD756_BYTE;
200		break;
201	case I2C_SMBUS_BYTE_DATA:
202		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
203		       SMB_HOST_ADDRESS);
204		outb_p(command, SMB_HOST_COMMAND);
205		if (read_write == I2C_SMBUS_WRITE)
206			outw_p(data->byte, SMB_HOST_DATA);
207		size = AMD756_BYTE_DATA;
208		break;
209	case I2C_SMBUS_WORD_DATA:
210		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
211		       SMB_HOST_ADDRESS);
212		outb_p(command, SMB_HOST_COMMAND);
213		if (read_write == I2C_SMBUS_WRITE)
214			outw_p(data->word, SMB_HOST_DATA);	/* TODO: endian???? */
215		size = AMD756_WORD_DATA;
216		break;
217	case I2C_SMBUS_BLOCK_DATA:
218		outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
219		       SMB_HOST_ADDRESS);
220		outb_p(command, SMB_HOST_COMMAND);
221		if (read_write == I2C_SMBUS_WRITE) {
222			len = data->block[0];
223			if (len < 0)
224				len = 0;
225			if (len > 32)
226				len = 32;
227			outw_p(len, SMB_HOST_DATA);
228			/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
229			for (i = 1; i <= len; i++)
230				outb_p(data->block[i],
231				       SMB_HOST_BLOCK_DATA);
232		}
233		size = AMD756_BLOCK_DATA;
234		break;
235	default:
236		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
237		return -EOPNOTSUPP;
238	}
239
240	/* How about enabling interrupts... */
241	outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
242
243	status = amd756_transaction(adap);
244	if (status)
245		return status;
246
247	if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
248		return 0;
249
250
251	switch (size) {
252	case AMD756_BYTE:
253		data->byte = inw_p(SMB_HOST_DATA);
254		break;
255	case AMD756_BYTE_DATA:
256		data->byte = inw_p(SMB_HOST_DATA);
257		break;
258	case AMD756_WORD_DATA:
259		data->word = inw_p(SMB_HOST_DATA);	/* TODO: endian???? */
260		break;
261	case AMD756_BLOCK_DATA:
262		data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f;
263		if(data->block[0] > 32)
264			data->block[0] = 32;
265		/* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */
266		for (i = 1; i <= data->block[0]; i++)
267			data->block[i] = inb_p(SMB_HOST_BLOCK_DATA);
268		break;
269	}
270
271	return 0;
272}
273
274static u32 amd756_func(struct i2c_adapter *adapter)
275{
276	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
277	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
278	    I2C_FUNC_SMBUS_BLOCK_DATA;
279}
280
281static const struct i2c_algorithm smbus_algorithm = {
282	.smbus_xfer	= amd756_access,
283	.functionality	= amd756_func,
284};
285
286struct i2c_adapter amd756_smbus = {
287	.owner		= THIS_MODULE,
288	.class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
289	.algo		= &smbus_algorithm,
290};
291
292enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 };
293static const char* chipname[] = {
294	"AMD756", "AMD766", "AMD768",
295	"nVidia nForce", "AMD8111",
296};
297
298static const struct pci_device_id amd756_ids[] = {
299	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B),
300	  .driver_data = AMD756 },
301	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413),
302	  .driver_data = AMD766 },
303	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443),
304	  .driver_data = AMD768 },
305	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS),
306	  .driver_data = AMD8111 },
307	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS),
308	  .driver_data = NFORCE },
309	{ 0, }
310};
311
312MODULE_DEVICE_TABLE (pci, amd756_ids);
313
314static int amd756_probe(struct pci_dev *pdev, const struct pci_device_id *id)
315{
316	int nforce = (id->driver_data == NFORCE);
317	int error;
318	u8 temp;
319	
320	if (amd756_ioport) {
321		dev_err(&pdev->dev, "Only one device supported "
322		       "(you have a strange motherboard, btw)\n");
323		return -ENODEV;
324	}
325
326	if (nforce) {
327		if (PCI_FUNC(pdev->devfn) != 1)
328			return -ENODEV;
329
330		pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport);
331		amd756_ioport &= 0xfffc;
332	} else { /* amd */
333		if (PCI_FUNC(pdev->devfn) != 3)
334			return -ENODEV;
335
336		pci_read_config_byte(pdev, SMBGCFG, &temp);
337		if ((temp & 128) == 0) {
338			dev_err(&pdev->dev,
339				"Error: SMBus controller I/O not enabled!\n");
340			return -ENODEV;
341		}
342
343		/* Determine the address of the SMBus areas */
344		/* Technically it is a dword but... */
345		pci_read_config_word(pdev, SMBBA, &amd756_ioport);
346		amd756_ioport &= 0xff00;
347		amd756_ioport += SMB_ADDR_OFFSET;
348	}
349
350	error = acpi_check_region(amd756_ioport, SMB_IOSIZE,
351				  amd756_driver.name);
352	if (error)
353		return -ENODEV;
354
355	if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
356		dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
357			amd756_ioport);
358		return -ENODEV;
359	}
360
361	pci_read_config_byte(pdev, SMBREV, &temp);
362	dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp);
363	dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport);
364
365	/* set up the sysfs linkage to our parent device */
366	amd756_smbus.dev.parent = &pdev->dev;
367
368	snprintf(amd756_smbus.name, sizeof(amd756_smbus.name),
369		 "SMBus %s adapter at %04x", chipname[id->driver_data],
370		 amd756_ioport);
371
372	error = i2c_add_adapter(&amd756_smbus);
373	if (error)
374		goto out_err;
375
376	return 0;
377
378 out_err:
379	release_region(amd756_ioport, SMB_IOSIZE);
380	return error;
381}
382
383static void amd756_remove(struct pci_dev *dev)
384{
385	i2c_del_adapter(&amd756_smbus);
386	release_region(amd756_ioport, SMB_IOSIZE);
387}
388
389static struct pci_driver amd756_driver = {
390	.name		= "amd756_smbus",
391	.id_table	= amd756_ids,
392	.probe		= amd756_probe,
393	.remove		= amd756_remove,
394};
395
396module_pci_driver(amd756_driver);
397
398MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>");
399MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver");
400MODULE_LICENSE("GPL");
401
402EXPORT_SYMBOL(amd756_smbus);