Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1200368 > unrolled thread

[PATCH v2 0/2] add a new driver to support SAMA5D4 watchdog timer

Started byWenyou Yang <wenyou.yang@atmel.com>
First post2015-08-05 04:50 +0200
Last post2015-08-05 10:50 +0200
Articles 5 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/2] add a new driver to support SAMA5D4 watchdog timer Wenyou Yang <wenyou.yang@atmel.com> - 2015-08-05 04:50 +0200
    [PATCH v2 2/2] Documentation: dt: binding: atmel-sama5d4-wdt: for SAMA5D4 watchdog driver Wenyou Yang <wenyou.yang@atmel.com> - 2015-08-05 04:50 +0200
    [PATCH v2 1/2] drivers: watchdog: add a driver to support SAMA5D4 watchdog timer Wenyou Yang <wenyou.yang@atmel.com> - 2015-08-05 04:50 +0200
      Re: [PATCH v2 1/2] drivers: watchdog: add a driver to support SAMA5D4  watchdog timer Guenter Roeck <linux@roeck-us.net> - 2015-08-05 08:20 +0200
        RE: [PATCH v2 1/2] drivers: watchdog: add a driver to support  SAMA5D4 watchdog timer "Yang, Wenyou" <Wenyou.Yang@atmel.com> - 2015-08-05 10:50 +0200

#1200368 — [PATCH v2 0/2] add a new driver to support SAMA5D4 watchdog timer

FromWenyou Yang <wenyou.yang@atmel.com>
Date2015-08-05 04:50 +0200
Subject[PATCH v2 0/2] add a new driver to support SAMA5D4 watchdog timer
Message-ID<pTWWe-4R3-3@gated-at.bofh.it>
Hello,

Thank for Guenter's advice, add a new driver to support SAMA5D4 watchdog timer.

Because the watchdog WDT_MR register can be written more than once, its work
mechanism is different from the previous one. Open the device file to enable
the watchdog hardware, close to disable it, and ping it from the user space
directly to keep it alive.

Best Regards,
Wenyou Yang

Wenyou Yang (2):
  drivers: watchdog: add a driver to support SAMA5D4 watchdog timer
  Documentation: dt: binding: atmel-sama5d4-wdt: for SAMA5D4 watchdog
    driver

 .../bindings/watchdog/atmel-sama5d4-wdt.txt        |   35 +++
 drivers/watchdog/Kconfig                           |    9 +
 drivers/watchdog/Makefile                          |    1 +
 drivers/watchdog/at91sam9_wdt.h                    |    4 +
 drivers/watchdog/atmel_wdt.c                       |  290 ++++++++++++++++++++
 5 files changed, 339 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt
 create mode 100644 drivers/watchdog/atmel_wdt.c

-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [next] | [standalone]


#1200369 — [PATCH v2 2/2] Documentation: dt: binding: atmel-sama5d4-wdt: for SAMA5D4 watchdog driver

FromWenyou Yang <wenyou.yang@atmel.com>
Date2015-08-05 04:50 +0200
Subject[PATCH v2 2/2] Documentation: dt: binding: atmel-sama5d4-wdt: for SAMA5D4 watchdog driver
Message-ID<pTWWe-4R3-7@gated-at.bofh.it>
In reply to#1200368
The compatible "atmel,sama5d4-wdt" supports the SAMA5D4 watchdog driver
and the watchdog's WDT_MR register can be written more than once.

Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
---
 .../bindings/watchdog/atmel-sama5d4-wdt.txt        |   35 ++++++++++++++++++++
 1 file changed, 35 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt b/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt
new file mode 100644
index 0000000..f7cc7c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/atmel-sama5d4-wdt.txt
@@ -0,0 +1,35 @@
+* Atmel SAMA5D4 Watchdog Timer (WDT) Controller
+
+Required properties:
+- compatible: "atmel,sama5d4-wdt"
+- reg: base physical address and length of memory mapped region.
+
+Optional properties:
+- timeout-sec: watchdog timeout value (in seconds).
+- interrupts: interrupt number to the CPU.
+- atmel,watchdog-type: should be "hardware" or "software".
+	"hardware": enable watchdog fault reset. A watchdog fault triggers
+		    watchdog reset.
+	"software": enable watchdog fault interrupt. A watchdog fault asserts
+		    watchdog interrupt.
+- atmel,idle-halt: present if you want to stop the watchdog when the CPU is
+		   in idle state.
+	CAUTION: This property should be used with care, it actually makes the
+	watchdog not counting when the CPU is in idle state, therefore the
+	watchdog reset time depends on mean CPU usage and will not reset at all
+	if the CPU stop working while it is in idle state, which is probably
+	not what you want.
+- atmel,dbg-halt: present if you want to stop the watchdog when the CPU is
+		  in debug state.
+
+Example:
+	watchdog@fc068640 {
+		compatible = "atmel,sama5d4-wdt";
+		reg = <0xfc068640 0x10>;
+		interrupts = <4 IRQ_TYPE_LEVEL_HIGH 5>;
+		timeout-sec = <10>;
+		atmel,watchdog-type = "hardware";
+		atmel,dbg-halt;
+		atmel,idle-halt;
+		status = "okay";
+	};
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1200370 — [PATCH v2 1/2] drivers: watchdog: add a driver to support SAMA5D4 watchdog timer

FromWenyou Yang <wenyou.yang@atmel.com>
Date2015-08-05 04:50 +0200
Subject[PATCH v2 1/2] drivers: watchdog: add a driver to support SAMA5D4 watchdog timer
Message-ID<pTWWe-4R3-9@gated-at.bofh.it>
In reply to#1200368
From SAMA5D4, the watchdog timer is upgrated with a new feature,
which is describled as in the datasheet, "WDT_MR can be written
until a LOCKMR command is issued in WDT_CR".
That is to say, as long as the bootstrap and u-boot don't issue
a LOCKMR command, WDT_MR can be written more than once in the driver.

So the SAMA5D4 watchdog driver's implementation is different from
the previous: the user application open the device file to enable
the watchdog timer hardware, and close to disable it, and set the
watchdog timer timeout by seting WDV and WDD fields of WDT_MR register,
and ping the watchdog by issuing WDRSTT command to WDT_CR register
with hard-coded key.

Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
---
 drivers/watchdog/Kconfig        |    9 ++
 drivers/watchdog/Makefile       |    1 +
 drivers/watchdog/at91sam9_wdt.h |    4 +
 drivers/watchdog/atmel_wdt.c    |  290 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 304 insertions(+)
 create mode 100644 drivers/watchdog/atmel_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index e5e7c55..4425813 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -152,6 +152,15 @@ config ARM_SP805_WATCHDOG
 	  ARM Primecell SP805 Watchdog timer. This will reboot your system when
 	  the timeout is reached.
 
+config ATMEL_WATCHDOG
+	tristate "Atmel SAMA5D4 Watchdog Timer"
+	depends on ARCH_AT91
+	select WATCHDOG_CORE
+	help
+	  Atmel watchdog timer embedded into SAMA5D4 chips. Its Watchdog Timer
+	  Mode Register(WDT_MR) can be written more than once.
+	  This will reboot your system when the timeout is reached.
+
 config AT91RM9200_WATCHDOG
 	tristate "AT91RM9200 watchdog"
 	depends on SOC_AT91RM9200 && MFD_SYSCON
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 5c19294..c24a8fc 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -30,6 +30,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
 
 # ARM Architecture
 obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
+obj-$(CONFIG_ATMEL_WATCHDOG) += atmel_wdt.o
 obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
 obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
 obj-$(CONFIG_CADENCE_WATCHDOG) += cadence_wdt.o
diff --git a/drivers/watchdog/at91sam9_wdt.h b/drivers/watchdog/at91sam9_wdt.h
index c6fbb2e6..79add4f 100644
--- a/drivers/watchdog/at91sam9_wdt.h
+++ b/drivers/watchdog/at91sam9_wdt.h
@@ -22,11 +22,15 @@
 
 #define AT91_WDT_MR		0x04			/* Watchdog Mode Register */
 #define		AT91_WDT_WDV		(0xfff << 0)		/* Counter Value */
+#define			AT91_WDT_WDV_MSK	(0xfff)
+#define			AT91_WDT_WDV_(x)	(((x) & AT91_WDT_WDV_MSK) << 0)
 #define		AT91_WDT_WDFIEN		(1     << 12)		/* Fault Interrupt Enable */
 #define		AT91_WDT_WDRSTEN	(1     << 13)		/* Reset Processor */
 #define		AT91_WDT_WDRPROC	(1     << 14)		/* Timer Restart */
 #define		AT91_WDT_WDDIS		(1     << 15)		/* Watchdog Disable */
 #define		AT91_WDT_WDD		(0xfff << 16)		/* Delta Value */
+#define			AT91_WDT_WDD_MSK	(0xfff)
+#define			AT91_WDT_WDD_(x)	(((x) & AT91_WDT_WDD_MSK) << 16)
 #define		AT91_WDT_WDDBGHLT	(1     << 28)		/* Debug Halt */
 #define		AT91_WDT_WDIDLEHLT	(1     << 29)		/* Idle Halt */
 
diff --git a/drivers/watchdog/atmel_wdt.c b/drivers/watchdog/atmel_wdt.c
new file mode 100644
index 0000000..e1cdc84
--- /dev/null
+++ b/drivers/watchdog/atmel_wdt.c
@@ -0,0 +1,290 @@
+/*
+ * Driver for Atmel SAMA5D4 Watchdog Timer
+ *
+ * Copyright (C) 2015 Atmel Corporation
+ *
+ * Licensed under GPLv2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+
+#include "at91sam9_wdt.h"
+
+/* minimum and maximum watchdog timeout, in seconds */
+#define MIN_WDT_TIMEOUT		1
+#define MAX_WDT_TIMEOUT		16
+#define WDT_DEFAULT_TIMEOUT	MAX_WDT_TIMEOUT
+
+#define WDT_MAX_WDV		0xFFF
+
+#define WDT_SEC2TICKS(s)	((s) ? (((s) << 8) - 1) : 0)
+
+struct atmel_wdt {
+	struct watchdog_device	wdd;
+	void __iomem		*reg_base;
+	u32	config;
+};
+
+static int wdt_timeout = WDT_DEFAULT_TIMEOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
+
+module_param(wdt_timeout, int, 0);
+MODULE_PARM_DESC(wdt_timeout,
+	"Watchdog wdt_timeout in seconds. (default = "
+	__MODULE_STRING(WDT_DEFAULT_TIMEOUT) ")");
+
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+	"Watchdog cannot be stopped once started (default="
+	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+#define wdt_read(wdt, field) \
+	readl_relaxed((wdt)->reg_base + (field))
+
+#define wdt_write(wtd, field, val) \
+	writel_relaxed((val), (wdt)->reg_base + (field))
+
+static int atmel_wdt_start(struct watchdog_device *wdd)
+{
+	struct atmel_wdt *wdt = watchdog_get_drvdata(wdd);
+	u32 reg;
+
+	reg = wdt_read(wdt, AT91_WDT_MR);
+	reg &= ~AT91_WDT_WDDIS;
+	wdt_write(wdt, AT91_WDT_MR, reg);
+
+	return 0;
+}
+
+static int atmel_wdt_stop(struct watchdog_device *wdd)
+{
+	struct atmel_wdt *wdt = watchdog_get_drvdata(wdd);
+	u32 reg;
+
+	reg = wdt_read(wdt, AT91_WDT_MR);
+	reg |= AT91_WDT_WDDIS;
+	wdt_write(wdt, AT91_WDT_MR, reg);
+
+	return 0;
+}
+
+static int atmel_wdt_ping(struct watchdog_device *wdd)
+{
+	struct atmel_wdt *wdt = watchdog_get_drvdata(wdd);
+
+	wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT);
+
+	return 0;
+}
+
+static int atmel_wdt_set_timeout(struct watchdog_device *wdd,
+				 unsigned int timeout)
+{
+	struct atmel_wdt *wdt = watchdog_get_drvdata(wdd);
+	u32 reg, value;
+
+	value = WDT_SEC2TICKS(timeout);
+	if (value > WDT_MAX_WDV)
+		return -EINVAL;
+
+	reg = wdt_read(wdt, AT91_WDT_MR);
+	reg &= ~AT91_WDT_WDV;
+	reg &= ~AT91_WDT_WDD;
+	reg |= AT91_WDT_WDV_(value);
+	reg |= AT91_WDT_WDD_(value);
+	wdt_write(wdt, AT91_WDT_MR, reg);
+
+	wdd->timeout = timeout;
+
+	return 0;
+}
+
+static const struct watchdog_info atmel_wdt_info = {
+	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+	.firmware_version = 0,
+	.identity = "Atmel SAMA5D4 Watchdog",
+};
+
+static struct watchdog_ops atmel_wdt_ops = {
+	.owner = THIS_MODULE,
+	.start = atmel_wdt_start,
+	.stop = atmel_wdt_stop,
+	.ping = atmel_wdt_ping,
+	.set_timeout = atmel_wdt_set_timeout,
+};
+
+static irqreturn_t atmel_wdt_irq_handler(int irq, void *dev_id)
+{
+	struct atmel_wdt *wdt = platform_get_drvdata(dev_id);
+
+	if (wdt_read(wdt, AT91_WDT_SR)) {
+		pr_crit("Atmel Watchdog Software Reset\n");
+		emergency_restart();
+		pr_crit("Reboot didn't ?????\n");
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int of_atmel_wdt_init(struct device_node *np, struct atmel_wdt *wdt)
+{
+	const char *tmp;
+
+	wdt->config = AT91_WDT_WDDIS;
+
+	if (!of_property_read_string(np, "atmel,watchdog-type", &tmp) &&
+	    !strcmp(tmp, "software"))
+		wdt->config |= AT91_WDT_WDFIEN;
+	else
+		wdt->config |= AT91_WDT_WDRSTEN;
+
+	if (of_property_read_bool(np, "atmel,idle-halt"))
+		wdt->config |= AT91_WDT_WDIDLEHLT;
+
+	if (of_property_read_bool(np, "atmel,dbg-halt"))
+		wdt->config |= AT91_WDT_WDDBGHLT;
+
+	return 0;
+}
+
+static int atmel_wdt_init(struct atmel_wdt *wdt)
+{
+	struct watchdog_device *wdd = &wdt->wdd;
+	u32 value, timeout;
+
+	timeout = WDT_SEC2TICKS(wdd->timeout);
+	if (timeout > WDT_MAX_WDV)
+		return -1;
+
+	/*
+	 * Because the fields WDV and WDD must not be modified when the WDDIS
+	 * bit is set, so clear the WDDIS bit before writing the WDT_MR.
+	 */
+	value = wdt_read(wdt, AT91_WDT_MR);
+	value &= ~AT91_WDT_WDDIS;
+	wdt_write(wdt, AT91_WDT_MR, value);
+
+	value = wdt->config;
+	value |= AT91_WDT_WDD_(timeout);
+	value |= AT91_WDT_WDV_(timeout);
+
+	wdt_write(wdt, AT91_WDT_MR, value);
+
+	return 0;
+}
+
+static int atmel_wdt_probe(struct platform_device *pdev)
+{
+	struct watchdog_device *wdd;
+	struct atmel_wdt *wdt;
+	struct resource *res;
+	void __iomem *regs;
+	int ret, irq = -1;
+
+	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+	if (!wdt)
+		return -ENOMEM;
+
+	wdd = &wdt->wdd;
+	wdd->timeout = wdt_timeout;
+	wdd->info = &atmel_wdt_info;
+	wdd->ops = &atmel_wdt_ops;
+	wdd->min_timeout = MIN_WDT_TIMEOUT;
+	wdd->max_timeout = MAX_WDT_TIMEOUT;
+
+	watchdog_set_drvdata(wdd, wdt);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(regs))
+		return PTR_ERR(regs);
+
+	wdt->reg_base = regs;
+
+	if (pdev->dev.of_node) {
+		irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
+		if (!irq)
+			dev_warn(&pdev->dev, "the IRQ NOT specify from DT\n");
+
+		ret = of_atmel_wdt_init(pdev->dev.of_node, wdt);
+		if (ret)
+			return ret;
+	}
+
+	if ((wdt->config & AT91_WDT_WDFIEN) && (irq >= 0)) {
+		ret = devm_request_irq(&pdev->dev, irq, atmel_wdt_irq_handler,
+				       0, pdev->name, pdev);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"cannot register interrupt handler\n");
+			return ret;
+		}
+	}
+
+	ret = watchdog_init_timeout(wdd, wdt_timeout, &pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to set timeout value\n");
+		return ret;
+	}
+
+	ret = atmel_wdt_init(wdt);
+	if (ret)
+		return ret;
+
+	watchdog_set_nowayout(wdd, nowayout);
+
+	ret = watchdog_register_device(wdd);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to register watchdog device\n");
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, wdt);
+
+	dev_info(&pdev->dev, "initialized (timeout = %d sec, nowayout = %d)\n",
+		 wdt_timeout, nowayout);
+
+	return 0;
+}
+
+static int atmel_wdt_remove(struct platform_device *pdev)
+{
+	struct atmel_wdt *wdt = platform_get_drvdata(pdev);
+
+	atmel_wdt_stop(&wdt->wdd);
+
+	watchdog_unregister_device(&wdt->wdd);
+
+	dev_info(&pdev->dev, "removed wdt\n");
+
+	return 0;
+}
+
+static const struct of_device_id atmel_wdt_of_match[] = {
+	{ .compatible = "atmel,sama5d4-wdt", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, atmel_wdt_of_match);
+
+static struct platform_driver atmel_wdt_driver = {
+	.probe		= atmel_wdt_probe,
+	.remove		= atmel_wdt_remove,
+	.driver		= {
+		.name	= "atmel-wdt",
+		.of_match_table = atmel_wdt_of_match,
+	},
+};
+module_platform_driver(atmel_wdt_driver);
+
+MODULE_ALIAS("platform:atmel-wdt");
+MODULE_AUTHOR("Atmel Corporation");
+MODULE_DESCRIPTION("Atmel SAMA5D4 Watchdog Timer driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1200430 — Re: [PATCH v2 1/2] drivers: watchdog: add a driver to support SAMA5D4 watchdog timer

FromGuenter Roeck <linux@roeck-us.net>
Date2015-08-05 08:20 +0200
SubjectRe: [PATCH v2 1/2] drivers: watchdog: add a driver to support SAMA5D4 watchdog timer
Message-ID<pU0dr-1iR-3@gated-at.bofh.it>
In reply to#1200370
On 08/04/2015 07:35 PM, Wenyou Yang wrote:
>>From SAMA5D4, the watchdog timer is upgrated with a new feature,
> which is describled as in the datasheet, "WDT_MR can be written
> until a LOCKMR command is issued in WDT_CR".
> That is to say, as long as the bootstrap and u-boot don't issue
> a LOCKMR command, WDT_MR can be written more than once in the driver.
>
> So the SAMA5D4 watchdog driver's implementation is different from
> the previous: the user application open the device file to enable

Which previous ? Please let the reader know which one you refer to.

> the watchdog timer hardware, and close to disable it, and set the
> watchdog timer timeout by seting WDV and WDD fields of WDT_MR register,
> and ping the watchdog by issuing WDRSTT command to WDT_CR register
> with hard-coded key.
>
> Signed-off-by: Wenyou Yang <wenyou.yang@atmel.com>
> ---
>   drivers/watchdog/Kconfig        |    9 ++
>   drivers/watchdog/Makefile       |    1 +
>   drivers/watchdog/at91sam9_wdt.h |    4 +
>   drivers/watchdog/atmel_wdt.c    |  290 +++++++++++++++++++++++++++++++++++++++
>   4 files changed, 304 insertions(+)
>   create mode 100644 drivers/watchdog/atmel_wdt.c
>
> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> index e5e7c55..4425813 100644
> --- a/drivers/watchdog/Kconfig
> +++ b/drivers/watchdog/Kconfig
> @@ -152,6 +152,15 @@ config ARM_SP805_WATCHDOG
>   	  ARM Primecell SP805 Watchdog timer. This will reboot your system when
>   	  the timeout is reached.
>
> +config ATMEL_WATCHDOG
> +	tristate "Atmel SAMA5D4 Watchdog Timer"
> +	depends on ARCH_AT91
> +	select WATCHDOG_CORE
> +	help
> +	  Atmel watchdog timer embedded into SAMA5D4 chips. Its Watchdog Timer
> +	  Mode Register(WDT_MR) can be written more than once.
> +	  This will reboot your system when the timeout is reached.
> +

ATMEL is highly generic. Can you find a more specific name ?
If this is part of the AT91 family, it could be something
like AT91SAMAD54, for example.

Same goes for the driver name.

>   config AT91RM9200_WATCHDOG
>   	tristate "AT91RM9200 watchdog"
>   	depends on SOC_AT91RM9200 && MFD_SYSCON
> diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> index 5c19294..c24a8fc 100644
> --- a/drivers/watchdog/Makefile
> +++ b/drivers/watchdog/Makefile
> @@ -30,6 +30,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
>
>   # ARM Architecture
>   obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
> +obj-$(CONFIG_ATMEL_WATCHDOG) += atmel_wdt.o
>   obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
>   obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
>   obj-$(CONFIG_CADENCE_WATCHDOG) += cadence_wdt.o
> diff --git a/drivers/watchdog/at91sam9_wdt.h b/drivers/watchdog/at91sam9_wdt.h
> index c6fbb2e6..79add4f 100644
> --- a/drivers/watchdog/at91sam9_wdt.h
> +++ b/drivers/watchdog/at91sam9_wdt.h
> @@ -22,11 +22,15 @@
>
>   #define AT91_WDT_MR		0x04			/* Watchdog Mode Register */
>   #define		AT91_WDT_WDV		(0xfff << 0)		/* Counter Value */
> +#define			AT91_WDT_WDV_MSK	(0xfff)

The ( ) is not necessary. AT91_WDT_WDV is already used as mask.
You should not need a second one.

> +#define			AT91_WDT_WDV_(x)	(((x) & AT91_WDT_WDV_MSK) << 0)

Please no '_' at the end of the macro name; find another name that isn't
as close to AT91_WDT_WDV.

>   #define		AT91_WDT_WDFIEN		(1     << 12)		/* Fault Interrupt Enable */
>   #define		AT91_WDT_WDRSTEN	(1     << 13)		/* Reset Processor */
>   #define		AT91_WDT_WDRPROC	(1     << 14)		/* Timer Restart */
>   #define		AT91_WDT_WDDIS		(1     << 15)		/* Watchdog Disable */
>   #define		AT91_WDT_WDD		(0xfff << 16)		/* Delta Value */
> +#define			AT91_WDT_WDD_MSK	(0xfff)

( ) is unnecessary. Also, AT91_WDT_WDD is already used as mask.
No need to specify a second one.

> +#define			AT91_WDT_WDD_(x)	(((x) & AT91_WDT_WDD_MSK) << 16)

Again, please no '_' at the end of the macro name.

>   #define		AT91_WDT_WDDBGHLT	(1     << 28)		/* Debug Halt */
>   #define		AT91_WDT_WDIDLEHLT	(1     << 29)		/* Idle Halt */
>
> diff --git a/drivers/watchdog/atmel_wdt.c b/drivers/watchdog/atmel_wdt.c
> new file mode 100644
> index 0000000..e1cdc84
> --- /dev/null
> +++ b/drivers/watchdog/atmel_wdt.c
> @@ -0,0 +1,290 @@
> +/*
> + * Driver for Atmel SAMA5D4 Watchdog Timer
> + *
> + * Copyright (C) 2015 Atmel Corporation
> + *
> + * Licensed under GPLv2.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_irq.h>
> +#include <linux/platform_device.h>
> +#include <linux/watchdog.h>
> +#include <linux/reboot.h>

Please use alphabetic order for include files. That makes
it easier to find files, and simplifies later additions.

> +
> +#include "at91sam9_wdt.h"
> +
> +/* minimum and maximum watchdog timeout, in seconds */
> +#define MIN_WDT_TIMEOUT		1
> +#define MAX_WDT_TIMEOUT		16
> +#define WDT_DEFAULT_TIMEOUT	MAX_WDT_TIMEOUT
> +
> +#define WDT_MAX_WDV		0xFFF
> +
> +#define WDT_SEC2TICKS(s)	((s) ? (((s) << 8) - 1) : 0)
> +
> +struct atmel_wdt {
> +	struct watchdog_device	wdd;
> +	void __iomem		*reg_base;
> +	u32	config;
> +};
> +
> +static int wdt_timeout = WDT_DEFAULT_TIMEOUT;
> +static bool nowayout = WATCHDOG_NOWAYOUT;
> +
> +module_param(wdt_timeout, int, 0);
> +MODULE_PARM_DESC(wdt_timeout,
> +	"Watchdog wdt_timeout in seconds. (default = "
> +	__MODULE_STRING(WDT_DEFAULT_TIMEOUT) ")");
> +
> +module_param(nowayout, bool, 0);
> +MODULE_PARM_DESC(nowayout,
> +	"Watchdog cannot be stopped once started (default="
> +	__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
> +
> +#define wdt_read(wdt, field) \
> +	readl_relaxed((wdt)->reg_base + (field))
> +
> +#define wdt_write(wtd, field, val) \
> +	writel_relaxed((val), (wdt)->reg_base + (field))
> +
> +static int atmel_wdt_start(struct watchdog_device *wdd)
> +{
> +	struct atmel_wdt *wdt = watchdog_get_drvdata(wdd);
> +	u32 reg;
> +
> +	reg = wdt_read(wdt, AT91_WDT_MR);
> +	reg &= ~AT91_WDT_WDDIS;
> +	wdt_write(wdt, AT91_WDT_MR, reg);
> +
> +	return 0;
> +}
> +
> +static int atmel_wdt_stop(struct watchdog_device *wdd)
> +{
> +	struct atmel_wdt *wdt = watchdog_get_drvdata(wdd);
> +	u32 reg;
> +
> +	reg = wdt_read(wdt, AT91_WDT_MR);
> +	reg |= AT91_WDT_WDDIS;
> +	wdt_write(wdt, AT91_WDT_MR, reg);
> +
> +	return 0;
> +}
> +
> +static int atmel_wdt_ping(struct watchdog_device *wdd)
> +{
> +	struct atmel_wdt *wdt = watchdog_get_drvdata(wdd);
> +
> +	wdt_write(wdt, AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT);
> +
> +	return 0;
> +}
> +
> +static int atmel_wdt_set_timeout(struct watchdog_device *wdd,
> +				 unsigned int timeout)
> +{
> +	struct atmel_wdt *wdt = watchdog_get_drvdata(wdd);
> +	u32 reg, value;
> +
> +	value = WDT_SEC2TICKS(timeout);
> +	if (value > WDT_MAX_WDV)
> +		return -EINVAL;
> +
Unnecessary check.

> +	reg = wdt_read(wdt, AT91_WDT_MR);
> +	reg &= ~AT91_WDT_WDV;
> +	reg &= ~AT91_WDT_WDD;
> +	reg |= AT91_WDT_WDV_(value);
> +	reg |= AT91_WDT_WDD_(value);
> +	wdt_write(wdt, AT91_WDT_MR, reg);
> +
> +	wdd->timeout = timeout;
> +
> +	return 0;
> +}
> +
> +static const struct watchdog_info atmel_wdt_info = {
> +	.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
> +	.firmware_version = 0,
> +	.identity = "Atmel SAMA5D4 Watchdog",
> +};
> +
> +static struct watchdog_ops atmel_wdt_ops = {
> +	.owner = THIS_MODULE,
> +	.start = atmel_wdt_start,
> +	.stop = atmel_wdt_stop,
> +	.ping = atmel_wdt_ping,
> +	.set_timeout = atmel_wdt_set_timeout,
> +};
> +
> +static irqreturn_t atmel_wdt_irq_handler(int irq, void *dev_id)
> +{
> +	struct atmel_wdt *wdt = platform_get_drvdata(dev_id);
> +
> +	if (wdt_read(wdt, AT91_WDT_SR)) {
> +		pr_crit("Atmel Watchdog Software Reset\n");
> +		emergency_restart();
> +		pr_crit("Reboot didn't ?????\n");
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static int of_atmel_wdt_init(struct device_node *np, struct atmel_wdt *wdt)
> +{
> +	const char *tmp;
> +
> +	wdt->config = AT91_WDT_WDDIS;
> +
> +	if (!of_property_read_string(np, "atmel,watchdog-type", &tmp) &&
> +	    !strcmp(tmp, "software"))
> +		wdt->config |= AT91_WDT_WDFIEN;
> +	else
> +		wdt->config |= AT91_WDT_WDRSTEN;
> +
> +	if (of_property_read_bool(np, "atmel,idle-halt"))
> +		wdt->config |= AT91_WDT_WDIDLEHLT;
> +
> +	if (of_property_read_bool(np, "atmel,dbg-halt"))
> +		wdt->config |= AT91_WDT_WDDBGHLT;
> +
> +	return 0;
> +}
> +
> +static int atmel_wdt_init(struct atmel_wdt *wdt)
> +{
> +	struct watchdog_device *wdd = &wdt->wdd;
> +	u32 value, timeout;
> +
> +	timeout = WDT_SEC2TICKS(wdd->timeout);
> +	if (timeout > WDT_MAX_WDV)
> +		return -1;
> +

Unnecessary range check.

> +	/*
> +	 * Because the fields WDV and WDD must not be modified when the WDDIS
> +	 * bit is set, so clear the WDDIS bit before writing the WDT_MR.
> +	 */
> +	value = wdt_read(wdt, AT91_WDT_MR);
> +	value &= ~AT91_WDT_WDDIS;
> +	wdt_write(wdt, AT91_WDT_MR, value);
> +
> +	value = wdt->config;
> +	value |= AT91_WDT_WDD_(timeout);
> +	value |= AT91_WDT_WDV_(timeout);
> +
> +	wdt_write(wdt, AT91_WDT_MR, value);
> +
> +	return 0;
> +}
> +
> +static int atmel_wdt_probe(struct platform_device *pdev)
> +{
> +	struct watchdog_device *wdd;
> +	struct atmel_wdt *wdt;
> +	struct resource *res;
> +	void __iomem *regs;
> +	int ret, irq = -1;
> +
> +	wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
> +	if (!wdt)
> +		return -ENOMEM;
> +
> +	wdd = &wdt->wdd;
> +	wdd->timeout = wdt_timeout;
> +	wdd->info = &atmel_wdt_info;
> +	wdd->ops = &atmel_wdt_ops;
> +	wdd->min_timeout = MIN_WDT_TIMEOUT;
> +	wdd->max_timeout = MAX_WDT_TIMEOUT;
> +
> +	watchdog_set_drvdata(wdd, wdt);
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(regs))
> +		return PTR_ERR(regs);
> +
> +	wdt->reg_base = regs;
> +
> +	if (pdev->dev.of_node) {
> +		irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
> +		if (!irq)
> +			dev_warn(&pdev->dev, "the IRQ NOT specify from DT\n");

"failed to get IRQ from DT" would be a better message.
This leaves irq set to 0 in the error case, and cause the code below
to request an interrupt.

> +
> +		ret = of_atmel_wdt_init(pdev->dev.of_node, wdt);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	if ((wdt->config & AT91_WDT_WDFIEN) && (irq >= 0)) {

Second ( ) is unnecessary.

> +		ret = devm_request_irq(&pdev->dev, irq, atmel_wdt_irq_handler,
> +				       0, pdev->name, pdev);
> +		if (ret) {
> +			dev_err(&pdev->dev,
> +				"cannot register interrupt handler\n");
> +			return ret;
> +		}
> +	}
> +
> +	ret = watchdog_init_timeout(wdd, wdt_timeout, &pdev->dev);
> +	if (ret) {
> +		dev_err(&pdev->dev, "unable to set timeout value\n");
> +		return ret;

I would suggest to set the default timeout in this case, as done by other drivers.

> +	}
> +
> +	ret = atmel_wdt_init(wdt);
> +	if (ret)
> +		return ret;
> +
> +	watchdog_set_nowayout(wdd, nowayout);
> +
> +	ret = watchdog_register_device(wdd);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to register watchdog device\n");
> +		return ret;
> +	}
> +
> +	platform_set_drvdata(pdev, wdt);
> +
> +	dev_info(&pdev->dev, "initialized (timeout = %d sec, nowayout = %d)\n",
> +		 wdt_timeout, nowayout);
> +
> +	return 0;
> +}
> +
> +static int atmel_wdt_remove(struct platform_device *pdev)
> +{
> +	struct atmel_wdt *wdt = platform_get_drvdata(pdev);
> +
> +	atmel_wdt_stop(&wdt->wdd);
> +
> +	watchdog_unregister_device(&wdt->wdd);
> +
> +	dev_info(&pdev->dev, "removed wdt\n");
> +
Unnecessary message.

> +	return 0;
> +}
> +
> +static const struct of_device_id atmel_wdt_of_match[] = {
> +	{ .compatible = "atmel,sama5d4-wdt", },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(of, atmel_wdt_of_match);
> +
> +static struct platform_driver atmel_wdt_driver = {
> +	.probe		= atmel_wdt_probe,
> +	.remove		= atmel_wdt_remove,
> +	.driver		= {
> +		.name	= "atmel-wdt",
> +		.of_match_table = atmel_wdt_of_match,
> +	},
> +};
> +module_platform_driver(atmel_wdt_driver);
> +
> +MODULE_ALIAS("platform:atmel-wdt");
> +MODULE_AUTHOR("Atmel Corporation");
> +MODULE_DESCRIPTION("Atmel SAMA5D4 Watchdog Timer driver");
> +MODULE_LICENSE("GPL v2");
>

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [next] | [standalone]


#1200540 — RE: [PATCH v2 1/2] drivers: watchdog: add a driver to support SAMA5D4 watchdog timer

From"Yang, Wenyou" <Wenyou.Yang@atmel.com>
Date2015-08-05 10:50 +0200
SubjectRE: [PATCH v2 1/2] drivers: watchdog: add a driver to support SAMA5D4 watchdog timer
Message-ID<pU2yC-4zf-17@gated-at.bofh.it>
In reply to#1200430
SGkgR3VlbnRlciwNCg0KVGhhbmsgeW91IHZlcnkgbXVjaCBmb3IgeW91ciByZXZpZXcuDQoNCkkg
d2lsbCBzZW5kIGEgbmV3IHZlcnNpb24gdG8gcmVzb2x2ZSB0aGVtLg0KDQo+IC0tLS0tT3JpZ2lu
YWwgTWVzc2FnZS0tLS0tDQo+IEZyb206IEd1ZW50ZXIgUm9lY2sgW21haWx0bzpsaW51eEByb2Vj
ay11cy5uZXRdDQo+IFNlbnQ6IDIwMTXE6jjUwjXI1SAxNDoxNA0KPiBUbzogWWFuZywgV2VueW91
OyB3aW1AaWd1YW5hLmJlOyByb2JoK2R0QGtlcm5lbC5vcmc7IHBhd2VsLm1vbGxAYXJtLmNvbTsN
Cj4gbWFyay5ydXRsYW5kQGFybS5jb207IGlqYytkZXZpY2V0cmVlQGhlbGxpb24ub3JnLnVrOyBn
YWxha0Bjb2RlYXVyb3JhLm9yZw0KPiBDYzogc3lsdmFpbi5yb2NoZXRAZmluc2VjdXIuY29tOyBG
ZXJyZSwgTmljb2xhczsgYm9yaXMuYnJlemlsbG9uQGZyZWUtDQo+IGVsZWN0cm9ucy5jb207IGRl
dmljZXRyZWVAdmdlci5rZXJuZWwub3JnOyBsaW51eC1rZXJuZWxAdmdlci5rZXJuZWwub3JnOyBs
aW51eC0NCj4gd2F0Y2hkb2dAdmdlci5rZXJuZWwub3JnOyBsaW51eC1hcm0ta2VybmVsQGxpc3Rz
LmluZnJhZGVhZC5vcmcNCj4gU3ViamVjdDogUmU6IFtQQVRDSCB2MiAxLzJdIGRyaXZlcnM6IHdh
dGNoZG9nOiBhZGQgYSBkcml2ZXIgdG8gc3VwcG9ydCBTQU1BNUQ0DQo+IHdhdGNoZG9nIHRpbWVy
DQo+IA0KPiBPbiAwOC8wNC8yMDE1IDA3OjM1IFBNLCBXZW55b3UgWWFuZyB3cm90ZToNCj4gPj5G
cm9tIFNBTUE1RDQsIHRoZSB3YXRjaGRvZyB0aW1lciBpcyB1cGdyYXRlZCB3aXRoIGEgbmV3IGZl
YXR1cmUsDQo+ID4gd2hpY2ggaXMgZGVzY3JpYmxlZCBhcyBpbiB0aGUgZGF0YXNoZWV0LCAiV0RU
X01SIGNhbiBiZSB3cml0dGVuIHVudGlsDQo+ID4gYSBMT0NLTVIgY29tbWFuZCBpcyBpc3N1ZWQg
aW4gV0RUX0NSIi4NCj4gPiBUaGF0IGlzIHRvIHNheSwgYXMgbG9uZyBhcyB0aGUgYm9vdHN0cmFw
IGFuZCB1LWJvb3QgZG9uJ3QgaXNzdWUgYQ0KPiA+IExPQ0tNUiBjb21tYW5kLCBXRFRfTVIgY2Fu
IGJlIHdyaXR0ZW4gbW9yZSB0aGFuIG9uY2UgaW4gdGhlIGRyaXZlci4NCj4gPg0KPiA+IFNvIHRo
ZSBTQU1BNUQ0IHdhdGNoZG9nIGRyaXZlcidzIGltcGxlbWVudGF0aW9uIGlzIGRpZmZlcmVudCBm
cm9tIHRoZQ0KPiA+IHByZXZpb3VzOiB0aGUgdXNlciBhcHBsaWNhdGlvbiBvcGVuIHRoZSBkZXZp
Y2UgZmlsZSB0byBlbmFibGUNCj4gDQo+IFdoaWNoIHByZXZpb3VzID8gUGxlYXNlIGxldCB0aGUg
cmVhZGVyIGtub3cgd2hpY2ggb25lIHlvdSByZWZlciB0by4NCj4gDQo+ID4gdGhlIHdhdGNoZG9n
IHRpbWVyIGhhcmR3YXJlLCBhbmQgY2xvc2UgdG8gZGlzYWJsZSBpdCwgYW5kIHNldCB0aGUNCj4g
PiB3YXRjaGRvZyB0aW1lciB0aW1lb3V0IGJ5IHNldGluZyBXRFYgYW5kIFdERCBmaWVsZHMgb2Yg
V0RUX01SDQo+ID4gcmVnaXN0ZXIsIGFuZCBwaW5nIHRoZSB3YXRjaGRvZyBieSBpc3N1aW5nIFdE
UlNUVCBjb21tYW5kIHRvIFdEVF9DUg0KPiA+IHJlZ2lzdGVyIHdpdGggaGFyZC1jb2RlZCBrZXku
DQo+ID4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBXZW55b3UgWWFuZyA8d2VueW91LnlhbmdAYXRtZWwu
Y29tPg0KPiA+IC0tLQ0KPiA+ICAgZHJpdmVycy93YXRjaGRvZy9LY29uZmlnICAgICAgICB8ICAg
IDkgKysNCj4gPiAgIGRyaXZlcnMvd2F0Y2hkb2cvTWFrZWZpbGUgICAgICAgfCAgICAxICsNCj4g
PiAgIGRyaXZlcnMvd2F0Y2hkb2cvYXQ5MXNhbTlfd2R0LmggfCAgICA0ICsNCj4gPiAgIGRyaXZl
cnMvd2F0Y2hkb2cvYXRtZWxfd2R0LmMgICAgfCAgMjkwDQo+ICsrKysrKysrKysrKysrKysrKysr
KysrKysrKysrKysrKysrKysrKw0KPiA+ICAgNCBmaWxlcyBjaGFuZ2VkLCAzMDQgaW5zZXJ0aW9u
cygrKQ0KPiA+ICAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvd2F0Y2hkb2cvYXRtZWxfd2R0
LmMNCj4gPg0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL3dhdGNoZG9nL0tjb25maWcgYi9kcml2
ZXJzL3dhdGNoZG9nL0tjb25maWcgaW5kZXgNCj4gPiBlNWU3YzU1Li40NDI1ODEzIDEwMDY0NA0K
PiA+IC0tLSBhL2RyaXZlcnMvd2F0Y2hkb2cvS2NvbmZpZw0KPiA+ICsrKyBiL2RyaXZlcnMvd2F0
Y2hkb2cvS2NvbmZpZw0KPiA+IEBAIC0xNTIsNiArMTUyLDE1IEBAIGNvbmZpZyBBUk1fU1A4MDVf
V0FUQ0hET0cNCj4gPiAgIAkgIEFSTSBQcmltZWNlbGwgU1A4MDUgV2F0Y2hkb2cgdGltZXIuIFRo
aXMgd2lsbCByZWJvb3QgeW91ciBzeXN0ZW0NCj4gd2hlbg0KPiA+ICAgCSAgdGhlIHRpbWVvdXQg
aXMgcmVhY2hlZC4NCj4gPg0KPiA+ICtjb25maWcgQVRNRUxfV0FUQ0hET0cNCj4gPiArCXRyaXN0
YXRlICJBdG1lbCBTQU1BNUQ0IFdhdGNoZG9nIFRpbWVyIg0KPiA+ICsJZGVwZW5kcyBvbiBBUkNI
X0FUOTENCj4gPiArCXNlbGVjdCBXQVRDSERPR19DT1JFDQo+ID4gKwloZWxwDQo+ID4gKwkgIEF0
bWVsIHdhdGNoZG9nIHRpbWVyIGVtYmVkZGVkIGludG8gU0FNQTVENCBjaGlwcy4gSXRzIFdhdGNo
ZG9nDQo+IFRpbWVyDQo+ID4gKwkgIE1vZGUgUmVnaXN0ZXIoV0RUX01SKSBjYW4gYmUgd3JpdHRl
biBtb3JlIHRoYW4gb25jZS4NCj4gPiArCSAgVGhpcyB3aWxsIHJlYm9vdCB5b3VyIHN5c3RlbSB3
aGVuIHRoZSB0aW1lb3V0IGlzIHJlYWNoZWQuDQo+ID4gKw0KPiANCj4gQVRNRUwgaXMgaGlnaGx5
IGdlbmVyaWMuIENhbiB5b3UgZmluZCBhIG1vcmUgc3BlY2lmaWMgbmFtZSA/DQo+IElmIHRoaXMg
aXMgcGFydCBvZiB0aGUgQVQ5MSBmYW1pbHksIGl0IGNvdWxkIGJlIHNvbWV0aGluZyBsaWtlIEFU
OTFTQU1BRDU0LCBmb3INCj4gZXhhbXBsZS4NCj4gDQo+IFNhbWUgZ29lcyBmb3IgdGhlIGRyaXZl
ciBuYW1lLg0KPiANCj4gPiAgIGNvbmZpZyBBVDkxUk05MjAwX1dBVENIRE9HDQo+ID4gICAJdHJp
c3RhdGUgIkFUOTFSTTkyMDAgd2F0Y2hkb2ciDQo+ID4gICAJZGVwZW5kcyBvbiBTT0NfQVQ5MVJN
OTIwMCAmJiBNRkRfU1lTQ09OIGRpZmYgLS1naXQNCj4gPiBhL2RyaXZlcnMvd2F0Y2hkb2cvTWFr
ZWZpbGUgYi9kcml2ZXJzL3dhdGNoZG9nL01ha2VmaWxlIGluZGV4DQo+ID4gNWMxOTI5NC4uYzI0
YThmYyAxMDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL3dhdGNoZG9nL01ha2VmaWxlDQo+ID4gKysr
IGIvZHJpdmVycy93YXRjaGRvZy9NYWtlZmlsZQ0KPiA+IEBAIC0zMCw2ICszMCw3IEBAIG9iai0k
KENPTkZJR19VU0JQQ1dBVENIRE9HKSArPSBwY3dkX3VzYi5vDQo+ID4NCj4gPiAgICMgQVJNIEFy
Y2hpdGVjdHVyZQ0KPiA+ICAgb2JqLSQoQ09ORklHX0FSTV9TUDgwNV9XQVRDSERPRykgKz0gc3A4
MDVfd2R0Lm8NCj4gPiArb2JqLSQoQ09ORklHX0FUTUVMX1dBVENIRE9HKSArPSBhdG1lbF93ZHQu
bw0KPiA+ICAgb2JqLSQoQ09ORklHX0FUOTFSTTkyMDBfV0FUQ0hET0cpICs9IGF0OTFybTkyMDBf
d2R0Lm8NCj4gPiAgIG9iai0kKENPTkZJR19BVDkxU0FNOVhfV0FUQ0hET0cpICs9IGF0OTFzYW05
X3dkdC5vDQo+ID4gICBvYmotJChDT05GSUdfQ0FERU5DRV9XQVRDSERPRykgKz0gY2FkZW5jZV93
ZHQubyBkaWZmIC0tZ2l0DQo+ID4gYS9kcml2ZXJzL3dhdGNoZG9nL2F0OTFzYW05X3dkdC5oIGIv
ZHJpdmVycy93YXRjaGRvZy9hdDkxc2FtOV93ZHQuaA0KPiA+IGluZGV4IGM2ZmJiMmU2Li43OWFk
ZDRmIDEwMDY0NA0KPiA+IC0tLSBhL2RyaXZlcnMvd2F0Y2hkb2cvYXQ5MXNhbTlfd2R0LmgNCj4g
PiArKysgYi9kcml2ZXJzL3dhdGNoZG9nL2F0OTFzYW05X3dkdC5oDQo+ID4gQEAgLTIyLDExICsy
MiwxNSBAQA0KPiA+DQo+ID4gICAjZGVmaW5lIEFUOTFfV0RUX01SCQkweDA0CQkJLyogV2F0Y2hk
b2cNCj4gTW9kZSBSZWdpc3RlciAqLw0KPiA+ICAgI2RlZmluZQkJQVQ5MV9XRFRfV0RWCQkoMHhm
ZmYgPDwgMCkJCS8qDQo+IENvdW50ZXIgVmFsdWUgKi8NCj4gPiArI2RlZmluZQkJCUFUOTFfV0RU
X1dEVl9NU0sJKDB4ZmZmKQ0KPiANCj4gVGhlICggKSBpcyBub3QgbmVjZXNzYXJ5LiBBVDkxX1dE
VF9XRFYgaXMgYWxyZWFkeSB1c2VkIGFzIG1hc2suDQo+IFlvdSBzaG91bGQgbm90IG5lZWQgYSBz
ZWNvbmQgb25lLg0KPiANCj4gPiArI2RlZmluZQkJCUFUOTFfV0RUX1dEVl8oeCkJKCgoeCkgJg0K
PiBBVDkxX1dEVF9XRFZfTVNLKSA8PCAwKQ0KPiANCj4gUGxlYXNlIG5vICdfJyBhdCB0aGUgZW5k
IG9mIHRoZSBtYWNybyBuYW1lOyBmaW5kIGFub3RoZXIgbmFtZSB0aGF0IGlzbid0IGFzIGNsb3Nl
IHRvDQo+IEFUOTFfV0RUX1dEVi4NCj4gDQo+ID4gICAjZGVmaW5lCQlBVDkxX1dEVF9XREZJRU4J
CSgxICAgICA8PCAxMikJCS8qDQo+IEZhdWx0IEludGVycnVwdCBFbmFibGUgKi8NCj4gPiAgICNk
ZWZpbmUJCUFUOTFfV0RUX1dEUlNURU4JKDEgICAgIDw8IDEzKQkJLyoNCj4gUmVzZXQgUHJvY2Vz
c29yICovDQo+ID4gICAjZGVmaW5lCQlBVDkxX1dEVF9XRFJQUk9DCSgxICAgICA8PCAxNCkJCS8q
DQo+IFRpbWVyIFJlc3RhcnQgKi8NCj4gPiAgICNkZWZpbmUJCUFUOTFfV0RUX1dERElTCQkoMSAg
ICAgPDwgMTUpCQkvKg0KPiBXYXRjaGRvZyBEaXNhYmxlICovDQo+ID4gICAjZGVmaW5lCQlBVDkx
X1dEVF9XREQJCSgweGZmZiA8PCAxNikJCS8qDQo+IERlbHRhIFZhbHVlICovDQo+ID4gKyNkZWZp
bmUJCQlBVDkxX1dEVF9XRERfTVNLCSgweGZmZikNCj4gDQo+ICggKSBpcyB1bm5lY2Vzc2FyeS4g
QWxzbywgQVQ5MV9XRFRfV0REIGlzIGFscmVhZHkgdXNlZCBhcyBtYXNrLg0KPiBObyBuZWVkIHRv
IHNwZWNpZnkgYSBzZWNvbmQgb25lLg0KPiANCj4gPiArI2RlZmluZQkJCUFUOTFfV0RUX1dERF8o
eCkJKCgoeCkgJg0KPiBBVDkxX1dEVF9XRERfTVNLKSA8PCAxNikNCj4gDQo+IEFnYWluLCBwbGVh
c2Ugbm8gJ18nIGF0IHRoZSBlbmQgb2YgdGhlIG1hY3JvIG5hbWUuDQo+IA0KPiA+ICAgI2RlZmlu
ZQkJQVQ5MV9XRFRfV0REQkdITFQJKDEgICAgIDw8IDI4KQkJLyoNCj4gRGVidWcgSGFsdCAqLw0K
PiA+ICAgI2RlZmluZQkJQVQ5MV9XRFRfV0RJRExFSExUCSgxICAgICA8PCAyOSkJCS8qDQo+IElk
bGUgSGFsdCAqLw0KPiA+DQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvd2F0Y2hkb2cvYXRtZWxf
d2R0LmMNCj4gPiBiL2RyaXZlcnMvd2F0Y2hkb2cvYXRtZWxfd2R0LmMgbmV3IGZpbGUgbW9kZSAx
MDA2NDQgaW5kZXgNCj4gPiAwMDAwMDAwLi5lMWNkYzg0DQo+ID4gLS0tIC9kZXYvbnVsbA0KPiA+
ICsrKyBiL2RyaXZlcnMvd2F0Y2hkb2cvYXRtZWxfd2R0LmMNCj4gPiBAQCAtMCwwICsxLDI5MCBA
QA0KPiA+ICsvKg0KPiA+ICsgKiBEcml2ZXIgZm9yIEF0bWVsIFNBTUE1RDQgV2F0Y2hkb2cgVGlt
ZXINCj4gPiArICoNCj4gPiArICogQ29weXJpZ2h0IChDKSAyMDE1IEF0bWVsIENvcnBvcmF0aW9u
DQo+ID4gKyAqDQo+ID4gKyAqIExpY2Vuc2VkIHVuZGVyIEdQTHYyLg0KPiA+ICsgKi8NCj4gPiAr
DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L21v
ZHVsZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvaW50ZXJydXB0Lmg+DQo+ID4gKyNpbmNsdWRl
IDxsaW51eC9pby5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvb2YuaD4NCj4gPiArI2luY2x1ZGUg
PGxpbnV4L29mX2lycS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgvcGxhdGZvcm1fZGV2aWNlLmg+
DQo+ID4gKyNpbmNsdWRlIDxsaW51eC93YXRjaGRvZy5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgv
cmVib290Lmg+DQo+IA0KPiBQbGVhc2UgdXNlIGFscGhhYmV0aWMgb3JkZXIgZm9yIGluY2x1ZGUg
ZmlsZXMuIFRoYXQgbWFrZXMgaXQgZWFzaWVyIHRvIGZpbmQgZmlsZXMsIGFuZA0KPiBzaW1wbGlm
aWVzIGxhdGVyIGFkZGl0aW9ucy4NCj4gDQo+ID4gKw0KPiA+ICsjaW5jbHVkZSAiYXQ5MXNhbTlf
d2R0LmgiDQo+ID4gKw0KPiA+ICsvKiBtaW5pbXVtIGFuZCBtYXhpbXVtIHdhdGNoZG9nIHRpbWVv
dXQsIGluIHNlY29uZHMgKi8NCj4gPiArI2RlZmluZSBNSU5fV0RUX1RJTUVPVVQJCTENCj4gPiAr
I2RlZmluZSBNQVhfV0RUX1RJTUVPVVQJCTE2DQo+ID4gKyNkZWZpbmUgV0RUX0RFRkFVTFRfVElN
RU9VVAlNQVhfV0RUX1RJTUVPVVQNCj4gPiArDQo+ID4gKyNkZWZpbmUgV0RUX01BWF9XRFYJCTB4
RkZGDQo+ID4gKw0KPiA+ICsjZGVmaW5lIFdEVF9TRUMyVElDS1MocykJKChzKSA/ICgoKHMpIDw8
IDgpIC0gMSkgOiAwKQ0KPiA+ICsNCj4gPiArc3RydWN0IGF0bWVsX3dkdCB7DQo+ID4gKwlzdHJ1
Y3Qgd2F0Y2hkb2dfZGV2aWNlCXdkZDsNCj4gPiArCXZvaWQgX19pb21lbQkJKnJlZ19iYXNlOw0K
PiA+ICsJdTMyCWNvbmZpZzsNCj4gPiArfTsNCj4gPiArDQo+ID4gK3N0YXRpYyBpbnQgd2R0X3Rp
bWVvdXQgPSBXRFRfREVGQVVMVF9USU1FT1VUOyBzdGF0aWMgYm9vbCBub3dheW91dCA9DQo+ID4g
K1dBVENIRE9HX05PV0FZT1VUOw0KPiA+ICsNCj4gPiArbW9kdWxlX3BhcmFtKHdkdF90aW1lb3V0
LCBpbnQsIDApOw0KPiA+ICtNT0RVTEVfUEFSTV9ERVNDKHdkdF90aW1lb3V0LA0KPiA+ICsJIldh
dGNoZG9nIHdkdF90aW1lb3V0IGluIHNlY29uZHMuIChkZWZhdWx0ID0gIg0KPiA+ICsJX19NT0RV
TEVfU1RSSU5HKFdEVF9ERUZBVUxUX1RJTUVPVVQpICIpIik7DQo+ID4gKw0KPiA+ICttb2R1bGVf
cGFyYW0obm93YXlvdXQsIGJvb2wsIDApOw0KPiA+ICtNT0RVTEVfUEFSTV9ERVNDKG5vd2F5b3V0
LA0KPiA+ICsJIldhdGNoZG9nIGNhbm5vdCBiZSBzdG9wcGVkIG9uY2Ugc3RhcnRlZCAoZGVmYXVs
dD0iDQo+ID4gKwlfX01PRFVMRV9TVFJJTkcoV0FUQ0hET0dfTk9XQVlPVVQpICIpIik7DQo+ID4g
Kw0KPiA+ICsjZGVmaW5lIHdkdF9yZWFkKHdkdCwgZmllbGQpIFwNCj4gPiArCXJlYWRsX3JlbGF4
ZWQoKHdkdCktPnJlZ19iYXNlICsgKGZpZWxkKSkNCj4gPiArDQo+ID4gKyNkZWZpbmUgd2R0X3dy
aXRlKHd0ZCwgZmllbGQsIHZhbCkgXA0KPiA+ICsJd3JpdGVsX3JlbGF4ZWQoKHZhbCksICh3ZHQp
LT5yZWdfYmFzZSArIChmaWVsZCkpDQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGF0bWVsX3dkdF9z
dGFydChzdHJ1Y3Qgd2F0Y2hkb2dfZGV2aWNlICp3ZGQpIHsNCj4gPiArCXN0cnVjdCBhdG1lbF93
ZHQgKndkdCA9IHdhdGNoZG9nX2dldF9kcnZkYXRhKHdkZCk7DQo+ID4gKwl1MzIgcmVnOw0KPiA+
ICsNCj4gPiArCXJlZyA9IHdkdF9yZWFkKHdkdCwgQVQ5MV9XRFRfTVIpOw0KPiA+ICsJcmVnICY9
IH5BVDkxX1dEVF9XRERJUzsNCj4gPiArCXdkdF93cml0ZSh3ZHQsIEFUOTFfV0RUX01SLCByZWcp
Ow0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50
IGF0bWVsX3dkdF9zdG9wKHN0cnVjdCB3YXRjaGRvZ19kZXZpY2UgKndkZCkgew0KPiA+ICsJc3Ry
dWN0IGF0bWVsX3dkdCAqd2R0ID0gd2F0Y2hkb2dfZ2V0X2RydmRhdGEod2RkKTsNCj4gPiArCXUz
MiByZWc7DQo+ID4gKw0KPiA+ICsJcmVnID0gd2R0X3JlYWQod2R0LCBBVDkxX1dEVF9NUik7DQo+
ID4gKwlyZWcgfD0gQVQ5MV9XRFRfV0RESVM7DQo+ID4gKwl3ZHRfd3JpdGUod2R0LCBBVDkxX1dE
VF9NUiwgcmVnKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr
c3RhdGljIGludCBhdG1lbF93ZHRfcGluZyhzdHJ1Y3Qgd2F0Y2hkb2dfZGV2aWNlICp3ZGQpIHsN
Cj4gPiArCXN0cnVjdCBhdG1lbF93ZHQgKndkdCA9IHdhdGNoZG9nX2dldF9kcnZkYXRhKHdkZCk7
DQo+ID4gKw0KPiA+ICsJd2R0X3dyaXRlKHdkdCwgQVQ5MV9XRFRfQ1IsIEFUOTFfV0RUX0tFWSB8
DQo+IEFUOTFfV0RUX1dEUlNUVCk7DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4g
PiArDQo+ID4gK3N0YXRpYyBpbnQgYXRtZWxfd2R0X3NldF90aW1lb3V0KHN0cnVjdCB3YXRjaGRv
Z19kZXZpY2UgKndkZCwNCj4gPiArCQkJCSB1bnNpZ25lZCBpbnQgdGltZW91dCkNCj4gPiArew0K
PiA+ICsJc3RydWN0IGF0bWVsX3dkdCAqd2R0ID0gd2F0Y2hkb2dfZ2V0X2RydmRhdGEod2RkKTsN
Cj4gPiArCXUzMiByZWcsIHZhbHVlOw0KPiA+ICsNCj4gPiArCXZhbHVlID0gV0RUX1NFQzJUSUNL
Uyh0aW1lb3V0KTsNCj4gPiArCWlmICh2YWx1ZSA+IFdEVF9NQVhfV0RWKQ0KPiA+ICsJCXJldHVy
biAtRUlOVkFMOw0KPiA+ICsNCj4gVW5uZWNlc3NhcnkgY2hlY2suDQo+IA0KPiA+ICsJcmVnID0g
d2R0X3JlYWQod2R0LCBBVDkxX1dEVF9NUik7DQo+ID4gKwlyZWcgJj0gfkFUOTFfV0RUX1dEVjsN
Cj4gPiArCXJlZyAmPSB+QVQ5MV9XRFRfV0REOw0KPiA+ICsJcmVnIHw9IEFUOTFfV0RUX1dEVl8o
dmFsdWUpOw0KPiA+ICsJcmVnIHw9IEFUOTFfV0RUX1dERF8odmFsdWUpOw0KPiA+ICsJd2R0X3dy
aXRlKHdkdCwgQVQ5MV9XRFRfTVIsIHJlZyk7DQo+ID4gKw0KPiA+ICsJd2RkLT50aW1lb3V0ID0g
dGltZW91dDsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3Rh
dGljIGNvbnN0IHN0cnVjdCB3YXRjaGRvZ19pbmZvIGF0bWVsX3dkdF9pbmZvID0gew0KPiA+ICsJ
Lm9wdGlvbnMgPSBXRElPRl9TRVRUSU1FT1VUIHwgV0RJT0ZfTUFHSUNDTE9TRSB8DQo+IFdESU9G
X0tFRVBBTElWRVBJTkcsDQo+ID4gKwkuZmlybXdhcmVfdmVyc2lvbiA9IDAsDQo+ID4gKwkuaWRl
bnRpdHkgPSAiQXRtZWwgU0FNQTVENCBXYXRjaGRvZyIsIH07DQo+ID4gKw0KPiA+ICtzdGF0aWMg
c3RydWN0IHdhdGNoZG9nX29wcyBhdG1lbF93ZHRfb3BzID0gew0KPiA+ICsJLm93bmVyID0gVEhJ
U19NT0RVTEUsDQo+ID4gKwkuc3RhcnQgPSBhdG1lbF93ZHRfc3RhcnQsDQo+ID4gKwkuc3RvcCA9
IGF0bWVsX3dkdF9zdG9wLA0KPiA+ICsJLnBpbmcgPSBhdG1lbF93ZHRfcGluZywNCj4gPiArCS5z
ZXRfdGltZW91dCA9IGF0bWVsX3dkdF9zZXRfdGltZW91dCwgfTsNCj4gPiArDQo+ID4gK3N0YXRp
YyBpcnFyZXR1cm5fdCBhdG1lbF93ZHRfaXJxX2hhbmRsZXIoaW50IGlycSwgdm9pZCAqZGV2X2lk
KSB7DQo+ID4gKwlzdHJ1Y3QgYXRtZWxfd2R0ICp3ZHQgPSBwbGF0Zm9ybV9nZXRfZHJ2ZGF0YShk
ZXZfaWQpOw0KPiA+ICsNCj4gPiArCWlmICh3ZHRfcmVhZCh3ZHQsIEFUOTFfV0RUX1NSKSkgew0K
PiA+ICsJCXByX2NyaXQoIkF0bWVsIFdhdGNoZG9nIFNvZnR3YXJlIFJlc2V0XG4iKTsNCj4gPiAr
CQllbWVyZ2VuY3lfcmVzdGFydCgpOw0KPiA+ICsJCXByX2NyaXQoIlJlYm9vdCBkaWRuJ3QgPz8/
Pz9cbiIpOw0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCXJldHVybiBJUlFfSEFORExFRDsNCj4gPiAr
fQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBvZl9hdG1lbF93ZHRfaW5pdChzdHJ1Y3QgZGV2aWNl
X25vZGUgKm5wLCBzdHJ1Y3QgYXRtZWxfd2R0DQo+ID4gKyp3ZHQpIHsNCj4gPiArCWNvbnN0IGNo
YXIgKnRtcDsNCj4gPiArDQo+ID4gKwl3ZHQtPmNvbmZpZyA9IEFUOTFfV0RUX1dERElTOw0KPiA+
ICsNCj4gPiArCWlmICghb2ZfcHJvcGVydHlfcmVhZF9zdHJpbmcobnAsICJhdG1lbCx3YXRjaGRv
Zy10eXBlIiwgJnRtcCkgJiYNCj4gPiArCSAgICAhc3RyY21wKHRtcCwgInNvZnR3YXJlIikpDQo+
ID4gKwkJd2R0LT5jb25maWcgfD0gQVQ5MV9XRFRfV0RGSUVOOw0KPiA+ICsJZWxzZQ0KPiA+ICsJ
CXdkdC0+Y29uZmlnIHw9IEFUOTFfV0RUX1dEUlNURU47DQo+ID4gKw0KPiA+ICsJaWYgKG9mX3By
b3BlcnR5X3JlYWRfYm9vbChucCwgImF0bWVsLGlkbGUtaGFsdCIpKQ0KPiA+ICsJCXdkdC0+Y29u
ZmlnIHw9IEFUOTFfV0RUX1dESURMRUhMVDsNCj4gPiArDQo+ID4gKwlpZiAob2ZfcHJvcGVydHlf
cmVhZF9ib29sKG5wLCAiYXRtZWwsZGJnLWhhbHQiKSkNCj4gPiArCQl3ZHQtPmNvbmZpZyB8PSBB
VDkxX1dEVF9XRERCR0hMVDsNCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsN
Cj4gPiArc3RhdGljIGludCBhdG1lbF93ZHRfaW5pdChzdHJ1Y3QgYXRtZWxfd2R0ICp3ZHQpIHsN
Cj4gPiArCXN0cnVjdCB3YXRjaGRvZ19kZXZpY2UgKndkZCA9ICZ3ZHQtPndkZDsNCj4gPiArCXUz
MiB2YWx1ZSwgdGltZW91dDsNCj4gPiArDQo+ID4gKwl0aW1lb3V0ID0gV0RUX1NFQzJUSUNLUyh3
ZGQtPnRpbWVvdXQpOw0KPiA+ICsJaWYgKHRpbWVvdXQgPiBXRFRfTUFYX1dEVikNCj4gPiArCQly
ZXR1cm4gLTE7DQo+ID4gKw0KPiANCj4gVW5uZWNlc3NhcnkgcmFuZ2UgY2hlY2suDQo+IA0KPiA+
ICsJLyoNCj4gPiArCSAqIEJlY2F1c2UgdGhlIGZpZWxkcyBXRFYgYW5kIFdERCBtdXN0IG5vdCBi
ZSBtb2RpZmllZCB3aGVuIHRoZQ0KPiBXRERJUw0KPiA+ICsJICogYml0IGlzIHNldCwgc28gY2xl
YXIgdGhlIFdERElTIGJpdCBiZWZvcmUgd3JpdGluZyB0aGUgV0RUX01SLg0KPiA+ICsJICovDQo+
ID4gKwl2YWx1ZSA9IHdkdF9yZWFkKHdkdCwgQVQ5MV9XRFRfTVIpOw0KPiA+ICsJdmFsdWUgJj0g
fkFUOTFfV0RUX1dERElTOw0KPiA+ICsJd2R0X3dyaXRlKHdkdCwgQVQ5MV9XRFRfTVIsIHZhbHVl
KTsNCj4gPiArDQo+ID4gKwl2YWx1ZSA9IHdkdC0+Y29uZmlnOw0KPiA+ICsJdmFsdWUgfD0gQVQ5
MV9XRFRfV0REXyh0aW1lb3V0KTsNCj4gPiArCXZhbHVlIHw9IEFUOTFfV0RUX1dEVl8odGltZW91
dCk7DQo+ID4gKw0KPiA+ICsJd2R0X3dyaXRlKHdkdCwgQVQ5MV9XRFRfTVIsIHZhbHVlKTsNCj4g
PiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBhdG1l
bF93ZHRfcHJvYmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikgew0KPiA+ICsJc3RydWN0
IHdhdGNoZG9nX2RldmljZSAqd2RkOw0KPiA+ICsJc3RydWN0IGF0bWVsX3dkdCAqd2R0Ow0KPiA+
ICsJc3RydWN0IHJlc291cmNlICpyZXM7DQo+ID4gKwl2b2lkIF9faW9tZW0gKnJlZ3M7DQo+ID4g
KwlpbnQgcmV0LCBpcnEgPSAtMTsNCj4gPiArDQo+ID4gKwl3ZHQgPSBkZXZtX2t6YWxsb2MoJnBk
ZXYtPmRldiwgc2l6ZW9mKCp3ZHQpLCBHRlBfS0VSTkVMKTsNCj4gPiArCWlmICghd2R0KQ0KPiA+
ICsJCXJldHVybiAtRU5PTUVNOw0KPiA+ICsNCj4gPiArCXdkZCA9ICZ3ZHQtPndkZDsNCj4gPiAr
CXdkZC0+dGltZW91dCA9IHdkdF90aW1lb3V0Ow0KPiA+ICsJd2RkLT5pbmZvID0gJmF0bWVsX3dk
dF9pbmZvOw0KPiA+ICsJd2RkLT5vcHMgPSAmYXRtZWxfd2R0X29wczsNCj4gPiArCXdkZC0+bWlu
X3RpbWVvdXQgPSBNSU5fV0RUX1RJTUVPVVQ7DQo+ID4gKwl3ZGQtPm1heF90aW1lb3V0ID0gTUFY
X1dEVF9USU1FT1VUOw0KPiA+ICsNCj4gPiArCXdhdGNoZG9nX3NldF9kcnZkYXRhKHdkZCwgd2R0
KTsNCj4gPiArDQo+ID4gKwlyZXMgPSBwbGF0Zm9ybV9nZXRfcmVzb3VyY2UocGRldiwgSU9SRVNP
VVJDRV9NRU0sIDApOw0KPiA+ICsJcmVncyA9IGRldm1faW9yZW1hcF9yZXNvdXJjZSgmcGRldi0+
ZGV2LCByZXMpOw0KPiA+ICsJaWYgKElTX0VSUihyZWdzKSkNCj4gPiArCQlyZXR1cm4gUFRSX0VS
UihyZWdzKTsNCj4gPiArDQo+ID4gKwl3ZHQtPnJlZ19iYXNlID0gcmVnczsNCj4gPiArDQo+ID4g
KwlpZiAocGRldi0+ZGV2Lm9mX25vZGUpIHsNCj4gPiArCQlpcnEgPSBpcnFfb2ZfcGFyc2VfYW5k
X21hcChwZGV2LT5kZXYub2Zfbm9kZSwgMCk7DQo+ID4gKwkJaWYgKCFpcnEpDQo+ID4gKwkJCWRl
dl93YXJuKCZwZGV2LT5kZXYsICJ0aGUgSVJRIE5PVCBzcGVjaWZ5IGZyb20gRFRcbiIpOw0KPiAN
Cj4gImZhaWxlZCB0byBnZXQgSVJRIGZyb20gRFQiIHdvdWxkIGJlIGEgYmV0dGVyIG1lc3NhZ2Uu
DQo+IFRoaXMgbGVhdmVzIGlycSBzZXQgdG8gMCBpbiB0aGUgZXJyb3IgY2FzZSwgYW5kIGNhdXNl
IHRoZSBjb2RlIGJlbG93IHRvIHJlcXVlc3QgYW4NCj4gaW50ZXJydXB0Lg0KPiANCj4gPiArDQo+
ID4gKwkJcmV0ID0gb2ZfYXRtZWxfd2R0X2luaXQocGRldi0+ZGV2Lm9mX25vZGUsIHdkdCk7DQo+
ID4gKwkJaWYgKHJldCkNCj4gPiArCQkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4gPiArDQo+ID4g
KwlpZiAoKHdkdC0+Y29uZmlnICYgQVQ5MV9XRFRfV0RGSUVOKSAmJiAoaXJxID49IDApKSB7DQo+
IA0KPiBTZWNvbmQgKCApIGlzIHVubmVjZXNzYXJ5Lg0KPiANCj4gPiArCQlyZXQgPSBkZXZtX3Jl
cXVlc3RfaXJxKCZwZGV2LT5kZXYsIGlycSwgYXRtZWxfd2R0X2lycV9oYW5kbGVyLA0KPiA+ICsJ
CQkJICAgICAgIDAsIHBkZXYtPm5hbWUsIHBkZXYpOw0KPiA+ICsJCWlmIChyZXQpIHsNCj4gPiAr
CQkJZGV2X2VycigmcGRldi0+ZGV2LA0KPiA+ICsJCQkJImNhbm5vdCByZWdpc3RlciBpbnRlcnJ1
cHQgaGFuZGxlclxuIik7DQo+ID4gKwkJCXJldHVybiByZXQ7DQo+ID4gKwkJfQ0KPiA+ICsJfQ0K
PiA+ICsNCj4gPiArCXJldCA9IHdhdGNoZG9nX2luaXRfdGltZW91dCh3ZGQsIHdkdF90aW1lb3V0
LCAmcGRldi0+ZGV2KTsNCj4gPiArCWlmIChyZXQpIHsNCj4gPiArCQlkZXZfZXJyKCZwZGV2LT5k
ZXYsICJ1bmFibGUgdG8gc2V0IHRpbWVvdXQgdmFsdWVcbiIpOw0KPiA+ICsJCXJldHVybiByZXQ7
DQo+IA0KPiBJIHdvdWxkIHN1Z2dlc3QgdG8gc2V0IHRoZSBkZWZhdWx0IHRpbWVvdXQgaW4gdGhp
cyBjYXNlLCBhcyBkb25lIGJ5IG90aGVyIGRyaXZlcnMuDQo+IA0KPiA+ICsJfQ0KPiA+ICsNCj4g
PiArCXJldCA9IGF0bWVsX3dkdF9pbml0KHdkdCk7DQo+ID4gKwlpZiAocmV0KQ0KPiA+ICsJCXJl
dHVybiByZXQ7DQo+ID4gKw0KPiA+ICsJd2F0Y2hkb2dfc2V0X25vd2F5b3V0KHdkZCwgbm93YXlv
dXQpOw0KPiA+ICsNCj4gPiArCXJldCA9IHdhdGNoZG9nX3JlZ2lzdGVyX2RldmljZSh3ZGQpOw0K
PiA+ICsJaWYgKHJldCkgew0KPiA+ICsJCWRldl9lcnIoJnBkZXYtPmRldiwgImZhaWxlZCB0byBy
ZWdpc3RlciB3YXRjaGRvZyBkZXZpY2VcbiIpOw0KPiA+ICsJCXJldHVybiByZXQ7DQo+ID4gKwl9
DQo+ID4gKw0KPiA+ICsJcGxhdGZvcm1fc2V0X2RydmRhdGEocGRldiwgd2R0KTsNCj4gPiArDQo+
ID4gKwlkZXZfaW5mbygmcGRldi0+ZGV2LCAiaW5pdGlhbGl6ZWQgKHRpbWVvdXQgPSAlZCBzZWMs
IG5vd2F5b3V0ID0gJWQpXG4iLA0KPiA+ICsJCSB3ZHRfdGltZW91dCwgbm93YXlvdXQpOw0KPiA+
ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGF0bWVs
X3dkdF9yZW1vdmUoc3RydWN0IHBsYXRmb3JtX2RldmljZSAqcGRldikgew0KPiA+ICsJc3RydWN0
IGF0bWVsX3dkdCAqd2R0ID0gcGxhdGZvcm1fZ2V0X2RydmRhdGEocGRldik7DQo+ID4gKw0KPiA+
ICsJYXRtZWxfd2R0X3N0b3AoJndkdC0+d2RkKTsNCj4gPiArDQo+ID4gKwl3YXRjaGRvZ191bnJl
Z2lzdGVyX2RldmljZSgmd2R0LT53ZGQpOw0KPiA+ICsNCj4gPiArCWRldl9pbmZvKCZwZGV2LT5k
ZXYsICJyZW1vdmVkIHdkdFxuIik7DQo+ID4gKw0KPiBVbm5lY2Vzc2FyeSBtZXNzYWdlLg0KPiAN
Cj4gPiArCXJldHVybiAwOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgY29uc3Qgc3RydWN0
IG9mX2RldmljZV9pZCBhdG1lbF93ZHRfb2ZfbWF0Y2hbXSA9IHsNCj4gPiArCXsgLmNvbXBhdGli
bGUgPSAiYXRtZWwsc2FtYTVkNC13ZHQiLCB9LA0KPiA+ICsJeyB9LA0KPiA+ICt9Ow0KPiA+ICtN
T0RVTEVfREVWSUNFX1RBQkxFKG9mLCBhdG1lbF93ZHRfb2ZfbWF0Y2gpOw0KPiA+ICsNCj4gPiAr
c3RhdGljIHN0cnVjdCBwbGF0Zm9ybV9kcml2ZXIgYXRtZWxfd2R0X2RyaXZlciA9IHsNCj4gPiAr
CS5wcm9iZQkJPSBhdG1lbF93ZHRfcHJvYmUsDQo+ID4gKwkucmVtb3ZlCQk9IGF0bWVsX3dkdF9y
ZW1vdmUsDQo+ID4gKwkuZHJpdmVyCQk9IHsNCj4gPiArCQkubmFtZQk9ICJhdG1lbC13ZHQiLA0K
PiA+ICsJCS5vZl9tYXRjaF90YWJsZSA9IGF0bWVsX3dkdF9vZl9tYXRjaCwNCj4gPiArCX0sDQo+
ID4gK307DQo+ID4gK21vZHVsZV9wbGF0Zm9ybV9kcml2ZXIoYXRtZWxfd2R0X2RyaXZlcik7DQo+
ID4gKw0KPiA+ICtNT0RVTEVfQUxJQVMoInBsYXRmb3JtOmF0bWVsLXdkdCIpOw0KPiA+ICtNT0RV
TEVfQVVUSE9SKCJBdG1lbCBDb3Jwb3JhdGlvbiIpOw0KPiA+ICtNT0RVTEVfREVTQ1JJUFRJT04o
IkF0bWVsIFNBTUE1RDQgV2F0Y2hkb2cgVGltZXIgZHJpdmVyIik7DQo+ID4gK01PRFVMRV9MSUNF
TlNFKCJHUEwgdjIiKTsNCj4gPg0KDQpCZXN0IFJlZ2FyZHMsDQpXZW55b3UgWWFuZw0K
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web