diff mbox series

[3/3] watchdog: bcm63xx_wdt: support BCM4908

Message ID 20211027215531.9996-3-zajec5@gmail.com (mailing list archive)
State Not Applicable
Headers show
Series [1/3] dt-bindings: watchdog: add Broadcom's BCM63xx watchdog | expand

Commit Message

Rafał Miłecki Oct. 27, 2021, 9:55 p.m. UTC
From: Rafał Miłecki <rafal@milecki.pl>

So far bcm63xx_wdt included support for Broadcom's watchdog block of old
MIPS devices only. It was also a fully platform (non-DT) driver.

The same block was recently found on BCM4908 with just a slightly
different registers layout. Extend this driver to support OF and add
support for per-chipset registers offsets.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
---
 drivers/watchdog/Kconfig       |  2 +-
 drivers/watchdog/bcm63xx_wdt.c | 63 ++++++++++++++++++++++++++++++----
 2 files changed, 57 insertions(+), 8 deletions(-)

Comments

Guenter Roeck Oct. 27, 2021, 10:22 p.m. UTC | #1
On Wed, Oct 27, 2021 at 11:55:31PM +0200, Rafał Miłecki wrote:
> From: Rafał Miłecki <rafal@milecki.pl>
> 
> So far bcm63xx_wdt included support for Broadcom's watchdog block of old
> MIPS devices only. It was also a fully platform (non-DT) driver.
> 
> The same block was recently found on BCM4908 with just a slightly
> different registers layout. Extend this driver to support OF and add
> support for per-chipset registers offsets.
> 
> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>

Please convert the driver to use the watchdog subsystem first.
Also, when doing so, please explain why you don't use the bcm7038
driver instead, since it serves the same hardware interface and
already supports the watchdog core.

Guenter
Florian Fainelli Oct. 27, 2021, 10:28 p.m. UTC | #2
On 10/27/21 3:22 PM, Guenter Roeck wrote:
> On Wed, Oct 27, 2021 at 11:55:31PM +0200, Rafał Miłecki wrote:
>> From: Rafał Miłecki <rafal@milecki.pl>
>>
>> So far bcm63xx_wdt included support for Broadcom's watchdog block of old
>> MIPS devices only. It was also a fully platform (non-DT) driver.
>>
>> The same block was recently found on BCM4908 with just a slightly
>> different registers layout. Extend this driver to support OF and add
>> support for per-chipset registers offsets.
>>
>> Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
> 
> Please convert the driver to use the watchdog subsystem first.
> Also, when doing so, please explain why you don't use the bcm7038
> driver instead, since it serves the same hardware interface and
> already supports the watchdog core.

This is too ugly unfortunately so yes let us use bcm7038_wdt.c and let
me know if you need help with converting arch/mips/bcm63xx to use the
bcm7038_wdt.c
diff mbox series

Patch

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 913cde027e92..58a2474cd929 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1711,7 +1711,7 @@  config OCTEON_WDT
 
 config BCM63XX_WDT
 	tristate "Broadcom BCM63xx hardware watchdog"
-	depends on BCM63XX || COMPILE_TEST
+	depends on ARCH_BCM4908 || BCM63XX || COMPILE_TEST
 	help
 	  Watchdog driver for the built in watchdog hardware in Broadcom
 	  BCM63xx SoC.
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 1334e7fe77d8..df3c7dfea00f 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -18,6 +18,7 @@ 
 #include <linux/miscdevice.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
+#include <linux/of_device.h>
 #include <linux/types.h>
 #include <linux/uaccess.h>
 #include <linux/watchdog.h>
@@ -39,7 +40,13 @@ 
 #define WDT_DEFAULT_TIME	30      /* seconds */
 #define WDT_MAX_TIME		256     /* seconds */
 
+enum bcm63xx_wdt_soc {
+	BCM63XX_WDT_SOC_BCM4908,
+	BCM63XX_WDT_SOC_BCM63XX,
+};
+
 static struct {
+	enum bcm63xx_wdt_soc soc;
 	void __iomem *regs;
 	struct timer_list timer;
 	unsigned long inuse;
@@ -54,11 +61,41 @@  module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
 	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static void bcm63xx_wdt_write_reg(u32 reg, u32 val)
+static const struct of_device_id bcm63xx_wdt_id_table[] = {
+	{ .compatible = "brcm,bcm4908-wdt", .data = (const void *)BCM63XX_WDT_SOC_BCM4908, },
+	{},
+};
+
+enum bcm63xx_wdt_regs {
+	BCM63XX_WDT_REG_DEFVAL = 0,
+	BCM63XX_WDT_REG_CTL,
+	BCM63XX_WDT_REG_SOFTRESET,
+};
+
+static const u16 bcm63xx_wdt_regs_bcm4908[] = {
+	[BCM63XX_WDT_REG_DEFVAL]	= 0x28,
+	[BCM63XX_WDT_REG_CTL]		= 0x2c,
+	[BCM63XX_WDT_REG_SOFTRESET]	= 0x34,
+};
+
+static const u16 bcm63xx_wdt_regs_bcm63xx[] = {
+	[BCM63XX_WDT_REG_DEFVAL]	= WDT_DEFVAL_REG,
+	[BCM63XX_WDT_REG_CTL]		= WDT_CTL_REG,
+};
+
+static void bcm63xx_wdt_write_reg(enum bcm63xx_wdt_regs reg, u32 val)
 {
 	void __iomem *addr = bcm63xx_wdt_device.regs;
 
-	addr += reg;
+	switch (bcm63xx_wdt_device.soc) {
+	case BCM63XX_WDT_SOC_BCM4908:
+		addr += bcm63xx_wdt_regs_bcm4908[reg];
+		break;
+	case BCM63XX_WDT_SOC_BCM63XX:
+		addr += bcm63xx_wdt_regs_bcm63xx[reg];
+		break;
+	}
+
 #ifdef BCM63XX
 	bcm_writel(val, addr);
 #else
@@ -69,15 +106,15 @@  static void bcm63xx_wdt_write_reg(u32 reg, u32 val)
 /* HW functions */
 static void bcm63xx_wdt_hw_start(void)
 {
-	bcm63xx_wdt_write_reg(WDT_DEFVAL_REG, 0xfffffffe);
-	bcm63xx_wdt_write_reg(WDT_CTL_REG, WDT_START_1);
-	bcm63xx_wdt_write_reg(WDT_CTL_REG, WDT_START_2);
+	bcm63xx_wdt_write_reg(BCM63XX_WDT_REG_DEFVAL, 0xfffffffe);
+	bcm63xx_wdt_write_reg(BCM63XX_WDT_REG_CTL, WDT_START_1);
+	bcm63xx_wdt_write_reg(BCM63XX_WDT_REG_CTL, WDT_START_2);
 }
 
 static void bcm63xx_wdt_hw_stop(void)
 {
-	bcm63xx_wdt_write_reg(WDT_CTL_REG, WDT_STOP_1);
-	bcm63xx_wdt_write_reg(WDT_CTL_REG, WDT_STOP_2);
+	bcm63xx_wdt_write_reg(BCM63XX_WDT_REG_CTL, WDT_STOP_1);
+	bcm63xx_wdt_write_reg(BCM63XX_WDT_REG_CTL, WDT_STOP_2);
 }
 
 #ifdef BCM63XX
@@ -252,9 +289,19 @@  static struct miscdevice bcm63xx_wdt_miscdev = {
 
 static int bcm63xx_wdt_probe(struct platform_device *pdev)
 {
+	struct device *dev = &pdev->dev;
+	const struct of_device_id *of_id;
 	int ret;
 	struct resource *r;
 
+	of_id = of_match_device(bcm63xx_wdt_id_table, dev);
+	if (of_id) {
+		bcm63xx_wdt_device.soc = (enum bcm63xx_wdt_soc)of_id->data;
+	} else {
+		/* Fallback */
+		bcm63xx_wdt_device.soc = BCM63XX_WDT_SOC_BCM63XX;
+	}
+
 	timer_setup(&bcm63xx_wdt_device.timer, bcm63xx_timer_tick, 0);
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -326,6 +373,7 @@  static struct platform_driver bcm63xx_wdt_driver = {
 	.shutdown = bcm63xx_wdt_shutdown,
 	.driver = {
 		.name = "bcm63xx-wdt",
+		.of_match_table = bcm63xx_wdt_id_table,
 	}
 };
 
@@ -333,6 +381,7 @@  module_platform_driver(bcm63xx_wdt_driver);
 
 MODULE_AUTHOR("Miguel Gaio <miguel.gaio@efixo.com>");
 MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_DEVICE_TABLE(of, bcm63xx_wdt_id_table);
 MODULE_DESCRIPTION("Driver for the Broadcom BCM63xx SoC watchdog");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:bcm63xx-wdt");