Skip to content

Commit f663898

Browse files
Bence Csókásbroonie
authored andcommitted
spi: atmel-quadspi: Factor out switching to Serial Memory Mode to function
SAMA7G5 support (that was forward-ported from v6.1) re-introduced a bug that was fixed in v6.12, thankfully only in the codepath of the new SoC. But to prevent similar mistakes in the future, we split out the offending code to a function, and use this, fixed version everywhere. To facilitate this, support function `atmel_qspi_update_config()` also had to be moved upwards. For best viewing experience, use `--color-moved-ws="allow-indentation-change" --color-moved`. Fixes: 5af4220 ("spi: atmel-quadspi: Add support for sama7g5 QSPI") Reported-by: Alexander Dahl <ada@thorsis.com> Closes: https://lore.kernel.org/linux-spi/20241218-appliance-jaws-90773405977a@thorsis.com/ Signed-off-by: Bence Csókás <csokas.bence@prolan.hu> Link: https://patch.msgid.link/20241218151754.365519-1-csokas.bence@prolan.hu Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 0acb906 commit f663898

File tree

1 file changed

+53
-48
lines changed

1 file changed

+53
-48
lines changed

drivers/spi/atmel-quadspi.c

Lines changed: 53 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,28 @@ static void atmel_qspi_write(u32 value, struct atmel_qspi *aq, u32 offset)
414414
writel_relaxed(value, aq->regs + offset);
415415
}
416416

417+
static int atmel_qspi_reg_sync(struct atmel_qspi *aq)
418+
{
419+
u32 val;
420+
int ret;
421+
422+
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
423+
!(val & QSPI_SR2_SYNCBSY), 40,
424+
ATMEL_QSPI_SYNC_TIMEOUT);
425+
return ret;
426+
}
427+
428+
static int atmel_qspi_update_config(struct atmel_qspi *aq)
429+
{
430+
int ret;
431+
432+
ret = atmel_qspi_reg_sync(aq);
433+
if (ret)
434+
return ret;
435+
atmel_qspi_write(QSPI_CR_UPDCFG, aq, QSPI_CR);
436+
return atmel_qspi_reg_sync(aq);
437+
}
438+
417439
static inline bool atmel_qspi_is_compatible(const struct spi_mem_op *op,
418440
const struct atmel_qspi_mode *mode)
419441
{
@@ -476,6 +498,25 @@ static bool atmel_qspi_supports_op(struct spi_mem *mem,
476498
return true;
477499
}
478500

501+
/*
502+
* If the QSPI controller is set in regular SPI mode, set it in
503+
* Serial Memory Mode (SMM).
504+
*/
505+
static int atmel_qspi_set_serial_memory_mode(struct atmel_qspi *aq)
506+
{
507+
int ret = 0;
508+
509+
if (!(aq->mr & QSPI_MR_SMM)) {
510+
aq->mr |= QSPI_MR_SMM;
511+
atmel_qspi_write(aq->mr, aq, QSPI_MR);
512+
513+
if (aq->caps->has_gclk)
514+
ret = atmel_qspi_update_config(aq);
515+
}
516+
517+
return ret;
518+
}
519+
479520
static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
480521
const struct spi_mem_op *op, u32 *offset)
481522
{
@@ -555,14 +596,9 @@ static int atmel_qspi_set_cfg(struct atmel_qspi *aq,
555596
ifr |= QSPI_IFR_TFRTYP_MEM;
556597
}
557598

558-
/*
559-
* If the QSPI controller is set in regular SPI mode, set it in
560-
* Serial Memory Mode (SMM).
561-
*/
562-
if (!(aq->mr & QSPI_MR_SMM)) {
563-
aq->mr |= QSPI_MR_SMM;
564-
atmel_qspi_write(aq->mr, aq, QSPI_MR);
565-
}
599+
mode = atmel_qspi_set_serial_memory_mode(aq);
600+
if (mode < 0)
601+
return mode;
566602

567603
/* Clear pending interrupts */
568604
(void)atmel_qspi_read(aq, QSPI_SR);
@@ -638,28 +674,6 @@ static int atmel_qspi_transfer(struct spi_mem *mem,
638674
return atmel_qspi_wait_for_completion(aq, QSPI_SR_CMD_COMPLETED);
639675
}
640676

641-
static int atmel_qspi_reg_sync(struct atmel_qspi *aq)
642-
{
643-
u32 val;
644-
int ret;
645-
646-
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
647-
!(val & QSPI_SR2_SYNCBSY), 40,
648-
ATMEL_QSPI_SYNC_TIMEOUT);
649-
return ret;
650-
}
651-
652-
static int atmel_qspi_update_config(struct atmel_qspi *aq)
653-
{
654-
int ret;
655-
656-
ret = atmel_qspi_reg_sync(aq);
657-
if (ret)
658-
return ret;
659-
atmel_qspi_write(QSPI_CR_UPDCFG, aq, QSPI_CR);
660-
return atmel_qspi_reg_sync(aq);
661-
}
662-
663677
static int atmel_qspi_sama7g5_set_cfg(struct atmel_qspi *aq,
664678
const struct spi_mem_op *op, u32 *offset)
665679
{
@@ -713,18 +727,9 @@ static int atmel_qspi_sama7g5_set_cfg(struct atmel_qspi *aq,
713727
ifr |= QSPI_IFR_TFRTYP_MEM;
714728
}
715729

716-
/*
717-
* If the QSPI controller is set in regular SPI mode, set it in
718-
* Serial Memory Mode (SMM).
719-
*/
720-
if (aq->mr != QSPI_MR_SMM) {
721-
atmel_qspi_write(QSPI_MR_SMM | QSPI_MR_DQSDLYEN, aq, QSPI_MR);
722-
aq->mr = QSPI_MR_SMM;
723-
724-
ret = atmel_qspi_update_config(aq);
725-
if (ret)
726-
return ret;
727-
}
730+
ret = atmel_qspi_set_serial_memory_mode(aq);
731+
if (ret < 0)
732+
return ret;
728733

729734
/* Clear pending interrupts */
730735
(void)atmel_qspi_read(aq, QSPI_SR);
@@ -1092,10 +1097,9 @@ static int atmel_qspi_sama7g5_init(struct atmel_qspi *aq)
10921097
}
10931098

10941099
/* Set the QSPI controller by default in Serial Memory Mode */
1095-
atmel_qspi_write(QSPI_MR_SMM | QSPI_MR_DQSDLYEN, aq, QSPI_MR);
1096-
aq->mr = QSPI_MR_SMM;
1097-
ret = atmel_qspi_update_config(aq);
1098-
if (ret)
1100+
aq->mr |= QSPI_MR_DQSDLYEN;
1101+
ret = atmel_qspi_set_serial_memory_mode(aq);
1102+
if (ret < 0)
10991103
return ret;
11001104

11011105
/* Enable the QSPI controller. */
@@ -1244,8 +1248,9 @@ static int atmel_qspi_init(struct atmel_qspi *aq)
12441248
atmel_qspi_write(QSPI_CR_SWRST, aq, QSPI_CR);
12451249

12461250
/* Set the QSPI controller by default in Serial Memory Mode */
1247-
aq->mr |= QSPI_MR_SMM;
1248-
atmel_qspi_write(aq->mr, aq, QSPI_MR);
1251+
ret = atmel_qspi_set_serial_memory_mode(aq);
1252+
if (ret < 0)
1253+
return ret;
12491254

12501255
/* Enable the QSPI controller */
12511256
atmel_qspi_write(QSPI_CR_QSPIEN, aq, QSPI_CR);

0 commit comments

Comments
 (0)