From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from bh-25.webhostbox.net ([208.91.199.152]:43214 "EHLO bh-25.webhostbox.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753205AbaIODCC (ORCPT ); Sun, 14 Sep 2014 23:02:02 -0400 Received: from mailnull by bh-25.webhostbox.net with sa-checked (Exim 4.82) (envelope-from ) id 1XTMYC-0026bY-HJ for linux-watchdog@vger.kernel.org; Mon, 15 Sep 2014 03:02:00 +0000 Message-ID: <541656A3.8030906@roeck-us.net> Date: Sun, 14 Sep 2014 20:01:55 -0700 From: Guenter Roeck MIME-Version: 1.0 To: Sergey Ryazanov , Ralf Baechle CC: Linux MIPS , Wim Van Sebroeck , linux-watchdog@vger.kernel.org Subject: Re: [RFC 13/18] watchdog: add Atheros AR2315 watchdog driver References: <1410723213-22440-1-git-send-email-ryazanov.s.a@gmail.com> <1410723213-22440-14-git-send-email-ryazanov.s.a@gmail.com> In-Reply-To: <1410723213-22440-14-git-send-email-ryazanov.s.a@gmail.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit Sender: linux-watchdog-owner@vger.kernel.org List-Id: linux-watchdog@vger.kernel.org On 09/14/2014 12:33 PM, Sergey Ryazanov wrote: > Signed-off-by: Sergey Ryazanov > Cc: Wim Van Sebroeck > Cc: linux-watchdog@vger.kernel.org > --- > arch/mips/ar231x/ar2315.c | 26 +++++- > drivers/watchdog/Kconfig | 7 ++ > drivers/watchdog/Makefile | 1 + > drivers/watchdog/ar2315-wtd.c | 202 ++++++++++++++++++++++++++++++++++++++++++ This should be two patches: One to instantiate the watchdog, the second the watchdog driver itself. The weatchdog driver should use the watchdog infrastructure. Guenter > 4 files changed, 235 insertions(+), 1 deletion(-) > create mode 100644 drivers/watchdog/ar2315-wtd.c > > diff --git a/arch/mips/ar231x/ar2315.c b/arch/mips/ar231x/ar2315.c > index cab3b76..62cf548 100644 > --- a/arch/mips/ar231x/ar2315.c > +++ b/arch/mips/ar231x/ar2315.c > @@ -62,7 +62,10 @@ static void ar2315_misc_irq_handler(unsigned irq, struct irq_desc *desc) > generic_handle_irq(AR2315_MISC_IRQ_GPIO); > } else if (pending & AR2315_ISR_UART0) > generic_handle_irq(AR2315_MISC_IRQ_UART0); > - else > + else if (pending & AR2315_ISR_WD) { > + ar231x_write_reg(AR2315_ISR, AR2315_ISR_WD); > + generic_handle_irq(AR2315_MISC_IRQ_WATCHDOG); > + } else > spurious_interrupt(); > } > > @@ -148,6 +151,26 @@ static struct platform_device ar2315_spiflash = { > .num_resources = ARRAY_SIZE(ar2315_spiflash_res) > }; > > +static struct resource ar2315_wdt_res[] = { > + { > + .flags = IORESOURCE_MEM, > + .start = AR2315_WD, > + .end = AR2315_WD + 8 - 1, > + }, > + { > + .flags = IORESOURCE_IRQ, > + .start = AR2315_MISC_IRQ_WATCHDOG, > + .end = AR2315_MISC_IRQ_WATCHDOG, > + } > +}; > + > +static struct platform_device ar2315_wdt = { > + .id = -1, > + .name = "ar2315-wdt", > + .resource = ar2315_wdt_res, > + .num_resources = ARRAY_SIZE(ar2315_wdt_res) > +}; > + > static struct resource ar2315_gpio_res[] = { > { > .name = "ar2315-gpio", > @@ -193,6 +216,7 @@ void __init ar2315_init_devices(void) > ar231x_find_config(ar2315_flash_limit); > > platform_device_register(&ar2315_gpio); > + platform_device_register(&ar2315_wdt); > platform_device_register(&ar2315_spiflash); > } > > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig > index f57312f..0e84f3a 100644 > --- a/drivers/watchdog/Kconfig > +++ b/drivers/watchdog/Kconfig > @@ -1186,6 +1186,13 @@ config RALINK_WDT > help > Hardware driver for the Ralink SoC Watchdog Timer. > > +config AR2315_WDT > + tristate "Atheros AR2315+ WiSoCs Watchdog Timer" > + depends on SOC_AR2315 > + help > + Hardware driver for the built-in watchdog timer on the Atheros > + AR2315/AR2316 WiSoCs. > + > # PARISC Architecture > > # POWERPC Architecture > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile > index 468c320..ef7f83b 100644 > --- a/drivers/watchdog/Makefile > +++ b/drivers/watchdog/Makefile > @@ -133,6 +133,7 @@ obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o > obj-$(CONFIG_PNX833X_WDT) += pnx833x_wdt.o > obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o > obj-$(CONFIG_AR7_WDT) += ar7_wdt.o > +obj-$(CONFIG_AR2315_WDT) += ar2315-wtd.o > obj-$(CONFIG_TXX9_WDT) += txx9wdt.o > obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o > octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o > diff --git a/drivers/watchdog/ar2315-wtd.c b/drivers/watchdog/ar2315-wtd.c > new file mode 100644 > index 0000000..8e1687a > --- /dev/null > +++ b/drivers/watchdog/ar2315-wtd.c > @@ -0,0 +1,202 @@ > +/* > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, see . > + * > + * Copyright (C) 2008 John Crispin > + * Based on EP93xx and ifxmips wdt driver 2008 ? > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define DRIVER_NAME "ar2315-wdt" > + > +#define CLOCK_RATE 40000000 > +#define HEARTBEAT(x) (x < 1 || x > 90 ? 20 : x) > + Whatever the logic is here, it does not make much sense to me. > +#define WDT_REG_TIMER 0x00 > +#define WDT_REG_CTRL 0x04 > + > +#define WDT_CTRL_ACT_NONE 0x00000000 /* No action */ > +#define WDT_CTRL_ACT_NMI 0x00000001 /* NMI on watchdog */ > +#define WDT_CTRL_ACT_RESET 0x00000002 /* reset on watchdog */ > + > +static int wdt_timeout = 20; > +static int started; > +static int in_use; > +static void __iomem *wdt_base; > + > +static inline void ar2315_wdt_wr(unsigned reg, u32 val) > +{ > + iowrite32(val, wdt_base + reg); > +} > + > +static void ar2315_wdt_enable(void) > +{ > + ar2315_wdt_wr(WDT_REG_TIMER, wdt_timeout * CLOCK_RATE); > +} > + > +static ssize_t ar2315_wdt_write(struct file *file, const char __user *data, > + size_t len, loff_t *ppos) > +{ > + if (len) > + ar2315_wdt_enable(); > + return len; > +} > + > +static int ar2315_wdt_open(struct inode *inode, struct file *file) > +{ > + if (in_use) > + return -EBUSY; > + ar2315_wdt_enable(); > + in_use = 1; > + started = 1; > + return nonseekable_open(inode, file); > +} > + > +static int ar2315_wdt_release(struct inode *inode, struct file *file) > +{ > + in_use = 0; > + return 0; > +} > + > +static irqreturn_t ar2315_wdt_interrupt(int irq, void *dev) > +{ > + struct platform_device *pdev = (struct platform_device *)dev; > + > + if (started) { > + dev_crit(&pdev->dev, "watchdog expired, rebooting system\n"); > + emergency_restart(); > + } else { > + ar2315_wdt_wr(WDT_REG_CTRL, 0); > + ar2315_wdt_wr(WDT_REG_TIMER, 0); > + } > + return IRQ_HANDLED; > +} > + > +static struct watchdog_info ident = { > + .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, > + .identity = "ar2315 Watchdog", > +}; > + > +static long ar2315_wdt_ioctl(struct file *file, unsigned int cmd, > + unsigned long arg) > +{ > + int new_wdt_timeout; > + int ret = -ENOIOCTLCMD; > + > + switch (cmd) { > + case WDIOC_GETSUPPORT: > + ret = copy_to_user((void __user *)arg, &ident, sizeof(ident)) ? > + -EFAULT : 0; > + break; > + case WDIOC_KEEPALIVE: > + ar2315_wdt_enable(); > + ret = 0; > + break; > + case WDIOC_SETTIMEOUT: > + ret = get_user(new_wdt_timeout, (int __user *)arg); > + if (ret) > + break; > + wdt_timeout = HEARTBEAT(new_wdt_timeout); > + ar2315_wdt_enable(); > + break; > + case WDIOC_GETTIMEOUT: > + ret = put_user(wdt_timeout, (int __user *)arg); > + break; > + } > + return ret; > +} > + > +static const struct file_operations ar2315_wdt_fops = { > + .owner = THIS_MODULE, > + .llseek = no_llseek, > + .write = ar2315_wdt_write, > + .unlocked_ioctl = ar2315_wdt_ioctl, > + .open = ar2315_wdt_open, > + .release = ar2315_wdt_release, > +}; > + > +static struct miscdevice ar2315_wdt_miscdev = { > + .minor = WATCHDOG_MINOR, > + .name = "watchdog", > + .fops = &ar2315_wdt_fops, > +}; > + > +static int ar2315_wdt_probe(struct platform_device *dev) > +{ > + struct resource *mem_res, *irq_res; > + int ret = 0; > + > + if (wdt_base) > + return -EBUSY; > + > + irq_res = platform_get_resource(dev, IORESOURCE_IRQ, 0); > + if (!irq_res) { > + dev_err(&dev->dev, "no IRQ resource\n"); > + return -ENOENT; > + } > + > + mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0); > + wdt_base = devm_ioremap_resource(&dev->dev, mem_res); > + if (IS_ERR(wdt_base)) > + return PTR_ERR(wdt_base); > + > + ret = devm_request_irq(&dev->dev, irq_res->start, ar2315_wdt_interrupt, > + IRQF_DISABLED, DRIVER_NAME, dev); > + if (ret) { > + dev_err(&dev->dev, "failed to register inetrrupt\n"); > + goto out; > + } > + > + ret = misc_register(&ar2315_wdt_miscdev); > + if (ret) > + dev_err(&dev->dev, "failed to register miscdev\n"); > + > +out: > + return ret; > +} > + > +static int ar2315_wdt_remove(struct platform_device *dev) > +{ > + misc_deregister(&ar2315_wdt_miscdev); > + return 0; > +} > + > +static struct platform_driver ar2315_wdt_driver = { > + .probe = ar2315_wdt_probe, > + .remove = ar2315_wdt_remove, > + .driver = { > + .name = DRIVER_NAME, > + .owner = THIS_MODULE, > + }, > +}; > + > +module_platform_driver(ar2315_wdt_driver); > + > +MODULE_DESCRIPTION("Atheros AR2315 hardware watchdog driver"); > +MODULE_AUTHOR("John Crispin "); > +MODULE_LICENSE("GPL"); > +MODULE_ALIAS("platform:" DRIVER_NAME); >