Skip to content

Commit 23c8db4

Browse files
smalaenashif
authored andcommitted
drivers: spi: siwx91x: Add helper to round GSPI freq to valid range
Add gspi_siwx91x_pick_lower_freq() to select the nearest lower supported GSPI clock frequency based on the requested value. The GSPI clock can operate only at discrete frequencies such as 80 MHz, 40 MHz, 26.6 MHz, 20 MHz, and so on (80 MHz divided by integer factors). If the requested frequency does not match one of these valid steps, it is rounded down to the nearest lower supported frequency. The driver now logs both the requested and the actual programmed frequency along with the divider value, helping users verify the effective SPI clock configuration. Signed-off-by: Sai Santhosh Malae <Santhosh.Malae@silabs.com>
1 parent cbb2fda commit 23c8db4

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

drivers/spi/spi_silabs_siwx91x_gspi.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,37 @@ static bool spi_siwx91x_is_dma_enabled_instance(const struct device *dev)
7676
#endif
7777
}
7878

79+
void gspi_siwx91x_pick_lower_freq(uint32_t clock_hz, uint32_t requested_hz, uint32_t *actual_hz_out,
80+
uint32_t *div_out)
81+
{
82+
/* Calculate divider that ensures freq <= requested */
83+
uint32_t divider = DIV_ROUND_UP(clock_hz, 2 * requested_hz);
84+
uint32_t actual_hz;
85+
86+
if (divider == 0U) {
87+
divider = 1U;
88+
}
89+
90+
/* Compute the actual achievable frequency */
91+
actual_hz = clock_hz / (2U * divider);
92+
93+
if (actual_hz_out) {
94+
*actual_hz_out = actual_hz;
95+
}
96+
97+
if (div_out) {
98+
*div_out = divider;
99+
}
100+
}
101+
79102
static int gspi_siwx91x_config(const struct device *dev, const struct spi_config *spi_cfg,
80103
spi_callback_t cb, void *userdata)
81104
{
82105
__maybe_unused struct gspi_siwx91x_data *data = dev->data;
83106
const struct gspi_siwx91x_config *cfg = dev->config;
84107
uint32_t bit_rate = spi_cfg->frequency;
85108
uint32_t clk_div_factor;
109+
uint32_t actual_freq;
86110
uint32_t clock_rate;
87111
int ret;
88112
__maybe_unused int channel_filter;
@@ -119,7 +143,13 @@ static int gspi_siwx91x_config(const struct device *dev, const struct spi_config
119143
if (ret) {
120144
return ret;
121145
}
122-
clk_div_factor = ((clock_rate / spi_cfg->frequency) / 2);
146+
147+
gspi_siwx91x_pick_lower_freq(clock_rate, spi_cfg->frequency, &actual_freq,
148+
&clk_div_factor);
149+
if (spi_cfg->frequency != actual_freq) {
150+
LOG_INF("Requested %u Hz, programmed %u Hz (divider=%u)",
151+
spi_cfg->frequency, actual_freq, clk_div_factor);
152+
}
123153
}
124154

125155
if (clk_div_factor < 1) {

0 commit comments

Comments
 (0)