Skip to content

Commit

Permalink
Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/jdelvare/staging

* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  i2c: Constify i2c_client where possible
  i2c-algo-bit: Complain about masters which can't read SCL
  i2c-algo-bit: Refactor adapter registration
  i2c: Add generic I2C multiplexer using GPIO API
  i2c-nforce2: Remove unnecessary cast of pci_get_drvdata
  i2c-i801: Include <linux/slab.h>
  • Loading branch information
torvalds committed Jan 11, 2011
2 parents 0be8c8b + 0cc43a1 commit 8adbf8d
Show file tree
Hide file tree
Showing 12 changed files with 362 additions and 48 deletions.
65 changes: 65 additions & 0 deletions Documentation/i2c/muxes/gpio-i2cmux
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
Kernel driver gpio-i2cmux

Author: Peter Korsgaard <[email protected]>

Description
-----------

gpio-i2cmux is an i2c mux driver providing access to I2C bus segments
from a master I2C bus and a hardware MUX controlled through GPIO pins.

E.G.:

---------- ---------- Bus segment 1 - - - - -
| | SCL/SDA | |-------------- | |
| |------------| |
| | | | Bus segment 2 | |
| Linux | GPIO 1..N | MUX |--------------- Devices
| |------------| | | |
| | | | Bus segment M
| | | |---------------| |
---------- ---------- - - - - -

SCL/SDA of the master I2C bus is multiplexed to bus segment 1..M
according to the settings of the GPIO pins 1..N.

Usage
-----

gpio-i2cmux uses the platform bus, so you need to provide a struct
platform_device with the platform_data pointing to a struct
gpio_i2cmux_platform_data with the I2C adapter number of the master
bus, the number of bus segments to create and the GPIO pins used
to control it. See include/linux/gpio-i2cmux.h for details.

E.G. something like this for a MUX providing 4 bus segments
controlled through 3 GPIO pins:

#include <linux/gpio-i2cmux.h>
#include <linux/platform_device.h>

static const unsigned myboard_gpiomux_gpios[] = {
AT91_PIN_PC26, AT91_PIN_PC25, AT91_PIN_PC24
};

static const unsigned myboard_gpiomux_values[] = {
0, 1, 2, 3
};

static struct gpio_i2cmux_platform_data myboard_i2cmux_data = {
.parent = 1,
.base_nr = 2, /* optional */
.values = myboard_gpiomux_values,
.n_values = ARRAY_SIZE(myboard_gpiomux_values),
.gpios = myboard_gpiomux_gpios,
.n_gpios = ARRAY_SIZE(myboard_gpiomux_gpios),
.idle = 4, /* optional */
};

static struct platform_device myboard_i2cmux = {
.name = "gpio-i2cmux",
.id = 0,
.dev = {
.platform_data = &myboard_i2cmux_data,
},
};
8 changes: 8 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -2692,6 +2692,14 @@ S: Supported
F: drivers/i2c/busses/i2c-gpio.c
F: include/linux/i2c-gpio.h

GENERIC GPIO I2C MULTIPLEXER DRIVER
M: Peter Korsgaard <[email protected]>
L: [email protected]
S: Supported
F: drivers/i2c/muxes/gpio-i2cmux.c
F: include/linux/gpio-i2cmux.h
F: Documentation/i2c/muxes/gpio-i2cmux

GENERIC HDLC (WAN) DRIVERS
M: Krzysztof Halasa <[email protected]>
W: http://www.kernel.org/pub/linux/utils/net/hdlc/
Expand Down
31 changes: 15 additions & 16 deletions drivers/i2c/algos/i2c-algo-bit.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,12 +600,14 @@ static const struct i2c_algorithm i2c_bit_algo = {
/*
* registering functions to load algorithms at runtime
*/
static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
static int __i2c_bit_add_bus(struct i2c_adapter *adap,
int (*add_adapter)(struct i2c_adapter *))
{
struct i2c_algo_bit_data *bit_adap = adap->algo_data;
int ret;

if (bit_test) {
int ret = test_bus(bit_adap, adap->name);
ret = test_bus(bit_adap, adap->name);
if (ret < 0)
return -ENODEV;
}
Expand All @@ -614,30 +616,27 @@ static int i2c_bit_prepare_bus(struct i2c_adapter *adap)
adap->algo = &i2c_bit_algo;
adap->retries = 3;

ret = add_adapter(adap);
if (ret < 0)
return ret;

/* Complain if SCL can't be read */
if (bit_adap->getscl == NULL) {
dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n");
dev_warn(&adap->dev, "Bus may be unreliable\n");
}
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_bit_add_bus(adap, i2c_add_adapter);
}
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);
return __i2c_bit_add_bus(adap, i2c_add_numbered_adapter);
}
EXPORT_SYMBOL(i2c_bit_add_numbered_bus);

Expand Down
1 change: 1 addition & 0 deletions drivers/i2c/busses/i2c-i801.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include <linux/acpi.h>
#include <linux/io.h>
#include <linux/dmi.h>
#include <linux/slab.h>

/* I801 SMBus address offsets */
#define SMBHSTSTS(p) (0 + (p)->smba)
Expand Down
2 changes: 1 addition & 1 deletion drivers/i2c/busses/i2c-nforce2.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_

static void __devexit nforce2_remove(struct pci_dev *dev)
{
struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
struct nforce2_smbus *smbuses = pci_get_drvdata(dev);

nforce2_set_reference(NULL);
if (smbuses[0].base) {
Expand Down
29 changes: 16 additions & 13 deletions drivers/i2c/i2c-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1362,7 +1362,7 @@ EXPORT_SYMBOL(i2c_transfer);
*
* Returns negative errno, or else the number of bytes written.
*/
int i2c_master_send(struct i2c_client *client, const char *buf, int count)
int i2c_master_send(const struct i2c_client *client, const char *buf, int count)
{
int ret;
struct i2c_adapter *adap = client->adapter;
Expand All @@ -1389,7 +1389,7 @@ EXPORT_SYMBOL(i2c_master_send);
*
* Returns negative errno, or else the number of bytes read.
*/
int i2c_master_recv(struct i2c_client *client, char *buf, int count)
int i2c_master_recv(const struct i2c_client *client, char *buf, int count)
{
struct i2c_adapter *adap = client->adapter;
struct i2c_msg msg;
Expand Down Expand Up @@ -1679,7 +1679,7 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
* This executes the SMBus "receive byte" protocol, returning negative errno
* else the byte received from the device.
*/
s32 i2c_smbus_read_byte(struct i2c_client *client)
s32 i2c_smbus_read_byte(const struct i2c_client *client)
{
union i2c_smbus_data data;
int status;
Expand All @@ -1699,7 +1699,7 @@ EXPORT_SYMBOL(i2c_smbus_read_byte);
* This executes the SMBus "send byte" protocol, returning negative errno
* else zero on success.
*/
s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)
{
return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
Expand All @@ -1714,7 +1714,7 @@ EXPORT_SYMBOL(i2c_smbus_write_byte);
* This executes the SMBus "read byte" protocol, returning negative errno
* else a data byte received from the device.
*/
s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)
{
union i2c_smbus_data data;
int status;
Expand All @@ -1735,7 +1735,8 @@ EXPORT_SYMBOL(i2c_smbus_read_byte_data);
* This executes the SMBus "write byte" protocol, returning negative errno
* else zero on success.
*/
s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command,
u8 value)
{
union i2c_smbus_data data;
data.byte = value;
Expand All @@ -1753,7 +1754,7 @@ EXPORT_SYMBOL(i2c_smbus_write_byte_data);
* This executes the SMBus "read word" protocol, returning negative errno
* else a 16-bit unsigned "word" received from the device.
*/
s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command)
{
union i2c_smbus_data data;
int status;
Expand All @@ -1774,7 +1775,8 @@ EXPORT_SYMBOL(i2c_smbus_read_word_data);
* This executes the SMBus "write word" protocol, returning negative errno
* else zero on success.
*/
s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command,
u16 value)
{
union i2c_smbus_data data;
data.word = value;
Expand All @@ -1793,7 +1795,8 @@ EXPORT_SYMBOL(i2c_smbus_write_word_data);
* This executes the SMBus "process call" protocol, returning negative errno
* else a 16-bit unsigned "word" received from the device.
*/
s32 i2c_smbus_process_call(struct i2c_client *client, u8 command, u16 value)
s32 i2c_smbus_process_call(const struct i2c_client *client, u8 command,
u16 value)
{
union i2c_smbus_data data;
int status;
Expand Down Expand Up @@ -1821,7 +1824,7 @@ EXPORT_SYMBOL(i2c_smbus_process_call);
* support this; its emulation through I2C messaging relies on a specific
* mechanism (I2C_M_RECV_LEN) which may not be implemented.
*/
s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
s32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command,
u8 *values)
{
union i2c_smbus_data data;
Expand All @@ -1848,7 +1851,7 @@ EXPORT_SYMBOL(i2c_smbus_read_block_data);
* This executes the SMBus "block write" protocol, returning negative errno
* else zero on success.
*/
s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command,
u8 length, const u8 *values)
{
union i2c_smbus_data data;
Expand All @@ -1864,7 +1867,7 @@ s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
EXPORT_SYMBOL(i2c_smbus_write_block_data);

/* Returns the number of read bytes */
s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command,
u8 length, u8 *values)
{
union i2c_smbus_data data;
Expand All @@ -1884,7 +1887,7 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
}
EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);

s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client, u8 command,
s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command,
u8 length, const u8 *values)
{
union i2c_smbus_data data;
Expand Down
12 changes: 12 additions & 0 deletions drivers/i2c/muxes/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,18 @@
menu "Multiplexer I2C Chip support"
depends on I2C_MUX

config I2C_MUX_GPIO
tristate "GPIO-based I2C multiplexer"
depends on GENERIC_GPIO
help
If you say yes to this option, support will be included for a
GPIO based I2C multiplexer. This driver provides access to
I2C busses connected through a MUX, which is controlled
through GPIO pins.

This driver can also be built as a module. If so, the module
will be called gpio-i2cmux.

config I2C_MUX_PCA9541
tristate "NXP PCA9541 I2C Master Selector"
depends on EXPERIMENTAL
Expand Down
1 change: 1 addition & 0 deletions drivers/i2c/muxes/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#
# Makefile for multiplexer I2C chip drivers.

obj-$(CONFIG_I2C_MUX_GPIO) += gpio-i2cmux.o
obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o
obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o

Expand Down
Loading

0 comments on commit 8adbf8d

Please sign in to comment.