[U-Boot] [PATCH] spi: kirkwood_spi: implement workaround for FE-9144572

Stefan Roese sr at denx.de
Sun Oct 15 07:53:48 UTC 2017


On 13.10.2017 03:05, Chris Packham wrote:
> Erratum NO. FE-9144572: The device SPI interface supports frequencies of
> up to 50 MHz.  However, due to this erratum, when the device core clock
> is 250 MHz and the SPI interfaces is configured for 50MHz SPI clock and
> CPOL=CPHA=1 there might occur data corruption on reads from the SPI
> device.
> 
> Implement the workaround by setting the TMISO_SAMPLE value to 0x2
> in the timing1 register.
> 
> Signed-off-by: Chris Packham <judge.packham at gmail.com>
> ---
> 
>   arch/arm/include/asm/arch-mvebu/spi.h |  6 ++++
>   drivers/spi/kirkwood_spi.c            | 62 +++++++++++++++++++++++++++++++++--
>   2 files changed, 65 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/arm/include/asm/arch-mvebu/spi.h b/arch/arm/include/asm/arch-mvebu/spi.h
> index 3545aed17347..1de510ea6da9 100644
> --- a/arch/arm/include/asm/arch-mvebu/spi.h
> +++ b/arch/arm/include/asm/arch-mvebu/spi.h
> @@ -57,6 +57,12 @@ struct kwspi_registers {
>   #define KWSPI_TXLSBF		(1 << 13)
>   #define KWSPI_RXLSBF		(1 << 14)
>   
> +/* Timing Parameters 1 Register */
> +#define KW_SPI_TMISO_SAMPLE_OFFSET	6
> +#define KW_SPI_TMISO_SAMPLE_MASK	(0x3 << KW_SPI_TMISO_SAMPLE_OFFSET)
> +#define KW_SPI_TMISO_SAMPLE_1		(1 << KW_SPI_TMISO_SAMPLE_OFFSET)
> +#define KW_SPI_TMISO_SAMPLE_2		(2 << KW_SPI_TMISO_SAMPLE_OFFSET)
> +
>   #define KWSPI_IRQUNMASK		1 /* unmask SPI interrupt */
>   #define KWSPI_IRQMASK		0 /* mask SPI interrupt */
>   #define KWSPI_SMEMRDIRQ		1 /* SerMem data xfer ready irq */
> diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c
> index 0c6bd295cde9..7992556d49eb 100644
> --- a/drivers/spi/kirkwood_spi.c
> +++ b/drivers/spi/kirkwood_spi.c
> @@ -243,6 +243,16 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>   
>   /* Here now the DM part */
>   
> +enum mvebu_spi_type {
> +	ORION_SPI,
> +	ARMADA_SPI,
> +};
> +
> +struct mvebu_spi_dev {
> +	enum mvebu_spi_type	typ;
> +	bool			is_errata_50mhz_ac;
> +};
> +
>   struct mvebu_spi_platdata {
>   	struct kwspi_registers *spireg;
>   };
> @@ -269,10 +279,30 @@ static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
>   	return 0;
>   }
>   
> +static void
> +mvebu_spi_50mhz_ac_timing_erratum(struct udevice *bus, uint mode)
> +{
> +	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
> +	struct kwspi_registers *reg = plat->spireg;
> +	u32 data = readl(&reg->timing1);
> +
> +	data &= ~KW_SPI_TMISO_SAMPLE_MASK;
> +
> +	if (CONFIG_SYS_TCLK == 250000000 &&
> +	    mode & SPI_CPOL &&
> +	    mode & SPI_CPHA)
> +		data |= KW_SPI_TMISO_SAMPLE_2;
> +	else
> +		data |= KW_SPI_TMISO_SAMPLE_1;
> +
> +	writel(data, &reg->timing1);
> +}
> +
>   static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
>   {
>   	struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
>   	struct kwspi_registers *reg = plat->spireg;
> +	const struct mvebu_spi_dev *drvdata;
>   	u32 data = readl(&reg->cfg);
>   
>   	data &= ~(KWSPI_CPHA | KWSPI_CPOL | KWSPI_RXLSBF | KWSPI_TXLSBF);
> @@ -286,6 +316,10 @@ static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
>   
>   	writel(data, &reg->cfg);
>   
> +	drvdata = (struct mvebu_spi_dev *)dev_get_driver_data(bus);
> +	if (drvdata->is_errata_50mhz_ac)
> +		mvebu_spi_50mhz_ac_timing_erratum(bus, mode);
> +
>   	return 0;
>   }
>   
> @@ -343,10 +377,32 @@ static const struct dm_spi_ops mvebu_spi_ops = {
>   	 */
>   };
>   
> +static const struct mvebu_spi_dev armada_xp_spi_dev_data = {
> +	.typ = ARMADA_SPI,
> +};
> +
> +static const struct mvebu_spi_dev armada_375_spi_dev_data = {
> +	.typ = ARMADA_SPI,
> +};
> +
> +static const struct mvebu_spi_dev armada_380_spi_dev_data = {
> +	.typ = ARMADA_SPI,
> +	.is_errata_50mhz_ac = true,
> +};
> +
>   static const struct udevice_id mvebu_spi_ids[] = {
> -	{ .compatible = "marvell,armada-375-spi" },
> -	{ .compatible = "marvell,armada-380-spi" },
> -	{ .compatible = "marvell,armada-xp-spi" },
> +	{
> +		.compatible = "marvell,armada-375-spi",
> +		.data = (ulong)&armada_375_spi_dev_data
> +	},
> +	{
> +		.compatible = "marvell,armada-380-spi",
> +		.data = (ulong)&armada_380_spi_dev_data
> +	},
> +	{
> +		.compatible = "marvell,armada-xp-spi",
> +		.data = (ulong)&armada_xp_spi_dev_data
> +	},
>   	{ }
>   };
>   
> 

Reviewed-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan


More information about the U-Boot mailing list