Re: [PATCH] watchdog: sbsa: Support architecture version 1

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 5/9/21 8:41 PM, Shaokun Zhang wrote:
Arm Base System Architecture 1.0[1] has introduced watchdog
revision 1 that increases the length the watchdog offset

Is that how they call the watchdog count register ?

Also, doesn't that mean that the maximum timeout supported
by the hardware is now larger ?

regiter to 48 bit, while other operation of the watchdog remains

register

the same.
Let's support the feature infered it from the architecture version

I can't parse this sentence.

of watchdog in W_IID register. If the version is 0x1, the watchdog

W_IIDR ?

offset register will be 48 bit, otherwise it will be 32 bit.

48 or 64 ? The code says 64.


[1] https://developer.arm.com/documentation/den0094/latest


There is no download link at that location. Someone with access
to the documentation will have to confirm this.

Cc: Wim Van Sebroeck <wim@xxxxxxxxxxxxxxxxxx>
Cc: Guenter Roeck <linux@xxxxxxxxxxxx>
Cc: Fu Wei <fu.wei@xxxxxxxxxx>
Cc: Suravee Suthikulpanit <Suravee.Suthikulpanit@xxxxxxx>
Cc: Al Stone <al.stone@xxxxxxxxxx>
Cc: Timur Tabi <timur@xxxxxxxxxxxxxx>
Cc: Jianchao Hu <hujianchao@xxxxxxxxxxxxx>
Cc: Huiqiang Wang <wanghuiqiang@xxxxxxxxxx>
Signed-off-by: Shaokun Zhang <zhangshaokun@xxxxxxxxxxxxx>
---
  drivers/watchdog/sbsa_gwdt.c | 46 +++++++++++++++++++++++++++++++++++++++-----
  1 file changed, 41 insertions(+), 5 deletions(-)

diff --git a/drivers/watchdog/sbsa_gwdt.c b/drivers/watchdog/sbsa_gwdt.c
index f0f1e3b2e463..ca4f7c416f1e 100644
--- a/drivers/watchdog/sbsa_gwdt.c
+++ b/drivers/watchdog/sbsa_gwdt.c
@@ -73,16 +73,21 @@
  #define SBSA_GWDT_WCS_WS0	BIT(1)
  #define SBSA_GWDT_WCS_WS1	BIT(2)
+#define SBSA_GWDT_VERSION_MASK 0xF
+#define SBSA_GWDT_VERSION_SHIFT 16
+
  /**
   * struct sbsa_gwdt - Internal representation of the SBSA GWDT
   * @wdd:		kernel watchdog_device structure
   * @clk:		store the System Counter clock frequency, in Hz.
+ * @version:            store the architecture version
   * @refresh_base:	Virtual address of the watchdog refresh frame
   * @control_base:	Virtual address of the watchdog control frame
   */
  struct sbsa_gwdt {
  	struct watchdog_device	wdd;
  	u32			clk;
+	int			version;
  	void __iomem		*refresh_base;
  	void __iomem		*control_base;
  };
@@ -113,6 +118,27 @@ MODULE_PARM_DESC(nowayout,
  		 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
/*
+ * Read and write are 32 or 64 bits depending on watchdog architecture
+ * version: if version is equal 0, its 32-bits operation; otherwise 64-bits
+ * operation is chosen.
+ */
+static u64 sbsa_gwdt_reg_read(struct sbsa_gwdt *gwdt)
+{
+	if (gwdt->version == 0)
+		return (u64)readl(gwdt->control_base + SBSA_GWDT_WOR);

Unnecessary typecast.

+	else
+		return readq(gwdt->control_base + SBSA_GWDT_WOR);
+}
+
+static void sbsa_gwdt_reg_write(u64 val, struct sbsa_gwdt *gwdt)

What is the point of making val an u64 variable ? Without changing
the maximum timeout it will never be larger than 0xffffffff.

+{
+	if (gwdt->version == 0)
+		writel((u32)val, gwdt->control_base + SBSA_GWDT_WOR);
+	else
+		writeq(val, gwdt->control_base + SBSA_GWDT_WOR);
+}
+
+/*
   * watchdog operation functions
   */
  static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
@@ -123,16 +149,14 @@ static int sbsa_gwdt_set_timeout(struct watchdog_device *wdd,
  	wdd->timeout = timeout;
if (action)
-		writel(gwdt->clk * timeout,
-		       gwdt->control_base + SBSA_GWDT_WOR);
+		sbsa_gwdt_reg_write(gwdt->clk * timeout, gwdt);
  	else
  		/*
  		 * In the single stage mode, The first signal (WS0) is ignored,
  		 * the timeout is (WOR * 2), so the WOR should be configured
  		 * to half value of timeout.
  		 */
-		writel(gwdt->clk / 2 * timeout,
-		       gwdt->control_base + SBSA_GWDT_WOR);
+		sbsa_gwdt_reg_write(gwdt->clk / 2 * timeout, gwdt);
return 0;
  }
@@ -149,7 +173,7 @@ static unsigned int sbsa_gwdt_get_timeleft(struct watchdog_device *wdd)
  	 */
  	if (!action &&
  	    !(readl(gwdt->control_base + SBSA_GWDT_WCS) & SBSA_GWDT_WCS_WS0))
-		timeleft += readl(gwdt->control_base + SBSA_GWDT_WOR);
+		timeleft += sbsa_gwdt_reg_read(gwdt);
timeleft += lo_hi_readq(gwdt->control_base + SBSA_GWDT_WCV) -
  		    arch_timer_read_counter();
@@ -172,6 +196,17 @@ static int sbsa_gwdt_keepalive(struct watchdog_device *wdd)
  	return 0;
  }
+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 = (ver >> SBSA_GWDT_VERSION_SHIFT) & SBSA_GWDT_VERSION_MASK;
+
+	gwdt->version = ver;
+}
+
  static int sbsa_gwdt_start(struct watchdog_device *wdd)
  {
  	struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
@@ -300,6 +335,7 @@ static int sbsa_gwdt_probe(struct platform_device *pdev)
  	 * it's also a ping, if watchdog is enabled.
  	 */
  	sbsa_gwdt_set_timeout(wdd, wdd->timeout);
+	sbsa_gwdt_get_version(wdd);
watchdog_stop_on_reboot(wdd);
  	ret = devm_watchdog_register_device(dev, wdd);





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux