Re: [RFC 1/4] watchdog: ni9x3x_wdt: Add NI 903x/913x watchdog driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Feb 04, 2016 at 07:28:00PM -0600, Kyle Roeschley wrote:
> Add support for the watchdog timer on NI cRIO-903x and cDAQ-913x real-
> time controllers.
> 
> Signed-off-by: Jeff Westfahl <jeff.westfahl@xxxxxx>
> Signed-off-by: Kyle Roeschley <kyle.roeschley@xxxxxx>
[..]
> +++ b/drivers/watchdog/ni9x3x_wdt.c
> @@ -0,0 +1,264 @@
[..]
> +#define NIWD_CONTROL_MODE		0x80
> +#define NIWD_CONTROL_PROC_RESET		0x20
> +#define NIWD_CONTROL_PET		0x10
> +#define NIWD_CONTROL_RUNNING		0x08
> +#define NIWD_CONTROL_CAPTURECOUNTER	0x04
> +#define NIWD_CONTROL_RESET		0x02
> +#define NIWD_CONTROL_ALARM		0x01
> +
> +#define NIWD_PERIOD_NS		30720
> +#define NIWD_MIN_TIMEOUT	1
> +#define NIWD_MAX_TIMEOUT	515
> +#define NIWD_DEFAULT_TIMEOUT	60
> +
> +#define NI9X3X_WDT_NAME		"ni9x3x_wdt"
> +
> +#define to_ni9x3x_wdt(_wdog)	container_of(_wdog, struct ni9x3x_wdt, wdog)
> +
> +struct ni9x3x_wdt {
> +	struct acpi_device *acpi_device;

Probably a bit easier if you just cache the 'struct device *' instead.
Or, just use wdog.parent.

> +	u16 io_base;
> +	u16 io_size;

You don't actually need io_size after probe().  I'm wondering if you
could just move the devm_request_region directly into your
acpi_walk_resources callback and drop this.

> +	spinlock_t lock;

This isn't used at all?  (I'm assuming it might be used in a later
patch, but if so, it should be introduced there).

> +	struct watchdog_device wdog;
> +};
> +
> +static void ni9x3x_wdt_start(struct ni9x3x_wdt *wdt)
> +{
> +	u8 control = inb(wdt->io_base + NIWD_CONTROL);
> +
> +	outb(control | NIWD_CONTROL_RESET, wdt->io_base + NIWD_CONTROL);
> +	outb(control | NIWD_CONTROL_PET, wdt->io_base + NIWD_CONTROL);
> +}
> +
> +static int ni9x3x_wdt_wdd_set_timeout(struct watchdog_device *wdd,
> +				      unsigned int timeout)
> +{
> +	struct ni9x3x_wdt *wdt = to_ni9x3x_wdt(wdd);
> +	u32 counter = timeout * (1000000000 / NIWD_PERIOD_NS);
> +
> +	outb(((0x00FF0000 & counter) >> 16), wdt->io_base + NIWD_SEED2);
> +	outb(((0x0000FF00 & counter) >> 8), wdt->io_base + NIWD_SEED1);
> +	outb((0x000000FF & counter), wdt->io_base + NIWD_SEED0);
> +
> +	return 0;
> +}
> +
> +static unsigned int ni9x3x_wdt_wdd_get_timeleft(struct watchdog_device *wdd)
> +{
> +	struct ni9x3x_wdt *wdt = to_ni9x3x_wdt(wdd);
> +	u8 control, counter0, counter1, counter2;
> +	u32 counter;
> +
> +	control = inb(wdt->io_base + NIWD_CONTROL);
> +	control |= NIWD_CONTROL_CAPTURECOUNTER;
> +	outb(control, wdt->io_base + NIWD_CONTROL);
> +
> +	counter2 = inb(wdt->io_base + NIWD_COUNTER2);
> +	counter1 = inb(wdt->io_base + NIWD_COUNTER1);
> +	counter0 = inb(wdt->io_base + NIWD_COUNTER0);
> +
> +	counter = (counter2 << 16) | (counter1 << 8) | counter0;
> +	counter = (counter * (u64)NIWD_PERIOD_NS) / 1000000000;
> +
> +	return (unsigned int)counter;

Nit: unnecessary cast.

> +}
[..]
> +static int ni9x3x_wdt_acpi_add(struct acpi_device *device)
> +{
> +	struct ni9x3x_wdt *wdt;
> +	acpi_status status;
> +	int ret;
> +
> +	wdt = devm_kzalloc(&device->dev, sizeof(*wdt), GFP_KERNEL);
> +	if (!wdt)
> +		return -ENOMEM;
> +
> +	device->driver_data = wdt;
> +	wdt->acpi_device = device;
> +
> +	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
> +				     ni9x3x_wdt_resources, wdt);
> +	if (ACPI_FAILURE(status) || wdt->io_base == 0 ||
> +	    wdt->io_size != NIWD_IO_SIZE) {
> +		dev_err(&device->dev, "failed to get resources\n");
> +		return -ENODEV;
> +	}
> +
> +	if (!devm_request_region(&device->dev, wdt->io_base, wdt->io_size,
> +				 NI9X3X_WDT_NAME)) {
> +		dev_err(&device->dev, "failed to get memory region\n");
> +		return -EBUSY;
> +	}
> +
> +	spin_lock_init(&wdt->lock);
> +
> +	wdt->wdog.info = &ni9x3x_wdt_wdd_info;
> +	wdt->wdog.ops = &ni9x3x_wdt_wdd_ops;
> +	wdt->wdog.min_timeout = NIWD_MIN_TIMEOUT;
> +	wdt->wdog.max_timeout = NIWD_MAX_TIMEOUT;
> +	wdt->wdog.timeout = NIWD_DEFAULT_TIMEOUT;
> +	wdt->wdog.parent = &device->dev;
> +
> +	ret = watchdog_register_device(&wdt->wdog);
> +	if (ret) {
> +		dev_err(&device->dev, "failed to register watchdog\n");
> +		return ret;
> +	}
> +
> +	/* Switch from boot mode to user mode */
> +	outb(NIWD_CONTROL_RESET | NIWD_CONTROL_MODE,
> +	     wdt->io_base + NIWD_CONTROL);
> +
> +	dev_info(&wdt->acpi_device->dev, "IO range 0x%04X-0x%04X\n",
> +		 wdt->io_base, wdt->io_base + wdt->io_size - 1);

dev_dbg(), please.  Booting is loud enough.

[..]
> +static struct acpi_driver ni9x3x_wdt_acpi_driver = {
> +	.name = NI9X3X_WDT_NAME,
> +	.ids = ni9x3x_wdt_device_ids,
> +	.ops = {
> +		.add = ni9x3x_wdt_acpi_add,
> +		.remove = ni9x3x_wdt_acpi_remove,
> +		},
> +};
> +
> +static int __init ni9x3x_wdt_init(void)
> +{
> +	return acpi_bus_register_driver(&ni9x3x_wdt_acpi_driver);
> +}
> +
> +static void __exit ni9x3x_wdt_exit(void)
> +{
> +	acpi_bus_unregister_driver(&ni9x3x_wdt_acpi_driver);
> +}
> +
> +module_init(ni9x3x_wdt_init);
> +module_exit(ni9x3x_wdt_exit);

module_acpi_driver(ni9x3x_wdt_acpi_driver)?

> +
> +MODULE_DEVICE_TABLE(acpi, ni9x3x_wdt_device_ids);

Suggestion: move this right below the table.

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux