diff options
author | Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com> | 2011-10-06 20:26:27 +0200 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2011-10-29 12:00:51 +0200 |
commit | 18c4089e6cd6b3052895481628f478ba8351ac00 (patch) | |
tree | c7611bc19e59e1b0a35c96b1ae2c23fd60d470bf /drivers/i2c/busses/i2c-designware.c | |
parent | i2c-designware: Check component type register (diff) | |
download | linux-18c4089e6cd6b3052895481628f478ba8351ac00.tar.xz linux-18c4089e6cd6b3052895481628f478ba8351ac00.zip |
i2c-designware: Allow mixed endianness accesses
Allows CPUs of a given endianness to access a dw controller of a different
endianness. Endianncess difference is detected at run time through the dw
component type register.
Signed-off-by: Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>
Signed-off-by: Dirk Brandewie <dirk.brandewie@gmail.com>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers/i2c/busses/i2c-designware.c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/i2c/busses/i2c-designware.c b/drivers/i2c/busses/i2c-designware.c index 49386951f7fd..934dfe1e6ce9 100644 --- a/drivers/i2c/busses/i2c-designware.c +++ b/drivers/i2c/busses/i2c-designware.c @@ -37,6 +37,7 @@ #include <linux/platform_device.h> #include <linux/io.h> #include <linux/slab.h> +#include <linux/swab.h> /* * Registers offset @@ -193,6 +194,7 @@ static char *abort_sources[] = { * @status: i2c master status, one of STATUS_* * @abort_source: copy of the TX_ABRT_SOURCE register * @irq: interrupt number for the i2c master + * @swab: true if the instantiated IP is of different endianess * @adapter: i2c subsystem adapter node * @tx_fifo_depth: depth of the hardware tx fifo * @rx_fifo_depth: depth of the hardware rx fifo @@ -216,6 +218,7 @@ struct dw_i2c_dev { unsigned int status; u32 abort_source; int irq; + int swab; struct i2c_adapter adapter; unsigned int tx_fifo_depth; unsigned int rx_fifo_depth; @@ -223,11 +226,19 @@ struct dw_i2c_dev { static u32 dw_readl(struct dw_i2c_dev *dev, int offset) { - return readl(dev->base + offset); + u32 value = readl(dev->base + offset); + + if (dev->swab) + return swab32(value); + else + return value; } static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) { + if (dev->swab) + b = swab32(b); + writel(b, dev->base + offset); } @@ -760,7 +771,9 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev) } reg = dw_readl(dev, DW_IC_COMP_TYPE); - if (reg != 0x44570140) { + if (reg == ___constant_swab32(0x44570140)) + dev->swab = 1; + else if (reg != 0x44570140) { dev_err(&pdev->dev, "Unknown Synopsys component type: " "0x%08x\n", reg); r = -ENODEV; |