diff mbox

[U-Boot] spi:ls102xqds:Support for compatibility for QSPI and DSPI modules drivers

Message ID 1411718199-27215-1-git-send-email-b44548@freescale.com
State Changes Requested
Delegated to: York Sun
Headers show

Commit Message

Chao Fu Sept. 26, 2014, 7:56 a.m. UTC
From: Chao Fu <B44548@freescale.com>

Useage:
For exmaple(ls1021 ls1021aqds):

	SPI bus defination can be find in
	arch/arm/include/asm/arch-ls102xa/config.h

	SPI_BUS_FSL_QSPI                                0
	SPI_BUS_FSL_DSPI1                               1
	SPI_BUS_FSL_DSPI2                               2

	and SPI devices info:
	AT45DB021 is on spi bus 1 cs 0
	S25FL064  is on spi bus 2 cs 0
	S25FL128S is on spi bus 0 cs 0

	Before using any SPI bus and SPI flash, execute sf probe bus:cs in uboot cmdline
	Such as use S25FL064, sf probe 2:0

Signed-off-by: Chao Fu <B44548@freescale.com>
---
 arch/arm/include/asm/arch-ls102xa/config.h |   5 +-
 board/freescale/ls1021aqds/ls1021aqds.c    |  33 ++++
 drivers/spi/Makefile                       |   1 +
 drivers/spi/fsl_dspi.c                     |  78 +++------
 drivers/spi/fsl_qspi.c                     |  35 ++--
 drivers/spi/fsl_spi_interface.c            | 267 +++++++++++++++++++++++++++++
 6 files changed, 339 insertions(+), 80 deletions(-)
 create mode 100644 drivers/spi/fsl_spi_interface.c

Comments

Andreas Färber Sept. 26, 2014, 5:58 p.m. UTC | #1
Hi,

Am 26.09.2014 um 09:56 schrieb Chao Fu:
> From: Chao Fu <B44548@freescale.com>
> 
> Useage:
> For exmaple(ls1021 ls1021aqds):
> 
> 	SPI bus defination can be find in
> 	arch/arm/include/asm/arch-ls102xa/config.h
> 
> 	SPI_BUS_FSL_QSPI                                0
> 	SPI_BUS_FSL_DSPI1                               1
> 	SPI_BUS_FSL_DSPI2                               2
> 
> 	and SPI devices info:
> 	AT45DB021 is on spi bus 1 cs 0
> 	S25FL064  is on spi bus 2 cs 0
> 	S25FL128S is on spi bus 0 cs 0
> 
> 	Before using any SPI bus and SPI flash, execute sf probe bus:cs in uboot cmdline
> 	Such as use S25FL064, sf probe 2:0

This could use some spellchecking... (usage, example, definition, found)

> 
> Signed-off-by: Chao Fu <B44548@freescale.com>
> ---
>  arch/arm/include/asm/arch-ls102xa/config.h |   5 +-
>  board/freescale/ls1021aqds/ls1021aqds.c    |  33 ++++
>  drivers/spi/Makefile                       |   1 +
>  drivers/spi/fsl_dspi.c                     |  78 +++------
>  drivers/spi/fsl_qspi.c                     |  35 ++--
>  drivers/spi/fsl_spi_interface.c            | 267 +++++++++++++++++++++++++++++
>  6 files changed, 339 insertions(+), 80 deletions(-)
>  create mode 100644 drivers/spi/fsl_spi_interface.c
[...]
> diff --git a/board/freescale/ls1021aqds/ls1021aqds.c b/board/freescale/ls1021aqds/ls1021aqds.c
> index 12e83f7..5db2126 100644
> --- a/board/freescale/ls1021aqds/ls1021aqds.c
> +++ b/board/freescale/ls1021aqds/ls1021aqds.c
> @@ -230,6 +230,39 @@ int board_init(void)
>  	return 0;
>  }
>  
> +int board_spi_find_bus(unsigned int bus, unsigned int cs)
> +{
> +	switch (bus) {
> +	case SPI_BUS_FSL_DSPI1:
> +	case SPI_BUS_FSL_DSPI2:
> +	case SPI_BUS_FSL_QSPI:
> +		break;
> +	default:
> +		return -1;
> +	}
> +
> +	switch (bus) {
> +	case SPI_BUS_FSL_DSPI1:
> +		if (cs == 0)
> +			return 0;
> +	case SPI_BUS_FSL_DSPI2:
> +		if (cs == 0)
> +			return 0;
> +	case SPI_BUS_FSL_QSPI:
> +		if (cs == 0)
> +			return 0;
> +	default:
> +		return -1;
> +	}
> +}
[snip]

This code is both redundant and potentially dangerous. In the cs != 0
case, it falls through to the next case label, where the same if is
being executed - no harm done, but someone might want to touch that code
in the future. Why not simply move a single if+return into the first switch?

Regards,
Andreas
Simon Glass Oct. 4, 2014, 2:46 a.m. UTC | #2
Hi,

On 26 September 2014 01:56, Chao Fu <b44548@freescale.com> wrote:
> From: Chao Fu <B44548@freescale.com>
>
> Useage:
> For exmaple(ls1021 ls1021aqds):
>
>         SPI bus defination can be find in
>         arch/arm/include/asm/arch-ls102xa/config.h
>
>         SPI_BUS_FSL_QSPI                                0
>         SPI_BUS_FSL_DSPI1                               1
>         SPI_BUS_FSL_DSPI2                               2
>
>         and SPI devices info:
>         AT45DB021 is on spi bus 1 cs 0
>         S25FL064  is on spi bus 2 cs 0
>         S25FL128S is on spi bus 0 cs 0
>
>         Before using any SPI bus and SPI flash, execute sf probe bus:cs in uboot cmdline
>         Such as use S25FL064, sf probe 2:0
>
> Signed-off-by: Chao Fu <B44548@freescale.com>
> ---
>  arch/arm/include/asm/arch-ls102xa/config.h |   5 +-
>  board/freescale/ls1021aqds/ls1021aqds.c    |  33 ++++
>  drivers/spi/Makefile                       |   1 +
>  drivers/spi/fsl_dspi.c                     |  78 +++------
>  drivers/spi/fsl_qspi.c                     |  35 ++--
>  drivers/spi/fsl_spi_interface.c            | 267 +++++++++++++++++++++++++++++
>  6 files changed, 339 insertions(+), 80 deletions(-)
>  create mode 100644 drivers/spi/fsl_spi_interface.c
>
> diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h
> index ed78c33..ccaf667 100644
> --- a/arch/arm/include/asm/arch-ls102xa/config.h
> +++ b/arch/arm/include/asm/arch-ls102xa/config.h
> @@ -42,7 +42,7 @@
>
>  #define WDOG1_BASE_ADDR                                (CONFIG_SYS_IMMR + 0x01ad0000)
>
> -#define QSPI0_BASE_ADDR                                (CONFIG_SYS_IMMR + 0x00550000)
> +#define QSPI_BASE_ADDR                         (CONFIG_SYS_IMMR + 0x00550000)
>  #define DSPI1_BASE_ADDR                                (CONFIG_SYS_IMMR + 0x01100000)
>
>  #define LPUART_BASE                            (CONFIG_SYS_IMMR + 0x01950000)
> @@ -63,6 +63,9 @@
>  #define CONFIG_SYS_FSL_QSPI_BE
>  #define CONFIG_SYS_FSL_DCU_BE
>
> +#define SPI_BUS_FSL_QSPI                               0
> +#define SPI_BUS_FSL_DSPI1                              1
> +
>  #define DCU_LAYER_MAX_NUM                      16
>
>  #define CONFIG_SYS_FSL_SRDS_1
> diff --git a/board/freescale/ls1021aqds/ls1021aqds.c b/board/freescale/ls1021aqds/ls1021aqds.c
> index 12e83f7..5db2126 100644
> --- a/board/freescale/ls1021aqds/ls1021aqds.c
> +++ b/board/freescale/ls1021aqds/ls1021aqds.c
> @@ -230,6 +230,39 @@ int board_init(void)
>         return 0;
>  }
>
> +int board_spi_find_bus(unsigned int bus, unsigned int cs)
> +{
> +       switch (bus) {
> +       case SPI_BUS_FSL_DSPI1:
> +       case SPI_BUS_FSL_DSPI2:
> +       case SPI_BUS_FSL_QSPI:
> +               break;
> +       default:
> +               return -1;
> +       }
> +
> +       switch (bus) {
> +       case SPI_BUS_FSL_DSPI1:
> +               if (cs == 0)
> +                       return 0;
> +       case SPI_BUS_FSL_DSPI2:
> +               if (cs == 0)
> +                       return 0;
> +       case SPI_BUS_FSL_QSPI:
> +               if (cs == 0)
> +                       return 0;
> +       default:
> +               return -1;
> +       }
> +}
> +
> +void board_print_spi_device(void)
> +{
> +       printf("LS1021aqds spi flash info:\n");
> +       printf("S25FL128S is on spi bus 0 cs 0\n");
> +       printf("AT45DB021 is on spi bus 1 cs 0\n");
> +}
> +
>  void ft_board_setup(void *blob, bd_t *bd)
>  {
>         ft_cpu_setup(blob, bd);
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index 6511263..82c3457 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -42,3 +42,4 @@ obj-$(CONFIG_TI_QSPI) += ti_qspi.o
>  obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
>  obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
>  obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
> +obj-$(CONFIG_FSL_SPI_INTERFACE) += fsl_spi_interface.o
> diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c
> index 72a5fa3..9d4133d 100644
> --- a/drivers/spi/fsl_dspi.c
> +++ b/drivers/spi/fsl_dspi.c
> @@ -40,6 +40,8 @@ struct dspi_slave {
>         int charbit;
>  };
>
> +unsigned long get_spi_bus_base(unsigned int bus);
> +
>  static inline struct dspi_slave *to_dspi_spi(struct spi_slave *slave)
>  {
>         return container_of(slave, struct dspi_slave, slave);
> @@ -125,22 +127,11 @@ int dspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
>
>         if (len) {
>                 if (dout != NULL) {
> -#ifdef CONFIG_LS102XA
> -                       if (flags == SPI_XFER_END)
> -                               ctrl |= DSPI_TFR_CONT;
> -#endif
>                         if (dspislave->charbit == 16)
>                                 dspi_tx(dspislave, ctrl, *spi_wr16);
>                         else
>                                 dspi_tx(dspislave, ctrl, *spi_wr);
>                         dspi_rx(dspislave);
> -#ifdef CONFIG_LS102XA
> -                       if (flags == SPI_XFER_END) {
> -                               ctrl &= ~DSPI_TFR_CONT;
> -                               dspi_tx(dspislave, ctrl, CONFIG_SPI_IDLE_VAL);
> -                               dspi_rx(dspislave);
> -                       }
> -#endif
>                 }
>
>                 if (din != NULL) {
> @@ -159,7 +150,8 @@ int dspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
>         return 0;
>  }
>
> -struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
> +struct spi_slave *dspi_setup_slave(unsigned int bus, unsigned int cs,
> +                               unsigned int max_hz, unsigned int mode)
>  {
>         /*
>          * bit definition for mode:
> @@ -174,6 +166,7 @@ struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
>          *     11 -  8: Delay after transfer scaler
>          *      7 -  0: SPI_CPHA, SPI_CPOL, SPI_LSB_FIRST
>          */
> +       struct dspi_slave *dspislave;
>         int prescaler[] = { 2, 3, 5, 7 };
>         int scaler[] = {
>                 2, 4, 6, 8,
> @@ -185,7 +178,12 @@ struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
>         int best_i, best_j, bestmatch = 0x7FFFFFFF, baud_speed, bus_clk;
>         u32 bus_setup = 0;
>
> -       dspislave->regs = (dspi_t *)MMAP_DSPI;
> +       dspislave = spi_alloc_slave(struct dspi_slave, bus, cs);
> +       if (!dspislave)
> +               return NULL;
> +
> +       dspislave->baudrate = max_hz;
> +       dspislave->regs = (struct dspi *)get_spi_bus_base(bus);
>
>  #if !defined(CONFIG_VF610) && !defined(CONFIG_LS102XA)
>         cfspi_port_conf();      /* port configuration */
> @@ -255,9 +253,9 @@ struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
>
>                 if ((mode & 0xF0000000) == 0)
>                         bus_setup |=
> -                       dspi_read32(&dspislave->regs->
> -                                       ctar[dspislave->slave.bus])
> -                       & 0x78000000;
> +                           dspi_read32(&dspislave->regs->
> +                               ctar[dspislave->slave.cs])
> +                           & 0x78000000;
>                 else
>                         bus_setup |= ((mode & 0xF0000000) >> 1);
>
> @@ -273,13 +271,13 @@ struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
>                 bus_setup |= (mode & 0x000FFF00) >> 4;  /* CSSCK, ASC, DT */
>         } else
>                 bus_setup |=
> -               dspi_read32(&dspislave->regs->ctar[dspislave->slave.bus])
> +                       dspi_read32(&dspislave->regs->ctar[dspislave->slave.cs])
>                         & 0x78FCFFF0;
>
>         dspislave->charbit =
> -           ((dspi_read32(&dspislave->regs->ctar[dspislave->slave.bus])
> -             & 0x78000000)
> -            == 0x78000000) ? 16 : 8;
> +           ((dspi_read32(&dspislave->regs->ctar[dspislave->slave.cs])
> +           & 0x78000000)
> +           == 0x78000000) ? 16 : 8;
>
>         pbrcnt = sizeof(prescaler) / sizeof(int);
>         brcnt = sizeof(scaler) / sizeof(int);
> @@ -304,21 +302,12 @@ struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
>         }
>
>         bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
> -       dspi_write32(&dspislave->regs->ctar[dspislave->slave.bus], bus_setup);
> +       dspi_write32(&dspislave->regs->ctar[dspislave->slave.cs], bus_setup);
>
>         return &dspislave->slave;
>  }
>  #endif                         /* CONFIG_FSL_DSPI */
>
> -#ifdef CONFIG_CMD_SPI
> -int spi_cs_is_valid(unsigned int bus, unsigned int cs)
> -{
> -       if (((cs >= 0) && (cs < 8)) && ((bus >= 0) && (bus < 8)))
> -               return 1;
> -       else
> -               return 0;
> -}
> -
>  void spi_init_f(void)
>  {
>  }
> @@ -327,32 +316,17 @@ void spi_init_r(void)
>  {
>  }
>
> -void spi_init(void)
> +void dspi_init(void)
>  {
>  }
>
> -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> -                                 unsigned int max_hz, unsigned int mode)
> -{
> -       struct dspi_slave *dspislave;
>
> -       if (!spi_cs_is_valid(bus, cs))
> -               return NULL;
> -       dspislave = spi_alloc_slave(struct dspi_slave, bus, cs);
> -       if (!dspislave)
> -               return NULL;
> -
> -       dspislave->baudrate = max_hz;
> -       /* specific setup */
> -       return dspi_setup_slave(dspislave, mode);
> -}
> -
> -void spi_free_slave(struct spi_slave *slave)
> +void dspi_free_slave(struct spi_slave *slave)
>  {
>         free(slave);
>  }
>
> -int spi_claim_bus(struct spi_slave *slave)
> +int dspi_claim_bus(struct spi_slave *slave)
>  {
>  #if defined(CONFIG_VF610) || defined(CONFIG_LS102XA)
>         return 0;
> @@ -361,16 +335,10 @@ int spi_claim_bus(struct spi_slave *slave)
>  #endif
>  }
>
> -void spi_release_bus(struct spi_slave *slave)
> +void dspi_release_bus(struct spi_slave *slave)
>  {
>  #if !defined(CONFIG_VF610) && !defined(CONFIG_LS102XA)
>         cfspi_release_bus(slave->bus, slave->cs);
>  #endif
>  }
>
> -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
> -            void *din, unsigned long flags)
> -{
> -       return dspi_xfer(slave, bitlen, dout, din, flags);
> -}
> -#endif                         /* CONFIG_CMD_SPI */
> diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
> index ba20bef..0957bac 100644
> --- a/drivers/spi/fsl_qspi.c
> +++ b/drivers/spi/fsl_qspi.c
> @@ -9,7 +9,7 @@
>  #include <common.h>
>  #include <malloc.h>
>  #include <spi.h>
> -#include <asm/io.h>
> +#include <linux/io.h>
>  #include <linux/sizes.h>
>  #include "fsl_qspi.h"
>
> @@ -51,14 +51,6 @@
>  #define qspi_write32           out_be32
>  #endif
>
> -static unsigned long spi_bases[] = {
> -       QSPI0_BASE_ADDR,
> -};
> -
> -static unsigned long amba_bases[] = {
> -       QSPI0_AMBA_BASE,
> -};
> -
>  struct fsl_qspi {
>         struct spi_slave slave;
>         unsigned long reg_base;
> @@ -67,6 +59,9 @@ struct fsl_qspi {
>         u8 cur_seqid;
>  };
>
> +unsigned long get_spi_bus_base(unsigned int bus);
> +unsigned long get_qspi_amba_base(unsigned int bus);
> +
>  /* QSPI support swapping the flash read/write data
>   * in hardware for LS102xA, but not for VF610 */
>  static inline u32 qspi_endian_xchg(u32 data)
> @@ -176,12 +171,7 @@ static void qspi_set_lut(struct fsl_qspi *qspi)
>         qspi_write32(&regs->lckcr, QSPI_LCKCR_LOCK);
>  }
>
> -void spi_init()
> -{
> -       /* do nothing */
> -}
> -
> -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> +struct spi_slave *qspi_setup_slave(unsigned int bus, unsigned int cs,
>                 unsigned int max_hz, unsigned int mode)
>  {
>         struct fsl_qspi *qspi;
> @@ -189,15 +179,12 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
>         u32 reg_val, smpr_val;
>         u32 total_size, seq_id;
>
> -       if (bus >= ARRAY_SIZE(spi_bases))
> -               return NULL;
> -
>         qspi = spi_alloc_slave(struct fsl_qspi, bus, cs);
>         if (!qspi)
>                 return NULL;
>
> -       qspi->reg_base = spi_bases[bus];
> -       qspi->amba_base = amba_bases[bus];
> +       qspi->reg_base = get_spi_bus_base(bus);
> +       qspi->amba_base = get_qspi_amba_base(bus);
>
>         qspi->slave.max_write_size = TX_BUFFER_SIZE;
>
> @@ -232,14 +219,14 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
>         return &qspi->slave;
>  }
>
> -void spi_free_slave(struct spi_slave *slave)
> +void qspi_free_slave(struct spi_slave *slave)
>  {
>         struct fsl_qspi *qspi = to_qspi_spi(slave);
>
>         free(qspi);
>  }
>
> -int spi_claim_bus(struct spi_slave *slave)
> +int qspi_claim_bus(struct spi_slave *slave)
>  {
>         return 0;
>  }
> @@ -436,7 +423,7 @@ static void qspi_op_se(struct fsl_qspi *qspi)
>         qspi_write32(&regs->mcr, mcr_reg);
>  }
>
> -int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> +int qspi_xfer(struct spi_slave *slave, unsigned int bitlen,
>                 const void *dout, void *din, unsigned long flags)
>  {
>         struct fsl_qspi *qspi = to_qspi_spi(slave);
> @@ -476,7 +463,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>         return 0;
>  }
>
> -void spi_release_bus(struct spi_slave *slave)
> +void qspi_release_bus(struct spi_slave *slave)
>  {
>         /* Nothing to do */
>  }
> diff --git a/drivers/spi/fsl_spi_interface.c b/drivers/spi/fsl_spi_interface.c
> new file mode 100644
> index 0000000..1f17ef0
> --- /dev/null
> +++ b/drivers/spi/fsl_spi_interface.c
> @@ -0,0 +1,267 @@
> +/*
> + * Copyright 2014 Freescale Semiconductor, Inc.
> + *
> + * Freescale Muti Serial Peripheral Interface (QSPI and DSPI) driver support
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <malloc.h>
> +#include <spi.h>
> +#include <linux/io.h>
> +#include <linux/errno.h>
> +
> +void dspi_init(void);
> +int dspi_claim_bus(struct spi_slave *slave);
> +int dspi_release_bus(struct spi_slave *slave);
> +int dspi_cs_is_valid(unsigned int bus, unsigned int cs);
> +struct spi_slave *dspi_setup_slave(unsigned int bus, unsigned int cs,
> +                               unsigned int max_hz, unsigned int mode);
> +void dspi_free_slave(struct spi_slave *slave);
> +void dspi_cs_activate(struct spi_slave *slave);
> +void dspi_cs_deactivate(struct spi_slave *slave);
> +int dspi_xfer(struct spi_slave *slave, unsigned int bitlen,
> +           const void *data_out, void *data_in, unsigned long flags);
> +void qspi_init(void);
> +int qspi_claim_bus(struct spi_slave *slave);
> +int qspi_release_bus(struct spi_slave *slave);
> +int qspi_cs_is_valid(unsigned int bus, unsigned int cs);
> +struct spi_slave *qspi_setup_slave(unsigned int bus, unsigned int cs,
> +                               unsigned int max_hz, unsigned int mode);
> +void qspi_free_slave(struct spi_slave *slave);
> +void qspi_cs_activate(struct spi_slave *slave);
> +void qspi_cs_deactivate(struct spi_slave *slave);
> +int qspi_xfer(struct spi_slave *slave, unsigned int bitlen,
> +           const void *data_out, void *data_in, unsigned long flags);
> +
> +void board_print_spi_device(void);
> +int board_spi_find_bus(unsigned int bus, unsigned int cs);
> +
> +struct fsl_spi_driver {
> +       void (*init)(void);
> +       int (*claim_bus)(struct spi_slave *slave);
> +       int (*release_bus)(struct spi_slave *slave);
> +       int (*cs_is_valid)(unsigned int bus, unsigned int cs);
> +       struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs,
> +                                       unsigned int max_hz, unsigned int mode);
> +       void (*free_slave)(struct spi_slave *slave);
> +       void (*cs_activate)(struct spi_slave *slave);
> +       void (*cs_deactivate)(struct spi_slave *slave);
> +       int (*xfer)(struct spi_slave *slave, unsigned int bitlen,
> +                   const void *data_out, void *data_in, unsigned long flags);
> +};

This is duplicating the SPI uclass used by driver model. Please take a
look at u-boot-dm.git branch spi-working. If you use driver model you
can avoid this.

> +
> +static struct fsl_spi_driver fsl_spi_drivers[] = {
> +#ifdef CONFIG_FSL_DSPI
> +       {
> +               .init           = dspi_init,
> +               .claim_bus      = dspi_claim_bus,
> +               .cs_is_valid    = NULL,
> +               .setup_slave    = dspi_setup_slave,
> +               .free_slave     = dspi_free_slave,
> +               .cs_activate    = NULL,
> +               .cs_deactivate  = NULL,
> +               .xfer           = dspi_xfer,
> +       },
> +#endif
> +#ifdef CONFIG_FSL_QSPI
> +       {
> +               .init           = NULL,
> +               .claim_bus      = qspi_claim_bus,
> +               .cs_is_valid    = NULL,
> +               .setup_slave    = qspi_setup_slave,
> +               .free_slave     = qspi_free_slave,
> +               .cs_activate    = NULL,
> +               .cs_deactivate  = NULL,
> +               .xfer           = qspi_xfer,
> +       },
> +#endif
> +};
> +
> +enum fsl_spi_driver_sel {
> +#ifdef CONFIG_FSL_DSPI
> +       DSPI_DRIVER,
> +#endif
> +#ifdef CONFIG_FSL_QSPI
> +       QSPI_DRIVER,
> +#endif
> +};
> +
> +struct fsl_spi_driver *find_fsl_spi_driver(unsigned int bus, unsigned int cs)
> +{
> +       unsigned int driver_sel;
> +
> +       if (board_spi_find_bus(bus, cs)) {
> +               board_print_spi_device();
> +               printf("can't find device on bus %d cs %d in board.\n",
> +                                                               bus, cs);
> +               return NULL;
> +       }
> +
> +       switch (bus) {
> +#ifdef SPI_BUS_FSL_DSPI1
> +       case SPI_BUS_FSL_DSPI1:
> +#endif
> +#ifdef SPI_BUS_FSL_DSPI2
> +       case SPI_BUS_FSL_DSPI2:
> +#endif
> +#ifdef SPI_BUS_FSL_DSPI3
> +       case SPI_BUS_FSL_DSPI3:
> +#endif
> +#ifdef SPI_BUS_FSL_DSPI4
> +       case SPI_BUS_FSL_DSPI4:
> +#endif
> +               driver_sel = DSPI_DRIVER;
> +               break;
> +#ifdef SPI_BUS_FSL_QSPI
> +       case SPI_BUS_FSL_QSPI:
> +#endif
> +#ifdef SPI_BUS_FSL_QSPI2
> +       case SPI_BUS_FSL_QSPI2:
> +#endif
> +               driver_sel = QSPI_DRIVER;
> +               break;
> +       default:
> +               return NULL;
> +       }
> +
> +       return &fsl_spi_drivers[driver_sel];
> +}
> +
> +unsigned long get_spi_bus_base(unsigned int bus)
> +{
> +       switch (bus) {
> +#ifdef SPI_BUS_FSL_DSPI1
> +       case SPI_BUS_FSL_DSPI1:
> +               return DSPI1_BASE_ADDR;
> +#endif
> +#ifdef SPI_BUS_FSL_DSPI2
> +       case SPI_BUS_FSL_DSPI2:
> +               return DSPI2_BASE_ADDR;
> +#endif
> +#ifdef SPI_BUS_FSL_DSPI3
> +       case SPI_BUS_FSL_DSPI3:
> +               return DSPI3_BASE_ADDR;
> +#endif
> +#ifdef SPI_BUS_FSL_DSPI4
> +       case SPI_BUS_FSL_DSPI4:
> +               return DSPI4_BASE_ADDR;
> +#endif
> +#ifdef SPI_BUS_FSL_QSPI
> +       case SPI_BUS_FSL_QSPI:
> +               return QSPI_BASE_ADDR;
> +#endif
> +#ifdef SPI_BUS_FSL_QSPI2
> +       case SPI_BUS_FSL_QSPI2:
> +               return QSPI2_BASE_ADDR;
> +#endif
> +       default:
> +               printf("FSL SPL:get bus base error %d", bus);
> +               return 0;
> +       }
> +}
> +
> +unsigned long get_qspi_amba_base(unsigned int bus)
> +{
> +       switch (bus) {
> +#ifdef SPI_BUS_FSL_QSPI
> +       case SPI_BUS_FSL_QSPI:
> +               return QSPI_AMBA_BASE;
> +#endif
> +#ifdef SPI_BUS_FSL_QSPI2
> +       case SPI_BUS_FSL_QSPI2:
> +               return QSPI2_AMBA_BASE;
> +#endif
> +       default:
> +               printf("FSL SPL:get qspi amba bus base error %d", bus);
> +               return 0;
> +       }
> +
> +       return 0;
> +}
> +
> +void spi_init()
> +{
> +       int i;
> +       struct fsl_spi_driver *driver;
> +
> +       for (i = 0; i < ARRAY_SIZE(fsl_spi_drivers); i++) {
> +               driver = &fsl_spi_drivers[i];
> +               if (driver && driver->init)
> +                       driver->init();
> +       }
> +}
> +
> +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
> +               unsigned int max_hz, unsigned int mode)
> +{
> +       struct fsl_spi_driver *driver = find_fsl_spi_driver(bus, cs);
> +
> +       if (!driver || !driver->setup_slave)
> +               return NULL;
> +
> +       return driver->setup_slave(bus, cs, max_hz, mode);
> +}
> +
> +int spi_claim_bus(struct spi_slave *slave)
> +{
> +       struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
> +                                                               slave->cs);
> +
> +       if (!driver)
> +               return 1;
> +       if (!driver->claim_bus)
> +               return 0;
> +
> +       return driver->claim_bus(slave);
> +}
> +
> +void spi_free_slave(struct spi_slave *slave)
> +{
> +       struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
> +                                                               slave->cs);
> +
> +       if (driver && driver->free_slave)
> +               return driver->free_slave(slave);
> +}
> +
> +int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> +               const void *dout, void *din, unsigned long flags)
> +{
> +       struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
> +                                                               slave->cs);
> +
> +       if (!driver || !driver->xfer)
> +               return -1;
> +
> +       return driver->xfer(slave, bitlen, dout, din, flags);
> +}
> +
> +void spi_release_bus(struct spi_slave *slave)
> +{
> +       struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
> +                                                               slave->cs);
> +
> +       if (driver && driver->release_bus)
> +               driver->release_bus(slave);
> +}
> +
> +
> +void spi_cs_activate(struct spi_slave *slave)
> +{
> +       struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
> +                                                               slave->cs);
> +
> +       if (driver && driver->cs_activate)
> +               driver->cs_activate(slave);
> +}
> +
> +void spi_cs_deactivate(struct spi_slave *slave)
> +{
> +       struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
> +                                                               slave->cs);
> +
> +       if (driver && driver->cs_deactivate)
> +               driver->cs_deactivate(slave);
> +}

This really is crying out for conversion to driver model.

Regards,
Simon
diff mbox

Patch

diff --git a/arch/arm/include/asm/arch-ls102xa/config.h b/arch/arm/include/asm/arch-ls102xa/config.h
index ed78c33..ccaf667 100644
--- a/arch/arm/include/asm/arch-ls102xa/config.h
+++ b/arch/arm/include/asm/arch-ls102xa/config.h
@@ -42,7 +42,7 @@ 
 
 #define WDOG1_BASE_ADDR				(CONFIG_SYS_IMMR + 0x01ad0000)
 
-#define QSPI0_BASE_ADDR				(CONFIG_SYS_IMMR + 0x00550000)
+#define QSPI_BASE_ADDR				(CONFIG_SYS_IMMR + 0x00550000)
 #define DSPI1_BASE_ADDR				(CONFIG_SYS_IMMR + 0x01100000)
 
 #define LPUART_BASE				(CONFIG_SYS_IMMR + 0x01950000)
@@ -63,6 +63,9 @@ 
 #define CONFIG_SYS_FSL_QSPI_BE
 #define CONFIG_SYS_FSL_DCU_BE
 
+#define SPI_BUS_FSL_QSPI                               0
+#define SPI_BUS_FSL_DSPI1                              1
+
 #define DCU_LAYER_MAX_NUM			16
 
 #define CONFIG_SYS_FSL_SRDS_1
diff --git a/board/freescale/ls1021aqds/ls1021aqds.c b/board/freescale/ls1021aqds/ls1021aqds.c
index 12e83f7..5db2126 100644
--- a/board/freescale/ls1021aqds/ls1021aqds.c
+++ b/board/freescale/ls1021aqds/ls1021aqds.c
@@ -230,6 +230,39 @@  int board_init(void)
 	return 0;
 }
 
+int board_spi_find_bus(unsigned int bus, unsigned int cs)
+{
+	switch (bus) {
+	case SPI_BUS_FSL_DSPI1:
+	case SPI_BUS_FSL_DSPI2:
+	case SPI_BUS_FSL_QSPI:
+		break;
+	default:
+		return -1;
+	}
+
+	switch (bus) {
+	case SPI_BUS_FSL_DSPI1:
+		if (cs == 0)
+			return 0;
+	case SPI_BUS_FSL_DSPI2:
+		if (cs == 0)
+			return 0;
+	case SPI_BUS_FSL_QSPI:
+		if (cs == 0)
+			return 0;
+	default:
+		return -1;
+	}
+}
+
+void board_print_spi_device(void)
+{
+	printf("LS1021aqds spi flash info:\n");
+	printf("S25FL128S is on spi bus 0 cs 0\n");
+	printf("AT45DB021 is on spi bus 1 cs 0\n");
+}
+
 void ft_board_setup(void *blob, bd_t *bd)
 {
 	ft_cpu_setup(blob, bd);
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 6511263..82c3457 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -42,3 +42,4 @@  obj-$(CONFIG_TI_QSPI) += ti_qspi.o
 obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
 obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
 obj-$(CONFIG_FSL_QSPI) += fsl_qspi.o
+obj-$(CONFIG_FSL_SPI_INTERFACE) += fsl_spi_interface.o
diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c
index 72a5fa3..9d4133d 100644
--- a/drivers/spi/fsl_dspi.c
+++ b/drivers/spi/fsl_dspi.c
@@ -40,6 +40,8 @@  struct dspi_slave {
 	int charbit;
 };
 
+unsigned long get_spi_bus_base(unsigned int bus);
+
 static inline struct dspi_slave *to_dspi_spi(struct spi_slave *slave)
 {
 	return container_of(slave, struct dspi_slave, slave);
@@ -125,22 +127,11 @@  int dspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
 
 	if (len) {
 		if (dout != NULL) {
-#ifdef CONFIG_LS102XA
-			if (flags == SPI_XFER_END)
-				ctrl |= DSPI_TFR_CONT;
-#endif
 			if (dspislave->charbit == 16)
 				dspi_tx(dspislave, ctrl, *spi_wr16);
 			else
 				dspi_tx(dspislave, ctrl, *spi_wr);
 			dspi_rx(dspislave);
-#ifdef CONFIG_LS102XA
-			if (flags == SPI_XFER_END) {
-				ctrl &= ~DSPI_TFR_CONT;
-				dspi_tx(dspislave, ctrl, CONFIG_SPI_IDLE_VAL);
-				dspi_rx(dspislave);
-			}
-#endif
 		}
 
 		if (din != NULL) {
@@ -159,7 +150,8 @@  int dspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
 	return 0;
 }
 
-struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
+struct spi_slave *dspi_setup_slave(unsigned int bus, unsigned int cs,
+				unsigned int max_hz, unsigned int mode)
 {
 	/*
 	 * bit definition for mode:
@@ -174,6 +166,7 @@  struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
 	 *     11 -  8: Delay after transfer scaler
 	 *      7 -  0: SPI_CPHA, SPI_CPOL, SPI_LSB_FIRST
 	 */
+	struct dspi_slave *dspislave;
 	int prescaler[] = { 2, 3, 5, 7 };
 	int scaler[] = {
 		2, 4, 6, 8,
@@ -185,7 +178,12 @@  struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
 	int best_i, best_j, bestmatch = 0x7FFFFFFF, baud_speed, bus_clk;
 	u32 bus_setup = 0;
 
-	dspislave->regs = (dspi_t *)MMAP_DSPI;
+	dspislave = spi_alloc_slave(struct dspi_slave, bus, cs);
+	if (!dspislave)
+		return NULL;
+
+	dspislave->baudrate = max_hz;
+	dspislave->regs = (struct dspi *)get_spi_bus_base(bus);
 
 #if !defined(CONFIG_VF610) && !defined(CONFIG_LS102XA)
 	cfspi_port_conf();	/* port configuration */
@@ -255,9 +253,9 @@  struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
 
 		if ((mode & 0xF0000000) == 0)
 			bus_setup |=
-			dspi_read32(&dspislave->regs->
-					ctar[dspislave->slave.bus])
-			& 0x78000000;
+			    dspi_read32(&dspislave->regs->
+				ctar[dspislave->slave.cs])
+			    & 0x78000000;
 		else
 			bus_setup |= ((mode & 0xF0000000) >> 1);
 
@@ -273,13 +271,13 @@  struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
 		bus_setup |= (mode & 0x000FFF00) >> 4;	/* CSSCK, ASC, DT */
 	} else
 		bus_setup |=
-		dspi_read32(&dspislave->regs->ctar[dspislave->slave.bus])
+			dspi_read32(&dspislave->regs->ctar[dspislave->slave.cs])
 			& 0x78FCFFF0;
 
 	dspislave->charbit =
-	    ((dspi_read32(&dspislave->regs->ctar[dspislave->slave.bus])
-	      & 0x78000000)
-	     == 0x78000000) ? 16 : 8;
+	    ((dspi_read32(&dspislave->regs->ctar[dspislave->slave.cs])
+	    & 0x78000000)
+	    == 0x78000000) ? 16 : 8;
 
 	pbrcnt = sizeof(prescaler) / sizeof(int);
 	brcnt = sizeof(scaler) / sizeof(int);
@@ -304,21 +302,12 @@  struct spi_slave *dspi_setup_slave(struct dspi_slave *dspislave, uint mode)
 	}
 
 	bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
-	dspi_write32(&dspislave->regs->ctar[dspislave->slave.bus], bus_setup);
+	dspi_write32(&dspislave->regs->ctar[dspislave->slave.cs], bus_setup);
 
 	return &dspislave->slave;
 }
 #endif				/* CONFIG_FSL_DSPI */
 
-#ifdef CONFIG_CMD_SPI
-int spi_cs_is_valid(unsigned int bus, unsigned int cs)
-{
-	if (((cs >= 0) && (cs < 8)) && ((bus >= 0) && (bus < 8)))
-		return 1;
-	else
-		return 0;
-}
-
 void spi_init_f(void)
 {
 }
@@ -327,32 +316,17 @@  void spi_init_r(void)
 {
 }
 
-void spi_init(void)
+void dspi_init(void)
 {
 }
 
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
-				  unsigned int max_hz, unsigned int mode)
-{
-	struct dspi_slave *dspislave;
 
-	if (!spi_cs_is_valid(bus, cs))
-		return NULL;
-	dspislave = spi_alloc_slave(struct dspi_slave, bus, cs);
-	if (!dspislave)
-		return NULL;
-
-	dspislave->baudrate = max_hz;
-	/* specific setup */
-	return dspi_setup_slave(dspislave, mode);
-}
-
-void spi_free_slave(struct spi_slave *slave)
+void dspi_free_slave(struct spi_slave *slave)
 {
 	free(slave);
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+int dspi_claim_bus(struct spi_slave *slave)
 {
 #if defined(CONFIG_VF610) || defined(CONFIG_LS102XA)
 	return 0;
@@ -361,16 +335,10 @@  int spi_claim_bus(struct spi_slave *slave)
 #endif
 }
 
-void spi_release_bus(struct spi_slave *slave)
+void dspi_release_bus(struct spi_slave *slave)
 {
 #if !defined(CONFIG_VF610) && !defined(CONFIG_LS102XA)
 	cfspi_release_bus(slave->bus, slave->cs);
 #endif
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
-	     void *din, unsigned long flags)
-{
-	return dspi_xfer(slave, bitlen, dout, din, flags);
-}
-#endif				/* CONFIG_CMD_SPI */
diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c
index ba20bef..0957bac 100644
--- a/drivers/spi/fsl_qspi.c
+++ b/drivers/spi/fsl_qspi.c
@@ -9,7 +9,7 @@ 
 #include <common.h>
 #include <malloc.h>
 #include <spi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/sizes.h>
 #include "fsl_qspi.h"
 
@@ -51,14 +51,6 @@ 
 #define qspi_write32		out_be32
 #endif
 
-static unsigned long spi_bases[] = {
-	QSPI0_BASE_ADDR,
-};
-
-static unsigned long amba_bases[] = {
-	QSPI0_AMBA_BASE,
-};
-
 struct fsl_qspi {
 	struct spi_slave slave;
 	unsigned long reg_base;
@@ -67,6 +59,9 @@  struct fsl_qspi {
 	u8 cur_seqid;
 };
 
+unsigned long get_spi_bus_base(unsigned int bus);
+unsigned long get_qspi_amba_base(unsigned int bus);
+
 /* QSPI support swapping the flash read/write data
  * in hardware for LS102xA, but not for VF610 */
 static inline u32 qspi_endian_xchg(u32 data)
@@ -176,12 +171,7 @@  static void qspi_set_lut(struct fsl_qspi *qspi)
 	qspi_write32(&regs->lckcr, QSPI_LCKCR_LOCK);
 }
 
-void spi_init()
-{
-	/* do nothing */
-}
-
-struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+struct spi_slave *qspi_setup_slave(unsigned int bus, unsigned int cs,
 		unsigned int max_hz, unsigned int mode)
 {
 	struct fsl_qspi *qspi;
@@ -189,15 +179,12 @@  struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	u32 reg_val, smpr_val;
 	u32 total_size, seq_id;
 
-	if (bus >= ARRAY_SIZE(spi_bases))
-		return NULL;
-
 	qspi = spi_alloc_slave(struct fsl_qspi, bus, cs);
 	if (!qspi)
 		return NULL;
 
-	qspi->reg_base = spi_bases[bus];
-	qspi->amba_base = amba_bases[bus];
+	qspi->reg_base = get_spi_bus_base(bus);
+	qspi->amba_base = get_qspi_amba_base(bus);
 
 	qspi->slave.max_write_size = TX_BUFFER_SIZE;
 
@@ -232,14 +219,14 @@  struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 	return &qspi->slave;
 }
 
-void spi_free_slave(struct spi_slave *slave)
+void qspi_free_slave(struct spi_slave *slave)
 {
 	struct fsl_qspi *qspi = to_qspi_spi(slave);
 
 	free(qspi);
 }
 
-int spi_claim_bus(struct spi_slave *slave)
+int qspi_claim_bus(struct spi_slave *slave)
 {
 	return 0;
 }
@@ -436,7 +423,7 @@  static void qspi_op_se(struct fsl_qspi *qspi)
 	qspi_write32(&regs->mcr, mcr_reg);
 }
 
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+int qspi_xfer(struct spi_slave *slave, unsigned int bitlen,
 		const void *dout, void *din, unsigned long flags)
 {
 	struct fsl_qspi *qspi = to_qspi_spi(slave);
@@ -476,7 +463,7 @@  int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 	return 0;
 }
 
-void spi_release_bus(struct spi_slave *slave)
+void qspi_release_bus(struct spi_slave *slave)
 {
 	/* Nothing to do */
 }
diff --git a/drivers/spi/fsl_spi_interface.c b/drivers/spi/fsl_spi_interface.c
new file mode 100644
index 0000000..1f17ef0
--- /dev/null
+++ b/drivers/spi/fsl_spi_interface.c
@@ -0,0 +1,267 @@ 
+/*
+ * Copyright 2014 Freescale Semiconductor, Inc.
+ *
+ * Freescale Muti Serial Peripheral Interface (QSPI and DSPI) driver support
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+
+void dspi_init(void);
+int dspi_claim_bus(struct spi_slave *slave);
+int dspi_release_bus(struct spi_slave *slave);
+int dspi_cs_is_valid(unsigned int bus, unsigned int cs);
+struct spi_slave *dspi_setup_slave(unsigned int bus, unsigned int cs,
+				unsigned int max_hz, unsigned int mode);
+void dspi_free_slave(struct spi_slave *slave);
+void dspi_cs_activate(struct spi_slave *slave);
+void dspi_cs_deactivate(struct spi_slave *slave);
+int dspi_xfer(struct spi_slave *slave, unsigned int bitlen,
+	    const void *data_out, void *data_in, unsigned long flags);
+void qspi_init(void);
+int qspi_claim_bus(struct spi_slave *slave);
+int qspi_release_bus(struct spi_slave *slave);
+int qspi_cs_is_valid(unsigned int bus, unsigned int cs);
+struct spi_slave *qspi_setup_slave(unsigned int bus, unsigned int cs,
+				unsigned int max_hz, unsigned int mode);
+void qspi_free_slave(struct spi_slave *slave);
+void qspi_cs_activate(struct spi_slave *slave);
+void qspi_cs_deactivate(struct spi_slave *slave);
+int qspi_xfer(struct spi_slave *slave, unsigned int bitlen,
+	    const void *data_out, void *data_in, unsigned long flags);
+
+void board_print_spi_device(void);
+int board_spi_find_bus(unsigned int bus, unsigned int cs);
+
+struct fsl_spi_driver {
+	void (*init)(void);
+	int (*claim_bus)(struct spi_slave *slave);
+	int (*release_bus)(struct spi_slave *slave);
+	int (*cs_is_valid)(unsigned int bus, unsigned int cs);
+	struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs,
+					unsigned int max_hz, unsigned int mode);
+	void (*free_slave)(struct spi_slave *slave);
+	void (*cs_activate)(struct spi_slave *slave);
+	void (*cs_deactivate)(struct spi_slave *slave);
+	int (*xfer)(struct spi_slave *slave, unsigned int bitlen,
+		    const void *data_out, void *data_in, unsigned long flags);
+};
+
+static struct fsl_spi_driver fsl_spi_drivers[] = {
+#ifdef CONFIG_FSL_DSPI
+	{
+		.init		= dspi_init,
+		.claim_bus	= dspi_claim_bus,
+		.cs_is_valid	= NULL,
+		.setup_slave	= dspi_setup_slave,
+		.free_slave	= dspi_free_slave,
+		.cs_activate	= NULL,
+		.cs_deactivate	= NULL,
+		.xfer		= dspi_xfer,
+	},
+#endif
+#ifdef CONFIG_FSL_QSPI
+	{
+		.init		= NULL,
+		.claim_bus	= qspi_claim_bus,
+		.cs_is_valid	= NULL,
+		.setup_slave	= qspi_setup_slave,
+		.free_slave	= qspi_free_slave,
+		.cs_activate	= NULL,
+		.cs_deactivate	= NULL,
+		.xfer		= qspi_xfer,
+	},
+#endif
+};
+
+enum fsl_spi_driver_sel {
+#ifdef CONFIG_FSL_DSPI
+	DSPI_DRIVER,
+#endif
+#ifdef CONFIG_FSL_QSPI
+	QSPI_DRIVER,
+#endif
+};
+
+struct fsl_spi_driver *find_fsl_spi_driver(unsigned int bus, unsigned int cs)
+{
+	unsigned int driver_sel;
+
+	if (board_spi_find_bus(bus, cs)) {
+		board_print_spi_device();
+		printf("can't find device on bus %d cs %d in board.\n",
+								bus, cs);
+		return NULL;
+	}
+
+	switch (bus) {
+#ifdef SPI_BUS_FSL_DSPI1
+	case SPI_BUS_FSL_DSPI1:
+#endif
+#ifdef SPI_BUS_FSL_DSPI2
+	case SPI_BUS_FSL_DSPI2:
+#endif
+#ifdef SPI_BUS_FSL_DSPI3
+	case SPI_BUS_FSL_DSPI3:
+#endif
+#ifdef SPI_BUS_FSL_DSPI4
+	case SPI_BUS_FSL_DSPI4:
+#endif
+		driver_sel = DSPI_DRIVER;
+		break;
+#ifdef SPI_BUS_FSL_QSPI
+	case SPI_BUS_FSL_QSPI:
+#endif
+#ifdef SPI_BUS_FSL_QSPI2
+	case SPI_BUS_FSL_QSPI2:
+#endif
+		driver_sel = QSPI_DRIVER;
+		break;
+	default:
+		return NULL;
+	}
+
+	return &fsl_spi_drivers[driver_sel];
+}
+
+unsigned long get_spi_bus_base(unsigned int bus)
+{
+	switch (bus) {
+#ifdef SPI_BUS_FSL_DSPI1
+	case SPI_BUS_FSL_DSPI1:
+		return DSPI1_BASE_ADDR;
+#endif
+#ifdef SPI_BUS_FSL_DSPI2
+	case SPI_BUS_FSL_DSPI2:
+		return DSPI2_BASE_ADDR;
+#endif
+#ifdef SPI_BUS_FSL_DSPI3
+	case SPI_BUS_FSL_DSPI3:
+		return DSPI3_BASE_ADDR;
+#endif
+#ifdef SPI_BUS_FSL_DSPI4
+	case SPI_BUS_FSL_DSPI4:
+		return DSPI4_BASE_ADDR;
+#endif
+#ifdef SPI_BUS_FSL_QSPI
+	case SPI_BUS_FSL_QSPI:
+		return QSPI_BASE_ADDR;
+#endif
+#ifdef SPI_BUS_FSL_QSPI2
+	case SPI_BUS_FSL_QSPI2:
+		return QSPI2_BASE_ADDR;
+#endif
+	default:
+		printf("FSL SPL:get bus base error %d", bus);
+		return 0;
+	}
+}
+
+unsigned long get_qspi_amba_base(unsigned int bus)
+{
+	switch (bus) {
+#ifdef SPI_BUS_FSL_QSPI
+	case SPI_BUS_FSL_QSPI:
+		return QSPI_AMBA_BASE;
+#endif
+#ifdef SPI_BUS_FSL_QSPI2
+	case SPI_BUS_FSL_QSPI2:
+		return QSPI2_AMBA_BASE;
+#endif
+	default:
+		printf("FSL SPL:get qspi amba bus base error %d", bus);
+		return 0;
+	}
+
+	return 0;
+}
+
+void spi_init()
+{
+	int i;
+	struct fsl_spi_driver *driver;
+
+	for (i = 0; i < ARRAY_SIZE(fsl_spi_drivers); i++) {
+		driver = &fsl_spi_drivers[i];
+		if (driver && driver->init)
+			driver->init();
+	}
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+		unsigned int max_hz, unsigned int mode)
+{
+	struct fsl_spi_driver *driver = find_fsl_spi_driver(bus, cs);
+
+	if (!driver || !driver->setup_slave)
+		return NULL;
+
+	return driver->setup_slave(bus, cs, max_hz, mode);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+	struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
+								slave->cs);
+
+	if (!driver)
+		return 1;
+	if (!driver->claim_bus)
+		return 0;
+
+	return driver->claim_bus(slave);
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+	struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
+								slave->cs);
+
+	if (driver && driver->free_slave)
+		return driver->free_slave(slave);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+		const void *dout, void *din, unsigned long flags)
+{
+	struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
+								slave->cs);
+
+	if (!driver || !driver->xfer)
+		return -1;
+
+	return driver->xfer(slave, bitlen, dout, din, flags);
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+	struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
+								slave->cs);
+
+	if (driver && driver->release_bus)
+		driver->release_bus(slave);
+}
+
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+	struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
+								slave->cs);
+
+	if (driver && driver->cs_activate)
+		driver->cs_activate(slave);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+	struct fsl_spi_driver *driver = find_fsl_spi_driver(slave->bus,
+								slave->cs);
+
+	if (driver && driver->cs_deactivate)
+		driver->cs_deactivate(slave);
+}