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:
Linus Torvalds 2007-05-04 17:46:27 -07:00
commit 8d41f0e8d5
61 changed files with 2911 additions and 902 deletions

View file

@ -190,18 +190,10 @@ Who: Jean Delvare <khali@linux-fr.org>
--------------------------- ---------------------------
What: i2c_adapter.dev What: i2c_adapter.list
i2c_adapter.list
When: July 2007 When: July 2007
Why: Superfluous, given i2c_adapter.class_dev: Why: Superfluous, this list duplicates the one maintained by the driver
* The "dev" was a stand-in for the physical device node that legacy core.
drivers would not have; but now it's almost always present. Any
remaining legacy drivers must upgrade (they now trigger warnings).
* The "list" duplicates class device children.
The delay in removing this is so upgraded lm_sensors and libsensors
can get deployed. (Removal causes minor changes in the sysfs layout,
notably the location of the adapter type name and parenting the i2c
client hardware directly from their controller.)
Who: Jean Delvare <khali@linux-fr.org>, Who: Jean Delvare <khali@linux-fr.org>,
David Brownell <dbrownell@users.sourceforge.net> David Brownell <dbrownell@users.sourceforge.net>
@ -331,3 +323,10 @@ Who: Cornelia Huck <cornelia.huck@de.ibm.com>
--------------------------- ---------------------------
What: i2c-ixp2000, i2c-ixp4xx and scx200_i2c drivers
When: September 2007
Why: Obsolete. The new i2c-gpio driver replaces all hardware-specific
I2C-over-GPIO drivers.
Who: Jean Delvare <khali@linux-fr.org>
---------------------------

View file

@ -9,6 +9,8 @@ Supported adapters:
* nForce4 MCP-04 10de:0034 * nForce4 MCP-04 10de:0034
* nForce4 MCP51 10de:0264 * nForce4 MCP51 10de:0264
* nForce4 MCP55 10de:0368 * nForce4 MCP55 10de:0368
* nForce4 MCP61 10de:03EB
* nForce4 MCP65 10de:0446
Datasheet: not publicly available, but seems to be similar to the Datasheet: not publicly available, but seems to be similar to the
AMD-8111 SMBus 2.0 adapter. AMD-8111 SMBus 2.0 adapter.

View file

@ -1,4 +1,4 @@
Revision 6, 2005-11-20 Revision 7, 2007-04-19
Jean Delvare <khali@linux-fr.org> Jean Delvare <khali@linux-fr.org>
Greg KH <greg@kroah.com> Greg KH <greg@kroah.com>
@ -20,6 +20,10 @@ yours for best results.
Technical changes: Technical changes:
* [Driver type] Any driver that was relying on i2c-isa has to be
converted to a proper isa, platform or pci driver. This is not
covered by this guide.
* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>. * [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
Includes typically look like that: Includes typically look like that:
#include <linux/module.h> #include <linux/module.h>
@ -27,12 +31,10 @@ Technical changes:
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-isa.h> /* for ISA drivers */
#include <linux/hwmon.h> /* for hardware monitoring drivers */ #include <linux/hwmon.h> /* for hardware monitoring drivers */
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h> /* if you need VRM support */ #include <linux/hwmon-vid.h> /* if you need VRM support */
#include <linux/err.h> /* for class registration */ #include <linux/err.h> /* for class registration */
#include <asm/io.h> /* if you have I/O operations */
Please respect this inclusion order. Some extra headers may be Please respect this inclusion order. Some extra headers may be
required for a given driver (e.g. "lm75.h"). required for a given driver (e.g. "lm75.h").
@ -69,20 +71,16 @@ Technical changes:
sensors mailing list <lm-sensors@lm-sensors.org> by providing a sensors mailing list <lm-sensors@lm-sensors.org> by providing a
patch to the Documentation/hwmon/sysfs-interface file. patch to the Documentation/hwmon/sysfs-interface file.
* [Attach] For I2C drivers, the attach function should make sure * [Attach] The attach function should make sure that the adapter's
that the adapter's class has I2C_CLASS_HWMON (or whatever class is class has I2C_CLASS_HWMON (or whatever class is suitable for your
suitable for your driver), using the following construct: driver), using the following construct:
if (!(adapter->class & I2C_CLASS_HWMON)) if (!(adapter->class & I2C_CLASS_HWMON))
return 0; return 0;
ISA-only drivers of course don't need this.
Call i2c_probe() instead of i2c_detect(). Call i2c_probe() instead of i2c_detect().
* [Detect] As mentioned earlier, the flags parameter is gone. * [Detect] As mentioned earlier, the flags parameter is gone.
The type_name and client_name strings are replaced by a single The type_name and client_name strings are replaced by a single
name string, which will be filled with a lowercase, short string. name string, which will be filled with a lowercase, short string.
In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
useless. Same for isa-only drivers, as the test would always be
true. Only hybrid drivers (which are quite rare) still need it.
The labels used for error paths are reduced to the number needed. The labels used for error paths are reduced to the number needed.
It is advised that the labels are given descriptive names such as It is advised that the labels are given descriptive names such as
exit and exit_free. Don't forget to properly set err before exit and exit_free. Don't forget to properly set err before

View file

@ -4,17 +4,23 @@ I2C and SMBus
============= =============
I2C (pronounce: I squared C) is a protocol developed by Philips. It is a I2C (pronounce: I squared C) is a protocol developed by Philips. It is a
slow two-wire protocol (10-400 kHz), but it suffices for many types of slow two-wire protocol (variable speed, up to 400 kHz), with a high speed
devices. extension (3.4 MHz). It provides an inexpensive bus for connecting many
types of devices with infrequent or low bandwidth communications needs.
I2C is widely used with embedded systems. Some systems use variants that
don't meet branding requirements, and so are not advertised as being I2C.
SMBus (System Management Bus) is a subset of the I2C protocol. Many SMBus (System Management Bus) is based on the I2C protocol, and is mostly
modern mainboards have a System Management Bus. There are a lot of a subset of I2C protocols and signaling. Many I2C devices will work on an
devices which can be connected to a SMBus; the most notable are modern SMBus, but some SMBus protocols add semantics beyond what is required to
memory chips with EEPROM memories and chips for hardware monitoring. achieve I2C branding. Modern PC mainboards rely on SMBus. The most common
devices connected through SMBus are RAM modules configured using I2C EEPROMs,
and hardware monitoring chips.
Because the SMBus is just a special case of the generalized I2C bus, we Because the SMBus is mostly a subset of the generalized I2C bus, we can
can simulate the SMBus protocol on plain I2C busses. The reverse is use its protocols on many I2C systems. However, there are systems that don't
regretfully impossible. meet both SMBus and I2C electrical constraints; and others which can't
implement all the common SMBus protocol semantics or messages.
Terminology Terminology
@ -29,6 +35,7 @@ When we talk about I2C, we use the following terms:
An Algorithm driver contains general code that can be used for a whole class An Algorithm driver contains general code that can be used for a whole class
of I2C adapters. Each specific adapter driver depends on one algorithm of I2C adapters. Each specific adapter driver depends on one algorithm
driver. driver.
A Driver driver (yes, this sounds ridiculous, sorry) contains the general A Driver driver (yes, this sounds ridiculous, sorry) contains the general
code to access some type of device. Each detected device gets its own code to access some type of device. Each detected device gets its own
data in the Client structure. Usually, Driver and Client are more closely data in the Client structure. Usually, Driver and Client are more closely
@ -40,6 +47,10 @@ a separate Adapter and Algorithm driver), and drivers for your I2C devices
in this package. See the lm_sensors project http://www.lm-sensors.nu in this package. See the lm_sensors project http://www.lm-sensors.nu
for device drivers. for device drivers.
At this time, Linux only operates I2C (or SMBus) in master mode; you can't
use these APIs to make a Linux system behave as a slave/device, either to
speak a custom protocol or to emulate some other device.
Included Bus Drivers Included Bus Drivers
==================== ====================

View file

@ -1,5 +1,5 @@
This is a small guide for those who want to write kernel drivers for I2C This is a small guide for those who want to write kernel drivers for I2C
or SMBus devices. or SMBus devices, using Linux as the protocol host/master (not slave).
To set up a driver, you need to do several things. Some are optional, and To set up a driver, you need to do several things. Some are optional, and
some things can be done slightly or completely different. Use this as a some things can be done slightly or completely different. Use this as a
@ -29,8 +29,16 @@ static struct i2c_driver foo_driver = {
.driver = { .driver = {
.name = "foo", .name = "foo",
}, },
/* iff driver uses driver model ("new style") binding model: */
.probe = foo_probe,
.remove = foo_remove,
/* else, driver uses "legacy" binding model: */
.attach_adapter = foo_attach_adapter, .attach_adapter = foo_attach_adapter,
.detach_client = foo_detach_client, .detach_client = foo_detach_client,
/* these may be used regardless of the driver binding model */
.shutdown = foo_shutdown, /* optional */ .shutdown = foo_shutdown, /* optional */
.suspend = foo_suspend, /* optional */ .suspend = foo_suspend, /* optional */
.resume = foo_resume, /* optional */ .resume = foo_resume, /* optional */
@ -40,7 +48,8 @@ static struct i2c_driver foo_driver = {
The name field is the driver name, and must not contain spaces. It The name field is the driver name, and must not contain spaces. It
should match the module name (if the driver can be compiled as a module), should match the module name (if the driver can be compiled as a module),
although you can use MODULE_ALIAS (passing "foo" in this example) to add although you can use MODULE_ALIAS (passing "foo" in this example) to add
another name for the module. another name for the module. If the driver name doesn't match the module
name, the module won't be automatically loaded (hotplug/coldplug).
All other fields are for call-back functions which will be explained All other fields are for call-back functions which will be explained
below. below.
@ -65,16 +74,13 @@ An example structure is below.
struct foo_data { struct foo_data {
struct i2c_client client; struct i2c_client client;
struct semaphore lock; /* For ISA access in `sensors' drivers. */
int sysctl_id; /* To keep the /proc directory entry for
`sensors' drivers. */
enum chips type; /* To keep the chips type for `sensors' drivers. */ enum chips type; /* To keep the chips type for `sensors' drivers. */
/* Because the i2c bus is slow, it is often useful to cache the read /* Because the i2c bus is slow, it is often useful to cache the read
information of a chip for some time (for example, 1 or 2 seconds). information of a chip for some time (for example, 1 or 2 seconds).
It depends of course on the device whether this is really worthwhile It depends of course on the device whether this is really worthwhile
or even sensible. */ or even sensible. */
struct semaphore update_lock; /* When we are reading lots of information, struct mutex update_lock; /* When we are reading lots of information,
another process should not update the another process should not update the
below information */ below information */
char valid; /* != 0 if the following fields are valid. */ char valid; /* != 0 if the following fields are valid. */
@ -95,8 +101,7 @@ some obscure clients). But we need generic reading and writing routines.
I have found it useful to define foo_read and foo_write function for this. I have found it useful to define foo_read and foo_write function for this.
For some cases, it will be easier to call the i2c functions directly, For some cases, it will be easier to call the i2c functions directly,
but many chips have some kind of register-value idea that can easily but many chips have some kind of register-value idea that can easily
be encapsulated. Also, some chips have both ISA and I2C interfaces, and be encapsulated.
it useful to abstract from this (only for `sensors' drivers).
The below functions are simple examples, and should not be copied The below functions are simple examples, and should not be copied
literally. literally.
@ -119,28 +124,101 @@ literally.
return i2c_smbus_write_word_data(client,reg,value); return i2c_smbus_write_word_data(client,reg,value);
} }
For sensors code, you may have to cope with ISA registers too. Something
like the below often works. Note the locking!
int foo_read_value(struct i2c_client *client, u8 reg)
{
int res;
if (i2c_is_isa_client(client)) {
down(&(((struct foo_data *) (client->data)) -> lock));
outb_p(reg,client->addr + FOO_ADDR_REG_OFFSET);
res = inb_p(client->addr + FOO_DATA_REG_OFFSET);
up(&(((struct foo_data *) (client->data)) -> lock));
return res;
} else
return i2c_smbus_read_byte_data(client,reg);
}
Writing is done the same way.
Probing and attaching Probing and attaching
===================== =====================
The Linux I2C stack was originally written to support access to hardware
monitoring chips on PC motherboards, and thus it embeds some assumptions
that are more appropriate to SMBus (and PCs) than to I2C. One of these
assumptions is that most adapters and devices drivers support the SMBUS_QUICK
protocol to probe device presence. Another is that devices and their drivers
can be sufficiently configured using only such probe primitives.
As Linux and its I2C stack became more widely used in embedded systems
and complex components such as DVB adapters, those assumptions became more
problematic. Drivers for I2C devices that issue interrupts need more (and
different) configuration information, as do drivers handling chip variants
that can't be distinguished by protocol probing, or which need some board
specific information to operate correctly.
Accordingly, the I2C stack now has two models for associating I2C devices
with their drivers: the original "legacy" model, and a newer one that's
fully compatible with the Linux 2.6 driver model. These models do not mix,
since the "legacy" model requires drivers to create "i2c_client" device
objects after SMBus style probing, while the Linux driver model expects
drivers to be given such device objects in their probe() routines.
Standard Driver Model Binding ("New Style")
-------------------------------------------
System infrastructure, typically board-specific initialization code or
boot firmware, reports what I2C devices exist. For example, there may be
a table, in the kernel or from the boot loader, identifying I2C devices
and linking them to board-specific configuration information about IRQs
and other wiring artifacts, chip type, and so on. That could be used to
create i2c_client objects for each I2C device.
I2C device drivers using this binding model work just like any other
kind of driver in Linux: they provide a probe() method to bind to
those devices, and a remove() method to unbind.
static int foo_probe(struct i2c_client *client);
static int foo_remove(struct i2c_client *client);
Remember that the i2c_driver does not create those client handles. The
handle may be used during foo_probe(). If foo_probe() reports success
(zero not a negative status code) it may save the handle and use it until
foo_remove() returns. That binding model is used by most Linux drivers.
Drivers match devices when i2c_client.driver_name and the driver name are
the same; this approach is used in several other busses that don't have
device typing support in the hardware. The driver and module name should
match, so hotplug/coldplug mechanisms will modprobe the driver.
Device Creation (Standard driver model)
---------------------------------------
If you know for a fact that an I2C device is connected to a given I2C bus,
you can instantiate that device by simply filling an i2c_board_info
structure with the device address and driver name, and calling
i2c_new_device(). This will create the device, then the driver core will
take care of finding the right driver and will call its probe() method.
If a driver supports different device types, you can specify the type you
want using the type field. You can also specify an IRQ and platform data
if needed.
Sometimes you know that a device is connected to a given I2C bus, but you
don't know the exact address it uses. This happens on TV adapters for
example, where the same driver supports dozens of slightly different
models, and I2C device addresses change from one model to the next. In
that case, you can use the i2c_new_probed_device() variant, which is
similar to i2c_new_device(), except that it takes an additional list of
possible I2C addresses to probe. A device is created for the first
responsive address in the list. If you expect more than one device to be
present in the address range, simply call i2c_new_probed_device() that
many times.
The call to i2c_new_device() or i2c_new_probed_device() typically happens
in the I2C bus driver. You may want to save the returned i2c_client
reference for later use.
Device Deletion (Standard driver model)
---------------------------------------
Each I2C device which has been created using i2c_new_device() or
i2c_new_probed_device() can be unregistered by calling
i2c_unregister_device(). If you don't call it explicitly, it will be
called automatically before the underlying I2C bus itself is removed, as a
device can't survive its parent in the device driver model.
Legacy Driver Binding Model
---------------------------
Most i2c devices can be present on several i2c addresses; for some this Most i2c devices can be present on several i2c addresses; for some this
is determined in hardware (by soldering some chip pins to Vcc or Ground), is determined in hardware (by soldering some chip pins to Vcc or Ground),
for others this can be changed in software (by writing to specific client for others this can be changed in software (by writing to specific client
@ -157,13 +235,9 @@ detection algorithm.
You do not have to use this parameter interface; but don't try to use You do not have to use this parameter interface; but don't try to use
function i2c_probe() if you don't. function i2c_probe() if you don't.
NOTE: If you want to write a `sensors' driver, the interface is slightly
different! See below.
Probing classes (Legacy model)
------------------------------
Probing classes
---------------
All parameters are given as lists of unsigned 16-bit integers. Lists are All parameters are given as lists of unsigned 16-bit integers. Lists are
terminated by I2C_CLIENT_END. terminated by I2C_CLIENT_END.
@ -210,8 +284,8 @@ Note that you *have* to call the defined variable `normal_i2c',
without any prefix! without any prefix!
Attaching to an adapter Attaching to an adapter (Legacy model)
----------------------- --------------------------------------
Whenever a new adapter is inserted, or for all adapters if the driver is Whenever a new adapter is inserted, or for all adapters if the driver is
being registered, the callback attach_adapter() is called. Now is the being registered, the callback attach_adapter() is called. Now is the
@ -237,17 +311,13 @@ them (unless a `force' parameter was used). In addition, addresses that
are already in use (by some other registered client) are skipped. are already in use (by some other registered client) are skipped.
The detect client function The detect client function (Legacy model)
-------------------------- -----------------------------------------
The detect client function is called by i2c_probe. The `kind' parameter The detect client function is called by i2c_probe. The `kind' parameter
contains -1 for a probed detection, 0 for a forced detection, or a positive contains -1 for a probed detection, 0 for a forced detection, or a positive
number for a forced detection with a chip type forced. number for a forced detection with a chip type forced.
Below, some things are only needed if this is a `sensors' driver. Those
parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
markers.
Returning an error different from -ENODEV in a detect function will cause Returning an error different from -ENODEV in a detect function will cause
the detection to stop: other addresses and adapters won't be scanned. the detection to stop: other addresses and adapters won't be scanned.
This should only be done on fatal or internal errors, such as a memory This should only be done on fatal or internal errors, such as a memory
@ -256,64 +326,20 @@ shortage or i2c_attach_client failing.
For now, you can ignore the `flags' parameter. It is there for future use. For now, you can ignore the `flags' parameter. It is there for future use.
int foo_detect_client(struct i2c_adapter *adapter, int address, int foo_detect_client(struct i2c_adapter *adapter, int address,
unsigned short flags, int kind) int kind)
{ {
int err = 0; int err = 0;
int i; int i;
struct i2c_client *new_client; struct i2c_client *client;
struct foo_data *data; struct foo_data *data;
const char *client_name = ""; /* For non-`sensors' drivers, put the real const char *name = "";
name here! */
/* Let's see whether this adapter can support what we need. /* Let's see whether this adapter can support what we need.
Please substitute the things you need here! Please substitute the things you need here! */
For `sensors' drivers, add `! is_isa &&' to the if statement */
if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA | if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_WRITE_BYTE)) I2C_FUNC_SMBUS_WRITE_BYTE))
goto ERROR0; goto ERROR0;
/* SENSORS ONLY START */
const char *type_name = "";
int is_isa = i2c_is_isa_adapter(adapter);
/* Do this only if the chip can additionally be found on the ISA bus
(hybrid chip). */
if (is_isa) {
/* Discard immediately if this ISA range is already used */
/* FIXME: never use check_region(), only request_region() */
if (check_region(address,FOO_EXTENT))
goto ERROR0;
/* Probe whether there is anything on this address.
Some example code is below, but you will have to adapt this
for your own driver */
if (kind < 0) /* Only if no force parameter was used */ {
/* We may need long timeouts at least for some chips. */
#define REALLY_SLOW_IO
i = inb_p(address + 1);
if (inb_p(address + 2) != i)
goto ERROR0;
if (inb_p(address + 3) != i)
goto ERROR0;
if (inb_p(address + 7) != i)
goto ERROR0;
#undef REALLY_SLOW_IO
/* Let's just hope nothing breaks here */
i = inb_p(address + 5) & 0x7f;
outb_p(~i & 0x7f,address+5);
if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
outb_p(i,address+5);
return 0;
}
}
}
/* SENSORS ONLY END */
/* OK. For now, we presume we have a valid client. We now create the /* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. client structure, even though we cannot fill it completely yet.
But it allows us to access several i2c functions safely */ But it allows us to access several i2c functions safely */
@ -323,13 +349,12 @@ For now, you can ignore the `flags' parameter. It is there for future use.
goto ERROR0; goto ERROR0;
} }
new_client = &data->client; client = &data->client;
i2c_set_clientdata(new_client, data); i2c_set_clientdata(client, data);
new_client->addr = address; client->addr = address;
new_client->adapter = adapter; client->adapter = adapter;
new_client->driver = &foo_driver; client->driver = &foo_driver;
new_client->flags = 0;
/* Now, we do the remaining detection. If no `force' parameter is used. */ /* Now, we do the remaining detection. If no `force' parameter is used. */
@ -337,19 +362,17 @@ For now, you can ignore the `flags' parameter. It is there for future use.
parameter was used. */ parameter was used. */
if (kind < 0) { if (kind < 0) {
/* The below is of course bogus */ /* The below is of course bogus */
if (foo_read(new_client,FOO_REG_GENERIC) != FOO_GENERIC_VALUE) if (foo_read(client, FOO_REG_GENERIC) != FOO_GENERIC_VALUE)
goto ERROR1; goto ERROR1;
} }
/* SENSORS ONLY START */
/* Next, specific detection. This is especially important for `sensors' /* Next, specific detection. This is especially important for `sensors'
devices. */ devices. */
/* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter /* Determine the chip type. Not needed if a `force_CHIPTYPE' parameter
was used. */ was used. */
if (kind <= 0) { if (kind <= 0) {
i = foo_read(new_client,FOO_REG_CHIPTYPE); i = foo_read(client, FOO_REG_CHIPTYPE);
if (i == FOO_TYPE_1) if (i == FOO_TYPE_1)
kind = chip1; /* As defined in the enum */ kind = chip1; /* As defined in the enum */
else if (i == FOO_TYPE_2) else if (i == FOO_TYPE_2)
@ -363,63 +386,31 @@ For now, you can ignore the `flags' parameter. It is there for future use.
/* Now set the type and chip names */ /* Now set the type and chip names */
if (kind == chip1) { if (kind == chip1) {
type_name = "chip1"; /* For /proc entry */ name = "chip1";
client_name = "CHIP 1";
} else if (kind == chip2) { } else if (kind == chip2) {
type_name = "chip2"; /* For /proc entry */ name = "chip2";
client_name = "CHIP 2";
} }
/* Reserve the ISA region */
if (is_isa)
request_region(address,FOO_EXTENT,type_name);
/* SENSORS ONLY END */
/* Fill in the remaining client fields. */ /* Fill in the remaining client fields. */
strcpy(new_client->name,client_name); strlcpy(client->name, name, I2C_NAME_SIZE);
/* SENSORS ONLY BEGIN */
data->type = kind; data->type = kind;
/* SENSORS ONLY END */ mutex_init(&data->update_lock); /* Only if you use this field */
data->valid = 0; /* Only if you use this field */
init_MUTEX(&data->update_lock); /* Only if you use this field */
/* Any other initializations in data must be done here too. */ /* Any other initializations in data must be done here too. */
/* Tell the i2c layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto ERROR3;
/* SENSORS ONLY BEGIN */
/* Register a new directory entry with module sensors. See below for
the `template' structure. */
if ((i = i2c_register_entry(new_client, type_name,
foo_dir_table_template,THIS_MODULE)) < 0) {
err = i;
goto ERROR4;
}
data->sysctl_id = i;
/* SENSORS ONLY END */
/* This function can write default values to the client registers, if /* This function can write default values to the client registers, if
needed. */ needed. */
foo_init_client(new_client); foo_init_client(client);
/* Tell the i2c layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto ERROR1;
return 0; return 0;
/* OK, this is not exactly good programming practice, usually. But it is /* OK, this is not exactly good programming practice, usually. But it is
very code-efficient in this case. */ very code-efficient in this case. */
ERROR4:
i2c_detach_client(new_client);
ERROR3:
ERROR2:
/* SENSORS ONLY START */
if (is_isa)
release_region(address,FOO_EXTENT);
/* SENSORS ONLY END */
ERROR1: ERROR1:
kfree(data); kfree(data);
ERROR0: ERROR0:
@ -427,8 +418,8 @@ For now, you can ignore the `flags' parameter. It is there for future use.
} }
Removing the client Removing the client (Legacy model)
=================== ==================================
The detach_client call back function is called when a client should be The detach_client call back function is called when a client should be
removed. It may actually fail, but only when panicking. This code is removed. It may actually fail, but only when panicking. This code is
@ -436,22 +427,12 @@ much simpler than the attachment code, fortunately!
int foo_detach_client(struct i2c_client *client) int foo_detach_client(struct i2c_client *client)
{ {
int err,i; int err;
/* SENSORS ONLY START */
/* Deregister with the `i2c-proc' module. */
i2c_deregister_entry(((struct lm78_data *)(client->data))->sysctl_id);
/* SENSORS ONLY END */
/* Try to detach the client from i2c space */ /* Try to detach the client from i2c space */
if ((err = i2c_detach_client(client))) if ((err = i2c_detach_client(client)))
return err; return err;
/* HYBRID SENSORS CHIP ONLY START */
if i2c_is_isa_client(client)
release_region(client->addr,LM78_EXTENT);
/* HYBRID SENSORS CHIP ONLY END */
kfree(i2c_get_clientdata(client)); kfree(i2c_get_clientdata(client));
return 0; return 0;
} }
@ -464,45 +445,34 @@ When the kernel is booted, or when your foo driver module is inserted,
you have to do some initializing. Fortunately, just attaching (registering) you have to do some initializing. Fortunately, just attaching (registering)
the driver module is usually enough. the driver module is usually enough.
/* Keep track of how far we got in the initialization process. If several
things have to initialized, and we fail halfway, only those things
have to be cleaned up! */
static int __initdata foo_initialized = 0;
static int __init foo_init(void) static int __init foo_init(void)
{ {
int res; int res;
printk("foo version %s (%s)\n",FOO_VERSION,FOO_DATE);
if ((res = i2c_add_driver(&foo_driver))) { if ((res = i2c_add_driver(&foo_driver))) {
printk("foo: Driver registration failed, module not inserted.\n"); printk("foo: Driver registration failed, module not inserted.\n");
foo_cleanup();
return res; return res;
} }
foo_initialized ++;
return 0; return 0;
} }
void foo_cleanup(void) static void __exit foo_cleanup(void)
{ {
if (foo_initialized == 1) { i2c_del_driver(&foo_driver);
if ((res = i2c_del_driver(&foo_driver))) {
printk("foo: Driver registration failed, module not removed.\n");
return;
}
foo_initialized --;
}
} }
/* Substitute your own name and email address */ /* Substitute your own name and email address */
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>" MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"
MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices"); MODULE_DESCRIPTION("Driver for Barf Inc. Foo I2C devices");
/* a few non-GPL license types are also allowed */
MODULE_LICENSE("GPL");
module_init(foo_init); module_init(foo_init);
module_exit(foo_cleanup); module_exit(foo_cleanup);
Note that some functions are marked by `__init', and some data structures Note that some functions are marked by `__init', and some data structures
by `__init_data'. Hose functions and structures can be removed after by `__initdata'. These functions and structures can be removed after
kernel booting (or module loading) is completed. kernel booting (or module loading) is completed.
@ -632,110 +602,7 @@ General purpose routines
Below all general purpose routines are listed, that were not mentioned Below all general purpose routines are listed, that were not mentioned
before. before.
/* This call returns a unique low identifier for each registered adapter, /* This call returns a unique low identifier for each registered adapter.
* or -1 if the adapter was not registered.
*/ */
extern int i2c_adapter_id(struct i2c_adapter *adap); extern int i2c_adapter_id(struct i2c_adapter *adap);
The sensors sysctl/proc interface
=================================
This section only applies if you write `sensors' drivers.
Each sensors driver creates a directory in /proc/sys/dev/sensors for each
registered client. The directory is called something like foo-i2c-4-65.
The sensors module helps you to do this as easily as possible.
The template
------------
You will need to define a ctl_table template. This template will automatically
be copied to a newly allocated structure and filled in where necessary when
you call sensors_register_entry.
First, I will give an example definition.
static ctl_table foo_dir_table_template[] = {
{ FOO_SYSCTL_FUNC1, "func1", NULL, 0, 0644, NULL, &i2c_proc_real,
&i2c_sysctl_real,NULL,&foo_func },
{ FOO_SYSCTL_FUNC2, "func2", NULL, 0, 0644, NULL, &i2c_proc_real,
&i2c_sysctl_real,NULL,&foo_func },
{ FOO_SYSCTL_DATA, "data", NULL, 0, 0644, NULL, &i2c_proc_real,
&i2c_sysctl_real,NULL,&foo_data },
{ 0 }
};
In the above example, three entries are defined. They can either be
accessed through the /proc interface, in the /proc/sys/dev/sensors/*
directories, as files named func1, func2 and data, or alternatively
through the sysctl interface, in the appropriate table, with identifiers
FOO_SYSCTL_FUNC1, FOO_SYSCTL_FUNC2 and FOO_SYSCTL_DATA.
The third, sixth and ninth parameters should always be NULL, and the
fourth should always be 0. The fifth is the mode of the /proc file;
0644 is safe, as the file will be owned by root:root.
The seventh and eighth parameters should be &i2c_proc_real and
&i2c_sysctl_real if you want to export lists of reals (scaled
integers). You can also use your own function for them, as usual.
Finally, the last parameter is the call-back to gather the data
(see below) if you use the *_proc_real functions.
Gathering the data
------------------
The call back functions (foo_func and foo_data in the above example)
can be called in several ways; the operation parameter determines
what should be done:
* If operation == SENSORS_PROC_REAL_INFO, you must return the
magnitude (scaling) in nrels_mag;
* If operation == SENSORS_PROC_REAL_READ, you must read information
from the chip and return it in results. The number of integers
to display should be put in nrels_mag;
* If operation == SENSORS_PROC_REAL_WRITE, you must write the
supplied information to the chip. nrels_mag will contain the number
of integers, results the integers themselves.
The *_proc_real functions will display the elements as reals for the
/proc interface. If you set the magnitude to 2, and supply 345 for
SENSORS_PROC_REAL_READ, it would display 3.45; and if the user would
write 45.6 to the /proc file, it would be returned as 4560 for
SENSORS_PROC_REAL_WRITE. A magnitude may even be negative!
An example function:
/* FOO_FROM_REG and FOO_TO_REG translate between scaled values and
register values. Note the use of the read cache. */
void foo_in(struct i2c_client *client, int operation, int ctl_name,
int *nrels_mag, long *results)
{
struct foo_data *data = client->data;
int nr = ctl_name - FOO_SYSCTL_FUNC1; /* reduce to 0 upwards */
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 2;
else if (operation == SENSORS_PROC_REAL_READ) {
/* Update the readings cache (if necessary) */
foo_update_client(client);
/* Get the readings from the cache */
results[0] = FOO_FROM_REG(data->foo_func_base[nr]);
results[1] = FOO_FROM_REG(data->foo_func_more[nr]);
results[2] = FOO_FROM_REG(data->foo_func_readonly[nr]);
*nrels_mag = 2;
} else if (operation == SENSORS_PROC_REAL_WRITE) {
if (*nrels_mag >= 1) {
/* Update the cache */
data->foo_base[nr] = FOO_TO_REG(results[0]);
/* Update the chip */
foo_write_value(client,FOO_REG_FUNC_BASE(nr),data->foo_base[nr]);
}
if (*nrels_mag >= 2) {
/* Update the cache */
data->foo_more[nr] = FOO_TO_REG(results[1]);
/* Update the chip */
foo_write_value(client,FOO_REG_FUNC_MORE(nr),data->foo_more[nr]);
}
}
}

View file

@ -733,6 +733,13 @@ M: tigran@aivazian.fsnet.co.uk
L: linux-kernel@vger.kernel.org L: linux-kernel@vger.kernel.org
S: Maintained S: Maintained
BLACKFIN I2C TWI DRIVER
P: Sonic Zhang
M: sonic.zhang@analog.com
L: uclinux-dist-devel@blackfin.uclinux.org (subscribers-only)
W: http://blackfin.uclinux.org/
S: Supported
BLOCK LAYER BLOCK LAYER
P: Jens Axboe P: Jens Axboe
M: axboe@kernel.dk M: axboe@kernel.dk
@ -1459,6 +1466,11 @@ L: linux-scsi@vger.kernel.org
W: http://www.icp-vortex.com/ W: http://www.icp-vortex.com/
S: Supported S: Supported
GENERIC GPIO I2C DRIVER
P: Haavard Skinnemoen
M: hskinnemoen@atmel.com
S: Supported
GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
P: Krzysztof Halasa P: Krzysztof Halasa
M: khc@pm.waw.pl M: khc@pm.waw.pl
@ -1631,6 +1643,13 @@ L: i2c@lm-sensors.org
T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/ T: quilt http://khali.linux-fr.org/devel/linux-2.6/jdelvare-i2c/
S: Maintained S: Maintained
I2C-TINY-USB DRIVER
P: Till Harbaum
M: till@harbaum.org
L: i2c@lm-sensors.org
T: http://www.harbaum.org/till/i2c_tiny_usb
S: Maintained
i386 BOOT CODE i386 BOOT CODE
P: Riley H. Williams P: Riley H. Williams
M: Riley@Williams.Name M: Riley@Williams.Name

View file

@ -25,7 +25,6 @@
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/sysdev.h> #include <linux/sysdev.h>
#include <linux/i2c.h>
#include <linux/hardirq.h> #include <linux/hardirq.h>
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/machdep.h> #include <asm/machdep.h>

View file

@ -58,7 +58,7 @@ obj-$(CONFIG_GAMEPORT) += input/gameport/
obj-$(CONFIG_INPUT) += input/ obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_I2O) += message/ obj-$(CONFIG_I2O) += message/
obj-$(CONFIG_RTC_LIB) += rtc/ obj-$(CONFIG_RTC_LIB) += rtc/
obj-$(CONFIG_I2C) += i2c/ obj-y += i2c/
obj-$(CONFIG_W1) += w1/ obj-$(CONFIG_W1) += w1/
obj-$(CONFIG_HWMON) += hwmon/ obj-$(CONFIG_HWMON) += hwmon/
obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_PHONE) += telephony/

View file

@ -2,9 +2,7 @@
# I2C subsystem configuration # I2C subsystem configuration
# #
menu "I2C support" menuconfig I2C
config I2C
tristate "I2C support" tristate "I2C support"
---help--- ---help---
I2C (pronounce: I-square-C) is a slow serial bus protocol used in I2C (pronounce: I-square-C) is a slow serial bus protocol used in
@ -22,9 +20,14 @@ config I2C
This I2C support can also be built as a module. If so, the module This I2C support can also be built as a module. If so, the module
will be called i2c-core. will be called i2c-core.
if I2C
config I2C_BOARDINFO
boolean
default y
config I2C_CHARDEV config I2C_CHARDEV
tristate "I2C device interface" tristate "I2C device interface"
depends on I2C
help help
Say Y here to use i2c-* device files, usually found in the /dev Say Y here to use i2c-* device files, usually found in the /dev
directory on your system. They make it possible to have user-space directory on your system. They make it possible to have user-space
@ -40,7 +43,6 @@ source drivers/i2c/chips/Kconfig
config I2C_DEBUG_CORE config I2C_DEBUG_CORE
bool "I2C Core debugging messages" bool "I2C Core debugging messages"
depends on I2C
help help
Say Y here if you want the I2C core to produce a bunch of debug Say Y here if you want the I2C core to produce a bunch of debug
messages to the system log. Select this if you are having a messages to the system log. Select this if you are having a
@ -48,7 +50,6 @@ config I2C_DEBUG_CORE
config I2C_DEBUG_ALGO config I2C_DEBUG_ALGO
bool "I2C Algorithm debugging messages" bool "I2C Algorithm debugging messages"
depends on I2C
help help
Say Y here if you want the I2C algorithm drivers to produce a bunch Say Y here if you want the I2C algorithm drivers to produce a bunch
of debug messages to the system log. Select this if you are having of debug messages to the system log. Select this if you are having
@ -57,7 +58,6 @@ config I2C_DEBUG_ALGO
config I2C_DEBUG_BUS config I2C_DEBUG_BUS
bool "I2C Bus debugging messages" bool "I2C Bus debugging messages"
depends on I2C
help help
Say Y here if you want the I2C bus drivers to produce a bunch of Say Y here if you want the I2C bus drivers to produce a bunch of
debug messages to the system log. Select this if you are having debug messages to the system log. Select this if you are having
@ -66,12 +66,10 @@ config I2C_DEBUG_BUS
config I2C_DEBUG_CHIP config I2C_DEBUG_CHIP
bool "I2C Chip debugging messages" bool "I2C Chip debugging messages"
depends on I2C
help help
Say Y here if you want the I2C chip drivers to produce a bunch of Say Y here if you want the I2C chip drivers to produce a bunch of
debug messages to the system log. Select this if you are having debug messages to the system log. Select this if you are having
a problem with I2C support and want to see more of what is going a problem with I2C support and want to see more of what is going
on. on.
endmenu endif # I2C

View file

@ -2,6 +2,7 @@
# Makefile for the i2c core. # Makefile for the i2c core.
# #
obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o
obj-$(CONFIG_I2C) += i2c-core.o obj-$(CONFIG_I2C) += i2c-core.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-y += busses/ chips/ algos/ obj-y += busses/ chips/ algos/

View file

@ -3,11 +3,9 @@
# #
menu "I2C Algorithms" menu "I2C Algorithms"
depends on I2C
config I2C_ALGOBIT config I2C_ALGOBIT
tristate "I2C bit-banging interfaces" tristate "I2C bit-banging interfaces"
depends on I2C
help help
This allows you to use a range of I2C adapters called bit-banging This allows you to use a range of I2C adapters called bit-banging
adapters. Say Y if you own an I2C adapter belonging to this class adapters. Say Y if you own an I2C adapter belonging to this class
@ -18,7 +16,6 @@ config I2C_ALGOBIT
config I2C_ALGOPCF config I2C_ALGOPCF
tristate "I2C PCF 8584 interfaces" tristate "I2C PCF 8584 interfaces"
depends on I2C
help help
This allows you to use a range of I2C adapters called PCF adapters. This allows you to use a range of I2C adapters called PCF adapters.
Say Y if you own an I2C adapter belonging to this class and then say Say Y if you own an I2C adapter belonging to this class and then say
@ -29,7 +26,6 @@ config I2C_ALGOPCF
config I2C_ALGOPCA config I2C_ALGOPCA
tristate "I2C PCA 9564 interfaces" tristate "I2C PCA 9564 interfaces"
depends on I2C
help help
This allows you to use a range of I2C adapters called PCA adapters. This allows you to use a range of I2C adapters called PCA adapters.
Say Y if you own an I2C adapter belonging to this class and then say Say Y if you own an I2C adapter belonging to this class and then say
@ -40,11 +36,11 @@ config I2C_ALGOPCA
config I2C_ALGO8XX config I2C_ALGO8XX
tristate "MPC8xx CPM I2C interface" tristate "MPC8xx CPM I2C interface"
depends on 8xx && I2C depends on 8xx
config I2C_ALGO_SGI config I2C_ALGO_SGI
tristate "I2C SGI interfaces" tristate "I2C SGI interfaces"
depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS) depends on SGI_IP22 || SGI_IP32 || X86_VISWS
help help
Supports the SGI interfaces like the ones found on SGI Indy VINO Supports the SGI interfaces like the ones found on SGI Indy VINO
or SGI O2 MACE. or SGI O2 MACE.

View file

@ -33,19 +33,30 @@
/* ----- global defines ----------------------------------------------- */ /* ----- global defines ----------------------------------------------- */
#define DEB(x) if (i2c_debug>=1) x;
#define DEB2(x) if (i2c_debug>=2) x;
#define DEBSTAT(x) if (i2c_debug>=3) x; /* print several statistical values*/
#define DEBPROTO(x) if (i2c_debug>=9) { x; }
/* debug the protocol by showing transferred bits */
#ifdef DEBUG
#define bit_dbg(level, dev, format, args...) \
do { \
if (i2c_debug >= level) \
dev_dbg(dev, format, ##args); \
} while (0)
#else
#define bit_dbg(level, dev, format, args...) \
do {} while (0)
#endif /* DEBUG */
/* ----- global variables --------------------------------------------- */ /* ----- global variables --------------------------------------------- */
/* module parameters:
*/
static int i2c_debug;
static int bit_test; /* see if the line-setting functions work */ static int bit_test; /* see if the line-setting functions work */
module_param(bit_test, bool, 0);
MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
#ifdef DEBUG
static int i2c_debug = 1;
module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2 verbose; 3 very verbose");
#endif
/* --- setting states on the bus with the right timing: --------------- */ /* --- setting states on the bus with the right timing: --------------- */
@ -57,19 +68,19 @@ static int bit_test; /* see if the line-setting functions work */
static inline void sdalo(struct i2c_algo_bit_data *adap) static inline void sdalo(struct i2c_algo_bit_data *adap)
{ {
setsda(adap,0); setsda(adap,0);
udelay(adap->udelay); udelay((adap->udelay + 1) / 2);
} }
static inline void sdahi(struct i2c_algo_bit_data *adap) static inline void sdahi(struct i2c_algo_bit_data *adap)
{ {
setsda(adap,1); setsda(adap,1);
udelay(adap->udelay); udelay((adap->udelay + 1) / 2);
} }
static inline void scllo(struct i2c_algo_bit_data *adap) static inline void scllo(struct i2c_algo_bit_data *adap)
{ {
setscl(adap,0); setscl(adap,0);
udelay(adap->udelay); udelay(adap->udelay / 2);
} }
/* /*
@ -98,7 +109,11 @@ static int sclhi(struct i2c_algo_bit_data *adap)
} }
cond_resched(); cond_resched();
} }
DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start)); #ifdef DEBUG
if (jiffies != start && i2c_debug >= 3)
pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go "
"high\n", jiffies - start);
#endif
done: done:
udelay(adap->udelay); udelay(adap->udelay);
@ -110,30 +125,29 @@ static int sclhi(struct i2c_algo_bit_data *adap)
static void i2c_start(struct i2c_algo_bit_data *adap) static void i2c_start(struct i2c_algo_bit_data *adap)
{ {
/* assert: scl, sda are high */ /* assert: scl, sda are high */
DEBPROTO(printk("S ")); setsda(adap, 0);
sdalo(adap); udelay(adap->udelay);
scllo(adap); scllo(adap);
} }
static void i2c_repstart(struct i2c_algo_bit_data *adap) static void i2c_repstart(struct i2c_algo_bit_data *adap)
{ {
/* scl, sda may not be high */ /* assert: scl is low */
DEBPROTO(printk(" Sr ")); sdahi(adap);
setsda(adap,1);
sclhi(adap); sclhi(adap);
setsda(adap, 0);
sdalo(adap); udelay(adap->udelay);
scllo(adap); scllo(adap);
} }
static void i2c_stop(struct i2c_algo_bit_data *adap) static void i2c_stop(struct i2c_algo_bit_data *adap)
{ {
DEBPROTO(printk("P\n"));
/* assert: scl is low */ /* assert: scl is low */
sdalo(adap); sdalo(adap);
sclhi(adap); sclhi(adap);
sdahi(adap); setsda(adap, 1);
udelay(adap->udelay);
} }
@ -145,7 +159,7 @@ static void i2c_stop(struct i2c_algo_bit_data *adap)
* 0 if the device did not ack * 0 if the device did not ack
* -ETIMEDOUT if an error occurred (while raising the scl line) * -ETIMEDOUT if an error occurred (while raising the scl line)
*/ */
static int i2c_outb(struct i2c_adapter *i2c_adap, char c) static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c)
{ {
int i; int i;
int sb; int sb;
@ -154,34 +168,32 @@ static int i2c_outb(struct i2c_adapter *i2c_adap, char c)
/* assert: scl is low */ /* assert: scl is low */
for ( i=7 ; i>=0 ; i-- ) { for ( i=7 ; i>=0 ; i-- ) {
sb = c & ( 1 << i ); sb = (c >> i) & 1;
setsda(adap,sb); setsda(adap,sb);
udelay(adap->udelay); udelay((adap->udelay + 1) / 2);
DEBPROTO(printk(KERN_DEBUG "%d",sb!=0));
if (sclhi(adap)<0) { /* timed out */ if (sclhi(adap)<0) { /* timed out */
sdahi(adap); /* we don't want to block the net */ bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at bit #%d\n", c&0xff, i)); "timeout at bit #%d\n", (int)c, i);
return -ETIMEDOUT; return -ETIMEDOUT;
}; };
/* do arbitration here: /* do arbitration here:
* if ( sb && ! getsda(adap) ) -> ouch! Get out of here. * if ( sb && ! getsda(adap) ) -> ouch! Get out of here.
*/ */
setscl(adap, 0 ); scllo(adap);
udelay(adap->udelay);
} }
sdahi(adap); sdahi(adap);
if (sclhi(adap)<0){ /* timeout */ if (sclhi(adap)<0){ /* timeout */
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x, timeout at ack\n", c&0xff)); bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, "
return -ETIMEDOUT; "timeout at ack\n", (int)c);
return -ETIMEDOUT;
}; };
/* read ack: SDA should be pulled down by slave */ /* read ack: SDA should be pulled down by slave */
ack=getsda(adap); /* ack: sda is pulled low ->success. */ ack = !getsda(adap); /* ack: sda is pulled low -> success */
DEB2(printk(KERN_DEBUG " i2c_outb: 0x%02x , getsda() = %d\n", c & 0xff, ack)); bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c,
ack ? "A" : "NA");
DEBPROTO( printk(KERN_DEBUG "[%2.2x]",c&0xff) );
DEBPROTO(if (0==ack){ printk(KERN_DEBUG " A ");} else printk(KERN_DEBUG " NA ") );
scllo(adap); scllo(adap);
return 0==ack; /* return 1 if device acked */ return ack;
/* assert: scl is low (sda undef) */ /* assert: scl is low (sda undef) */
} }
@ -198,19 +210,18 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
sdahi(adap); sdahi(adap);
for (i=0;i<8;i++) { for (i=0;i<8;i++) {
if (sclhi(adap)<0) { /* timeout */ if (sclhi(adap)<0) { /* timeout */
DEB2(printk(KERN_DEBUG " i2c_inb: timeout at bit #%d\n", 7-i)); bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit "
"#%d\n", 7 - i);
return -ETIMEDOUT; return -ETIMEDOUT;
}; };
indata *= 2; indata *= 2;
if ( getsda(adap) ) if ( getsda(adap) )
indata |= 0x01; indata |= 0x01;
scllo(adap); setscl(adap, 0);
udelay(i == 7 ? adap->udelay / 2 : adap->udelay);
} }
/* assert: scl is low */ /* assert: scl is low */
DEB2(printk(KERN_DEBUG "i2c_inb: 0x%02x\n", indata & 0xff)); return indata;
DEBPROTO(printk(KERN_DEBUG " 0x%02x", indata & 0xff));
return (int) (indata & 0xff);
} }
/* /*
@ -221,73 +232,67 @@ static int test_bus(struct i2c_algo_bit_data *adap, char* name) {
int scl,sda; int scl,sda;
if (adap->getscl==NULL) if (adap->getscl==NULL)
printk(KERN_INFO "i2c-algo-bit.o: Testing SDA only, " pr_info("%s: Testing SDA only, SCL is not readable\n", name);
"SCL is not readable.\n");
sda=getsda(adap); sda=getsda(adap);
scl=(adap->getscl==NULL?1:getscl(adap)); scl=(adap->getscl==NULL?1:getscl(adap));
printk(KERN_DEBUG "i2c-algo-bit.o: (0) scl=%d, sda=%d\n",scl,sda);
if (!scl || !sda ) { if (!scl || !sda ) {
printk(KERN_WARNING "i2c-algo-bit.o: %s seems to be busy.\n", name); printk(KERN_WARNING "%s: bus seems to be busy\n", name);
goto bailout; goto bailout;
} }
sdalo(adap); sdalo(adap);
sda=getsda(adap); sda=getsda(adap);
scl=(adap->getscl==NULL?1:getscl(adap)); scl=(adap->getscl==NULL?1:getscl(adap));
printk(KERN_DEBUG "i2c-algo-bit.o: (1) scl=%d, sda=%d\n",scl,sda);
if ( 0 != sda ) { if ( 0 != sda ) {
printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck high!\n"); printk(KERN_WARNING "%s: SDA stuck high!\n", name);
goto bailout; goto bailout;
} }
if ( 0 == scl ) { if ( 0 == scl ) {
printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low " printk(KERN_WARNING "%s: SCL unexpected low "
"while pulling SDA low!\n"); "while pulling SDA low!\n", name);
goto bailout; goto bailout;
} }
sdahi(adap); sdahi(adap);
sda=getsda(adap); sda=getsda(adap);
scl=(adap->getscl==NULL?1:getscl(adap)); scl=(adap->getscl==NULL?1:getscl(adap));
printk(KERN_DEBUG "i2c-algo-bit.o: (2) scl=%d, sda=%d\n",scl,sda);
if ( 0 == sda ) { if ( 0 == sda ) {
printk(KERN_WARNING "i2c-algo-bit.o: SDA stuck low!\n"); printk(KERN_WARNING "%s: SDA stuck low!\n", name);
goto bailout; goto bailout;
} }
if ( 0 == scl ) { if ( 0 == scl ) {
printk(KERN_WARNING "i2c-algo-bit.o: SCL unexpected low " printk(KERN_WARNING "%s: SCL unexpected low "
"while pulling SDA high!\n"); "while pulling SDA high!\n", name);
goto bailout; goto bailout;
} }
scllo(adap); scllo(adap);
sda=getsda(adap); sda=getsda(adap);
scl=(adap->getscl==NULL?0:getscl(adap)); scl=(adap->getscl==NULL?0:getscl(adap));
printk(KERN_DEBUG "i2c-algo-bit.o: (3) scl=%d, sda=%d\n",scl,sda);
if ( 0 != scl ) { if ( 0 != scl ) {
printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck high!\n"); printk(KERN_WARNING "%s: SCL stuck high!\n", name);
goto bailout; goto bailout;
} }
if ( 0 == sda ) { if ( 0 == sda ) {
printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low " printk(KERN_WARNING "%s: SDA unexpected low "
"while pulling SCL low!\n"); "while pulling SCL low!\n", name);
goto bailout; goto bailout;
} }
sclhi(adap); sclhi(adap);
sda=getsda(adap); sda=getsda(adap);
scl=(adap->getscl==NULL?1:getscl(adap)); scl=(adap->getscl==NULL?1:getscl(adap));
printk(KERN_DEBUG "i2c-algo-bit.o: (4) scl=%d, sda=%d\n",scl,sda);
if ( 0 == scl ) { if ( 0 == scl ) {
printk(KERN_WARNING "i2c-algo-bit.o: SCL stuck low!\n"); printk(KERN_WARNING "%s: SCL stuck low!\n", name);
goto bailout; goto bailout;
} }
if ( 0 == sda ) { if ( 0 == sda ) {
printk(KERN_WARNING "i2c-algo-bit.o: SDA unexpected low " printk(KERN_WARNING "%s: SDA unexpected low "
"while pulling SCL high!\n"); "while pulling SCL high!\n", name);
goto bailout; goto bailout;
} }
printk(KERN_INFO "i2c-algo-bit.o: %s passed test.\n",name); pr_info("%s: Test OK\n", name);
return 0; return 0;
bailout: bailout:
sdahi(adap); sdahi(adap);
@ -312,44 +317,39 @@ static int try_address(struct i2c_adapter *i2c_adap,
int i,ret = -1; int i,ret = -1;
for (i=0;i<=retries;i++) { for (i=0;i<=retries;i++) {
ret = i2c_outb(i2c_adap,addr); ret = i2c_outb(i2c_adap,addr);
if (ret==1) if (ret == 1 || i == retries)
break; /* success! */
i2c_stop(adap);
udelay(5/*adap->udelay*/);
if (i==retries) /* no success */
break; break;
i2c_start(adap); bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n");
i2c_stop(adap);
udelay(adap->udelay); udelay(adap->udelay);
yield();
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
i2c_start(adap);
} }
DEB2(if (i) if (i && ret)
printk(KERN_DEBUG "i2c-algo-bit.o: Used %d tries to %s client at 0x%02x : %s\n", bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at "
i+1, addr & 1 ? "read" : "write", addr>>1, "0x%02x: %s\n", i + 1,
ret==1 ? "success" : ret==0 ? "no ack" : "failed, timeout?" ) addr & 1 ? "read from" : "write to", addr >> 1,
); ret == 1 ? "success" : "failed, timeout?");
return ret; return ret;
} }
static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
{ {
struct i2c_algo_bit_data *adap = i2c_adap->algo_data; const unsigned char *temp = msg->buf;
char c;
const char *temp = msg->buf;
int count = msg->len; int count = msg->len;
unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
int retval; int retval;
int wrcount=0; int wrcount=0;
while (count > 0) { while (count > 0) {
c = *temp; retval = i2c_outb(i2c_adap, *temp);
DEB2(dev_dbg(&i2c_adap->dev, "sendbytes: writing %2.2X\n", c&0xff));
retval = i2c_outb(i2c_adap,c);
if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */ if ((retval>0) || (nak_ok && (retval==0))) { /* ok or ignored NAK */
count--; count--;
temp++; temp++;
wrcount++; wrcount++;
} else { /* arbitration or no acknowledge */ } else { /* arbitration or no acknowledge */
dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n"); dev_err(&i2c_adap->dev, "sendbytes: error - bailout.\n");
i2c_stop(adap);
return (retval<0)? retval : -EFAULT; return (retval<0)? retval : -EFAULT;
/* got a better one ?? */ /* got a better one ?? */
} }
@ -362,7 +362,7 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
int inval; int inval;
int rdcount=0; /* counts bytes read */ int rdcount=0; /* counts bytes read */
struct i2c_algo_bit_data *adap = i2c_adap->algo_data; struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
char *temp = msg->buf; unsigned char *temp = msg->buf;
int count = msg->len; int count = msg->len;
while (count > 0) { while (count > 0) {
@ -371,30 +371,44 @@ static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
*temp = inval; *temp = inval;
rdcount++; rdcount++;
} else { /* read timed out */ } else { /* read timed out */
printk(KERN_ERR "i2c-algo-bit.o: readbytes: i2c_inb timed out.\n");
break; break;
} }
temp++; temp++;
count--; count--;
if (msg->flags & I2C_M_NO_RD_ACK) if (msg->flags & I2C_M_NO_RD_ACK) {
bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x\n",
inval);
continue; continue;
if ( count > 0 ) { /* send ack */
sdalo(adap);
DEBPROTO(printk(" Am "));
} else {
sdahi(adap); /* neg. ack on last byte */
DEBPROTO(printk(" NAm "));
} }
/* assert: sda is high */
if (count) /* send ack */
setsda(adap, 0);
udelay((adap->udelay + 1) / 2);
bit_dbg(2, &i2c_adap->dev, "i2c_inb: 0x%02x %s\n", inval,
count ? "A" : "NA");
if (sclhi(adap)<0) { /* timeout */ if (sclhi(adap)<0) { /* timeout */
sdahi(adap); dev_err(&i2c_adap->dev, "readbytes: timeout at ack\n");
printk(KERN_ERR "i2c-algo-bit.o: readbytes: Timeout at ack\n");
return -ETIMEDOUT; return -ETIMEDOUT;
}; };
scllo(adap); scllo(adap);
sdahi(adap);
/* Some SMBus transactions require that we receive the
transaction length as the first read byte. */
if (rdcount == 1 && (msg->flags & I2C_M_RECV_LEN)) {
if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) {
dev_err(&i2c_adap->dev, "readbytes: invalid "
"block length (%d)\n", inval);
return -EREMOTEIO;
}
/* The original count value accounts for the extra
bytes, that is, either 1 for a regular transaction,
or 2 for a PEC transaction. */
count += inval;
msg->len += inval;
}
} }
return rdcount; return rdcount;
} }
@ -421,27 +435,31 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
if ( (flags & I2C_M_TEN) ) { if ( (flags & I2C_M_TEN) ) {
/* a ten bit address */ /* a ten bit address */
addr = 0xf0 | (( msg->addr >> 7) & 0x03); addr = 0xf0 | (( msg->addr >> 7) & 0x03);
DEB2(printk(KERN_DEBUG "addr0: %d\n",addr)); bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
/* try extended address code...*/ /* try extended address code...*/
ret = try_address(i2c_adap, addr, retries); ret = try_address(i2c_adap, addr, retries);
if ((ret != 1) && !nak_ok) { if ((ret != 1) && !nak_ok) {
printk(KERN_ERR "died at extended address code.\n"); dev_err(&i2c_adap->dev,
"died at extended address code\n");
return -EREMOTEIO; return -EREMOTEIO;
} }
/* the remaining 8 bit address */ /* the remaining 8 bit address */
ret = i2c_outb(i2c_adap,msg->addr & 0x7f); ret = i2c_outb(i2c_adap,msg->addr & 0x7f);
if ((ret != 1) && !nak_ok) { if ((ret != 1) && !nak_ok) {
/* the chip did not ack / xmission error occurred */ /* the chip did not ack / xmission error occurred */
printk(KERN_ERR "died at 2nd address code.\n"); dev_err(&i2c_adap->dev, "died at 2nd address code\n");
return -EREMOTEIO; return -EREMOTEIO;
} }
if ( flags & I2C_M_RD ) { if ( flags & I2C_M_RD ) {
bit_dbg(3, &i2c_adap->dev, "emitting repeated "
"start condition\n");
i2c_repstart(adap); i2c_repstart(adap);
/* okay, now switch into reading mode */ /* okay, now switch into reading mode */
addr |= 0x01; addr |= 0x01;
ret = try_address(i2c_adap, addr, retries); ret = try_address(i2c_adap, addr, retries);
if ((ret!=1) && !nak_ok) { if ((ret!=1) && !nak_ok) {
printk(KERN_ERR "died at extended address code.\n"); dev_err(&i2c_adap->dev,
"died at repeated address code\n");
return -EREMOTEIO; return -EREMOTEIO;
} }
} }
@ -468,44 +486,62 @@ static int bit_xfer(struct i2c_adapter *i2c_adap,
int i,ret; int i,ret;
unsigned short nak_ok; unsigned short nak_ok;
bit_dbg(3, &i2c_adap->dev, "emitting start condition\n");
i2c_start(adap); i2c_start(adap);
for (i=0;i<num;i++) { for (i=0;i<num;i++) {
pmsg = &msgs[i]; pmsg = &msgs[i];
nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; nak_ok = pmsg->flags & I2C_M_IGNORE_NAK;
if (!(pmsg->flags & I2C_M_NOSTART)) { if (!(pmsg->flags & I2C_M_NOSTART)) {
if (i) { if (i) {
bit_dbg(3, &i2c_adap->dev, "emitting "
"repeated start condition\n");
i2c_repstart(adap); i2c_repstart(adap);
} }
ret = bit_doAddress(i2c_adap, pmsg); ret = bit_doAddress(i2c_adap, pmsg);
if ((ret != 0) && !nak_ok) { if ((ret != 0) && !nak_ok) {
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: NAK from device addr %2.2x msg #%d\n" bit_dbg(1, &i2c_adap->dev, "NAK from "
,msgs[i].addr,i)); "device addr 0x%02x msg #%d\n",
return (ret<0) ? ret : -EREMOTEIO; msgs[i].addr, i);
goto bailout;
} }
} }
if (pmsg->flags & I2C_M_RD ) { if (pmsg->flags & I2C_M_RD ) {
/* read bytes into buffer*/ /* read bytes into buffer*/
ret = readbytes(i2c_adap, pmsg); ret = readbytes(i2c_adap, pmsg);
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: read %d bytes.\n",ret)); if (ret >= 1)
if (ret < pmsg->len ) { bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n",
return (ret<0)? ret : -EREMOTEIO; ret, ret == 1 ? "" : "s");
if (ret < pmsg->len) {
if (ret >= 0)
ret = -EREMOTEIO;
goto bailout;
} }
} else { } else {
/* write bytes from buffer */ /* write bytes from buffer */
ret = sendbytes(i2c_adap, pmsg); ret = sendbytes(i2c_adap, pmsg);
DEB2(printk(KERN_DEBUG "i2c-algo-bit.o: wrote %d bytes.\n",ret)); if (ret >= 1)
if (ret < pmsg->len ) { bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n",
return (ret<0) ? ret : -EREMOTEIO; 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); i2c_stop(adap);
return num; return ret;
} }
static u32 bit_func(struct i2c_adapter *adap) static u32 bit_func(struct i2c_adapter *adap)
{ {
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
I2C_FUNC_SMBUS_READ_BLOCK_DATA |
I2C_FUNC_SMBUS_BLOCK_PROC_CALL |
I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING;
} }
@ -520,7 +556,7 @@ static const struct i2c_algorithm i2c_bit_algo = {
/* /*
* registering functions to load algorithms at runtime * registering functions to load algorithms at runtime
*/ */
int i2c_bit_add_bus(struct i2c_adapter *adap) static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
{ {
struct i2c_algo_bit_data *bit_adap = adap->algo_data; struct i2c_algo_bit_data *bit_adap = adap->algo_data;
@ -530,25 +566,39 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
return -ENODEV; return -ENODEV;
} }
DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
/* register new adapter to i2c module... */ /* register new adapter to i2c module... */
adap->algo = &i2c_bit_algo; adap->algo = &i2c_bit_algo;
adap->timeout = 100; /* default values, should */ adap->timeout = 100; /* default values, should */
adap->retries = 3; /* be replaced by defines */ adap->retries = 3; /* be replaced by defines */
return 0;
}
int i2c_bit_add_bus(struct i2c_adapter *adap)
{
int err;
err = i2c_bit_prepare_bus(adap);
if (err)
return err;
return i2c_add_adapter(adap); return i2c_add_adapter(adap);
} }
EXPORT_SYMBOL(i2c_bit_add_bus); EXPORT_SYMBOL(i2c_bit_add_bus);
int i2c_bit_add_numbered_bus(struct i2c_adapter *adap)
{
int err;
err = i2c_bit_prepare_bus(adap);
if (err)
return err;
return i2c_add_numbered_adapter(adap);
}
EXPORT_SYMBOL(i2c_bit_add_numbered_bus);
MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_param(bit_test, bool, 0);
module_param(i2c_debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(bit_test, "Test the lines of the bus to see if it is stuck");
MODULE_PARM_DESC(i2c_debug,
"debug level - 0 off; 1 normal; 2,3 more verbose; 9 bit-protocol");

View file

@ -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 * This file is subject to the terms and conditions of the GNU General Public
* License version 2 as published by the Free Software Foundation. * License version 2 as published by the Free Software Foundation.
* *
@ -162,8 +163,8 @@ static const struct i2c_algorithm sgi_algo = {
.functionality = sgi_func, .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) int i2c_sgi_add_bus(struct i2c_adapter *adap)
{ {

View file

@ -3,11 +3,10 @@
# #
menu "I2C Hardware Bus support" menu "I2C Hardware Bus support"
depends on I2C
config I2C_ALI1535 config I2C_ALI1535
tristate "ALI 1535" tristate "ALI 1535"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the SMB If you say yes to this option, support will be included for the SMB
Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB
@ -19,7 +18,7 @@ config I2C_ALI1535
config I2C_ALI1563 config I2C_ALI1563
tristate "ALI 1563" tristate "ALI 1563"
depends on I2C && PCI && EXPERIMENTAL depends on PCI && EXPERIMENTAL
help help
If you say yes to this option, support will be included for the SMB If you say yes to this option, support will be included for the SMB
Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB
@ -31,7 +30,7 @@ config I2C_ALI1563
config I2C_ALI15X3 config I2C_ALI15X3
tristate "ALI 15x3" tristate "ALI 15x3"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces. Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
@ -41,7 +40,7 @@ config I2C_ALI15X3
config I2C_AMD756 config I2C_AMD756
tristate "AMD 756/766/768/8111 and nVidia nForce" tristate "AMD 756/766/768/8111 and nVidia nForce"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the AMD If you say yes to this option, support will be included for the AMD
756/766/768 mainboard I2C interfaces. The driver also includes 756/766/768 mainboard I2C interfaces. The driver also includes
@ -66,7 +65,7 @@ config I2C_AMD756_S4882
config I2C_AMD8111 config I2C_AMD8111
tristate "AMD 8111" tristate "AMD 8111"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
second (SMBus 2.0) AMD 8111 mainboard I2C interface. second (SMBus 2.0) AMD 8111 mainboard I2C interface.
@ -76,14 +75,14 @@ config I2C_AMD8111
config I2C_AT91 config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)" tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
depends on I2C && ARCH_AT91 && EXPERIMENTAL depends on ARCH_AT91 && EXPERIMENTAL
help help
This supports the use of the I2C interface on Atmel AT91 This supports the use of the I2C interface on Atmel AT91
processors. processors.
config I2C_AU1550 config I2C_AU1550
tristate "Au1550/Au1200 SMBus interface" tristate "Au1550/Au1200 SMBus interface"
depends on I2C && (SOC_AU1550 || SOC_AU1200) depends on SOC_AU1550 || SOC_AU1200
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
Au1550 and Au1200 SMBus interface. Au1550 and Au1200 SMBus interface.
@ -91,9 +90,25 @@ config I2C_AU1550
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-au1550. will be called i2c-au1550.
config I2C_BLACKFIN_TWI
tristate "Blackfin TWI I2C support"
depends on BF534 || BF536 || BF537
help
This is the TWI I2C device driver for Blackfin 534/536/537.
This driver can also be built as a module. If so, the module
will be called i2c-bfin-twi.
config I2C_BLACKFIN_TWI_CLK_KHZ
int "Blackfin TWI I2C clock (kHz)"
depends on I2C_BLACKFIN_TWI
range 10 400
default 50
help
The unit of the TWI clock is kHz.
config I2C_ELEKTOR config I2C_ELEKTOR
tristate "Elektor ISA card" tristate "Elektor ISA card"
depends on I2C && ISA && BROKEN_ON_SMP depends on ISA && BROKEN_ON_SMP
select I2C_ALGOPCF select I2C_ALGOPCF
help help
This supports the PCF8584 ISA bus I2C adapter. Say Y if you own This supports the PCF8584 ISA bus I2C adapter. Say Y if you own
@ -102,9 +117,17 @@ config I2C_ELEKTOR
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called i2c-elektor. will be called i2c-elektor.
config I2C_GPIO
tristate "GPIO-based bitbanging I2C"
depends on GENERIC_GPIO
select I2C_ALGOBIT
help
This is a very simple bitbanging I2C driver utilizing the
arch-neutral GPIO API to control the SCL and SDA lines.
config I2C_HYDRA config I2C_HYDRA
tristate "CHRP Apple Hydra Mac I/O I2C interface" tristate "CHRP Apple Hydra Mac I/O I2C interface"
depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL depends on PCI && PPC_CHRP && EXPERIMENTAL
select I2C_ALGOBIT select I2C_ALGOBIT
help help
This supports the use of the I2C interface in the Apple Hydra Mac This supports the use of the I2C interface in the Apple Hydra Mac
@ -116,7 +139,7 @@ config I2C_HYDRA
config I2C_I801 config I2C_I801
tristate "Intel 82801 (ICH)" tristate "Intel 82801 (ICH)"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the Intel If you say yes to this option, support will be included for the Intel
801 family of mainboard I2C interfaces. Specifically, the following 801 family of mainboard I2C interfaces. Specifically, the following
@ -139,7 +162,7 @@ config I2C_I801
config I2C_I810 config I2C_I810
tristate "Intel 810/815" tristate "Intel 810/815"
depends on I2C && PCI depends on PCI
select I2C_ALGOBIT select I2C_ALGOBIT
help help
If you say yes to this option, support will be included for the Intel If you say yes to this option, support will be included for the Intel
@ -156,7 +179,7 @@ config I2C_I810
config I2C_PXA config I2C_PXA
tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)" tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
depends on I2C && EXPERIMENTAL && ARCH_PXA depends on EXPERIMENTAL && ARCH_PXA
help help
If you have devices in the PXA I2C bus, say yes to this option. If you have devices in the PXA I2C bus, say yes to this option.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
@ -172,7 +195,7 @@ config I2C_PXA_SLAVE
config I2C_PIIX4 config I2C_PIIX4
tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the Intel If you say yes to this option, support will be included for the Intel
PIIX4 family of mainboard I2C interfaces. Specifically, the following PIIX4 family of mainboard I2C interfaces. Specifically, the following
@ -195,7 +218,7 @@ config I2C_PIIX4
config I2C_IBM_IIC config I2C_IBM_IIC
tristate "IBM PPC 4xx on-chip I2C interface" tristate "IBM PPC 4xx on-chip I2C interface"
depends on IBM_OCP && I2C depends on IBM_OCP
help help
Say Y here if you want to use IIC peripheral found on Say Y here if you want to use IIC peripheral found on
embedded IBM PPC 4xx based systems. embedded IBM PPC 4xx based systems.
@ -205,7 +228,7 @@ config I2C_IBM_IIC
config I2C_IOP3XX config I2C_IOP3XX
tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
depends on (ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX) && I2C depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
help help
Say Y here if you want to use the IIC bus controller on Say Y here if you want to use the IIC bus controller on
the Intel IOPx3xx I/O Processors or IXP4xx Network Processors. the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
@ -215,11 +238,10 @@ config I2C_IOP3XX
config I2C_ISA config I2C_ISA
tristate tristate
depends on I2C
config I2C_IXP4XX config I2C_IXP4XX
tristate "IXP4xx GPIO-Based I2C Interface" tristate "IXP4xx GPIO-Based I2C Interface (DEPRECATED)"
depends on I2C && ARCH_IXP4XX depends on ARCH_IXP4XX
select I2C_ALGOBIT select I2C_ALGOBIT
help help
Say Y here if you have an Intel IXP4xx(420,421,422,425) based Say Y here if you have an Intel IXP4xx(420,421,422,425) based
@ -228,9 +250,12 @@ config I2C_IXP4XX
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called i2c-ixp4xx. will be called i2c-ixp4xx.
This driver is deprecated and will be dropped soon. Use i2c-gpio
instead.
config I2C_IXP2000 config I2C_IXP2000
tristate "IXP2000 GPIO-Based I2C Interface" tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
depends on I2C && ARCH_IXP2000 depends on ARCH_IXP2000
select I2C_ALGOBIT select I2C_ALGOBIT
help help
Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based Say Y here if you have an Intel IXP2000(2400, 2800, 2850) based
@ -239,9 +264,12 @@ config I2C_IXP2000
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called i2c-ixp2000. will be called i2c-ixp2000.
This driver is deprecated and will be dropped soon. Use i2c-gpio
instead.
config I2C_POWERMAC config I2C_POWERMAC
tristate "Powermac I2C interface" tristate "Powermac I2C interface"
depends on I2C && PPC_PMAC depends on PPC_PMAC
default y default y
help help
This exposes the various PowerMac i2c interfaces to the linux i2c This exposes the various PowerMac i2c interfaces to the linux i2c
@ -253,7 +281,7 @@ config I2C_POWERMAC
config I2C_MPC config I2C_MPC
tristate "MPC107/824x/85xx/52xx/86xx" tristate "MPC107/824x/85xx/52xx/86xx"
depends on I2C && PPC32 depends on PPC32
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
@ -265,7 +293,7 @@ config I2C_MPC
config I2C_NFORCE2 config I2C_NFORCE2
tristate "Nvidia nForce2, nForce3 and nForce4" tristate "Nvidia nForce2, nForce3 and nForce4"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the Nvidia If you say yes to this option, support will be included for the Nvidia
nForce2, nForce3 and nForce4 families of mainboard I2C interfaces. nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
@ -275,7 +303,7 @@ config I2C_NFORCE2
config I2C_OCORES config I2C_OCORES
tristate "OpenCores I2C Controller" tristate "OpenCores I2C Controller"
depends on I2C && EXPERIMENTAL depends on EXPERIMENTAL
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
OpenCores I2C controller. For details see OpenCores I2C controller. For details see
@ -286,7 +314,7 @@ config I2C_OCORES
config I2C_OMAP config I2C_OMAP
tristate "OMAP I2C adapter" tristate "OMAP I2C adapter"
depends on I2C && ARCH_OMAP depends on ARCH_OMAP
default y if MACH_OMAP_H3 || MACH_OMAP_OSK default y if MACH_OMAP_H3 || MACH_OMAP_OSK
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
@ -296,7 +324,7 @@ config I2C_OMAP
config I2C_PARPORT config I2C_PARPORT
tristate "Parallel port adapter" tristate "Parallel port adapter"
depends on I2C && PARPORT depends on PARPORT
select I2C_ALGOBIT select I2C_ALGOBIT
help help
This supports parallel port I2C adapters such as the ones made by This supports parallel port I2C adapters such as the ones made by
@ -320,7 +348,6 @@ config I2C_PARPORT
config I2C_PARPORT_LIGHT config I2C_PARPORT_LIGHT
tristate "Parallel port adapter (light)" tristate "Parallel port adapter (light)"
depends on I2C
select I2C_ALGOBIT select I2C_ALGOBIT
help help
This supports parallel port I2C adapters such as the ones made by This supports parallel port I2C adapters such as the ones made by
@ -344,13 +371,13 @@ config I2C_PARPORT_LIGHT
config I2C_PASEMI config I2C_PASEMI
tristate "PA Semi SMBus interface" tristate "PA Semi SMBus interface"
depends on PPC_PASEMI && I2C && PCI depends on PPC_PASEMI && PCI
help help
Supports the PA Semi PWRficient on-chip SMBus interfaces. Supports the PA Semi PWRficient on-chip SMBus interfaces.
config I2C_PROSAVAGE config I2C_PROSAVAGE
tristate "S3/VIA (Pro)Savage" tristate "S3/VIA (Pro)Savage"
depends on I2C && PCI depends on PCI
select I2C_ALGOBIT select I2C_ALGOBIT
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
@ -365,19 +392,19 @@ config I2C_PROSAVAGE
config I2C_RPXLITE config I2C_RPXLITE
tristate "Embedded Planet RPX Lite/Classic support" tristate "Embedded Planet RPX Lite/Classic support"
depends on (RPXLITE || RPXCLASSIC) && I2C depends on RPXLITE || RPXCLASSIC
select I2C_ALGO8XX select I2C_ALGO8XX
config I2C_S3C2410 config I2C_S3C2410
tristate "S3C2410 I2C Driver" tristate "S3C2410 I2C Driver"
depends on I2C && ARCH_S3C2410 depends on ARCH_S3C2410
help help
Say Y here to include support for I2C controller in the Say Y here to include support for I2C controller in the
Samsung S3C2410 based System-on-Chip devices. Samsung S3C2410 based System-on-Chip devices.
config I2C_SAVAGE4 config I2C_SAVAGE4
tristate "S3 Savage 4" tristate "S3 Savage 4"
depends on I2C && PCI && EXPERIMENTAL depends on PCI && EXPERIMENTAL
select I2C_ALGOBIT select I2C_ALGOBIT
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
@ -388,13 +415,25 @@ config I2C_SAVAGE4
config I2C_SIBYTE config I2C_SIBYTE
tristate "SiByte SMBus interface" tristate "SiByte SMBus interface"
depends on SIBYTE_SB1xxx_SOC && I2C depends on SIBYTE_SB1xxx_SOC
help help
Supports the SiByte SOC on-chip I2C interfaces (2 channels). Supports the SiByte SOC on-chip I2C interfaces (2 channels).
config I2C_SIMTEC
tristate "Simtec Generic I2C interface"
select I2C_ALGOBIT
help
If you say yes to this option, support will be inclyded for
the Simtec Generic I2C interface. This driver is for the
simple I2C bus used on newer Simtec products for general
I2C, such as DDC on the Simtec BBD2016A.
This driver can also be build as a module. If so, the module
will be called i2c-simtec.
config SCx200_I2C config SCx200_I2C
tristate "NatSemi SCx200 I2C using GPIO pins" tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
depends on SCx200_GPIO && I2C depends on SCx200_GPIO
select I2C_ALGOBIT select I2C_ALGOBIT
help help
Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
@ -404,6 +443,9 @@ config SCx200_I2C
This support is also available as a module. If so, the module This support is also available as a module. If so, the module
will be called scx200_i2c. will be called scx200_i2c.
This driver is deprecated and will be dropped soon. Use i2c-gpio
(or scx200_acb) instead.
config SCx200_I2C_SCL config SCx200_I2C_SCL
int "GPIO pin used for SCL" int "GPIO pin used for SCL"
depends on SCx200_I2C depends on SCx200_I2C
@ -422,7 +464,7 @@ config SCx200_I2C_SDA
config SCx200_ACB config SCx200_ACB
tristate "Geode ACCESS.bus support" tristate "Geode ACCESS.bus support"
depends on X86_32 && I2C && PCI depends on X86_32 && PCI
help help
Enable the use of the ACCESS.bus controllers on the Geode SCx200 and Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
SC1100 processors and the CS5535 and CS5536 Geode companion devices. SC1100 processors and the CS5535 and CS5536 Geode companion devices.
@ -434,7 +476,7 @@ config SCx200_ACB
config I2C_SIS5595 config I2C_SIS5595
tristate "SiS 5595" tristate "SiS 5595"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
SiS5595 SMBus (a subset of I2C) interface. SiS5595 SMBus (a subset of I2C) interface.
@ -444,7 +486,7 @@ config I2C_SIS5595
config I2C_SIS630 config I2C_SIS630
tristate "SiS 630/730" tristate "SiS 630/730"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
SiS630 and SiS730 SMBus (a subset of I2C) interface. SiS630 and SiS730 SMBus (a subset of I2C) interface.
@ -454,7 +496,7 @@ config I2C_SIS630
config I2C_SIS96X config I2C_SIS96X
tristate "SiS 96x" tristate "SiS 96x"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the SiS If you say yes to this option, support will be included for the SiS
96x SMBus (a subset of I2C) interfaces. Specifically, the following 96x SMBus (a subset of I2C) interfaces. Specifically, the following
@ -472,7 +514,7 @@ config I2C_SIS96X
config I2C_STUB config I2C_STUB
tristate "I2C/SMBus Test Stub" tristate "I2C/SMBus Test Stub"
depends on I2C && EXPERIMENTAL && 'm' depends on EXPERIMENTAL && m
default 'n' default 'n'
help help
This module may be useful to developers of SMBus client drivers, This module may be useful to developers of SMBus client drivers,
@ -483,9 +525,20 @@ config I2C_STUB
If you don't know what to do here, definitely say N. If you don't know what to do here, definitely say N.
config I2C_TINY_USB
tristate "I2C-Tiny-USB"
depends on USB
help
If you say yes to this option, support will be included for the
i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See
http://www.harbaum.org/till/i2c_tiny_usb for hardware details.
This driver can also be built as a module. If so, the module
will be called i2c-tiny-usb.
config I2C_VERSATILE config I2C_VERSATILE
tristate "ARM Versatile/Realview I2C bus support" tristate "ARM Versatile/Realview I2C bus support"
depends on I2C && (ARCH_VERSATILE || ARCH_REALVIEW) depends on ARCH_VERSATILE || ARCH_REALVIEW
select I2C_ALGOBIT select I2C_ALGOBIT
help help
Say yes if you want to support the I2C serial bus on ARMs Versatile Say yes if you want to support the I2C serial bus on ARMs Versatile
@ -496,7 +549,7 @@ config I2C_VERSATILE
config I2C_ACORN config I2C_ACORN
bool "Acorn IOC/IOMD I2C bus support" bool "Acorn IOC/IOMD I2C bus support"
depends on I2C && ARCH_ACORN depends on ARCH_ACORN
default y default y
select I2C_ALGOBIT select I2C_ALGOBIT
help help
@ -506,7 +559,7 @@ config I2C_ACORN
config I2C_VIA config I2C_VIA
tristate "VIA 82C586B" tristate "VIA 82C586B"
depends on I2C && PCI && EXPERIMENTAL depends on PCI && EXPERIMENTAL
select I2C_ALGOBIT select I2C_ALGOBIT
help help
If you say yes to this option, support will be included for the VIA If you say yes to this option, support will be included for the VIA
@ -517,7 +570,7 @@ config I2C_VIA
config I2C_VIAPRO config I2C_VIAPRO
tristate "VIA VT82C596/82C686/82xx and CX700" tristate "VIA VT82C596/82C686/82xx and CX700"
depends on I2C && PCI depends on PCI
help help
If you say yes to this option, support will be included for the VIA If you say yes to this option, support will be included for the VIA
VT82C596 and later SMBus interface. Specifically, the following VT82C596 and later SMBus interface. Specifically, the following
@ -536,7 +589,7 @@ config I2C_VIAPRO
config I2C_VOODOO3 config I2C_VOODOO3
tristate "Voodoo 3" tristate "Voodoo 3"
depends on I2C && PCI depends on PCI
select I2C_ALGOBIT select I2C_ALGOBIT
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
@ -547,7 +600,7 @@ config I2C_VOODOO3
config I2C_PCA_ISA config I2C_PCA_ISA
tristate "PCA9564 on an ISA bus" tristate "PCA9564 on an ISA bus"
depends on I2C depends on ISA
select I2C_ALGOPCA select I2C_ALGOPCA
default n default n
help help
@ -564,7 +617,7 @@ config I2C_PCA_ISA
config I2C_MV64XXX config I2C_MV64XXX
tristate "Marvell mv64xxx I2C Controller" tristate "Marvell mv64xxx I2C Controller"
depends on I2C && MV64X60 && EXPERIMENTAL depends on MV64X60 && EXPERIMENTAL
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
built-in I2C interface on the Marvell 64xxx line of host bridges. built-in I2C interface on the Marvell 64xxx line of host bridges.
@ -574,7 +627,7 @@ config I2C_MV64XXX
config I2C_PNX config I2C_PNX
tristate "I2C bus support for Philips PNX targets" tristate "I2C bus support for Philips PNX targets"
depends on ARCH_PNX4008 && I2C depends on ARCH_PNX4008
help help
This driver supports the Philips IP3204 I2C IP block master and/or This driver supports the Philips IP3204 I2C IP block master and/or
slave controller slave controller

View file

@ -10,7 +10,9 @@ obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
obj-$(CONFIG_I2C_I801) += i2c-i801.o obj-$(CONFIG_I2C_I801) += i2c-i801.o
obj-$(CONFIG_I2C_I810) += i2c-i810.o obj-$(CONFIG_I2C_I810) += i2c-i810.o
@ -37,10 +39,12 @@ obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o
obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o
obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o
obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o
obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o
obj-$(CONFIG_I2C_VIA) += i2c-via.o obj-$(CONFIG_I2C_VIA) += i2c-via.o

View file

@ -497,7 +497,7 @@ static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_
/* set up the sysfs linkage to our parent device */ /* set up the sysfs linkage to our parent device */
ali1535_adapter.dev.parent = &dev->dev; ali1535_adapter.dev.parent = &dev->dev;
snprintf(ali1535_adapter.name, I2C_NAME_SIZE, snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name),
"SMBus ALI1535 adapter at %04x", ali1535_smba); "SMBus ALI1535 adapter at %04x", ali1535_smba);
return i2c_add_adapter(&ali1535_adapter); return i2c_add_adapter(&ali1535_adapter);
} }

View file

@ -492,7 +492,7 @@ static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_
/* set up the sysfs linkage to our parent device */ /* set up the sysfs linkage to our parent device */
ali15x3_adapter.dev.parent = &dev->dev; ali15x3_adapter.dev.parent = &dev->dev;
snprintf(ali15x3_adapter.name, I2C_NAME_SIZE, snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name),
"SMBus ALI15X3 adapter at %04x", ali15x3_smba); "SMBus ALI15X3 adapter at %04x", ali15x3_smba);
return i2c_add_adapter(&ali15x3_adapter); return i2c_add_adapter(&ali15x3_adapter);
} }

View file

@ -365,7 +365,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
} }
smbus->adapter.owner = THIS_MODULE; smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, I2C_NAME_SIZE, snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"SMBus2 AMD8111 adapter at %04x", smbus->base); "SMBus2 AMD8111 adapter at %04x", smbus->base);
smbus->adapter.id = I2C_HW_SMBUS_AMD8111; smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.class = I2C_CLASS_HWMON;

View 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);

View file

@ -35,6 +35,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/isa.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-pcf.h> #include <linux/i2c-algo-pcf.h>
@ -207,7 +208,7 @@ static struct i2c_adapter pcf_isa_ops = {
.name = "i2c-elektor", .name = "i2c-elektor",
}; };
static int __init i2c_pcfisa_init(void) static int __devinit elektor_match(struct device *dev, unsigned int id)
{ {
#ifdef __alpha__ #ifdef __alpha__
/* check to see we have memory mapped PCF8584 connected to the /* check to see we have memory mapped PCF8584 connected to the
@ -222,9 +223,8 @@ static int __init i2c_pcfisa_init(void)
/* yeap, we've found cypress, let's check config */ /* yeap, we've found cypress, let's check config */
if (!pci_read_config_byte(cy693_dev, 0x47, &config)) { if (!pci_read_config_byte(cy693_dev, 0x47, &config)) {
pr_debug("%s: found cy82c693, config " dev_dbg(dev, "found cy82c693, config "
"register 0x47 = 0x%02x\n", "register 0x47 = 0x%02x\n", config);
pcf_isa_ops.name, config);
/* UP2000 board has this register set to 0xe1, /* UP2000 board has this register set to 0xe1,
but the most significant bit as seems can be but the most significant bit as seems can be
@ -244,9 +244,9 @@ static int __init i2c_pcfisa_init(void)
8.25 MHz (PCI/4) clock 8.25 MHz (PCI/4) clock
(this can be read from cypress) */ (this can be read from cypress) */
clock = I2C_PCF_CLK | I2C_PCF_TRNS90; clock = I2C_PCF_CLK | I2C_PCF_TRNS90;
pr_info("%s: found API UP2000 like " dev_info(dev, "found API UP2000 like "
"board, will probe PCF8584 " "board, will probe PCF8584 "
"later\n", pcf_isa_ops.name); "later\n");
} }
} }
pci_dev_put(cy693_dev); pci_dev_put(cy693_dev);
@ -256,22 +256,27 @@ static int __init i2c_pcfisa_init(void)
/* sanity checks for mmapped I/O */ /* sanity checks for mmapped I/O */
if (mmapped && base < 0xc8000) { if (mmapped && base < 0xc8000) {
printk(KERN_ERR "%s: incorrect base address (%#x) specified " dev_err(dev, "incorrect base address (%#x) specified "
"for mmapped I/O\n", pcf_isa_ops.name, base); "for mmapped I/O\n", base);
return -ENODEV; return 0;
} }
if (base == 0) { if (base == 0) {
base = DEFAULT_BASE; base = DEFAULT_BASE;
} }
return 1;
}
static int __devinit elektor_probe(struct device *dev, unsigned int id)
{
init_waitqueue_head(&pcf_wait); init_waitqueue_head(&pcf_wait);
if (pcf_isa_init()) if (pcf_isa_init())
return -ENODEV; return -ENODEV;
pcf_isa_ops.dev.parent = dev;
if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
goto fail; goto fail;
dev_info(&pcf_isa_ops.dev, "found device at %#x\n", base); dev_info(dev, "found device at %#x\n", base);
return 0; return 0;
@ -291,7 +296,7 @@ static int __init i2c_pcfisa_init(void)
return -ENODEV; return -ENODEV;
} }
static void i2c_pcfisa_exit(void) static int __devexit elektor_remove(struct device *dev, unsigned int id)
{ {
i2c_del_adapter(&pcf_isa_ops); i2c_del_adapter(&pcf_isa_ops);
@ -307,6 +312,28 @@ static void i2c_pcfisa_exit(void)
iounmap(base_iomem); iounmap(base_iomem);
release_mem_region(base, 2); release_mem_region(base, 2);
} }
return 0;
}
static struct isa_driver i2c_elektor_driver = {
.match = elektor_match,
.probe = elektor_probe,
.remove = __devexit_p(elektor_remove),
.driver = {
.owner = THIS_MODULE,
.name = "i2c-elektor",
},
};
static int __init i2c_pcfisa_init(void)
{
return isa_register_driver(&i2c_elektor_driver, 1);
}
static void __exit i2c_pcfisa_exit(void)
{
isa_unregister_driver(&i2c_elektor_driver);
} }
MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");

View 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");

View file

@ -527,7 +527,7 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
/* set up the sysfs linkage to our parent device */ /* set up the sysfs linkage to our parent device */
i801_adapter.dev.parent = &dev->dev; i801_adapter.dev.parent = &dev->dev;
snprintf(i801_adapter.name, I2C_NAME_SIZE, snprintf(i801_adapter.name, sizeof(i801_adapter.name),
"SMBus I801 adapter at %04lx", i801_smba); "SMBus I801 adapter at %04lx", i801_smba);
err = i2c_add_adapter(&i801_adapter); err = i2c_add_adapter(&i801_adapter);
if (err) { if (err) {

View file

@ -41,6 +41,10 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/completion.h> #include <linux/completion.h>
/* Exported by i2c-core for i2c-isa only */
extern void i2c_adapter_dev_release(struct device *dev);
extern struct class i2c_adapter_class;
static u32 isa_func(struct i2c_adapter *adapter); static u32 isa_func(struct i2c_adapter *adapter);
/* This is the actual algorithm we define */ /* This is the actual algorithm we define */
@ -64,16 +68,6 @@ static u32 isa_func(struct i2c_adapter *adapter)
} }
/* Copied from i2c-core */
static ssize_t show_adapter_name(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_adapter *adap = dev_to_i2c_adapter(dev);
return sprintf(buf, "%s\n", adap->name);
}
static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL);
/* We implement an interface which resembles i2c_{add,del}_driver, /* We implement an interface which resembles i2c_{add,del}_driver,
but for i2c-isa drivers. We don't have to remember and handle lists but for i2c-isa drivers. We don't have to remember and handle lists
of drivers and adapters so this is much more simple, of course. */ of drivers and adapters so this is much more simple, of course. */
@ -139,41 +133,18 @@ static int __init i2c_isa_init(void)
isa_adapter.nr = ANY_I2C_ISA_BUS; isa_adapter.nr = ANY_I2C_ISA_BUS;
isa_adapter.dev.parent = &platform_bus; isa_adapter.dev.parent = &platform_bus;
sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr); sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
isa_adapter.dev.driver = &i2c_adapter_driver;
isa_adapter.dev.release = &i2c_adapter_dev_release; isa_adapter.dev.release = &i2c_adapter_dev_release;
isa_adapter.dev.class = &i2c_adapter_class;
err = device_register(&isa_adapter.dev); err = device_register(&isa_adapter.dev);
if (err) { if (err) {
printk(KERN_ERR "i2c-isa: Failed to register device\n"); printk(KERN_ERR "i2c-isa: Failed to register device\n");
goto exit; goto exit;
} }
err = device_create_file(&isa_adapter.dev, &dev_attr_name);
if (err) {
printk(KERN_ERR "i2c-isa: Failed to create name file\n");
goto exit_unregister;
}
/* Add this adapter to the i2c_adapter class */
memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
isa_adapter.class_dev.dev = &isa_adapter.dev;
isa_adapter.class_dev.class = &i2c_adapter_class;
strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
BUS_ID_SIZE);
err = class_device_register(&isa_adapter.class_dev);
if (err) {
printk(KERN_ERR "i2c-isa: Failed to register class device\n");
goto exit_remove_name;
}
dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name); dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
return 0; return 0;
exit_remove_name:
device_remove_file(&isa_adapter.dev, &dev_attr_name);
exit_unregister:
init_completion(&isa_adapter.dev_released); /* Needed? */
device_unregister(&isa_adapter.dev);
wait_for_completion(&isa_adapter.dev_released);
exit: exit:
return err; return err;
} }
@ -201,15 +172,11 @@ static void __exit i2c_isa_exit(void)
/* Clean up the sysfs representation */ /* Clean up the sysfs representation */
dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n"); dev_dbg(&isa_adapter.dev, "Unregistering from sysfs\n");
init_completion(&isa_adapter.dev_released); init_completion(&isa_adapter.dev_released);
init_completion(&isa_adapter.class_dev_released);
class_device_unregister(&isa_adapter.class_dev);
device_remove_file(&isa_adapter.dev, &dev_attr_name);
device_unregister(&isa_adapter.dev); device_unregister(&isa_adapter.dev);
/* Wait for sysfs to drop all references */ /* Wait for sysfs to drop all references */
dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n"); dev_dbg(&isa_adapter.dev, "Waiting for sysfs completion\n");
wait_for_completion(&isa_adapter.dev_released); wait_for_completion(&isa_adapter.dev_released);
wait_for_completion(&isa_adapter.class_dev_released);
dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name); dev_dbg(&isa_adapter.dev, "%s unregistered\n", isa_adapter.name);
} }

View file

@ -118,7 +118,7 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
drv_data->adapter.id = I2C_HW_B_IXP2000, drv_data->adapter.id = I2C_HW_B_IXP2000,
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
I2C_NAME_SIZE); sizeof(drv_data->adapter.name));
drv_data->adapter.algo_data = &drv_data->algo_data, drv_data->adapter.algo_data = &drv_data->algo_data,
drv_data->adapter.dev.parent = &plat_dev->dev; drv_data->adapter.dev.parent = &plat_dev->dev;

View file

@ -127,7 +127,7 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
drv_data->adapter.id = I2C_HW_B_IXP4XX; drv_data->adapter.id = I2C_HW_B_IXP4XX;
drv_data->adapter.class = I2C_CLASS_HWMON; drv_data->adapter.class = I2C_CLASS_HWMON;
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
I2C_NAME_SIZE); sizeof(drv_data->adapter.name));
drv_data->adapter.algo_data = &drv_data->algo_data; drv_data->adapter.algo_data = &drv_data->algo_data;
drv_data->adapter.dev.parent = &plat_dev->dev; drv_data->adapter.dev.parent = &plat_dev->dev;

View file

@ -508,7 +508,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
} }
strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
I2C_NAME_SIZE); sizeof(drv_data->adapter.name));
init_waitqueue_head(&drv_data->waitq); init_waitqueue_head(&drv_data->waitq);
spin_lock_init(&drv_data->lock); spin_lock_init(&drv_data->lock);

View file

@ -33,6 +33,8 @@
nForce4 MCP-04 0034 nForce4 MCP-04 0034
nForce4 MCP51 0264 nForce4 MCP51 0264
nForce4 MCP55 0368 nForce4 MCP55 0368
nForce MCP61 03EB
nForce MCP65 0446
This driver supports the 2 SMBuses that are included in the MCP of the This driver supports the 2 SMBuses that are included in the MCP of the
nForce2/3/4/5xx chipsets. nForce2/3/4/5xx chipsets.
@ -200,6 +202,8 @@ static struct pci_device_id nforce2_ids[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) },
{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) },
{ 0 } { 0 }
}; };
@ -240,7 +244,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo = &smbus_algorithm;
smbus->adapter.algo_data = smbus; smbus->adapter.algo_data = smbus;
smbus->adapter.dev.parent = &dev->dev; smbus->adapter.dev.parent = &dev->dev;
snprintf(smbus->adapter.name, I2C_NAME_SIZE, snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"SMBus nForce2 adapter at %04x", smbus->base); "SMBus nForce2 adapter at %04x", smbus->base);
error = i2c_add_adapter(&smbus->adapter); error = i2c_add_adapter(&smbus->adapter);

View file

@ -605,7 +605,8 @@ omap_i2c_probe(struct platform_device *pdev)
adap->dev.parent = &pdev->dev; adap->dev.parent = &pdev->dev;
/* i2c device drivers may be active on return from add_adapter() */ /* i2c device drivers may be active on return from add_adapter() */
r = i2c_add_adapter(adap); adap->nr = pdev->id;
r = i2c_add_numbered_adapter(adap);
if (r) { if (r) {
dev_err(dev->dev, "failure adding adapter\n"); dev_err(dev->dev, "failure adding adapter\n");
goto err_free_irq; goto err_free_irq;

View file

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------ * /* ------------------------------------------------------------------------ *
* i2c-parport.c I2C bus over parallel port * * i2c-parport-light.c I2C bus over parallel port *
* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ *
Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
Based on older i2c-velleman.c driver Based on older i2c-velleman.c driver
Copyright (C) 1995-2000 Simon G. Vogl Copyright (C) 1995-2000 Simon G. Vogl
@ -27,6 +27,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
@ -34,6 +35,9 @@
#include "i2c-parport.h" #include "i2c-parport.h"
#define DEFAULT_BASE 0x378 #define DEFAULT_BASE 0x378
#define DRVNAME "i2c-parport-light"
static struct platform_device *pdev;
static u16 base; static u16 base;
module_param(base, ushort, 0); module_param(base, ushort, 0);
@ -106,7 +110,7 @@ static struct i2c_algo_bit_data parport_algo_data = {
.timeout = HZ, .timeout = HZ,
}; };
/* ----- I2c structure ---------------------------------------------------- */ /* ----- Driver registration ---------------------------------------------- */
static struct i2c_adapter parport_adapter = { static struct i2c_adapter parport_adapter = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
@ -116,30 +120,14 @@ static struct i2c_adapter parport_adapter = {
.name = "Parallel port adapter (light)", .name = "Parallel port adapter (light)",
}; };
/* ----- Module loading, unloading and information ------------------------ */ static int __devinit i2c_parport_probe(struct platform_device *pdev)
static int __init i2c_parport_init(void)
{ {
if (type < 0) { int err;
printk(KERN_WARNING "i2c-parport: adapter type unspecified\n"); struct resource *res;
return -ENODEV;
}
if (type >= ARRAY_SIZE(adapter_parm)) { res = platform_get_resource(pdev, IORESOURCE_IO, 0);
printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); if (!request_region(res->start, res->end - res->start + 1, DRVNAME))
return -ENODEV; return -EBUSY;
}
if (base == 0) {
printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
base = DEFAULT_BASE;
}
if (!request_region(base, 3, "i2c-parport"))
return -ENODEV;
if (!adapter_parm[type].getscl.val)
parport_algo_data.getscl = NULL;
/* Reset hardware to a sane state (SCL and SDA high) */ /* Reset hardware to a sane state (SCL and SDA high) */
parport_setsda(NULL, 1); parport_setsda(NULL, 1);
@ -148,23 +136,125 @@ static int __init i2c_parport_init(void)
if (adapter_parm[type].init.val) if (adapter_parm[type].init.val)
line_set(1, &adapter_parm[type].init); line_set(1, &adapter_parm[type].init);
if (i2c_bit_add_bus(&parport_adapter) < 0) { parport_adapter.dev.parent = &pdev->dev;
printk(KERN_ERR "i2c-parport: Unable to register with I2C\n"); err = i2c_bit_add_bus(&parport_adapter);
release_region(base, 3); if (err) {
return -ENODEV; dev_err(&pdev->dev, "Unable to register with I2C\n");
goto exit_region;
} }
return 0; return 0;
exit_region:
release_region(res->start, res->end - res->start + 1);
return err;
} }
static void __exit i2c_parport_exit(void) static int __devexit i2c_parport_remove(struct platform_device *pdev)
{ {
struct resource *res;
i2c_del_adapter(&parport_adapter);
/* Un-init if needed (power off...) */ /* Un-init if needed (power off...) */
if (adapter_parm[type].init.val) if (adapter_parm[type].init.val)
line_set(0, &adapter_parm[type].init); line_set(0, &adapter_parm[type].init);
i2c_del_adapter(&parport_adapter); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
release_region(base, 3); release_region(res->start, res->end - res->start + 1);
return 0;
}
static struct platform_driver i2c_parport_driver = {
.driver = {
.owner = THIS_MODULE,
.name = DRVNAME,
},
.probe = i2c_parport_probe,
.remove = __devexit_p(i2c_parport_remove),
};
static int __init i2c_parport_device_add(u16 address)
{
struct resource res = {
.start = address,
.end = address + 2,
.name = DRVNAME,
.flags = IORESOURCE_IO,
};
int err;
pdev = platform_device_alloc(DRVNAME, -1);
if (!pdev) {
err = -ENOMEM;
printk(KERN_ERR DRVNAME ": Device allocation failed\n");
goto exit;
}
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
printk(KERN_ERR DRVNAME ": Device resource addition failed "
"(%d)\n", err);
goto exit_device_put;
}
err = platform_device_add(pdev);
if (err) {
printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
goto exit_device_put;
}
return 0;
exit_device_put:
platform_device_put(pdev);
exit:
return err;
}
static int __init i2c_parport_init(void)
{
int err;
if (type < 0) {
printk(KERN_ERR DRVNAME ": adapter type unspecified\n");
return -ENODEV;
}
if (type >= ARRAY_SIZE(adapter_parm)) {
printk(KERN_ERR DRVNAME ": invalid type (%d)\n", type);
return -ENODEV;
}
if (base == 0) {
pr_info(DRVNAME ": using default base 0x%x\n", DEFAULT_BASE);
base = DEFAULT_BASE;
}
if (!adapter_parm[type].getscl.val)
parport_algo_data.getscl = NULL;
/* Sets global pdev as a side effect */
err = i2c_parport_device_add(base);
if (err)
goto exit;
err = platform_driver_register(&i2c_parport_driver);
if (err)
goto exit_device;
return 0;
exit_device:
platform_device_unregister(pdev);
exit:
return err;
}
static void __exit i2c_parport_exit(void)
{
platform_driver_unregister(&i2c_parport_driver);
platform_device_unregister(pdev);
} }
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");

View file

@ -1,7 +1,7 @@
/* ------------------------------------------------------------------------ * /* ------------------------------------------------------------------------ *
* i2c-parport.c I2C bus over parallel port * * i2c-parport.c I2C bus over parallel port *
* ------------------------------------------------------------------------ * * ------------------------------------------------------------------------ *
Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> Copyright (C) 2003-2007 Jean Delvare <khali@linux-fr.org>
Based on older i2c-philips-par.c driver Based on older i2c-philips-par.c driver
Copyright (C) 1995-2000 Simon G. Vogl Copyright (C) 1995-2000 Simon G. Vogl
@ -137,19 +137,12 @@ static struct i2c_algo_bit_data parport_algo_data = {
.setscl = parport_setscl, .setscl = parport_setscl,
.getsda = parport_getsda, .getsda = parport_getsda,
.getscl = parport_getscl, .getscl = parport_getscl,
.udelay = 60, .udelay = 10, /* ~50 kbps */
.timeout = HZ, .timeout = HZ,
}; };
/* ----- I2c and parallel port call-back functions and structures --------- */ /* ----- I2c and parallel port call-back functions and structures --------- */
static struct i2c_adapter parport_adapter = {
.owner = THIS_MODULE,
.class = I2C_CLASS_HWMON,
.id = I2C_HW_B_LP,
.name = "Parallel port adapter",
};
static void i2c_parport_attach (struct parport *port) static void i2c_parport_attach (struct parport *port)
{ {
struct i2c_par *adapter; struct i2c_par *adapter;
@ -169,10 +162,17 @@ static void i2c_parport_attach (struct parport *port)
} }
/* Fill the rest of the structure */ /* Fill the rest of the structure */
adapter->adapter = parport_adapter; adapter->adapter.owner = THIS_MODULE;
adapter->adapter.class = I2C_CLASS_HWMON;
adapter->adapter.id = I2C_HW_B_LP;
strlcpy(adapter->adapter.name, "Parallel port adapter",
sizeof(adapter->adapter.name));
adapter->algo_data = parport_algo_data; adapter->algo_data = parport_algo_data;
if (!adapter_parm[type].getscl.val) /* Slow down if we can't sense SCL */
if (!adapter_parm[type].getscl.val) {
adapter->algo_data.getscl = NULL; adapter->algo_data.getscl = NULL;
adapter->algo_data.udelay = 50; /* ~10 kbps */
}
adapter->algo_data.data = port; adapter->algo_data.data = port;
adapter->adapter.algo_data = &adapter->algo_data; adapter->adapter.algo_data = &adapter->algo_data;
@ -214,11 +214,12 @@ static void i2c_parport_detach (struct parport *port)
for (prev = NULL, adapter = adapter_list; adapter; for (prev = NULL, adapter = adapter_list; adapter;
prev = adapter, adapter = adapter->next) { prev = adapter, adapter = adapter->next) {
if (adapter->pdev->port == port) { if (adapter->pdev->port == port) {
i2c_del_adapter(&adapter->adapter);
/* Un-init if needed (power off...) */ /* Un-init if needed (power off...) */
if (adapter_parm[type].init.val) if (adapter_parm[type].init.val)
line_set(port, 0, &adapter_parm[type].init); line_set(port, 0, &adapter_parm[type].init);
i2c_del_adapter(&adapter->adapter);
parport_unregister_device(adapter->pdev); parport_unregister_device(adapter->pdev);
if (prev) if (prev)
prev->next = adapter->next; prev->next = adapter->next;

View file

@ -358,7 +358,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
} }
smbus->adapter.owner = THIS_MODULE; smbus->adapter.owner = THIS_MODULE;
snprintf(smbus->adapter.name, I2C_NAME_SIZE, snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
"PA Semi SMBus adapter at 0x%lx", smbus->base); "PA Semi SMBus adapter at 0x%lx", smbus->base);
smbus->adapter.class = I2C_CLASS_HWMON; smbus->adapter.class = I2C_CLASS_HWMON;
smbus->adapter.algo = &smbus_algorithm; smbus->adapter.algo = &smbus_algorithm;

View file

@ -28,6 +28,7 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/wait.h> #include <linux/wait.h>
#include <linux/isa.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-pca.h> #include <linux/i2c-algo-pca.h>
@ -119,27 +120,26 @@ static struct i2c_adapter pca_isa_ops = {
.name = "PCA9564 ISA Adapter", .name = "PCA9564 ISA Adapter",
}; };
static int __init pca_isa_init(void) static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
{ {
init_waitqueue_head(&pca_wait); init_waitqueue_head(&pca_wait);
printk(KERN_INFO "i2c-pca-isa: i/o base %#08lx. irq %d\n", base, irq); dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);
if (!request_region(base, IO_SIZE, "i2c-pca-isa")) { if (!request_region(base, IO_SIZE, "i2c-pca-isa")) {
printk(KERN_ERR "i2c-pca-isa: I/O address %#08lx is in use.\n", base); dev_err(dev, "I/O address %#08lx is in use\n", base);
goto out; goto out;
} }
if (irq > -1) { if (irq > -1) {
if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) { if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) {
printk(KERN_ERR "i2c-pca-isa: Request irq%d failed\n", irq); dev_err(dev, "Request irq%d failed\n", irq);
goto out_region; goto out_region;
} }
} }
if (i2c_pca_add_bus(&pca_isa_ops) < 0) { if (i2c_pca_add_bus(&pca_isa_ops) < 0) {
printk(KERN_ERR "i2c-pca-isa: Failed to add i2c bus\n"); dev_err(dev, "Failed to add i2c bus\n");
goto out_irq; goto out_irq;
} }
@ -154,7 +154,7 @@ static int __init pca_isa_init(void)
return -ENODEV; return -ENODEV;
} }
static void pca_isa_exit(void) static int __devexit pca_isa_remove(struct device *dev, unsigned int id)
{ {
i2c_del_adapter(&pca_isa_ops); i2c_del_adapter(&pca_isa_ops);
@ -163,6 +163,27 @@ static void pca_isa_exit(void)
free_irq(irq, &pca_isa_ops); free_irq(irq, &pca_isa_ops);
} }
release_region(base, IO_SIZE); release_region(base, IO_SIZE);
return 0;
}
static struct isa_driver pca_isa_driver = {
.probe = pca_isa_probe,
.remove = __devexit_p(pca_isa_remove),
.driver = {
.owner = THIS_MODULE,
.name = "i2c-pca-isa",
}
};
static int __init pca_isa_init(void)
{
return isa_register_driver(&pca_isa_driver, 1);
}
static void __exit pca_isa_exit(void)
{
isa_unregister_driver(&pca_isa_driver);
} }
MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>"); MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");

View file

@ -428,7 +428,7 @@ static int __devinit piix4_probe(struct pci_dev *dev,
/* set up the sysfs linkage to our parent device */ /* set up the sysfs linkage to our parent device */
piix4_adapter.dev.parent = &dev->dev; piix4_adapter.dev.parent = &dev->dev;
snprintf(piix4_adapter.name, I2C_NAME_SIZE, snprintf(piix4_adapter.name, sizeof(piix4_adapter.name),
"SMBus PIIX4 adapter at %04x", piix4_smba); "SMBus PIIX4 adapter at %04x", piix4_smba);
if ((retval = i2c_add_adapter(&piix4_adapter))) { if ((retval = i2c_add_adapter(&piix4_adapter))) {

View file

@ -539,6 +539,18 @@ static inline void i2c_pxa_start_message(struct pxa_i2c *i2c)
writel(icr | ICR_START | ICR_TB, _ICR(i2c)); writel(icr | ICR_START | ICR_TB, _ICR(i2c));
} }
static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c)
{
u32 icr;
/*
* Clear the STOP and ACK flags
*/
icr = readl(_ICR(i2c));
icr &= ~(ICR_STOP | ICR_ACKNAK);
writel(icr, _IRC(i2c));
}
/* /*
* We are protected by the adapter bus mutex. * We are protected by the adapter bus mutex.
*/ */
@ -581,6 +593,7 @@ static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num)
* The rest of the processing occurs in the interrupt handler. * The rest of the processing occurs in the interrupt handler.
*/ */
timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5);
i2c_pxa_stop_message(i2c);
/* /*
* We place the return code in i2c->msg_idx. * We place the return code in i2c->msg_idx.
@ -825,7 +838,7 @@ static const struct i2c_algorithm i2c_pxa_algorithm = {
}; };
static struct pxa_i2c i2c_pxa = { static struct pxa_i2c i2c_pxa = {
.lock = SPIN_LOCK_UNLOCKED, .lock = __SPIN_LOCK_UNLOCKED(i2c_pxa.lock),
.adap = { .adap = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.algo = &i2c_pxa_algorithm, .algo = &i2c_pxa_algorithm,

View file

@ -61,6 +61,8 @@ struct s3c24xx_i2c {
unsigned int msg_idx; unsigned int msg_idx;
unsigned int msg_ptr; unsigned int msg_ptr;
unsigned int tx_setup;
enum s3c24xx_i2c_state state; enum s3c24xx_i2c_state state;
void __iomem *regs; void __iomem *regs;
@ -199,8 +201,11 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c,
dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr);
writeb(addr, i2c->regs + S3C2410_IICDS); writeb(addr, i2c->regs + S3C2410_IICDS);
// delay a bit and reset iiccon before setting start (per samsung) /* delay here to ensure the data byte has gotten onto the bus
udelay(1); * before the transaction is started */
ndelay(i2c->tx_setup);
dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon);
writel(iiccon, i2c->regs + S3C2410_IICCON); writel(iiccon, i2c->regs + S3C2410_IICCON);
@ -322,7 +327,15 @@ static int i2s_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
if (!is_msgend(i2c)) { if (!is_msgend(i2c)) {
byte = i2c->msg->buf[i2c->msg_ptr++]; byte = i2c->msg->buf[i2c->msg_ptr++];
writeb(byte, i2c->regs + S3C2410_IICDS); writeb(byte, i2c->regs + S3C2410_IICDS);
/* delay after writing the byte to allow the
* data setup time on the bus, as writing the
* data to the register causes the first bit
* to appear on SDA, and SCL will change as
* soon as the interrupt is acknowledged */
ndelay(i2c->tx_setup);
} else if (!is_lastmsg(i2c)) { } else if (!is_lastmsg(i2c)) {
/* we need to go to the next i2c message */ /* we need to go to the next i2c message */
@ -570,9 +583,10 @@ static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
}; };
static struct s3c24xx_i2c s3c24xx_i2c = { static struct s3c24xx_i2c s3c24xx_i2c = {
.lock = SPIN_LOCK_UNLOCKED, .lock = __SPIN_LOCK_UNLOCKED(s3c24xx_i2c.lock),
.wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait), .wait = __WAIT_QUEUE_HEAD_INITIALIZER(s3c24xx_i2c.wait),
.adap = { .tx_setup = 50,
.adap = {
.name = "s3c2410-i2c", .name = "s3c2410-i2c",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.algo = &s3c24xx_i2c_algorithm, .algo = &s3c24xx_i2c_algorithm,
@ -731,26 +745,6 @@ static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c)
return 0; return 0;
} }
static void s3c24xx_i2c_free(struct s3c24xx_i2c *i2c)
{
if (i2c->clk != NULL && !IS_ERR(i2c->clk)) {
clk_disable(i2c->clk);
clk_put(i2c->clk);
i2c->clk = NULL;
}
if (i2c->regs != NULL) {
iounmap(i2c->regs);
i2c->regs = NULL;
}
if (i2c->ioarea != NULL) {
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
i2c->ioarea = NULL;
}
}
/* s3c24xx_i2c_probe /* s3c24xx_i2c_probe
* *
* called by the bus driver when a suitable device is found * called by the bus driver when a suitable device is found
@ -769,7 +763,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (IS_ERR(i2c->clk)) { if (IS_ERR(i2c->clk)) {
dev_err(&pdev->dev, "cannot get clock\n"); dev_err(&pdev->dev, "cannot get clock\n");
ret = -ENOENT; ret = -ENOENT;
goto out; goto err_noclk;
} }
dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
@ -782,7 +776,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (res == NULL) { if (res == NULL) {
dev_err(&pdev->dev, "cannot find IO resource\n"); dev_err(&pdev->dev, "cannot find IO resource\n");
ret = -ENOENT; ret = -ENOENT;
goto out; goto err_clk;
} }
i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1, i2c->ioarea = request_mem_region(res->start, (res->end-res->start)+1,
@ -791,7 +785,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (i2c->ioarea == NULL) { if (i2c->ioarea == NULL) {
dev_err(&pdev->dev, "cannot request IO\n"); dev_err(&pdev->dev, "cannot request IO\n");
ret = -ENXIO; ret = -ENXIO;
goto out; goto err_clk;
} }
i2c->regs = ioremap(res->start, (res->end-res->start)+1); i2c->regs = ioremap(res->start, (res->end-res->start)+1);
@ -799,7 +793,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (i2c->regs == NULL) { if (i2c->regs == NULL) {
dev_err(&pdev->dev, "cannot map IO\n"); dev_err(&pdev->dev, "cannot map IO\n");
ret = -ENXIO; ret = -ENXIO;
goto out; goto err_ioarea;
} }
dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res); dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", i2c->regs, i2c->ioarea, res);
@ -813,7 +807,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
ret = s3c24xx_i2c_init(i2c); ret = s3c24xx_i2c_init(i2c);
if (ret != 0) if (ret != 0)
goto out; goto err_iomap;
/* find the IRQ for this unit (note, this relies on the init call to /* find the IRQ for this unit (note, this relies on the init call to
* ensure no current IRQs pending * ensure no current IRQs pending
@ -823,7 +817,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (res == NULL) { if (res == NULL) {
dev_err(&pdev->dev, "cannot find IRQ\n"); dev_err(&pdev->dev, "cannot find IRQ\n");
ret = -ENOENT; ret = -ENOENT;
goto out; goto err_iomap;
} }
ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED, ret = request_irq(res->start, s3c24xx_i2c_irq, IRQF_DISABLED,
@ -831,7 +825,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
if (ret != 0) { if (ret != 0) {
dev_err(&pdev->dev, "cannot claim IRQ\n"); dev_err(&pdev->dev, "cannot claim IRQ\n");
goto out; goto err_iomap;
} }
i2c->irq = res; i2c->irq = res;
@ -841,17 +835,29 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
ret = i2c_add_adapter(&i2c->adap); ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "failed to add bus to i2c core\n"); dev_err(&pdev->dev, "failed to add bus to i2c core\n");
goto out; goto err_irq;
} }
platform_set_drvdata(pdev, i2c); platform_set_drvdata(pdev, i2c);
dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id); dev_info(&pdev->dev, "%s: S3C I2C adapter\n", i2c->adap.dev.bus_id);
return 0;
out: err_irq:
if (ret < 0) free_irq(i2c->irq->start, i2c);
s3c24xx_i2c_free(i2c);
err_iomap:
iounmap(i2c->regs);
err_ioarea:
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
err_clk:
clk_disable(i2c->clk);
clk_put(i2c->clk);
err_noclk:
return ret; return ret;
} }
@ -863,11 +869,17 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
static int s3c24xx_i2c_remove(struct platform_device *pdev) static int s3c24xx_i2c_remove(struct platform_device *pdev)
{ {
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);
if (i2c != NULL) { i2c_del_adapter(&i2c->adap);
s3c24xx_i2c_free(i2c); free_irq(i2c->irq->start, i2c);
platform_set_drvdata(pdev, NULL);
} clk_disable(i2c->clk);
clk_put(i2c->clk);
iounmap(i2c->regs);
release_resource(i2c->ioarea);
kfree(i2c->ioarea);
return 0; return 0;
} }

View 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");

View file

@ -300,7 +300,7 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
/* set up the sysfs linkage to our parent device */ /* set up the sysfs linkage to our parent device */
sis96x_adapter.dev.parent = &dev->dev; sis96x_adapter.dev.parent = &dev->dev;
snprintf(sis96x_adapter.name, I2C_NAME_SIZE, snprintf(sis96x_adapter.name, sizeof(sis96x_adapter.name),
"SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base); "SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base);
if ((retval = i2c_add_adapter(&sis96x_adapter))) { if ((retval = i2c_add_adapter(&sis96x_adapter))) {

View 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");

View file

@ -404,7 +404,7 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
} }
vt596_adapter.dev.parent = &pdev->dev; vt596_adapter.dev.parent = &pdev->dev;
snprintf(vt596_adapter.name, I2C_NAME_SIZE, snprintf(vt596_adapter.name, sizeof(vt596_adapter.name),
"SMBus Via Pro adapter at %04x", vt596_smba); "SMBus Via Pro adapter at %04x", vt596_smba);
vt596_pdev = pci_dev_get(pdev); vt596_pdev = pci_dev_get(pdev);

View file

@ -441,7 +441,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
adapter = &iface->adapter; adapter = &iface->adapter;
i2c_set_adapdata(adapter, iface); i2c_set_adapdata(adapter, iface);
snprintf(adapter->name, I2C_NAME_SIZE, "%s ACB%d", text, index); snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index);
adapter->owner = THIS_MODULE; adapter->owner = THIS_MODULE;
adapter->id = I2C_HW_SMBUS_SCX200; adapter->id = I2C_HW_SMBUS_SCX200;
adapter->algo = &scx200_acb_algorithm; adapter->algo = &scx200_acb_algorithm;
@ -599,6 +599,7 @@ static __init int scx200_scan_pci(void)
else { else {
int i; int i;
pci_dev_put(pdev);
for (i = 0; i < MAX_DEVICES; ++i) { for (i = 0; i < MAX_DEVICES; ++i) {
if (base[i] == 0) if (base[i] == 0)
continue; continue;

View file

@ -3,11 +3,10 @@
# #
menu "Miscellaneous I2C Chip support" menu "Miscellaneous I2C Chip support"
depends on I2C
config SENSORS_DS1337 config SENSORS_DS1337
tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock" tristate "Dallas Semiconductor DS1337 and DS1339 Real Time Clock"
depends on I2C && EXPERIMENTAL depends on EXPERIMENTAL
help help
If you say yes here you get support for Dallas Semiconductor If you say yes here you get support for Dallas Semiconductor
DS1337 and DS1339 real-time clock chips. DS1337 and DS1339 real-time clock chips.
@ -17,7 +16,7 @@ config SENSORS_DS1337
config SENSORS_DS1374 config SENSORS_DS1374
tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock" tristate "Maxim/Dallas Semiconductor DS1374 Real Time Clock"
depends on I2C && EXPERIMENTAL depends on EXPERIMENTAL
help help
If you say yes here you get support for Dallas Semiconductor If you say yes here you get support for Dallas Semiconductor
DS1374 real-time clock chips. DS1374 real-time clock chips.
@ -27,7 +26,7 @@ config SENSORS_DS1374
config SENSORS_EEPROM config SENSORS_EEPROM
tristate "EEPROM reader" tristate "EEPROM reader"
depends on I2C && EXPERIMENTAL depends on EXPERIMENTAL
help help
If you say yes here you get read-only access to the EEPROM data If you say yes here you get read-only access to the EEPROM data
available on modern memory DIMMs and Sony Vaio laptops. Such available on modern memory DIMMs and Sony Vaio laptops. Such
@ -38,7 +37,7 @@ config SENSORS_EEPROM
config SENSORS_PCF8574 config SENSORS_PCF8574
tristate "Philips PCF8574 and PCF8574A" tristate "Philips PCF8574 and PCF8574A"
depends on I2C && EXPERIMENTAL depends on EXPERIMENTAL
default n default n
help help
If you say yes here you get support for Philips PCF8574 and If you say yes here you get support for Philips PCF8574 and
@ -52,7 +51,7 @@ config SENSORS_PCF8574
config SENSORS_PCA9539 config SENSORS_PCA9539
tristate "Philips PCA9539 16-bit I/O port" tristate "Philips PCA9539 16-bit I/O port"
depends on I2C && EXPERIMENTAL depends on EXPERIMENTAL
help help
If you say yes here you get support for the Philips PCA9539 If you say yes here you get support for the Philips PCA9539
16-bit I/O port. 16-bit I/O port.
@ -62,7 +61,7 @@ config SENSORS_PCA9539
config SENSORS_PCF8591 config SENSORS_PCF8591
tristate "Philips PCF8591" tristate "Philips PCF8591"
depends on I2C && EXPERIMENTAL depends on EXPERIMENTAL
default n default n
help help
If you say yes here you get support for Philips PCF8591 chips. If you say yes here you get support for Philips PCF8591 chips.
@ -75,7 +74,7 @@ config SENSORS_PCF8591
config ISP1301_OMAP config ISP1301_OMAP
tristate "Philips ISP1301 with OMAP OTG" tristate "Philips ISP1301 with OMAP OTG"
depends on I2C && ARCH_OMAP_OTG depends on ARCH_OMAP_OTG
help help
If you say yes here you get support for the Philips ISP1301 If you say yes here you get support for the Philips ISP1301
USB-On-The-Go transceiver working with the OMAP OTG controller. USB-On-The-Go transceiver working with the OMAP OTG controller.
@ -90,7 +89,7 @@ config ISP1301_OMAP
# and having mostly OMAP-specific board support # and having mostly OMAP-specific board support
config TPS65010 config TPS65010
tristate "TPS6501x Power Management chips" tristate "TPS6501x Power Management chips"
depends on I2C && ARCH_OMAP depends on ARCH_OMAP
default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK default y if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_OSK
help help
If you say yes here you get support for the TPS6501x series of If you say yes here you get support for the TPS6501x series of
@ -103,7 +102,7 @@ config TPS65010
config SENSORS_M41T00 config SENSORS_M41T00
tristate "ST M41T00 RTC chip" tristate "ST M41T00 RTC chip"
depends on I2C && PPC32 depends on PPC32
help help
If you say yes here you get support for the ST M41T00 RTC chip. If you say yes here you get support for the ST M41T00 RTC chip.
@ -112,7 +111,7 @@ config SENSORS_M41T00
config SENSORS_MAX6875 config SENSORS_MAX6875
tristate "Maxim MAX6875 Power supply supervisor" tristate "Maxim MAX6875 Power supply supervisor"
depends on I2C && EXPERIMENTAL depends on EXPERIMENTAL
help help
If you say yes here you get support for the Maxim MAX6875 If you say yes here you get support for the Maxim MAX6875
EEPROM-programmable, quad power-supply sequencer/supervisor. EEPROM-programmable, quad power-supply sequencer/supervisor.

View 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
View 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;

View file

@ -459,7 +459,8 @@ therm_of_probe( struct of_device *dev, const struct of_device_id *match )
static int static int
therm_of_remove( struct of_device *dev ) therm_of_remove( struct of_device *dev )
{ {
return i2c_del_driver( &g4fan_driver ); i2c_del_driver( &g4fan_driver );
return 0;
} }
static struct of_device_id therm_of_match[] = {{ static struct of_device_id therm_of_match[] = {{

View file

@ -183,7 +183,8 @@ int flexcop_i2c_init(struct flexcop_device *fc)
mutex_init(&fc->i2c_mutex); mutex_init(&fc->i2c_mutex);
memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter)); memset(&fc->i2c_adap, 0, sizeof(struct i2c_adapter));
strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",I2C_NAME_SIZE); strncpy(fc->i2c_adap.name, "B2C2 FlexCop device",
sizeof(fc->i2c_adap.name));
i2c_set_adapdata(&fc->i2c_adap,fc); i2c_set_adapdata(&fc->i2c_adap,fc);

View file

@ -19,7 +19,7 @@ int dvb_usb_i2c_init(struct dvb_usb_device *d)
return -EINVAL; return -EINVAL;
} }
strncpy(d->i2c_adap.name,d->desc->name,I2C_NAME_SIZE); strncpy(d->i2c_adap.name, d->desc->name, sizeof(d->i2c_adap.name));
#ifdef I2C_ADAP_CLASS_TV_DIGITAL #ifdef I2C_ADAP_CLASS_TV_DIGITAL
d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL, d->i2c_adap.class = I2C_ADAP_CLASS_TV_DIGITAL,
#else #else

View file

@ -105,9 +105,9 @@ struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enu
} }
EXPORT_SYMBOL(dibx000_get_i2c_adapter); EXPORT_SYMBOL(dibx000_get_i2c_adapter);
static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst) static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char *name, struct dibx000_i2c_master *mst)
{ {
strncpy(i2c_adap->name, name, I2C_NAME_SIZE); strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
i2c_adap->class = I2C_CLASS_TV_DIGITAL, i2c_adap->class = I2C_CLASS_TV_DIGITAL,
i2c_adap->algo = algo; i2c_adap->algo = algo;
i2c_adap->algo_data = NULL; i2c_adap->algo_data = NULL;

View file

@ -26,7 +26,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/i2c.h>
#include <media/tuner.h> #include <media/tuner.h>
#include <media/cx2341x.h> #include <media/cx2341x.h>

View file

@ -15,6 +15,7 @@
#ifndef __LINUX_OVCAMCHIP_PRIV_H #ifndef __LINUX_OVCAMCHIP_PRIV_H
#define __LINUX_OVCAMCHIP_PRIV_H #define __LINUX_OVCAMCHIP_PRIV_H
#include <linux/i2c.h>
#include <media/ovcamchip.h> #include <media/ovcamchip.h>
#ifdef DEBUG #ifdef DEBUG

View file

@ -24,7 +24,6 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/i2c.h>
#include <media/v4l2-dev.h> #include <media/v4l2-dev.h>
#include <media/tuner.h> #include <media/tuner.h>
#include "usbvision.h" #include "usbvision.h"

View file

@ -104,7 +104,8 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
chan->dinfo = dinfo; chan->dinfo = dinfo;
chan->reg = reg; chan->reg = reg;
snprintf(chan->adapter.name, I2C_NAME_SIZE, "intelfb %s", name); snprintf(chan->adapter.name, sizeof(chan->adapter.name),
"intelfb %s", name);
chan->adapter.owner = THIS_MODULE; chan->adapter.owner = THIS_MODULE;
chan->adapter.id = I2C_HW_B_INTELFB; chan->adapter.id = I2C_HW_B_INTELFB;
chan->adapter.algo_data = &chan->algo; chan->adapter.algo_data = &chan->algo;

View file

@ -111,7 +111,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
b->mask.data = data; b->mask.data = data;
b->mask.clock = clock; b->mask.clock = clock;
b->adapter = matrox_i2c_adapter_template; b->adapter = matrox_i2c_adapter_template;
snprintf(b->adapter.name, I2C_NAME_SIZE, name, snprintf(b->adapter.name, sizeof(b->adapter.name), name,
minfo->fbcon.node); minfo->fbcon.node);
i2c_set_adapdata(&b->adapter, b); i2c_set_adapdata(&b->adapter, b);
b->adapter.algo_data = &b->bac; b->adapter.algo_data = &b->bac;

View file

@ -38,11 +38,14 @@ struct i2c_algo_bit_data {
int (*getscl) (void *data); int (*getscl) (void *data);
/* local settings */ /* local settings */
int udelay; /* half-clock-cycle time in microsecs */ int udelay; /* half clock cycle time in us,
/* i.e. clock is (500 / udelay) KHz */ minimum 2 us for fast-mode I2C,
minimum 5 us for standard-mode I2C and SMBus,
maximum 50 us for SMBus */
int timeout; /* in jiffies */ int timeout; /* in jiffies */
}; };
int i2c_bit_add_bus(struct i2c_adapter *); int i2c_bit_add_bus(struct i2c_adapter *);
int i2c_bit_add_numbered_bus(struct i2c_adapter *);
#endif /* _LINUX_I2C_ALGO_BIT_H */ #endif /* _LINUX_I2C_ALGO_BIT_H */

38
include/linux/i2c-gpio.h Normal file
View 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 */

View file

@ -258,8 +258,9 @@
/* --- MCP107 adapter */ /* --- MCP107 adapter */
#define I2C_HW_MPC107 0x0d0000 #define I2C_HW_MPC107 0x0d0000
/* --- Marvell mv64xxx i2c adapter */ /* --- Embedded adapters */
#define I2C_HW_MV64XXX 0x190000 #define I2C_HW_MV64XXX 0x190000
#define I2C_HW_BLACKFIN 0x190001 /* ADI Blackfin I2C TWI driver */
/* --- Miscellaneous adapters */ /* --- Miscellaneous adapters */
#define I2C_HW_SAA7146 0x060000 /* SAA7146 video decoder bus */ #define I2C_HW_SAA7146 0x060000 /* SAA7146 video decoder bus */

View file

@ -35,11 +35,6 @@
#include <linux/sched.h> /* for completion */ #include <linux/sched.h> /* for completion */
#include <linux/mutex.h> #include <linux/mutex.h>
/* --- For i2c-isa ---------------------------------------------------- */
extern void i2c_adapter_dev_release(struct device *dev);
extern struct device_driver i2c_adapter_driver;
extern struct class i2c_adapter_class;
extern struct bus_type i2c_bus_type; extern struct bus_type i2c_bus_type;
/* --- General options ------------------------------------------------ */ /* --- General options ------------------------------------------------ */
@ -87,6 +82,9 @@ extern s32 i2c_smbus_write_byte_data(struct i2c_client * client,
extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
extern s32 i2c_smbus_write_word_data(struct i2c_client * client, extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
u8 command, u16 value); u8 command, u16 value);
/* Returns the number of read bytes */
extern s32 i2c_smbus_read_block_data(struct i2c_client *client,
u8 command, u8 *values);
extern s32 i2c_smbus_write_block_data(struct i2c_client * client, extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
u8 command, u8 length, u8 command, u8 length,
const u8 *values); const u8 *values);
@ -114,7 +112,7 @@ struct i2c_driver {
* can be used by the driver to test if the bus meets its conditions * can be used by the driver to test if the bus meets its conditions
* & seek for the presence of the chip(s) it supports. If found, it * & seek for the presence of the chip(s) it supports. If found, it
* registers the client(s) that are on the bus to the i2c admin. via * registers the client(s) that are on the bus to the i2c admin. via
* i2c_attach_client. * i2c_attach_client. (LEGACY I2C DRIVERS ONLY)
*/ */
int (*attach_adapter)(struct i2c_adapter *); int (*attach_adapter)(struct i2c_adapter *);
int (*detach_adapter)(struct i2c_adapter *); int (*detach_adapter)(struct i2c_adapter *);
@ -122,10 +120,17 @@ struct i2c_driver {
/* tells the driver that a client is about to be deleted & gives it /* tells the driver that a client is about to be deleted & gives it
* the chance to remove its private data. Also, if the client struct * the chance to remove its private data. Also, if the client struct
* has been dynamically allocated by the driver in the function above, * has been dynamically allocated by the driver in the function above,
* it must be freed here. * it must be freed here. (LEGACY I2C DRIVERS ONLY)
*/ */
int (*detach_client)(struct i2c_client *); int (*detach_client)(struct i2c_client *);
/* Standard driver model interfaces, for "new style" i2c drivers.
* With the driver model, device enumeration is NEVER done by drivers;
* it's done by infrastructure. (NEW STYLE DRIVERS ONLY)
*/
int (*probe)(struct i2c_client *);
int (*remove)(struct i2c_client *);
/* driver model interfaces that don't relate to enumeration */ /* driver model interfaces that don't relate to enumeration */
void (*shutdown)(struct i2c_client *); void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t mesg); int (*suspend)(struct i2c_client *, pm_message_t mesg);
@ -141,25 +146,34 @@ struct i2c_driver {
}; };
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
#define I2C_NAME_SIZE 50 #define I2C_NAME_SIZE 20
/* /**
* i2c_client identifies a single device (i.e. chip) that is connected to an * struct i2c_client - represent an I2C slave device
* i2c bus. The behaviour is defined by the routines of the driver. This * @addr: Address used on the I2C bus connected to the parent adapter.
* function is mainly used for lookup & other admin. functions. * @name: Indicates the type of the device, usually a chip name that's
* generic enough to hide second-sourcing and compatible revisions.
* @dev: Driver model device node for the slave.
* @driver_name: Identifies new-style driver used with this device; also
* used as the module name for hotplug/coldplug modprobe support.
*
* An i2c_client identifies a single device (i.e. chip) connected to an
* i2c bus. The behaviour is defined by the routines of the driver.
*/ */
struct i2c_client { struct i2c_client {
unsigned int flags; /* div., see below */ unsigned short flags; /* div., see below */
unsigned short addr; /* chip address - NOTE: 7bit */ unsigned short addr; /* chip address - NOTE: 7bit */
/* addresses are stored in the */ /* addresses are stored in the */
/* _LOWER_ 7 bits */ /* _LOWER_ 7 bits */
char name[I2C_NAME_SIZE];
struct i2c_adapter *adapter; /* the adapter we sit on */ struct i2c_adapter *adapter; /* the adapter we sit on */
struct i2c_driver *driver; /* and our access routines */ struct i2c_driver *driver; /* and our access routines */
int usage_count; /* How many accesses currently */ int usage_count; /* How many accesses currently */
/* to the client */ /* to the client */
struct device dev; /* the device structure */ struct device dev; /* the device structure */
int irq; /* irq issued by device (or -1) */
char driver_name[KOBJ_NAME_LEN];
struct list_head list; struct list_head list;
char name[I2C_NAME_SIZE];
struct completion released; struct completion released;
}; };
#define to_i2c_client(d) container_of(d, struct i2c_client, dev) #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@ -179,6 +193,76 @@ static inline void i2c_set_clientdata (struct i2c_client *dev, void *data)
dev_set_drvdata (&dev->dev, data); dev_set_drvdata (&dev->dev, data);
} }
/**
* struct i2c_board_info - template for device creation
* @driver_name: identifies the driver to be bound to the device
* @type: optional chip type information, to initialize i2c_client.name
* @flags: to initialize i2c_client.flags
* @addr: stored in i2c_client.addr
* @platform_data: stored in i2c_client.dev.platform_data
* @irq: stored in i2c_client.irq
* I2C doesn't actually support hardware probing, although controllers and
* devices may be able to use I2C_SMBUS_QUICK to tell whether or not there's
* a device at a given address. Drivers commonly need more information than
* that, such as chip type, configuration, associated IRQ, and so on.
*
* i2c_board_info is used to build tables of information listing I2C devices
* that are present. This information is used to grow the driver model tree
* for "new style" I2C drivers. For mainboards this is done statically using
* i2c_register_board_info(), where @bus_num represents an adapter that isn't
* yet available. For add-on boards, i2c_new_device() does this dynamically
* with the adapter already known.
*/
struct i2c_board_info {
char driver_name[KOBJ_NAME_LEN];
char type[I2C_NAME_SIZE];
unsigned short flags;
unsigned short addr;
void *platform_data;
int irq;
};
/**
* I2C_BOARD_INFO - macro used to list an i2c device and its driver
* @driver: identifies the driver to use with the device
* @dev_addr: the device's address on the bus.
*
* This macro initializes essential fields of a struct i2c_board_info,
* declaring what has been provided on a particular board. Optional
* fields (such as the chip type, its associated irq, or device-specific
* platform_data) are provided using conventional syntax.
*/
#define I2C_BOARD_INFO(driver,dev_addr) \
.driver_name = (driver), .addr = (dev_addr)
/* Add-on boards should register/unregister their devices; e.g. a board
* with integrated I2C, a config eeprom, sensors, and a codec that's
* used in conjunction with the primary hardware.
*/
extern struct i2c_client *
i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info);
/* If you don't know the exact address of an I2C device, use this variant
* instead, which can probe for device presence in a list of possible
* addresses.
*/
extern struct i2c_client *
i2c_new_probed_device(struct i2c_adapter *adap,
struct i2c_board_info *info,
unsigned short const *addr_list);
extern void i2c_unregister_device(struct i2c_client *);
/* Mainboard arch_initcall() code should register all its I2C devices.
* This is done at arch_initcall time, before declaring any i2c adapters.
* Modules for add-on boards must use other calls.
*/
extern int
i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned n);
/* /*
* The following structs are for those who like to implement new bus drivers: * The following structs are for those who like to implement new bus drivers:
* i2c_algorithm is the interface to a class of hardware solutions which can * i2c_algorithm is the interface to a class of hardware solutions which can
@ -228,17 +312,14 @@ struct i2c_adapter {
int timeout; int timeout;
int retries; int retries;
struct device dev; /* the adapter device */ struct device dev; /* the adapter device */
struct class_device class_dev; /* the class device */
int nr; int nr;
struct list_head clients; struct list_head clients;
struct list_head list; struct list_head list;
char name[I2C_NAME_SIZE]; char name[48];
struct completion dev_released; struct completion dev_released;
struct completion class_dev_released;
}; };
#define dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
#define class_dev_to_i2c_adapter(d) container_of(d, struct i2c_adapter, class_dev)
static inline void *i2c_get_adapdata (struct i2c_adapter *dev) static inline void *i2c_get_adapdata (struct i2c_adapter *dev)
{ {
@ -290,9 +371,10 @@ struct i2c_client_address_data {
*/ */
extern int i2c_add_adapter(struct i2c_adapter *); extern int i2c_add_adapter(struct i2c_adapter *);
extern int i2c_del_adapter(struct i2c_adapter *); extern int i2c_del_adapter(struct i2c_adapter *);
extern int i2c_add_numbered_adapter(struct i2c_adapter *);
extern int i2c_register_driver(struct module *, struct i2c_driver *); extern int i2c_register_driver(struct module *, struct i2c_driver *);
extern int i2c_del_driver(struct i2c_driver *); extern void i2c_del_driver(struct i2c_driver *);
static inline int i2c_add_driver(struct i2c_driver *driver) static inline int i2c_add_driver(struct i2c_driver *driver)
{ {
@ -365,6 +447,7 @@ struct i2c_msg {
#define I2C_M_REV_DIR_ADDR 0x2000 #define I2C_M_REV_DIR_ADDR 0x2000
#define I2C_M_IGNORE_NAK 0x1000 #define I2C_M_IGNORE_NAK 0x1000
#define I2C_M_NO_RD_ACK 0x0800 #define I2C_M_NO_RD_ACK 0x0800
#define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */
__u16 len; /* msg length */ __u16 len; /* msg length */
__u8 *buf; /* pointer to msg data */ __u8 *buf; /* pointer to msg data */
}; };

View file

@ -1213,11 +1213,13 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5 #define PCI_DEVICE_ID_NVIDIA_NVENET_16 0x03E5
#define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6 #define PCI_DEVICE_ID_NVIDIA_NVENET_17 0x03E6
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA 0x03E7
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS 0x03EB
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE 0x03EC
#define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE #define PCI_DEVICE_ID_NVIDIA_NVENET_18 0x03EE
#define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF #define PCI_DEVICE_ID_NVIDIA_NVENET_19 0x03EF
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2 0x03F6
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3 0x03F7
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS 0x0446
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE 0x0448
#define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450 #define PCI_DEVICE_ID_NVIDIA_NVENET_20 0x0450
#define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451 #define PCI_DEVICE_ID_NVIDIA_NVENET_21 0x0451

View file

@ -16,7 +16,6 @@
#include <linux/videodev.h> #include <linux/videodev.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <linux/i2c.h>
/* --------------------------------- */ /* --------------------------------- */
/* ENUMERATIONS */ /* ENUMERATIONS */

View file

@ -23,6 +23,7 @@
#define _TUNER_H #define _TUNER_H
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/i2c.h>
#include <media/tuner-types.h> #include <media/tuner-types.h>
extern int tuner_debug; extern int tuner_debug;

View file

@ -1,7 +1,6 @@
#ifndef _TAS_IOCTL_H_ #ifndef _TAS_IOCTL_H_
#define _TAS_IOCTL_H_ #define _TAS_IOCTL_H_
#include <linux/i2c.h>
#include <linux/soundcard.h> #include <linux/soundcard.h>