/* * There are four counters that can be used for watchdog on Armada 37xx. * The addresses for counter control registers are register base plus ID*0x10, * where ID is 0, 1, 2 or 3. * * In this driver we use IDs 0 and 1. Counter ID 1 is used as watchdog counter, * while counter ID 0 is used to implement pinging the watchdog: counter ID 1 is * set to restart counting from initial value on counter ID 0 end count event. * Pinging is done by forcing immediate end count event on counter ID 0. * If only one counter was used, pinging would have to be implemented by * disabling and enabling the counter, leaving the system in a vulnerable state * for a (really) short period of time. * * Counters ID 2 and 3 are enabled by default even before U-Boot loads, * therefore this driver does not provide a way to use them, eg. by setting a * property in device tree.
*/
static u64 get_counter_value(struct armada_37xx_watchdog *dev, int id)
{
u64 val;
/* * when low is read, high is latched into flip-flops so that it can be * read consistently without using software debouncing
*/
val = readl(dev->reg + CNTR_COUNT_LOW(id));
val |= ((u64)readl(dev->reg + CNTR_COUNT_HIGH(id))) << 32;
/* * Compute the timeout in clock rate. We use smallest possible * prescaler, which divides the clock rate by 2 * (CNTR_CTRL_PRESCALE_MIN).
*/
dev->timeout = (u64)dev->clk_rate * timeout;
do_div(dev->timeout, CNTR_CTRL_PRESCALE_MIN);
/* init counter 0 as retrigger counter for counter 1 */
init_counter(dev, CNTR_ID_RETRIGGER, CNTR_CTRL_MODE_ONESHOT, 0);
set_counter_value(dev, CNTR_ID_RETRIGGER, 0);
/* init counter 1 to be retriggerable by counter 0 end count */
init_counter(dev, CNTR_ID_WDOG, CNTR_CTRL_MODE_HWSIG,
CNTR_CTRL_TRIG_SRC_PREV_CNTR);
set_counter_value(dev, CNTR_ID_WDOG, dev->timeout);
dev->clk_rate = clk_get_rate(dev->clk); if (!dev->clk_rate) return -EINVAL;
/* * Since the timeout in seconds is given as 32 bit unsigned int, and * the counters hold 64 bit values, even after multiplication by clock * rate the counter can hold timeout of UINT_MAX seconds.
*/
dev->wdt.min_timeout = 1;
dev->wdt.max_timeout = UINT_MAX;
dev->wdt.parent = &pdev->dev;
/* default value, possibly override by module parameter or dtb */
dev->wdt.timeout = WATCHDOG_TIMEOUT;
watchdog_init_timeout(&dev->wdt, timeout, &pdev->dev);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.