Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: orion: Fix maximum baud rates for Armada 370/XP

The commit df59fa7f4bca "spi: orion: support armada extended baud
rates" was too optimistic for the maximum baud rate that the Armada
SoCs can support. According to the hardware datasheet the maximum
frequency supported by the Armada 370 SoC is tclk/4. But for the
Armada XP, Armada 38x and Armada 39x SoCs the limitation is 50MHz and
for the Armada 375 it is tclk/15.

Currently the armada-370-spi compatible is only used by the Armada 370
and the Armada XP device tree. On Armada 370, tclk cannot be higher
than 200MHz. In order to be able to handle both SoCs, we can take the
minimum of 50MHz and tclk/4.

A proper solution is adding a compatible string for each SoC, but it
can't be done as a fix for compatibility reason (we can't modify
device tree that have been already released) and it will be part of a
separate patch.

Fixes: df59fa7f4bca (spi: orion: support armada extended baud rates)
Reported-by: Kostya Porotchkin <kostap@marvell.com>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: <stable@vger.kernel.org>

authored by

Gregory CLEMENT and committed by
Mark Brown
ce2f6ea1 b787f68c

+23 -2
+23 -2
drivers/spi/spi-orion.c
··· 61 61 62 62 struct orion_spi_dev { 63 63 enum orion_spi_type typ; 64 + /* 65 + * min_divisor and max_hz should be exclusive, the only we can 66 + * have both is for managing the armada-370-spi case with old 67 + * device tree 68 + */ 69 + unsigned long max_hz; 64 70 unsigned int min_divisor; 65 71 unsigned int max_divisor; 66 72 u32 prescale_mask; ··· 393 387 394 388 static const struct orion_spi_dev armada_spi_dev_data = { 395 389 .typ = ARMADA_SPI, 396 - .min_divisor = 1, 390 + .min_divisor = 4, 397 391 .max_divisor = 1920, 392 + .max_hz = 50000000, 398 393 .prescale_mask = ARMADA_SPI_CLK_PRESCALE_MASK, 399 394 }; 400 395 ··· 461 454 goto out; 462 455 463 456 tclk_hz = clk_get_rate(spi->clk); 464 - master->max_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->min_divisor); 457 + 458 + /* 459 + * With old device tree, armada-370-spi could be used with 460 + * Armada XP, however for this SoC the maximum frequency is 461 + * 50MHz instead of tclk/4. On Armada 370, tclk cannot be 462 + * higher than 200MHz. So, in order to be able to handle both 463 + * SoCs, we can take the minimum of 50MHz and tclk/4. 464 + */ 465 + if (of_device_is_compatible(pdev->dev.of_node, 466 + "marvell,armada-370-spi")) 467 + master->max_speed_hz = min(devdata->max_hz, 468 + DIV_ROUND_UP(tclk_hz, devdata->min_divisor)); 469 + else 470 + master->max_speed_hz = 471 + DIV_ROUND_UP(tclk_hz, devdata->min_divisor); 465 472 master->min_speed_hz = DIV_ROUND_UP(tclk_hz, devdata->max_divisor); 466 473 467 474 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);