From b4f0b74ea37789eeeabe57b7ccd5808df076c081 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 25 Apr 2012 22:29:43 +0200 Subject: i2c: muxes: rename first set of drivers to a standard pattern Apply a naming pattern like in the rest of the subsystem to a first set of mux drivers. Those drivers are the low-hanging fruit; we want to pick them to motivate upcoming drivers to follow the new pattern. The missing GPIO driver will be converted in a later patch. Signed-off-by: Wolfram Sang Acked-by: Guenter Roeck (pca9541) Acked-by: Jean Delvare --- MAINTAINERS | 2 +- drivers/i2c/muxes/Kconfig | 4 +- drivers/i2c/muxes/Makefile | 4 +- drivers/i2c/muxes/i2c-mux-pca9541.c | 401 ++++++++++++++++++++++++++++++++++++ drivers/i2c/muxes/i2c-mux-pca954x.c | 291 ++++++++++++++++++++++++++ drivers/i2c/muxes/pca9541.c | 401 ------------------------------------ drivers/i2c/muxes/pca954x.c | 291 -------------------------- 7 files changed, 697 insertions(+), 697 deletions(-) create mode 100644 drivers/i2c/muxes/i2c-mux-pca9541.c create mode 100644 drivers/i2c/muxes/i2c-mux-pca954x.c delete mode 100644 drivers/i2c/muxes/pca9541.c delete mode 100644 drivers/i2c/muxes/pca954x.c diff --git a/MAINTAINERS b/MAINTAINERS index 7071633..f0c3b45 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5104,7 +5104,7 @@ PCA9541 I2C BUS MASTER SELECTOR DRIVER M: Guenter Roeck L: linux-i2c@vger.kernel.org S: Maintained -F: drivers/i2c/muxes/pca9541.c +F: drivers/i2c/muxes/i2c-mux-pca9541.c PCA9564/PCA9665 I2C BUS DRIVER M: Wolfram Sang diff --git a/drivers/i2c/muxes/Kconfig b/drivers/i2c/muxes/Kconfig index 90b7a01..e14a420 100644 --- a/drivers/i2c/muxes/Kconfig +++ b/drivers/i2c/muxes/Kconfig @@ -25,7 +25,7 @@ config I2C_MUX_PCA9541 I2C Master Selector. This driver can also be built as a module. If so, the module - will be called pca9541. + will be called i2c-mux-pca9541. config I2C_MUX_PCA954x tristate "Philips PCA954x I2C Mux/switches" @@ -35,6 +35,6 @@ config I2C_MUX_PCA954x I2C mux/switch devices. This driver can also be built as a module. If so, the module - will be called pca954x. + will be called i2c-mux-pca954x. endmenu diff --git a/drivers/i2c/muxes/Makefile b/drivers/i2c/muxes/Makefile index 4640436..0868335 100644 --- a/drivers/i2c/muxes/Makefile +++ b/drivers/i2c/muxes/Makefile @@ -2,7 +2,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 +obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o +obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c new file mode 100644 index 0000000..8aacde1 --- /dev/null +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c @@ -0,0 +1,401 @@ +/* + * I2C multiplexer driver for PCA9541 bus master selector + * + * Copyright (c) 2010 Ericsson AB. + * + * Author: Guenter Roeck + * + * Derived from: + * pca954x.c + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * The PCA9541 is a bus master selector. It supports two I2C masters connected + * to a single slave bus. + * + * Before each bus transaction, a master has to acquire bus ownership. After the + * transaction is complete, bus ownership has to be released. This fits well + * into the I2C multiplexer framework, which provides select and release + * functions for this purpose. For this reason, this driver is modeled as + * single-channel I2C bus multiplexer. + * + * This driver assumes that the two bus masters are controlled by two different + * hosts. If a single host controls both masters, platform code has to ensure + * that only one of the masters is instantiated at any given time. + */ + +#define PCA9541_CONTROL 0x01 +#define PCA9541_ISTAT 0x02 + +#define PCA9541_CTL_MYBUS (1 << 0) +#define PCA9541_CTL_NMYBUS (1 << 1) +#define PCA9541_CTL_BUSON (1 << 2) +#define PCA9541_CTL_NBUSON (1 << 3) +#define PCA9541_CTL_BUSINIT (1 << 4) +#define PCA9541_CTL_TESTON (1 << 6) +#define PCA9541_CTL_NTESTON (1 << 7) + +#define PCA9541_ISTAT_INTIN (1 << 0) +#define PCA9541_ISTAT_BUSINIT (1 << 1) +#define PCA9541_ISTAT_BUSOK (1 << 2) +#define PCA9541_ISTAT_BUSLOST (1 << 3) +#define PCA9541_ISTAT_MYTEST (1 << 6) +#define PCA9541_ISTAT_NMYTEST (1 << 7) + +#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) +#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) +#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) +#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) + +/* arbitration timeouts, in jiffies */ +#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ +#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ + +/* arbitration retry delays, in us */ +#define SELECT_DELAY_SHORT 50 +#define SELECT_DELAY_LONG 1000 + +struct pca9541 { + struct i2c_adapter *mux_adap; + unsigned long select_timeout; + unsigned long arb_timeout; +}; + +static const struct i2c_device_id pca9541_id[] = { + {"pca9541", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, pca9541_id); + +/* + * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock the adapter a second time. + */ +static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[2]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 2; + buf[0] = command; + buf[1] = val; + msg.buf = buf; + ret = adap->algo->master_xfer(adap, &msg, 1); + } else { + union i2c_smbus_data data; + + data.byte = val; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + command, + I2C_SMBUS_BYTE_DATA, &data); + } + + return ret; +} + +/* + * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() + * as they will try to lock adapter a second time. + */ +static int pca9541_reg_read(struct i2c_client *client, u8 command) +{ + struct i2c_adapter *adap = client->adapter; + int ret; + u8 val; + + if (adap->algo->master_xfer) { + struct i2c_msg msg[2] = { + { + .addr = client->addr, + .flags = 0, + .len = 1, + .buf = &command + }, + { + .addr = client->addr, + .flags = I2C_M_RD, + .len = 1, + .buf = &val + } + }; + ret = adap->algo->master_xfer(adap, msg, 2); + if (ret == 2) + ret = val; + else if (ret >= 0) + ret = -EIO; + } else { + union i2c_smbus_data data; + + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_READ, + command, + I2C_SMBUS_BYTE_DATA, &data); + if (!ret) + ret = data.byte; + } + return ret; +} + +/* + * Arbitration management functions + */ + +/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ +static void pca9541_release_bus(struct i2c_client *client) +{ + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg >= 0 && !busoff(reg) && mybus(reg)) + pca9541_reg_write(client, PCA9541_CONTROL, + (reg & PCA9541_CTL_NBUSON) >> 1); +} + +/* + * Arbitration is defined as a two-step process. A bus master can only activate + * the slave bus if it owns it; otherwise it has to request ownership first. + * This multi-step process ensures that access contention is resolved + * gracefully. + * + * Bus Ownership Other master Action + * state requested access + * ---------------------------------------------------- + * off - yes wait for arbitration timeout or + * for other master to drop request + * off no no take ownership + * off yes no turn on bus + * on yes - done + * on no - wait for arbitration timeout or + * for other master to release bus + * + * The main contention point occurs if the slave bus is off and both masters + * request ownership at the same time. In this case, one master will turn on + * the slave bus, believing that it owns it. The other master will request + * bus ownership. Result is that the bus is turned on, and master which did + * _not_ own the slave bus before ends up owning it. + */ + +/* Control commands per PCA9541 datasheet */ +static const u8 pca9541_control[16] = { + 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 +}; + +/* + * Channel arbitration + * + * Return values: + * <0: error + * 0 : bus not acquired + * 1 : bus acquired + */ +static int pca9541_arbitrate(struct i2c_client *client) +{ + struct pca9541 *data = i2c_get_clientdata(client); + int reg; + + reg = pca9541_reg_read(client, PCA9541_CONTROL); + if (reg < 0) + return reg; + + if (busoff(reg)) { + int istat; + /* + * Bus is off. Request ownership or turn it on unless + * other master requested ownership. + */ + istat = pca9541_reg_read(client, PCA9541_ISTAT); + if (!(istat & PCA9541_ISTAT_NMYTEST) + || time_is_before_eq_jiffies(data->arb_timeout)) { + /* + * Other master did not request ownership, + * or arbitration timeout expired. Take the bus. + */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_NTESTON); + data->select_timeout = SELECT_DELAY_SHORT; + } else { + /* + * Other master requested ownership. + * Set extra long timeout to give it time to acquire it. + */ + data->select_timeout = SELECT_DELAY_LONG * 2; + } + } else if (mybus(reg)) { + /* + * Bus is on, and we own it. We are done with acquisition. + * Reset NTESTON and BUSINIT, then return success. + */ + if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg & ~(PCA9541_CTL_NTESTON + | PCA9541_CTL_BUSINIT)); + return 1; + } else { + /* + * Other master owns the bus. + * If arbitration timeout has expired, force ownership. + * Otherwise request it. + */ + data->select_timeout = SELECT_DELAY_LONG; + if (time_is_before_eq_jiffies(data->arb_timeout)) { + /* Time is up, take the bus and reset it. */ + pca9541_reg_write(client, + PCA9541_CONTROL, + pca9541_control[reg & 0x0f] + | PCA9541_CTL_BUSINIT + | PCA9541_CTL_NTESTON); + } else { + /* Request bus ownership if needed */ + if (!(reg & PCA9541_CTL_NTESTON)) + pca9541_reg_write(client, + PCA9541_CONTROL, + reg | PCA9541_CTL_NTESTON); + } + } + return 0; +} + +static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan) +{ + struct pca9541 *data = i2c_get_clientdata(client); + int ret; + unsigned long timeout = jiffies + ARB2_TIMEOUT; + /* give up after this time */ + + data->arb_timeout = jiffies + ARB_TIMEOUT; + /* force bus ownership after this time */ + + do { + ret = pca9541_arbitrate(client); + if (ret) + return ret < 0 ? ret : 0; + + if (data->select_timeout == SELECT_DELAY_SHORT) + udelay(data->select_timeout); + else + msleep(data->select_timeout / 1000); + } while (time_is_after_eq_jiffies(timeout)); + + return -ETIMEDOUT; +} + +static int pca9541_release_chan(struct i2c_adapter *adap, + void *client, u32 chan) +{ + pca9541_release_bus(client); + return 0; +} + +/* + * I2C init/probing/exit functions + */ +static int pca9541_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = client->adapter; + struct pca954x_platform_data *pdata = client->dev.platform_data; + struct pca9541 *data; + int force; + int ret = -ENODEV; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) + goto err; + + data = kzalloc(sizeof(struct pca9541), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto err; + } + + i2c_set_clientdata(client, data); + + /* + * I2C accesses are unprotected here. + * We have to lock the adapter before releasing the bus. + */ + i2c_lock_adapter(adap); + pca9541_release_bus(client); + i2c_unlock_adapter(adap); + + /* Create mux adapter */ + + force = 0; + if (pdata) + force = pdata->modes[0].adap_id; + data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client, + force, 0, + pca9541_select_chan, + pca9541_release_chan); + + if (data->mux_adap == NULL) { + dev_err(&client->dev, "failed to register master selector\n"); + goto exit_free; + } + + dev_info(&client->dev, "registered master selector for I2C %s\n", + client->name); + + return 0; + +exit_free: + kfree(data); +err: + return ret; +} + +static int pca9541_remove(struct i2c_client *client) +{ + struct pca9541 *data = i2c_get_clientdata(client); + + i2c_del_mux_adapter(data->mux_adap); + + kfree(data); + return 0; +} + +static struct i2c_driver pca9541_driver = { + .driver = { + .name = "pca9541", + .owner = THIS_MODULE, + }, + .probe = pca9541_probe, + .remove = pca9541_remove, + .id_table = pca9541_id, +}; + +module_i2c_driver(pca9541_driver); + +MODULE_AUTHOR("Guenter Roeck "); +MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c new file mode 100644 index 0000000..f2dfe0d --- /dev/null +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -0,0 +1,291 @@ +/* + * I2C multiplexer + * + * Copyright (c) 2008-2009 Rodolfo Giometti + * Copyright (c) 2008-2009 Eurotech S.p.A. + * + * This module supports the PCA954x series of I2C multiplexer/switch chips + * made by Philips Semiconductors. + * This includes the: + * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 + * and PCA9548. + * + * These chips are all controlled via the I2C bus itself, and all have a + * single 8-bit register. The upstream "parent" bus fans out to two, + * four, or eight downstream busses or channels; which of these + * are selected is determined by the chip type and register contents. A + * mux can select only one sub-bus at a time; a switch can select any + * combination simultaneously. + * + * Based on: + * pca954x.c from Kumar Gala + * Copyright (C) 2006 + * + * Based on: + * pca954x.c from Ken Harrenstien + * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) + * + * Based on: + * i2c-virtual_cb.c from Brian Kuschak + * and + * pca9540.c from Jean Delvare . + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define PCA954X_MAX_NCHANS 8 + +enum pca_type { + pca_9540, + pca_9542, + pca_9543, + pca_9544, + pca_9545, + pca_9546, + pca_9547, + pca_9548, +}; + +struct pca954x { + enum pca_type type; + struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; + + u8 last_chan; /* last register value */ +}; + +struct chip_desc { + u8 nchans; + u8 enable; /* used for muxes only */ + enum muxtype { + pca954x_ismux = 0, + pca954x_isswi + } muxtype; +}; + +/* Provide specs for the PCA954x types we know about */ +static const struct chip_desc chips[] = { + [pca_9540] = { + .nchans = 2, + .enable = 0x4, + .muxtype = pca954x_ismux, + }, + [pca_9543] = { + .nchans = 2, + .muxtype = pca954x_isswi, + }, + [pca_9544] = { + .nchans = 4, + .enable = 0x4, + .muxtype = pca954x_ismux, + }, + [pca_9545] = { + .nchans = 4, + .muxtype = pca954x_isswi, + }, + [pca_9547] = { + .nchans = 8, + .enable = 0x8, + .muxtype = pca954x_ismux, + }, + [pca_9548] = { + .nchans = 8, + .muxtype = pca954x_isswi, + }, +}; + +static const struct i2c_device_id pca954x_id[] = { + { "pca9540", pca_9540 }, + { "pca9542", pca_9540 }, + { "pca9543", pca_9543 }, + { "pca9544", pca_9544 }, + { "pca9545", pca_9545 }, + { "pca9546", pca_9545 }, + { "pca9547", pca_9547 }, + { "pca9548", pca_9548 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, pca954x_id); + +/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() + for this as they will try to lock adapter a second time */ +static int pca954x_reg_write(struct i2c_adapter *adap, + struct i2c_client *client, u8 val) +{ + int ret = -ENODEV; + + if (adap->algo->master_xfer) { + struct i2c_msg msg; + char buf[1]; + + msg.addr = client->addr; + msg.flags = 0; + msg.len = 1; + buf[0] = val; + msg.buf = buf; + ret = adap->algo->master_xfer(adap, &msg, 1); + } else { + union i2c_smbus_data data; + ret = adap->algo->smbus_xfer(adap, client->addr, + client->flags, + I2C_SMBUS_WRITE, + val, I2C_SMBUS_BYTE, &data); + } + + return ret; +} + +static int pca954x_select_chan(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + const struct chip_desc *chip = &chips[data->type]; + u8 regval; + int ret = 0; + + /* we make switches look like muxes, not sure how to be smarter */ + if (chip->muxtype == pca954x_ismux) + regval = chan | chip->enable; + else + regval = 1 << chan; + + /* Only select the channel if its different from the last channel */ + if (data->last_chan != regval) { + ret = pca954x_reg_write(adap, client, regval); + data->last_chan = regval; + } + + return ret; +} + +static int pca954x_deselect_mux(struct i2c_adapter *adap, + void *client, u32 chan) +{ + struct pca954x *data = i2c_get_clientdata(client); + + /* Deselect active channel */ + data->last_chan = 0; + return pca954x_reg_write(adap, client, data->last_chan); +} + +/* + * I2C init/probing/exit functions + */ +static int pca954x_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); + struct pca954x_platform_data *pdata = client->dev.platform_data; + int num, force; + struct pca954x *data; + int ret = -ENODEV; + + if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) + goto err; + + data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto err; + } + + i2c_set_clientdata(client, data); + + /* Write the mux register at addr to verify + * that the mux is in fact present. This also + * initializes the mux to disconnected state. + */ + if (i2c_smbus_write_byte(client, 0) < 0) { + dev_warn(&client->dev, "probe failed\n"); + goto exit_free; + } + + data->type = id->driver_data; + data->last_chan = 0; /* force the first selection */ + + /* Now create an adapter for each channel */ + for (num = 0; num < chips[data->type].nchans; num++) { + force = 0; /* dynamic adap number */ + if (pdata) { + if (num < pdata->num_modes) + /* force static number */ + force = pdata->modes[num].adap_id; + else + /* discard unconfigured channels */ + break; + } + + data->virt_adaps[num] = + i2c_add_mux_adapter(adap, &client->dev, client, + force, num, pca954x_select_chan, + (pdata && pdata->modes[num].deselect_on_exit) + ? pca954x_deselect_mux : NULL); + + if (data->virt_adaps[num] == NULL) { + ret = -ENODEV; + dev_err(&client->dev, + "failed to register multiplexed adapter" + " %d as bus %d\n", num, force); + goto virt_reg_failed; + } + } + + dev_info(&client->dev, + "registered %d multiplexed busses for I2C %s %s\n", + num, chips[data->type].muxtype == pca954x_ismux + ? "mux" : "switch", client->name); + + return 0; + +virt_reg_failed: + for (num--; num >= 0; num--) + i2c_del_mux_adapter(data->virt_adaps[num]); +exit_free: + kfree(data); +err: + return ret; +} + +static int pca954x_remove(struct i2c_client *client) +{ + struct pca954x *data = i2c_get_clientdata(client); + const struct chip_desc *chip = &chips[data->type]; + int i, err; + + for (i = 0; i < chip->nchans; ++i) + if (data->virt_adaps[i]) { + err = i2c_del_mux_adapter(data->virt_adaps[i]); + if (err) + return err; + data->virt_adaps[i] = NULL; + } + + kfree(data); + return 0; +} + +static struct i2c_driver pca954x_driver = { + .driver = { + .name = "pca954x", + .owner = THIS_MODULE, + }, + .probe = pca954x_probe, + .remove = pca954x_remove, + .id_table = pca954x_id, +}; + +module_i2c_driver(pca954x_driver); + +MODULE_AUTHOR("Rodolfo Giometti "); +MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/muxes/pca9541.c b/drivers/i2c/muxes/pca9541.c deleted file mode 100644 index 8aacde1..0000000 --- a/drivers/i2c/muxes/pca9541.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * I2C multiplexer driver for PCA9541 bus master selector - * - * Copyright (c) 2010 Ericsson AB. - * - * Author: Guenter Roeck - * - * Derived from: - * pca954x.c - * - * Copyright (c) 2008-2009 Rodolfo Giometti - * Copyright (c) 2008-2009 Eurotech S.p.A. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * The PCA9541 is a bus master selector. It supports two I2C masters connected - * to a single slave bus. - * - * Before each bus transaction, a master has to acquire bus ownership. After the - * transaction is complete, bus ownership has to be released. This fits well - * into the I2C multiplexer framework, which provides select and release - * functions for this purpose. For this reason, this driver is modeled as - * single-channel I2C bus multiplexer. - * - * This driver assumes that the two bus masters are controlled by two different - * hosts. If a single host controls both masters, platform code has to ensure - * that only one of the masters is instantiated at any given time. - */ - -#define PCA9541_CONTROL 0x01 -#define PCA9541_ISTAT 0x02 - -#define PCA9541_CTL_MYBUS (1 << 0) -#define PCA9541_CTL_NMYBUS (1 << 1) -#define PCA9541_CTL_BUSON (1 << 2) -#define PCA9541_CTL_NBUSON (1 << 3) -#define PCA9541_CTL_BUSINIT (1 << 4) -#define PCA9541_CTL_TESTON (1 << 6) -#define PCA9541_CTL_NTESTON (1 << 7) - -#define PCA9541_ISTAT_INTIN (1 << 0) -#define PCA9541_ISTAT_BUSINIT (1 << 1) -#define PCA9541_ISTAT_BUSOK (1 << 2) -#define PCA9541_ISTAT_BUSLOST (1 << 3) -#define PCA9541_ISTAT_MYTEST (1 << 6) -#define PCA9541_ISTAT_NMYTEST (1 << 7) - -#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) -#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) -#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) -#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) - -/* arbitration timeouts, in jiffies */ -#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ -#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ - -/* arbitration retry delays, in us */ -#define SELECT_DELAY_SHORT 50 -#define SELECT_DELAY_LONG 1000 - -struct pca9541 { - struct i2c_adapter *mux_adap; - unsigned long select_timeout; - unsigned long arb_timeout; -}; - -static const struct i2c_device_id pca9541_id[] = { - {"pca9541", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, pca9541_id); - -/* - * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() - * as they will try to lock the adapter a second time. - */ -static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) -{ - struct i2c_adapter *adap = client->adapter; - int ret; - - if (adap->algo->master_xfer) { - struct i2c_msg msg; - char buf[2]; - - msg.addr = client->addr; - msg.flags = 0; - msg.len = 2; - buf[0] = command; - buf[1] = val; - msg.buf = buf; - ret = adap->algo->master_xfer(adap, &msg, 1); - } else { - union i2c_smbus_data data; - - data.byte = val; - ret = adap->algo->smbus_xfer(adap, client->addr, - client->flags, - I2C_SMBUS_WRITE, - command, - I2C_SMBUS_BYTE_DATA, &data); - } - - return ret; -} - -/* - * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() - * as they will try to lock adapter a second time. - */ -static int pca9541_reg_read(struct i2c_client *client, u8 command) -{ - struct i2c_adapter *adap = client->adapter; - int ret; - u8 val; - - if (adap->algo->master_xfer) { - struct i2c_msg msg[2] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = &command - }, - { - .addr = client->addr, - .flags = I2C_M_RD, - .len = 1, - .buf = &val - } - }; - ret = adap->algo->master_xfer(adap, msg, 2); - if (ret == 2) - ret = val; - else if (ret >= 0) - ret = -EIO; - } else { - union i2c_smbus_data data; - - ret = adap->algo->smbus_xfer(adap, client->addr, - client->flags, - I2C_SMBUS_READ, - command, - I2C_SMBUS_BYTE_DATA, &data); - if (!ret) - ret = data.byte; - } - return ret; -} - -/* - * Arbitration management functions - */ - -/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ -static void pca9541_release_bus(struct i2c_client *client) -{ - int reg; - - reg = pca9541_reg_read(client, PCA9541_CONTROL); - if (reg >= 0 && !busoff(reg) && mybus(reg)) - pca9541_reg_write(client, PCA9541_CONTROL, - (reg & PCA9541_CTL_NBUSON) >> 1); -} - -/* - * Arbitration is defined as a two-step process. A bus master can only activate - * the slave bus if it owns it; otherwise it has to request ownership first. - * This multi-step process ensures that access contention is resolved - * gracefully. - * - * Bus Ownership Other master Action - * state requested access - * ---------------------------------------------------- - * off - yes wait for arbitration timeout or - * for other master to drop request - * off no no take ownership - * off yes no turn on bus - * on yes - done - * on no - wait for arbitration timeout or - * for other master to release bus - * - * The main contention point occurs if the slave bus is off and both masters - * request ownership at the same time. In this case, one master will turn on - * the slave bus, believing that it owns it. The other master will request - * bus ownership. Result is that the bus is turned on, and master which did - * _not_ own the slave bus before ends up owning it. - */ - -/* Control commands per PCA9541 datasheet */ -static const u8 pca9541_control[16] = { - 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 -}; - -/* - * Channel arbitration - * - * Return values: - * <0: error - * 0 : bus not acquired - * 1 : bus acquired - */ -static int pca9541_arbitrate(struct i2c_client *client) -{ - struct pca9541 *data = i2c_get_clientdata(client); - int reg; - - reg = pca9541_reg_read(client, PCA9541_CONTROL); - if (reg < 0) - return reg; - - if (busoff(reg)) { - int istat; - /* - * Bus is off. Request ownership or turn it on unless - * other master requested ownership. - */ - istat = pca9541_reg_read(client, PCA9541_ISTAT); - if (!(istat & PCA9541_ISTAT_NMYTEST) - || time_is_before_eq_jiffies(data->arb_timeout)) { - /* - * Other master did not request ownership, - * or arbitration timeout expired. Take the bus. - */ - pca9541_reg_write(client, - PCA9541_CONTROL, - pca9541_control[reg & 0x0f] - | PCA9541_CTL_NTESTON); - data->select_timeout = SELECT_DELAY_SHORT; - } else { - /* - * Other master requested ownership. - * Set extra long timeout to give it time to acquire it. - */ - data->select_timeout = SELECT_DELAY_LONG * 2; - } - } else if (mybus(reg)) { - /* - * Bus is on, and we own it. We are done with acquisition. - * Reset NTESTON and BUSINIT, then return success. - */ - if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) - pca9541_reg_write(client, - PCA9541_CONTROL, - reg & ~(PCA9541_CTL_NTESTON - | PCA9541_CTL_BUSINIT)); - return 1; - } else { - /* - * Other master owns the bus. - * If arbitration timeout has expired, force ownership. - * Otherwise request it. - */ - data->select_timeout = SELECT_DELAY_LONG; - if (time_is_before_eq_jiffies(data->arb_timeout)) { - /* Time is up, take the bus and reset it. */ - pca9541_reg_write(client, - PCA9541_CONTROL, - pca9541_control[reg & 0x0f] - | PCA9541_CTL_BUSINIT - | PCA9541_CTL_NTESTON); - } else { - /* Request bus ownership if needed */ - if (!(reg & PCA9541_CTL_NTESTON)) - pca9541_reg_write(client, - PCA9541_CONTROL, - reg | PCA9541_CTL_NTESTON); - } - } - return 0; -} - -static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan) -{ - struct pca9541 *data = i2c_get_clientdata(client); - int ret; - unsigned long timeout = jiffies + ARB2_TIMEOUT; - /* give up after this time */ - - data->arb_timeout = jiffies + ARB_TIMEOUT; - /* force bus ownership after this time */ - - do { - ret = pca9541_arbitrate(client); - if (ret) - return ret < 0 ? ret : 0; - - if (data->select_timeout == SELECT_DELAY_SHORT) - udelay(data->select_timeout); - else - msleep(data->select_timeout / 1000); - } while (time_is_after_eq_jiffies(timeout)); - - return -ETIMEDOUT; -} - -static int pca9541_release_chan(struct i2c_adapter *adap, - void *client, u32 chan) -{ - pca9541_release_bus(client); - return 0; -} - -/* - * I2C init/probing/exit functions - */ -static int pca9541_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adap = client->adapter; - struct pca954x_platform_data *pdata = client->dev.platform_data; - struct pca9541 *data; - int force; - int ret = -ENODEV; - - if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) - goto err; - - data = kzalloc(sizeof(struct pca9541), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err; - } - - i2c_set_clientdata(client, data); - - /* - * I2C accesses are unprotected here. - * We have to lock the adapter before releasing the bus. - */ - i2c_lock_adapter(adap); - pca9541_release_bus(client); - i2c_unlock_adapter(adap); - - /* Create mux adapter */ - - force = 0; - if (pdata) - force = pdata->modes[0].adap_id; - data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client, - force, 0, - pca9541_select_chan, - pca9541_release_chan); - - if (data->mux_adap == NULL) { - dev_err(&client->dev, "failed to register master selector\n"); - goto exit_free; - } - - dev_info(&client->dev, "registered master selector for I2C %s\n", - client->name); - - return 0; - -exit_free: - kfree(data); -err: - return ret; -} - -static int pca9541_remove(struct i2c_client *client) -{ - struct pca9541 *data = i2c_get_clientdata(client); - - i2c_del_mux_adapter(data->mux_adap); - - kfree(data); - return 0; -} - -static struct i2c_driver pca9541_driver = { - .driver = { - .name = "pca9541", - .owner = THIS_MODULE, - }, - .probe = pca9541_probe, - .remove = pca9541_remove, - .id_table = pca9541_id, -}; - -module_i2c_driver(pca9541_driver); - -MODULE_AUTHOR("Guenter Roeck "); -MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c deleted file mode 100644 index f2dfe0d..0000000 --- a/drivers/i2c/muxes/pca954x.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * I2C multiplexer - * - * Copyright (c) 2008-2009 Rodolfo Giometti - * Copyright (c) 2008-2009 Eurotech S.p.A. - * - * This module supports the PCA954x series of I2C multiplexer/switch chips - * made by Philips Semiconductors. - * This includes the: - * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 - * and PCA9548. - * - * These chips are all controlled via the I2C bus itself, and all have a - * single 8-bit register. The upstream "parent" bus fans out to two, - * four, or eight downstream busses or channels; which of these - * are selected is determined by the chip type and register contents. A - * mux can select only one sub-bus at a time; a switch can select any - * combination simultaneously. - * - * Based on: - * pca954x.c from Kumar Gala - * Copyright (C) 2006 - * - * Based on: - * pca954x.c from Ken Harrenstien - * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) - * - * Based on: - * i2c-virtual_cb.c from Brian Kuschak - * and - * pca9540.c from Jean Delvare . - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define PCA954X_MAX_NCHANS 8 - -enum pca_type { - pca_9540, - pca_9542, - pca_9543, - pca_9544, - pca_9545, - pca_9546, - pca_9547, - pca_9548, -}; - -struct pca954x { - enum pca_type type; - struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; - - u8 last_chan; /* last register value */ -}; - -struct chip_desc { - u8 nchans; - u8 enable; /* used for muxes only */ - enum muxtype { - pca954x_ismux = 0, - pca954x_isswi - } muxtype; -}; - -/* Provide specs for the PCA954x types we know about */ -static const struct chip_desc chips[] = { - [pca_9540] = { - .nchans = 2, - .enable = 0x4, - .muxtype = pca954x_ismux, - }, - [pca_9543] = { - .nchans = 2, - .muxtype = pca954x_isswi, - }, - [pca_9544] = { - .nchans = 4, - .enable = 0x4, - .muxtype = pca954x_ismux, - }, - [pca_9545] = { - .nchans = 4, - .muxtype = pca954x_isswi, - }, - [pca_9547] = { - .nchans = 8, - .enable = 0x8, - .muxtype = pca954x_ismux, - }, - [pca_9548] = { - .nchans = 8, - .muxtype = pca954x_isswi, - }, -}; - -static const struct i2c_device_id pca954x_id[] = { - { "pca9540", pca_9540 }, - { "pca9542", pca_9540 }, - { "pca9543", pca_9543 }, - { "pca9544", pca_9544 }, - { "pca9545", pca_9545 }, - { "pca9546", pca_9545 }, - { "pca9547", pca_9547 }, - { "pca9548", pca_9548 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, pca954x_id); - -/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() - for this as they will try to lock adapter a second time */ -static int pca954x_reg_write(struct i2c_adapter *adap, - struct i2c_client *client, u8 val) -{ - int ret = -ENODEV; - - if (adap->algo->master_xfer) { - struct i2c_msg msg; - char buf[1]; - - msg.addr = client->addr; - msg.flags = 0; - msg.len = 1; - buf[0] = val; - msg.buf = buf; - ret = adap->algo->master_xfer(adap, &msg, 1); - } else { - union i2c_smbus_data data; - ret = adap->algo->smbus_xfer(adap, client->addr, - client->flags, - I2C_SMBUS_WRITE, - val, I2C_SMBUS_BYTE, &data); - } - - return ret; -} - -static int pca954x_select_chan(struct i2c_adapter *adap, - void *client, u32 chan) -{ - struct pca954x *data = i2c_get_clientdata(client); - const struct chip_desc *chip = &chips[data->type]; - u8 regval; - int ret = 0; - - /* we make switches look like muxes, not sure how to be smarter */ - if (chip->muxtype == pca954x_ismux) - regval = chan | chip->enable; - else - regval = 1 << chan; - - /* Only select the channel if its different from the last channel */ - if (data->last_chan != regval) { - ret = pca954x_reg_write(adap, client, regval); - data->last_chan = regval; - } - - return ret; -} - -static int pca954x_deselect_mux(struct i2c_adapter *adap, - void *client, u32 chan) -{ - struct pca954x *data = i2c_get_clientdata(client); - - /* Deselect active channel */ - data->last_chan = 0; - return pca954x_reg_write(adap, client, data->last_chan); -} - -/* - * I2C init/probing/exit functions - */ -static int pca954x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); - struct pca954x_platform_data *pdata = client->dev.platform_data; - int num, force; - struct pca954x *data; - int ret = -ENODEV; - - if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) - goto err; - - data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err; - } - - i2c_set_clientdata(client, data); - - /* Write the mux register at addr to verify - * that the mux is in fact present. This also - * initializes the mux to disconnected state. - */ - if (i2c_smbus_write_byte(client, 0) < 0) { - dev_warn(&client->dev, "probe failed\n"); - goto exit_free; - } - - data->type = id->driver_data; - data->last_chan = 0; /* force the first selection */ - - /* Now create an adapter for each channel */ - for (num = 0; num < chips[data->type].nchans; num++) { - force = 0; /* dynamic adap number */ - if (pdata) { - if (num < pdata->num_modes) - /* force static number */ - force = pdata->modes[num].adap_id; - else - /* discard unconfigured channels */ - break; - } - - data->virt_adaps[num] = - i2c_add_mux_adapter(adap, &client->dev, client, - force, num, pca954x_select_chan, - (pdata && pdata->modes[num].deselect_on_exit) - ? pca954x_deselect_mux : NULL); - - if (data->virt_adaps[num] == NULL) { - ret = -ENODEV; - dev_err(&client->dev, - "failed to register multiplexed adapter" - " %d as bus %d\n", num, force); - goto virt_reg_failed; - } - } - - dev_info(&client->dev, - "registered %d multiplexed busses for I2C %s %s\n", - num, chips[data->type].muxtype == pca954x_ismux - ? "mux" : "switch", client->name); - - return 0; - -virt_reg_failed: - for (num--; num >= 0; num--) - i2c_del_mux_adapter(data->virt_adaps[num]); -exit_free: - kfree(data); -err: - return ret; -} - -static int pca954x_remove(struct i2c_client *client) -{ - struct pca954x *data = i2c_get_clientdata(client); - const struct chip_desc *chip = &chips[data->type]; - int i, err; - - for (i = 0; i < chip->nchans; ++i) - if (data->virt_adaps[i]) { - err = i2c_del_mux_adapter(data->virt_adaps[i]); - if (err) - return err; - data->virt_adaps[i] = NULL; - } - - kfree(data); - return 0; -} - -static struct i2c_driver pca954x_driver = { - .driver = { - .name = "pca954x", - .owner = THIS_MODULE, - }, - .probe = pca954x_probe, - .remove = pca954x_remove, - .id_table = pca954x_id, -}; - -module_i2c_driver(pca954x_driver); - -MODULE_AUTHOR("Rodolfo Giometti "); -MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); -MODULE_LICENSE("GPL v2"); -- cgit v1.1