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 ...
This commit is contained in:
Коммит
ae32adc1e0
|
@ -0,0 +1,60 @@
|
|||
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
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
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>;
|
||||
};
|
|
@ -1,11 +1,11 @@
|
|||
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 @@ err_free_irq:
|
|||
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;
|
||||
|
|
|
@ -1,157 +0,0 @@
|
|||
/*
|
||||
* 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. */
|
||||
|
||||
/* s3c24xx_i2c_is2440()
|
||||
*
|
||||
* return true is this is an s3c2440
|
||||
*/
|
||||
|
||||
static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(i2c->dev);
|
||||
enum s3c24xx_i2c_type type;
|
||||
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
|
||||
if (i2c->dev->of_node)
|
||||
return of_device_is_compatible(i2c->dev->of_node,
|
||||
"samsung,s3c2440-i2c");
|
||||
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
|
||||
|
||||
type = platform_get_device_id(pdev)->driver_data;
|
||||
return type == TYPE_S3C2440;
|
||||
/* s3c24xx_get_device_quirks
|
||||
*
|
||||
* Get controller type either from device tree or platform device variant.
|
||||
*/
|
||||
|
||||
static inline unsigned int s3c24xx_get_device_quirks(struct platform_device *pdev)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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 @@ free_gpio:
|
|||
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 @@ err:
|
|||
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", ®);
|
||||
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
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#
|
||||
# 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 @@ alloc_failed:
|
|||
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");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* 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)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче