[U-Boot] [PATCH] spi:ls102xqds:Support for compatibility for QSPI and DSPI modules drivers
Chao Fu
b44548 at freescale.com
Fri Sep 26 09:56:39 CEST 2014
From: Chao Fu <B44548 at 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 at 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);
+};
+
+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);
+}
--
1.8.4
More information about the U-Boot
mailing list