You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6: i2c: Stop using i2c_adapter.class_dev i2c: Remove the warning on missing adapter device i2c: Declare more i2c_adapter parent devices i2c: PA Semi SMBus driver i2c-amd8111: Proposed cleanups i2c-parport: Add support for One For All remote JP1 interface i2c-viapro: Add support for the VIA CX700 south bridge i2c: Add IDs to adapters i2c: Update the list of bus IDs i2c: Add driver suspend/resume/shutdown support i2c: completion header cleanups i2c-i801: Document the SMBus unhiding quirk i2c-i801: Spelling fix i2c: Fix typo in SMBus Write Word Data description i2c-piix4: Add support for the ATI SB600 i2c-nforce2: Drop unused reference to pci_dev i2c/vt8231: Remove superfluous initialization i2c-ali1563: Fix device initialization i2c-ali1563: Improve the status messages
This commit is contained in:
@@ -48,14 +48,9 @@ following:
|
||||
The SMBus controller is function 3 in device 1f. Class 0c05 is SMBus Serial
|
||||
Controller.
|
||||
|
||||
If you do NOT see the 24x3 device at function 3, and you can't figure out
|
||||
any way in the BIOS to enable it,
|
||||
|
||||
The ICH chips are quite similar to Intel's PIIX4 chip, at least in the
|
||||
SMBus controller.
|
||||
|
||||
See the file i2c-piix4 for some additional information.
|
||||
|
||||
|
||||
Process Call Support
|
||||
--------------------
|
||||
@@ -74,6 +69,61 @@ SMBus 2.0 Support
|
||||
|
||||
The 82801DB (ICH4) and later chips support several SMBus 2.0 features.
|
||||
|
||||
|
||||
Hidden ICH SMBus
|
||||
----------------
|
||||
|
||||
If your system has an Intel ICH south bridge, but you do NOT see the
|
||||
SMBus device at 00:1f.3 in lspci, and you can't figure out any way in the
|
||||
BIOS to enable it, it means it has been hidden by the BIOS code. Asus is
|
||||
well known for first doing this on their P4B motherboard, and many other
|
||||
boards after that. Some vendor machines are affected as well.
|
||||
|
||||
The first thing to try is the "i2c_ec" ACPI driver. It could be that the
|
||||
SMBus was hidden on purpose because it'll be driven by ACPI. If the
|
||||
i2c_ec driver works for you, just forget about the i2c-i801 driver and
|
||||
don't try to unhide the ICH SMBus. Even if i2c_ec doesn't work, you
|
||||
better make sure that the SMBus isn't used by the ACPI code. Try loading
|
||||
the "fan" and "thermal" drivers, and check in /proc/acpi/fan and
|
||||
/proc/acpi/thermal_zone. If you find anything there, it's likely that
|
||||
the ACPI is accessing the SMBus and it's safer not to unhide it. Only
|
||||
once you are certain that ACPI isn't using the SMBus, you can attempt
|
||||
to unhide it.
|
||||
|
||||
In order to unhide the SMBus, we need to change the value of a PCI
|
||||
register before the kernel enumerates the PCI devices. This is done in
|
||||
drivers/pci/quirks.c, where all affected boards must be listed (see
|
||||
function asus_hides_smbus_hostbridge.) If the SMBus device is missing,
|
||||
and you think there's something interesting on the SMBus (e.g. a
|
||||
hardware monitoring chip), you need to add your board to the list.
|
||||
|
||||
The motherboard is identified using the subvendor and subdevice IDs of the
|
||||
host bridge PCI device. Get yours with "lspci -n -v -s 00:00.0":
|
||||
|
||||
00:00.0 Class 0600: 8086:2570 (rev 02)
|
||||
Subsystem: 1043:80f2
|
||||
Flags: bus master, fast devsel, latency 0
|
||||
Memory at fc000000 (32-bit, prefetchable) [size=32M]
|
||||
Capabilities: [e4] #09 [2106]
|
||||
Capabilities: [a0] AGP version 3.0
|
||||
|
||||
Here the host bridge ID is 2570 (82865G/PE/P), the subvendor ID is 1043
|
||||
(Asus) and the subdevice ID is 80f2 (P4P800-X). You can find the symbolic
|
||||
names for the bridge ID and the subvendor ID in include/linux/pci_ids.h,
|
||||
and then add a case for your subdevice ID at the right place in
|
||||
drivers/pci/quirks.c. Then please give it very good testing, to make sure
|
||||
that the unhidden SMBus doesn't conflict with e.g. ACPI.
|
||||
|
||||
If it works, proves useful (i.e. there are usable chips on the SMBus)
|
||||
and seems safe, please submit a patch for inclusion into the kernel.
|
||||
|
||||
Note: There's a useful script in lm_sensors 2.10.2 and later, named
|
||||
unhide_ICH_SMBus (in prog/hotplug), which uses the fakephp driver to
|
||||
temporarily unhide the SMBus without having to patch and recompile your
|
||||
kernel. It's very convenient if you just want to check if there's
|
||||
anything interesting on your hidden ICH SMBus.
|
||||
|
||||
|
||||
**********************
|
||||
The lm_sensors project gratefully acknowledges the support of Texas
|
||||
Instruments in the initial development of this driver.
|
||||
|
||||
@@ -19,6 +19,7 @@ It currently supports the following devices:
|
||||
* (type=4) Analog Devices ADM1032 evaluation board
|
||||
* (type=5) Analog Devices evaluation boards: ADM1025, ADM1030, ADM1031
|
||||
* (type=6) Barco LPT->DVI (K5800236) adapter
|
||||
* (type=7) One For All JP1 parallel port adapter
|
||||
|
||||
These devices use different pinout configurations, so you have to tell
|
||||
the driver what you have, using the type module parameter. There is no
|
||||
@@ -157,3 +158,17 @@ many more, using /dev/velleman.
|
||||
http://home.wanadoo.nl/hihihi/libk8005.htm
|
||||
http://struyve.mine.nu:8080/index.php?block=k8000
|
||||
http://sourceforge.net/projects/libk8005/
|
||||
|
||||
|
||||
One For All JP1 parallel port adapter
|
||||
-------------------------------------
|
||||
|
||||
The JP1 project revolves around a set of remote controls which expose
|
||||
the I2C bus their internal configuration EEPROM lives on via a 6 pin
|
||||
jumper in the battery compartment. More details can be found at:
|
||||
|
||||
http://www.hifi-remote.com/jp1/
|
||||
|
||||
Details of the simple parallel port hardware can be found at:
|
||||
|
||||
http://www.hifi-remote.com/jp1/hardware.shtml
|
||||
|
||||
@@ -6,7 +6,7 @@ Supported adapters:
|
||||
Datasheet: Publicly available at the Intel website
|
||||
* ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
|
||||
Datasheet: Only available via NDA from ServerWorks
|
||||
* ATI IXP southbridges IXP200, IXP300, IXP400
|
||||
* ATI IXP200, IXP300, IXP400 and SB600 southbridges
|
||||
Datasheet: Not publicly available
|
||||
* Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge
|
||||
Datasheet: Publicly available at the SMSC website http://www.smsc.com
|
||||
|
||||
@@ -13,6 +13,9 @@ Supported adapters:
|
||||
* VIA Technologies, Inc. VT8235, VT8237R, VT8237A, VT8251
|
||||
Datasheet: available on request and under NDA from VIA
|
||||
|
||||
* VIA Technologies, Inc. CX700
|
||||
Datasheet: available on request and under NDA from VIA
|
||||
|
||||
Authors:
|
||||
Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>,
|
||||
@@ -44,6 +47,7 @@ Your lspci -n listing must show one of these :
|
||||
device 1106:3227 (VT8237R)
|
||||
device 1106:3337 (VT8237A)
|
||||
device 1106:3287 (VT8251)
|
||||
device 1106:8324 (CX700)
|
||||
|
||||
If none of these show up, you should look in the BIOS for settings like
|
||||
enable ACPI / SMBus or even USB.
|
||||
@@ -51,3 +55,6 @@ enable ACPI / SMBus or even USB.
|
||||
Except for the oldest chips (VT82C596A/B, VT82C686A and most probably
|
||||
VT8231), this driver supports I2C block transactions. Such transactions
|
||||
are mainly useful to read from and write to EEPROMs.
|
||||
|
||||
The CX700 additionally appears to support SMBus PEC, although this driver
|
||||
doesn't implement it yet.
|
||||
|
||||
@@ -129,6 +129,12 @@ Technical changes:
|
||||
structure, those name member should be initialized to a driver name
|
||||
string. i2c_driver itself has no name member anymore.
|
||||
|
||||
* [Driver model] Instead of shutdown or reboot notifiers, provide a
|
||||
shutdown() method in your driver.
|
||||
|
||||
* [Power management] Use the driver model suspend() and resume()
|
||||
callbacks instead of the obsolete pm_register() calls.
|
||||
|
||||
Coding policy:
|
||||
|
||||
* [Copyright] Use (C), not (c), for copyright.
|
||||
|
||||
@@ -97,7 +97,7 @@ SMBus Write Word Data
|
||||
=====================
|
||||
|
||||
This is the opposite operation of the Read Word Data command. 16 bits
|
||||
of data is read from a device, from a designated register that is
|
||||
of data is written to a device, to the designated register that is
|
||||
specified through the Comm byte.
|
||||
|
||||
S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
|
||||
|
||||
@@ -21,20 +21,26 @@ The driver structure
|
||||
|
||||
Usually, you will implement a single driver structure, and instantiate
|
||||
all clients from it. Remember, a driver structure contains general access
|
||||
routines, a client structure specific information like the actual I2C
|
||||
address.
|
||||
routines, and should be zero-initialized except for fields with data you
|
||||
provide. A client structure holds device-specific information like the
|
||||
driver model device node, and its I2C address.
|
||||
|
||||
static struct i2c_driver foo_driver = {
|
||||
.driver = {
|
||||
.name = "foo",
|
||||
},
|
||||
.attach_adapter = &foo_attach_adapter,
|
||||
.detach_client = &foo_detach_client,
|
||||
.command = &foo_command /* may be NULL */
|
||||
.attach_adapter = foo_attach_adapter,
|
||||
.detach_client = foo_detach_client,
|
||||
.shutdown = foo_shutdown, /* optional */
|
||||
.suspend = foo_suspend, /* optional */
|
||||
.resume = foo_resume, /* optional */
|
||||
.command = foo_command, /* optional */
|
||||
}
|
||||
|
||||
The name field must match the driver name, including the case. It must not
|
||||
contain spaces, and may be up to 31 characters long.
|
||||
The name field is the driver name, and must not contain spaces. It
|
||||
should match the module name (if the driver can be compiled as a module),
|
||||
although you can use MODULE_ALIAS (passing "foo" in this example) to add
|
||||
another name for the module.
|
||||
|
||||
All other fields are for call-back functions which will be explained
|
||||
below.
|
||||
@@ -43,11 +49,18 @@ below.
|
||||
Extra client data
|
||||
=================
|
||||
|
||||
The client structure has a special `data' field that can point to any
|
||||
structure at all. You can use this to keep client-specific data. You
|
||||
Each client structure has a special `data' field that can point to any
|
||||
structure at all. You should use this to keep device-specific data,
|
||||
especially in drivers that handle multiple I2C or SMBUS devices. You
|
||||
do not always need this, but especially for `sensors' drivers, it can
|
||||
be very useful.
|
||||
|
||||
/* store the value */
|
||||
void i2c_set_clientdata(struct i2c_client *client, void *data);
|
||||
|
||||
/* retrieve the value */
|
||||
void *i2c_get_clientdata(struct i2c_client *client);
|
||||
|
||||
An example structure is below.
|
||||
|
||||
struct foo_data {
|
||||
@@ -493,6 +506,33 @@ by `__init_data'. Hose functions and structures can be removed after
|
||||
kernel booting (or module loading) is completed.
|
||||
|
||||
|
||||
Power Management
|
||||
================
|
||||
|
||||
If your I2C device needs special handling when entering a system low
|
||||
power state -- like putting a transceiver into a low power mode, or
|
||||
activating a system wakeup mechanism -- do that in the suspend() method.
|
||||
The resume() method should reverse what the suspend() method does.
|
||||
|
||||
These are standard driver model calls, and they work just like they
|
||||
would for any other driver stack. The calls can sleep, and can use
|
||||
I2C messaging to the device being suspended or resumed (since their
|
||||
parent I2C adapter is active when these calls are issued, and IRQs
|
||||
are still enabled).
|
||||
|
||||
|
||||
System Shutdown
|
||||
===============
|
||||
|
||||
If your I2C device needs special handling when the system shuts down
|
||||
or reboots (including kexec) -- like turning something off -- use a
|
||||
shutdown() method.
|
||||
|
||||
Again, this is a standard driver model call, working just like it
|
||||
would for any other driver stack: the calls can sleep, and can use
|
||||
I2C messaging.
|
||||
|
||||
|
||||
Command function
|
||||
================
|
||||
|
||||
|
||||
@@ -2523,6 +2523,12 @@ M: olof@lixom.net
|
||||
L: netdev@vger.kernel.org
|
||||
S: Maintained
|
||||
|
||||
PA SEMI SMBUS DRIVER
|
||||
P: Olof Johansson
|
||||
M: olof@lixom.net
|
||||
L: i2c@lm-sensors.org
|
||||
S: Maintained
|
||||
|
||||
PARALLEL PORT SUPPORT
|
||||
P: Phil Blundell
|
||||
M: philb@gnu.org
|
||||
|
||||
@@ -340,6 +340,7 @@ static int acpi_ec_hc_add(struct acpi_device *device)
|
||||
smbus->adapter.owner = THIS_MODULE;
|
||||
smbus->adapter.algo = &acpi_ec_smbus_algorithm;
|
||||
smbus->adapter.algo_data = smbus;
|
||||
smbus->adapter.dev.parent = &device->dev;
|
||||
|
||||
if (i2c_add_adapter(&smbus->adapter)) {
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_WARN,
|
||||
|
||||
@@ -727,7 +727,6 @@ int vt8231_detect(struct i2c_adapter *adapter)
|
||||
client->addr = isa_address;
|
||||
client->adapter = adapter;
|
||||
client->driver = &vt8231_driver;
|
||||
client->dev.parent = &adapter->dev;
|
||||
|
||||
/* Fill in the remaining client fields and put into the global list */
|
||||
strlcpy(client->name, "vt8231", I2C_NAME_SIZE);
|
||||
|
||||
@@ -183,6 +183,7 @@ config I2C_PIIX4
|
||||
ATI IXP200
|
||||
ATI IXP300
|
||||
ATI IXP400
|
||||
ATI SB600
|
||||
Serverworks OSB4
|
||||
Serverworks CSB5
|
||||
Serverworks CSB6
|
||||
@@ -341,6 +342,13 @@ config I2C_PARPORT_LIGHT
|
||||
This support is also available as a module. If so, the module
|
||||
will be called i2c-parport-light.
|
||||
|
||||
config I2C_PASEMI
|
||||
tristate "PA Semi SMBus interface"
|
||||
# depends on PPC_PASEMI && I2C && PCI
|
||||
depends on I2C && PCI
|
||||
help
|
||||
Supports the PA Semi PWRficient on-chip SMBus interfaces.
|
||||
|
||||
config I2C_PROSAVAGE
|
||||
tristate "S3/VIA (Pro)Savage"
|
||||
depends on I2C && PCI
|
||||
@@ -499,11 +507,11 @@ config I2C_VIA
|
||||
will be called i2c-via.
|
||||
|
||||
config I2C_VIAPRO
|
||||
tristate "VIA 82C596/82C686/82xx"
|
||||
tristate "VIA VT82C596/82C686/82xx and CX700"
|
||||
depends on I2C && PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the VIA
|
||||
82C596/82C686/82xx I2C interfaces. Specifically, the following
|
||||
VT82C596 and later SMBus interface. Specifically, the following
|
||||
chipsets are supported:
|
||||
VT82C596A/B
|
||||
VT82C686A/B
|
||||
@@ -512,6 +520,7 @@ config I2C_VIAPRO
|
||||
VT8235
|
||||
VT8237R/A
|
||||
VT8251
|
||||
CX700
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called i2c-viapro.
|
||||
|
||||
@@ -27,6 +27,7 @@ obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o
|
||||
obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
|
||||
obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o
|
||||
obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o
|
||||
obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o
|
||||
obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o
|
||||
obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o
|
||||
obj-$(CONFIG_I2C_PNX) += i2c-pnx.o
|
||||
|
||||
@@ -475,6 +475,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter ali1535_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_ALI1535,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
@@ -314,35 +314,11 @@ static u32 ali1563_func(struct i2c_adapter * a)
|
||||
}
|
||||
|
||||
|
||||
static void ali1563_enable(struct pci_dev * dev)
|
||||
{
|
||||
u16 ctrl;
|
||||
|
||||
pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
|
||||
ctrl |= 0x7;
|
||||
pci_write_config_word(dev,ALI1563_SMBBA,ctrl);
|
||||
}
|
||||
|
||||
static int __devinit ali1563_setup(struct pci_dev * dev)
|
||||
{
|
||||
u16 ctrl;
|
||||
|
||||
pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
|
||||
printk("ali1563: SMBus control = %04x\n",ctrl);
|
||||
|
||||
/* Check if device is even enabled first */
|
||||
if (!(ctrl & ALI1563_SMB_IOEN)) {
|
||||
dev_warn(&dev->dev,"I/O space not enabled, trying manually\n");
|
||||
ali1563_enable(dev);
|
||||
}
|
||||
if (!(ctrl & ALI1563_SMB_IOEN)) {
|
||||
dev_warn(&dev->dev,"I/O space still not enabled, giving up\n");
|
||||
goto Err;
|
||||
}
|
||||
if (!(ctrl & ALI1563_SMB_HOSTEN)) {
|
||||
dev_warn(&dev->dev,"Host Controller not enabled\n");
|
||||
goto Err;
|
||||
}
|
||||
|
||||
/* SMB I/O Base in high 12 bits and must be aligned with the
|
||||
* size of the I/O space. */
|
||||
@@ -351,11 +327,31 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
|
||||
dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
|
||||
goto Err;
|
||||
}
|
||||
if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
|
||||
ali1563_pci_driver.name)) {
|
||||
dev_warn(&dev->dev,"Could not allocate I/O space");
|
||||
|
||||
/* Check if device is enabled */
|
||||
if (!(ctrl & ALI1563_SMB_HOSTEN)) {
|
||||
dev_warn(&dev->dev, "Host Controller not enabled\n");
|
||||
goto Err;
|
||||
}
|
||||
if (!(ctrl & ALI1563_SMB_IOEN)) {
|
||||
dev_warn(&dev->dev, "I/O space not enabled, trying manually\n");
|
||||
pci_write_config_word(dev, ALI1563_SMBBA,
|
||||
ctrl | ALI1563_SMB_IOEN);
|
||||
pci_read_config_word(dev, ALI1563_SMBBA, &ctrl);
|
||||
if (!(ctrl & ALI1563_SMB_IOEN)) {
|
||||
dev_err(&dev->dev, "I/O space still not enabled, "
|
||||
"giving up\n");
|
||||
goto Err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
|
||||
ali1563_pci_driver.name)) {
|
||||
dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",
|
||||
ali1563_smba);
|
||||
goto Err;
|
||||
}
|
||||
dev_info(&dev->dev, "Found ALi1563 SMBus at 0x%04x\n", ali1563_smba);
|
||||
|
||||
return 0;
|
||||
Err:
|
||||
@@ -374,6 +370,7 @@ static const struct i2c_algorithm ali1563_algorithm = {
|
||||
|
||||
static struct i2c_adapter ali1563_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_ALI1563,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &ali1563_algorithm,
|
||||
};
|
||||
@@ -384,13 +381,18 @@ static int __devinit ali1563_probe(struct pci_dev * dev,
|
||||
int error;
|
||||
|
||||
if ((error = ali1563_setup(dev)))
|
||||
return error;
|
||||
goto exit;
|
||||
ali1563_adapter.dev.parent = &dev->dev;
|
||||
sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x",
|
||||
ali1563_smba);
|
||||
if ((error = i2c_add_adapter(&ali1563_adapter)))
|
||||
ali1563_shutdown(dev);
|
||||
printk("%s: Returning %d\n",__FUNCTION__,error);
|
||||
goto exit_shutdown;
|
||||
return 0;
|
||||
|
||||
exit_shutdown:
|
||||
ali1563_shutdown(dev);
|
||||
exit:
|
||||
dev_warn(&dev->dev, "ALi1563 SMBus probe failed (%d)\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@@ -470,6 +470,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter ali15x3_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_ALI15X3,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
@@ -184,12 +184,14 @@ static int __init amd756_s4882_init(void)
|
||||
s4882_algo[0].smbus_xfer = amd756_access_virt0;
|
||||
s4882_adapter[0] = amd756_smbus;
|
||||
s4882_adapter[0].algo = s4882_algo;
|
||||
s4882_adapter[0].dev.parent = amd756_smbus.dev.parent;
|
||||
for (i = 1; i < 5; i++) {
|
||||
s4882_algo[i] = *(amd756_smbus.algo);
|
||||
s4882_adapter[i] = amd756_smbus;
|
||||
sprintf(s4882_adapter[i].name,
|
||||
"SMBus 8111 adapter (CPU%d)", i-1);
|
||||
s4882_adapter[i].algo = s4882_algo+i;
|
||||
s4882_adapter[i].dev.parent = amd756_smbus.dev.parent;
|
||||
}
|
||||
s4882_algo[1].smbus_xfer = amd756_access_virt1;
|
||||
s4882_algo[2].smbus_xfer = amd756_access_virt2;
|
||||
|
||||
@@ -301,6 +301,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
struct i2c_adapter amd756_smbus = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_AMD756,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
@@ -76,7 +76,8 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
|
||||
udelay(1);
|
||||
|
||||
if (!timeout) {
|
||||
dev_warn(&smbus->dev->dev, "Timeout while waiting for IBF to clear\n");
|
||||
dev_warn(&smbus->dev->dev,
|
||||
"Timeout while waiting for IBF to clear\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -91,14 +92,16 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
|
||||
udelay(1);
|
||||
|
||||
if (!timeout) {
|
||||
dev_warn(&smbus->dev->dev, "Timeout while waiting for OBF to set\n");
|
||||
dev_warn(&smbus->dev->dev,
|
||||
"Timeout while waiting for OBF to set\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address, unsigned char *data)
|
||||
static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
|
||||
unsigned char *data)
|
||||
{
|
||||
if (amd_ec_wait_write(smbus))
|
||||
return -1;
|
||||
@@ -115,7 +118,8 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address, unsigned char data)
|
||||
static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
|
||||
unsigned char data)
|
||||
{
|
||||
if (amd_ec_wait_write(smbus))
|
||||
return -1;
|
||||
@@ -175,18 +179,19 @@ static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
|
||||
#define AMD_SMB_PRTCL_PEC 0x80
|
||||
|
||||
|
||||
static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
|
||||
char read_write, u8 command, int size, union i2c_smbus_data * data)
|
||||
static 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, len, pec, temp[2];
|
||||
int i;
|
||||
|
||||
protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ : AMD_SMB_PRTCL_WRITE;
|
||||
protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ
|
||||
: AMD_SMB_PRTCL_WRITE;
|
||||
pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0;
|
||||
|
||||
switch (size) {
|
||||
|
||||
case I2C_SMBUS_QUICK:
|
||||
protocol |= AMD_SMB_PRTCL_QUICK;
|
||||
read_write = I2C_SMBUS_WRITE;
|
||||
@@ -208,8 +213,10 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
amd_ec_write(smbus, AMD_SMB_CMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
amd_ec_write(smbus, AMD_SMB_DATA, data->word);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA,
|
||||
data->word & 0xff);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + 1,
|
||||
data->word >> 8);
|
||||
}
|
||||
protocol |= AMD_SMB_PRTCL_WORD_DATA | pec;
|
||||
break;
|
||||
@@ -217,27 +224,31 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
amd_ec_write(smbus, AMD_SMB_CMD, command);
|
||||
if (read_write == I2C_SMBUS_WRITE) {
|
||||
len = min_t(u8, data->block[0], 32);
|
||||
len = min_t(u8, data->block[0],
|
||||
I2C_SMBUS_BLOCK_MAX);
|
||||
amd_ec_write(smbus, AMD_SMB_BCNT, len);
|
||||
for (i = 0; i < len; i++)
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + i,
|
||||
data->block[i + 1]);
|
||||
}
|
||||
protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec;
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
len = min_t(u8, data->block[0], 32);
|
||||
len = min_t(u8, data->block[0],
|
||||
I2C_SMBUS_BLOCK_MAX);
|
||||
amd_ec_write(smbus, AMD_SMB_CMD, command);
|
||||
amd_ec_write(smbus, AMD_SMB_BCNT, len);
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
for (i = 0; i < len; i++)
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + i,
|
||||
data->block[i + 1]);
|
||||
protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA;
|
||||
break;
|
||||
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
amd_ec_write(smbus, AMD_SMB_CMD, command);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA, data->word);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA, data->word & 0xff);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + 1, data->word >> 8);
|
||||
protocol = AMD_SMB_PRTCL_PROC_CALL | pec;
|
||||
read_write = I2C_SMBUS_READ;
|
||||
@@ -248,7 +259,8 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
|
||||
amd_ec_write(smbus, AMD_SMB_CMD, command);
|
||||
amd_ec_write(smbus, AMD_SMB_BCNT, len);
|
||||
for (i = 0; i < len; i++)
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + i, data->block[i + 1]);
|
||||
amd_ec_write(smbus, AMD_SMB_DATA + i,
|
||||
data->block[i + 1]);
|
||||
protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec;
|
||||
read_write = I2C_SMBUS_READ;
|
||||
break;
|
||||
@@ -280,7 +292,6 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
|
||||
return 0;
|
||||
|
||||
switch (size) {
|
||||
|
||||
case I2C_SMBUS_BYTE:
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
amd_ec_read(smbus, AMD_SMB_DATA, &data->byte);
|
||||
@@ -296,10 +307,11 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL:
|
||||
amd_ec_read(smbus, AMD_SMB_BCNT, &len);
|
||||
len = min_t(u8, len, 32);
|
||||
len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX);
|
||||
case I2C_SMBUS_I2C_BLOCK_DATA:
|
||||
for (i = 0; i < len; i++)
|
||||
amd_ec_read(smbus, AMD_SMB_DATA + i, data->block + i + 1);
|
||||
amd_ec_read(smbus, AMD_SMB_DATA + i,
|
||||
data->block + i + 1);
|
||||
data->block[0] = len;
|
||||
break;
|
||||
}
|
||||
@@ -310,7 +322,8 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short fl
|
||||
|
||||
static u32 amd8111_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
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_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC;
|
||||
@@ -329,12 +342,13 @@ static struct pci_device_id amd8111_ids[] = {
|
||||
|
||||
MODULE_DEVICE_TABLE (pci, amd8111_ids);
|
||||
|
||||
static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
static int __devinit amd8111_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct amd_smbus *smbus;
|
||||
int error = -ENODEV;
|
||||
int error;
|
||||
|
||||
if (~pci_resource_flags(dev, 0) & IORESOURCE_IO)
|
||||
if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
|
||||
return -ENODEV;
|
||||
|
||||
smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL);
|
||||
@@ -345,12 +359,15 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_
|
||||
smbus->base = pci_resource_start(dev, 0);
|
||||
smbus->size = pci_resource_len(dev, 0);
|
||||
|
||||
if (!request_region(smbus->base, smbus->size, amd8111_driver.name))
|
||||
if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
|
||||
error = -EBUSY;
|
||||
goto out_kfree;
|
||||
}
|
||||
|
||||
smbus->adapter.owner = THIS_MODULE;
|
||||
snprintf(smbus->adapter.name, I2C_NAME_SIZE,
|
||||
"SMBus2 AMD8111 adapter at %04x", smbus->base);
|
||||
smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
|
||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||
smbus->adapter.algo = &smbus_algorithm;
|
||||
smbus->adapter.algo_data = smbus;
|
||||
@@ -358,11 +375,11 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_
|
||||
/* set up the driverfs linkage to our parent device */
|
||||
smbus->adapter.dev.parent = &dev->dev;
|
||||
|
||||
pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
|
||||
error = i2c_add_adapter(&smbus->adapter);
|
||||
if (error)
|
||||
goto out_release_region;
|
||||
|
||||
pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0);
|
||||
pci_set_drvdata(dev, smbus);
|
||||
return 0;
|
||||
|
||||
@@ -370,10 +387,9 @@ static int __devinit amd8111_probe(struct pci_dev *dev, const struct pci_device_
|
||||
release_region(smbus->base, smbus->size);
|
||||
out_kfree:
|
||||
kfree(smbus);
|
||||
return -1;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static void __devexit amd8111_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct amd_smbus *smbus = pci_get_drvdata(dev);
|
||||
@@ -395,7 +411,6 @@ static int __init i2c_amd8111_init(void)
|
||||
return pci_register_driver(&amd8111_driver);
|
||||
}
|
||||
|
||||
|
||||
static void __exit i2c_amd8111_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&amd8111_driver);
|
||||
|
||||
@@ -123,7 +123,7 @@ static int i801_transaction(void)
|
||||
dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
|
||||
return -1;
|
||||
} else {
|
||||
dev_dbg(&I801_dev->dev, "Successfull!\n");
|
||||
dev_dbg(&I801_dev->dev, "Successful!\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,6 +442,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter i801_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_I801,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
||||
@@ -171,6 +171,7 @@ static struct i2c_algo_bit_data i810_i2c_bit_data = {
|
||||
|
||||
static struct i2c_adapter i810_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_B_I810,
|
||||
.name = "I810/I815 I2C Adapter",
|
||||
.algo_data = &i810_i2c_bit_data,
|
||||
};
|
||||
@@ -186,6 +187,7 @@ static struct i2c_algo_bit_data i810_ddc_bit_data = {
|
||||
|
||||
static struct i2c_adapter i810_ddc_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_B_I810,
|
||||
.name = "I810/I815 DDC Adapter",
|
||||
.algo_data = &i810_ddc_bit_data,
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user