Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1200368 > unrolled thread
| Started by | Wenyou Yang <wenyou.yang@atmel.com> |
|---|---|
| First post | 2015-08-05 04:50 +0200 |
| Last post | 2015-08-05 10:50 +0200 |
| Articles | 5 — 3 participants |
Back to article view | Back to linux.kernel
[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
| From | Wenyou Yang <wenyou.yang@atmel.com> |
|---|---|
| Date | 2015-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]
| From | Wenyou Yang <wenyou.yang@atmel.com> |
|---|---|
| Date | 2015-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]
| From | Wenyou Yang <wenyou.yang@atmel.com> |
|---|---|
| Date | 2015-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]
| From | Guenter Roeck <linux@roeck-us.net> |
|---|---|
| Date | 2015-08-05 08:20 +0200 |
| Subject | Re: [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]
| From | "Yang, Wenyou" <Wenyou.Yang@atmel.com> |
|---|---|
| Date | 2015-08-05 10:50 +0200 |
| Subject | RE: [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