From patchwork Thu Dec 14 15:04:12 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elad Nachman X-Patchwork-Id: 754824 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="RjOwJMpS" Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 89B4A124; Thu, 14 Dec 2023 07:05:24 -0800 (PST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 3BE9LVwZ002218; Thu, 14 Dec 2023 07:04:28 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=4Vrpl3GKq0ZVGwiSMqAGII/gJtRkuWeqYblf7IvmvjA=; b=RjO wJMpSS2S3x9syhPon6RWbnCbMFltFFsQXNj+yVIXlbEVQOfMO7HBfDHjtqXvEYKb PRB+d6OpWZy2PM4nTd/SVceKsQhZwv5ez32SgDEk5+cWuK5rMvzD5lSeKqW0Yy2o GzqFCP2t/yDv1tK1EapaBrrBg/Cl90KqLKH+86OgsJS1MQuyUAOYZ18vCpt4QixG V5AoN+tWnYVXChUprGcymqwavK5msLAG5jTuxYqAFmuL/V1fDCSM8hpN3o3YINPd sJ0so/CVjlQznki/uWW3A/KqfaRkoCgadsgyKR80cnJGa1TLIkcIiOhrQJBE3SKH 4l0gI5O8OZRRYInh8Pg== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3uyy0m93tf-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 14 Dec 2023 07:04:27 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Thu, 14 Dec 2023 07:04:25 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Thu, 14 Dec 2023 07:04:25 -0800 Received: from dc3lp-swdev041.marvell.com (dc3lp-swdev041.marvell.com [10.6.60.191]) by maili.marvell.com (Postfix) with ESMTP id 88A283F7074; Thu, 14 Dec 2023 07:04:21 -0800 (PST) From: Elad Nachman To: , , , , , , , , , , , , , , CC: , Subject: [PATCH 1/3] dt-bindings: watchdog: add Marvell AC5 watchdog Date: Thu, 14 Dec 2023 17:04:12 +0200 Message-ID: <20231214150414.1849058-2-enachman@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231214150414.1849058-1-enachman@marvell.com> References: <20231214150414.1849058-1-enachman@marvell.com> Precedence: bulk X-Mailing-List: linux-watchdog@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-GUID: 9rMqeby1yL3v-5cQjbDFjlyjx1Mq44Mf X-Proofpoint-ORIG-GUID: 9rMqeby1yL3v-5cQjbDFjlyjx1Mq44Mf X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-09_02,2023-12-07_01,2023-05-22_02 From: Elad Nachman Add definitions and examples for Marvell AC5 variant of the sbsa watchdog. Marvell variant requires more memory definitions, since the initialization is more complex, and involves several register sets. Signed-off-by: Elad Nachman --- .../bindings/watchdog/arm,sbsa-gwdt.yaml | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/watchdog/arm,sbsa-gwdt.yaml b/Documentation/devicetree/bindings/watchdog/arm,sbsa-gwdt.yaml index aa804f96acba..331e9aa7c2f7 100644 --- a/Documentation/devicetree/bindings/watchdog/arm,sbsa-gwdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/arm,sbsa-gwdt.yaml @@ -20,12 +20,17 @@ allOf: properties: compatible: - const: arm,sbsa-gwdt + enum: + - arm,sbsa-gwdt + - marvell,ac5-wd reg: items: - description: Watchdog control frame - description: Refresh frame + - description: Marvell CPU control frame + - description: Marvell Management frame + - description: Marvell reset control unit frame interrupts: description: The Watchdog Signal 0 (WS0) SPI (Shared Peripheral Interrupt) @@ -39,12 +44,55 @@ required: unevaluatedProperties: false examples: + # First example is for generic ARM one + # Next examples are for Marvell. + # They are organized as three sets: + # first set is for global watchdog, then CPU core #0 private watchdog, + # and finally CPU core #1 private watchdog + # Examples are given for AC5 or Ironman. For AC5X SOC, the last + # reg item's low address (0x840F8000) should be replaced with 0x944F8000 - | watchdog@2a440000 { compatible = "arm,sbsa-gwdt"; reg = <0x2a440000 0x1000>, - <0x2a450000 0x1000>; + <0x2a450000 0x1000>, + <0x0 0x0>, + <0x0 0x0>, + <0x0 0x0>; interrupts = <0 27 4>; timeout-sec = <30>; }; + - | + watchdog@80216000 { + compatible = "marvell,ac5-wd"; + reg = <0x80216000 0x1000>, + <0x80215000 0x1000>, + <0x80210000 0x1000>, + <0x7f900000 0x1000>, + <0x840F8000 0x1000>; + interrupts = <0 124 4>; + timeout-sec = <30>; + }; + - | + watchdog@80212000 { + compatible = "marvell,ac5-wd"; + reg = <0x80212000 0x1000>, + <0x80211000 0x1000>, + <0x80210000 0x1000>, + <0x7f900000 0x1000>, + <0x840F8000 0x1000>; + interrupts = <0 122 4>; + timeout-sec = <30>; + }; + - | + watchdog@80214000 { + compatible = "marvell,ac5-wd"; + reg = <0x80214000 0x1000>, + <0x80213000 0x1000>, + <0x80210000 0x1000>, + <0x7f900000 0x1000>, + <0x840F8000 0x1000>; + interrupts = <0 122 4>; + timeout-sec = <30>; + }; ... From patchwork Thu Dec 14 15:04:13 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elad Nachman X-Patchwork-Id: 754823 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="KNalxmWA" Received: from mx0b-0016f401.pphosted.com (mx0b-0016f401.pphosted.com [67.231.156.173]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AF818182; Thu, 14 Dec 2023 07:05:33 -0800 (PST) Received: from pps.filterd (m0045851.ppops.net [127.0.0.1]) by mx0b-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 3BE9Lqc6016870; Thu, 14 Dec 2023 07:04:32 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=c+KSLbDoDzpXnRUguZfTCy+EBnWOgf+TQnT2K6R3LKc=; b=KNa lxmWAXOd2Z4cYooSU5UCtf3PO774y0Mpc9PkE4XoVZrZUj0PSSHpbot/y+pk9jiB whkfReFVAQIp78sc0reuHsQf3gk6P+a2Wm76KWcNxWZfEEkJQrw9ND8ODxUO6GUO aagoSAllXNICFW5jnE8gPkeWQ4isfJyf7BZt4rf8tFBeMaVflYIBBF40DjejL3eg BzMzsKJKqvA+Ukbul/IPZkMPTjgwkxspihWiiYogwSlfd42bH1JqtTReNV/PFfi4 0lb4lSH2AR1EhTwBM6DtXIrZoWTXe5NYGPg7U8ijkd9abovX6aHtqI2U9hjO/uiu ubiZpdI1A9W1MTP/JuQ== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0b-0016f401.pphosted.com (PPS) with ESMTPS id 3uyy0ns36f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 14 Dec 2023 07:04:31 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Thu, 14 Dec 2023 07:04:30 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Thu, 14 Dec 2023 07:04:30 -0800 Received: from dc3lp-swdev041.marvell.com (dc3lp-swdev041.marvell.com [10.6.60.191]) by maili.marvell.com (Postfix) with ESMTP id 0B7813F7077; Thu, 14 Dec 2023 07:04:25 -0800 (PST) From: Elad Nachman To: , , , , , , , , , , , , , , CC: , Subject: [PATCH 2/3] arm64: dts: ac5: add watchdog nodes Date: Thu, 14 Dec 2023 17:04:13 +0200 Message-ID: <20231214150414.1849058-3-enachman@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231214150414.1849058-1-enachman@marvell.com> References: <20231214150414.1849058-1-enachman@marvell.com> Precedence: bulk X-Mailing-List: linux-watchdog@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-ORIG-GUID: HFPwXkbmfHwAQFdtlK6yVdicb1PU5u_d X-Proofpoint-GUID: HFPwXkbmfHwAQFdtlK6yVdicb1PU5u_d X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-09_02,2023-12-07_01,2023-05-22_02 From: Elad Nachman Add watchdog nodes to ac5 and ac5x device tree files Signed-off-by: Elad Nachman --- arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi | 14 ++++++++++++++ arch/arm64/boot/dts/marvell/ac5-98dx35xx.dtsi | 8 ++++++++ 2 files changed, 22 insertions(+) diff --git a/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi b/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi index b5e042b8e929..e898c6bd31f0 100644 --- a/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi +++ b/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi @@ -307,6 +307,20 @@ nand: nand-controller@805b0000 { status = "disabled"; }; +/* + * Global Watchdog: + */ + watchdog: watchdog@80216000 { + compatible = "marvell,ac5-wd"; + reg = <0x0 0x80216000 0 0x1000>, + <0x0 0x80215000 0 0x1000>, + <0x0 0x80210000 0 0x1000>, + <0x0 0x7f900000 0 0x1000>, + <0x0 0x840F8000 0 0x1000>; + interrupts = ; + timeout-sec = <30>; + }; + gic: interrupt-controller@80600000 { compatible = "arm,gic-v3"; #interrupt-cells = <3>; diff --git a/arch/arm64/boot/dts/marvell/ac5-98dx35xx.dtsi b/arch/arm64/boot/dts/marvell/ac5-98dx35xx.dtsi index 2ab72f854bea..d850c30db552 100644 --- a/arch/arm64/boot/dts/marvell/ac5-98dx35xx.dtsi +++ b/arch/arm64/boot/dts/marvell/ac5-98dx35xx.dtsi @@ -15,3 +15,11 @@ / { &cnm_clock { clock-frequency = <325000000>; }; + +&watchdog { + reg = <0x0 0x80216000 0 0x1000>, + <0x0 0x80215000 0 0x1000>, + <0x0 0x80210000 0 0x1000>, + <0x0 0x7f900000 0 0x1000>, + <0x0 0x944F8000 0 0x1000>; +}; From patchwork Thu Dec 14 15:04:14 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Elad Nachman X-Patchwork-Id: 754314 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=marvell.com header.i=@marvell.com header.b="bz7DLXRq" Received: from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com [67.231.148.174]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 261AF11B; Thu, 14 Dec 2023 07:05:29 -0800 (PST) Received: from pps.filterd (m0045849.ppops.net [127.0.0.1]) by mx0a-0016f401.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 3BE9LPtu002192; Thu, 14 Dec 2023 07:04:36 -0800 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= pfpt0220; bh=0k5JxIroS0rjZhxYB09WliNOhejrEn49LGWcWaMMDF4=; b=bz7 DLXRqTTtqmAEkb2/+DBVhRz3c2cvz0tm4MKgdsj05Z8ptaFSx+aAGxgECXM5yqCk NhljViKNcmoO/XMh/igyGK4oENPGgeSJdVFzGwqsR9jA3BEoRzCGqOviKkN6Ip+i bo7zQj1uo8RI5GGpVF6htWAZUrZ1jOSvlf6/2vNv0RvfqD0TggzN5G57eeFE9nzz xORpczZq9OTGMoPW7+ht4FuapZPHryxyzs1HOpEqt3BjKXkkX6evhRrZeWqNahkY JEmzTS8/mWaDsg25xsiYXplmMfke1aj+GxPWeRiehTOwRZdeYtGa44zZ9Fzdd/8q 18+hR8PVhQa9p6/L7Rg== Received: from dc5-exch01.marvell.com ([199.233.59.181]) by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3uyy0m93u9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT); Thu, 14 Dec 2023 07:04:36 -0800 (PST) Received: from DC5-EXCH01.marvell.com (10.69.176.38) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server (TLS) id 15.0.1497.48; Thu, 14 Dec 2023 07:04:35 -0800 Received: from maili.marvell.com (10.69.176.80) by DC5-EXCH01.marvell.com (10.69.176.38) with Microsoft SMTP Server id 15.0.1497.48 via Frontend Transport; Thu, 14 Dec 2023 07:04:35 -0800 Received: from dc3lp-swdev041.marvell.com (dc3lp-swdev041.marvell.com [10.6.60.191]) by maili.marvell.com (Postfix) with ESMTP id 82B433F7074; Thu, 14 Dec 2023 07:04:30 -0800 (PST) From: Elad Nachman To: , , , , , , , , , , , , , , CC: , Subject: [PATCH 3/3] watchdog: sbsa_gwdt: add support for Marvell ac5 Date: Thu, 14 Dec 2023 17:04:14 +0200 Message-ID: <20231214150414.1849058-4-enachman@marvell.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231214150414.1849058-1-enachman@marvell.com> References: <20231214150414.1849058-1-enachman@marvell.com> Precedence: bulk X-Mailing-List: linux-watchdog@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Proofpoint-GUID: xhSphp6M_DwYrAhq7xFM_hy2fbhCyZUi X-Proofpoint-ORIG-GUID: xhSphp6M_DwYrAhq7xFM_hy2fbhCyZUi X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-09_02,2023-12-07_01,2023-05-22_02 From: Elad Nachman Add support for Marvell ac5/x variant of the ARM sbsa global watchdog. This watchdog deviates from the standard driver by the following items: 1. Registers reside in secure register section. hence access is only possible via SMC calls to ATF. 2. There are couple more registers which reside in other register areas, which needs to be configured in order for the watchdog to properly generate reset through the SOC. The new Marvell compatibility string differentiates between the original sbsa mode of operation and the Marvell mode of operation. Signed-off-by: Elad Nachman --- drivers/watchdog/sbsa_gwdt.c | 247 ++++++++++++++++++++++++++++++++--- 1 file changed, 226 insertions(+), 21 deletions(-) diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c index 5f23913ce3b4..0bc6f53f0968 100644 --- a/drivers/watchdog/sbsa_gwdt.c +++ b/drivers/watchdog/sbsa_gwdt.c @@ -46,10 +46,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #define DRV_NAME "sbsa-gwdt" #define WATCHDOG_NAME "SBSA Generic Watchdog" @@ -75,6 +78,68 @@ #define SBSA_GWDT_VERSION_MASK 0xF #define SBSA_GWDT_VERSION_SHIFT 16 +/* Marvell AC5/X SMCs, taken from arm trusted firmware */ +#define SMC_FID_READ_REG 0x80007FFE +#define SMC_FID_WRITE_REG 0x80007FFD + +/* Marvell registers offsets: */ +#define SBSA_GWDT_MARVELL_CPU_WD_RST_EN_REG 0x30 +#define SBSA_GWDT_MARVELL_MNG_ID_REG 0x4C +#define SBSA_GWDT_MARVELL_RST_CTRL_REG 0x0C + +#define SBSA_GWDT_MARVELL_ID_MASK GENMASK(19, 12) +#define SBSA_GWDT_MARVELL_AC5_ID 0xB4000 +#define SBSA_GWDT_MARVELL_AC5X_ID 0x98000 +#define SBSA_GWDT_MARVELL_IML_ID 0xA0000 +#define SBSA_GWDT_MARVELL_IMM_ID 0xA2000 + +#define SBSA_GWDT_MARVELL_AC5_RST_UNIT_WD_BIT BIT(6) +/* The following applies to AC5X, IronMan L and M: */ +#define SBSA_GWDT_MARVELL_IRONMAN_RST_UNIT_WD_BIT BIT(7) + +/* + * Action to perform after watchdog gets WS1 (watchdog signal 1) interrupt + * PWD = Private Watchdog, GWD - Global Watchdog, mpp - multi purpose pin + * + * 0 = Enable 1 = Disable (Default) + * + * BIT 0: CPU 0 reset by PWD 0 + * BIT 1: CPU 1 reset by PWD 1 + * BIT 2: CPU 0 reset by GWD + * BIT 3: CPU 1 reset by GWD + * BIT 4: PWD 0 sys reset out + * BIT 5: PWD 1 sys reset out + * BIT 6: GWD sys reset out + * BIT 7: Reserved + * BIT 8: PWD 0 mpp reset out + * BIT 9: PWD 1 mpp reset out + * BIT 10: GWD mpp reset out + * + */ +#define SBSA_GWDT_MARVELL_RST_CPU0_BY_PWD0 BIT(0) +#define SBSA_GWDT_MARVELL_RST_CPU1_BY_PWD1 BIT(1) +#define SBSA_GWDT_MARVELL_RST_CPU0_BY_GWD BIT(2) +#define SBSA_GWDT_MARVELL_RST_CPU1_BY_GWD BIT(3) +#define SBSA_GWDT_MARVELL_RST_SYSRST_BY_PWD0 BIT(4) +#define SBSA_GWDT_MARVELL_RST_SYSRST_BY_PWD1 BIT(5) +#define SBSA_GWDT_MARVELL_RST_SYSRST_BY_GWD BIT(6) +#define SBSA_GWDT_MARVELL_RST_RESERVED BIT(7) +#define SBSA_GWDT_MARVELL_RST_MPP_BY_PWD0 BIT(8) +#define SBSA_GWDT_MARVELL_RST_MPP_BY_PWD1 BIT(9) +#define SBSA_GWDT_MARVELL_RST_MPP_BY_GWD BIT(10) + +/** + * struct sbsa_gwdt_regs_ops - ops for register read/write, depending on SOC + * @reg_read: register read ops function + * @read_write: register write ops function + */ +struct sbsa_gwdt_regs_ops { + u32 (*reg_read32)(void __iomem *ptr); + __u64 (*reg_read64)(void __iomem *ptr); + void (*reg_write32)(u32 val, void __iomem *ptr); + void (*reg_write64)(__u64 val, void __iomem *ptr); +}; + /** * struct sbsa_gwdt - Internal representation of the SBSA GWDT * @wdd: kernel watchdog_device structure @@ -89,6 +154,7 @@ struct sbsa_gwdt { int version; void __iomem *refresh_base; void __iomem *control_base; + const struct sbsa_gwdt_regs_ops *soc_reg_ops; }; #define DEFAULT_TIMEOUT 10 /* seconds */ @@ -116,6 +182,91 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +/* + * By default, have the Global watchdog cause System Reset: + */ +static unsigned int reset = 0xFFFFFFFF ^ SBSA_GWDT_MARVELL_RST_SYSRST_BY_GWD; +module_param(reset, uint, 0); +MODULE_PARM_DESC(reset, "Action to perform after watchdog gets WS1 interrupt"); + +/* + * Marvell AC5/X use SMC, while others use direct register access + */ +static u32 sbsa_gwdt_smc_readl(void __iomem *addr) +{ + struct arm_smccc_res smc_res; + + arm_smccc_smc(SMC_FID_READ_REG, (unsigned long)addr, + 0, 0, 0, 0, 0, 0, &smc_res); + return (u32)smc_res.a0; +} + +static void sbsa_gwdt_smc_writel(u32 val, void __iomem *addr) +{ + struct arm_smccc_res smc_res; + + arm_smccc_smc(SMC_FID_WRITE_REG, (unsigned long)addr, + (unsigned long)val, 0, 0, 0, 0, 0, &smc_res); +} + +static inline u64 sbsa_gwdt_lo_hi_smc_readq(void __iomem *addr) +{ + u32 low, high; + + low = sbsa_gwdt_smc_readl(addr); + high = sbsa_gwdt_smc_readl(addr + 4); + /* read twice, as a workaround to HW limitation */ + low = sbsa_gwdt_smc_readl(addr); + + return low + ((u64)high << 32); +} + +static inline void sbsa_gwdt_lo_hi_smc_writeq(__u64 val, void __iomem *addr) +{ + u32 low, high; + + low = val & 0xffffffff; + high = val >> 32; + sbsa_gwdt_smc_writel(low, addr); + sbsa_gwdt_smc_writel(high, addr + 4); + /* write twice, as a workaround to HW limitation */ + sbsa_gwdt_smc_writel(low, addr); +} + +static u32 sbsa_gwdt_direct_reg_readl(void __iomem *addr) +{ + return readl(addr); +} + +static void sbsa_gwdt_direct_reg_writel(u32 val, void __iomem *addr) +{ + writel(val, addr); +} + +static inline u64 sbsa_gwdt_lo_hi_direct_readq(void __iomem *addr) +{ + return lo_hi_readq(addr); +} + +static inline void sbsa_gwdt_lo_hi_direct_writeq(__u64 val, void __iomem *addr) +{ + lo_hi_writeq(val, addr); +} + +static const struct sbsa_gwdt_regs_ops smc_reg_ops = { + .reg_read32 = sbsa_gwdt_smc_readl, + .reg_read64 = sbsa_gwdt_lo_hi_smc_readq, + .reg_write32 = sbsa_gwdt_smc_writel, + .reg_write64 = sbsa_gwdt_lo_hi_smc_writeq +}; + +static const struct sbsa_gwdt_regs_ops direct_reg_ops = { + .reg_read32 = sbsa_gwdt_direct_reg_readl, + .reg_read64 = sbsa_gwdt_lo_hi_direct_readq, + .reg_write32 = sbsa_gwdt_direct_reg_writel, + .reg_write64 = sbsa_gwdt_lo_hi_smc_writeq +}; + /* * Arm Base System Architecture 1.0 introduces watchdog v1 which * increases the length watchdog offset register to 48 bits. @@ -127,17 +278,17 @@ MODULE_PARM_DESC(nowayout, static u64 sbsa_gwdt_reg_read(struct sbsa_gwdt *gwdt) { if (gwdt->version == 0) - return readl(gwdt->control_base + SBSA_GWDT_WOR); + return gwdt->soc_reg_ops->reg_read32(gwdt->control_base + SBSA_GWDT_WOR); else - return lo_hi_readq(gwdt->control_base + SBSA_GWDT_WOR); + return gwdt->soc_reg_ops->reg_read64(gwdt->control_base + SBSA_GWDT_WOR); } static void sbsa_gwdt_reg_write(u64 val, struct sbsa_gwdt *gwdt) { if (gwdt->version == 0) - writel((u32)val, gwdt->control_base + SBSA_GWDT_WOR); + gwdt->soc_reg_ops->reg_write32((u32)val, gwdt->control_base + SBSA_GWDT_WOR); else - lo_hi_writeq(val, gwdt->control_base + SBSA_GWDT_WOR); + gwdt->soc_reg_ops->reg_write64(val, gwdt->control_base + SBSA_GWDT_WOR); } /* @@ -175,10 +326,11 @@ static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd) * timeleft = WOR + (WCV - system counter) */ if (!action && - !(readl(gwdt->control_base + SBSA_GWDT_WCS) & SBSA_GWDT_WCS_WS0)) + !(gwdt->soc_reg_ops->reg_read32(gwdt->control_base + SBSA_GWDT_WCS) + & SBSA_GWDT_WCS_WS0)) timeleft += sbsa_gwdt_reg_read(gwdt); - timeleft += lo_hi_readq(gwdt->control_base + SBSA_GWDT_WCV) - + timeleft += gwdt->soc_reg_ops->reg_read64(gwdt->control_base + SBSA_GWDT_WCV) - arch_timer_read_counter(); do_div(timeleft, gwdt->clk); @@ -194,7 +346,7 @@ static int sbsa_gwdt_keepalive(struct watchdog_device *wdd) * Writing WRR for an explicit watchdog refresh. * You can write anyting (like 0). */ - writel(0, gwdt->refresh_base + SBSA_GWDT_WRR); + gwdt->soc_reg_ops->reg_write32(0, gwdt->refresh_base + SBSA_GWDT_WRR); return 0; } @@ -204,7 +356,7 @@ static void sbsa_gwdt_get_version(struct watchdog_device *wdd) struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); int ver; - ver = readl(gwdt->control_base + SBSA_GWDT_W_IIDR); + ver = gwdt->soc_reg_ops->reg_read32(gwdt->control_base + SBSA_GWDT_W_IIDR); ver = (ver >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK; gwdt->version = ver; @@ -215,7 +367,7 @@ static int sbsa_gwdt_start(struct watchdog_device *wdd) struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); /* writing WCS will cause an explicit watchdog refresh */ - writel(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS); + gwdt->soc_reg_ops->reg_write32(SBSA_GWDT_WCS_EN, gwdt->control_base + SBSA_GWDT_WCS); return 0; } @@ -225,7 +377,7 @@ static int sbsa_gwdt_stop(struct watchdog_device *wdd) struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd); /* Simply write 0 to WCS to clean WCS_EN bit */ - writel(0, gwdt->control_base + SBSA_GWDT_WCS); + gwdt->soc_reg_ops->reg_write32(0, gwdt->control_base + SBSA_GWDT_WCS); return 0; } @@ -257,24 +409,55 @@ static const struct watchdog_ops sbsa_gwdt_ops = { static int sbsa_gwdt_probe(struct platform_device *pdev) { void __iomem *rf_base, *cf_base; + void __iomem *cpu_ctrl_base = NULL, *mng_base = NULL, + *rst_ctrl_base = NULL; struct device *dev = &pdev->dev; + struct device_node *np = pdev->dev.of_node; struct watchdog_device *wdd; struct sbsa_gwdt *gwdt; + struct resource *res; int ret, irq; - u32 status; + bool marvell = false; + u32 status, id, val; gwdt = devm_kzalloc(dev, sizeof(*gwdt), GFP_KERNEL); if (!gwdt) return -ENOMEM; platform_set_drvdata(pdev, gwdt); - cf_base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(cf_base)) - return PTR_ERR(cf_base); - - rf_base = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(rf_base)) - return PTR_ERR(rf_base); + if (of_device_is_compatible(np, "marvell,ac5-wd")) { + marvell = true; + gwdt->soc_reg_ops = &smc_reg_ops; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + cf_base = res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (IS_ERR(res)) + return PTR_ERR(res); + rf_base = res->start; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (IS_ERR(res)) + return PTR_ERR(res); + cpu_ctrl_base = res->start; + mng_base = devm_platform_ioremap_resource(pdev, 3); + if (IS_ERR(mng_base)) + return PTR_ERR(mng_base); + rst_ctrl_base = devm_platform_ioremap_resource(pdev, 4); + if (IS_ERR(rst_ctrl_base)) + return PTR_ERR(rst_ctrl_base); + } else { + gwdt->soc_reg_ops = &direct_reg_ops; + cf_base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(cf_base)) + return PTR_ERR(cf_base); + + rf_base = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(rf_base)) + return PTR_ERR(rf_base); + } /* * Get the frequency of system counter from the cp15 interface of ARM @@ -299,7 +482,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) else wdd->max_hw_heartbeat_ms = GENMASK_ULL(47, 0) / gwdt->clk * 1000; - status = readl(cf_base + SBSA_GWDT_WCS); + status = gwdt->soc_reg_ops->reg_read32(cf_base + SBSA_GWDT_WCS); if (status & SBSA_GWDT_WCS_WS1) { dev_warn(dev, "System reset by WDT.\n"); wdd->bootstatus |= WDIOF_CARDRESET; @@ -317,7 +500,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) * In case there is a pending ws0 interrupt, just ping * the watchdog before registering the interrupt routine */ - writel(0, rf_base + SBSA_GWDT_WRR); + gwdt->soc_reg_ops->reg_write32(0, rf_base + SBSA_GWDT_WRR); if (devm_request_irq(dev, irq, sbsa_gwdt_interrupt, 0, pdev->name, gwdt)) { action = 0; @@ -347,7 +530,28 @@ static int sbsa_gwdt_probe(struct platform_device *pdev) ret = devm_watchdog_register_device(dev, wdd); if (ret) return ret; - + /* + * Marvell AC5/X/IM: need to configure the watchdog + * HW to trigger reset on WS1 (Watchdog Signal 1): + * + * 1. Configure the watchdog signal enable (routing) + * according to configuration + * 2. Unmask the wd_rst input signal to the reset unit + */ + if (marvell) { + gwdt->soc_reg_ops->reg_write32(reset, cpu_ctrl_base + + SBSA_GWDT_MARVELL_CPU_WD_RST_EN_REG); + id = readl(mng_base + SBSA_GWDT_MARVELL_MNG_ID_REG) & + SBSA_GWDT_MARVELL_ID_MASK; + + if (id == SBSA_GWDT_MARVELL_AC5_ID) + val = SBSA_GWDT_MARVELL_AC5_RST_UNIT_WD_BIT; + else + val = SBSA_GWDT_MARVELL_IRONMAN_RST_UNIT_WD_BIT; + + writel(readl(rst_ctrl_base + SBSA_GWDT_MARVELL_RST_CTRL_REG) & ~val, + rst_ctrl_base + SBSA_GWDT_MARVELL_RST_CTRL_REG); + } dev_info(dev, "Initialized with %ds timeout @ %u Hz, action=%d.%s\n", wdd->timeout, gwdt->clk, action, status & SBSA_GWDT_WCS_EN ? " [enabled]" : ""); @@ -383,6 +587,7 @@ static const struct dev_pm_ops sbsa_gwdt_pm_ops = { static const struct of_device_id sbsa_gwdt_of_match[] = { { .compatible = "arm,sbsa-gwdt", }, + { .compatible = "marvell,ac5-wd", }, {}, }; MODULE_DEVICE_TABLE(of, sbsa_gwdt_of_match);