Skip to content

Commit c528ecf

Browse files
ambarusbroonie
authored andcommitted
spi: atmel-quadspi: Add verbose debug facilities to monitor register accesses
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 138f56e commit c528ecf

File tree

1 file changed

+97
-22
lines changed

1 file changed

+97
-22
lines changed

drivers/spi/atmel-quadspi.c

Lines changed: 97 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,81 @@ static const struct atmel_qspi_mode atmel_qspi_modes[] = {
173173
{ 4, 4, 4, QSPI_IFR_WIDTH_QUAD_CMD },
174174
};
175175

176+
#ifdef VERBOSE_DEBUG
177+
static const char *atmel_qspi_reg_name(u32 offset, char *tmp, size_t sz)
178+
{
179+
switch (offset) {
180+
case QSPI_CR:
181+
return "CR";
182+
case QSPI_MR:
183+
return "MR";
184+
case QSPI_RD:
185+
return "MR";
186+
case QSPI_TD:
187+
return "TD";
188+
case QSPI_SR:
189+
return "SR";
190+
case QSPI_IER:
191+
return "IER";
192+
case QSPI_IDR:
193+
return "IDR";
194+
case QSPI_IMR:
195+
return "IMR";
196+
case QSPI_SCR:
197+
return "SCR";
198+
case QSPI_IAR:
199+
return "IAR";
200+
case QSPI_ICR:
201+
return "ICR/WICR";
202+
case QSPI_IFR:
203+
return "IFR";
204+
case QSPI_RICR:
205+
return "RICR";
206+
case QSPI_SMR:
207+
return "SMR";
208+
case QSPI_SKR:
209+
return "SKR";
210+
case QSPI_WPMR:
211+
return "WPMR";
212+
case QSPI_WPSR:
213+
return "WPSR";
214+
case QSPI_VERSION:
215+
return "VERSION";
216+
default:
217+
snprintf(tmp, sz, "0x%02x", offset);
218+
break;
219+
}
220+
221+
return tmp;
222+
}
223+
#endif /* VERBOSE_DEBUG */
224+
225+
static u32 atmel_qspi_read(struct atmel_qspi *aq, u32 offset)
226+
{
227+
u32 value = readl_relaxed(aq->regs + offset);
228+
229+
#ifdef VERBOSE_DEBUG
230+
char tmp[8];
231+
232+
dev_vdbg(&aq->pdev->dev, "read 0x%08x from %s\n", value,
233+
atmel_qspi_reg_name(offset, tmp, sizeof(tmp)));
234+
#endif /* VERBOSE_DEBUG */
235+
236+
return value;
237+
}
238+
239+
static void atmel_qspi_write(u32 value, struct atmel_qspi *aq, u32 offset)
240+
{
241+
#ifdef VERBOSE_DEBUG
242+
char tmp[8];
243+
244+
dev_vdbg(&aq->pdev->dev, "write 0x%08x into %s\n", value,
245+
atmel_qspi_reg_name(offset, tmp, sizeof(tmp)));
246+
#endif /* VERBOSE_DEBUG */
247+
248+
writel_relaxed(value, aq->regs + offset);
249+
}
250+
176251
static inline bool atmel_qspi_is_compatible(const struct spi_mem_op *op,
177252
const struct atmel_qspi_mode *mode)
178253
{
@@ -293,32 +368,32 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
293368
* Serial Memory Mode (SMM).
294369
*/
295370
if (aq->mr != QSPI_MR_SMM) {
296-
writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR);
371+
atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
297372
aq->mr = QSPI_MR_SMM;
298373
}
299374

300375
/* Clear pending interrupts */
301-
(void)readl_relaxed(aq->regs + QSPI_SR);
376+
(void)atmel_qspi_read(aq, QSPI_SR);
302377

303378
if (aq->caps->has_ricr) {
304379
if (!op->addr.nbytes && op->data.dir == SPI_MEM_DATA_IN)
305380
ifr |= QSPI_IFR_APBTFRTYP_READ;
306381

307382
/* Set QSPI Instruction Frame registers */
308-
writel_relaxed(iar, aq->regs + QSPI_IAR);
383+
atmel_qspi_write(iar, aq, QSPI_IAR);
309384
if (op->data.dir == SPI_MEM_DATA_IN)
310-
writel_relaxed(icr, aq->regs + QSPI_RICR);
385+
atmel_qspi_write(icr, aq, QSPI_RICR);
311386
else
312-
writel_relaxed(icr, aq->regs + QSPI_WICR);
313-
writel_relaxed(ifr, aq->regs + QSPI_IFR);
387+
atmel_qspi_write(icr, aq, QSPI_WICR);
388+
atmel_qspi_write(ifr, aq, QSPI_IFR);
314389
} else {
315390
if (op->data.dir == SPI_MEM_DATA_OUT)
316391
ifr |= QSPI_IFR_SAMA5D2_WRITE_TRSFR;
317392

318393
/* Set QSPI Instruction Frame registers */
319-
writel_relaxed(iar, aq->regs + QSPI_IAR);
320-
writel_relaxed(icr, aq->regs + QSPI_ICR);
321-
writel_relaxed(ifr, aq->regs + QSPI_IFR);
394+
atmel_qspi_write(iar, aq, QSPI_IAR);
395+
atmel_qspi_write(icr, aq, QSPI_ICR);
396+
atmel_qspi_write(ifr, aq, QSPI_IFR);
322397
}
323398

324399
return 0;
@@ -345,7 +420,7 @@ static int atmel_qspi_exec_op(struct spi_mem *mem, const struct spi_mem_op *op)
345420
/* Skip to the final steps if there is no data */
346421
if (op->data.nbytes) {
347422
/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
348-
(void)readl_relaxed(aq->regs + QSPI_IFR);
423+
(void)atmel_qspi_read(aq, QSPI_IFR);
349424

350425
/* Send/Receive data */
351426
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)
356431
op->data.nbytes);
357432

358433
/* Release the chip-select */
359-
writel_relaxed(QSPI_CR_LASTXFER, aq->regs + QSPI_CR);
434+
atmel_qspi_write(QSPI_CR_LASTXFER, aq, QSPI_CR);
360435
}
361436

362437
/* Poll INSTRuction End status */
363-
sr = readl_relaxed(aq->regs + QSPI_SR);
438+
sr = atmel_qspi_read(aq, QSPI_SR);
364439
if ((sr & QSPI_SR_CMD_COMPLETED) == QSPI_SR_CMD_COMPLETED)
365440
return err;
366441

367442
/* Wait for INSTRuction End interrupt */
368443
reinit_completion(&aq->cmd_completion);
369444
aq->pending = sr & QSPI_SR_CMD_COMPLETED;
370-
writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IER);
445+
atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IER);
371446
if (!wait_for_completion_timeout(&aq->cmd_completion,
372447
msecs_to_jiffies(1000)))
373448
err = -ETIMEDOUT;
374-
writel_relaxed(QSPI_SR_CMD_COMPLETED, aq->regs + QSPI_IDR);
449+
atmel_qspi_write(QSPI_SR_CMD_COMPLETED, aq, QSPI_IDR);
375450

376451
return err;
377452
}
@@ -410,31 +485,31 @@ static int atmel_qspi_setup(struct spi_device *spi)
410485
scbr--;
411486

412487
aq->scr = QSPI_SCR_SCBR(scbr);
413-
writel_relaxed(aq->scr, aq->regs + QSPI_SCR);
488+
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
414489

415490
return 0;
416491
}
417492

418493
static void atmel_qspi_init(struct atmel_qspi *aq)
419494
{
420495
/* Reset the QSPI controller */
421-
writel_relaxed(QSPI_CR_SWRST, aq->regs + QSPI_CR);
496+
atmel_qspi_write(QSPI_CR_SWRST, aq, QSPI_CR);
422497

423498
/* Set the QSPI controller by default in Serial Memory Mode */
424-
writel_relaxed(QSPI_MR_SMM, aq->regs + QSPI_MR);
499+
atmel_qspi_write(QSPI_MR_SMM, aq, QSPI_MR);
425500
aq->mr = QSPI_MR_SMM;
426501

427502
/* Enable the QSPI controller */
428-
writel_relaxed(QSPI_CR_QSPIEN, aq->regs + QSPI_CR);
503+
atmel_qspi_write(QSPI_CR_QSPIEN, aq, QSPI_CR);
429504
}
430505

431506
static irqreturn_t atmel_qspi_interrupt(int irq, void *dev_id)
432507
{
433508
struct atmel_qspi *aq = dev_id;
434509
u32 status, mask, pending;
435510

436-
status = readl_relaxed(aq->regs + QSPI_SR);
437-
mask = readl_relaxed(aq->regs + QSPI_IMR);
511+
status = atmel_qspi_read(aq, QSPI_SR);
512+
mask = atmel_qspi_read(aq, QSPI_IMR);
438513
pending = status & mask;
439514

440515
if (!pending)
@@ -569,7 +644,7 @@ static int atmel_qspi_remove(struct platform_device *pdev)
569644
struct atmel_qspi *aq = spi_controller_get_devdata(ctrl);
570645

571646
spi_unregister_controller(ctrl);
572-
writel_relaxed(QSPI_CR_QSPIDIS, aq->regs + QSPI_CR);
647+
atmel_qspi_write(QSPI_CR_QSPIDIS, aq, QSPI_CR);
573648
clk_disable_unprepare(aq->qspick);
574649
clk_disable_unprepare(aq->pclk);
575650
return 0;
@@ -596,7 +671,7 @@ static int __maybe_unused atmel_qspi_resume(struct device *dev)
596671

597672
atmel_qspi_init(aq);
598673

599-
writel_relaxed(aq->scr, aq->regs + QSPI_SCR);
674+
atmel_qspi_write(aq->scr, aq, QSPI_SCR);
600675

601676
return 0;
602677
}

0 commit comments

Comments
 (0)