From: <Tudor.Ambarus-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
To: <broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>,
<Nicolas.Ferre-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>,
<alexandre.belloni-LDxbnhwyfcJBDgjK7y7TUQ@public.gmane.org>,
<Ludovic.Desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Cc: <linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
<linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>,
<Tudor.Ambarus-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
Subject: [PATCH] spi: atmel-quadspi: Add verbose debug facilities to monitor register accesses
Date: Fri, 20 Mar 2020 06:51:01 +0000 [thread overview]
Message-ID: <20200320065058.891221-1-tudor.ambarus@microchip.com> (raw)
From: Tudor Ambarus <tudor.ambarus-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
This feature should not be enabled in release but can be useful for
developers who need to monitor register accesses at some specific places.
Helped me identify a bug in u-boot, by comparing the register accesses
from the linux driver with the ones from its u-boot variant.
Signed-off-by: Tudor Ambarus <tudor.ambarus-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
---
drivers/spi/atmel-quadspi.c | 119 +++++++++++++++++++++++++++++-------
1 file changed, 97 insertions(+), 22 deletions(-)
diff --git a/drivers/spi/atmel-quadspi.c b/drivers/spi/atmel-quadspi.c
index 13def7f78b9e..cb44d1e169aa 100644
--- a/drivers/spi/atmel-quadspi.c
+++ b/drivers/spi/atmel-quadspi.c
@@ -173,6 +173,81 @@ static const struct atmel_qspi_mode atmel_qspi_modes[] = {
{ 4, 4, 4, QSPI_IFR_WIDTH_QUAD_CMD },
};
+#ifdef VERBOSE_DEBUG
+static const char *atmel_qspi_reg_name(u32 offset, char *tmp, size_t sz)
+{
+ switch (offset) {
+ case QSPI_CR:
+ return "CR";
+ case QSPI_MR:
+ return "MR";
+ case QSPI_RD:
+ return "MR";
+ case QSPI_TD:
+ return "TD";
+ case QSPI_SR:
+ return "SR";
+ case QSPI_IER:
+ return "IER";
+ case QSPI_IDR:
+ return "IDR";
+ case QSPI_IMR:
+ return "IMR";
+ case QSPI_SCR:
+ return "SCR";
+ case QSPI_IAR:
+ return "IAR";
+ case QSPI_ICR:
+ return "ICR/WICR";
+ case QSPI_IFR:
+ return "IFR";
+ case QSPI_RICR:
+ return "RICR";
+ case QSPI_SMR:
+ return "SMR";
+ case QSPI_SKR:
+ return "SKR";
+ case QSPI_WPMR:
+ return "WPMR";
+ case QSPI_WPSR:
+ return "WPSR";
+ case QSPI_VERSION:
+ return "VERSION";
+ default:
+ snprintf(tmp, sz, "0x%02x", offset);
+ break;
+ }
+
+ return tmp;
+}
+#endif /* VERBOSE_DEBUG */
+
+static u32 atmel_qspi_read(struct atmel_qspi *aq, u32 offset)
+{
+ u32 value = readl_relaxed(aq->regs + offset);
+
+#ifdef VERBOSE_DEBUG
+ char tmp[8];
+
+ dev_vdbg(&aq->pdev->dev, "read 0x%08x from %s\n", value,
+ atmel_qspi_reg_name(offset, tmp, sizeof(tmp)));
+#endif /* VERBOSE_DEBUG */
+
+ return value;
+}
+
+static void atmel_qspi_write(u32 value, struct atmel_qspi *aq, u32 offset)
+{
+#ifdef VERBOSE_DEBUG
+ char tmp[8];
+
+ dev_vdbg(&aq->pdev->dev, "write 0x%08x into %s\n", value,
+ atmel_qspi_reg_name(offset, tmp, sizeof(tmp)));
+#endif /* VERBOSE_DEBUG */
+
+ writel_relaxed(value, aq->regs + offset);
+}
+
static inline bool atmel_qspi_is_compatible(const struct spi_mem_op *op,
const struct atmel_qspi_mode *mode)
{
@@ -293,32 +368,32 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
* Serial Memory Mode (SMM).
*/
if (aq->mr != QSPI_MR_SMM) {
- writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR);
+ atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
aq->mr = QSPI_MR_SMM;
}
/* Clear pending interrupts */
- (void)readl_relaxed(aq->regs + QSPI_SR);
+ (void)atmel_qspi_read(aq, QSPI_SR);
if (aq->caps->has_ricr) {
if (!op->addr.nbytes && op->data.dir == SPI_MEM_DATA_IN)
ifr |= QSPI_IFR_APBTFRTYP_READ;
/* Set QSPI Instruction Frame registers */
- writel_relaxed(iar, aq->regs + QSPI_IAR);
+ atmel_qspi_write(iar, aq, QSPI_IAR);
if (op->data.dir == SPI_MEM_DATA_IN)
- writel_relaxed(icr, aq->regs + QSPI_RICR);
+ atmel_qspi_write(icr, aq, QSPI_RICR);
else
- writel_relaxed(icr, aq->regs + QSPI_WICR);
- writel_relaxed(ifr, aq->regs + QSPI_IFR);
+ atmel_qspi_write(icr, aq, QSPI_WICR);
+ atmel_qspi_write(ifr, aq, QSPI_IFR);
} else {
if (op->data.dir == SPI_MEM_DATA_OUT)
ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR;
/* Set QSPI Instruction Frame registers */
- writel_relaxed(iar, aq->regs + QSPI_IAR);
- writel_relaxed(icr, aq->regs + QSPI_ICR);
- writel_relaxed(ifr, aq->regs + QSPI_IFR);
+ atmel_qspi_write(iar, aq, QSPI_IAR);
+ atmel_qspi_write(icr, aq, QSPI_ICR);
+ atmel_qspi_write(ifr, aq, QSPI_IFR);
}
return 0;
@@ -345,7 +420,7 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
/* Skip to the final steps if there is no data */
if (op->data.nbytes) {
/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
- (void)readl_relaxed(aq->regs + QSPI_IFR);
+ (void)atmel_qspi_read(aq, QSPI_IFR);
/* Send/Receive data */
if (op->data.dir == SPI_MEM_DATA_IN)
@@ -356,22 +431,22 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
op->data.nbytes);
/* Release the chip-select */
- writel_relaxed(QSPI_CR_LASTXFER, aq->regs + QSPI_CR);
+ atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
}
/* Poll INSTRuction End status */
- sr = readl_relaxed(aq->regs + QSPI_SR);
+ sr = atmel_qspi_read(aq, QSPI_SR);
if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
return err;
/* Wait for INSTRuction End interrupt */
reinit_completion(&aq->cmd_completion);
aq->pending = sr & QSPI_SR_CMD_COMPLETED;
- writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IER);
+ atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IER);
if (!wait_for_completion_timeout(&aq->cmd_completion,
msecs_to_jiffies(1000)))
err = -ETIMEDOUT;
- writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IDR);
+ atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IDR);
return err;
}
@@ -410,7 +485,7 @@ static int atmel_qspi_setup(struct spi_device *spi)
scbr--;
aq->scr = QSPI_SCR_SCBR(scbr);
- writel_relaxed(aq->scr, aq->regs + QSPI_SCR);
+ atmel_qspi_write(aq->scr, aq, QSPI_SCR);
return 0;
}
@@ -418,14 +493,14 @@ static int atmel_qspi_setup(struct spi_device *spi)
static void atmel_qspi_init(struct atmel_qspi *aq)
{
/* Reset the QSPI controller */
- writel_relaxed(QSPI_CR_SWRST, aq->regs + QSPI_CR);
+ atmel_qspi_write(QSPI_CR_SWRST, aq, QSPI_CR);
/* Set the QSPI controller by default in Serial Memory Mode */
- writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR);
+ atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
aq->mr = QSPI_MR_SMM;
/* Enable the QSPI controller */
- writel_relaxed(QSPI_CR_QSPIEN, aq->regs + QSPI_CR);
+ atmel_qspi_write(QSPI_CR_QSPIEN, aq, QSPI_CR);
}
static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)
@@ -433,8 +508,8 @@ static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)
struct atmel_qspi *aq = dev_id;
u32 status, mask, pending;
- status = readl_relaxed(aq->regs + QSPI_SR);
- mask = readl_relaxed(aq->regs + QSPI_IMR);
+ status = atmel_qspi_read(aq, QSPI_SR);
+ mask = atmel_qspi_read(aq, QSPI_IMR);
pending = status & mask;
if (!pending)
@@ -569,7 +644,7 @@ static int atmel_qspi_remove(struct platform_device *pdev)
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
spi_unregister_controller(ctrl);
- writel_relaxed(QSPI_CR_QSPIDIS, aq->regs + QSPI_CR);
+ atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR);
clk_disable_unprepare(aq->qspick);
clk_disable_unprepare(aq->pclk);
return 0;
@@ -596,7 +671,7 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev)
atmel_qspi_init(aq);
- writel_relaxed(aq->scr, aq->regs + QSPI_SCR);
+ atmel_qspi_write(aq->scr, aq, QSPI_SCR);
return 0;
}
--
2.23.0
next reply other threads:[~2020-03-20 6:51 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-03-20 6:51 Tudor.Ambarus-UWL1GkI3JZL3oGB3hsPCZA [this message]
[not found] ` <20200320065058.891221-1-tudor.ambarus-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org>
2020-03-20 12:11 ` [PATCH] spi: atmel-quadspi: Add verbose debug facilities to monitor register accesses Mark Brown
2020-03-25 7:44 ` Tudor.Ambarus
2020-03-20 13:05 ` Applied "spi: atmel-quadspi: Add verbose debug facilities to monitor register accesses" to the spi tree Mark Brown
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=20200320065058.891221-1-tudor.ambarus@microchip.com \
--to=tudor.ambarus-uwl1gki3jzl3ogb3hspcza@public.gmane.org \
--cc=Ludovic.Desroches-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org \
--cc=Nicolas.Ferre-UWL1GkI3JZL3oGB3hsPCZA@public.gmane.org \
--cc=alexandre.belloni-LDxbnhwyfcJBDgjK7y7TUQ@public.gmane.org \
--cc=broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-spi-u79uwXL29TY76Z2rM5mHXA@public.gmane.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).