Add UCLASS_TEE for Trusted Execution Environment
[oweals/u-boot.git] / drivers / spi / stm32_qspi.c
index 4bc4455d2ef99155cbd675d2a553741c71308d6f..3b92254a5ce16adb668ced4e3038a2b5102dd643 100644 (file)
 #include <dm.h>
 #include <errno.h>
 #include <malloc.h>
+#include <reset.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <asm/io.h>
 #include <asm/arch/stm32.h>
-
-DECLARE_GLOBAL_DATA_PTR;
+#include <linux/ioport.h>
 
 struct stm32_qspi_regs {
        u32 cr;         /* 0x00 */
@@ -155,6 +155,8 @@ enum STM32_QSPI_CCR_FMODE {
 /* default SCK frequency, unit: HZ */
 #define STM32_QSPI_DEFAULT_SCK_FREQ 108000000
 
+#define STM32_MAX_NORCHIP 2
+
 struct stm32_qspi_platdata {
        u32 base;
        u32 memory_map;
@@ -212,7 +214,13 @@ static void _stm32_qspi_set_flash_size(struct stm32_qspi_priv *priv, u32 size)
                        fsize << STM32_QSPI_DCR_FSIZE_SHIFT);
 }
 
-static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv)
+static void _stm32_qspi_set_cs(struct stm32_qspi_priv *priv, unsigned int cs)
+{
+       clrsetbits_le32(&priv->regs->cr, STM32_QSPI_CR_FSEL,
+                       cs ? STM32_QSPI_CR_FSEL : 0);
+}
+
+static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv, u8 fmode)
 {
        unsigned int ccr_reg = 0;
        u8 imode, admode, dmode;
@@ -221,21 +229,21 @@ static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv)
 
        imode = STM32_QSPI_CCR_IMODE_ONE_LINE;
        admode = STM32_QSPI_CCR_ADMODE_ONE_LINE;
-
-       if (mode & SPI_RX_QUAD) {
-               dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE;
-               if (mode & SPI_TX_QUAD) {
-                       imode = STM32_QSPI_CCR_IMODE_FOUR_LINE;
-                       admode = STM32_QSPI_CCR_ADMODE_FOUR_LINE;
-               }
-       } else if (mode & SPI_RX_DUAL) {
-               dmode = STM32_QSPI_CCR_DMODE_TWO_LINE;
-               if (mode & SPI_TX_DUAL) {
-                       imode = STM32_QSPI_CCR_IMODE_TWO_LINE;
-                       admode = STM32_QSPI_CCR_ADMODE_TWO_LINE;
+       dmode = STM32_QSPI_CCR_DMODE_ONE_LINE;
+
+       if ((priv->command & CMD_HAS_ADR) && (priv->command & CMD_HAS_DATA)) {
+               if (fmode == STM32_QSPI_CCR_IND_WRITE) {
+                       if (mode & SPI_TX_QUAD)
+                               dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE;
+                       else if (mode & SPI_TX_DUAL)
+                               dmode = STM32_QSPI_CCR_DMODE_TWO_LINE;
+               } else if ((fmode == STM32_QSPI_CCR_MEM_MAP) ||
+                        (fmode == STM32_QSPI_CCR_IND_READ)) {
+                       if (mode & SPI_RX_QUAD)
+                               dmode = STM32_QSPI_CCR_DMODE_FOUR_LINE;
+                       else if (mode & SPI_RX_DUAL)
+                               dmode = STM32_QSPI_CCR_DMODE_TWO_LINE;
                }
-       } else {
-               dmode = STM32_QSPI_CCR_DMODE_ONE_LINE;
        }
 
        if (priv->command & CMD_HAS_DATA)
@@ -250,8 +258,11 @@ static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv)
                                << STM32_QSPI_CCR_ADSIZE_SHIFT);
                ccr_reg |= (admode << STM32_QSPI_CCR_ADMODE_SHIFT);
        }
+
+       ccr_reg |= (fmode << STM32_QSPI_CCR_FMODE_SHIFT);
        ccr_reg |= (imode << STM32_QSPI_CCR_IMODE_SHIFT);
        ccr_reg |= cmd;
+
        return ccr_reg;
 }
 
@@ -264,8 +275,7 @@ static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv,
                        | CMD_HAS_DUMMY;
        priv->dummycycles = flash->dummy_byte * 8;
 
-       ccr_reg = _stm32_qspi_gen_ccr(priv);
-       ccr_reg |= (STM32_QSPI_CCR_MEM_MAP << STM32_QSPI_CCR_FMODE_SHIFT);
+       ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_MEM_MAP);
 
        _stm32_qspi_wait_for_not_busy(priv);
 
@@ -351,9 +361,8 @@ static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
                }
 
                if (flags & SPI_XFER_END) {
-                       ccr_reg = _stm32_qspi_gen_ccr(priv);
-                       ccr_reg |= STM32_QSPI_CCR_IND_WRITE
-                                       << STM32_QSPI_CCR_FMODE_SHIFT;
+                       ccr_reg = _stm32_qspi_gen_ccr(priv,
+                                                     STM32_QSPI_CCR_IND_WRITE);
 
                        _stm32_qspi_wait_for_not_busy(priv);
 
@@ -384,9 +393,7 @@ static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
                        }
                }
        } else if (din) {
-               ccr_reg = _stm32_qspi_gen_ccr(priv);
-               ccr_reg |= STM32_QSPI_CCR_IND_READ
-                               << STM32_QSPI_CCR_FMODE_SHIFT;
+               ccr_reg = _stm32_qspi_gen_ccr(priv, STM32_QSPI_CCR_IND_READ);
 
                _stm32_qspi_wait_for_not_busy(priv);
 
@@ -413,27 +420,23 @@ static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
 
 static int stm32_qspi_ofdata_to_platdata(struct udevice *bus)
 {
-       struct fdt_resource res_regs, res_mem;
+       struct resource res_regs, res_mem;
        struct stm32_qspi_platdata *plat = bus->platdata;
-       const void *blob = gd->fdt_blob;
-       int node = dev_of_offset(bus);
        int ret;
 
-       ret = fdt_get_named_resource(blob, node, "reg", "reg-names",
-                                    "QuadSPI", &res_regs);
+       ret = dev_read_resource_byname(bus, "qspi", &res_regs);
        if (ret) {
                debug("Error: can't get regs base addresses(ret = %d)!\n", ret);
                return -ENOMEM;
        }
-       ret = fdt_get_named_resource(blob, node, "reg", "reg-names",
-                                    "QuadSPI-memory", &res_mem);
+       ret = dev_read_resource_byname(bus, "qspi_mm", &res_mem);
        if (ret) {
                debug("Error: can't get mmap base address(ret = %d)!\n", ret);
                return -ENOMEM;
        }
 
-       plat->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency",
-                                       STM32_QSPI_DEFAULT_SCK_FREQ);
+       plat->max_hz = dev_read_u32_default(bus, "spi-max-frequency",
+                                           STM32_QSPI_DEFAULT_SCK_FREQ);
 
        plat->base = res_regs.start;
        plat->memory_map = res_mem.start;
@@ -454,6 +457,7 @@ static int stm32_qspi_probe(struct udevice *bus)
        struct stm32_qspi_priv *priv = dev_get_priv(bus);
        struct dm_spi_bus *dm_spi_bus;
        struct clk clk;
+       struct reset_ctl reset_ctl;
        int ret;
 
        dm_spi_bus = bus->uclass_priv;
@@ -481,6 +485,19 @@ static int stm32_qspi_probe(struct udevice *bus)
                return priv->clock_rate;
        }
 
+       ret = reset_get_by_index(bus, 0, &reset_ctl);
+       if (ret) {
+               if (ret != -ENOENT) {
+                       dev_err(bus, "failed to get reset\n");
+                       clk_disable(&clk);
+                       return ret;
+               }
+       } else {
+               /* Reset QSPI controller */
+               reset_assert(&reset_ctl);
+               udelay(2);
+               reset_deassert(&reset_ctl);
+       }
 
        setbits_le32(&priv->regs->cr, STM32_QSPI_CR_SSHIFT);
 
@@ -497,10 +514,17 @@ static int stm32_qspi_claim_bus(struct udevice *dev)
        struct stm32_qspi_priv *priv;
        struct udevice *bus;
        struct spi_flash *flash;
+       struct dm_spi_slave_platdata *slave_plat;
 
        bus = dev->parent;
        priv = dev_get_priv(bus);
        flash = dev_get_uclass_priv(dev);
+       slave_plat = dev_get_parent_platdata(dev);
+
+       if (slave_plat->cs >= STM32_MAX_NORCHIP)
+               return -ENODEV;
+
+       _stm32_qspi_set_cs(priv, slave_plat->cs);
 
        _stm32_qspi_set_flash_size(priv, flash->size);
 
@@ -635,6 +659,7 @@ static const struct dm_spi_ops stm32_qspi_ops = {
 
 static const struct udevice_id stm32_qspi_ids[] = {
        { .compatible = "st,stm32-qspi" },
+       { .compatible = "st,stm32f469-qspi" },
        { }
 };