Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

Pull i2c updates from Jean Delvare:
 "Most visible changes are the SMBus multiplexing support added to the
  i2c-i801 driver, as well as support for the VIA VX900."

* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  i2c-piix4: Fix build failure
  i2c: Correct struct i2c_driver doc about detection
  i2c-i801: Let i2c-mux-gpio find the GPIO chip
  i2c-mux-gpio: Update documentation
  i2c-mux-gpio: Add support for dynamically allocated GPIO pins
  i2c-mux-gpio: Use devm_kzalloc instead of kzalloc
  i2c-i801: Support SMBus multiplexing on Asus Z8 series
  i2c-viapro: Add VIA VX900 device ID
  i2c-parport: i2c_parport_irq can be static
  i2c-designware: i2c_dw_xfer_msg can be static
  i2c/scx200_*: Replace printks with pr_<level>s
  i2c: Make I2C available on UML
  i2c: Convert struct i2c_msg initialization to C99 format
  i2c-smbus: Convert kzalloc to devm_kzalloc
  i2c-mux: Add support for device auto-detection
This commit is contained in:
Linus Torvalds 2012-10-08 06:35:17 +09:00
commit 1b033447bf
23 changed files with 347 additions and 73 deletions

View File

@ -20,7 +20,10 @@ Supported adapters:
Datasheet: available on http://linux.via.com.tw
* VIA Technologies, Inc. VX855/VX875
Datasheet: Availability unknown
Datasheet: available on http://linux.via.com.tw
* VIA Technologies, Inc. VX900
Datasheet: available on http://linux.via.com.tw
Authors:
Kyösti Mälkki <kmalkki@cc.hut.fi>,
@ -57,6 +60,7 @@ Your lspci -n listing must show one of these :
device 1106:8324 (CX700)
device 1106:8353 (VX800/VX820)
device 1106:8409 (VX855/VX875)
device 1106:8410 (VX900)
If none of these show up, you should look in the BIOS for settings like
enable ACPI / SMBus or even USB.

View File

@ -63,3 +63,21 @@ static struct platform_device myboard_i2cmux = {
.platform_data = &myboard_i2cmux_data,
},
};
If you don't know the absolute GPIO pin numbers at registration time,
you can instead provide a chip name (.chip_name) and relative GPIO pin
numbers, and the i2c-gpio-mux driver will do the work for you,
including deferred probing if the GPIO chip isn't immediately
available.
Device Registration
-------------------
When registering your i2c-gpio-mux device, you should pass the number
of any GPIO pin it uses as the device ID. This guarantees that every
instance has a different ID.
Alternatively, if you don't need a stable device name, you can simply
pass PLATFORM_DEVID_AUTO as the device ID, and the platform core will
assign a dynamic ID to your device. If you do not know the absolute
GPIO pin numbers at registration time, this is even the only option.

View File

@ -4,7 +4,7 @@
menuconfig I2C
tristate "I2C support"
depends on HAS_IOMEM
depends on !S390
select RT_MUTEXES
---help---
I2C (pronounce: I-squared-C) is a slow serial bus protocol used in
@ -49,6 +49,7 @@ config I2C_CHARDEV
config I2C_MUX
tristate "I2C bus multiplexing support"
depends on HAS_IOMEM
help
Say Y here if you want the I2C core to support the ability to
handle multiplexed I2C bus topologies, by presenting each
@ -86,6 +87,19 @@ config I2C_SMBUS
source drivers/i2c/algos/Kconfig
source drivers/i2c/busses/Kconfig
config I2C_STUB
tristate "I2C/SMBus Test Stub"
depends on EXPERIMENTAL && m
default 'n'
help
This module may be useful to developers of SMBus client drivers,
especially for certain kinds of sensor chips.
If you do build this module, be sure to read the notes and warnings
in <file:Documentation/i2c/i2c-stub>.
If you don't know what to do here, definitely say N.
config I2C_DEBUG_CORE
bool "I2C Core debugging messages"
help
@ -103,6 +117,7 @@ config I2C_DEBUG_ALGO
config I2C_DEBUG_BUS
bool "I2C Bus debugging messages"
depends on HAS_IOMEM
help
Say Y here if you want the I2C bus drivers to produce a bunch of
debug messages to the system log. Select this if you are having

View File

@ -3,6 +3,7 @@
#
menu "I2C Hardware Bus support"
depends on HAS_IOMEM
comment "PC SMBus host controller drivers"
depends on PCI
@ -80,6 +81,7 @@ config I2C_I801
tristate "Intel 82801 (ICH/PCH)"
depends on PCI
select CHECK_SIGNATURE if X86 && DMI
select GPIOLIB if I2C_MUX
help
If you say yes to this option, support will be included for the Intel
801 family of mainboard I2C interfaces. Specifically, the following
@ -224,7 +226,7 @@ config I2C_VIA
will be called i2c-via.
config I2C_VIAPRO
tristate "VIA VT82C596/82C686/82xx and CX700/VX8xx"
tristate "VIA VT82C596/82C686/82xx and CX700/VX8xx/VX900"
depends on PCI
help
If you say yes to this option, support will be included for the VIA
@ -240,6 +242,7 @@ config I2C_VIAPRO
CX700
VX800/VX820
VX855/VX875
VX900
This driver can also be built as a module. If so, the module
will be called i2c-viapro.
@ -849,19 +852,6 @@ config I2C_SIBYTE
help
Supports the SiByte SOC on-chip I2C interfaces (2 channels).
config I2C_STUB
tristate "I2C/SMBus Test Stub"
depends on EXPERIMENTAL && m
default 'n'
help
This module may be useful to developers of SMBus client drivers,
especially for certain kinds of sensor chips.
If you do build this module, be sure to read the notes and warnings
in <file:Documentation/i2c/i2c-stub>.
If you don't know what to do here, definitely say N.
config SCx200_I2C
tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
depends on SCx200_GPIO

View File

@ -370,7 +370,7 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev)
* messages into the tx buffer. Even if the size of i2c_msg data is
* longer than the size of the tx buffer, it handles everything.
*/
void
static void
i2c_dw_xfer_msg(struct dw_i2c_dev *dev)
{
struct i2c_msg *msgs = dev->msgs;

View File

@ -80,6 +80,13 @@
#include <linux/dmi.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/err.h>
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
#include <linux/gpio.h>
#include <linux/i2c-mux-gpio.h>
#include <linux/platform_device.h>
#endif
/* I801 SMBus address offsets */
#define SMBHSTSTS(p) (0 + (p)->smba)
@ -158,6 +165,15 @@
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
struct i801_mux_config {
char *gpio_chip;
unsigned values[3];
int n_values;
unsigned classes[3];
unsigned gpios[2]; /* Relative to gpio_chip->base */
int n_gpios;
};
struct i801_priv {
struct i2c_adapter adapter;
unsigned long smba;
@ -175,6 +191,11 @@ struct i801_priv {
int count;
int len;
u8 *data;
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
const struct i801_mux_config *mux_drvdata;
struct platform_device *mux_pdev;
#endif
};
static struct pci_driver i801_driver;
@ -900,6 +921,165 @@ static void __init input_apanel_init(void) {}
static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}
#endif /* CONFIG_X86 && CONFIG_DMI */
#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE
static struct i801_mux_config i801_mux_config_asus_z8_d12 = {
.gpio_chip = "gpio_ich",
.values = { 0x02, 0x03 },
.n_values = 2,
.classes = { I2C_CLASS_SPD, I2C_CLASS_SPD },
.gpios = { 52, 53 },
.n_gpios = 2,
};
static struct i801_mux_config i801_mux_config_asus_z8_d18 = {
.gpio_chip = "gpio_ich",
.values = { 0x02, 0x03, 0x01 },
.n_values = 3,
.classes = { I2C_CLASS_SPD, I2C_CLASS_SPD, I2C_CLASS_SPD },
.gpios = { 52, 53 },
.n_gpios = 2,
};
static struct dmi_system_id __devinitdata mux_dmi_table[] = {
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8NA-D6(C)"),
},
.driver_data = &i801_mux_config_asus_z8_d12,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)E-D12(X)"),
},
.driver_data = &i801_mux_config_asus_z8_d12,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8NH-D12"),
},
.driver_data = &i801_mux_config_asus_z8_d12,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8PH-D12/IFB"),
},
.driver_data = &i801_mux_config_asus_z8_d12,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8NR-D12"),
},
.driver_data = &i801_mux_config_asus_z8_d12,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8P(N)H-D12"),
},
.driver_data = &i801_mux_config_asus_z8_d12,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8PG-D18"),
},
.driver_data = &i801_mux_config_asus_z8_d18,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8PE-D18"),
},
.driver_data = &i801_mux_config_asus_z8_d18,
},
{
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
DMI_MATCH(DMI_BOARD_NAME, "Z8PS-D12"),
},
.driver_data = &i801_mux_config_asus_z8_d12,
},
{ }
};
/* Setup multiplexing if needed */
static int __devinit i801_add_mux(struct i801_priv *priv)
{
struct device *dev = &priv->adapter.dev;
const struct i801_mux_config *mux_config;
struct i2c_mux_gpio_platform_data gpio_data;
int err;
if (!priv->mux_drvdata)
return 0;
mux_config = priv->mux_drvdata;
/* Prepare the platform data */
memset(&gpio_data, 0, sizeof(struct i2c_mux_gpio_platform_data));
gpio_data.parent = priv->adapter.nr;
gpio_data.values = mux_config->values;
gpio_data.n_values = mux_config->n_values;
gpio_data.classes = mux_config->classes;
gpio_data.gpio_chip = mux_config->gpio_chip;
gpio_data.gpios = mux_config->gpios;
gpio_data.n_gpios = mux_config->n_gpios;
gpio_data.idle = I2C_MUX_GPIO_NO_IDLE;
/* Register the mux device */
priv->mux_pdev = platform_device_register_data(dev, "i2c-mux-gpio",
PLATFORM_DEVID_AUTO, &gpio_data,
sizeof(struct i2c_mux_gpio_platform_data));
if (IS_ERR(priv->mux_pdev)) {
err = PTR_ERR(priv->mux_pdev);
priv->mux_pdev = NULL;
dev_err(dev, "Failed to register i2c-mux-gpio device\n");
return err;
}
return 0;
}
static void __devexit i801_del_mux(struct i801_priv *priv)
{
if (priv->mux_pdev)
platform_device_unregister(priv->mux_pdev);
}
static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)
{
const struct dmi_system_id *id;
const struct i801_mux_config *mux_config;
unsigned int class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
int i;
id = dmi_first_match(mux_dmi_table);
if (id) {
/* Remove from branch classes from trunk */
mux_config = id->driver_data;
for (i = 0; i < mux_config->n_values; i++)
class &= ~mux_config->classes[i];
/* Remember for later */
priv->mux_drvdata = mux_config;
}
return class;
}
#else
static inline int i801_add_mux(struct i801_priv *priv) { return 0; }
static inline void i801_del_mux(struct i801_priv *priv) { }
static inline unsigned int i801_get_adapter_class(struct i801_priv *priv)
{
return I2C_CLASS_HWMON | I2C_CLASS_SPD;
}
#endif
static int __devinit i801_probe(struct pci_dev *dev,
const struct pci_device_id *id)
{
@ -913,7 +1093,7 @@ static int __devinit i801_probe(struct pci_dev *dev,
i2c_set_adapdata(&priv->adapter, priv);
priv->adapter.owner = THIS_MODULE;
priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
priv->adapter.class = i801_get_adapter_class(priv);
priv->adapter.algo = &smbus_algorithm;
priv->pci_dev = dev;
@ -1033,6 +1213,8 @@ static int __devinit i801_probe(struct pci_dev *dev,
}
i801_probe_optional_slaves(priv);
/* We ignore errors - multiplexing is optional */
i801_add_mux(priv);
pci_set_drvdata(dev, priv);
@ -1052,6 +1234,7 @@ static void __devexit i801_remove(struct pci_dev *dev)
{
struct i801_priv *priv = pci_get_drvdata(dev);
i801_del_mux(priv);
i2c_del_adapter(&priv->adapter);
pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg);

View File

@ -151,7 +151,7 @@ static const struct i2c_algo_bit_data parport_algo_data = {
/* ----- I2c and parallel port call-back functions and structures --------- */
void i2c_parport_irq(void *data)
static void i2c_parport_irq(void *data)
{
struct i2c_par *adapter = data;
struct i2c_client *ara = adapter->ara;

View File

@ -37,6 +37,7 @@
#include <linux/stddef.h>
#include <linux/ioport.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/dmi.h>
#include <linux/acpi.h>

View File

@ -401,6 +401,7 @@ found:
case PCI_DEVICE_ID_VIA_CX700:
case PCI_DEVICE_ID_VIA_VX800:
case PCI_DEVICE_ID_VIA_VX855:
case PCI_DEVICE_ID_VIA_VX900:
case PCI_DEVICE_ID_VIA_8251:
case PCI_DEVICE_ID_VIA_8237:
case PCI_DEVICE_ID_VIA_8237A:
@ -470,6 +471,8 @@ static DEFINE_PCI_DEVICE_TABLE(vt596_ids) = {
.driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855),
.driver_data = SMBBA3 },
{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX900),
.driver_data = SMBBA3 },
{ 0, }
};

View File

@ -23,6 +23,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
@ -37,8 +39,6 @@
#include <linux/scx200.h>
#define NAME "scx200_acb"
MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver");
MODULE_ALIAS("platform:cs5535-smb");
@ -398,7 +398,7 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
outb(0x70, ACBCTL2);
if (inb(ACBCTL2) != 0x70) {
pr_debug(NAME ": ACBCTL2 readback failed\n");
pr_debug("ACBCTL2 readback failed\n");
return -ENXIO;
}
@ -406,8 +406,7 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
val = inb(ACBCTL1);
if (val) {
pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n",
val);
pr_debug("disabled, but ACBCTL1=0x%02x\n", val);
return -ENXIO;
}
@ -417,8 +416,8 @@ static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface)
val = inb(ACBCTL1);
if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) {
pr_debug(NAME ": enabled, but NMINTE won't be set, "
"ACBCTL1=0x%02x\n", val);
pr_debug("enabled, but NMINTE won't be set, ACBCTL1=0x%02x\n",
val);
return -ENXIO;
}
@ -433,7 +432,7 @@ static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text,
iface = kzalloc(sizeof(*iface), GFP_KERNEL);
if (!iface) {
printk(KERN_ERR NAME ": can't allocate memory\n");
pr_err("can't allocate memory\n");
return NULL;
}
@ -459,14 +458,14 @@ static int __devinit scx200_acb_create(struct scx200_acb_iface *iface)
rc = scx200_acb_probe(iface);
if (rc) {
printk(KERN_WARNING NAME ": probe failed\n");
pr_warn("probe failed\n");
return rc;
}
scx200_acb_reset(iface);
if (i2c_add_adapter(adapter) < 0) {
printk(KERN_ERR NAME ": failed to register\n");
pr_err("failed to register\n");
return -ENODEV;
}
@ -493,8 +492,7 @@ static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text,
return NULL;
if (!request_region(base, 8, iface->adapter.name)) {
printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n",
base, base + 8 - 1);
pr_err("can't allocate io 0x%lx-0x%lx\n", base, base + 8 - 1);
goto errout_free;
}
@ -583,7 +581,7 @@ static __init void scx200_scan_isa(void)
static int __init scx200_acb_init(void)
{
pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n");
pr_debug("NatSemi SCx200 ACCESS.bus Driver\n");
/* First scan for ISA-based devices */
scx200_scan_isa(); /* XXX: should we care about errors? */

View File

@ -21,6 +21,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
@ -31,8 +33,6 @@
#include <linux/scx200_gpio.h>
#define NAME "scx200_i2c"
MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver");
MODULE_LICENSE("GPL");
@ -88,17 +88,17 @@ static struct i2c_adapter scx200_i2c_ops = {
static int scx200_i2c_init(void)
{
pr_debug(NAME ": NatSemi SCx200 I2C Driver\n");
pr_debug("NatSemi SCx200 I2C Driver\n");
if (!scx200_gpio_present()) {
printk(KERN_ERR NAME ": no SCx200 gpio pins available\n");
pr_err("no SCx200 gpio pins available\n");
return -ENODEV;
}
pr_debug(NAME ": SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda);
pr_debug("SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda);
if (scl == -1 || sda == -1 || scl == sda) {
printk(KERN_ERR NAME ": scl and sda must be specified\n");
pr_err("scl and sda must be specified\n");
return -EINVAL;
}
@ -107,8 +107,7 @@ static int scx200_i2c_init(void)
scx200_gpio_configure(sda, ~2, 5);
if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) {
printk(KERN_ERR NAME ": adapter %s registration failed\n",
scx200_i2c_ops.name);
pr_err("adapter %s registration failed\n", scx200_i2c_ops.name);
return -ENODEV;
}

View File

@ -1989,12 +1989,22 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
int num = read_write == I2C_SMBUS_READ ? 2 : 1;
struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 },
{ addr, flags | I2C_M_RD, 0, msgbuf1 }
};
int i;
u8 partial_pec = 0;
int status;
struct i2c_msg msg[2] = {
{
.addr = addr,
.flags = flags,
.len = 1,
.buf = msgbuf0,
}, {
.addr = addr,
.flags = flags | I2C_M_RD,
.len = 0,
.buf = msgbuf1,
},
};
msgbuf0[0] = command;
switch (size) {

View File

@ -88,9 +88,23 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap)
return parent->algo->functionality(parent);
}
/* Return all parent classes, merged */
static unsigned int i2c_mux_parent_classes(struct i2c_adapter *parent)
{
unsigned int class = 0;
do {
class |= parent->class;
parent = i2c_parent_is_i2c_adapter(parent);
} while (parent);
return class;
}
struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
struct device *mux_dev,
void *mux_priv, u32 force_nr, u32 chan_id,
unsigned int class,
int (*select) (struct i2c_adapter *,
void *, u32),
int (*deselect) (struct i2c_adapter *,
@ -127,6 +141,14 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
priv->adap.algo_data = priv;
priv->adap.dev.parent = &parent->dev;
/* Sanity check on class */
if (i2c_mux_parent_classes(parent) & class)
dev_err(&parent->dev,
"Segment %d behind mux can't share classes with ancestors\n",
chan_id);
else
priv->adap.class = class;
/*
* Try to populate the mux adapter's of_node, expands to
* nothing if !CONFIG_OF.

View File

@ -142,7 +142,8 @@ static int smbalert_probe(struct i2c_client *ara,
struct i2c_adapter *adapter = ara->adapter;
int res;
alert = kzalloc(sizeof(struct i2c_smbus_alert), GFP_KERNEL);
alert = devm_kzalloc(&ara->dev, sizeof(struct i2c_smbus_alert),
GFP_KERNEL);
if (!alert)
return -ENOMEM;
@ -154,10 +155,8 @@ static int smbalert_probe(struct i2c_client *ara,
if (setup->irq > 0) {
res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq,
0, "smbus_alert", alert);
if (res) {
kfree(alert);
if (res)
return res;
}
}
i2c_set_clientdata(ara, alert);
@ -167,14 +166,12 @@ static int smbalert_probe(struct i2c_client *ara,
return 0;
}
/* IRQ resource is managed so it is freed automatically */
/* IRQ and memory resources are managed so they are freed automatically */
static int smbalert_remove(struct i2c_client *ara)
{
struct i2c_smbus_alert *alert = i2c_get_clientdata(ara);
cancel_work_sync(&alert->alert);
kfree(alert);
return 0;
}

View File

@ -21,6 +21,7 @@ struct gpiomux {
struct i2c_adapter *parent;
struct i2c_adapter **adap; /* child busses */
struct i2c_mux_gpio_platform_data data;
unsigned gpio_base;
};
static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
@ -28,7 +29,8 @@ static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
int i;
for (i = 0; i < mux->data.n_gpios; i++)
gpio_set_value(mux->data.gpios[i], val & (1 << i));
gpio_set_value(mux->gpio_base + mux->data.gpios[i],
val & (1 << i));
}
static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan)
@ -49,13 +51,19 @@ static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan)
return 0;
}
static int __devinit match_gpio_chip_by_label(struct gpio_chip *chip,
void *data)
{
return !strcmp(chip->label, data);
}
static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
{
struct gpiomux *mux;
struct i2c_mux_gpio_platform_data *pdata;
struct i2c_adapter *parent;
int (*deselect) (struct i2c_adapter *, void *, u32);
unsigned initial_state;
unsigned initial_state, gpio_base;
int i, ret;
pdata = pdev->dev.platform_data;
@ -64,6 +72,23 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
/*
* If a GPIO chip name is provided, the GPIO pin numbers provided are
* relative to its base GPIO number. Otherwise they are absolute.
*/
if (pdata->gpio_chip) {
struct gpio_chip *gpio;
gpio = gpiochip_find(pdata->gpio_chip,
match_gpio_chip_by_label);
if (!gpio)
return -EPROBE_DEFER;
gpio_base = gpio->base;
} else {
gpio_base = 0;
}
parent = i2c_get_adapter(pdata->parent);
if (!parent) {
dev_err(&pdev->dev, "Parent adapter (%d) not found\n",
@ -71,7 +96,7 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
return -ENODEV;
}
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
mux = devm_kzalloc(&pdev->dev, sizeof(*mux), GFP_KERNEL);
if (!mux) {
ret = -ENOMEM;
goto alloc_failed;
@ -79,11 +104,13 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
mux->parent = parent;
mux->data = *pdata;
mux->adap = kzalloc(sizeof(struct i2c_adapter *) * pdata->n_values,
GFP_KERNEL);
mux->gpio_base = gpio_base;
mux->adap = devm_kzalloc(&pdev->dev,
sizeof(*mux->adap) * pdata->n_values,
GFP_KERNEL);
if (!mux->adap) {
ret = -ENOMEM;
goto alloc_failed2;
goto alloc_failed;
}
if (pdata->idle != I2C_MUX_GPIO_NO_IDLE) {
@ -95,17 +122,19 @@ static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
}
for (i = 0; i < pdata->n_gpios; i++) {
ret = gpio_request(pdata->gpios[i], "i2c-mux-gpio");
ret = gpio_request(gpio_base + pdata->gpios[i], "i2c-mux-gpio");
if (ret)
goto err_request_gpio;
gpio_direction_output(pdata->gpios[i],
gpio_direction_output(gpio_base + pdata->gpios[i],
initial_state & (1 << i));
}
for (i = 0; i < pdata->n_values; i++) {
u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0;
unsigned int class = pdata->classes ? pdata->classes[i] : 0;
mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, i,
mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr,
i, class,
i2c_mux_gpio_select, deselect);
if (!mux->adap[i]) {
ret = -ENODEV;
@ -127,10 +156,7 @@ add_adapter_failed:
i = pdata->n_gpios;
err_request_gpio:
for (; i > 0; i--)
gpio_free(pdata->gpios[i - 1]);
kfree(mux->adap);
alloc_failed2:
kfree(mux);
gpio_free(gpio_base + pdata->gpios[i - 1]);
alloc_failed:
i2c_put_adapter(parent);
@ -146,12 +172,10 @@ static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
i2c_del_mux_adapter(mux->adap[i]);
for (i = 0; i < mux->data.n_gpios; i++)
gpio_free(mux->data.gpios[i]);
gpio_free(mux->gpio_base + mux->data.gpios[i]);
platform_set_drvdata(pdev, NULL);
i2c_put_adapter(mux->parent);
kfree(mux->adap);
kfree(mux);
return 0;
}

View File

@ -354,7 +354,7 @@ static int pca9541_probe(struct i2c_client *client,
if (pdata)
force = pdata->modes[0].adap_id;
data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client,
force, 0,
force, 0, 0,
pca9541_select_chan,
pca9541_release_chan);

View File

@ -186,7 +186,7 @@ static int pca954x_probe(struct i2c_client *client,
{
struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent);
struct pca954x_platform_data *pdata = client->dev.platform_data;
int num, force;
int num, force, class;
struct pca954x *data;
int ret = -ENODEV;
@ -216,18 +216,20 @@ static int pca954x_probe(struct i2c_client *client,
/* Now create an adapter for each channel */
for (num = 0; num < chips[data->type].nchans; num++) {
force = 0; /* dynamic adap number */
class = 0; /* no class by default */
if (pdata) {
if (num < pdata->num_modes)
if (num < pdata->num_modes) {
/* force static number */
force = pdata->modes[num].adap_id;
else
class = pdata->modes[num].class;
} else
/* discard unconfigured channels */
break;
}
data->virt_adaps[num] =
i2c_add_mux_adapter(adap, &client->dev, client,
force, num, pca954x_select_chan,
force, num, class, pca954x_select_chan,
(pdata && pdata->modes[num].deselect_on_exit)
? pca954x_deselect_mux : NULL);

View File

@ -221,7 +221,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
(mux->pdata->base_bus_num + i) : 0;
mux->busses[i] = i2c_add_mux_adapter(mux->parent, &pdev->dev,
mux, bus, i,
mux, bus, i, 0,
i2c_mux_pinctrl_select,
deselect);
if (!mux->busses[i]) {

View File

@ -21,6 +21,9 @@
* @values: Array of bitmasks of GPIO settings (low/high) for each
* position
* @n_values: Number of multiplexer positions (busses to instantiate)
* @classes: Optional I2C auto-detection classes
* @gpio_chip: Optional GPIO chip name; if set, GPIO pin numbers are given
* relative to the base GPIO number of that chip
* @gpios: Array of GPIO numbers used to control MUX
* @n_gpios: Number of GPIOs used to control MUX
* @idle: Bitmask to write to MUX when idle or GPIO_I2CMUX_NO_IDLE if not used
@ -30,6 +33,8 @@ struct i2c_mux_gpio_platform_data {
int base_nr;
const unsigned *values;
int n_values;
const unsigned *classes;
char *gpio_chip;
const unsigned *gpios;
int n_gpios;
unsigned idle;

View File

@ -36,6 +36,7 @@
struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
struct device *mux_dev,
void *mux_priv, u32 force_nr, u32 chan_id,
unsigned int class,
int (*select) (struct i2c_adapter *,
void *mux_dev, u32 chan_id),
int (*deselect) (struct i2c_adapter *,

View File

@ -144,7 +144,7 @@ extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
* The driver.owner field should be set to the module owner of this driver.
* The driver.name field should be set to the name of this driver.
*
* For automatic device detection, both @detect and @address_data must
* For automatic device detection, both @detect and @address_list must
* be defined. @class should also be set, otherwise only devices forced
* with module parameters will be created. The detect function must
* fill at least the name field of the i2c_board_info structure it is

View File

@ -36,6 +36,7 @@
struct pca954x_platform_mode {
int adap_id;
unsigned int deselect_on_exit:1;
unsigned int class;
};
/* Per mux/switch data, used with i2c_register_board_info */

View File

@ -1427,6 +1427,7 @@
#define PCI_DEVICE_ID_VIA_CX700_IDE 0x0581
#define PCI_DEVICE_ID_VIA_VX800 0x8353
#define PCI_DEVICE_ID_VIA_VX855 0x8409
#define PCI_DEVICE_ID_VIA_VX900 0x8410
#define PCI_DEVICE_ID_VIA_8371_1 0x8391
#define PCI_DEVICE_ID_VIA_82C598_1 0x8598
#define PCI_DEVICE_ID_VIA_838X_1 0xB188