Skip to content

Commit 86d0749

Browse files
varshini-rajendranbroonie
authored andcommitted
spi: atmel-quadspi: add padcalib, 2xgclk, and dllon capabilities
Introduce capability flags for SoC-specific variations of the QuadSPI controller: - has_padcalib: controller supports pad calibration - has_2xgclk: requires GCLK at half the data rate (2x clocking) - has_dllon: controller supports DLL clock Set `has_padcalib` for Octal controllers that provide pad calibration support. Use `has_2xgclk` for controllers that require the GCLK to run at twice the data rate. Differentiate SoC integration variants with the `has_dllon` flag and set it as needed. Signed-off-by: Varshini Rajendran <varshini.rajendran@microchip.com> Signed-off-by: Dharma Balasubiramani <dharma.b@microchip.com> Link: https://patch.msgid.link/20250908-microchip-qspi-v2-3-8f3d69fdd5c9@microchip.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent f3837ed commit 86d0749

1 file changed

Lines changed: 60 additions & 32 deletions

File tree

drivers/spi/atmel-quadspi.c

Lines changed: 60 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ struct atmel_qspi_caps {
262262
bool has_ricr;
263263
bool octal;
264264
bool has_dma;
265+
bool has_2xgclk;
266+
bool has_padcalib;
267+
bool has_dllon;
265268
};
266269

267270
struct atmel_qspi_ops;
@@ -1027,13 +1030,25 @@ static int atmel_qspi_set_pad_calibration(struct atmel_qspi *aq)
10271030
aq, QSPI_PCALCFG);
10281031

10291032
/* DLL On + start calibration. */
1030-
atmel_qspi_write(QSPI_CR_DLLON | QSPI_CR_STPCAL, aq, QSPI_CR);
1033+
if (aq->caps->has_dllon)
1034+
atmel_qspi_write(QSPI_CR_DLLON | QSPI_CR_STPCAL, aq, QSPI_CR);
1035+
/* If there is no DLL support only start calibration. */
1036+
else
1037+
atmel_qspi_write(QSPI_CR_STPCAL, aq, QSPI_CR);
10311038

1032-
/* Check synchronization status before updating configuration. */
1033-
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
1034-
(val & QSPI_SR2_DLOCK) &&
1035-
!(val & QSPI_SR2_CALBSY), 40,
1036-
ATMEL_QSPI_TIMEOUT);
1039+
/*
1040+
* Check DLL clock lock and synchronization status before updating
1041+
* configuration.
1042+
*/
1043+
if (aq->caps->has_dllon)
1044+
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
1045+
(val & QSPI_SR2_DLOCK) &&
1046+
!(val & QSPI_SR2_CALBSY), 40,
1047+
ATMEL_QSPI_TIMEOUT);
1048+
else
1049+
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
1050+
!(val & QSPI_SR2_CALBSY), 40,
1051+
ATMEL_QSPI_TIMEOUT);
10371052

10381053
/* Refresh analogic blocks every 1 ms.*/
10391054
atmel_qspi_write(FIELD_PREP(QSPI_REFRESH_DELAY_COUNTER,
@@ -1049,23 +1064,28 @@ static int atmel_qspi_set_gclk(struct atmel_qspi *aq)
10491064
int ret;
10501065

10511066
/* Disable DLL before setting GCLK */
1052-
status = atmel_qspi_read(aq, QSPI_SR2);
1053-
if (status & QSPI_SR2_DLOCK) {
1054-
atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
1067+
if (aq->caps->has_dllon) {
1068+
status = atmel_qspi_read(aq, QSPI_SR2);
1069+
if (status & QSPI_SR2_DLOCK) {
1070+
atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
1071+
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
1072+
!(val & QSPI_SR2_DLOCK), 40,
1073+
ATMEL_QSPI_TIMEOUT);
1074+
if (ret)
1075+
return ret;
1076+
}
10551077

1056-
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
1057-
!(val & QSPI_SR2_DLOCK), 40,
1058-
ATMEL_QSPI_TIMEOUT);
1059-
if (ret)
1060-
return ret;
1078+
if (aq->target_max_speed_hz > QSPI_DLLCFG_THRESHOLD_FREQ)
1079+
atmel_qspi_write(QSPI_DLLCFG_RANGE, aq, QSPI_DLLCFG);
1080+
else
1081+
atmel_qspi_write(0, aq, QSPI_DLLCFG);
10611082
}
10621083

1063-
if (aq->target_max_speed_hz > QSPI_DLLCFG_THRESHOLD_FREQ)
1064-
atmel_qspi_write(QSPI_DLLCFG_RANGE, aq, QSPI_DLLCFG);
1084+
if (aq->caps->has_2xgclk)
1085+
ret = clk_set_rate(aq->gclk, 2 * aq->target_max_speed_hz);
10651086
else
1066-
atmel_qspi_write(0, aq, QSPI_DLLCFG);
1087+
ret = clk_set_rate(aq->gclk, aq->target_max_speed_hz);
10671088

1068-
ret = clk_set_rate(aq->gclk, aq->target_max_speed_hz);
10691089
if (ret) {
10701090
dev_err(&aq->pdev->dev, "Failed to set generic clock rate.\n");
10711091
return ret;
@@ -1088,11 +1108,16 @@ static int atmel_qspi_sama7g5_init(struct atmel_qspi *aq)
10881108
if (ret)
10891109
return ret;
10901110

1091-
if (aq->caps->octal) {
1111+
/*
1112+
* Check if the SoC supports pad calibration in Octal SPI mode.
1113+
* Proceed only if both the capabilities are true.
1114+
*/
1115+
if (aq->caps->octal && aq->caps->has_padcalib) {
10921116
ret = atmel_qspi_set_pad_calibration(aq);
10931117
if (ret)
10941118
return ret;
1095-
} else {
1119+
/* Start DLL on only if the SoC supports the same */
1120+
} else if (aq->caps->has_dllon) {
10961121
atmel_qspi_write(QSPI_CR_DLLON, aq, QSPI_CR);
10971122
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
10981123
(val & QSPI_SR2_DLOCK), 40,
@@ -1458,19 +1483,19 @@ static int atmel_qspi_sama7g5_suspend(struct atmel_qspi *aq)
14581483

14591484
clk_disable_unprepare(aq->gclk);
14601485

1461-
atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
1462-
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
1463-
!(val & QSPI_SR2_DLOCK), 40,
1464-
ATMEL_QSPI_TIMEOUT);
1465-
if (ret)
1466-
return ret;
1467-
1468-
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
1469-
!(val & QSPI_SR2_CALBSY), 40,
1470-
ATMEL_QSPI_TIMEOUT);
1471-
if (ret)
1472-
return ret;
1486+
if (aq->caps->has_dllon) {
1487+
atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
1488+
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
1489+
!(val & QSPI_SR2_DLOCK), 40,
1490+
ATMEL_QSPI_TIMEOUT);
1491+
if (ret)
1492+
return ret;
1493+
}
14731494

1495+
if (aq->caps->has_padcalib)
1496+
return readl_poll_timeout(aq->regs + QSPI_SR2, val,
1497+
!(val & QSPI_SR2_CALBSY), 40,
1498+
ATMEL_QSPI_TIMEOUT);
14741499
return 0;
14751500
}
14761501

@@ -1607,12 +1632,15 @@ static const struct atmel_qspi_caps atmel_sama7g5_ospi_caps = {
16071632
.has_gclk = true,
16081633
.octal = true,
16091634
.has_dma = true,
1635+
.has_padcalib = true,
1636+
.has_dllon = true,
16101637
};
16111638

16121639
static const struct atmel_qspi_caps atmel_sama7g5_qspi_caps = {
16131640
.max_speed_hz = SAMA7G5_QSPI1_SDR_MAX_SPEED_HZ,
16141641
.has_gclk = true,
16151642
.has_dma = true,
1643+
.has_dllon = true,
16161644
};
16171645

16181646
static const struct of_device_id atmel_qspi_dt_ids[] = {

0 commit comments

Comments
 (0)