From: Joel Stanley <joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
To: Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
Cc: wim-IQzOog9fTRqzQB+pC5nmwQ@public.gmane.org,
linux-watchdog-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
Jeremy Kerr <jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org>,
Benjamin Herrenschmidt
<benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org>,
Arnd Bergmann <arnd-r2nGTMty4D4@public.gmane.org>
Subject: Re: [PATCH 2/2] watchdog: Add Aspeed watchdog driver
Date: Tue, 10 May 2016 20:40:21 +0930 [thread overview]
Message-ID: <CACPK8XfK4Qt2GaSL7eVoNkCawbtXqFX9bGRcgyAyq7R2yuSZkA@mail.gmail.com> (raw)
In-Reply-To: <5730A339.80006-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
Hey Guenter,
Thanks for the review.
On Tue, May 10, 2016 at 12:18 AM, Guenter Roeck <linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org> wrote:
>> +#define WDT_STATUS 0x00
>> +#define WDT_RELOAD_VALUE 0x04
>> +#define WDT_RESTART 0x08
>> +#define WDT_CTRL 0x0C
>> +#define WDT_CTRL_RESET_MODE_SOC (0x00 << 5)
>> +#define WDT_CTRL_RESET_MODE_FULL_CHIP (0x01 << 5)
>> +#define WDT_CTRL_1MHZ_CLK BIT(4)
>> +#define WDT_CTRL_WDT_EXT BIT(3)
>> +#define WDT_CTRL_WDT_INTR BIT(2)
>> +#define WDT_CTRL_RESET_SYSTEM BIT(1)
>> +#define WDT_CTRL_ENABLE BIT(0)
>> +
>> +#define WDT_RESTART_MAGIC 0x4755
>
>
> Please don't use tabs after #define.
Oops, typo. Thanks.
>
>> +
>> +static struct aspeed_wdt *to_aspeed_wdt(struct watchdog_device *wdd)
>> +{
>> + return container_of(wdd, struct aspeed_wdt, wdd);
>> +}
>> +
>> +
>
> Please no double empty lines.
>
>> +static void aspeed_wdt_enable(struct aspeed_wdt *wdt, int count)
>> +{
>> + wdt->ctrl |= WDT_CTRL_ENABLE;
>> +
>> + writel(0, wdt->base + WDT_CTRL);
>> + writel(count, wdt->base + WDT_RELOAD_VALUE);
>> + writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
>> + writel(wdt->ctrl, wdt->base + WDT_CTRL);
>
>
> Is it really necessary to write 0 into the ctrl register when enabling
> the watchdog ? Problem with it is two-fold: It changes the clock rate
> for a brief period of time, and it disables the watchdog while updating
> the timeout. Both is undesirable unless really needed.
In general I agree. However, the datasheet explicitly spells out these
four steps in this order. Writing zero is a shortcut; I could write
ctrl with the enable bit set to zero.
We've been using the driver in this fashion for the past year.
>> +}
>> +
>> +static int aspeed_wdt_start(struct watchdog_device *wdd)
>> +{
>> + struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> + dev_dbg(wdd->parent, "starting with timeout of %d (rate %lu)\n",
>> + wdd->timeout, wdt->rate);
>
>
> Are those dev_dbg() really useful ?
I did use them in writing the driver. They can go.
>
>> + aspeed_wdt_enable(wdt, wdd->timeout * wdt->rate);
>> +
>> + return 0;
>> +}
>> +
>> +static int aspeed_wdt_stop(struct watchdog_device *wdd)
>> +{
>> + struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> + wdt->ctrl &= ~WDT_CTRL_ENABLE;
>> + writel(wdt->ctrl, wdt->base + WDT_CTRL);
>> +
>> + return 0;
>> +}
>> +
>> +static int aspeed_wdt_ping(struct watchdog_device *wdd)
>> +{
>> + struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> + dev_dbg(wdd->parent, "ping\n");
>> + writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART);
>> + return 0;
>> +}
>> +
>> +static int aspeed_wdt_set_timeout(struct watchdog_device *wdd,
>> + unsigned int timeout)
>> +{
>> + dev_dbg(wdd->parent, "timeout set to %u\n", timeout);
>> + wdd->timeout = timeout;
>> +
>> + return aspeed_wdt_start(wdd);
>> +}
>> +
>> +static int aspeed_wdt_restart(struct watchdog_device *wdd,
>> + unsigned long action, void *data)
>> +{
>> + struct aspeed_wdt *wdt = to_aspeed_wdt(wdd);
>> +
>> + aspeed_wdt_enable(wdt, 128 * wdt->rate / 1000);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct watchdog_ops aspeed_wdt_ops = {
>> + .start = aspeed_wdt_start,
>> + .stop = aspeed_wdt_stop,
>> + .ping = aspeed_wdt_ping,
>> + .set_timeout = aspeed_wdt_set_timeout,
>> + .restart = aspeed_wdt_restart,
>> + .owner = THIS_MODULE,
>> +};
>> +
>> +static const struct watchdog_info aspeed_wdt_info = {
>> + .options = WDIOF_KEEPALIVEPING
>> + | WDIOF_MAGICCLOSE
>> + | WDIOF_SETTIMEOUT,
>> + .identity = KBUILD_MODNAME,
>> +};
>> +
>> +static int aspeed_wdt_remove(struct platform_device *pdev)
>> +{
>> + struct aspeed_wdt *wdt = platform_get_drvdata(pdev);
>> +
>> + watchdog_unregister_device(&wdt->wdd);
>> +
>> + return 0;
>> +}
>> +
>> +static int aspeed_wdt_probe(struct platform_device *pdev)
>> +{
>> + struct aspeed_wdt *wdt;
>> + struct resource *res;
>> + int ret;
>> +
>> + wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
>> + if (!wdt)
>> + return -ENOMEM;
>> +
>> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> + wdt->base = devm_ioremap_resource(&pdev->dev, res);
>> + if (IS_ERR(wdt->base))
>> + return PTR_ERR(wdt->base);
>> +
>> + /*
>> + * The ast2400 wdt can run at PCLK, or 1MHz. The ast2500 only
>> + * runs at 1MHz. We chose to always run at 1MHz, as there's no
>> + * good reason to have a faster watchdog counter.
>> + */
>> + wdt->rate = 1000000;
>
>
> Why not just use a define ?
I will add one.
The comment is informative though for people who read the ast2400
datasheet and wonder why we don't provide the option clocking with
pclk, I will leave it in.
>> + wdt->wdd.info = &aspeed_wdt_info;
>> + wdt->wdd.ops = &aspeed_wdt_ops;
>> + wdt->wdd.min_timeout = 1;
>> + wdt->wdd.max_timeout = 0x10000000U / wdt->rate;
>> + wdt->wdd.parent = &pdev->dev;
>> +
>> + wdt->wdd.timeout = min(wdt->wdd.max_timeout, 30U);
>
>
> Pretty much the same here. Since max_timeout is a constant,
> it is well known that it is larger than 30 seconds.
> Might as well use defines for max_timeout and timeout.
Ok.
>
>> + watchdog_init_timeout(&wdt->wdd, 0, &pdev->dev);
>> +
>> + wdt->ctrl = WDT_CTRL_RESET_MODE_SOC |
>
>
> Only reset tha SoC ? Are you sure this is what you want ?
I think this is left over from experiments when tracking down a reset
bug in u-boot. I will confirm and change it back to FULL_CHIP.
>
>> + WDT_CTRL_1MHZ_CLK |
>> + WDT_CTRL_RESET_SYSTEM;
>> +
>> + /* Ensure hardware is in consistent state */
>> + aspeed_wdt_stop(&wdt->wdd);
>> +
>
> An alternative might be to check if the watchdog is running, and inform
> the watchdog core about it so it can generate heartbeats as required
> until user space opens the watchdog device. This would ensure that the
> system is protected during boot.
I will implement this.
> ctrl is really static except for the enable flag. Not really sure
> if having a variable for it has any real benefits - you might as well
> just read the register and update the enable flag instead as needed when
> starting or stopping the watchdog. Is there a reason for not doing that ?
Not really. I find it cleaner to keep a copy of the register instead
of read-modify-write, but if you feel strongly about it I can change.
>
>> + ret = watchdog_register_device(&wdt->wdd);
>> + if (ret) {
>> + dev_err(&pdev->dev, "failed to register\n");
>> + goto err;
>
>
> Unnecessary goto. Just return.
Ok.
>
>
>> + }
>> +
>> + dev_info(&pdev->dev, "rate %lu, max timeout %u, timeout %d\n",
>> + wdt->rate, wdt->wdd.max_timeout, wdt->wdd.timeout);
>> +
>> + platform_set_drvdata(pdev, wdt);
>> +err:
>> + return ret;
>> +}
>> +
>> +static struct platform_driver aspeed_watchdog_driver = {
>> + .probe = aspeed_wdt_probe,
>> + .remove = aspeed_wdt_remove,
>> + .driver = {
>> + .name = KBUILD_MODNAME,
>> + .of_match_table = of_match_ptr(aspeed_wdt_of_table),
>> + },
>> +};
>> +module_platform_driver(aspeed_watchdog_driver);
>> +
>> +MODULE_DESCRIPTION("Aspeed Watchdog Driver");
>> +MODULE_LICENSE("GPL");
>>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-watchdog" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2016-05-10 11:10 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-09 12:34 [PATCH 0/2] watchdog: Add Aspeed watchdog driver Joel Stanley
[not found] ` <1462797277-14969-1-git-send-email-joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
2016-05-09 12:34 ` [PATCH 1/2] doc/devicetree: Add Aspeed watchdog timer bindings Joel Stanley
[not found] ` <1462797277-14969-2-git-send-email-joel-U3u1mxZcP9KHXe+LvDLADg@public.gmane.org>
2016-05-09 20:38 ` Rob Herring
2016-05-10 11:24 ` Joel Stanley
2016-05-09 12:34 ` [PATCH 2/2] watchdog: Add Aspeed watchdog driver Joel Stanley
2016-05-09 14:48 ` Guenter Roeck
[not found] ` <5730A339.80006-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org>
2016-05-10 11:10 ` Joel Stanley [this message]
[not found] ` <CACPK8XfK4Qt2GaSL7eVoNkCawbtXqFX9bGRcgyAyq7R2yuSZkA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2016-05-10 13:25 ` Guenter Roeck
2016-05-12 14:17 ` [PATCH v2 0/2] " Joel Stanley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CACPK8XfK4Qt2GaSL7eVoNkCawbtXqFX9bGRcgyAyq7R2yuSZkA@mail.gmail.com \
--to=joel-u3u1mxzcp9khxe+lvdladg@public.gmane.org \
--cc=arnd-r2nGTMty4D4@public.gmane.org \
--cc=benh-XVmvHMARGAS8U2dJNN8I7kB+6BGkLq7r@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=jk-mnsaURCQ41sdnm+yROfE0A@public.gmane.org \
--cc=linux-0h96xk9xTtrk1uMJSBkQmQ@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-watchdog-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=wim-IQzOog9fTRqzQB+pC5nmwQ@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).