linux/drivers/watchdog/imgpdc_wdt.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Imagination Technologies PowerDown Controller Watchdog Timer.
 *
 * Copyright (c) 2014 Imagination Technologies Ltd.
 *
 * Based on drivers/watchdog/sunxi_wdt.c Copyright (c) 2013 Carlo Caione
 *                                                     2012 Henrik Nordstrom
 *
 * Notes
 * -----
 * The timeout value is rounded to the next power of two clock cycles.
 * This is configured using the PDC_WDT_CONFIG register, according to this
 * formula:
 *
 *     timeout = 2^(delay + 1) clock cycles
 *
 * Where 'delay' is the value written in PDC_WDT_CONFIG register.
 *
 * Therefore, the hardware only allows to program watchdog timeouts, expressed
 * as a power of two number of watchdog clock cycles. The current implementation
 * guarantees that the actual watchdog timeout will be _at least_ the value
 * programmed in the imgpdg_wdt driver.
 *
 * The following table shows how the user-configured timeout relates
 * to the actual hardware timeout (watchdog clock @ 40000 Hz):
 *
 * input timeout | WD_DELAY | actual timeout
 * -----------------------------------
 *      10       |   18     |  13 seconds
 *      20       |   19     |  26 seconds
 *      30       |   20     |  52 seconds
 *      60       |   21     |  104 seconds
 *
 * Albeit coarse, this granularity would suffice most watchdog uses.
 * If the platform allows it, the user should be able to change the watchdog
 * clock rate and achieve a finer timeout granularity.
 */

#include <linux/clk.h>
#include <linux/io.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/watchdog.h>

/* registers */
#define PDC_WDT_SOFT_RESET
#define PDC_WDT_CONFIG
  #define PDC_WDT_CONFIG_ENABLE
  #define PDC_WDT_CONFIG_DELAY_MASK

#define PDC_WDT_TICKLE1
#define PDC_WDT_TICKLE1_MAGIC
#define PDC_WDT_TICKLE2
#define PDC_WDT_TICKLE2_MAGIC

#define PDC_WDT_TICKLE_STATUS_MASK
#define PDC_WDT_TICKLE_STATUS_SHIFT
#define PDC_WDT_TICKLE_STATUS_HRESET
#define PDC_WDT_TICKLE_STATUS_TIMEOUT
#define PDC_WDT_TICKLE_STATUS_TICKLE
#define PDC_WDT_TICKLE_STATUS_SRESET
#define PDC_WDT_TICKLE_STATUS_USER

/* Timeout values are in seconds */
#define PDC_WDT_MIN_TIMEOUT
#define PDC_WDT_DEF_TIMEOUT

static int heartbeat;
module_param(heartbeat, int, 0);
MODULE_PARM_DESC();

static bool nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, bool, 0);
MODULE_PARM_DESC();

struct pdc_wdt_dev {};

static int pdc_wdt_keepalive(struct watchdog_device *wdt_dev)
{}

static int pdc_wdt_stop(struct watchdog_device *wdt_dev)
{}

static void __pdc_wdt_set_timeout(struct pdc_wdt_dev *wdt)
{}

static int pdc_wdt_set_timeout(struct watchdog_device *wdt_dev,
			       unsigned int new_timeout)
{}

/* Start the watchdog timer (delay should already be set) */
static int pdc_wdt_start(struct watchdog_device *wdt_dev)
{}

static int pdc_wdt_restart(struct watchdog_device *wdt_dev,
			   unsigned long action, void *data)
{}

static const struct watchdog_info pdc_wdt_info =;

static const struct watchdog_ops pdc_wdt_ops =;

static int pdc_wdt_probe(struct platform_device *pdev)
{}

static const struct of_device_id pdc_wdt_match[] =;
MODULE_DEVICE_TABLE(of, pdc_wdt_match);

static struct platform_driver pdc_wdt_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();