diff options
Diffstat (limited to 'drivers/spi')
-rw-r--r-- | drivers/spi/Kconfig | 37 | ||||
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/atmel_spi.c | 286 | ||||
-rw-r--r-- | drivers/spi/atmel_spi.h | 15 | ||||
-rw-r--r-- | drivers/spi/davinci_spi.c | 157 | ||||
-rw-r--r-- | drivers/spi/fsl_dspi.c | 132 | ||||
-rw-r--r-- | drivers/spi/fsl_espi.c | 444 | ||||
-rw-r--r-- | drivers/spi/mxs_spi.c | 158 | ||||
-rw-r--r-- | drivers/spi/soft_spi_legacy.c | 168 |
9 files changed, 441 insertions, 957 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 5941520..09b9cb1 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -119,6 +119,12 @@ config CF_SPI Enable the ColdFire SPI driver. This driver can be used on some m68k SoCs. +config DAVINCI_SPI + bool "Davinci & Keystone SPI driver" + depends on ARCH_DAVINCI || ARCH_KEYSTONE + help + Enable the Davinci SPI driver + config DESIGNWARE_SPI bool "Designware SPI driver" help @@ -207,6 +213,12 @@ config MVEBU_A3700_SPI used to access the SPI NOR flash on platforms embedding this Marvell IP core. +config MXS_SPI + bool "MXS SPI Driver" + help + Enable the MXS SPI controller driver. This driver can be used + on the i.MX23 and i.MX28 SoCs. + config NXP_FSPI bool "NXP FlexSPI driver" depends on SPI_MEM @@ -280,6 +292,12 @@ config SPI_SIFIVE The SiFive SPI controller driver is found on various SiFive SoCs. +config SOFT_SPI + bool "Soft SPI driver" + help + Enable Soft SPI driver. This driver is to use GPIO simulate + the SPI protocol. + config SPI_SUNXI bool "Allwinner SoC SPI controllers" default ARCH_SUNXI @@ -385,13 +403,6 @@ config ZYNQMP_GQSPI endif # if DM_SPI -config SOFT_SPI - bool "Soft SPI driver" - depends on DM_SPI || (DEPRECATED && !DM_SPI) - help - Enable Soft SPI driver. This driver is to use GPIO simulate - the SPI protocol. - config FSL_ESPI bool "Freescale eSPI driver" imply SPI_FLASH_BAR @@ -400,12 +411,6 @@ config FSL_ESPI access the SPI interface and SPI NOR flash on platforms embedding this Freescale eSPI IP core. -config DAVINCI_SPI - bool "Davinci & Keystone SPI driver" - depends on ARCH_DAVINCI || ARCH_KEYSTONE - help - Enable the Davinci SPI driver - config SH_QSPI bool "Renesas Quad SPI driver" help @@ -424,12 +429,6 @@ config MXC_SPI Enable the MXC SPI controller driver. This driver can be used on various i.MX SoCs such as i.MX31/35/51/6/7. -config MXS_SPI - bool "MXS SPI Driver" - help - Enable the MXS SPI controller driver. This driver can be used - on the i.MX23 and i.MX28 SoCs. - config OMAP3_SPI bool "McSPI driver for OMAP" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 3427764..54881a7 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_TI_QSPI) += ti_qspi.o else obj-y += spi.o obj-$(CONFIG_SPI_MEM) += spi-mem-nodm.o -obj-$(CONFIG_SOFT_SPI) += soft_spi_legacy.o endif obj-$(CONFIG_ALTERA_SPI) += altera_spi.o diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index f076e92..b120664 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -9,217 +9,102 @@ #include <spi.h> #include <malloc.h> #include <wait_bit.h> - #include <asm/io.h> - #include <asm/arch/clk.h> #include <asm/arch/hardware.h> -#ifdef CONFIG_DM_SPI #include <asm/arch/at91_spi.h> -#endif #if CONFIG_IS_ENABLED(DM_GPIO) #include <asm/gpio.h> #endif +#include <linux/bitops.h> -#include "atmel_spi.h" - -#ifndef CONFIG_DM_SPI - -static int spi_has_wdrbt(struct atmel_spi_slave *slave) -{ - unsigned int ver; - - ver = spi_readl(slave, VERSION); - - return (ATMEL_SPI_VERSION_REV(ver) >= 0x210); -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct atmel_spi_slave *as; - unsigned int scbr; - u32 csrx; - void *regs; - - if (!spi_cs_is_valid(bus, cs)) - return NULL; - - switch (bus) { - case 0: - regs = (void *)ATMEL_BASE_SPI0; - break; -#ifdef ATMEL_BASE_SPI1 - case 1: - regs = (void *)ATMEL_BASE_SPI1; - break; -#endif -#ifdef ATMEL_BASE_SPI2 - case 2: - regs = (void *)ATMEL_BASE_SPI2; - break; -#endif -#ifdef ATMEL_BASE_SPI3 - case 3: - regs = (void *)ATMEL_BASE_SPI3; - break; -#endif - default: - return NULL; - } - - - scbr = (get_spi_clk_rate(bus) + max_hz - 1) / max_hz; - if (scbr > ATMEL_SPI_CSRx_SCBR_MAX) - /* Too low max SCK rate */ - return NULL; - if (scbr < 1) - scbr = 1; - - csrx = ATMEL_SPI_CSRx_SCBR(scbr); - csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8); - if (!(mode & SPI_CPHA)) - csrx |= ATMEL_SPI_CSRx_NCPHA; - if (mode & SPI_CPOL) - csrx |= ATMEL_SPI_CSRx_CPOL; - - as = spi_alloc_slave(struct atmel_spi_slave, bus, cs); - if (!as) - return NULL; - - as->regs = regs; - as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS - | ATMEL_SPI_MR_PCS(~(1 << cs) & 0xf); - if (spi_has_wdrbt(as)) - as->mr |= ATMEL_SPI_MR_WDRBT; - - spi_writel(as, CSR(cs), csrx); - - return &as->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct atmel_spi_slave *as = to_atmel_spi(slave); - - free(as); -} - -int spi_claim_bus(struct spi_slave *slave) -{ - struct atmel_spi_slave *as = to_atmel_spi(slave); - - /* Enable the SPI hardware */ - spi_writel(as, CR, ATMEL_SPI_CR_SPIEN); - - /* - * Select the slave. This should set SCK to the correct - * initial state, etc. - */ - spi_writel(as, MR, as->mr); - - return 0; -} - -void spi_release_bus(struct spi_slave *slave) -{ - struct atmel_spi_slave *as = to_atmel_spi(slave); - - /* Disable the SPI hardware */ - spi_writel(as, CR, ATMEL_SPI_CR_SPIDIS); -} - -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) -{ - struct atmel_spi_slave *as = to_atmel_spi(slave); - unsigned int len_tx; - unsigned int len_rx; - unsigned int len; - u32 status; - const u8 *txp = dout; - u8 *rxp = din; - u8 value; - - if (bitlen == 0) - /* Finish any previously submitted transfers */ - goto out; - - /* - * TODO: The controller can do non-multiple-of-8 bit - * transfers, but this driver currently doesn't support it. - * - * It's also not clear how such transfers are supposed to be - * represented as a stream of bytes...this is a limitation of - * the current SPI interface. - */ - if (bitlen % 8) { - /* Errors always terminate an ongoing transfer */ - flags |= SPI_XFER_END; - goto out; - } - - len = bitlen / 8; - - /* - * The controller can do automatic CS control, but it is - * somewhat quirky, and it doesn't really buy us much anyway - * in the context of U-Boot. - */ - if (flags & SPI_XFER_BEGIN) { - spi_cs_activate(slave); - /* - * sometimes the RDR is not empty when we get here, - * in theory that should not happen, but it DOES happen. - * Read it here to be on the safe side. - * That also clears the OVRES flag. Required if the - * following loop exits due to OVRES! - */ - spi_readl(as, RDR); - } - - for (len_tx = 0, len_rx = 0; len_rx < len; ) { - status = spi_readl(as, SR); - - if (status & ATMEL_SPI_SR_OVRES) - return -1; - - if (len_tx < len && (status & ATMEL_SPI_SR_TDRE)) { - if (txp) - value = *txp++; - else - value = 0; - spi_writel(as, TDR, value); - len_tx++; - } - if (status & ATMEL_SPI_SR_RDRF) { - value = spi_readl(as, RDR); - if (rxp) - *rxp++ = value; - len_rx++; - } - } - -out: - if (flags & SPI_XFER_END) { - /* - * Wait until the transfer is completely done before - * we deactivate CS. - */ - do { - status = spi_readl(as, SR); - } while (!(status & ATMEL_SPI_SR_TXEMPTY)); - - spi_cs_deactivate(slave); - } - - return 0; -} - -#else +/* + * Register definitions for the Atmel AT32/AT91 SPI Controller + */ +/* Register offsets */ +#define ATMEL_SPI_CR 0x0000 +#define ATMEL_SPI_MR 0x0004 +#define ATMEL_SPI_RDR 0x0008 +#define ATMEL_SPI_TDR 0x000c +#define ATMEL_SPI_SR 0x0010 +#define ATMEL_SPI_IER 0x0014 +#define ATMEL_SPI_IDR 0x0018 +#define ATMEL_SPI_IMR 0x001c +#define ATMEL_SPI_CSR(x) (0x0030 + 4 * (x)) +#define ATMEL_SPI_VERSION 0x00fc + +/* Bits in CR */ +#define ATMEL_SPI_CR_SPIEN BIT(0) +#define ATMEL_SPI_CR_SPIDIS BIT(1) +#define ATMEL_SPI_CR_SWRST BIT(7) +#define ATMEL_SPI_CR_LASTXFER BIT(24) + +/* Bits in MR */ +#define ATMEL_SPI_MR_MSTR BIT(0) +#define ATMEL_SPI_MR_PS BIT(1) +#define ATMEL_SPI_MR_PCSDEC BIT(2) +#define ATMEL_SPI_MR_FDIV BIT(3) +#define ATMEL_SPI_MR_MODFDIS BIT(4) +#define ATMEL_SPI_MR_WDRBT BIT(5) +#define ATMEL_SPI_MR_LLB BIT(7) +#define ATMEL_SPI_MR_PCS(x) (((x) & 15) << 16) +#define ATMEL_SPI_MR_DLYBCS(x) ((x) << 24) + +/* Bits in RDR */ +#define ATMEL_SPI_RDR_RD(x) (x) +#define ATMEL_SPI_RDR_PCS(x) ((x) << 16) + +/* Bits in TDR */ +#define ATMEL_SPI_TDR_TD(x) (x) +#define ATMEL_SPI_TDR_PCS(x) ((x) << 16) +#define ATMEL_SPI_TDR_LASTXFER BIT(24) + +/* Bits in SR/IER/IDR/IMR */ +#define ATMEL_SPI_SR_RDRF BIT(0) +#define ATMEL_SPI_SR_TDRE BIT(1) +#define ATMEL_SPI_SR_MODF BIT(2) +#define ATMEL_SPI_SR_OVRES BIT(3) +#define ATMEL_SPI_SR_ENDRX BIT(4) +#define ATMEL_SPI_SR_ENDTX BIT(5) +#define ATMEL_SPI_SR_RXBUFF BIT(6) +#define ATMEL_SPI_SR_TXBUFE BIT(7) +#define ATMEL_SPI_SR_NSSR BIT(8) +#define ATMEL_SPI_SR_TXEMPTY BIT(9) +#define ATMEL_SPI_SR_SPIENS BIT(16) + +/* Bits in CSRx */ +#define ATMEL_SPI_CSRx_CPOL BIT(0) +#define ATMEL_SPI_CSRx_NCPHA BIT(1) +#define ATMEL_SPI_CSRx_CSAAT BIT(3) +#define ATMEL_SPI_CSRx_BITS(x) ((x) << 4) +#define ATMEL_SPI_CSRx_SCBR(x) ((x) << 8) +#define ATMEL_SPI_CSRx_SCBR_MAX GENMASK(7, 0) +#define ATMEL_SPI_CSRx_DLYBS(x) ((x) << 16) +#define ATMEL_SPI_CSRx_DLYBCT(x) ((x) << 24) + +/* Bits in VERSION */ +#define ATMEL_SPI_VERSION_REV(x) ((x) & 0xfff) +#define ATMEL_SPI_VERSION_MFN(x) ((x) << 16) + +/* Constants for CSRx:BITS */ +#define ATMEL_SPI_BITS_8 0 +#define ATMEL_SPI_BITS_9 1 +#define ATMEL_SPI_BITS_10 2 +#define ATMEL_SPI_BITS_11 3 +#define ATMEL_SPI_BITS_12 4 +#define ATMEL_SPI_BITS_13 5 +#define ATMEL_SPI_BITS_14 6 +#define ATMEL_SPI_BITS_15 7 +#define ATMEL_SPI_BITS_16 8 #define MAX_CS_COUNT 4 +/* Register access macros */ +#define spi_readl(as, reg) \ + readl(as->regs + ATMEL_SPI_##reg) +#define spi_writel(as, reg, value) \ + writel(value, as->regs + ATMEL_SPI_##reg) + struct atmel_spi_platdata { struct at91_spi *regs; }; @@ -507,4 +392,3 @@ U_BOOT_DRIVER(atmel_spi) = { .priv_auto_alloc_size = sizeof(struct atmel_spi_priv), .probe = atmel_spi_probe, }; -#endif diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h index 6167bd1..9663cca 100644 --- a/drivers/spi/atmel_spi.h +++ b/drivers/spi/atmel_spi.h @@ -79,23 +79,8 @@ #define ATMEL_SPI_BITS_15 7 #define ATMEL_SPI_BITS_16 8 -struct atmel_spi_slave { - struct spi_slave slave; - void *regs; - u32 mr; -}; - -static inline struct atmel_spi_slave *to_atmel_spi(struct spi_slave *slave) -{ - return container_of(slave, struct atmel_spi_slave, slave); -} - /* Register access macros */ #define spi_readl(as, reg) \ readl(as->regs + ATMEL_SPI_##reg) #define spi_writel(as, reg, value) \ writel(value, as->regs + ATMEL_SPI_##reg) - -#if !defined(CONFIG_SYS_SPI_WRITE_TOUT) -#define CONFIG_SYS_SPI_WRITE_TOUT (5 * CONFIG_SYS_HZ) -#endif diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c index 97ac97b..e1e9b45 100644 --- a/drivers/spi/davinci_spi.c +++ b/drivers/spi/davinci_spi.c @@ -55,41 +55,6 @@ /* SPIDEF */ #define SPIDEF_CSDEF0_MASK BIT(0) -#ifndef CONFIG_DM_SPI -#define SPI0_BUS 0 -#define SPI0_BASE CONFIG_SYS_SPI_BASE -/* - * Define default SPI0_NUM_CS as 1 for existing platforms that uses this - * driver. Platform can configure number of CS using CONFIG_SYS_SPI0_NUM_CS - * if more than one CS is supported and by defining CONFIG_SYS_SPI0. - */ -#ifndef CONFIG_SYS_SPI0 -#define SPI0_NUM_CS 1 -#else -#define SPI0_NUM_CS CONFIG_SYS_SPI0_NUM_CS -#endif - -/* - * define CONFIG_SYS_SPI1 when platform has spi-1 device (bus #1) and - * CONFIG_SYS_SPI1_NUM_CS defines number of CS on this bus - */ -#ifdef CONFIG_SYS_SPI1 -#define SPI1_BUS 1 -#define SPI1_NUM_CS CONFIG_SYS_SPI1_NUM_CS -#define SPI1_BASE CONFIG_SYS_SPI1_BASE -#endif - -/* - * define CONFIG_SYS_SPI2 when platform has spi-2 device (bus #2) and - * CONFIG_SYS_SPI2_NUM_CS defines number of CS on this bus - */ -#ifdef CONFIG_SYS_SPI2 -#define SPI2_BUS 2 -#define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS -#define SPI2_BASE CONFIG_SYS_SPI2_BASE -#endif -#endif - DECLARE_GLOBAL_DATA_PTR; /* davinci spi register set */ @@ -122,9 +87,6 @@ struct davinci_spi_regs { /* davinci spi slave */ struct davinci_spi_slave { -#ifndef CONFIG_DM_SPI - struct spi_slave slave; -#endif struct davinci_spi_regs *regs; unsigned int freq; /* current SPI bus frequency */ unsigned int mode; /* current SPI mode used */ @@ -346,124 +308,6 @@ out: return 0; } -#ifndef CONFIG_DM_SPI - -static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave) -{ - return container_of(slave, struct davinci_spi_slave, slave); -} - -int spi_cs_is_valid(unsigned int bus, unsigned int cs) -{ - int ret = 0; - - switch (bus) { - case SPI0_BUS: - if (cs < SPI0_NUM_CS) - ret = 1; - break; -#ifdef CONFIG_SYS_SPI1 - case SPI1_BUS: - if (cs < SPI1_NUM_CS) - ret = 1; - break; -#endif -#ifdef CONFIG_SYS_SPI2 - case SPI2_BUS: - if (cs < SPI2_NUM_CS) - ret = 1; - break; -#endif - default: - /* Invalid bus number. Do nothing */ - break; - } - return ret; -} - -void spi_cs_activate(struct spi_slave *slave) -{ - /* do nothing */ -} - -void spi_cs_deactivate(struct spi_slave *slave) -{ - /* do nothing */ -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct davinci_spi_slave *ds; - - if (!spi_cs_is_valid(bus, cs)) - return NULL; - - ds = spi_alloc_slave(struct davinci_spi_slave, bus, cs); - if (!ds) - return NULL; - - switch (bus) { - case SPI0_BUS: - ds->regs = (struct davinci_spi_regs *)SPI0_BASE; - break; -#ifdef CONFIG_SYS_SPI1 - case SPI1_BUS: - ds->regs = (struct davinci_spi_regs *)SPI1_BASE; - break; -#endif -#ifdef CONFIG_SYS_SPI2 - case SPI2_BUS: - ds->regs = (struct davinci_spi_regs *)SPI2_BASE; - break; -#endif - default: /* Invalid bus number */ - return NULL; - } - - ds->freq = max_hz; - ds->mode = mode; - - return &ds->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct davinci_spi_slave *ds = to_davinci_spi(slave); - - free(ds); -} - -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) -{ - struct davinci_spi_slave *ds = to_davinci_spi(slave); - - ds->cur_cs = slave->cs; - - return __davinci_spi_xfer(ds, bitlen, dout, din, flags); -} - -int spi_claim_bus(struct spi_slave *slave) -{ - struct davinci_spi_slave *ds = to_davinci_spi(slave); - -#ifdef CONFIG_SPI_HALF_DUPLEX - ds->half_duplex = true; -#else - ds->half_duplex = false; -#endif - return __davinci_spi_claim_bus(ds, ds->slave.cs); -} - -void spi_release_bus(struct spi_slave *slave) -{ - struct davinci_spi_slave *ds = to_davinci_spi(slave); - - __davinci_spi_release_bus(ds); -} - -#else static int davinci_spi_set_speed(struct udevice *bus, uint max_hz) { struct davinci_spi_slave *ds = dev_get_priv(bus); @@ -582,4 +426,3 @@ U_BOOT_DRIVER(davinci_spi) = { .ops = &davinci_spi_ops, .priv_auto_alloc_size = sizeof(struct davinci_spi_slave), }; -#endif diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c index 1cdb233..78ad61ca 100644 --- a/drivers/spi/fsl_dspi.c +++ b/drivers/spi/fsl_dspi.c @@ -100,13 +100,6 @@ struct fsl_dspi_priv { struct dspi *regs; }; -#ifndef CONFIG_DM_SPI -struct fsl_dspi { - struct spi_slave slave; - struct fsl_dspi_priv priv; -}; -#endif - __weak void cpu_dspi_port_conf(void) { } @@ -414,131 +407,7 @@ static int fsl_dspi_cfg_speed(struct fsl_dspi_priv *priv, uint speed) return 0; } -#ifndef CONFIG_DM_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; -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct fsl_dspi *dspi; - uint mcr_cfg_val; - - dspi = spi_alloc_slave(struct fsl_dspi, bus, cs); - if (!dspi) - return NULL; - - cpu_dspi_port_conf(); - -#ifdef CONFIG_SYS_FSL_DSPI_BE - dspi->priv.flags |= DSPI_FLAG_REGMAP_ENDIAN_BIG; -#endif - - dspi->priv.regs = (struct dspi *)MMAP_DSPI; - -#ifdef CONFIG_M68K - dspi->priv.bus_clk = gd->bus_clk; -#else - dspi->priv.bus_clk = mxc_get_clock(MXC_DSPI_CLK); -#endif - dspi->priv.speed_hz = FSL_DSPI_DEFAULT_SCK_FREQ; - - /* default: all CS signals inactive state is high */ - mcr_cfg_val = DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK | - DSPI_MCR_CRXF | DSPI_MCR_CTXF; - fsl_dspi_init_mcr(&dspi->priv, mcr_cfg_val); - - for (i = 0; i < FSL_DSPI_MAX_CHIPSELECT; i++) - dspi->priv.ctar_val[i] = DSPI_CTAR_DEFAULT_VALUE; - -#ifdef CONFIG_SYS_DSPI_CTAR0 - if (FSL_DSPI_MAX_CHIPSELECT > 0) - dspi->priv.ctar_val[0] = CONFIG_SYS_DSPI_CTAR0; -#endif -#ifdef CONFIG_SYS_DSPI_CTAR1 - if (FSL_DSPI_MAX_CHIPSELECT > 1) - dspi->priv.ctar_val[1] = CONFIG_SYS_DSPI_CTAR1; -#endif -#ifdef CONFIG_SYS_DSPI_CTAR2 - if (FSL_DSPI_MAX_CHIPSELECT > 2) - dspi->priv.ctar_val[2] = CONFIG_SYS_DSPI_CTAR2; -#endif -#ifdef CONFIG_SYS_DSPI_CTAR3 - if (FSL_DSPI_MAX_CHIPSELECT > 3) - dspi->priv.ctar_val[3] = CONFIG_SYS_DSPI_CTAR3; -#endif -#ifdef CONFIG_SYS_DSPI_CTAR4 - if (FSL_DSPI_MAX_CHIPSELECT > 4) - dspi->priv.ctar_val[4] = CONFIG_SYS_DSPI_CTAR4; -#endif -#ifdef CONFIG_SYS_DSPI_CTAR5 - if (FSL_DSPI_MAX_CHIPSELECT > 5) - dspi->priv.ctar_val[5] = CONFIG_SYS_DSPI_CTAR5; -#endif -#ifdef CONFIG_SYS_DSPI_CTAR6 - if (FSL_DSPI_MAX_CHIPSELECT > 6) - dspi->priv.ctar_val[6] = CONFIG_SYS_DSPI_CTAR6; -#endif -#ifdef CONFIG_SYS_DSPI_CTAR7 - if (FSL_DSPI_MAX_CHIPSELECT > 7) - dspi->priv.ctar_val[7] = CONFIG_SYS_DSPI_CTAR7; -#endif - fsl_dspi_cfg_speed(&dspi->priv, max_hz); - - /* configure transfer mode */ - fsl_dspi_cfg_ctar_mode(&dspi->priv, cs, mode); - - /* configure active state of CSX */ - fsl_dspi_cfg_cs_active_state(&dspi->priv, cs, mode); - - return &dspi->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - free(slave); -} - -int spi_claim_bus(struct spi_slave *slave) -{ - uint sr_val; - struct fsl_dspi *dspi = (struct fsl_dspi *)slave; - - cpu_dspi_claim_bus(slave->bus, slave->cs); - - fsl_dspi_clr_fifo(&dspi->priv); - - /* check module TX and RX status */ - sr_val = dspi_read32(dspi->priv.flags, &dspi->priv.regs->sr); - if ((sr_val & DSPI_SR_TXRXS) != DSPI_SR_TXRXS) { - debug("DSPI RX/TX not ready!\n"); - return -EIO; - } - - return 0; -} - -void spi_release_bus(struct spi_slave *slave) -{ - struct fsl_dspi *dspi = (struct fsl_dspi *)slave; - - dspi_halt(&dspi->priv, 1); - cpu_dspi_release_bus(slave->bus.slave->cs); -} - -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, - void *din, unsigned long flags) -{ - struct fsl_dspi *dspi = (struct fsl_dspi *)slave; - return dspi_xfer(&dspi->priv, slave->cs, bitlen, dout, din, flags); -} -#else static int fsl_dspi_child_pre_probe(struct udevice *dev) { struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); @@ -745,4 +614,3 @@ U_BOOT_DRIVER(fsl_dspi) = { .child_pre_probe = fsl_dspi_child_pre_probe, .bind = fsl_dspi_bind, }; -#endif diff --git a/drivers/spi/fsl_espi.c b/drivers/spi/fsl_espi.c index 50d194f..5c76fd9 100644 --- a/drivers/spi/fsl_espi.c +++ b/drivers/spi/fsl_espi.c @@ -3,7 +3,9 @@ * eSPI controller driver. * * Copyright 2010-2011 Freescale Semiconductor, Inc. + * Copyright 2020 NXP * Author: Mingkai Hu (Mingkai.hu@freescale.com) + * Chuanhua Han (chuanhua.han@nxp.com) */ #include <common.h> @@ -14,10 +16,16 @@ #include <malloc.h> #include <spi.h> #include <asm/immap_85xx.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <dm/platform_data/fsl_espi.h> struct fsl_spi_slave { struct spi_slave slave; ccsr_espi_t *espi; + u32 speed_hz; + unsigned int cs; unsigned int div16; unsigned int pm; int tx_timeout; @@ -31,6 +39,9 @@ struct fsl_spi_slave { #define to_fsl_spi_slave(s) container_of(s, struct fsl_spi_slave, slave) #define US_PER_SECOND 1000000UL +/* default SCK frequency, unit: HZ */ +#define FSL_ESPI_DEFAULT_SCK_FREQ 10000000 + #define ESPI_MAX_CS_NUM 4 #define ESPI_FIFO_WIDTH_BIT 32 @@ -65,116 +76,27 @@ struct fsl_spi_slave { #define ESPI_MAX_DATA_TRANSFER_LEN 0xFFF0 -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct fsl_spi_slave *fsl; - sys_info_t sysinfo; - unsigned long spibrg = 0; - unsigned long spi_freq = 0; - unsigned char pm = 0; - - if (!spi_cs_is_valid(bus, cs)) - return NULL; - - fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs); - if (!fsl) - return NULL; - - fsl->espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR); - fsl->mode = mode; - fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN; - - /* Set eSPI BRG clock source */ - get_sys_info(&sysinfo); - spibrg = sysinfo.freq_systembus / 2; - fsl->div16 = 0; - if ((spibrg / max_hz) > 32) { - fsl->div16 = ESPI_CSMODE_DIV16; - pm = spibrg / (max_hz * 16 * 2); - if (pm > 16) { - pm = 16; - debug("Requested speed is too low: %d Hz, %ld Hz " - "is used.\n", max_hz, spibrg / (32 * 16)); - } - } else - pm = spibrg / (max_hz * 2); - if (pm) - pm--; - fsl->pm = pm; - - if (fsl->div16) - spi_freq = spibrg / ((pm + 1) * 2 * 16); - else - spi_freq = spibrg / ((pm + 1) * 2); - - /* set tx_timeout to 10 times of one espi FIFO entry go out */ - fsl->tx_timeout = DIV_ROUND_UP((US_PER_SECOND * ESPI_FIFO_WIDTH_BIT - * 10), spi_freq); - - return &fsl->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); - free(fsl); -} - -int spi_claim_bus(struct spi_slave *slave) +void fsl_spi_cs_activate(struct spi_slave *slave, uint cs) { struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); ccsr_espi_t *espi = fsl->espi; - unsigned char pm = fsl->pm; - unsigned int cs = slave->cs; - unsigned int mode = fsl->mode; - unsigned int div16 = fsl->div16; - int i; - - debug("%s: bus:%i cs:%i\n", __func__, slave->bus, cs); - - /* Enable eSPI interface */ - out_be32(&espi->mode, ESPI_MODE_RXTHR(3) - | ESPI_MODE_TXTHR(4) | ESPI_MODE_EN); - - out_be32(&espi->event, 0xffffffff); /* Clear all eSPI events */ - out_be32(&espi->mask, 0x00000000); /* Mask all eSPI interrupts */ - - /* Init CS mode interface */ - for (i = 0; i < ESPI_MAX_CS_NUM; i++) - out_be32(&espi->csmode[i], ESPI_CSMODE_INIT_VAL); - - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) & - ~(ESPI_CSMODE_PM(0xF) | ESPI_CSMODE_DIV16 - | ESPI_CSMODE_CI_INACTIVEHIGH | ESPI_CSMODE_CP_BEGIN_EDGCLK - | ESPI_CSMODE_REV_MSB_FIRST | ESPI_CSMODE_LEN(0xF))); - - /* Set eSPI BRG clock source */ - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_PM(pm) | div16); - - /* Set eSPI mode */ - if (mode & SPI_CPHA) - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_CP_BEGIN_EDGCLK); - if (mode & SPI_CPOL) - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_CI_INACTIVEHIGH); - - /* Character bit order: msb first */ - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_REV_MSB_FIRST); - - /* Character length in bits, between 0x3~0xf, i.e. 4bits~16bits */ - out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) - | ESPI_CSMODE_LEN(7)); + unsigned int com = 0; + size_t data_len = fsl->data_len; - return 0; + com &= ~(ESPI_COM_CS(0x3) | ESPI_COM_TRANLEN(0xFFFF)); + com |= ESPI_COM_CS(cs); + com |= ESPI_COM_TRANLEN(data_len - 1); + out_be32(&espi->com, com); } -void spi_release_bus(struct spi_slave *slave) +void fsl_spi_cs_deactivate(struct spi_slave *slave) { + struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); + ccsr_espi_t *espi = fsl->espi; + /* clear the RXCNT and TXCNT */ + out_be32(&espi->mode, in_be32(&espi->mode) & (~ESPI_MODE_EN)); + out_be32(&espi->mode, in_be32(&espi->mode) | ESPI_MODE_EN); } static void fsl_espi_tx(struct fsl_spi_slave *fsl, const void *dout) @@ -207,7 +129,8 @@ static void fsl_espi_tx(struct fsl_spi_slave *fsl, const void *dout) debug("***spi_xfer:...Tx timeout! event = %08x\n", event); } -static int fsl_espi_rx(struct fsl_spi_slave *fsl, void *din, unsigned int bytes) +static int fsl_espi_rx(struct fsl_spi_slave *fsl, void *din, + unsigned int bytes) { ccsr_espi_t *espi = fsl->espi; unsigned int tmpdin, rx_times; @@ -239,10 +162,17 @@ static int fsl_espi_rx(struct fsl_spi_slave *fsl, void *din, unsigned int bytes) return bytes; } -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, - void *data_in, unsigned long flags) +void espi_release_bus(struct fsl_spi_slave *fsl) { - struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); + /* Disable the SPI hardware */ + out_be32(&fsl->espi->mode, + in_be32(&fsl->espi->mode) & (~ESPI_MODE_EN)); +} + +int espi_xfer(struct fsl_spi_slave *fsl, uint cs, unsigned int bitlen, + const void *data_out, void *data_in, unsigned long flags) +{ + struct spi_slave *slave = &fsl->slave; ccsr_espi_t *espi = fsl->espi; unsigned int event, rx_bytes; const void *dout = NULL; @@ -261,13 +191,14 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, max_tran_len = fsl->max_transfer_length; switch (flags) { case SPI_XFER_BEGIN: - cmd_len = fsl->cmd_len = data_len; + cmd_len = data_len; + fsl->cmd_len = cmd_len; memcpy(cmd_buf, data_out, cmd_len); return 0; case 0: case SPI_XFER_END: if (bitlen == 0) { - spi_cs_deactivate(slave); + fsl_spi_cs_deactivate(slave); return 0; } buf_len = 2 * cmd_len + min(data_len, (size_t)max_tran_len); @@ -307,7 +238,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, num_blks = DIV_ROUND_UP(tran_len + cmd_len, 4); num_bytes = (tran_len + cmd_len) % 4; fsl->data_len = tran_len + cmd_len; - spi_cs_activate(slave); + fsl_spi_cs_activate(slave, cs); /* Clear all eSPI events */ out_be32(&espi->event , 0xffffffff); @@ -350,37 +281,304 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out, *(int *)buffer += tran_len; } } - spi_cs_deactivate(slave); + fsl_spi_cs_deactivate(slave); } free(buffer); return 0; } +void espi_claim_bus(struct fsl_spi_slave *fsl, unsigned int cs) +{ + ccsr_espi_t *espi = fsl->espi; + unsigned char pm = fsl->pm; + unsigned int mode = fsl->mode; + unsigned int div16 = fsl->div16; + int i; + + /* Enable eSPI interface */ + out_be32(&espi->mode, ESPI_MODE_RXTHR(3) + | ESPI_MODE_TXTHR(4) | ESPI_MODE_EN); + + out_be32(&espi->event, 0xffffffff); /* Clear all eSPI events */ + out_be32(&espi->mask, 0x00000000); /* Mask all eSPI interrupts */ + + /* Init CS mode interface */ + for (i = 0; i < ESPI_MAX_CS_NUM; i++) + out_be32(&espi->csmode[i], ESPI_CSMODE_INIT_VAL); + + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) & + ~(ESPI_CSMODE_PM(0xF) | ESPI_CSMODE_DIV16 + | ESPI_CSMODE_CI_INACTIVEHIGH | ESPI_CSMODE_CP_BEGIN_EDGCLK + | ESPI_CSMODE_REV_MSB_FIRST | ESPI_CSMODE_LEN(0xF))); + + /* Set eSPI BRG clock source */ + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_PM(pm) | div16); + + /* Set eSPI mode */ + if (mode & SPI_CPHA) + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_CP_BEGIN_EDGCLK); + if (mode & SPI_CPOL) + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_CI_INACTIVEHIGH); + + /* Character bit order: msb first */ + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_REV_MSB_FIRST); + + /* Character length in bits, between 0x3~0xf, i.e. 4bits~16bits */ + out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) + | ESPI_CSMODE_LEN(7)); +} + +void espi_setup_slave(struct fsl_spi_slave *fsl) +{ + unsigned int max_hz; + sys_info_t sysinfo; + unsigned long spibrg = 0; + unsigned long spi_freq = 0; + unsigned char pm = 0; + + max_hz = fsl->speed_hz; + + get_sys_info(&sysinfo); + spibrg = sysinfo.freq_systembus / 2; + fsl->div16 = 0; + if ((spibrg / max_hz) > 32) { + fsl->div16 = ESPI_CSMODE_DIV16; + pm = spibrg / (max_hz * 16 * 2); + if (pm > 16) { + pm = 16; + debug("max_hz is too low: %d Hz, %ld Hz is used.\n", + max_hz, spibrg / (32 * 16)); + } + } else { + pm = spibrg / (max_hz * 2); + } + if (pm) + pm--; + fsl->pm = pm; + + if (fsl->div16) + spi_freq = spibrg / ((pm + 1) * 2 * 16); + else + spi_freq = spibrg / ((pm + 1) * 2); + + /* set tx_timeout to 10 times of one espi FIFO entry go out */ + fsl->tx_timeout = DIV_ROUND_UP((US_PER_SECOND * ESPI_FIFO_WIDTH_BIT + * 10), spi_freq);/* Set eSPI BRG clock source */ +} + +#if !CONFIG_IS_ENABLED(DM_SPI) int spi_cs_is_valid(unsigned int bus, unsigned int cs) { return bus == 0 && cs < ESPI_MAX_CS_NUM; } -void spi_cs_activate(struct spi_slave *slave) +struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, + unsigned int max_hz, unsigned int mode) +{ + struct fsl_spi_slave *fsl; + + if (!spi_cs_is_valid(bus, cs)) + return NULL; + + fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs); + if (!fsl) + return NULL; + + fsl->espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR); + fsl->mode = mode; + fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN; + fsl->speed_hz = max_hz; + + espi_setup_slave(fsl); + + return &fsl->slave; +} + +void spi_free_slave(struct spi_slave *slave) { struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); - ccsr_espi_t *espi = fsl->espi; - unsigned int com = 0; - size_t data_len = fsl->data_len; - com &= ~(ESPI_COM_CS(0x3) | ESPI_COM_TRANLEN(0xFFFF)); - com |= ESPI_COM_CS(slave->cs); - com |= ESPI_COM_TRANLEN(data_len - 1); - out_be32(&espi->com, com); + free(fsl); } -void spi_cs_deactivate(struct spi_slave *slave) +int spi_claim_bus(struct spi_slave *slave) { struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); - ccsr_espi_t *espi = fsl->espi; - /* clear the RXCNT and TXCNT */ - out_be32(&espi->mode, in_be32(&espi->mode) & (~ESPI_MODE_EN)); - out_be32(&espi->mode, in_be32(&espi->mode) | ESPI_MODE_EN); + espi_claim_bus(fsl, slave->cs); + + return 0; } + +void spi_release_bus(struct spi_slave *slave) +{ + struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave); + + espi_release_bus(fsl); +} + +int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, + void *din, unsigned long flags) +{ + struct fsl_spi_slave *fsl = (struct fsl_spi_slave *)slave; + + return espi_xfer(fsl, slave->cs, bitlen, dout, din, flags); +} +#else +static void __espi_set_speed(struct fsl_spi_slave *fsl) +{ + espi_setup_slave(fsl); + + /* Set eSPI BRG clock source */ + out_be32(&fsl->espi->csmode[fsl->cs], + in_be32(&fsl->espi->csmode[fsl->cs]) + | ESPI_CSMODE_PM(fsl->pm) | fsl->div16); +} + +static void __espi_set_mode(struct fsl_spi_slave *fsl) +{ + /* Set eSPI mode */ + if (fsl->mode & SPI_CPHA) + out_be32(&fsl->espi->csmode[fsl->cs], + in_be32(&fsl->espi->csmode[fsl->cs]) + | ESPI_CSMODE_CP_BEGIN_EDGCLK); + if (fsl->mode & SPI_CPOL) + out_be32(&fsl->espi->csmode[fsl->cs], + in_be32(&fsl->espi->csmode[fsl->cs]) + | ESPI_CSMODE_CI_INACTIVEHIGH); +} + +static int fsl_espi_claim_bus(struct udevice *dev) +{ + struct udevice *bus = dev->parent; + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + espi_claim_bus(fsl, fsl->cs); + + return 0; +} + +static int fsl_espi_release_bus(struct udevice *dev) +{ + struct udevice *bus = dev->parent; + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + espi_release_bus(fsl); + + return 0; +} + +static int fsl_espi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct udevice *bus = dev->parent; + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + return espi_xfer(fsl, fsl->cs, bitlen, dout, din, flags); +} + +static int fsl_espi_set_speed(struct udevice *bus, uint speed) +{ + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + debug("%s speed %u\n", __func__, speed); + fsl->speed_hz = speed; + + __espi_set_speed(fsl); + + return 0; +} + +static int fsl_espi_set_mode(struct udevice *bus, uint mode) +{ + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + debug("%s mode %u\n", __func__, mode); + fsl->mode = mode; + + __espi_set_mode(fsl); + + return 0; +} + +static int fsl_espi_child_pre_probe(struct udevice *dev) +{ + struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); + struct udevice *bus = dev->parent; + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + debug("%s cs %u\n", __func__, slave_plat->cs); + fsl->cs = slave_plat->cs; + + return 0; +} + +static int fsl_espi_probe(struct udevice *bus) +{ + struct fsl_espi_platdata *plat = dev_get_platdata(bus); + struct fsl_spi_slave *fsl = dev_get_priv(bus); + + fsl->espi = (ccsr_espi_t *)((u32)plat->regs_addr); + fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN; + fsl->speed_hz = plat->speed_hz; + + debug("%s probe done, bus-num %d.\n", bus->name, bus->seq); + + return 0; +} + +static const struct dm_spi_ops fsl_espi_ops = { + .claim_bus = fsl_espi_claim_bus, + .release_bus = fsl_espi_release_bus, + .xfer = fsl_espi_xfer, + .set_speed = fsl_espi_set_speed, + .set_mode = fsl_espi_set_mode, +}; + +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) +static int fsl_espi_ofdata_to_platdata(struct udevice *bus) +{ + fdt_addr_t addr; + struct fsl_espi_platdata *plat = bus->platdata; + const void *blob = gd->fdt_blob; + int node = dev_of_offset(bus); + + addr = dev_read_addr(bus); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + plat->regs_addr = lower_32_bits(addr); + plat->speed_hz = fdtdec_get_int(blob, node, "spi-max-frequency", + FSL_ESPI_DEFAULT_SCK_FREQ); + + debug("ESPI: regs=%p, max-frequency=%d\n", + &plat->regs_addr, plat->speed_hz); + + return 0; +} + +static const struct udevice_id fsl_espi_ids[] = { + { .compatible = "fsl,mpc8536-espi" }, + { } +}; +#endif + +U_BOOT_DRIVER(fsl_espi) = { + .name = "fsl_espi", + .id = UCLASS_SPI, +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + .of_match = fsl_espi_ids, + .ofdata_to_platdata = fsl_espi_ofdata_to_platdata, +#endif + .ops = &fsl_espi_ops, + .platdata_auto_alloc_size = sizeof(struct fsl_espi_platdata), + .priv_auto_alloc_size = sizeof(struct fsl_spi_slave), + .probe = fsl_espi_probe, + .child_pre_probe = fsl_espi_child_pre_probe, +}; +#endif diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c index 0da4a80..e231e96 100644 --- a/drivers/spi/mxs_spi.c +++ b/drivers/spi/mxs_spi.c @@ -13,7 +13,10 @@ */ #include <common.h> +#include <dm.h> +#include <dt-structs.h> #include <cpu_func.h> +#include <errno.h> #include <log.h> #include <malloc.h> #include <memalign.h> @@ -34,34 +37,9 @@ #define MXSSSP_SMALL_TRANSFER 512 -static void mxs_spi_start_xfer(struct mxs_ssp_regs *ssp_regs) -{ - writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set); - writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_clr); -} - -static void mxs_spi_end_xfer(struct mxs_ssp_regs *ssp_regs) -{ - writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_clr); - writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set); -} - -#if !CONFIG_IS_ENABLED(DM_SPI) -struct mxs_spi_slave { - struct spi_slave slave; - uint32_t max_khz; - uint32_t mode; - struct mxs_ssp_regs *regs; -}; - -static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave) -{ - return container_of(slave, struct mxs_spi_slave, slave); -} -#else -#include <dm.h> -#include <errno.h> -#include <dt-structs.h> +/* Base numbers of i.MX2[38] clk for ssp0 IP block */ +#define MXS_SSP_IMX23_CLKID_SSP0 33 +#define MXS_SSP_IMX28_CLKID_SSP0 46 #ifdef CONFIG_MX28 #define dtd_fsl_imx_spi dtd_fsl_imx28_spi @@ -87,20 +65,24 @@ struct mxs_spi_priv { unsigned int clk_id; unsigned int mode; }; -#endif -#if !CONFIG_IS_ENABLED(DM_SPI) -static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave, - char *data, int length, int write, unsigned long flags) +static void mxs_spi_start_xfer(struct mxs_ssp_regs *ssp_regs) { - struct mxs_ssp_regs *ssp_regs = slave->regs; -#else + writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set); + writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_clr); +} + +static void mxs_spi_end_xfer(struct mxs_ssp_regs *ssp_regs) +{ + writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_clr); + writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set); +} + static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv, char *data, int length, int write, unsigned long flags) { struct mxs_ssp_regs *ssp_regs = priv->regs; -#endif if (flags & SPI_XFER_BEGIN) mxs_spi_start_xfer(ssp_regs); @@ -156,17 +138,10 @@ static int mxs_spi_xfer_pio(struct mxs_spi_priv *priv, return 0; } -#if !CONFIG_IS_ENABLED(DM_SPI) -static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave, - char *data, int length, int write, unsigned long flags) -{ - struct mxs_ssp_regs *ssp_regs = slave->regs; -#else static int mxs_spi_xfer_dma(struct mxs_spi_priv *priv, char *data, int length, int write, unsigned long flags) { struct mxs_ssp_regs *ssp_regs = priv->regs; -#endif const int xfer_max_sz = 0xff00; const int desc_count = DIV_ROUND_UP(length, xfer_max_sz) + 1; struct mxs_dma_desc *dp; @@ -207,11 +182,7 @@ static int mxs_spi_xfer_dma(struct mxs_spi_priv *priv, /* Invalidate the area, so no writeback into the RAM races with DMA */ invalidate_dcache_range(dstart, dstart + cache_data_count); -#if !CONFIG_IS_ENABLED(DM_SPI) - dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + slave->slave.bus; -#else dmach = priv->dma_channel; -#endif dp = desc; while (length) { @@ -288,20 +259,12 @@ static int mxs_spi_xfer_dma(struct mxs_spi_priv *priv, return ret; } -#if !CONFIG_IS_ENABLED(DM_SPI) -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) -{ - struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave); - struct mxs_ssp_regs *ssp_regs = mxs_slave->regs; -#else int mxs_spi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, void *din, unsigned long flags) { struct udevice *bus = dev_get_parent(dev); struct mxs_spi_priv *priv = dev_get_priv(bus); struct mxs_ssp_regs *ssp_regs = priv->regs; -#endif int len = bitlen / 8; char dummy; int write = 0; @@ -345,99 +308,13 @@ int mxs_spi_xfer(struct udevice *dev, unsigned int bitlen, if (!dma || (len < MXSSSP_SMALL_TRANSFER)) { writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr); -#if !CONFIG_IS_ENABLED(DM_SPI) - return mxs_spi_xfer_pio(mxs_slave, data, len, write, flags); -#else return mxs_spi_xfer_pio(priv, data, len, write, flags); -#endif } else { writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set); -#if !CONFIG_IS_ENABLED(DM_SPI) - return mxs_spi_xfer_dma(mxs_slave, data, len, write, flags); -#else return mxs_spi_xfer_dma(priv, data, len, write, flags); -#endif } } -#if !CONFIG_IS_ENABLED(DM_SPI) -int spi_cs_is_valid(unsigned int bus, unsigned int cs) -{ - /* MXS SPI: 4 ports and 3 chip selects maximum */ - if (!mxs_ssp_bus_id_valid(bus) || cs > 2) - return 0; - else - return 1; -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct mxs_spi_slave *mxs_slave; - - if (!spi_cs_is_valid(bus, cs)) { - printf("mxs_spi: invalid bus %d / chip select %d\n", bus, cs); - return NULL; - } - - mxs_slave = spi_alloc_slave(struct mxs_spi_slave, bus, cs); - if (!mxs_slave) - return NULL; - - if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + bus)) - goto err_init; - - mxs_slave->max_khz = max_hz / 1000; - mxs_slave->mode = mode; - mxs_slave->regs = mxs_ssp_regs_by_bus(bus); - - return &mxs_slave->slave; - -err_init: - free(mxs_slave); - return NULL; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave); - - free(mxs_slave); -} - -int spi_claim_bus(struct spi_slave *slave) -{ - struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave); - struct mxs_ssp_regs *ssp_regs = mxs_slave->regs; - u32 reg = 0; - - mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg); - - writel((slave->cs << MXS_SSP_CHIPSELECT_SHIFT) | - SSP_CTRL0_BUS_WIDTH_ONE_BIT, - &ssp_regs->hw_ssp_ctrl0); - - reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS; - reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0; - reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0; - writel(reg, &ssp_regs->hw_ssp_ctrl1); - - writel(0, &ssp_regs->hw_ssp_cmd0); - - mxs_set_ssp_busclock(slave->bus, mxs_slave->max_khz); - - return 0; -} - -void spi_release_bus(struct spi_slave *slave) -{ -} - -#else /* CONFIG_DM_SPI */ -/* Base numbers of i.MX2[38] clk for ssp0 IP block */ -#define MXS_SSP_IMX23_CLKID_SSP0 33 -#define MXS_SSP_IMX28_CLKID_SSP0 46 - static int mxs_spi_probe(struct udevice *bus) { struct mxs_spi_platdata *plat = dev_get_platdata(bus); @@ -625,4 +502,3 @@ U_BOOT_DRIVER(mxs_spi) = { .priv_auto_alloc_size = sizeof(struct mxs_spi_priv), .probe = mxs_spi_probe, }; -#endif diff --git a/drivers/spi/soft_spi_legacy.c b/drivers/spi/soft_spi_legacy.c deleted file mode 100644 index cc5ab5f..0000000 --- a/drivers/spi/soft_spi_legacy.c +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2002 - * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com. - * - * Influenced by code from: - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - */ - -#include <common.h> -#include <spi.h> - -#include <malloc.h> - -/*----------------------------------------------------------------------- - * Definitions - */ - -#ifdef DEBUG_SPI -#define PRINTD(fmt,args...) printf (fmt ,##args) -#else -#define PRINTD(fmt,args...) -#endif - -struct soft_spi_slave { - struct spi_slave slave; - unsigned int mode; -}; - -static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave) -{ - return container_of(slave, struct soft_spi_slave, slave); -} - -/*=====================================================================*/ -/* Public Functions */ -/*=====================================================================*/ - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - struct soft_spi_slave *ss; - - if (!spi_cs_is_valid(bus, cs)) - return NULL; - - ss = spi_alloc_slave(struct soft_spi_slave, bus, cs); - if (!ss) - return NULL; - - ss->mode = mode; - - /* TODO: Use max_hz to limit the SCK rate */ - - return &ss->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct soft_spi_slave *ss = to_soft_spi(slave); - - free(ss); -} - -int spi_claim_bus(struct spi_slave *slave) -{ -#ifdef CONFIG_SYS_IMMR - volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; -#endif - struct soft_spi_slave *ss = to_soft_spi(slave); - - /* - * Make sure the SPI clock is in idle state as defined for - * this slave. - */ - if (ss->mode & SPI_CPOL) - SPI_SCL(1); - else - SPI_SCL(0); - - return 0; -} - -void spi_release_bus(struct spi_slave *slave) -{ - /* Nothing to do */ -} - -/*----------------------------------------------------------------------- - * SPI transfer - * - * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks - * "bitlen" bits in the SPI MISO port. That's just the way SPI works. - * - * The source of the outgoing bits is the "dout" parameter and the - * destination of the input bits is the "din" parameter. Note that "dout" - * and "din" can point to the same memory location, in which case the - * input data overwrites the output data (since both are buffered by - * temporary variables, this is OK). - */ -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) -{ -#ifdef CONFIG_SYS_IMMR - volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; -#endif - struct soft_spi_slave *ss = to_soft_spi(slave); - uchar tmpdin = 0; - uchar tmpdout = 0; - const u8 *txd = dout; - u8 *rxd = din; - int cpol = ss->mode & SPI_CPOL; - int cpha = ss->mode & SPI_CPHA; - unsigned int j; - - PRINTD("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n", - slave->bus, slave->cs, *(uint *)txd, *(uint *)rxd, bitlen); - - if (flags & SPI_XFER_BEGIN) - spi_cs_activate(slave); - - for(j = 0; j < bitlen; j++) { - /* - * Check if it is time to work on a new byte. - */ - if ((j % 8) == 0) { - if (txd) - tmpdout = *txd++; - else - tmpdout = 0; - if(j != 0) { - if (rxd) - *rxd++ = tmpdin; - } - tmpdin = 0; - } - - if (!cpha) - SPI_SCL(!cpol); - SPI_SDA(tmpdout & 0x80); - SPI_DELAY; - if (cpha) - SPI_SCL(!cpol); - else - SPI_SCL(cpol); - tmpdin <<= 1; - tmpdin |= SPI_READ; - tmpdout <<= 1; - SPI_DELAY; - if (cpha) - SPI_SCL(cpol); - } - /* - * If the number of bits isn't a multiple of 8, shift the last - * bits over to left-justify them. Then store the last byte - * read in. - */ - if (rxd) { - if ((bitlen % 8) != 0) - tmpdin <<= 8 - (bitlen % 8); - *rxd++ = tmpdin; - } - - if (flags & SPI_XFER_END) - spi_cs_deactivate(slave); - - return(0); -} |