Re: [PATCH 1/2] i2c-mv64xxx: Add I2C Transaction Generator support
On Fri, Jun 07, 2013 at 05:42:22PM +0200, Gregory CLEMENT wrote: > From: Zbigniew Bodek > > The I2C Transaction Generator offloads CPU from managing I2C > transfer step by step. > > This feature is currently only available on Armada XP, so usage of > this mechanism is activated through device tree. > > [gregory.clem...@free-electrons.com: Rewrite some part to be applied > on the the code modified by Russell King's fixes] > [gregory.clem...@free-electrons.com: Merge and split the commits to > push them to the accurate maintainer i2c and of]] > [gregory.clem...@free-electrons.com: Reword the commit log] > > Signed-off-by: Piotr Ziecik > Signed-off-by: Gregory CLEMENT > --- > drivers/i2c/busses/i2c-mv64xxx.c | 143 > +-- > 1 file changed, 139 insertions(+), 4 deletions(-) > > diff --git a/drivers/i2c/busses/i2c-mv64xxx.c > b/drivers/i2c/busses/i2c-mv64xxx.c > index 6356439..5376dc3 100644 > --- a/drivers/i2c/busses/i2c-mv64xxx.c > +++ b/drivers/i2c/busses/i2c-mv64xxx.c > @@ -24,7 +24,7 @@ > #include > #include > > -/* Register defines */ > +/* Register defines (I2C port) */ > #define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 > #define MV64XXX_I2C_REG_DATA0x04 > #define MV64XXX_I2C_REG_CONTROL 0x08 > @@ -59,6 +59,29 @@ > #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK0xe8 > #define MV64XXX_I2C_STATUS_NO_STATUS0xf8 > > +/* Register defines (I2C bridge) */ > +#define MV64XXX_I2C_REG_TX_DATA_LO 0xC0 > +#define MV64XXX_I2C_REG_TX_DATA_HI 0xC4 > +#define MV64XXX_I2C_REG_RX_DATA_LO 0xC8 > +#define MV64XXX_I2C_REG_RX_DATA_HI 0xCC > +#define MV64XXX_I2C_REG_BRIDGE_CONTROL 0xD0 > +#define MV64XXX_I2C_REG_BRIDGE_STATUS 0xD4 > +#define MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE 0xD8 > +#define MV64XXX_I2C_REG_BRIDGE_INTR_MASK0xDC > +#define MV64XXX_I2C_REG_BRIDGE_TIMING 0xE0 > + > +/* Bridge Control values */ > +#define MV64XXX_I2C_BRIDGE_CONTROL_WR 0x0001 > +#define MV64XXX_I2C_BRIDGE_CONTROL_RD 0x0002 > +#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2 > +#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT 0x1000 > +#define MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT13 > +#define MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT16 > +#define MV64XXX_I2C_BRIDGE_CONTROL_ENABLE 0x0008 > + > +/* Bridge Status values */ > +#define MV64XXX_I2C_BRIDGE_STATUS_ERROR 0x0001 > + > /* Driver states */ > enum { > MV64XXX_I2C_STATE_INVALID, > @@ -110,6 +133,7 @@ struct mv64xxx_i2c_data { > spinlock_t lock; > struct i2c_msg *msg; > struct i2c_adapter adapter; > + int bridge_enabled; > }; > > static void > @@ -157,6 +181,16 @@ mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) > writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); > writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, > drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); > + > + if (drv_data->bridge_enabled) { > + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); > + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_TIMING); > + writel(0, drv_data->reg_base + > + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); > + writel(0, drv_data->reg_base + > + MV64XXX_I2C_REG_BRIDGE_INTR_MASK); > + } > + > drv_data->state = MV64XXX_I2C_STATE_IDLE; > } > > @@ -368,6 +402,19 @@ mv64xxx_i2c_intr(int irq, void *dev_id) > irqreturn_t rc = IRQ_NONE; > > spin_lock_irqsave(_data->lock, flags); > + > + if (drv_data->bridge_enabled) { > + if (readl(drv_data->reg_base + > + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE)) { > + writel(0, drv_data->reg_base + > + MV64XXX_I2C_REG_BRIDGE_CONTROL); > + writel(0, drv_data->reg_base + > + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); > + drv_data->block = 0; > + wake_up(_data->waitq); > + rc = IRQ_HANDLED; > + } > + } > while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & > MV64XXX_I2C_REG_CONTROL_IFLG) { > status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS); > @@ -446,6 +493,81 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data > *drv_data, struct i2c_msg *msg, > return drv_data->rc; > } > >
Re: [PATCH 1/2] i2c-mv64xxx: Add I2C Transaction Generator support
Dear Gregory CLEMENT, On Fri, 7 Jun 2013 17:42:22 +0200, Gregory CLEMENT wrote: > /* Driver states */ > enum { > MV64XXX_I2C_STATE_INVALID, > @@ -110,6 +133,7 @@ struct mv64xxx_i2c_data { > spinlock_t lock; > struct i2c_msg *msg; > struct i2c_adapter adapter; > + int bridge_enabled; bool ? > @@ -528,6 +652,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, > { > u32 bus_freq, tclk; > int rc = 0; > + const char *bridge_status; > > /* CLK is mandatory when using DT to describe the i2c bus. We >* need to know tclk in order to calculate bus clock > @@ -554,6 +679,15 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, >* So hard code the value to 1 second. >*/ > drv_data->adapter.timeout = HZ; > + > + /* > + * Acquire information on Transaction Generator support. > + */ > + bridge_status = of_get_property(np, "", NULL); It is not clear to me what this new bridge_status local variable is doing. > + if (of_property_read_bool(np, "i2c,i2c-bridge")) > + drv_data->bridge_enabled = 1; > + else > + drv_data->bridge_enabled = 0; This could be written directly as: drv_data->bridge_enabled = of_property_read_bool(np, "i2c,i2c-bridge"); Thanks, Thomas -- Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[PATCH 1/2] i2c-mv64xxx: Add I2C Transaction Generator support
From: Zbigniew Bodek The I2C Transaction Generator offloads CPU from managing I2C transfer step by step. This feature is currently only available on Armada XP, so usage of this mechanism is activated through device tree. [gregory.clem...@free-electrons.com: Rewrite some part to be applied on the the code modified by Russell King's fixes] [gregory.clem...@free-electrons.com: Merge and split the commits to push them to the accurate maintainer i2c and of]] [gregory.clem...@free-electrons.com: Reword the commit log] Signed-off-by: Piotr Ziecik Signed-off-by: Gregory CLEMENT --- drivers/i2c/busses/i2c-mv64xxx.c | 143 +-- 1 file changed, 139 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 6356439..5376dc3 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -24,7 +24,7 @@ #include #include -/* Register defines */ +/* Register defines (I2C port) */ #defineMV64XXX_I2C_REG_SLAVE_ADDR 0x00 #defineMV64XXX_I2C_REG_DATA0x04 #defineMV64XXX_I2C_REG_CONTROL 0x08 @@ -59,6 +59,29 @@ #defineMV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK0xe8 #defineMV64XXX_I2C_STATUS_NO_STATUS0xf8 +/* Register defines (I2C bridge) */ +#defineMV64XXX_I2C_REG_TX_DATA_LO 0xC0 +#defineMV64XXX_I2C_REG_TX_DATA_HI 0xC4 +#defineMV64XXX_I2C_REG_RX_DATA_LO 0xC8 +#defineMV64XXX_I2C_REG_RX_DATA_HI 0xCC +#defineMV64XXX_I2C_REG_BRIDGE_CONTROL 0xD0 +#defineMV64XXX_I2C_REG_BRIDGE_STATUS 0xD4 +#defineMV64XXX_I2C_REG_BRIDGE_INTR_CAUSE 0xD8 +#defineMV64XXX_I2C_REG_BRIDGE_INTR_MASK0xDC +#defineMV64XXX_I2C_REG_BRIDGE_TIMING 0xE0 + +/* Bridge Control values */ +#defineMV64XXX_I2C_BRIDGE_CONTROL_WR 0x0001 +#defineMV64XXX_I2C_BRIDGE_CONTROL_RD 0x0002 +#defineMV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2 +#defineMV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT 0x1000 +#defineMV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT13 +#defineMV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT16 +#defineMV64XXX_I2C_BRIDGE_CONTROL_ENABLE 0x0008 + +/* Bridge Status values */ +#defineMV64XXX_I2C_BRIDGE_STATUS_ERROR 0x0001 + /* Driver states */ enum { MV64XXX_I2C_STATE_INVALID, @@ -110,6 +133,7 @@ struct mv64xxx_i2c_data { spinlock_t lock; struct i2c_msg *msg; struct i2c_adapter adapter; + int bridge_enabled; }; static void @@ -157,6 +181,16 @@ mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); + + if (drv_data->bridge_enabled) { + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data->reg_base + MV64XXX_I2C_REG_BRIDGE_TIMING); + writel(0, drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + writel(0, drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_MASK); + } + drv_data->state = MV64XXX_I2C_STATE_IDLE; } @@ -368,6 +402,19 @@ mv64xxx_i2c_intr(int irq, void *dev_id) irqreturn_t rc = IRQ_NONE; spin_lock_irqsave(_data->lock, flags); + + if (drv_data->bridge_enabled) { + if (readl(drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE)) { + writel(0, drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data->reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + drv_data->block = 0; + wake_up(_data->waitq); + rc = IRQ_HANDLED; + } + } while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & MV64XXX_I2C_REG_CONTROL_IFLG) { status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS); @@ -446,6 +493,81 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, return drv_data->rc; } +static int +mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) +{ + unsigned long data_reg_hi = 0; + unsigned long data_reg_lo = 0; +
[PATCH 1/2] i2c-mv64xxx: Add I2C Transaction Generator support
From: Zbigniew Bodek z...@semihalf.com The I2C Transaction Generator offloads CPU from managing I2C transfer step by step. This feature is currently only available on Armada XP, so usage of this mechanism is activated through device tree. [gregory.clem...@free-electrons.com: Rewrite some part to be applied on the the code modified by Russell King's fixes] [gregory.clem...@free-electrons.com: Merge and split the commits to push them to the accurate maintainer i2c and of]] [gregory.clem...@free-electrons.com: Reword the commit log] Signed-off-by: Piotr Ziecik ko...@semihalf.com Signed-off-by: Gregory CLEMENT gregory.clem...@free-electrons.com --- drivers/i2c/busses/i2c-mv64xxx.c | 143 +-- 1 file changed, 139 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 6356439..5376dc3 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -24,7 +24,7 @@ #include linux/clk.h #include linux/err.h -/* Register defines */ +/* Register defines (I2C port) */ #defineMV64XXX_I2C_REG_SLAVE_ADDR 0x00 #defineMV64XXX_I2C_REG_DATA0x04 #defineMV64XXX_I2C_REG_CONTROL 0x08 @@ -59,6 +59,29 @@ #defineMV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK0xe8 #defineMV64XXX_I2C_STATUS_NO_STATUS0xf8 +/* Register defines (I2C bridge) */ +#defineMV64XXX_I2C_REG_TX_DATA_LO 0xC0 +#defineMV64XXX_I2C_REG_TX_DATA_HI 0xC4 +#defineMV64XXX_I2C_REG_RX_DATA_LO 0xC8 +#defineMV64XXX_I2C_REG_RX_DATA_HI 0xCC +#defineMV64XXX_I2C_REG_BRIDGE_CONTROL 0xD0 +#defineMV64XXX_I2C_REG_BRIDGE_STATUS 0xD4 +#defineMV64XXX_I2C_REG_BRIDGE_INTR_CAUSE 0xD8 +#defineMV64XXX_I2C_REG_BRIDGE_INTR_MASK0xDC +#defineMV64XXX_I2C_REG_BRIDGE_TIMING 0xE0 + +/* Bridge Control values */ +#defineMV64XXX_I2C_BRIDGE_CONTROL_WR 0x0001 +#defineMV64XXX_I2C_BRIDGE_CONTROL_RD 0x0002 +#defineMV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2 +#defineMV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT 0x1000 +#defineMV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT13 +#defineMV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT16 +#defineMV64XXX_I2C_BRIDGE_CONTROL_ENABLE 0x0008 + +/* Bridge Status values */ +#defineMV64XXX_I2C_BRIDGE_STATUS_ERROR 0x0001 + /* Driver states */ enum { MV64XXX_I2C_STATE_INVALID, @@ -110,6 +133,7 @@ struct mv64xxx_i2c_data { spinlock_t lock; struct i2c_msg *msg; struct i2c_adapter adapter; + int bridge_enabled; }; static void @@ -157,6 +181,16 @@ mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) writel(0, drv_data-reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, drv_data-reg_base + MV64XXX_I2C_REG_CONTROL); + + if (drv_data-bridge_enabled) { + writel(0, drv_data-reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data-reg_base + MV64XXX_I2C_REG_BRIDGE_TIMING); + writel(0, drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + writel(0, drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_MASK); + } + drv_data-state = MV64XXX_I2C_STATE_IDLE; } @@ -368,6 +402,19 @@ mv64xxx_i2c_intr(int irq, void *dev_id) irqreturn_t rc = IRQ_NONE; spin_lock_irqsave(drv_data-lock, flags); + + if (drv_data-bridge_enabled) { + if (readl(drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE)) { + writel(0, drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + drv_data-block = 0; + wake_up(drv_data-waitq); + rc = IRQ_HANDLED; + } + } while (readl(drv_data-reg_base + MV64XXX_I2C_REG_CONTROL) MV64XXX_I2C_REG_CONTROL_IFLG) { status = readl(drv_data-reg_base + MV64XXX_I2C_REG_STATUS); @@ -446,6 +493,81 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, return drv_data-rc; } +static int +mv64xxx_i2c_offload_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg) +{ +
Re: [PATCH 1/2] i2c-mv64xxx: Add I2C Transaction Generator support
Dear Gregory CLEMENT, On Fri, 7 Jun 2013 17:42:22 +0200, Gregory CLEMENT wrote: /* Driver states */ enum { MV64XXX_I2C_STATE_INVALID, @@ -110,6 +133,7 @@ struct mv64xxx_i2c_data { spinlock_t lock; struct i2c_msg *msg; struct i2c_adapter adapter; + int bridge_enabled; bool ? @@ -528,6 +652,7 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, { u32 bus_freq, tclk; int rc = 0; + const char *bridge_status; /* CLK is mandatory when using DT to describe the i2c bus. We * need to know tclk in order to calculate bus clock @@ -554,6 +679,15 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, * So hard code the value to 1 second. */ drv_data-adapter.timeout = HZ; + + /* + * Acquire information on Transaction Generator support. + */ + bridge_status = of_get_property(np, , NULL); It is not clear to me what this new bridge_status local variable is doing. + if (of_property_read_bool(np, i2c,i2c-bridge)) + drv_data-bridge_enabled = 1; + else + drv_data-bridge_enabled = 0; This could be written directly as: drv_data-bridge_enabled = of_property_read_bool(np, i2c,i2c-bridge); Thanks, Thomas -- Thomas Petazzoni, Free Electrons Kernel, drivers, real-time and embedded Linux development, consulting, training and support. http://free-electrons.com -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: [PATCH 1/2] i2c-mv64xxx: Add I2C Transaction Generator support
On Fri, Jun 07, 2013 at 05:42:22PM +0200, Gregory CLEMENT wrote: From: Zbigniew Bodek z...@semihalf.com The I2C Transaction Generator offloads CPU from managing I2C transfer step by step. This feature is currently only available on Armada XP, so usage of this mechanism is activated through device tree. [gregory.clem...@free-electrons.com: Rewrite some part to be applied on the the code modified by Russell King's fixes] [gregory.clem...@free-electrons.com: Merge and split the commits to push them to the accurate maintainer i2c and of]] [gregory.clem...@free-electrons.com: Reword the commit log] Signed-off-by: Piotr Ziecik ko...@semihalf.com Signed-off-by: Gregory CLEMENT gregory.clem...@free-electrons.com --- drivers/i2c/busses/i2c-mv64xxx.c | 143 +-- 1 file changed, 139 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index 6356439..5376dc3 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -24,7 +24,7 @@ #include linux/clk.h #include linux/err.h -/* Register defines */ +/* Register defines (I2C port) */ #define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 #define MV64XXX_I2C_REG_DATA0x04 #define MV64XXX_I2C_REG_CONTROL 0x08 @@ -59,6 +59,29 @@ #define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK0xe8 #define MV64XXX_I2C_STATUS_NO_STATUS0xf8 +/* Register defines (I2C bridge) */ +#define MV64XXX_I2C_REG_TX_DATA_LO 0xC0 +#define MV64XXX_I2C_REG_TX_DATA_HI 0xC4 +#define MV64XXX_I2C_REG_RX_DATA_LO 0xC8 +#define MV64XXX_I2C_REG_RX_DATA_HI 0xCC +#define MV64XXX_I2C_REG_BRIDGE_CONTROL 0xD0 +#define MV64XXX_I2C_REG_BRIDGE_STATUS 0xD4 +#define MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE 0xD8 +#define MV64XXX_I2C_REG_BRIDGE_INTR_MASK0xDC +#define MV64XXX_I2C_REG_BRIDGE_TIMING 0xE0 + +/* Bridge Control values */ +#define MV64XXX_I2C_BRIDGE_CONTROL_WR 0x0001 +#define MV64XXX_I2C_BRIDGE_CONTROL_RD 0x0002 +#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_SHIFT 2 +#define MV64XXX_I2C_BRIDGE_CONTROL_ADDR_EXT 0x1000 +#define MV64XXX_I2C_BRIDGE_CONTROL_TX_SIZE_SHIFT13 +#define MV64XXX_I2C_BRIDGE_CONTROL_RX_SIZE_SHIFT16 +#define MV64XXX_I2C_BRIDGE_CONTROL_ENABLE 0x0008 + +/* Bridge Status values */ +#define MV64XXX_I2C_BRIDGE_STATUS_ERROR 0x0001 + /* Driver states */ enum { MV64XXX_I2C_STATE_INVALID, @@ -110,6 +133,7 @@ struct mv64xxx_i2c_data { spinlock_t lock; struct i2c_msg *msg; struct i2c_adapter adapter; + int bridge_enabled; }; static void @@ -157,6 +181,16 @@ mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) writel(0, drv_data-reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, drv_data-reg_base + MV64XXX_I2C_REG_CONTROL); + + if (drv_data-bridge_enabled) { + writel(0, drv_data-reg_base + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data-reg_base + MV64XXX_I2C_REG_BRIDGE_TIMING); + writel(0, drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + writel(0, drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_MASK); + } + drv_data-state = MV64XXX_I2C_STATE_IDLE; } @@ -368,6 +402,19 @@ mv64xxx_i2c_intr(int irq, void *dev_id) irqreturn_t rc = IRQ_NONE; spin_lock_irqsave(drv_data-lock, flags); + + if (drv_data-bridge_enabled) { + if (readl(drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE)) { + writel(0, drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_CONTROL); + writel(0, drv_data-reg_base + + MV64XXX_I2C_REG_BRIDGE_INTR_CAUSE); + drv_data-block = 0; + wake_up(drv_data-waitq); + rc = IRQ_HANDLED; + } + } while (readl(drv_data-reg_base + MV64XXX_I2C_REG_CONTROL) MV64XXX_I2C_REG_CONTROL_IFLG) { status = readl(drv_data-reg_base + MV64XXX_I2C_REG_STATUS); @@ -446,6 +493,81 @@ mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, return drv_data-rc; } +static int