diff options
author | Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com> | 2011-10-06 14:26:27 -0400 |
---|---|---|
committer | Ben Dooks <ben-linux@fluff.org> | 2011-10-29 06:00:51 -0400 |
commit | 18c4089e6cd6b3052895481628f478ba8351ac00 (patch) | |
tree | c7611bc19e59e1b0a35c96b1ae2c23fd60d470bf /drivers/i2c | |
parent | 4ff895bc8b90e30ff8e89ca7bc6666b229c77e5d (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.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 @@ | |||
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 | ||
224 | static u32 dw_readl(struct dw_i2c_dev *dev, int offset) | 227 | static 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 | ||
229 | static void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) | 237 | static 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; |