Skip to content

Commit 2d9f487

Browse files
vaishnavachathbroonie
authored andcommitted
spi: omap2-mcspi: Fix hardcoded reference clock
A hardcoded reference clock of 48 MHz is used to calculate the clock divisor values, but the reference clock frequency can be different across devices and can be configured which can cause a mismatch between the reported frequency and actual SPI clock frequency observed. Fix this by fetching the clock rate from the clock provider and falling back to hardcoded reference only if the clock is not supplied. Fixes: 2cd7d39 ("arm64: dts: ti: k3-am654: Add McSPI DT nodes") Signed-off-by: Vaishnav Achath <[email protected]> Reviewed-by: Dhruva Gole <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 9f778f3 commit 2d9f487

File tree

1 file changed

+20
-11
lines changed

1 file changed

+20
-11
lines changed

drivers/spi/spi-omap2-mcspi.c

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,12 @@ struct omap2_mcspi {
125125
struct omap2_mcspi_dma *dma_channels;
126126
struct device *dev;
127127
struct omap2_mcspi_regs ctx;
128+
struct clk *ref_clk;
128129
int fifo_depth;
129130
bool target_aborted;
130131
unsigned int pin_dir:1;
131132
size_t max_xfer_len;
133+
u32 ref_clk_hz;
132134
};
133135

134136
struct omap2_mcspi_cs {
@@ -880,12 +882,12 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
880882
return count - c;
881883
}
882884

883-
static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
885+
static u32 omap2_mcspi_calc_divisor(u32 speed_hz, u32 ref_clk_hz)
884886
{
885887
u32 div;
886888

887889
for (div = 0; div < 15; div++)
888-
if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
890+
if (speed_hz >= (ref_clk_hz >> div))
889891
return div;
890892

891893
return 15;
@@ -897,7 +899,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
897899
{
898900
struct omap2_mcspi_cs *cs = spi->controller_state;
899901
struct omap2_mcspi *mcspi;
900-
u32 l = 0, clkd = 0, div, extclk = 0, clkg = 0;
902+
u32 ref_clk_hz, l = 0, clkd = 0, div, extclk = 0, clkg = 0;
901903
u8 word_len = spi->bits_per_word;
902904
u32 speed_hz = spi->max_speed_hz;
903905

@@ -911,14 +913,15 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi,
911913
if (t && t->speed_hz)
912914
speed_hz = t->speed_hz;
913915

914-
speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
915-
if (speed_hz < (OMAP2_MCSPI_MAX_FREQ / OMAP2_MCSPI_MAX_DIVIDER)) {
916-
clkd = omap2_mcspi_calc_divisor(speed_hz);
917-
speed_hz = OMAP2_MCSPI_MAX_FREQ >> clkd;
916+
ref_clk_hz = mcspi->ref_clk_hz;
917+
speed_hz = min_t(u32, speed_hz, ref_clk_hz);
918+
if (speed_hz < (ref_clk_hz / OMAP2_MCSPI_MAX_DIVIDER)) {
919+
clkd = omap2_mcspi_calc_divisor(speed_hz, ref_clk_hz);
920+
speed_hz = ref_clk_hz >> clkd;
918921
clkg = 0;
919922
} else {
920-
div = (OMAP2_MCSPI_MAX_FREQ + speed_hz - 1) / speed_hz;
921-
speed_hz = OMAP2_MCSPI_MAX_FREQ / div;
923+
div = (ref_clk_hz + speed_hz - 1) / speed_hz;
924+
speed_hz = ref_clk_hz / div;
922925
clkd = (div - 1) & 0xf;
923926
extclk = (div - 1) >> 4;
924927
clkg = OMAP2_MCSPI_CHCONF_CLKG;
@@ -1448,8 +1451,6 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
14481451
ctlr->cleanup = omap2_mcspi_cleanup;
14491452
ctlr->target_abort = omap2_mcspi_target_abort;
14501453
ctlr->dev.of_node = node;
1451-
ctlr->max_speed_hz = OMAP2_MCSPI_MAX_FREQ;
1452-
ctlr->min_speed_hz = OMAP2_MCSPI_MAX_FREQ >> 15;
14531454
ctlr->use_gpio_descriptors = true;
14541455

14551456
platform_set_drvdata(pdev, ctlr);
@@ -1519,6 +1520,14 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
15191520
goto free_ctlr;
15201521
}
15211522

1523+
mcspi->ref_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
1524+
if (mcspi->ref_clk)
1525+
mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk);
1526+
else
1527+
mcspi->ref_clk_hz = OMAP2_MCSPI_MAX_FREQ;
1528+
ctlr->max_speed_hz = mcspi->ref_clk_hz;
1529+
ctlr->min_speed_hz = mcspi->ref_clk_hz >> 15;
1530+
15221531
pm_runtime_use_autosuspend(&pdev->dev);
15231532
pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT);
15241533
pm_runtime_enable(&pdev->dev);

0 commit comments

Comments
 (0)