aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorJean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>2011-10-06 14:26:27 -0400
committerBen Dooks <ben-linux@fluff.org>2011-10-29 06:00:51 -0400
commit18c4089e6cd6b3052895481628f478ba8351ac00 (patch)
treec7611bc19e59e1b0a35c96b1ae2c23fd60d470bf /drivers/i2c
parent4ff895bc8b90e30ff8e89ca7bc6666b229c77e5d (diff)
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')
-rw-r--r--drivers/i2c/busses/i2c-designware.c17
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 @@
37#include <linux/platform_device.h> 37#include <linux/platform_device.h>
38#include <linux/io.h> 38#include <linux/io.h>
39#include <linux/slab.h> 39#include <linux/slab.h>
40#include <linux/swab.h>
40 41
41/* 42/*
42 * Registers offset 43 * Registers offset
@@ -193,6 +194,7 @@ static char *abort_sources[] = {
193 * @status: i2c master status, one of STATUS_* 194 * @status: i2c master status, one of STATUS_*
194 * @abort_source: copy of the TX_ABRT_SOURCE register 195 * @abort_source: copy of the TX_ABRT_SOURCE register
195 * @irq: interrupt number for the i2c master 196 * @irq: interrupt number for the i2c master
197 * @swab: true if the instantiated IP is of different endianess
196 * @adapter: i2c subsystem adapter node 198 * @adapter: i2c subsystem adapter node
197 * @tx_fifo_depth: depth of the hardware tx fifo 199 * @tx_fifo_depth: depth of the hardware tx fifo
198 * @rx_fifo_depth: depth of the hardware rx fifo 200 * @rx_fifo_depth: depth of the hardware rx fifo
@@ -216,6 +218,7 @@ struct dw_i2c_dev {
216 unsigned int status; 218 unsigned int status;
217 u32 abort_source; 219 u32 abort_source;
218 int irq; 220 int irq;
221 int swab;
219 struct i2c_adapter adapter; 222 struct i2c_adapter adapter;
220 unsigned int tx_fifo_depth; 223 unsigned int tx_fifo_depth;
221 unsigned int rx_fifo_depth; 224 unsigned int rx_fifo_depth;
@@ -223,11 +226,19 @@ struct dw_i2c_dev {
223 226
224static u32 dw_readl(struct dw_i2c_dev *dev, int offset) 227static u32 dw_readl(struct dw_i2c_dev *dev, int offset)
225{ 228{
226 return readl(dev->base + offset); 229 u32 value = readl(dev->base + offset);
230
231 if (dev->swab)
232 return swab32(value);
233 else
234 return value;
227} 235}
228 236
229static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) 237static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
230{ 238{
239 if (dev->swab)
240 b = swab32(b);
241
231 writel(b, dev->base + offset); 242 writel(b, dev->base + offset);
232} 243}
233 244
@@ -760,7 +771,9 @@ static int __devinit dw_i2c_probe(struct platform_device *pdev)
760 } 771 }
761 772
762 reg = dw_readl(dev, DW_IC_COMP_TYPE); 773 reg = dw_readl(dev, DW_IC_COMP_TYPE);
763 if (reg != 0x44570140) { 774 if (reg == ___constant_swab32(0x44570140))
775 dev->swab = 1;
776 else if (reg != 0x44570140) {
764 dev_err(&pdev->dev, "Unknown Synopsys component type: " 777 dev_err(&pdev->dev, "Unknown Synopsys component type: "
765 "0x%08x\n", reg); 778 "0x%08x\n", reg);
766 r = -ENODEV; 779 r = -ENODEV;