Home | History | Annotate | Line # | Download | only in xscale
ixp425_wdog.c revision 1.1.54.1
      1  1.1.54.1  yamt /*	$NetBSD: ixp425_wdog.c,v 1.1.54.1 2008/05/18 12:31:41 yamt Exp $	*/
      2       1.1   scw 
      3       1.1   scw /*-
      4       1.1   scw  * Copyright (c) 2006 The NetBSD Foundation, Inc.
      5       1.1   scw  * All rights reserved.
      6       1.1   scw  *
      7       1.1   scw  * This code is derived from software contributed to The NetBSD Foundation
      8       1.1   scw  * by Steve C. Woodford.
      9       1.1   scw  *
     10       1.1   scw  * Redistribution and use in source and binary forms, with or without
     11       1.1   scw  * modification, are permitted provided that the following conditions
     12       1.1   scw  * are met:
     13       1.1   scw  * 1. Redistributions of source code must retain the above copyright
     14       1.1   scw  *    notice, this list of conditions and the following disclaimer.
     15       1.1   scw  * 2. Redistributions in binary form must reproduce the above copyright
     16       1.1   scw  *    notice, this list of conditions and the following disclaimer in the
     17       1.1   scw  *    documentation and/or other materials provided with the distribution.
     18       1.1   scw  *
     19       1.1   scw  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20       1.1   scw  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21       1.1   scw  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22       1.1   scw  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23       1.1   scw  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24       1.1   scw  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25       1.1   scw  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26       1.1   scw  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27       1.1   scw  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28       1.1   scw  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29       1.1   scw  * POSSIBILITY OF SUCH DAMAGE.
     30       1.1   scw  */
     31       1.1   scw 
     32       1.1   scw #include "opt_ddb.h"
     33       1.1   scw 
     34       1.1   scw #include <sys/cdefs.h>
     35  1.1.54.1  yamt __KERNEL_RCSID(0, "$NetBSD: ixp425_wdog.c,v 1.1.54.1 2008/05/18 12:31:41 yamt Exp $");
     36       1.1   scw 
     37       1.1   scw #include <sys/systm.h>
     38       1.1   scw #include <sys/param.h>
     39       1.1   scw #include <sys/kernel.h>
     40       1.1   scw #include <sys/device.h>
     41       1.1   scw #include <sys/wdog.h>
     42       1.1   scw 
     43       1.1   scw #include <dev/clock_subr.h>
     44       1.1   scw #include <dev/sysmon/sysmonvar.h>
     45       1.1   scw 
     46       1.1   scw #include <machine/intr.h>
     47       1.1   scw #include <machine/bus.h>
     48       1.1   scw 
     49       1.1   scw #include <arm/xscale/ixp425reg.h>
     50       1.1   scw #include <arm/xscale/ixp425var.h>
     51       1.1   scw #include <arm/xscale/ixp425_sipvar.h>
     52       1.1   scw 
     53       1.1   scw #ifdef DDB
     54       1.1   scw #include <machine/db_machdep.h>
     55       1.1   scw #include <ddb/db_extern.h>
     56       1.1   scw #endif
     57       1.1   scw 
     58       1.1   scw struct ixpdog_softc {
     59       1.1   scw 	struct device sc_dev;
     60       1.1   scw 	struct sysmon_wdog sc_smw;
     61       1.1   scw 	bus_space_tag_t sc_bust;
     62       1.1   scw 	bus_space_handle_t sc_bush;
     63       1.1   scw 	uint32_t sc_preset;
     64       1.1   scw 	int sc_armed;
     65       1.1   scw };
     66       1.1   scw 
     67       1.1   scw #define	IXPDOG_DEFAULT_PERIOD	8
     68       1.1   scw #ifndef	IXP425_CLOCK_FREQ
     69       1.1   scw #define	IXPDOG_COUNTS_PER_SEC	66666600
     70       1.1   scw #else
     71       1.1   scw #define	IXPDOG_COUNTS_PER_SEC	IXP425_CLOCK_FREQ
     72       1.1   scw #endif
     73       1.1   scw 
     74       1.1   scw static int ixpdog_match(struct device *, struct cfdata *, void *);
     75       1.1   scw static void ixpdog_attach(struct device *, struct device *, void *);
     76       1.1   scw 
     77       1.1   scw CFATTACH_DECL(ixpdog, sizeof(struct ixpdog_softc),
     78       1.1   scw     ixpdog_match, ixpdog_attach, NULL, NULL);
     79       1.1   scw 
     80       1.1   scw static void ixpdog_control(struct ixpdog_softc *, int);
     81       1.1   scw static int ixpdog_tickle(struct sysmon_wdog *);
     82       1.1   scw static int ixpdog_setmode(struct sysmon_wdog *);
     83       1.1   scw 
     84       1.1   scw #ifdef DDB
     85       1.1   scw static struct ixpdog_softc *ixpdog_softc;
     86       1.1   scw static void ixpdog_ddb_trap(int);
     87       1.1   scw #endif
     88       1.1   scw 
     89       1.1   scw 
     90       1.1   scw static int
     91       1.1   scw ixpdog_match(struct device *parent, struct cfdata *match, void *arg)
     92       1.1   scw {
     93       1.1   scw 	struct ixpsip_attach_args *sa = arg;
     94       1.1   scw 
     95       1.1   scw 	return (sa->sa_addr == IXP425_OST_WDOG_HWBASE);
     96       1.1   scw }
     97       1.1   scw 
     98       1.1   scw static void
     99       1.1   scw ixpdog_attach(struct device *parent, struct device *self, void *arg)
    100       1.1   scw {
    101       1.1   scw 	struct ixpdog_softc *sc = (struct ixpdog_softc *)self;
    102       1.1   scw 	struct ixpsip_attach_args *sa = arg;
    103       1.1   scw 
    104       1.1   scw 	aprint_naive("\n");
    105       1.1   scw 	aprint_normal(": Watchdog Timer\n");
    106       1.1   scw 
    107       1.1   scw 	sc->sc_bust = sa->sa_iot;
    108       1.1   scw 
    109       1.1   scw 	if (bus_space_map(sc->sc_bust, sa->sa_addr, IXP425_OST_WDOG_SIZE, 0,
    110       1.1   scw 	    &sc->sc_bush)) {
    111       1.1   scw 		aprint_error("%s: Failed to map watchdog registers\n",
    112       1.1   scw 		    sc->sc_dev.dv_xname);
    113       1.1   scw 		return;
    114       1.1   scw 	}
    115       1.1   scw 
    116       1.1   scw 	sc->sc_preset = IXPDOG_COUNTS_PER_SEC * hz * IXPDOG_DEFAULT_PERIOD;
    117       1.1   scw 	sc->sc_armed = 0;
    118       1.1   scw 	ixpdog_control(sc, 0);
    119       1.1   scw 
    120       1.1   scw #ifdef DDB
    121       1.1   scw 	ixpdog_softc = sc;
    122       1.1   scw 	db_trap_callback = ixpdog_ddb_trap;
    123       1.1   scw #endif
    124       1.1   scw 
    125       1.1   scw 	sc->sc_smw.smw_name = sc->sc_dev.dv_xname;
    126       1.1   scw 	sc->sc_smw.smw_cookie = sc;
    127       1.1   scw 	sc->sc_smw.smw_setmode = ixpdog_setmode;
    128       1.1   scw 	sc->sc_smw.smw_tickle = ixpdog_tickle;
    129       1.1   scw 	sc->sc_smw.smw_period = IXPDOG_DEFAULT_PERIOD;
    130       1.1   scw 
    131       1.1   scw 	if (sysmon_wdog_register(&sc->sc_smw) != 0)
    132       1.1   scw 		aprint_error("%s: unable to register watchdog with sysmon\n",
    133       1.1   scw 		    sc->sc_dev.dv_xname);
    134       1.1   scw }
    135       1.1   scw 
    136       1.1   scw static void
    137       1.1   scw ixpdog_control(struct ixpdog_softc *sc, int enable)
    138       1.1   scw {
    139       1.1   scw 	uint32_t reg;
    140       1.1   scw 	int s;
    141       1.1   scw 
    142       1.1   scw 	s = disable_interrupts(I32_bit);
    143       1.1   scw 	bus_space_write_2(sc->sc_bust, sc->sc_bush, IXP425_OST_WDOG_KEY,
    144       1.1   scw 	    OST_WDOG_KEY_MAJICK);
    145       1.1   scw 	reg = bus_space_read_4(sc->sc_bust, sc->sc_bush, IXP425_OST_WDOG_ENAB);
    146       1.1   scw 
    147       1.1   scw 	if (!enable)
    148       1.1   scw 		reg &= ~(OST_WDOG_ENAB_CNT_ENA | OST_WDOG_ENAB_RST_ENA);
    149       1.1   scw 	else {
    150       1.1   scw 		bus_space_write_4(sc->sc_bust, sc->sc_bush, IXP425_OST_WDOG,
    151       1.1   scw 		    sc->sc_preset);
    152       1.1   scw 		reg |= OST_WDOG_ENAB_CNT_ENA | OST_WDOG_ENAB_RST_ENA;
    153       1.1   scw 	}
    154       1.1   scw 
    155       1.1   scw 	bus_space_write_4(sc->sc_bust, sc->sc_bush, IXP425_OST_WDOG_ENAB, reg);
    156       1.1   scw 	bus_space_write_2(sc->sc_bust, sc->sc_bush, IXP425_OST_WDOG_KEY,
    157       1.1   scw 	    ~OST_WDOG_KEY_MAJICK);
    158       1.1   scw 	restore_interrupts(s);
    159       1.1   scw }
    160       1.1   scw 
    161       1.1   scw static int
    162       1.1   scw ixpdog_tickle(struct sysmon_wdog *smw)
    163       1.1   scw {
    164       1.1   scw 	struct ixpdog_softc *sc = smw->smw_cookie;
    165       1.1   scw 	int s;
    166       1.1   scw 
    167       1.1   scw 	s = disable_interrupts(I32_bit);
    168       1.1   scw 	bus_space_write_2(sc->sc_bust, sc->sc_bush, IXP425_OST_WDOG_KEY,
    169       1.1   scw 	    OST_WDOG_KEY_MAJICK);
    170       1.1   scw 	bus_space_write_4(sc->sc_bust, sc->sc_bush, IXP425_OST_WDOG,
    171       1.1   scw 	    sc->sc_preset);
    172       1.1   scw 	bus_space_write_2(sc->sc_bust, sc->sc_bush, IXP425_OST_WDOG_KEY,
    173       1.1   scw 	    ~OST_WDOG_KEY_MAJICK);
    174       1.1   scw 	restore_interrupts(s);
    175       1.1   scw 
    176       1.1   scw 	return (0);
    177       1.1   scw }
    178       1.1   scw 
    179       1.1   scw static int
    180       1.1   scw ixpdog_setmode(struct sysmon_wdog *smw)
    181       1.1   scw {
    182       1.1   scw 	struct ixpdog_softc *sc = smw->smw_cookie;
    183       1.1   scw 
    184       1.1   scw 	if ((smw->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED)
    185       1.1   scw 		sc->sc_armed = 0;
    186       1.1   scw 	else {
    187       1.1   scw 		if (smw->smw_period == WDOG_PERIOD_DEFAULT)
    188       1.1   scw 			smw->smw_period = IXPDOG_DEFAULT_PERIOD;
    189       1.1   scw 		sc->sc_preset = IXPDOG_COUNTS_PER_SEC * hz * smw->smw_period;
    190       1.1   scw 		if (sc->sc_preset < (IXPDOG_COUNTS_PER_SEC * hz) ||
    191       1.1   scw 		    sc->sc_preset < smw->smw_period)
    192       1.1   scw 			return (EOPNOTSUPP);
    193       1.1   scw 
    194       1.1   scw 		sc->sc_armed = 1;
    195       1.1   scw 	}
    196       1.1   scw 
    197       1.1   scw 	ixpdog_control(sc, sc->sc_armed);
    198       1.1   scw 
    199       1.1   scw 	return (0);
    200       1.1   scw }
    201       1.1   scw 
    202       1.1   scw #ifdef DDB
    203       1.1   scw static void
    204       1.1   scw ixpdog_ddb_trap(int enter)
    205       1.1   scw {
    206       1.1   scw 	struct ixpdog_softc *sc;
    207       1.1   scw 
    208       1.1   scw 	if ((sc = ixpdog_softc) == NULL)
    209       1.1   scw 		return;
    210       1.1   scw 
    211       1.1   scw 	sc->sc_armed += enter ? (-1) : 1;
    212       1.1   scw 
    213       1.1   scw 	if ((enter && sc->sc_armed == 0) || (!enter && sc->sc_armed == 1))
    214       1.1   scw 		ixpdog_control(sc, sc->sc_armed);
    215       1.1   scw }
    216       1.1   scw #endif
    217