/** * cdns_wdt_start - Enable and start the watchdog. * * @wdd: watchdog device * * The counter value is calculated according to the formula: * calculated count = (timeout * clock) / prescaler + 1. * The calculated count is divided by 0x1000 to obtain the field value * to write to counter control register. * Clears the contents of prescaler and counter reset value. Sets the * prescaler to 4096 and the calculated count and access key * to write to CCR Register. * Sets the WDT (WDEN bit) and either the Reset signal(RSTEN bit) * or Interrupt signal(IRQEN) with a specified cycles and the access * key to write to ZMR Register. * * Return: always 0 */ static int cdns_wdt_start(struct watchdog_device *wdd) { struct cdns_wdt *wdt = watchdog_get_drvdata(wdd); unsigned int data = 0; unsigned short count; unsigned long clock_f = clk_get_rate(wdt->clk); /* * Counter value divisor to obtain the value of * counter reset to be written to control register. */ count = (wdd->timeout * (clock_f / wdt->prescaler)) / CDNS_WDT_COUNTER_VALUE_DIVISOR + 1; /* Check for boundary conditions of counter value */ if (count > CDNS_WDT_COUNTER_MAX) count = CDNS_WDT_COUNTER_MAX; spin_lock(&wdt->io_lock); cdns_wdt_writereg(wdt->regs + CDNS_WDT_ZMR_OFFSET, CDNS_WDT_ZMR_ZKEY_VAL); /* Shift the count value to correct bit positions */ count = (count << 2) & CDNS_WDT_CCR_CRV_MASK; /* Write counter access key first to be able write to register */ data = count | CDNS_WDT_REGISTER_ACCESS_KEY | wdt->ctrl_clksel; cdns_wdt_writereg(wdt->regs + CDNS_WDT_CCR_OFFSET, data); data = CDNS_WDT_ZMR_WDEN_MASK | CDNS_WDT_ZMR_RSTLEN_16 | CDNS_WDT_ZMR_ZKEY_VAL; /* Reset on timeout if specified in device tree. */ if (wdt->rst) { data |= CDNS_WDT_ZMR_RSTEN_MASK; data &= ~CDNS_WDT_ZMR_IRQEN_MASK; } else { data &= ~CDNS_WDT_ZMR_RSTEN_MASK; data |= CDNS_WDT_ZMR_IRQEN_MASK; } cdns_wdt_writereg(wdt->regs + CDNS_WDT_ZMR_OFFSET, data); spin_unlock(&wdt->io_lock); cdns_wdt_writereg(wdt->regs + CDNS_WDT_RESTART_OFFSET, CDNS_WDT_RESTART_KEY); return 0; }
/** * cdns_wdt_reload - Reload the watchdog timer (i.e. pat the watchdog). * * @wdd: watchdog device * * Write the restart key value (0x00001999) to the restart register. * * Return: always 0 */ static int cdns_wdt_reload(struct watchdog_device *wdd) { struct cdns_wdt *wdt = watchdog_get_drvdata(wdd); spin_lock(&wdt->io_lock); cdns_wdt_writereg(wdt, CDNS_WDT_RESTART_OFFSET, CDNS_WDT_RESTART_KEY); spin_unlock(&wdt->io_lock); return 0; }
/** * cdns_wdt_stop - Stop the watchdog. * * @wdd: watchdog device * * Read the contents of the ZMR register, clear the WDEN bit * in the register and set the access key for successful write. * * Return: always 0 */ static int cdns_wdt_stop(struct watchdog_device *wdd) { struct cdns_wdt *wdt = watchdog_get_drvdata(wdd); spin_lock(&wdt->io_lock); cdns_wdt_writereg(wdt, CDNS_WDT_ZMR_OFFSET, CDNS_WDT_ZMR_ZKEY_VAL & (~CDNS_WDT_ZMR_WDEN_MASK)); spin_unlock(&wdt->io_lock); return 0; }