mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2025-12-10 06:24:40 +01:00
Add a new microchipsw target aimed add supporting Microchip switch SoC-s. Start by supporting LAN969x SoC-s as the first subtarget. Signed-off-by: Robert Marko <robert.marko@sartura.hr>
178 lines
5.6 KiB
Diff
178 lines
5.6 KiB
Diff
From 0f52d98240cdce03944c967d4fe4faab032f8f57 Mon Sep 17 00:00:00 2001
|
|
From: Varshini Rajendran <varshini.rajendran@microchip.com>
|
|
Date: Mon, 8 Sep 2025 09:44:18 +0530
|
|
Subject: [PATCH 109/112] 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>
|
|
---
|
|
drivers/spi/atmel-quadspi.c | 92 ++++++++++++++++++++++++-------------
|
|
1 file changed, 60 insertions(+), 32 deletions(-)
|
|
|
|
--- a/drivers/spi/atmel-quadspi.c
|
|
+++ b/drivers/spi/atmel-quadspi.c
|
|
@@ -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;
|
|
@@ -1028,13 +1031,25 @@ static int atmel_qspi_set_pad_calibratio
|
|
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,
|
|
@@ -1050,23 +1065,28 @@ static int atmel_qspi_set_gclk(struct at
|
|
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;
|
|
@@ -1089,11 +1109,16 @@ static int atmel_qspi_sama7g5_init(struc
|
|
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,
|
|
@@ -1434,19 +1459,19 @@ static int atmel_qspi_sama7g5_suspend(st
|
|
|
|
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;
|
|
}
|
|
|
|
@@ -1584,12 +1609,15 @@ static const struct atmel_qspi_caps atme
|
|
.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[] = {
|