From patchwork Fri Oct 12 07:00:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryder Lee X-Patchwork-Id: 982866 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mediatek.com Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 42Wdzd3xF8z9s2P for ; Fri, 12 Oct 2018 18:01:29 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 6B02BC21D8A; Fri, 12 Oct 2018 07:01:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: * X-Spam-Status: No, score=1.3 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED, RDNS_NONE, UNPARSEABLE_RELAY autolearn=no autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id CC6F0C21C3F; Fri, 12 Oct 2018 07:01:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id A1CABC21C57; Fri, 12 Oct 2018 07:01:18 +0000 (UTC) Received: from mailgw01.mediatek.com (unknown [210.61.82.183]) by lists.denx.de (Postfix) with ESMTP id D528EC21BE5 for ; Fri, 12 Oct 2018 07:01:16 +0000 (UTC) X-UUID: 2bcbb6f5107e4655bb607c16bef27ae9-20181012 X-UUID: 2bcbb6f5107e4655bb607c16bef27ae9-20181012 Received: from mtkmrs01.mediatek.inc [(172.21.131.159)] by mailgw01.mediatek.com (envelope-from ) (mhqrelay.mediatek.com ESMTP with TLS) with ESMTP id 564065716; Fri, 12 Oct 2018 15:01:13 +0800 Received: from mtkcas07.mediatek.inc (172.21.101.84) by mtkmbs08n1.mediatek.inc (172.21.101.55) with Microsoft SMTP Server (TLS) id 15.0.1395.4; Fri, 12 Oct 2018 15:01:13 +0800 Received: from mtkslt306.mediatek.inc (10.21.14.136) by mtkcas07.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1395.4 via Frontend Transport; Fri, 12 Oct 2018 15:01:13 +0800 From: Ryder Lee To: Tom Rini , Simon Glass , Albert Aribaud Date: Fri, 12 Oct 2018 15:00:58 +0800 Message-ID: <1f2ac4d73192ddc6c62e5903c4fa7d8e186f6666.1539326908.git.ryder.lee@mediatek.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: References: MIME-Version: 1.0 X-MTK: N Cc: Ryder Lee , Steven Liu , Roy Luo , Sean Wang , u-boot@lists.denx.de Subject: [U-Boot] [PATCH v2 09/18] watchdog: MediaTek: add watchdog driver for MediaTek SoCs X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This patch adds a common driver for the Mediatek SoC integrated watchdog. Signed-off-by: Ryder Lee Tested-by: Matthias Brugger Reviewed-by: Simon Glass --- drivers/watchdog/Kconfig | 8 +++ drivers/watchdog/Makefile | 1 + drivers/watchdog/mtk_wdt.c | 135 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 drivers/watchdog/mtk_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index d545b3e..57a12f5 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -103,6 +103,14 @@ config WDT_CDNS Select this to enable Cadence watchdog timer, which can be found on some Xilinx Microzed Platform. +config WDT_MTK + bool "MediaTek watchdog timer support" + depends on WDT && ARCH_MEDIATEK + help + Select this to enable watchdog timer for MediaTek SoCs. + The watchdog timer is stopped when initialized. + It performs full SoC reset. + config XILINX_TB_WATCHDOG bool "Xilinx Axi watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 08406ca..04fa4a6 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -23,3 +23,4 @@ obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o obj-$(CONFIG_WDT_ORION) += orion_wdt.o obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o obj-$(CONFIG_MPC8xx_WATCHDOG) += mpc8xx_wdt.o +obj-$(CONFIG_WDT_MTK) += mtk_wdt.o diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c new file mode 100644 index 0000000..0b50173 --- /dev/null +++ b/drivers/watchdog/mtk_wdt.c @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Watchdog driver for MediaTek SoCs + * + * Copyright (C) 2018 MediaTek Inc. + * Author: Ryder Lee + */ + +#include +#include +#include +#include + +#define MTK_WDT_MODE 0x00 +#define MTK_WDT_LENGTH 0x04 +#define MTK_WDT_RESTART 0x08 +#define MTK_WDT_STATUS 0x0c +#define MTK_WDT_INTERVAL 0x10 +#define MTK_WDT_SWRST 0x14 +#define MTK_WDT_REQ_MODE 0x30 +#define MTK_WDT_DEBUG_CTL 0x40 + +#define WDT_MODE_KEY (0x22 << 24) +#define WDT_MODE_EN BIT(0) +#define WDT_MODE_EXTPOL BIT(1) +#define WDT_MODE_EXTEN BIT(2) +#define WDT_MODE_IRQ_EN BIT(3) +#define WDT_MODE_DUAL_EN BIT(6) + +#define WDT_LENGTH_KEY 0x8 +#define WDT_LENGTH_TIMEOUT(n) ((n) << 5) + +#define WDT_RESTART_KEY 0x1971 +#define WDT_SWRST_KEY 0x1209 + +struct mtk_wdt_priv { + void __iomem *base; +}; + +static int mtk_wdt_reset(struct udevice *dev) +{ + struct mtk_wdt_priv *priv = dev_get_priv(dev); + + /* Reload watchdog duration */ + writel(WDT_RESTART_KEY, priv->base + MTK_WDT_RESTART); + + return 0; +} + +static int mtk_wdt_stop(struct udevice *dev) +{ + struct mtk_wdt_priv *priv = dev_get_priv(dev); + + clrsetbits_le32(priv->base + MTK_WDT_MODE, WDT_MODE_EN, WDT_MODE_KEY); + + return 0; +} + +static int mtk_wdt_expire_now(struct udevice *dev, ulong flags) +{ + struct mtk_wdt_priv *priv = dev_get_priv(dev); + + /* Kick watchdog to prevent counter == 0 */ + writel(WDT_RESTART_KEY, priv->base + MTK_WDT_RESTART); + + /* Reset */ + writel(WDT_SWRST_KEY, priv->base + MTK_WDT_SWRST); + hang(); + + return 0; +} + +static void mtk_wdt_set_timeout(struct udevice *dev, unsigned int timeout) +{ + struct mtk_wdt_priv *priv = dev_get_priv(dev); + + /* + * One bit is the value of 512 ticks + * The clock has 32 KHz + */ + timeout = WDT_LENGTH_TIMEOUT(timeout << 6) | WDT_LENGTH_KEY; + writel(timeout, priv->base + MTK_WDT_LENGTH); + + mtk_wdt_reset(dev); +} + +static int mtk_wdt_start(struct udevice *dev, u64 timeout, ulong flags) +{ + struct mtk_wdt_priv *priv = dev_get_priv(dev); + + mtk_wdt_set_timeout(dev, timeout); + + /* Enable watchdog reset signal */ + setbits_le32(priv->base + MTK_WDT_MODE, + WDT_MODE_EN | WDT_MODE_KEY | WDT_MODE_EXTEN); + + return 0; +} + +static int mtk_wdt_probe(struct udevice *dev) +{ + struct mtk_wdt_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr_ptr(dev); + if (!priv->base) + return -ENOENT; + + /* Clear status */ + clrsetbits_le32(priv->base + MTK_WDT_MODE, + WDT_MODE_IRQ_EN | WDT_MODE_EXTPOL, WDT_MODE_KEY); + + return mtk_wdt_stop(dev); +} + +static const struct wdt_ops mtk_wdt_ops = { + .start = mtk_wdt_start, + .reset = mtk_wdt_reset, + .stop = mtk_wdt_stop, + .expire_now = mtk_wdt_expire_now, +}; + +static const struct udevice_id mtk_wdt_ids[] = { + { .compatible = "mediatek,wdt"}, + {} +}; + +U_BOOT_DRIVER(mtk_wdt) = { + .name = "mtk_wdt", + .id = UCLASS_WDT, + .of_match = mtk_wdt_ids, + .priv_auto_alloc_size = sizeof(struct mtk_wdt_priv), + .probe = mtk_wdt_probe, + .ops = &mtk_wdt_ops, + .flags = DM_FLAG_PRE_RELOC, +};