forked from Minki/linux
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-core: Some style cleanups i2c-piix4: Add support for the Broadcom HT1100 chipset i2c-piix4: Add support to SB800 SMBus changes i2c-pca-platform: Use defaults if no platform_data given i2c-algo-pca: Use timeout for checking the state machine i2c-algo-pca: Rework waiting for a free bus i2c-algo-pca: Add PCA9665 support i2c: Adapt debug macros for KERN_* constants i2c-davinci: Fix timeout handling i2c: Adapter timeout is in jiffies i2c: Set a default timeout value for all adapters i2c: Add missing KERN_* constants to printks i2c-algo-pcf: Handle timeout correctly i2c-algo-pcf: Style cleanups eeprom/at24: Remove EXPERIMENTAL i2c-nforce2: Add support for MCP67, MCP73, MCP78S and MCP79 i2c: Clarify which clients are auto-removed i2c: Let checkpatch shout on users of the legacy model i2c: Document the different ways to instantiate i2c devices
This commit is contained in:
commit
07d43ba986
@ -340,7 +340,8 @@ Who: Krzysztof Piotr Oledzki <ole@ans.pl>
|
||||
---------------------------
|
||||
|
||||
What: i2c_attach_client(), i2c_detach_client(), i2c_driver->detach_client()
|
||||
When: 2.6.29 (ideally) or 2.6.30 (more likely)
|
||||
When: 2.6.30
|
||||
Check: i2c_attach_client i2c_detach_client
|
||||
Why: Deprecated by the new (standard) device driver binding model. Use
|
||||
i2c_driver->probe() and ->remove() instead.
|
||||
Who: Jean Delvare <khali@linux-fr.org>
|
||||
|
@ -7,10 +7,14 @@ Supported adapters:
|
||||
* nForce3 250Gb MCP 10de:00E4
|
||||
* nForce4 MCP 10de:0052
|
||||
* nForce4 MCP-04 10de:0034
|
||||
* nForce4 MCP51 10de:0264
|
||||
* nForce4 MCP55 10de:0368
|
||||
* nForce4 MCP61 10de:03EB
|
||||
* nForce4 MCP65 10de:0446
|
||||
* nForce MCP51 10de:0264
|
||||
* nForce MCP55 10de:0368
|
||||
* nForce MCP61 10de:03EB
|
||||
* nForce MCP65 10de:0446
|
||||
* nForce MCP67 10de:0542
|
||||
* nForce MCP73 10de:07D8
|
||||
* nForce MCP78S 10de:0752
|
||||
* nForce MCP79 10de:0AA2
|
||||
|
||||
Datasheet: not publicly available, but seems to be similar to the
|
||||
AMD-8111 SMBus 2.0 adapter.
|
||||
|
@ -4,7 +4,7 @@ Supported adapters:
|
||||
* Intel 82371AB PIIX4 and PIIX4E
|
||||
* Intel 82443MX (440MX)
|
||||
Datasheet: Publicly available at the Intel website
|
||||
* ServerWorks OSB4, CSB5, CSB6 and HT-1000 southbridges
|
||||
* ServerWorks OSB4, CSB5, CSB6, HT-1000 and HT-1100 southbridges
|
||||
Datasheet: Only available via NDA from ServerWorks
|
||||
* ATI IXP200, IXP300, IXP400, SB600, SB700 and SB800 southbridges
|
||||
Datasheet: Not publicly available
|
||||
|
167
Documentation/i2c/instantiating-devices
Normal file
167
Documentation/i2c/instantiating-devices
Normal file
@ -0,0 +1,167 @@
|
||||
How to instantiate I2C devices
|
||||
==============================
|
||||
|
||||
Unlike PCI or USB devices, I2C devices are not enumerated at the hardware
|
||||
level. Instead, the software must know which devices are connected on each
|
||||
I2C bus segment, and what address these devices are using. For this
|
||||
reason, the kernel code must instantiate I2C devices explicitly. There are
|
||||
several ways to achieve this, depending on the context and requirements.
|
||||
|
||||
|
||||
Method 1: Declare the I2C devices by bus number
|
||||
-----------------------------------------------
|
||||
|
||||
This method is appropriate when the I2C bus is a system bus as is the case
|
||||
for many embedded systems. On such systems, each I2C bus has a number
|
||||
which is known in advance. It is thus possible to pre-declare the I2C
|
||||
devices which live on this bus. This is done with an array of struct
|
||||
i2c_board_info which is registered by calling i2c_register_board_info().
|
||||
|
||||
Example (from omap2 h4):
|
||||
|
||||
static struct i2c_board_info __initdata h4_i2c_board_info[] = {
|
||||
{
|
||||
I2C_BOARD_INFO("isp1301_omap", 0x2d),
|
||||
.irq = OMAP_GPIO_IRQ(125),
|
||||
},
|
||||
{ /* EEPROM on mainboard */
|
||||
I2C_BOARD_INFO("24c01", 0x52),
|
||||
.platform_data = &m24c01,
|
||||
},
|
||||
{ /* EEPROM on cpu card */
|
||||
I2C_BOARD_INFO("24c01", 0x57),
|
||||
.platform_data = &m24c01,
|
||||
},
|
||||
};
|
||||
|
||||
static void __init omap_h4_init(void)
|
||||
{
|
||||
(...)
|
||||
i2c_register_board_info(1, h4_i2c_board_info,
|
||||
ARRAY_SIZE(h4_i2c_board_info));
|
||||
(...)
|
||||
}
|
||||
|
||||
The above code declares 3 devices on I2C bus 1, including their respective
|
||||
addresses and custom data needed by their drivers. When the I2C bus in
|
||||
question is registered, the I2C devices will be instantiated automatically
|
||||
by i2c-core.
|
||||
|
||||
The devices will be automatically unbound and destroyed when the I2C bus
|
||||
they sit on goes away (if ever.)
|
||||
|
||||
|
||||
Method 2: Instantiate the devices explicitly
|
||||
--------------------------------------------
|
||||
|
||||
This method is appropriate when a larger device uses an I2C bus for
|
||||
internal communication. A typical case is TV adapters. These can have a
|
||||
tuner, a video decoder, an audio decoder, etc. usually connected to the
|
||||
main chip by the means of an I2C bus. You won't know the number of the I2C
|
||||
bus in advance, so the method 1 described above can't be used. Instead,
|
||||
you can instantiate your I2C devices explicitly. This is done by filling
|
||||
a struct i2c_board_info and calling i2c_new_device().
|
||||
|
||||
Example (from the sfe4001 network driver):
|
||||
|
||||
static struct i2c_board_info sfe4001_hwmon_info = {
|
||||
I2C_BOARD_INFO("max6647", 0x4e),
|
||||
};
|
||||
|
||||
int sfe4001_init(struct efx_nic *efx)
|
||||
{
|
||||
(...)
|
||||
efx->board_info.hwmon_client =
|
||||
i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);
|
||||
|
||||
(...)
|
||||
}
|
||||
|
||||
The above code instantiates 1 I2C device on the I2C bus which is on the
|
||||
network adapter in question.
|
||||
|
||||
A variant of this is when you don't know for sure if an I2C device is
|
||||
present or not (for example for an optional feature which is not present
|
||||
on cheap variants of a board but you have no way to tell them apart), or
|
||||
it may have different addresses from one board to the next (manufacturer
|
||||
changing its design without notice). In this case, you can call
|
||||
i2c_new_probed_device() instead of i2c_new_device().
|
||||
|
||||
Example (from the pnx4008 OHCI driver):
|
||||
|
||||
static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
|
||||
|
||||
static int __devinit usb_hcd_pnx4008_probe(struct platform_device *pdev)
|
||||
{
|
||||
(...)
|
||||
struct i2c_adapter *i2c_adap;
|
||||
struct i2c_board_info i2c_info;
|
||||
|
||||
(...)
|
||||
i2c_adap = i2c_get_adapter(2);
|
||||
memset(&i2c_info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
|
||||
isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
|
||||
normal_i2c);
|
||||
i2c_put_adapter(i2c_adap);
|
||||
(...)
|
||||
}
|
||||
|
||||
The above code instantiates up to 1 I2C device on the I2C bus which is on
|
||||
the OHCI adapter in question. It first tries at address 0x2c, if nothing
|
||||
is found there it tries address 0x2d, and if still nothing is found, it
|
||||
simply gives up.
|
||||
|
||||
The driver which instantiated the I2C device is responsible for destroying
|
||||
it on cleanup. This is done by calling i2c_unregister_device() on the
|
||||
pointer that was earlier returned by i2c_new_device() or
|
||||
i2c_new_probed_device().
|
||||
|
||||
|
||||
Method 3: Probe an I2C bus for certain devices
|
||||
----------------------------------------------
|
||||
|
||||
Sometimes you do not have enough information about an I2C device, not even
|
||||
to call i2c_new_probed_device(). The typical case is hardware monitoring
|
||||
chips on PC mainboards. There are several dozen models, which can live
|
||||
at 25 different addresses. Given the huge number of mainboards out there,
|
||||
it is next to impossible to build an exhaustive list of the hardware
|
||||
monitoring chips being used. Fortunately, most of these chips have
|
||||
manufacturer and device ID registers, so they can be identified by
|
||||
probing.
|
||||
|
||||
In that case, I2C devices are neither declared nor instantiated
|
||||
explicitly. Instead, i2c-core will probe for such devices as soon as their
|
||||
drivers are loaded, and if any is found, an I2C device will be
|
||||
instantiated automatically. In order to prevent any misbehavior of this
|
||||
mechanism, the following restrictions apply:
|
||||
* The I2C device driver must implement the detect() method, which
|
||||
identifies a supported device by reading from arbitrary registers.
|
||||
* Only buses which are likely to have a supported device and agree to be
|
||||
probed, will be probed. For example this avoids probing for hardware
|
||||
monitoring chips on a TV adapter.
|
||||
|
||||
Example:
|
||||
See lm90_driver and lm90_detect() in drivers/hwmon/lm90.c
|
||||
|
||||
I2C devices instantiated as a result of such a successful probe will be
|
||||
destroyed automatically when the driver which detected them is removed,
|
||||
or when the underlying I2C bus is itself destroyed, whichever happens
|
||||
first.
|
||||
|
||||
Those of you familiar with the i2c subsystem of 2.4 kernels and early 2.6
|
||||
kernels will find out that this method 3 is essentially similar to what
|
||||
was done there. Two significant differences are:
|
||||
* Probing is only one way to instantiate I2C devices now, while it was the
|
||||
only way back then. Where possible, methods 1 and 2 should be preferred.
|
||||
Method 3 should only be used when there is no other way, as it can have
|
||||
undesirable side effects.
|
||||
* I2C buses must now explicitly say which I2C driver classes can probe
|
||||
them (by the means of the class bitfield), while all I2C buses were
|
||||
probed by default back then. The default is an empty class which means
|
||||
that no probing happens. The purpose of the class bitfield is to limit
|
||||
the aforementioned undesirable side effects.
|
||||
|
||||
Once again, method 3 should be avoided wherever possible. Explicit device
|
||||
instantiation (methods 1 and 2) is much preferred for it is safer and
|
||||
faster.
|
@ -207,15 +207,26 @@ You simply have to define a detect callback which will attempt to
|
||||
identify supported devices (returning 0 for supported ones and -ENODEV
|
||||
for unsupported ones), a list of addresses to probe, and a device type
|
||||
(or class) so that only I2C buses which may have that type of device
|
||||
connected (and not otherwise enumerated) will be probed. The i2c
|
||||
core will then call you back as needed and will instantiate a device
|
||||
for you for every successful detection.
|
||||
connected (and not otherwise enumerated) will be probed. For example,
|
||||
a driver for a hardware monitoring chip for which auto-detection is
|
||||
needed would set its class to I2C_CLASS_HWMON, and only I2C adapters
|
||||
with a class including I2C_CLASS_HWMON would be probed by this driver.
|
||||
Note that the absence of matching classes does not prevent the use of
|
||||
a device of that type on the given I2C adapter. All it prevents is
|
||||
auto-detection; explicit instantiation of devices is still possible.
|
||||
|
||||
Note that this mechanism is purely optional and not suitable for all
|
||||
devices. You need some reliable way to identify the supported devices
|
||||
(typically using device-specific, dedicated identification registers),
|
||||
otherwise misdetections are likely to occur and things can get wrong
|
||||
quickly.
|
||||
quickly. Keep in mind that the I2C protocol doesn't include any
|
||||
standard way to detect the presence of a chip at a given address, let
|
||||
alone a standard way to identify devices. Even worse is the lack of
|
||||
semantics associated to bus transfers, which means that the same
|
||||
transfer can be seen as a read operation by a chip and as a write
|
||||
operation by another chip. For these reasons, explicit device
|
||||
instantiation should always be preferred to auto-detection where
|
||||
possible.
|
||||
|
||||
|
||||
Device Deletion
|
||||
|
@ -229,7 +229,7 @@ static struct resource i2c_resources[] = {
|
||||
static struct i2c_pca9564_pf_platform_data i2c_platform_data = {
|
||||
.gpio = 0,
|
||||
.i2c_clock_speed = I2C_PCA_CON_330kHz,
|
||||
.timeout = 100,
|
||||
.timeout = HZ,
|
||||
};
|
||||
|
||||
static struct platform_device i2c_device = {
|
||||
|
@ -604,9 +604,7 @@ static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
adap->algo = &i2c_bit_algo;
|
||||
|
||||
adap->timeout = 100; /* default values, should */
|
||||
adap->retries = 3; /* be replaced by defines */
|
||||
adap->retries = 3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,14 +22,18 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-pca.h>
|
||||
|
||||
#define DEB1(fmt, args...) do { if (i2c_debug>=1) printk(fmt, ## args); } while(0)
|
||||
#define DEB2(fmt, args...) do { if (i2c_debug>=2) printk(fmt, ## args); } while(0)
|
||||
#define DEB3(fmt, args...) do { if (i2c_debug>=3) printk(fmt, ## args); } while(0)
|
||||
#define DEB1(fmt, args...) do { if (i2c_debug >= 1) \
|
||||
printk(KERN_DEBUG fmt, ## args); } while (0)
|
||||
#define DEB2(fmt, args...) do { if (i2c_debug >= 2) \
|
||||
printk(KERN_DEBUG fmt, ## args); } while (0)
|
||||
#define DEB3(fmt, args...) do { if (i2c_debug >= 3) \
|
||||
printk(KERN_DEBUG fmt, ## args); } while (0)
|
||||
|
||||
static int i2c_debug;
|
||||
|
||||
@ -43,19 +47,27 @@ static int i2c_debug;
|
||||
#define pca_wait(adap) adap->wait_for_completion(adap->data)
|
||||
#define pca_reset(adap) adap->reset_chip(adap->data)
|
||||
|
||||
static void pca9665_reset(void *pd)
|
||||
{
|
||||
struct i2c_algo_pca_data *adap = pd;
|
||||
pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET);
|
||||
pca_outw(adap, I2C_PCA_IND, 0xA5);
|
||||
pca_outw(adap, I2C_PCA_IND, 0x5A);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate a start condition on the i2c bus.
|
||||
*
|
||||
* returns after the start condition has occurred
|
||||
*/
|
||||
static void pca_start(struct i2c_algo_pca_data *adap)
|
||||
static int pca_start(struct i2c_algo_pca_data *adap)
|
||||
{
|
||||
int sta = pca_get_con(adap);
|
||||
DEB2("=== START\n");
|
||||
sta |= I2C_PCA_CON_STA;
|
||||
sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
|
||||
pca_set_con(adap, sta);
|
||||
pca_wait(adap);
|
||||
return pca_wait(adap);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -63,14 +75,14 @@ static void pca_start(struct i2c_algo_pca_data *adap)
|
||||
*
|
||||
* return after the repeated start condition has occurred
|
||||
*/
|
||||
static void pca_repeated_start(struct i2c_algo_pca_data *adap)
|
||||
static int pca_repeated_start(struct i2c_algo_pca_data *adap)
|
||||
{
|
||||
int sta = pca_get_con(adap);
|
||||
DEB2("=== REPEATED START\n");
|
||||
sta |= I2C_PCA_CON_STA;
|
||||
sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI);
|
||||
pca_set_con(adap, sta);
|
||||
pca_wait(adap);
|
||||
return pca_wait(adap);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -96,7 +108,7 @@ static void pca_stop(struct i2c_algo_pca_data *adap)
|
||||
*
|
||||
* returns after the address has been sent
|
||||
*/
|
||||
static void pca_address(struct i2c_algo_pca_data *adap,
|
||||
static int pca_address(struct i2c_algo_pca_data *adap,
|
||||
struct i2c_msg *msg)
|
||||
{
|
||||
int sta = pca_get_con(adap);
|
||||
@ -113,7 +125,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
|
||||
sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
|
||||
pca_set_con(adap, sta);
|
||||
|
||||
pca_wait(adap);
|
||||
return pca_wait(adap);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -121,7 +133,7 @@ static void pca_address(struct i2c_algo_pca_data *adap,
|
||||
*
|
||||
* Returns after the byte has been transmitted
|
||||
*/
|
||||
static void pca_tx_byte(struct i2c_algo_pca_data *adap,
|
||||
static int pca_tx_byte(struct i2c_algo_pca_data *adap,
|
||||
__u8 b)
|
||||
{
|
||||
int sta = pca_get_con(adap);
|
||||
@ -131,7 +143,7 @@ static void pca_tx_byte(struct i2c_algo_pca_data *adap,
|
||||
sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI);
|
||||
pca_set_con(adap, sta);
|
||||
|
||||
pca_wait(adap);
|
||||
return pca_wait(adap);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -151,7 +163,7 @@ static void pca_rx_byte(struct i2c_algo_pca_data *adap,
|
||||
*
|
||||
* Returns after next byte has arrived.
|
||||
*/
|
||||
static void pca_rx_ack(struct i2c_algo_pca_data *adap,
|
||||
static int pca_rx_ack(struct i2c_algo_pca_data *adap,
|
||||
int ack)
|
||||
{
|
||||
int sta = pca_get_con(adap);
|
||||
@ -162,7 +174,7 @@ static void pca_rx_ack(struct i2c_algo_pca_data *adap,
|
||||
sta |= I2C_PCA_CON_AA;
|
||||
|
||||
pca_set_con(adap, sta);
|
||||
pca_wait(adap);
|
||||
return pca_wait(adap);
|
||||
}
|
||||
|
||||
static int pca_xfer(struct i2c_adapter *i2c_adap,
|
||||
@ -175,14 +187,17 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
|
||||
int numbytes = 0;
|
||||
int state;
|
||||
int ret;
|
||||
int timeout = i2c_adap->timeout;
|
||||
int completed = 1;
|
||||
unsigned long timeout = jiffies + i2c_adap->timeout;
|
||||
|
||||
while ((state = pca_status(adap)) != 0xf8 && timeout--) {
|
||||
msleep(10);
|
||||
}
|
||||
if (state != 0xf8) {
|
||||
dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
|
||||
return -EAGAIN;
|
||||
while (pca_status(adap) != 0xf8) {
|
||||
if (time_before(jiffies, timeout)) {
|
||||
msleep(10);
|
||||
} else {
|
||||
dev_dbg(&i2c_adap->dev, "bus is not idle. status is "
|
||||
"%#04x\n", state);
|
||||
return -EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
DEB1("{{{ XFER %d messages\n", num);
|
||||
@ -218,18 +233,19 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
|
||||
|
||||
switch (state) {
|
||||
case 0xf8: /* On reset or stop the bus is idle */
|
||||
pca_start(adap);
|
||||
completed = pca_start(adap);
|
||||
break;
|
||||
|
||||
case 0x08: /* A START condition has been transmitted */
|
||||
case 0x10: /* A repeated start condition has been transmitted */
|
||||
pca_address(adap, msg);
|
||||
completed = pca_address(adap, msg);
|
||||
break;
|
||||
|
||||
case 0x18: /* SLA+W has been transmitted; ACK has been received */
|
||||
case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */
|
||||
if (numbytes < msg->len) {
|
||||
pca_tx_byte(adap, msg->buf[numbytes]);
|
||||
completed = pca_tx_byte(adap,
|
||||
msg->buf[numbytes]);
|
||||
numbytes++;
|
||||
break;
|
||||
}
|
||||
@ -237,7 +253,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
|
||||
if (curmsg == num)
|
||||
pca_stop(adap);
|
||||
else
|
||||
pca_repeated_start(adap);
|
||||
completed = pca_repeated_start(adap);
|
||||
break;
|
||||
|
||||
case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
|
||||
@ -246,21 +262,22 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
|
||||
goto out;
|
||||
|
||||
case 0x40: /* SLA+R has been transmitted; ACK has been received */
|
||||
pca_rx_ack(adap, msg->len > 1);
|
||||
completed = pca_rx_ack(adap, msg->len > 1);
|
||||
break;
|
||||
|
||||
case 0x50: /* Data bytes has been received; ACK has been returned */
|
||||
if (numbytes < msg->len) {
|
||||
pca_rx_byte(adap, &msg->buf[numbytes], 1);
|
||||
numbytes++;
|
||||
pca_rx_ack(adap, numbytes < msg->len - 1);
|
||||
completed = pca_rx_ack(adap,
|
||||
numbytes < msg->len - 1);
|
||||
break;
|
||||
}
|
||||
curmsg++; numbytes = 0;
|
||||
if (curmsg == num)
|
||||
pca_stop(adap);
|
||||
else
|
||||
pca_repeated_start(adap);
|
||||
completed = pca_repeated_start(adap);
|
||||
break;
|
||||
|
||||
case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
|
||||
@ -283,7 +300,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
|
||||
if (curmsg == num)
|
||||
pca_stop(adap);
|
||||
else
|
||||
pca_repeated_start(adap);
|
||||
completed = pca_repeated_start(adap);
|
||||
} else {
|
||||
DEB2("NOT ACK sent after data byte received. "
|
||||
"Not final byte. numbytes %d. len %d\n",
|
||||
@ -309,11 +326,13 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
|
||||
break;
|
||||
}
|
||||
|
||||
if (!completed)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = curmsg;
|
||||
out:
|
||||
DEB1(KERN_CRIT "}}} transfered %d/%d messages. "
|
||||
DEB1("}}} transfered %d/%d messages. "
|
||||
"status is %#04x. control is %#04x\n",
|
||||
curmsg, num, pca_status(adap),
|
||||
pca_get_con(adap));
|
||||
@ -330,26 +349,171 @@ static const struct i2c_algorithm pca_algo = {
|
||||
.functionality = pca_func,
|
||||
};
|
||||
|
||||
static unsigned int pca_probe_chip(struct i2c_adapter *adap)
|
||||
{
|
||||
struct i2c_algo_pca_data *pca_data = adap->algo_data;
|
||||
/* The trick here is to check if there is an indirect register
|
||||
* available. If there is one, we will read the value we first
|
||||
* wrote on I2C_PCA_IADR. Otherwise, we will read the last value
|
||||
* we wrote on I2C_PCA_ADR
|
||||
*/
|
||||
pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR);
|
||||
pca_outw(pca_data, I2C_PCA_IND, 0xAA);
|
||||
pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ITO);
|
||||
pca_outw(pca_data, I2C_PCA_IND, 0x00);
|
||||
pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR);
|
||||
if (pca_inw(pca_data, I2C_PCA_IND) == 0xAA) {
|
||||
printk(KERN_INFO "%s: PCA9665 detected.\n", adap->name);
|
||||
return I2C_PCA_CHIP_9665;
|
||||
} else {
|
||||
printk(KERN_INFO "%s: PCA9564 detected.\n", adap->name);
|
||||
return I2C_PCA_CHIP_9564;
|
||||
}
|
||||
}
|
||||
|
||||
static int pca_init(struct i2c_adapter *adap)
|
||||
{
|
||||
static int freqs[] = {330,288,217,146,88,59,44,36};
|
||||
int clock;
|
||||
struct i2c_algo_pca_data *pca_data = adap->algo_data;
|
||||
|
||||
if (pca_data->i2c_clock > 7) {
|
||||
printk(KERN_WARNING "%s: Invalid I2C clock speed selected. Trying default.\n",
|
||||
adap->name);
|
||||
pca_data->i2c_clock = I2C_PCA_CON_59kHz;
|
||||
}
|
||||
|
||||
adap->algo = &pca_algo;
|
||||
|
||||
pca_reset(pca_data);
|
||||
if (pca_probe_chip(adap) == I2C_PCA_CHIP_9564) {
|
||||
static int freqs[] = {330, 288, 217, 146, 88, 59, 44, 36};
|
||||
int clock;
|
||||
|
||||
clock = pca_clock(pca_data);
|
||||
DEB1(KERN_INFO "%s: Clock frequency is %dkHz\n", adap->name, freqs[clock]);
|
||||
if (pca_data->i2c_clock > 7) {
|
||||
switch (pca_data->i2c_clock) {
|
||||
case 330000:
|
||||
pca_data->i2c_clock = I2C_PCA_CON_330kHz;
|
||||
break;
|
||||
case 288000:
|
||||
pca_data->i2c_clock = I2C_PCA_CON_288kHz;
|
||||
break;
|
||||
case 217000:
|
||||
pca_data->i2c_clock = I2C_PCA_CON_217kHz;
|
||||
break;
|
||||
case 146000:
|
||||
pca_data->i2c_clock = I2C_PCA_CON_146kHz;
|
||||
break;
|
||||
case 88000:
|
||||
pca_data->i2c_clock = I2C_PCA_CON_88kHz;
|
||||
break;
|
||||
case 59000:
|
||||
pca_data->i2c_clock = I2C_PCA_CON_59kHz;
|
||||
break;
|
||||
case 44000:
|
||||
pca_data->i2c_clock = I2C_PCA_CON_44kHz;
|
||||
break;
|
||||
case 36000:
|
||||
pca_data->i2c_clock = I2C_PCA_CON_36kHz;
|
||||
break;
|
||||
default:
|
||||
printk(KERN_WARNING
|
||||
"%s: Invalid I2C clock speed selected."
|
||||
" Using default 59kHz.\n", adap->name);
|
||||
pca_data->i2c_clock = I2C_PCA_CON_59kHz;
|
||||
}
|
||||
} else {
|
||||
printk(KERN_WARNING "%s: "
|
||||
"Choosing the clock frequency based on "
|
||||
"index is deprecated."
|
||||
" Use the nominal frequency.\n", adap->name);
|
||||
}
|
||||
|
||||
pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
|
||||
pca_reset(pca_data);
|
||||
|
||||
clock = pca_clock(pca_data);
|
||||
printk(KERN_INFO "%s: Clock frequency is %dkHz\n",
|
||||
adap->name, freqs[clock]);
|
||||
|
||||
pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock);
|
||||
} else {
|
||||
int clock;
|
||||
int mode;
|
||||
int tlow, thi;
|
||||
/* Values can be found on PCA9665 datasheet section 7.3.2.6 */
|
||||
int min_tlow, min_thi;
|
||||
/* These values are the maximum raise and fall values allowed
|
||||
* by the I2C operation mode (Standard, Fast or Fast+)
|
||||
* They are used (added) below to calculate the clock dividers
|
||||
* of PCA9665. Note that they are slightly different of the
|
||||
* real maximum, to allow the change on mode exactly on the
|
||||
* maximum clock rate for each mode
|
||||
*/
|
||||
int raise_fall_time;
|
||||
|
||||
struct i2c_algo_pca_data *pca_data = adap->algo_data;
|
||||
|
||||
/* Ignore the reset function from the module,
|
||||
* we can use the parallel bus reset
|
||||
*/
|
||||
pca_data->reset_chip = pca9665_reset;
|
||||
|
||||
if (pca_data->i2c_clock > 1265800) {
|
||||
printk(KERN_WARNING "%s: I2C clock speed too high."
|
||||
" Using 1265.8kHz.\n", adap->name);
|
||||
pca_data->i2c_clock = 1265800;
|
||||
}
|
||||
|
||||
if (pca_data->i2c_clock < 60300) {
|
||||
printk(KERN_WARNING "%s: I2C clock speed too low."
|
||||
" Using 60.3kHz.\n", adap->name);
|
||||
pca_data->i2c_clock = 60300;
|
||||
}
|
||||
|
||||
/* To avoid integer overflow, use clock/100 for calculations */
|
||||
clock = pca_clock(pca_data) / 100;
|
||||
|
||||
if (pca_data->i2c_clock > 10000) {
|
||||
mode = I2C_PCA_MODE_TURBO;
|
||||
min_tlow = 14;
|
||||
min_thi = 5;
|
||||
raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */
|
||||
} else if (pca_data->i2c_clock > 4000) {
|
||||
mode = I2C_PCA_MODE_FASTP;
|
||||
min_tlow = 17;
|
||||
min_thi = 9;
|
||||
raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */
|
||||
} else if (pca_data->i2c_clock > 1000) {
|
||||
mode = I2C_PCA_MODE_FAST;
|
||||
min_tlow = 44;
|
||||
min_thi = 20;
|
||||
raise_fall_time = 58; /* Raise 29e-8s, Fall 29e-8s */
|
||||
} else {
|
||||
mode = I2C_PCA_MODE_STD;
|
||||
min_tlow = 157;
|
||||
min_thi = 134;
|
||||
raise_fall_time = 127; /* Raise 29e-8s, Fall 98e-8s */
|
||||
}
|
||||
|
||||
/* The minimum clock that respects the thi/tlow = 134/157 is
|
||||
* 64800 Hz. Below that, we have to fix the tlow to 255 and
|
||||
* calculate the thi factor.
|
||||
*/
|
||||
if (clock < 648) {
|
||||
tlow = 255;
|
||||
thi = 1000000 - clock * raise_fall_time;
|
||||
thi /= (I2C_PCA_OSC_PER * clock) - tlow;
|
||||
} else {
|
||||
tlow = (1000000 - clock * raise_fall_time) * min_tlow;
|
||||
tlow /= I2C_PCA_OSC_PER * clock * (min_thi + min_tlow);
|
||||
thi = tlow * min_thi / min_tlow;
|
||||
}
|
||||
|
||||
pca_reset(pca_data);
|
||||
|
||||
printk(KERN_INFO
|
||||
"%s: Clock frequency is %dHz\n", adap->name, clock * 100);
|
||||
|
||||
pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IMODE);
|
||||
pca_outw(pca_data, I2C_PCA_IND, mode);
|
||||
pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLL);
|
||||
pca_outw(pca_data, I2C_PCA_IND, tlow);
|
||||
pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLH);
|
||||
pca_outw(pca_data, I2C_PCA_IND, thi);
|
||||
|
||||
pca_set_con(pca_data, I2C_PCA_CON_ENSIO);
|
||||
}
|
||||
udelay(500); /* 500 us for oscilator to stabilise */
|
||||
|
||||
return 0;
|
||||
@ -384,7 +548,7 @@ EXPORT_SYMBOL(i2c_pca_add_numbered_bus);
|
||||
|
||||
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>, "
|
||||
"Wolfram Sang <w.sang@pengutronix.de>");
|
||||
MODULE_DESCRIPTION("I2C-Bus PCA9564 algorithm");
|
||||
MODULE_DESCRIPTION("I2C-Bus PCA9564/PCA9665 algorithm");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(i2c_debug, int, 0);
|
||||
|
@ -1,31 +1,30 @@
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* Copyright (C) 1995-1997 Simon G. Vogl
|
||||
1998-2000 Hans Berglund
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
|
||||
Frodo Looijaard <frodol@dds.nl> ,and also from Martin Bailey
|
||||
<mbailey@littlefeet-inc.com> */
|
||||
|
||||
/* Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple
|
||||
messages, proper stop/repstart signaling during receive,
|
||||
added detect code */
|
||||
/*
|
||||
* i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters
|
||||
*
|
||||
* Copyright (C) 1995-1997 Simon G. Vogl
|
||||
* 1998-2000 Hans Berglund
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and
|
||||
* Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey
|
||||
* <mbailey@littlefeet-inc.com>
|
||||
*
|
||||
* Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple
|
||||
* messages, proper stop/repstart signaling during receive, added detect code
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@ -38,17 +37,18 @@
|
||||
#include "i2c-algo-pcf.h"
|
||||
|
||||
|
||||
#define DEB2(x) if (i2c_debug>=2) x
|
||||
#define DEB3(x) if (i2c_debug>=3) x /* print several statistical values*/
|
||||
#define DEBPROTO(x) if (i2c_debug>=9) x;
|
||||
/* debug the protocol by showing transferred bits */
|
||||
#define DEB2(x) if (i2c_debug >= 2) x
|
||||
#define DEB3(x) if (i2c_debug >= 3) x /* print several statistical values */
|
||||
#define DEBPROTO(x) if (i2c_debug >= 9) x;
|
||||
/* debug the protocol by showing transferred bits */
|
||||
#define DEF_TIMEOUT 16
|
||||
|
||||
/* module parameters:
|
||||
/*
|
||||
* module parameters:
|
||||
*/
|
||||
static int i2c_debug;
|
||||
|
||||
/* --- setting states on the bus with the right timing: --------------- */
|
||||
/* setting states on the bus with the right timing: */
|
||||
|
||||
#define set_pcf(adap, ctl, val) adap->setpcf(adap->data, ctl, val)
|
||||
#define get_pcf(adap, ctl) adap->getpcf(adap->data, ctl)
|
||||
@ -57,22 +57,21 @@ static int i2c_debug;
|
||||
#define i2c_outb(adap, val) adap->setpcf(adap->data, 0, val)
|
||||
#define i2c_inb(adap) adap->getpcf(adap->data, 0)
|
||||
|
||||
/* --- other auxiliary functions -------------------------------------- */
|
||||
/* other auxiliary functions */
|
||||
|
||||
static void i2c_start(struct i2c_algo_pcf_data *adap)
|
||||
static void i2c_start(struct i2c_algo_pcf_data *adap)
|
||||
{
|
||||
DEBPROTO(printk("S "));
|
||||
DEBPROTO(printk(KERN_DEBUG "S "));
|
||||
set_pcf(adap, 1, I2C_PCF_START);
|
||||
}
|
||||
|
||||
static void i2c_repstart(struct i2c_algo_pcf_data *adap)
|
||||
static void i2c_repstart(struct i2c_algo_pcf_data *adap)
|
||||
{
|
||||
DEBPROTO(printk(" Sr "));
|
||||
set_pcf(adap, 1, I2C_PCF_REPSTART);
|
||||
}
|
||||
|
||||
|
||||
static void i2c_stop(struct i2c_algo_pcf_data *adap)
|
||||
static void i2c_stop(struct i2c_algo_pcf_data *adap)
|
||||
{
|
||||
DEBPROTO(printk("P\n"));
|
||||
set_pcf(adap, 1, I2C_PCF_STOP);
|
||||
@ -82,17 +81,17 @@ static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
|
||||
{
|
||||
DEB2(printk(KERN_INFO
|
||||
"i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
|
||||
*status));
|
||||
|
||||
/* Cleanup from LAB -- reset and enable ESO.
|
||||
*status));
|
||||
/*
|
||||
* Cleanup from LAB -- reset and enable ESO.
|
||||
* This resets the PCF8584; since we've lost the bus, no
|
||||
* further attempts should be made by callers to clean up
|
||||
* (no i2c_stop() etc.)
|
||||
*/
|
||||
set_pcf(adap, 1, I2C_PCF_PIN);
|
||||
set_pcf(adap, 1, I2C_PCF_ESO);
|
||||
|
||||
/* We pause for a time period sufficient for any running
|
||||
/*
|
||||
* We pause for a time period sufficient for any running
|
||||
* I2C transaction to complete -- the arbitration logic won't
|
||||
* work properly until the next START is seen.
|
||||
* It is assumed the bus driver or client has set a proper value.
|
||||
@ -108,48 +107,50 @@ static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
|
||||
get_pcf(adap, 1)));
|
||||
}
|
||||
|
||||
static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
|
||||
static int wait_for_bb(struct i2c_algo_pcf_data *adap)
|
||||
{
|
||||
|
||||
int timeout = DEF_TIMEOUT;
|
||||
int status;
|
||||
|
||||
status = get_pcf(adap, 1);
|
||||
#ifndef STUB_I2C
|
||||
while (timeout-- && !(status & I2C_PCF_BB)) {
|
||||
|
||||
while (!(status & I2C_PCF_BB) && --timeout) {
|
||||
udelay(100); /* wait for 100 us */
|
||||
status = get_pcf(adap, 1);
|
||||
}
|
||||
#endif
|
||||
if (timeout <= 0) {
|
||||
|
||||
if (timeout == 0) {
|
||||
printk(KERN_ERR "Timeout waiting for Bus Busy\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return (timeout<=0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
|
||||
static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status)
|
||||
{
|
||||
|
||||
int timeout = DEF_TIMEOUT;
|
||||
|
||||
*status = get_pcf(adap, 1);
|
||||
#ifndef STUB_I2C
|
||||
while (timeout-- && (*status & I2C_PCF_PIN)) {
|
||||
|
||||
while ((*status & I2C_PCF_PIN) && --timeout) {
|
||||
adap->waitforpin(adap->data);
|
||||
*status = get_pcf(adap, 1);
|
||||
}
|
||||
if (*status & I2C_PCF_LAB) {
|
||||
handle_lab(adap, status);
|
||||
return(-EINTR);
|
||||
return -EINTR;
|
||||
}
|
||||
#endif
|
||||
if (timeout <= 0)
|
||||
return(-1);
|
||||
else
|
||||
return(0);
|
||||
|
||||
if (timeout == 0)
|
||||
return -ETIMEDOUT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* This should perform the 'PCF8584 initialization sequence' as described
|
||||
* in the Philips IC12 data book (1995, Aug 29).
|
||||
* There should be a 30 clock cycle wait after reset, I assume this
|
||||
@ -164,18 +165,21 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
|
||||
{
|
||||
unsigned char temp;
|
||||
|
||||
DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n", get_pcf(adap, 1)));
|
||||
DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n",
|
||||
get_pcf(adap, 1)));
|
||||
|
||||
/* S1=0x80: S0 selected, serial interface off */
|
||||
set_pcf(adap, 1, I2C_PCF_PIN);
|
||||
/* check to see S1 now used as R/W ctrl -
|
||||
PCF8584 does that when ESO is zero */
|
||||
/*
|
||||
* check to see S1 now used as R/W ctrl -
|
||||
* PCF8584 does that when ESO is zero
|
||||
*/
|
||||
if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) {
|
||||
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp));
|
||||
return -ENXIO; /* definetly not PCF8584 */
|
||||
}
|
||||
|
||||
/* load own address in S0, effective address is (own << 1) */
|
||||
/* load own address in S0, effective address is (own << 1) */
|
||||
i2c_outb(adap, get_own(adap));
|
||||
/* check it's really written */
|
||||
if ((temp = i2c_inb(adap)) != get_own(adap)) {
|
||||
@ -183,7 +187,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* S1=0xA0, next byte in S2 */
|
||||
/* S1=0xA0, next byte in S2 */
|
||||
set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1);
|
||||
/* check to see S2 now selected */
|
||||
if (((temp = get_pcf(adap, 1)) & 0x7f) != I2C_PCF_ES1) {
|
||||
@ -191,7 +195,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* load clock register S2 */
|
||||
/* load clock register S2 */
|
||||
i2c_outb(adap, get_clock(adap));
|
||||
/* check it's really written, the only 5 lowest bits does matter */
|
||||
if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) {
|
||||
@ -199,7 +203,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/* Enable serial interface, idle, S0 selected */
|
||||
/* Enable serial interface, idle, S0 selected */
|
||||
set_pcf(adap, 1, I2C_PCF_IDLE);
|
||||
|
||||
/* check to see PCF is really idled and we can access status register */
|
||||
@ -207,57 +211,47 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap)
|
||||
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp));
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
|
||||
printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ----- Utility functions
|
||||
*/
|
||||
|
||||
static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf,
|
||||
int count, int last)
|
||||
int count, int last)
|
||||
{
|
||||
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
|
||||
int wrcount, status, timeout;
|
||||
|
||||
|
||||
for (wrcount=0; wrcount<count; ++wrcount) {
|
||||
DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n",
|
||||
buf[wrcount]&0xff));
|
||||
buf[wrcount] & 0xff));
|
||||
i2c_outb(adap, buf[wrcount]);
|
||||
timeout = wait_for_pin(adap, &status);
|
||||
if (timeout) {
|
||||
if (timeout == -EINTR) {
|
||||
/* arbitration lost */
|
||||
return -EINTR;
|
||||
}
|
||||
if (timeout == -EINTR)
|
||||
return -EINTR; /* arbitration lost */
|
||||
|
||||
i2c_stop(adap);
|
||||
dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n");
|
||||
return -EREMOTEIO; /* got a better one ?? */
|
||||
}
|
||||
#ifndef STUB_I2C
|
||||
if (status & I2C_PCF_LRB) {
|
||||
i2c_stop(adap);
|
||||
dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n");
|
||||
return -EREMOTEIO; /* got a better one ?? */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (last) {
|
||||
if (last)
|
||||
i2c_stop(adap);
|
||||
}
|
||||
else {
|
||||
else
|
||||
i2c_repstart(adap);
|
||||
}
|
||||
|
||||
return (wrcount);
|
||||
return wrcount;
|
||||
}
|
||||
|
||||
|
||||
static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
|
||||
int count, int last)
|
||||
int count, int last)
|
||||
{
|
||||
int i, status;
|
||||
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
|
||||
@ -267,42 +261,36 @@ static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf,
|
||||
for (i = 0; i <= count; i++) {
|
||||
|
||||
if ((wfp = wait_for_pin(adap, &status))) {
|
||||
if (wfp == -EINTR) {
|
||||
/* arbitration lost */
|
||||
return -EINTR;
|
||||
}
|
||||
if (wfp == -EINTR)
|
||||
return -EINTR; /* arbitration lost */
|
||||
|
||||
i2c_stop(adap);
|
||||
dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n");
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef STUB_I2C
|
||||
if ((status & I2C_PCF_LRB) && (i != count)) {
|
||||
i2c_stop(adap);
|
||||
dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n");
|
||||
return (-1);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
if (i == count - 1) {
|
||||
set_pcf(adap, 1, I2C_PCF_ESO);
|
||||
} else
|
||||
if (i == count) {
|
||||
if (last) {
|
||||
} else if (i == count) {
|
||||
if (last)
|
||||
i2c_stop(adap);
|
||||
} else {
|
||||
else
|
||||
i2c_repstart(adap);
|
||||
}
|
||||
};
|
||||
|
||||
if (i) {
|
||||
buf[i - 1] = i2c_inb(adap);
|
||||
} else {
|
||||
i2c_inb(adap); /* dummy read */
|
||||
}
|
||||
|
||||
if (i)
|
||||
buf[i - 1] = i2c_inb(adap);
|
||||
else
|
||||
i2c_inb(adap); /* dummy read */
|
||||
}
|
||||
|
||||
return (i - 1);
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
|
||||
@ -323,14 +311,14 @@ static int pcf_doAddress(struct i2c_algo_pcf_data *adap,
|
||||
}
|
||||
|
||||
static int pcf_xfer(struct i2c_adapter *i2c_adap,
|
||||
struct i2c_msg *msgs,
|
||||
struct i2c_msg *msgs,
|
||||
int num)
|
||||
{
|
||||
struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
|
||||
struct i2c_msg *pmsg;
|
||||
int i;
|
||||
int ret=0, timeout, status;
|
||||
|
||||
|
||||
if (adap->xfer_begin)
|
||||
adap->xfer_begin(adap->data);
|
||||
|
||||
@ -338,25 +326,24 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
|
||||
timeout = wait_for_bb(adap);
|
||||
if (timeout) {
|
||||
DEB2(printk(KERN_ERR "i2c-algo-pcf.o: "
|
||||
"Timeout waiting for BB in pcf_xfer\n");)
|
||||
"Timeout waiting for BB in pcf_xfer\n");)
|
||||
i = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0;ret >= 0 && i < num; i++) {
|
||||
pmsg = &msgs[i];
|
||||
|
||||
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n",
|
||||
pmsg->flags & I2C_M_RD ? "read" : "write",
|
||||
pmsg->len, pmsg->addr, i + 1, num);)
|
||||
|
||||
pmsg->len, pmsg->addr, i + 1, num);)
|
||||
|
||||
ret = pcf_doAddress(adap, pmsg);
|
||||
|
||||
/* Send START */
|
||||
if (i == 0) {
|
||||
i2c_start(adap);
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
i2c_start(adap);
|
||||
|
||||
/* Wait for PIN (pending interrupt NOT) */
|
||||
timeout = wait_for_pin(adap, &status);
|
||||
if (timeout) {
|
||||
@ -371,8 +358,7 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
|
||||
i = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifndef STUB_I2C
|
||||
|
||||
/* Check LRB (last rcvd bit - slave ack) */
|
||||
if (status & I2C_PCF_LRB) {
|
||||
i2c_stop(adap);
|
||||
@ -380,27 +366,24 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
|
||||
i = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n",
|
||||
i, msgs[i].addr, msgs[i].flags, msgs[i].len);)
|
||||
|
||||
/* Read */
|
||||
|
||||
if (pmsg->flags & I2C_M_RD) {
|
||||
/* read bytes into buffer*/
|
||||
ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len,
|
||||
(i + 1 == num));
|
||||
|
||||
(i + 1 == num));
|
||||
|
||||
if (ret != pmsg->len) {
|
||||
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: "
|
||||
"only read %d bytes.\n",ret));
|
||||
} else {
|
||||
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: read %d bytes.\n",ret));
|
||||
}
|
||||
} else { /* Write */
|
||||
} else {
|
||||
ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len,
|
||||
(i + 1 == num));
|
||||
|
||||
(i + 1 == num));
|
||||
|
||||
if (ret != pmsg->len) {
|
||||
DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: "
|
||||
"only wrote %d bytes.\n",ret));
|
||||
@ -413,24 +396,23 @@ static int pcf_xfer(struct i2c_adapter *i2c_adap,
|
||||
out:
|
||||
if (adap->xfer_end)
|
||||
adap->xfer_end(adap->data);
|
||||
return (i);
|
||||
return i;
|
||||
}
|
||||
|
||||
static u32 pcf_func(struct i2c_adapter *adap)
|
||||
{
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||
I2C_FUNC_PROTOCOL_MANGLING;
|
||||
}
|
||||
|
||||
/* -----exported algorithm data: ------------------------------------- */
|
||||
|
||||
/* exported algorithm data: */
|
||||
static const struct i2c_algorithm pcf_algo = {
|
||||
.master_xfer = pcf_xfer,
|
||||
.functionality = pcf_func,
|
||||
};
|
||||
|
||||
/*
|
||||
* registering functions to load algorithms at runtime
|
||||
/*
|
||||
* registering functions to load algorithms at runtime
|
||||
*/
|
||||
int i2c_pcf_add_bus(struct i2c_adapter *adap)
|
||||
{
|
||||
@ -441,7 +423,6 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
adap->algo = &pcf_algo;
|
||||
adap->timeout = 100;
|
||||
|
||||
if ((rval = pcf_init_8584(pcf_adap)))
|
||||
return rval;
|
||||
@ -458,4 +439,4 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
|
||||
MODULE_PARM_DESC(i2c_debug,
|
||||
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
|
||||
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol");
|
||||
|
@ -132,6 +132,7 @@ config I2C_PIIX4
|
||||
Serverworks CSB5
|
||||
Serverworks CSB6
|
||||
Serverworks HT-1000
|
||||
Serverworks HT-1100
|
||||
SMSC Victory66
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
@ -617,12 +618,12 @@ config I2C_ELEKTOR
|
||||
will be called i2c-elektor.
|
||||
|
||||
config I2C_PCA_ISA
|
||||
tristate "PCA9564 on an ISA bus"
|
||||
tristate "PCA9564/PCA9665 on an ISA bus"
|
||||
depends on ISA
|
||||
select I2C_ALGOPCA
|
||||
default n
|
||||
help
|
||||
This driver supports ISA boards using the Philips PCA9564
|
||||
This driver supports ISA boards using the Philips PCA9564/PCA9665
|
||||
parallel bus to I2C bus controller.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
@ -634,11 +635,11 @@ config I2C_PCA_ISA
|
||||
time). If unsure, say N.
|
||||
|
||||
config I2C_PCA_PLATFORM
|
||||
tristate "PCA9564 as platform device"
|
||||
tristate "PCA9564/PCA9665 as platform device"
|
||||
select I2C_ALGOPCA
|
||||
default n
|
||||
help
|
||||
This driver supports a memory mapped Philips PCA9564
|
||||
This driver supports a memory mapped Philips PCA9564/PCA9665
|
||||
parallel bus to I2C bus controller.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
|
@ -216,7 +216,7 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev,
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
timeout = jiffies + DAVINCI_I2C_TIMEOUT;
|
||||
timeout = jiffies + dev->adapter.timeout;
|
||||
while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG)
|
||||
& DAVINCI_I2C_STR_BB) {
|
||||
if (time_after(jiffies, timeout)) {
|
||||
@ -289,7 +289,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
|
||||
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
|
||||
|
||||
r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
|
||||
DAVINCI_I2C_TIMEOUT);
|
||||
dev->adapter.timeout);
|
||||
if (r == 0) {
|
||||
dev_err(dev->dev, "controller timed out\n");
|
||||
i2c_davinci_init(dev);
|
||||
@ -546,9 +546,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
|
||||
strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
|
||||
adap->algo = &i2c_davinci_algo;
|
||||
adap->dev.parent = &pdev->dev;
|
||||
|
||||
/* FIXME */
|
||||
adap->timeout = 1;
|
||||
adap->timeout = DAVINCI_I2C_TIMEOUT;
|
||||
|
||||
adap->nr = pdev->id;
|
||||
r = i2c_add_numbered_adapter(adap);
|
||||
|
@ -415,7 +415,7 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){
|
||||
if (dev->irq >= 0){
|
||||
/* Interrupt mode */
|
||||
ret = wait_event_interruptible_timeout(dev->wq,
|
||||
!(in_8(&iic->sts) & STS_PT), dev->adap.timeout * HZ);
|
||||
!(in_8(&iic->sts) & STS_PT), dev->adap.timeout);
|
||||
|
||||
if (unlikely(ret < 0))
|
||||
DBG("%d: wait interrupted\n", dev->idx);
|
||||
@ -426,7 +426,7 @@ static int iic_wait_for_tc(struct ibm_iic_private* dev){
|
||||
}
|
||||
else {
|
||||
/* Polling mode */
|
||||
unsigned long x = jiffies + dev->adap.timeout * HZ;
|
||||
unsigned long x = jiffies + dev->adap.timeout;
|
||||
|
||||
while (in_8(&iic->sts) & STS_PT){
|
||||
if (unlikely(time_after(jiffies, x))){
|
||||
@ -748,7 +748,7 @@ static int __devinit iic_probe(struct of_device *ofdev,
|
||||
i2c_set_adapdata(adap, dev);
|
||||
adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
adap->algo = &iic_algo;
|
||||
adap->timeout = 1;
|
||||
adap->timeout = HZ;
|
||||
|
||||
ret = i2c_add_adapter(adap);
|
||||
if (ret < 0) {
|
||||
|
@ -488,7 +488,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
|
||||
/*
|
||||
* Default values...should these come in from board code?
|
||||
*/
|
||||
new_adapter->timeout = 100;
|
||||
new_adapter->timeout = HZ;
|
||||
new_adapter->algo = &iop3xx_i2c_algo;
|
||||
|
||||
init_waitqueue_head(&adapter_data->waitq);
|
||||
|
@ -116,7 +116,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
|
||||
} else {
|
||||
/* Interrupt mode */
|
||||
result = wait_event_interruptible_timeout(i2c->queue,
|
||||
(i2c->interrupt & CSR_MIF), timeout * HZ);
|
||||
(i2c->interrupt & CSR_MIF), timeout);
|
||||
|
||||
if (unlikely(result < 0)) {
|
||||
pr_debug("I2C: wait interrupted\n");
|
||||
@ -311,7 +311,7 @@ static struct i2c_adapter mpc_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "MPC adapter",
|
||||
.algo = &mpc_algo,
|
||||
.timeout = 1,
|
||||
.timeout = HZ,
|
||||
};
|
||||
|
||||
static int __devinit fsl_i2c_probe(struct of_device *op, const struct of_device_id *match)
|
||||
|
@ -358,7 +358,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
|
||||
char abort = 0;
|
||||
|
||||
time_left = wait_event_interruptible_timeout(drv_data->waitq,
|
||||
!drv_data->block, msecs_to_jiffies(drv_data->adapter.timeout));
|
||||
!drv_data->block, drv_data->adapter.timeout);
|
||||
|
||||
spin_lock_irqsave(&drv_data->lock, flags);
|
||||
if (!time_left) { /* Timed out */
|
||||
@ -374,8 +374,7 @@ mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
|
||||
spin_unlock_irqrestore(&drv_data->lock, flags);
|
||||
|
||||
time_left = wait_event_timeout(drv_data->waitq,
|
||||
!drv_data->block,
|
||||
msecs_to_jiffies(drv_data->adapter.timeout));
|
||||
!drv_data->block, drv_data->adapter.timeout);
|
||||
|
||||
if ((time_left <= 0) && drv_data->block) {
|
||||
drv_data->state = MV64XXX_I2C_STATE_IDLE;
|
||||
@ -530,7 +529,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
|
||||
drv_data->adapter.algo = &mv64xxx_i2c_algo;
|
||||
drv_data->adapter.owner = THIS_MODULE;
|
||||
drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
|
||||
drv_data->adapter.timeout = pdata->timeout;
|
||||
drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
|
||||
drv_data->adapter.nr = pd->id;
|
||||
platform_set_drvdata(pd, drv_data);
|
||||
i2c_set_adapdata(&drv_data->adapter, drv_data);
|
||||
|
@ -31,10 +31,14 @@
|
||||
nForce3 250Gb MCP 00E4
|
||||
nForce4 MCP 0052
|
||||
nForce4 MCP-04 0034
|
||||
nForce4 MCP51 0264
|
||||
nForce4 MCP55 0368
|
||||
nForce MCP51 0264
|
||||
nForce MCP55 0368
|
||||
nForce MCP61 03EB
|
||||
nForce MCP65 0446
|
||||
nForce MCP67 0542
|
||||
nForce MCP73 07D8
|
||||
nForce MCP78S 0752
|
||||
nForce MCP79 0AA2
|
||||
|
||||
This driver supports the 2 SMBuses that are included in the MCP of the
|
||||
nForce2/3/4/5xx chipsets.
|
||||
@ -315,6 +319,10 @@ static struct pci_device_id nforce2_ids[] = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS) },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
@ -41,15 +42,17 @@ static int irq = -1;
|
||||
|
||||
/* Data sheet recommends 59kHz for 100kHz operation due to variation
|
||||
* in the actual clock rate */
|
||||
static int clock = I2C_PCA_CON_59kHz;
|
||||
static int clock = 59000;
|
||||
|
||||
static struct i2c_adapter pca_isa_ops;
|
||||
static wait_queue_head_t pca_wait;
|
||||
|
||||
static void pca_isa_writebyte(void *pd, int reg, int val)
|
||||
{
|
||||
#ifdef DEBUG_IO
|
||||
static char *names[] = { "T/O", "DAT", "ADR", "CON" };
|
||||
printk("*** write %s at %#lx <= %#04x\n", names[reg], base+reg, val);
|
||||
printk(KERN_DEBUG "*** write %s at %#lx <= %#04x\n", names[reg],
|
||||
base+reg, val);
|
||||
#endif
|
||||
outb(val, base+reg);
|
||||
}
|
||||
@ -60,7 +63,7 @@ static int pca_isa_readbyte(void *pd, int reg)
|
||||
#ifdef DEBUG_IO
|
||||
{
|
||||
static char *names[] = { "STA", "DAT", "ADR", "CON" };
|
||||
printk("*** read %s => %#04x\n", names[reg], res);
|
||||
printk(KERN_DEBUG "*** read %s => %#04x\n", names[reg], res);
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
@ -68,16 +71,22 @@ static int pca_isa_readbyte(void *pd, int reg)
|
||||
|
||||
static int pca_isa_waitforcompletion(void *pd)
|
||||
{
|
||||
int ret = 0;
|
||||
long ret = ~0;
|
||||
unsigned long timeout;
|
||||
|
||||
if (irq > -1) {
|
||||
ret = wait_event_interruptible(pca_wait,
|
||||
pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI);
|
||||
ret = wait_event_interruptible_timeout(pca_wait,
|
||||
pca_isa_readbyte(pd, I2C_PCA_CON)
|
||||
& I2C_PCA_CON_SI, pca_isa_ops.timeout);
|
||||
} else {
|
||||
while ((pca_isa_readbyte(pd, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0)
|
||||
/* Do polling */
|
||||
timeout = jiffies + pca_isa_ops.timeout;
|
||||
while (((pca_isa_readbyte(pd, I2C_PCA_CON)
|
||||
& I2C_PCA_CON_SI) == 0)
|
||||
&& (ret = time_before(jiffies, timeout)))
|
||||
udelay(100);
|
||||
}
|
||||
return ret;
|
||||
return ret > 0;
|
||||
}
|
||||
|
||||
static void pca_isa_resetchip(void *pd)
|
||||
@ -102,8 +111,8 @@ static struct i2c_algo_pca_data pca_isa_data = {
|
||||
static struct i2c_adapter pca_isa_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.algo_data = &pca_isa_data,
|
||||
.name = "PCA9564 ISA Adapter",
|
||||
.timeout = 100,
|
||||
.name = "PCA9564/PCA9665 ISA Adapter",
|
||||
.timeout = HZ,
|
||||
};
|
||||
|
||||
static int __devinit pca_isa_match(struct device *dev, unsigned int id)
|
||||
@ -195,7 +204,7 @@ static void __exit pca_isa_exit(void)
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
|
||||
MODULE_DESCRIPTION("ISA base PCA9564 driver");
|
||||
MODULE_DESCRIPTION("ISA base PCA9564/PCA9665 driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_param(base, ulong, 0);
|
||||
@ -204,7 +213,13 @@ MODULE_PARM_DESC(base, "I/O base address");
|
||||
module_param(irq, int, 0);
|
||||
MODULE_PARM_DESC(irq, "IRQ");
|
||||
module_param(clock, int, 0);
|
||||
MODULE_PARM_DESC(clock, "Clock rate as described in table 1 of PCA9564 datasheet");
|
||||
MODULE_PARM_DESC(clock, "Clock rate in hertz.\n\t\t"
|
||||
"For PCA9564: 330000,288000,217000,146000,"
|
||||
"88000,59000,44000,36000\n"
|
||||
"\t\tFor PCA9665:\tStandard: 60300 - 100099\n"
|
||||
"\t\t\t\tFast: 100100 - 400099\n"
|
||||
"\t\t\t\tFast+: 400100 - 10000099\n"
|
||||
"\t\t\t\tTurbo: Up to 1265800");
|
||||
|
||||
module_init(pca_isa_init);
|
||||
module_exit(pca_isa_exit);
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
@ -81,24 +82,23 @@ static void i2c_pca_pf_writebyte32(void *pd, int reg, int val)
|
||||
static int i2c_pca_pf_waitforcompletion(void *pd)
|
||||
{
|
||||
struct i2c_pca_pf_data *i2c = pd;
|
||||
int ret = 0;
|
||||
long ret = ~0;
|
||||
unsigned long timeout;
|
||||
|
||||
if (i2c->irq) {
|
||||
ret = wait_event_interruptible(i2c->wait,
|
||||
ret = wait_event_interruptible_timeout(i2c->wait,
|
||||
i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
|
||||
& I2C_PCA_CON_SI);
|
||||
& I2C_PCA_CON_SI, i2c->adap.timeout);
|
||||
} else {
|
||||
/*
|
||||
* Do polling...
|
||||
* XXX: Could get stuck in extreme cases!
|
||||
* Maybe add timeout, but using irqs is preferred anyhow.
|
||||
*/
|
||||
while ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
|
||||
/* Do polling */
|
||||
timeout = jiffies + i2c->adap.timeout;
|
||||
while (((i2c->algo_data.read_byte(i2c, I2C_PCA_CON)
|
||||
& I2C_PCA_CON_SI) == 0)
|
||||
&& (ret = time_before(jiffies, timeout)))
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return ret > 0;
|
||||
}
|
||||
|
||||
static void i2c_pca_pf_dummyreset(void *pd)
|
||||
@ -172,14 +172,25 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
|
||||
|
||||
i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
|
||||
i2c->adap.owner = THIS_MODULE;
|
||||
snprintf(i2c->adap.name, sizeof(i2c->adap.name), "PCA9564 at 0x%08lx",
|
||||
(unsigned long) res->start);
|
||||
snprintf(i2c->adap.name, sizeof(i2c->adap.name),
|
||||
"PCA9564/PCA9665 at 0x%08lx",
|
||||
(unsigned long) res->start);
|
||||
i2c->adap.algo_data = &i2c->algo_data;
|
||||
i2c->adap.dev.parent = &pdev->dev;
|
||||
i2c->adap.timeout = platform_data->timeout;
|
||||
|
||||
i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
|
||||
if (platform_data) {
|
||||
i2c->adap.timeout = platform_data->timeout;
|
||||
i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed;
|
||||
i2c->gpio = platform_data->gpio;
|
||||
} else {
|
||||
i2c->adap.timeout = HZ;
|
||||
i2c->algo_data.i2c_clock = 59000;
|
||||
i2c->gpio = -1;
|
||||
}
|
||||
|
||||
i2c->algo_data.data = i2c;
|
||||
i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
|
||||
i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
|
||||
|
||||
switch (res->flags & IORESOURCE_MEM_TYPE_MASK) {
|
||||
case IORESOURCE_MEM_32BIT:
|
||||
@ -197,11 +208,6 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
|
||||
break;
|
||||
}
|
||||
|
||||
i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion;
|
||||
|
||||
i2c->gpio = platform_data->gpio;
|
||||
i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset;
|
||||
|
||||
/* Use gpio_is_valid() when in mainline */
|
||||
if (i2c->gpio > -1) {
|
||||
ret = gpio_request(i2c->gpio, i2c->adap.name);
|
||||
@ -246,7 +252,7 @@ e_remap:
|
||||
e_alloc:
|
||||
release_mem_region(res->start, res_len(res));
|
||||
e_print:
|
||||
printk(KERN_ERR "Registering PCA9564 FAILED! (%d)\n", ret);
|
||||
printk(KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -290,7 +296,7 @@ static void __exit i2c_pca_pf_exit(void)
|
||||
}
|
||||
|
||||
MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
|
||||
MODULE_DESCRIPTION("I2C-PCA9564 platform driver");
|
||||
MODULE_DESCRIPTION("I2C-PCA9564/PCA9665 platform driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(i2c_pca_pf_init);
|
||||
|
@ -20,7 +20,7 @@
|
||||
/*
|
||||
Supports:
|
||||
Intel PIIX4, 440MX
|
||||
Serverworks OSB4, CSB5, CSB6, HT-1000
|
||||
Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100
|
||||
ATI IXP200, IXP300, IXP400, SB600, SB700, SB800
|
||||
SMSC Victory66
|
||||
|
||||
@ -226,6 +226,70 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev,
|
||||
const struct pci_device_id *id)
|
||||
{
|
||||
unsigned short smba_idx = 0xcd6;
|
||||
u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c;
|
||||
|
||||
/* SB800 SMBus does not support forcing address */
|
||||
if (force || force_addr) {
|
||||
dev_err(&PIIX4_dev->dev, "SB800 SMBus does not support "
|
||||
"forcing address!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Determine the address of the SMBus areas */
|
||||
if (!request_region(smba_idx, 2, "smba_idx")) {
|
||||
dev_err(&PIIX4_dev->dev, "SMBus base address index region "
|
||||
"0x%x already in use!\n", smba_idx);
|
||||
return -EBUSY;
|
||||
}
|
||||
outb_p(smb_en, smba_idx);
|
||||
smba_en_lo = inb_p(smba_idx + 1);
|
||||
outb_p(smb_en + 1, smba_idx);
|
||||
smba_en_hi = inb_p(smba_idx + 1);
|
||||
release_region(smba_idx, 2);
|
||||
|
||||
if ((smba_en_lo & 1) == 0) {
|
||||
dev_err(&PIIX4_dev->dev,
|
||||
"Host SMBus controller not enabled!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0;
|
||||
if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
|
||||
return -EBUSY;
|
||||
|
||||
if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
|
||||
dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
|
||||
piix4_smba);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* Request the SMBus I2C bus config region */
|
||||
if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) {
|
||||
dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region "
|
||||
"0x%x already in use!\n", piix4_smba + i2ccfg_offset);
|
||||
release_region(piix4_smba, SMBIOSIZE);
|
||||
piix4_smba = 0;
|
||||
return -EBUSY;
|
||||
}
|
||||
i2ccfg = inb_p(piix4_smba + i2ccfg_offset);
|
||||
release_region(piix4_smba + i2ccfg_offset, 1);
|
||||
|
||||
if (i2ccfg & 1)
|
||||
dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n");
|
||||
else
|
||||
dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n");
|
||||
|
||||
dev_info(&PIIX4_dev->dev,
|
||||
"SMBus Host Controller at 0x%x, revision %d\n",
|
||||
piix4_smba, i2ccfg >> 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int piix4_transaction(void)
|
||||
{
|
||||
int temp;
|
||||
@ -423,6 +487,8 @@ static struct pci_device_id piix4_ids[] = {
|
||||
PCI_DEVICE_ID_SERVERWORKS_CSB6) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
|
||||
PCI_DEVICE_ID_SERVERWORKS_HT1000SB) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS,
|
||||
PCI_DEVICE_ID_SERVERWORKS_HT1100LD) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
@ -433,7 +499,14 @@ static int __devinit piix4_probe(struct pci_dev *dev,
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = piix4_setup(dev, id);
|
||||
if ((dev->vendor == PCI_VENDOR_ID_ATI) &&
|
||||
(dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) &&
|
||||
(dev->revision >= 0x40))
|
||||
/* base address location etc changed in SB800 */
|
||||
retval = piix4_setup_sb800(dev, id);
|
||||
else
|
||||
retval = piix4_setup(dev, id);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
|
@ -191,7 +191,8 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev)
|
||||
i2c_set_adapdata(adapter, NULL);
|
||||
/* We aren't that prepared to deal with this... */
|
||||
if (rc)
|
||||
printk("i2c-powermac.c: Failed to remove bus %s !\n",
|
||||
printk(KERN_WARNING
|
||||
"i2c-powermac.c: Failed to remove bus %s !\n",
|
||||
adapter->name);
|
||||
platform_set_drvdata(dev, NULL);
|
||||
kfree(adapter);
|
||||
|
@ -210,11 +210,12 @@ static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id);
|
||||
static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why)
|
||||
{
|
||||
unsigned int i;
|
||||
printk("i2c: error: %s\n", why);
|
||||
printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
|
||||
printk(KERN_ERR "i2c: error: %s\n", why);
|
||||
printk(KERN_ERR "i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n",
|
||||
i2c->msg_num, i2c->msg_idx, i2c->msg_ptr);
|
||||
printk("i2c: ICR: %08x ISR: %08x\n"
|
||||
"i2c: log: ", readl(_ICR(i2c)), readl(_ISR(i2c)));
|
||||
printk(KERN_ERR "i2c: ICR: %08x ISR: %08x\n",
|
||||
readl(_ICR(i2c)), readl(_ISR(i2c)));
|
||||
printk(KERN_DEBUG "i2c: log: ");
|
||||
for (i = 0; i < i2c->irqlogidx; i++)
|
||||
printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]);
|
||||
printk("\n");
|
||||
|
@ -152,7 +152,7 @@ static void i2c_device_shutdown(struct device *dev)
|
||||
driver->shutdown(to_i2c_client(dev));
|
||||
}
|
||||
|
||||
static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
|
||||
static int i2c_device_suspend(struct device *dev, pm_message_t mesg)
|
||||
{
|
||||
struct i2c_driver *driver;
|
||||
|
||||
@ -164,7 +164,7 @@ static int i2c_device_suspend(struct device * dev, pm_message_t mesg)
|
||||
return driver->suspend(to_i2c_client(dev), mesg);
|
||||
}
|
||||
|
||||
static int i2c_device_resume(struct device * dev)
|
||||
static int i2c_device_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_driver *driver;
|
||||
|
||||
@ -187,13 +187,15 @@ static void i2c_client_dev_release(struct device *dev)
|
||||
kfree(to_i2c_client(dev));
|
||||
}
|
||||
|
||||
static ssize_t show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t
|
||||
show_client_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
return sprintf(buf, "%s\n", client->name);
|
||||
}
|
||||
|
||||
static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static ssize_t
|
||||
show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
|
||||
@ -365,8 +367,7 @@ static struct i2c_driver dummy_driver = {
|
||||
* This returns the new i2c client, which should be saved for later use with
|
||||
* i2c_unregister_device(); or NULL to indicate an error.
|
||||
*/
|
||||
struct i2c_client *
|
||||
i2c_new_dummy(struct i2c_adapter *adapter, u16 address)
|
||||
struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address)
|
||||
{
|
||||
struct i2c_board_info info = {
|
||||
I2C_BOARD_INFO("dummy", address),
|
||||
@ -413,8 +414,8 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
|
||||
if (devinfo->busnum == adapter->nr
|
||||
&& !i2c_new_device(adapter,
|
||||
&devinfo->board_info))
|
||||
printk(KERN_ERR "i2c-core: can't create i2c%d-%04x\n",
|
||||
i2c_adapter_id(adapter),
|
||||
dev_err(&adapter->dev,
|
||||
"Can't create device at 0x%02x\n",
|
||||
devinfo->board_info.addr);
|
||||
}
|
||||
mutex_unlock(&__i2c_board_lock);
|
||||
@ -459,6 +460,11 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
|
||||
pr_debug("I2C adapter driver [%s] forgot to specify "
|
||||
"physical device\n", adap->name);
|
||||
}
|
||||
|
||||
/* Set default timeout to 1 second if not already set */
|
||||
if (adap->timeout == 0)
|
||||
adap->timeout = HZ;
|
||||
|
||||
dev_set_name(&adap->dev, "i2c-%d", adap->nr);
|
||||
adap->dev.release = &i2c_adapter_dev_release;
|
||||
adap->dev.class = &i2c_adapter_class;
|
||||
@ -581,7 +587,8 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
|
||||
struct i2c_client *client, *_n;
|
||||
int res;
|
||||
|
||||
/* Remove the devices we created ourselves */
|
||||
/* Remove the devices we created ourselves as the result of hardware
|
||||
* probing (using a driver's detect method) */
|
||||
list_for_each_entry_safe(client, _n, &driver->clients, detected) {
|
||||
if (client->adapter == adapter) {
|
||||
dev_dbg(&adapter->dev, "Removing %s at 0x%x\n",
|
||||
@ -749,6 +756,8 @@ static int __detach_adapter(struct device *dev, void *data)
|
||||
struct i2c_driver *driver = data;
|
||||
struct i2c_client *client, *_n;
|
||||
|
||||
/* Remove the devices we created ourselves as the result of hardware
|
||||
* probing (using a driver's detect method) */
|
||||
list_for_each_entry_safe(client, _n, &driver->clients, detected) {
|
||||
dev_dbg(&adapter->dev, "Removing %s at 0x%x\n",
|
||||
client->name, client->addr);
|
||||
@ -1012,7 +1021,7 @@ module_exit(i2c_exit);
|
||||
* Note that there is no requirement that each message be sent to
|
||||
* the same slave address, although that is the most common model.
|
||||
*/
|
||||
int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
|
||||
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -1519,8 +1528,7 @@ EXPORT_SYMBOL(i2c_put_adapter);
|
||||
/* The SMBus parts */
|
||||
|
||||
#define POLY (0x1070U << 3)
|
||||
static u8
|
||||
crc8(u16 data)
|
||||
static u8 crc8(u16 data)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -1984,9 +1992,9 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
|
||||
* This executes an SMBus protocol operation, and returns a negative
|
||||
* errno code else zero on success.
|
||||
*/
|
||||
s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
|
||||
s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
|
||||
char read_write, u8 command, int protocol,
|
||||
union i2c_smbus_data * data)
|
||||
union i2c_smbus_data *data)
|
||||
{
|
||||
s32 res;
|
||||
|
||||
|
@ -2,7 +2,7 @@ menu "EEPROM support"
|
||||
|
||||
config EEPROM_AT24
|
||||
tristate "I2C EEPROMs from most vendors"
|
||||
depends on I2C && SYSFS && EXPERIMENTAL
|
||||
depends on I2C && SYSFS
|
||||
help
|
||||
Enable this driver to get read/write support to most I2C EEPROMs,
|
||||
after you configure the driver to know about each EEPROM on
|
||||
|
@ -1,7 +1,14 @@
|
||||
#ifndef _LINUX_I2C_ALGO_PCA_H
|
||||
#define _LINUX_I2C_ALGO_PCA_H
|
||||
|
||||
/* Clock speeds for the bus */
|
||||
/* Chips known to the pca algo */
|
||||
#define I2C_PCA_CHIP_9564 0x00
|
||||
#define I2C_PCA_CHIP_9665 0x01
|
||||
|
||||
/* Internal period for PCA9665 oscilator */
|
||||
#define I2C_PCA_OSC_PER 3 /* e10-8s */
|
||||
|
||||
/* Clock speeds for the bus for PCA9564*/
|
||||
#define I2C_PCA_CON_330kHz 0x00
|
||||
#define I2C_PCA_CON_288kHz 0x01
|
||||
#define I2C_PCA_CON_217kHz 0x02
|
||||
@ -18,6 +25,26 @@
|
||||
#define I2C_PCA_ADR 0x02 /* OWN ADR Read/Write */
|
||||
#define I2C_PCA_CON 0x03 /* CONTROL Read/Write */
|
||||
|
||||
/* PCA9665 registers */
|
||||
#define I2C_PCA_INDPTR 0x00 /* INDIRECT Pointer Write Only */
|
||||
#define I2C_PCA_IND 0x02 /* INDIRECT Read/Write */
|
||||
|
||||
/* PCA9665 indirect registers */
|
||||
#define I2C_PCA_ICOUNT 0x00 /* Byte Count for buffered mode */
|
||||
#define I2C_PCA_IADR 0x01 /* OWN ADR */
|
||||
#define I2C_PCA_ISCLL 0x02 /* SCL LOW period */
|
||||
#define I2C_PCA_ISCLH 0x03 /* SCL HIGH period */
|
||||
#define I2C_PCA_ITO 0x04 /* TIMEOUT */
|
||||
#define I2C_PCA_IPRESET 0x05 /* Parallel bus reset */
|
||||
#define I2C_PCA_IMODE 0x06 /* I2C Bus mode */
|
||||
|
||||
/* PCA9665 I2C bus mode */
|
||||
#define I2C_PCA_MODE_STD 0x00 /* Standard mode */
|
||||
#define I2C_PCA_MODE_FAST 0x01 /* Fast mode */
|
||||
#define I2C_PCA_MODE_FASTP 0x02 /* Fast Plus mode */
|
||||
#define I2C_PCA_MODE_TURBO 0x03 /* Turbo mode */
|
||||
|
||||
|
||||
#define I2C_PCA_CON_AA 0x80 /* Assert Acknowledge */
|
||||
#define I2C_PCA_CON_ENSIO 0x40 /* Enable */
|
||||
#define I2C_PCA_CON_STA 0x20 /* Start */
|
||||
@ -31,7 +58,9 @@ struct i2c_algo_pca_data {
|
||||
int (*read_byte) (void *data, int reg);
|
||||
int (*wait_for_completion) (void *data);
|
||||
void (*reset_chip) (void *data);
|
||||
/* i2c_clock values are defined in linux/i2c-algo-pca.h */
|
||||
/* For PCA9564, use one of the predefined frequencies:
|
||||
* 330000, 288000, 217000, 146000, 88000, 59000, 44000, 36000
|
||||
* For PCA9665, use the frequency you want here. */
|
||||
unsigned int i2c_clock;
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,7 @@ struct i2c_pca9564_pf_platform_data {
|
||||
* not supplied (negative value), but it
|
||||
* cannot exit some error conditions then */
|
||||
int i2c_clock_speed; /* values are defined in linux/i2c-algo-pca.h */
|
||||
int timeout; /* timeout = this value * 10us */
|
||||
int timeout; /* timeout in jiffies */
|
||||
};
|
||||
|
||||
#endif /* I2C_PCA9564_PLATFORM_H */
|
||||
|
@ -1237,6 +1237,7 @@
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_22 0x0452
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_23 0x0453
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS 0x0542
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_24 0x054C
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_25 0x054D
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E
|
||||
@ -1247,11 +1248,14 @@
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_31 0x07DF
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS 0x0752
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_32 0x0760
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_33 0x0761
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_34 0x0762
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_35 0x0763
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS 0x07D8
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS 0x0AA2
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_36 0x0AB0
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_37 0x0AB1
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_38 0x0AB2
|
||||
@ -1475,6 +1479,7 @@
|
||||
#define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
|
||||
#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
|
||||
#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
|
||||
#define PCI_DEVICE_ID_SERVERWORKS_HT1100LD 0x0408
|
||||
|
||||
#define PCI_VENDOR_ID_SBE 0x1176
|
||||
#define PCI_DEVICE_ID_SBE_WANXL100 0x0301
|
||||
|
Loading…
Reference in New Issue
Block a user