[PATCH v2 1/2] watchdog: NXP LPC18xx Watchdog Timer Driver

Ariel D'Alessandro ariel at vanguardiasur.com.ar
Sat Jul 4 19:06:19 PDT 2015


Hi Joachim,

El 01/07/15 a las 20:04, Joachim Eastwood escibió:
> Hi Ariel,
> 
> On 1 July 2015 at 22:52, Ariel D'Alessandro <ariel at vanguardiasur.com.ar> wrote:
>> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
>> index 742fbbc..31100c2 100644
>> --- a/drivers/watchdog/Kconfig
>> +++ b/drivers/watchdog/Kconfig
>> @@ -547,6 +547,17 @@ config DIGICOLOR_WATCHDOG
>>           To compile this driver as a module, choose M here: the
>>           module will be called digicolor_wdt.
>>
>> +config LPC18XX_WATCHDOG
>> +       tristate "LCP18XX Watchdog"
> 
> LPC18xx/43xx in tristate to indicate that is usable for both families.

Ok, I'll do that.

> 
>> +       depends on ARCH_LPC18XX
>> +       select WATCHDOG_CORE
> 
> Maybe add COMPILE_TEST. At least a couple of other watchdog drivers does that.

Yes, that's correct. I'll add it in the next version.

> 
>> +       help
>> +         Say Y here if to include support for the watchdog timer
>> +         in NXP LPC SoCs family, which includes LPC18xx/LPC43xx
>> +         processors.
>> +         To compile this driver as a module, choose M here: the
>> +         module will be called lpc18xx_wdt.
>> +
> [...]
>> +static int lpc18xx_wdt_feed(struct watchdog_device *wdt_dev)
>> +{
>> +       struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev);
>> +       unsigned long flags;
>> +
>> +       /*
>> +        * An abort condition will occur if an interrupt happens during the feed
>> +        * sequence.
>> +        */
>> +       raw_local_irq_save(flags);
> 
> Any particular reason why you are using the raw variant of
> local_irq_save/restore?
> raw_local_irq_save doesn't seem to be a common function for drivers to
> call at all.

No, you're right, raw variants don't seem to be necessary.

> 
> If you need a lock to protect register access as well you could use a
> spin lock with irq save.

Yes but, as Ezequiel said in his response, the watchdog framework
serializes this access. So I think a lock isn't necessary.

> 
>> +       writel(LPC18XX_WDT_FEED_MAGIC1, lpc18xx_wdt->base + LPC18XX_WDT_FEED);
>> +       writel(LPC18XX_WDT_FEED_MAGIC2, lpc18xx_wdt->base + LPC18XX_WDT_FEED);
>> +       raw_local_irq_restore(flags);
>> +
>> +       return 0;
>> +}
> [...]
>> +unsigned int lpc18xx_wdt_get_timeleft(struct watchdog_device *wdt_dev)
>> +{
>> +       struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev);
>> +       unsigned long clk_rate = clk_get_rate(lpc18xx_wdt->wdt_clk);
>> +       unsigned int val;
>> +
>> +       val = readl(lpc18xx_wdt->base + LPC18XX_WDT_TV);
>> +       return ((val * LPC18XX_WDT_CLK_DIV) / clk_rate);
> 
> Outer parentheses on return is unnecessary.

You're right, I'll fix it.

> 
>> +}
>> +
>> +static int lpc18xx_wdt_start(struct watchdog_device *wdt_dev)
>> +{
>> +       struct lpc18xx_wdt_dev *lpc18xx_wdt = watchdog_get_drvdata(wdt_dev);
>> +       unsigned int val;
>> +
>> +       if (timer_pending(&lpc18xx_wdt->timer))
>> +               del_timer(&lpc18xx_wdt->timer);
>> +
>> +       val = readl(lpc18xx_wdt->base + LPC18XX_WDT_MOD);
>> +       val |= LPC18XX_WDT_MOD_WDEN;
>> +       val |= LPC18XX_WDT_MOD_WDRESET;
>> +       writel(val, lpc18xx_wdt->base + LPC18XX_WDT_MOD);
> 
> R-M-W sequence should probably be protect with a lock.

We can continue discussing this point on Ezequiel's response.

> 
>> +       /*
>> +        * Setting the WDEN bit in the WDMOD register is not sufficient to
>> +        * enable the Watchdog. A valid feed sequence must be completed after
>> +        * setting WDEN before the Watchdog is capable of generating a reset.
>> +        */
>> +       lpc18xx_wdt_feed(wdt_dev);
>> +
>> +       return 0;
>> +}
> 
> 
> regards,
> Joachim Eastwood
> 



More information about the linux-arm-kernel mailing list