amd8111 support, patch from

+* Vojtech Pavlik <vojtech@suse.cz>


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1616 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
Mark D. Studebaker committed 2002-11-17 19:44:46 +00:00
1 parent d999488cd1
commit 3929e57a5b
11 files changed
+478 -9

No files matched your search

+7 -3
View File
@@ -17,7 +17,7 @@ ask CVS about it:
-----------------------------------------------------------------------------
2.6.6 (20021???)
2.6.6 (200211??)
NOTE: Requires i2c-2.6.6 or newer.
File doc/busses/i2c-ali1535: Add license, miscellaneous changes
File doc/busses/i2c-ali15x3: Add license, miscellaneous changes
@@ -37,7 +37,10 @@ ask CVS about it:
kernel 2.5.43
Module gl518sm: Iterate allowed only for rev 0x00
Module i2c-amd756: Configure base address for nForce support;
check for uninitialized base address
check for uninitialized base address;
add support for amd8111 (SMBus 1.0)
Module i2c-amd8111: New (SMBus 2.0)
Module i2c-ipmb: New
Module i2c-ipmi: New
Module i2c-sis630: Add support for SiS730
Module i2c-sis645: Improve support for SiS645/961;
@@ -58,7 +61,8 @@ ask CVS about it:
Program sensors: Add support for MC1066, Rambus Rimms;
fix w83781d temp3 alarm; fix gl518sm rev 0x00 recognition;
initial support for Sony Vaio eeprom
Program sensors-detect: Add support for MC1066, smart battery, 8235, IPMI;
Program sensors-detect: Add support for MC1066, smart battery, 8235,
IPMI, AMD8111;
add ACPI method for IBM system detection;
work with old Perl versions again;
initial support for Sony Vaio eeprom
+3
View File
@@ -80,4 +80,7 @@ problems.
* Jean Delvare <khali@linux-fr.org>
Author of the decode-vaio.pl Vaio EEPROM decoder.
Perl scripts maintainer, tester, dmidecode maintainer, bug fixer.
* Vojtech Pavlik <vojtech@suse.cz>
Author of the i2c-amd8111 bus driver.
Added support for amd8111 SMBus 1.0 controller to i2c-amd756.
+3 -2
View File
@@ -40,7 +40,8 @@ See the lm_sensors download page for guidance:
At least the following I2C/SMBus adapters are supported:
Acer Labs M1533, M1535, and M1543C
AMD 756, 766, and 768
AMD 756, 766, 768 and 8111
AMD 8111 SMBus 2.0
Apple Hydra (used on some PPC machines)
DEC 21272/21274 (Tsunami/Typhoon - on Alpha boards)
Intel I801 ICH/ICH0/ICH2/ICH3 (used in Intel 810, 810E, 815E, 820, 840 chipsets)
@@ -53,7 +54,7 @@ At least the following I2C/SMBus adapters are supported:
SMSC Victory66
3Dfx Voodoo 3 and Banshee
VIA Technologies VT82C586B, VT82C596A/B, VT82C686A/B, VT8231,
VT8233, and VT8233A.
VT8233, VT8233A, and VT8235.
At least the following hardware sensor chips are supported:
+7 -1
View File
@@ -6,6 +6,7 @@ Supported adapters:
* AMD 756
* AMD 766
* AMD 768
* AMD 8111
Datasheets: Publicly available on AMD website
* nVidia nForce
@@ -21,4 +22,9 @@ Module Parameters
Description
-----------
This driver supports the AMD 756, 766, and 768 Peripheral Bus Controllers.
This driver supports the AMD 756, 766, 768 and 8111 Peripheral Bus Controllers, and
the nVidia nForce.
Note that for the 8111, there are two SMBus adapters. The SMBus 1.0 adapter is
supported by this driver, and the SMBus 2.0 adapter is supported
by the i2c-amd8111 driver.
+44
View File
@@ -0,0 +1,44 @@
Kernel driver `i2c-adm8111.o'
Status: Untested.
Supported adapters:
* AMD-8111 SMBus 2.0 PCI interface
* Possibly any other interface that implements the ACPI 2.0 EC interface
Datasheets: Publicly available at AMD and ACPI websites
Author: Vojtech Pavlik <vojtech@suse.cz>
Module Parameters
-----------------
None.
Description
-----------
If you see something like this:
00:07.2 SMBus: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0 (rev 02)
Subsystem: Advanced Micro Devices [AMD] AMD-8111 SMBus 2.0
Flags: medium devsel, IRQ 19
I/O ports at d400 [size=32]
in your 'lspci -v', then this driver is for your chipset.
Process Call Support
--------------------
The chip supports it, but it's not implemented in the driver at the moment.
SMBus 2.0 Support
-----------------
The chip supports SMBus 2.0, however the only extension the driver
supports is PEC. Slave mode or host notification are not implemented.
Note that for the 8111, there are two SMBus adapters. The SMBus 2.0 adapter is
supported by this driver, and the SMBus 1.0 adapter is supported
by the i2c-amd756 driver.
+1 -1
View File
@@ -69,7 +69,7 @@ applied to this code.
Thank Yous
-----------
Mark D. Studebaker <mds@paradyne.com>
Mark D. Studebaker <mdsxyz123@yahoo.com>
- design hints and bug fixes
Alexander Maylsh <amalysh@web.de>
- ditto, plus an important datasheet... almost the one I really wanted
+4
View File
@@ -26,6 +26,7 @@ KERNELBUSSESDIR := $(MODULE_DIR)
# These targets are NOT included in 'mkpatch' ...
KERNELBUSSESTARGETS :=
ifeq ($(shell if grep -q '^CONFIG_IPMI_HANDLER=' $(LINUX)/.config; then echo 1; fi),1)
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-ipmb.o
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-ipmi.o
endif
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-sis630.o
@@ -41,6 +42,9 @@ endif
ifneq ($(shell if grep -q '^CONFIG_I2C_AMD756=y' $(LINUX)/.config; then echo 1; fi),1)
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-amd756.o
endif
ifneq ($(shell if grep -q '^CONFIG_I2C_AMD8111=y' $(LINUX)/.config; then echo 1; fi),1)
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-amd8111.o
endif
ifneq ($(shell if grep -q '^CONFIG_I2C_HYDRA=y' $(LINUX)/.config; then echo 1; fi),1)
KERNELBUSSESTARGETS += $(MODULE_DIR)/i2c-hydra.o
endif
+9 -2
View File
@@ -52,6 +52,12 @@
#ifndef PCI_DEVICE_ID_AMD_766
#define PCI_DEVICE_ID_AMD_766 0x7413
#endif
#ifndef PCI_DEVICE_ID_AMD_768_SMBUS
#define PCI_DEVICE_ID_AMD_768_SMBUS 0x7443
#endif
#ifndef PCI_DEVICE_ID_AMD_8111_SMBUS
#define PCI_DEVICE_ID_AMD_8111_SMBUS 0x746B
#endif
#ifndef PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS
#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS 0x01B4
#endif
@@ -67,8 +73,9 @@ struct sd {
static struct sd supported[] = {
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_756, 3, "AMD756", 1},
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_766, 3, "AMD766", 1},
{PCI_VENDOR_ID_AMD, 0x7443, 3, "AMD768", 1},
{PCI_VENDOR_ID_NVIDIA, 0x01B4, 1, "nVidia nForce", 0},
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_768_SMBUS, 3, "AMD768", 1},
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS, 3, "AMD8111", 1},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS, 1, "nVidia nForce", 0},
{0, 0, 0}
};
+383
View File
@@ -0,0 +1,383 @@
/*
* SMBus 2.0 driver for AMD-8111 IO-Hub.
*
* Copyright (c) 2002 Vojtech Pavlik
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation version 2.
*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/stddef.h>
#include <linux/sched.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include "version.h"
MODULE_LICENSE("GPL");
MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>");
MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver");
struct amd_smbus {
struct pci_dev *dev;
struct i2c_adapter adapter;
int base;
int size;
};
/*
* AMD PCI control registers definitions.
*/
#define AMD_PCI_MISC 0x48
#define AMD_PCI_MISC_SCI 0x04 /* deliver SCI */
#define AMD_PCI_MISC_INT 0x02 /* deliver PCI IRQ */
#define AMD_PCI_MISC_SPEEDUP 0x01 /* 16x clock speedup */
/*
* ACPI 2.0 chapter 13 PCI interface definitions.
*/
#define AMD_EC_DATA 0x00 /* data register */
#define AMD_EC_SC 0x04 /* status of controller */
#define AMD_EC_CMD 0x04 /* command register */
#define AMD_EC_ICR 0x08 /* interrupt control register */
#define AMD_EC_SC_SMI 0x04 /* smi event pending */
#define AMD_EC_SC_SCI 0x02 /* sci event pending */
#define AMD_EC_SC_BURST 0x01 /* burst mode enabled */
#define AMD_EC_SC_CMD 0x08 /* byte in data reg is command */
#define AMD_EC_SC_IBF 0x02 /* data ready for embedded controller */
#define AMD_EC_SC_OBF 0x01 /* data ready for host */
#define AMD_EC_CMD_RD 0x80 /* read EC */
#define AMD_EC_CMD_WR 0x81 /* write EC */
#define AMD_EC_CMD_BE 0x82 /* enable burst mode */
#define AMD_EC_CMD_BD 0x83 /* disable burst mode */
#define AMD_EC_CMD_QR 0x84 /* query EC */
/*
* ACPI 2.0 chapter 13 access of registers of the EC
*/
unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
{
int timeout = 500;
while (timeout-- && (inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF))
udelay(1);
if (!timeout) {
printk(KERN_WARNING "i2c-amd811.c: Timeout while waiting for IBF to clear\n");
return -1;
}
return 0;
}
unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
{
int timeout = 500;
while (timeout-- && (~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF))
udelay(1);
if (!timeout) {
printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for OBF to set\n");
return -1;
}
return 0;
}
unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data)
{
if (amd_ec_wait_write(smbus))
return -1;
outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
if (amd_ec_wait_write(smbus))
return -1;
outb(address, smbus->base + AMD_EC_DATA);
if (amd_ec_wait_read(smbus))
return -1;
*data = inb(smbus->base + AMD_EC_DATA);
return 0;
}
unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data)
{
if (amd_ec_wait_write(smbus))
return -1;
outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
if (amd_ec_wait_write(smbus))
return -1;
outb(address, smbus->base + AMD_EC_DATA);
if (amd_ec_wait_write(smbus))
return -1;
outb(data, smbus->base + AMD_EC_DATA);
return 0;
}
/*
* ACPI 2.0 chapter 13 SMBus 2.0 EC register model
*/
#define AMD_SMB_PRTCL 0x00 /* protocol, PEC */
#define AMD_SMB_STS 0x01 /* status */
#define AMD_SMB_ADDR 0x02 /* address */
#define AMD_SMB_CMD 0x03 /* command */
#define AMD_SMB_DATA 0x04 /* 32 data registers */
#define AMD_SMB_BCNT 0x24 /* number of data bytes */
#define AMD_SMB_ALRM_A 0x25 /* alarm address */
#define AMD_SMB_ALRM_D 0x26 /* 2 bytes alarm data */
#define AMD_SMB_STS_DONE 0x80
#define AMD_SMB_STS_ALRM 0x40
#define AMD_SMB_STS_RES 0x20
#define AMD_SMB_STS_STATUS 0x1f
#define AMD_SMB_STATUS_OK 0x00
#define AMD_SMB_STATUS_FAIL 0x07
#define AMD_SMB_STATUS_DNAK 0x10
#define AMD_SMB_STATUS_DERR 0x11
#define AMD_SMB_STATUS_CMD_DENY 0x12
#define AMD_SMB_STATUS_UNKNOWN 0x13
#define AMD_SMB_STATUS_ACC_DENY 0x17
#define AMD_SMB_STATUS_TIMEOUT 0x18
#define AMD_SMB_STATUS_NOTSUP 0x19
#define AMD_SMB_STATUS_BUSY 0x1A
#define AMD_SMB_STATUS_PEC 0x1F
#define AMD_SMB_PRTCL_QUICK 0x02
#define AMD_SMB_PRTCL_BYTE 0x04
#define AMD_SMB_PRTCL_BYTE_DATA 0x06
#define AMD_SMB_PRTCL_WORD_DATA 0x08
#define AMD_SMB_PRTCL_BLOCK_DATA 0x0a
#define AMD_SMB_PRTCL_PROC_CALL 0x0c
#define AMD_SMB_PRTCL_BLOCK_PROC_CALL 0x0d
#define AMD_SMB_PRTCL_I2C_BLOCK_DATA 0x4a
#define AMD_SMB_PRTCL_PEC 0x80
s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
char read_write, u8 command, int size, union i2c_smbus_data * data)
{
struct amd_smbus *smbus = adap->algo_data;
unsigned char protocol = read_write; /* 1 = read, 0 = write */
unsigned char temp[2];
int i, timeout = 5000;
switch (size) {
case I2C_SMBUS_QUICK:
protocol |= AMD_SMB_PRTCL_QUICK;
break;
case I2C_SMBUS_BYTE:
if (!read_write)
amd_ec_write(smbus, AMD_SMB_DATA, data->byte);
protocol |= AMD_SMB_PRTCL_BYTE;
break;
case I2C_SMBUS_BYTE_DATA:
amd_ec_write(smbus, AMD_SMB_CMD, command);
if (!read_write)
amd_ec_write(smbus, AMD_SMB_DATA, data->byte);
protocol |= AMD_SMB_PRTCL_BYTE_DATA;
break;
case I2C_SMBUS_WORD_DATA:
amd_ec_write(smbus, AMD_SMB_CMD, command);
if (!read_write) {
amd_ec_write(smbus, AMD_SMB_DATA, data->byte);
amd_ec_write(smbus, AMD_SMB_DATA + 1, data->byte >> 8);
}
protocol |= AMD_SMB_PRTCL_WORD_DATA;
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_DATA_PEC:
case I2C_SMBUS_I2C_BLOCK_DATA:
amd_ec_write(smbus, AMD_SMB_CMD, command);
if (!read_write)
for (i = 0; i < data->block[0]; i++)
amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
switch (size) {
case I2C_SMBUS_BLOCK_DATA:
protocol |= AMD_SMB_PRTCL_BLOCK_DATA;
break;
case I2C_SMBUS_BLOCK_DATA_PEC:
protocol |= AMD_SMB_PRTCL_BLOCK_DATA | AMD_SMB_PRTCL_PEC;
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
break;
}
break;
case I2C_SMBUS_PROC_CALL: /* We don't support proc_call yet */
default:
printk(KERN_WARNING "i2c-amd8111.c: Unsupported transaction %d\n", size);
return -1;
}
amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
while (timeout && ~temp[0] & AMD_SMB_STS_DONE) {
amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
udelay(10);
timeout--;
}
if (!timeout)
return -1;
if (~temp[0] & AMD_SMB_STS_DONE) {
printk(KERN_WARNING "i2c-amd8111.c: Transaction completed with error %#x\n", temp[0]);
return -1;
}
if (!read_write) /* We're done, no values to return; */
return 0;
switch (size) {
case I2C_SMBUS_BYTE:
case I2C_SMBUS_BYTE_DATA:
amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
break;
case I2C_SMBUS_WORD_DATA:
amd_ec_read(smbus, AMD_SMB_DATA, temp + 0);
amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1);
data->word = (temp[1] << 8) | temp[0];
break;
case I2C_SMBUS_BLOCK_DATA:
case I2C_SMBUS_BLOCK_DATA_PEC:
case I2C_SMBUS_I2C_BLOCK_DATA:
for (i = 0; i < data->block[0]; i++)
amd_ec_read(smbus, AMD_SMB_DATA + i, data->block + i + 1);
break;
}
return 0;
}
void amd8111_inc(struct i2c_adapter *adapter)
{
MOD_INC_USE_COUNT;
}
void amd8111_dec(struct i2c_adapter *adapter)
{
MOD_DEC_USE_COUNT;
}
u32 amd8111_func(struct i2c_adapter *adapter)
{
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK |
I2C_FUNC_SMBUS_BLOCK_DATA_PEC | I2C_FUNC_SMBUS_HWPEC_CALC;
}
static struct i2c_algorithm smbus_algorithm = {
.name = "Non-I2C SMBus 2.0 adapter",
.id = I2C_ALGO_SMBUS,
.smbus_xfer = amd8111_access,
.functionality = amd8111_func,
};
static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
struct amd_smbus *smbus;
if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
return -1;
if (!(smbus = kmalloc(sizeof(struct amd_smbus), GFP_KERNEL)))
return -1;
memset(smbus, 0, sizeof(struct amd_smbus));
pci_set_drvdata(dev, smbus);
smbus->dev = dev;
smbus->base = pci_resource_start(dev, 0);
smbus->size = pci_resource_len(dev, 0);
if (!request_region(smbus->base, smbus->size, "amd81111 SMBus 2.0")) {
kfree(smbus);
return -1;
}
sprintf(smbus->adapter.name, "SMBus2 AMD8111 adapter at %04x", smbus->base);
smbus->adapter.id = I2C_ALGO_SMBUS | I2C_HW_SMBUS_AMD8111;
smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus;
smbus->adapter.inc_use = amd8111_inc;
smbus->adapter.dec_use = amd8111_dec;
pci_write_config_dword(dev, AMD_PCI_MISC, 0);
if (i2c_add_adapter(&smbus->adapter)) {
printk(KERN_WARNING "i2c-amd8111.c: Failed to register adapter.\n");
release_region(smbus->base, smbus->size);
kfree(smbus);
return -1;
}
printk(KERN_INFO "i2c-amd8111.c: AMD8111 SMBus 2.0 adapter at pci%s\n", dev->slot_name);
return 0;
}
static void __devexit amd8111_remove(struct pci_dev *dev)
{
struct amd_smbus *smbus = pci_get_drvdata(dev);
if (i2c_del_adapter(&smbus->adapter)) {
printk(KERN_WARNING "i2c-amd81111.c: Failed to unregister adapter.\n");
return;
}
release_region(smbus->base, smbus->size);
kfree(smbus);
}
static struct pci_device_id amd8111_id_table[] __devinitdata =
{{ 0x1022, 0x746a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
{ 0 }};
static struct pci_driver amd8111_driver = {
.name = "amd8111 smbus 2.0",
.id_table = amd8111_id_table,
.probe = amd8111_probe,
.remove = amd8111_remove,
};
int __init amd8111_init(void)
{
return pci_module_init(&amd8111_driver);
}
void __exit amd8111_exit(void)
{
pci_unregister_driver(&amd8111_driver);
}
module_init(amd8111_init);
module_exit(amd8111_exit);
+1
View File
@@ -3,6 +3,7 @@ kernel/busses/dmi_scan.h include/linux/dmi_scan.h
kernel/busses/i2c-ali1535.c drivers/i2c/i2c-ali1535.c
kernel/busses/i2c-ali15x3.c drivers/i2c/i2c-ali15x3.c
kernel/busses/i2c-amd756.c drivers/i2c/i2c-amd756.c
kernel/busses/i2c-amd8111.c drivers/i2c/i2c-amd8111.c
kernel/busses/i2c-hydra.c drivers/i2c/i2c-hydra.c
kernel/busses/i2c-i801.c drivers/i2c/i2c-i801.c
kernel/busses/i2c-i810.c drivers/i2c/i2c-i810.c
+16
View File
@@ -303,6 +303,22 @@ use vars qw(@pci_adapters @chip_ids @undetectable_adapters @dmidecode);
driver => "i2c-amd756",
match => sub { $_[0] =~ /^SMBus AMD768 adapter at [0-9,a-f]{4}/ },
},
{
vendid => 0x1022,
devid => 0x746b,
func => 3,
procid => "AMD-8111 ACPI",
driver => "i2c-amd756",
match => sub { $_[0] =~ /^SMBus AMD8111 adapter at [0-9,a-f]{4}/ },
},
{
vendid => 0x1022,
devid => 0x746a,
func => 2,
procid => "AMD-8111 SMBus 2.0",
driver => "i2c-amd8111",
match => sub { $_[0] =~ /^SMBus2 AMD8111 adapter at [0-9,a-f]{4}/ },
},
{
vendid => 0x102b,
devid => 0x0519,