Skip to content

Commit

Permalink
Merge branch 'i2c-embedded/for-3.4' of git://git.pengutronix.de/git/w…
Browse files Browse the repository at this point in the history
…sa/linux

Pull i2c embedded updates from Wolfram Sang:
 "Nothing special from i2c-embedded for this merge window.  Two new
  drivers, minor feature additions, bugfixes, cleanups.

  All patches have been in linux-next for some time, too."

* 'i2c-embedded/for-3.4' of git://git.pengutronix.de/git/wsa/linux:
  i2c-eg20t: Remove write-only variables
  i2c-eg20t: Rework pch_i2c_wait_for_bus_idle to reduce wait time
  i2c-s3c2410: Add stub runtime power management
  i2c-s3c2410: Convert to devm_kzalloc()
  i2c: add CSR SiRFprimaII on-chip I2C controllers driver
  i2c: tegra: Remove unnecessary write to INT_STATUS
  i2c: imx: fix imx driver to work though signal is pending
  i2c: designware: dw_i2c_init_driver as subsys initcall
  misc: at24: describe platform_data with kernel_doc
  i2c: Move I2C_EG20T option to the right place.
  i2c: Support for Netlogic XLR/XLS I2C controller.
  i2c: mpc: Add support for SMBUS_READ_BLOCK_DATA
  i2c: versatile: Add Device Tree support
  • Loading branch information
Linus Torvalds committed Mar 23, 2012
2 parents 475c77e + bbceeee commit fc2bb8d
Show file tree
Hide file tree
Showing 13 changed files with 912 additions and 66 deletions.
19 changes: 19 additions & 0 deletions Documentation/devicetree/bindings/i2c/sirf-i2c.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
I2C for SiRFprimaII platforms

Required properties :
- compatible : Must be "sirf,prima2-i2c"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: interrupt number to the cpu.

Optional properties:
- clock-frequency : Constains desired I2C/HS-I2C bus clock frequency in Hz.
The absence of the propoerty indicates the default frequency 100 kHz.

Examples :

i2c0: i2c@b00e0000 {
compatible = "sirf,prima2-i2c";
reg = <0xb00e0000 0x10000>;
interrupts = <24>;
};
44 changes: 32 additions & 12 deletions drivers/i2c/busses/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,21 @@ config I2C_DESIGNWARE_PCI
This driver can also be built as a module. If so, the module
will be called i2c-designware-pci.

config I2C_EG20T
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
depends on PCI
help
This driver is for PCH(Platform controller Hub) I2C of EG20T which
is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH I2C bus device.

This driver also can be used for LAPIS Semiconductor IOH(Input/
Output Hub), ML7213, ML7223 and ML7831.
ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
for MP(Media Phone) use and ML7831 IOH is for general purpose use.
ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.

config I2C_GPIO
tristate "GPIO-based bitbanging I2C"
depends on GENERIC_GPIO
Expand Down Expand Up @@ -630,6 +645,16 @@ config I2C_SIMTEC
This driver can also be built as a module. If so, the module
will be called i2c-simtec.

config I2C_SIRF
tristate "CSR SiRFprimaII I2C interface"
depends on ARCH_PRIMA2
help
If you say yes to this option, support will be included for the
CSR SiRFprimaII I2C interface.

This driver can also be built as a module. If so, the module
will be called i2c-sirf.

config I2C_STU300
tristate "ST Microelectronics DDC I2C interface"
depends on MACH_U300
Expand Down Expand Up @@ -681,20 +706,15 @@ config I2C_XILINX
This driver can also be built as a module. If so, the module
will be called xilinx_i2c.

config I2C_EG20T
tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C"
depends on PCI
config I2C_XLR
tristate "XLR I2C support"
depends on CPU_XLR
help
This driver is for PCH(Platform controller Hub) I2C of EG20T which
is an IOH(Input/Output Hub) for x86 embedded processor.
This driver can access PCH I2C bus device.
This driver enables support for the on-chip I2C interface of
the Netlogic XLR/XLS MIPS processors.

This driver also can be used for LAPIS Semiconductor IOH(Input/
Output Hub), ML7213, ML7223 and ML7831.
ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
for MP(Media Phone) use and ML7831 IOH is for general purpose use.
ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
This driver can also be built as a module. If so, the module
will be called i2c-xlr.

comment "External I2C/SMBus adapter drivers"

Expand Down
4 changes: 3 additions & 1 deletion drivers/i2c/busses/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o
i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o
i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o
obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o
Expand All @@ -63,12 +64,13 @@ obj-$(CONFIG_I2C_S6000) += i2c-s6000.o
obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o
obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o
obj-$(CONFIG_I2C_STU300) += i2c-stu300.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o
obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o
obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o
obj-$(CONFIG_I2C_XLR) += i2c-xlr.o

# External I2C/SMBus adapter drivers
obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o
Expand Down
2 changes: 1 addition & 1 deletion drivers/i2c/busses/i2c-designware-platdrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ static int __init dw_i2c_init_driver(void)
{
return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe);
}
module_init(dw_i2c_init_driver);
subsys_initcall(dw_i2c_init_driver);

static void __exit dw_i2c_exit_driver(void)
{
Expand Down
44 changes: 21 additions & 23 deletions drivers/i2c/busses/i2c-eg20t.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,30 +271,36 @@ static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2)
/**
* pch_i2c_wait_for_bus_idle() - check the status of bus.
* @adap: Pointer to struct i2c_algo_pch_data.
* @timeout: waiting time counter (us).
* @timeout: waiting time counter (ms).
*/
static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
s32 timeout)
{
void __iomem *p = adap->pch_base_address;
ktime_t ns_val;
int schedule = 0;
unsigned long end = jiffies + msecs_to_jiffies(timeout);

while (ioread32(p + PCH_I2CSR) & I2CMBB_BIT) {
if (time_after(jiffies, end)) {
pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
pch_err(adap, "%s: Timeout Error.return%d\n",
__func__, -ETIME);
pch_i2c_init(adap);

if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
return 0;
return -ETIME;
}

/* MAX timeout value is timeout*1000*1000nsec */
ns_val = ktime_add_ns(ktime_get(), timeout*1000*1000);
do {
msleep(20);
if ((ioread32(p + PCH_I2CSR) & I2CMBB_BIT) == 0)
return 0;
} while (ktime_lt(ktime_get(), ns_val));
if (!schedule)
/* Retry after some usecs */
udelay(5);
else
/* Wait a bit more without consuming CPU */
usleep_range(20, 1000);

pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR));
pch_err(adap, "%s: Timeout Error.return%d\n", __func__, -ETIME);
pch_i2c_init(adap);
schedule = 1;
}

return -ETIME;
return 0;
}

/**
Expand Down Expand Up @@ -778,8 +784,6 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *pmsg;
u32 i = 0;
u32 status;
u32 msglen;
u32 subaddrlen;
s32 ret;

struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
Expand All @@ -804,12 +808,6 @@ static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
status = pmsg->flags;
pch_dbg(adap,
"After invoking I2C_MODE_SEL :flag= 0x%x\n", status);
/* calculate sub address length and message length */
/* these are applicable only for buffer mode */
subaddrlen = pmsg->buf[0];
/* calculate actual message length excluding
* the sub address fields */
msglen = (pmsg->len) - (subaddrlen + 1);

if ((status & (I2C_M_RD)) != false) {
ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num),
Expand Down
5 changes: 0 additions & 5 deletions drivers/i2c/busses/i2c-imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,11 +149,6 @@ static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
break;
if (!for_busy && !(temp & I2SR_IBB))
break;
if (signal_pending(current)) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> I2C Interrupted\n", __func__);
return -EINTR;
}
if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> I2C bus is busy\n", __func__);
Expand Down
63 changes: 49 additions & 14 deletions drivers/i2c/busses/i2c-mpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,7 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
}

static int mpc_read(struct mpc_i2c *i2c, int target,
u8 *data, int length, int restart)
u8 *data, int length, int restart, bool recv_len)
{
unsigned timeout = i2c->adap.timeout;
int i, result;
Expand All @@ -470,7 +470,7 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
return result;

if (length) {
if (length == 1)
if (length == 1 && !recv_len)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
else
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA);
Expand All @@ -479,17 +479,46 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
}

for (i = 0; i < length; i++) {
u8 byte;

result = i2c_wait(i2c, timeout, 0);
if (result < 0)
return result;

/* Generate txack on next to last byte */
if (i == length - 2)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
/* Do not generate stop on last byte */
if (i == length - 1)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX);
data[i] = readb(i2c->base + MPC_I2C_DR);
/*
* For block reads, we have to know the total length (1st byte)
* before we can determine if we are done.
*/
if (i || !recv_len) {
/* Generate txack on next to last byte */
if (i == length - 2)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
| CCR_TXAK);
/* Do not generate stop on last byte */
if (i == length - 1)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
| CCR_MTX);
}

byte = readb(i2c->base + MPC_I2C_DR);

/*
* Adjust length if first received byte is length.
* The length is 1 length byte plus actually data length
*/
if (i == 0 && recv_len) {
if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX)
return -EPROTO;
length += byte;
/*
* For block reads, generate txack here if data length
* is 1 byte (total length is 2 bytes).
*/
if (length == 2)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA
| CCR_TXAK);
}
data[i] = byte;
}

return length;
Expand Down Expand Up @@ -532,20 +561,26 @@ static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
"Doing %s %d bytes to 0x%02x - %d of %d messages\n",
pmsg->flags & I2C_M_RD ? "read" : "write",
pmsg->len, pmsg->addr, i + 1, num);
if (pmsg->flags & I2C_M_RD)
ret =
mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
else
if (pmsg->flags & I2C_M_RD) {
bool recv_len = pmsg->flags & I2C_M_RECV_LEN;

ret = mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i,
recv_len);
if (recv_len && ret > 0)
pmsg->len = ret;
} else {
ret =
mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i);
}
}
mpc_i2c_stop(i2c);
return (ret < 0) ? ret : num;
}

static u32 mpc_functionality(struct i2c_adapter *adap)
{
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL
| I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
}

static const struct i2c_algorithm mpc_algo = {
Expand Down
14 changes: 11 additions & 3 deletions drivers/i2c/busses/i2c-s3c2410.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/clk.h>
#include <linux/cpufreq.h>
#include <linux/slab.h>
Expand Down Expand Up @@ -564,6 +565,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
int retry;
int ret;

pm_runtime_get_sync(&adap->dev);
clk_enable(i2c->clk);

for (retry = 0; retry < adap->retries; retry++) {
Expand All @@ -572,6 +574,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,

if (ret != -EAGAIN) {
clk_disable(i2c->clk);
pm_runtime_put_sync(&adap->dev);
return ret;
}

Expand All @@ -581,6 +584,7 @@ static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
}

clk_disable(i2c->clk);
pm_runtime_put_sync(&adap->dev);
return -EREMOTEIO;
}

Expand Down Expand Up @@ -890,7 +894,7 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
}
}

i2c = kzalloc(sizeof(struct s3c24xx_i2c), GFP_KERNEL);
i2c = devm_kzalloc(&pdev->dev, sizeof(struct s3c24xx_i2c), GFP_KERNEL);
if (!i2c) {
dev_err(&pdev->dev, "no memory for state\n");
return -ENOMEM;
Expand Down Expand Up @@ -1013,6 +1017,9 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
of_i2c_register_devices(&i2c->adap);
platform_set_drvdata(pdev, i2c);

pm_runtime_enable(&pdev->dev);
pm_runtime_enable(&i2c->adap.dev);

dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev));
clk_disable(i2c->clk);
return 0;
Expand All @@ -1035,7 +1042,6 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev)
clk_put(i2c->clk);

err_noclk:
kfree(i2c);
return ret;
}

Expand All @@ -1048,6 +1054,9 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
{
struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev);

pm_runtime_disable(&i2c->adap.dev);
pm_runtime_disable(&pdev->dev);

s3c24xx_i2c_deregister_cpufreq(i2c);

i2c_del_adapter(&i2c->adap);
Expand All @@ -1061,7 +1070,6 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev)
release_resource(i2c->ioarea);
s3c24xx_i2c_dt_gpio_free(i2c);
kfree(i2c->ioarea);
kfree(i2c);

return 0;
}
Expand Down
Loading

0 comments on commit fc2bb8d

Please sign in to comment.