提交 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: ...@@ -6,14 +6,18 @@ Required properties:
- compatible: value should be either of the following. - compatible: value should be either of the following.
(a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c. (a) "samsung, s3c2410-i2c", for i2c compatible with s3c2410 i2c.
(b) "samsung, s3c2440-i2c", for i2c compatible with s3c2440 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 - reg: physical base address of the controller and length of memory mapped
region. region.
- interrupts: interrupt number to the cpu. - interrupts: interrupt number to the cpu.
- samsung,i2c-sda-delay: Delay (in ns) applied to data line (SDA) edges. - 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: 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 - samsung,i2c-slave-addr: Slave address in multi-master enviroment. If not
specified, default value is 0. specified, default value is 0.
- samsung,i2c-max-bus-freq: Desired frequency in Hz of the bus. If not - 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> Author: Peter Korsgaard <peter.korsgaard@barco.com>
Description 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. from a master I2C bus and a hardware MUX controlled through GPIO pins.
E.G.: E.G.:
...@@ -26,16 +26,16 @@ according to the settings of the GPIO pins 1..N. ...@@ -26,16 +26,16 @@ according to the settings of the GPIO pins 1..N.
Usage 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 platform_device with the platform_data pointing to a struct
gpio_i2cmux_platform_data with the I2C adapter number of the master 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 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 E.G. something like this for a MUX providing 4 bus segments
controlled through 3 GPIO pins: controlled through 3 GPIO pins:
#include <linux/gpio-i2cmux.h> #include <linux/i2c-gpio-mux.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
static const unsigned myboard_gpiomux_gpios[] = { static const unsigned myboard_gpiomux_gpios[] = {
...@@ -57,7 +57,7 @@ static struct gpio_i2cmux_platform_data myboard_i2cmux_data = { ...@@ -57,7 +57,7 @@ static struct gpio_i2cmux_platform_data myboard_i2cmux_data = {
}; };
static struct platform_device myboard_i2cmux = { static struct platform_device myboard_i2cmux = {
.name = "gpio-i2cmux", .name = "i2c-gpio-mux",
.id = 0, .id = 0,
.dev = { .dev = {
.platform_data = &myboard_i2cmux_data, .platform_data = &myboard_i2cmux_data,
......
...@@ -2988,9 +2988,9 @@ GENERIC GPIO I2C MULTIPLEXER DRIVER ...@@ -2988,9 +2988,9 @@ GENERIC GPIO I2C MULTIPLEXER DRIVER
M: Peter Korsgaard <peter.korsgaard@barco.com> M: Peter Korsgaard <peter.korsgaard@barco.com>
L: linux-i2c@vger.kernel.org L: linux-i2c@vger.kernel.org
S: Supported S: Supported
F: drivers/i2c/muxes/gpio-i2cmux.c F: drivers/i2c/muxes/i2c-mux-gpio.c
F: include/linux/gpio-i2cmux.h F: include/linux/i2c-mux-gpio.h
F: Documentation/i2c/muxes/gpio-i2cmux F: Documentation/i2c/muxes/i2c-mux-gpio
GENERIC HDLC (WAN) DRIVERS GENERIC HDLC (WAN) DRIVERS
M: Krzysztof Halasa <khc@pm.waw.pl> M: Krzysztof Halasa <khc@pm.waw.pl>
...@@ -5148,7 +5148,7 @@ PCA9541 I2C BUS MASTER SELECTOR DRIVER ...@@ -5148,7 +5148,7 @@ PCA9541 I2C BUS MASTER SELECTOR DRIVER
M: Guenter Roeck <guenter.roeck@ericsson.com> M: Guenter Roeck <guenter.roeck@ericsson.com>
L: linux-i2c@vger.kernel.org L: linux-i2c@vger.kernel.org
S: Maintained S: Maintained
F: drivers/i2c/muxes/pca9541.c F: drivers/i2c/muxes/i2c-mux-pca9541.c
PCA9564/PCA9665 I2C BUS DRIVER PCA9564/PCA9665 I2C BUS DRIVER
M: Wolfram Sang <w.sang@pengutronix.de> M: Wolfram Sang <w.sang@pengutronix.de>
......
...@@ -49,7 +49,6 @@ config I2C_CHARDEV ...@@ -49,7 +49,6 @@ config I2C_CHARDEV
config I2C_MUX config I2C_MUX
tristate "I2C bus multiplexing support" tristate "I2C bus multiplexing support"
depends on EXPERIMENTAL
help help
Say Y here if you want the I2C core to support the ability to Say Y here if you want the I2C core to support the ability to
handle multiplexed I2C bus topologies, by presenting each handle multiplexed I2C bus topologies, by presenting each
......
...@@ -445,20 +445,6 @@ config I2C_IOP3XX ...@@ -445,20 +445,6 @@ config I2C_IOP3XX
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-iop3xx. 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 config I2C_MPC
tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx" tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
depends on PPC depends on PPC
......
...@@ -44,7 +44,6 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o ...@@ -44,7 +44,6 @@ obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
obj-$(CONFIG_I2C_IMX) += i2c-imx.o obj-$(CONFIG_I2C_IMX) += i2c-imx.o
obj-$(CONFIG_I2C_INTEL_MID) += i2c-intel-mid.o obj-$(CONFIG_I2C_INTEL_MID) += i2c-intel-mid.o
obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.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_MPC) += i2c-mpc.o
obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
obj-$(CONFIG_I2C_MXS) += i2c-mxs.o obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
......
...@@ -755,7 +755,7 @@ static int davinci_i2c_remove(struct platform_device *pdev) ...@@ -755,7 +755,7 @@ static int davinci_i2c_remove(struct platform_device *pdev)
dev->clk = NULL; dev->clk = NULL;
davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0);
free_irq(IRQ_I2C, dev); free_irq(dev->irq, dev);
iounmap(dev->base); iounmap(dev->base);
kfree(dev); kfree(dev);
......
...@@ -164,9 +164,15 @@ static char *abort_sources[] = { ...@@ -164,9 +164,15 @@ static char *abort_sources[] = {
u32 dw_readl(struct dw_i2c_dev *dev, int offset) 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); return swab32(value);
else else
return value; return value;
...@@ -174,10 +180,15 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset) ...@@ -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) void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
{ {
if (dev->swab) if (dev->accessor_flags & ACCESS_SWAP)
b = swab32(b); 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 static u32
...@@ -251,14 +262,14 @@ int i2c_dw_init(struct dw_i2c_dev *dev) ...@@ -251,14 +262,14 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
input_clock_khz = dev->get_clk_rate_khz(dev); input_clock_khz = dev->get_clk_rate_khz(dev);
/* Configure register endianess access */
reg = dw_readl(dev, DW_IC_COMP_TYPE); reg = dw_readl(dev, DW_IC_COMP_TYPE);
if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) { if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
dev->swab = 1; /* Configure register endianess access */
reg = DW_IC_COMP_TYPE_VALUE; dev->accessor_flags |= ACCESS_SWAP;
} } else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
/* Configure register access mode 16bit */
if (reg != DW_IC_COMP_TYPE_VALUE) { dev->accessor_flags |= ACCESS_16BIT;
} else if (reg != DW_IC_COMP_TYPE_VALUE) {
dev_err(dev->dev, "Unknown Synopsys component type: " dev_err(dev->dev, "Unknown Synopsys component type: "
"0x%08x\n", reg); "0x%08x\n", reg);
return -ENODEV; return -ENODEV;
......
...@@ -82,7 +82,7 @@ struct dw_i2c_dev { ...@@ -82,7 +82,7 @@ struct dw_i2c_dev {
unsigned int status; unsigned int status;
u32 abort_source; u32 abort_source;
int irq; int irq;
int swab; u32 accessor_flags;
struct i2c_adapter adapter; struct i2c_adapter adapter;
u32 functionality; u32 functionality;
u32 master_cfg; u32 master_cfg;
...@@ -90,6 +90,9 @@ struct dw_i2c_dev { ...@@ -90,6 +90,9 @@ struct dw_i2c_dev {
unsigned int rx_fifo_depth; 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 u32 dw_readl(struct dw_i2c_dev *dev, int offset);
extern void dw_writel(struct dw_i2c_dev *dev, u32 b, 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); extern int i2c_dw_init(struct dw_i2c_dev *dev);
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/of_i2c.h> #include <linux/of_i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "i2c-designware-core.h" #include "i2c-designware-core.h"
...@@ -95,7 +96,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev) ...@@ -95,7 +96,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
r = -ENODEV; r = -ENODEV;
goto err_free_mem; goto err_free_mem;
} }
clk_enable(dev->clk); clk_prepare_enable(dev->clk);
dev->functionality = dev->functionality =
I2C_FUNC_I2C | I2C_FUNC_I2C |
...@@ -155,7 +156,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev) ...@@ -155,7 +156,7 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
err_iounmap: err_iounmap:
iounmap(dev->base); iounmap(dev->base);
err_unuse_clocks: err_unuse_clocks:
clk_disable(dev->clk); clk_disable_unprepare(dev->clk);
clk_put(dev->clk); clk_put(dev->clk);
dev->clk = NULL; dev->clk = NULL;
err_free_mem: err_free_mem:
...@@ -177,7 +178,7 @@ static int __devexit dw_i2c_remove(struct platform_device *pdev) ...@@ -177,7 +178,7 @@ static int __devexit dw_i2c_remove(struct platform_device *pdev)
i2c_del_adapter(&dev->adapter); i2c_del_adapter(&dev->adapter);
put_device(&pdev->dev); put_device(&pdev->dev);
clk_disable(dev->clk); clk_disable_unprepare(dev->clk);
clk_put(dev->clk); clk_put(dev->clk);
dev->clk = NULL; dev->clk = NULL;
...@@ -198,6 +199,31 @@ static const struct of_device_id dw_i2c_of_match[] = { ...@@ -198,6 +199,31 @@ static const struct of_device_id dw_i2c_of_match[] = {
MODULE_DEVICE_TABLE(of, dw_i2c_of_match); MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
#endif #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 */ /* work with hotplug and coldplug */
MODULE_ALIAS("platform:i2c_designware"); MODULE_ALIAS("platform:i2c_designware");
...@@ -207,6 +233,7 @@ static struct platform_driver dw_i2c_driver = { ...@@ -207,6 +233,7 @@ static struct platform_driver dw_i2c_driver = {
.name = "i2c_designware", .name = "i2c_designware",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.of_match_table = of_match_ptr(dw_i2c_of_match), .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) ...@@ -263,11 +263,6 @@ static void pch_i2c_init(struct i2c_algo_pch_data *adap)
init_waitqueue_head(&pch_event); 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. * pch_i2c_wait_for_bus_idle() - check the status of bus.
* @adap: Pointer to struct i2c_algo_pch_data. * @adap: Pointer to struct i2c_algo_pch_data.
...@@ -316,33 +311,6 @@ static void pch_i2c_start(struct i2c_algo_pch_data *adap) ...@@ -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_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 * pch_i2c_getack() - to confirm ACK/NACK
* @adap: Pointer to struct i2c_algo_pch_data. * @adap: Pointer to struct i2c_algo_pch_data.
...@@ -373,6 +341,40 @@ static void pch_i2c_stop(struct i2c_algo_pch_data *adap) ...@@ -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); 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 * pch_i2c_repstart() - generate repeated start condition in normal mode
* @adap: Pointer to struct i2c_algo_pch_data. * @adap: Pointer to struct i2c_algo_pch_data.
...@@ -427,27 +429,12 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap, ...@@ -427,27 +429,12 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
if (first) if (first)
pch_i2c_start(adap); pch_i2c_start(adap);
rtn = pch_i2c_wait_for_xfer_complete(adap); rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn == 0) { if (rtn)
if (pch_i2c_getack(adap)) { return rtn;
pch_dbg(adap, "Receive NACK for slave address"
"setting\n"); addr_8_lsb = (addr & I2C_ADDR_MSK);
return -EIO; iowrite32(addr_8_lsb, p + PCH_I2CDR);
}
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;
}
} else { } else {
/* set 7 bit slave address and R/W bit as 0 */ /* set 7 bit slave address and R/W bit as 0 */
iowrite32(addr << 1, p + PCH_I2CDR); iowrite32(addr << 1, p + PCH_I2CDR);
...@@ -455,44 +442,21 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap, ...@@ -455,44 +442,21 @@ static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap,
pch_i2c_start(adap); pch_i2c_start(adap);
} }
rtn = pch_i2c_wait_for_xfer_complete(adap); rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn == 0) { if (rtn)
if (pch_i2c_getack(adap)) { return rtn;
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;
}
for (wrcount = 0; wrcount < length; ++wrcount) { for (wrcount = 0; wrcount < length; ++wrcount) {
/* write buffer value to I2C data register */ /* write buffer value to I2C data register */
iowrite32(buf[wrcount], p + PCH_I2CDR); iowrite32(buf[wrcount], p + PCH_I2CDR);
pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]); pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]);
rtn = pch_i2c_wait_for_xfer_complete(adap); rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn == 0) { if (rtn)
if (pch_i2c_getack(adap)) { return rtn;
pch_dbg(adap, "Receive NACK for slave address"
"setting\n"); pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMCF_BIT);
return -EIO; pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT);
}
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;
}
} }
/* check if this is the last message */ /* 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, ...@@ -580,50 +544,21 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (first) if (first)
pch_i2c_start(adap); pch_i2c_start(adap);
rtn = pch_i2c_wait_for_xfer_complete(adap); rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn == 0) { if (rtn)
if (pch_i2c_getack(adap)) { return rtn;
pch_dbg(adap, "Receive NACK for slave address"
"setting\n"); addr_8_lsb = (addr & I2C_ADDR_MSK);
return -EIO; iowrite32(addr_8_lsb, p + PCH_I2CDR);
}
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;
}
pch_i2c_restart(adap); pch_i2c_restart(adap);
rtn = pch_i2c_wait_for_xfer_complete(adap);
if (rtn == 0) { rtn = pch_i2c_wait_for_check_xfer(adap);
if (pch_i2c_getack(adap)) { if (rtn)
pch_dbg(adap, "Receive NACK for slave address" return rtn;
"setting\n");
return -EIO; addr_2_msb |= I2C_RD;
} iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR);
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;
}
} else { } else {
/* 7 address bits + R/W bit */ /* 7 address bits + R/W bit */
addr = (((addr) << 1) | (I2C_RD)); addr = (((addr) << 1) | (I2C_RD));
...@@ -634,23 +569,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, ...@@ -634,23 +569,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (first) if (first)
pch_i2c_start(adap); pch_i2c_start(adap);
rtn = pch_i2c_wait_for_xfer_complete(adap); rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn == 0) { if (rtn)
if (pch_i2c_getack(adap)) { return rtn;
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;
}
if (length == 0) { if (length == 0) {
pch_i2c_stop(adap); pch_i2c_stop(adap);
...@@ -669,18 +590,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, ...@@ -669,18 +590,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (loop != 1) if (loop != 1)
read_index++; read_index++;
rtn = pch_i2c_wait_for_xfer_complete(adap); rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn == 0) { if (rtn)
if (pch_i2c_getack(adap)) { return rtn;
pch_dbg(adap, "Receive NACK for slave"
"address setting\n");
return -EIO;
}
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
} /* end for */ } /* end for */
pch_i2c_sendnack(adap); pch_i2c_sendnack(adap);
...@@ -690,17 +602,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, ...@@ -690,17 +602,9 @@ static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
if (length != 1) if (length != 1)
read_index++; read_index++;
rtn = pch_i2c_wait_for_xfer_complete(adap); rtn = pch_i2c_wait_for_check_xfer(adap);
if (rtn == 0) { if (rtn)
if (pch_i2c_getack(adap)) { return rtn;
pch_dbg(adap, "Receive NACK for slave"
"address setting\n");
return -EIO;
}
} else { /* wait-event timeout */
pch_i2c_stop(adap);
return -ETIME;
}
if (last) if (last)
pch_i2c_stop(adap); pch_i2c_stop(adap);
...@@ -790,7 +694,7 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -790,7 +694,7 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
ret = mutex_lock_interruptible(&pch_mutex); ret = mutex_lock_interruptible(&pch_mutex);
if (ret) if (ret)
return -ERESTARTSYS; return ret;
if (adap->p_adapter_info->pch_i2c_suspended) { if (adap->p_adapter_info->pch_i2c_suspended) {
mutex_unlock(&pch_mutex); mutex_unlock(&pch_mutex);
...@@ -909,7 +813,7 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev, ...@@ -909,7 +813,7 @@ static int __devinit pch_i2c_probe(struct pci_dev *pdev,
pch_adap->owner = THIS_MODULE; pch_adap->owner = THIS_MODULE;
pch_adap->class = I2C_CLASS_HWMON; 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 = &pch_algorithm;
pch_adap->algo_data = &adap_info->pch_data[i]; pch_adap->algo_data = &adap_info->pch_data[i];
...@@ -963,7 +867,7 @@ static void __devexit pch_i2c_remove(struct pci_dev *pdev) ...@@ -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); pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address);
for (i = 0; i < adap_info->ch_num; i++) 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); pci_set_drvdata(pdev, NULL);
......
...@@ -190,12 +190,7 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) ...@@ -190,12 +190,7 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev)
adap->dev.parent = &pdev->dev; adap->dev.parent = &pdev->dev;
adap->dev.of_node = pdev->dev.of_node; adap->dev.of_node = pdev->dev.of_node;
/* adap->nr = pdev->id;
* 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;
ret = i2c_bit_add_numbered_bus(adap); ret = i2c_bit_add_numbered_bus(adap);
if (ret) if (ret)
goto err_add_bus; goto err_add_bus;
......
...@@ -512,7 +512,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) ...@@ -512,7 +512,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
} }
/* Setup i2c_imx driver structure */ /* 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.owner = THIS_MODULE;
i2c_imx->adapter.algo = &i2c_imx_algo; i2c_imx->adapter.algo = &i2c_imx_algo;
i2c_imx->adapter.dev.parent = &pdev->dev; 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 { ...@@ -64,6 +64,9 @@ struct mpc_i2c {
struct i2c_adapter adap; struct i2c_adapter adap;
int irq; int irq;
u32 real_clk; u32 real_clk;
#ifdef CONFIG_PM
u8 fdr, dfsrr;
#endif
}; };
struct mpc_i2c_divider { struct mpc_i2c_divider {
...@@ -703,6 +706,30 @@ static int __devexit fsl_i2c_remove(struct platform_device *op) ...@@ -703,6 +706,30 @@ static int __devexit fsl_i2c_remove(struct platform_device *op)
return 0; 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 = { static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = {
.setup = mpc_i2c_setup_512x, .setup = mpc_i2c_setup_512x,
}; };
...@@ -747,6 +774,9 @@ static struct platform_driver mpc_i2c_driver = { ...@@ -747,6 +774,9 @@ static struct platform_driver mpc_i2c_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = DRV_NAME, .name = DRV_NAME,
.of_match_table = mpc_i2c_of_match, .of_match_table = mpc_i2c_of_match,
#ifdef CONFIG_PM
.pm = &mpc_i2c_pm_ops,
#endif
}, },
}; };
......
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include <linux/i2c-ocores.h> #include <linux/i2c-ocores.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/of_i2c.h>
struct ocores_i2c { struct ocores_i2c {
void __iomem *base; void __iomem *base;
...@@ -343,6 +344,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev) ...@@ -343,6 +344,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
if (pdata) { if (pdata) {
for (i = 0; i < pdata->num_devices; i++) for (i = 0; i < pdata->num_devices; i++)
i2c_new_device(&i2c->adap, pdata->devices + i); i2c_new_device(&i2c->adap, pdata->devices + i);
} else {
of_i2c_register_devices(&i2c->adap);
} }
return 0; return 0;
......
...@@ -171,7 +171,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) ...@@ -171,7 +171,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
i2c->io_size = resource_size(res); i2c->io_size = resource_size(res);
i2c->irq = irq; i2c->irq = irq;
i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; i2c->adap.nr = pdev->id;
i2c->adap.owner = THIS_MODULE; i2c->adap.owner = THIS_MODULE;
snprintf(i2c->adap.name, sizeof(i2c->adap.name), snprintf(i2c->adap.name, sizeof(i2c->adap.name),
"PCA9564/PCA9665 at 0x%08lx", "PCA9564/PCA9665 at 0x%08lx",
......
...@@ -1131,11 +1131,6 @@ static int i2c_pxa_probe(struct platform_device *dev) ...@@ -1131,11 +1131,6 @@ static int i2c_pxa_probe(struct platform_device *dev)
spin_lock_init(&i2c->lock); spin_lock_init(&i2c->lock);
init_waitqueue_head(&i2c->wait); 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; i2c->adap.nr = dev->id;
snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u", snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u",
i2c->adap.nr); i2c->adap.nr);
......
...@@ -44,8 +44,12 @@ ...@@ -44,8 +44,12 @@
#include <plat/regs-iic.h> #include <plat/regs-iic.h>
#include <plat/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 { enum s3c24xx_i2c_state {
STATE_IDLE, STATE_IDLE,
STATE_START, STATE_START,
...@@ -54,14 +58,10 @@ enum s3c24xx_i2c_state { ...@@ -54,14 +58,10 @@ enum s3c24xx_i2c_state {
STATE_STOP STATE_STOP
}; };
enum s3c24xx_i2c_type {
TYPE_S3C2410,
TYPE_S3C2440,
};
struct s3c24xx_i2c { struct s3c24xx_i2c {
spinlock_t lock; spinlock_t lock;
wait_queue_head_t wait; wait_queue_head_t wait;
unsigned int quirks;
unsigned int suspended:1; unsigned int suspended:1;
struct i2c_msg *msg; struct i2c_msg *msg;
...@@ -88,26 +88,45 @@ struct s3c24xx_i2c { ...@@ -88,26 +88,45 @@ struct s3c24xx_i2c {
#endif #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); if (pdev->dev.of_node) {
enum s3c24xx_i2c_type type; const struct of_device_id *match;
match = of_match_node(&s3c24xx_i2c_match, pdev->dev.of_node);
#ifdef CONFIG_OF return (unsigned int)match->data;
if (i2c->dev->of_node) }
return of_device_is_compatible(i2c->dev->of_node,
"samsung,s3c2440-i2c");
#endif
type = platform_get_device_id(pdev)->driver_data; return platform_get_device_id(pdev)->driver_data;
return type == TYPE_S3C2440;
} }
/* s3c24xx_i2c_master_complete /* s3c24xx_i2c_master_complete
...@@ -471,6 +490,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) ...@@ -471,6 +490,13 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
unsigned long iicstat; unsigned long iicstat;
int timeout = 400; 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) { while (timeout-- > 0) {
iicstat = readl(i2c->regs + S3C2410_IICSTAT); iicstat = readl(i2c->regs + S3C2410_IICSTAT);
...@@ -480,6 +506,15 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) ...@@ -480,6 +506,15 @@ static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c)
msleep(1); 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; return -ETIMEDOUT;
} }
...@@ -676,7 +711,7 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) ...@@ -676,7 +711,7 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got)
writel(iiccon, i2c->regs + S3C2410_IICCON); writel(iiccon, i2c->regs + S3C2410_IICCON);
if (s3c24xx_i2c_is2440(i2c)) { if (i2c->quirks & QUIRK_S3C2440) {
unsigned long sda_delay; unsigned long sda_delay;
if (pdata->sda_delay) { if (pdata->sda_delay) {
...@@ -761,6 +796,9 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) ...@@ -761,6 +796,9 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
{ {
int idx, gpio, ret; int idx, gpio, ret;
if (i2c->quirks & QUIRK_NO_GPIO)
return 0;
for (idx = 0; idx < 2; idx++) { for (idx = 0; idx < 2; idx++) {
gpio = of_get_gpio(i2c->dev->of_node, idx); gpio = of_get_gpio(i2c->dev->of_node, idx);
if (!gpio_is_valid(gpio)) { if (!gpio_is_valid(gpio)) {
...@@ -785,6 +823,10 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) ...@@ -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) static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c)
{ {
unsigned int idx; unsigned int idx;
if (i2c->quirks & QUIRK_NO_GPIO)
return;
for (idx = 0; idx < 2; idx++) for (idx = 0; idx < 2; idx++)
gpio_free(i2c->gpios[idx]); gpio_free(i2c->gpios[idx]);
} }
...@@ -906,6 +948,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) ...@@ -906,6 +948,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
goto err_noclk; goto err_noclk;
} }
i2c->quirks = s3c24xx_get_device_quirks(pdev);
if (pdata) if (pdata)
memcpy(i2c->pdata, pdata, sizeof(*pdata)); memcpy(i2c->pdata, pdata, sizeof(*pdata));
else else
...@@ -1110,28 +1153,6 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { ...@@ -1110,28 +1153,6 @@ static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = {
/* device driver for platform bus bits */ /* 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 = { static struct platform_driver s3c24xx_i2c_driver = {
.probe = s3c24xx_i2c_probe, .probe = s3c24xx_i2c_probe,
.remove = s3c24xx_i2c_remove, .remove = s3c24xx_i2c_remove,
...@@ -1140,7 +1161,7 @@ static struct platform_driver s3c24xx_i2c_driver = { ...@@ -1140,7 +1161,7 @@ static struct platform_driver s3c24xx_i2c_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "s3c-i2c", .name = "s3c-i2c",
.pm = S3C24XX_DEV_PM_OPS, .pm = S3C24XX_DEV_PM_OPS,
.of_match_table = s3c24xx_i2c_match, .of_match_table = of_match_ptr(s3c24xx_i2c_match),
}, },
}; };
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/of_i2c.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/clk.h> #include <linux/clk.h>
...@@ -653,6 +654,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) ...@@ -653,6 +654,7 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
adap->dev.parent = &dev->dev; adap->dev.parent = &dev->dev;
adap->retries = 5; adap->retries = 5;
adap->nr = dev->id; adap->nr = dev->id;
adap->dev.of_node = dev->dev.of_node;
strlcpy(adap->name, dev->name, sizeof(adap->name)); strlcpy(adap->name, dev->name, sizeof(adap->name));
...@@ -667,6 +669,8 @@ static int sh_mobile_i2c_probe(struct platform_device *dev) ...@@ -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", dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n",
adap->nr, pd->bus_speed); adap->nr, pd->bus_speed);
of_i2c_register_devices(adap);
return 0; return 0;
err_all: err_all:
...@@ -710,11 +714,18 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = { ...@@ -710,11 +714,18 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
.runtime_resume = sh_mobile_i2c_runtime_nop, .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 = { static struct platform_driver sh_mobile_i2c_driver = {
.driver = { .driver = {
.name = "i2c-sh_mobile", .name = "i2c-sh_mobile",
.owner = THIS_MODULE, .owner = THIS_MODULE,
.pm = &sh_mobile_i2c_dev_pm_ops, .pm = &sh_mobile_i2c_dev_pm_ops,
.of_match_table = sh_mobile_i2c_dt_ids,
}, },
.probe = sh_mobile_i2c_probe, .probe = sh_mobile_i2c_probe,
.remove = sh_mobile_i2c_remove, .remove = sh_mobile_i2c_remove,
......
...@@ -401,8 +401,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -401,8 +401,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
disable_irq_nosync(i2c_dev->irq); disable_irq_nosync(i2c_dev->irq);
i2c_dev->irq_disabled = 1; i2c_dev->irq_disabled = 1;
} }
complete(&i2c_dev->msg_complete);
goto err; goto err;
} }
...@@ -411,7 +409,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -411,7 +409,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
i2c_dev->msg_err |= I2C_ERR_NO_ACK; i2c_dev->msg_err |= I2C_ERR_NO_ACK;
if (status & I2C_INT_ARBITRATION_LOST) if (status & I2C_INT_ARBITRATION_LOST)
i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST; i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST;
complete(&i2c_dev->msg_complete);
goto err; goto err;
} }
...@@ -429,14 +426,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -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); 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) { if (status & I2C_INT_PACKET_XFER_COMPLETE) {
BUG_ON(i2c_dev->msg_buf_remaining); BUG_ON(i2c_dev->msg_buf_remaining);
complete(&i2c_dev->msg_complete); 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; return IRQ_HANDLED;
err: err:
/* An error occurred, mask all interrupts */ /* An error occurred, mask all interrupts */
...@@ -446,6 +443,8 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) ...@@ -446,6 +443,8 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
i2c_writel(i2c_dev, status, I2C_INT_STATUS); i2c_writel(i2c_dev, status, I2C_INT_STATUS);
if (i2c_dev->is_dvc) if (i2c_dev->is_dvc)
dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
complete(&i2c_dev->msg_complete);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -476,12 +475,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ...@@ -476,12 +475,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
packet_header = msg->len - 1; packet_header = msg->len - 1;
i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); 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) if (!stop)
packet_header |= I2C_HEADER_REPEAT_START; 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; packet_header |= I2C_HEADER_10BIT_ADDR;
} else {
packet_header |= msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
}
if (msg->flags & I2C_M_IGNORE_NAK) if (msg->flags & I2C_M_IGNORE_NAK)
packet_header |= I2C_HEADER_CONT_ON_NAK; packet_header |= I2C_HEADER_CONT_ON_NAK;
if (msg->flags & I2C_M_RD) if (msg->flags & I2C_M_RD)
...@@ -557,7 +559,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], ...@@ -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) 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 = { static const struct i2c_algorithm tegra_i2c_algo = {
......
...@@ -104,13 +104,8 @@ static int i2c_versatile_probe(struct platform_device *dev) ...@@ -104,13 +104,8 @@ static int i2c_versatile_probe(struct platform_device *dev)
i2c->algo = i2c_versatile_algo; i2c->algo = i2c_versatile_algo;
i2c->algo.data = i2c; i2c->algo.data = i2c;
if (dev->id >= 0) { i2c->adap.nr = dev->id;
/* static bus numbering */ ret = i2c_bit_add_numbered_bus(&i2c->adap);
i2c->adap.nr = dev->id;
ret = i2c_bit_add_numbered_bus(&i2c->adap);
} else
/* dynamic bus numbering */
ret = i2c_bit_add_bus(&i2c->adap);
if (ret >= 0) { if (ret >= 0) {
platform_set_drvdata(dev, i2c); platform_set_drvdata(dev, i2c);
of_i2c_register_devices(&i2c->adap); of_i2c_register_devices(&i2c->adap);
......
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/i2c-xiic.h> #include <linux/i2c-xiic.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/of_i2c.h>
#define DRIVER_NAME "xiic-i2c" #define DRIVER_NAME "xiic-i2c"
...@@ -705,8 +706,6 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) ...@@ -705,8 +706,6 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
goto resource_missing; goto resource_missing;
pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
if (!pdata)
return -EINVAL;
i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
if (!i2c) if (!i2c)
...@@ -730,6 +729,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) ...@@ -730,6 +729,7 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
i2c->adap = xiic_adapter; i2c->adap = xiic_adapter;
i2c_set_adapdata(&i2c->adap, i2c); i2c_set_adapdata(&i2c->adap, i2c);
i2c->adap.dev.parent = &pdev->dev; i2c->adap.dev.parent = &pdev->dev;
i2c->adap.dev.of_node = pdev->dev.of_node;
xiic_reinit(i2c); xiic_reinit(i2c);
...@@ -748,9 +748,13 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev) ...@@ -748,9 +748,13 @@ static int __devinit xiic_i2c_probe(struct platform_device *pdev)
goto add_adapter_failed; goto add_adapter_failed;
} }
/* add in known devices to the bus */ if (pdata) {
for (i = 0; i < pdata->num_devices; i++) /* add in known devices to the bus */
i2c_new_device(&i2c->adap, pdata->devices + i); for (i = 0; i < pdata->num_devices; i++)
i2c_new_device(&i2c->adap, pdata->devices + i);
}
of_i2c_register_devices(&i2c->adap);
return 0; return 0;
...@@ -795,12 +799,21 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev) ...@@ -795,12 +799,21 @@ static int __devexit xiic_i2c_remove(struct platform_device* pdev)
return 0; 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 = { static struct platform_driver xiic_i2c_driver = {
.probe = xiic_i2c_probe, .probe = xiic_i2c_probe,
.remove = __devexit_p(xiic_i2c_remove), .remove = __devexit_p(xiic_i2c_remove),
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = DRIVER_NAME, .name = DRIVER_NAME,
.of_match_table = of_match_ptr(xiic_of_match),
}, },
}; };
......
...@@ -772,6 +772,23 @@ struct device_type i2c_adapter_type = { ...@@ -772,6 +772,23 @@ struct device_type i2c_adapter_type = {
}; };
EXPORT_SYMBOL_GPL(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 #ifdef CONFIG_I2C_COMPAT
static struct class_compat *i2c_adapter_compat_class; static struct class_compat *i2c_adapter_compat_class;
#endif #endif
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-mux.h> #include <linux/i2c-mux.h>
#include <linux/of.h>
#include <linux/of_i2c.h>
/* multiplexer per channel data */ /* multiplexer per channel data */
struct i2c_mux_priv { struct i2c_mux_priv {
...@@ -31,11 +33,11 @@ struct i2c_mux_priv { ...@@ -31,11 +33,11 @@ struct i2c_mux_priv {
struct i2c_algorithm algo; struct i2c_algorithm algo;
struct i2c_adapter *parent; struct i2c_adapter *parent;
void *mux_dev; /* the mux chip/device */ void *mux_priv; /* the mux chip/device */
u32 chan_id; /* the channel id */ u32 chan_id; /* the channel id */
int (*select)(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_dev, u32 chan_id); int (*deselect)(struct i2c_adapter *, void *mux_priv, u32 chan_id);
}; };
static int i2c_mux_master_xfer(struct i2c_adapter *adap, static int i2c_mux_master_xfer(struct i2c_adapter *adap,
...@@ -47,11 +49,11 @@ 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. */ /* 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) if (ret >= 0)
ret = parent->algo->master_xfer(parent, msgs, num); ret = parent->algo->master_xfer(parent, msgs, num);
if (priv->deselect) if (priv->deselect)
priv->deselect(parent, priv->mux_dev, priv->chan_id); priv->deselect(parent, priv->mux_priv, priv->chan_id);
return ret; return ret;
} }
...@@ -67,12 +69,12 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, ...@@ -67,12 +69,12 @@ static int i2c_mux_smbus_xfer(struct i2c_adapter *adap,
/* Select the right mux port and perform the transfer. */ /* 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) if (ret >= 0)
ret = parent->algo->smbus_xfer(parent, addr, flags, ret = parent->algo->smbus_xfer(parent, addr, flags,
read_write, command, size, data); read_write, command, size, data);
if (priv->deselect) if (priv->deselect)
priv->deselect(parent, priv->mux_dev, priv->chan_id); priv->deselect(parent, priv->mux_priv, priv->chan_id);
return ret; return ret;
} }
...@@ -87,7 +89,8 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap) ...@@ -87,7 +89,8 @@ static u32 i2c_mux_functionality(struct i2c_adapter *adap)
} }
struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, 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 *, int (*select) (struct i2c_adapter *,
void *, u32), void *, u32),
int (*deselect) (struct i2c_adapter *, int (*deselect) (struct i2c_adapter *,
...@@ -102,7 +105,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, ...@@ -102,7 +105,7 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
/* Set up private adapter data */ /* Set up private adapter data */
priv->parent = parent; priv->parent = parent;
priv->mux_dev = mux_dev; priv->mux_priv = mux_priv;
priv->chan_id = chan_id; priv->chan_id = chan_id;
priv->select = select; priv->select = select;
priv->deselect = deselect; priv->deselect = deselect;
...@@ -124,6 +127,25 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, ...@@ -124,6 +127,25 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent,
priv->adap.algo_data = priv; priv->adap.algo_data = priv;
priv->adap.dev.parent = &parent->dev; 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) { if (force_nr) {
priv->adap.nr = force_nr; priv->adap.nr = force_nr;
ret = i2c_add_numbered_adapter(&priv->adap); ret = i2c_add_numbered_adapter(&priv->adap);
...@@ -141,6 +163,8 @@ struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, ...@@ -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", dev_info(&parent->dev, "Added multiplexed i2c bus %d\n",
i2c_adapter_id(&priv->adap)); i2c_adapter_id(&priv->adap));
of_i2c_register_devices(&priv->adap);
return &priv->adap; return &priv->adap;
} }
EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); EXPORT_SYMBOL_GPL(i2c_add_mux_adapter);
......
...@@ -15,7 +15,7 @@ config I2C_MUX_GPIO ...@@ -15,7 +15,7 @@ config I2C_MUX_GPIO
through GPIO pins. through GPIO pins.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called gpio-i2cmux. will be called i2c-mux-gpio.
config I2C_MUX_PCA9541 config I2C_MUX_PCA9541
tristate "NXP PCA9541 I2C Master Selector" tristate "NXP PCA9541 I2C Master Selector"
...@@ -25,7 +25,7 @@ config I2C_MUX_PCA9541 ...@@ -25,7 +25,7 @@ config I2C_MUX_PCA9541
I2C Master Selector. I2C Master Selector.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called pca9541. will be called i2c-mux-pca9541.
config I2C_MUX_PCA954x config I2C_MUX_PCA954x
tristate "Philips PCA954x I2C Mux/switches" tristate "Philips PCA954x I2C Mux/switches"
...@@ -35,6 +35,6 @@ config I2C_MUX_PCA954x ...@@ -35,6 +35,6 @@ config I2C_MUX_PCA954x
I2C mux/switch devices. I2C mux/switch devices.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called pca954x. will be called i2c-mux-pca954x.
endmenu endmenu
# #
# Makefile for multiplexer I2C chip drivers. # Makefile for multiplexer I2C chip drivers.
obj-$(CONFIG_I2C_MUX_GPIO) += gpio-i2cmux.o obj-$(CONFIG_I2C_MUX_GPIO) += i2c-mux-gpio.o
obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux-pca9541.o
obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o
ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-mux.h> #include <linux/i2c-mux.h>
#include <linux/gpio-i2cmux.h> #include <linux/i2c-mux-gpio.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -20,10 +20,10 @@ ...@@ -20,10 +20,10 @@
struct gpiomux { struct gpiomux {
struct i2c_adapter *parent; struct i2c_adapter *parent;
struct i2c_adapter **adap; /* child busses */ 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; int i;
...@@ -31,28 +31,28 @@ static void gpiomux_set(const struct gpiomux *mux, unsigned val) ...@@ -31,28 +31,28 @@ static void gpiomux_set(const struct gpiomux *mux, unsigned val)
gpio_set_value(mux->data.gpios[i], val & (1 << i)); 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; struct gpiomux *mux = data;
gpiomux_set(mux, mux->data.values[chan]); i2c_mux_gpio_set(mux, mux->data.values[chan]);
return 0; 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; struct gpiomux *mux = data;
gpiomux_set(mux, mux->data.idle); i2c_mux_gpio_set(mux, mux->data.idle);
return 0; 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 gpiomux *mux;
struct gpio_i2cmux_platform_data *pdata; struct i2c_mux_gpio_platform_data *pdata;
struct i2c_adapter *parent; struct i2c_adapter *parent;
int (*deselect) (struct i2c_adapter *, void *, u32); int (*deselect) (struct i2c_adapter *, void *, u32);
unsigned initial_state; unsigned initial_state;
...@@ -86,16 +86,16 @@ static int __devinit gpiomux_probe(struct platform_device *pdev) ...@@ -86,16 +86,16 @@ static int __devinit gpiomux_probe(struct platform_device *pdev)
goto alloc_failed2; goto alloc_failed2;
} }
if (pdata->idle != GPIO_I2CMUX_NO_IDLE) { if (pdata->idle != I2C_MUX_GPIO_NO_IDLE) {
initial_state = pdata->idle; initial_state = pdata->idle;
deselect = gpiomux_deselect; deselect = i2c_mux_gpio_deselect;
} else { } else {
initial_state = pdata->values[0]; initial_state = pdata->values[0];
deselect = NULL; deselect = NULL;
} }
for (i = 0; i < pdata->n_gpios; i++) { 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) if (ret)
goto err_request_gpio; goto err_request_gpio;
gpio_direction_output(pdata->gpios[i], gpio_direction_output(pdata->gpios[i],
...@@ -105,8 +105,8 @@ static int __devinit gpiomux_probe(struct platform_device *pdev) ...@@ -105,8 +105,8 @@ static int __devinit gpiomux_probe(struct platform_device *pdev)
for (i = 0; i < pdata->n_values; i++) { for (i = 0; i < pdata->n_values; i++) {
u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0; u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0;
mux->adap[i] = i2c_add_mux_adapter(parent, mux, nr, i, mux->adap[i] = i2c_add_mux_adapter(parent, &pdev->dev, mux, nr, i,
gpiomux_select, deselect); i2c_mux_gpio_select, deselect);
if (!mux->adap[i]) { if (!mux->adap[i]) {
ret = -ENODEV; ret = -ENODEV;
dev_err(&pdev->dev, "Failed to add adapter %d\n", i); dev_err(&pdev->dev, "Failed to add adapter %d\n", i);
...@@ -137,7 +137,7 @@ static int __devinit gpiomux_probe(struct platform_device *pdev) ...@@ -137,7 +137,7 @@ static int __devinit gpiomux_probe(struct platform_device *pdev)
return ret; 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); struct gpiomux *mux = platform_get_drvdata(pdev);
int i; int i;
...@@ -156,18 +156,18 @@ static int __devexit gpiomux_remove(struct platform_device *pdev) ...@@ -156,18 +156,18 @@ static int __devexit gpiomux_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct platform_driver gpiomux_driver = { static struct platform_driver i2c_mux_gpio_driver = {
.probe = gpiomux_probe, .probe = i2c_mux_gpio_probe,
.remove = __devexit_p(gpiomux_remove), .remove = __devexit_p(i2c_mux_gpio_remove),
.driver = { .driver = {
.owner = THIS_MODULE, .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_DESCRIPTION("GPIO-based I2C multiplexer driver");
MODULE_AUTHOR("Peter Korsgaard <peter.korsgaard@barco.com>"); MODULE_AUTHOR("Peter Korsgaard <peter.korsgaard@barco.com>");
MODULE_LICENSE("GPL"); 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, ...@@ -353,7 +353,8 @@ static int pca9541_probe(struct i2c_client *client,
force = 0; force = 0;
if (pdata) if (pdata)
force = pdata->modes[0].adap_id; 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_select_chan,
pca9541_release_chan); pca9541_release_chan);
......
...@@ -226,7 +226,7 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -226,7 +226,7 @@ static int pca954x_probe(struct i2c_client *client,
} }
data->virt_adaps[num] = data->virt_adaps[num] =
i2c_add_mux_adapter(adap, client, i2c_add_mux_adapter(adap, &client->dev, client,
force, num, pca954x_select_chan, force, num, pca954x_select_chan,
(pdata && pdata->modes[num].deselect_on_exit) (pdata && pdata->modes[num].deselect_on_exit)
? pca954x_deselect_mux : NULL); ? pca954x_deselect_mux : NULL);
......
...@@ -90,8 +90,22 @@ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) ...@@ -90,8 +90,22 @@ struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
if (!dev) if (!dev)
return NULL; return NULL;
return to_i2c_client(dev); return i2c_verify_client(dev);
} }
EXPORT_SYMBOL(of_find_i2c_device_by_node); 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"); MODULE_LICENSE("GPL");
/* /*
* gpio-i2cmux interface to platform code * i2c-mux-gpio interface to platform code
* *
* Peter Korsgaard <peter.korsgaard@barco.com> * Peter Korsgaard <peter.korsgaard@barco.com>
* *
...@@ -8,14 +8,14 @@ ...@@ -8,14 +8,14 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifndef _LINUX_GPIO_I2CMUX_H #ifndef _LINUX_I2C_MUX_GPIO_H
#define _LINUX_GPIO_I2CMUX_H #define _LINUX_I2C_MUX_GPIO_H
/* MUX has no specific idle mode */ /* 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 * @parent: Parent I2C bus adapter number
* @base_nr: Base I2C bus number to number adapters from or zero for dynamic * @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 * @values: Array of bitmasks of GPIO settings (low/high) for each
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
* @n_gpios: Number of GPIOs 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 * @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 parent;
int base_nr; int base_nr;
const unsigned *values; const unsigned *values;
...@@ -35,4 +35,4 @@ struct gpio_i2cmux_platform_data { ...@@ -35,4 +35,4 @@ struct gpio_i2cmux_platform_data {
unsigned idle; unsigned idle;
}; };
#endif /* _LINUX_GPIO_I2CMUX_H */ #endif /* _LINUX_I2C_MUX_GPIO_H */
...@@ -34,7 +34,8 @@ ...@@ -34,7 +34,8 @@
* mux control. * mux control.
*/ */
struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, 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 *, int (*select) (struct i2c_adapter *,
void *mux_dev, u32 chan_id), void *mux_dev, u32 chan_id),
int (*deselect) (struct i2c_adapter *, int (*deselect) (struct i2c_adapter *,
......
...@@ -232,6 +232,7 @@ struct i2c_client { ...@@ -232,6 +232,7 @@ struct i2c_client {
#define to_i2c_client(d) container_of(d, struct i2c_client, dev) #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_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) 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); ...@@ -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 */ /* 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); 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 #else
static inline void of_i2c_register_devices(struct i2c_adapter *adap) 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.
先完成此消息的编辑!
想要评论请 注册