From 9ba63c4fa10cf446eff06a3200822d22b0c31c31 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 17 Aug 2008 06:23:05 +0100 Subject: [ARM] 5201/1: PXA3xx: Add support for power i2c bus Add power I2C support for PXA3xx processors Signed-off-by: Mike Rapoport Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 44d838410f1..5d5fbc518b7 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -60,6 +60,7 @@ struct pxa_i2c { u32 icrlog[32]; void __iomem *reg_base; + unsigned int reg_shift; unsigned long iobase; unsigned long iosize; @@ -68,11 +69,11 @@ struct pxa_i2c { int use_pio; }; -#define _IBMR(i2c) ((i2c)->reg_base + 0) -#define _IDBR(i2c) ((i2c)->reg_base + 8) -#define _ICR(i2c) ((i2c)->reg_base + 0x10) -#define _ISR(i2c) ((i2c)->reg_base + 0x18) -#define _ISAR(i2c) ((i2c)->reg_base + 0x20) +#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)) /* * I2C Slave mode address @@ -993,6 +994,7 @@ static int i2c_pxa_probe(struct platform_device *dev) ret = -EIO; goto eremap; } + i2c->reg_shift = (cpu_is_pxa3xx() && (dev->id == 1)) ? 0 : 1; i2c->iobase = res->start; i2c->iosize = res_len(res); -- cgit v1.2.3 From 387fa6a5eca021ed5bef5454413b7cdfda74ba41 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Mon, 18 Aug 2008 14:38:48 +0100 Subject: [ARM] 5203/1: i2c-pxa: fix scheduling while atomic in i2c_pxa_abort() i2c_pxa_abort can be called from the atomic context. Change it to use mdelay and counted loop. Signed-off-by: Dmitry Baryshkov Acked-by: Eric Miao Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 5d5fbc518b7..57fbffd1ccc 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -189,14 +189,14 @@ static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c) static void i2c_pxa_abort(struct pxa_i2c *i2c) { - unsigned long timeout = jiffies + HZ/4; + int i = 250; if (i2c_pxa_is_slavemode(i2c)) { dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__); return; } - while (time_before(jiffies, timeout) && (readl(_IBMR(i2c)) & 0x1) == 0) { + while ((i > 0) && (readl(_IBMR(i2c)) & 0x1) == 0) { unsigned long icr = readl(_ICR(i2c)); icr &= ~ICR_START; @@ -206,7 +206,8 @@ static void i2c_pxa_abort(struct pxa_i2c *i2c) show_state(i2c); - msleep(1); + mdelay(1); + i --; } writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP), -- cgit v1.2.3 From e7d48fa2b5fbc7f74bb7ef4a8d7e080b0e831ef0 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 26 Aug 2008 10:40:50 +0100 Subject: [I2C] pxa: provide late suspend and early resume hooks Properly hook the I2C driver into the PM code; the previous fix for this (ece5f7b3c4fde70a1ae4add7372ebca5c90bc34d) worked around the platform where I2C is required to be available early during resume. It has been found to be sufficient to use the early resume hook for this function, so the original hack can die. Leave the hack in place for the PIO transfer handler though. Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 57fbffd1ccc..518b57c795c 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -909,12 +909,6 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num struct pxa_i2c *i2c = adap->algo_data; int ret, i; - /* If the I2C controller is disabled we need to reset it (probably due - to a suspend/resume destroying state). We do this here as we can then - avoid worrying about resuming the controller before its users. */ - if (!(readl(_ICR(i2c)) & ICR_IUE)) - i2c_pxa_reset(i2c); - for (i = adap->retries; i >= 0; i--) { ret = i2c_pxa_do_xfer(i2c, msgs, num); if (ret != I2C_RETRY) @@ -1085,9 +1079,33 @@ static int __exit i2c_pxa_remove(struct platform_device *dev) return 0; } +#ifdef CONFIG_PM +static int i2c_pxa_suspend_late(struct platform_device *dev, pm_message_t state) +{ + struct pxa_i2c *i2c = platform_get_drvdata(dev); + clk_disable(i2c->clk); + return 0; +} + +static int i2c_pxa_resume_early(struct platform_device *dev) +{ + struct pxa_i2c *i2c = platform_get_drvdata(dev); + + clk_enable(i2c->clk); + i2c_pxa_reset(i2c); + + return 0; +} +#else +#define i2c_pxa_suspend_late NULL +#define i2c_pxa_resume_early NULL +#endif + static struct platform_driver i2c_pxa_driver = { .probe = i2c_pxa_probe, .remove = __exit_p(i2c_pxa_remove), + .suspend_late = i2c_pxa_suspend_late, + .resume_early = i2c_pxa_resume_early, .driver = { .name = "pxa2xx-i2c", .owner = THIS_MODULE, -- cgit v1.2.3 From c46c948260f41af18b277c1eb1895d788d3605dc Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 3 Oct 2008 15:07:36 +0100 Subject: [ARM] 5278/1: i2c-pxa fast mode support Add fast_mode option to i2c_pxa_platform_data and use it to set the ICR_FM bit appropriately when i2c_pxa_reset is called. Parameter called fast_mode rather than frequency as this driver is also used for the i2c_pxa_pwr bus which has different normal and fast frequencies. Signed-off-by: Jonathan Cameron Acked-by: Eric Miao Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 518b57c795c..8b38ed0379d 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -66,7 +66,8 @@ struct pxa_i2c { unsigned long iosize; int irq; - int use_pio; + unsigned int use_pio :1; + unsigned int fast_mode :1; }; #define _IBMR(i2c) ((i2c)->reg_base + (0x0 << (i2c)->reg_shift)) @@ -366,7 +367,7 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c) writel(i2c->slave_addr, _ISAR(i2c)); /* set control register values */ - writel(I2C_ICR_INIT, _ICR(i2c)); + writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); #ifdef CONFIG_I2C_PXA_SLAVE dev_info(&i2c->adap.dev, "Enabling slave mode\n"); @@ -1010,6 +1011,7 @@ static int i2c_pxa_probe(struct platform_device *dev) if (plat) { i2c->adap.class = plat->class; i2c->use_pio = plat->use_pio; + i2c->fast_mode = plat->fast_mode; } if (i2c->use_pio) { -- cgit v1.2.3 From 283afa06619ed3e4dd7b5431f862fe23625c452f Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Mon, 8 Sep 2008 14:15:08 +0800 Subject: [ARM] pxa: move i2c register and bit definitions into i2c-pxa.c Signed-off-by: Eric Miao Signed-off-by: Russell King --- drivers/i2c/busses/i2c-pxa.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) (limited to 'drivers/i2c') diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 8b38ed0379d..906f9b9d715 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -38,7 +38,44 @@ #include #include #include -#include + +/* + * I2C registers and 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 */ +#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */ +#define ICR_TB (1 << 3) /* transfer byte bit */ +#define ICR_MA (1 << 4) /* master abort */ +#define ICR_SCLE (1 << 5) /* master clock enable */ +#define ICR_IUE (1 << 6) /* unit enable */ +#define ICR_GCD (1 << 7) /* general call disable */ +#define ICR_ITEIE (1 << 8) /* enable tx interrupts */ +#define ICR_IRFIE (1 << 9) /* enable rx interrupts */ +#define ICR_BEIE (1 << 10) /* enable bus error ints */ +#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */ +#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */ +#define ICR_SADIE (1 << 13) /* slave address detected int enable */ +#define ICR_UR (1 << 14) /* unit reset */ +#define ICR_FM (1 << 15) /* fast mode */ + +#define ISR_RWM (1 << 0) /* read/write mode */ +#define ISR_ACKNAK (1 << 1) /* ack/nak status */ +#define ISR_UB (1 << 2) /* unit busy */ +#define ISR_IBB (1 << 3) /* bus busy */ +#define ISR_SSD (1 << 4) /* slave stop detected */ +#define ISR_ALD (1 << 5) /* arbitration loss detected */ +#define ISR_ITE (1 << 6) /* tx buffer empty */ +#define ISR_IRF (1 << 7) /* rx buffer full */ +#define ISR_GCAD (1 << 8) /* general call address detected */ +#define ISR_SAD (1 << 9) /* slave address detected */ +#define ISR_BED (1 << 10) /* bus error no ACK/NAK */ struct pxa_i2c { spinlock_t lock; -- cgit v1.2.3