提交 ae32adc1 编写于 作者: L Linus Torvalds

Merge branch 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux

Pull i2c-embedded changes from Wolfram Sang:
 "Major changes:

   - lots of devicetree additions for existing drivers.  I tried hard to
     make sure the bindings are proper.  In more complicated cases, I
     requested acks from people having more experience with them than
     me.  That took a bit of extra time and also some time went into
     discussions with developers about what bindings are and what not.
     I have the feeling that the workflow with bindings should be
     improved to scale better.  I will spend some more thought on
     this...

   - i2c-muxes are succesfully used meanwhile, so we dropped
     EXPERIMENTAL for them and renamed the drivers to a standard pattern
     to match the rest of the subsystem.  They can also be used with
     devicetree now.

   - ixp2000 was removed since the whole platform goes away.

   - cleanups (strlcpy instead of strcpy, NULL instead of 0)

   - The rest is typical driver fixes I assume.

  All patches have been in linux-next at least since v3.4-rc6."

Fixed up trivial conflict in arch/arm/mach-lpc32xx/common.c due to the
same patch already having come in through the arm/soc trees, with
additional patches on top of it.

* 'i2c-embedded/for-next' of git://git.pengutronix.de/git/wsa/linux: (35 commits)
  i2c: davinci: Free requested IRQ in remove
  i2c: ocores: register OF i2c devices
  i2c: tegra: notify transfer-complete after clearing status.
  I2C: xiic: Add OF binding support
  i2c: Rename last mux driver to standard pattern
  i2c: tegra: fix 10bit address configuration
  i2c: muxes: rename first set of drivers to a standard pattern
  of/i2c: implement of_find_i2c_adapter_by_node
  i2c: implement i2c_verify_adapter
  i2c-s3c2410: Add HDMIPHY quirk for S3C2440
  i2c-s3c2410: Rework device type handling
  i2c: muxes are not EXPERIMENTAL anymore
  i2c/of: Automatically populate i2c mux busses from device tree data.
  i2c: Add a struct device * parameter to i2c_add_mux_adapter()
  of/i2c: call i2c_verify_client from of_find_i2c_device_by_node
  i2c: designware: Add clk_{un}prepare() support
  i2c: designware: add PM support
  i2c: ixp2000: remove driver
  i2c: pnx: add device tree support
  i2c: imx: don't use strcpy but strlcpy
  ...
Common i2c bus multiplexer/switch properties.
An i2c bus multiplexer/switch will have several child busses that are
numbered uniquely in a device dependent manner. The nodes for an i2c bus
multiplexer/switch will have one child node for each child
bus.
Required properties:
- #address-cells = <1>;
- #size-cells = <0>;
Required properties for child nodes:
- #address-cells = <1>;
- #size-cells = <0>;
- reg : The sub-bus number.
Optional properties for child nodes:
- Other properties specific to the multiplexer/switch hardware.
- Child nodes conforming to i2c bus binding
Example :
/*
An NXP pca9548 8 channel I2C multiplexer at address 0x70
with two NXP pca8574 GPIO expanders attached, one each to
ports 3 and 4.
*/
mux@70 {
compatible = "nxp,pca9548";
reg = <0x70>;
#address-cells = <1>;
#size-cells = <0>;
i2c@3 {
#address-cells = <1>;
#size-cells = <0>;
reg = <3>;
gpio1: gpio@38 {
compatible = "nxp,pca8574";
reg = <0x38>;
#gpio-cells = <2>;
gpio-controller;
};
};
i2c@4 {
#address-cells = <1>;
#size-cells = <0>;
reg = <4>;
gpio2: gpio@38 {
compatible = "nxp,pca8574";
reg = <0x38>;
#gpio-cells = <2>;
gpio-controller;
};
};
};
......@@ -6,14 +6,18 @@ Required properties:
- compatible: value should be either of the following.
(a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
(b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 i2c.
(c) "samsung, s3c2440-hdmiphy-i2c", for s3c2440-like i2c used
inside HDMIPHY block found on several samsung SoCs
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: interrupt number to the cpu.
- samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges.
- gpios: The order of the gpios should be the following: <SDA, SCL>.
The gpio specifier depends on the gpio controller.
Optional properties:
- gpios: The order of the gpios should be the following: <SDA, SCL>.
The gpio specifier depends on the gpio controller. Required in all
cases except for "samsung,s3c2440-hdmiphy-i2c" whose input/output
lines are permanently wired to the respective client
- samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
specified, default value is 0.
- samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not
......
Xilinx IIC controller:
Required properties:
- compatible : Must be "xlnx,xps-iic-2.00.a"
- reg : IIC register location and length
- interrupts : IIC controller unterrupt
- #address-cells = <1>
- #size-cells = <0>
Optional properties:
- Child nodes conforming to i2c bus binding
Example:
axi_iic_0: i2c@40800000 {
compatible = "xlnx,xps-iic-2.00.a";
interrupts = < 1 2 >;
reg = < 0x40800000 0x10000 >;
#size-cells = <0>;
#address-cells = <1>;
};
Kernel driver gpio-i2cmux
Kernel driver i2c-gpio-mux
Author: Peter Korsgaard <peter.korsgaard@barco.com>
Description
-----------
gpio-i2cmux is an i2c mux driver providing access to I2C bus segments
i2c-gpio-mux 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.:
......@@ -26,16 +26,16 @@ according to the settings of the GPIO pins 1..N.
Usage
-----
gpio-i2cmux uses the platform bus, so you need to provide a struct
i2c-gpio-mux 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.
to control it. See include/linux/i2c-gpio-mux.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/i2c-gpio-mux.h>
#include <linux/platform_device.h>
static const unsigned myboard_gpiomux_gpios[] = {
......@@ -57,7 +57,7 @@ static struct gpio_i2cmux_platform_data myboard_i2cmux_data = {
};
static struct platform_device myboard_i2cmux = {
.name = "gpio-i2cmux",
.name = "i2c-gpio-mux",
.id = 0,
.dev = {
.platform_data = &myboard_i2cmux_data,
......
......@@ -2988,9 +2988,9 @@ GENERIC GPIO I2C MULTIPLEXER DRIVER
M: Peter Korsgaard <peter.korsgaard@barco.com>
L: linux-i2c@vger.kernel.org
S: Supported
F: drivers/i2c/muxes/gpio-i2cmux.c
F: include/linux/gpio-i2cmux.h
F: Documentation/i2c/muxes/gpio-i2cmux
F: drivers/i2c/muxes/i2c-mux-gpio.c
F: include/linux/i2c-mux-gpio.h
F: Documentation/i2c/muxes/i2c-mux-gpio
GENERIC HDLC (WAN) DRIVERS
M: Krzysztof Halasa <khc@pm.waw.pl>
......@@ -5148,7 +5148,7 @@ PCA9541 I2C BUS MASTER SELECTOR DRIVER
M: Guenter Roeck <guenter.roeck@ericsson.com>
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 <w.sang@pengutronix.de>
......
......@@ -49,7 +49,6 @@ config I2C_CHARDEV
config I2C_MUX
tristate "I2C bus multiplexing support"
depends on EXPERIMENTAL
help
Say Y here if you want the I2C core to support the ability to
handle multiplexed I2C bus topologies, by presenting each
......
......@@ -445,20 +445,6 @@ config I2C_IOP3XX
This driver can also be built as a module. If so, the module
will be called i2c-iop3xx.
config I2C_IXP2000
tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
depends on ARCH_IXP2000
select I2C_ALGOBIT
help
Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
system and are using GPIO lines for an I2C bus.
This support is also available as a module. If so, the module
will be called i2c-ixp2000.
This driver is deprecated and will be dropped soon. Use i2c-gpio
instead.
config I2C_MPC
tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
depends on PPC
......
......@@ -44,7 +44,6 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IMX) += i2c-imx.o
obj-$(CONFIG_I2C_INTEL_MID) += i2c-intel-mid.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
......
......@@ -755,7 +755,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
dev->clk = NULL;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
free_irq(IRQ_I2C, dev);
free_irq(dev->irq, dev);
iounmap(dev->base);
kfree(dev);
......
......@@ -164,9 +164,15 @@ static char *abort_sources[] = {
u32 dw_readl(struct dw_i2c_dev *dev, int offset)
{
u32 value = readl(dev->base + offset);
u32 value;
if (dev->swab)
if (dev->accessor_flags & ACCESS_16BIT)
value = readw(dev->base + offset) |
(readw(dev->base + offset + 2) << 16);
else
value = readl(dev->base + offset);
if (dev->accessor_flags & ACCESS_SWAP)
return swab32(value);
else
return value;
......@@ -174,10 +180,15 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset)
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
{
if (dev->swab)
if (dev->accessor_flags & ACCESS_SWAP)
b = swab32(b);
writel(b, dev->base + offset);
if (dev->accessor_flags & ACCESS_16BIT) {
writew((u16)b, dev->base + offset);
writew((u16)(b >> 16), dev->base + offset + 2);
} else {
writel(b, dev->base + offset);
}
}
static u32
......@@ -251,14 +262,14 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
input_clock_khz = dev->get_clk_rate_khz(dev);
/* Configure register endianess access */
reg = dw_readl(dev, DW_IC_COMP_TYPE);
if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
dev->swab = 1;
reg = DW_IC_COMP_TYPE_VALUE;
}
if (reg != DW_IC_COMP_TYPE_VALUE) {
/* Configure register endianess access */
dev->accessor_flags |= ACCESS_SWAP;
} else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
/* Configure register access mode 16bit */
dev->accessor_flags |= ACCESS_16BIT;
} else if (reg != DW_IC_COMP_TYPE_VALUE) {
dev_err(dev->dev, "Unknown Synopsys component type: "
"0x%08x\n", reg);
return -ENODEV;
......
......@@ -82,7 +82,7 @@ struct dw_i2c_dev {
unsigned int status;
u32 abort_source;
int irq;
int swab;
u32 accessor_flags;
struct i2c_adapter adapter;
u32 functionality;
u32 master_cfg;
......@@ -90,6 +90,9 @@ struct dw_i2c_dev {
unsigned int rx_fifo_depth;
};
#define ACCESS_SWAP 0x00000001
#define ACCESS_16BIT 0x00000002
extern u32 dw_readl(struct dw_i2c_dev *dev, int offset);
extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset);
extern int i2c_dw_init(struct dw_i2c_dev *dev);
......
......@@ -36,6 +36,7 @@
#include <linux/interrupt.h>
#include <linux/of_i2c.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/io.h>
#include <linux/slab.h>
#include "i2c-designware-core.h"
......@@ -95,7 +96,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
r = -ENODEV;
goto err_free_mem;
}
clk_enable(dev->clk);
clk_prepare_enable(dev->clk);
dev->functionality =
I2C_FUNC_I2C |
......@@ -155,7 +156,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
err_iounmap:
iounmap(dev->base);
err_unuse_clocks:
clk_disable(dev->clk);
clk_disable_unprepare(dev->clk);
clk_put(dev->clk);
dev->clk = NULL;
err_free_mem:
......@@ -177,7 +178,7 @@ static int __devexit dw_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&dev->adapter);
put_device(&pdev->dev);
clk_disable(dev->clk);
clk_disable_unprepare(dev->clk);
clk_put(dev->clk);
dev->clk = NULL;
......@@ -198,6 +199,31 @@ static const struct of_device_id dw_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
#endif
#ifdef CONFIG_PM
static int dw_i2c_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
clk_disable_unprepare(i_dev->clk);
return 0;
}
static int dw_i2c_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
clk_prepare_enable(i_dev->clk);
i2c_dw_init(i_dev);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume);
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:i2c_designware");
......@@ -207,6 +233,7 @@ static struct platform_driver dw_i2c_driver = {
.name = "i2c_designware",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(dw_i2c_of_match),
.pm = &dw_i2c_dev_pm_ops,
},
};
......
......@@ -263,11 +263,6 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
init_waitqueue_head(&pch_event);
}
static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
{
return cmp1.tv64 < cmp2.tv64;
}
/**
* pch_i2c_wait_for_bus_idle() - check the status of bus.
* @adap: Pointer to struct i2c_algo_pch_data.
......@@ -316,33 +311,6 @@ static void pch_i2c_start(struct i2c_algo_pch_data *adap)
pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_START);
}
/**
* pch_i2c_wait_for_xfer_complete() - initiates a wait for the tx complete event
* @adap: Pointer to struct i2c_algo_pch_data.
*/
static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap)
{
long ret;
ret = wait_event_timeout(pch_event,
(adap->pch_event_flag != 0), msecs_to_jiffies(1000));
if (ret == 0) {
pch_err(adap, "timeout: %x\n", adap->pch_event_flag);
adap->pch_event_flag = 0;
return -ETIMEDOUT;
}
if (adap->pch_event_flag & I2C_ERROR_MASK) {
pch_err(adap, "error bits set: %x\n", adap->pch_event_flag);
adap->pch_event_flag = 0;
return -EIO;
}
adap->pch_event_flag = 0;
return 0;
}
/**
* pch_i2c_getack() - to confirm ACK/NACK
* @adap: Pointer to struct i2c_algo_pch_data.
......@@ -373,6 +341,40 @@ static void pch_i2c_stop(struct i2c_algo_pch_data *adap)
pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_START);
}
static int pch_i2c_wait_for_check_xfer(struct i2c_algo_pch_data *adap)
{
long ret;
ret = wait_event_timeout(pch_event,
(adap->pch_event_flag != 0), msecs_to_jiffies(1000));
if (!ret) {
pch_err(adap, "%s:wait-event timeout\n", __func__);
adap->pch_event_flag = 0;
pch_i2c_stop(adap);
pch_i2c_init(adap);
return -ETIMEDOUT;
}
if (adap->pch_event_flag & I2C_ERROR_MASK) {
pch_err(adap, "Lost Arbitration\n");
adap->pch_event_flag = 0;
pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
pch_i2c_init(adap);
return -EAGAIN;
}
adap->pch_event_flag = 0;
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave address"
"setting\n");
return -EIO;
}
return 0;
}
/**
* pch_i2c_repstart() - generate repeated start condition in normal mode
* @adap: Pointer to struct i2c_algo_pch_data.
......@@ -427,27 +429,12 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
if (first)
pch_i2c_start(adap);
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) {
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave address"
"setting\n");
return -EIO;
}
addr_8_lsb = (addr & I2C_ADDR_MSK);
iowrite32(addr_8_lsb, p + PCH_I2CDR);
} else if (rtn == -EIO) { /* Arbitration Lost */
pch_err(adap, "Lost Arbitration\n");
pch_clrbit(adap->pch_base_address, PCH_I2CSR,
I2CMAL_BIT);
pch_clrbit(adap->pch_base_address, PCH_I2CSR,
I2CMIF_BIT);
pch_i2c_init(adap);
return -EAGAIN;
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn)
return rtn;
addr_8_lsb = (addr & I2C_ADDR_MSK);
iowrite32(addr_8_lsb, p + PCH_I2CDR);
} else {
/* set 7 bit slave address and R/W bit as 0 */
iowrite32(addr << 1, p + PCH_I2CDR);
......@@ -455,44 +442,21 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
pch_i2c_start(adap);
}
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) {
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave address"
"setting\n");
return -EIO;
}
} else if (rtn == -EIO) { /* Arbitration Lost */
pch_err(adap, "Lost Arbitration\n");
pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
pch_i2c_init(adap);
return -EAGAIN;
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn)
return rtn;
for (wrcount = 0; wrcount < length; ++wrcount) {
/* write buffer value to I2C data register */
iowrite32(buf[wrcount], p + PCH_I2CDR);
pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) {
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave address"
"setting\n");
return -EIO;
}
pch_clrbit(adap->pch_base_address, PCH_I2CSR,
I2CMCF_BIT);
pch_clrbit(adap->pch_base_address, PCH_I2CSR,
I2CMIF_BIT);
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn)
return rtn;
pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMCF_BIT);
pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
}
/* check if this is the last message */
......@@ -580,50 +544,21 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (first)
pch_i2c_start(adap);
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) {
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave address"
"setting\n");
return -EIO;
}
addr_8_lsb = (addr & I2C_ADDR_MSK);
iowrite32(addr_8_lsb, p + PCH_I2CDR);
} else if (rtn == -EIO) { /* Arbitration Lost */
pch_err(adap, "Lost Arbitration\n");
pch_clrbit(adap->pch_base_address, PCH_I2CSR,
I2CMAL_BIT);
pch_clrbit(adap->pch_base_address, PCH_I2CSR,
I2CMIF_BIT);
pch_i2c_init(adap);
return -EAGAIN;
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn)
return rtn;
addr_8_lsb = (addr & I2C_ADDR_MSK);
iowrite32(addr_8_lsb, p + PCH_I2CDR);
pch_i2c_restart(adap);
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) {
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave address"
"setting\n");
return -EIO;
}
addr_2_msb |= I2C_RD;
iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK,
p + PCH_I2CDR);
} else if (rtn == -EIO) { /* Arbitration Lost */
pch_err(adap, "Lost Arbitration\n");
pch_clrbit(adap->pch_base_address, PCH_I2CSR,
I2CMAL_BIT);
pch_clrbit(adap->pch_base_address, PCH_I2CSR,
I2CMIF_BIT);
pch_i2c_init(adap);
return -EAGAIN;
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn)
return rtn;
addr_2_msb |= I2C_RD;
iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
} else {
/* 7 address bits + R/W bit */
addr = (((addr) << 1) | (I2C_RD));
......@@ -634,23 +569,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (first)
pch_i2c_start(adap);
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) {
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave address"
"setting\n");
return -EIO;
}
} else if (rtn == -EIO) { /* Arbitration Lost */
pch_err(adap, "Lost Arbitration\n");
pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT);
pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
pch_i2c_init(adap);
return -EAGAIN;
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn)
return rtn;
if (length == 0) {
pch_i2c_stop(adap);
......@@ -669,18 +590,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (loop != 1)
read_index++;
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) {
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave"
"address setting\n");
return -EIO;
}
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn)
return rtn;
} /* end for */
pch_i2c_sendnack(adap);
......@@ -690,17 +602,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (length != 1)
read_index++;
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) {
if (pch_i2c_getack(adap)) {
pch_dbg(adap, "Receive NACK for slave"
"address setting\n");
return -EIO;
}
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn)
return rtn;
if (last)
pch_i2c_stop(adap);
......@@ -790,7 +694,7 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
ret = mutex_lock_interruptible(&pch_mutex);
if (ret)
return -ERESTARTSYS;
return ret;
if (adap->p_adapter_info->pch_i2c_suspended) {
mutex_unlock(&pch_mutex);
......@@ -909,7 +813,7 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev,
pch_adap->owner = THIS_MODULE;
pch_adap->class = I2C_CLASS_HWMON;
strcpy(pch_adap->name, KBUILD_MODNAME);
strlcpy(pch_adap->name, KBUILD_MODNAME, sizeof(pch_adap->name));
pch_adap->algo = &pch_algorithm;
pch_adap->algo_data = &adap_info->pch_data[i];
......@@ -963,7 +867,7 @@ static void __devexit pch_i2c_remove(struct pci_dev *pdev)
pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address);
for (i = 0; i < adap_info->ch_num; i++)
adap_info->pch_data[i].pch_base_address = 0;
adap_info->pch_data[i].pch_base_address = NULL;
pci_set_drvdata(pdev, NULL);
......
......@@ -190,12 +190,7 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev)
adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node;
/*
* If "dev->id" is negative we consider it as zero.
* The reason to do so is to avoid sysfs names that only make
* sense when there are multiple adapters.
*/
adap->nr = (pdev->id != -1) ? pdev->id : 0;
adap->nr = pdev->id;
ret = i2c_bit_add_numbered_bus(adap);
if (ret)
goto err_add_bus;
......
......@@ -512,7 +512,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
}
/* Setup i2c_imx driver structure */
strcpy(i2c_imx->adapter.name, pdev->name);
strlcpy(i2c_imx->adapter.name, pdev->name, sizeof(i2c_imx->adapter.name));
i2c_imx->adapter.owner = THIS_MODULE;
i2c_imx->adapter.algo = &i2c_imx_algo;
i2c_imx->adapter.dev.parent = &pdev->dev;
......
/*
* drivers/i2c/busses/i2c-ixp2000.c
*
* I2C adapter for IXP2000 systems using GPIOs for I2C bus
*
* Author: Deepak Saxena <dsaxena@plexity.net>
* Based on IXDP2400 code by: Naeem M. Afzal <naeem.m.afzal@intel.com>
* Made generic by: Jeff Daly <jeffrey.daly@intel.com>
*
* Copyright (c) 2003-2004 MontaVista Software Inc.
*
* 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.
*
* From Jeff Daly:
*
* I2C adapter driver for Intel IXDP2xxx platforms. This should work for any
* IXP2000 platform if it uses the HW GPIO in the same manner. Basically,
* SDA and SCL GPIOs have external pullups. Setting the respective GPIO to
* an input will make the signal a '1' via the pullup. Setting them to
* outputs will pull them down.
*
* The GPIOs are open drain signals and are used as configuration strap inputs
* during power-up so there's generally a buffer on the board that needs to be
* 'enabled' to drive the GPIOs.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/slab.h>
#include <mach/hardware.h> /* Pick up IXP2000-specific bits */
#include <mach/gpio-ixp2000.h>
static inline int ixp2000_scl_pin(void *data)
{
return ((struct ixp2000_i2c_pins*)data)->scl_pin;
}
static inline int ixp2000_sda_pin(void *data)
{
return ((struct ixp2000_i2c_pins*)data)->sda_pin;
}
static void ixp2000_bit_setscl(void *data, int val)
{
int i = 5000;
if (val) {
gpio_line_config(ixp2000_scl_pin(data), GPIO_IN);
while(!gpio_line_get(ixp2000_scl_pin(data)) && i--);
} else {
gpio_line_config(ixp2000_scl_pin(data), GPIO_OUT);
}
}
static void ixp2000_bit_setsda(void *data, int val)
{
if (val) {
gpio_line_config(ixp2000_sda_pin(data), GPIO_IN);
} else {
gpio_line_config(ixp2000_sda_pin(data), GPIO_OUT);
}
}
static int ixp2000_bit_getscl(void *data)
{
return gpio_line_get(ixp2000_scl_pin(data));
}
static int ixp2000_bit_getsda(void *data)
{
return gpio_line_get(ixp2000_sda_pin(data));
}
struct ixp2000_i2c_data {
struct ixp2000_i2c_pins *gpio_pins;
struct i2c_adapter adapter;
struct i2c_algo_bit_data algo_data;
};
static int ixp2000_i2c_remove(struct platform_device *plat_dev)
{
struct ixp2000_i2c_data *drv_data = platform_get_drvdata(plat_dev);
platform_set_drvdata(plat_dev, NULL);
i2c_del_adapter(&drv_data->adapter);
kfree(drv_data);
return 0;
}
static int ixp2000_i2c_probe(struct platform_device *plat_dev)
{
int err;
struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data;
struct ixp2000_i2c_data *drv_data =
kzalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL);
if (!drv_data)
return -ENOMEM;
drv_data->gpio_pins = gpio;
drv_data->algo_data.data = gpio;
drv_data->algo_data.setsda = ixp2000_bit_setsda;
drv_data->algo_data.setscl = ixp2000_bit_setscl;
drv_data->algo_data.getsda = ixp2000_bit_getsda;
drv_data->algo_data.getscl = ixp2000_bit_getscl;
drv_data->algo_data.udelay = 6;
drv_data->algo_data.timeout = HZ;
strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name,
sizeof(drv_data->adapter.name));
drv_data->adapter.algo_data = &drv_data->algo_data,
drv_data->adapter.dev.parent = &plat_dev->dev;
gpio_line_config(gpio->sda_pin, GPIO_IN);
gpio_line_config(gpio->scl_pin, GPIO_IN);
gpio_line_set(gpio->scl_pin, 0);
gpio_line_set(gpio->sda_pin, 0);
if ((err = i2c_bit_add_bus(&drv_data->adapter)) != 0) {
dev_err(&plat_dev->dev, "Could not install, error %d\n", err);
kfree(drv_data);
return err;
}
platform_set_drvdata(plat_dev, drv_data);
return 0;
}
static struct platform_driver ixp2000_i2c_driver = {
.probe = ixp2000_i2c_probe,
.remove = ixp2000_i2c_remove,
.driver = {
.name = "IXP2000-I2C",
.owner = THIS_MODULE,
},
};
module_platform_driver(ixp2000_i2c_driver);
MODULE_AUTHOR ("Deepak Saxena <dsaxena@plexity.net>");
MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:IXP2000-I2C");
......@@ -64,6 +64,9 @@ struct mpc_i2c {
struct i2c_adapter adap;
int irq;
u32 real_clk;
#ifdef CONFIG_PM
u8 fdr, dfsrr;
#endif
};
struct mpc_i2c_divider {
......@@ -703,6 +706,30 @@ static int __devexit fsl_i2c_remove(struct platform_device *op)
return 0;
};
#ifdef CONFIG_PM
static int mpc_i2c_suspend(struct device *dev)
{
struct mpc_i2c *i2c = dev_get_drvdata(dev);
i2c->fdr = readb(i2c->base + MPC_I2C_FDR);
i2c->dfsrr = readb(i2c->base + MPC_I2C_DFSRR);
return 0;
}
static int mpc_i2c_resume(struct device *dev)
{
struct mpc_i2c *i2c = dev_get_drvdata(dev);
writeb(i2c->fdr, i2c->base + MPC_I2C_FDR);
writeb(i2c->dfsrr, i2c->base + MPC_I2C_DFSRR);
return 0;
}
SIMPLE_DEV_PM_OPS(mpc_i2c_pm_ops, mpc_i2c_suspend, mpc_i2c_resume);
#endif
static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
.setup = mpc_i2c_setup_512x,
};
......@@ -747,6 +774,9 @@ static struct platform_driver mpc_i2c_driver = {
.owner = THIS_MODULE,
.name = DRV_NAME,
.of_match_table = mpc_i2c_of_match,
#ifdef CONFIG_PM
.pm = &mpc_i2c_pm_ops,
#endif
},
};
......
......@@ -55,6 +55,7 @@
#include <linux/i2c-ocores.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of_i2c.h>
struct ocores_i2c {
void __iomem *base;
......@@ -343,6 +344,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
if (pdata) {
for (i = 0; i < pdata->num_devices; i++)
i2c_new_device(&i2c->adap, pdata->devices + i);
} else {
of_i2c_register_devices(&i2c->adap);
}
return 0;
......
......@@ -171,7 +171,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
i2c->io_size = resource_size(res);
i2c->irq = irq;
i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0;
i2c->adap.nr = pdev->id;
i2c->adap.owner = THIS_MODULE;
snprintf(i2c->adap.name, sizeof(i2c->adap.name),
"PCA9564/PCA9665 at 0x%08lx",
......
......@@ -1131,11 +1131,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
spin_lock_init(&i2c->lock);
init_waitqueue_head(&i2c->wait);
/*
* If "dev->id" is negative we consider it as zero.
* The reason to do so is to avoid sysfs names that only make
* sense when there are multiple adapters.
*/
i2c->adap.nr = dev->id;
snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
i2c->adap.nr);
......
......@@ -44,8 +44,12 @@
#include <plat/regs-iic.h>
#include <plat/iic.h>
/* i2c controller state */
/* Treat S3C2410 as baseline hardware, anything else is supported via quirks */
#define QUIRK_S3C2440 (1 << 0)
#define QUIRK_HDMIPHY (1 << 1)
#define QUIRK_NO_GPIO (1 << 2)
/* i2c controller state */
enum s3c24xx_i2c_state {
STATE_IDLE,
STATE_START,
......@@ -54,14 +58,10 @@ enum s3c24xx_i2c_state {
STATE_STOP
};
enum s3c24xx_i2c_type {
TYPE_S3C2410,
TYPE_S3C2440,
};
struct s3c24xx_i2c {
spinlock_t lock;
wait_queue_head_t wait;
unsigned int quirks;
unsigned int suspended:1;
struct i2c_msg *msg;
......@@ -88,26 +88,45 @@ struct s3c24xx_i2c {
#endif
};
/* default platform data removed, dev should always carry data. */
static struct platform_device_id s3c24xx_driver_ids[] = {
{
.name = "s3c2410-i2c",
.driver_data = 0,
}, {
.name = "s3c2440-i2c",
.driver_data = QUIRK_S3C2440,
}, {
.name = "s3c2440-hdmiphy-i2c",
.driver_data = QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO,
}, { },
};
MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
#ifdef CONFIG_OF
static const struct of_device_id s3c24xx_i2c_match[] = {
{ .compatible = "samsung,s3c2410-i2c", .data = (void *)0 },
{ .compatible = "samsung,s3c2440-i2c", .data = (void *)QUIRK_S3C2440 },
{ .compatible = "samsung,s3c2440-hdmiphy-i2c",
.data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
#endif
/* s3c24xx_i2c_is2440()
/* s3c24xx_get_device_quirks
*
* return true is this is an s3c2440
* Get controller type either from device tree or platform device variant.
*/
static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
static inline unsigned int s3c24xx_get_device_quirks(struct platform_device *pdev)
{
struct platform_device *pdev = to_platform_device(i2c->dev);
enum s3c24xx_i2c_type type;
#ifdef CONFIG_OF
if (i2c->dev->of_node)
return of_device_is_compatible(i2c->dev->of_node,
"samsung,s3c2440-i2c");
#endif
if (pdev->dev.of_node) {
const struct of_device_id *match;
match = of_match_node(&s3c24xx_i2c_match, pdev->dev.of_node);
return (unsigned int)match->data;
}
type = platform_get_device_id(pdev)->driver_data;
return type == TYPE_S3C2440;
return platform_get_device_id(pdev)->driver_data;
}
/* s3c24xx_i2c_master_complete
......@@ -471,6 +490,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
unsigned long iicstat;
int timeout = 400;
/* the timeout for HDMIPHY is reduced to 10 ms because
* the hangup is expected to happen, so waiting 400 ms
* causes only unnecessary system hangup
*/
if (i2c->quirks & QUIRK_HDMIPHY)
timeout = 10;
while (timeout-- > 0) {
iicstat = readl(i2c->regs + S3C2410_IICSTAT);
......@@ -480,6 +506,15 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
msleep(1);
}
/* hang-up of bus dedicated for HDMIPHY occurred, resetting */
if (i2c->quirks & QUIRK_HDMIPHY) {
writel(0, i2c->regs + S3C2410_IICCON);
writel(0, i2c->regs + S3C2410_IICSTAT);
writel(0, i2c->regs + S3C2410_IICDS);
return 0;
}
return -ETIMEDOUT;
}
......@@ -676,7 +711,7 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
writel(iiccon, i2c->regs + S3C2410_IICCON);
if (s3c24xx_i2c_is2440(i2c)) {
if (i2c->quirks & QUIRK_S3C2440) {
unsigned long sda_delay;
if (pdata->sda_delay) {
......@@ -761,6 +796,9 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
{
int idx, gpio, ret;
if (i2c->quirks & QUIRK_NO_GPIO)
return 0;
for (idx = 0; idx < 2; idx++) {
gpio = of_get_gpio(i2c->dev->of_node, idx);
if (!gpio_is_valid(gpio)) {
......@@ -785,6 +823,10 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
{
unsigned int idx;
if (i2c->quirks & QUIRK_NO_GPIO)
return;
for (idx = 0; idx < 2; idx++)
gpio_free(i2c->gpios[idx]);
}
......@@ -906,6 +948,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_noclk;
}
i2c->quirks = s3c24xx_get_device_quirks(pdev);
if (pdata)
memcpy(i2c->pdata, pdata, sizeof(*pdata));
else
......@@ -1110,28 +1153,6 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
/* device driver for platform bus bits */
static struct platform_device_id s3c24xx_driver_ids[] = {
{
.name = "s3c2410-i2c",
.driver_data = TYPE_S3C2410,
}, {
.name = "s3c2440-i2c",
.driver_data = TYPE_S3C2440,
}, { },
};
MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids);
#ifdef CONFIG_OF
static const struct of_device_id s3c24xx_i2c_match[] = {
{ .compatible = "samsung,s3c2410-i2c" },
{ .compatible = "samsung,s3c2440-i2c" },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
#else
#define s3c24xx_i2c_match NULL
#endif
static struct platform_driver s3c24xx_i2c_driver = {
.probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove,
......@@ -1140,7 +1161,7 @@ static struct platform_driver s3c24xx_i2c_driver = {
.owner = THIS_MODULE,
.name = "s3c-i2c",
.pm = S3C24XX_DEV_PM_OPS,
.of_match_table = s3c24xx_i2c_match,
.of_match_table = of_match_ptr(s3c24xx_i2c_match),
},
};
......
......@@ -27,6 +27,7 @@
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/of_i2c.h>
#include <linux/err.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
......@@ -653,6 +654,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
adap->dev.parent = &dev->dev;
adap->retries = 5;
adap->nr = dev->id;
adap->dev.of_node = dev->dev.of_node;
strlcpy(adap->name, dev->name, sizeof(adap->name));
......@@ -667,6 +669,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n",
adap->nr, pd->bus_speed);
of_i2c_register_devices(adap);
return 0;
err_all:
......@@ -710,11 +714,18 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
.runtime_resume = sh_mobile_i2c_runtime_nop,
};
static const struct of_device_id sh_mobile_i2c_dt_ids[] __devinitconst = {
{ .compatible = "renesas,rmobile-iic", },
{},
};
MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
static struct platform_driver sh_mobile_i2c_driver = {
.driver = {
.name = "i2c-sh_mobile",
.owner = THIS_MODULE,
.pm = &sh_mobile_i2c_dev_pm_ops,
.of_match_table = sh_mobile_i2c_dt_ids,
},
.probe = sh_mobile_i2c_probe,
.remove = sh_mobile_i2c_remove,
......
......@@ -401,8 +401,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
disable_irq_nosync(i2c_dev->irq);
i2c_dev->irq_disabled = 1;
}
complete(&i2c_dev->msg_complete);
goto err;
}
......@@ -411,7 +409,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
i2c_dev->msg_err |= I2C_ERR_NO_ACK;
if (status & I2C_INT_ARBITRATION_LOST)
i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST;
complete(&i2c_dev->msg_complete);
goto err;
}
......@@ -429,14 +426,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ);
}
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
if (status & I2C_INT_PACKET_XFER_COMPLETE) {
BUG_ON(i2c_dev->msg_buf_remaining);
complete(&i2c_dev->msg_complete);
}
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
return IRQ_HANDLED;
err:
/* An error occurred, mask all interrupts */
......@@ -446,6 +443,8 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
i2c_writel(i2c_dev, status, I2C_INT_STATUS);
if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
complete(&i2c_dev->msg_complete);
return IRQ_HANDLED;
}
......@@ -476,12 +475,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
packet_header = msg->len - 1;
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
packet_header = msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
packet_header |= I2C_HEADER_IE_ENABLE;
packet_header = I2C_HEADER_IE_ENABLE;
if (!stop)
packet_header |= I2C_HEADER_REPEAT_START;
if (msg->flags & I2C_M_TEN)
if (msg->flags & I2C_M_TEN) {
packet_header |= msg->addr;
packet_header |= I2C_HEADER_10BIT_ADDR;
} else {
packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
}
if (msg->flags & I2C_M_IGNORE_NAK)
packet_header |= I2C_HEADER_CONT_ON_NAK;
if (msg->flags & I2C_M_RD)
......@@ -557,7 +559,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
static u32 tegra_i2c_func(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
}
static const struct i2c_algorithm tegra_i2c_algo = {
......
......@@ -104,13 +104,8 @@ static int i2c_versatile_probe(struct platform_device *dev)
i2c->algo = i2c_versatile_algo;
i2c->algo.data = i2c;
if (dev->id >= 0) {
/* static bus numbering */
i2c->adap.nr = dev->id;
ret = i2c_bit_add_numbered_bus(&i2c->adap);
} else
/* dynamic bus numbering */
ret = i2c_bit_add_bus(&i2c->adap);
i2c->adap.nr = dev->id;
ret = i2c_bit_add_numbered_bus(&i2c->adap);
if (ret >= 0) {
platform_set_drvdata(dev, i2c);
of_i2c_register_devices(&i2c->adap);
......
......@@ -40,6 +40,7 @@
#include <linux/i2c-xiic.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/of_i2c.h>
#define DRIVER_NAME "xiic-i2c"
......@@ -705,8 +706,6 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
goto resource_missing;
pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
if (!pdata)
return -EINVAL;
i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
if (!i2c)
......@@ -730,6 +729,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
i2c->adap = xiic_adapter;
i2c_set_adapdata(&i2c->adap, i2c);
i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = pdev->dev.of_node;
xiic_reinit(i2c);
......@@ -748,9 +748,13 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
goto add_adapter_failed;
}
/* add in known devices to the bus */
for (i = 0; i < pdata->num_devices; i++)
i2c_new_device(&i2c->adap, pdata->devices + i);
if (pdata) {
/* add in known devices to the bus */
for (i = 0; i < pdata->num_devices; i++)
i2c_new_device(&i2c->adap, pdata->devices + i);
}
of_i2c_register_devices(&i2c->adap);
return 0;
......@@ -795,12 +799,21 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev)
return 0;
}
#if defined(CONFIG_OF)
static const struct of_device_id xiic_of_match[] __devinitconst = {
{ .compatible = "xlnx,xps-iic-2.00.a", },
{},
};
MODULE_DEVICE_TABLE(of, xiic_of_match);
#endif
static struct platform_driver xiic_i2c_driver = {
.probe = xiic_i2c_probe,
.remove = __devexit_p(xiic_i2c_remove),
.driver = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(xiic_of_match),
},
};
......
......@@ -772,6 +772,23 @@ struct device_type i2c_adapter_type = {
};
EXPORT_SYMBOL_GPL(i2c_adapter_type);
/**
* i2c_verify_adapter - return parameter as i2c_adapter or NULL
* @dev: device, probably from some driver model iterator
*
* When traversing the driver model tree, perhaps using driver model
* iterators like @device_for_each_child(), you can't assume very much
* about the nodes you find. Use this function to avoid oopses caused
* by wrongly treating some non-I2C device as an i2c_adapter.
*/
struct i2c_adapter *i2c_verify_adapter(struct device *dev)
{
return (dev->type == &i2c_adapter_type)
? to_i2c_adapter(dev)
: NULL;
}
EXPORT_SYMBOL(i2c_verify_adapter);
#ifdef CONFIG_I2C_COMPAT
static struct class_compat *i2c_adapter_compat_class;
#endif
......
......@@ -24,6 +24,8 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/of.h>
#include <linux/of_i2c.h>
/* multiplexer per channel data */
struct i2c_mux_priv {
......@@ -31,11 +33,11 @@ struct i2c_mux_priv {
struct i2c_algorithm algo;
struct i2c_adapter *parent;
void *mux_dev; /* the mux chip/device */
void *mux_priv; /* the mux chip/device */
u32 chan_id; /* the channel id */
int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id);
int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id);
int (*select)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
};
static int i2c_mux_master_xfer(struct i2c_adapter *adap,
......@@ -47,11 +49,11 @@ static int i2c_mux_master_xfer(struct i2c_adapter *adap,
/* Switch to the right mux port and perform the transfer. */
ret = priv->select(parent, priv->mux_dev, priv->chan_id);
ret = priv->select(parent, priv->mux_priv, priv->chan_id);
if (ret >= 0)
ret = parent->algo->master_xfer(parent, msgs, num);
if (priv->deselect)
priv->deselect(parent, priv->mux_dev, priv->chan_id);
priv->deselect(parent, priv->mux_priv, priv->chan_id);
return ret;
}
......@@ -67,12 +69,12 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
/* Select the right mux port and perform the transfer. */
ret = priv->select(parent, priv->mux_dev, priv->chan_id);
ret = priv->select(parent, priv->mux_priv, priv->chan_id);
if (ret >= 0)
ret = parent->algo->smbus_xfer(parent, addr, flags,
read_write, command, size, data);
if (priv->deselect)
priv->deselect(parent, priv->mux_dev, priv->chan_id);
priv->deselect(parent, priv->mux_priv, priv->chan_id);
return ret;
}
......@@ -87,7 +89,8 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap)
}
struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
void *mux_dev, u32 force_nr, u32 chan_id,
struct device *mux_dev,
void *mux_priv, u32 force_nr, u32 chan_id,
int (*select) (struct i2c_adapter *,
void *, u32),
int (*deselect) (struct i2c_adapter *,
......@@ -102,7 +105,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
/* Set up private adapter data */
priv->parent = parent;
priv->mux_dev = mux_dev;
priv->mux_priv = mux_priv;
priv->chan_id = chan_id;
priv->select = select;
priv->deselect = deselect;
......@@ -124,6 +127,25 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
priv->adap.algo_data = priv;
priv->adap.dev.parent = &parent->dev;
/*
* Try to populate the mux adapter's of_node, expands to
* nothing if !CONFIG_OF.
*/
if (mux_dev->of_node) {
struct device_node *child;
u32 reg;
for_each_child_of_node(mux_dev->of_node, child) {
ret = of_property_read_u32(child, "reg", &reg);
if (ret)
continue;
if (chan_id == reg) {
priv->adap.dev.of_node = child;
break;
}
}
}
if (force_nr) {
priv->adap.nr = force_nr;
ret = i2c_add_numbered_adapter(&priv->adap);
......@@ -141,6 +163,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
i2c_adapter_id(&priv->adap));
of_i2c_register_devices(&priv->adap);
return &priv->adap;
}
EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
......
......@@ -15,7 +15,7 @@ config I2C_MUX_GPIO
through GPIO pins.
This driver can also be built as a module. If so, the module
will be called gpio-i2cmux.
will be called i2c-mux-gpio.
config I2C_MUX_PCA9541
tristate "NXP PCA9541 I2C Master Selector"
......@@ -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
#
# 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_GPIO) += i2c-mux-gpio.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
......@@ -10,7 +10,7 @@
#include <linux/i2c.h>
#include <linux/i2c-mux.h>
#include <linux/gpio-i2cmux.h>
#include <linux/i2c-mux-gpio.h>
#include <linux/platform_device.h>
#include <linux/init.h>
#include <linux/module.h>
......@@ -20,10 +20,10 @@
struct gpiomux {
struct i2c_adapter *parent;
struct i2c_adapter **adap; /* child busses */
struct gpio_i2cmux_platform_data data;
struct i2c_mux_gpio_platform_data data;
};
static void gpiomux_set(const struct gpiomux *mux, unsigned val)
static void i2c_mux_gpio_set(const struct gpiomux *mux, unsigned val)
{
int i;
......@@ -31,28 +31,28 @@ static void gpiomux_set(const struct gpiomux *mux, unsigned val)
gpio_set_value(mux->data.gpios[i], val & (1 << i));
}
static int gpiomux_select(struct i2c_adapter *adap, void *data, u32 chan)
static int i2c_mux_gpio_select(struct i2c_adapter *adap, void *data, u32 chan)
{
struct gpiomux *mux = data;
gpiomux_set(mux, mux->data.values[chan]);
i2c_mux_gpio_set(mux, mux->data.values[chan]);
return 0;
}
static int gpiomux_deselect(struct i2c_adapter *adap, void *data, u32 chan)
static int i2c_mux_gpio_deselect(struct i2c_adapter *adap, void *data, u32 chan)
{
struct gpiomux *mux = data;
gpiomux_set(mux, mux->data.idle);
i2c_mux_gpio_set(mux, mux->data.idle);
return 0;
}
static int __devinit gpiomux_probe(struct platform_device *pdev)
static int __devinit i2c_mux_gpio_probe(struct platform_device *pdev)
{
struct gpiomux *mux;
struct gpio_i2cmux_platform_data *pdata;
struct i2c_mux_gpio_platform_data *pdata;
struct i2c_adapter *parent;
int (*deselect) (struct i2c_adapter *, void *, u32);
unsigned initial_state;
......@@ -86,16 +86,16 @@ static int __devinit gpiomux_probe(struct platform_device *pdev)
goto alloc_failed2;
}
if (pdata->idle != GPIO_I2CMUX_NO_IDLE) {
if (pdata->idle != I2C_MUX_GPIO_NO_IDLE) {
initial_state = pdata->idle;
deselect = gpiomux_deselect;
deselect = i2c_mux_gpio_deselect;
} else {
initial_state = pdata->values[0];
deselect = NULL;
}
for (i = 0; i < pdata->n_gpios; i++) {
ret = gpio_request(pdata->gpios[i], "gpio-i2cmux");
ret = gpio_request(pdata->gpios[i], "i2c-mux-gpio");
if (ret)
goto err_request_gpio;
gpio_direction_output(pdata->gpios[i],
......@@ -105,8 +105,8 @@ static int __devinit gpiomux_probe(struct platform_device *pdev)
for (i = 0; i < pdata->n_values; i++) {
u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0;
mux->adap[i] = i2c_add_mux_adapter(parent, mux, nr, i,
gpiomux_select, deselect);
mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, i,
i2c_mux_gpio_select, deselect);
if (!mux->adap[i]) {
ret = -ENODEV;
dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
......@@ -137,7 +137,7 @@ static int __devinit gpiomux_probe(struct platform_device *pdev)
return ret;
}
static int __devexit gpiomux_remove(struct platform_device *pdev)
static int __devexit i2c_mux_gpio_remove(struct platform_device *pdev)
{
struct gpiomux *mux = platform_get_drvdata(pdev);
int i;
......@@ -156,18 +156,18 @@ static int __devexit gpiomux_remove(struct platform_device *pdev)
return 0;
}
static struct platform_driver gpiomux_driver = {
.probe = gpiomux_probe,
.remove = __devexit_p(gpiomux_remove),
static struct platform_driver i2c_mux_gpio_driver = {
.probe = i2c_mux_gpio_probe,
.remove = __devexit_p(i2c_mux_gpio_remove),
.driver = {
.owner = THIS_MODULE,
.name = "gpio-i2cmux",
.name = "i2c-mux-gpio",
},
};
module_platform_driver(gpiomux_driver);
module_platform_driver(i2c_mux_gpio_driver);
MODULE_DESCRIPTION("GPIO-based I2C multiplexer driver");
MODULE_AUTHOR("Peter Korsgaard <peter.korsgaard@barco.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:gpio-i2cmux");
MODULE_ALIAS("platform:i2c-mux-gpio");
......@@ -353,7 +353,8 @@ static int pca9541_probe(struct i2c_client *client,
force = 0;
if (pdata)
force = pdata->modes[0].adap_id;
data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0,
data->mux_adap = i2c_add_mux_adapter(adap, &client->dev, client,
force, 0,
pca9541_select_chan,
pca9541_release_chan);
......
......@@ -226,7 +226,7 @@ static int pca954x_probe(struct i2c_client *client,
}
data->virt_adaps[num] =
i2c_add_mux_adapter(adap, client,
i2c_add_mux_adapter(adap, &client->dev, client,
force, num, pca954x_select_chan,
(pdata && pdata->modes[num].deselect_on_exit)
? pca954x_deselect_mux : NULL);
......
......@@ -90,8 +90,22 @@ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
if (!dev)
return NULL;
return to_i2c_client(dev);
return i2c_verify_client(dev);
}
EXPORT_SYMBOL(of_find_i2c_device_by_node);
/* must call put_device() when done with returned i2c_adapter device */
struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
{
struct device *dev;
dev = bus_find_device(&i2c_bus_type, NULL, node,
of_dev_node_match);
if (!dev)
return NULL;
return i2c_verify_adapter(dev);
}
EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
MODULE_LICENSE("GPL");
/*
* gpio-i2cmux interface to platform code
* i2c-mux-gpio interface to platform code
*
* Peter Korsgaard <peter.korsgaard@barco.com>
*
......@@ -8,14 +8,14 @@
* published by the Free Software Foundation.
*/
#ifndef _LINUX_GPIO_I2CMUX_H
#define _LINUX_GPIO_I2CMUX_H
#ifndef _LINUX_I2C_MUX_GPIO_H
#define _LINUX_I2C_MUX_GPIO_H
/* MUX has no specific idle mode */
#define GPIO_I2CMUX_NO_IDLE ((unsigned)-1)
#define I2C_MUX_GPIO_NO_IDLE ((unsigned)-1)
/**
* struct gpio_i2cmux_platform_data - Platform-dependent data for gpio-i2cmux
* struct i2c_mux_gpio_platform_data - Platform-dependent data for i2c-mux-gpio
* @parent: Parent I2C bus adapter number
* @base_nr: Base I2C bus number to number adapters from or zero for dynamic
* @values: Array of bitmasks of GPIO settings (low/high) for each
......@@ -25,7 +25,7 @@
* @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
*/
struct gpio_i2cmux_platform_data {
struct i2c_mux_gpio_platform_data {
int parent;
int base_nr;
const unsigned *values;
......@@ -35,4 +35,4 @@ struct gpio_i2cmux_platform_data {
unsigned idle;
};
#endif /* _LINUX_GPIO_I2CMUX_H */
#endif /* _LINUX_I2C_MUX_GPIO_H */
......@@ -34,7 +34,8 @@
* mux control.
*/
struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
void *mux_dev, u32 force_nr, u32 chan_id,
struct device *mux_dev,
void *mux_priv, u32 force_nr, u32 chan_id,
int (*select) (struct i2c_adapter *,
void *mux_dev, u32 chan_id),
int (*deselect) (struct i2c_adapter *,
......
......@@ -232,6 +232,7 @@ struct i2c_client {
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
extern struct i2c_client *i2c_verify_client(struct device *dev);
extern struct i2c_adapter *i2c_verify_adapter(struct device *dev);
static inline struct i2c_client *kobj_to_i2c_client(struct kobject *kobj)
{
......
......@@ -20,6 +20,10 @@ extern void of_i2c_register_devices(struct i2c_adapter *adap);
/* must call put_device() when done with returned i2c_client device */
extern struct i2c_client *of_find_i2c_device_by_node(struct device_node *node);
/* must call put_device() when done with returned i2c_adapter device */
extern struct i2c_adapter *of_find_i2c_adapter_by_node(
struct device_node *node);
#else
static inline void of_i2c_register_devices(struct i2c_adapter *adap)
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册