Message ID | 1411718199-27215-1-git-send-email-b44548@freescale.com |
---|---|
State | Changes Requested |
Delegated to: | York Sun |
Headers | show |
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
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(®s->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(®s->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 --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(®s->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(®s->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); +}