]> git.sur5r.net Git - u-boot/blobdiff - drivers/spi/stm32_qspi.c
spi: stm32_qspi: Add reset support
[u-boot] / drivers / spi / stm32_qspi.c
index 05358ebf4cd1bbb7512acf7d4049b53e60dd6191..f6cc35336320ce1ec0e5cba4e9f0879e1d34b39d 100644 (file)
@@ -1,24 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * (C) Copyright 2016
  *
  * Michael Kurz, <michi.kurz@gmail.com>
  *
  * STM32 QSPI driver
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <errno.h>
 #include <malloc.h>
+#include <reset.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <asm/io.h>
-#include <dm.h>
-#include <errno.h>
 #include <asm/arch/stm32.h>
-#include <asm/arch/stm32_defs.h>
-
-DECLARE_GLOBAL_DATA_PTR;
+#include <linux/ioport.h>
 
 struct stm32_qspi_regs {
        u32 cr;         /* 0x00 */
@@ -156,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;
@@ -164,6 +165,7 @@ struct stm32_qspi_platdata {
 
 struct stm32_qspi_priv {
        struct stm32_qspi_regs *regs;
+       ulong clock_rate;
        u32 max_hz;
        u32 mode;
 
@@ -206,11 +208,18 @@ static void _stm32_qspi_wait_for_ftf(struct stm32_qspi_priv *priv)
 static void _stm32_qspi_set_flash_size(struct stm32_qspi_priv *priv, u32 size)
 {
        u32 fsize = fls(size) - 1;
+
        clrsetbits_le32(&priv->regs->dcr,
                        STM32_QSPI_DCR_FSIZE_MASK << STM32_QSPI_DCR_FSIZE_SHIFT,
                        fsize << STM32_QSPI_DCR_FSIZE_SHIFT);
 }
 
+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)
 {
        unsigned int ccr_reg = 0;
@@ -255,13 +264,15 @@ static unsigned int _stm32_qspi_gen_ccr(struct stm32_qspi_priv *priv)
 }
 
 static void _stm32_qspi_enable_mmap(struct stm32_qspi_priv *priv,
-               struct spi_flash *flash)
+                                   struct spi_flash *flash)
 {
+       unsigned int ccr_reg;
+
        priv->command = flash->read_cmd | CMD_HAS_ADR | CMD_HAS_DATA
                        | CMD_HAS_DUMMY;
        priv->dummycycles = flash->dummy_byte * 8;
 
-       unsigned int ccr_reg = _stm32_qspi_gen_ccr(priv);
+       ccr_reg = _stm32_qspi_gen_ccr(priv);
        ccr_reg |= (STM32_QSPI_CCR_MEM_MAP << STM32_QSPI_CCR_FMODE_SHIFT);
 
        _stm32_qspi_wait_for_not_busy(priv);
@@ -291,10 +302,12 @@ static void _stm32_qspi_start_xfer(struct stm32_qspi_priv *priv, u32 cr_reg)
 }
 
 static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
-               struct spi_flash *flash, unsigned int bitlen,
-               const u8 *dout, u8 *din, unsigned long flags)
+                           struct spi_flash *flash, unsigned int bitlen,
+                           const u8 *dout, u8 *din, unsigned long flags)
 {
        unsigned int words = bitlen / 8;
+       u32 ccr_reg;
+       int i;
 
        if (flags & SPI_XFER_MMAP) {
                _stm32_qspi_enable_mmap(priv, flash);
@@ -346,7 +359,7 @@ static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
                }
 
                if (flags & SPI_XFER_END) {
-                       u32 ccr_reg = _stm32_qspi_gen_ccr(priv);
+                       ccr_reg = _stm32_qspi_gen_ccr(priv);
                        ccr_reg |= STM32_QSPI_CCR_IND_WRITE
                                        << STM32_QSPI_CCR_FMODE_SHIFT;
 
@@ -365,7 +378,7 @@ static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
 
                                debug("%s: words:%d data:", __func__, words);
 
-                               int i = 0;
+                               i = 0;
                                while (words > i) {
                                        writeb(dout[i], &priv->regs->dr);
                                        debug("%02x ", dout[i]);
@@ -379,7 +392,7 @@ static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
                        }
                }
        } else if (din) {
-               u32 ccr_reg = _stm32_qspi_gen_ccr(priv);
+               ccr_reg = _stm32_qspi_gen_ccr(priv);
                ccr_reg |= STM32_QSPI_CCR_IND_READ
                                << STM32_QSPI_CCR_FMODE_SHIFT;
 
@@ -394,7 +407,7 @@ static int _stm32_qspi_xfer(struct stm32_qspi_priv *priv,
 
                debug("%s: data:", __func__);
 
-               int i = 0;
+               i = 0;
                while (words > i) {
                        din[i] = readb(&priv->regs->dr);
                        debug("%02x ", din[i]);
@@ -408,27 +421,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;
@@ -448,6 +457,9 @@ static int stm32_qspi_probe(struct udevice *bus)
        struct stm32_qspi_platdata *plat = dev_get_platdata(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;
 
@@ -457,7 +469,36 @@ static int stm32_qspi_probe(struct udevice *bus)
 
        priv->max_hz = plat->max_hz;
 
-       clock_setup(QSPI_CLOCK_CFG);
+       ret = clk_get_by_index(bus, 0, &clk);
+       if (ret < 0)
+               return ret;
+
+       ret = clk_enable(&clk);
+
+       if (ret) {
+               dev_err(bus, "failed to enable clock\n");
+               return ret;
+       }
+
+       priv->clock_rate = clk_get_rate(&clk);
+       if (priv->clock_rate < 0) {
+               clk_disable(&clk);
+               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);
 
@@ -474,10 +515,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);
 
@@ -500,7 +548,7 @@ static int stm32_qspi_release_bus(struct udevice *dev)
 }
 
 static int stm32_qspi_xfer(struct udevice *dev, unsigned int bitlen,
-               const void *dout, void *din, unsigned long flags)
+                          const void *dout, void *din, unsigned long flags)
 {
        struct stm32_qspi_priv *priv;
        struct udevice *bus;
@@ -518,12 +566,13 @@ static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
 {
        struct stm32_qspi_platdata *plat = bus->platdata;
        struct stm32_qspi_priv *priv = dev_get_priv(bus);
+       u32 qspi_clk = priv->clock_rate;
+       u32 prescaler = 255;
+       u32 csht;
 
        if (speed > plat->max_hz)
                speed = plat->max_hz;
 
-       u32 qspi_clk = clock_get(CLOCK_AHB);
-       u32 prescaler = 255;
        if (speed > 0) {
                prescaler = DIV_ROUND_UP(qspi_clk, speed) - 1;
                if (prescaler > 255)
@@ -532,7 +581,7 @@ static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
                        prescaler = 0;
        }
 
-       u32 csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000);
+       csht = DIV_ROUND_UP((5 * qspi_clk) / (prescaler + 1), 100000000);
        csht = (csht - 1) & STM32_QSPI_DCR_CSHT_MASK;
 
        _stm32_qspi_wait_for_not_busy(priv);
@@ -542,7 +591,6 @@ static int stm32_qspi_set_speed(struct udevice *bus, uint speed)
                        STM32_QSPI_CR_PRESCALER_SHIFT,
                        prescaler << STM32_QSPI_CR_PRESCALER_SHIFT);
 
-
        clrsetbits_le32(&priv->regs->dcr,
                        STM32_QSPI_DCR_CSHT_MASK << STM32_QSPI_DCR_CSHT_SHIFT,
                        csht << STM32_QSPI_DCR_CSHT_SHIFT);
@@ -612,6 +660,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" },
        { }
 };