All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] driver updates from PM branch for upstream
@ 2009-06-25 21:34 Kevin Hilman
  2009-06-25 21:34 ` [PATCH 1/4] OMAP: McSPI: enable wake-ups and smart-idle Kevin Hilman
  0 siblings, 1 reply; 15+ messages in thread
From: Kevin Hilman @ 2009-06-25 21:34 UTC (permalink / raw)
  To: linux-omap

This is a series of driver patches (i2c, SPI) from the PM branch
that are ready to go upstream via the sybsystem lists.

Here's one more review pass before I send them to their respective lists.

Applies to current Linus' tree or 'omap-fixes' branch of linux-omap.

Kevin


Hemanth V (1):
  OMAP3 McSPI: Adds context save/restore

Jouni Hogander (2):
  OMAP: McSPI: enable wake-ups and smart-idle
  OMAP: McSPI: Convert bit shifted values into BIT format

Rajendra Nayak (1):
  I2C: OMAP3: PM: (re)init for every transfer to support off-mode

 drivers/i2c/busses/i2c-omap.c |   59 +++++++++-----
 drivers/spi/omap2_mcspi.c     |  179 +++++++++++++++++++++++++++++------------
 2 files changed, 165 insertions(+), 73 deletions(-)


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/4] OMAP: McSPI: enable wake-ups and smart-idle
  2009-06-25 21:34 [PATCH 0/4] driver updates from PM branch for upstream Kevin Hilman
@ 2009-06-25 21:34 ` Kevin Hilman
  2009-06-25 21:34   ` [PATCH 2/4] OMAP: McSPI: Convert bit shifted values into BIT format Kevin Hilman
  0 siblings, 1 reply; 15+ messages in thread
From: Kevin Hilman @ 2009-06-25 21:34 UTC (permalink / raw)
  To: linux-omap; +Cc: Jouni Hogander, Tony Lindgren

From: Jouni Hogander <jouni.hogander@nokia.com>

By default, enable module wakeups and put module in smart-idle.

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/spi/omap2_mcspi.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index eee4b6e..2b64091 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -59,6 +59,8 @@
 
 /* per-register bitmasks: */
 
+#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE	(2 << 3)
+#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP	(1 << 2)
 #define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE	(1 << 0)
 #define OMAP2_MCSPI_SYSCONFIG_SOFTRESET	(1 << 1)
 
@@ -90,6 +92,7 @@
 
 #define OMAP2_MCSPI_CHCTRL_EN		(1 << 0)
 
+#define OMAP2_MCSPI_WAKEUPENABLE_WKEN	(1 << 0)
 
 /* We have 2 DMA channels per CS, one for RX and one for TX */
 struct omap2_mcspi_dma {
@@ -873,8 +876,12 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
 	} while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
 
 	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
-			/* (3 << 8) | (2 << 3) | */
-			OMAP2_MCSPI_SYSCONFIG_AUTOIDLE);
+			OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
+			OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
+			OMAP2_MCSPI_SYSCONFIG_SMARTIDLE);
+
+	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
+			OMAP2_MCSPI_WAKEUPENABLE_WKEN);
 
 	omap2_mcspi_set_master_mode(master);
 
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/4] OMAP: McSPI: Convert bit shifted values into BIT format
  2009-06-25 21:34 ` [PATCH 1/4] OMAP: McSPI: enable wake-ups and smart-idle Kevin Hilman
@ 2009-06-25 21:34   ` Kevin Hilman
  2009-06-25 21:34     ` [PATCH 3/4] OMAP3 McSPI: Adds context save/restore Kevin Hilman
  0 siblings, 1 reply; 15+ messages in thread
From: Kevin Hilman @ 2009-06-25 21:34 UTC (permalink / raw)
  To: linux-omap; +Cc: Jouni Hogander, Tony Lindgren

From: Jouni Hogander <jouni.hogander@nokia.com>

Convert bit shifted values into BIT format

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/spi/omap2_mcspi.c |   50 ++++++++++++++++++++++----------------------
 1 files changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 2b64091..0016078 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -59,40 +59,40 @@
 
 /* per-register bitmasks: */
 
-#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE	(2 << 3)
-#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP	(1 << 2)
-#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE	(1 << 0)
-#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET	(1 << 1)
+#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE	BIT(4)
+#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP	BIT(2)
+#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE	BIT(0)
+#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET	BIT(1)
 
-#define OMAP2_MCSPI_SYSSTATUS_RESETDONE	(1 << 0)
+#define OMAP2_MCSPI_SYSSTATUS_RESETDONE	BIT(0)
 
-#define OMAP2_MCSPI_MODULCTRL_SINGLE	(1 << 0)
-#define OMAP2_MCSPI_MODULCTRL_MS	(1 << 2)
-#define OMAP2_MCSPI_MODULCTRL_STEST	(1 << 3)
+#define OMAP2_MCSPI_MODULCTRL_SINGLE	BIT(0)
+#define OMAP2_MCSPI_MODULCTRL_MS	BIT(2)
+#define OMAP2_MCSPI_MODULCTRL_STEST	BIT(3)
 
-#define OMAP2_MCSPI_CHCONF_PHA		(1 << 0)
-#define OMAP2_MCSPI_CHCONF_POL		(1 << 1)
+#define OMAP2_MCSPI_CHCONF_PHA		BIT(0)
+#define OMAP2_MCSPI_CHCONF_POL		BIT(1)
 #define OMAP2_MCSPI_CHCONF_CLKD_MASK	(0x0f << 2)
-#define OMAP2_MCSPI_CHCONF_EPOL		(1 << 6)
+#define OMAP2_MCSPI_CHCONF_EPOL		BIT(6)
 #define OMAP2_MCSPI_CHCONF_WL_MASK	(0x1f << 7)
-#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY	(0x01 << 12)
-#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY	(0x02 << 12)
+#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY	BIT(12)
+#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY	BIT(13)
 #define OMAP2_MCSPI_CHCONF_TRM_MASK	(0x03 << 12)
-#define OMAP2_MCSPI_CHCONF_DMAW		(1 << 14)
-#define OMAP2_MCSPI_CHCONF_DMAR		(1 << 15)
-#define OMAP2_MCSPI_CHCONF_DPE0		(1 << 16)
-#define OMAP2_MCSPI_CHCONF_DPE1		(1 << 17)
-#define OMAP2_MCSPI_CHCONF_IS		(1 << 18)
-#define OMAP2_MCSPI_CHCONF_TURBO	(1 << 19)
-#define OMAP2_MCSPI_CHCONF_FORCE	(1 << 20)
+#define OMAP2_MCSPI_CHCONF_DMAW		BIT(14)
+#define OMAP2_MCSPI_CHCONF_DMAR		BIT(15)
+#define OMAP2_MCSPI_CHCONF_DPE0		BIT(16)
+#define OMAP2_MCSPI_CHCONF_DPE1		BIT(17)
+#define OMAP2_MCSPI_CHCONF_IS		BIT(18)
+#define OMAP2_MCSPI_CHCONF_TURBO	BIT(19)
+#define OMAP2_MCSPI_CHCONF_FORCE	BIT(20)
 
-#define OMAP2_MCSPI_CHSTAT_RXS		(1 << 0)
-#define OMAP2_MCSPI_CHSTAT_TXS		(1 << 1)
-#define OMAP2_MCSPI_CHSTAT_EOT		(1 << 2)
+#define OMAP2_MCSPI_CHSTAT_RXS		BIT(0)
+#define OMAP2_MCSPI_CHSTAT_TXS		BIT(1)
+#define OMAP2_MCSPI_CHSTAT_EOT		BIT(2)
 
-#define OMAP2_MCSPI_CHCTRL_EN		(1 << 0)
+#define OMAP2_MCSPI_CHCTRL_EN		BIT(0)
 
-#define OMAP2_MCSPI_WAKEUPENABLE_WKEN	(1 << 0)
+#define OMAP2_MCSPI_WAKEUPENABLE_WKEN	BIT(0)
 
 /* We have 2 DMA channels per CS, one for RX and one for TX */
 struct omap2_mcspi_dma {
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/4] OMAP3 McSPI: Adds context save/restore
  2009-06-25 21:34   ` [PATCH 2/4] OMAP: McSPI: Convert bit shifted values into BIT format Kevin Hilman
@ 2009-06-25 21:34     ` Kevin Hilman
  2009-06-25 21:34       ` [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode Kevin Hilman
  2009-06-26 12:02       ` [PATCH 3/4] OMAP3 McSPI: Adds context save/restore Aaro Koskinen
  0 siblings, 2 replies; 15+ messages in thread
From: Kevin Hilman @ 2009-06-25 21:34 UTC (permalink / raw)
  To: linux-omap; +Cc: Hemanth V

From: Hemanth V <hemanthv@ti.com>

This patch adds context save/restore feature to McSPI driver.
This includes fixes by Aaro Koskinen

Signed-off-by: Hemanth V <hemanthv@ti.com>
Reviewed-by: Aaro Koskinen <Aaro.Koskinen@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/spi/omap2_mcspi.c |  134 +++++++++++++++++++++++++++++++++-----------
 1 files changed, 100 insertions(+), 34 deletions(-)

diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index 0016078..5240c01 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -41,6 +41,9 @@
 
 #define OMAP2_MCSPI_MAX_FREQ		48000000
 
+/* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */
+#define OMAP2_MCSPI_MAX_CTRL 		4
+
 #define OMAP2_MCSPI_REVISION		0x00
 #define OMAP2_MCSPI_SYSCONFIG		0x10
 #define OMAP2_MCSPI_SYSSTATUS		0x14
@@ -131,8 +134,21 @@ struct omap2_mcspi_cs {
 	void __iomem		*base;
 	unsigned long		phys;
 	int			word_len;
+	/* Context save and restore shadow register */
+	u32			chconf0;
+};
+
+/* used for context save and restore, structure members to be updated whenever
+ * corresponding registers are modified.
+ */
+struct omap2_mcspi_regs {
+	u32 sysconfig;
+	u32 modulctrl;
+	u32 wakeupenable;
 };
 
+static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL];
+
 static struct workqueue_struct *omap2_mcspi_wq;
 
 #define MOD_REG_BIT(val, mask, set) do { \
@@ -172,12 +188,27 @@ static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
 	return __raw_readl(cs->base + idx);
 }
 
+static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
+{
+	struct omap2_mcspi_cs *cs = spi->controller_state;
+
+	return cs->chconf0;
+}
+
+static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
+{
+	struct omap2_mcspi_cs *cs = spi->controller_state;
+
+	cs->chconf0 = val;
+	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val);
+}
+
 static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
 		int is_read, int enable)
 {
 	u32 l, rw;
 
-	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+	l = mcspi_cached_chconf0(spi);
 
 	if (is_read) /* 1 is read, 0 write */
 		rw = OMAP2_MCSPI_CHCONF_DMAR;
@@ -185,7 +216,7 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
 		rw = OMAP2_MCSPI_CHCONF_DMAW;
 
 	MOD_REG_BIT(l, rw, enable);
-	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+	mcspi_write_chconf0(spi, l);
 }
 
 static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
@@ -200,9 +231,9 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
 {
 	u32 l;
 
-	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+	l = mcspi_cached_chconf0(spi);
 	MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
-	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+	mcspi_write_chconf0(spi, l);
 }
 
 static void omap2_mcspi_set_master_mode(struct spi_master *master)
@@ -217,6 +248,41 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master)
 	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
 	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
 	mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
+
+	omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l;
+}
+
+static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
+{
+	struct spi_master *spi_cntrl;
+	spi_cntrl = mcspi->master;
+
+	/* McSPI: context restore */
+	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL,
+			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl);
+
+	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_SYSCONFIG,
+			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].sysconfig);
+
+	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
+			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
+}
+static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
+{
+	clk_disable(mcspi->ick);
+	clk_disable(mcspi->fck);
+}
+
+static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
+{
+	if (clk_enable(mcspi->ick))
+		return -ENODEV;
+	if (clk_enable(mcspi->fck))
+		return -ENODEV;
+
+	omap2_mcspi_restore_ctx(mcspi);
+
+	return 0;
 }
 
 static unsigned
@@ -338,7 +404,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 	c = count;
 	word_len = cs->word_len;
 
-	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+	l = mcspi_cached_chconf0(spi);
 	l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
 
 	/* We store the pre-calculated register addresses on stack to speed
@@ -378,8 +444,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 				 * more word i/o: switch to rx+tx
 				 */
 				if (c == 0 && tx == NULL)
-					mcspi_write_cs_reg(spi,
-							OMAP2_MCSPI_CHCONF0, l);
+					mcspi_write_chconf0(spi, l);
 				*rx++ = __raw_readl(rx_reg);
 #ifdef VERBOSE
 				dev_dbg(&spi->dev, "read-%d %02x\n",
@@ -417,8 +482,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 				 * more word i/o: switch to rx+tx
 				 */
 				if (c == 0 && tx == NULL)
-					mcspi_write_cs_reg(spi,
-							OMAP2_MCSPI_CHCONF0, l);
+					mcspi_write_chconf0(spi, l);
 				*rx++ = __raw_readl(rx_reg);
 #ifdef VERBOSE
 				dev_dbg(&spi->dev, "read-%d %04x\n",
@@ -456,8 +520,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
 				 * more word i/o: switch to rx+tx
 				 */
 				if (c == 0 && tx == NULL)
-					mcspi_write_cs_reg(spi,
-							OMAP2_MCSPI_CHCONF0, l);
+					mcspi_write_chconf0(spi, l);
 				*rx++ = __raw_readl(rx_reg);
 #ifdef VERBOSE
 				dev_dbg(&spi->dev, "read-%d %04x\n",
@@ -486,10 +549,12 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 {
 	struct omap2_mcspi_cs *cs = spi->controller_state;
 	struct omap2_mcspi *mcspi;
+	struct spi_master *spi_cntrl;
 	u32 l = 0, div = 0;
 	u8 word_len = spi->bits_per_word;
 
 	mcspi = spi_master_get_devdata(spi->master);
+	spi_cntrl = mcspi->master;
 
 	if (t != NULL && t->bits_per_word)
 		word_len = t->bits_per_word;
@@ -503,7 +568,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 	} else
 		div = 15;
 
-	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+	l = mcspi_cached_chconf0(spi);
 
 	/* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
 	 * REVISIT: this controller could support SPI_3WIRE mode.
@@ -535,7 +600,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 	else
 		l &= ~OMAP2_MCSPI_CHCONF_PHA;
 
-	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
+	mcspi_write_chconf0(spi, l);
 
 	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
 			OMAP2_MCSPI_MAX_FREQ / (1 << div),
@@ -628,6 +693,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
 			return -ENOMEM;
 		cs->base = mcspi->base + spi->chip_select * 0x14;
 		cs->phys = mcspi->phys + spi->chip_select * 0x14;
+		cs->chconf0 = 0;
 		spi->controller_state = cs;
 	}
 
@@ -638,11 +704,11 @@ static int omap2_mcspi_setup(struct spi_device *spi)
 			return ret;
 	}
 
-	clk_enable(mcspi->ick);
-	clk_enable(mcspi->fck);
+	if (omap2_mcspi_enable_clocks(mcspi))
+		return -ENODEV;
+
 	ret = omap2_mcspi_setup_transfer(spi, NULL);
-	clk_disable(mcspi->fck);
-	clk_disable(mcspi->ick);
+	omap2_mcspi_disable_clocks(mcspi);
 
 	return ret;
 }
@@ -674,8 +740,8 @@ static void omap2_mcspi_work(struct work_struct *work)
 	mcspi = container_of(work, struct omap2_mcspi, work);
 	spin_lock_irq(&mcspi->lock);
 
-	clk_enable(mcspi->ick);
-	clk_enable(mcspi->fck);
+	if (omap2_mcspi_enable_clocks(mcspi))
+		goto out;
 
 	/* We only enable one channel at a time -- the one whose message is
 	 * at the head of the queue -- although this controller would gladly
@@ -722,13 +788,13 @@ static void omap2_mcspi_work(struct work_struct *work)
 				cs_active = 1;
 			}
 
-			chconf = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
+			chconf = mcspi_cached_chconf0(spi);
 			chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
 			if (t->tx_buf == NULL)
 				chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
 			else if (t->rx_buf == NULL)
 				chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
-			mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, chconf);
+			mcspi_write_chconf0(spi, chconf);
 
 			if (t->len) {
 				unsigned	count;
@@ -777,9 +843,9 @@ static void omap2_mcspi_work(struct work_struct *work)
 		spin_lock_irq(&mcspi->lock);
 	}
 
-	clk_disable(mcspi->fck);
-	clk_disable(mcspi->ick);
+	omap2_mcspi_disable_clocks(mcspi);
 
+out:
 	spin_unlock_irq(&mcspi->lock);
 }
 
@@ -866,8 +932,8 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
 	struct spi_master	*master = mcspi->master;
 	u32			tmp;
 
-	clk_enable(mcspi->ick);
-	clk_enable(mcspi->fck);
+	if (omap2_mcspi_enable_clocks(mcspi))
+		return -1;
 
 	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
 			OMAP2_MCSPI_SYSCONFIG_SOFTRESET);
@@ -875,18 +941,18 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
 		tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS);
 	} while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
 
-	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
-			OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
-			OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
-			OMAP2_MCSPI_SYSCONFIG_SMARTIDLE);
+	tmp = OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
+		OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
+		OMAP2_MCSPI_SYSCONFIG_SMARTIDLE;
+	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, tmp);
+	omap2_mcspi_ctx[master->bus_num - 1].sysconfig = tmp;
 
-	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
-			OMAP2_MCSPI_WAKEUPENABLE_WKEN);
+	tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
+	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp);
+	omap2_mcspi_ctx[master->bus_num - 1].wakeupenable = tmp;
 
 	omap2_mcspi_set_master_mode(master);
-
-	clk_disable(mcspi->fck);
-	clk_disable(mcspi->ick);
+	omap2_mcspi_disable_clocks(mcspi);
 	return 0;
 }
 
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-25 21:34     ` [PATCH 3/4] OMAP3 McSPI: Adds context save/restore Kevin Hilman
@ 2009-06-25 21:34       ` Kevin Hilman
  2009-06-26 11:13         ` Aaro Koskinen
  2009-06-26 12:02       ` [PATCH 3/4] OMAP3 McSPI: Adds context save/restore Aaro Koskinen
  1 sibling, 1 reply; 15+ messages in thread
From: Kevin Hilman @ 2009-06-25 21:34 UTC (permalink / raw)
  To: linux-omap
  Cc: Rajendra Nayak, Jouni Hogander, Jagadeesh Bhaskar Pakaravoor,
	Aaro Koskinen

From: Rajendra Nayak <rnayak@ti.com>

Because of OMAP off-mode, powerdomain can go off when I2C is idle.
Save enough state, and do a re-init for each transfer.

Additional save/restore state added by Jagadeesh Bhaskar Pakaravoor
(SYSC_REG) and Aaro Koskinen (wakeup sources.)

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
Cc: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/i2c/busses/i2c-omap.c |   59 +++++++++++++++++++++++++++--------------
 1 files changed, 39 insertions(+), 20 deletions(-)

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ad8d201..0a5d871 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -178,6 +178,12 @@ struct omap_i2c_dev {
 	unsigned		b_hw:1;		/* bad h/w fixes */
 	unsigned		idle:1;
 	u16			iestate;	/* Saved interrupt register */
+	u16			pscstate;
+	u16			scllstate;
+	u16			sclhstate;
+	u16			bufstate;
+	u16			syscstate;
+	u16			westate;
 };
 
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
@@ -230,9 +236,16 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 
 	clk_enable(dev->iclk);
 	clk_enable(dev->fclk);
+	if (cpu_is_omap34xx()) {
+		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->bufstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->syscstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+	}
 	dev->idle = 0;
-	if (dev->iestate)
-		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
 }
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev)
@@ -258,7 +271,7 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
 
 static int omap_i2c_init(struct omap_i2c_dev *dev)
 {
-	u16 psc = 0, scll = 0, sclh = 0;
+	u16 psc = 0, scll = 0, sclh = 0, buf = 0;
 	u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
 	unsigned long fclk_rate = 12000000;
 	unsigned long timeout;
@@ -289,21 +302,22 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 		} else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
 			u32 v;
 
-			v = SYSC_AUTOIDLE_MASK;
-			v |= SYSC_ENAWAKEUP_MASK;
-			v |= (SYSC_IDLEMODE_SMART <<
+			dev->syscstate = SYSC_AUTOIDLE_MASK;
+			dev->syscstate |= SYSC_ENAWAKEUP_MASK;
+			dev->syscstate |= (SYSC_IDLEMODE_SMART <<
 			      __ffs(SYSC_SIDLEMODE_MASK));
-			v |= (SYSC_CLOCKACTIVITY_FCLK <<
+			dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK <<
 			      __ffs(SYSC_CLOCKACTIVITY_MASK));
 
-			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
+							dev->syscstate);
 			/*
 			 * Enabling all wakup sources to stop I2C freezing on
 			 * WFI instruction.
 			 * REVISIT: Some wkup sources might not be needed.
 			 */
-			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
-							OMAP_I2C_WE_ALL);
+			dev->westate = OMAP_I2C_WE_ALL;
+			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
 
 		}
 	}
@@ -394,23 +408,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
 	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
 
-	if (dev->fifo_size)
-		/* Note: setup required fifo size - 1 */
-		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
-					(dev->fifo_size - 1) << 8 | /* RTRSH */
-					OMAP_I2C_BUF_RXFIF_CLR |
-					(dev->fifo_size - 1) | /* XTRSH */
-					OMAP_I2C_BUF_TXFIF_CLR);
+	if (dev->fifo_size) {
+		/* Note: setup required fifo size - 1. RTRSH and XTRSH */
+		buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR |
+			(dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR;
+		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
+	}
 
 	/* Take the I2C module out of reset: */
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 
 	/* Enable interrupts */
-	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
-			(OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+	dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
 			OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
 			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
-				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
+				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
+	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+	if (cpu_is_omap34xx()) {
+		dev->pscstate = psc;
+		dev->scllstate = scll;
+		dev->sclhstate = sclh;
+		dev->bufstate = buf;
+	}
 	return 0;
 }
 
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-25 21:34       ` [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode Kevin Hilman
@ 2009-06-26 11:13         ` Aaro Koskinen
  2009-06-26 14:19           ` Kevin Hilman
  0 siblings, 1 reply; 15+ messages in thread
From: Aaro Koskinen @ 2009-06-26 11:13 UTC (permalink / raw)
  To: ext Kevin Hilman
  Cc: linux-omap, Rajendra Nayak, Hogander Jouni (Nokia-D/Tampere),
	Jagadeesh Bhaskar Pakaravoor

Hello,

Kevin Hilman wrote:
 > From: Rajendra Nayak <rnayak@ti.com>
 >
 > Because of OMAP off-mode, powerdomain can go off when I2C is idle.
 > Save enough state, and do a re-init for each transfer.
 >
 > Additional save/restore state added by Jagadeesh Bhaskar Pakaravoor
 > (SYSC_REG) and Aaro Koskinen (wakeup sources.)
 >
 > Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
 > Signed-off-by: Rajendra Nayak <rnayak@ti.com>
 > Cc: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
 > Cc: Aaro Koskinen <aaro.koskinen@nokia.com>
 > Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>

This patch introduces a compiler warning:

   CC      drivers/i2c/busses/i2c-omap.o
drivers/i2c/busses/i2c-omap.c: In function 'omap_i2c_init':
drivers/i2c/busses/i2c-omap.c:303: warning: unused variable 'v'

So the declaration of "v" should be also removed here:

 > @@ -289,21 +302,22 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 >  		} else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
 >  			u32 v;
 >
 > -			v = SYSC_AUTOIDLE_MASK;
 > -			v |= SYSC_ENAWAKEUP_MASK;
 > -			v |= (SYSC_IDLEMODE_SMART <<
 > +			dev->syscstate = SYSC_AUTOIDLE_MASK;
 > +			dev->syscstate |= SYSC_ENAWAKEUP_MASK;
 > +			dev->syscstate |= (SYSC_IDLEMODE_SMART <<

A.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/4] OMAP3 McSPI: Adds context save/restore
  2009-06-25 21:34     ` [PATCH 3/4] OMAP3 McSPI: Adds context save/restore Kevin Hilman
  2009-06-25 21:34       ` [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode Kevin Hilman
@ 2009-06-26 12:02       ` Aaro Koskinen
  2009-06-29 14:25         ` Aaro Koskinen
  1 sibling, 1 reply; 15+ messages in thread
From: Aaro Koskinen @ 2009-06-26 12:02 UTC (permalink / raw)
  To: ext Kevin Hilman; +Cc: linux-omap, Hemanth V

Hello,

I'm afraid this patch needs more work. The optimized restoration of 
chconf can cause occasionally errors with off mode if multiple chip 
selects are in use. In practice it is needed to restore all CHxCONF 
registers, not just the one by a specific chip select.

ext Kevin Hilman wrote:
> From: Hemanth V <hemanthv@ti.com>
> 
> This patch adds context save/restore feature to McSPI driver.
> This includes fixes by Aaro Koskinen
> 
> Signed-off-by: Hemanth V <hemanthv@ti.com>
> Reviewed-by: Aaro Koskinen <Aaro.Koskinen@nokia.com>
> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
> ---
>  drivers/spi/omap2_mcspi.c |  134 +++++++++++++++++++++++++++++++++-----------
>  1 files changed, 100 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
> index 0016078..5240c01 100644
> --- a/drivers/spi/omap2_mcspi.c
> +++ b/drivers/spi/omap2_mcspi.c
> @@ -41,6 +41,9 @@
>  
>  #define OMAP2_MCSPI_MAX_FREQ		48000000
>  
> +/* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */
> +#define OMAP2_MCSPI_MAX_CTRL 		4
> +
>  #define OMAP2_MCSPI_REVISION		0x00
>  #define OMAP2_MCSPI_SYSCONFIG		0x10
>  #define OMAP2_MCSPI_SYSSTATUS		0x14
> @@ -131,8 +134,21 @@ struct omap2_mcspi_cs {
>  	void __iomem		*base;
>  	unsigned long		phys;
>  	int			word_len;
> +	/* Context save and restore shadow register */
> +	u32			chconf0;
> +};
> +
> +/* used for context save and restore, structure members to be updated whenever
> + * corresponding registers are modified.
> + */
> +struct omap2_mcspi_regs {
> +	u32 sysconfig;
> +	u32 modulctrl;
> +	u32 wakeupenable;
>  };
>  
> +static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL];
> +
>  static struct workqueue_struct *omap2_mcspi_wq;
>  
>  #define MOD_REG_BIT(val, mask, set) do { \
> @@ -172,12 +188,27 @@ static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
>  	return __raw_readl(cs->base + idx);
>  }
>  
> +static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
> +{
> +	struct omap2_mcspi_cs *cs = spi->controller_state;
> +
> +	return cs->chconf0;
> +}
> +
> +static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
> +{
> +	struct omap2_mcspi_cs *cs = spi->controller_state;
> +
> +	cs->chconf0 = val;
> +	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val);
> +}
> +
>  static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
>  		int is_read, int enable)
>  {
>  	u32 l, rw;
>  
> -	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
> +	l = mcspi_cached_chconf0(spi);
>  
>  	if (is_read) /* 1 is read, 0 write */
>  		rw = OMAP2_MCSPI_CHCONF_DMAR;
> @@ -185,7 +216,7 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
>  		rw = OMAP2_MCSPI_CHCONF_DMAW;
>  
>  	MOD_REG_BIT(l, rw, enable);
> -	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
> +	mcspi_write_chconf0(spi, l);
>  }
>  
>  static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable)
> @@ -200,9 +231,9 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active)
>  {
>  	u32 l;
>  
> -	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
> +	l = mcspi_cached_chconf0(spi);
>  	MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active);
> -	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
> +	mcspi_write_chconf0(spi, l);
>  }
>  
>  static void omap2_mcspi_set_master_mode(struct spi_master *master)
> @@ -217,6 +248,41 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master)
>  	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0);
>  	MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1);
>  	mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l);
> +
> +	omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l;
> +}
> +
> +static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
> +{
> +	struct spi_master *spi_cntrl;
> +	spi_cntrl = mcspi->master;
> +
> +	/* McSPI: context restore */
> +	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL,
> +			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl);
> +
> +	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_SYSCONFIG,
> +			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].sysconfig);
> +
> +	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
> +			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
> +}
> +static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
> +{
> +	clk_disable(mcspi->ick);
> +	clk_disable(mcspi->fck);
> +}
> +
> +static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
> +{
> +	if (clk_enable(mcspi->ick))
> +		return -ENODEV;
> +	if (clk_enable(mcspi->fck))
> +		return -ENODEV;
> +
> +	omap2_mcspi_restore_ctx(mcspi);
> +
> +	return 0;
>  }
>  
>  static unsigned
> @@ -338,7 +404,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
>  	c = count;
>  	word_len = cs->word_len;
>  
> -	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
> +	l = mcspi_cached_chconf0(spi);
>  	l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
>  
>  	/* We store the pre-calculated register addresses on stack to speed
> @@ -378,8 +444,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
>  				 * more word i/o: switch to rx+tx
>  				 */
>  				if (c == 0 && tx == NULL)
> -					mcspi_write_cs_reg(spi,
> -							OMAP2_MCSPI_CHCONF0, l);
> +					mcspi_write_chconf0(spi, l);
>  				*rx++ = __raw_readl(rx_reg);
>  #ifdef VERBOSE
>  				dev_dbg(&spi->dev, "read-%d %02x\n",
> @@ -417,8 +482,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
>  				 * more word i/o: switch to rx+tx
>  				 */
>  				if (c == 0 && tx == NULL)
> -					mcspi_write_cs_reg(spi,
> -							OMAP2_MCSPI_CHCONF0, l);
> +					mcspi_write_chconf0(spi, l);
>  				*rx++ = __raw_readl(rx_reg);
>  #ifdef VERBOSE
>  				dev_dbg(&spi->dev, "read-%d %04x\n",
> @@ -456,8 +520,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
>  				 * more word i/o: switch to rx+tx
>  				 */
>  				if (c == 0 && tx == NULL)
> -					mcspi_write_cs_reg(spi,
> -							OMAP2_MCSPI_CHCONF0, l);
> +					mcspi_write_chconf0(spi, l);
>  				*rx++ = __raw_readl(rx_reg);
>  #ifdef VERBOSE
>  				dev_dbg(&spi->dev, "read-%d %04x\n",
> @@ -486,10 +549,12 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
>  {
>  	struct omap2_mcspi_cs *cs = spi->controller_state;
>  	struct omap2_mcspi *mcspi;
> +	struct spi_master *spi_cntrl;
>  	u32 l = 0, div = 0;
>  	u8 word_len = spi->bits_per_word;
>  
>  	mcspi = spi_master_get_devdata(spi->master);
> +	spi_cntrl = mcspi->master;
>  
>  	if (t != NULL && t->bits_per_word)
>  		word_len = t->bits_per_word;
> @@ -503,7 +568,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
>  	} else
>  		div = 15;
>  
> -	l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
> +	l = mcspi_cached_chconf0(spi);
>  
>  	/* standard 4-wire master mode:  SCK, MOSI/out, MISO/in, nCS
>  	 * REVISIT: this controller could support SPI_3WIRE mode.
> @@ -535,7 +600,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
>  	else
>  		l &= ~OMAP2_MCSPI_CHCONF_PHA;
>  
> -	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l);
> +	mcspi_write_chconf0(spi, l);
>  
>  	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
>  			OMAP2_MCSPI_MAX_FREQ / (1 << div),
> @@ -628,6 +693,7 @@ static int omap2_mcspi_setup(struct spi_device *spi)
>  			return -ENOMEM;
>  		cs->base = mcspi->base + spi->chip_select * 0x14;
>  		cs->phys = mcspi->phys + spi->chip_select * 0x14;
> +		cs->chconf0 = 0;
>  		spi->controller_state = cs;
>  	}
>  
> @@ -638,11 +704,11 @@ static int omap2_mcspi_setup(struct spi_device *spi)
>  			return ret;
>  	}
>  
> -	clk_enable(mcspi->ick);
> -	clk_enable(mcspi->fck);
> +	if (omap2_mcspi_enable_clocks(mcspi))
> +		return -ENODEV;
> +
>  	ret = omap2_mcspi_setup_transfer(spi, NULL);
> -	clk_disable(mcspi->fck);
> -	clk_disable(mcspi->ick);
> +	omap2_mcspi_disable_clocks(mcspi);
>  
>  	return ret;
>  }
> @@ -674,8 +740,8 @@ static void omap2_mcspi_work(struct work_struct *work)
>  	mcspi = container_of(work, struct omap2_mcspi, work);
>  	spin_lock_irq(&mcspi->lock);
>  
> -	clk_enable(mcspi->ick);
> -	clk_enable(mcspi->fck);
> +	if (omap2_mcspi_enable_clocks(mcspi))
> +		goto out;
>  
>  	/* We only enable one channel at a time -- the one whose message is
>  	 * at the head of the queue -- although this controller would gladly
> @@ -722,13 +788,13 @@ static void omap2_mcspi_work(struct work_struct *work)
>  				cs_active = 1;
>  			}
>  
> -			chconf = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
> +			chconf = mcspi_cached_chconf0(spi);
>  			chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK;
>  			if (t->tx_buf == NULL)
>  				chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY;
>  			else if (t->rx_buf == NULL)
>  				chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY;
> -			mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, chconf);
> +			mcspi_write_chconf0(spi, chconf);
>  
>  			if (t->len) {
>  				unsigned	count;
> @@ -777,9 +843,9 @@ static void omap2_mcspi_work(struct work_struct *work)
>  		spin_lock_irq(&mcspi->lock);
>  	}
>  
> -	clk_disable(mcspi->fck);
> -	clk_disable(mcspi->ick);
> +	omap2_mcspi_disable_clocks(mcspi);
>  
> +out:
>  	spin_unlock_irq(&mcspi->lock);
>  }
>  
> @@ -866,8 +932,8 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
>  	struct spi_master	*master = mcspi->master;
>  	u32			tmp;
>  
> -	clk_enable(mcspi->ick);
> -	clk_enable(mcspi->fck);
> +	if (omap2_mcspi_enable_clocks(mcspi))
> +		return -1;
>  
>  	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
>  			OMAP2_MCSPI_SYSCONFIG_SOFTRESET);
> @@ -875,18 +941,18 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
>  		tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS);
>  	} while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
>  
> -	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
> -			OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
> -			OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
> -			OMAP2_MCSPI_SYSCONFIG_SMARTIDLE);
> +	tmp = OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
> +		OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
> +		OMAP2_MCSPI_SYSCONFIG_SMARTIDLE;
> +	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, tmp);
> +	omap2_mcspi_ctx[master->bus_num - 1].sysconfig = tmp;
>  
> -	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE,
> -			OMAP2_MCSPI_WAKEUPENABLE_WKEN);
> +	tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
> +	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp);
> +	omap2_mcspi_ctx[master->bus_num - 1].wakeupenable = tmp;
>  
>  	omap2_mcspi_set_master_mode(master);
> -
> -	clk_disable(mcspi->fck);
> -	clk_disable(mcspi->ick);
> +	omap2_mcspi_disable_clocks(mcspi);
>  	return 0;
>  }
>  


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-26 11:13         ` Aaro Koskinen
@ 2009-06-26 14:19           ` Kevin Hilman
  2009-06-29  8:51             ` HU TAO-TGHK48
  0 siblings, 1 reply; 15+ messages in thread
From: Kevin Hilman @ 2009-06-26 14:19 UTC (permalink / raw)
  To: Aaro Koskinen
  Cc: linux-omap, Rajendra Nayak, Hogander Jouni (Nokia-D/Tampere),
	Jagadeesh Bhaskar Pakaravoor

Aaro Koskinen <aaro.koskinen@nokia.com> writes:

> Kevin Hilman wrote:
>> From: Rajendra Nayak <rnayak@ti.com>
>>
>> Because of OMAP off-mode, powerdomain can go off when I2C is idle.
>> Save enough state, and do a re-init for each transfer.
>>
>> Additional save/restore state added by Jagadeesh Bhaskar Pakaravoor
>> (SYSC_REG) and Aaro Koskinen (wakeup sources.)
>>
>> Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
>> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
>> Cc: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
>> Cc: Aaro Koskinen <aaro.koskinen@nokia.com>
>> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>
> This patch introduces a compiler warning:
>
>   CC      drivers/i2c/busses/i2c-omap.o
> drivers/i2c/busses/i2c-omap.c: In function 'omap_i2c_init':
> drivers/i2c/busses/i2c-omap.c:303: warning: unused variable 'v'
>
> So the declaration of "v" should be also removed here:
>

Thanks, updated patch in my queue an below for reference.

Kevin

>From 6880534c0a42beea0e500a566f910875342c313b Mon Sep 17 00:00:00 2001
From: Rajendra Nayak <rnayak@ti.com>
Date: Fri, 26 Sep 2008 17:48:07 +0530
Subject: [PATCH] I2C: OMAP3: PM: (re)init for every transfer to support off-mode

Because of OMAP off-mode, powerdomain can go off when I2C is idle.
Save enough state, and do a re-init for each transfer.

Additional save/restore state added by Jagadeesh Bhaskar Pakaravoor
(SYSC_REG) and Aaro Koskinen (wakeup sources.)

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
Cc: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/i2c/busses/i2c-omap.c |   62 +++++++++++++++++++++++++---------------
 1 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index ece0125..6b28e8a 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -178,6 +178,12 @@ struct omap_i2c_dev {
 	unsigned		b_hw:1;		/* bad h/w fixes */
 	unsigned		idle:1;
 	u16			iestate;	/* Saved interrupt register */
+	u16			pscstate;
+	u16			scllstate;
+	u16			sclhstate;
+	u16			bufstate;
+	u16			syscstate;
+	u16			westate;
 };
 
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
@@ -230,9 +236,16 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 
 	clk_enable(dev->iclk);
 	clk_enable(dev->fclk);
+	if (cpu_is_omap34xx()) {
+		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->bufstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->syscstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+	}
 	dev->idle = 0;
-	if (dev->iestate)
-		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
 }
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev)
@@ -258,7 +271,7 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev)
 
 static int omap_i2c_init(struct omap_i2c_dev *dev)
 {
-	u16 psc = 0, scll = 0, sclh = 0;
+	u16 psc = 0, scll = 0, sclh = 0, buf = 0;
 	u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
 	unsigned long fclk_rate = 12000000;
 	unsigned long timeout;
@@ -287,24 +300,22 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 					   SYSC_AUTOIDLE_MASK);
 
 		} else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
-			u32 v;
-
-			v = SYSC_AUTOIDLE_MASK;
-			v |= SYSC_ENAWAKEUP_MASK;
-			v |= (SYSC_IDLEMODE_SMART <<
+			dev->syscstate = SYSC_AUTOIDLE_MASK;
+			dev->syscstate |= SYSC_ENAWAKEUP_MASK;
+			dev->syscstate |= (SYSC_IDLEMODE_SMART <<
 			      __ffs(SYSC_SIDLEMODE_MASK));
-			v |= (SYSC_CLOCKACTIVITY_FCLK <<
+			dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK <<
 			      __ffs(SYSC_CLOCKACTIVITY_MASK));
 
-			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
+							dev->syscstate);
 			/*
 			 * Enabling all wakup sources to stop I2C freezing on
 			 * WFI instruction.
 			 * REVISIT: Some wkup sources might not be needed.
 			 */
-			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
-							OMAP_I2C_WE_ALL);
-
+			dev->westate = OMAP_I2C_WE_ALL;
+			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
 		}
 	}
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
@@ -373,23 +384,28 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
 	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
 
-	if (dev->fifo_size)
-		/* Note: setup required fifo size - 1 */
-		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
-					(dev->fifo_size - 1) << 8 | /* RTRSH */
-					OMAP_I2C_BUF_RXFIF_CLR |
-					(dev->fifo_size - 1) | /* XTRSH */
-					OMAP_I2C_BUF_TXFIF_CLR);
+	if (dev->fifo_size) {
+		/* Note: setup required fifo size - 1. RTRSH and XTRSH */
+		buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR |
+			(dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR;
+		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
+	}
 
 	/* Take the I2C module out of reset: */
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 
 	/* Enable interrupts */
-	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
-			(OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+	dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
 			OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
 			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
-				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0));
+				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0);
+	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+	if (cpu_is_omap34xx()) {
+		dev->pscstate = psc;
+		dev->scllstate = scll;
+		dev->sclhstate = sclh;
+		dev->bufstate = buf;
+	}
 	return 0;
 }
 
-- 
1.6.3.2


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* RE: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-26 14:19           ` Kevin Hilman
@ 2009-06-29  8:51             ` HU TAO-TGHK48
  2009-06-29 17:04               ` Kevin Hilman
  0 siblings, 1 reply; 15+ messages in thread
From: HU TAO-TGHK48 @ 2009-06-29  8:51 UTC (permalink / raw)
  To: Kevin Hilman, Aaro Koskinen
  Cc: linux-omap, Rajendra Nayak, Hogander Jouni (Nokia-D/Tampere),
	Jagadeesh Bhaskar Pakaravoor

I think we also need extra patch for fixing stability issue.

Sometimes after back from retention/off mode, OMAP3430 I2C controller
stops working even all register settings are restored.

OMAP3430 TRM says: "During active mode (I2Ci.I2C_CON[15] I2C_EN bit is
set to 1), make no changes to the I2Ci.I2C_SCLL and I2Ci.I2C_SCLH
registers. 
Changes may result in unpredictable behavior."


diff --git a/drivers/i2c/busses/i2c-omap.c
b/drivers/i2c/busses/i2c-omap.c index 5ce055c..b084209 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -238,12 +238,14 @@ static void omap_i2c_unidle(struct omap_i2c_dev
*dev)
 		clk_enable(dev->iclk);
 	clk_enable(dev->fclk);
 	if (cpu_is_omap34xx()) {
+		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
 		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG,
dev->pscstate);
 		omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
dev->scllstate);
 		omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
dev->sclhstate);
 		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
dev->bufstate);
 		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
dev->syscstate);
 		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
OMAP_I2C_CON_EN);
 	}
 	dev->idle = 0;
 	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);

-----Original Message-----
From: linux-omap-owner@vger.kernel.org
[mailto:linux-omap-owner@vger.kernel.org] On Behalf Of Kevin Hilman
Sent: Friday, June 26, 2009 10:19 PM
To: Aaro Koskinen
Cc: linux-omap@vger.kernel.org; Rajendra Nayak; Hogander Jouni
(Nokia-D/Tampere); Jagadeesh Bhaskar Pakaravoor
Subject: Re: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to
support off-mode

Aaro Koskinen <aaro.koskinen@nokia.com> writes:

> Kevin Hilman wrote:
>> From: Rajendra Nayak <rnayak@ti.com>
>>
>> Because of OMAP off-mode, powerdomain can go off when I2C is idle.
>> Save enough state, and do a re-init for each transfer.
>>
>> Additional save/restore state added by Jagadeesh Bhaskar Pakaravoor
>> (SYSC_REG) and Aaro Koskinen (wakeup sources.)
>>
>> Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
>> Signed-off-by: Rajendra Nayak <rnayak@ti.com>
>> Cc: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
>> Cc: Aaro Koskinen <aaro.koskinen@nokia.com>
>> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>
> This patch introduces a compiler warning:
>
>   CC      drivers/i2c/busses/i2c-omap.o
> drivers/i2c/busses/i2c-omap.c: In function 'omap_i2c_init':
> drivers/i2c/busses/i2c-omap.c:303: warning: unused variable 'v'
>
> So the declaration of "v" should be also removed here:
>

Thanks, updated patch in my queue an below for reference.

Kevin

>From 6880534c0a42beea0e500a566f910875342c313b Mon Sep 17 00:00:00 2001
From: Rajendra Nayak <rnayak@ti.com>
Date: Fri, 26 Sep 2008 17:48:07 +0530
Subject: [PATCH] I2C: OMAP3: PM: (re)init for every transfer to support
off-mode

Because of OMAP off-mode, powerdomain can go off when I2C is idle.
Save enough state, and do a re-init for each transfer.

Additional save/restore state added by Jagadeesh Bhaskar Pakaravoor
(SYSC_REG) and Aaro Koskinen (wakeup sources.)

Signed-off-by: Jouni Hogander <jouni.hogander@nokia.com>
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
Cc: Jagadeesh Bhaskar Pakaravoor <j-pakaravoor@ti.com>
Cc: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/i2c/busses/i2c-omap.c |   62
+++++++++++++++++++++++++---------------
 1 files changed, 39 insertions(+), 23 deletions(-)

diff --git a/drivers/i2c/busses/i2c-omap.c
b/drivers/i2c/busses/i2c-omap.c index ece0125..6b28e8a 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -178,6 +178,12 @@ struct omap_i2c_dev {
 	unsigned		b_hw:1;		/* bad h/w fixes */
 	unsigned		idle:1;
 	u16			iestate;	/* Saved interrupt
register */
+	u16			pscstate;
+	u16			scllstate;
+	u16			sclhstate;
+	u16			bufstate;
+	u16			syscstate;
+	u16			westate;
 };
 
 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, @@
-230,9 +236,16 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev)
 
 	clk_enable(dev->iclk);
 	clk_enable(dev->fclk);
+	if (cpu_is_omap34xx()) {
+		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG,
dev->pscstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
dev->scllstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
dev->sclhstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
dev->bufstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
dev->syscstate);
+		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
+	}
 	dev->idle = 0;
-	if (dev->iestate)
-		omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
 }
 
 static void omap_i2c_idle(struct omap_i2c_dev *dev) @@ -258,7 +271,7 @@
static void omap_i2c_idle(struct omap_i2c_dev *dev)
 
 static int omap_i2c_init(struct omap_i2c_dev *dev)  {
-	u16 psc = 0, scll = 0, sclh = 0;
+	u16 psc = 0, scll = 0, sclh = 0, buf = 0;
 	u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0;
 	unsigned long fclk_rate = 12000000;
 	unsigned long timeout;
@@ -287,24 +300,22 @@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 					   SYSC_AUTOIDLE_MASK);
 
 		} else if (dev->rev >= OMAP_I2C_REV_ON_3430) {
-			u32 v;
-
-			v = SYSC_AUTOIDLE_MASK;
-			v |= SYSC_ENAWAKEUP_MASK;
-			v |= (SYSC_IDLEMODE_SMART <<
+			dev->syscstate = SYSC_AUTOIDLE_MASK;
+			dev->syscstate |= SYSC_ENAWAKEUP_MASK;
+			dev->syscstate |= (SYSC_IDLEMODE_SMART <<
 			      __ffs(SYSC_SIDLEMODE_MASK));
-			v |= (SYSC_CLOCKACTIVITY_FCLK <<
+			dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK <<
 			      __ffs(SYSC_CLOCKACTIVITY_MASK));
 
-			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, v);
+			omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
+							dev->syscstate);
 			/*
 			 * Enabling all wakup sources to stop I2C
freezing on
 			 * WFI instruction.
 			 * REVISIT: Some wkup sources might not be
needed.
 			 */
-			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
-
OMAP_I2C_WE_ALL);
-
+			dev->westate = OMAP_I2C_WE_ALL;
+			omap_i2c_write_reg(dev, OMAP_I2C_WE_REG,
dev->westate);
 		}
 	}
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); @@ -373,23 +384,28
@@ static int omap_i2c_init(struct omap_i2c_dev *dev)
 	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll);
 	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh);
 
-	if (dev->fifo_size)
-		/* Note: setup required fifo size - 1 */
-		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
-					(dev->fifo_size - 1) << 8 | /*
RTRSH */
-					OMAP_I2C_BUF_RXFIF_CLR |
-					(dev->fifo_size - 1) | /* XTRSH
*/
-					OMAP_I2C_BUF_TXFIF_CLR);
+	if (dev->fifo_size) {
+		/* Note: setup required fifo size - 1. RTRSH and XTRSH
*/
+		buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR
|
+			(dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR;
+		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf);
+	}
 
 	/* Take the I2C module out of reset: */
 	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
 
 	/* Enable interrupts */
-	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
-			(OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+	dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
 			OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
 			OMAP_I2C_IE_AL)  | ((dev->fifo_size) ?
-				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) :
0));
+				(OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) :
0);
+	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);
+	if (cpu_is_omap34xx()) {
+		dev->pscstate = psc;
+		dev->scllstate = scll;
+		dev->sclhstate = sclh;
+		dev->bufstate = buf;
+	}
 	return 0;
 }
 
--
1.6.3.2

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@vger.kernel.org More majordomo info
at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 3/4] OMAP3 McSPI: Adds context save/restore
  2009-06-26 12:02       ` [PATCH 3/4] OMAP3 McSPI: Adds context save/restore Aaro Koskinen
@ 2009-06-29 14:25         ` Aaro Koskinen
  0 siblings, 0 replies; 15+ messages in thread
From: Aaro Koskinen @ 2009-06-29 14:25 UTC (permalink / raw)
  To: ext Kevin Hilman; +Cc: linux-omap, Hemanth V, Hogander Jouni (Nokia-D/Tampere)

[-- Attachment #1: Type: text/plain, Size: 990 bytes --]

Hello,

Koskinen Aaro (Nokia-D/Helsinki) wrote:
> I'm afraid this patch needs more work. The optimized restoration of
> chconf can cause occasionally errors with off mode if multiple chip
> selects are in use. In practice it is needed to restore all CHxCONF
> registers, not just the one by a specific chip select.
> 
> ext Kevin Hilman wrote:
>> From: Hemanth V <hemanthv@ti.com>
>>
>> This patch adds context save/restore feature to McSPI driver.
>> This includes fixes by Aaro Koskinen
>>
>> Signed-off-by: Hemanth V <hemanthv@ti.com>
>> Reviewed-by: Aaro Koskinen <Aaro.Koskinen@nokia.com>
>> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
>> ---
>>  drivers/spi/omap2_mcspi.c |  134 +++++++++++++++++++++++++++++++++-----------
>>  1 files changed, 100 insertions(+), 34 deletions(-)

Here's a patch on top of PM branch that restores all the registers. This 
is basically the same what Jouni originally suggested 
(http://marc.info/?l=linux-omap&m=123366825525879&w=2).

A.

[-- Attachment #2: 0001-PM-OMAP-SPI-Restore-all-CHxCONF-registers.patch --]
[-- Type: text/x-diff, Size: 2940 bytes --]

>From 92ee5d91385e96a358d44b0e59ae3484d4191786 Mon Sep 17 00:00:00 2001
From: Aaro Koskinen <aaro.koskinen@nokia.com>
Date: Mon, 29 Jun 2009 14:20:49 +0300
Subject: [PATCH] PM: OMAP: SPI: Restore all CHxCONF registers

Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
---
 drivers/spi/omap2_mcspi.c |   21 ++++++++++++++-------
 1 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
index a75c546..264bd21 100644
--- a/drivers/spi/omap2_mcspi.c
+++ b/drivers/spi/omap2_mcspi.c
@@ -43,6 +43,7 @@
 
 /* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */
 #define OMAP2_MCSPI_MAX_CTRL 		4
+#define OMAP2_MCSPI_MAX_CS 		4
 
 #define OMAP2_MCSPI_REVISION		0x00
 #define OMAP2_MCSPI_SYSCONFIG		0x10
@@ -134,8 +135,6 @@ struct omap2_mcspi_cs {
 	void __iomem		*base;
 	unsigned long		phys;
 	int			word_len;
-	/* Context save and restore shadow register */
-	u32			chconf0;
 };
 
 /* used for context save and restore, structure members to be updated whenever
@@ -145,6 +144,8 @@ struct omap2_mcspi_regs {
 	u32 sysconfig;
 	u32 modulctrl;
 	u32 wakeupenable;
+	/* Context save and restore shadow register for each chipselect */
+	u32 chconf0[OMAP2_MCSPI_MAX_CS];
 };
 
 static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL];
@@ -190,16 +191,16 @@ static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx)
 
 static inline u32 mcspi_cached_chconf0(const struct spi_device *spi)
 {
-	struct omap2_mcspi_cs *cs = spi->controller_state;
+	int cs = spi->chip_select;
 
-	return cs->chconf0;
+	return omap2_mcspi_ctx[spi->master->bus_num - 1].chconf0[cs];
 }
 
 static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
 {
-	struct omap2_mcspi_cs *cs = spi->controller_state;
+	int cs = spi->chip_select;
 
-	cs->chconf0 = val;
+	omap2_mcspi_ctx[spi->master->bus_num - 1].chconf0[cs] = val;
 	mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val);
 }
 
@@ -255,6 +256,8 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master)
 static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
 {
 	struct spi_master *spi_cntrl;
+	int cs;
+
 	spi_cntrl = mcspi->master;
 
 	/* McSPI: context restore */
@@ -266,6 +269,11 @@ static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi)
 
 	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
 			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
+
+	for (cs = 0; cs < spi_cntrl->num_chipselect; cs++)
+		mcspi_write_reg(spi_cntrl,
+			cs * 0x14 + OMAP2_MCSPI_CHCONF0,
+			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].chconf0[cs]);
 }
 static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
 {
@@ -704,7 +712,6 @@ static int omap2_mcspi_setup(struct spi_device *spi)
 			return -ENOMEM;
 		cs->base = mcspi->base + spi->chip_select * 0x14;
 		cs->phys = mcspi->phys + spi->chip_select * 0x14;
-		cs->chconf0 = 0;
 		spi->controller_state = cs;
 	}
 
-- 
1.5.4.3


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-29  8:51             ` HU TAO-TGHK48
@ 2009-06-29 17:04               ` Kevin Hilman
  2009-06-29 19:28                 ` Hunter, Jon
  0 siblings, 1 reply; 15+ messages in thread
From: Kevin Hilman @ 2009-06-29 17:04 UTC (permalink / raw)
  To: HU TAO-TGHK48
  Cc: Aaro Koskinen, linux-omap, Rajendra Nayak,
	Hogander Jouni (Nokia-D/Tampere),
	Jagadeesh Bhaskar Pakaravoor

"HU TAO-TGHK48" <taohu@motorola.com> writes:

> I think we also need extra patch for fixing stability issue.
>
> Sometimes after back from retention/off mode, OMAP3430 I2C controller
> stops working even all register settings are restored.
>
> OMAP3430 TRM says: "During active mode (I2Ci.I2C_CON[15] I2C_EN bit is
> set to 1), make no changes to the I2Ci.I2C_SCLL and I2Ci.I2C_SCLH
> registers. 
> Changes may result in unpredictable behavior."
>
> diff --git a/drivers/i2c/busses/i2c-omap.c
> b/drivers/i2c/busses/i2c-omap.c index 5ce055c..b084209 100644
> --- a/drivers/i2c/busses/i2c-omap.c
> +++ b/drivers/i2c/busses/i2c-omap.c
> @@ -238,12 +238,14 @@ static void omap_i2c_unidle(struct omap_i2c_dev
> *dev)
>  		clk_enable(dev->iclk);
>  	clk_enable(dev->fclk);
>  	if (cpu_is_omap34xx()) {
> +		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
>  		omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG,
> dev->pscstate);
>  		omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
> dev->scllstate);
>  		omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
> dev->sclhstate);
>  		omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG,
> dev->bufstate);
>  		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG,
> dev->syscstate);
>  		omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate);
> +		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
> OMAP_I2C_CON_EN);
>  	}
>  	dev->idle = 0;
>  	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate);

Shouldn't you do a read-modify-write of I2C_CON_REG here?  Otherwise,
you're loosing any of the other settings in I2C_CON_REG.

Not being an expert in the I2C hardware, I'm not sure if it matters,
but this doesn't seem quite right due to possible side effects.

Kevin


^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-29 17:04               ` Kevin Hilman
@ 2009-06-29 19:28                 ` Hunter, Jon
  2009-06-29 21:15                   ` Kevin Hilman
  0 siblings, 1 reply; 15+ messages in thread
From: Hunter, Jon @ 2009-06-29 19:28 UTC (permalink / raw)
  To: Kevin Hilman, HU TAO-TGHK48
  Cc: Aaro Koskinen, linux-omap, Nayak, Rajendra,
	Hogander Jouni (Nokia-D/Tampere),
	Pakaravoor, Jagadeesh


Hi Kevin,

> Shouldn't you do a read-modify-write of I2C_CON_REG here?  Otherwise,
> you're loosing any of the other settings in I2C_CON_REG.
>
> Not being an expert in the I2C hardware, I'm not sure if it matters,
> but this doesn't seem quite right due to possible side effects.

This is a good question and this exact same issue came up on the omapzoom tree. For the omapzoom tree we ended up not implementing a read-modify-write here. The reason being that omap_i2c_unidle is called at the beginning of every transfer and we are re-configuring the I2C_CON register for every transfer. So when consulting with the TI linux team they said that it is ok to simply write 0 and clear the register here so we start over fresh for each transfer.  

I was trying to think if there would be any harm in doing a read-modify-write here. Probably not. You would not want the STT bit (generate a start command) to get set, however, this bit should not be set in the first place when entering this function. 

This change has been implemented in the omapzoom tree and so for you reference please see:
http://git.omapzoom.org/?p=repo/omapkernel.git;a=commit;h=ec70a0af52df54638a4fa33fc0dc3d24b1f893f1

Cheers
Jon

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-29 19:28                 ` Hunter, Jon
@ 2009-06-29 21:15                   ` Kevin Hilman
  2009-06-30 16:49                     ` Hunter, Jon
  0 siblings, 1 reply; 15+ messages in thread
From: Kevin Hilman @ 2009-06-29 21:15 UTC (permalink / raw)
  To: Hunter, Jon
  Cc: HU TAO-TGHK48, Aaro Koskinen, linux-omap, Nayak, Rajendra,
	Hogander Jouni (Nokia-D/Tampere),
	Pakaravoor, Jagadeesh

"Hunter, Jon" <jon-hunter@ti.com> writes:

> Hi Kevin,
>
>> Shouldn't you do a read-modify-write of I2C_CON_REG here?  Otherwise,
>> you're loosing any of the other settings in I2C_CON_REG.
>>
>> Not being an expert in the I2C hardware, I'm not sure if it matters,
>> but this doesn't seem quite right due to possible side effects.
>
> This is a good question and this exact same issue came up on the
> omapzoom tree. For the omapzoom tree we ended up not implementing a
> read-modify-write here. The reason being that omap_i2c_unidle is
> called at the beginning of every transfer and we are re-configuring
> the I2C_CON register for every transfer. So when consulting with the
> TI linux team they said that it is ok to simply write 0 and clear
> the register here so we start over fresh for each transfer.
>
> I was trying to think if there would be any harm in doing a
> read-modify-write here. Probably not. You would not want the STT bit
> (generate a start command) to get set, however, this bit should not
> be set in the first place when entering this function.
>
> This change has been implemented in the omapzoom tree and so for you
>reference please see:
>http://git.omapzoom.org/?p=repo/omapkernel.git;a=commit;h=ec70a0af52df54638a4fa33fc0dc3d24b1f893f1

Jon, thanks for the clarification.  I will fold this change into
the upstream-bound I2C changes.

Also thanks for the pointer to the original patch with author/signoff
credits.

Tao, in the future please be sure to cite original authors and/or
sources when submitting patches to the list.

Thanks,

Kevin

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-29 21:15                   ` Kevin Hilman
@ 2009-06-30 16:49                     ` Hunter, Jon
  2009-07-01  9:43                       ` HU TAO-TGHK48
  0 siblings, 1 reply; 15+ messages in thread
From: Hunter, Jon @ 2009-06-30 16:49 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: HU TAO-TGHK48, Aaro Koskinen, linux-omap, Nayak, Rajendra,
	Hogander Jouni (Nokia-D/Tampere),
	Pakaravoor, Jagadeesh

Hi Kevin,

> Jon, thanks for the clarification.  I will fold this change into
> the upstream-bound I2C changes.

Thanks.

> Tao, in the future please be sure to cite original authors and/or
> sources when submitting patches to the list.

Actually, I should point out that Hu Tao and I worked on this together originally for the omapzoom.org tree. So I should have added Hu Tao's name to this when submitting originally to omapzoom.org. So we should give credit to Hu Tao on this. Sorry about that.

Cheers,
Jon

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode
  2009-06-30 16:49                     ` Hunter, Jon
@ 2009-07-01  9:43                       ` HU TAO-TGHK48
  0 siblings, 0 replies; 15+ messages in thread
From: HU TAO-TGHK48 @ 2009-07-01  9:43 UTC (permalink / raw)
  To: Hunter, Jon, Kevin Hilman
  Cc: Aaro Koskinen, linux-omap, Nayak, Rajendra,
	Hogander Jouni (Nokia-D/Tampere),
	Pakaravoor, Jagadeesh, Chen Xiaolong-A21785

Hi, Jon

It is fine.

In fact, the credit should be given to Xiaolong Chen
(A21785@motorola.com).



-----Original Message-----
From: Hunter, Jon [mailto:jon-hunter@ti.com] 
Sent: Wednesday, July 01, 2009 12:49 AM
To: Kevin Hilman
Cc: HU TAO-TGHK48; Aaro Koskinen; linux-omap@vger.kernel.org; Nayak,
Rajendra; Hogander Jouni (Nokia-D/Tampere); Pakaravoor, Jagadeesh
Subject: RE: [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to
support off-mode

Hi Kevin,

> Jon, thanks for the clarification.  I will fold this change into the 
> upstream-bound I2C changes.

Thanks.

> Tao, in the future please be sure to cite original authors and/or 
> sources when submitting patches to the list.

Actually, I should point out that Hu Tao and I worked on this together
originally for the omapzoom.org tree. So I should have added Hu Tao's
name to this when submitting originally to omapzoom.org. So we should
give credit to Hu Tao on this. Sorry about that.

Cheers,
Jon

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2009-07-01  9:43 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-25 21:34 [PATCH 0/4] driver updates from PM branch for upstream Kevin Hilman
2009-06-25 21:34 ` [PATCH 1/4] OMAP: McSPI: enable wake-ups and smart-idle Kevin Hilman
2009-06-25 21:34   ` [PATCH 2/4] OMAP: McSPI: Convert bit shifted values into BIT format Kevin Hilman
2009-06-25 21:34     ` [PATCH 3/4] OMAP3 McSPI: Adds context save/restore Kevin Hilman
2009-06-25 21:34       ` [PATCH 4/4] I2C: OMAP3: PM: (re)init for every transfer to support off-mode Kevin Hilman
2009-06-26 11:13         ` Aaro Koskinen
2009-06-26 14:19           ` Kevin Hilman
2009-06-29  8:51             ` HU TAO-TGHK48
2009-06-29 17:04               ` Kevin Hilman
2009-06-29 19:28                 ` Hunter, Jon
2009-06-29 21:15                   ` Kevin Hilman
2009-06-30 16:49                     ` Hunter, Jon
2009-07-01  9:43                       ` HU TAO-TGHK48
2009-06-26 12:02       ` [PATCH 3/4] OMAP3 McSPI: Adds context save/restore Aaro Koskinen
2009-06-29 14:25         ` Aaro Koskinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.