[PATCH] watchdog: sirf: add watchdog driver of CSR SiRFprimaII and SiRFatlasVI

Barry Song 21cnbao at gmail.com
Wed Aug 28 23:19:21 EDT 2013


Hi Wim,

thanks for reviewing. xianglong, will you do some update according to
Wim's comments.

> >
> > +config SIRFSOC_WATCHDOG
> > +     tristate "SiRFSOC watchdog"
> > +     depends on ARCH_SIRF
>
> You are missing a:
>         select WATCHDOG_CORE
> here.

ok. it was done by changing defconfig:
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_CORE=y
but we can move to your solution.

> > +
> > +
> > +static unsigned int default_timeout = SIRFSOC_WDT_DEFAULT_TIMEOUT;
> > +module_param(default_timeout, uint, 0);
> > +MODULE_PARM_DESC(default_timeout, "Default watchdog timeout (in seconds)");
>
> Preferred module parameter name is timeout .
>

ok.

> > +static unsigned int sirfsoc_wdt_gettimeleft(struct watchdog_device *wdd)
> > +{
> > +     u32 counter, match;
> > +     int time_left;
> > +
> > +     counter = readl(watchdog_get_drvdata(wdd) + SIRFSOC_TIMER_COUNTER_LO);
> > +     match = readl(watchdog_get_drvdata(wdd) +
> > +             SIRFSOC_TIMER_MATCH_0 + (SIRFSOC_TIMER_WDT_INDEX << 2));
> > +
> > +     if (match >= counter) {
> > +             time_left = match-counter;
> > +     } else {
> > +             /* rollover */
> > +             time_left = (0xffffffffUL - counter) + match;
> > +     }
>
> should be:
>         if (match >= counter)
>                 time_left = match-counter;
>         else
>                 /* rollover */
>                 time_left = (0xffffffffUL - counter) + match;
>
> according to coding style.

yes. need fix.

>
> > +
> > +     return time_left / CLOCK_TICK_RATE;
> > +}
> > +
> > +static int sirfsoc_wdt_updatetimeout(struct watchdog_device *wdd)
> > +{
> > +     u32 counter, timeout_ticks;
> > +
> > +     timeout_ticks = wdd->timeout * CLOCK_TICK_RATE;
> > +
> > +     /* Enable the latch before reading the LATCH_LO register */
> > +     writel(1, watchdog_get_drvdata(wdd) + SIRFSOC_TIMER_LATCH);
> > +
> > +     /* Set the TO value */
> > +     counter = readl(watchdog_get_drvdata(wdd) + SIRFSOC_TIMER_LATCHED_LO);
> > +
> > +     if ((0xffffffffUL - counter) >= timeout_ticks) {
> > +             counter += timeout_ticks;
> > +     } else {
> > +             /* Rollover */
> > +             counter = timeout_ticks - (0xffffffffUL - counter);
> > +     }
>
> Same here (coding style).

agree.

>
> > +     writel(counter, watchdog_get_drvdata(wdd) +
> > +             SIRFSOC_TIMER_MATCH_0 + (SIRFSOC_TIMER_WDT_INDEX << 2));
> > +
> > +     return 0;
> > +}
> > +
> > +static int sirfsoc_wdt_enable(struct watchdog_device *wdd)
> > +{
> > +     sirfsoc_wdt_updatetimeout(wdd);
> > +
> > +     /*
> > +      * NOTE: If interrupt is not enabled
> > +      * then WD-Reset doesn't get generated at all.
> > +      */
> > +     writel(readl(watchdog_get_drvdata(wdd) + SIRFSOC_TIMER_INT_EN)
> > +             | (1 << SIRFSOC_TIMER_WDT_INDEX),
> > +             watchdog_get_drvdata(wdd) + SIRFSOC_TIMER_INT_EN);
> > +     writel(1, watchdog_get_drvdata(wdd) + SIRFSOC_TIMER_WATCHDOG_EN);
>
> Wouldn't it be better to define a local variable first that get's the value
> of watchdog_get_drvdata(wdd)? This would definitely improve readability.
> Goes also for other functions (like sirfsoc_wdt_gettimeleft and
> sirfsoc_wdt_disable).
>

ok

> > +
> > +static int sirfsoc_wdt_settimeout(struct watchdog_device *wdd, unsigned int to)
> > +{
> > +     if (to < SIRFSOC_WDT_MIN_TIMEOUT)
> > +             to = SIRFSOC_WDT_MIN_TIMEOUT;
> > +     if (to > SIRFSOC_WDT_MAX_TIMEOUT)
> > +             to = SIRFSOC_WDT_MAX_TIMEOUT;
>
> Hmm, since SIRFSOC_WDT_MIN_TIMEOUT and SIRFSOC_WDT_MAX_TIMEOUT are defined:
> setting the timeout will call watchdog_set_timeout and that function will do a:
> if (watchdog_timeout_invalid(wddev, timeout))
>                 return -EINVAL;
>
> with watchdog_timeout_invalid returning:
>         ((wdd->max_timeout != 0) && (t < wdd->min_timeout || t > wdd->max_timeout));
>
> So this will never happen...

so we will drop this.

>
>
> > +     wdd->timeout = to;
> > +     sirfsoc_wdt_updatetimeout(wdd);
> > +
> > +     return 0;
> > +}
> > +
> > +#define OPTIONS (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE)
> > +
> > +static const struct watchdog_info sirfsoc_wdt_ident = {
> > +     .options          =     OPTIONS,
> > +     .firmware_version =     0,
> > +     .identity         =     "SiRFSOC Watchdog",
> > +};
> > +
> > +static struct watchdog_ops sirfsoc_wdt_ops = {
> > +     .owner = THIS_MODULE,
> > +     .start = sirfsoc_wdt_enable,
> > +     .stop = sirfsoc_wdt_disable,
> > +     .get_timeleft = sirfsoc_wdt_gettimeleft,
> > +     .ping = sirfsoc_wdt_updatetimeout,
> > +     .set_timeout = sirfsoc_wdt_settimeout,
> > +};
> > +
> > +static struct watchdog_device sirfsoc_wdd = {
> > +     .info = &sirfsoc_wdt_ident,
> > +     .ops = &sirfsoc_wdt_ops,
> > +     .timeout = SIRFSOC_WDT_DEFAULT_TIMEOUT,
> > +     .min_timeout = SIRFSOC_WDT_MIN_TIMEOUT,
> > +     .max_timeout = SIRFSOC_WDT_MAX_TIMEOUT,
> > +};
> > +
> > +static int sirfsoc_wdt_probe(struct platform_device *pdev)
> > +{
> > +     struct resource *res;
> > +     int ret;
> > +     void __iomem *base;
> > +
> > +     /* reserve static register mappings */
> > +     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +     if (!res) {
> > +             dev_err(&pdev->dev, "sirfsoc wdt: could not get mem resources\n");
> > +             ret = -ENOMEM;
> > +             goto out;
> > +     }
> > +
> > +     base = devm_ioremap_resource(&pdev->dev, res);
> > +     if (!base) {
> > +             dev_err(&pdev->dev, "sirfsoc wdt: could not remap the mem\n");
> > +             ret = -EADDRNOTAVAIL;
> > +             goto out;
> > +     }
> > +     watchdog_set_drvdata(&sirfsoc_wdd, base);
> > +
> > +     sirfsoc_wdd.timeout = default_timeout;
>
> You can consider using watchdog_init_timeout here.
> I would also advice to add watchdog_set_nowayout and use the nowayout functionality.

agree.

> > +
> > +MODULE_DESCRIPTION("SiRF SoC watchdog driver");
> > +MODULE_AUTHOR("Xianglong Du <Xianglong.Du at csr.com>");
> > +MODULE_LICENSE("GPL v2");
> > +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
>
> This alias can be removed if you have the platform alias (like listed in the following line).
>
> > +MODULE_ALIAS("platform:sirfsoc-wdt");

agree.


> > --
> > 1.7.4.1
>
> Kind regards,
> Wim.
>

-barry



More information about the linux-arm-kernel mailing list