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@xxxxxx>
This patch adds context save/restore feature to McSPI driver.
This includes fixes by Aaro Koskinen
Signed-off-by: Hemanth V <hemanthv@xxxxxx>
Reviewed-by: Aaro Koskinen <Aaro.Koskinen@xxxxxxxxx>
Signed-off-by: Kevin Hilman <khilman@xxxxxxxxxxxxxxxxxxx>
---
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.
>From 92ee5d91385e96a358d44b0e59ae3484d4191786 Mon Sep 17 00:00:00 2001
From: Aaro Koskinen <aaro.koskinen@xxxxxxxxx>
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@xxxxxxxxx>
---
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