Skip to content

Commit

Permalink
i2c: designware: Add support for 16bit register access
Browse files Browse the repository at this point in the history
The STM SPEAr platform can only access the i2c controller register
via 16bit read/write functions. This patch adds support to
automatically detect this 16bit access mode.

Signed-off-by: Stefan Roese <sr@denx.de>
Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
  • Loading branch information
Stefan Roese authored and Wolfram Sang committed May 12, 2012
1 parent 44454ba commit a8a9f3f
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 11 deletions.
31 changes: 21 additions & 10 deletions drivers/i2c/busses/i2c-designware-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,20 +164,31 @@ 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;
}

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
Expand Down Expand Up @@ -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;
Expand Down
5 changes: 4 additions & 1 deletion drivers/i2c/busses/i2c-designware-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,17 @@ 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;
unsigned int tx_fifo_depth;
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);
Expand Down

0 comments on commit a8a9f3f

Please sign in to comment.