You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
@@ -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,
|
||||
+4
-4
@@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
+75
-171
@@ -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);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user