]> git.sur5r.net Git - u-boot/blobdiff - drivers/spi/ti_qspi.c
Merge git://git.denx.de/u-boot-mips
[u-boot] / drivers / spi / ti_qspi.c
index 1e2c432ede66b04b13a4991acd8de16531cedd50..bea3aff943196bd3dd8415bd4addb3960534d617 100644 (file)
@@ -16,6 +16,9 @@
 #include <asm/omap_gpio.h>
 #include <asm/omap_common.h>
 #include <asm/ti-common/ti-edma3.h>
+#include <linux/kernel.h>
+#include <regmap.h>
+#include <syscon.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -118,21 +121,18 @@ static void ti_spi_set_speed(struct ti_qspi_priv *priv, uint hz)
        if (!hz)
                clk_div = 0;
        else
-               clk_div = (priv->fclk / hz) - 1;
+               clk_div = DIV_ROUND_UP(priv->fclk, hz) - 1;
+
+       /* truncate clk_div value to QSPI_CLK_DIV_MAX */
+       if (clk_div > QSPI_CLK_DIV_MAX)
+               clk_div = QSPI_CLK_DIV_MAX;
 
        debug("ti_spi_set_speed: hz: %d, clock divider %d\n", hz, clk_div);
 
        /* disable SCLK */
        writel(readl(&priv->base->clk_ctrl) & ~QSPI_CLK_EN,
               &priv->base->clk_ctrl);
-
-       /* assign clk_div values */
-       if (clk_div < 0)
-               clk_div = 0;
-       else if (clk_div > QSPI_CLK_DIV_MAX)
-               clk_div = QSPI_CLK_DIV_MAX;
-
-       /* enable SCLK */
+       /* enable SCLK and program the clk divider */
        writel(QSPI_CLK_EN | clk_div, &priv->base->clk_ctrl);
 }
 
@@ -226,13 +226,6 @@ static int __ti_qspi_xfer(struct ti_qspi_priv *priv, unsigned int bitlen,
                priv->cmd |= QSPI_3_PIN;
        priv->cmd |= 0xfff;
 
-/* FIXME: This delay is required for successfull
- * completion of read/write/erase. Once its root
- * caused, it will be remove from the driver.
- */
-#ifdef CONFIG_AM43XX
-       udelay(100);
-#endif
        while (words) {
                u8 xfer_len = 0;
 
@@ -363,7 +356,7 @@ static void ti_spi_setup_spi_register(struct ti_qspi_priv *priv)
                        QSPI_SETUP0_NUM_D_BYTES_8_BITS |
                        QSPI_SETUP0_READ_QUAD | QSPI_CMD_WRITE |
                        QSPI_NUM_DUMMY_BITS);
-       slave->mode_rx = SPI_RX_QUAD;
+       slave->mode |= SPI_RX_QUAD;
 #else
        memval |= QSPI_CMD_READ | QSPI_SETUP0_NUM_A_BYTES |
                        QSPI_SETUP0_NUM_D_BYTES_NO_BITS |
@@ -392,7 +385,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
        priv->base = (struct ti_qspi_regs *)QSPI_BASE;
        priv->mode = mode;
-#if defined(CONFIG_DRA7XX) || defined(CONFIG_AM57XX)
+#if defined(CONFIG_DRA7XX)
        priv->ctrl_mod_mmap = (void *)CORE_CTRL_IO;
        priv->slave.memory_map = (void *)MMAP_START_ADDR_DRA;
        priv->fclk = QSPI_DRA7XX_FCLK;
@@ -449,7 +442,7 @@ static void __ti_qspi_setup_memorymap(struct ti_qspi_priv *priv,
                                      bool enable)
 {
        u32 memval;
-       u32 mode = slave->mode_rx & (SPI_RX_QUAD | SPI_RX_DUAL);
+       u32 mode = slave->mode & (SPI_RX_QUAD | SPI_RX_DUAL);
 
        if (!enable) {
                writel(0, &priv->base->setup0);
@@ -463,7 +456,7 @@ static void __ti_qspi_setup_memorymap(struct ti_qspi_priv *priv,
                memval |= QSPI_CMD_READ_QUAD;
                memval |= QSPI_SETUP0_NUM_D_BYTES_8_BITS;
                memval |= QSPI_SETUP0_READ_QUAD;
-               slave->mode_rx = SPI_RX_QUAD;
+               slave->mode |= SPI_RX_QUAD;
                break;
        case SPI_RX_DUAL:
                memval |= QSPI_CMD_READ_DUAL;
@@ -558,21 +551,56 @@ static int ti_qspi_probe(struct udevice *bus)
        return 0;
 }
 
+static void *map_syscon_chipselects(struct udevice *bus)
+{
+#if CONFIG_IS_ENABLED(SYSCON)
+       struct udevice *syscon;
+       struct regmap *regmap;
+       const fdt32_t *cell;
+       int len, err;
+
+       err = uclass_get_device_by_phandle(UCLASS_SYSCON, bus,
+                                          "syscon-chipselects", &syscon);
+       if (err) {
+               debug("%s: unable to find syscon device (%d)\n", __func__,
+                     err);
+               return NULL;
+       }
+
+       regmap = syscon_get_regmap(syscon);
+       if (IS_ERR(regmap)) {
+               debug("%s: unable to find regmap (%ld)\n", __func__,
+                     PTR_ERR(regmap));
+               return NULL;
+       }
+
+       cell = fdt_getprop(gd->fdt_blob, dev_of_offset(bus),
+                          "syscon-chipselects", &len);
+       if (len < 2*sizeof(fdt32_t)) {
+               debug("%s: offset not available\n", __func__);
+               return NULL;
+       }
+
+       return fdtdec_get_number(cell + 1, 1) + regmap_get_range(regmap, 0);
+#else
+       fdt_addr_t addr;
+       addr = devfdt_get_addr_index(bus, 2);
+       return (addr == FDT_ADDR_T_NONE) ? NULL :
+               map_physmem(addr, 0, MAP_NOCACHE);
+#endif
+}
+
 static int ti_qspi_ofdata_to_platdata(struct udevice *bus)
 {
        struct ti_qspi_priv *priv = dev_get_priv(bus);
        const void *blob = gd->fdt_blob;
-       int node = bus->of_offset;
-       fdt_addr_t addr;
-       void *mmap;
+       int node = dev_of_offset(bus);
 
-       priv->base = map_physmem(dev_get_addr(bus), sizeof(struct ti_qspi_regs),
-                                MAP_NOCACHE);
-       priv->memory_map = map_physmem(dev_get_addr_index(bus, 1), 0,
+       priv->ctrl_mod_mmap = map_syscon_chipselects(bus);
+       priv->base = map_physmem(devfdt_get_addr(bus),
+                                sizeof(struct ti_qspi_regs), MAP_NOCACHE);
+       priv->memory_map = map_physmem(devfdt_get_addr_index(bus, 1), 0,
                                       MAP_NOCACHE);
-       addr = dev_get_addr_index(bus, 2);
-       mmap = map_physmem(dev_get_addr_index(bus, 2), 0, MAP_NOCACHE);
-       priv->ctrl_mod_mmap = (addr == FDT_ADDR_T_NONE) ? NULL : mmap;
 
        priv->max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", -1);
        if (priv->max_hz < 0) {