From: tony@atomide.com (Tony Lindgren)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 09/17] omap: McBSP: Use cache when modifying individual register bits
Date: Wed, 10 Feb 2010 19:36:00 -0800 [thread overview]
Message-ID: <20100211033600.1624.26105.stgit@baageli.muru.com> (raw)
In-Reply-To: <20100211033310.1624.80025.stgit@baageli.muru.com>
From: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
Change the way McBSP registers are updated: use cached values instead of
relying upon those read back from the device.
With this patch, I have finally managed to get rid of all random
playback/recording hangups on my OMAP1510 based Amstrad Delta hardware. Before
that, values read back from McBSP registers to be used for updating them
happened to be errornous.
>From the hardware side, the issue appeared to be caused by a relatively high
power requirements of an external USB adapter connected to the board's printer
dedicated USB port.
I think there is one important point that makes this patch worth of applying,
apart from my hardware quality. With the current code, if it ever happens to
any machine, no matter if OMAP1510 or newer, to read incorrect value from a
McBSP register, this wrong value will get written back without any checking.
That can lead to hardware damage if, for example, an input pin is turned into
output as a result.
Applies on top of patch 3 from this series:
[PATCH v9 3/4] OMAP: McBSP: Introduce caching in register write operations
Tested on OMAP1510 based Amstrad Delta using linux-omap for-next, commit
fb7380d70e041e4b3892f6b19dff7efb609d15a4 (2.6.33-rc3+ dated 2010-01-11).
Compile-tested with omap_3430sdp_defconfig.
Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl>
Acked-by: Peter Ujfalusi <peter.ujfalusi@nokia.com>
Acked-by: Jarkko Nikula <jhnikula@gmail.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/plat-omap/mcbsp.c | 78 +++++++++++++++++++++++++++-----------------
1 files changed, 47 insertions(+), 31 deletions(-)
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 61e440a..473be3d 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -114,7 +114,8 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n",
irqst_spcr2);
/* Writing zero to XSYNC_ERR clears the IRQ */
- MCBSP_WRITE(mcbsp_tx, SPCR2, irqst_spcr2 & ~(XSYNC_ERR));
+ MCBSP_WRITE(mcbsp_tx, SPCR2,
+ MCBSP_READ_CACHE(mcbsp_tx, SPCR2) & ~(XSYNC_ERR));
} else {
complete(&mcbsp_tx->tx_irq_completion);
}
@@ -134,7 +135,8 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n",
irqst_spcr1);
/* Writing zero to RSYNC_ERR clears the IRQ */
- MCBSP_WRITE(mcbsp_rx, SPCR1, irqst_spcr1 & ~(RSYNC_ERR));
+ MCBSP_WRITE(mcbsp_rx, SPCR1,
+ MCBSP_READ_CACHE(mcbsp_rx, SPCR1) & ~(RSYNC_ERR));
} else {
complete(&mcbsp_rx->tx_irq_completion);
}
@@ -544,24 +546,25 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
}
mcbsp = id_to_mcbsp_ptr(id);
- mcbsp->rx_word_length = (MCBSP_READ(mcbsp, RCR1) >> 5) & 0x7;
- mcbsp->tx_word_length = (MCBSP_READ(mcbsp, XCR1) >> 5) & 0x7;
+ mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7;
+ mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7;
- idle = !((MCBSP_READ(mcbsp, SPCR2) | MCBSP_READ(mcbsp, SPCR1)) & 1);
+ idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+ MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
if (idle) {
/* Start the sample generator */
- w = MCBSP_READ(mcbsp, SPCR2);
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
}
/* Enable transmitter and receiver */
tx &= 1;
- w = MCBSP_READ(mcbsp, SPCR2);
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
MCBSP_WRITE(mcbsp, SPCR2, w | tx);
rx &= 1;
- w = MCBSP_READ(mcbsp, SPCR1);
+ w = MCBSP_READ_CACHE(mcbsp, SPCR1);
MCBSP_WRITE(mcbsp, SPCR1, w | rx);
/*
@@ -574,16 +577,16 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
if (idle) {
/* Start frame sync */
- w = MCBSP_READ(mcbsp, SPCR2);
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
}
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
/* Release the transmitter and receiver */
- w = MCBSP_READ(mcbsp, XCCR);
+ w = MCBSP_READ_CACHE(mcbsp, XCCR);
w &= ~(tx ? XDISABLE : 0);
MCBSP_WRITE(mcbsp, XCCR, w);
- w = MCBSP_READ(mcbsp, RCCR);
+ w = MCBSP_READ_CACHE(mcbsp, RCCR);
w &= ~(rx ? RDISABLE : 0);
MCBSP_WRITE(mcbsp, RCCR, w);
}
@@ -609,28 +612,29 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
/* Reset transmitter */
tx &= 1;
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
- w = MCBSP_READ(mcbsp, XCCR);
+ w = MCBSP_READ_CACHE(mcbsp, XCCR);
w |= (tx ? XDISABLE : 0);
MCBSP_WRITE(mcbsp, XCCR, w);
}
- w = MCBSP_READ(mcbsp, SPCR2);
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
MCBSP_WRITE(mcbsp, SPCR2, w & ~tx);
/* Reset receiver */
rx &= 1;
if (cpu_is_omap2430() || cpu_is_omap34xx()) {
- w = MCBSP_READ(mcbsp, RCCR);
+ w = MCBSP_READ_CACHE(mcbsp, RCCR);
w |= (rx ? RDISABLE : 0);
MCBSP_WRITE(mcbsp, RCCR, w);
}
- w = MCBSP_READ(mcbsp, SPCR1);
+ w = MCBSP_READ_CACHE(mcbsp, SPCR1);
MCBSP_WRITE(mcbsp, SPCR1, w & ~rx);
- idle = !((MCBSP_READ(mcbsp, SPCR2) | MCBSP_READ(mcbsp, SPCR1)) & 1);
+ idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+ MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
if (idle) {
/* Reset the sample rate generator */
- w = MCBSP_READ(mcbsp, SPCR2);
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
}
}
@@ -653,7 +657,7 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) {
/* clear error */
MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ(mcbsp, SPCR2) & (~XSYNC_ERR));
+ MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XSYNC_ERR));
/* resend */
return -1;
} else {
@@ -662,10 +666,12 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
if (attemps++ > 1000) {
MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ(mcbsp, SPCR2) & (~XRST));
+ MCBSP_READ_CACHE(mcbsp, SPCR2) &
+ (~XRST));
udelay(10);
MCBSP_WRITE(mcbsp, SPCR2,
- MCBSP_READ(mcbsp, SPCR2) | (XRST));
+ MCBSP_READ_CACHE(mcbsp, SPCR2) |
+ (XRST));
udelay(10);
dev_err(mcbsp->dev, "Could not write to"
" McBSP%d Register\n", mcbsp->id);
@@ -692,7 +698,7 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf)
if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) {
/* clear error */
MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ(mcbsp, SPCR1) & (~RSYNC_ERR));
+ MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RSYNC_ERR));
/* resend */
return -1;
} else {
@@ -701,10 +707,12 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf)
while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) {
if (attemps++ > 1000) {
MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ(mcbsp, SPCR1) & (~RRST));
+ MCBSP_READ_CACHE(mcbsp, SPCR1) &
+ (~RRST));
udelay(10);
MCBSP_WRITE(mcbsp, SPCR1,
- MCBSP_READ(mcbsp, SPCR1) | (RRST));
+ MCBSP_READ_CACHE(mcbsp, SPCR1) |
+ (RRST));
udelay(10);
dev_err(mcbsp->dev, "Could not read from"
" McBSP%d Register\n", mcbsp->id);
@@ -790,9 +798,11 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
spcr2 = MCBSP_READ(mcbsp, SPCR2);
if (attempts++ > 1000) {
/* We must reset the transmitter */
- MCBSP_WRITE(mcbsp, SPCR2, spcr2 & (~XRST));
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
udelay(10);
- MCBSP_WRITE(mcbsp, SPCR2, spcr2 | XRST);
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
udelay(10);
dev_err(mcbsp->dev, "McBSP%d transmitter not "
"ready\n", mcbsp->id);
@@ -811,9 +821,11 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
spcr1 = MCBSP_READ(mcbsp, SPCR1);
if (attempts++ > 1000) {
/* We must reset the receiver */
- MCBSP_WRITE(mcbsp, SPCR1, spcr1 & (~RRST));
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
udelay(10);
- MCBSP_WRITE(mcbsp, SPCR1, spcr1 | RRST);
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
udelay(10);
dev_err(mcbsp->dev, "McBSP%d receiver not "
"ready\n", mcbsp->id);
@@ -857,9 +869,11 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
spcr2 = MCBSP_READ(mcbsp, SPCR2);
if (attempts++ > 1000) {
/* We must reset the transmitter */
- MCBSP_WRITE(mcbsp, SPCR2, spcr2 & (~XRST));
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
udelay(10);
- MCBSP_WRITE(mcbsp, SPCR2, spcr2 | XRST);
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
udelay(10);
dev_err(mcbsp->dev, "McBSP%d transmitter not "
"ready\n", mcbsp->id);
@@ -878,9 +892,11 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
spcr1 = MCBSP_READ(mcbsp, SPCR1);
if (attempts++ > 1000) {
/* We must reset the receiver */
- MCBSP_WRITE(mcbsp, SPCR1, spcr1 & (~RRST));
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
udelay(10);
- MCBSP_WRITE(mcbsp, SPCR1, spcr1 | RRST);
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
udelay(10);
dev_err(mcbsp->dev, "McBSP%d receiver not "
"ready\n", mcbsp->id);
next prev parent reply other threads:[~2010-02-11 3:36 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-02-11 3:35 [PATCH 00/17] omap updates for 2.6.34 merge window, part 1 Tony Lindgren
2010-02-11 3:35 ` [PATCH 01/17] omap: convert boards to use physmap-flash Tony Lindgren
2010-02-11 3:35 ` [PATCH 02/17] MTD: remove no longer used OMAP flash map Tony Lindgren
2010-02-11 3:35 ` [PATCH 03/17] omap iommu: cleanup iommu page address mask and definitions Tony Lindgren
2010-02-11 3:35 ` [PATCH 04/17] omap: iommu: fix incorrect address for supersection 1st entry Tony Lindgren
2010-02-11 3:35 ` [PATCH 05/17] omap iommu: fix incorrect address for largepage " Tony Lindgren
2010-02-11 3:35 ` [PATCH 06/17] omap: McBSP: Use macros for all register read/write operations Tony Lindgren
2010-02-11 3:35 ` [PATCH 07/17] omap: McBSP: Modify macros/functions API for easy cache access Tony Lindgren
2010-02-11 3:35 ` [PATCH 08/17] omap: McBSP: Introduce caching in register write operations Tony Lindgren
2010-02-11 3:36 ` Tony Lindgren [this message]
2010-02-11 3:36 ` [PATCH 10/17] omap1: mailbox: kill compile warning Tony Lindgren
2010-02-11 3:36 ` [PATCH 11/17] omap2/3/4: mailbox: kill compile warning in mailbox.c Tony Lindgren
2010-02-11 3:36 ` [PATCH 12/17] omap2/3/4: gpmc: kill compile warning Tony Lindgren
2010-02-11 3:36 ` [PATCH 13/17] omap2/3/4: gpmc: avoid section definitions on headers Tony Lindgren
2010-02-11 3:45 ` [PATCH 14/17] omap2/3/4: serial: fix coding style indentaion Tony Lindgren
2010-02-11 3:45 ` [PATCH 15/17] omap2/3/4: Introducing 'gpmc-nand.c' for GPMC specific NAND init Tony Lindgren
2010-02-11 3:46 ` [PATCH 16/17] omap3: SDP: Introducing 'board-sdp-flash.c' for flash init Tony Lindgren
2010-02-11 3:46 ` [PATCH 17/17] omap3: Add support for flash on 3430SDP board Tony Lindgren
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100211033600.1624.26105.stgit@baageli.muru.com \
--to=tony@atomide.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).