X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fspi%2Ffsl_qspi.c;h=e877d99bb051a312ca82893b233c1011143a7d4b;hb=7949576664ac8fe8c0da08fcd8c611b9616719f1;hp=5dc69a6865762a562bf64115f899e489748976cd;hpb=f95a4b3a5518818c831f1136053f9b2366018d0b;p=oweals%2Fu-boot.git diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 5dc69a6865..e877d99bb0 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -1,9 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2013-2015 Freescale Semiconductor, Inc. * * Freescale Quad Serial Peripheral Interface (QSPI) driver - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -11,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -85,7 +85,6 @@ DECLARE_GLOBAL_DATA_PTR; /* QSPI max chipselect signals number */ #define FSL_QSPI_MAX_CHIPSELECT_NUM 4 -#ifdef CONFIG_DM_SPI /** * struct fsl_qspi_platdata - platform data for Freescale QSPI * @@ -106,7 +105,6 @@ struct fsl_qspi_platdata { u32 flash_num; u32 num_chipselect; }; -#endif /** * struct fsl_qspi_priv - private data for Freescale QSPI @@ -137,12 +135,6 @@ struct fsl_qspi_priv { struct fsl_qspi_regs *regs; }; -#ifndef CONFIG_DM_SPI -struct fsl_qspi { - struct spi_slave slave; - struct fsl_qspi_priv priv; -}; -#endif static u32 qspi_read32(u32 flags, u32 *addr) { @@ -156,6 +148,18 @@ static void qspi_write32(u32 flags, u32 *addr, u32 val) out_be32(addr, val) : out_le32(addr, val); } +static inline int is_controller_busy(const struct fsl_qspi_priv *priv) +{ + u32 val; + u32 mask = QSPI_SR_BUSY_MASK | QSPI_SR_AHB_ACC_MASK | + QSPI_SR_IP_ACC_MASK; + + if (priv->flags & QSPI_FLAG_REGMAP_ENDIAN_BIG) + mask = (u32)cpu_to_be32(mask); + + return readl_poll_timeout(&priv->regs->sr, val, !(val & mask), 1000); +} + /* QSPI support swapping the flash read/write data * in hardware for LS102xA, but not for VF610 */ static inline u32 qspi_endian_xchg(u32 data) @@ -389,13 +393,13 @@ static inline void qspi_ahb_read(struct fsl_qspi_priv *priv, u8 *rxbuf, int len) { struct fsl_qspi_regs *regs = priv->regs; u32 mcr_reg; - void *rx_addr = NULL; + void *rx_addr; mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | - QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); + mcr_reg); rx_addr = (void *)(uintptr_t)(priv->cur_amba_base + priv->sf_addr); /* Read out the data directly from the AHB buffer. */ @@ -425,6 +429,14 @@ static void qspi_enable_ddr_mode(struct fsl_qspi_priv *priv) reg |= BIT(29); qspi_write32(priv->flags, ®s->mcr, reg); + + /* Enable the TDH to 1 for some platforms like imx6ul, imx7d, etc + * These two bits are reserved on other platforms + */ + reg = qspi_read32(priv->flags, ®s->flshcr); + reg &= ~(BIT(17)); + reg |= BIT(16); + qspi_write32(priv->flags, ®s->flshcr, reg); } /* @@ -478,7 +490,7 @@ static void qspi_op_rdbank(struct fsl_qspi_priv *priv, u8 *rxbuf, u32 len) mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | - QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); + mcr_reg); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base); @@ -523,7 +535,7 @@ static void qspi_op_rdid(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | - QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); + mcr_reg); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base); @@ -569,7 +581,7 @@ static void qspi_op_read(struct fsl_qspi_priv *priv, u32 *rxbuf, u32 len) mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | - QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); + mcr_reg); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); to_or_from = priv->sf_addr + priv->cur_amba_base; @@ -621,7 +633,7 @@ static void qspi_op_write(struct fsl_qspi_priv *priv, u8 *txbuf, u32 len) mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | - QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); + mcr_reg); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); status_reg = 0; @@ -696,7 +708,7 @@ static void qspi_op_rdsr(struct fsl_qspi_priv *priv, void *rxbuf, u32 len) mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | - QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); + mcr_reg); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); qspi_write32(priv->flags, ®s->sfar, priv->cur_amba_base); @@ -733,7 +745,7 @@ static void qspi_op_erase(struct fsl_qspi_priv *priv) mcr_reg = qspi_read32(priv->flags, ®s->mcr); qspi_write32(priv->flags, ®s->mcr, QSPI_MCR_CLR_RXF_MASK | QSPI_MCR_CLR_TXF_MASK | - QSPI_MCR_RESERVED_MASK | QSPI_MCR_END_CFD_LE); + mcr_reg); qspi_write32(priv->flags, ®s->rbct, QSPI_RBCT_RXBRD_USEIPS); to_or_from = priv->sf_addr + priv->cur_amba_base; @@ -851,136 +863,7 @@ void qspi_cfg_smpr(struct fsl_qspi_priv *priv, u32 clear_bits, u32 set_bits) smpr_val |= set_bits; qspi_write32(priv->flags, &priv->regs->smpr, smpr_val); } -#ifndef CONFIG_DM_SPI -static unsigned long spi_bases[] = { - QSPI0_BASE_ADDR, -#ifdef CONFIG_MX6SX - QSPI1_BASE_ADDR, -#endif -}; - -static unsigned long amba_bases[] = { - QSPI0_AMBA_BASE, -#ifdef CONFIG_MX6SX - QSPI1_AMBA_BASE, -#endif -}; - -static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave) -{ - return container_of(slave, struct fsl_qspi, slave); -} - -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) -{ - u32 mcr_val; - struct fsl_qspi *qspi; - struct fsl_qspi_regs *regs; - u32 total_size; - - if (bus >= ARRAY_SIZE(spi_bases)) - return NULL; - - if (cs >= FSL_QSPI_FLASH_NUM) - return NULL; - - qspi = spi_alloc_slave(struct fsl_qspi, bus, cs); - if (!qspi) - return NULL; - -#ifdef CONFIG_SYS_FSL_QSPI_BE - qspi->priv.flags |= QSPI_FLAG_REGMAP_ENDIAN_BIG; -#endif - - regs = (struct fsl_qspi_regs *)spi_bases[bus]; - qspi->priv.regs = regs; - /* - * According cs, use different amba_base to choose the - * corresponding flash devices. - * - * If not, only one flash device is used even if passing - * different cs using `sf probe` - */ - qspi->priv.cur_amba_base = amba_bases[bus] + cs * FSL_QSPI_FLASH_SIZE; - - qspi->slave.max_write_size = TX_BUFFER_SIZE; - - mcr_val = qspi_read32(qspi->priv.flags, ®s->mcr); - - /* Set endianness to LE for i.mx */ - if (IS_ENABLED(CONFIG_MX6) || IS_ENABLED(CONFIG_MX7)) - mcr_val = QSPI_MCR_END_CFD_LE; - - qspi_write32(qspi->priv.flags, ®s->mcr, - QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK | - (mcr_val & QSPI_MCR_END_CFD_MASK)); - - qspi_cfg_smpr(&qspi->priv, - ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK | - QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK), 0); - - total_size = FSL_QSPI_FLASH_SIZE * FSL_QSPI_FLASH_NUM; - /* - * Any read access to non-implemented addresses will provide - * undefined results. - * - * In case single die flash devices, TOP_ADDR_MEMA2 and - * TOP_ADDR_MEMB2 should be initialized/programmed to - * TOP_ADDR_MEMA1 and TOP_ADDR_MEMB1 respectively - in effect, - * setting the size of these devices to 0. This would ensure - * that the complete memory map is assigned to only one flash device. - */ - qspi_write32(qspi->priv.flags, ®s->sfa1ad, - FSL_QSPI_FLASH_SIZE | amba_bases[bus]); - qspi_write32(qspi->priv.flags, ®s->sfa2ad, - FSL_QSPI_FLASH_SIZE | amba_bases[bus]); - qspi_write32(qspi->priv.flags, ®s->sfb1ad, - total_size | amba_bases[bus]); - qspi_write32(qspi->priv.flags, ®s->sfb2ad, - total_size | amba_bases[bus]); - - qspi_set_lut(&qspi->priv); - -#ifdef CONFIG_SYS_FSL_QSPI_AHB - qspi_init_ahb_read(&qspi->priv); -#endif - - qspi_module_disable(&qspi->priv, 0); - - return &qspi->slave; -} - -void spi_free_slave(struct spi_slave *slave) -{ - struct fsl_qspi *qspi = to_qspi_spi(slave); - - free(qspi); -} -int spi_claim_bus(struct spi_slave *slave) -{ - return 0; -} - -void spi_release_bus(struct spi_slave *slave) -{ - /* Nothing to do */ -} - -int spi_xfer(struct spi_slave *slave, unsigned int bitlen, - const void *dout, void *din, unsigned long flags) -{ - struct fsl_qspi *qspi = to_qspi_spi(slave); - - return qspi_xfer(&qspi->priv, bitlen, dout, din, flags); -} - -void spi_init(void) -{ - /* Nothing to do */ -} -#else static int fsl_qspi_child_pre_probe(struct udevice *dev) { struct spi_slave *slave = dev_get_parent_priv(dev); @@ -992,7 +875,6 @@ static int fsl_qspi_child_pre_probe(struct udevice *dev) static int fsl_qspi_probe(struct udevice *bus) { - u32 mcr_val; u32 amba_size_per_chip; struct fsl_qspi_platdata *plat = dev_get_platdata(bus); struct fsl_qspi_priv *priv = dev_get_priv(bus); @@ -1018,26 +900,16 @@ static int fsl_qspi_probe(struct udevice *bus) priv->num_chipselect = plat->num_chipselect; /* make sure controller is not busy anywhere */ - ret = wait_for_bit_le32(&priv->regs->sr, - QSPI_SR_BUSY_MASK | - QSPI_SR_AHB_ACC_MASK | - QSPI_SR_IP_ACC_MASK, - false, 100, false); + ret = is_controller_busy(priv); if (ret) { debug("ERROR : The controller is busy\n"); return ret; } - mcr_val = qspi_read32(priv->flags, &priv->regs->mcr); - - /* Set endianness to LE for i.mx */ - if (IS_ENABLED(CONFIG_MX6) || IS_ENABLED(CONFIG_MX7)) - mcr_val = QSPI_MCR_END_CFD_LE; - qspi_write32(priv->flags, &priv->regs->mcr, QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK | - (mcr_val & QSPI_MCR_END_CFD_MASK)); + QSPI_MCR_END_CFD_LE); qspi_cfg_smpr(priv, ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK | QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK), 0); @@ -1185,11 +1057,7 @@ static int fsl_qspi_claim_bus(struct udevice *dev) priv = dev_get_priv(bus); /* make sure controller is not busy anywhere */ - ret = wait_for_bit_le32(&priv->regs->sr, - QSPI_SR_BUSY_MASK | - QSPI_SR_AHB_ACC_MASK | - QSPI_SR_IP_ACC_MASK, - false, 100, false); + ret = is_controller_busy(priv); if (ret) { debug("ERROR : The controller is busy\n"); @@ -1255,4 +1123,3 @@ U_BOOT_DRIVER(fsl_qspi) = { .probe = fsl_qspi_probe, .child_pre_probe = fsl_qspi_child_pre_probe, }; -#endif