mirror of
https://github.com/torvalds/linux.git
synced 2024-12-02 00:51:44 +00: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:
commit
33e563c119
@ -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,
|
||||
};
|
||||
|
@ -727,6 +727,7 @@ static int __devinit iic_probe(struct ocp_device *ocp){
|
||||
|
||||
/* Register it with i2c layer */
|
||||
adap = &dev->adap;
|
||||
adap->dev.parent = &ocp->dev;
|
||||
strcpy(adap->name, "IBM IIC");
|
||||
i2c_set_adapdata(adap, dev);
|
||||
adap->id = I2C_HW_OCP;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-isa.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
static u32 isa_func(struct i2c_adapter *adapter);
|
||||
|
||||
|
@ -520,6 +520,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
|
||||
rc = -ENXIO;
|
||||
goto exit_unmap_regs;
|
||||
}
|
||||
drv_data->adapter.dev.parent = &pd->dev;
|
||||
drv_data->adapter.id = I2C_HW_MV64XXX;
|
||||
drv_data->adapter.algo = &mv64xxx_i2c_algo;
|
||||
drv_data->adapter.owner = THIS_MODULE;
|
||||
|
@ -57,7 +57,6 @@ MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver");
|
||||
|
||||
|
||||
struct nforce2_smbus {
|
||||
struct pci_dev *dev;
|
||||
struct i2c_adapter adapter;
|
||||
int base;
|
||||
int size;
|
||||
@ -230,7 +229,6 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
|
||||
smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
|
||||
smbus->size = 64;
|
||||
}
|
||||
smbus->dev = dev;
|
||||
|
||||
if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
|
||||
dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
|
||||
@ -238,6 +236,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
|
||||
return -1;
|
||||
}
|
||||
smbus->adapter.owner = THIS_MODULE;
|
||||
smbus->adapter.id = I2C_HW_SMBUS_NFORCE2;
|
||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||
smbus->adapter.algo = &smbus_algorithm;
|
||||
smbus->adapter.algo_data = smbus;
|
||||
|
@ -88,6 +88,13 @@ static struct adapter_parm adapter_parm[] = {
|
||||
.getscl = { 0x40, STAT, 0 },
|
||||
.init = { 0xfc, DATA, 0 },
|
||||
},
|
||||
/* type 7: One For All JP1 parallel port adapter */
|
||||
{
|
||||
.setsda = { 0x01, DATA, 0 },
|
||||
.setscl = { 0x02, DATA, 0 },
|
||||
.getsda = { 0x80, STAT, 1 },
|
||||
.init = { 0x04, DATA, 1 },
|
||||
},
|
||||
};
|
||||
|
||||
static int type = -1;
|
||||
@ -101,4 +108,5 @@ MODULE_PARM_DESC(type,
|
||||
" 4 = ADM1032 evaluation board\n"
|
||||
" 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n"
|
||||
" 6 = Barco LPT->DVI (K5800236) adapter\n"
|
||||
" 7 = One For All JP1 parallel port adapter\n"
|
||||
);
|
||||
|
426
drivers/i2c/busses/i2c-pasemi.c
Normal file
426
drivers/i2c/busses/i2c-pasemi.c
Normal file
@ -0,0 +1,426 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2007 PA Semi, Inc
|
||||
*
|
||||
* SMBus host driver for PA Semi PWRficient
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/stddef.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
static struct pci_driver pasemi_smb_driver;
|
||||
|
||||
struct pasemi_smbus {
|
||||
struct pci_dev *dev;
|
||||
struct i2c_adapter adapter;
|
||||
unsigned long base;
|
||||
int size;
|
||||
};
|
||||
|
||||
/* Register offsets */
|
||||
#define REG_MTXFIFO 0x00
|
||||
#define REG_MRXFIFO 0x04
|
||||
#define REG_SMSTA 0x14
|
||||
#define REG_CTL 0x1c
|
||||
|
||||
/* Register defs */
|
||||
#define MTXFIFO_READ 0x00000400
|
||||
#define MTXFIFO_STOP 0x00000200
|
||||
#define MTXFIFO_START 0x00000100
|
||||
#define MTXFIFO_DATA_M 0x000000ff
|
||||
|
||||
#define MRXFIFO_EMPTY 0x00000100
|
||||
#define MRXFIFO_DATA_M 0x000000ff
|
||||
|
||||
#define SMSTA_XEN 0x08000000
|
||||
|
||||
#define CTL_MRR 0x00000400
|
||||
#define CTL_MTR 0x00000200
|
||||
#define CTL_CLK_M 0x000000ff
|
||||
|
||||
#define CLK_100K_DIV 84
|
||||
#define CLK_400K_DIV 21
|
||||
|
||||
static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
|
||||
{
|
||||
dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n",
|
||||
smbus->base + reg, val);
|
||||
outl(val, smbus->base + reg);
|
||||
}
|
||||
|
||||
static inline int reg_read(struct pasemi_smbus *smbus, int reg)
|
||||
{
|
||||
int ret;
|
||||
ret = inl(smbus->base + reg);
|
||||
dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n",
|
||||
smbus->base + reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define TXFIFO_WR(smbus, reg) reg_write((smbus), REG_MTXFIFO, (reg))
|
||||
#define RXFIFO_RD(smbus) reg_read((smbus), REG_MRXFIFO)
|
||||
|
||||
static void pasemi_smb_clear(struct pasemi_smbus *smbus)
|
||||
{
|
||||
unsigned int status;
|
||||
|
||||
status = reg_read(smbus, REG_SMSTA);
|
||||
reg_write(smbus, REG_SMSTA, status);
|
||||
}
|
||||
|
||||
static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus)
|
||||
{
|
||||
int timeout = 10;
|
||||
unsigned int status;
|
||||
|
||||
status = reg_read(smbus, REG_SMSTA);
|
||||
|
||||
while (!(status & SMSTA_XEN) && timeout--) {
|
||||
msleep(1);
|
||||
status = reg_read(smbus, REG_SMSTA);
|
||||
}
|
||||
|
||||
if (timeout < 0) {
|
||||
dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status);
|
||||
reg_write(smbus, REG_SMSTA, status);
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
/* Clear XEN */
|
||||
reg_write(smbus, REG_SMSTA, SMSTA_XEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msg, int stop)
|
||||
{
|
||||
struct pasemi_smbus *smbus = adapter->algo_data;
|
||||
int read, i, err;
|
||||
u32 rd;
|
||||
|
||||
read = msg->flags & I2C_M_RD ? 1 : 0;
|
||||
|
||||
TXFIFO_WR(smbus, MTXFIFO_START | (msg->addr << 1) | read);
|
||||
|
||||
if (read) {
|
||||
TXFIFO_WR(smbus, msg->len | MTXFIFO_READ |
|
||||
(stop ? MTXFIFO_STOP : 0));
|
||||
|
||||
err = pasemi_smb_waitready(smbus);
|
||||
if (err)
|
||||
goto reset_out;
|
||||
|
||||
for (i = 0; i < msg->len; i++) {
|
||||
rd = RXFIFO_RD(smbus);
|
||||
if (rd & MRXFIFO_EMPTY) {
|
||||
err = -ENODATA;
|
||||
goto reset_out;
|
||||
}
|
||||
msg->buf[i] = rd & MRXFIFO_DATA_M;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < msg->len - 1; i++)
|
||||
TXFIFO_WR(smbus, msg->buf[i]);
|
||||
|
||||
TXFIFO_WR(smbus, msg->buf[msg->len] |
|
||||
(stop ? MTXFIFO_STOP : 0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
reset_out:
|
||||
reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
|
||||
(CLK_100K_DIV & CTL_CLK_M)));
|
||||
return err;
|
||||
}
|
||||
|
||||
static int pasemi_i2c_xfer(struct i2c_adapter *adapter,
|
||||
struct i2c_msg *msgs, int num)
|
||||
{
|
||||
struct pasemi_smbus *smbus = adapter->algo_data;
|
||||
int ret, i;
|
||||
|
||||
pasemi_smb_clear(smbus);
|
||||
|
||||
ret = 0;
|
||||
|
||||
for (i = 0; i < num && !ret; i++)
|
||||
ret = pasemi_i2c_xfer_msg(adapter, &msgs[i], (i == (num - 1)));
|
||||
|
||||
return ret ? ret : num;
|
||||
}
|
||||
|
||||
static int pasemi_smb_xfer(struct i2c_adapter *adapter,
|
||||
u16 addr, unsigned short flags, char read_write, u8 command,
|
||||
int size, union i2c_smbus_data *data)
|
||||
{
|
||||
struct pasemi_smbus *smbus = adapter->algo_data;
|
||||
unsigned int rd;
|
||||
int read_flag, err;
|
||||
int len = 0, i;
|
||||
|
||||
/* All our ops take 8-bit shifted addresses */
|
||||
addr <<= 1;
|
||||
read_flag = read_write == I2C_SMBUS_READ;
|
||||
|
||||
pasemi_smb_clear(smbus);
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_QUICK:
|
||||
TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START |
|
||||
MTXFIFO_STOP);
|
||||
break;
|
||||
case I2C_SMBUS_BYTE:
|
||||
TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START);
|
||||
if (read_write)
|
||||
TXFIFO_WR(smbus, 1 | MTXFIFO_STOP | MTXFIFO_READ);
|
||||
else
|
||||
TXFIFO_WR(smbus, MTXFIFO_STOP | command);
|
||||
break;
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
TXFIFO_WR(smbus, addr | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, command);
|
||||
if (read_write) {
|
||||
TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, 1 | MTXFIFO_READ | MTXFIFO_STOP);
|
||||
} else {
|
||||
TXFIFO_WR(smbus, MTXFIFO_STOP | data->byte);
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
TXFIFO_WR(smbus, addr | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, command);
|
||||
if (read_write) {
|
||||
TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, 2 | MTXFIFO_READ | MTXFIFO_STOP);
|
||||
} else {
|
||||
TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
|
||||
TXFIFO_WR(smbus, MTXFIFO_STOP | (data->word >> 8));
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
TXFIFO_WR(smbus, addr | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, command);
|
||||
if (read_write) {
|
||||
TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, 1 | MTXFIFO_READ);
|
||||
rd = RXFIFO_RD(smbus);
|
||||
len = min_t(u8, (rd & MRXFIFO_DATA_M),
|
||||
I2C_SMBUS_BLOCK_MAX);
|
||||
TXFIFO_WR(smbus, (len + 1) | MTXFIFO_READ |
|
||||
MTXFIFO_STOP);
|
||||
} else {
|
||||
len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX);
|
||||
TXFIFO_WR(smbus, len);
|
||||
for (i = 1; i < len; i++)
|
||||
TXFIFO_WR(smbus, data->block[i]);
|
||||
TXFIFO_WR(smbus, data->block[len] | MTXFIFO_STOP);
|
||||
}
|
||||
break;
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
read_write = I2C_SMBUS_READ;
|
||||
TXFIFO_WR(smbus, addr | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, command);
|
||||
TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
|
||||
TXFIFO_WR(smbus, (data->word >> 8) & MTXFIFO_DATA_M);
|
||||
TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, 2 | MTXFIFO_STOP | MTXFIFO_READ);
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL:
|
||||
len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX - 1);
|
||||
read_write = I2C_SMBUS_READ;
|
||||
TXFIFO_WR(smbus, addr | MTXFIFO_START);
|
||||
TXFIFO_WR(smbus, command);
|
||||
TXFIFO_WR(smbus, len);
|
||||
for (i = 1; i <= len; i++)
|
||||
TXFIFO_WR(smbus, data->block[i]);
|
||||
TXFIFO_WR(smbus, addr | I2C_SMBUS_READ);
|
||||
TXFIFO_WR(smbus, MTXFIFO_READ | 1);
|
||||
rd = RXFIFO_RD(smbus);
|
||||
len = min_t(u8, (rd & MRXFIFO_DATA_M),
|
||||
I2C_SMBUS_BLOCK_MAX - len);
|
||||
TXFIFO_WR(smbus, (len + 1) | MTXFIFO_READ | MTXFIFO_STOP);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_warn(&adapter->dev, "Unsupported transaction %d\n", size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
err = pasemi_smb_waitready(smbus);
|
||||
if (err)
|
||||
goto reset_out;
|
||||
|
||||
if (read_write == I2C_SMBUS_WRITE)
|
||||
return 0;
|
||||
|
||||
switch (size) {
|
||||
case I2C_SMBUS_BYTE:
|
||||
case I2C_SMBUS_BYTE_DATA:
|
||||
rd = RXFIFO_RD(smbus);
|
||||
if (rd & MRXFIFO_EMPTY) {
|
||||
err = -ENODATA;
|
||||
goto reset_out;
|
||||
}
|
||||
data->byte = rd & MRXFIFO_DATA_M;
|
||||
break;
|
||||
case I2C_SMBUS_WORD_DATA:
|
||||
case I2C_SMBUS_PROC_CALL:
|
||||
rd = RXFIFO_RD(smbus);
|
||||
if (rd & MRXFIFO_EMPTY) {
|
||||
err = -ENODATA;
|
||||
goto reset_out;
|
||||
}
|
||||
data->word = rd & MRXFIFO_DATA_M;
|
||||
rd = RXFIFO_RD(smbus);
|
||||
if (rd & MRXFIFO_EMPTY) {
|
||||
err = -ENODATA;
|
||||
goto reset_out;
|
||||
}
|
||||
data->word |= (rd & MRXFIFO_DATA_M) << 8;
|
||||
break;
|
||||
case I2C_SMBUS_BLOCK_DATA:
|
||||
case I2C_SMBUS_BLOCK_PROC_CALL:
|
||||
data->block[0] = len;
|
||||
for (i = 1; i <= len; i ++) {
|
||||
rd = RXFIFO_RD(smbus);
|
||||
if (rd & MRXFIFO_EMPTY) {
|
||||
err = -ENODATA;
|
||||
goto reset_out;
|
||||
}
|
||||
data->block[i] = rd & MRXFIFO_DATA_M;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
reset_out:
|
||||
reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
|
||||
(CLK_100K_DIV & CTL_CLK_M)));
|
||||
return err;
|
||||
}
|
||||
|
||||
static u32 pasemi_smb_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_PROC_CALL |
|
||||
I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm smbus_algorithm = {
|
||||
.master_xfer = pasemi_i2c_xfer,
|
||||
.smbus_xfer = pasemi_smb_xfer,
|
||||
.functionality = pasemi_smb_func,
|
||||
};
|
||||
|
||||
static int __devinit pasemi_smb_probe(struct pci_dev *dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
struct pasemi_smbus *smbus;
|
||||
int error;
|
||||
|
||||
if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
|
||||
return -ENODEV;
|
||||
|
||||
smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL);
|
||||
if (!smbus)
|
||||
return -ENOMEM;
|
||||
|
||||
smbus->dev = dev;
|
||||
smbus->base = pci_resource_start(dev, 0);
|
||||
smbus->size = pci_resource_len(dev, 0);
|
||||
|
||||
if (!request_region(smbus->base, smbus->size,
|
||||
pasemi_smb_driver.name)) {
|
||||
error = -EBUSY;
|
||||
goto out_kfree;
|
||||
}
|
||||
|
||||
smbus->adapter.owner = THIS_MODULE;
|
||||
snprintf(smbus->adapter.name, I2C_NAME_SIZE,
|
||||
"PA Semi SMBus adapter at 0x%lx", smbus->base);
|
||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||
smbus->adapter.algo = &smbus_algorithm;
|
||||
smbus->adapter.algo_data = smbus;
|
||||
|
||||
/* set up the driverfs linkage to our parent device */
|
||||
smbus->adapter.dev.parent = &dev->dev;
|
||||
|
||||
reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
|
||||
(CLK_100K_DIV & CTL_CLK_M)));
|
||||
|
||||
error = i2c_add_adapter(&smbus->adapter);
|
||||
if (error)
|
||||
goto out_release_region;
|
||||
|
||||
pci_set_drvdata(dev, smbus);
|
||||
|
||||
return 0;
|
||||
|
||||
out_release_region:
|
||||
release_region(smbus->base, smbus->size);
|
||||
out_kfree:
|
||||
kfree(smbus);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void __devexit pasemi_smb_remove(struct pci_dev *dev)
|
||||
{
|
||||
struct pasemi_smbus *smbus = pci_get_drvdata(dev);
|
||||
|
||||
i2c_del_adapter(&smbus->adapter);
|
||||
release_region(smbus->base, smbus->size);
|
||||
kfree(smbus);
|
||||
}
|
||||
|
||||
static struct pci_device_id pasemi_smb_ids[] = {
|
||||
{ PCI_DEVICE(0x1959, 0xa003) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, pasemi_smb_ids);
|
||||
|
||||
static struct pci_driver pasemi_smb_driver = {
|
||||
.name = "i2c-pasemi",
|
||||
.id_table = pasemi_smb_ids,
|
||||
.probe = pasemi_smb_probe,
|
||||
.remove = __devexit_p(pasemi_smb_remove),
|
||||
};
|
||||
|
||||
static int __init pasemi_smb_init(void)
|
||||
{
|
||||
return pci_register_driver(&pasemi_smb_driver);
|
||||
}
|
||||
|
||||
static void __exit pasemi_smb_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&pasemi_smb_driver);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
|
||||
MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver");
|
||||
|
||||
module_init(pasemi_smb_init);
|
||||
module_exit(pasemi_smb_exit);
|
@ -23,6 +23,7 @@
|
||||
Supports:
|
||||
Intel PIIX4, 440MX
|
||||
Serverworks OSB4, CSB5, CSB6, HT-1000
|
||||
ATI IXP200, IXP300, IXP400, SB600
|
||||
SMSC Victory66
|
||||
|
||||
Note: we assume there can only be one device, with one SMBus interface.
|
||||
@ -383,6 +384,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter piix4_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_PIIX4,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
@ -396,6 +398,8 @@ static struct pci_device_id piix4_ids[] = {
|
||||
.driver_data = 0 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS),
|
||||
.driver_data = 0 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SMBUS),
|
||||
.driver_data = 0 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4),
|
||||
.driver_data = 0 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5),
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <asm/prom.h>
|
||||
|
@ -145,6 +145,7 @@ static struct i2c_algo_bit_data sav_i2c_bit_data = {
|
||||
|
||||
static struct i2c_adapter savage4_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_B_SAVAGE,
|
||||
.name = "I2C Savage4 adapter",
|
||||
.algo_data = &sav_i2c_bit_data,
|
||||
};
|
||||
|
@ -365,6 +365,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter sis5595_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_SIS5595,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
@ -457,6 +457,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter sis630_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_SIS630,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
@ -249,6 +249,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter sis96x_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_SIS96X,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
|
@ -86,6 +86,7 @@ static struct i2c_algo_bit_data bit_data = {
|
||||
|
||||
static struct i2c_adapter vt586b_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_B_VIA,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.name = "VIA i2c",
|
||||
.algo_data = &bit_data,
|
||||
|
@ -4,7 +4,7 @@
|
||||
Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>,
|
||||
Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
||||
Mark D. Studebaker <mdsxyz123@yahoo.com>
|
||||
Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
|
||||
Copyright (C) 2005 - 2007 Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
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
|
||||
@ -36,6 +36,7 @@
|
||||
VT8237R 0x3227 yes
|
||||
VT8237A 0x3337 yes
|
||||
VT8251 0x3287 yes
|
||||
CX700 0x8324 yes
|
||||
|
||||
Note: we assume there can only be one device, with one SMBus interface.
|
||||
*/
|
||||
@ -306,6 +307,7 @@ static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
static struct i2c_adapter vt596_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_SMBUS_VIA2,
|
||||
.class = I2C_CLASS_HWMON,
|
||||
.algo = &smbus_algorithm,
|
||||
};
|
||||
@ -383,6 +385,7 @@ found:
|
||||
dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
|
||||
|
||||
switch (pdev->device) {
|
||||
case PCI_DEVICE_ID_VIA_CX700:
|
||||
case PCI_DEVICE_ID_VIA_8251:
|
||||
case PCI_DEVICE_ID_VIA_8237:
|
||||
case PCI_DEVICE_ID_VIA_8237A:
|
||||
@ -442,6 +445,8 @@ static struct pci_device_id vt596_ids[] = {
|
||||
.driver_data = SMBBA1 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
|
||||
.driver_data = SMBBA3 },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700),
|
||||
.driver_data = SMBBA3 },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
@ -165,6 +165,7 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
|
||||
|
||||
static struct i2c_adapter voodoo3_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_B_VOO,
|
||||
.class = I2C_CLASS_TV_ANALOG,
|
||||
.name = "I2C Voodoo3/Banshee adapter",
|
||||
.algo_data = &voo_i2c_bit_data,
|
||||
@ -181,6 +182,7 @@ static struct i2c_algo_bit_data voo_ddc_bit_data = {
|
||||
|
||||
static struct i2c_adapter voodoo3_ddc_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_B_VOO,
|
||||
.class = I2C_CLASS_DDC,
|
||||
.name = "DDC Voodoo3/Banshee adapter",
|
||||
.algo_data = &voo_ddc_bit_data,
|
||||
|
@ -428,7 +428,7 @@ static __init int scx200_acb_probe(struct scx200_acb_iface *iface)
|
||||
}
|
||||
|
||||
static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
|
||||
int index)
|
||||
struct device *dev, int index)
|
||||
{
|
||||
struct scx200_acb_iface *iface;
|
||||
struct i2c_adapter *adapter;
|
||||
@ -446,6 +446,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
|
||||
adapter->id = I2C_HW_SMBUS_SCX200;
|
||||
adapter->algo = &scx200_acb_algorithm;
|
||||
adapter->class = I2C_CLASS_HWMON;
|
||||
adapter->dev.parent = dev;
|
||||
|
||||
mutex_init(&iface->mutex);
|
||||
|
||||
@ -486,7 +487,7 @@ static __init int scx200_create_pci(const char *text, struct pci_dev *pdev,
|
||||
struct scx200_acb_iface *iface;
|
||||
int rc;
|
||||
|
||||
iface = scx200_create_iface(text, 0);
|
||||
iface = scx200_create_iface(text, &pdev->dev, 0);
|
||||
|
||||
if (iface == NULL)
|
||||
return -ENOMEM;
|
||||
@ -524,7 +525,7 @@ static int __init scx200_create_isa(const char *text, unsigned long base,
|
||||
struct scx200_acb_iface *iface;
|
||||
int rc;
|
||||
|
||||
iface = scx200_create_iface(text, index);
|
||||
iface = scx200_create_iface(text, NULL, index);
|
||||
|
||||
if (iface == NULL)
|
||||
return -ENOMEM;
|
||||
|
@ -81,6 +81,7 @@ static struct i2c_algo_bit_data scx200_i2c_data = {
|
||||
|
||||
static struct i2c_adapter scx200_i2c_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.id = I2C_HW_B_SCX200,
|
||||
.algo_data = &scx200_i2c_data,
|
||||
.name = "NatSemi SCx200 I2C",
|
||||
};
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/completion.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
|
||||
@ -40,30 +41,15 @@ static LIST_HEAD(drivers);
|
||||
static DEFINE_MUTEX(core_lists);
|
||||
static DEFINE_IDR(i2c_adapter_idr);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* match always succeeds, as we want the probe() to tell if we really accept this match */
|
||||
static int i2c_device_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int i2c_bus_suspend(struct device * dev, pm_message_t state)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (dev->driver && dev->driver->suspend)
|
||||
rc = dev->driver->suspend(dev, state);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int i2c_bus_resume(struct device * dev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (dev->driver && dev->driver->resume)
|
||||
rc = dev->driver->resume(dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int i2c_device_probe(struct device *dev)
|
||||
{
|
||||
return -ENODEV;
|
||||
@ -74,15 +60,53 @@ static int i2c_device_remove(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i2c_device_shutdown(struct device *dev)
|
||||
{
|
||||
struct i2c_driver *driver;
|
||||
|
||||
if (!dev->driver)
|
||||
return;
|
||||
driver = to_i2c_driver(dev->driver);
|
||||
if (driver->shutdown)
|
||||
driver->shutdown(to_i2c_client(dev));
|
||||
}
|
||||
|
||||
static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
|
||||
{
|
||||
struct i2c_driver *driver;
|
||||
|
||||
if (!dev->driver)
|
||||
return 0;
|
||||
driver = to_i2c_driver(dev->driver);
|
||||
if (!driver->suspend)
|
||||
return 0;
|
||||
return driver->suspend(to_i2c_client(dev), mesg);
|
||||
}
|
||||
|
||||
static int i2c_device_resume(struct device * dev)
|
||||
{
|
||||
struct i2c_driver *driver;
|
||||
|
||||
if (!dev->driver)
|
||||
return 0;
|
||||
driver = to_i2c_driver(dev->driver);
|
||||
if (!driver->resume)
|
||||
return 0;
|
||||
return driver->resume(to_i2c_client(dev));
|
||||
}
|
||||
|
||||
struct bus_type i2c_bus_type = {
|
||||
.name = "i2c",
|
||||
.match = i2c_device_match,
|
||||
.probe = i2c_device_probe,
|
||||
.remove = i2c_device_remove,
|
||||
.suspend = i2c_bus_suspend,
|
||||
.resume = i2c_bus_resume,
|
||||
.name = "i2c",
|
||||
.match = i2c_device_match,
|
||||
.probe = i2c_device_probe,
|
||||
.remove = i2c_device_remove,
|
||||
.shutdown = i2c_device_shutdown,
|
||||
.suspend = i2c_device_suspend,
|
||||
.resume = i2c_device_resume,
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void i2c_adapter_dev_release(struct device *dev)
|
||||
{
|
||||
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
|
||||
@ -193,9 +217,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
|
||||
*/
|
||||
if (adap->dev.parent == NULL) {
|
||||
adap->dev.parent = &platform_bus;
|
||||
printk(KERN_WARNING "**WARNING** I2C adapter driver [%s] "
|
||||
"forgot to specify physical device; fix it!\n",
|
||||
adap->name);
|
||||
pr_debug("I2C adapter driver [%s] forgot to specify "
|
||||
"physical device\n", adap->name);
|
||||
}
|
||||
sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
|
||||
adap->dev.driver = &i2c_adapter_driver;
|
||||
|
@ -1434,6 +1434,7 @@ static int __devinit add_card(struct pci_dev *dev,
|
||||
i2c_adapter_data = bit_data;
|
||||
i2c_ad->algo_data = &i2c_adapter_data;
|
||||
i2c_adapter_data.data = lynx;
|
||||
i2c_ad->dev.parent = &dev->dev;
|
||||
|
||||
PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d",
|
||||
reg_read(lynx, SERIAL_EEPROM_CONTROL));
|
||||
|
@ -190,6 +190,7 @@ int flexcop_i2c_init(struct flexcop_device *fc)
|
||||
fc->i2c_adap.class = I2C_CLASS_TV_DIGITAL;
|
||||
fc->i2c_adap.algo = &flexcop_algo;
|
||||
fc->i2c_adap.algo_data = NULL;
|
||||
fc->i2c_adap.dev.parent = fc->dev;
|
||||
|
||||
if ((ret = i2c_add_adapter(&fc->i2c_adap)) < 0)
|
||||
return ret;
|
||||
|
@ -27,6 +27,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
|
||||
#endif
|
||||
d->i2c_adap.algo = d->props.i2c_algo;
|
||||
d->i2c_adap.algo_data = NULL;
|
||||
d->i2c_adap.dev.parent = &d->udev->dev;
|
||||
|
||||
i2c_set_adapdata(&d->i2c_adap, d);
|
||||
|
||||
|
@ -1690,6 +1690,7 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i
|
||||
#endif
|
||||
ttusb->i2c_adap.algo = &ttusb_dec_algo;
|
||||
ttusb->i2c_adap.algo_data = NULL;
|
||||
ttusb->i2c_adap.dev.parent = &udev->dev;
|
||||
|
||||
result = i2c_add_adapter(&ttusb->i2c_adap);
|
||||
if (result) {
|
||||
|
@ -549,6 +549,7 @@ static int cafe_smbus_setup(struct cafe_camera *cam)
|
||||
adap->client_unregister = cafe_smbus_detach;
|
||||
adap->algo = &cafe_smbus_algo;
|
||||
strcpy(adap->name, "cafe_ccic");
|
||||
adap->dev.parent = &cam->pdev->dev;
|
||||
i2c_set_adapdata(adap, cam);
|
||||
ret = i2c_add_adapter(adap);
|
||||
if (ret)
|
||||
|
@ -977,6 +977,7 @@ void pvr2_i2c_core_init(struct pvr2_hdw *hdw)
|
||||
memcpy(&hdw->i2c_adap,&pvr2_i2c_adap_template,sizeof(hdw->i2c_adap));
|
||||
memcpy(&hdw->i2c_algo,&pvr2_i2c_algo_template,sizeof(hdw->i2c_algo));
|
||||
strlcpy(hdw->i2c_adap.name,hdw->name,sizeof(hdw->i2c_adap.name));
|
||||
hdw->i2c_adap.dev.parent = &hdw->usb_dev->dev;
|
||||
hdw->i2c_adap.algo = &hdw->i2c_algo;
|
||||
hdw->i2c_adap.algo_data = hdw;
|
||||
hdw->i2c_pend_mask = 0;
|
||||
|
@ -258,6 +258,7 @@ int usbvision_init_i2c(struct usb_usbvision *usbvision)
|
||||
sprintf(usbvision->i2c_adap.name + strlen(usbvision->i2c_adap.name),
|
||||
" #%d", usbvision->vdev->minor & 0x1f);
|
||||
PDEBUG(DBG_I2C,"Adaptername: %s", usbvision->i2c_adap.name);
|
||||
usbvision->i2c_adap.dev.parent = &usbvision->dev->dev;
|
||||
|
||||
i2c_set_adapdata(&usbvision->i2c_adap, usbvision);
|
||||
i2c_set_clientdata(&usbvision->i2c_client, usbvision);
|
||||
|
@ -1573,6 +1573,7 @@ static int w9968cf_i2c_init(struct w9968cf_device* cam)
|
||||
|
||||
memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter));
|
||||
strcpy(cam->i2c_adapter.name, "w9968cf");
|
||||
cam->i2c_adapter.dev.parent = &cam->usbdev->dev;
|
||||
i2c_set_adapdata(&cam->i2c_adapter, cam);
|
||||
|
||||
DBG(6, "Registering I2C adapter with kernel...")
|
||||
|
@ -843,6 +843,7 @@ zoran_register_i2c (struct zoran *zr)
|
||||
sizeof(I2C_NAME(&zr->i2c_adapter)) - 1);
|
||||
i2c_set_adapdata(&zr->i2c_adapter, zr);
|
||||
zr->i2c_adapter.algo_data = &zr->i2c_algo;
|
||||
zr->i2c_adapter.dev.parent = &zr->pci_dev->dev;
|
||||
return i2c_bit_add_bus(&zr->i2c_adapter);
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ static int ds1672_probe(struct i2c_adapter *adapter, int address, int kind)
|
||||
struct i2c_client *client;
|
||||
struct rtc_device *rtc;
|
||||
|
||||
dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
|
||||
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
|
||||
err = -ENODEV;
|
||||
|
@ -279,7 +279,7 @@ static int pcf8563_probe(struct i2c_adapter *adapter, int address, int kind)
|
||||
|
||||
int err = 0;
|
||||
|
||||
dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
|
||||
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
|
||||
err = -ENODEV;
|
||||
|
@ -499,7 +499,7 @@ static int rs5c372_probe(struct i2c_adapter *adapter, int address, int kind)
|
||||
struct rs5c372 *rs5c372;
|
||||
struct rtc_time tm;
|
||||
|
||||
dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
|
||||
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
|
||||
err = -ENODEV;
|
||||
|
@ -506,7 +506,7 @@ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
|
||||
struct i2c_client *client;
|
||||
struct rtc_device *rtc;
|
||||
|
||||
dev_dbg(adapter->class_dev.dev, "%s\n", __FUNCTION__);
|
||||
dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
|
||||
err = -ENODEV;
|
||||
|
@ -115,6 +115,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
|
||||
minfo->fbcon.node);
|
||||
i2c_set_adapdata(&b->adapter, b);
|
||||
b->adapter.algo_data = &b->bac;
|
||||
b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev;
|
||||
b->bac = matrox_i2c_algo_template;
|
||||
b->bac.data = b;
|
||||
err = i2c_bit_add_bus(&b->adapter);
|
||||
|
@ -232,7 +232,6 @@
|
||||
#define I2C_HW_SMBUS_PIIX4 0x040000
|
||||
#define I2C_HW_SMBUS_ALI15X3 0x040001
|
||||
#define I2C_HW_SMBUS_VIA2 0x040002
|
||||
#define I2C_HW_SMBUS_VOODOO3 0x040003
|
||||
#define I2C_HW_SMBUS_I801 0x040004
|
||||
#define I2C_HW_SMBUS_AMD756 0x040005
|
||||
#define I2C_HW_SMBUS_SIS5595 0x040006
|
||||
@ -248,13 +247,11 @@
|
||||
#define I2C_HW_SMBUS_OV519 0x040010 /* OV519 USB 1.1 webcam IC */
|
||||
#define I2C_HW_SMBUS_OVFX2 0x040011 /* Cypress/OmniVision FX2 webcam */
|
||||
#define I2C_HW_SMBUS_CAFE 0x040012 /* Marvell 88ALP01 "CAFE" cam */
|
||||
#define I2C_HW_SMBUS_ALI1563 0x040013
|
||||
|
||||
/* --- ISA pseudo-adapter */
|
||||
#define I2C_HW_ISA 0x050000
|
||||
|
||||
/* --- IPMI pseudo-adapter */
|
||||
#define I2C_HW_IPMI 0x0b0000
|
||||
|
||||
/* --- IPMB adapter */
|
||||
#define I2C_HW_IPMB 0x0c0000
|
||||
|
||||
|
@ -125,7 +125,12 @@ struct i2c_driver {
|
||||
* it must be freed here.
|
||||
*/
|
||||
int (*detach_client)(struct i2c_client *);
|
||||
|
||||
|
||||
/* driver model interfaces that don't relate to enumeration */
|
||||
void (*shutdown)(struct i2c_client *);
|
||||
int (*suspend)(struct i2c_client *, pm_message_t mesg);
|
||||
int (*resume)(struct i2c_client *);
|
||||
|
||||
/* a ioctl like command that can be used to perform specific functions
|
||||
* with the device.
|
||||
*/
|
||||
|
@ -369,6 +369,7 @@
|
||||
#define PCI_DEVICE_ID_ATI_IXP400_SATA2 0x437a
|
||||
#define PCI_DEVICE_ID_ATI_IXP600_SATA 0x4380
|
||||
#define PCI_DEVICE_ID_ATI_IXP600_SRAID 0x4381
|
||||
#define PCI_DEVICE_ID_ATI_IXP600_SMBUS 0x4385
|
||||
#define PCI_DEVICE_ID_ATI_IXP600_IDE 0x438c
|
||||
|
||||
#define PCI_VENDOR_ID_VLSI 0x1004
|
||||
|
Loading…
Reference in New Issue
Block a user