i2c: designware: Add support for 16bit register access
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>
This commit is contained in:

committed by
Wolfram Sang

parent
44454baa7c
commit
a8a9f3fef1
@@ -164,9 +164,15 @@ static char *abort_sources[] = {
|
|||||||
|
|
||||||
u32 dw_readl(struct dw_i2c_dev *dev, int offset)
|
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);
|
return swab32(value);
|
||||||
else
|
else
|
||||||
return value;
|
return value;
|
||||||
@@ -174,10 +180,15 @@ u32 dw_readl(struct dw_i2c_dev *dev, int offset)
|
|||||||
|
|
||||||
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
|
void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset)
|
||||||
{
|
{
|
||||||
if (dev->swab)
|
if (dev->accessor_flags & ACCESS_SWAP)
|
||||||
b = swab32(b);
|
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
|
static u32
|
||||||
@@ -251,14 +262,14 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
|
|||||||
|
|
||||||
input_clock_khz = dev->get_clk_rate_khz(dev);
|
input_clock_khz = dev->get_clk_rate_khz(dev);
|
||||||
|
|
||||||
/* Configure register endianess access */
|
|
||||||
reg = dw_readl(dev, DW_IC_COMP_TYPE);
|
reg = dw_readl(dev, DW_IC_COMP_TYPE);
|
||||||
if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
|
if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) {
|
||||||
dev->swab = 1;
|
/* Configure register endianess access */
|
||||||
reg = DW_IC_COMP_TYPE_VALUE;
|
dev->accessor_flags |= ACCESS_SWAP;
|
||||||
}
|
} else if (reg == (DW_IC_COMP_TYPE_VALUE & 0x0000ffff)) {
|
||||||
|
/* Configure register access mode 16bit */
|
||||||
if (reg != DW_IC_COMP_TYPE_VALUE) {
|
dev->accessor_flags |= ACCESS_16BIT;
|
||||||
|
} else if (reg != DW_IC_COMP_TYPE_VALUE) {
|
||||||
dev_err(dev->dev, "Unknown Synopsys component type: "
|
dev_err(dev->dev, "Unknown Synopsys component type: "
|
||||||
"0x%08x\n", reg);
|
"0x%08x\n", reg);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@@ -82,7 +82,7 @@ struct dw_i2c_dev {
|
|||||||
unsigned int status;
|
unsigned int status;
|
||||||
u32 abort_source;
|
u32 abort_source;
|
||||||
int irq;
|
int irq;
|
||||||
int swab;
|
u32 accessor_flags;
|
||||||
struct i2c_adapter adapter;
|
struct i2c_adapter adapter;
|
||||||
u32 functionality;
|
u32 functionality;
|
||||||
u32 master_cfg;
|
u32 master_cfg;
|
||||||
@@ -90,6 +90,9 @@ struct dw_i2c_dev {
|
|||||||
unsigned int rx_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 u32 dw_readl(struct dw_i2c_dev *dev, int offset);
|
||||||
extern void dw_writel(struct dw_i2c_dev *dev, u32 b, 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);
|
extern int i2c_dw_init(struct dw_i2c_dev *dev);
|
||||||
|
Reference in New Issue
Block a user