From nobody Sun Feb 8 06:00:01 2026 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 85C021B0F32 for ; Mon, 7 Apr 2025 16:03:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744041821; cv=none; b=AOp+bQHUdZ/ZwzKHuX82uQ18dXCLEPnfWlK56MoPI+mb8wbwrWkuFmuwyNS4SkwmJOqALupQ9dBMSFMaOnLNVNSiUP3tZqwBSbW9XVSp7rMspP0c4bxY3pXV3KsNL5ZrD1q9ITbdqK0hnOnF2Ngi5mHujBMmmfhtVb1b9SWLl38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744041821; c=relaxed/simple; bh=cwUg5LduXXZcufnnSzBfEonNlCK2lmvkVORVQf2hbvI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rc6EuNvA+uJ8tP2EE+CKrkvLItz99Bvi81Ml+++5opPqpGEofEFZuKnvYt0CStSeoZXHXFkLvrg86oa/TsSw4uMrNxND0j2e6hToF93tIMNoIqBDyvvKGNteZhS9DC707mSVDhVr/rF5piDqOB+JodlaMjXowDyDfr6OIGJ0rlk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=dZ0gSQ+k; arc=none smtp.client-ip=209.85.128.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="dZ0gSQ+k" Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-43cf3192f3bso45729045e9.1 for ; Mon, 07 Apr 2025 09:03:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1744041818; x=1744646618; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wbL55eomgr//IZJoFaosxxTA80M3t+xWAEMNMsogd4o=; b=dZ0gSQ+k/qITe+teA4mXmxNx0O6eTsggoiImqwRIx3eJDpQTV5I/d6mSdXVOxAKU1c M7pK4DjGxjPzk9PKe/DbzaYLGzIbyNFhbYIQl78Ur5FPC5OymDvdQwXkvc7U57Wpn7Mw ZvvO5swq6FpOuMjP95lAhxvHptKO7jqOwri0A+xxQLoMjzgorBdOQ/pPvtgGN9Q8YQup DLxcz4mGgcZwu52aSEqIJpU7ul+Clsod/A1k+BUVhw/YE1UF1mfhu3Skv7TSTW19Z6iZ FNwoQZSb46qNZuFQdcP896RnHiXdPMQFA84P+gX/ULYgWW20/hRZslfnB+ChMm92lXIB sX6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744041818; x=1744646618; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wbL55eomgr//IZJoFaosxxTA80M3t+xWAEMNMsogd4o=; b=JcTMieXs2f/sAPzqNDd1Mn+ZKttBK8Du63TCXS4meITNS7TR+29+pMcrXuEr4hG7VN jpDs9Y09Fz5CC6jkTe/soKixDYOH+Sl0nCYX7aVJvNwUfHJ8Z1if8Vi+/dQN7SdFbaew /kM0ofMVQuJYboEff2So6vWIkr1xzZpXljE93zBPnqRnGmQVEbccEqzV7QX6JSR2OYIb TjyCrpcIWiNTCLiLPC8hOh2WTko6Hj1CD8iRJHDbO9f4ZaJ56iBNkP+JBgFeq9c02kDi /D/GtVlzvsgViHDbxFeYJX3l9v/RPYBlNE4R7hvG8aui4a9bfi2CnbgOoHaptGF95G5W khOw== X-Forwarded-Encrypted: i=1; AJvYcCU9MPtOEKG2pfBBtvc2BJB4XWbisStcb+gR52rIlj8ANeLbVdrkJcRTgZoY60D6QfmdJLei6E3euj5zqPE=@vger.kernel.org X-Gm-Message-State: AOJu0Ywcs7PCzHwpVig+1mqM3jv4FPQV5xBOLatydhu4KMyDMIU71Txr kp+5tG/2fhOcbxJSlSYo1fbzNgLo1MpzhcMJrzQpoLEhEdEwmkvR25mzJwm9cKk= X-Gm-Gg: ASbGncs5lqVP7GhcpDw7wQlHbXs8299hL5CEp6jTyDFP4maWYpLVsLxvfHUCQRZz/2G 9jVtmWWzMOthAMlbiTMz7biKHg5R8HJPO725Yp8HxKXogIw7r/Rh5a2VYPWTh/nboeBy7C0BH9h VCjLi9gxyhP0ZUJhUgyEgYz35y+F7b1XFgmxq6g36DktskybhQH2gsi4r98nxXZOK9CEaZRxoi/ rFjBu2kIxb8HeNavudiBaPjshJtLptDrC7eK47UReePWHhmtU5CyflX1ZuC4yiRFd34t9W0BNfO EUfhqhGN/9FT3tTke8yTDkUdORqL2V3UueDTtiwW/FnM0ZqJgjNLIrsiIGWTzYnquD0Kmfw= X-Google-Smtp-Source: AGHT+IGz+Q5GGF73nsTcrEA6hA6PV9lyUFIqD+pbjsmX9Oz/pnvq3IzYO9Cy6F+x+KrU3yJohdTA8Q== X-Received: by 2002:a05:6000:1a87:b0:398:fd9b:b935 with SMTP id ffacd0b85a97d-39d1475794amr11311063f8f.53.1744041817603; Mon, 07 Apr 2025 09:03:37 -0700 (PDT) Received: from mai.. (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43ec17b3572sm137701205e9.39.2025.04.07.09.03.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Apr 2025 09:03:33 -0700 (PDT) From: Daniel Lezcano To: wim@linux-watchdog.org Cc: linux@roeck-us.net, linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, S32@nxp.com, ghennadi.procopciuc@nxp.com, thomas.fossati@linaro.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 1/2] dt-bindings: watchdog: Add NXP Software Watchdog Timer Date: Mon, 7 Apr 2025 18:03:16 +0200 Message-ID: <20250407160318.936142-2-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250407160318.936142-1-daniel.lezcano@linaro.org> References: <20250407160318.936142-1-daniel.lezcano@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Describe the Software Watchdog Timer available on the S32G platforms. Cc: Ghennadi Procopciuc Cc: Thomas Fossati Signed-off-by: Daniel Lezcano --- .../bindings/watchdog/nxp,s32g2-swt.yaml | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 Documentation/devicetree/bindings/watchdog/nxp,s32g2-sw= t.yaml diff --git a/Documentation/devicetree/bindings/watchdog/nxp,s32g2-swt.yaml = b/Documentation/devicetree/bindings/watchdog/nxp,s32g2-swt.yaml new file mode 100644 index 000000000000..48ba9e9979ee --- /dev/null +++ b/Documentation/devicetree/bindings/watchdog/nxp,s32g2-swt.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/watchdog/nxp,s32g2-swt.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP Software Watchdog Timer (SWT) + +maintainers: + - Daniel Lezcano + +allOf: + - $ref: watchdog.yaml# + +properties: + compatible: + oneOf: + - const: nxp,s32g2-swt + - items: + - const: nxp,s32g3-swt + - const: nxp,s32g2-swt + + reg: + maxItems: 1 + + clocks: + items: + - description: Counter clock + - description: Module clock + - description: Register clock + minItems: 1 + + clock-names: + items: + - const: counter + - const: module + - const: register + minItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + +unevaluatedProperties: false + +examples: + - | + watchdog@40100000 { + compatible =3D "nxp,s32g2-swt"; + reg =3D <0x40100000 0x1000>; + clocks =3D <&clks 0x3a>, <&clks 0x3b>; + clock-names =3D "counter", "module"; + timeout-sec =3D <10>; + }; --=20 2.43.0 From nobody Sun Feb 8 06:00:01 2026 Received: from mail-wm1-f48.google.com (mail-wm1-f48.google.com [209.85.128.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13E14206F01 for ; Mon, 7 Apr 2025 16:03:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744041825; cv=none; b=dXeEe9olwKmQh5gWofcIgNwnJ3Wg2uAlWZOnQRTgKgC2gOnLTUCnilcJ3jGWcpt4prEkePMC/BmTe7VQksSLG5VMXQErJJqomhpRz3C4rAUfYm6ABpUKdW9V0PW+ZIBtBxLjraYG0vp+jUz09+Cdnow+/SzvMMydKPnYlZAOyO4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1744041825; c=relaxed/simple; bh=W0gT9T+Y/rLewOC8430cdKW7jrE6Czo6lGNGw7FIZdM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Rh4PLPEL9T90CTTfuhsai+k0nf14MZt1eIFcVgmoC4CPdHLC5qUZzwfETKG4ZQcmxYdbhycJifxRMbniKbV8dNWykTGKP5fca51lcdWT0SCyHsWfU5aV+aCdXpkIRzre9QkDoGk2nSNyGPpW6LpJRILDEc3KdQy1MSl96KH4Toc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=M4HUXeq5; arc=none smtp.client-ip=209.85.128.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="M4HUXeq5" Received: by mail-wm1-f48.google.com with SMTP id 5b1f17b1804b1-43cec5cd73bso25095365e9.3 for ; Mon, 07 Apr 2025 09:03:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1744041821; x=1744646621; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Oq0LoJnjHMVsrmCQmRrhBcUFErmi4KUqj1rAYGtayes=; b=M4HUXeq5BcauhYC23nO8rC818p5lUvcaAojYMyal6KaU1/W/gd+3TA81G7VIxPYWmN AX6dZRH50jQAURgYNvHaU86vEWpEQNT9863JeyvCLC5FuegV4Idd/qkH75MAoSh4zqMB Xi03YU4kkQTTr7g4BXik5cw3N9wB6YRYrH3hyBNAXDr+7qGWTfKwCI2TphP/yipGTXhx nSGpFUUvFbMoLuYQMlDobizRsofdl2nBhZC5qrfFTdA2uLYki2Ewp59RWSWwHsbcVgmt siD5fvCn6rHzY4Oyq9Bj4gcJosoH0yobV1WNiiJYgejlL2kY9r0MYSDPhfIzoPJPZowQ XOcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744041821; x=1744646621; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Oq0LoJnjHMVsrmCQmRrhBcUFErmi4KUqj1rAYGtayes=; b=qjSmLP+MpKWUYsOkik/5Tr7B1ggKhpWmrvSC7Zy7sZDYRUynf6S1lW6bLb0hiTRJzA 9WVMKFYjPl/VVYRCHWLytsEjp17N3wAT6KIxbpcP0HCjc9BOenX1HpYKmE0aET2eV6WJ XxM2Mfj8wPL7yqK2NdoXEycVh6qYu0SkqikwpGPZ6otDc14OmHBXYU6Wv4DhJCfTdXWg 8PBTilKyNP7pF/wl48mB8z/KAt8MHbPP9+m+gczmAtclpA3MHz4sP1hGkwJz39bYuDmk J8RCWS6q4n0J6QV0u42VnNCMsGmDP8o4CD00JMzzXkkZ/NaPr/0WxDdXG+rLg/ZorEAI 0olQ== X-Forwarded-Encrypted: i=1; AJvYcCXWLMxp0xFQaXLHTi71msnSXmFg6S8NvZJQ9ygIeVZOn+a2vzfU8Y69vDOHUqdcmgcUTVLBIanVex0jMXw=@vger.kernel.org X-Gm-Message-State: AOJu0Yxqk5bQy6aD18/E40WuqxIuOYmxwMyYHbIEXIehBDCik6+R40zq gS2ez9bw+tHP2ehQGDc2rCi7cZi15RcUqE6JVm6GoaVKlPR9DvkAvu12Rz/Ei3c= X-Gm-Gg: ASbGncs78AV0ecyhPnwAse7vC1z+52L0Hpfym0FlgkyciJnpJ5cMa0r/2bXkbPxEuDU SZpjXx2u82b7/k9sdFjmxyKfPO2GXX3WGVQTkkup+2UQPGgeSv5m26ZmHlDTrHVKSLqWMY80oZj awhFs4GfrcdTK7UsSBfUNF7YkXArR122oDvOOZAhYa0uT6jhw7jYs/1/rMEX+Ub1bXnP+avNpN/ AzwXb9RvAyBtNLn1ym06VojM4jXRqNFOcNyAJuov7bKlH8Ki6v12npKukh6uPf1vkX4wxetfDyr OI6oHCfTw4c305Nmsu5itGyrFIO2afA/qpYbTjNuCLSZviUM8f8ov2nZJx8Lmrl//t3bdR8= X-Google-Smtp-Source: AGHT+IEaOPNZ55E0jL5Q5wFU6TOJjT4ILPjdaEq5V1twcqbLAouVO720iTO2LCMwirBP/FJpkB0CKw== X-Received: by 2002:a05:600c:4684:b0:43c:e467:d6ce with SMTP id 5b1f17b1804b1-43ee061708bmr95789835e9.4.1744041819586; Mon, 07 Apr 2025 09:03:39 -0700 (PDT) Received: from mai.. (146725694.box.freepro.com. [130.180.211.218]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43ec17b3572sm137701205e9.39.2025.04.07.09.03.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Apr 2025 09:03:38 -0700 (PDT) From: Daniel Lezcano To: wim@linux-watchdog.org Cc: linux@roeck-us.net, linux-watchdog@vger.kernel.org, linux-kernel@vger.kernel.org, S32@nxp.com, ghennadi.procopciuc@nxp.com, thomas.fossati@linaro.org, robh@kernel.org, krzk+dt@kernel.org, conor+dt@kernel.org, devicetree@vger.kernel.org Subject: [PATCH v3 2/2] watchdog: Add the Watchdog Timer for the NXP S32 platform Date: Mon, 7 Apr 2025 18:03:17 +0200 Message-ID: <20250407160318.936142-3-daniel.lezcano@linaro.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250407160318.936142-1-daniel.lezcano@linaro.org> References: <20250407160318.936142-1-daniel.lezcano@linaro.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The S32 platform has several Watchdog Timer available and tied with a CPU. The SWT0 is the only one which directly asserts the reset line, other SWT require an external setup to configure the reset behavior which is not part of this change. As a side note, in the NXP documentation, the s32g2 and s32g3 reference manuals refer the watchdog as the 'Software Timer Watchdog' where the name can be misleading as it is actually a hardware watchdog. The maximum watchdog timeout value depends on the clock feeding the SWT counter which is 32bits wide. On the s32g274-rb2, the clock has a rate of 51MHz which result on 83 seconds maximum timeout. The timeout can be specified via the device tree with the usual existing bindings 'timeout-sec' or via the module param timeout. The watchdog can be loaded with the 'nowayout' option, preventing the watchdog to be stopped. The watchdog can be started at boot time with the 'early-enable' option, thus letting the watchdog framework to service the watchdog counter. The watchdog support the magic character to stop when the userspace releases the device. Cc: Ghennadi Procopciuc Cc: Thomas Fossati Signed-off-by: Daniel Lezcano --- drivers/watchdog/Kconfig | 9 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/s32g_wdt.c | 313 ++++++++++++++++++++++++++++++++++++ 3 files changed, 323 insertions(+) create mode 100644 drivers/watchdog/s32g_wdt.c diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index f81705f8539a..4ab4275ef49f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -792,6 +792,15 @@ config IMX7ULP_WDT To compile this driver as a module, choose M here: the module will be called imx7ulp_wdt. =20 +config S32G_WDT + tristate "S32G Watchdog" + depends on ARCH_S32 || COMPILE_TEST + select WATCHDOG_CORE + help + This is the driver for the hardware watchdog on the NXP + S32G platforms. If you wish to have watchdog support + enabled, say Y, otherwise say N. + config DB500_WATCHDOG tristate "ST-Ericsson DB800 watchdog" depends on MFD_DB8500_PRCMU diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 8411626fa162..d0f9826e32c3 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_TS72XX_WATCHDOG) +=3D ts72xx_wdt.o obj-$(CONFIG_IMX2_WDT) +=3D imx2_wdt.o obj-$(CONFIG_IMX_SC_WDT) +=3D imx_sc_wdt.o obj-$(CONFIG_IMX7ULP_WDT) +=3D imx7ulp_wdt.o +obj-$(CONFIG_S32G_WDT) +=3D s32g_wdt.o obj-$(CONFIG_DB500_WATCHDOG) +=3D db8500_wdt.o obj-$(CONFIG_RETU_WATCHDOG) +=3D retu_wdt.o obj-$(CONFIG_BCM2835_WDT) +=3D bcm2835_wdt.o diff --git a/drivers/watchdog/s32g_wdt.c b/drivers/watchdog/s32g_wdt.c new file mode 100644 index 000000000000..f7e44c39aace --- /dev/null +++ b/drivers/watchdog/s32g_wdt.c @@ -0,0 +1,313 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Watchdog driver for S32G SoC + * + * Copyright 2017-2019, 2021-2025 NXP. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "s32g-swt" + +#define S32G_SWT_CR(__base) ((__base) + 0x00) /* Control Register offset */ +#define S32G_SWT_CR_SM (BIT(9) | BIT(10)) /* -> Service Mode */ +#define S32G_SWT_CR_STP BIT(2) /* -> Stop Mode Control */ +#define S32G_SWT_CR_FRZ BIT(1) /* -> Debug Mode Control */ +#define S32G_SWT_CR_WEN BIT(0) /* -> Watchdog Enable */ + +#define S32G_SWT_TO(__base) ((__base) + 0x08) /* Timeout Register offset */ + +#define S32G_SWT_SR(__base) ((__base) + 0x10) /* Service Register offset */ +#define S32G_WDT_SEQ1 0xA602 /* -> service sequence number 1 */ +#define S32G_WDT_SEQ2 0xB480 /* -> service sequence number 2 */ + +#define S32G_SWT_CO(__base) ((__base) + 0x14) /* Counter output register */ + +#define S32G_WDT_DEFAULT_TIMEOUT 30 + +struct s32g_wdt_device { + int rate; + void __iomem *base; + struct watchdog_device wdog; +}; + +static bool nowayout =3D WATCHDOG_NOWAYOUT; +module_param(nowayout, bool, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (defau= lt=3D" + __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); + +static unsigned int timeout_param =3D S32G_WDT_DEFAULT_TIMEOUT; +module_param(timeout_param, uint, 0); +MODULE_PARM_DESC(timeout_param, "Watchdog timeout in seconds (default=3D" + __MODULE_STRING(S32G_WDT_DEFAULT_TIMEOUT) ")"); + +static bool early_enable; +module_param(early_enable, bool, 0); +MODULE_PARM_DESC(early_enable, + "Watchdog is started on module insertion (default=3Dfalse)"); + +static const struct watchdog_info s32g_wdt_info =3D { + .identity =3D "s32g watchdog", + .options =3D WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | + WDIOC_GETTIMEOUT | WDIOC_GETTIMELEFT, +}; + +static struct s32g_wdt_device *wdd_to_s32g_wdt(struct watchdog_device *wdd) +{ + return container_of(wdd, struct s32g_wdt_device, wdog); +} + +static unsigned int wdog_sec_to_count(struct s32g_wdt_device *wdev, unsign= ed int timeout) +{ + return wdev->rate * timeout; +} + +static int s32g_wdt_ping(struct watchdog_device *wdog) +{ + struct s32g_wdt_device *wdev =3D wdd_to_s32g_wdt(wdog); + + writel(S32G_WDT_SEQ1, S32G_SWT_SR(wdev->base)); + writel(S32G_WDT_SEQ2, S32G_SWT_SR(wdev->base)); + + return 0; +} + +static int s32g_wdt_start(struct watchdog_device *wdog) +{ + struct s32g_wdt_device *wdev =3D wdd_to_s32g_wdt(wdog); + unsigned long val; + + val =3D readl(S32G_SWT_CR(wdev->base)); + + val |=3D S32G_SWT_CR_WEN; + + writel(val, S32G_SWT_CR(wdev->base)); + + return 0; +} + +static int s32g_wdt_stop(struct watchdog_device *wdog) +{ + struct s32g_wdt_device *wdev =3D wdd_to_s32g_wdt(wdog); + unsigned long val; + + val =3D readl(S32G_SWT_CR(wdev->base)); + + val &=3D ~S32G_SWT_CR_WEN; + + writel(val, S32G_SWT_CR(wdev->base)); + + return 0; +} + +static int s32g_wdt_set_timeout(struct watchdog_device *wdog, unsigned int= timeout) +{ + struct s32g_wdt_device *wdev =3D wdd_to_s32g_wdt(wdog); + + writel(wdog_sec_to_count(wdev, timeout), S32G_SWT_TO(wdev->base)); + + /* + * Conforming to the documentation, the timeout counter is + * loaded when servicing is operated (aka ping) or when the + * counter is enabled. In case the watchdog is already started + * it must be stopped and started again to update the timeout + * register or a ping can be sent to refresh the counter. Here + * we choose to send a ping to the watchdog which is harmless + * if the watchdog is stopped. + */ + return s32g_wdt_ping(wdog); +} + +static unsigned int s32g_wdt_get_timeleft(struct watchdog_device *wdog) +{ + struct s32g_wdt_device *wdev =3D wdd_to_s32g_wdt(wdog); + unsigned long counter; + bool is_running; + + /* + * The counter output can be read only if the SWT is + * disabled. Given the latency between the internal counter + * and the counter output update, there can be very small + * difference. However, we can accept this matter of fact + * given the resolution is a second based unit for the output. + */ + is_running =3D watchdog_hw_running(wdog); + + if (is_running) + s32g_wdt_stop(wdog); + + counter =3D readl(S32G_SWT_CO(wdev->base)); + + if (is_running) + s32g_wdt_start(wdog); + + return counter / wdev->rate; +} + +static const struct watchdog_ops s32g_wdt_ops =3D { + .owner =3D THIS_MODULE, + .start =3D s32g_wdt_start, + .stop =3D s32g_wdt_stop, + .ping =3D s32g_wdt_ping, + .set_timeout =3D s32g_wdt_set_timeout, + .get_timeleft =3D s32g_wdt_get_timeleft, +}; + +static void s32g_wdt_init(struct s32g_wdt_device *wdev) +{ + unsigned long val; + + /* Set the watchdog's Time-Out value */ + val =3D wdog_sec_to_count(wdev, wdev->wdog.timeout); + + writel(val, S32G_SWT_TO(wdev->base)); + + /* + * Get the control register content. We are at init time, the + * watchdog should not be started. + */ + val =3D readl(S32G_SWT_CR(wdev->base)); + + /* + * We want to allow the watchdog timer to be stopped when + * device enters debug mode. + */ + val |=3D S32G_SWT_CR_FRZ; + + /* + * However, when the CPU is in WFI or suspend mode, the + * watchdog must continue. The documentation refers it as the + * stopped mode. + */ + val &=3D ~S32G_SWT_CR_STP; + + /* + * Use Fixed Service Sequence to ping the watchdog which is + * 0x00 configuration value for the service mode. It should be + * already set because it is the default value but we reset it + * in case. + */ + val &=3D ~S32G_SWT_CR_SM; + + writel(val, S32G_SWT_CR(wdev->base)); + + /* + * When the 'early_enable' option is set, we start the + * watchdog from the kernel. + */ + if (early_enable) { + s32g_wdt_start(&wdev->wdog); + set_bit(WDOG_HW_RUNNING, &wdev->wdog.status); + } +} + +static int s32g_wdt_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + struct resource *res; + struct clk *clk; + struct s32g_wdt_device *wdev; + struct watchdog_device *wdog; + int ret; + + wdev =3D devm_kzalloc(dev, sizeof(*wdev), GFP_KERNEL); + if (!wdev) + return -ENOMEM; + + res =3D platform_get_resource(pdev, IORESOURCE_MEM, 0); + wdev->base =3D devm_ioremap_resource(dev, res); + if (IS_ERR(wdev->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(wdev->base), "Can not get resou= rce\n"); + + clk =3D devm_clk_get_enabled(dev, "counter"); + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "Can't get Watchdog clock\n"); + + wdev->rate =3D clk_get_rate(clk); + if (!wdev->rate) { + dev_err(dev, "Input clock rate is not valid\n"); + return -EINVAL; + } + + wdog =3D &wdev->wdog; + wdog->info =3D &s32g_wdt_info; + wdog->ops =3D &s32g_wdt_ops; + + /* + * The code converts the timeout into a counter a value, if + * the value is less than 0x100, then it is clamped by the SWT + * module, so it is safe to specify a zero value as the + * minimum timeout. + */ + wdog->min_timeout =3D 0; + + /* + * The counter register is a 32 bits long, so the maximum + * counter value is UINT_MAX and the timeout in second is the + * value divided by the rate. + * + * For instance, a rate of 51MHz lead to 84 seconds maximum + * timeout. + */ + wdog->max_timeout =3D UINT_MAX / wdev->rate; + + /* + * The module param and the DT 'timeout-sec' property will + * override the default value if they are specified. + */ + ret =3D watchdog_init_timeout(wdog, timeout_param, dev); + if (ret) + return ret; + + /* + * As soon as the watchdog is started, there is no way to stop + * it if the 'nowayout' option is set at boot time + */ + watchdog_set_nowayout(wdog, nowayout); + + /* + * The devm_ version of the watchdog_register_device() + * function will call watchdog_unregister_device() when the + * device is removed. + */ + watchdog_stop_on_unregister(wdog); + + s32g_wdt_init(wdev); + + ret =3D devm_watchdog_register_device(dev, wdog); + if (ret) + return dev_err_probe(dev, ret, "Cannot register watchdog device\n"); + + dev_info(dev, "S32G Watchdog Timer Registered, timeout=3D%ds, nowayout=3D= %d, early_enable=3D%d\n", + wdog->timeout, nowayout, early_enable); + + return 0; +} + +static const struct of_device_id s32g_wdt_dt_ids[] =3D { + { .compatible =3D "nxp,s32g2-swt" }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, s32g_wdt_dt_ids); + +static struct platform_driver s32g_wdt_driver =3D { + .probe =3D s32g_wdt_probe, + .driver =3D { + .name =3D DRIVER_NAME, + .of_match_table =3D s32g_wdt_dt_ids, + }, +}; + +module_platform_driver(s32g_wdt_driver); + +MODULE_AUTHOR("Daniel Lezcano "); +MODULE_DESCRIPTION("Watchdog driver for S32G SoC"); +MODULE_LICENSE("GPL"); --=20 2.43.0