[PATCH v1 0/3] spi: Sync Kirkwood SPI driver with Marvell version

This patchset adds some Kirkwood SPI driver patches from the Marvell SDK. This is needed to resolve some issues with correct SPI NOR operation on the CN9132 DB board.
Thanks, Stefan
Grzegorz Jaszczyk (1): spi: kirkwood: prevent limiting speed to 0
Ken Ma (1): spi: kirkwood: support extended baud rates
Marcin Wojtas (1): spi: kirkwood: prevent configuring speed exceeding max controller freq
drivers/spi/kirkwood_spi.c | 67 +++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-)

From: Ken Ma make@marvell.com
The Armada SoC family implementation of this SPI hardware module has extended the configuration register to allow for a wider range of SPI clock rates. Specifically the Serial Baud Rate Pre-selection bits in the SPI Interface Configuration Register now also use bits 6 and 7 as well.
Modify the baud rate calculation to handle these differences for the Armada case. Potentially a baud rate can be setup using a number of different pre-scalar and scalar combinations. This code tries all possible pre-scalar divisors (8 in total) to try and find the most accurate set.
Signed-off-by: Ken Ma make@marvell.com Signed-off-by: Stefan Roese sr@denx.de ---
drivers/spi/kirkwood_spi.c | 60 ++++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 5 deletions(-)
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c index 43812da0ebb7..3dc62f351a06 100644 --- a/drivers/spi/kirkwood_spi.c +++ b/drivers/spi/kirkwood_spi.c @@ -111,12 +111,62 @@ static int mvebu_spi_set_speed(struct udevice *bus, uint hz) { struct mvebu_spi_plat *plat = dev_get_plat(bus); struct kwspi_registers *reg = plat->spireg; - u32 data; + u32 data, divider; + unsigned int spr, sppr; + + /* + * Calculate spi clock prescaller using max_hz. + * SPPR is SPI Baud Rate Pre-selection, it holds bits 5 and 7:6 in + * SPI Interface Configuration Register; + * SPR is SPI Baud Rate Selection, it holds bits 3:0 in SPI Interface + * Configuration Register. + * The SPR together with the SPPR define the SPI CLK frequency as + * follows: + * SPI actual frequency = core_clk / (SPR * (2 ^ SPPR)) + */ + divider = DIV_ROUND_UP(CONFIG_SYS_TCLK, hz); + if (divider < 16) { + /* This is the easy case, divider is less than 16 */ + spr = divider; + sppr = 0; + + } else { + unsigned int two_pow_sppr; + /* + * Find the highest bit set in divider. This and the + * three next bits define SPR (apart from rounding). + * SPPR is then the number of zero bits that must be + * appended: + */ + sppr = fls(divider) - 4; + + /* + * As SPR only has 4 bits, we have to round divider up + * to the next multiple of 2 ** sppr. + */ + two_pow_sppr = 1 << sppr; + divider = (divider + two_pow_sppr - 1) & -two_pow_sppr; + + /* + * recalculate sppr as rounding up divider might have + * increased it enough to change the position of the + * highest set bit. In this case the bit that now + * doesn't make it into SPR is 0, so there is no need to + * round again. + */ + sppr = fls(divider) - 4; + spr = divider >> sppr; + + /* + * Now do range checking. SPR is constructed to have a + * width of 4 bits, so this is fine for sure. So we + * still need to check for sppr to fit into 3 bits: + */ + if (sppr > 7) + return -EINVAL; + }
- /* calculate spi clock prescaller using max_hz */ - data = ((CONFIG_SYS_TCLK / 2) / hz) + 0x10; - data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data; - data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data; + data = ((sppr & 0x6) << 5) | ((sppr & 0x1) << 4) | spr;
/* program spi clock prescaler using max_hz */ writel(KWSPI_ADRLEN_3BYTE | data, ®->cfg);

From: Marcin Wojtas mw@semihalf.com
This patch adds a limitation in the kirkwood_spi driver set_speed hook, which prevents setting too high transfer speed.
Signed-off-by: Marcin Wojtas mw@semihalf.com Reviewed-by: Kostya Porotchkin kostap@marvell.com Tested-by: Kostya Porotchkin kostap@marvell.com Signed-off-by: Stefan Roese sr@denx.de ---
drivers/spi/kirkwood_spi.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c index 3dc62f351a06..063ed5f35a3a 100644 --- a/drivers/spi/kirkwood_spi.c +++ b/drivers/spi/kirkwood_spi.c @@ -110,10 +110,17 @@ static int _spi_xfer(struct kwspi_registers *reg, unsigned int bitlen, static int mvebu_spi_set_speed(struct udevice *bus, uint hz) { struct mvebu_spi_plat *plat = dev_get_plat(bus); + struct dm_spi_bus *spi = dev_get_uclass_priv(bus); struct kwspi_registers *reg = plat->spireg; u32 data, divider; unsigned int spr, sppr;
+ if (hz > spi->max_hz) { + debug("%s: limit speed to the max_hz of the bus %d\n", + __func__, spi->max_hz); + hz = spi->max_hz; + } + /* * Calculate spi clock prescaller using max_hz. * SPPR is SPI Baud Rate Pre-selection, it holds bits 5 and 7:6 in

From: Grzegorz Jaszczyk jaz@semihalf.com
After commit 1fe929ed497bcc8975be8d37383ebafd22b99dd2 ("spi: kirkwood: prevent configuring speed exceeding max controller freq") the spi frequency could be set to 0 on platform where spi-max-frequency is not defined (e.g. on armada-388-gp). Prevent limiting speed in mentioned cases.
Signed-off-by: Grzegorz Jaszczyk jaz@semihalf.com Tested-by: Kostya Porotchkin kostap@marvell.com Reviewed-by: Marcin Wojtas marcin@marvell.com Reviewed-by: Kostya Porotchkin kostap@marvell.com Signed-off-by: Stefan Roese sr@denx.de ---
drivers/spi/kirkwood_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c index 063ed5f35a3a..bc5da0a1e6e9 100644 --- a/drivers/spi/kirkwood_spi.c +++ b/drivers/spi/kirkwood_spi.c @@ -115,7 +115,7 @@ static int mvebu_spi_set_speed(struct udevice *bus, uint hz) u32 data, divider; unsigned int spr, sppr;
- if (hz > spi->max_hz) { + if (spi->max_hz && (hz > spi->max_hz)) { debug("%s: limit speed to the max_hz of the bus %d\n", __func__, spi->max_hz); hz = spi->max_hz;
participants (1)
-
Stefan Roese