aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2021-09-30 11:29:41 -0400
committerTom Rini <trini@konsulko.com>2021-09-30 11:29:41 -0400
commit8bef03683623d6a7adfff1f859ed44fad9e92ed7 (patch)
treebe2734e3581e083ce199230c259a192914651bff /drivers
parentc8988efc884c680eb4f34295df6689a7e312c15d (diff)
parentdced079c53b283e15f04282f405de410a9be584d (diff)
downloadu-boot-8bef03683623d6a7adfff1f859ed44fad9e92ed7.zip
u-boot-8bef03683623d6a7adfff1f859ed44fad9e92ed7.tar.gz
u-boot-8bef03683623d6a7adfff1f859ed44fad9e92ed7.tar.bz2
Merge tag 'xilinx-for-v2022.01-rc1' of https://source.denx.de/u-boot/custodians/u-boot-microblaze into next
Xilinx changes for v2022.01-rc1 zynq: - Enable capsule update for qspi and mmc - Update zed DT qspi compatible string zynqmp: - Add missing modeboot for EMMC - Add missing nand DT properties - List all eeproms for SC on vck190 - Add vck190 SC psu_init clk: - Handle only GATE type clock for Versal watchdog: - Update versal driver to handle system reset
Diffstat (limited to 'drivers')
-rw-r--r--drivers/clk/clk_versal.c5
-rw-r--r--drivers/mtd/spi/Kconfig2
-rw-r--r--drivers/mtd/spi/spi-nor-core.c17
-rw-r--r--drivers/watchdog/xilinx_wwdt.c100
4 files changed, 83 insertions, 41 deletions
diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c
index 62523d2..a9dd57b 100644
--- a/drivers/clk/clk_versal.c
+++ b/drivers/clk/clk_versal.c
@@ -725,7 +725,10 @@ static int versal_clk_enable(struct clk *clk)
clk_id = priv->clk[clk->id].clk_id;
- return xilinx_pm_request(PM_CLOCK_ENABLE, clk_id, 0, 0, 0, NULL);
+ if (versal_clock_gate(clk_id))
+ return xilinx_pm_request(PM_CLOCK_ENABLE, clk_id, 0, 0, 0, NULL);
+
+ return 0;
}
static struct clk_ops versal_clk_ops = {
diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig
index ddeef37..408a53f 100644
--- a/drivers/mtd/spi/Kconfig
+++ b/drivers/mtd/spi/Kconfig
@@ -57,7 +57,7 @@ config SF_DEFAULT_CS
config SF_DEFAULT_MODE
hex "SPI Flash default mode (see include/spi.h)"
depends on SPI_FLASH || DM_SPI_FLASH
- default 3
+ default 0
help
The default mode may be provided by the platform
to handle the common case when only a single serial
diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c
index d5d905f..f1b4e5e 100644
--- a/drivers/mtd/spi/spi-nor-core.c
+++ b/drivers/mtd/spi/spi-nor-core.c
@@ -10,6 +10,7 @@
*/
#include <common.h>
+#include <flash.h>
#include <log.h>
#include <watchdog.h>
#include <dm.h>
@@ -26,6 +27,7 @@
#include <linux/mtd/mtd.h>
#include <linux/mtd/spi-nor.h>
+#include <mtd/cfi_flash.h>
#include <spi-mem.h>
#include <spi.h>
@@ -3664,6 +3666,11 @@ int spi_nor_scan(struct spi_nor *nor)
struct mtd_info *mtd = &nor->mtd;
struct spi_slave *spi = nor->spi;
int ret;
+ int cfi_mtd_nb = 0;
+
+#ifdef CONFIG_SYS_MAX_FLASH_BANKS
+ cfi_mtd_nb = CONFIG_SYS_MAX_FLASH_BANKS;
+#endif
/* Reset SPI protocol for all commands. */
nor->reg_proto = SNOR_PROTO_1_1_1;
@@ -3715,8 +3722,12 @@ int spi_nor_scan(struct spi_nor *nor)
if (ret)
return ret;
- if (!mtd->name)
- mtd->name = info->name;
+ if (!mtd->name) {
+ sprintf(nor->mtd_name, "%s%d",
+ MTD_DEV_TYPE(MTD_DEV_TYPE_NOR),
+ cfi_mtd_nb + dev_seq(nor->dev));
+ mtd->name = nor->mtd_name;
+ }
mtd->dev = nor->dev;
mtd->priv = nor;
mtd->type = MTD_NORFLASH;
@@ -3821,7 +3832,7 @@ int spi_nor_scan(struct spi_nor *nor)
nor->rdsr_dummy = params.rdsr_dummy;
nor->rdsr_addr_nbytes = params.rdsr_addr_nbytes;
- nor->name = mtd->name;
+ nor->name = info->name;
nor->size = mtd->size;
nor->erase_size = mtd->erasesize;
nor->sector_size = mtd->erasesize;
diff --git a/drivers/watchdog/xilinx_wwdt.c b/drivers/watchdog/xilinx_wwdt.c
index c8e6c60..d582e3c 100644
--- a/drivers/watchdog/xilinx_wwdt.c
+++ b/drivers/watchdog/xilinx_wwdt.c
@@ -3,7 +3,7 @@
* Xilinx window watchdog timer driver.
*
* Author(s): Michal Simek <michal.simek@xilinx.com>
- * Ashok Reddy Soma <ashokred@xilinx.com>
+ * Ashok Reddy Soma <ashok.reddy.soma@xilinx.com>
*
* Copyright (c) 2020, Xilinx Inc.
*/
@@ -23,13 +23,22 @@
/* Generic Control/Status Register Masks */
#define XWT_WWCSR_GWEN_MASK BIT(0) /* Enable Bit */
-/* Register offsets for the Wdt device */
-#define XWT_WWREF_OFFSET 0x1000 /* Refresh Register */
-#define XWT_WWCSR_OFFSET 0x2000 /* Control/Status Register */
-#define XWT_WWOFF_OFFSET 0x2008 /* Offset Register */
-#define XWT_WWCMP0_OFFSET 0x2010 /* Compare Value Register0 */
-#define XWT_WWCMP1_OFFSET 0x2014 /* Compare Value Register1 */
-#define XWT_WWWRST_OFFSET 0x2FD0 /* Warm Reset Register */
+/* Register offsets for the WWDT device */
+#define XWT_WWDT_MWR_OFFSET 0x00
+#define XWT_WWDT_ESR_OFFSET 0x04
+#define XWT_WWDT_FCR_OFFSET 0x08
+#define XWT_WWDT_FWR_OFFSET 0x0c
+#define XWT_WWDT_SWR_OFFSET 0x10
+#define XWT_WWDT_CNT_MIN 1
+#define XWT_WWDT_CNT_MAX 0xffffffff
+
+/* Master Write Control Register Masks */
+#define XWT_WWDT_MWR_MASK BIT(0)
+
+/* Enable and Status Register Masks */
+#define XWT_WWDT_ESR_WINT_MASK BIT(16)
+#define XWT_WWDT_ESR_WSW_MASK BIT(8)
+#define XWT_WWDT_ESR_WEN_MASK BIT(0)
struct xlnx_wwdt_priv {
bool enable_once;
@@ -43,16 +52,23 @@ struct xlnx_wwdt_plat {
static int xlnx_wwdt_reset(struct udevice *dev)
{
+ u32 esr;
struct xlnx_wwdt_priv *wdt = dev_get_priv(dev);
- regmap_write(wdt->regs, XWT_WWREF_OFFSET, XWT_WWREF_GWRR_MASK);
+ regmap_write(wdt->regs, XWT_WWDT_MWR_OFFSET, XWT_WWDT_MWR_MASK);
+ regmap_read(wdt->regs, XWT_WWDT_ESR_OFFSET, &esr);
+ esr |= XWT_WWDT_ESR_WINT_MASK;
+ esr &= ~XWT_WWDT_ESR_WSW_MASK;
+ regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, esr);
+ regmap_read(wdt->regs, XWT_WWDT_ESR_OFFSET, &esr);
+ esr |= XWT_WWDT_ESR_WSW_MASK;
+ regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, esr);
return 0;
}
static int xlnx_wwdt_stop(struct udevice *dev)
{
- u32 csr;
struct xlnx_wwdt_priv *wdt = dev_get_priv(dev);
if (wdt->enable_once) {
@@ -60,10 +76,9 @@ static int xlnx_wwdt_stop(struct udevice *dev)
return -EBUSY;
}
- /* Disable the generic watchdog timer */
- regmap_read(wdt->regs, XWT_WWCSR_OFFSET, &csr);
- csr &= ~(XWT_WWCSR_GWEN_MASK);
- regmap_write(wdt->regs, XWT_WWCSR_OFFSET, csr);
+ /* Disable the window watchdog timer */
+ regmap_write(wdt->regs, XWT_WWDT_MWR_OFFSET, XWT_WWDT_MWR_MASK);
+ regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, ~(u32)XWT_WWDT_ESR_WEN_MASK);
clk_disable(&wdt->clk);
@@ -72,11 +87,11 @@ static int xlnx_wwdt_stop(struct udevice *dev)
return 0;
}
-static int xlnx_wwdt_start(struct udevice *dev, u64 timeout, ulong flags)
+static int xlnx_wwdt_start(struct udevice *dev, u64 timeout_ms, ulong flags)
{
int ret;
- u32 csr;
- u64 count;
+ u32 esr;
+ u64 count, timeout;
unsigned long clock_f;
struct xlnx_wwdt_priv *wdt = dev_get_priv(dev);
@@ -88,40 +103,52 @@ static int xlnx_wwdt_start(struct udevice *dev, u64 timeout, ulong flags)
dev_dbg(dev, "%s: CLK %ld\n", __func__, clock_f);
+ /* Convert timeout from msec to sec */
+ timeout = timeout_ms / 1000;
+
/* Calculate timeout count */
count = timeout * clock_f;
+ /* Count should be at least 1 */
+ if (count < XWT_WWDT_CNT_MIN) {
+ debug("%s: watchdog won't fire with 0 ticks\n", __func__);
+ count = XWT_WWDT_CNT_MIN;
+ }
+
+ /* Limit the count to maximum possible value */
+ if (count > XWT_WWDT_CNT_MAX) {
+ debug("%s: maximum watchdog timeout exceeded\n", __func__);
+ count = XWT_WWDT_CNT_MAX;
+ }
+
ret = clk_enable(&wdt->clk);
if (ret) {
dev_err(dev, "failed to enable clock\n");
return ret;
}
- /*
- * Timeout count is half as there are two windows
- * first window overflow is ignored (interrupt),
- * reset is only generated at second window overflow
- */
- count = count >> 1;
-
- /* Disable the generic watchdog timer */
- regmap_read(wdt->regs, XWT_WWCSR_OFFSET, &csr);
- csr &= ~(XWT_WWCSR_GWEN_MASK);
- regmap_write(wdt->regs, XWT_WWCSR_OFFSET, csr);
+ /* Disable the window watchdog timer */
+ regmap_write(wdt->regs, XWT_WWDT_MWR_OFFSET, XWT_WWDT_MWR_MASK);
+ regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, ~(u32)XWT_WWDT_ESR_WEN_MASK);
- /* Set compare and offset registers for generic watchdog timeout */
- regmap_write(wdt->regs, XWT_WWCMP0_OFFSET, (u32)count);
- regmap_write(wdt->regs, XWT_WWCMP1_OFFSET, 0);
- regmap_write(wdt->regs, XWT_WWOFF_OFFSET, (u32)count);
+ /* Set first window and second window registers with timeout */
+ regmap_write(wdt->regs, XWT_WWDT_FWR_OFFSET, 0); /* No pre-timeout */
+ regmap_write(wdt->regs, XWT_WWDT_SWR_OFFSET, (u32)count);
+ regmap_write(wdt->regs, XWT_WWDT_FCR_OFFSET, 0);
- /* Enable the generic watchdog timer */
- regmap_read(wdt->regs, XWT_WWCSR_OFFSET, &csr);
- csr |= (XWT_WWCSR_GWEN_MASK);
- regmap_write(wdt->regs, XWT_WWCSR_OFFSET, csr);
+ /* Enable the window watchdog timer */
+ regmap_read(wdt->regs, XWT_WWDT_ESR_OFFSET, &esr);
+ esr |= XWT_WWDT_ESR_WEN_MASK;
+ regmap_write(wdt->regs, XWT_WWDT_ESR_OFFSET, esr);
return 0;
}
+static int xlnx_wwdt_expire_now(struct udevice *dev, ulong flags)
+{
+ return xlnx_wwdt_start(dev, XWT_WWDT_CNT_MIN, flags);
+}
+
static int xlnx_wwdt_probe(struct udevice *dev)
{
int ret;
@@ -160,6 +187,7 @@ static const struct wdt_ops xlnx_wwdt_ops = {
.start = xlnx_wwdt_start,
.reset = xlnx_wwdt_reset,
.stop = xlnx_wwdt_stop,
+ .expire_now = xlnx_wwdt_expire_now,
};
static const struct udevice_id xlnx_wwdt_ids[] = {