1/* $NetBSD: i80321_wdog.c,v 1.6 2003/07/15 00:24:54 lukem Exp $ */ 2 3/*- 4 * Copyright (c) 2005 Olivier Houchard 5 * Copyright (c) 2002 Wasabi Systems, Inc. 6 * All rights reserved. 7 * 8 * Written by Jason R. Thorpe for Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed for the NetBSD Project by 21 * Wasabi Systems, Inc. 22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse 23 * or promote products derived from this software without specific prior 24 * written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39/* 40 * Watchdog timer support for the Intel i80321 I/O processor. 41 */ 42 43#include <sys/cdefs.h> 44__FBSDID("$FreeBSD$"); 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/watchdog.h> 49#include <sys/bus.h> 50#include <sys/kernel.h> 51#include <sys/module.h> 52 53#include <machine/bus.h> 54#include <machine/cpufunc.h> 55#include <machine/machdep.h> 56 57#include <arm/xscale/i80321/i80321reg.h> 58#include <arm/xscale/i80321/i80321var.h> 59 60 61struct iopwdog_softc { 62 device_t dev; 63 int armed; 64 int wdog_period; 65}; 66 67static __inline void 68wdtcr_write(uint32_t val) 69{ 70 71#ifdef CPU_XSCALE_81342 72 __asm __volatile("mcr p6, 0, %0, c7, c9, 0" 73#else 74 __asm __volatile("mcr p6, 0, %0, c7, c1, 0" 75#endif 76 : 77 : "r" (val)); 78} 79 80static void 81iopwdog_tickle(void *arg) 82{ 83 struct iopwdog_softc *sc = arg; 84 85 if (!sc->armed) 86 return; 87 wdtcr_write(WDTCR_ENABLE1); 88 wdtcr_write(WDTCR_ENABLE2); 89} 90 91static int 92iopwdog_probe(device_t dev) 93{ 94 struct iopwdog_softc *sc = device_get_softc(dev); 95 char buf[128]; 96 97 /* 98 * XXX Should compute the period based on processor speed. 99 * For a 600MHz XScale core, the wdog must be tickled approx. 100 * every 7 seconds. 101 */ 102 103 sc->wdog_period = 7; 104 sprintf(buf, "i80321 Watchdog, must be tickled every %d seconds", 105 sc->wdog_period); 106 device_set_desc_copy(dev, buf); 107 108 return (0); 109} 110 111static void 112iopwdog_watchdog_fn(void *private, u_int cmd, int *error) 113{ 114 struct iopwdog_softc *sc = private; 115 116 cmd &= WD_INTERVAL; 117 if (cmd > 0 && cmd <= 63 118 && (uint64_t)1<<cmd <= (uint64_t)sc->wdog_period * 1000000000) { 119 /* Valid value -> Enable watchdog */ 120 iopwdog_tickle(sc); 121 sc->armed = 1; 122 *error = 0; 123 } else { 124 /* Can't disable this watchdog! */ 125 if (sc->armed) 126 *error = EOPNOTSUPP; 127 } 128} 129 130static int 131iopwdog_attach(device_t dev) 132{ 133 struct iopwdog_softc *sc = device_get_softc(dev); 134 135 sc->dev = dev; 136 sc->armed = 0; 137 EVENTHANDLER_REGISTER(watchdog_list, iopwdog_watchdog_fn, sc, 0); 138 return (0); 139} 140 141static device_method_t iopwdog_methods[] = { 142 DEVMETHOD(device_probe, iopwdog_probe), 143 DEVMETHOD(device_attach, iopwdog_attach), 144 {0, 0}, 145}; 146 147static driver_t iopwdog_driver = { 148 "iopwdog", 149 iopwdog_methods, 150 sizeof(struct iopwdog_softc), 151}; 152static devclass_t iopwdog_devclass; 153 154DRIVER_MODULE(iopwdog, iq, iopwdog_driver, iopwdog_devclass, 0, 0); 155