[PATCH v3 03/13] spi: parse two-element spi-max-frequency property

From: Santhosh Kumar K

Date: Wed May 27 2026 - 14:00:12 EST


Some SPI controllers support high-speed operating modes that require
controller-side configuration before the device can be driven at its
rated maximum. In such cases the device has two relevant speeds: a
conservative rate for baseline operation and a maximum rate achievable
once the controller is fully configured.

Extend struct spi_device with a base_speed_hz field. Update
of_spi_parse_dt() to populate base_speed_hz from the first element and
max_speed_hz from the second when spi-max-frequency carries two values.
A single-element property continues to populate only max_speed_hz,
preserving existing behaviour. base_speed_hz is zero when not set.

Signed-off-by: Santhosh Kumar K <s-k6@xxxxxx>
---
drivers/spi/spi.c | 17 ++++++++++++++---
include/linux/spi/spi.h | 2 ++
2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 76e3563c523f..a1050b1a1d4c 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -2364,7 +2364,7 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
struct device_node *nc)
{
u32 value, cs[SPI_DEVICE_CS_CNT_MAX], map[SPI_DEVICE_DATA_LANE_CNT_MAX];
- int rc, idx, max_num_data_lanes;
+ int rc, idx, max_num_data_lanes, nfreq;

/* Mode (clock phase/polarity/etc.) */
if (of_property_read_bool(nc, "spi-cpha"))
@@ -2596,9 +2596,20 @@ static int of_spi_parse_dt(struct spi_controller *ctlr, struct spi_device *spi,
*/
spi->cs_index_mask = BIT(0);

- /* Device speed */
- if (!of_property_read_u32(nc, "spi-max-frequency", &value))
+ /*
+ * Device speed: a single value sets max_speed_hz; two values set
+ * base_speed_hz (conservative) and max_speed_hz (maximum after
+ * controller-side configuration).
+ */
+ nfreq = of_property_count_u32_elems(nc, "spi-max-frequency");
+ if (nfreq == 2) {
+ of_property_read_u32_index(nc, "spi-max-frequency", 0,
+ &spi->base_speed_hz);
+ of_property_read_u32_index(nc, "spi-max-frequency", 1,
+ &spi->max_speed_hz);
+ } else if (!of_property_read_u32(nc, "spi-max-frequency", &value)) {
spi->max_speed_hz = value;
+ }

/* Device CS delays */
of_spi_parse_dt_cs_delay(nc, &spi->cs_setup, "spi-cs-setup-delay-ns");
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index f6ed93eff00b..e4fc8ac1c889 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -139,6 +139,7 @@ extern void spi_transfer_cs_change_delay_exec(struct spi_message *msg,
* @max_speed_hz: Maximum clock rate to be used with this chip
* (on this board); may be changed by the device's driver.
* The spi_transfer.speed_hz can override this for each transfer.
+ * @base_speed_hz: Conservative clock rate for the device; zero when not set.
* @bits_per_word: Data transfers involve one or more words; word sizes
* like eight or 12 bits are common. In-memory wordsizes are
* powers of two bytes (e.g. 20 bit samples use 32 bits).
@@ -191,6 +192,7 @@ struct spi_device {
struct device dev;
struct spi_controller *controller;
u32 max_speed_hz;
+ u32 base_speed_hz;
u8 bits_per_word;
bool rt;
#define SPI_NO_TX BIT(31) /* No transmit wire */
--
2.34.1