mirror of
https://github.com/torvalds/linux.git
synced 2026-05-24 15:12:13 +02:00
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>
This commit is contained in:
parent
f3837edc05
commit
86d074921e
|
|
@ -262,6 +262,9 @@ struct atmel_qspi_caps {
|
|||
bool has_ricr;
|
||||
bool octal;
|
||||
bool has_dma;
|
||||
bool has_2xgclk;
|
||||
bool has_padcalib;
|
||||
bool has_dllon;
|
||||
};
|
||||
|
||||
struct atmel_qspi_ops;
|
||||
|
|
@ -1027,13 +1030,25 @@ static int atmel_qspi_set_pad_calibration(struct atmel_qspi *aq)
|
|||
aq, QSPI_PCALCFG);
|
||||
|
||||
/* DLL On + start calibration. */
|
||||
atmel_qspi_write(QSPI_CR_DLLON | QSPI_CR_STPCAL, aq, QSPI_CR);
|
||||
if (aq->caps->has_dllon)
|
||||
atmel_qspi_write(QSPI_CR_DLLON | QSPI_CR_STPCAL, aq, QSPI_CR);
|
||||
/* If there is no DLL support only start calibration. */
|
||||
else
|
||||
atmel_qspi_write(QSPI_CR_STPCAL, aq, QSPI_CR);
|
||||
|
||||
/* Check synchronization status before updating configuration. */
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
(val & QSPI_SR2_DLOCK) &&
|
||||
!(val & QSPI_SR2_CALBSY), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
/*
|
||||
* Check DLL clock lock and synchronization status before updating
|
||||
* configuration.
|
||||
*/
|
||||
if (aq->caps->has_dllon)
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
(val & QSPI_SR2_DLOCK) &&
|
||||
!(val & QSPI_SR2_CALBSY), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
else
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
!(val & QSPI_SR2_CALBSY), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
|
||||
/* Refresh analogic blocks every 1 ms.*/
|
||||
atmel_qspi_write(FIELD_PREP(QSPI_REFRESH_DELAY_COUNTER,
|
||||
|
|
@ -1049,23 +1064,28 @@ static int atmel_qspi_set_gclk(struct atmel_qspi *aq)
|
|||
int ret;
|
||||
|
||||
/* Disable DLL before setting GCLK */
|
||||
status = atmel_qspi_read(aq, QSPI_SR2);
|
||||
if (status & QSPI_SR2_DLOCK) {
|
||||
atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
|
||||
if (aq->caps->has_dllon) {
|
||||
status = atmel_qspi_read(aq, QSPI_SR2);
|
||||
if (status & QSPI_SR2_DLOCK) {
|
||||
atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
!(val & QSPI_SR2_DLOCK), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
!(val & QSPI_SR2_DLOCK), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (aq->target_max_speed_hz > QSPI_DLLCFG_THRESHOLD_FREQ)
|
||||
atmel_qspi_write(QSPI_DLLCFG_RANGE, aq, QSPI_DLLCFG);
|
||||
else
|
||||
atmel_qspi_write(0, aq, QSPI_DLLCFG);
|
||||
}
|
||||
|
||||
if (aq->target_max_speed_hz > QSPI_DLLCFG_THRESHOLD_FREQ)
|
||||
atmel_qspi_write(QSPI_DLLCFG_RANGE, aq, QSPI_DLLCFG);
|
||||
if (aq->caps->has_2xgclk)
|
||||
ret = clk_set_rate(aq->gclk, 2 * aq->target_max_speed_hz);
|
||||
else
|
||||
atmel_qspi_write(0, aq, QSPI_DLLCFG);
|
||||
ret = clk_set_rate(aq->gclk, aq->target_max_speed_hz);
|
||||
|
||||
ret = clk_set_rate(aq->gclk, aq->target_max_speed_hz);
|
||||
if (ret) {
|
||||
dev_err(&aq->pdev->dev, "Failed to set generic clock rate.\n");
|
||||
return ret;
|
||||
|
|
@ -1088,11 +1108,16 @@ static int atmel_qspi_sama7g5_init(struct atmel_qspi *aq)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (aq->caps->octal) {
|
||||
/*
|
||||
* Check if the SoC supports pad calibration in Octal SPI mode.
|
||||
* Proceed only if both the capabilities are true.
|
||||
*/
|
||||
if (aq->caps->octal && aq->caps->has_padcalib) {
|
||||
ret = atmel_qspi_set_pad_calibration(aq);
|
||||
if (ret)
|
||||
return ret;
|
||||
} else {
|
||||
/* Start DLL on only if the SoC supports the same */
|
||||
} else if (aq->caps->has_dllon) {
|
||||
atmel_qspi_write(QSPI_CR_DLLON, aq, QSPI_CR);
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
(val & QSPI_SR2_DLOCK), 40,
|
||||
|
|
@ -1458,19 +1483,19 @@ static int atmel_qspi_sama7g5_suspend(struct atmel_qspi *aq)
|
|||
|
||||
clk_disable_unprepare(aq->gclk);
|
||||
|
||||
atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
!(val & QSPI_SR2_DLOCK), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
!(val & QSPI_SR2_CALBSY), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (aq->caps->has_dllon) {
|
||||
atmel_qspi_write(QSPI_CR_DLLOFF, aq, QSPI_CR);
|
||||
ret = readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
!(val & QSPI_SR2_DLOCK), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (aq->caps->has_padcalib)
|
||||
return readl_poll_timeout(aq->regs + QSPI_SR2, val,
|
||||
!(val & QSPI_SR2_CALBSY), 40,
|
||||
ATMEL_QSPI_TIMEOUT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1607,12 +1632,15 @@ static const struct atmel_qspi_caps atmel_sama7g5_ospi_caps = {
|
|||
.has_gclk = true,
|
||||
.octal = true,
|
||||
.has_dma = true,
|
||||
.has_padcalib = true,
|
||||
.has_dllon = true,
|
||||
};
|
||||
|
||||
static const struct atmel_qspi_caps atmel_sama7g5_qspi_caps = {
|
||||
.max_speed_hz = SAMA7G5_QSPI1_SDR_MAX_SPEED_HZ,
|
||||
.has_gclk = true,
|
||||
.has_dma = true,
|
||||
.has_dllon = true,
|
||||
};
|
||||
|
||||
static const struct of_device_id atmel_qspi_dt_ids[] = {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user