i2c-pxa2xx: use dynamic register layout

This will prepare the driver to handle register layouts where certain
registers are not available at all.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Ben Dooks <ben-linux@fluff.org>
This commit is contained in:
Sebastian Andrzej Siewior 2011-02-23 12:38:15 +01:00 committed by Ben Dooks
parent a952baa034
commit d6668c7cd4
1 changed files with 50 additions and 20 deletions

View File

@ -38,29 +38,49 @@
#include <asm/irq.h>
#include <plat/i2c.h>
struct pxa_reg_layout {
u32 ibmr;
u32 idbr;
u32 icr;
u32 isr;
u32 isar;
};
enum pxa_i2c_types {
REGS_PXA2XX,
REGS_PXA3XX,
};
/*
* I2C register offsets will be shifted 0 or 1 bit left, depending on
* different SoCs
* I2C registers definitions
*/
#define REG_SHIFT_0 (0 << 0)
#define REG_SHIFT_1 (1 << 0)
#define REG_SHIFT(d) ((d) & 0x1)
static struct pxa_reg_layout pxa_reg_layout[] = {
[REGS_PXA2XX] = {
.ibmr = 0x00,
.idbr = 0x10,
.icr = 0x20,
.isr = 0x30,
.isar = 0x40,
},
[REGS_PXA3XX] = {
.ibmr = 0x00,
.idbr = 0x08,
.icr = 0x10,
.isr = 0x18,
.isar = 0x20,
},
};
static const struct platform_device_id i2c_pxa_id_table[] = {
{ "pxa2xx-i2c", REG_SHIFT_1 },
{ "pxa3xx-pwri2c", REG_SHIFT_0 },
{ "pxa2xx-i2c", REGS_PXA2XX },
{ "pxa3xx-pwri2c", REGS_PXA3XX },
{ },
};
MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
/*
* I2C registers and bit definitions
* I2C bit definitions
*/
#define IBMR (0x00)
#define IDBR (0x08)
#define ICR (0x10)
#define ISR (0x18)
#define ISAR (0x20)
#define ICR_START (1 << 0) /* start bit */
#define ICR_STOP (1 << 1) /* stop bit */
@ -111,7 +131,11 @@ struct pxa_i2c {
u32 icrlog[32];
void __iomem *reg_base;
unsigned int reg_shift;
void __iomem *reg_ibmr;
void __iomem *reg_idbr;
void __iomem *reg_icr;
void __iomem *reg_isr;
void __iomem *reg_isar;
unsigned long iobase;
unsigned long iosize;
@ -121,11 +145,11 @@ struct pxa_i2c {
unsigned int fast_mode :1;
};
#define _IBMR(i2c) ((i2c)->reg_base + (0x0 << (i2c)->reg_shift))
#define _IDBR(i2c) ((i2c)->reg_base + (0x4 << (i2c)->reg_shift))
#define _ICR(i2c) ((i2c)->reg_base + (0x8 << (i2c)->reg_shift))
#define _ISR(i2c) ((i2c)->reg_base + (0xc << (i2c)->reg_shift))
#define _ISAR(i2c) ((i2c)->reg_base + (0x10 << (i2c)->reg_shift))
#define _IBMR(i2c) ((i2c)->reg_ibmr)
#define _IDBR(i2c) ((i2c)->reg_idbr)
#define _ICR(i2c) ((i2c)->reg_icr)
#define _ISR(i2c) ((i2c)->reg_isr)
#define _ISAR(i2c) ((i2c)->reg_isar)
/*
* I2C Slave mode address
@ -1001,6 +1025,7 @@ static int i2c_pxa_probe(struct platform_device *dev)
struct resource *res;
struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
const struct platform_device_id *id = platform_get_device_id(dev);
enum pxa_i2c_types i2c_type = id->driver_data;
int ret;
int irq;
@ -1044,7 +1069,12 @@ static int i2c_pxa_probe(struct platform_device *dev)
ret = -EIO;
goto eremap;
}
i2c->reg_shift = REG_SHIFT(id->driver_data);
i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr;
i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr;
i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;
i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr;
i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
i2c->iobase = res->start;
i2c->iosize = resource_size(res);