From: Nick Hawkins <[email protected]>
The GXP is the HPE BMC SoC that is used in the majority
of current generation HPE servers. Traditionally the asic will
last multiple generations of server before being replaced.
Info about SoC:
HPE GXP is the name of the HPE Soc. This SoC is used to implement many BMC
features at HPE. It supports ARMv7 architecture based on the Cortex A9
core. It is capable of using an AXI bus to whicha memory controller is
attached. It has multiple SPI interfaces to connect boot flash and BIOS
flash. It uses a 10/100/1000 MAC for network connectivity. It has multiple
i2c engines to drive connectivity with a host infrastructure. There
currently are no public specifications but this process is being worked.
Previously there was a requirement to reset the EHCI controller for the
asic to boot. This functionality has been moved to the u-boot
bootloader.
Signed-off-by: Nick Hawkins <[email protected]>
---
v7:
* No change
v6:
* Adjusted title to match log entries
* Reconfigured commit message to be closer to 75 char.
* Add space before comment delimiter.
* Added a more elaborate Kconfig help section and fixed punctuation.
* Fixed l2c_aux_map initialization.
v5:
* Fixed version log
* Removed incorrect statement about reset.
v4:
* Removed unnecessary code: restart, iomap, init_machine
* Reordered Kconfig depends
* Removed SPARSE_IRQ, MULTI_IRQ_HANDLER, IRQ_DOMAIN, PINCTL from
Kconfig
v3:
* Put into proper patchset format
v2:
* No change
---
arch/arm/Kconfig | 2 ++
arch/arm/Makefile | 1 +
arch/arm/mach-hpe/Kconfig | 23 +++++++++++++++++++++++
arch/arm/mach-hpe/Makefile | 1 +
arch/arm/mach-hpe/gxp.c | 16 ++++++++++++++++
5 files changed, 43 insertions(+)
create mode 100644 arch/arm/mach-hpe/Kconfig
create mode 100644 arch/arm/mach-hpe/Makefile
create mode 100644 arch/arm/mach-hpe/gxp.c
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2e8091e2d8a8..13f77eec7c40 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -620,6 +620,8 @@ source "arch/arm/mach-highbank/Kconfig"
source "arch/arm/mach-hisi/Kconfig"
+source "arch/arm/mach-hpe/Kconfig"
+
source "arch/arm/mach-imx/Kconfig"
source "arch/arm/mach-integrator/Kconfig"
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index a2391b8de5a5..97a89023c10f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -179,6 +179,7 @@ machine-$(CONFIG_ARCH_FOOTBRIDGE) += footbridge
machine-$(CONFIG_ARCH_GEMINI) += gemini
machine-$(CONFIG_ARCH_HIGHBANK) += highbank
machine-$(CONFIG_ARCH_HISI) += hisi
+machine-$(CONFIG_ARCH_HPE) += hpe
machine-$(CONFIG_ARCH_INTEGRATOR) += integrator
machine-$(CONFIG_ARCH_IOP32X) += iop32x
machine-$(CONFIG_ARCH_IXP4XX) += ixp4xx
diff --git a/arch/arm/mach-hpe/Kconfig b/arch/arm/mach-hpe/Kconfig
new file mode 100644
index 000000000000..3372bbf38d38
--- /dev/null
+++ b/arch/arm/mach-hpe/Kconfig
@@ -0,0 +1,23 @@
+menuconfig ARCH_HPE
+ bool "HPE SoC support"
+ depends on ARCH_MULTI_V7
+ help
+ This enables support for HPE ARM based BMC chips.
+if ARCH_HPE
+
+config ARCH_HPE_GXP
+ bool "HPE GXP SoC"
+ depends on ARCH_MULTI_V7
+ select ARM_VIC
+ select GENERIC_IRQ_CHIP
+ select CLKSRC_MMIO
+ help
+ HPE GXP is the name of the HPE Soc. This SoC is used to implement many
+ BMC features at HPE. It supports ARMv7 architecture based on the Cortex
+ A9 core. It is capable of using an AXI bus to which a memory controller
+ is attached. It has multiple SPI interfaces to connect boot flash and
+ BIOS flash. It uses a 10/100/1000 MAC for network connectivity. It
+ has multiple i2c engines to drive connectivity with a host
+ infrastructure.
+
+endif
diff --git a/arch/arm/mach-hpe/Makefile b/arch/arm/mach-hpe/Makefile
new file mode 100644
index 000000000000..8b0a91234df4
--- /dev/null
+++ b/arch/arm/mach-hpe/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_ARCH_HPE_GXP) += gxp.o
diff --git a/arch/arm/mach-hpe/gxp.c b/arch/arm/mach-hpe/gxp.c
new file mode 100644
index 000000000000..ef3341373006
--- /dev/null
+++ b/arch/arm/mach-hpe/gxp.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */
+
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+
+static const char * const gxp_board_dt_compat[] = {
+ "hpe,gxp",
+ NULL,
+};
+
+DT_MACHINE_START(GXP_DT, "HPE GXP")
+ .dt_compat = gxp_board_dt_compat,
+ .l2c_aux_val = 0,
+ .l2c_aux_mask = ~0,
+MACHINE_END
--
2.17.1
From: Nick Hawkins <[email protected]>
Add support for the HPE GXP Watchdog. The GXP asic contains a full
complement of timers one of which is the watchdog timer. The watchdog
timer is 16 bit and has 10ms resolution. The watchdog is created as a
child device of timer since the same register range is used.
Signed-off-by: Nick Hawkins <[email protected]>
---
v7:
* Change commit description to replace Adding with Add and compliment
with complement
* Removed unused include files of_address.h and of_platform.h
* Fixed the max timeout on watchdog to be 655350
* Changed time variable computations in gxp_wdt_set_timeout to be clear
* Decreased reboot delay to 10ms from 100ms
* Added comment to explain why it is necessary to pass the base address
over a private interface from the timer driver.
v6:
* No code change.
* Fixed commit subject line to match the ones in log.
* Adjusted commit message to be closer to 75 chars per line.
v5:
* Fixed version log
* Added details to Kconfig for module support.
* Adjusted commit messaged
v4:
* Made watchdog a child of timer as they share the same register region
per change request on dtsi.
* Removed extra parenthesis
* Fixed u8 u32 u64 usage
* Fixed alignment issue
* Reconfigured conditional statement for interrupt setup
* Removed unused gxp_wdt_remove function
v3:
* Put into proper patchset format
v2:
* No change
---
drivers/watchdog/Kconfig | 11 +++
drivers/watchdog/Makefile | 1 +
drivers/watchdog/gxp-wdt.c | 173 +++++++++++++++++++++++++++++++++++++
3 files changed, 185 insertions(+)
create mode 100644 drivers/watchdog/gxp-wdt.c
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index c4e82a8d863f..a591cc6aa152 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1820,6 +1820,17 @@ config RALINK_WDT
help
Hardware driver for the Ralink SoC Watchdog Timer.
+config GXP_WATCHDOG
+ tristate "HPE GXP watchdog support"
+ depends on ARCH_HPE_GXP
+ select WATCHDOG_CORE
+ help
+ Say Y here to include support for the watchdog timer
+ in HPE GXP SoCs.
+
+ To compile this driver as a module, choose M here.
+ The module will be called gxp-wdt.
+
config MT7621_WDT
tristate "Mediatek SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index f7da867e8782..e2acf3a0d0fc 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_RTD119X_WATCHDOG) += rtd119x_wdt.o
obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o
obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o
obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o
+obj-$(CONFIG_GXP_WATCHDOG) += gxp-wdt.o
obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o
obj-$(CONFIG_MSC313E_WATCHDOG) += msc313e_wdt.o
obj-$(CONFIG_APPLE_WATCHDOG) += apple_wdt.o
diff --git a/drivers/watchdog/gxp-wdt.c b/drivers/watchdog/gxp-wdt.c
new file mode 100644
index 000000000000..2605249e35d1
--- /dev/null
+++ b/drivers/watchdog/gxp-wdt.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/watchdog.h>
+
+#define MASK_WDGCS_ENABLE 0x01
+#define MASK_WDGCS_RELOAD 0x04
+#define MASK_WDGCS_NMIEN 0x08
+#define MASK_WDGCS_WARN 0x80
+
+#define WDT_MAX_TIMEOUT_MS 655350
+#define WDT_DEFAULT_TIMEOUT 30
+#define SECS_TO_WDOG_TICKS(x) ((x) * 100)
+#define WDOG_TICKS_TO_SECS(x) ((x) / 100)
+
+#define GXP_WDT_CNT_OFS 0x10
+#define GXP_WDT_CTRL_OFS 0x16
+
+struct gxp_wdt {
+ void __iomem *base;
+ struct watchdog_device wdd;
+};
+
+static void gxp_wdt_enable_reload(struct gxp_wdt *drvdata)
+{
+ u8 val;
+
+ val = readb(drvdata->base + GXP_WDT_CTRL_OFS);
+ val |= (MASK_WDGCS_ENABLE | MASK_WDGCS_RELOAD);
+ writeb(val, drvdata->base + GXP_WDT_CTRL_OFS);
+}
+
+static int gxp_wdt_start(struct watchdog_device *wdd)
+{
+ struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
+
+ writew(SECS_TO_WDOG_TICKS(wdd->timeout), drvdata->base + GXP_WDT_CNT_OFS);
+ gxp_wdt_enable_reload(drvdata);
+ return 0;
+}
+
+static int gxp_wdt_stop(struct watchdog_device *wdd)
+{
+ struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
+ u8 val;
+
+ val = readb_relaxed(drvdata->base + GXP_WDT_CTRL_OFS);
+ val &= ~MASK_WDGCS_ENABLE;
+ writeb(val, drvdata->base + GXP_WDT_CTRL_OFS);
+ return 0;
+}
+
+static int gxp_wdt_set_timeout(struct watchdog_device *wdd,
+ unsigned int timeout)
+{
+ struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
+ u32 actual;
+
+ wdd->timeout = timeout;
+ actual = min(timeout * 100, wdd->max_hw_heartbeat_ms / 10);
+ writew(actual, drvdata->base + GXP_WDT_CNT_OFS);
+
+ return 0;
+}
+
+static unsigned int gxp_wdt_get_timeleft(struct watchdog_device *wdd)
+{
+ struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
+ u32 val = readw(drvdata->base + GXP_WDT_CNT_OFS);
+
+ return WDOG_TICKS_TO_SECS(val);
+}
+
+static int gxp_wdt_ping(struct watchdog_device *wdd)
+{
+ struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
+
+ gxp_wdt_enable_reload(drvdata);
+ return 0;
+}
+
+static int gxp_restart(struct watchdog_device *wdd, unsigned long action,
+ void *data)
+{
+ struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
+
+ writew(1, drvdata->base + GXP_WDT_CNT_OFS);
+ gxp_wdt_enable_reload(drvdata);
+ mdelay(100);
+ return 0;
+}
+
+static const struct watchdog_ops gxp_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = gxp_wdt_start,
+ .stop = gxp_wdt_stop,
+ .ping = gxp_wdt_ping,
+ .set_timeout = gxp_wdt_set_timeout,
+ .get_timeleft = gxp_wdt_get_timeleft,
+ .restart = gxp_restart,
+};
+
+static const struct watchdog_info gxp_wdt_info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .identity = "HPE GXP Watchdog timer",
+};
+
+static int gxp_wdt_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct gxp_wdt *drvdata;
+ int err;
+ u8 val;
+
+ drvdata = devm_kzalloc(dev, sizeof(struct gxp_wdt), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ /* The register area where the timer and watchdog reside is disarranged.
+ * Hence mapping individual register blocks for the timer and watchdog
+ * is not recommended as they would have access to each others
+ * registers. Based on feedback the watchdog is no longer part of the
+ * device tree file and the timer driver now creates the watchdog as a
+ * child device. During the watchdogs creation, the timer driver passes
+ * the base address to the watchdog over the private interface.
+ */
+
+ drvdata->base = (void __iomem *)dev->platform_data;
+
+ drvdata->wdd.info = &gxp_wdt_info;
+ drvdata->wdd.ops = &gxp_wdt_ops;
+ drvdata->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
+ drvdata->wdd.parent = dev;
+ drvdata->wdd.timeout = WDT_DEFAULT_TIMEOUT;
+
+ watchdog_set_drvdata(&drvdata->wdd, drvdata);
+ watchdog_set_nowayout(&drvdata->wdd, WATCHDOG_NOWAYOUT);
+
+ val = readb(drvdata->base + GXP_WDT_CTRL_OFS);
+
+ if (val & MASK_WDGCS_ENABLE)
+ set_bit(WDOG_HW_RUNNING, &drvdata->wdd.status);
+
+ watchdog_set_restart_priority(&drvdata->wdd, 128);
+
+ watchdog_stop_on_reboot(&drvdata->wdd);
+ err = devm_watchdog_register_device(dev, &drvdata->wdd);
+ if (err) {
+ dev_err(dev, "Failed to register watchdog device");
+ return err;
+ }
+
+ dev_info(dev, "HPE GXP watchdog timer");
+
+ return 0;
+}
+
+static struct platform_driver gxp_wdt_driver = {
+ .probe = gxp_wdt_probe,
+ .driver = {
+ .name = "gxp-wdt",
+ },
+};
+module_platform_driver(gxp_wdt_driver);
+
+MODULE_AUTHOR("Nick Hawkins <[email protected]>");
+MODULE_AUTHOR("Jean-Marie Verdun <[email protected]>");
+MODULE_DESCRIPTION("Driver for GXP watchdog timer");
--
2.17.1
From: Nick Hawkins <[email protected]>
Enable HPE GXP Architecture and its watchdog for base support for HPE
GXP SoCs.
Signed-off-by: Nick Hawkins <[email protected]>
---
v7:
* No change
v6:
* Changed the title to match others in log
* Changed the patch description
* Ran savedefconfig to place GXP configs in file correctly
v5:
* Fix version log
v4:
* No change
v3:
* Put into proper patch format
* Modified the multi_v7_defconfig instead of creating a gxp_defconfig
v2:
* Created gxp_defconfig
---
arch/arm/configs/multi_v7_defconfig | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 6e0c8c19b35c..bdbb1c90e65d 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -42,6 +42,8 @@ CONFIG_ARCH_HI3xxx=y
CONFIG_ARCH_HIP01=y
CONFIG_ARCH_HIP04=y
CONFIG_ARCH_HIX5HD2=y
+CONFIG_ARCH_HPE=y
+CONFIG_ARCH_HPE_GXP=y
CONFIG_ARCH_MXC=y
CONFIG_SOC_IMX50=y
CONFIG_SOC_IMX51=y
@@ -562,6 +564,7 @@ CONFIG_BCM47XX_WDT=y
CONFIG_BCM2835_WDT=y
CONFIG_BCM_KONA_WDT=y
CONFIG_BCM7038_WDT=m
+CONFIG_GXP_WATCHDOG=y
CONFIG_BCMA_HOST_SOC=y
CONFIG_BCMA_DRIVER_GMAC_CMN=y
CONFIG_BCMA_DRIVER_GPIO=y
--
2.17.1
From: Nick Hawkins <[email protected]>
Add support for the HPE GXP Timer and Watchdog. There are multiple
timers on the SoC but only one is enabled at this time.
Signed-off-by: Nick Hawkins <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Reviewed-by: Rob Herring <[email protected]>
---
v7:
* Resubmission to fix subject from
dt-bindings: timer: hpe,gxp-timer: Creation to
dt-bindings: timer: hpe,gxp-timer: Add HPE GXP Timer and Watchdog
based on comment: 'The subject after prefixes does not match it better.
What is "creation"? "Add HPE GXP Timer and Watchdog"'
* Copied over Reviewed-by tags from previous patch.
v6:
* Removed simple-mfd compatible, timer will create watchdog without
watchdog node.
* Removed timer0 label
* Changed title from HPE GXP TIMER to HPE GXP Timer
* Changed clock name iopclk to iop
* Set additionalProperties to false
* Added space after ',' in the compatible list
* Changed subject to match the log better
* Altered description to take up 75 characters per line
* Changed description to better describe the patch
v5:
* Fix versioning
* Fixed typo time -> timer
v4:
* Made watchdog a child of timer
* Added reference clock
v3:
* Removed maintainer change from patch
* Verified there was no compilation errors
* Added reference code in separate patch of patchset
v2:
* Converted from txt to yaml
---
.../bindings/timer/hpe,gxp-timer.yaml | 47 +++++++++++++++++++
1 file changed, 47 insertions(+)
create mode 100644 Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
diff --git a/Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml b/Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
new file mode 100644
index 000000000000..d33d90f44d28
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/hpe,gxp-timer.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/timer/hpe,gxp-timer.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: HPE GXP Timer
+
+maintainers:
+ - Nick Hawkins <[email protected]>
+ - Jean-Marie Verdun <[email protected]>
+
+properties:
+ compatible:
+ const: hpe,gxp-timer
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: iop
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+
+additionalProperties: false
+
+examples:
+ - |
+ timer@c0000000 {
+ compatible = "hpe,gxp-timer";
+ reg = <0x80 0x16>;
+ interrupts = <0>;
+ interrupt-parent = <&vic0>;
+ clocks = <&iopclk>;
+ clock-names = "iop";
+ };
--
2.17.1
On 5/6/22 12:13, [email protected] wrote:
> From: Nick Hawkins <[email protected]>
>
> Add support for the HPE GXP Watchdog. The GXP asic contains a full
> complement of timers one of which is the watchdog timer. The watchdog
> timer is 16 bit and has 10ms resolution. The watchdog is created as a
> child device of timer since the same register range is used.
>
> Signed-off-by: Nick Hawkins <[email protected]>
>
> ---
> v7:
> * Change commit description to replace Adding with Add and compliment
> with complement
> * Removed unused include files of_address.h and of_platform.h
> * Fixed the max timeout on watchdog to be 655350
> * Changed time variable computations in gxp_wdt_set_timeout to be clear
> * Decreased reboot delay to 10ms from 100ms
> * Added comment to explain why it is necessary to pass the base address
> over a private interface from the timer driver.
> v6:
> * No code change.
> * Fixed commit subject line to match the ones in log.
> * Adjusted commit message to be closer to 75 chars per line.
> v5:
> * Fixed version log
> * Added details to Kconfig for module support.
> * Adjusted commit messaged
> v4:
> * Made watchdog a child of timer as they share the same register region
> per change request on dtsi.
> * Removed extra parenthesis
> * Fixed u8 u32 u64 usage
> * Fixed alignment issue
> * Reconfigured conditional statement for interrupt setup
> * Removed unused gxp_wdt_remove function
> v3:
> * Put into proper patchset format
> v2:
> * No change
> ---
> drivers/watchdog/Kconfig | 11 +++
> drivers/watchdog/Makefile | 1 +
> drivers/watchdog/gxp-wdt.c | 173 +++++++++++++++++++++++++++++++++++++
> 3 files changed, 185 insertions(+)
> create mode 100644 drivers/watchdog/gxp-wdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index c4e82a8d863f..a591cc6aa152 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -1820,6 +1820,17 @@ config RALINK_WDT
> help
> Hardware driver for the Ralink SoC Watchdog Timer.
>
> +config GXP_WATCHDOG
> + tristate "HPE GXP watchdog support"
> + depends on ARCH_HPE_GXP
> + select WATCHDOG_CORE
> + help
> + Say Y here to include support for the watchdog timer
> + in HPE GXP SoCs.
> +
> + To compile this driver as a module, choose M here.
> + The module will be called gxp-wdt.
> +
> config MT7621_WDT
> tristate "Mediatek SoC watchdog"
> select WATCHDOG_CORE
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index f7da867e8782..e2acf3a0d0fc 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -92,6 +92,7 @@ obj-$(CONFIG_RTD119X_WATCHDOG) += rtd119x_wdt.o
> obj-$(CONFIG_SPRD_WATCHDOG) += sprd_wdt.o
> obj-$(CONFIG_PM8916_WATCHDOG) += pm8916_wdt.o
> obj-$(CONFIG_ARM_SMC_WATCHDOG) += arm_smc_wdt.o
> +obj-$(CONFIG_GXP_WATCHDOG) += gxp-wdt.o
> obj-$(CONFIG_VISCONTI_WATCHDOG) += visconti_wdt.o
> obj-$(CONFIG_MSC313E_WATCHDOG) += msc313e_wdt.o
> obj-$(CONFIG_APPLE_WATCHDOG) += apple_wdt.o
> diff --git a/drivers/watchdog/gxp-wdt.c b/drivers/watchdog/gxp-wdt.c
> new file mode 100644
> index 000000000000..2605249e35d1
> --- /dev/null
> +++ b/drivers/watchdog/gxp-wdt.c
> @@ -0,0 +1,173 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (C) 2022 Hewlett-Packard Enterprise Development Company, L.P. */
> +
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/types.h>
> +#include <linux/watchdog.h>
> +
> +#define MASK_WDGCS_ENABLE 0x01
> +#define MASK_WDGCS_RELOAD 0x04
> +#define MASK_WDGCS_NMIEN 0x08
> +#define MASK_WDGCS_WARN 0x80
> +
> +#define WDT_MAX_TIMEOUT_MS 655350
> +#define WDT_DEFAULT_TIMEOUT 30
> +#define SECS_TO_WDOG_TICKS(x) ((x) * 100)
> +#define WDOG_TICKS_TO_SECS(x) ((x) / 100)
> +
> +#define GXP_WDT_CNT_OFS 0x10
> +#define GXP_WDT_CTRL_OFS 0x16
> +
> +struct gxp_wdt {
> + void __iomem *base;
> + struct watchdog_device wdd;
> +};
> +
> +static void gxp_wdt_enable_reload(struct gxp_wdt *drvdata)
> +{
> + u8 val;
> +
> + val = readb(drvdata->base + GXP_WDT_CTRL_OFS);
> + val |= (MASK_WDGCS_ENABLE | MASK_WDGCS_RELOAD);
> + writeb(val, drvdata->base + GXP_WDT_CTRL_OFS);
> +}
> +
> +static int gxp_wdt_start(struct watchdog_device *wdd)
> +{
> + struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
> +
> + writew(SECS_TO_WDOG_TICKS(wdd->timeout), drvdata->base + GXP_WDT_CNT_OFS);
> + gxp_wdt_enable_reload(drvdata);
> + return 0;
> +}
> +
> +static int gxp_wdt_stop(struct watchdog_device *wdd)
> +{
> + struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
> + u8 val;
> +
> + val = readb_relaxed(drvdata->base + GXP_WDT_CTRL_OFS);
> + val &= ~MASK_WDGCS_ENABLE;
> + writeb(val, drvdata->base + GXP_WDT_CTRL_OFS);
> + return 0;
> +}
> +
> +static int gxp_wdt_set_timeout(struct watchdog_device *wdd,
> + unsigned int timeout)
> +{
> + struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
> + u32 actual;
> +
> + wdd->timeout = timeout;
> + actual = min(timeout * 100, wdd->max_hw_heartbeat_ms / 10);
> + writew(actual, drvdata->base + GXP_WDT_CNT_OFS);
> +
> + return 0;
> +}
> +
> +static unsigned int gxp_wdt_get_timeleft(struct watchdog_device *wdd)
> +{
> + struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
> + u32 val = readw(drvdata->base + GXP_WDT_CNT_OFS);
> +
> + return WDOG_TICKS_TO_SECS(val);
> +}
> +
> +static int gxp_wdt_ping(struct watchdog_device *wdd)
> +{
> + struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
> +
> + gxp_wdt_enable_reload(drvdata);
> + return 0;
> +}
> +
> +static int gxp_restart(struct watchdog_device *wdd, unsigned long action,
> + void *data)
> +{
> + struct gxp_wdt *drvdata = watchdog_get_drvdata(wdd);
> +
> + writew(1, drvdata->base + GXP_WDT_CNT_OFS);
> + gxp_wdt_enable_reload(drvdata);
> + mdelay(100);
> + return 0;
> +}
> +
> +static const struct watchdog_ops gxp_wdt_ops = {
> + .owner = THIS_MODULE,
> + .start = gxp_wdt_start,
> + .stop = gxp_wdt_stop,
> + .ping = gxp_wdt_ping,
> + .set_timeout = gxp_wdt_set_timeout,
> + .get_timeleft = gxp_wdt_get_timeleft,
> + .restart = gxp_restart,
> +};
> +
> +static const struct watchdog_info gxp_wdt_info = {
> + .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
> + .identity = "HPE GXP Watchdog timer",
> +};
> +
> +static int gxp_wdt_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct gxp_wdt *drvdata;
> + int err;
> + u8 val;
> +
> + drvdata = devm_kzalloc(dev, sizeof(struct gxp_wdt), GFP_KERNEL);
> + if (!drvdata)
> + return -ENOMEM;
> +
> + /* The register area where the timer and watchdog reside is disarranged.
> + * Hence mapping individual register blocks for the timer and watchdog
> + * is not recommended as they would have access to each others
> + * registers. Based on feedback the watchdog is no longer part of the
> + * device tree file and the timer driver now creates the watchdog as a
> + * child device. During the watchdogs creation, the timer driver passes
> + * the base address to the watchdog over the private interface.
> + */
/*
* Please use standard multi-line comments in the watchdog subsystem.
*/
> +
> + drvdata->base = (void __iomem *)dev->platform_data;
> +
> + drvdata->wdd.info = &gxp_wdt_info;
> + drvdata->wdd.ops = &gxp_wdt_ops;
> + drvdata->wdd.max_hw_heartbeat_ms = WDT_MAX_TIMEOUT_MS;
> + drvdata->wdd.parent = dev;
> + drvdata->wdd.timeout = WDT_DEFAULT_TIMEOUT;
> +
> + watchdog_set_drvdata(&drvdata->wdd, drvdata);
> + watchdog_set_nowayout(&drvdata->wdd, WATCHDOG_NOWAYOUT);
> +
> + val = readb(drvdata->base + GXP_WDT_CTRL_OFS);
> +
> + if (val & MASK_WDGCS_ENABLE)
> + set_bit(WDOG_HW_RUNNING, &drvdata->wdd.status);
> +
> + watchdog_set_restart_priority(&drvdata->wdd, 128);
> +
> + watchdog_stop_on_reboot(&drvdata->wdd);
> + err = devm_watchdog_register_device(dev, &drvdata->wdd);
> + if (err) {
> + dev_err(dev, "Failed to register watchdog device");
> + return err;
> + }
> +
> + dev_info(dev, "HPE GXP watchdog timer");
> +
> + return 0;
> +}
> +
> +static struct platform_driver gxp_wdt_driver = {
> + .probe = gxp_wdt_probe,
> + .driver = {
> + .name = "gxp-wdt",
> + },
> +};
> +module_platform_driver(gxp_wdt_driver);
> +
> +MODULE_AUTHOR("Nick Hawkins <[email protected]>");
> +MODULE_AUTHOR("Jean-Marie Verdun <[email protected]>");
> +MODULE_DESCRIPTION("Driver for GXP watchdog timer");
On 5/6/22 12:13, [email protected] wrote:
> From: Nick Hawkins <[email protected]>
>
> + /* The register area where the timer and watchdog reside is disarranged.
> + * Hence mapping individual register blocks for the timer and watchdog
> + * is not recommended as they would have access to each others
> + * registers. Based on feedback the watchdog is no longer part of the
> + * device tree file and the timer driver now creates the watchdog as a
> + * child device. During the watchdogs creation, the timer driver passes
> + * the base address to the watchdog over the private interface.
> + */
/*
* Please use standard multi-line comments in the watchdog subsystem.
*/
Hi Guenter,
Thank you for the feedback. I will fix this with a v8 version of the patchset.
-Nick
Hi!
> From: Nick Hawkins <[email protected]>
>
> The GXP is the HPE BMC SoC that is used in the majority
> of current generation HPE servers. Traditionally the asic will
> last multiple generations of server before being replaced.
>
> Info about SoC:
Normally, 1/7 goes into the same thread as 0/7 mail.
Best regards,
Pavel
> > From: Nick Hawkins <[email protected]>
> >
> > The GXP is the HPE BMC SoC that is used in the majority of current
> > generation HPE servers. Traditionally the asic will last multiple
> > generations of server before being replaced.
> >
> > Info about SoC:
> Normally, 1/7 goes into the same thread as 0/7 mail.
Hello Pavel,
Thank you for the feedback. I believe the code is already in the process of being merged upstream in version v8. For future reference can you elaborate on what you mean?
Thanks,
-Nick Hawkins
On Wed 2022-06-01 14:14:33, Hawkins, Nick wrote:
> > > From: Nick Hawkins <[email protected]>
> > >
> > > The GXP is the HPE BMC SoC that is used in the majority of current
> > > generation HPE servers. Traditionally the asic will last multiple
> > > generations of server before being replaced.
> > >
> > > Info about SoC:
>
> > Normally, 1/7 goes into the same thread as 0/7 mail.
>
> Hello Pavel,
>
> Thank you for the feedback. I believe the code is already in the process of being merged upstream in version v8. For future reference can you elaborate on what you mean?
>
You used separate email threads for 0/7 and the rest of the
patches. Normally, they should go to single email thread.
Best regards,
Pavel
--
People of Russia, stop Putin before his war on Ukraine escalates.
On Wed, Jun 1, 2022 at 10:57 PM Pavel Machek <[email protected]> wrote:
> On Wed 2022-06-01 14:14:33, Hawkins, Nick wrote:
> > > > From: Nick Hawkins <[email protected]>
> > > >
> > > > The GXP is the HPE BMC SoC that is used in the majority of current
> > > > generation HPE servers. Traditionally the asic will last multiple
> > > > generations of server before being replaced.
> > > >
> > > > Info about SoC:
> >
> > > Normally, 1/7 goes into the same thread as 0/7 mail.
> >
> > Hello Pavel,
> >
> > Thank you for the feedback. I believe the code is already in the process of being merged upstream in version v8. For future reference can you elaborate on what you mean?
> >
>
> You used separate email threads for 0/7 and the rest of the
> patches. Normally, they should go to single email thread.
>
To clarify: the way this is normally done is to prepare the series using
'git format-patch --cover-letter ...' and then send it using 'git send-email
--thread --no-chain-reply', which makes all patches a reply to the
cover letter.
Arnd
> To clarify: the way this is normally done is to prepare the series using 'git format-patch --cover-letter ...' and then send it using 'git send-email --thread --no-chain-reply', which makes all patches a reply to the cover letter.
I see thank you for the information! I will be sure to use this on future patch sets.
-Nick Hawkins