mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 13:31:02 +07:00
Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6: (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
|
||||
i2c_adapter.list
|
||||
What: i2c_adapter.list
|
||||
When: July 2007
|
||||
Why: Superfluous, given i2c_adapter.class_dev:
|
||||
* The "dev" was a stand-in for the physical device node that legacy
|
||||
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.)
|
||||
Why: Superfluous, this list duplicates the one maintained by the driver
|
||||
core.
|
||||
Who: Jean Delvare <khali@linux-fr.org>,
|
||||
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 MCP51 10de:0264
|
||||
* nForce4 MCP55 10de:0368
|
||||
* nForce4 MCP61 10de:03EB
|
||||
* nForce4 MCP65 10de:0446
|
||||
|
||||
Datasheet: not publicly available, but seems to be similar to the
|
||||
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>
|
||||
Greg KH <greg@kroah.com>
|
||||
|
||||
@ -20,6 +20,10 @@ yours for best results.
|
||||
|
||||
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 typically look like that:
|
||||
#include <linux/module.h>
|
||||
@ -27,12 +31,10 @@ Technical changes:
|
||||
#include <linux/slab.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-isa.h> /* for ISA drivers */
|
||||
#include <linux/hwmon.h> /* for hardware monitoring drivers */
|
||||
#include <linux/hwmon-sysfs.h>
|
||||
#include <linux/hwmon-vid.h> /* if you need VRM support */
|
||||
#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
|
||||
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
|
||||
patch to the Documentation/hwmon/sysfs-interface file.
|
||||
|
||||
* [Attach] For I2C drivers, the attach function should make sure
|
||||
that the adapter's class has I2C_CLASS_HWMON (or whatever class is
|
||||
suitable for your driver), using the following construct:
|
||||
* [Attach] The attach function should make sure that the adapter's
|
||||
class has I2C_CLASS_HWMON (or whatever class is suitable for your
|
||||
driver), using the following construct:
|
||||
if (!(adapter->class & I2C_CLASS_HWMON))
|
||||
return 0;
|
||||
ISA-only drivers of course don't need this.
|
||||
Call i2c_probe() instead of i2c_detect().
|
||||
|
||||
* [Detect] As mentioned earlier, the flags parameter is gone.
|
||||
The type_name and client_name strings are replaced by a single
|
||||
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.
|
||||
It is advised that the labels are given descriptive names such as
|
||||
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
|
||||
slow two-wire protocol (10-400 kHz), but it suffices for many types of
|
||||
devices.
|
||||
slow two-wire protocol (variable speed, up to 400 kHz), with a high speed
|
||||
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
|
||||
modern mainboards have a System Management Bus. There are a lot of
|
||||
devices which can be connected to a SMBus; the most notable are modern
|
||||
memory chips with EEPROM memories and chips for hardware monitoring.
|
||||
SMBus (System Management Bus) is based on the I2C protocol, and is mostly
|
||||
a subset of I2C protocols and signaling. Many I2C devices will work on an
|
||||
SMBus, but some SMBus protocols add semantics beyond what is required to
|
||||
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
|
||||
can simulate the SMBus protocol on plain I2C busses. The reverse is
|
||||
regretfully impossible.
|
||||
Because the SMBus is mostly a subset of the generalized I2C bus, we can
|
||||
use its protocols on many I2C systems. However, there are systems that don't
|
||||
meet both SMBus and I2C electrical constraints; and others which can't
|
||||
implement all the common SMBus protocol semantics or messages.
|
||||
|
||||
|
||||
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
|
||||
of I2C adapters. Each specific adapter driver depends on one algorithm
|
||||
driver.
|
||||
|
||||
A Driver driver (yes, this sounds ridiculous, sorry) contains the general
|
||||
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
|
||||
@ -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
|
||||
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
|
||||
====================
|
||||
|
@ -1,5 +1,5 @@
|
||||
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
|
||||
some things can be done slightly or completely different. Use this as a
|
||||
@ -29,8 +29,16 @@ static struct i2c_driver foo_driver = {
|
||||
.driver = {
|
||||
.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,
|
||||
.detach_client = foo_detach_client,
|
||||
|
||||
/* these may be used regardless of the driver binding model */
|
||||
.shutdown = foo_shutdown, /* optional */
|
||||
.suspend = foo_suspend, /* 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
|
||||
should match the module name (if the driver can be compiled as a module),
|
||||
although you can use MODULE_ALIAS (passing "foo" in this example) to add
|
||||
another name for the module.
|
||||
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
|
||||
below.
|
||||
@ -65,16 +74,13 @@ An example structure is below.
|
||||
|
||||
struct foo_data {
|
||||
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. */
|
||||
|
||||
/* 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).
|
||||
It depends of course on the device whether this is really worthwhile
|
||||
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
|
||||
below information */
|
||||
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.
|
||||
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
|
||||
be encapsulated. Also, some chips have both ISA and I2C interfaces, and
|
||||
it useful to abstract from this (only for `sensors' drivers).
|
||||
be encapsulated.
|
||||
|
||||
The below functions are simple examples, and should not be copied
|
||||
literally.
|
||||
@ -119,28 +124,101 @@ literally.
|
||||
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
|
||||
=====================
|
||||
|
||||
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
|
||||
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
|
||||
@ -157,13 +235,9 @@ detection algorithm.
|
||||
You do not have to use this parameter interface; but don't try to use
|
||||
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
|
||||
---------------
|
||||
Probing classes (Legacy model)
|
||||
------------------------------
|
||||
|
||||
All parameters are given as lists of unsigned 16-bit integers. Lists are
|
||||
terminated by I2C_CLIENT_END.
|
||||
@ -210,8 +284,8 @@ Note that you *have* to call the defined variable `normal_i2c',
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
The detect client function
|
||||
--------------------------
|
||||
The detect client function (Legacy model)
|
||||
-----------------------------------------
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
@ -256,64 +326,20 @@ shortage or i2c_attach_client failing.
|
||||
For now, you can ignore the `flags' parameter. It is there for future use.
|
||||
|
||||
int foo_detect_client(struct i2c_adapter *adapter, int address,
|
||||
unsigned short flags, int kind)
|
||||
int kind)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
struct i2c_client *new_client;
|
||||
struct i2c_client *client;
|
||||
struct foo_data *data;
|
||||
const char *client_name = ""; /* For non-`sensors' drivers, put the real
|
||||
name here! */
|
||||
const char *name = "";
|
||||
|
||||
/* Let's see whether this adapter can support what we need.
|
||||
Please substitute the things you need here!
|
||||
For `sensors' drivers, add `! is_isa &&' to the if statement */
|
||||
Please substitute the things you need here! */
|
||||
if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_WRITE_BYTE))
|
||||
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
|
||||
client structure, even though we cannot fill it completely yet.
|
||||
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;
|
||||
}
|
||||
|
||||
new_client = &data->client;
|
||||
i2c_set_clientdata(new_client, data);
|
||||
client = &data->client;
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
new_client->addr = address;
|
||||
new_client->adapter = adapter;
|
||||
new_client->driver = &foo_driver;
|
||||
new_client->flags = 0;
|
||||
client->addr = address;
|
||||
client->adapter = adapter;
|
||||
client->driver = &foo_driver;
|
||||
|
||||
/* 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. */
|
||||
if (kind < 0) {
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* SENSORS ONLY START */
|
||||
|
||||
/* Next, specific detection. This is especially important for `sensors'
|
||||
devices. */
|
||||
|
||||
/* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
|
||||
was used. */
|
||||
if (kind <= 0) {
|
||||
i = foo_read(new_client,FOO_REG_CHIPTYPE);
|
||||
i = foo_read(client, FOO_REG_CHIPTYPE);
|
||||
if (i == FOO_TYPE_1)
|
||||
kind = chip1; /* As defined in the enum */
|
||||
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 */
|
||||
if (kind == chip1) {
|
||||
type_name = "chip1"; /* For /proc entry */
|
||||
client_name = "CHIP 1";
|
||||
name = "chip1";
|
||||
} else if (kind == chip2) {
|
||||
type_name = "chip2"; /* For /proc entry */
|
||||
client_name = "CHIP 2";
|
||||
name = "chip2";
|
||||
}
|
||||
|
||||
/* Reserve the ISA region */
|
||||
if (is_isa)
|
||||
request_region(address,FOO_EXTENT,type_name);
|
||||
|
||||
/* SENSORS ONLY END */
|
||||
|
||||
/* Fill in the remaining client fields. */
|
||||
strcpy(new_client->name,client_name);
|
||||
|
||||
/* SENSORS ONLY BEGIN */
|
||||
strlcpy(client->name, name, I2C_NAME_SIZE);
|
||||
data->type = kind;
|
||||
/* SENSORS ONLY END */
|
||||
|
||||
data->valid = 0; /* Only if you use this field */
|
||||
init_MUTEX(&data->update_lock); /* Only if you use this field */
|
||||
mutex_init(&data->update_lock); /* Only if you use this field */
|
||||
|
||||
/* 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
|
||||
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;
|
||||
|
||||
/* OK, this is not exactly good programming practice, usually. But it is
|
||||
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:
|
||||
kfree(data);
|
||||
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
|
||||
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 err,i;
|
||||
|
||||
/* SENSORS ONLY START */
|
||||
/* Deregister with the `i2c-proc' module. */
|
||||
i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
|
||||
/* SENSORS ONLY END */
|
||||
int err;
|
||||
|
||||
/* Try to detach the client from i2c space */
|
||||
if ((err = i2c_detach_client(client)))
|
||||
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));
|
||||
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)
|
||||
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)
|
||||
{
|
||||
int res;
|
||||
printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);
|
||||
|
||||
if ((res = i2c_add_driver(&foo_driver))) {
|
||||
printk("foo: Driver registration failed, module not inserted.\n");
|
||||
foo_cleanup();
|
||||
return res;
|
||||
}
|
||||
foo_initialized ++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void foo_cleanup(void)
|
||||
static void __exit foo_cleanup(void)
|
||||
{
|
||||
if (foo_initialized == 1) {
|
||||
if ((res = i2c_del_driver(&foo_driver))) {
|
||||
printk("foo: Driver registration failed, module not removed.\n");
|
||||
return;
|
||||
}
|
||||
foo_initialized --;
|
||||
}
|
||||
i2c_del_driver(&foo_driver);
|
||||
}
|
||||
|
||||
/* Substitute your own name and email address */
|
||||
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
|
||||
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_exit(foo_cleanup);
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@ -632,110 +602,7 @@ General purpose routines
|
||||
Below all general purpose routines are listed, that were not mentioned
|
||||
before.
|
||||
|
||||
/* This call returns a unique low identifier for each registered adapter,
|
||||
* or -1 if the adapter was not registered.
|
||||
/* This call returns a unique low identifier for each registered adapter.
|
||||
*/
|
||||
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
|
||||
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
|
||||
P: Jens Axboe
|
||||
M: axboe@kernel.dk
|
||||
@ -1459,6 +1466,11 @@ L: linux-scsi@vger.kernel.org
|
||||
W: http://www.icp-vortex.com/
|
||||
S: Supported
|
||||
|
||||
GENERIC GPIO I2C DRIVER
|
||||
P: Haavard Skinnemoen
|
||||
M: hskinnemoen@atmel.com
|
||||
S: Supported
|
||||
|
||||
GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
|
||||
P: Krzysztof Halasa
|
||||
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/
|
||||
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
|
||||
P: Riley H. Williams
|
||||
M: Riley@Williams.Name
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <linux/cpufreq.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/sysdev.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/hardirq.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/machdep.h>
|
||||
|
@ -58,7 +58,7 @@ obj-$(CONFIG_GAMEPORT) += input/gameport/
|
||||
obj-$(CONFIG_INPUT) += input/
|
||||
obj-$(CONFIG_I2O) += message/
|
||||
obj-$(CONFIG_RTC_LIB) += rtc/
|
||||
obj-$(CONFIG_I2C) += i2c/
|
||||
obj-y += i2c/
|
||||
obj-$(CONFIG_W1) += w1/
|
||||
obj-$(CONFIG_HWMON) += hwmon/
|
||||
obj-$(CONFIG_PHONE) += telephony/
|
||||
|
@ -2,9 +2,7 @@
|
||||
# I2C subsystem configuration
|
||||
#
|
||||
|
||||
menu "I2C support"
|
||||
|
||||
config I2C
|
||||
menuconfig I2C
|
||||
tristate "I2C support"
|
||||
---help---
|
||||
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
|
||||
will be called i2c-core.
|
||||
|
||||
if I2C
|
||||
|
||||
config I2C_BOARDINFO
|
||||
boolean
|
||||
default y
|
||||
|
||||
config I2C_CHARDEV
|
||||
tristate "I2C device interface"
|
||||
depends on I2C
|
||||
help
|
||||
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
|
||||
@ -40,7 +43,6 @@ source drivers/i2c/chips/Kconfig
|
||||
|
||||
config I2C_DEBUG_CORE
|
||||
bool "I2C Core debugging messages"
|
||||
depends on I2C
|
||||
help
|
||||
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
|
||||
@ -48,7 +50,6 @@ config I2C_DEBUG_CORE
|
||||
|
||||
config I2C_DEBUG_ALGO
|
||||
bool "I2C Algorithm debugging messages"
|
||||
depends on I2C
|
||||
help
|
||||
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
|
||||
@ -57,7 +58,6 @@ config I2C_DEBUG_ALGO
|
||||
|
||||
config I2C_DEBUG_BUS
|
||||
bool "I2C Bus debugging messages"
|
||||
depends on I2C
|
||||
help
|
||||
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
|
||||
@ -66,12 +66,10 @@ config I2C_DEBUG_BUS
|
||||
|
||||
config I2C_DEBUG_CHIP
|
||||
bool "I2C Chip debugging messages"
|
||||
depends on I2C
|
||||
help
|
||||
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
|
||||
a problem with I2C support and want to see more of what is going
|
||||
on.
|
||||
|
||||
endmenu
|
||||
|
||||
endif # I2C
|
||||
|
@ -2,6 +2,7 @@
|
||||
# Makefile for the i2c core.
|
||||
#
|
||||
|
||||
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
|
||||
obj-$(CONFIG_I2C) += i2c-core.o
|
||||
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
|
||||
obj-y += busses/ chips/ algos/
|
||||
|
@ -3,11 +3,9 @@
|
||||
#
|
||||
|
||||
menu "I2C Algorithms"
|
||||
depends on I2C
|
||||
|
||||
config I2C_ALGOBIT
|
||||
tristate "I2C bit-banging interfaces"
|
||||
depends on I2C
|
||||
help
|
||||
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
|
||||
@ -18,7 +16,6 @@ config I2C_ALGOBIT
|
||||
|
||||
config I2C_ALGOPCF
|
||||
tristate "I2C PCF 8584 interfaces"
|
||||
depends on I2C
|
||||
help
|
||||
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
|
||||
@ -29,7 +26,6 @@ config I2C_ALGOPCF
|
||||
|
||||
config I2C_ALGOPCA
|
||||
tristate "I2C PCA 9564 interfaces"
|
||||
depends on I2C
|
||||
help
|
||||
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
|
||||
@ -40,11 +36,11 @@ config I2C_ALGOPCA
|
||||
|
||||
config I2C_ALGO8XX
|
||||
tristate "MPC8xx CPM I2C interface"
|
||||
depends on 8xx && I2C
|
||||
depends on 8xx
|
||||
|
||||
config I2C_ALGO_SGI
|
||||
tristate "I2C SGI interfaces"
|
||||
depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)
|
||||
depends on SGI_IP22 || SGI_IP32 || X86_VISWS
|
||||
help
|
||||
Supports the SGI interfaces like the ones found on SGI Indy VINO
|
||||
or SGI O2 MACE.
|
||||
|
@ -33,19 +33,30 @@
|
||||
|
||||
|
||||
/* ----- 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 --------------------------------------------- */
|
||||
|
||||
/* module parameters:
|
||||
*/
|
||||
static int i2c_debug;
|
||||
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: --------------- */
|
||||
|
||||
@ -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)
|
||||
{
|
||||
setsda(adap,0);
|
||||
udelay(adap->udelay);
|
||||
udelay((adap->udelay + 1) / 2);
|
||||
}
|
||||
|
||||
static inline void sdahi(struct i2c_algo_bit_data *adap)
|
||||
{
|
||||
setsda(adap,1);
|
||||
udelay(adap->udelay);
|
||||
udelay((adap->udelay + 1) / 2);
|
||||
}
|
||||
|
||||
static inline void scllo(struct i2c_algo_bit_data *adap)
|
||||
{
|
||||
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();
|
||||
}
|
||||
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:
|
||||
udelay(adap->udelay);
|
||||
@ -110,30 +125,29 @@ static int sclhi(struct i2c_algo_bit_data *adap)
|
||||
static void i2c_start(struct i2c_algo_bit_data *adap)
|
||||
{
|
||||
/* assert: scl, sda are high */
|
||||
DEBPROTO(printk("S "));
|
||||
sdalo(adap);
|
||||
setsda(adap, 0);
|
||||
udelay(adap->udelay);
|
||||
scllo(adap);
|
||||
}
|
||||
|
||||
static void i2c_repstart(struct i2c_algo_bit_data *adap)
|
||||
{
|
||||
/* scl, sda may not be high */
|
||||
DEBPROTO(printk(" Sr "));
|
||||
setsda(adap,1);
|
||||
/* assert: scl is low */
|
||||
sdahi(adap);
|
||||
sclhi(adap);
|
||||
|
||||
sdalo(adap);
|
||||
setsda(adap, 0);
|
||||
udelay(adap->udelay);
|
||||
scllo(adap);
|
||||
}
|
||||
|
||||
|
||||
static void i2c_stop(struct i2c_algo_bit_data *adap)
|
||||
{
|
||||
DEBPROTO(printk("P\n"));
|
||||
/* assert: scl is low */
|
||||
sdalo(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
|
||||
* -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 sb;
|
||||
@ -154,34 +168,32 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
|
||||
|
||||
/* assert: scl is low */
|
||||
for ( i=7 ; i>=0 ; i-- ) {
|
||||
sb = c & ( 1 << i );
|
||||
sb = (c >> i) & 1;
|
||||
setsda(adap,sb);
|
||||
udelay(adap->udelay);
|
||||
DEBPROTO(printk(KERN_DEBUG "%d",sb!=0));
|
||||
udelay((adap->udelay + 1) / 2);
|
||||
if (sclhi(adap)<0) { /* timed out */
|
||||
sdahi(adap); /* we don't want to block the net */
|
||||
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i));
|
||||
bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
|
||||
"timeout at bit #%d\n", (int)c, i);
|
||||
return -ETIMEDOUT;
|
||||
};
|
||||
/* do arbitration here:
|
||||
* if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
|
||||
*/
|
||||
setscl(adap, 0 );
|
||||
udelay(adap->udelay);
|
||||
scllo(adap);
|
||||
}
|
||||
sdahi(adap);
|
||||
if (sclhi(adap)<0){ /* timeout */
|
||||
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff));
|
||||
return -ETIMEDOUT;
|
||||
bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
|
||||
"timeout at ack\n", (int)c);
|
||||
return -ETIMEDOUT;
|
||||
};
|
||||
/* read ack: SDA should be pulled down by slave */
|
||||
ack=getsda(adap); /* ack: sda is pulled low ->success. */
|
||||
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack));
|
||||
ack = !getsda(adap); /* ack: sda is pulled low -> success */
|
||||
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);
|
||||
return 0==ack; /* return 1 if device acked */
|
||||
return ack;
|
||||
/* assert: scl is low (sda undef) */
|
||||
}
|
||||
|
||||
@ -198,19 +210,18 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
|
||||
sdahi(adap);
|
||||
for (i=0;i<8;i++) {
|
||||
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;
|
||||
};
|
||||
indata *= 2;
|
||||
if ( getsda(adap) )
|
||||
indata |= 0x01;
|
||||
scllo(adap);
|
||||
setscl(adap, 0);
|
||||
udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
|
||||
}
|
||||
/* assert: scl is low */
|
||||
DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff));
|
||||
|
||||
DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff));
|
||||
return (int) (indata & 0xff);
|
||||
return indata;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -221,73 +232,67 @@ static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
|
||||
int scl,sda;
|
||||
|
||||
if (adap->getscl==NULL)
|
||||
printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, "
|
||||
"SCL is not readable.\n");
|
||||
pr_info("%s: Testing SDA only, SCL is not readable\n", name);
|
||||
|
||||
sda=getsda(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 ) {
|
||||
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;
|
||||
}
|
||||
|
||||
sdalo(adap);
|
||||
sda=getsda(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 ) {
|
||||
printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n");
|
||||
printk(KERN_WARNING "%s: SDA stuck high!\n", name);
|
||||
goto bailout;
|
||||
}
|
||||
if ( 0 == scl ) {
|
||||
printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
|
||||
"while pulling SDA low!\n");
|
||||
printk(KERN_WARNING "%s: SCL unexpected low "
|
||||
"while pulling SDA low!\n", name);
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
sdahi(adap);
|
||||
sda=getsda(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 ) {
|
||||
printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n");
|
||||
printk(KERN_WARNING "%s: SDA stuck low!\n", name);
|
||||
goto bailout;
|
||||
}
|
||||
if ( 0 == scl ) {
|
||||
printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low "
|
||||
"while pulling SDA high!\n");
|
||||
printk(KERN_WARNING "%s: SCL unexpected low "
|
||||
"while pulling SDA high!\n", name);
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
scllo(adap);
|
||||
sda=getsda(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 ) {
|
||||
printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n");
|
||||
printk(KERN_WARNING "%s: SCL stuck high!\n", name);
|
||||
goto bailout;
|
||||
}
|
||||
if ( 0 == sda ) {
|
||||
printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
|
||||
"while pulling SCL low!\n");
|
||||
printk(KERN_WARNING "%s: SDA unexpected low "
|
||||
"while pulling SCL low!\n", name);
|
||||
goto bailout;
|
||||
}
|
||||
|
||||
sclhi(adap);
|
||||
sda=getsda(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 ) {
|
||||
printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n");
|
||||
printk(KERN_WARNING "%s: SCL stuck low!\n", name);
|
||||
goto bailout;
|
||||
}
|
||||
if ( 0 == sda ) {
|
||||
printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low "
|
||||
"while pulling SCL high!\n");
|
||||
printk(KERN_WARNING "%s: SDA unexpected low "
|
||||
"while pulling SCL high!\n", name);
|
||||
goto bailout;
|
||||
}
|
||||
printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name);
|
||||
pr_info("%s: Test OK\n", name);
|
||||
return 0;
|
||||
bailout:
|
||||
sdahi(adap);
|
||||
@ -312,44 +317,39 @@ static int try_address(struct i2c_adapter *i2c_adap,
|
||||
int i,ret = -1;
|
||||
for (i=0;i<=retries;i++) {
|
||||
ret = i2c_outb(i2c_adap,addr);
|
||||
if (ret==1)
|
||||
break; /* success! */
|
||||
i2c_stop(adap);
|
||||
udelay(5/*adap->udelay*/);
|
||||
if (i==retries) /* no success */
|
||||
if (ret == 1 || i == retries)
|
||||
break;
|
||||
i2c_start(adap);
|
||||
bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
|
||||
i2c_stop(adap);
|
||||
udelay(adap->udelay);
|
||||
yield();
|
||||
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
|
||||
i2c_start(adap);
|
||||
}
|
||||
DEB2(if (i)
|
||||
printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n",
|
||||
i+1, addr & 1 ? "read" : "write", addr>>1,
|
||||
ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" )
|
||||
);
|
||||
if (i && ret)
|
||||
bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
|
||||
"0x%02x: %s\n", i + 1,
|
||||
addr & 1 ? "read from" : "write to", addr >> 1,
|
||||
ret == 1 ? "success" : "failed, timeout?");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
||||
{
|
||||
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
|
||||
char c;
|
||||
const char *temp = msg->buf;
|
||||
const unsigned char *temp = msg->buf;
|
||||
int count = msg->len;
|
||||
unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
|
||||
int retval;
|
||||
int wrcount=0;
|
||||
|
||||
while (count > 0) {
|
||||
c = *temp;
|
||||
DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff));
|
||||
retval = i2c_outb(i2c_adap,c);
|
||||
retval = i2c_outb(i2c_adap, *temp);
|
||||
if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */
|
||||
count--;
|
||||
temp++;
|
||||
wrcount++;
|
||||
} else { /* arbitration or no acknowledge */
|
||||
dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
|
||||
i2c_stop(adap);
|
||||
return (retval<0)? retval : -EFAULT;
|
||||
/* got a better one ?? */
|
||||
}
|
||||
@ -362,7 +362,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
||||
int inval;
|
||||
int rdcount=0; /* counts bytes read */
|
||||
struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
|
||||
char *temp = msg->buf;
|
||||
unsigned char *temp = msg->buf;
|
||||
int count = msg->len;
|
||||
|
||||
while (count > 0) {
|
||||
@ -371,30 +371,44 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
||||
*temp = inval;
|
||||
rdcount++;
|
||||
} else { /* read timed out */
|
||||
printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
temp++;
|
||||
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;
|
||||
|
||||
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 */
|
||||
sdahi(adap);
|
||||
printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n");
|
||||
dev_err(&i2c_adap->dev, "readbytes: timeout at ack\n");
|
||||
return -ETIMEDOUT;
|
||||
};
|
||||
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;
|
||||
}
|
||||
@ -421,27 +435,31 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
|
||||
if ( (flags & I2C_M_TEN) ) {
|
||||
/* a ten bit address */
|
||||
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...*/
|
||||
ret = try_address(i2c_adap, addr, retries);
|
||||
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;
|
||||
}
|
||||
/* the remaining 8 bit address */
|
||||
ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
|
||||
if ((ret != 1) && !nak_ok) {
|
||||
/* 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;
|
||||
}
|
||||
if ( flags & I2C_M_RD ) {
|
||||
bit_dbg(3, &i2c_adap->dev, "emitting repeated "
|
||||
"start condition\n");
|
||||
i2c_repstart(adap);
|
||||
/* okay, now switch into reading mode */
|
||||
addr |= 0x01;
|
||||
ret = try_address(i2c_adap, addr, retries);
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -468,44 +486,62 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
|
||||
int i,ret;
|
||||
unsigned short nak_ok;
|
||||
|
||||
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
|
||||
i2c_start(adap);
|
||||
for (i=0;i<num;i++) {
|
||||
pmsg = &msgs[i];
|
||||
nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;
|
||||
if (!(pmsg->flags & I2C_M_NOSTART)) {
|
||||
if (i) {
|
||||
bit_dbg(3, &i2c_adap->dev, "emitting "
|
||||
"repeated start condition\n");
|
||||
i2c_repstart(adap);
|
||||
}
|
||||
ret = bit_doAddress(i2c_adap, pmsg);
|
||||
if ((ret != 0) && !nak_ok) {
|
||||
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n"
|
||||
,msgs[i].addr,i));
|
||||
return (ret<0) ? ret : -EREMOTEIO;
|
||||
bit_dbg(1, &i2c_adap->dev, "NAK from "
|
||||
"device addr 0x%02x msg #%d\n",
|
||||
msgs[i].addr, i);
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
if (pmsg->flags & I2C_M_RD ) {
|
||||
/* read bytes into buffer*/
|
||||
ret = readbytes(i2c_adap, pmsg);
|
||||
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret));
|
||||
if (ret < pmsg->len ) {
|
||||
return (ret<0)? ret : -EREMOTEIO;
|
||||
if (ret >= 1)
|
||||
bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",
|
||||
ret, ret == 1 ? "" : "s");
|
||||
if (ret < pmsg->len) {
|
||||
if (ret >= 0)
|
||||
ret = -EREMOTEIO;
|
||||
goto bailout;
|
||||
}
|
||||
} else {
|
||||
/* write bytes from buffer */
|
||||
ret = sendbytes(i2c_adap, pmsg);
|
||||
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret));
|
||||
if (ret < pmsg->len ) {
|
||||
return (ret<0) ? ret : -EREMOTEIO;
|
||||
if (ret >= 1)
|
||||
bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",
|
||||
ret, ret == 1 ? "" : "s");
|
||||
if (ret < pmsg->len) {
|
||||
if (ret >= 0)
|
||||
ret = -EREMOTEIO;
|
||||
goto bailout;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = i;
|
||||
|
||||
bailout:
|
||||
bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
|
||||
i2c_stop(adap);
|
||||
return num;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 bit_func(struct i2c_adapter *adap)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -520,7 +556,7 @@ static const struct i2c_algorithm i2c_bit_algo = {
|
||||
/*
|
||||
* 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;
|
||||
|
||||
@ -530,25 +566,39 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
adap->algo = &i2c_bit_algo;
|
||||
|
||||
adap->timeout = 100; /* default values, should */
|
||||
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);
|
||||
}
|
||||
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_DESCRIPTION("I2C-Bus bit-banging algorithm");
|
||||
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,6 +1,7 @@
|
||||
/*
|
||||
* 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
|
||||
* License version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
@ -162,8 +163,8 @@ static const struct i2c_algorithm sgi_algo = {
|
||||
.functionality = sgi_func,
|
||||
};
|
||||
|
||||
/*
|
||||
* registering functions to load algorithms at runtime
|
||||
/*
|
||||
* registering functions to load algorithms at runtime
|
||||
*/
|
||||
int i2c_sgi_add_bus(struct i2c_adapter *adap)
|
||||
{
|
||||
|
@ -3,11 +3,10 @@
|
||||
#
|
||||
|
||||
menu "I2C Hardware Bus support"
|
||||
depends on I2C
|
||||
|
||||
config I2C_ALI1535
|
||||
tristate "ALI 1535"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
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
|
||||
@ -19,7 +18,7 @@ config I2C_ALI1535
|
||||
|
||||
config I2C_ALI1563
|
||||
tristate "ALI 1563"
|
||||
depends on I2C && PCI && EXPERIMENTAL
|
||||
depends on PCI && EXPERIMENTAL
|
||||
help
|
||||
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
|
||||
@ -31,7 +30,7 @@ config I2C_ALI1563
|
||||
|
||||
config I2C_ALI15X3
|
||||
tristate "ALI 15x3"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
|
||||
@ -41,7 +40,7 @@ config I2C_ALI15X3
|
||||
|
||||
config I2C_AMD756
|
||||
tristate "AMD 756/766/768/8111 and nVidia nForce"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the AMD
|
||||
756/766/768 mainboard I2C interfaces. The driver also includes
|
||||
@ -66,7 +65,7 @@ config I2C_AMD756_S4882
|
||||
|
||||
config I2C_AMD8111
|
||||
tristate "AMD 8111"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
second (SMBus 2.0) AMD 8111 mainboard I2C interface.
|
||||
@ -76,14 +75,14 @@ config I2C_AMD8111
|
||||
|
||||
config I2C_AT91
|
||||
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
|
||||
depends on I2C && ARCH_AT91 && EXPERIMENTAL
|
||||
depends on ARCH_AT91 && EXPERIMENTAL
|
||||
help
|
||||
This supports the use of the I2C interface on Atmel AT91
|
||||
processors.
|
||||
|
||||
config I2C_AU1550
|
||||
tristate "Au1550/Au1200 SMBus interface"
|
||||
depends on I2C && (SOC_AU1550 || SOC_AU1200)
|
||||
depends on SOC_AU1550 || SOC_AU1200
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
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
|
||||
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
|
||||
tristate "Elektor ISA card"
|
||||
depends on I2C && ISA && BROKEN_ON_SMP
|
||||
depends on ISA && BROKEN_ON_SMP
|
||||
select I2C_ALGOPCF
|
||||
help
|
||||
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
|
||||
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
|
||||
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
|
||||
help
|
||||
This supports the use of the I2C interface in the Apple Hydra Mac
|
||||
@ -116,7 +139,7 @@ config I2C_HYDRA
|
||||
|
||||
config I2C_I801
|
||||
tristate "Intel 82801 (ICH)"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the Intel
|
||||
801 family of mainboard I2C interfaces. Specifically, the following
|
||||
@ -139,7 +162,7 @@ config I2C_I801
|
||||
|
||||
config I2C_I810
|
||||
tristate "Intel 810/815"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
If you say yes to this option, support will be included for the Intel
|
||||
@ -156,7 +179,7 @@ config I2C_I810
|
||||
|
||||
config I2C_PXA
|
||||
tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
|
||||
depends on I2C && EXPERIMENTAL && ARCH_PXA
|
||||
depends on EXPERIMENTAL && ARCH_PXA
|
||||
help
|
||||
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
|
||||
@ -172,7 +195,7 @@ config I2C_PXA_SLAVE
|
||||
|
||||
config I2C_PIIX4
|
||||
tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the Intel
|
||||
PIIX4 family of mainboard I2C interfaces. Specifically, the following
|
||||
@ -195,7 +218,7 @@ config I2C_PIIX4
|
||||
|
||||
config I2C_IBM_IIC
|
||||
tristate "IBM PPC 4xx on-chip I2C interface"
|
||||
depends on IBM_OCP && I2C
|
||||
depends on IBM_OCP
|
||||
help
|
||||
Say Y here if you want to use IIC peripheral found on
|
||||
embedded IBM PPC 4xx based systems.
|
||||
@ -205,7 +228,7 @@ config I2C_IBM_IIC
|
||||
|
||||
config I2C_IOP3XX
|
||||
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
|
||||
Say Y here if you want to use the IIC bus controller on
|
||||
the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
|
||||
@ -215,11 +238,10 @@ config I2C_IOP3XX
|
||||
|
||||
config I2C_ISA
|
||||
tristate
|
||||
depends on I2C
|
||||
|
||||
config I2C_IXP4XX
|
||||
tristate "IXP4xx GPIO-Based I2C Interface"
|
||||
depends on I2C && ARCH_IXP4XX
|
||||
tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)"
|
||||
depends on ARCH_IXP4XX
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
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
|
||||
will be called i2c-ixp4xx.
|
||||
|
||||
This driver is deprecated and will be dropped soon. Use i2c-gpio
|
||||
instead.
|
||||
|
||||
config I2C_IXP2000
|
||||
tristate "IXP2000 GPIO-Based I2C Interface"
|
||||
depends on I2C && ARCH_IXP2000
|
||||
tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
|
||||
depends on ARCH_IXP2000
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
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
|
||||
will be called i2c-ixp2000.
|
||||
|
||||
This driver is deprecated and will be dropped soon. Use i2c-gpio
|
||||
instead.
|
||||
|
||||
config I2C_POWERMAC
|
||||
tristate "Powermac I2C interface"
|
||||
depends on I2C && PPC_PMAC
|
||||
depends on PPC_PMAC
|
||||
default y
|
||||
help
|
||||
This exposes the various PowerMac i2c interfaces to the linux i2c
|
||||
@ -253,7 +281,7 @@ config I2C_POWERMAC
|
||||
|
||||
config I2C_MPC
|
||||
tristate "MPC107/824x/85xx/52xx/86xx"
|
||||
depends on I2C && PPC32
|
||||
depends on PPC32
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
|
||||
@ -265,7 +293,7 @@ config I2C_MPC
|
||||
|
||||
config I2C_NFORCE2
|
||||
tristate "Nvidia nForce2, nForce3 and nForce4"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the Nvidia
|
||||
nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
|
||||
@ -275,7 +303,7 @@ config I2C_NFORCE2
|
||||
|
||||
config I2C_OCORES
|
||||
tristate "OpenCores I2C Controller"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
OpenCores I2C controller. For details see
|
||||
@ -286,7 +314,7 @@ config I2C_OCORES
|
||||
|
||||
config I2C_OMAP
|
||||
tristate "OMAP I2C adapter"
|
||||
depends on I2C && ARCH_OMAP
|
||||
depends on ARCH_OMAP
|
||||
default y if MACH_OMAP_H3 || MACH_OMAP_OSK
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
@ -296,7 +324,7 @@ config I2C_OMAP
|
||||
|
||||
config I2C_PARPORT
|
||||
tristate "Parallel port adapter"
|
||||
depends on I2C && PARPORT
|
||||
depends on PARPORT
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
This supports parallel port I2C adapters such as the ones made by
|
||||
@ -320,7 +348,6 @@ config I2C_PARPORT
|
||||
|
||||
config I2C_PARPORT_LIGHT
|
||||
tristate "Parallel port adapter (light)"
|
||||
depends on I2C
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
This supports parallel port I2C adapters such as the ones made by
|
||||
@ -344,13 +371,13 @@ config I2C_PARPORT_LIGHT
|
||||
|
||||
config I2C_PASEMI
|
||||
tristate "PA Semi SMBus interface"
|
||||
depends on PPC_PASEMI && I2C && PCI
|
||||
depends on PPC_PASEMI && PCI
|
||||
help
|
||||
Supports the PA Semi PWRficient on-chip SMBus interfaces.
|
||||
|
||||
config I2C_PROSAVAGE
|
||||
tristate "S3/VIA (Pro)Savage"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
@ -365,19 +392,19 @@ config I2C_PROSAVAGE
|
||||
|
||||
config I2C_RPXLITE
|
||||
tristate "Embedded Planet RPX Lite/Classic support"
|
||||
depends on (RPXLITE || RPXCLASSIC) && I2C
|
||||
depends on RPXLITE || RPXCLASSIC
|
||||
select I2C_ALGO8XX
|
||||
|
||||
config I2C_S3C2410
|
||||
tristate "S3C2410 I2C Driver"
|
||||
depends on I2C && ARCH_S3C2410
|
||||
depends on ARCH_S3C2410
|
||||
help
|
||||
Say Y here to include support for I2C controller in the
|
||||
Samsung S3C2410 based System-on-Chip devices.
|
||||
|
||||
config I2C_SAVAGE4
|
||||
tristate "S3 Savage 4"
|
||||
depends on I2C && PCI && EXPERIMENTAL
|
||||
depends on PCI && EXPERIMENTAL
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
@ -388,13 +415,25 @@ config I2C_SAVAGE4
|
||||
|
||||
config I2C_SIBYTE
|
||||
tristate "SiByte SMBus interface"
|
||||
depends on SIBYTE_SB1xxx_SOC && I2C
|
||||
depends on SIBYTE_SB1xxx_SOC
|
||||
help
|
||||
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
|
||||
tristate "NatSemi SCx200 I2C using GPIO pins"
|
||||
depends on SCx200_GPIO && I2C
|
||||
tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
|
||||
depends on SCx200_GPIO
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
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
|
||||
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
|
||||
int "GPIO pin used for SCL"
|
||||
depends on SCx200_I2C
|
||||
@ -422,7 +464,7 @@ config SCx200_I2C_SDA
|
||||
|
||||
config SCx200_ACB
|
||||
tristate "Geode ACCESS.bus support"
|
||||
depends on X86_32 && I2C && PCI
|
||||
depends on X86_32 && PCI
|
||||
help
|
||||
Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
|
||||
SC1100 processors and the CS5535 and CS5536 Geode companion devices.
|
||||
@ -434,7 +476,7 @@ config SCx200_ACB
|
||||
|
||||
config I2C_SIS5595
|
||||
tristate "SiS 5595"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
SiS5595 SMBus (a subset of I2C) interface.
|
||||
@ -444,7 +486,7 @@ config I2C_SIS5595
|
||||
|
||||
config I2C_SIS630
|
||||
tristate "SiS 630/730"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
SiS630 and SiS730 SMBus (a subset of I2C) interface.
|
||||
@ -454,7 +496,7 @@ config I2C_SIS630
|
||||
|
||||
config I2C_SIS96X
|
||||
tristate "SiS 96x"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the SiS
|
||||
96x SMBus (a subset of I2C) interfaces. Specifically, the following
|
||||
@ -472,7 +514,7 @@ config I2C_SIS96X
|
||||
|
||||
config I2C_STUB
|
||||
tristate "I2C/SMBus Test Stub"
|
||||
depends on I2C && EXPERIMENTAL && 'm'
|
||||
depends on EXPERIMENTAL && m
|
||||
default 'n'
|
||||
help
|
||||
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.
|
||||
|
||||
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
|
||||
tristate "ARM Versatile/Realview I2C bus support"
|
||||
depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW)
|
||||
depends on ARCH_VERSATILE || ARCH_REALVIEW
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
Say yes if you want to support the I2C serial bus on ARMs Versatile
|
||||
@ -496,7 +549,7 @@ config I2C_VERSATILE
|
||||
|
||||
config I2C_ACORN
|
||||
bool "Acorn IOC/IOMD I2C bus support"
|
||||
depends on I2C && ARCH_ACORN
|
||||
depends on ARCH_ACORN
|
||||
default y
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
@ -506,7 +559,7 @@ config I2C_ACORN
|
||||
|
||||
config I2C_VIA
|
||||
tristate "VIA 82C586B"
|
||||
depends on I2C && PCI && EXPERIMENTAL
|
||||
depends on PCI && EXPERIMENTAL
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
If you say yes to this option, support will be included for the VIA
|
||||
@ -517,7 +570,7 @@ config I2C_VIA
|
||||
|
||||
config I2C_VIAPRO
|
||||
tristate "VIA VT82C596/82C686/82xx and CX700"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
help
|
||||
If you say yes to this option, support will be included for the VIA
|
||||
VT82C596 and later SMBus interface. Specifically, the following
|
||||
@ -536,7 +589,7 @@ config I2C_VIAPRO
|
||||
|
||||
config I2C_VOODOO3
|
||||
tristate "Voodoo 3"
|
||||
depends on I2C && PCI
|
||||
depends on PCI
|
||||
select I2C_ALGOBIT
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
@ -547,7 +600,7 @@ config I2C_VOODOO3
|
||||
|
||||
config I2C_PCA_ISA
|
||||
tristate "PCA9564 on an ISA bus"
|
||||
depends on I2C
|
||||
depends on ISA
|
||||
select I2C_ALGOPCA
|
||||
default n
|
||||
help
|
||||
@ -564,7 +617,7 @@ config I2C_PCA_ISA
|
||||
|
||||
config I2C_MV64XXX
|
||||
tristate "Marvell mv64xxx I2C Controller"
|
||||
depends on I2C && MV64X60 && EXPERIMENTAL
|
||||
depends on MV64X60 && EXPERIMENTAL
|
||||
help
|
||||
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.
|
||||
@ -574,7 +627,7 @@ config I2C_MV64XXX
|
||||
|
||||
config I2C_PNX
|
||||
tristate "I2C bus support for Philips PNX targets"
|
||||
depends on ARCH_PNX4008 && I2C
|
||||
depends on ARCH_PNX4008
|
||||
help
|
||||
This driver supports the Philips IP3204 I2C IP block master and/or
|
||||
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_AT91) += i2c-at91.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_GPIO) += i2c-gpio.o
|
||||
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
|
||||
obj-$(CONFIG_I2C_I801) += i2c-i801.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_SAVAGE4) += i2c-savage4.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_SIS630) += i2c-sis630.o
|
||||
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.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_ACORN) += i2c-acorn.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 */
|
||||
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);
|
||||
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 */
|
||||
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);
|
||||
return i2c_add_adapter(&ali15x3_adapter);
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
|
||||
}
|
||||
|
||||
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);
|
||||
smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
|
||||
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/wait.h>
|
||||
|
||||
#include <linux/isa.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-pcf.h>
|
||||
|
||||
@ -207,7 +208,7 @@ static struct i2c_adapter pcf_isa_ops = {
|
||||
.name = "i2c-elektor",
|
||||
};
|
||||
|
||||
static int __init i2c_pcfisa_init(void)
|
||||
static int __devinit elektor_match(struct device *dev, unsigned int id)
|
||||
{
|
||||
#ifdef __alpha__
|
||||
/* 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 */
|
||||
if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
|
||||
|
||||
pr_debug("%s: found cy82c693, config "
|
||||
"register 0x47 = 0x%02x\n",
|
||||
pcf_isa_ops.name, config);
|
||||
dev_dbg(dev, "found cy82c693, config "
|
||||
"register 0x47 = 0x%02x\n", config);
|
||||
|
||||
/* UP2000 board has this register set to 0xe1,
|
||||
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
|
||||
(this can be read from cypress) */
|
||||
clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
|
||||
pr_info("%s: found API UP2000 like "
|
||||
"board, will probe PCF8584 "
|
||||
"later\n", pcf_isa_ops.name);
|
||||
dev_info(dev, "found API UP2000 like "
|
||||
"board, will probe PCF8584 "
|
||||
"later\n");
|
||||
}
|
||||
}
|
||||
pci_dev_put(cy693_dev);
|
||||
@ -256,22 +256,27 @@ static int __init i2c_pcfisa_init(void)
|
||||
|
||||
/* sanity checks for mmapped I/O */
|
||||
if (mmapped && base < 0xc8000) {
|
||||
printk(KERN_ERR "%s: incorrect base address (%#x) specified "
|
||||
"for mmapped I/O\n", pcf_isa_ops.name, base);
|
||||
return -ENODEV;
|
||||
dev_err(dev, "incorrect base address (%#x) specified "
|
||||
"for mmapped I/O\n", base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (base == 0) {
|
||||
base = DEFAULT_BASE;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __devinit elektor_probe(struct device *dev, unsigned int id)
|
||||
{
|
||||
init_waitqueue_head(&pcf_wait);
|
||||
if (pcf_isa_init())
|
||||
return -ENODEV;
|
||||
pcf_isa_ops.dev.parent = dev;
|
||||
if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
|
||||
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;
|
||||
|
||||
@ -291,7 +296,7 @@ static int __init i2c_pcfisa_init(void)
|
||||
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);
|
||||
|
||||
@ -307,6 +312,28 @@ static void i2c_pcfisa_exit(void)
|
||||
iounmap(base_iomem);
|
||||
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>");
|
||||
|
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 */
|
||||
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);
|
||||
err = i2c_add_adapter(&i801_adapter);
|
||||
if (err) {
|
||||
|
@ -41,6 +41,10 @@
|
||||
#include <linux/platform_device.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);
|
||||
|
||||
/* 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,
|
||||
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. */
|
||||
@ -139,41 +133,18 @@ static int __init i2c_isa_init(void)
|
||||
isa_adapter.nr = ANY_I2C_ISA_BUS;
|
||||
isa_adapter.dev.parent = &platform_bus;
|
||||
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.class = &i2c_adapter_class;
|
||||
err = device_register(&isa_adapter.dev);
|
||||
if (err) {
|
||||
printk(KERN_ERR "i2c-isa: Failed to register device\n");
|
||||
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);
|
||||
|
||||
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:
|
||||
return err;
|
||||
}
|
||||
@ -201,15 +172,11 @@ static void __exit i2c_isa_exit(void)
|
||||
/* Clean up the sysfs representation */
|
||||
dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
|
||||
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);
|
||||
|
||||
/* Wait for sysfs to drop all references */
|
||||
dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
|
||||
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);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
|
||||
|
||||
drv_data->adapter.id = I2C_HW_B_IXP2000,
|
||||
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.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.class = I2C_CLASS_HWMON;
|
||||
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.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",
|
||||
I2C_NAME_SIZE);
|
||||
sizeof(drv_data->adapter.name));
|
||||
|
||||
init_waitqueue_head(&drv_data->waitq);
|
||||
spin_lock_init(&drv_data->lock);
|
||||
|
@ -33,6 +33,8 @@
|
||||
nForce4 MCP-04 0034
|
||||
nForce4 MCP51 0264
|
||||
nForce4 MCP55 0368
|
||||
nForce MCP61 03EB
|
||||
nForce MCP65 0446
|
||||
|
||||
This driver supports the 2 SMBuses that are included in the MCP of the
|
||||
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_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_MCP61_SMBUS) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },
|
||||
{ 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_data = smbus;
|
||||
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);
|
||||
|
||||
error = i2c_add_adapter(&smbus->adapter);
|
||||
|
@ -605,7 +605,8 @@ omap_i2c_probe(struct platform_device *pdev)
|
||||
adap->dev.parent = &pdev->dev;
|
||||
|
||||
/* 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) {
|
||||
dev_err(dev->dev, "failure adding adapter\n");
|
||||
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
|
||||
Copyright (C) 1995-2000 Simon G. Vogl
|
||||
@ -27,6 +27,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
@ -34,6 +35,9 @@
|
||||
#include "i2c-parport.h"
|
||||
|
||||
#define DEFAULT_BASE 0x378
|
||||
#define DRVNAME "i2c-parport-light"
|
||||
|
||||
static struct platform_device *pdev;
|
||||
|
||||
static u16 base;
|
||||
module_param(base, ushort, 0);
|
||||
@ -106,7 +110,7 @@ static struct i2c_algo_bit_data parport_algo_data = {
|
||||
.timeout = HZ,
|
||||
};
|
||||
|
||||
/* ----- I2c structure ---------------------------------------------------- */
|
||||
/* ----- Driver registration ---------------------------------------------- */
|
||||
|
||||
static struct i2c_adapter parport_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
@ -116,30 +120,14 @@ static struct i2c_adapter parport_adapter = {
|
||||
.name = "Parallel port adapter (light)",
|
||||
};
|
||||
|
||||
/* ----- Module loading, unloading and information ------------------------ */
|
||||
|
||||
static int __init i2c_parport_init(void)
|
||||
static int __devinit i2c_parport_probe(struct platform_device *pdev)
|
||||
{
|
||||
if (type < 0) {
|
||||
printk(KERN_WARNING "i2c-parport: adapter type unspecified\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
int err;
|
||||
struct resource *res;
|
||||
|
||||
if (type >= ARRAY_SIZE(adapter_parm)) {
|
||||
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
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;
|
||||
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||
if (!request_region(res->start, res->end - res->start + 1, DRVNAME))
|
||||
return -EBUSY;
|
||||
|
||||
/* Reset hardware to a sane state (SCL and SDA high) */
|
||||
parport_setsda(NULL, 1);
|
||||
@ -148,23 +136,125 @@ static int __init i2c_parport_init(void)
|
||||
if (adapter_parm[type].init.val)
|
||||
line_set(1, &adapter_parm[type].init);
|
||||
|
||||
if (i2c_bit_add_bus(&parport_adapter) < 0) {
|
||||
printk(KERN_ERR "i2c-parport: Unable to register with I2C\n");
|
||||
release_region(base, 3);
|
||||
return -ENODEV;
|
||||
parport_adapter.dev.parent = &pdev->dev;
|
||||
err = i2c_bit_add_bus(&parport_adapter);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Unable to register with I2C\n");
|
||||
goto exit_region;
|
||||
}
|
||||
|
||||
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...) */
|
||||
if (adapter_parm[type].init.val)
|
||||
line_set(0, &adapter_parm[type].init);
|
||||
|
||||
i2c_del_adapter(&parport_adapter);
|
||||
release_region(base, 3);
|
||||
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||
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>");
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* ------------------------------------------------------------------------ *
|
||||
* 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
|
||||
Copyright (C) 1995-2000 Simon G. Vogl
|
||||
@ -137,19 +137,12 @@ static struct i2c_algo_bit_data parport_algo_data = {
|
||||
.setscl = parport_setscl,
|
||||
.getsda = parport_getsda,
|
||||
.getscl = parport_getscl,
|
||||
.udelay = 60,
|
||||
.udelay = 10, /* ~50 kbps */
|
||||
.timeout = HZ,
|
||||
};
|
||||
|
||||
/* ----- 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)
|
||||
{
|
||||
struct i2c_par *adapter;
|
||||
@ -169,10 +162,17 @@ static void i2c_parport_attach (struct parport *port)
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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.udelay = 50; /* ~10 kbps */
|
||||
}
|
||||
adapter->algo_data.data = port;
|
||||
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;
|
||||
prev = adapter, adapter = adapter->next) {
|
||||
if (adapter->pdev->port == port) {
|
||||
i2c_del_adapter(&adapter->adapter);
|
||||
|
||||
/* Un-init if needed (power off...) */
|
||||
if (adapter_parm[type].init.val)
|
||||
line_set(port, 0, &adapter_parm[type].init);
|
||||
|
||||
i2c_del_adapter(&adapter->adapter);
|
||||
parport_unregister_device(adapter->pdev);
|
||||
if (prev)
|
||||
prev->next = adapter->next;
|
||||
|
@ -358,7 +358,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
|
||||
}
|
||||
|
||||
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);
|
||||
smbus->adapter.class = I2C_CLASS_HWMON;
|
||||
smbus->adapter.algo = &smbus_algorithm;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/pci.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <linux/isa.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-pca.h>
|
||||
|
||||
@ -119,27 +120,26 @@ static struct i2c_adapter pca_isa_ops = {
|
||||
.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);
|
||||
|
||||
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")) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (irq > -1) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ static int __init pca_isa_init(void)
|
||||
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);
|
||||
|
||||
@ -163,6 +163,27 @@ static void pca_isa_exit(void)
|
||||
free_irq(irq, &pca_isa_ops);
|
||||
}
|
||||
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>");
|
||||
|
@ -428,7 +428,7 @@ static int __devinit piix4_probe(struct pci_dev *dev,
|
||||
/* set up the sysfs linkage to our parent device */
|
||||
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);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
@ -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.
|
||||
*/
|
||||
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.
|
||||
@ -825,7 +838,7 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
|
||||
};
|
||||
|
||||
static struct pxa_i2c i2c_pxa = {
|
||||
.lock = SPIN_LOCK_UNLOCKED,
|
||||
.lock = __SPIN_LOCK_UNLOCKED(i2c_pxa.lock),
|
||||
.adap = {
|
||||
.owner = THIS_MODULE,
|
||||
.algo = &i2c_pxa_algorithm,
|
||||
|
@ -61,6 +61,8 @@ struct s3c24xx_i2c {
|
||||
unsigned int msg_idx;
|
||||
unsigned int msg_ptr;
|
||||
|
||||
unsigned int tx_setup;
|
||||
|
||||
enum s3c24xx_i2c_state state;
|
||||
|
||||
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);
|
||||
writeb(addr, i2c->regs + S3C2410_IICDS);
|
||||
|
||||
// delay a bit and reset iiccon before setting start (per samsung)
|
||||
udelay(1);
|
||||
/* delay here to ensure the data byte has gotten onto the bus
|
||||
* before the transaction is started */
|
||||
|
||||
ndelay(i2c->tx_setup);
|
||||
|
||||
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
|
||||
writel(iiccon, i2c->regs + S3C2410_IICCON);
|
||||
|
||||
@ -322,7 +327,15 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
|
||||
if (!is_msgend(i2c)) {
|
||||
byte = i2c->msg->buf[i2c->msg_ptr++];
|
||||
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)) {
|
||||
/* we need to go to the next i2c message */
|
||||
|
||||
@ -570,9 +583,10 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
|
||||
};
|
||||
|
||||
static struct s3c24xx_i2c s3c24xx_i2c = {
|
||||
.lock = SPIN_LOCK_UNLOCKED,
|
||||
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
|
||||
.adap = {
|
||||
.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
|
||||
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
|
||||
.tx_setup = 50,
|
||||
.adap = {
|
||||
.name = "s3c2410-i2c",
|
||||
.owner = THIS_MODULE,
|
||||
.algo = &s3c24xx_i2c_algorithm,
|
||||
@ -731,26 +745,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
|
||||
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
|
||||
*
|
||||
* 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)) {
|
||||
dev_err(&pdev->dev, "cannot get clock\n");
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
goto err_noclk;
|
||||
}
|
||||
|
||||
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) {
|
||||
dev_err(&pdev->dev, "cannot find IO resource\n");
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
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) {
|
||||
dev_err(&pdev->dev, "cannot request IO\n");
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
goto err_clk;
|
||||
}
|
||||
|
||||
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) {
|
||||
dev_err(&pdev->dev, "cannot map IO\n");
|
||||
ret = -ENXIO;
|
||||
goto out;
|
||||
goto err_ioarea;
|
||||
}
|
||||
|
||||
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);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
goto err_iomap;
|
||||
|
||||
/* find the IRQ for this unit (note, this relies on the init call to
|
||||
* ensure no current IRQs pending
|
||||
@ -823,7 +817,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
if (res == NULL) {
|
||||
dev_err(&pdev->dev, "cannot find IRQ\n");
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
goto err_iomap;
|
||||
}
|
||||
|
||||
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) {
|
||||
dev_err(&pdev->dev, "cannot claim IRQ\n");
|
||||
goto out;
|
||||
goto err_iomap;
|
||||
}
|
||||
|
||||
i2c->irq = res;
|
||||
@ -841,17 +835,29 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
ret = i2c_add_adapter(&i2c->adap);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to add bus to i2c core\n");
|
||||
goto out;
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, i2c);
|
||||
|
||||
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
|
||||
return 0;
|
||||
|
||||
out:
|
||||
if (ret < 0)
|
||||
s3c24xx_i2c_free(i2c);
|
||||
err_irq:
|
||||
free_irq(i2c->irq->start, 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;
|
||||
}
|
||||
|
||||
@ -863,11 +869,17 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
|
||||
static int s3c24xx_i2c_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
|
||||
|
||||
if (i2c != NULL) {
|
||||
s3c24xx_i2c_free(i2c);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
||||
i2c_del_adapter(&i2c->adap);
|
||||
free_irq(i2c->irq->start, i2c);
|
||||
|
||||
clk_disable(i2c->clk);
|
||||
clk_put(i2c->clk);
|
||||
|
||||
iounmap(i2c->regs);
|
||||
|
||||
release_resource(i2c->ioarea);
|
||||
kfree(i2c->ioarea);
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
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 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
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->id = I2C_HW_SMBUS_SCX200;
|
||||
adapter->algo = &scx200_acb_algorithm;
|
||||
@ -599,6 +599,7 @@ static __init int scx200_scan_pci(void)
|
||||
else {
|
||||
int i;
|
||||
|
||||
pci_dev_put(pdev);
|
||||
for (i = 0; i < MAX_DEVICES; ++i) {
|
||||
if (base[i] == 0)
|
||||
continue;
|
||||
|
@ -3,11 +3,10 @@
|
||||
#
|
||||
|
||||
menu "Miscellaneous I2C Chip support"
|
||||
depends on I2C
|
||||
|
||||
config SENSORS_DS1337
|
||||
tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1337 and DS1339 real-time clock chips.
|
||||
@ -17,7 +16,7 @@ config SENSORS_DS1337
|
||||
|
||||
config SENSORS_DS1374
|
||||
tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1374 real-time clock chips.
|
||||
@ -27,7 +26,7 @@ config SENSORS_DS1374
|
||||
|
||||
config SENSORS_EEPROM
|
||||
tristate "EEPROM reader"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get read-only access to the EEPROM data
|
||||
available on modern memory DIMMs and Sony Vaio laptops. Such
|
||||
@ -38,7 +37,7 @@ config SENSORS_EEPROM
|
||||
|
||||
config SENSORS_PCF8574
|
||||
tristate "Philips PCF8574 and PCF8574A"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
default n
|
||||
help
|
||||
If you say yes here you get support for Philips PCF8574 and
|
||||
@ -52,7 +51,7 @@ config SENSORS_PCF8574
|
||||
|
||||
config SENSORS_PCA9539
|
||||
tristate "Philips PCA9539 16-bit I/O port"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for the Philips PCA9539
|
||||
16-bit I/O port.
|
||||
@ -62,7 +61,7 @@ config SENSORS_PCA9539
|
||||
|
||||
config SENSORS_PCF8591
|
||||
tristate "Philips PCF8591"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
default n
|
||||
help
|
||||
If you say yes here you get support for Philips PCF8591 chips.
|
||||
@ -75,7 +74,7 @@ config SENSORS_PCF8591
|
||||
|
||||
config ISP1301_OMAP
|
||||
tristate "Philips ISP1301 with OMAP OTG"
|
||||
depends on I2C && ARCH_OMAP_OTG
|
||||
depends on ARCH_OMAP_OTG
|
||||
help
|
||||
If you say yes here you get support for the Philips ISP1301
|
||||
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
|
||||
config TPS65010
|
||||
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
|
||||
help
|
||||
If you say yes here you get support for the TPS6501x series of
|
||||
@ -103,7 +102,7 @@ config TPS65010
|
||||
|
||||
config SENSORS_M41T00
|
||||
tristate "ST M41T00 RTC chip"
|
||||
depends on I2C && PPC32
|
||||
depends on PPC32
|
||||
help
|
||||
If you say yes here you get support for the ST M41T00 RTC chip.
|
||||
|
||||
@ -112,7 +111,7 @@ config SENSORS_M41T00
|
||||
|
||||
config SENSORS_MAX6875
|
||||
tristate "Maxim MAX6875 Power supply supervisor"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for the Maxim MAX6875
|
||||
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
|
||||
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[] = {{
|
||||
|
@ -183,7 +183,8 @@ int flexcop_i2c_init(struct flexcop_device *fc)
|
||||
mutex_init(&fc->i2c_mutex);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -19,7 +19,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
|
||||
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
|
||||
d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
|
||||
#else
|
||||
|
@ -105,9 +105,9 @@ struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enu
|
||||
}
|
||||
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->algo = algo;
|
||||
i2c_adap->algo_data = NULL;
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <media/tuner.h>
|
||||
#include <media/cx2341x.h>
|
||||
|
@ -15,6 +15,7 @@
|
||||
#ifndef __LINUX_OVCAMCHIP_PRIV_H
|
||||
#define __LINUX_OVCAMCHIP_PRIV_H
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <media/ovcamchip.h>
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <media/v4l2-dev.h>
|
||||
#include <media/tuner.h>
|
||||
#include "usbvision.h"
|
||||
|
@ -104,7 +104,8 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
|
||||
|
||||
chan->dinfo = dinfo;
|
||||
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.id = I2C_HW_B_INTELFB;
|
||||
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.clock = clock;
|
||||
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);
|
||||
i2c_set_adapdata(&b->adapter, b);
|
||||
b->adapter.algo_data = &b->bac;
|
||||
|
@ -38,11 +38,14 @@ struct i2c_algo_bit_data {
|
||||
int (*getscl) (void *data);
|
||||
|
||||
/* local settings */
|
||||
int udelay; /* half-clock-cycle time in microsecs */
|
||||
/* i.e. clock is (500 / udelay) KHz */
|
||||
int udelay; /* half clock cycle time in us,
|
||||
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 i2c_bit_add_bus(struct i2c_adapter *);
|
||||
int i2c_bit_add_numbered_bus(struct i2c_adapter *);
|
||||
|
||||
#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 */
|
||||
#define I2C_HW_MPC107 0x0d0000
|
||||
|
||||
/* --- Marvell mv64xxx i2c adapter */
|
||||
/* --- Embedded adapters */
|
||||
#define I2C_HW_MV64XXX 0x190000
|
||||
#define I2C_HW_BLACKFIN 0x190001 /* ADI Blackfin I2C TWI driver */
|
||||
|
||||
/* --- Miscellaneous adapters */
|
||||
#define I2C_HW_SAA7146 0x060000 /* SAA7146 video decoder bus */
|
||||
|
@ -35,11 +35,6 @@
|
||||
#include <linux/sched.h> /* for completion */
|
||||
#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;
|
||||
|
||||
/* --- 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_write_word_data(struct i2c_client * client,
|
||||
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,
|
||||
u8 command, u8 length,
|
||||
const u8 *values);
|
||||
@ -114,7 +112,7 @@ struct i2c_driver {
|
||||
* 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
|
||||
* 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 (*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
|
||||
* the chance to remove its private data. Also, if the client struct
|
||||
* 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 *);
|
||||
|
||||
/* 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 */
|
||||
void (*shutdown)(struct i2c_client *);
|
||||
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 I2C_NAME_SIZE 50
|
||||
#define I2C_NAME_SIZE 20
|
||||
|
||||
/*
|
||||
* i2c_client identifies a single device (i.e. chip) that is connected to an
|
||||
* i2c bus. The behaviour is defined by the routines of the driver. This
|
||||
* function is mainly used for lookup & other admin. functions.
|
||||
/**
|
||||
* struct i2c_client - represent an I2C slave device
|
||||
* @addr: Address used on the I2C bus connected to the parent adapter.
|
||||
* @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 {
|
||||
unsigned int flags; /* div., see below */
|
||||
unsigned short flags; /* div., see below */
|
||||
unsigned short addr; /* chip address - NOTE: 7bit */
|
||||
/* addresses are stored in the */
|
||||
/* _LOWER_ 7 bits */
|
||||
char name[I2C_NAME_SIZE];
|
||||
struct i2c_adapter *adapter; /* the adapter we sit on */
|
||||
struct i2c_driver *driver; /* and our access routines */
|
||||
int usage_count; /* How many accesses currently */
|
||||
/* to the client */
|
||||
struct device dev; /* the device structure */
|
||||
int irq; /* irq issued by device (or -1) */
|
||||
char driver_name[KOBJ_NAME_LEN];
|
||||
struct list_head list;
|
||||
char name[I2C_NAME_SIZE];
|
||||
struct completion released;
|
||||
};
|
||||
#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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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:
|
||||
* i2c_algorithm is the interface to a class of hardware solutions which can
|
||||
@ -228,17 +312,14 @@ struct i2c_adapter {
|
||||
int timeout;
|
||||
int retries;
|
||||
struct device dev; /* the adapter device */
|
||||
struct class_device class_dev; /* the class device */
|
||||
|
||||
int nr;
|
||||
struct list_head clients;
|
||||
struct list_head list;
|
||||
char name[I2C_NAME_SIZE];
|
||||
char name[48];
|
||||
struct completion dev_released;
|
||||
struct completion class_dev_released;
|
||||
};
|
||||
#define dev_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)
|
||||
#define to_i2c_adapter(d) container_of(d, 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_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_del_driver(struct i2c_driver *);
|
||||
extern void i2c_del_driver(struct i2c_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_IGNORE_NAK 0x1000
|
||||
#define I2C_M_NO_RD_ACK 0x0800
|
||||
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
|
||||
__u16 len; /* msg length */
|
||||
__u8 *buf; /* pointer to msg data */
|
||||
};
|
||||
|
@ -1213,11 +1213,13 @@
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6
|
||||
#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_NVENET_18 0x03EE
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF
|
||||
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6
|
||||
#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_NVENET_20 0x0450
|
||||
#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
#include <linux/videodev.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
/* --------------------------------- */
|
||||
/* ENUMERATIONS */
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define _TUNER_H
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <media/tuner-types.h>
|
||||
|
||||
extern int tuner_debug;
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef _TAS_IOCTL_H_
|
||||
#define _TAS_IOCTL_H_
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/soundcard.h>
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user