1140303Scognet/* $NetBSD: i80321_wdog.c,v 1.6 2003/07/15 00:24:54 lukem Exp $ */ 2140303Scognet 3140307Scognet/*- 4140303Scognet * Copyright (c) 2005 Olivier Houchard 5140303Scognet * Copyright (c) 2002 Wasabi Systems, Inc. 6140303Scognet * All rights reserved. 7140303Scognet * 8140303Scognet * Written by Jason R. Thorpe for Wasabi Systems, Inc. 9140303Scognet * 10140303Scognet * Redistribution and use in source and binary forms, with or without 11140303Scognet * modification, are permitted provided that the following conditions 12140303Scognet * are met: 13140303Scognet * 1. Redistributions of source code must retain the above copyright 14140303Scognet * notice, this list of conditions and the following disclaimer. 15140303Scognet * 2. Redistributions in binary form must reproduce the above copyright 16140303Scognet * notice, this list of conditions and the following disclaimer in the 17140303Scognet * documentation and/or other materials provided with the distribution. 18140303Scognet * 3. All advertising materials mentioning features or use of this software 19140303Scognet * must display the following acknowledgement: 20140303Scognet * This product includes software developed for the NetBSD Project by 21140303Scognet * Wasabi Systems, Inc. 22140303Scognet * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23140303Scognet * or promote products derived from this software without specific prior 24140303Scognet * written permission. 25140303Scognet * 26140303Scognet * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27140303Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28140303Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29140303Scognet * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30140303Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31140303Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32140303Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33140303Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34140303Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35140303Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36140303Scognet * POSSIBILITY OF SUCH DAMAGE. 37140303Scognet */ 38140303Scognet 39140303Scognet/* 40140303Scognet * Watchdog timer support for the Intel i80321 I/O processor. 41140303Scognet */ 42140303Scognet 43140303Scognet#include <sys/cdefs.h> 44140303Scognet__FBSDID("$FreeBSD$"); 45140303Scognet 46140303Scognet#include <sys/param.h> 47140303Scognet#include <sys/systm.h> 48140303Scognet#include <sys/watchdog.h> 49140303Scognet#include <sys/bus.h> 50140303Scognet#include <sys/kernel.h> 51140303Scognet#include <sys/module.h> 52140303Scognet 53140303Scognet#include <machine/bus.h> 54140303Scognet#include <machine/cpufunc.h> 55140303Scognet#include <machine/machdep.h> 56140303Scognet 57140303Scognet#include <arm/xscale/i80321/i80321reg.h> 58140303Scognet#include <arm/xscale/i80321/i80321var.h> 59140303Scognet 60140303Scognet 61140303Scognetstruct iopwdog_softc { 62140303Scognet device_t dev; 63140303Scognet int armed; 64140303Scognet int wdog_period; 65140303Scognet}; 66140303Scognet 67140303Scognetstatic __inline void 68140303Scognetwdtcr_write(uint32_t val) 69140303Scognet{ 70140303Scognet 71171627Scognet#ifdef CPU_XSCALE_81342 72171627Scognet __asm __volatile("mcr p6, 0, %0, c7, c9, 0" 73171627Scognet#else 74140303Scognet __asm __volatile("mcr p6, 0, %0, c7, c1, 0" 75171627Scognet#endif 76140303Scognet : 77140303Scognet : "r" (val)); 78140303Scognet} 79140303Scognet 80140303Scognetstatic void 81140303Scognetiopwdog_tickle(void *arg) 82140303Scognet{ 83140303Scognet struct iopwdog_softc *sc = arg; 84140303Scognet 85140303Scognet if (!sc->armed) 86140303Scognet return; 87140303Scognet wdtcr_write(WDTCR_ENABLE1); 88140303Scognet wdtcr_write(WDTCR_ENABLE2); 89140303Scognet} 90140303Scognet 91140303Scognetstatic int 92140303Scognetiopwdog_probe(device_t dev) 93140303Scognet{ 94140303Scognet struct iopwdog_softc *sc = device_get_softc(dev); 95140303Scognet char buf[128]; 96140303Scognet 97140303Scognet /* 98140303Scognet * XXX Should compute the period based on processor speed. 99140303Scognet * For a 600MHz XScale core, the wdog must be tickled approx. 100140303Scognet * every 7 seconds. 101140303Scognet */ 102140303Scognet 103140303Scognet sc->wdog_period = 7; 104140303Scognet sprintf(buf, "i80321 Watchdog, must be tickled every %d seconds", 105140303Scognet sc->wdog_period); 106140303Scognet device_set_desc_copy(dev, buf); 107140303Scognet 108140303Scognet return (0); 109140303Scognet} 110140303Scognet 111140303Scognetstatic void 112140303Scognetiopwdog_watchdog_fn(void *private, u_int cmd, int *error) 113140303Scognet{ 114140303Scognet struct iopwdog_softc *sc = private; 115140303Scognet 116165260Sn_hibma cmd &= WD_INTERVAL; 117165260Sn_hibma if (cmd > 0 && cmd <= 63 118167950Sn_hibma && (uint64_t)1<<cmd <= (uint64_t)sc->wdog_period * 1000000000) { 119165260Sn_hibma /* Valid value -> Enable watchdog */ 120165260Sn_hibma iopwdog_tickle(sc); 121165260Sn_hibma sc->armed = 1; 122165260Sn_hibma *error = 0; 123165260Sn_hibma } else { 124167950Sn_hibma /* Can't disable this watchdog! */ 125165260Sn_hibma if (sc->armed) 126165260Sn_hibma *error = EOPNOTSUPP; 127165260Sn_hibma } 128140303Scognet} 129140303Scognet 130140303Scognetstatic int 131140303Scognetiopwdog_attach(device_t dev) 132140303Scognet{ 133140303Scognet struct iopwdog_softc *sc = device_get_softc(dev); 134140303Scognet 135140303Scognet sc->dev = dev; 136140303Scognet sc->armed = 0; 137140303Scognet EVENTHANDLER_REGISTER(watchdog_list, iopwdog_watchdog_fn, sc, 0); 138140303Scognet return (0); 139140303Scognet} 140140303Scognet 141140303Scognetstatic device_method_t iopwdog_methods[] = { 142140303Scognet DEVMETHOD(device_probe, iopwdog_probe), 143140303Scognet DEVMETHOD(device_attach, iopwdog_attach), 144140303Scognet {0, 0}, 145140303Scognet}; 146140303Scognet 147140303Scognetstatic driver_t iopwdog_driver = { 148140303Scognet "iopwdog", 149140303Scognet iopwdog_methods, 150140303Scognet sizeof(struct iopwdog_softc), 151140303Scognet}; 152140303Scognetstatic devclass_t iopwdog_devclass; 153140303Scognet 154140303ScognetDRIVER_MODULE(iopwdog, iq, iopwdog_driver, iopwdog_devclass, 0, 0); 155