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: (44 commits) i2c-s3c2410: Fix bug in releasing driver i2c-s3c2410: Fix I2C SDA to SCL setup time i2c: New i2c-tiny-usb bus driver i2c: Documentation update i2c: SPIN_LOCK_UNLOCKED cleanup i2c: Obsolete i2c-ixp2000, i2c-ixp4xx and scx200_i2c i2c: New Simtec I2C bus driver i2c: Bitbanging I2C bus driver using the GPIO API Use menuconfig objects - I2C i2c: Restore i2c_smbus_read_block_data i2c-pxa: Clean transaction stop i2c-algo-bit: Improve debugging i2c-algo-bit: Implement a 50/50 SCL duty cycle i2c-omap: Switch to static adapter numbering i2c: Blackfin Two Wire Interface driver i2c-algo-sgi: Comment and whitespace cleanups i2c: Make i2c_del_driver a void function i2c: Move i2c-isa-only exported symbol declarations i2c: Document i2c_new_device() i2c: Add i2c_new_probed_device() ... Fixed trivial conflict in Documentation/feature-removal-schedule.txt manually. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
commit
8d41f0e8d5
@ -190,18 +190,10 @@ Who: Jean Delvare <khali@linux-fr.org>
|
|||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
What: i2c_adapter.dev
|
What: i2c_adapter.list
|
||||||
i2c_adapter.list
|
|
||||||
When: July 2007
|
When: July 2007
|
||||||
Why: Superfluous, given i2c_adapter.class_dev:
|
Why: Superfluous, this list duplicates the one maintained by the driver
|
||||||
* The "dev" was a stand-in for the physical device node that legacy
|
core.
|
||||||
drivers would not have; but now it's almost always present. Any
|
|
||||||
remaining legacy drivers must upgrade (they now trigger warnings).
|
|
||||||
* The "list" duplicates class device children.
|
|
||||||
The delay in removing this is so upgraded lm_sensors and libsensors
|
|
||||||
can get deployed. (Removal causes minor changes in the sysfs layout,
|
|
||||||
notably the location of the adapter type name and parenting the i2c
|
|
||||||
client hardware directly from their controller.)
|
|
||||||
Who: Jean Delvare <khali@linux-fr.org>,
|
Who: Jean Delvare <khali@linux-fr.org>,
|
||||||
David Brownell <dbrownell@users.sourceforge.net>
|
David Brownell <dbrownell@users.sourceforge.net>
|
||||||
|
|
||||||
@ -331,3 +323,10 @@ Who: Cornelia Huck <cornelia.huck@de.ibm.com>
|
|||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
|
What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
|
||||||
|
When: September 2007
|
||||||
|
Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific
|
||||||
|
I2C-over-GPIO drivers.
|
||||||
|
Who: Jean Delvare <khali@linux-fr.org>
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
@ -9,6 +9,8 @@ Supported adapters:
|
|||||||
* nForce4 MCP-04 10de:0034
|
* nForce4 MCP-04 10de:0034
|
||||||
* nForce4 MCP51 10de:0264
|
* nForce4 MCP51 10de:0264
|
||||||
* nForce4 MCP55 10de:0368
|
* nForce4 MCP55 10de:0368
|
||||||
|
* nForce4 MCP61 10de:03EB
|
||||||
|
* nForce4 MCP65 10de:0446
|
||||||
|
|
||||||
Datasheet: not publicly available, but seems to be similar to the
|
Datasheet: not publicly available, but seems to be similar to the
|
||||||
AMD-8111 SMBus 2.0 adapter.
|
AMD-8111 SMBus 2.0 adapter.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Revision 6, 2005-11-20
|
Revision 7, 2007-04-19
|
||||||
Jean Delvare <khali@linux-fr.org>
|
Jean Delvare <khali@linux-fr.org>
|
||||||
Greg KH <greg@kroah.com>
|
Greg KH <greg@kroah.com>
|
||||||
|
|
||||||
@ -20,6 +20,10 @@ yours for best results.
|
|||||||
|
|
||||||
Technical changes:
|
Technical changes:
|
||||||
|
|
||||||
|
* [Driver type] Any driver that was relying on i2c-isa has to be
|
||||||
|
converted to a proper isa, platform or pci driver. This is not
|
||||||
|
covered by this guide.
|
||||||
|
|
||||||
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
|
||||||
Includes typically look like that:
|
Includes typically look like that:
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -27,12 +31,10 @@ Technical changes:
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-isa.h> /* for ISA drivers */
|
|
||||||
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||||
#include <linux/hwmon-sysfs.h>
|
#include <linux/hwmon-sysfs.h>
|
||||||
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
||||||
#include <linux/err.h> /* for class registration */
|
#include <linux/err.h> /* for class registration */
|
||||||
#include <asm/io.h> /* if you have I/O operations */
|
|
||||||
Please respect this inclusion order. Some extra headers may be
|
Please respect this inclusion order. Some extra headers may be
|
||||||
required for a given driver (e.g. "lm75.h").
|
required for a given driver (e.g. "lm75.h").
|
||||||
|
|
||||||
@ -69,20 +71,16 @@ Technical changes:
|
|||||||
sensors mailing list <lm-sensors@lm-sensors.org> by providing a
|
sensors mailing list <lm-sensors@lm-sensors.org> by providing a
|
||||||
patch to the Documentation/hwmon/sysfs-interface file.
|
patch to the Documentation/hwmon/sysfs-interface file.
|
||||||
|
|
||||||
* [Attach] For I2C drivers, the attach function should make sure
|
* [Attach] The attach function should make sure that the adapter's
|
||||||
that the adapter's class has I2C_CLASS_HWMON (or whatever class is
|
class has I2C_CLASS_HWMON (or whatever class is suitable for your
|
||||||
suitable for your driver), using the following construct:
|
driver), using the following construct:
|
||||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||||
return 0;
|
return 0;
|
||||||
ISA-only drivers of course don't need this.
|
|
||||||
Call i2c_probe() instead of i2c_detect().
|
Call i2c_probe() instead of i2c_detect().
|
||||||
|
|
||||||
* [Detect] As mentioned earlier, the flags parameter is gone.
|
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||||
The type_name and client_name strings are replaced by a single
|
The type_name and client_name strings are replaced by a single
|
||||||
name string, which will be filled with a lowercase, short string.
|
name string, which will be filled with a lowercase, short string.
|
||||||
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
|
|
||||||
useless. Same for isa-only drivers, as the test would always be
|
|
||||||
true. Only hybrid drivers (which are quite rare) still need it.
|
|
||||||
The labels used for error paths are reduced to the number needed.
|
The labels used for error paths are reduced to the number needed.
|
||||||
It is advised that the labels are given descriptive names such as
|
It is advised that the labels are given descriptive names such as
|
||||||
exit and exit_free. Don't forget to properly set err before
|
exit and exit_free. Don't forget to properly set err before
|
||||||
|
@ -4,17 +4,23 @@ I2C and SMBus
|
|||||||
=============
|
=============
|
||||||
|
|
||||||
I2C (pronounce: I squared C) is a protocol developed by Philips. It is a
|
I2C (pronounce: I squared C) is a protocol developed by Philips. It is a
|
||||||
slow two-wire protocol (10-400 kHz), but it suffices for many types of
|
slow two-wire protocol (variable speed, up to 400 kHz), with a high speed
|
||||||
devices.
|
extension (3.4 MHz). It provides an inexpensive bus for connecting many
|
||||||
|
types of devices with infrequent or low bandwidth communications needs.
|
||||||
|
I2C is widely used with embedded systems. Some systems use variants that
|
||||||
|
don't meet branding requirements, and so are not advertised as being I2C.
|
||||||
|
|
||||||
SMBus (System Management Bus) is a subset of the I2C protocol. Many
|
SMBus (System Management Bus) is based on the I2C protocol, and is mostly
|
||||||
modern mainboards have a System Management Bus. There are a lot of
|
a subset of I2C protocols and signaling. Many I2C devices will work on an
|
||||||
devices which can be connected to a SMBus; the most notable are modern
|
SMBus, but some SMBus protocols add semantics beyond what is required to
|
||||||
memory chips with EEPROM memories and chips for hardware monitoring.
|
achieve I2C branding. Modern PC mainboards rely on SMBus. The most common
|
||||||
|
devices connected through SMBus are RAM modules configured using I2C EEPROMs,
|
||||||
|
and hardware monitoring chips.
|
||||||
|
|
||||||
Because the SMBus is just a special case of the generalized I2C bus, we
|
Because the SMBus is mostly a subset of the generalized I2C bus, we can
|
||||||
can simulate the SMBus protocol on plain I2C busses. The reverse is
|
use its protocols on many I2C systems. However, there are systems that don't
|
||||||
regretfully impossible.
|
meet both SMBus and I2C electrical constraints; and others which can't
|
||||||
|
implement all the common SMBus protocol semantics or messages.
|
||||||
|
|
||||||
|
|
||||||
Terminology
|
Terminology
|
||||||
@ -29,6 +35,7 @@ When we talk about I2C, we use the following terms:
|
|||||||
An Algorithm driver contains general code that can be used for a whole class
|
An Algorithm driver contains general code that can be used for a whole class
|
||||||
of I2C adapters. Each specific adapter driver depends on one algorithm
|
of I2C adapters. Each specific adapter driver depends on one algorithm
|
||||||
driver.
|
driver.
|
||||||
|
|
||||||
A Driver driver (yes, this sounds ridiculous, sorry) contains the general
|
A Driver driver (yes, this sounds ridiculous, sorry) contains the general
|
||||||
code to access some type of device. Each detected device gets its own
|
code to access some type of device. Each detected device gets its own
|
||||||
data in the Client structure. Usually, Driver and Client are more closely
|
data in the Client structure. Usually, Driver and Client are more closely
|
||||||
@ -40,6 +47,10 @@ a separate Adapter and Algorithm driver), and drivers for your I2C devices
|
|||||||
in this package. See the lm_sensors project http://www.lm-sensors.nu
|
in this package. See the lm_sensors project http://www.lm-sensors.nu
|
||||||
for device drivers.
|
for device drivers.
|
||||||
|
|
||||||
|
At this time, Linux only operates I2C (or SMBus) in master mode; you can't
|
||||||
|
use these APIs to make a Linux system behave as a slave/device, either to
|
||||||
|
speak a custom protocol or to emulate some other device.
|
||||||
|
|
||||||
|
|
||||||
Included Bus Drivers
|
Included Bus Drivers
|
||||||
====================
|
====================
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
This is a small guide for those who want to write kernel drivers for I2C
|
This is a small guide for those who want to write kernel drivers for I2C
|
||||||
or SMBus devices.
|
or SMBus devices, using Linux as the protocol host/master (not slave).
|
||||||
|
|
||||||
To set up a driver, you need to do several things. Some are optional, and
|
To set up a driver, you need to do several things. Some are optional, and
|
||||||
some things can be done slightly or completely different. Use this as a
|
some things can be done slightly or completely different. Use this as a
|
||||||
@ -29,8 +29,16 @@ static struct i2c_driver foo_driver = {
|
|||||||
.driver = {
|
.driver = {
|
||||||
.name = "foo",
|
.name = "foo",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* iff driver uses driver model ("new style") binding model: */
|
||||||
|
.probe = foo_probe,
|
||||||
|
.remove = foo_remove,
|
||||||
|
|
||||||
|
/* else, driver uses "legacy" binding model: */
|
||||||
.attach_adapter = foo_attach_adapter,
|
.attach_adapter = foo_attach_adapter,
|
||||||
.detach_client = foo_detach_client,
|
.detach_client = foo_detach_client,
|
||||||
|
|
||||||
|
/* these may be used regardless of the driver binding model */
|
||||||
.shutdown = foo_shutdown, /* optional */
|
.shutdown = foo_shutdown, /* optional */
|
||||||
.suspend = foo_suspend, /* optional */
|
.suspend = foo_suspend, /* optional */
|
||||||
.resume = foo_resume, /* optional */
|
.resume = foo_resume, /* optional */
|
||||||
@ -40,7 +48,8 @@ static struct i2c_driver foo_driver = {
|
|||||||
The name field is the driver name, and must not contain spaces. It
|
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),
|
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
|
although you can use MODULE_ALIAS (passing "foo" in this example) to add
|
||||||
another name for the module.
|
another name for the module. If the driver name doesn't match the module
|
||||||
|
name, the module won't be automatically loaded (hotplug/coldplug).
|
||||||
|
|
||||||
All other fields are for call-back functions which will be explained
|
All other fields are for call-back functions which will be explained
|
||||||
below.
|
below.
|
||||||
@ -65,16 +74,13 @@ An example structure is below.
|
|||||||
|
|
||||||
struct foo_data {
|
struct foo_data {
|
||||||
struct i2c_client client;
|
struct i2c_client client;
|
||||||
struct semaphore lock; /* For ISA access in `sensors' drivers. */
|
|
||||||
int sysctl_id; /* To keep the /proc directory entry for
|
|
||||||
`sensors' drivers. */
|
|
||||||
enum chips type; /* To keep the chips type for `sensors' drivers. */
|
enum chips type; /* To keep the chips type for `sensors' drivers. */
|
||||||
|
|
||||||
/* Because the i2c bus is slow, it is often useful to cache the read
|
/* Because the i2c bus is slow, it is often useful to cache the read
|
||||||
information of a chip for some time (for example, 1 or 2 seconds).
|
information of a chip for some time (for example, 1 or 2 seconds).
|
||||||
It depends of course on the device whether this is really worthwhile
|
It depends of course on the device whether this is really worthwhile
|
||||||
or even sensible. */
|
or even sensible. */
|
||||||
struct semaphore update_lock; /* When we are reading lots of information,
|
struct mutex update_lock; /* When we are reading lots of information,
|
||||||
another process should not update the
|
another process should not update the
|
||||||
below information */
|
below information */
|
||||||
char valid; /* != 0 if the following fields are valid. */
|
char valid; /* != 0 if the following fields are valid. */
|
||||||
@ -95,8 +101,7 @@ some obscure clients). But we need generic reading and writing routines.
|
|||||||
I have found it useful to define foo_read and foo_write function for this.
|
I have found it useful to define foo_read and foo_write function for this.
|
||||||
For some cases, it will be easier to call the i2c functions directly,
|
For some cases, it will be easier to call the i2c functions directly,
|
||||||
but many chips have some kind of register-value idea that can easily
|
but many chips have some kind of register-value idea that can easily
|
||||||
be encapsulated. Also, some chips have both ISA and I2C interfaces, and
|
be encapsulated.
|
||||||
it useful to abstract from this (only for `sensors' drivers).
|
|
||||||
|
|
||||||
The below functions are simple examples, and should not be copied
|
The below functions are simple examples, and should not be copied
|
||||||
literally.
|
literally.
|
||||||
@ -119,28 +124,101 @@ literally.
|
|||||||
return i2c_smbus_write_word_data(client,reg,value);
|
return i2c_smbus_write_word_data(client,reg,value);
|
||||||
}
|
}
|
||||||
|
|
||||||
For sensors code, you may have to cope with ISA registers too. Something
|
|
||||||
like the below often works. Note the locking!
|
|
||||||
|
|
||||||
int foo_read_value(struct i2c_client *client, u8 reg)
|
|
||||||
{
|
|
||||||
int res;
|
|
||||||
if (i2c_is_isa_client(client)) {
|
|
||||||
down(&(((struct foo_data *) (client->data)) -> lock));
|
|
||||||
outb_p(reg,client->addr + FOO_ADDR_REG_OFFSET);
|
|
||||||
res = inb_p(client->addr + FOO_DATA_REG_OFFSET);
|
|
||||||
up(&(((struct foo_data *) (client->data)) -> lock));
|
|
||||||
return res;
|
|
||||||
} else
|
|
||||||
return i2c_smbus_read_byte_data(client,reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
Writing is done the same way.
|
|
||||||
|
|
||||||
|
|
||||||
Probing and attaching
|
Probing and attaching
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
The Linux I2C stack was originally written to support access to hardware
|
||||||
|
monitoring chips on PC motherboards, and thus it embeds some assumptions
|
||||||
|
that are more appropriate to SMBus (and PCs) than to I2C. One of these
|
||||||
|
assumptions is that most adapters and devices drivers support the SMBUS_QUICK
|
||||||
|
protocol to probe device presence. Another is that devices and their drivers
|
||||||
|
can be sufficiently configured using only such probe primitives.
|
||||||
|
|
||||||
|
As Linux and its I2C stack became more widely used in embedded systems
|
||||||
|
and complex components such as DVB adapters, those assumptions became more
|
||||||
|
problematic. Drivers for I2C devices that issue interrupts need more (and
|
||||||
|
different) configuration information, as do drivers handling chip variants
|
||||||
|
that can't be distinguished by protocol probing, or which need some board
|
||||||
|
specific information to operate correctly.
|
||||||
|
|
||||||
|
Accordingly, the I2C stack now has two models for associating I2C devices
|
||||||
|
with their drivers: the original "legacy" model, and a newer one that's
|
||||||
|
fully compatible with the Linux 2.6 driver model. These models do not mix,
|
||||||
|
since the "legacy" model requires drivers to create "i2c_client" device
|
||||||
|
objects after SMBus style probing, while the Linux driver model expects
|
||||||
|
drivers to be given such device objects in their probe() routines.
|
||||||
|
|
||||||
|
|
||||||
|
Standard Driver Model Binding ("New Style")
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
System infrastructure, typically board-specific initialization code or
|
||||||
|
boot firmware, reports what I2C devices exist. For example, there may be
|
||||||
|
a table, in the kernel or from the boot loader, identifying I2C devices
|
||||||
|
and linking them to board-specific configuration information about IRQs
|
||||||
|
and other wiring artifacts, chip type, and so on. That could be used to
|
||||||
|
create i2c_client objects for each I2C device.
|
||||||
|
|
||||||
|
I2C device drivers using this binding model work just like any other
|
||||||
|
kind of driver in Linux: they provide a probe() method to bind to
|
||||||
|
those devices, and a remove() method to unbind.
|
||||||
|
|
||||||
|
static int foo_probe(struct i2c_client *client);
|
||||||
|
static int foo_remove(struct i2c_client *client);
|
||||||
|
|
||||||
|
Remember that the i2c_driver does not create those client handles. The
|
||||||
|
handle may be used during foo_probe(). If foo_probe() reports success
|
||||||
|
(zero not a negative status code) it may save the handle and use it until
|
||||||
|
foo_remove() returns. That binding model is used by most Linux drivers.
|
||||||
|
|
||||||
|
Drivers match devices when i2c_client.driver_name and the driver name are
|
||||||
|
the same; this approach is used in several other busses that don't have
|
||||||
|
device typing support in the hardware. The driver and module name should
|
||||||
|
match, so hotplug/coldplug mechanisms will modprobe the driver.
|
||||||
|
|
||||||
|
|
||||||
|
Device Creation (Standard driver model)
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
If you know for a fact that an I2C device is connected to a given I2C bus,
|
||||||
|
you can instantiate that device by simply filling an i2c_board_info
|
||||||
|
structure with the device address and driver name, and calling
|
||||||
|
i2c_new_device(). This will create the device, then the driver core will
|
||||||
|
take care of finding the right driver and will call its probe() method.
|
||||||
|
If a driver supports different device types, you can specify the type you
|
||||||
|
want using the type field. You can also specify an IRQ and platform data
|
||||||
|
if needed.
|
||||||
|
|
||||||
|
Sometimes you know that a device is connected to a given I2C bus, but you
|
||||||
|
don't know the exact address it uses. This happens on TV adapters for
|
||||||
|
example, where the same driver supports dozens of slightly different
|
||||||
|
models, and I2C device addresses change from one model to the next. In
|
||||||
|
that case, you can use the i2c_new_probed_device() variant, which is
|
||||||
|
similar to i2c_new_device(), except that it takes an additional list of
|
||||||
|
possible I2C addresses to probe. A device is created for the first
|
||||||
|
responsive address in the list. If you expect more than one device to be
|
||||||
|
present in the address range, simply call i2c_new_probed_device() that
|
||||||
|
many times.
|
||||||
|
|
||||||
|
The call to i2c_new_device() or i2c_new_probed_device() typically happens
|
||||||
|
in the I2C bus driver. You may want to save the returned i2c_client
|
||||||
|
reference for later use.
|
||||||
|
|
||||||
|
|
||||||
|
Device Deletion (Standard driver model)
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
Each I2C device which has been created using i2c_new_device() or
|
||||||
|
i2c_new_probed_device() can be unregistered by calling
|
||||||
|
i2c_unregister_device(). If you don't call it explicitly, it will be
|
||||||
|
called automatically before the underlying I2C bus itself is removed, as a
|
||||||
|
device can't survive its parent in the device driver model.
|
||||||
|
|
||||||
|
|
||||||
|
Legacy Driver Binding Model
|
||||||
|
---------------------------
|
||||||
|
|
||||||
Most i2c devices can be present on several i2c addresses; for some this
|
Most i2c devices can be present on several i2c addresses; for some this
|
||||||
is determined in hardware (by soldering some chip pins to Vcc or Ground),
|
is determined in hardware (by soldering some chip pins to Vcc or Ground),
|
||||||
for others this can be changed in software (by writing to specific client
|
for others this can be changed in software (by writing to specific client
|
||||||
@ -157,13 +235,9 @@ detection algorithm.
|
|||||||
You do not have to use this parameter interface; but don't try to use
|
You do not have to use this parameter interface; but don't try to use
|
||||||
function i2c_probe() if you don't.
|
function i2c_probe() if you don't.
|
||||||
|
|
||||||
NOTE: If you want to write a `sensors' driver, the interface is slightly
|
|
||||||
different! See below.
|
|
||||||
|
|
||||||
|
Probing classes (Legacy model)
|
||||||
|
------------------------------
|
||||||
Probing classes
|
|
||||||
---------------
|
|
||||||
|
|
||||||
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
||||||
terminated by I2C_CLIENT_END.
|
terminated by I2C_CLIENT_END.
|
||||||
@ -210,8 +284,8 @@ Note that you *have* to call the defined variable `normal_i2c',
|
|||||||
without any prefix!
|
without any prefix!
|
||||||
|
|
||||||
|
|
||||||
Attaching to an adapter
|
Attaching to an adapter (Legacy model)
|
||||||
-----------------------
|
--------------------------------------
|
||||||
|
|
||||||
Whenever a new adapter is inserted, or for all adapters if the driver is
|
Whenever a new adapter is inserted, or for all adapters if the driver is
|
||||||
being registered, the callback attach_adapter() is called. Now is the
|
being registered, the callback attach_adapter() is called. Now is the
|
||||||
@ -237,17 +311,13 @@ them (unless a `force' parameter was used). In addition, addresses that
|
|||||||
are already in use (by some other registered client) are skipped.
|
are already in use (by some other registered client) are skipped.
|
||||||
|
|
||||||
|
|
||||||
The detect client function
|
The detect client function (Legacy model)
|
||||||
--------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
The detect client function is called by i2c_probe. The `kind' parameter
|
The detect client function is called by i2c_probe. The `kind' parameter
|
||||||
contains -1 for a probed detection, 0 for a forced detection, or a positive
|
contains -1 for a probed detection, 0 for a forced detection, or a positive
|
||||||
number for a forced detection with a chip type forced.
|
number for a forced detection with a chip type forced.
|
||||||
|
|
||||||
Below, some things are only needed if this is a `sensors' driver. Those
|
|
||||||
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
|
|
||||||
markers.
|
|
||||||
|
|
||||||
Returning an error different from -ENODEV in a detect function will cause
|
Returning an error different from -ENODEV in a detect function will cause
|
||||||
the detection to stop: other addresses and adapters won't be scanned.
|
the detection to stop: other addresses and adapters won't be scanned.
|
||||||
This should only be done on fatal or internal errors, such as a memory
|
This should only be done on fatal or internal errors, such as a memory
|
||||||
@ -256,64 +326,20 @@ shortage or i2c_attach_client failing.
|
|||||||
For now, you can ignore the `flags' parameter. It is there for future use.
|
For now, you can ignore the `flags' parameter. It is there for future use.
|
||||||
|
|
||||||
int foo_detect_client(struct i2c_adapter *adapter, int address,
|
int foo_detect_client(struct i2c_adapter *adapter, int address,
|
||||||
unsigned short flags, int kind)
|
int kind)
|
||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int i;
|
int i;
|
||||||
struct i2c_client *new_client;
|
struct i2c_client *client;
|
||||||
struct foo_data *data;
|
struct foo_data *data;
|
||||||
const char *client_name = ""; /* For non-`sensors' drivers, put the real
|
const char *name = "";
|
||||||
name here! */
|
|
||||||
|
|
||||||
/* Let's see whether this adapter can support what we need.
|
/* Let's see whether this adapter can support what we need.
|
||||||
Please substitute the things you need here!
|
Please substitute the things you need here! */
|
||||||
For `sensors' drivers, add `! is_isa &&' to the if statement */
|
|
||||||
if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
|
if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
|
||||||
I2C_FUNC_SMBUS_WRITE_BYTE))
|
I2C_FUNC_SMBUS_WRITE_BYTE))
|
||||||
goto ERROR0;
|
goto ERROR0;
|
||||||
|
|
||||||
/* SENSORS ONLY START */
|
|
||||||
const char *type_name = "";
|
|
||||||
int is_isa = i2c_is_isa_adapter(adapter);
|
|
||||||
|
|
||||||
/* Do this only if the chip can additionally be found on the ISA bus
|
|
||||||
(hybrid chip). */
|
|
||||||
|
|
||||||
if (is_isa) {
|
|
||||||
|
|
||||||
/* Discard immediately if this ISA range is already used */
|
|
||||||
/* FIXME: never use check_region(), only request_region() */
|
|
||||||
if (check_region(address,FOO_EXTENT))
|
|
||||||
goto ERROR0;
|
|
||||||
|
|
||||||
/* Probe whether there is anything on this address.
|
|
||||||
Some example code is below, but you will have to adapt this
|
|
||||||
for your own driver */
|
|
||||||
|
|
||||||
if (kind < 0) /* Only if no force parameter was used */ {
|
|
||||||
/* We may need long timeouts at least for some chips. */
|
|
||||||
#define REALLY_SLOW_IO
|
|
||||||
i = inb_p(address + 1);
|
|
||||||
if (inb_p(address + 2) != i)
|
|
||||||
goto ERROR0;
|
|
||||||
if (inb_p(address + 3) != i)
|
|
||||||
goto ERROR0;
|
|
||||||
if (inb_p(address + 7) != i)
|
|
||||||
goto ERROR0;
|
|
||||||
#undef REALLY_SLOW_IO
|
|
||||||
|
|
||||||
/* Let's just hope nothing breaks here */
|
|
||||||
i = inb_p(address + 5) & 0x7f;
|
|
||||||
outb_p(~i & 0x7f,address+5);
|
|
||||||
if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
|
|
||||||
outb_p(i,address+5);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* SENSORS ONLY END */
|
|
||||||
|
|
||||||
/* OK. For now, we presume we have a valid client. We now create the
|
/* OK. For now, we presume we have a valid client. We now create the
|
||||||
client structure, even though we cannot fill it completely yet.
|
client structure, even though we cannot fill it completely yet.
|
||||||
But it allows us to access several i2c functions safely */
|
But it allows us to access several i2c functions safely */
|
||||||
@ -323,13 +349,12 @@ For now, you can ignore the `flags' parameter. It is there for future use.
|
|||||||
goto ERROR0;
|
goto ERROR0;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_client = &data->client;
|
client = &data->client;
|
||||||
i2c_set_clientdata(new_client, data);
|
i2c_set_clientdata(client, data);
|
||||||
|
|
||||||
new_client->addr = address;
|
client->addr = address;
|
||||||
new_client->adapter = adapter;
|
client->adapter = adapter;
|
||||||
new_client->driver = &foo_driver;
|
client->driver = &foo_driver;
|
||||||
new_client->flags = 0;
|
|
||||||
|
|
||||||
/* Now, we do the remaining detection. If no `force' parameter is used. */
|
/* Now, we do the remaining detection. If no `force' parameter is used. */
|
||||||
|
|
||||||
@ -337,19 +362,17 @@ For now, you can ignore the `flags' parameter. It is there for future use.
|
|||||||
parameter was used. */
|
parameter was used. */
|
||||||
if (kind < 0) {
|
if (kind < 0) {
|
||||||
/* The below is of course bogus */
|
/* The below is of course bogus */
|
||||||
if (foo_read(new_client,FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
|
if (foo_read(client, FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
|
||||||
goto ERROR1;
|
goto ERROR1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SENSORS ONLY START */
|
|
||||||
|
|
||||||
/* Next, specific detection. This is especially important for `sensors'
|
/* Next, specific detection. This is especially important for `sensors'
|
||||||
devices. */
|
devices. */
|
||||||
|
|
||||||
/* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
|
/* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
|
||||||
was used. */
|
was used. */
|
||||||
if (kind <= 0) {
|
if (kind <= 0) {
|
||||||
i = foo_read(new_client,FOO_REG_CHIPTYPE);
|
i = foo_read(client, FOO_REG_CHIPTYPE);
|
||||||
if (i == FOO_TYPE_1)
|
if (i == FOO_TYPE_1)
|
||||||
kind = chip1; /* As defined in the enum */
|
kind = chip1; /* As defined in the enum */
|
||||||
else if (i == FOO_TYPE_2)
|
else if (i == FOO_TYPE_2)
|
||||||
@ -363,63 +386,31 @@ For now, you can ignore the `flags' parameter. It is there for future use.
|
|||||||
|
|
||||||
/* Now set the type and chip names */
|
/* Now set the type and chip names */
|
||||||
if (kind == chip1) {
|
if (kind == chip1) {
|
||||||
type_name = "chip1"; /* For /proc entry */
|
name = "chip1";
|
||||||
client_name = "CHIP 1";
|
|
||||||
} else if (kind == chip2) {
|
} else if (kind == chip2) {
|
||||||
type_name = "chip2"; /* For /proc entry */
|
name = "chip2";
|
||||||
client_name = "CHIP 2";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reserve the ISA region */
|
|
||||||
if (is_isa)
|
|
||||||
request_region(address,FOO_EXTENT,type_name);
|
|
||||||
|
|
||||||
/* SENSORS ONLY END */
|
|
||||||
|
|
||||||
/* Fill in the remaining client fields. */
|
/* Fill in the remaining client fields. */
|
||||||
strcpy(new_client->name,client_name);
|
strlcpy(client->name, name, I2C_NAME_SIZE);
|
||||||
|
|
||||||
/* SENSORS ONLY BEGIN */
|
|
||||||
data->type = kind;
|
data->type = kind;
|
||||||
/* SENSORS ONLY END */
|
mutex_init(&data->update_lock); /* Only if you use this field */
|
||||||
|
|
||||||
data->valid = 0; /* Only if you use this field */
|
|
||||||
init_MUTEX(&data->update_lock); /* Only if you use this field */
|
|
||||||
|
|
||||||
/* Any other initializations in data must be done here too. */
|
/* Any other initializations in data must be done here too. */
|
||||||
|
|
||||||
/* Tell the i2c layer a new client has arrived */
|
|
||||||
if ((err = i2c_attach_client(new_client)))
|
|
||||||
goto ERROR3;
|
|
||||||
|
|
||||||
/* SENSORS ONLY BEGIN */
|
|
||||||
/* Register a new directory entry with module sensors. See below for
|
|
||||||
the `template' structure. */
|
|
||||||
if ((i = i2c_register_entry(new_client, type_name,
|
|
||||||
foo_dir_table_template,THIS_MODULE)) < 0) {
|
|
||||||
err = i;
|
|
||||||
goto ERROR4;
|
|
||||||
}
|
|
||||||
data->sysctl_id = i;
|
|
||||||
|
|
||||||
/* SENSORS ONLY END */
|
|
||||||
|
|
||||||
/* This function can write default values to the client registers, if
|
/* This function can write default values to the client registers, if
|
||||||
needed. */
|
needed. */
|
||||||
foo_init_client(new_client);
|
foo_init_client(client);
|
||||||
|
|
||||||
|
/* Tell the i2c layer a new client has arrived */
|
||||||
|
if ((err = i2c_attach_client(client)))
|
||||||
|
goto ERROR1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* OK, this is not exactly good programming practice, usually. But it is
|
/* OK, this is not exactly good programming practice, usually. But it is
|
||||||
very code-efficient in this case. */
|
very code-efficient in this case. */
|
||||||
|
|
||||||
ERROR4:
|
|
||||||
i2c_detach_client(new_client);
|
|
||||||
ERROR3:
|
|
||||||
ERROR2:
|
|
||||||
/* SENSORS ONLY START */
|
|
||||||
if (is_isa)
|
|
||||||
release_region(address,FOO_EXTENT);
|
|
||||||
/* SENSORS ONLY END */
|
|
||||||
ERROR1:
|
ERROR1:
|
||||||
kfree(data);
|
kfree(data);
|
||||||
ERROR0:
|
ERROR0:
|
||||||
@ -427,8 +418,8 @@ For now, you can ignore the `flags' parameter. It is there for future use.
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Removing the client
|
Removing the client (Legacy model)
|
||||||
===================
|
==================================
|
||||||
|
|
||||||
The detach_client call back function is called when a client should be
|
The detach_client call back function is called when a client should be
|
||||||
removed. It may actually fail, but only when panicking. This code is
|
removed. It may actually fail, but only when panicking. This code is
|
||||||
@ -436,22 +427,12 @@ much simpler than the attachment code, fortunately!
|
|||||||
|
|
||||||
int foo_detach_client(struct i2c_client *client)
|
int foo_detach_client(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
int err,i;
|
int err;
|
||||||
|
|
||||||
/* SENSORS ONLY START */
|
|
||||||
/* Deregister with the `i2c-proc' module. */
|
|
||||||
i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
|
|
||||||
/* SENSORS ONLY END */
|
|
||||||
|
|
||||||
/* Try to detach the client from i2c space */
|
/* Try to detach the client from i2c space */
|
||||||
if ((err = i2c_detach_client(client)))
|
if ((err = i2c_detach_client(client)))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* HYBRID SENSORS CHIP ONLY START */
|
|
||||||
if i2c_is_isa_client(client)
|
|
||||||
release_region(client->addr,LM78_EXTENT);
|
|
||||||
/* HYBRID SENSORS CHIP ONLY END */
|
|
||||||
|
|
||||||
kfree(i2c_get_clientdata(client));
|
kfree(i2c_get_clientdata(client));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -464,45 +445,34 @@ When the kernel is booted, or when your foo driver module is inserted,
|
|||||||
you have to do some initializing. Fortunately, just attaching (registering)
|
you have to do some initializing. Fortunately, just attaching (registering)
|
||||||
the driver module is usually enough.
|
the driver module is usually enough.
|
||||||
|
|
||||||
/* Keep track of how far we got in the initialization process. If several
|
|
||||||
things have to initialized, and we fail halfway, only those things
|
|
||||||
have to be cleaned up! */
|
|
||||||
static int __initdata foo_initialized = 0;
|
|
||||||
|
|
||||||
static int __init foo_init(void)
|
static int __init foo_init(void)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);
|
|
||||||
|
|
||||||
if ((res = i2c_add_driver(&foo_driver))) {
|
if ((res = i2c_add_driver(&foo_driver))) {
|
||||||
printk("foo: Driver registration failed, module not inserted.\n");
|
printk("foo: Driver registration failed, module not inserted.\n");
|
||||||
foo_cleanup();
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
foo_initialized ++;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void foo_cleanup(void)
|
static void __exit foo_cleanup(void)
|
||||||
{
|
{
|
||||||
if (foo_initialized == 1) {
|
i2c_del_driver(&foo_driver);
|
||||||
if ((res = i2c_del_driver(&foo_driver))) {
|
|
||||||
printk("foo: Driver registration failed, module not removed.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
foo_initialized --;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Substitute your own name and email address */
|
/* Substitute your own name and email address */
|
||||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
|
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
|
||||||
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
|
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
|
||||||
|
|
||||||
|
/* a few non-GPL license types are also allowed */
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
module_init(foo_init);
|
module_init(foo_init);
|
||||||
module_exit(foo_cleanup);
|
module_exit(foo_cleanup);
|
||||||
|
|
||||||
Note that some functions are marked by `__init', and some data structures
|
Note that some functions are marked by `__init', and some data structures
|
||||||
by `__init_data'. Hose functions and structures can be removed after
|
by `__initdata'. These functions and structures can be removed after
|
||||||
kernel booting (or module loading) is completed.
|
kernel booting (or module loading) is completed.
|
||||||
|
|
||||||
|
|
||||||
@ -632,110 +602,7 @@ General purpose routines
|
|||||||
Below all general purpose routines are listed, that were not mentioned
|
Below all general purpose routines are listed, that were not mentioned
|
||||||
before.
|
before.
|
||||||
|
|
||||||
/* This call returns a unique low identifier for each registered adapter,
|
/* This call returns a unique low identifier for each registered adapter.
|
||||||
* or -1 if the adapter was not registered.
|
|
||||||
*/
|
*/
|
||||||
extern int i2c_adapter_id(struct i2c_adapter *adap);
|
extern int i2c_adapter_id(struct i2c_adapter *adap);
|
||||||
|
|
||||||
|
|
||||||
The sensors sysctl/proc interface
|
|
||||||
=================================
|
|
||||||
|
|
||||||
This section only applies if you write `sensors' drivers.
|
|
||||||
|
|
||||||
Each sensors driver creates a directory in /proc/sys/dev/sensors for each
|
|
||||||
registered client. The directory is called something like foo-i2c-4-65.
|
|
||||||
The sensors module helps you to do this as easily as possible.
|
|
||||||
|
|
||||||
The template
|
|
||||||
------------
|
|
||||||
|
|
||||||
You will need to define a ctl_table template. This template will automatically
|
|
||||||
be copied to a newly allocated structure and filled in where necessary when
|
|
||||||
you call sensors_register_entry.
|
|
||||||
|
|
||||||
First, I will give an example definition.
|
|
||||||
static ctl_table foo_dir_table_template[] = {
|
|
||||||
{ FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real,
|
|
||||||
&i2c_sysctl_real,NULL,&foo_func },
|
|
||||||
{ FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &i2c_proc_real,
|
|
||||||
&i2c_sysctl_real,NULL,&foo_func },
|
|
||||||
{ FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &i2c_proc_real,
|
|
||||||
&i2c_sysctl_real,NULL,&foo_data },
|
|
||||||
{ 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
In the above example, three entries are defined. They can either be
|
|
||||||
accessed through the /proc interface, in the /proc/sys/dev/sensors/*
|
|
||||||
directories, as files named func1, func2 and data, or alternatively
|
|
||||||
through the sysctl interface, in the appropriate table, with identifiers
|
|
||||||
FOO_SYSCTL_FUNC1, FOO_SYSCTL_FUNC2 and FOO_SYSCTL_DATA.
|
|
||||||
|
|
||||||
The third, sixth and ninth parameters should always be NULL, and the
|
|
||||||
fourth should always be 0. The fifth is the mode of the /proc file;
|
|
||||||
0644 is safe, as the file will be owned by root:root.
|
|
||||||
|
|
||||||
The seventh and eighth parameters should be &i2c_proc_real and
|
|
||||||
&i2c_sysctl_real if you want to export lists of reals (scaled
|
|
||||||
integers). You can also use your own function for them, as usual.
|
|
||||||
Finally, the last parameter is the call-back to gather the data
|
|
||||||
(see below) if you use the *_proc_real functions.
|
|
||||||
|
|
||||||
|
|
||||||
Gathering the data
|
|
||||||
------------------
|
|
||||||
|
|
||||||
The call back functions (foo_func and foo_data in the above example)
|
|
||||||
can be called in several ways; the operation parameter determines
|
|
||||||
what should be done:
|
|
||||||
|
|
||||||
* If operation == SENSORS_PROC_REAL_INFO, you must return the
|
|
||||||
magnitude (scaling) in nrels_mag;
|
|
||||||
* If operation == SENSORS_PROC_REAL_READ, you must read information
|
|
||||||
from the chip and return it in results. The number of integers
|
|
||||||
to display should be put in nrels_mag;
|
|
||||||
* If operation == SENSORS_PROC_REAL_WRITE, you must write the
|
|
||||||
supplied information to the chip. nrels_mag will contain the number
|
|
||||||
of integers, results the integers themselves.
|
|
||||||
|
|
||||||
The *_proc_real functions will display the elements as reals for the
|
|
||||||
/proc interface. If you set the magnitude to 2, and supply 345 for
|
|
||||||
SENSORS_PROC_REAL_READ, it would display 3.45; and if the user would
|
|
||||||
write 45.6 to the /proc file, it would be returned as 4560 for
|
|
||||||
SENSORS_PROC_REAL_WRITE. A magnitude may even be negative!
|
|
||||||
|
|
||||||
An example function:
|
|
||||||
|
|
||||||
/* FOO_FROM_REG and FOO_TO_REG translate between scaled values and
|
|
||||||
register values. Note the use of the read cache. */
|
|
||||||
void foo_in(struct i2c_client *client, int operation, int ctl_name,
|
|
||||||
int *nrels_mag, long *results)
|
|
||||||
{
|
|
||||||
struct foo_data *data = client->data;
|
|
||||||
int nr = ctl_name - FOO_SYSCTL_FUNC1; /* reduce to 0 upwards */
|
|
||||||
|
|
||||||
if (operation == SENSORS_PROC_REAL_INFO)
|
|
||||||
*nrels_mag = 2;
|
|
||||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
|
||||||
/* Update the readings cache (if necessary) */
|
|
||||||
foo_update_client(client);
|
|
||||||
/* Get the readings from the cache */
|
|
||||||
results[0] = FOO_FROM_REG(data->foo_func_base[nr]);
|
|
||||||
results[1] = FOO_FROM_REG(data->foo_func_more[nr]);
|
|
||||||
results[2] = FOO_FROM_REG(data->foo_func_readonly[nr]);
|
|
||||||
*nrels_mag = 2;
|
|
||||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
|
||||||
if (*nrels_mag >= 1) {
|
|
||||||
/* Update the cache */
|
|
||||||
data->foo_base[nr] = FOO_TO_REG(results[0]);
|
|
||||||
/* Update the chip */
|
|
||||||
foo_write_value(client,FOO_REG_FUNC_BASE(nr),data->foo_base[nr]);
|
|
||||||
}
|
|
||||||
if (*nrels_mag >= 2) {
|
|
||||||
/* Update the cache */
|
|
||||||
data->foo_more[nr] = FOO_TO_REG(results[1]);
|
|
||||||
/* Update the chip */
|
|
||||||
foo_write_value(client,FOO_REG_FUNC_MORE(nr),data->foo_more[nr]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
19
MAINTAINERS
19
MAINTAINERS
@ -733,6 +733,13 @@ M: tigran@aivazian.fsnet.co.uk
|
|||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
BLACKFIN I2C TWI DRIVER
|
||||||
|
P: Sonic Zhang
|
||||||
|
M: sonic.zhang@analog.com
|
||||||
|
L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
|
||||||
|
W: http://blackfin.uclinux.org/
|
||||||
|
S: Supported
|
||||||
|
|
||||||
BLOCK LAYER
|
BLOCK LAYER
|
||||||
P: Jens Axboe
|
P: Jens Axboe
|
||||||
M: axboe@kernel.dk
|
M: axboe@kernel.dk
|
||||||
@ -1459,6 +1466,11 @@ L: linux-scsi@vger.kernel.org
|
|||||||
W: http://www.icp-vortex.com/
|
W: http://www.icp-vortex.com/
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
|
GENERIC GPIO I2C DRIVER
|
||||||
|
P: Haavard Skinnemoen
|
||||||
|
M: hskinnemoen@atmel.com
|
||||||
|
S: Supported
|
||||||
|
|
||||||
GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
|
GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
|
||||||
P: Krzysztof Halasa
|
P: Krzysztof Halasa
|
||||||
M: khc@pm.waw.pl
|
M: khc@pm.waw.pl
|
||||||
@ -1631,6 +1643,13 @@ L: i2c@lm-sensors.org
|
|||||||
T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
|
T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
I2C-TINY-USB DRIVER
|
||||||
|
P: Till Harbaum
|
||||||
|
M: till@harbaum.org
|
||||||
|
L: i2c@lm-sensors.org
|
||||||
|
T: http://www.harbaum.org/till/i2c_tiny_usb
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
i386 BOOT CODE
|
i386 BOOT CODE
|
||||||
P: Riley H. Williams
|
P: Riley H. Williams
|
||||||
M: Riley@Williams.Name
|
M: Riley@Williams.Name
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include <linux/cpufreq.h>
|
#include <linux/cpufreq.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/sysdev.h>
|
#include <linux/sysdev.h>
|
||||||
#include <linux/i2c.h>
|
|
||||||
#include <linux/hardirq.h>
|
#include <linux/hardirq.h>
|
||||||
#include <asm/prom.h>
|
#include <asm/prom.h>
|
||||||
#include <asm/machdep.h>
|
#include <asm/machdep.h>
|
||||||
|
@ -58,7 +58,7 @@ obj-$(CONFIG_GAMEPORT) += input/gameport/
|
|||||||
obj-$(CONFIG_INPUT) += input/
|
obj-$(CONFIG_INPUT) += input/
|
||||||
obj-$(CONFIG_I2O) += message/
|
obj-$(CONFIG_I2O) += message/
|
||||||
obj-$(CONFIG_RTC_LIB) += rtc/
|
obj-$(CONFIG_RTC_LIB) += rtc/
|
||||||
obj-$(CONFIG_I2C) += i2c/
|
obj-y += i2c/
|
||||||
obj-$(CONFIG_W1) += w1/
|
obj-$(CONFIG_W1) += w1/
|
||||||
obj-$(CONFIG_HWMON) += hwmon/
|
obj-$(CONFIG_HWMON) += hwmon/
|
||||||
obj-$(CONFIG_PHONE) += telephony/
|
obj-$(CONFIG_PHONE) += telephony/
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
# I2C subsystem configuration
|
# I2C subsystem configuration
|
||||||
#
|
#
|
||||||
|
|
||||||
menu "I2C support"
|
menuconfig I2C
|
||||||
|
|
||||||
config I2C
|
|
||||||
tristate "I2C support"
|
tristate "I2C support"
|
||||||
---help---
|
---help---
|
||||||
I2C (pronounce: I-square-C) is a slow serial bus protocol used in
|
I2C (pronounce: I-square-C) is a slow serial bus protocol used in
|
||||||
@ -22,9 +20,14 @@ config I2C
|
|||||||
This I2C support can also be built as a module. If so, the module
|
This I2C support can also be built as a module. If so, the module
|
||||||
will be called i2c-core.
|
will be called i2c-core.
|
||||||
|
|
||||||
|
if I2C
|
||||||
|
|
||||||
|
config I2C_BOARDINFO
|
||||||
|
boolean
|
||||||
|
default y
|
||||||
|
|
||||||
config I2C_CHARDEV
|
config I2C_CHARDEV
|
||||||
tristate "I2C device interface"
|
tristate "I2C device interface"
|
||||||
depends on I2C
|
|
||||||
help
|
help
|
||||||
Say Y here to use i2c-* device files, usually found in the /dev
|
Say Y here to use i2c-* device files, usually found in the /dev
|
||||||
directory on your system. They make it possible to have user-space
|
directory on your system. They make it possible to have user-space
|
||||||
@ -40,7 +43,6 @@ source drivers/i2c/chips/Kconfig
|
|||||||
|
|
||||||
config I2C_DEBUG_CORE
|
config I2C_DEBUG_CORE
|
||||||
bool "I2C Core debugging messages"
|
bool "I2C Core debugging messages"
|
||||||
depends on I2C
|
|
||||||
help
|
help
|
||||||
Say Y here if you want the I2C core to produce a bunch of debug
|
Say Y here if you want the I2C core to produce a bunch of debug
|
||||||
messages to the system log. Select this if you are having a
|
messages to the system log. Select this if you are having a
|
||||||
@ -48,7 +50,6 @@ config I2C_DEBUG_CORE
|
|||||||
|
|
||||||
config I2C_DEBUG_ALGO
|
config I2C_DEBUG_ALGO
|
||||||
bool "I2C Algorithm debugging messages"
|
bool "I2C Algorithm debugging messages"
|
||||||
depends on I2C
|
|
||||||
help
|
help
|
||||||
Say Y here if you want the I2C algorithm drivers to produce a bunch
|
Say Y here if you want the I2C algorithm drivers to produce a bunch
|
||||||
of debug messages to the system log. Select this if you are having
|
of debug messages to the system log. Select this if you are having
|
||||||
@ -57,7 +58,6 @@ config I2C_DEBUG_ALGO
|
|||||||
|
|
||||||
config I2C_DEBUG_BUS
|
config I2C_DEBUG_BUS
|
||||||
bool "I2C Bus debugging messages"
|
bool "I2C Bus debugging messages"
|
||||||
depends on I2C
|
|
||||||
help
|
help
|
||||||
Say Y here if you want the I2C bus drivers to produce a bunch of
|
Say Y here if you want the I2C bus drivers to produce a bunch of
|
||||||
debug messages to the system log. Select this if you are having
|
debug messages to the system log. Select this if you are having
|
||||||
@ -66,12 +66,10 @@ config I2C_DEBUG_BUS
|
|||||||
|
|
||||||
config I2C_DEBUG_CHIP
|
config I2C_DEBUG_CHIP
|
||||||
bool "I2C Chip debugging messages"
|
bool "I2C Chip debugging messages"
|
||||||
depends on I2C
|
|
||||||
help
|
help
|
||||||
Say Y here if you want the I2C chip drivers to produce a bunch of
|
Say Y here if you want the I2C chip drivers to produce a bunch of
|
||||||
debug messages to the system log. Select this if you are having
|
debug messages to the system log. Select this if you are having
|
||||||
a problem with I2C support and want to see more of what is going
|
a problem with I2C support and want to see more of what is going
|
||||||
on.
|
on.
|
||||||
|
|
||||||
endmenu
|
endif # I2C
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
# Makefile for the i2c core.
|
# Makefile for the i2c core.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
|
||||||
obj-$(CONFIG_I2C) += i2c-core.o
|
obj-$(CONFIG_I2C) += i2c-core.o
|
||||||
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
|
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
|
||||||
obj-y += busses/ chips/ algos/
|
obj-y += busses/ chips/ algos/
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
menu "I2C Algorithms"
|
menu "I2C Algorithms"
|
||||||
depends on I2C
|
|
||||||
|
|
||||||
config I2C_ALGOBIT
|
config I2C_ALGOBIT
|
||||||
tristate "I2C bit-banging interfaces"
|
tristate "I2C bit-banging interfaces"
|
||||||
depends on I2C
|
|
||||||
help
|
help
|
||||||
This allows you to use a range of I2C adapters called bit-banging
|
This allows you to use a range of I2C adapters called bit-banging
|
||||||
adapters. Say Y if you own an I2C adapter belonging to this class
|
adapters. Say Y if you own an I2C adapter belonging to this class
|
||||||
@ -18,7 +16,6 @@ config I2C_ALGOBIT
|
|||||||
|
|
||||||
config I2C_ALGOPCF
|
config I2C_ALGOPCF
|
||||||
tristate "I2C PCF 8584 interfaces"
|
tristate "I2C PCF 8584 interfaces"
|
||||||
depends on I2C
|
|
||||||
help
|
help
|
||||||
This allows you to use a range of I2C adapters called PCF adapters.
|
This allows you to use a range of I2C adapters called PCF adapters.
|
||||||
Say Y if you own an I2C adapter belonging to this class and then say
|
Say Y if you own an I2C adapter belonging to this class and then say
|
||||||
@ -29,7 +26,6 @@ config I2C_ALGOPCF
|
|||||||
|
|
||||||
config I2C_ALGOPCA
|
config I2C_ALGOPCA
|
||||||
tristate "I2C PCA 9564 interfaces"
|
tristate "I2C PCA 9564 interfaces"
|
||||||
depends on I2C
|
|
||||||
help
|
help
|
||||||
This allows you to use a range of I2C adapters called PCA adapters.
|
This allows you to use a range of I2C adapters called PCA adapters.
|
||||||
Say Y if you own an I2C adapter belonging to this class and then say
|
Say Y if you own an I2C adapter belonging to this class and then say
|
||||||
@ -40,11 +36,11 @@ config I2C_ALGOPCA
|
|||||||
|
|
||||||
config I2C_ALGO8XX
|
config I2C_ALGO8XX
|
||||||
tristate "MPC8xx CPM I2C interface"
|
tristate "MPC8xx CPM I2C interface"
|
||||||
depends on 8xx && I2C
|
depends on 8xx
|
||||||
|
|
||||||
config I2C_ALGO_SGI
|
config I2C_ALGO_SGI
|
||||||
tristate "I2C SGI interfaces"
|
tristate "I2C SGI interfaces"
|
||||||
depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)
|
depends on SGI_IP22 || SGI_IP32 || X86_VISWS
|
||||||
help
|
help
|
||||||
Supports the SGI interfaces like the ones found on SGI Indy VINO
|
Supports the SGI interfaces like the ones found on SGI Indy VINO
|
||||||
or SGI O2 MACE.
|
or SGI O2 MACE.
|
||||||
|
@ -33,19 +33,30 @@
|
|||||||
|
|
||||||
|
|
||||||
/* ----- global defines ----------------------------------------------- */
|
/* ----- global defines ----------------------------------------------- */
|
||||||
#define DEB(x) if (i2c_debug>=1) x;
|
|
||||||
#define DEB2(x) if (i2c_debug>=2) x;
|
|
||||||
#define DEBSTAT(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 */
|
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#define bit_dbg(level, dev, format, args...) \
|
||||||
|
do { \
|
||||||
|
if (i2c_debug >= level) \
|
||||||
|
dev_dbg(dev, format, ##args); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
#define bit_dbg(level, dev, format, args...) \
|
||||||
|
do {} while (0)
|
||||||
|
#endif /* DEBUG */
|
||||||
|
|
||||||
/* ----- global variables --------------------------------------------- */
|
/* ----- global variables --------------------------------------------- */
|
||||||
|
|
||||||
/* module parameters:
|
|
||||||
*/
|
|
||||||
static int i2c_debug;
|
|
||||||
static int bit_test; /* see if the line-setting functions work */
|
static int bit_test; /* see if the line-setting functions work */
|
||||||
|
module_param(bit_test, bool, 0);
|
||||||
|
MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
static int i2c_debug = 1;
|
||||||
|
module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
|
||||||
|
MODULE_PARM_DESC(i2c_debug,
|
||||||
|
"debug level - 0 off; 1 normal; 2 verbose; 3 very verbose");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* --- setting states on the bus with the right timing: --------------- */
|
/* --- setting states on the bus with the right timing: --------------- */
|
||||||
|
|
||||||
@ -57,19 +68,19 @@ static int bit_test; /* see if the line-setting functions work */
|
|||||||
static inline void sdalo(struct i2c_algo_bit_data *adap)
|
static inline void sdalo(struct i2c_algo_bit_data *adap)
|
||||||
{
|
{
|
||||||
setsda(adap,0);
|
setsda(adap,0);
|
||||||
udelay(adap->udelay);
|
udelay((adap->udelay + 1) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void sdahi(struct i2c_algo_bit_data *adap)
|
static inline void sdahi(struct i2c_algo_bit_data *adap)
|
||||||
{
|
{
|
||||||
setsda(adap,1);
|
setsda(adap,1);
|
||||||
udelay(adap->udelay);
|
udelay((adap->udelay + 1) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void scllo(struct i2c_algo_bit_data *adap)
|
static inline void scllo(struct i2c_algo_bit_data *adap)
|
||||||
{
|
{
|
||||||
setscl(adap,0);
|
setscl(adap,0);
|
||||||
udelay(adap->udelay);
|
udelay(adap->udelay / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -98,7 +109,11 @@ static int sclhi(struct i2c_algo_bit_data *adap)
|
|||||||
}
|
}
|
||||||
cond_resched();
|
cond_resched();
|
||||||
}
|
}
|
||||||
DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
|
#ifdef DEBUG
|
||||||
|
if (jiffies != start && i2c_debug >= 3)
|
||||||
|
pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go "
|
||||||
|
"high\n", jiffies - start);
|
||||||
|
#endif
|
||||||
|
|
||||||
done:
|
done:
|
||||||
udelay(adap->udelay);
|
udelay(adap->udelay);
|
||||||
@ -110,30 +125,29 @@ done:
|
|||||||
static void i2c_start(struct i2c_algo_bit_data *adap)
|
static void i2c_start(struct i2c_algo_bit_data *adap)
|
||||||
{
|
{
|
||||||
/* assert: scl, sda are high */
|
/* assert: scl, sda are high */
|
||||||
DEBPROTO(printk("S "));
|
setsda(adap, 0);
|
||||||
sdalo(adap);
|
udelay(adap->udelay);
|
||||||
scllo(adap);
|
scllo(adap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i2c_repstart(struct i2c_algo_bit_data *adap)
|
static void i2c_repstart(struct i2c_algo_bit_data *adap)
|
||||||
{
|
{
|
||||||
/* scl, sda may not be high */
|
/* assert: scl is low */
|
||||||
DEBPROTO(printk(" Sr "));
|
sdahi(adap);
|
||||||
setsda(adap,1);
|
|
||||||
sclhi(adap);
|
sclhi(adap);
|
||||||
|
setsda(adap, 0);
|
||||||
sdalo(adap);
|
udelay(adap->udelay);
|
||||||
scllo(adap);
|
scllo(adap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void i2c_stop(struct i2c_algo_bit_data *adap)
|
static void i2c_stop(struct i2c_algo_bit_data *adap)
|
||||||
{
|
{
|
||||||
DEBPROTO(printk("P\n"));
|
|
||||||
/* assert: scl is low */
|
/* assert: scl is low */
|
||||||
sdalo(adap);
|
sdalo(adap);
|
||||||
sclhi(adap);
|
sclhi(adap);
|
||||||
sdahi(adap);
|
setsda(adap, 1);
|
||||||
|
udelay(adap->udelay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -145,7 +159,7 @@ static void i2c_stop(struct i2c_algo_bit_data *adap)
|
|||||||
* 0 if the device did not ack
|
* 0 if the device did not ack
|
||||||
* -ETIMEDOUT if an error occurred (while raising the scl line)
|
* -ETIMEDOUT if an error occurred (while raising the scl line)
|
||||||
*/
|
*/
|
||||||
static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
|
static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int sb;
|
int sb;
|
||||||
@ -154,34 +168,32 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
|
|||||||
|
|
||||||
/* assert: scl is low */
|
/* assert: scl is low */
|
||||||
for ( i=7 ; i>=0 ; i-- ) {
|
for ( i=7 ; i>=0 ; i-- ) {
|
||||||
sb = c & ( 1 << i );
|
sb = (c >> i) & 1;
|
||||||
setsda(adap,sb);
|
setsda(adap,sb);
|
||||||
udelay(adap->udelay);
|
udelay((adap->udelay + 1) / 2);
|
||||||
DEBPROTO(printk(KERN_DEBUG "%d",sb!=0));
|
|
||||||
if (sclhi(adap)<0) { /* timed out */
|
if (sclhi(adap)<0) { /* timed out */
|
||||||
sdahi(adap); /* we don't want to block the net */
|
bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
|
||||||
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i));
|
"timeout at bit #%d\n", (int)c, i);
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
};
|
};
|
||||||
/* do arbitration here:
|
/* do arbitration here:
|
||||||
* if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
|
* if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
|
||||||
*/
|
*/
|
||||||
setscl(adap, 0 );
|
scllo(adap);
|
||||||
udelay(adap->udelay);
|
|
||||||
}
|
}
|
||||||
sdahi(adap);
|
sdahi(adap);
|
||||||
if (sclhi(adap)<0){ /* timeout */
|
if (sclhi(adap)<0){ /* timeout */
|
||||||
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff));
|
bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
|
||||||
|
"timeout at ack\n", (int)c);
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
};
|
};
|
||||||
/* read ack: SDA should be pulled down by slave */
|
/* read ack: SDA should be pulled down by slave */
|
||||||
ack=getsda(adap); /* ack: sda is pulled low ->success. */
|
ack = !getsda(adap); /* ack: sda is pulled low -> success */
|
||||||
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack));
|
bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
|
||||||
|
ack ? "A" : "NA");
|
||||||
|
|
||||||
DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) );
|
|
||||||
DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") );
|
|
||||||
scllo(adap);
|
scllo(adap);
|
||||||
return 0==ack; /* return 1 if device acked */
|
return ack;
|
||||||
/* assert: scl is low (sda undef) */
|
/* assert: scl is low (sda undef) */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,19 +210,18 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
|
|||||||
sdahi(adap);
|
sdahi(adap);
|
||||||
for (i=0;i<8;i++) {
|
for (i=0;i<8;i++) {
|
||||||
if (sclhi(adap)<0) { /* timeout */
|
if (sclhi(adap)<0) { /* timeout */
|
||||||
DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i));
|
bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
|
||||||
|
"#%d\n", 7 - i);
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
};
|
};
|
||||||
indata *= 2;
|
indata *= 2;
|
||||||
if ( getsda(adap) )
|
if ( getsda(adap) )
|
||||||
indata |= 0x01;
|
indata |= 0x01;
|
||||||
scllo(adap);
|
setscl(adap, 0);
|
||||||
|
udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
|
||||||
}
|
}
|
||||||
/* assert: scl is low */
|
/* assert: scl is low */
|
||||||
DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff));
|
return indata;
|
||||||
|
|
||||||
DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff));
|
|
||||||
return (int) (indata & 0xff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -221,73 +232,67 @@ static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
|
|||||||
int scl,sda;
|
int scl,sda;
|
||||||
|
|
||||||
if (adap->getscl==NULL)
|
if (adap->getscl==NULL)
|
||||||
printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, "
|
pr_info("%s: Testing SDA only, SCL is not readable\n", name);
|
||||||
"SCL is not readable.\n");
|
|
||||||
|
|
||||||
sda=getsda(adap);
|
sda=getsda(adap);
|
||||||
scl=(adap->getscl==NULL?1:getscl(adap));
|
scl=(adap->getscl==NULL?1:getscl(adap));
|
||||||
printk(KERN_DEBUG "i2c-algo-bit.o: (0) scl=%d, sda=%d\n",scl,sda);
|
|
||||||
if (!scl || !sda ) {
|
if (!scl || !sda ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: %s seems to be busy.\n", name);
|
printk(KERN_WARNING "%s: bus seems to be busy\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdalo(adap);
|
sdalo(adap);
|
||||||
sda=getsda(adap);
|
sda=getsda(adap);
|
||||||
scl=(adap->getscl==NULL?1:getscl(adap));
|
scl=(adap->getscl==NULL?1:getscl(adap));
|
||||||
printk(KERN_DEBUG "i2c-algo-bit.o: (1) scl=%d, sda=%d\n",scl,sda);
|
|
||||||
if ( 0 != sda ) {
|
if ( 0 != sda ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n");
|
printk(KERN_WARNING "%s: SDA stuck high!\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
if ( 0 == scl ) {
|
if ( 0 == scl ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
|
printk(KERN_WARNING "%s: SCL unexpected low "
|
||||||
"while pulling SDA low!\n");
|
"while pulling SDA low!\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
sdahi(adap);
|
sdahi(adap);
|
||||||
sda=getsda(adap);
|
sda=getsda(adap);
|
||||||
scl=(adap->getscl==NULL?1:getscl(adap));
|
scl=(adap->getscl==NULL?1:getscl(adap));
|
||||||
printk(KERN_DEBUG "i2c-algo-bit.o: (2) scl=%d, sda=%d\n",scl,sda);
|
|
||||||
if ( 0 == sda ) {
|
if ( 0 == sda ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n");
|
printk(KERN_WARNING "%s: SDA stuck low!\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
if ( 0 == scl ) {
|
if ( 0 == scl ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
|
printk(KERN_WARNING "%s: SCL unexpected low "
|
||||||
"while pulling SDA high!\n");
|
"while pulling SDA high!\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
scllo(adap);
|
scllo(adap);
|
||||||
sda=getsda(adap);
|
sda=getsda(adap);
|
||||||
scl=(adap->getscl==NULL?0:getscl(adap));
|
scl=(adap->getscl==NULL?0:getscl(adap));
|
||||||
printk(KERN_DEBUG "i2c-algo-bit.o: (3) scl=%d, sda=%d\n",scl,sda);
|
|
||||||
if ( 0 != scl ) {
|
if ( 0 != scl ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n");
|
printk(KERN_WARNING "%s: SCL stuck high!\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
if ( 0 == sda ) {
|
if ( 0 == sda ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
|
printk(KERN_WARNING "%s: SDA unexpected low "
|
||||||
"while pulling SCL low!\n");
|
"while pulling SCL low!\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
|
|
||||||
sclhi(adap);
|
sclhi(adap);
|
||||||
sda=getsda(adap);
|
sda=getsda(adap);
|
||||||
scl=(adap->getscl==NULL?1:getscl(adap));
|
scl=(adap->getscl==NULL?1:getscl(adap));
|
||||||
printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda);
|
|
||||||
if ( 0 == scl ) {
|
if ( 0 == scl ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n");
|
printk(KERN_WARNING "%s: SCL stuck low!\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
if ( 0 == sda ) {
|
if ( 0 == sda ) {
|
||||||
printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
|
printk(KERN_WARNING "%s: SDA unexpected low "
|
||||||
"while pulling SCL high!\n");
|
"while pulling SCL high!\n", name);
|
||||||
goto bailout;
|
goto bailout;
|
||||||
}
|
}
|
||||||
printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name);
|
pr_info("%s: Test OK\n", name);
|
||||||
return 0;
|
return 0;
|
||||||
bailout:
|
bailout:
|
||||||
sdahi(adap);
|
sdahi(adap);
|
||||||
@ -312,44 +317,39 @@ static int try_address(struct i2c_adapter *i2c_adap,
|
|||||||
int i,ret = -1;
|
int i,ret = -1;
|
||||||
for (i=0;i<=retries;i++) {
|
for (i=0;i<=retries;i++) {
|
||||||
ret = i2c_outb(i2c_adap,addr);
|
ret = i2c_outb(i2c_adap,addr);
|
||||||
if (ret==1)
|
if (ret == 1 || i == retries)
|
||||||
break; /* success! */
|
|
||||||
i2c_stop(adap);
|
|
||||||
udelay(5/*adap->udelay*/);
|
|
||||||
if (i==retries) /* no success */
|
|
||||||
break;
|
break;
|
||||||
i2c_start(adap);
|
bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
|
||||||
|
i2c_stop(adap);
|
||||||
udelay(adap->udelay);
|
udelay(adap->udelay);
|
||||||
|
yield();
|
||||||
|
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
|
||||||
|
i2c_start(adap);
|
||||||
}
|
}
|
||||||
DEB2(if (i)
|
if (i && ret)
|
||||||
printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n",
|
bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
|
||||||
i+1, addr & 1 ? "read" : "write", addr>>1,
|
"0x%02x: %s\n", i + 1,
|
||||||
ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" )
|
addr & 1 ? "read from" : "write to", addr >> 1,
|
||||||
);
|
ret == 1 ? "success" : "failed, timeout?");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
||||||
{
|
{
|
||||||
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
|
const unsigned char *temp = msg->buf;
|
||||||
char c;
|
|
||||||
const char *temp = msg->buf;
|
|
||||||
int count = msg->len;
|
int count = msg->len;
|
||||||
unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
|
unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
|
||||||
int retval;
|
int retval;
|
||||||
int wrcount=0;
|
int wrcount=0;
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
c = *temp;
|
retval = i2c_outb(i2c_adap, *temp);
|
||||||
DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff));
|
|
||||||
retval = i2c_outb(i2c_adap,c);
|
|
||||||
if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */
|
if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */
|
||||||
count--;
|
count--;
|
||||||
temp++;
|
temp++;
|
||||||
wrcount++;
|
wrcount++;
|
||||||
} else { /* arbitration or no acknowledge */
|
} else { /* arbitration or no acknowledge */
|
||||||
dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
|
dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
|
||||||
i2c_stop(adap);
|
|
||||||
return (retval<0)? retval : -EFAULT;
|
return (retval<0)? retval : -EFAULT;
|
||||||
/* got a better one ?? */
|
/* got a better one ?? */
|
||||||
}
|
}
|
||||||
@ -362,7 +362,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
|||||||
int inval;
|
int inval;
|
||||||
int rdcount=0; /* counts bytes read */
|
int rdcount=0; /* counts bytes read */
|
||||||
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
|
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
|
||||||
char *temp = msg->buf;
|
unsigned char *temp = msg->buf;
|
||||||
int count = msg->len;
|
int count = msg->len;
|
||||||
|
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
@ -371,30 +371,44 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
|||||||
*temp = inval;
|
*temp = inval;
|
||||||
rdcount++;
|
rdcount++;
|
||||||
} else { /* read timed out */
|
} else { /* read timed out */
|
||||||
printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp++;
|
temp++;
|
||||||
count--;
|
count--;
|
||||||
|
|
||||||
if (msg->flags & I2C_M_NO_RD_ACK)
|
if (msg->flags & I2C_M_NO_RD_ACK) {
|
||||||
|
bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x\n",
|
||||||
|
inval);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if ( count > 0 ) { /* send ack */
|
|
||||||
sdalo(adap);
|
|
||||||
DEBPROTO(printk(" Am "));
|
|
||||||
} else {
|
|
||||||
sdahi(adap); /* neg. ack on last byte */
|
|
||||||
DEBPROTO(printk(" NAm "));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* assert: sda is high */
|
||||||
|
if (count) /* send ack */
|
||||||
|
setsda(adap, 0);
|
||||||
|
udelay((adap->udelay + 1) / 2);
|
||||||
|
bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x %s\n", inval,
|
||||||
|
count ? "A" : "NA");
|
||||||
if (sclhi(adap)<0) { /* timeout */
|
if (sclhi(adap)<0) { /* timeout */
|
||||||
sdahi(adap);
|
dev_err(&i2c_adap->dev, "readbytes: timeout at ack\n");
|
||||||
printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n");
|
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
};
|
};
|
||||||
scllo(adap);
|
scllo(adap);
|
||||||
sdahi(adap);
|
|
||||||
|
/* Some SMBus transactions require that we receive the
|
||||||
|
transaction length as the first read byte. */
|
||||||
|
if (rdcount == 1 && (msg->flags & I2C_M_RECV_LEN)) {
|
||||||
|
if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
|
||||||
|
dev_err(&i2c_adap->dev, "readbytes: invalid "
|
||||||
|
"block length (%d)\n", inval);
|
||||||
|
return -EREMOTEIO;
|
||||||
|
}
|
||||||
|
/* The original count value accounts for the extra
|
||||||
|
bytes, that is, either 1 for a regular transaction,
|
||||||
|
or 2 for a PEC transaction. */
|
||||||
|
count += inval;
|
||||||
|
msg->len += inval;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rdcount;
|
return rdcount;
|
||||||
}
|
}
|
||||||
@ -421,27 +435,31 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
|||||||
if ( (flags & I2C_M_TEN) ) {
|
if ( (flags & I2C_M_TEN) ) {
|
||||||
/* a ten bit address */
|
/* a ten bit address */
|
||||||
addr = 0xf0 | (( msg->addr >> 7) & 0x03);
|
addr = 0xf0 | (( msg->addr >> 7) & 0x03);
|
||||||
DEB2(printk(KERN_DEBUG "addr0: %d\n",addr));
|
bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
|
||||||
/* try extended address code...*/
|
/* try extended address code...*/
|
||||||
ret = try_address(i2c_adap, addr, retries);
|
ret = try_address(i2c_adap, addr, retries);
|
||||||
if ((ret != 1) && !nak_ok) {
|
if ((ret != 1) && !nak_ok) {
|
||||||
printk(KERN_ERR "died at extended address code.\n");
|
dev_err(&i2c_adap->dev,
|
||||||
|
"died at extended address code\n");
|
||||||
return -EREMOTEIO;
|
return -EREMOTEIO;
|
||||||
}
|
}
|
||||||
/* the remaining 8 bit address */
|
/* the remaining 8 bit address */
|
||||||
ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
|
ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
|
||||||
if ((ret != 1) && !nak_ok) {
|
if ((ret != 1) && !nak_ok) {
|
||||||
/* the chip did not ack / xmission error occurred */
|
/* the chip did not ack / xmission error occurred */
|
||||||
printk(KERN_ERR "died at 2nd address code.\n");
|
dev_err(&i2c_adap->dev, "died at 2nd address code\n");
|
||||||
return -EREMOTEIO;
|
return -EREMOTEIO;
|
||||||
}
|
}
|
||||||
if ( flags & I2C_M_RD ) {
|
if ( flags & I2C_M_RD ) {
|
||||||
|
bit_dbg(3, &i2c_adap->dev, "emitting repeated "
|
||||||
|
"start condition\n");
|
||||||
i2c_repstart(adap);
|
i2c_repstart(adap);
|
||||||
/* okay, now switch into reading mode */
|
/* okay, now switch into reading mode */
|
||||||
addr |= 0x01;
|
addr |= 0x01;
|
||||||
ret = try_address(i2c_adap, addr, retries);
|
ret = try_address(i2c_adap, addr, retries);
|
||||||
if ((ret!=1) && !nak_ok) {
|
if ((ret!=1) && !nak_ok) {
|
||||||
printk(KERN_ERR "died at extended address code.\n");
|
dev_err(&i2c_adap->dev,
|
||||||
|
"died at repeated address code\n");
|
||||||
return -EREMOTEIO;
|
return -EREMOTEIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,44 +486,62 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
|
|||||||
int i,ret;
|
int i,ret;
|
||||||
unsigned short nak_ok;
|
unsigned short nak_ok;
|
||||||
|
|
||||||
|
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
|
||||||
i2c_start(adap);
|
i2c_start(adap);
|
||||||
for (i=0;i<num;i++) {
|
for (i=0;i<num;i++) {
|
||||||
pmsg = &msgs[i];
|
pmsg = &msgs[i];
|
||||||
nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;
|
nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;
|
||||||
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
||||||
if (i) {
|
if (i) {
|
||||||
|
bit_dbg(3, &i2c_adap->dev, "emitting "
|
||||||
|
"repeated start condition\n");
|
||||||
i2c_repstart(adap);
|
i2c_repstart(adap);
|
||||||
}
|
}
|
||||||
ret = bit_doAddress(i2c_adap, pmsg);
|
ret = bit_doAddress(i2c_adap, pmsg);
|
||||||
if ((ret != 0) && !nak_ok) {
|
if ((ret != 0) && !nak_ok) {
|
||||||
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n"
|
bit_dbg(1, &i2c_adap->dev, "NAK from "
|
||||||
,msgs[i].addr,i));
|
"device addr 0x%02x msg #%d\n",
|
||||||
return (ret<0) ? ret : -EREMOTEIO;
|
msgs[i].addr, i);
|
||||||
|
goto bailout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pmsg->flags & I2C_M_RD ) {
|
if (pmsg->flags & I2C_M_RD ) {
|
||||||
/* read bytes into buffer*/
|
/* read bytes into buffer*/
|
||||||
ret = readbytes(i2c_adap, pmsg);
|
ret = readbytes(i2c_adap, pmsg);
|
||||||
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret));
|
if (ret >= 1)
|
||||||
|
bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",
|
||||||
|
ret, ret == 1 ? "" : "s");
|
||||||
if (ret < pmsg->len) {
|
if (ret < pmsg->len) {
|
||||||
return (ret<0)? ret : -EREMOTEIO;
|
if (ret >= 0)
|
||||||
|
ret = -EREMOTEIO;
|
||||||
|
goto bailout;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* write bytes from buffer */
|
/* write bytes from buffer */
|
||||||
ret = sendbytes(i2c_adap, pmsg);
|
ret = sendbytes(i2c_adap, pmsg);
|
||||||
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret));
|
if (ret >= 1)
|
||||||
|
bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",
|
||||||
|
ret, ret == 1 ? "" : "s");
|
||||||
if (ret < pmsg->len) {
|
if (ret < pmsg->len) {
|
||||||
return (ret<0) ? ret : -EREMOTEIO;
|
if (ret >= 0)
|
||||||
|
ret = -EREMOTEIO;
|
||||||
|
goto bailout;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret = i;
|
||||||
|
|
||||||
|
bailout:
|
||||||
|
bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
|
||||||
i2c_stop(adap);
|
i2c_stop(adap);
|
||||||
return num;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 bit_func(struct i2c_adapter *adap)
|
static u32 bit_func(struct i2c_adapter *adap)
|
||||||
{
|
{
|
||||||
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
|
||||||
|
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
|
||||||
|
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
|
||||||
I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
|
I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,7 +556,7 @@ static const struct i2c_algorithm i2c_bit_algo = {
|
|||||||
/*
|
/*
|
||||||
* registering functions to load algorithms at runtime
|
* registering functions to load algorithms at runtime
|
||||||
*/
|
*/
|
||||||
int i2c_bit_add_bus(struct i2c_adapter *adap)
|
static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
|
||||||
{
|
{
|
||||||
struct i2c_algo_bit_data *bit_adap = adap->algo_data;
|
struct i2c_algo_bit_data *bit_adap = adap->algo_data;
|
||||||
|
|
||||||
@ -530,25 +566,39 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
|
|
||||||
|
|
||||||
/* register new adapter to i2c module... */
|
/* register new adapter to i2c module... */
|
||||||
adap->algo = &i2c_bit_algo;
|
adap->algo = &i2c_bit_algo;
|
||||||
|
|
||||||
adap->timeout = 100; /* default values, should */
|
adap->timeout = 100; /* default values, should */
|
||||||
adap->retries = 3; /* be replaced by defines */
|
adap->retries = 3; /* be replaced by defines */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i2c_bit_add_bus(struct i2c_adapter *adap)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = i2c_bit_prepare_bus(adap);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
return i2c_add_adapter(adap);
|
return i2c_add_adapter(adap);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(i2c_bit_add_bus);
|
EXPORT_SYMBOL(i2c_bit_add_bus);
|
||||||
|
|
||||||
|
int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = i2c_bit_prepare_bus(adap);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return i2c_add_numbered_adapter(adap);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(i2c_bit_add_numbered_bus);
|
||||||
|
|
||||||
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
|
||||||
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
|
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
module_param(bit_test, bool, 0);
|
|
||||||
module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
|
|
||||||
|
|
||||||
MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
|
|
||||||
MODULE_PARM_DESC(i2c_debug,
|
|
||||||
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* i2c-algo-sgi.c: i2c driver algorithms for SGI adapters.
|
* i2c-algo-sgi.c: i2c driver algorithm used by the VINO (SGI Indy) and
|
||||||
|
* MACE (SGI O2) chips.
|
||||||
*
|
*
|
||||||
* This file is subject to the terms and conditions of the GNU General Public
|
* This file is subject to the terms and conditions of the GNU General Public
|
||||||
* License version 2 as published by the Free Software Foundation.
|
* License version 2 as published by the Free Software Foundation.
|
||||||
|
@ -3,11 +3,10 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
menu "I2C Hardware Bus support"
|
menu "I2C Hardware Bus support"
|
||||||
depends on I2C
|
|
||||||
|
|
||||||
config I2C_ALI1535
|
config I2C_ALI1535
|
||||||
tristate "ALI 1535"
|
tristate "ALI 1535"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the SMB
|
If you say yes to this option, support will be included for the SMB
|
||||||
Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB
|
Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB
|
||||||
@ -19,7 +18,7 @@ config I2C_ALI1535
|
|||||||
|
|
||||||
config I2C_ALI1563
|
config I2C_ALI1563
|
||||||
tristate "ALI 1563"
|
tristate "ALI 1563"
|
||||||
depends on I2C && PCI && EXPERIMENTAL
|
depends on PCI && EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the SMB
|
If you say yes to this option, support will be included for the SMB
|
||||||
Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB
|
Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB
|
||||||
@ -31,7 +30,7 @@ config I2C_ALI1563
|
|||||||
|
|
||||||
config I2C_ALI15X3
|
config I2C_ALI15X3
|
||||||
tristate "ALI 15x3"
|
tristate "ALI 15x3"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
|
Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
|
||||||
@ -41,7 +40,7 @@ config I2C_ALI15X3
|
|||||||
|
|
||||||
config I2C_AMD756
|
config I2C_AMD756
|
||||||
tristate "AMD 756/766/768/8111 and nVidia nForce"
|
tristate "AMD 756/766/768/8111 and nVidia nForce"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the AMD
|
If you say yes to this option, support will be included for the AMD
|
||||||
756/766/768 mainboard I2C interfaces. The driver also includes
|
756/766/768 mainboard I2C interfaces. The driver also includes
|
||||||
@ -66,7 +65,7 @@ config I2C_AMD756_S4882
|
|||||||
|
|
||||||
config I2C_AMD8111
|
config I2C_AMD8111
|
||||||
tristate "AMD 8111"
|
tristate "AMD 8111"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
second (SMBus 2.0) AMD 8111 mainboard I2C interface.
|
second (SMBus 2.0) AMD 8111 mainboard I2C interface.
|
||||||
@ -76,14 +75,14 @@ config I2C_AMD8111
|
|||||||
|
|
||||||
config I2C_AT91
|
config I2C_AT91
|
||||||
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
|
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
|
||||||
depends on I2C && ARCH_AT91 && EXPERIMENTAL
|
depends on ARCH_AT91 && EXPERIMENTAL
|
||||||
help
|
help
|
||||||
This supports the use of the I2C interface on Atmel AT91
|
This supports the use of the I2C interface on Atmel AT91
|
||||||
processors.
|
processors.
|
||||||
|
|
||||||
config I2C_AU1550
|
config I2C_AU1550
|
||||||
tristate "Au1550/Au1200 SMBus interface"
|
tristate "Au1550/Au1200 SMBus interface"
|
||||||
depends on I2C && (SOC_AU1550 || SOC_AU1200)
|
depends on SOC_AU1550 || SOC_AU1200
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
Au1550 and Au1200 SMBus interface.
|
Au1550 and Au1200 SMBus interface.
|
||||||
@ -91,9 +90,25 @@ config I2C_AU1550
|
|||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called i2c-au1550.
|
will be called i2c-au1550.
|
||||||
|
|
||||||
|
config I2C_BLACKFIN_TWI
|
||||||
|
tristate "Blackfin TWI I2C support"
|
||||||
|
depends on BF534 || BF536 || BF537
|
||||||
|
help
|
||||||
|
This is the TWI I2C device driver for Blackfin 534/536/537.
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called i2c-bfin-twi.
|
||||||
|
|
||||||
|
config I2C_BLACKFIN_TWI_CLK_KHZ
|
||||||
|
int "Blackfin TWI I2C clock (kHz)"
|
||||||
|
depends on I2C_BLACKFIN_TWI
|
||||||
|
range 10 400
|
||||||
|
default 50
|
||||||
|
help
|
||||||
|
The unit of the TWI clock is kHz.
|
||||||
|
|
||||||
config I2C_ELEKTOR
|
config I2C_ELEKTOR
|
||||||
tristate "Elektor ISA card"
|
tristate "Elektor ISA card"
|
||||||
depends on I2C && ISA && BROKEN_ON_SMP
|
depends on ISA && BROKEN_ON_SMP
|
||||||
select I2C_ALGOPCF
|
select I2C_ALGOPCF
|
||||||
help
|
help
|
||||||
This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
|
This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
|
||||||
@ -102,9 +117,17 @@ config I2C_ELEKTOR
|
|||||||
This support is also available as a module. If so, the module
|
This support is also available as a module. If so, the module
|
||||||
will be called i2c-elektor.
|
will be called i2c-elektor.
|
||||||
|
|
||||||
|
config I2C_GPIO
|
||||||
|
tristate "GPIO-based bitbanging I2C"
|
||||||
|
depends on GENERIC_GPIO
|
||||||
|
select I2C_ALGOBIT
|
||||||
|
help
|
||||||
|
This is a very simple bitbanging I2C driver utilizing the
|
||||||
|
arch-neutral GPIO API to control the SCL and SDA lines.
|
||||||
|
|
||||||
config I2C_HYDRA
|
config I2C_HYDRA
|
||||||
tristate "CHRP Apple Hydra Mac I/O I2C interface"
|
tristate "CHRP Apple Hydra Mac I/O I2C interface"
|
||||||
depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL
|
depends on PCI && PPC_CHRP && EXPERIMENTAL
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
This supports the use of the I2C interface in the Apple Hydra Mac
|
This supports the use of the I2C interface in the Apple Hydra Mac
|
||||||
@ -116,7 +139,7 @@ config I2C_HYDRA
|
|||||||
|
|
||||||
config I2C_I801
|
config I2C_I801
|
||||||
tristate "Intel 82801 (ICH)"
|
tristate "Intel 82801 (ICH)"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the Intel
|
If you say yes to this option, support will be included for the Intel
|
||||||
801 family of mainboard I2C interfaces. Specifically, the following
|
801 family of mainboard I2C interfaces. Specifically, the following
|
||||||
@ -139,7 +162,7 @@ config I2C_I801
|
|||||||
|
|
||||||
config I2C_I810
|
config I2C_I810
|
||||||
tristate "Intel 810/815"
|
tristate "Intel 810/815"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the Intel
|
If you say yes to this option, support will be included for the Intel
|
||||||
@ -156,7 +179,7 @@ config I2C_I810
|
|||||||
|
|
||||||
config I2C_PXA
|
config I2C_PXA
|
||||||
tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
|
tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
|
||||||
depends on I2C && EXPERIMENTAL && ARCH_PXA
|
depends on EXPERIMENTAL && ARCH_PXA
|
||||||
help
|
help
|
||||||
If you have devices in the PXA I2C bus, say yes to this option.
|
If you have devices in the PXA I2C bus, say yes to this option.
|
||||||
This driver can also be built as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
@ -172,7 +195,7 @@ config I2C_PXA_SLAVE
|
|||||||
|
|
||||||
config I2C_PIIX4
|
config I2C_PIIX4
|
||||||
tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
|
tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the Intel
|
If you say yes to this option, support will be included for the Intel
|
||||||
PIIX4 family of mainboard I2C interfaces. Specifically, the following
|
PIIX4 family of mainboard I2C interfaces. Specifically, the following
|
||||||
@ -195,7 +218,7 @@ config I2C_PIIX4
|
|||||||
|
|
||||||
config I2C_IBM_IIC
|
config I2C_IBM_IIC
|
||||||
tristate "IBM PPC 4xx on-chip I2C interface"
|
tristate "IBM PPC 4xx on-chip I2C interface"
|
||||||
depends on IBM_OCP && I2C
|
depends on IBM_OCP
|
||||||
help
|
help
|
||||||
Say Y here if you want to use IIC peripheral found on
|
Say Y here if you want to use IIC peripheral found on
|
||||||
embedded IBM PPC 4xx based systems.
|
embedded IBM PPC 4xx based systems.
|
||||||
@ -205,7 +228,7 @@ config I2C_IBM_IIC
|
|||||||
|
|
||||||
config I2C_IOP3XX
|
config I2C_IOP3XX
|
||||||
tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
|
tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
|
||||||
depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX) && I2C
|
depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
|
||||||
help
|
help
|
||||||
Say Y here if you want to use the IIC bus controller on
|
Say Y here if you want to use the IIC bus controller on
|
||||||
the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
|
the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
|
||||||
@ -215,11 +238,10 @@ config I2C_IOP3XX
|
|||||||
|
|
||||||
config I2C_ISA
|
config I2C_ISA
|
||||||
tristate
|
tristate
|
||||||
depends on I2C
|
|
||||||
|
|
||||||
config I2C_IXP4XX
|
config I2C_IXP4XX
|
||||||
tristate "IXP4xx GPIO-Based I2C Interface"
|
tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)"
|
||||||
depends on I2C && ARCH_IXP4XX
|
depends on ARCH_IXP4XX
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
Say Y here if you have an Intel IXP4xx(420,421,422,425) based
|
Say Y here if you have an Intel IXP4xx(420,421,422,425) based
|
||||||
@ -228,9 +250,12 @@ config I2C_IXP4XX
|
|||||||
This support is also available as a module. If so, the module
|
This support is also available as a module. If so, the module
|
||||||
will be called i2c-ixp4xx.
|
will be called i2c-ixp4xx.
|
||||||
|
|
||||||
|
This driver is deprecated and will be dropped soon. Use i2c-gpio
|
||||||
|
instead.
|
||||||
|
|
||||||
config I2C_IXP2000
|
config I2C_IXP2000
|
||||||
tristate "IXP2000 GPIO-Based I2C Interface"
|
tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
|
||||||
depends on I2C && ARCH_IXP2000
|
depends on ARCH_IXP2000
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based
|
Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based
|
||||||
@ -239,9 +264,12 @@ config I2C_IXP2000
|
|||||||
This support is also available as a module. If so, the module
|
This support is also available as a module. If so, the module
|
||||||
will be called i2c-ixp2000.
|
will be called i2c-ixp2000.
|
||||||
|
|
||||||
|
This driver is deprecated and will be dropped soon. Use i2c-gpio
|
||||||
|
instead.
|
||||||
|
|
||||||
config I2C_POWERMAC
|
config I2C_POWERMAC
|
||||||
tristate "Powermac I2C interface"
|
tristate "Powermac I2C interface"
|
||||||
depends on I2C && PPC_PMAC
|
depends on PPC_PMAC
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
This exposes the various PowerMac i2c interfaces to the linux i2c
|
This exposes the various PowerMac i2c interfaces to the linux i2c
|
||||||
@ -253,7 +281,7 @@ config I2C_POWERMAC
|
|||||||
|
|
||||||
config I2C_MPC
|
config I2C_MPC
|
||||||
tristate "MPC107/824x/85xx/52xx/86xx"
|
tristate "MPC107/824x/85xx/52xx/86xx"
|
||||||
depends on I2C && PPC32
|
depends on PPC32
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
|
built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
|
||||||
@ -265,7 +293,7 @@ config I2C_MPC
|
|||||||
|
|
||||||
config I2C_NFORCE2
|
config I2C_NFORCE2
|
||||||
tristate "Nvidia nForce2, nForce3 and nForce4"
|
tristate "Nvidia nForce2, nForce3 and nForce4"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the Nvidia
|
If you say yes to this option, support will be included for the Nvidia
|
||||||
nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
|
nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
|
||||||
@ -275,7 +303,7 @@ config I2C_NFORCE2
|
|||||||
|
|
||||||
config I2C_OCORES
|
config I2C_OCORES
|
||||||
tristate "OpenCores I2C Controller"
|
tristate "OpenCores I2C Controller"
|
||||||
depends on I2C && EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
OpenCores I2C controller. For details see
|
OpenCores I2C controller. For details see
|
||||||
@ -286,7 +314,7 @@ config I2C_OCORES
|
|||||||
|
|
||||||
config I2C_OMAP
|
config I2C_OMAP
|
||||||
tristate "OMAP I2C adapter"
|
tristate "OMAP I2C adapter"
|
||||||
depends on I2C && ARCH_OMAP
|
depends on ARCH_OMAP
|
||||||
default y if MACH_OMAP_H3 || MACH_OMAP_OSK
|
default y if MACH_OMAP_H3 || MACH_OMAP_OSK
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
@ -296,7 +324,7 @@ config I2C_OMAP
|
|||||||
|
|
||||||
config I2C_PARPORT
|
config I2C_PARPORT
|
||||||
tristate "Parallel port adapter"
|
tristate "Parallel port adapter"
|
||||||
depends on I2C && PARPORT
|
depends on PARPORT
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
This supports parallel port I2C adapters such as the ones made by
|
This supports parallel port I2C adapters such as the ones made by
|
||||||
@ -320,7 +348,6 @@ config I2C_PARPORT
|
|||||||
|
|
||||||
config I2C_PARPORT_LIGHT
|
config I2C_PARPORT_LIGHT
|
||||||
tristate "Parallel port adapter (light)"
|
tristate "Parallel port adapter (light)"
|
||||||
depends on I2C
|
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
This supports parallel port I2C adapters such as the ones made by
|
This supports parallel port I2C adapters such as the ones made by
|
||||||
@ -344,13 +371,13 @@ config I2C_PARPORT_LIGHT
|
|||||||
|
|
||||||
config I2C_PASEMI
|
config I2C_PASEMI
|
||||||
tristate "PA Semi SMBus interface"
|
tristate "PA Semi SMBus interface"
|
||||||
depends on PPC_PASEMI && I2C && PCI
|
depends on PPC_PASEMI && PCI
|
||||||
help
|
help
|
||||||
Supports the PA Semi PWRficient on-chip SMBus interfaces.
|
Supports the PA Semi PWRficient on-chip SMBus interfaces.
|
||||||
|
|
||||||
config I2C_PROSAVAGE
|
config I2C_PROSAVAGE
|
||||||
tristate "S3/VIA (Pro)Savage"
|
tristate "S3/VIA (Pro)Savage"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
@ -365,19 +392,19 @@ config I2C_PROSAVAGE
|
|||||||
|
|
||||||
config I2C_RPXLITE
|
config I2C_RPXLITE
|
||||||
tristate "Embedded Planet RPX Lite/Classic support"
|
tristate "Embedded Planet RPX Lite/Classic support"
|
||||||
depends on (RPXLITE || RPXCLASSIC) && I2C
|
depends on RPXLITE || RPXCLASSIC
|
||||||
select I2C_ALGO8XX
|
select I2C_ALGO8XX
|
||||||
|
|
||||||
config I2C_S3C2410
|
config I2C_S3C2410
|
||||||
tristate "S3C2410 I2C Driver"
|
tristate "S3C2410 I2C Driver"
|
||||||
depends on I2C && ARCH_S3C2410
|
depends on ARCH_S3C2410
|
||||||
help
|
help
|
||||||
Say Y here to include support for I2C controller in the
|
Say Y here to include support for I2C controller in the
|
||||||
Samsung S3C2410 based System-on-Chip devices.
|
Samsung S3C2410 based System-on-Chip devices.
|
||||||
|
|
||||||
config I2C_SAVAGE4
|
config I2C_SAVAGE4
|
||||||
tristate "S3 Savage 4"
|
tristate "S3 Savage 4"
|
||||||
depends on I2C && PCI && EXPERIMENTAL
|
depends on PCI && EXPERIMENTAL
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
@ -388,13 +415,25 @@ config I2C_SAVAGE4
|
|||||||
|
|
||||||
config I2C_SIBYTE
|
config I2C_SIBYTE
|
||||||
tristate "SiByte SMBus interface"
|
tristate "SiByte SMBus interface"
|
||||||
depends on SIBYTE_SB1xxx_SOC && I2C
|
depends on SIBYTE_SB1xxx_SOC
|
||||||
help
|
help
|
||||||
Supports the SiByte SOC on-chip I2C interfaces (2 channels).
|
Supports the SiByte SOC on-chip I2C interfaces (2 channels).
|
||||||
|
|
||||||
|
config I2C_SIMTEC
|
||||||
|
tristate "Simtec Generic I2C interface"
|
||||||
|
select I2C_ALGOBIT
|
||||||
|
help
|
||||||
|
If you say yes to this option, support will be inclyded for
|
||||||
|
the Simtec Generic I2C interface. This driver is for the
|
||||||
|
simple I2C bus used on newer Simtec products for general
|
||||||
|
I2C, such as DDC on the Simtec BBD2016A.
|
||||||
|
|
||||||
|
This driver can also be build as a module. If so, the module
|
||||||
|
will be called i2c-simtec.
|
||||||
|
|
||||||
config SCx200_I2C
|
config SCx200_I2C
|
||||||
tristate "NatSemi SCx200 I2C using GPIO pins"
|
tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
|
||||||
depends on SCx200_GPIO && I2C
|
depends on SCx200_GPIO
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
|
Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
|
||||||
@ -404,6 +443,9 @@ config SCx200_I2C
|
|||||||
This support is also available as a module. If so, the module
|
This support is also available as a module. If so, the module
|
||||||
will be called scx200_i2c.
|
will be called scx200_i2c.
|
||||||
|
|
||||||
|
This driver is deprecated and will be dropped soon. Use i2c-gpio
|
||||||
|
(or scx200_acb) instead.
|
||||||
|
|
||||||
config SCx200_I2C_SCL
|
config SCx200_I2C_SCL
|
||||||
int "GPIO pin used for SCL"
|
int "GPIO pin used for SCL"
|
||||||
depends on SCx200_I2C
|
depends on SCx200_I2C
|
||||||
@ -422,7 +464,7 @@ config SCx200_I2C_SDA
|
|||||||
|
|
||||||
config SCx200_ACB
|
config SCx200_ACB
|
||||||
tristate "Geode ACCESS.bus support"
|
tristate "Geode ACCESS.bus support"
|
||||||
depends on X86_32 && I2C && PCI
|
depends on X86_32 && PCI
|
||||||
help
|
help
|
||||||
Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
|
Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
|
||||||
SC1100 processors and the CS5535 and CS5536 Geode companion devices.
|
SC1100 processors and the CS5535 and CS5536 Geode companion devices.
|
||||||
@ -434,7 +476,7 @@ config SCx200_ACB
|
|||||||
|
|
||||||
config I2C_SIS5595
|
config I2C_SIS5595
|
||||||
tristate "SiS 5595"
|
tristate "SiS 5595"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
SiS5595 SMBus (a subset of I2C) interface.
|
SiS5595 SMBus (a subset of I2C) interface.
|
||||||
@ -444,7 +486,7 @@ config I2C_SIS5595
|
|||||||
|
|
||||||
config I2C_SIS630
|
config I2C_SIS630
|
||||||
tristate "SiS 630/730"
|
tristate "SiS 630/730"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
SiS630 and SiS730 SMBus (a subset of I2C) interface.
|
SiS630 and SiS730 SMBus (a subset of I2C) interface.
|
||||||
@ -454,7 +496,7 @@ config I2C_SIS630
|
|||||||
|
|
||||||
config I2C_SIS96X
|
config I2C_SIS96X
|
||||||
tristate "SiS 96x"
|
tristate "SiS 96x"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the SiS
|
If you say yes to this option, support will be included for the SiS
|
||||||
96x SMBus (a subset of I2C) interfaces. Specifically, the following
|
96x SMBus (a subset of I2C) interfaces. Specifically, the following
|
||||||
@ -472,7 +514,7 @@ config I2C_SIS96X
|
|||||||
|
|
||||||
config I2C_STUB
|
config I2C_STUB
|
||||||
tristate "I2C/SMBus Test Stub"
|
tristate "I2C/SMBus Test Stub"
|
||||||
depends on I2C && EXPERIMENTAL && 'm'
|
depends on EXPERIMENTAL && m
|
||||||
default 'n'
|
default 'n'
|
||||||
help
|
help
|
||||||
This module may be useful to developers of SMBus client drivers,
|
This module may be useful to developers of SMBus client drivers,
|
||||||
@ -483,9 +525,20 @@ config I2C_STUB
|
|||||||
|
|
||||||
If you don't know what to do here, definitely say N.
|
If you don't know what to do here, definitely say N.
|
||||||
|
|
||||||
|
config I2C_TINY_USB
|
||||||
|
tristate "I2C-Tiny-USB"
|
||||||
|
depends on USB
|
||||||
|
help
|
||||||
|
If you say yes to this option, support will be included for the
|
||||||
|
i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See
|
||||||
|
http://www.harbaum.org/till/i2c_tiny_usb for hardware details.
|
||||||
|
|
||||||
|
This driver can also be built as a module. If so, the module
|
||||||
|
will be called i2c-tiny-usb.
|
||||||
|
|
||||||
config I2C_VERSATILE
|
config I2C_VERSATILE
|
||||||
tristate "ARM Versatile/Realview I2C bus support"
|
tristate "ARM Versatile/Realview I2C bus support"
|
||||||
depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW)
|
depends on ARCH_VERSATILE || ARCH_REALVIEW
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
Say yes if you want to support the I2C serial bus on ARMs Versatile
|
Say yes if you want to support the I2C serial bus on ARMs Versatile
|
||||||
@ -496,7 +549,7 @@ config I2C_VERSATILE
|
|||||||
|
|
||||||
config I2C_ACORN
|
config I2C_ACORN
|
||||||
bool "Acorn IOC/IOMD I2C bus support"
|
bool "Acorn IOC/IOMD I2C bus support"
|
||||||
depends on I2C && ARCH_ACORN
|
depends on ARCH_ACORN
|
||||||
default y
|
default y
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
@ -506,7 +559,7 @@ config I2C_ACORN
|
|||||||
|
|
||||||
config I2C_VIA
|
config I2C_VIA
|
||||||
tristate "VIA 82C586B"
|
tristate "VIA 82C586B"
|
||||||
depends on I2C && PCI && EXPERIMENTAL
|
depends on PCI && EXPERIMENTAL
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the VIA
|
If you say yes to this option, support will be included for the VIA
|
||||||
@ -517,7 +570,7 @@ config I2C_VIA
|
|||||||
|
|
||||||
config I2C_VIAPRO
|
config I2C_VIAPRO
|
||||||
tristate "VIA VT82C596/82C686/82xx and CX700"
|
tristate "VIA VT82C596/82C686/82xx and CX700"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the VIA
|
If you say yes to this option, support will be included for the VIA
|
||||||
VT82C596 and later SMBus interface. Specifically, the following
|
VT82C596 and later SMBus interface. Specifically, the following
|
||||||
@ -536,7 +589,7 @@ config I2C_VIAPRO
|
|||||||
|
|
||||||
config I2C_VOODOO3
|
config I2C_VOODOO3
|
||||||
tristate "Voodoo 3"
|
tristate "Voodoo 3"
|
||||||
depends on I2C && PCI
|
depends on PCI
|
||||||
select I2C_ALGOBIT
|
select I2C_ALGOBIT
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
@ -547,7 +600,7 @@ config I2C_VOODOO3
|
|||||||
|
|
||||||
config I2C_PCA_ISA
|
config I2C_PCA_ISA
|
||||||
tristate "PCA9564 on an ISA bus"
|
tristate "PCA9564 on an ISA bus"
|
||||||
depends on I2C
|
depends on ISA
|
||||||
select I2C_ALGOPCA
|
select I2C_ALGOPCA
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
@ -564,7 +617,7 @@ config I2C_PCA_ISA
|
|||||||
|
|
||||||
config I2C_MV64XXX
|
config I2C_MV64XXX
|
||||||
tristate "Marvell mv64xxx I2C Controller"
|
tristate "Marvell mv64xxx I2C Controller"
|
||||||
depends on I2C && MV64X60 && EXPERIMENTAL
|
depends on MV64X60 && EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
built-in I2C interface on the Marvell 64xxx line of host bridges.
|
built-in I2C interface on the Marvell 64xxx line of host bridges.
|
||||||
@ -574,7 +627,7 @@ config I2C_MV64XXX
|
|||||||
|
|
||||||
config I2C_PNX
|
config I2C_PNX
|
||||||
tristate "I2C bus support for Philips PNX targets"
|
tristate "I2C bus support for Philips PNX targets"
|
||||||
depends on ARCH_PNX4008 && I2C
|
depends on ARCH_PNX4008
|
||||||
help
|
help
|
||||||
This driver supports the Philips IP3204 I2C IP block master and/or
|
This driver supports the Philips IP3204 I2C IP block master and/or
|
||||||
slave controller
|
slave controller
|
||||||
|
@ -10,7 +10,9 @@ obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
|
|||||||
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
|
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
|
||||||
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
|
obj-$(CONFIG_I2C_AT91) += i2c-at91.o
|
||||||
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
|
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
|
||||||
|
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
|
||||||
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
|
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
|
||||||
|
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
|
||||||
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
|
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
|
||||||
obj-$(CONFIG_I2C_I801) += i2c-i801.o
|
obj-$(CONFIG_I2C_I801) += i2c-i801.o
|
||||||
obj-$(CONFIG_I2C_I810) += i2c-i810.o
|
obj-$(CONFIG_I2C_I810) += i2c-i810.o
|
||||||
@ -37,10 +39,12 @@ obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
|
|||||||
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
|
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
|
||||||
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
|
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
|
||||||
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
|
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
|
||||||
|
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
|
||||||
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
|
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
|
||||||
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
|
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
|
||||||
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
|
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
|
||||||
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
|
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
|
||||||
|
obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
|
||||||
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
|
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
|
||||||
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
|
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
|
||||||
obj-$(CONFIG_I2C_VIA) += i2c-via.o
|
obj-$(CONFIG_I2C_VIA) += i2c-via.o
|
||||||
|
@ -497,7 +497,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_
|
|||||||
/* set up the sysfs linkage to our parent device */
|
/* set up the sysfs linkage to our parent device */
|
||||||
ali1535_adapter.dev.parent = &dev->dev;
|
ali1535_adapter.dev.parent = &dev->dev;
|
||||||
|
|
||||||
snprintf(ali1535_adapter.name, I2C_NAME_SIZE,
|
snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name),
|
||||||
"SMBus ALI1535 adapter at %04x", ali1535_smba);
|
"SMBus ALI1535 adapter at %04x", ali1535_smba);
|
||||||
return i2c_add_adapter(&ali1535_adapter);
|
return i2c_add_adapter(&ali1535_adapter);
|
||||||
}
|
}
|
||||||
|
@ -492,7 +492,7 @@ static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_
|
|||||||
/* set up the sysfs linkage to our parent device */
|
/* set up the sysfs linkage to our parent device */
|
||||||
ali15x3_adapter.dev.parent = &dev->dev;
|
ali15x3_adapter.dev.parent = &dev->dev;
|
||||||
|
|
||||||
snprintf(ali15x3_adapter.name, I2C_NAME_SIZE,
|
snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
|
||||||
"SMBus ALI15X3 adapter at %04x", ali15x3_smba);
|
"SMBus ALI15X3 adapter at %04x", ali15x3_smba);
|
||||||
return i2c_add_adapter(&ali15x3_adapter);
|
return i2c_add_adapter(&ali15x3_adapter);
|
||||||
}
|
}
|
||||||
|
@ -365,7 +365,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
smbus->adapter.owner = THIS_MODULE;
|
smbus->adapter.owner = THIS_MODULE;
|
||||||
snprintf(smbus->adapter.name, I2C_NAME_SIZE,
|
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
|
||||||
"SMBus2 AMD8111 adapter at %04x", smbus->base);
|
"SMBus2 AMD8111 adapter at %04x", smbus->base);
|
||||||
smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
|
smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
|
||||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||||
|
644
drivers/i2c/busses/i2c-bfin-twi.c
Normal file
644
drivers/i2c/busses/i2c-bfin-twi.c
Normal file
@ -0,0 +1,644 @@
|
|||||||
|
/*
|
||||||
|
* drivers/i2c/busses/i2c-bfin-twi.c
|
||||||
|
*
|
||||||
|
* Description: Driver for Blackfin Two Wire Interface
|
||||||
|
*
|
||||||
|
* Author: sonicz <sonic.zhang@analog.com>
|
||||||
|
*
|
||||||
|
* Copyright (c) 2005-2007 Analog Devices, Inc.
|
||||||
|
*
|
||||||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/mm.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#include <asm/blackfin.h>
|
||||||
|
#include <asm/irq.h>
|
||||||
|
|
||||||
|
#define POLL_TIMEOUT (2 * HZ)
|
||||||
|
|
||||||
|
/* SMBus mode*/
|
||||||
|
#define TWI_I2C_MODE_STANDARD 0x01
|
||||||
|
#define TWI_I2C_MODE_STANDARDSUB 0x02
|
||||||
|
#define TWI_I2C_MODE_COMBINED 0x04
|
||||||
|
|
||||||
|
struct bfin_twi_iface {
|
||||||
|
struct mutex twi_lock;
|
||||||
|
int irq;
|
||||||
|
spinlock_t lock;
|
||||||
|
char read_write;
|
||||||
|
u8 command;
|
||||||
|
u8 *transPtr;
|
||||||
|
int readNum;
|
||||||
|
int writeNum;
|
||||||
|
int cur_mode;
|
||||||
|
int manual_stop;
|
||||||
|
int result;
|
||||||
|
int timeout_count;
|
||||||
|
struct timer_list timeout_timer;
|
||||||
|
struct i2c_adapter adap;
|
||||||
|
struct completion complete;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct bfin_twi_iface twi_iface;
|
||||||
|
|
||||||
|
static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface)
|
||||||
|
{
|
||||||
|
unsigned short twi_int_status = bfin_read_TWI_INT_STAT();
|
||||||
|
unsigned short mast_stat = bfin_read_TWI_MASTER_STAT();
|
||||||
|
|
||||||
|
if (twi_int_status & XMTSERV) {
|
||||||
|
/* Transmit next data */
|
||||||
|
if (iface->writeNum > 0) {
|
||||||
|
bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
|
||||||
|
iface->writeNum--;
|
||||||
|
}
|
||||||
|
/* start receive immediately after complete sending in
|
||||||
|
* combine mode.
|
||||||
|
*/
|
||||||
|
else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
|
||||||
|
| MDIR | RSTART);
|
||||||
|
} else if (iface->manual_stop)
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
|
||||||
|
| STOP);
|
||||||
|
SSYNC();
|
||||||
|
/* Clear status */
|
||||||
|
bfin_write_TWI_INT_STAT(XMTSERV);
|
||||||
|
SSYNC();
|
||||||
|
}
|
||||||
|
if (twi_int_status & RCVSERV) {
|
||||||
|
if (iface->readNum > 0) {
|
||||||
|
/* Receive next data */
|
||||||
|
*(iface->transPtr) = bfin_read_TWI_RCV_DATA8();
|
||||||
|
if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
|
||||||
|
/* Change combine mode into sub mode after
|
||||||
|
* read first data.
|
||||||
|
*/
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
|
||||||
|
/* Get read number from first byte in block
|
||||||
|
* combine mode.
|
||||||
|
*/
|
||||||
|
if (iface->readNum == 1 && iface->manual_stop)
|
||||||
|
iface->readNum = *iface->transPtr + 1;
|
||||||
|
}
|
||||||
|
iface->transPtr++;
|
||||||
|
iface->readNum--;
|
||||||
|
} else if (iface->manual_stop) {
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL()
|
||||||
|
| STOP);
|
||||||
|
SSYNC();
|
||||||
|
}
|
||||||
|
/* Clear interrupt source */
|
||||||
|
bfin_write_TWI_INT_STAT(RCVSERV);
|
||||||
|
SSYNC();
|
||||||
|
}
|
||||||
|
if (twi_int_status & MERR) {
|
||||||
|
bfin_write_TWI_INT_STAT(MERR);
|
||||||
|
bfin_write_TWI_INT_MASK(0);
|
||||||
|
bfin_write_TWI_MASTER_STAT(0x3e);
|
||||||
|
bfin_write_TWI_MASTER_CTL(0);
|
||||||
|
SSYNC();
|
||||||
|
iface->result = -1;
|
||||||
|
/* if both err and complete int stats are set, return proper
|
||||||
|
* results.
|
||||||
|
*/
|
||||||
|
if (twi_int_status & MCOMP) {
|
||||||
|
bfin_write_TWI_INT_STAT(MCOMP);
|
||||||
|
bfin_write_TWI_INT_MASK(0);
|
||||||
|
bfin_write_TWI_MASTER_CTL(0);
|
||||||
|
SSYNC();
|
||||||
|
/* If it is a quick transfer, only address bug no data,
|
||||||
|
* not an err, return 1.
|
||||||
|
*/
|
||||||
|
if (iface->writeNum == 0 && (mast_stat & BUFRDERR))
|
||||||
|
iface->result = 1;
|
||||||
|
/* If address not acknowledged return -1,
|
||||||
|
* else return 0.
|
||||||
|
*/
|
||||||
|
else if (!(mast_stat & ANAK))
|
||||||
|
iface->result = 0;
|
||||||
|
}
|
||||||
|
complete(&iface->complete);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (twi_int_status & MCOMP) {
|
||||||
|
bfin_write_TWI_INT_STAT(MCOMP);
|
||||||
|
SSYNC();
|
||||||
|
if (iface->cur_mode == TWI_I2C_MODE_COMBINED) {
|
||||||
|
if (iface->readNum == 0) {
|
||||||
|
/* set the read number to 1 and ask for manual
|
||||||
|
* stop in block combine mode
|
||||||
|
*/
|
||||||
|
iface->readNum = 1;
|
||||||
|
iface->manual_stop = 1;
|
||||||
|
bfin_write_TWI_MASTER_CTL(
|
||||||
|
bfin_read_TWI_MASTER_CTL()
|
||||||
|
| (0xff << 6));
|
||||||
|
} else {
|
||||||
|
/* set the readd number in other
|
||||||
|
* combine mode.
|
||||||
|
*/
|
||||||
|
bfin_write_TWI_MASTER_CTL(
|
||||||
|
(bfin_read_TWI_MASTER_CTL() &
|
||||||
|
(~(0xff << 6))) |
|
||||||
|
( iface->readNum << 6));
|
||||||
|
}
|
||||||
|
/* remove restart bit and enable master receive */
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() &
|
||||||
|
~RSTART);
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() |
|
||||||
|
MEN | MDIR);
|
||||||
|
SSYNC();
|
||||||
|
} else {
|
||||||
|
iface->result = 1;
|
||||||
|
bfin_write_TWI_INT_MASK(0);
|
||||||
|
bfin_write_TWI_MASTER_CTL(0);
|
||||||
|
SSYNC();
|
||||||
|
complete(&iface->complete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Interrupt handler */
|
||||||
|
static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct bfin_twi_iface *iface = dev_id;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&iface->lock, flags);
|
||||||
|
del_timer(&iface->timeout_timer);
|
||||||
|
bfin_twi_handle_interrupt(iface);
|
||||||
|
spin_unlock_irqrestore(&iface->lock, flags);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bfin_twi_timeout(unsigned long data)
|
||||||
|
{
|
||||||
|
struct bfin_twi_iface *iface = (struct bfin_twi_iface *)data;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&iface->lock, flags);
|
||||||
|
bfin_twi_handle_interrupt(iface);
|
||||||
|
if (iface->result == 0) {
|
||||||
|
iface->timeout_count--;
|
||||||
|
if (iface->timeout_count > 0) {
|
||||||
|
iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
|
||||||
|
add_timer(&iface->timeout_timer);
|
||||||
|
} else {
|
||||||
|
iface->result = -1;
|
||||||
|
complete(&iface->complete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&iface->lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generic i2c master transfer entrypoint
|
||||||
|
*/
|
||||||
|
static int bfin_twi_master_xfer(struct i2c_adapter *adap,
|
||||||
|
struct i2c_msg *msgs, int num)
|
||||||
|
{
|
||||||
|
struct bfin_twi_iface *iface = adap->algo_data;
|
||||||
|
struct i2c_msg *pmsg;
|
||||||
|
int i, ret;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
|
mutex_lock(&iface->twi_lock);
|
||||||
|
|
||||||
|
while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
|
||||||
|
mutex_unlock(&iface->twi_lock);
|
||||||
|
yield();
|
||||||
|
mutex_lock(&iface->twi_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
for (i = 0; rc >= 0 && i < num; i++) {
|
||||||
|
pmsg = &msgs[i];
|
||||||
|
if (pmsg->flags & I2C_M_TEN) {
|
||||||
|
dev_err(&(adap->dev), "i2c-bfin-twi: 10 bits addr "
|
||||||
|
"not supported !\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_STANDARD;
|
||||||
|
iface->manual_stop = 0;
|
||||||
|
iface->transPtr = pmsg->buf;
|
||||||
|
iface->writeNum = iface->readNum = pmsg->len;
|
||||||
|
iface->result = 0;
|
||||||
|
iface->timeout_count = 10;
|
||||||
|
/* Set Transmit device address */
|
||||||
|
bfin_write_TWI_MASTER_ADDR(pmsg->addr);
|
||||||
|
|
||||||
|
/* FIFO Initiation. Data in FIFO should be
|
||||||
|
* discarded before start a new operation.
|
||||||
|
*/
|
||||||
|
bfin_write_TWI_FIFO_CTL(0x3);
|
||||||
|
SSYNC();
|
||||||
|
bfin_write_TWI_FIFO_CTL(0);
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
if (pmsg->flags & I2C_M_RD)
|
||||||
|
iface->read_write = I2C_SMBUS_READ;
|
||||||
|
else {
|
||||||
|
iface->read_write = I2C_SMBUS_WRITE;
|
||||||
|
/* Transmit first data */
|
||||||
|
if (iface->writeNum > 0) {
|
||||||
|
bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
|
||||||
|
iface->writeNum--;
|
||||||
|
SSYNC();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear int stat */
|
||||||
|
bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
|
||||||
|
|
||||||
|
/* Interrupt mask . Enable XMT, RCV interrupt */
|
||||||
|
bfin_write_TWI_INT_MASK(MCOMP | MERR |
|
||||||
|
((iface->read_write == I2C_SMBUS_READ)?
|
||||||
|
RCVSERV : XMTSERV));
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
if (pmsg->len > 0 && pmsg->len <= 255)
|
||||||
|
bfin_write_TWI_MASTER_CTL(pmsg->len << 6);
|
||||||
|
else if (pmsg->len > 255) {
|
||||||
|
bfin_write_TWI_MASTER_CTL(0xff << 6);
|
||||||
|
iface->manual_stop = 1;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
|
||||||
|
iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
|
||||||
|
add_timer(&iface->timeout_timer);
|
||||||
|
|
||||||
|
/* Master enable */
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
|
||||||
|
((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
|
||||||
|
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
wait_for_completion(&iface->complete);
|
||||||
|
|
||||||
|
rc = iface->result;
|
||||||
|
if (rc == 1)
|
||||||
|
ret++;
|
||||||
|
else if (rc == -1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release mutex */
|
||||||
|
mutex_unlock(&iface->twi_lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SMBus type transfer entrypoint
|
||||||
|
*/
|
||||||
|
|
||||||
|
int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr,
|
||||||
|
unsigned short flags, char read_write,
|
||||||
|
u8 command, int size, union i2c_smbus_data *data)
|
||||||
|
{
|
||||||
|
struct bfin_twi_iface *iface = adap->algo_data;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!(bfin_read_TWI_CONTROL() & TWI_ENA))
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
|
mutex_lock(&iface->twi_lock);
|
||||||
|
|
||||||
|
while (bfin_read_TWI_MASTER_STAT() & BUSBUSY) {
|
||||||
|
mutex_unlock(&iface->twi_lock);
|
||||||
|
yield();
|
||||||
|
mutex_lock(&iface->twi_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
iface->writeNum = 0;
|
||||||
|
iface->readNum = 0;
|
||||||
|
|
||||||
|
/* Prepare datas & select mode */
|
||||||
|
switch (size) {
|
||||||
|
case I2C_SMBUS_QUICK:
|
||||||
|
iface->transPtr = NULL;
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_STANDARD;
|
||||||
|
break;
|
||||||
|
case I2C_SMBUS_BYTE:
|
||||||
|
if (data == NULL)
|
||||||
|
iface->transPtr = NULL;
|
||||||
|
else {
|
||||||
|
if (read_write == I2C_SMBUS_READ)
|
||||||
|
iface->readNum = 1;
|
||||||
|
else
|
||||||
|
iface->writeNum = 1;
|
||||||
|
iface->transPtr = &data->byte;
|
||||||
|
}
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_STANDARD;
|
||||||
|
break;
|
||||||
|
case I2C_SMBUS_BYTE_DATA:
|
||||||
|
if (read_write == I2C_SMBUS_READ) {
|
||||||
|
iface->readNum = 1;
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_COMBINED;
|
||||||
|
} else {
|
||||||
|
iface->writeNum = 1;
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
|
||||||
|
}
|
||||||
|
iface->transPtr = &data->byte;
|
||||||
|
break;
|
||||||
|
case I2C_SMBUS_WORD_DATA:
|
||||||
|
if (read_write == I2C_SMBUS_READ) {
|
||||||
|
iface->readNum = 2;
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_COMBINED;
|
||||||
|
} else {
|
||||||
|
iface->writeNum = 2;
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
|
||||||
|
}
|
||||||
|
iface->transPtr = (u8 *)&data->word;
|
||||||
|
break;
|
||||||
|
case I2C_SMBUS_PROC_CALL:
|
||||||
|
iface->writeNum = 2;
|
||||||
|
iface->readNum = 2;
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_COMBINED;
|
||||||
|
iface->transPtr = (u8 *)&data->word;
|
||||||
|
break;
|
||||||
|
case I2C_SMBUS_BLOCK_DATA:
|
||||||
|
if (read_write == I2C_SMBUS_READ) {
|
||||||
|
iface->readNum = 0;
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_COMBINED;
|
||||||
|
} else {
|
||||||
|
iface->writeNum = data->block[0] + 1;
|
||||||
|
iface->cur_mode = TWI_I2C_MODE_STANDARDSUB;
|
||||||
|
}
|
||||||
|
iface->transPtr = data->block;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
iface->result = 0;
|
||||||
|
iface->manual_stop = 0;
|
||||||
|
iface->read_write = read_write;
|
||||||
|
iface->command = command;
|
||||||
|
iface->timeout_count = 10;
|
||||||
|
|
||||||
|
/* FIFO Initiation. Data in FIFO should be discarded before
|
||||||
|
* start a new operation.
|
||||||
|
*/
|
||||||
|
bfin_write_TWI_FIFO_CTL(0x3);
|
||||||
|
SSYNC();
|
||||||
|
bfin_write_TWI_FIFO_CTL(0);
|
||||||
|
|
||||||
|
/* clear int stat */
|
||||||
|
bfin_write_TWI_INT_STAT(MERR|MCOMP|XMTSERV|RCVSERV);
|
||||||
|
|
||||||
|
/* Set Transmit device address */
|
||||||
|
bfin_write_TWI_MASTER_ADDR(addr);
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
iface->timeout_timer.expires = jiffies + POLL_TIMEOUT;
|
||||||
|
add_timer(&iface->timeout_timer);
|
||||||
|
|
||||||
|
switch (iface->cur_mode) {
|
||||||
|
case TWI_I2C_MODE_STANDARDSUB:
|
||||||
|
bfin_write_TWI_XMT_DATA8(iface->command);
|
||||||
|
bfin_write_TWI_INT_MASK(MCOMP | MERR |
|
||||||
|
((iface->read_write == I2C_SMBUS_READ) ?
|
||||||
|
RCVSERV : XMTSERV));
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
if (iface->writeNum + 1 <= 255)
|
||||||
|
bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
|
||||||
|
else {
|
||||||
|
bfin_write_TWI_MASTER_CTL(0xff << 6);
|
||||||
|
iface->manual_stop = 1;
|
||||||
|
}
|
||||||
|
/* Master enable */
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
|
||||||
|
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
|
||||||
|
break;
|
||||||
|
case TWI_I2C_MODE_COMBINED:
|
||||||
|
bfin_write_TWI_XMT_DATA8(iface->command);
|
||||||
|
bfin_write_TWI_INT_MASK(MCOMP | MERR | RCVSERV | XMTSERV);
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
if (iface->writeNum > 0)
|
||||||
|
bfin_write_TWI_MASTER_CTL((iface->writeNum + 1) << 6);
|
||||||
|
else
|
||||||
|
bfin_write_TWI_MASTER_CTL(0x1 << 6);
|
||||||
|
/* Master enable */
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
|
||||||
|
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
bfin_write_TWI_MASTER_CTL(0);
|
||||||
|
if (size != I2C_SMBUS_QUICK) {
|
||||||
|
/* Don't access xmit data register when this is a
|
||||||
|
* read operation.
|
||||||
|
*/
|
||||||
|
if (iface->read_write != I2C_SMBUS_READ) {
|
||||||
|
if (iface->writeNum > 0) {
|
||||||
|
bfin_write_TWI_XMT_DATA8(*(iface->transPtr++));
|
||||||
|
if (iface->writeNum <= 255)
|
||||||
|
bfin_write_TWI_MASTER_CTL(iface->writeNum << 6);
|
||||||
|
else {
|
||||||
|
bfin_write_TWI_MASTER_CTL(0xff << 6);
|
||||||
|
iface->manual_stop = 1;
|
||||||
|
}
|
||||||
|
iface->writeNum--;
|
||||||
|
} else {
|
||||||
|
bfin_write_TWI_XMT_DATA8(iface->command);
|
||||||
|
bfin_write_TWI_MASTER_CTL(1 << 6);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (iface->readNum > 0 && iface->readNum <= 255)
|
||||||
|
bfin_write_TWI_MASTER_CTL(iface->readNum << 6);
|
||||||
|
else if (iface->readNum > 255) {
|
||||||
|
bfin_write_TWI_MASTER_CTL(0xff << 6);
|
||||||
|
iface->manual_stop = 1;
|
||||||
|
} else {
|
||||||
|
del_timer(&iface->timeout_timer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bfin_write_TWI_INT_MASK(MCOMP | MERR |
|
||||||
|
((iface->read_write == I2C_SMBUS_READ) ?
|
||||||
|
RCVSERV : XMTSERV));
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
/* Master enable */
|
||||||
|
bfin_write_TWI_MASTER_CTL(bfin_read_TWI_MASTER_CTL() | MEN |
|
||||||
|
((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) |
|
||||||
|
((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
wait_for_completion(&iface->complete);
|
||||||
|
|
||||||
|
rc = (iface->result >= 0) ? 0 : -1;
|
||||||
|
|
||||||
|
/* Release mutex */
|
||||||
|
mutex_unlock(&iface->twi_lock);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return what the adapter supports
|
||||||
|
*/
|
||||||
|
static u32 bfin_twi_functionality(struct i2c_adapter *adap)
|
||||||
|
{
|
||||||
|
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_I2C;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct i2c_algorithm bfin_twi_algorithm = {
|
||||||
|
.master_xfer = bfin_twi_master_xfer,
|
||||||
|
.smbus_xfer = bfin_twi_smbus_xfer,
|
||||||
|
.functionality = bfin_twi_functionality,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int i2c_bfin_twi_suspend(struct platform_device *dev, pm_message_t state)
|
||||||
|
{
|
||||||
|
/* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
|
||||||
|
|
||||||
|
/* Disable TWI */
|
||||||
|
bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() & ~TWI_ENA);
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_bfin_twi_resume(struct platform_device *dev)
|
||||||
|
{
|
||||||
|
/* struct bfin_twi_iface *iface = platform_get_drvdata(dev);*/
|
||||||
|
|
||||||
|
/* Enable TWI */
|
||||||
|
bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_bfin_twi_probe(struct platform_device *dev)
|
||||||
|
{
|
||||||
|
struct bfin_twi_iface *iface = &twi_iface;
|
||||||
|
struct i2c_adapter *p_adap;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
mutex_init(&(iface->twi_lock));
|
||||||
|
spin_lock_init(&(iface->lock));
|
||||||
|
init_completion(&(iface->complete));
|
||||||
|
iface->irq = IRQ_TWI;
|
||||||
|
|
||||||
|
init_timer(&(iface->timeout_timer));
|
||||||
|
iface->timeout_timer.function = bfin_twi_timeout;
|
||||||
|
iface->timeout_timer.data = (unsigned long)iface;
|
||||||
|
|
||||||
|
p_adap = &iface->adap;
|
||||||
|
p_adap->id = I2C_HW_BLACKFIN;
|
||||||
|
strlcpy(p_adap->name, dev->name, sizeof(p_adap->name));
|
||||||
|
p_adap->algo = &bfin_twi_algorithm;
|
||||||
|
p_adap->algo_data = iface;
|
||||||
|
p_adap->class = I2C_CLASS_ALL;
|
||||||
|
p_adap->dev.parent = &dev->dev;
|
||||||
|
|
||||||
|
rc = request_irq(iface->irq, bfin_twi_interrupt_entry,
|
||||||
|
IRQF_DISABLED, dev->name, iface);
|
||||||
|
if (rc) {
|
||||||
|
dev_err(&(p_adap->dev), "i2c-bfin-twi: can't get IRQ %d !\n",
|
||||||
|
iface->irq);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set TWI internal clock as 10MHz */
|
||||||
|
bfin_write_TWI_CONTROL(((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F);
|
||||||
|
|
||||||
|
/* Set Twi interface clock as specified */
|
||||||
|
bfin_write_TWI_CLKDIV((( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
|
||||||
|
<< 8) | (( 5*1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ )
|
||||||
|
& 0xFF));
|
||||||
|
|
||||||
|
/* Enable TWI */
|
||||||
|
bfin_write_TWI_CONTROL(bfin_read_TWI_CONTROL() | TWI_ENA);
|
||||||
|
SSYNC();
|
||||||
|
|
||||||
|
rc = i2c_add_adapter(p_adap);
|
||||||
|
if (rc < 0)
|
||||||
|
free_irq(iface->irq, iface);
|
||||||
|
else
|
||||||
|
platform_set_drvdata(dev, iface);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_bfin_twi_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct bfin_twi_iface *iface = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
|
||||||
|
i2c_del_adapter(&(iface->adap));
|
||||||
|
free_irq(iface->irq, iface);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver i2c_bfin_twi_driver = {
|
||||||
|
.probe = i2c_bfin_twi_probe,
|
||||||
|
.remove = i2c_bfin_twi_remove,
|
||||||
|
.suspend = i2c_bfin_twi_suspend,
|
||||||
|
.resume = i2c_bfin_twi_resume,
|
||||||
|
.driver = {
|
||||||
|
.name = "i2c-bfin-twi",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init i2c_bfin_twi_init(void)
|
||||||
|
{
|
||||||
|
pr_info("I2C: Blackfin I2C TWI driver\n");
|
||||||
|
|
||||||
|
return platform_driver_register(&i2c_bfin_twi_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit i2c_bfin_twi_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&i2c_bfin_twi_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
|
||||||
|
MODULE_DESCRIPTION("I2C-Bus adapter routines for Blackfin TWI");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
module_init(i2c_bfin_twi_init);
|
||||||
|
module_exit(i2c_bfin_twi_exit);
|
@ -35,6 +35,7 @@
|
|||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
|
|
||||||
|
#include <linux/isa.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-algo-pcf.h>
|
#include <linux/i2c-algo-pcf.h>
|
||||||
|
|
||||||
@ -207,7 +208,7 @@ static struct i2c_adapter pcf_isa_ops = {
|
|||||||
.name = "i2c-elektor",
|
.name = "i2c-elektor",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init i2c_pcfisa_init(void)
|
static int __devinit elektor_match(struct device *dev, unsigned int id)
|
||||||
{
|
{
|
||||||
#ifdef __alpha__
|
#ifdef __alpha__
|
||||||
/* check to see we have memory mapped PCF8584 connected to the
|
/* check to see we have memory mapped PCF8584 connected to the
|
||||||
@ -222,9 +223,8 @@ static int __init i2c_pcfisa_init(void)
|
|||||||
/* yeap, we've found cypress, let's check config */
|
/* yeap, we've found cypress, let's check config */
|
||||||
if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
|
if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
|
||||||
|
|
||||||
pr_debug("%s: found cy82c693, config "
|
dev_dbg(dev, "found cy82c693, config "
|
||||||
"register 0x47 = 0x%02x\n",
|
"register 0x47 = 0x%02x\n", config);
|
||||||
pcf_isa_ops.name, config);
|
|
||||||
|
|
||||||
/* UP2000 board has this register set to 0xe1,
|
/* UP2000 board has this register set to 0xe1,
|
||||||
but the most significant bit as seems can be
|
but the most significant bit as seems can be
|
||||||
@ -244,9 +244,9 @@ static int __init i2c_pcfisa_init(void)
|
|||||||
8.25 MHz (PCI/4) clock
|
8.25 MHz (PCI/4) clock
|
||||||
(this can be read from cypress) */
|
(this can be read from cypress) */
|
||||||
clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
|
clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
|
||||||
pr_info("%s: found API UP2000 like "
|
dev_info(dev, "found API UP2000 like "
|
||||||
"board, will probe PCF8584 "
|
"board, will probe PCF8584 "
|
||||||
"later\n", pcf_isa_ops.name);
|
"later\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pci_dev_put(cy693_dev);
|
pci_dev_put(cy693_dev);
|
||||||
@ -256,22 +256,27 @@ static int __init i2c_pcfisa_init(void)
|
|||||||
|
|
||||||
/* sanity checks for mmapped I/O */
|
/* sanity checks for mmapped I/O */
|
||||||
if (mmapped && base < 0xc8000) {
|
if (mmapped && base < 0xc8000) {
|
||||||
printk(KERN_ERR "%s: incorrect base address (%#x) specified "
|
dev_err(dev, "incorrect base address (%#x) specified "
|
||||||
"for mmapped I/O\n", pcf_isa_ops.name, base);
|
"for mmapped I/O\n", base);
|
||||||
return -ENODEV;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
base = DEFAULT_BASE;
|
base = DEFAULT_BASE;
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __devinit elektor_probe(struct device *dev, unsigned int id)
|
||||||
|
{
|
||||||
init_waitqueue_head(&pcf_wait);
|
init_waitqueue_head(&pcf_wait);
|
||||||
if (pcf_isa_init())
|
if (pcf_isa_init())
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
pcf_isa_ops.dev.parent = dev;
|
||||||
if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
|
if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base);
|
dev_info(dev, "found device at %#x\n", base);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -291,7 +296,7 @@ static int __init i2c_pcfisa_init(void)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void i2c_pcfisa_exit(void)
|
static int __devexit elektor_remove(struct device *dev, unsigned int id)
|
||||||
{
|
{
|
||||||
i2c_del_adapter(&pcf_isa_ops);
|
i2c_del_adapter(&pcf_isa_ops);
|
||||||
|
|
||||||
@ -307,6 +312,28 @@ static void i2c_pcfisa_exit(void)
|
|||||||
iounmap(base_iomem);
|
iounmap(base_iomem);
|
||||||
release_mem_region(base, 2);
|
release_mem_region(base, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct isa_driver i2c_elektor_driver = {
|
||||||
|
.match = elektor_match,
|
||||||
|
.probe = elektor_probe,
|
||||||
|
.remove = __devexit_p(elektor_remove),
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "i2c-elektor",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init i2c_pcfisa_init(void)
|
||||||
|
{
|
||||||
|
return isa_register_driver(&i2c_elektor_driver, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit i2c_pcfisa_exit(void)
|
||||||
|
{
|
||||||
|
isa_unregister_driver(&i2c_elektor_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
|
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
|
||||||
|
215
drivers/i2c/busses/i2c-gpio.c
Normal file
215
drivers/i2c/busses/i2c-gpio.c
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* Bitbanging I2C bus driver using the GPIO API
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Atmel Corporation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-algo-bit.h>
|
||||||
|
#include <linux/i2c-gpio.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#include <asm/gpio.h>
|
||||||
|
|
||||||
|
/* Toggle SDA by changing the direction of the pin */
|
||||||
|
static void i2c_gpio_setsda_dir(void *data, int state)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
gpio_direction_input(pdata->sda_pin);
|
||||||
|
else
|
||||||
|
gpio_direction_output(pdata->sda_pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle SDA by changing the output value of the pin. This is only
|
||||||
|
* valid for pins configured as open drain (i.e. setting the value
|
||||||
|
* high effectively turns off the output driver.)
|
||||||
|
*/
|
||||||
|
static void i2c_gpio_setsda_val(void *data, int state)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
gpio_set_value(pdata->sda_pin, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toggle SCL by changing the direction of the pin. */
|
||||||
|
static void i2c_gpio_setscl_dir(void *data, int state)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
if (state)
|
||||||
|
gpio_direction_input(pdata->scl_pin);
|
||||||
|
else
|
||||||
|
gpio_direction_output(pdata->scl_pin, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Toggle SCL by changing the output value of the pin. This is used
|
||||||
|
* for pins that are configured as open drain and for output-only
|
||||||
|
* pins. The latter case will break the i2c protocol, but it will
|
||||||
|
* often work in practice.
|
||||||
|
*/
|
||||||
|
static void i2c_gpio_setscl_val(void *data, int state)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
gpio_set_value(pdata->scl_pin, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i2c_gpio_getsda(void *data)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
return gpio_get_value(pdata->sda_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
int i2c_gpio_getscl(void *data)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata = data;
|
||||||
|
|
||||||
|
return gpio_get_value(pdata->scl_pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init i2c_gpio_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata;
|
||||||
|
struct i2c_algo_bit_data *bit_data;
|
||||||
|
struct i2c_adapter *adap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pdata = pdev->dev.platform_data;
|
||||||
|
if (!pdata)
|
||||||
|
return -ENXIO;
|
||||||
|
|
||||||
|
ret = -ENOMEM;
|
||||||
|
adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
|
||||||
|
if (!adap)
|
||||||
|
goto err_alloc_adap;
|
||||||
|
bit_data = kzalloc(sizeof(struct i2c_algo_bit_data), GFP_KERNEL);
|
||||||
|
if (!bit_data)
|
||||||
|
goto err_alloc_bit_data;
|
||||||
|
|
||||||
|
ret = gpio_request(pdata->sda_pin, "sda");
|
||||||
|
if (ret)
|
||||||
|
goto err_request_sda;
|
||||||
|
ret = gpio_request(pdata->scl_pin, "scl");
|
||||||
|
if (ret)
|
||||||
|
goto err_request_scl;
|
||||||
|
|
||||||
|
if (pdata->sda_is_open_drain) {
|
||||||
|
gpio_direction_output(pdata->sda_pin, 1);
|
||||||
|
bit_data->setsda = i2c_gpio_setsda_val;
|
||||||
|
} else {
|
||||||
|
gpio_direction_input(pdata->sda_pin);
|
||||||
|
bit_data->setsda = i2c_gpio_setsda_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdata->scl_is_open_drain || pdata->scl_is_output_only) {
|
||||||
|
gpio_direction_output(pdata->scl_pin, 1);
|
||||||
|
bit_data->setscl = i2c_gpio_setscl_val;
|
||||||
|
} else {
|
||||||
|
gpio_direction_input(pdata->scl_pin);
|
||||||
|
bit_data->setscl = i2c_gpio_setscl_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pdata->scl_is_output_only)
|
||||||
|
bit_data->getscl = i2c_gpio_getscl;
|
||||||
|
bit_data->getsda = i2c_gpio_getsda;
|
||||||
|
|
||||||
|
if (pdata->udelay)
|
||||||
|
bit_data->udelay = pdata->udelay;
|
||||||
|
else if (pdata->scl_is_output_only)
|
||||||
|
bit_data->udelay = 50; /* 10 kHz */
|
||||||
|
else
|
||||||
|
bit_data->udelay = 5; /* 100 kHz */
|
||||||
|
|
||||||
|
if (pdata->timeout)
|
||||||
|
bit_data->timeout = pdata->timeout;
|
||||||
|
else
|
||||||
|
bit_data->timeout = HZ / 10; /* 100 ms */
|
||||||
|
|
||||||
|
bit_data->data = pdata;
|
||||||
|
|
||||||
|
adap->owner = THIS_MODULE;
|
||||||
|
snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
|
||||||
|
adap->algo_data = bit_data;
|
||||||
|
adap->dev.parent = &pdev->dev;
|
||||||
|
|
||||||
|
ret = i2c_bit_add_bus(adap);
|
||||||
|
if (ret)
|
||||||
|
goto err_add_bus;
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, adap);
|
||||||
|
|
||||||
|
dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n",
|
||||||
|
pdata->sda_pin, pdata->scl_pin,
|
||||||
|
pdata->scl_is_output_only
|
||||||
|
? ", no clock stretching" : "");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_add_bus:
|
||||||
|
gpio_free(pdata->scl_pin);
|
||||||
|
err_request_scl:
|
||||||
|
gpio_free(pdata->sda_pin);
|
||||||
|
err_request_sda:
|
||||||
|
kfree(bit_data);
|
||||||
|
err_alloc_bit_data:
|
||||||
|
kfree(adap);
|
||||||
|
err_alloc_adap:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __exit i2c_gpio_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct i2c_gpio_platform_data *pdata;
|
||||||
|
struct i2c_adapter *adap;
|
||||||
|
|
||||||
|
adap = platform_get_drvdata(pdev);
|
||||||
|
pdata = pdev->dev.platform_data;
|
||||||
|
|
||||||
|
i2c_del_adapter(adap);
|
||||||
|
gpio_free(pdata->scl_pin);
|
||||||
|
gpio_free(pdata->sda_pin);
|
||||||
|
kfree(adap->algo_data);
|
||||||
|
kfree(adap);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver i2c_gpio_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "i2c-gpio",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.remove = __exit_p(i2c_gpio_remove),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init i2c_gpio_init(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = platform_driver_probe(&i2c_gpio_driver, i2c_gpio_probe);
|
||||||
|
if (ret)
|
||||||
|
printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
module_init(i2c_gpio_init);
|
||||||
|
|
||||||
|
static void __exit i2c_gpio_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&i2c_gpio_driver);
|
||||||
|
}
|
||||||
|
module_exit(i2c_gpio_exit);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>");
|
||||||
|
MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
@ -527,7 +527,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
|
|||||||
/* set up the sysfs linkage to our parent device */
|
/* set up the sysfs linkage to our parent device */
|
||||||
i801_adapter.dev.parent = &dev->dev;
|
i801_adapter.dev.parent = &dev->dev;
|
||||||
|
|
||||||
snprintf(i801_adapter.name, I2C_NAME_SIZE,
|
snprintf(i801_adapter.name, sizeof(i801_adapter.name),
|
||||||
"SMBus I801 adapter at %04lx", i801_smba);
|
"SMBus I801 adapter at %04lx", i801_smba);
|
||||||
err = i2c_add_adapter(&i801_adapter);
|
err = i2c_add_adapter(&i801_adapter);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -41,6 +41,10 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
|
|
||||||
|
/* Exported by i2c-core for i2c-isa only */
|
||||||
|
extern void i2c_adapter_dev_release(struct device *dev);
|
||||||
|
extern struct class i2c_adapter_class;
|
||||||
|
|
||||||
static u32 isa_func(struct i2c_adapter *adapter);
|
static u32 isa_func(struct i2c_adapter *adapter);
|
||||||
|
|
||||||
/* This is the actual algorithm we define */
|
/* This is the actual algorithm we define */
|
||||||
@ -64,16 +68,6 @@ static u32 isa_func(struct i2c_adapter *adapter)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Copied from i2c-core */
|
|
||||||
static ssize_t show_adapter_name(struct device *dev,
|
|
||||||
struct device_attribute *attr, char *buf)
|
|
||||||
{
|
|
||||||
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
|
|
||||||
return sprintf(buf, "%s\n", adap->name);
|
|
||||||
}
|
|
||||||
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
|
|
||||||
|
|
||||||
|
|
||||||
/* We implement an interface which resembles i2c_{add,del}_driver,
|
/* We implement an interface which resembles i2c_{add,del}_driver,
|
||||||
but for i2c-isa drivers. We don't have to remember and handle lists
|
but for i2c-isa drivers. We don't have to remember and handle lists
|
||||||
of drivers and adapters so this is much more simple, of course. */
|
of drivers and adapters so this is much more simple, of course. */
|
||||||
@ -139,41 +133,18 @@ static int __init i2c_isa_init(void)
|
|||||||
isa_adapter.nr = ANY_I2C_ISA_BUS;
|
isa_adapter.nr = ANY_I2C_ISA_BUS;
|
||||||
isa_adapter.dev.parent = &platform_bus;
|
isa_adapter.dev.parent = &platform_bus;
|
||||||
sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
|
sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
|
||||||
isa_adapter.dev.driver = &i2c_adapter_driver;
|
|
||||||
isa_adapter.dev.release = &i2c_adapter_dev_release;
|
isa_adapter.dev.release = &i2c_adapter_dev_release;
|
||||||
|
isa_adapter.dev.class = &i2c_adapter_class;
|
||||||
err = device_register(&isa_adapter.dev);
|
err = device_register(&isa_adapter.dev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "i2c-isa: Failed to register device\n");
|
printk(KERN_ERR "i2c-isa: Failed to register device\n");
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
err = device_create_file(&isa_adapter.dev, &dev_attr_name);
|
|
||||||
if (err) {
|
|
||||||
printk(KERN_ERR "i2c-isa: Failed to create name file\n");
|
|
||||||
goto exit_unregister;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add this adapter to the i2c_adapter class */
|
|
||||||
memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
|
|
||||||
isa_adapter.class_dev.dev = &isa_adapter.dev;
|
|
||||||
isa_adapter.class_dev.class = &i2c_adapter_class;
|
|
||||||
strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
|
|
||||||
BUS_ID_SIZE);
|
|
||||||
err = class_device_register(&isa_adapter.class_dev);
|
|
||||||
if (err) {
|
|
||||||
printk(KERN_ERR "i2c-isa: Failed to register class device\n");
|
|
||||||
goto exit_remove_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
|
dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
exit_remove_name:
|
|
||||||
device_remove_file(&isa_adapter.dev, &dev_attr_name);
|
|
||||||
exit_unregister:
|
|
||||||
init_completion(&isa_adapter.dev_released); /* Needed? */
|
|
||||||
device_unregister(&isa_adapter.dev);
|
|
||||||
wait_for_completion(&isa_adapter.dev_released);
|
|
||||||
exit:
|
exit:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -201,15 +172,11 @@ static void __exit i2c_isa_exit(void)
|
|||||||
/* Clean up the sysfs representation */
|
/* Clean up the sysfs representation */
|
||||||
dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
|
dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
|
||||||
init_completion(&isa_adapter.dev_released);
|
init_completion(&isa_adapter.dev_released);
|
||||||
init_completion(&isa_adapter.class_dev_released);
|
|
||||||
class_device_unregister(&isa_adapter.class_dev);
|
|
||||||
device_remove_file(&isa_adapter.dev, &dev_attr_name);
|
|
||||||
device_unregister(&isa_adapter.dev);
|
device_unregister(&isa_adapter.dev);
|
||||||
|
|
||||||
/* Wait for sysfs to drop all references */
|
/* Wait for sysfs to drop all references */
|
||||||
dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
|
dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
|
||||||
wait_for_completion(&isa_adapter.dev_released);
|
wait_for_completion(&isa_adapter.dev_released);
|
||||||
wait_for_completion(&isa_adapter.class_dev_released);
|
|
||||||
|
|
||||||
dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
|
dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
|
|||||||
|
|
||||||
drv_data->adapter.id = I2C_HW_B_IXP2000,
|
drv_data->adapter.id = I2C_HW_B_IXP2000,
|
||||||
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
|
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
|
||||||
I2C_NAME_SIZE);
|
sizeof(drv_data->adapter.name));
|
||||||
drv_data->adapter.algo_data = &drv_data->algo_data,
|
drv_data->adapter.algo_data = &drv_data->algo_data,
|
||||||
|
|
||||||
drv_data->adapter.dev.parent = &plat_dev->dev;
|
drv_data->adapter.dev.parent = &plat_dev->dev;
|
||||||
|
@ -127,7 +127,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
|
|||||||
drv_data->adapter.id = I2C_HW_B_IXP4XX;
|
drv_data->adapter.id = I2C_HW_B_IXP4XX;
|
||||||
drv_data->adapter.class = I2C_CLASS_HWMON;
|
drv_data->adapter.class = I2C_CLASS_HWMON;
|
||||||
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
|
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
|
||||||
I2C_NAME_SIZE);
|
sizeof(drv_data->adapter.name));
|
||||||
drv_data->adapter.algo_data = &drv_data->algo_data;
|
drv_data->adapter.algo_data = &drv_data->algo_data;
|
||||||
|
|
||||||
drv_data->adapter.dev.parent = &plat_dev->dev;
|
drv_data->adapter.dev.parent = &plat_dev->dev;
|
||||||
|
@ -508,7 +508,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
|
strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
|
||||||
I2C_NAME_SIZE);
|
sizeof(drv_data->adapter.name));
|
||||||
|
|
||||||
init_waitqueue_head(&drv_data->waitq);
|
init_waitqueue_head(&drv_data->waitq);
|
||||||
spin_lock_init(&drv_data->lock);
|
spin_lock_init(&drv_data->lock);
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
nForce4 MCP-04 0034
|
nForce4 MCP-04 0034
|
||||||
nForce4 MCP51 0264
|
nForce4 MCP51 0264
|
||||||
nForce4 MCP55 0368
|
nForce4 MCP55 0368
|
||||||
|
nForce MCP61 03EB
|
||||||
|
nForce MCP65 0446
|
||||||
|
|
||||||
This driver supports the 2 SMBuses that are included in the MCP of the
|
This driver supports the 2 SMBuses that are included in the MCP of the
|
||||||
nForce2/3/4/5xx chipsets.
|
nForce2/3/4/5xx chipsets.
|
||||||
@ -200,6 +202,8 @@ static struct pci_device_id nforce2_ids[] = {
|
|||||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) },
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
|
{ 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) },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -240,7 +244,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
|
|||||||
smbus->adapter.algo = &smbus_algorithm;
|
smbus->adapter.algo = &smbus_algorithm;
|
||||||
smbus->adapter.algo_data = smbus;
|
smbus->adapter.algo_data = smbus;
|
||||||
smbus->adapter.dev.parent = &dev->dev;
|
smbus->adapter.dev.parent = &dev->dev;
|
||||||
snprintf(smbus->adapter.name, I2C_NAME_SIZE,
|
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
|
||||||
"SMBus nForce2 adapter at %04x", smbus->base);
|
"SMBus nForce2 adapter at %04x", smbus->base);
|
||||||
|
|
||||||
error = i2c_add_adapter(&smbus->adapter);
|
error = i2c_add_adapter(&smbus->adapter);
|
||||||
|
@ -605,7 +605,8 @@ omap_i2c_probe(struct platform_device *pdev)
|
|||||||
adap->dev.parent = &pdev->dev;
|
adap->dev.parent = &pdev->dev;
|
||||||
|
|
||||||
/* i2c device drivers may be active on return from add_adapter() */
|
/* i2c device drivers may be active on return from add_adapter() */
|
||||||
r = i2c_add_adapter(adap);
|
adap->nr = pdev->id;
|
||||||
|
r = i2c_add_numbered_adapter(adap);
|
||||||
if (r) {
|
if (r) {
|
||||||
dev_err(dev->dev, "failure adding adapter\n");
|
dev_err(dev->dev, "failure adding adapter\n");
|
||||||
goto err_free_irq;
|
goto err_free_irq;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* ------------------------------------------------------------------------ *
|
/* ------------------------------------------------------------------------ *
|
||||||
* i2c-parport.c I2C bus over parallel port *
|
* i2c-parport-light.c I2C bus over parallel port *
|
||||||
* ------------------------------------------------------------------------ *
|
* ------------------------------------------------------------------------ *
|
||||||
Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
|
Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
|
||||||
|
|
||||||
Based on older i2c-velleman.c driver
|
Based on older i2c-velleman.c driver
|
||||||
Copyright (C) 1995-2000 Simon G. Vogl
|
Copyright (C) 1995-2000 Simon G. Vogl
|
||||||
@ -27,6 +27,7 @@
|
|||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-algo-bit.h>
|
#include <linux/i2c-algo-bit.h>
|
||||||
@ -34,6 +35,9 @@
|
|||||||
#include "i2c-parport.h"
|
#include "i2c-parport.h"
|
||||||
|
|
||||||
#define DEFAULT_BASE 0x378
|
#define DEFAULT_BASE 0x378
|
||||||
|
#define DRVNAME "i2c-parport-light"
|
||||||
|
|
||||||
|
static struct platform_device *pdev;
|
||||||
|
|
||||||
static u16 base;
|
static u16 base;
|
||||||
module_param(base, ushort, 0);
|
module_param(base, ushort, 0);
|
||||||
@ -106,7 +110,7 @@ static struct i2c_algo_bit_data parport_algo_data = {
|
|||||||
.timeout = HZ,
|
.timeout = HZ,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----- I2c structure ---------------------------------------------------- */
|
/* ----- Driver registration ---------------------------------------------- */
|
||||||
|
|
||||||
static struct i2c_adapter parport_adapter = {
|
static struct i2c_adapter parport_adapter = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
@ -116,30 +120,14 @@ static struct i2c_adapter parport_adapter = {
|
|||||||
.name = "Parallel port adapter (light)",
|
.name = "Parallel port adapter (light)",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----- Module loading, unloading and information ------------------------ */
|
static int __devinit i2c_parport_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
static int __init i2c_parport_init(void)
|
|
||||||
{
|
{
|
||||||
if (type < 0) {
|
int err;
|
||||||
printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
|
struct resource *res;
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type >= ARRAY_SIZE(adapter_parm)) {
|
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
|
if (!request_region(res->start, res->end - res->start + 1, DRVNAME))
|
||||||
return -ENODEV;
|
return -EBUSY;
|
||||||
}
|
|
||||||
|
|
||||||
if (base == 0) {
|
|
||||||
printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
|
|
||||||
base = DEFAULT_BASE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!request_region(base, 3, "i2c-parport"))
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
if (!adapter_parm[type].getscl.val)
|
|
||||||
parport_algo_data.getscl = NULL;
|
|
||||||
|
|
||||||
/* Reset hardware to a sane state (SCL and SDA high) */
|
/* Reset hardware to a sane state (SCL and SDA high) */
|
||||||
parport_setsda(NULL, 1);
|
parport_setsda(NULL, 1);
|
||||||
@ -148,23 +136,125 @@ static int __init i2c_parport_init(void)
|
|||||||
if (adapter_parm[type].init.val)
|
if (adapter_parm[type].init.val)
|
||||||
line_set(1, &adapter_parm[type].init);
|
line_set(1, &adapter_parm[type].init);
|
||||||
|
|
||||||
if (i2c_bit_add_bus(&parport_adapter) < 0) {
|
parport_adapter.dev.parent = &pdev->dev;
|
||||||
printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
|
err = i2c_bit_add_bus(&parport_adapter);
|
||||||
release_region(base, 3);
|
if (err) {
|
||||||
return -ENODEV;
|
dev_err(&pdev->dev, "Unable to register with I2C\n");
|
||||||
|
goto exit_region;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
exit_region:
|
||||||
|
release_region(res->start, res->end - res->start + 1);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit i2c_parport_exit(void)
|
static int __devexit i2c_parport_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
struct resource *res;
|
||||||
|
|
||||||
|
i2c_del_adapter(&parport_adapter);
|
||||||
|
|
||||||
/* Un-init if needed (power off...) */
|
/* Un-init if needed (power off...) */
|
||||||
if (adapter_parm[type].init.val)
|
if (adapter_parm[type].init.val)
|
||||||
line_set(0, &adapter_parm[type].init);
|
line_set(0, &adapter_parm[type].init);
|
||||||
|
|
||||||
i2c_del_adapter(&parport_adapter);
|
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
release_region(base, 3);
|
release_region(res->start, res->end - res->start + 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver i2c_parport_driver = {
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = DRVNAME,
|
||||||
|
},
|
||||||
|
.probe = i2c_parport_probe,
|
||||||
|
.remove = __devexit_p(i2c_parport_remove),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init i2c_parport_device_add(u16 address)
|
||||||
|
{
|
||||||
|
struct resource res = {
|
||||||
|
.start = address,
|
||||||
|
.end = address + 2,
|
||||||
|
.name = DRVNAME,
|
||||||
|
.flags = IORESOURCE_IO,
|
||||||
|
};
|
||||||
|
int err;
|
||||||
|
|
||||||
|
pdev = platform_device_alloc(DRVNAME, -1);
|
||||||
|
if (!pdev) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = platform_device_add_resources(pdev, &res, 1);
|
||||||
|
if (err) {
|
||||||
|
printk(KERN_ERR DRVNAME ": Device resource addition failed "
|
||||||
|
"(%d)\n", err);
|
||||||
|
goto exit_device_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = platform_device_add(pdev);
|
||||||
|
if (err) {
|
||||||
|
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
|
||||||
|
err);
|
||||||
|
goto exit_device_put;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit_device_put:
|
||||||
|
platform_device_put(pdev);
|
||||||
|
exit:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init i2c_parport_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (type < 0) {
|
||||||
|
printk(KERN_ERR DRVNAME ": adapter type unspecified\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type >= ARRAY_SIZE(adapter_parm)) {
|
||||||
|
printk(KERN_ERR DRVNAME ": invalid type (%d)\n", type);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (base == 0) {
|
||||||
|
pr_info(DRVNAME ": using default base 0x%x\n", DEFAULT_BASE);
|
||||||
|
base = DEFAULT_BASE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!adapter_parm[type].getscl.val)
|
||||||
|
parport_algo_data.getscl = NULL;
|
||||||
|
|
||||||
|
/* Sets global pdev as a side effect */
|
||||||
|
err = i2c_parport_device_add(base);
|
||||||
|
if (err)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
err = platform_driver_register(&i2c_parport_driver);
|
||||||
|
if (err)
|
||||||
|
goto exit_device;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
exit_device:
|
||||||
|
platform_device_unregister(pdev);
|
||||||
|
exit:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit i2c_parport_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&i2c_parport_driver);
|
||||||
|
platform_device_unregister(pdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
|
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* ------------------------------------------------------------------------ *
|
/* ------------------------------------------------------------------------ *
|
||||||
* i2c-parport.c I2C bus over parallel port *
|
* i2c-parport.c I2C bus over parallel port *
|
||||||
* ------------------------------------------------------------------------ *
|
* ------------------------------------------------------------------------ *
|
||||||
Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
|
Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
|
||||||
|
|
||||||
Based on older i2c-philips-par.c driver
|
Based on older i2c-philips-par.c driver
|
||||||
Copyright (C) 1995-2000 Simon G. Vogl
|
Copyright (C) 1995-2000 Simon G. Vogl
|
||||||
@ -137,19 +137,12 @@ static struct i2c_algo_bit_data parport_algo_data = {
|
|||||||
.setscl = parport_setscl,
|
.setscl = parport_setscl,
|
||||||
.getsda = parport_getsda,
|
.getsda = parport_getsda,
|
||||||
.getscl = parport_getscl,
|
.getscl = parport_getscl,
|
||||||
.udelay = 60,
|
.udelay = 10, /* ~50 kbps */
|
||||||
.timeout = HZ,
|
.timeout = HZ,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----- I2c and parallel port call-back functions and structures --------- */
|
/* ----- I2c and parallel port call-back functions and structures --------- */
|
||||||
|
|
||||||
static struct i2c_adapter parport_adapter = {
|
|
||||||
.owner = THIS_MODULE,
|
|
||||||
.class = I2C_CLASS_HWMON,
|
|
||||||
.id = I2C_HW_B_LP,
|
|
||||||
.name = "Parallel port adapter",
|
|
||||||
};
|
|
||||||
|
|
||||||
static void i2c_parport_attach (struct parport *port)
|
static void i2c_parport_attach (struct parport *port)
|
||||||
{
|
{
|
||||||
struct i2c_par *adapter;
|
struct i2c_par *adapter;
|
||||||
@ -169,10 +162,17 @@ static void i2c_parport_attach (struct parport *port)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fill the rest of the structure */
|
/* Fill the rest of the structure */
|
||||||
adapter->adapter = parport_adapter;
|
adapter->adapter.owner = THIS_MODULE;
|
||||||
|
adapter->adapter.class = I2C_CLASS_HWMON;
|
||||||
|
adapter->adapter.id = I2C_HW_B_LP;
|
||||||
|
strlcpy(adapter->adapter.name, "Parallel port adapter",
|
||||||
|
sizeof(adapter->adapter.name));
|
||||||
adapter->algo_data = parport_algo_data;
|
adapter->algo_data = parport_algo_data;
|
||||||
if (!adapter_parm[type].getscl.val)
|
/* Slow down if we can't sense SCL */
|
||||||
|
if (!adapter_parm[type].getscl.val) {
|
||||||
adapter->algo_data.getscl = NULL;
|
adapter->algo_data.getscl = NULL;
|
||||||
|
adapter->algo_data.udelay = 50; /* ~10 kbps */
|
||||||
|
}
|
||||||
adapter->algo_data.data = port;
|
adapter->algo_data.data = port;
|
||||||
adapter->adapter.algo_data = &adapter->algo_data;
|
adapter->adapter.algo_data = &adapter->algo_data;
|
||||||
|
|
||||||
@ -214,11 +214,12 @@ static void i2c_parport_detach (struct parport *port)
|
|||||||
for (prev = NULL, adapter = adapter_list; adapter;
|
for (prev = NULL, adapter = adapter_list; adapter;
|
||||||
prev = adapter, adapter = adapter->next) {
|
prev = adapter, adapter = adapter->next) {
|
||||||
if (adapter->pdev->port == port) {
|
if (adapter->pdev->port == port) {
|
||||||
|
i2c_del_adapter(&adapter->adapter);
|
||||||
|
|
||||||
/* Un-init if needed (power off...) */
|
/* Un-init if needed (power off...) */
|
||||||
if (adapter_parm[type].init.val)
|
if (adapter_parm[type].init.val)
|
||||||
line_set(port, 0, &adapter_parm[type].init);
|
line_set(port, 0, &adapter_parm[type].init);
|
||||||
|
|
||||||
i2c_del_adapter(&adapter->adapter);
|
|
||||||
parport_unregister_device(adapter->pdev);
|
parport_unregister_device(adapter->pdev);
|
||||||
if (prev)
|
if (prev)
|
||||||
prev->next = adapter->next;
|
prev->next = adapter->next;
|
||||||
|
@ -358,7 +358,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
smbus->adapter.owner = THIS_MODULE;
|
smbus->adapter.owner = THIS_MODULE;
|
||||||
snprintf(smbus->adapter.name, I2C_NAME_SIZE,
|
snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
|
||||||
"PA Semi SMBus adapter at 0x%lx", smbus->base);
|
"PA Semi SMBus adapter at 0x%lx", smbus->base);
|
||||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||||
smbus->adapter.algo = &smbus_algorithm;
|
smbus->adapter.algo = &smbus_algorithm;
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
|
|
||||||
|
#include <linux/isa.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/i2c-algo-pca.h>
|
#include <linux/i2c-algo-pca.h>
|
||||||
|
|
||||||
@ -119,27 +120,26 @@ static struct i2c_adapter pca_isa_ops = {
|
|||||||
.name = "PCA9564 ISA Adapter",
|
.name = "PCA9564 ISA Adapter",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init pca_isa_init(void)
|
static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
|
||||||
{
|
{
|
||||||
|
|
||||||
init_waitqueue_head(&pca_wait);
|
init_waitqueue_head(&pca_wait);
|
||||||
|
|
||||||
printk(KERN_INFO "i2c-pca-isa: i/o base %#08lx. irq %d\n", base, irq);
|
dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);
|
||||||
|
|
||||||
if (!request_region(base, IO_SIZE, "i2c-pca-isa")) {
|
if (!request_region(base, IO_SIZE, "i2c-pca-isa")) {
|
||||||
printk(KERN_ERR "i2c-pca-isa: I/O address %#08lx is in use.\n", base);
|
dev_err(dev, "I/O address %#08lx is in use\n", base);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (irq > -1) {
|
if (irq > -1) {
|
||||||
if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) {
|
if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) {
|
||||||
printk(KERN_ERR "i2c-pca-isa: Request irq%d failed\n", irq);
|
dev_err(dev, "Request irq%d failed\n", irq);
|
||||||
goto out_region;
|
goto out_region;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
|
if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
|
||||||
printk(KERN_ERR "i2c-pca-isa: Failed to add i2c bus\n");
|
dev_err(dev, "Failed to add i2c bus\n");
|
||||||
goto out_irq;
|
goto out_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ static int __init pca_isa_init(void)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pca_isa_exit(void)
|
static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
|
||||||
{
|
{
|
||||||
i2c_del_adapter(&pca_isa_ops);
|
i2c_del_adapter(&pca_isa_ops);
|
||||||
|
|
||||||
@ -163,6 +163,27 @@ static void pca_isa_exit(void)
|
|||||||
free_irq(irq, &pca_isa_ops);
|
free_irq(irq, &pca_isa_ops);
|
||||||
}
|
}
|
||||||
release_region(base, IO_SIZE);
|
release_region(base, IO_SIZE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct isa_driver pca_isa_driver = {
|
||||||
|
.probe = pca_isa_probe,
|
||||||
|
.remove = __devexit_p(pca_isa_remove),
|
||||||
|
.driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "i2c-pca-isa",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init pca_isa_init(void)
|
||||||
|
{
|
||||||
|
return isa_register_driver(&pca_isa_driver, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit pca_isa_exit(void)
|
||||||
|
{
|
||||||
|
isa_unregister_driver(&pca_isa_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
|
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
|
||||||
|
@ -428,7 +428,7 @@ static int __devinit piix4_probe(struct pci_dev *dev,
|
|||||||
/* set up the sysfs linkage to our parent device */
|
/* set up the sysfs linkage to our parent device */
|
||||||
piix4_adapter.dev.parent = &dev->dev;
|
piix4_adapter.dev.parent = &dev->dev;
|
||||||
|
|
||||||
snprintf(piix4_adapter.name, I2C_NAME_SIZE,
|
snprintf(piix4_adapter.name, sizeof(piix4_adapter.name),
|
||||||
"SMBus PIIX4 adapter at %04x", piix4_smba);
|
"SMBus PIIX4 adapter at %04x", piix4_smba);
|
||||||
|
|
||||||
if ((retval = i2c_add_adapter(&piix4_adapter))) {
|
if ((retval = i2c_add_adapter(&piix4_adapter))) {
|
||||||
|
@ -539,6 +539,18 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
|
|||||||
writel(icr | ICR_START | ICR_TB, _ICR(i2c));
|
writel(icr | ICR_START | ICR_TB, _ICR(i2c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
|
||||||
|
{
|
||||||
|
u32 icr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the STOP and ACK flags
|
||||||
|
*/
|
||||||
|
icr = readl(_ICR(i2c));
|
||||||
|
icr &= ~(ICR_STOP | ICR_ACKNAK);
|
||||||
|
writel(icr, _IRC(i2c));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We are protected by the adapter bus mutex.
|
* We are protected by the adapter bus mutex.
|
||||||
*/
|
*/
|
||||||
@ -581,6 +593,7 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
|
|||||||
* The rest of the processing occurs in the interrupt handler.
|
* The rest of the processing occurs in the interrupt handler.
|
||||||
*/
|
*/
|
||||||
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
|
||||||
|
i2c_pxa_stop_message(i2c);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We place the return code in i2c->msg_idx.
|
* We place the return code in i2c->msg_idx.
|
||||||
@ -825,7 +838,7 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct pxa_i2c i2c_pxa = {
|
static struct pxa_i2c i2c_pxa = {
|
||||||
.lock = SPIN_LOCK_UNLOCKED,
|
.lock = __SPIN_LOCK_UNLOCKED(i2c_pxa.lock),
|
||||||
.adap = {
|
.adap = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.algo = &i2c_pxa_algorithm,
|
.algo = &i2c_pxa_algorithm,
|
||||||
|
@ -61,6 +61,8 @@ struct s3c24xx_i2c {
|
|||||||
unsigned int msg_idx;
|
unsigned int msg_idx;
|
||||||
unsigned int msg_ptr;
|
unsigned int msg_ptr;
|
||||||
|
|
||||||
|
unsigned int tx_setup;
|
||||||
|
|
||||||
enum s3c24xx_i2c_state state;
|
enum s3c24xx_i2c_state state;
|
||||||
|
|
||||||
void __iomem *regs;
|
void __iomem *regs;
|
||||||
@ -199,8 +201,11 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
|
|||||||
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
|
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
|
||||||
writeb(addr, i2c->regs + S3C2410_IICDS);
|
writeb(addr, i2c->regs + S3C2410_IICDS);
|
||||||
|
|
||||||
// delay a bit and reset iiccon before setting start (per samsung)
|
/* delay here to ensure the data byte has gotten onto the bus
|
||||||
udelay(1);
|
* before the transaction is started */
|
||||||
|
|
||||||
|
ndelay(i2c->tx_setup);
|
||||||
|
|
||||||
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
|
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
|
||||||
writel(iiccon, i2c->regs + S3C2410_IICCON);
|
writel(iiccon, i2c->regs + S3C2410_IICCON);
|
||||||
|
|
||||||
@ -323,6 +328,14 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
|
|||||||
byte = i2c->msg->buf[i2c->msg_ptr++];
|
byte = i2c->msg->buf[i2c->msg_ptr++];
|
||||||
writeb(byte, i2c->regs + S3C2410_IICDS);
|
writeb(byte, i2c->regs + S3C2410_IICDS);
|
||||||
|
|
||||||
|
/* delay after writing the byte to allow the
|
||||||
|
* data setup time on the bus, as writing the
|
||||||
|
* data to the register causes the first bit
|
||||||
|
* to appear on SDA, and SCL will change as
|
||||||
|
* soon as the interrupt is acknowledged */
|
||||||
|
|
||||||
|
ndelay(i2c->tx_setup);
|
||||||
|
|
||||||
} else if (!is_lastmsg(i2c)) {
|
} else if (!is_lastmsg(i2c)) {
|
||||||
/* we need to go to the next i2c message */
|
/* we need to go to the next i2c message */
|
||||||
|
|
||||||
@ -570,8 +583,9 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct s3c24xx_i2c s3c24xx_i2c = {
|
static struct s3c24xx_i2c s3c24xx_i2c = {
|
||||||
.lock = SPIN_LOCK_UNLOCKED,
|
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
|
||||||
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
|
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
|
||||||
|
.tx_setup = 50,
|
||||||
.adap = {
|
.adap = {
|
||||||
.name = "s3c2410-i2c",
|
.name = "s3c2410-i2c",
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
@ -731,26 +745,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c)
|
|
||||||
{
|
|
||||||
if (i2c->clk != NULL && !IS_ERR(i2c->clk)) {
|
|
||||||
clk_disable(i2c->clk);
|
|
||||||
clk_put(i2c->clk);
|
|
||||||
i2c->clk = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c->regs != NULL) {
|
|
||||||
iounmap(i2c->regs);
|
|
||||||
i2c->regs = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i2c->ioarea != NULL) {
|
|
||||||
release_resource(i2c->ioarea);
|
|
||||||
kfree(i2c->ioarea);
|
|
||||||
i2c->ioarea = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* s3c24xx_i2c_probe
|
/* s3c24xx_i2c_probe
|
||||||
*
|
*
|
||||||
* called by the bus driver when a suitable device is found
|
* called by the bus driver when a suitable device is found
|
||||||
@ -769,7 +763,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||||||
if (IS_ERR(i2c->clk)) {
|
if (IS_ERR(i2c->clk)) {
|
||||||
dev_err(&pdev->dev, "cannot get clock\n");
|
dev_err(&pdev->dev, "cannot get clock\n");
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto out;
|
goto err_noclk;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
|
dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
|
||||||
@ -782,7 +776,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
dev_err(&pdev->dev, "cannot find IO resource\n");
|
dev_err(&pdev->dev, "cannot find IO resource\n");
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto out;
|
goto err_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
|
i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
|
||||||
@ -791,7 +785,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||||||
if (i2c->ioarea == NULL) {
|
if (i2c->ioarea == NULL) {
|
||||||
dev_err(&pdev->dev, "cannot request IO\n");
|
dev_err(&pdev->dev, "cannot request IO\n");
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
goto out;
|
goto err_clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c->regs = ioremap(res->start, (res->end-res->start)+1);
|
i2c->regs = ioremap(res->start, (res->end-res->start)+1);
|
||||||
@ -799,7 +793,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||||||
if (i2c->regs == NULL) {
|
if (i2c->regs == NULL) {
|
||||||
dev_err(&pdev->dev, "cannot map IO\n");
|
dev_err(&pdev->dev, "cannot map IO\n");
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
goto out;
|
goto err_ioarea;
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
|
dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
|
||||||
@ -813,7 +807,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
ret = s3c24xx_i2c_init(i2c);
|
ret = s3c24xx_i2c_init(i2c);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out;
|
goto err_iomap;
|
||||||
|
|
||||||
/* find the IRQ for this unit (note, this relies on the init call to
|
/* find the IRQ for this unit (note, this relies on the init call to
|
||||||
* ensure no current IRQs pending
|
* ensure no current IRQs pending
|
||||||
@ -823,7 +817,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
dev_err(&pdev->dev, "cannot find IRQ\n");
|
dev_err(&pdev->dev, "cannot find IRQ\n");
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
goto out;
|
goto err_iomap;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
|
ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
|
||||||
@ -831,7 +825,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
dev_err(&pdev->dev, "cannot claim IRQ\n");
|
dev_err(&pdev->dev, "cannot claim IRQ\n");
|
||||||
goto out;
|
goto err_iomap;
|
||||||
}
|
}
|
||||||
|
|
||||||
i2c->irq = res;
|
i2c->irq = res;
|
||||||
@ -841,17 +835,29 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
|||||||
ret = i2c_add_adapter(&i2c->adap);
|
ret = i2c_add_adapter(&i2c->adap);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
|
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
|
||||||
goto out;
|
goto err_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, i2c);
|
platform_set_drvdata(pdev, i2c);
|
||||||
|
|
||||||
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
|
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
|
||||||
|
return 0;
|
||||||
|
|
||||||
out:
|
err_irq:
|
||||||
if (ret < 0)
|
free_irq(i2c->irq->start, i2c);
|
||||||
s3c24xx_i2c_free(i2c);
|
|
||||||
|
|
||||||
|
err_iomap:
|
||||||
|
iounmap(i2c->regs);
|
||||||
|
|
||||||
|
err_ioarea:
|
||||||
|
release_resource(i2c->ioarea);
|
||||||
|
kfree(i2c->ioarea);
|
||||||
|
|
||||||
|
err_clk:
|
||||||
|
clk_disable(i2c->clk);
|
||||||
|
clk_put(i2c->clk);
|
||||||
|
|
||||||
|
err_noclk:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -864,10 +870,16 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
|
|||||||
{
|
{
|
||||||
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
|
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
if (i2c != NULL) {
|
i2c_del_adapter(&i2c->adap);
|
||||||
s3c24xx_i2c_free(i2c);
|
free_irq(i2c->irq->start, i2c);
|
||||||
platform_set_drvdata(pdev, NULL);
|
|
||||||
}
|
clk_disable(i2c->clk);
|
||||||
|
clk_put(i2c->clk);
|
||||||
|
|
||||||
|
iounmap(i2c->regs);
|
||||||
|
|
||||||
|
release_resource(i2c->ioarea);
|
||||||
|
kfree(i2c->ioarea);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
186
drivers/i2c/busses/i2c-simtec.c
Normal file
186
drivers/i2c/busses/i2c-simtec.c
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005 Simtec Electronics
|
||||||
|
* Ben Dooks <ben@simtec.co.uk>
|
||||||
|
*
|
||||||
|
* Simtec Generic I2C Controller
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
* 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/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/i2c-algo-bit.h>
|
||||||
|
|
||||||
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
struct simtec_i2c_data {
|
||||||
|
struct resource *ioarea;
|
||||||
|
void __iomem *reg;
|
||||||
|
struct i2c_adapter adap;
|
||||||
|
struct i2c_algo_bit_data bit;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CMD_SET_SDA (1<<2)
|
||||||
|
#define CMD_SET_SCL (1<<3)
|
||||||
|
|
||||||
|
#define STATE_SDA (1<<0)
|
||||||
|
#define STATE_SCL (1<<1)
|
||||||
|
|
||||||
|
/* i2c bit-bus functions */
|
||||||
|
|
||||||
|
static void simtec_i2c_setsda(void *pw, int state)
|
||||||
|
{
|
||||||
|
struct simtec_i2c_data *pd = pw;
|
||||||
|
writeb(CMD_SET_SDA | (state ? STATE_SDA : 0), pd->reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void simtec_i2c_setscl(void *pw, int state)
|
||||||
|
{
|
||||||
|
struct simtec_i2c_data *pd = pw;
|
||||||
|
writeb(CMD_SET_SCL | (state ? STATE_SCL : 0), pd->reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int simtec_i2c_getsda(void *pw)
|
||||||
|
{
|
||||||
|
struct simtec_i2c_data *pd = pw;
|
||||||
|
return readb(pd->reg) & STATE_SDA ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int simtec_i2c_getscl(void *pw)
|
||||||
|
{
|
||||||
|
struct simtec_i2c_data *pd = pw;
|
||||||
|
return readb(pd->reg) & STATE_SCL ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* device registration */
|
||||||
|
|
||||||
|
static int simtec_i2c_probe(struct platform_device *dev)
|
||||||
|
{
|
||||||
|
struct simtec_i2c_data *pd;
|
||||||
|
struct resource *res;
|
||||||
|
int size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL);
|
||||||
|
if (pd == NULL) {
|
||||||
|
dev_err(&dev->dev, "cannot allocate private data\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
platform_set_drvdata(dev, pd);
|
||||||
|
|
||||||
|
res = platform_get_resource(dev, IORESOURCE_MEM, 0);
|
||||||
|
if (res == NULL) {
|
||||||
|
dev_err(&dev->dev, "cannot find IO resource\n");
|
||||||
|
ret = -ENOENT;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (res->end-res->start)+1;
|
||||||
|
|
||||||
|
pd->ioarea = request_mem_region(res->start, size, dev->name);
|
||||||
|
if (pd->ioarea == NULL) {
|
||||||
|
dev_err(&dev->dev, "cannot request IO\n");
|
||||||
|
ret = -ENXIO;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pd->reg = ioremap(res->start, size);
|
||||||
|
if (pd->reg == NULL) {
|
||||||
|
dev_err(&dev->dev, "cannot map IO\n");
|
||||||
|
ret = -ENXIO;
|
||||||
|
goto err_res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup the private data */
|
||||||
|
|
||||||
|
pd->adap.owner = THIS_MODULE;
|
||||||
|
pd->adap.algo_data = &pd->bit;
|
||||||
|
pd->adap.dev.parent = &dev->dev;
|
||||||
|
|
||||||
|
strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name));
|
||||||
|
|
||||||
|
pd->bit.data = pd;
|
||||||
|
pd->bit.setsda = simtec_i2c_setsda;
|
||||||
|
pd->bit.setscl = simtec_i2c_setscl;
|
||||||
|
pd->bit.getsda = simtec_i2c_getsda;
|
||||||
|
pd->bit.getscl = simtec_i2c_getscl;
|
||||||
|
pd->bit.timeout = HZ;
|
||||||
|
pd->bit.udelay = 20;
|
||||||
|
|
||||||
|
ret = i2c_bit_add_bus(&pd->adap);
|
||||||
|
if (ret)
|
||||||
|
goto err_all;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_all:
|
||||||
|
iounmap(pd->reg);
|
||||||
|
|
||||||
|
err_res:
|
||||||
|
release_resource(pd->ioarea);
|
||||||
|
kfree(pd->ioarea);
|
||||||
|
|
||||||
|
err:
|
||||||
|
kfree(pd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int simtec_i2c_remove(struct platform_device *dev)
|
||||||
|
{
|
||||||
|
struct simtec_i2c_data *pd = platform_get_drvdata(dev);
|
||||||
|
|
||||||
|
i2c_del_adapter(&pd->adap);
|
||||||
|
|
||||||
|
iounmap(pd->reg);
|
||||||
|
release_resource(pd->ioarea);
|
||||||
|
kfree(pd->ioarea);
|
||||||
|
kfree(pd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* device driver */
|
||||||
|
|
||||||
|
static struct platform_driver simtec_i2c_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "simtec-i2c",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
},
|
||||||
|
.probe = simtec_i2c_probe,
|
||||||
|
.remove = simtec_i2c_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init i2c_adap_simtec_init(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&simtec_i2c_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit i2c_adap_simtec_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&simtec_i2c_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(i2c_adap_simtec_init);
|
||||||
|
module_exit(i2c_adap_simtec_exit);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
|
||||||
|
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
|
||||||
|
MODULE_LICENSE("GPL");
|
@ -300,7 +300,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
|
|||||||
/* set up the sysfs linkage to our parent device */
|
/* set up the sysfs linkage to our parent device */
|
||||||
sis96x_adapter.dev.parent = &dev->dev;
|
sis96x_adapter.dev.parent = &dev->dev;
|
||||||
|
|
||||||
snprintf(sis96x_adapter.name, I2C_NAME_SIZE,
|
snprintf(sis96x_adapter.name, sizeof(sis96x_adapter.name),
|
||||||
"SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base);
|
"SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base);
|
||||||
|
|
||||||
if ((retval = i2c_add_adapter(&sis96x_adapter))) {
|
if ((retval = i2c_add_adapter(&sis96x_adapter))) {
|
||||||
|
277
drivers/i2c/busses/i2c-tiny-usb.c
Normal file
277
drivers/i2c/busses/i2c-tiny-usb.c
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
* driver for the i2c-tiny-usb adapter - 1.0
|
||||||
|
* http://www.harbaum.org/till/i2c_tiny_usb
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.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 the Free Software Foundation, version 2.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
/* include interfaces to usb layer */
|
||||||
|
#include <linux/usb.h>
|
||||||
|
|
||||||
|
/* include interface to i2c layer */
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
|
||||||
|
/* commands via USB, must match command ids in the firmware */
|
||||||
|
#define CMD_ECHO 0
|
||||||
|
#define CMD_GET_FUNC 1
|
||||||
|
#define CMD_SET_DELAY 2
|
||||||
|
#define CMD_GET_STATUS 3
|
||||||
|
|
||||||
|
#define CMD_I2C_IO 4
|
||||||
|
#define CMD_I2C_IO_BEGIN (1<<0)
|
||||||
|
#define CMD_I2C_IO_END (1<<1)
|
||||||
|
|
||||||
|
/* i2c bit delay, default is 10us -> 100kHz */
|
||||||
|
static int delay = 10;
|
||||||
|
module_param(delay, int, 0);
|
||||||
|
MODULE_PARM_DESC(delay, "bit delay in microseconds, "
|
||||||
|
"e.g. 10 for 100kHz (default is 100kHz)");
|
||||||
|
|
||||||
|
static int usb_read(struct i2c_adapter *adapter, int cmd,
|
||||||
|
int value, int index, void *data, int len);
|
||||||
|
|
||||||
|
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
||||||
|
int value, int index, void *data, int len);
|
||||||
|
|
||||||
|
/* ----- begin of i2c layer ---------------------------------------------- */
|
||||||
|
|
||||||
|
#define STATUS_IDLE 0
|
||||||
|
#define STATUS_ADDRESS_ACK 1
|
||||||
|
#define STATUS_ADDRESS_NAK 2
|
||||||
|
|
||||||
|
static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num)
|
||||||
|
{
|
||||||
|
unsigned char status;
|
||||||
|
struct i2c_msg *pmsg;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
dev_dbg(&adapter->dev, "master xfer %d messages:\n", num);
|
||||||
|
|
||||||
|
for (i = 0 ; i < num ; i++) {
|
||||||
|
int cmd = CMD_I2C_IO;
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
cmd |= CMD_I2C_IO_BEGIN;
|
||||||
|
|
||||||
|
if (i == num-1)
|
||||||
|
cmd |= CMD_I2C_IO_END;
|
||||||
|
|
||||||
|
pmsg = &msgs[i];
|
||||||
|
|
||||||
|
dev_dbg(&adapter->dev,
|
||||||
|
" %d: %s (flags %d) %d bytes to 0x%02x\n",
|
||||||
|
i, pmsg->flags & I2C_M_RD ? "read" : "write",
|
||||||
|
pmsg->flags, pmsg->len, pmsg->addr);
|
||||||
|
|
||||||
|
/* and directly send the message */
|
||||||
|
if (pmsg->flags & I2C_M_RD) {
|
||||||
|
/* read data */
|
||||||
|
if (usb_read(adapter, cmd,
|
||||||
|
pmsg->flags, pmsg->addr,
|
||||||
|
pmsg->buf, pmsg->len) != pmsg->len) {
|
||||||
|
dev_err(&adapter->dev,
|
||||||
|
"failure reading data\n");
|
||||||
|
return -EREMOTEIO;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* write data */
|
||||||
|
if (usb_write(adapter, cmd,
|
||||||
|
pmsg->flags, pmsg->addr,
|
||||||
|
pmsg->buf, pmsg->len) != pmsg->len) {
|
||||||
|
dev_err(&adapter->dev,
|
||||||
|
"failure writing data\n");
|
||||||
|
return -EREMOTEIO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* read status */
|
||||||
|
if (usb_read(adapter, CMD_GET_STATUS, 0, 0, &status, 1) != 1) {
|
||||||
|
dev_err(&adapter->dev, "failure reading status\n");
|
||||||
|
return -EREMOTEIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(&adapter->dev, " status = %d\n", status);
|
||||||
|
if (status == STATUS_ADDRESS_NAK)
|
||||||
|
return -EREMOTEIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 usb_func(struct i2c_adapter *adapter)
|
||||||
|
{
|
||||||
|
u32 func;
|
||||||
|
|
||||||
|
/* get functionality from adapter */
|
||||||
|
if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) !=
|
||||||
|
sizeof(func)) {
|
||||||
|
dev_err(&adapter->dev, "failure reading functionality\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This is the actual algorithm we define */
|
||||||
|
static const struct i2c_algorithm usb_algorithm = {
|
||||||
|
.master_xfer = usb_xfer,
|
||||||
|
.functionality = usb_func,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ----- end of i2c layer ------------------------------------------------ */
|
||||||
|
|
||||||
|
/* ----- begin of usb layer ---------------------------------------------- */
|
||||||
|
|
||||||
|
/* The usb i2c interface uses a vid/pid pair donated by */
|
||||||
|
/* Future Technology Devices International Ltd. */
|
||||||
|
static struct usb_device_id i2c_tiny_usb_table [] = {
|
||||||
|
{ USB_DEVICE(0x0403, 0xc631) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(usb, i2c_tiny_usb_table);
|
||||||
|
|
||||||
|
/* Structure to hold all of our device specific stuff */
|
||||||
|
struct i2c_tiny_usb {
|
||||||
|
struct usb_device *usb_dev; /* the usb device for this device */
|
||||||
|
struct usb_interface *interface; /* the interface for this device */
|
||||||
|
struct i2c_adapter adapter; /* i2c related things */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int usb_read(struct i2c_adapter *adapter, int cmd,
|
||||||
|
int value, int index, void *data, int len)
|
||||||
|
{
|
||||||
|
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
||||||
|
|
||||||
|
/* do control transfer */
|
||||||
|
return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0),
|
||||||
|
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE |
|
||||||
|
USB_DIR_IN, value, index, data, len, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int usb_write(struct i2c_adapter *adapter, int cmd,
|
||||||
|
int value, int index, void *data, int len)
|
||||||
|
{
|
||||||
|
struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data;
|
||||||
|
|
||||||
|
/* do control transfer */
|
||||||
|
return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0),
|
||||||
|
cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
|
||||||
|
value, index, data, len, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev)
|
||||||
|
{
|
||||||
|
usb_put_dev(dev->usb_dev);
|
||||||
|
kfree(dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int i2c_tiny_usb_probe(struct usb_interface *interface,
|
||||||
|
const struct usb_device_id *id)
|
||||||
|
{
|
||||||
|
struct i2c_tiny_usb *dev;
|
||||||
|
int retval = -ENOMEM;
|
||||||
|
u16 version;
|
||||||
|
|
||||||
|
dev_dbg(&interface->dev, "probing usb device\n");
|
||||||
|
|
||||||
|
/* allocate memory for our device state and initialize it */
|
||||||
|
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||||
|
if (dev == NULL) {
|
||||||
|
dev_err(&interface->dev, "Out of memory\n");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
|
||||||
|
dev->interface = interface;
|
||||||
|
|
||||||
|
/* save our data pointer in this interface device */
|
||||||
|
usb_set_intfdata(interface, dev);
|
||||||
|
|
||||||
|
version = le16_to_cpu(dev->usb_dev->descriptor.bcdDevice);
|
||||||
|
dev_info(&interface->dev,
|
||||||
|
"version %x.%02x found at bus %03d address %03d\n",
|
||||||
|
version >> 8, version & 0xff,
|
||||||
|
dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
|
||||||
|
|
||||||
|
/* setup i2c adapter description */
|
||||||
|
dev->adapter.owner = THIS_MODULE;
|
||||||
|
dev->adapter.class = I2C_CLASS_HWMON;
|
||||||
|
dev->adapter.algo = &usb_algorithm;
|
||||||
|
dev->adapter.algo_data = dev;
|
||||||
|
snprintf(dev->adapter.name, I2C_NAME_SIZE,
|
||||||
|
"i2c-tiny-usb at bus %03d device %03d",
|
||||||
|
dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
|
||||||
|
|
||||||
|
if (usb_write(&dev->adapter, CMD_SET_DELAY,
|
||||||
|
cpu_to_le16(delay), 0, NULL, 0) != 0) {
|
||||||
|
dev_err(&dev->adapter.dev,
|
||||||
|
"failure setting delay to %dus\n", delay);
|
||||||
|
retval = -EIO;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev->adapter.dev.parent = &dev->interface->dev;
|
||||||
|
|
||||||
|
/* and finally attach to i2c layer */
|
||||||
|
i2c_add_adapter(&dev->adapter);
|
||||||
|
|
||||||
|
/* inform user about successful attachment to i2c layer */
|
||||||
|
dev_info(&dev->adapter.dev, "connected i2c-tiny-usb device\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if (dev)
|
||||||
|
i2c_tiny_usb_free(dev);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void i2c_tiny_usb_disconnect(struct usb_interface *interface)
|
||||||
|
{
|
||||||
|
struct i2c_tiny_usb *dev = usb_get_intfdata(interface);
|
||||||
|
|
||||||
|
i2c_del_adapter(&dev->adapter);
|
||||||
|
usb_set_intfdata(interface, NULL);
|
||||||
|
i2c_tiny_usb_free(dev);
|
||||||
|
|
||||||
|
dev_dbg(&interface->dev, "disconnected\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct usb_driver i2c_tiny_usb_driver = {
|
||||||
|
.name = "i2c-tiny-usb",
|
||||||
|
.probe = i2c_tiny_usb_probe,
|
||||||
|
.disconnect = i2c_tiny_usb_disconnect,
|
||||||
|
.id_table = i2c_tiny_usb_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init usb_i2c_tiny_usb_init(void)
|
||||||
|
{
|
||||||
|
/* register this driver with the USB subsystem */
|
||||||
|
return usb_register(&i2c_tiny_usb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit usb_i2c_tiny_usb_exit(void)
|
||||||
|
{
|
||||||
|
/* deregister this driver with the USB subsystem */
|
||||||
|
usb_deregister(&i2c_tiny_usb_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(usb_i2c_tiny_usb_init);
|
||||||
|
module_exit(usb_i2c_tiny_usb_exit);
|
||||||
|
|
||||||
|
/* ----- end of usb layer ------------------------------------------------ */
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Till Harbaum <Till@Harbaum.org>");
|
||||||
|
MODULE_DESCRIPTION("i2c-tiny-usb driver v1.0");
|
||||||
|
MODULE_LICENSE("GPL");
|
@ -404,7 +404,7 @@ found:
|
|||||||
}
|
}
|
||||||
|
|
||||||
vt596_adapter.dev.parent = &pdev->dev;
|
vt596_adapter.dev.parent = &pdev->dev;
|
||||||
snprintf(vt596_adapter.name, I2C_NAME_SIZE,
|
snprintf(vt596_adapter.name, sizeof(vt596_adapter.name),
|
||||||
"SMBus Via Pro adapter at %04x", vt596_smba);
|
"SMBus Via Pro adapter at %04x", vt596_smba);
|
||||||
|
|
||||||
vt596_pdev = pci_dev_get(pdev);
|
vt596_pdev = pci_dev_get(pdev);
|
||||||
|
@ -441,7 +441,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
|
|||||||
|
|
||||||
adapter = &iface->adapter;
|
adapter = &iface->adapter;
|
||||||
i2c_set_adapdata(adapter, iface);
|
i2c_set_adapdata(adapter, iface);
|
||||||
snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index);
|
snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
|
||||||
adapter->owner = THIS_MODULE;
|
adapter->owner = THIS_MODULE;
|
||||||
adapter->id = I2C_HW_SMBUS_SCX200;
|
adapter->id = I2C_HW_SMBUS_SCX200;
|
||||||
adapter->algo = &scx200_acb_algorithm;
|
adapter->algo = &scx200_acb_algorithm;
|
||||||
@ -599,6 +599,7 @@ static __init int scx200_scan_pci(void)
|
|||||||
else {
|
else {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
pci_dev_put(pdev);
|
||||||
for (i = 0; i < MAX_DEVICES; ++i) {
|
for (i = 0; i < MAX_DEVICES; ++i) {
|
||||||
if (base[i] == 0)
|
if (base[i] == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -3,11 +3,10 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
menu "Miscellaneous I2C Chip support"
|
menu "Miscellaneous I2C Chip support"
|
||||||
depends on I2C
|
|
||||||
|
|
||||||
config SENSORS_DS1337
|
config SENSORS_DS1337
|
||||||
tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
|
tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
|
||||||
depends on I2C && EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes here you get support for Dallas Semiconductor
|
If you say yes here you get support for Dallas Semiconductor
|
||||||
DS1337 and DS1339 real-time clock chips.
|
DS1337 and DS1339 real-time clock chips.
|
||||||
@ -17,7 +16,7 @@ config SENSORS_DS1337
|
|||||||
|
|
||||||
config SENSORS_DS1374
|
config SENSORS_DS1374
|
||||||
tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
|
tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
|
||||||
depends on I2C && EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes here you get support for Dallas Semiconductor
|
If you say yes here you get support for Dallas Semiconductor
|
||||||
DS1374 real-time clock chips.
|
DS1374 real-time clock chips.
|
||||||
@ -27,7 +26,7 @@ config SENSORS_DS1374
|
|||||||
|
|
||||||
config SENSORS_EEPROM
|
config SENSORS_EEPROM
|
||||||
tristate "EEPROM reader"
|
tristate "EEPROM reader"
|
||||||
depends on I2C && EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes here you get read-only access to the EEPROM data
|
If you say yes here you get read-only access to the EEPROM data
|
||||||
available on modern memory DIMMs and Sony Vaio laptops. Such
|
available on modern memory DIMMs and Sony Vaio laptops. Such
|
||||||
@ -38,7 +37,7 @@ config SENSORS_EEPROM
|
|||||||
|
|
||||||
config SENSORS_PCF8574
|
config SENSORS_PCF8574
|
||||||
tristate "Philips PCF8574 and PCF8574A"
|
tristate "Philips PCF8574 and PCF8574A"
|
||||||
depends on I2C && EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
If you say yes here you get support for Philips PCF8574 and
|
If you say yes here you get support for Philips PCF8574 and
|
||||||
@ -52,7 +51,7 @@ config SENSORS_PCF8574
|
|||||||
|
|
||||||
config SENSORS_PCA9539
|
config SENSORS_PCA9539
|
||||||
tristate "Philips PCA9539 16-bit I/O port"
|
tristate "Philips PCA9539 16-bit I/O port"
|
||||||
depends on I2C && EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes here you get support for the Philips PCA9539
|
If you say yes here you get support for the Philips PCA9539
|
||||||
16-bit I/O port.
|
16-bit I/O port.
|
||||||
@ -62,7 +61,7 @@ config SENSORS_PCA9539
|
|||||||
|
|
||||||
config SENSORS_PCF8591
|
config SENSORS_PCF8591
|
||||||
tristate "Philips PCF8591"
|
tristate "Philips PCF8591"
|
||||||
depends on I2C && EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
If you say yes here you get support for Philips PCF8591 chips.
|
If you say yes here you get support for Philips PCF8591 chips.
|
||||||
@ -75,7 +74,7 @@ config SENSORS_PCF8591
|
|||||||
|
|
||||||
config ISP1301_OMAP
|
config ISP1301_OMAP
|
||||||
tristate "Philips ISP1301 with OMAP OTG"
|
tristate "Philips ISP1301 with OMAP OTG"
|
||||||
depends on I2C && ARCH_OMAP_OTG
|
depends on ARCH_OMAP_OTG
|
||||||
help
|
help
|
||||||
If you say yes here you get support for the Philips ISP1301
|
If you say yes here you get support for the Philips ISP1301
|
||||||
USB-On-The-Go transceiver working with the OMAP OTG controller.
|
USB-On-The-Go transceiver working with the OMAP OTG controller.
|
||||||
@ -90,7 +89,7 @@ config ISP1301_OMAP
|
|||||||
# and having mostly OMAP-specific board support
|
# and having mostly OMAP-specific board support
|
||||||
config TPS65010
|
config TPS65010
|
||||||
tristate "TPS6501x Power Management chips"
|
tristate "TPS6501x Power Management chips"
|
||||||
depends on I2C && ARCH_OMAP
|
depends on ARCH_OMAP
|
||||||
default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
|
default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
|
||||||
help
|
help
|
||||||
If you say yes here you get support for the TPS6501x series of
|
If you say yes here you get support for the TPS6501x series of
|
||||||
@ -103,7 +102,7 @@ config TPS65010
|
|||||||
|
|
||||||
config SENSORS_M41T00
|
config SENSORS_M41T00
|
||||||
tristate "ST M41T00 RTC chip"
|
tristate "ST M41T00 RTC chip"
|
||||||
depends on I2C && PPC32
|
depends on PPC32
|
||||||
help
|
help
|
||||||
If you say yes here you get support for the ST M41T00 RTC chip.
|
If you say yes here you get support for the ST M41T00 RTC chip.
|
||||||
|
|
||||||
@ -112,7 +111,7 @@ config SENSORS_M41T00
|
|||||||
|
|
||||||
config SENSORS_MAX6875
|
config SENSORS_MAX6875
|
||||||
tristate "Maxim MAX6875 Power supply supervisor"
|
tristate "Maxim MAX6875 Power supply supervisor"
|
||||||
depends on I2C && EXPERIMENTAL
|
depends on EXPERIMENTAL
|
||||||
help
|
help
|
||||||
If you say yes here you get support for the Maxim MAX6875
|
If you say yes here you get support for the Maxim MAX6875
|
||||||
EEPROM-programmable, quad power-supply sequencer/supervisor.
|
EEPROM-programmable, quad power-supply sequencer/supervisor.
|
||||||
|
90
drivers/i2c/i2c-boardinfo.c
Normal file
90
drivers/i2c/i2c-boardinfo.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* i2c-boardinfo.h - collect pre-declarations of I2C devices
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
|
||||||
|
#include "i2c-core.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* These symbols are exported ONLY FOR the i2c core.
|
||||||
|
* No other users will be supported.
|
||||||
|
*/
|
||||||
|
DEFINE_MUTEX(__i2c_board_lock);
|
||||||
|
EXPORT_SYMBOL_GPL(__i2c_board_lock);
|
||||||
|
|
||||||
|
LIST_HEAD(__i2c_board_list);
|
||||||
|
EXPORT_SYMBOL_GPL(__i2c_board_list);
|
||||||
|
|
||||||
|
int __i2c_first_dynamic_bus_num;
|
||||||
|
EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* i2c_register_board_info - statically declare I2C devices
|
||||||
|
* @busnum: identifies the bus to which these devices belong
|
||||||
|
* @info: vector of i2c device descriptors
|
||||||
|
* @len: how many descriptors in the vector; may be zero to reserve
|
||||||
|
* the specified bus number.
|
||||||
|
*
|
||||||
|
* Systems using the Linux I2C driver stack can declare tables of board info
|
||||||
|
* while they initialize. This should be done in board-specific init code
|
||||||
|
* near arch_initcall() time, or equivalent, before any I2C adapter driver is
|
||||||
|
* registered. For example, mainboard init code could define several devices,
|
||||||
|
* as could the init code for each daughtercard in a board stack.
|
||||||
|
*
|
||||||
|
* The I2C devices will be created later, after the adapter for the relevant
|
||||||
|
* bus has been registered. After that moment, standard driver model tools
|
||||||
|
* are used to bind "new style" I2C drivers to the devices. The bus number
|
||||||
|
* for any device declared using this routine is not available for dynamic
|
||||||
|
* allocation.
|
||||||
|
*
|
||||||
|
* The board info passed can safely be __initdata, but be careful of embedded
|
||||||
|
* pointers (for platform_data, functions, etc) since that won't be copied.
|
||||||
|
*/
|
||||||
|
int __init
|
||||||
|
i2c_register_board_info(int busnum,
|
||||||
|
struct i2c_board_info const *info, unsigned len)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
|
||||||
|
mutex_lock(&__i2c_board_lock);
|
||||||
|
|
||||||
|
/* dynamic bus numbers will be assigned after the last static one */
|
||||||
|
if (busnum >= __i2c_first_dynamic_bus_num)
|
||||||
|
__i2c_first_dynamic_bus_num = busnum + 1;
|
||||||
|
|
||||||
|
for (status = 0; len; len--, info++) {
|
||||||
|
struct i2c_devinfo *devinfo;
|
||||||
|
|
||||||
|
devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL);
|
||||||
|
if (!devinfo) {
|
||||||
|
pr_debug("i2c-core: can't register boardinfo!\n");
|
||||||
|
status = -ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
devinfo->busnum = busnum;
|
||||||
|
devinfo->board_info = *info;
|
||||||
|
list_add_tail(&devinfo->list, &__i2c_board_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&__i2c_board_lock);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
31
drivers/i2c/i2c-core.h
Normal file
31
drivers/i2c/i2c-core.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* i2c-core.h - interfaces internal to the I2C framework
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct i2c_devinfo {
|
||||||
|
struct list_head list;
|
||||||
|
int busnum;
|
||||||
|
struct i2c_board_info board_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* board_lock protects board_list and first_dynamic_bus_num.
|
||||||
|
* only i2c core components are allowed to use these symbols.
|
||||||
|
*/
|
||||||
|
extern struct mutex __i2c_board_lock;
|
||||||
|
extern struct list_head __i2c_board_list;
|
||||||
|
extern int __i2c_first_dynamic_bus_num;
|
||||||
|
|
@ -459,7 +459,8 @@ therm_of_probe( struct of_device *dev, const struct of_device_id *match )
|
|||||||
static int
|
static int
|
||||||
therm_of_remove( struct of_device *dev )
|
therm_of_remove( struct of_device *dev )
|
||||||
{
|
{
|
||||||
return i2c_del_driver( &g4fan_driver );
|
i2c_del_driver( &g4fan_driver );
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct of_device_id therm_of_match[] = {{
|
static struct of_device_id therm_of_match[] = {{
|
||||||
|
@ -183,7 +183,8 @@ int flexcop_i2c_init(struct flexcop_device *fc)
|
|||||||
mutex_init(&fc->i2c_mutex);
|
mutex_init(&fc->i2c_mutex);
|
||||||
|
|
||||||
memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
|
memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
|
||||||
strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE);
|
strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",
|
||||||
|
sizeof(fc->i2c_adap.name));
|
||||||
|
|
||||||
i2c_set_adapdata(&fc->i2c_adap,fc);
|
i2c_set_adapdata(&fc->i2c_adap,fc);
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE);
|
strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
|
||||||
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
|
#ifdef I2C_ADAP_CLASS_TV_DIGITAL
|
||||||
d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
|
d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
|
||||||
#else
|
#else
|
||||||
|
@ -105,9 +105,9 @@ struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enu
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dibx000_get_i2c_adapter);
|
EXPORT_SYMBOL(dibx000_get_i2c_adapter);
|
||||||
|
|
||||||
static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst)
|
static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char *name, struct dibx000_i2c_master *mst)
|
||||||
{
|
{
|
||||||
strncpy(i2c_adap->name, name, I2C_NAME_SIZE);
|
strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
|
||||||
i2c_adap->class = I2C_CLASS_TV_DIGITAL,
|
i2c_adap->class = I2C_CLASS_TV_DIGITAL,
|
||||||
i2c_adap->algo = algo;
|
i2c_adap->algo = algo;
|
||||||
i2c_adap->algo_data = NULL;
|
i2c_adap->algo_data = NULL;
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
#include <linux/i2c.h>
|
|
||||||
|
|
||||||
#include <media/tuner.h>
|
#include <media/tuner.h>
|
||||||
#include <media/cx2341x.h>
|
#include <media/cx2341x.h>
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#ifndef __LINUX_OVCAMCHIP_PRIV_H
|
#ifndef __LINUX_OVCAMCHIP_PRIV_H
|
||||||
#define __LINUX_OVCAMCHIP_PRIV_H
|
#define __LINUX_OVCAMCHIP_PRIV_H
|
||||||
|
|
||||||
|
#include <linux/i2c.h>
|
||||||
#include <media/ovcamchip.h>
|
#include <media/ovcamchip.h>
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/i2c.h>
|
|
||||||
#include <media/v4l2-dev.h>
|
#include <media/v4l2-dev.h>
|
||||||
#include <media/tuner.h>
|
#include <media/tuner.h>
|
||||||
#include "usbvision.h"
|
#include "usbvision.h"
|
||||||
|
@ -104,7 +104,8 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
|
|||||||
|
|
||||||
chan->dinfo = dinfo;
|
chan->dinfo = dinfo;
|
||||||
chan->reg = reg;
|
chan->reg = reg;
|
||||||
snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name);
|
snprintf(chan->adapter.name, sizeof(chan->adapter.name),
|
||||||
|
"intelfb %s", name);
|
||||||
chan->adapter.owner = THIS_MODULE;
|
chan->adapter.owner = THIS_MODULE;
|
||||||
chan->adapter.id = I2C_HW_B_INTELFB;
|
chan->adapter.id = I2C_HW_B_INTELFB;
|
||||||
chan->adapter.algo_data = &chan->algo;
|
chan->adapter.algo_data = &chan->algo;
|
||||||
|
@ -111,7 +111,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
|
|||||||
b->mask.data = data;
|
b->mask.data = data;
|
||||||
b->mask.clock = clock;
|
b->mask.clock = clock;
|
||||||
b->adapter = matrox_i2c_adapter_template;
|
b->adapter = matrox_i2c_adapter_template;
|
||||||
snprintf(b->adapter.name, I2C_NAME_SIZE, name,
|
snprintf(b->adapter.name, sizeof(b->adapter.name), name,
|
||||||
minfo->fbcon.node);
|
minfo->fbcon.node);
|
||||||
i2c_set_adapdata(&b->adapter, b);
|
i2c_set_adapdata(&b->adapter, b);
|
||||||
b->adapter.algo_data = &b->bac;
|
b->adapter.algo_data = &b->bac;
|
||||||
|
@ -38,11 +38,14 @@ struct i2c_algo_bit_data {
|
|||||||
int (*getscl) (void *data);
|
int (*getscl) (void *data);
|
||||||
|
|
||||||
/* local settings */
|
/* local settings */
|
||||||
int udelay; /* half-clock-cycle time in microsecs */
|
int udelay; /* half clock cycle time in us,
|
||||||
/* i.e. clock is (500 / udelay) KHz */
|
minimum 2 us for fast-mode I2C,
|
||||||
|
minimum 5 us for standard-mode I2C and SMBus,
|
||||||
|
maximum 50 us for SMBus */
|
||||||
int timeout; /* in jiffies */
|
int timeout; /* in jiffies */
|
||||||
};
|
};
|
||||||
|
|
||||||
int i2c_bit_add_bus(struct i2c_adapter *);
|
int i2c_bit_add_bus(struct i2c_adapter *);
|
||||||
|
int i2c_bit_add_numbered_bus(struct i2c_adapter *);
|
||||||
|
|
||||||
#endif /* _LINUX_I2C_ALGO_BIT_H */
|
#endif /* _LINUX_I2C_ALGO_BIT_H */
|
||||||
|
38
include/linux/i2c-gpio.h
Normal file
38
include/linux/i2c-gpio.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* i2c-gpio interface to platform code
|
||||||
|
*
|
||||||
|
* Copyright (C) 2007 Atmel Corporation
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#ifndef _LINUX_I2C_GPIO_H
|
||||||
|
#define _LINUX_I2C_GPIO_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct i2c_gpio_platform_data - Platform-dependent data for i2c-gpio
|
||||||
|
* @sda_pin: GPIO pin ID to use for SDA
|
||||||
|
* @scl_pin: GPIO pin ID to use for SCL
|
||||||
|
* @udelay: signal toggle delay. SCL frequency is (500 / udelay) kHz
|
||||||
|
* @timeout: clock stretching timeout in jiffies. If the slave keeps
|
||||||
|
* SCL low for longer than this, the transfer will time out.
|
||||||
|
* @sda_is_open_drain: SDA is configured as open drain, i.e. the pin
|
||||||
|
* isn't actively driven high when setting the output value high.
|
||||||
|
* gpio_get_value() must return the actual pin state even if the
|
||||||
|
* pin is configured as an output.
|
||||||
|
* @scl_is_open_drain: SCL is set up as open drain. Same requirements
|
||||||
|
* as for sda_is_open_drain apply.
|
||||||
|
* @scl_is_output_only: SCL output drivers cannot be turned off.
|
||||||
|
*/
|
||||||
|
struct i2c_gpio_platform_data {
|
||||||
|
unsigned int sda_pin;
|
||||||
|
unsigned int scl_pin;
|
||||||
|
int udelay;
|
||||||
|
int timeout;
|
||||||
|
unsigned int sda_is_open_drain:1;
|
||||||
|
unsigned int scl_is_open_drain:1;
|
||||||
|
unsigned int scl_is_output_only:1;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _LINUX_I2C_GPIO_H */
|
@ -258,8 +258,9 @@
|
|||||||
/* --- MCP107 adapter */
|
/* --- MCP107 adapter */
|
||||||
#define I2C_HW_MPC107 0x0d0000
|
#define I2C_HW_MPC107 0x0d0000
|
||||||
|
|
||||||
/* --- Marvell mv64xxx i2c adapter */
|
/* --- Embedded adapters */
|
||||||
#define I2C_HW_MV64XXX 0x190000
|
#define I2C_HW_MV64XXX 0x190000
|
||||||
|
#define I2C_HW_BLACKFIN 0x190001 /* ADI Blackfin I2C TWI driver */
|
||||||
|
|
||||||
/* --- Miscellaneous adapters */
|
/* --- Miscellaneous adapters */
|
||||||
#define I2C_HW_SAA7146 0x060000 /* SAA7146 video decoder bus */
|
#define I2C_HW_SAA7146 0x060000 /* SAA7146 video decoder bus */
|
||||||
|
@ -35,11 +35,6 @@
|
|||||||
#include <linux/sched.h> /* for completion */
|
#include <linux/sched.h> /* for completion */
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
/* --- For i2c-isa ---------------------------------------------------- */
|
|
||||||
|
|
||||||
extern void i2c_adapter_dev_release(struct device *dev);
|
|
||||||
extern struct device_driver i2c_adapter_driver;
|
|
||||||
extern struct class i2c_adapter_class;
|
|
||||||
extern struct bus_type i2c_bus_type;
|
extern struct bus_type i2c_bus_type;
|
||||||
|
|
||||||
/* --- General options ------------------------------------------------ */
|
/* --- General options ------------------------------------------------ */
|
||||||
@ -87,6 +82,9 @@ extern s32 i2c_smbus_write_byte_data(struct i2c_client * client,
|
|||||||
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
|
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
|
||||||
extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
|
extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
|
||||||
u8 command, u16 value);
|
u8 command, u16 value);
|
||||||
|
/* Returns the number of read bytes */
|
||||||
|
extern s32 i2c_smbus_read_block_data(struct i2c_client *client,
|
||||||
|
u8 command, u8 *values);
|
||||||
extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
|
extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
|
||||||
u8 command, u8 length,
|
u8 command, u8 length,
|
||||||
const u8 *values);
|
const u8 *values);
|
||||||
@ -114,7 +112,7 @@ struct i2c_driver {
|
|||||||
* can be used by the driver to test if the bus meets its conditions
|
* can be used by the driver to test if the bus meets its conditions
|
||||||
* & seek for the presence of the chip(s) it supports. If found, it
|
* & seek for the presence of the chip(s) it supports. If found, it
|
||||||
* registers the client(s) that are on the bus to the i2c admin. via
|
* registers the client(s) that are on the bus to the i2c admin. via
|
||||||
* i2c_attach_client.
|
* i2c_attach_client. (LEGACY I2C DRIVERS ONLY)
|
||||||
*/
|
*/
|
||||||
int (*attach_adapter)(struct i2c_adapter *);
|
int (*attach_adapter)(struct i2c_adapter *);
|
||||||
int (*detach_adapter)(struct i2c_adapter *);
|
int (*detach_adapter)(struct i2c_adapter *);
|
||||||
@ -122,10 +120,17 @@ struct i2c_driver {
|
|||||||
/* tells the driver that a client is about to be deleted & gives it
|
/* tells the driver that a client is about to be deleted & gives it
|
||||||
* the chance to remove its private data. Also, if the client struct
|
* the chance to remove its private data. Also, if the client struct
|
||||||
* has been dynamically allocated by the driver in the function above,
|
* has been dynamically allocated by the driver in the function above,
|
||||||
* it must be freed here.
|
* it must be freed here. (LEGACY I2C DRIVERS ONLY)
|
||||||
*/
|
*/
|
||||||
int (*detach_client)(struct i2c_client *);
|
int (*detach_client)(struct i2c_client *);
|
||||||
|
|
||||||
|
/* Standard driver model interfaces, for "new style" i2c drivers.
|
||||||
|
* With the driver model, device enumeration is NEVER done by drivers;
|
||||||
|
* it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
|
||||||
|
*/
|
||||||
|
int (*probe)(struct i2c_client *);
|
||||||
|
int (*remove)(struct i2c_client *);
|
||||||
|
|
||||||
/* driver model interfaces that don't relate to enumeration */
|
/* driver model interfaces that don't relate to enumeration */
|
||||||
void (*shutdown)(struct i2c_client *);
|
void (*shutdown)(struct i2c_client *);
|
||||||
int (*suspend)(struct i2c_client *, pm_message_t mesg);
|
int (*suspend)(struct i2c_client *, pm_message_t mesg);
|
||||||
@ -141,25 +146,34 @@ struct i2c_driver {
|
|||||||
};
|
};
|
||||||
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
|
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
|
||||||
|
|
||||||
#define I2C_NAME_SIZE 50
|
#define I2C_NAME_SIZE 20
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* i2c_client identifies a single device (i.e. chip) that is connected to an
|
* struct i2c_client - represent an I2C slave device
|
||||||
* i2c bus. The behaviour is defined by the routines of the driver. This
|
* @addr: Address used on the I2C bus connected to the parent adapter.
|
||||||
* function is mainly used for lookup & other admin. functions.
|
* @name: Indicates the type of the device, usually a chip name that's
|
||||||
|
* generic enough to hide second-sourcing and compatible revisions.
|
||||||
|
* @dev: Driver model device node for the slave.
|
||||||
|
* @driver_name: Identifies new-style driver used with this device; also
|
||||||
|
* used as the module name for hotplug/coldplug modprobe support.
|
||||||
|
*
|
||||||
|
* An i2c_client identifies a single device (i.e. chip) connected to an
|
||||||
|
* i2c bus. The behaviour is defined by the routines of the driver.
|
||||||
*/
|
*/
|
||||||
struct i2c_client {
|
struct i2c_client {
|
||||||
unsigned int flags; /* div., see below */
|
unsigned short flags; /* div., see below */
|
||||||
unsigned short addr; /* chip address - NOTE: 7bit */
|
unsigned short addr; /* chip address - NOTE: 7bit */
|
||||||
/* addresses are stored in the */
|
/* addresses are stored in the */
|
||||||
/* _LOWER_ 7 bits */
|
/* _LOWER_ 7 bits */
|
||||||
|
char name[I2C_NAME_SIZE];
|
||||||
struct i2c_adapter *adapter; /* the adapter we sit on */
|
struct i2c_adapter *adapter; /* the adapter we sit on */
|
||||||
struct i2c_driver *driver; /* and our access routines */
|
struct i2c_driver *driver; /* and our access routines */
|
||||||
int usage_count; /* How many accesses currently */
|
int usage_count; /* How many accesses currently */
|
||||||
/* to the client */
|
/* to the client */
|
||||||
struct device dev; /* the device structure */
|
struct device dev; /* the device structure */
|
||||||
|
int irq; /* irq issued by device (or -1) */
|
||||||
|
char driver_name[KOBJ_NAME_LEN];
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
char name[I2C_NAME_SIZE];
|
|
||||||
struct completion released;
|
struct completion released;
|
||||||
};
|
};
|
||||||
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
|
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
|
||||||
@ -179,6 +193,76 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
|
|||||||
dev_set_drvdata (&dev->dev, data);
|
dev_set_drvdata (&dev->dev, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct i2c_board_info - template for device creation
|
||||||
|
* @driver_name: identifies the driver to be bound to the device
|
||||||
|
* @type: optional chip type information, to initialize i2c_client.name
|
||||||
|
* @flags: to initialize i2c_client.flags
|
||||||
|
* @addr: stored in i2c_client.addr
|
||||||
|
* @platform_data: stored in i2c_client.dev.platform_data
|
||||||
|
* @irq: stored in i2c_client.irq
|
||||||
|
|
||||||
|
* I2C doesn't actually support hardware probing, although controllers and
|
||||||
|
* devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
|
||||||
|
* a device at a given address. Drivers commonly need more information than
|
||||||
|
* that, such as chip type, configuration, associated IRQ, and so on.
|
||||||
|
*
|
||||||
|
* i2c_board_info is used to build tables of information listing I2C devices
|
||||||
|
* that are present. This information is used to grow the driver model tree
|
||||||
|
* for "new style" I2C drivers. For mainboards this is done statically using
|
||||||
|
* i2c_register_board_info(), where @bus_num represents an adapter that isn't
|
||||||
|
* yet available. For add-on boards, i2c_new_device() does this dynamically
|
||||||
|
* with the adapter already known.
|
||||||
|
*/
|
||||||
|
struct i2c_board_info {
|
||||||
|
char driver_name[KOBJ_NAME_LEN];
|
||||||
|
char type[I2C_NAME_SIZE];
|
||||||
|
unsigned short flags;
|
||||||
|
unsigned short addr;
|
||||||
|
void *platform_data;
|
||||||
|
int irq;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* I2C_BOARD_INFO - macro used to list an i2c device and its driver
|
||||||
|
* @driver: identifies the driver to use with the device
|
||||||
|
* @dev_addr: the device's address on the bus.
|
||||||
|
*
|
||||||
|
* This macro initializes essential fields of a struct i2c_board_info,
|
||||||
|
* declaring what has been provided on a particular board. Optional
|
||||||
|
* fields (such as the chip type, its associated irq, or device-specific
|
||||||
|
* platform_data) are provided using conventional syntax.
|
||||||
|
*/
|
||||||
|
#define I2C_BOARD_INFO(driver,dev_addr) \
|
||||||
|
.driver_name = (driver), .addr = (dev_addr)
|
||||||
|
|
||||||
|
|
||||||
|
/* Add-on boards should register/unregister their devices; e.g. a board
|
||||||
|
* with integrated I2C, a config eeprom, sensors, and a codec that's
|
||||||
|
* used in conjunction with the primary hardware.
|
||||||
|
*/
|
||||||
|
extern struct i2c_client *
|
||||||
|
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
|
||||||
|
|
||||||
|
/* If you don't know the exact address of an I2C device, use this variant
|
||||||
|
* instead, which can probe for device presence in a list of possible
|
||||||
|
* addresses.
|
||||||
|
*/
|
||||||
|
extern struct i2c_client *
|
||||||
|
i2c_new_probed_device(struct i2c_adapter *adap,
|
||||||
|
struct i2c_board_info *info,
|
||||||
|
unsigned short const *addr_list);
|
||||||
|
|
||||||
|
extern void i2c_unregister_device(struct i2c_client *);
|
||||||
|
|
||||||
|
/* Mainboard arch_initcall() code should register all its I2C devices.
|
||||||
|
* This is done at arch_initcall time, before declaring any i2c adapters.
|
||||||
|
* Modules for add-on boards must use other calls.
|
||||||
|
*/
|
||||||
|
extern int
|
||||||
|
i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned n);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following structs are for those who like to implement new bus drivers:
|
* The following structs are for those who like to implement new bus drivers:
|
||||||
* i2c_algorithm is the interface to a class of hardware solutions which can
|
* i2c_algorithm is the interface to a class of hardware solutions which can
|
||||||
@ -228,17 +312,14 @@ struct i2c_adapter {
|
|||||||
int timeout;
|
int timeout;
|
||||||
int retries;
|
int retries;
|
||||||
struct device dev; /* the adapter device */
|
struct device dev; /* the adapter device */
|
||||||
struct class_device class_dev; /* the class device */
|
|
||||||
|
|
||||||
int nr;
|
int nr;
|
||||||
struct list_head clients;
|
struct list_head clients;
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
char name[I2C_NAME_SIZE];
|
char name[48];
|
||||||
struct completion dev_released;
|
struct completion dev_released;
|
||||||
struct completion class_dev_released;
|
|
||||||
};
|
};
|
||||||
#define dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
|
#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
|
||||||
#define class_dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, class_dev)
|
|
||||||
|
|
||||||
static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
|
static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
|
||||||
{
|
{
|
||||||
@ -290,9 +371,10 @@ struct i2c_client_address_data {
|
|||||||
*/
|
*/
|
||||||
extern int i2c_add_adapter(struct i2c_adapter *);
|
extern int i2c_add_adapter(struct i2c_adapter *);
|
||||||
extern int i2c_del_adapter(struct i2c_adapter *);
|
extern int i2c_del_adapter(struct i2c_adapter *);
|
||||||
|
extern int i2c_add_numbered_adapter(struct i2c_adapter *);
|
||||||
|
|
||||||
extern int i2c_register_driver(struct module *, struct i2c_driver *);
|
extern int i2c_register_driver(struct module *, struct i2c_driver *);
|
||||||
extern int i2c_del_driver(struct i2c_driver *);
|
extern void i2c_del_driver(struct i2c_driver *);
|
||||||
|
|
||||||
static inline int i2c_add_driver(struct i2c_driver *driver)
|
static inline int i2c_add_driver(struct i2c_driver *driver)
|
||||||
{
|
{
|
||||||
@ -365,6 +447,7 @@ struct i2c_msg {
|
|||||||
#define I2C_M_REV_DIR_ADDR 0x2000
|
#define I2C_M_REV_DIR_ADDR 0x2000
|
||||||
#define I2C_M_IGNORE_NAK 0x1000
|
#define I2C_M_IGNORE_NAK 0x1000
|
||||||
#define I2C_M_NO_RD_ACK 0x0800
|
#define I2C_M_NO_RD_ACK 0x0800
|
||||||
|
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
|
||||||
__u16 len; /* msg length */
|
__u16 len; /* msg length */
|
||||||
__u8 *buf; /* pointer to msg data */
|
__u8 *buf; /* pointer to msg data */
|
||||||
};
|
};
|
||||||
|
@ -1213,11 +1213,13 @@
|
|||||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5
|
#define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6
|
#define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7
|
||||||
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS 0x03EB
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE
|
#define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF
|
#define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7
|
||||||
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS 0x0446
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450
|
#define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450
|
||||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451
|
#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
#include <linux/videodev.h>
|
#include <linux/videodev.h>
|
||||||
#include <media/v4l2-common.h>
|
#include <media/v4l2-common.h>
|
||||||
#include <linux/i2c.h>
|
|
||||||
|
|
||||||
/* --------------------------------- */
|
/* --------------------------------- */
|
||||||
/* ENUMERATIONS */
|
/* ENUMERATIONS */
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define _TUNER_H
|
#define _TUNER_H
|
||||||
|
|
||||||
#include <linux/videodev2.h>
|
#include <linux/videodev2.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
#include <media/tuner-types.h>
|
#include <media/tuner-types.h>
|
||||||
|
|
||||||
extern int tuner_debug;
|
extern int tuner_debug;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#ifndef _TAS_IOCTL_H_
|
#ifndef _TAS_IOCTL_H_
|
||||||
#define _TAS_IOCTL_H_
|
#define _TAS_IOCTL_H_
|
||||||
|
|
||||||
#include <linux/i2c.h>
|
|
||||||
#include <linux/soundcard.h>
|
#include <linux/soundcard.h>
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user