xref: /openbsd/sys/dev/pci/tcpcib.c (revision 8d2c75e4)
1*8d2c75e4Smpi /*	$OpenBSD: tcpcib.c,v 1.9 2022/03/11 18:00:52 mpi Exp $	*/
2f6ad04e6Sjsg 
3f6ad04e6Sjsg /*
4f6ad04e6Sjsg  * Copyright (c) 2012 Matt Dainty <matt@bodgit-n-scarper.com>
5f6ad04e6Sjsg  *
6f6ad04e6Sjsg  * Permission to use, copy, modify, and distribute this software for any
7f6ad04e6Sjsg  * purpose with or without fee is hereby granted, provided that the above
8f6ad04e6Sjsg  * copyright notice and this permission notice appear in all copies.
9f6ad04e6Sjsg  *
10f6ad04e6Sjsg  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11f6ad04e6Sjsg  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12f6ad04e6Sjsg  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13f6ad04e6Sjsg  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14f6ad04e6Sjsg  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
15f6ad04e6Sjsg  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16f6ad04e6Sjsg  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17f6ad04e6Sjsg  */
18f6ad04e6Sjsg 
19f6ad04e6Sjsg /*
2018078679Skettenis  * Intel Atom E600 series LPC bridge also containing HPET and watchdog
21f6ad04e6Sjsg  */
22f6ad04e6Sjsg 
23f6ad04e6Sjsg #include <sys/param.h>
24f6ad04e6Sjsg #include <sys/systm.h>
25f6ad04e6Sjsg #include <sys/device.h>
2618078679Skettenis #include <sys/timetc.h>
27f6ad04e6Sjsg 
28f6ad04e6Sjsg #include <machine/bus.h>
29f6ad04e6Sjsg 
30f6ad04e6Sjsg #include <dev/pci/pcireg.h>
31f6ad04e6Sjsg #include <dev/pci/pcivar.h>
32f6ad04e6Sjsg #include <dev/pci/pcidevs.h>
33f6ad04e6Sjsg 
34f6ad04e6Sjsg #define	E600_LPC_SMBA		0x40		/* SMBus Base Address */
35f6ad04e6Sjsg #define	E600_LPC_GBA		0x44		/* GPIO Base Address */
36f6ad04e6Sjsg #define	E600_LPC_WDTBA		0x84		/* WDT Base Address */
37f6ad04e6Sjsg 
38f6ad04e6Sjsg #define	E600_WDT_SIZE		64		/* I/O region size */
39f6ad04e6Sjsg #define	E600_WDT_PV1		0x00		/* Preload Value 1 Register */
40f6ad04e6Sjsg #define	E600_WDT_PV2		0x04		/* Preload Value 2 Register */
41f6ad04e6Sjsg #define	E600_WDT_RR0		0x0c		/* Reload Register 0 */
42f6ad04e6Sjsg #define	E600_WDT_RR1		0x0d		/* Reload Register 1 */
43f6ad04e6Sjsg #define	E600_WDT_RR1_RELOAD	(1 << 0)	/* WDT Reload Flag */
44f6ad04e6Sjsg #define	E600_WDT_RR1_TIMEOUT	(1 << 1)	/* WDT Timeout Flag */
45f6ad04e6Sjsg #define	E600_WDT_WDTCR		0x10		/* WDT Configuration Register */
46f6ad04e6Sjsg #define	E600_WDT_WDTCR_PRE	(1 << 2)	/* WDT Prescalar Select */
47f6ad04e6Sjsg #define	E600_WDT_WDTCR_RESET	(1 << 3)	/* WDT Reset Select */
48f6ad04e6Sjsg #define	E600_WDT_WDTCR_ENABLE	(1 << 4)	/* WDT Reset Enable */
49f6ad04e6Sjsg #define	E600_WDT_WDTCR_TIMEOUT	(1 << 5)	/* WDT Timeout Output Enable */
50f6ad04e6Sjsg #define	E600_WDT_DCR		0x14		/* Down Counter Register */
51f6ad04e6Sjsg #define	E600_WDT_WDTLR		0x18		/* WDT Lock Register */
52f6ad04e6Sjsg #define	E600_WDT_WDTLR_LOCK	(1 << 0)	/* Watchdog Timer Lock */
53f6ad04e6Sjsg #define	E600_WDT_WDTLR_ENABLE	(1 << 1)	/* Watchdog Timer Enable */
54f6ad04e6Sjsg #define	E600_WDT_WDTLR_TIMEOUT	(1 << 2)	/* WDT Timeout Configuration */
55f6ad04e6Sjsg 
5618078679Skettenis #define	E600_HPET_BASE		0xfed00000	/* HPET register base */
5718078679Skettenis #define	E600_HPET_SIZE		0x00000400	/* HPET register size */
5818078679Skettenis 
5918078679Skettenis #define	E600_HPET_GCID		0x000		/* Capabilities and ID */
6018078679Skettenis #define	E600_HPET_GCID_WIDTH	(1 << 13)	/* Counter Size */
6118078679Skettenis #define	E600_HPET_PERIOD	0x004		/* Counter Tick Period */
6218078679Skettenis #define	E600_HPET_GC		0x010		/* General Configuration */
6318078679Skettenis #define	E600_HPET_GC_ENABLE	(1 << 0)	/* Overall Enable */
6418078679Skettenis #define	E600_HPET_GIS		0x020		/* General Interrupt Status */
6518078679Skettenis #define	E600_HPET_MCV		0x0f0		/* Main Counter Value */
6618078679Skettenis #define	E600_HPET_T0C		0x100		/* Timer 0 Config and Capabilities */
6718078679Skettenis #define	E600_HPET_T0CV		0x108		/* Timer 0 Comparator Value */
6818078679Skettenis #define	E600_HPET_T1C		0x120		/* Timer 1 Config and Capabilities */
6918078679Skettenis #define	E600_HPET_T1CV		0x128		/* Timer 1 Comparator Value */
7018078679Skettenis #define	E600_HPET_T2C		0x140		/* Timer 2 Config and Capabilities */
7118078679Skettenis #define	E600_HPET_T2CV		0x148		/* Timer 2 Comparator Value */
7218078679Skettenis 
73f6ad04e6Sjsg struct tcpcib_softc {
74f6ad04e6Sjsg 	struct device sc_dev;
75f6ad04e6Sjsg 
76f6ad04e6Sjsg 	/* Keep track of which parts of the hardware are active */
77f6ad04e6Sjsg 	int sc_active;
78f6ad04e6Sjsg #define	E600_WDT_ACTIVE		(1 << 0)
7918078679Skettenis #define	E600_HPET_ACTIVE	(1 << 1)
80f6ad04e6Sjsg 
81f6ad04e6Sjsg 	/* Watchdog interface */
82f6ad04e6Sjsg 	bus_space_tag_t sc_wdt_iot;
83f6ad04e6Sjsg 	bus_space_handle_t sc_wdt_ioh;
84f6ad04e6Sjsg 
85f6ad04e6Sjsg 	int sc_wdt_period;
8618078679Skettenis 
8718078679Skettenis 	/* High Precision Event Timer */
8818078679Skettenis 	bus_space_tag_t sc_hpet_iot;
8918078679Skettenis 	bus_space_handle_t sc_hpet_ioh;
9018078679Skettenis 
9118078679Skettenis 	struct timecounter sc_hpet_timecounter;
92f6ad04e6Sjsg };
93f6ad04e6Sjsg 
94f6ad04e6Sjsg struct cfdriver tcpcib_cd = {
95f6ad04e6Sjsg 	NULL, "tcpcib", DV_DULL
96f6ad04e6Sjsg };
97f6ad04e6Sjsg 
98f6ad04e6Sjsg int	 tcpcib_match(struct device *, void *, void *);
99f6ad04e6Sjsg void	 tcpcib_attach(struct device *, struct device *, void *);
100f6ad04e6Sjsg int	 tcpcib_activate(struct device *, int);
101f6ad04e6Sjsg 
102f6ad04e6Sjsg int	 tcpcib_wdt_cb(void *, int);
103f6ad04e6Sjsg void	 tcpcib_wdt_init(struct tcpcib_softc *, int);
104f6ad04e6Sjsg void	 tcpcib_wdt_start(struct tcpcib_softc *);
105f6ad04e6Sjsg void	 tcpcib_wdt_stop(struct tcpcib_softc *);
106f6ad04e6Sjsg 
10718078679Skettenis u_int	 tcpcib_hpet_get_timecount(struct timecounter *tc);
10818078679Skettenis 
109*8d2c75e4Smpi const struct cfattach tcpcib_ca = {
110f6ad04e6Sjsg 	sizeof(struct tcpcib_softc), tcpcib_match, tcpcib_attach,
111f6ad04e6Sjsg 	NULL, tcpcib_activate
112f6ad04e6Sjsg };
113f6ad04e6Sjsg 
114f6ad04e6Sjsg /* from arch/<*>/pci/pcib.c */
115f6ad04e6Sjsg void	pcibattach(struct device *parent, struct device *self, void *aux);
116f6ad04e6Sjsg 
117f6ad04e6Sjsg const struct pci_matchid tcpcib_devices[] = {
118f6ad04e6Sjsg 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_E600_LPC }
119f6ad04e6Sjsg };
120f6ad04e6Sjsg 
121f6ad04e6Sjsg static __inline void
tcpcib_wdt_unlock(struct tcpcib_softc * sc)122f6ad04e6Sjsg tcpcib_wdt_unlock(struct tcpcib_softc *sc)
123f6ad04e6Sjsg {
124f6ad04e6Sjsg 	/* Register unlocking sequence */
125f6ad04e6Sjsg 	bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR0, 0x80);
126f6ad04e6Sjsg 	bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR0, 0x86);
127f6ad04e6Sjsg }
128f6ad04e6Sjsg 
129f6ad04e6Sjsg void
tcpcib_wdt_init(struct tcpcib_softc * sc,int period)130f6ad04e6Sjsg tcpcib_wdt_init(struct tcpcib_softc *sc, int period)
131f6ad04e6Sjsg {
132f6ad04e6Sjsg 	u_int32_t preload;
133f6ad04e6Sjsg 
134f6ad04e6Sjsg 	/* Set new timeout */
135f6ad04e6Sjsg 	preload = (period * 33000000) >> 15;
136f6ad04e6Sjsg 	preload--;
137f6ad04e6Sjsg 
138f6ad04e6Sjsg 	/*
139f6ad04e6Sjsg 	 * Set watchdog to perform a cold reset toggling the GPIO pin and the
140f6ad04e6Sjsg 	 * prescaler set to 1ms-10m resolution
141f6ad04e6Sjsg 	 */
142f6ad04e6Sjsg 	bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_WDTCR,
143f6ad04e6Sjsg 	    E600_WDT_WDTCR_ENABLE);
144f6ad04e6Sjsg 	tcpcib_wdt_unlock(sc);
145f6ad04e6Sjsg 	bus_space_write_4(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_PV1, 0);
146f6ad04e6Sjsg 	tcpcib_wdt_unlock(sc);
147f6ad04e6Sjsg 	bus_space_write_4(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_PV2,
148f6ad04e6Sjsg 	    preload);
149f6ad04e6Sjsg 	tcpcib_wdt_unlock(sc);
150f6ad04e6Sjsg 	bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR1,
151f6ad04e6Sjsg 	    E600_WDT_RR1_RELOAD);
152f6ad04e6Sjsg }
153f6ad04e6Sjsg 
154f6ad04e6Sjsg void
tcpcib_wdt_start(struct tcpcib_softc * sc)155f6ad04e6Sjsg tcpcib_wdt_start(struct tcpcib_softc *sc)
156f6ad04e6Sjsg {
157f6ad04e6Sjsg 	/* Enable watchdog */
158f6ad04e6Sjsg 	bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_WDTLR,
159f6ad04e6Sjsg 	    E600_WDT_WDTLR_ENABLE);
160f6ad04e6Sjsg }
161f6ad04e6Sjsg 
162f6ad04e6Sjsg void
tcpcib_wdt_stop(struct tcpcib_softc * sc)163f6ad04e6Sjsg tcpcib_wdt_stop(struct tcpcib_softc *sc)
164f6ad04e6Sjsg {
165f6ad04e6Sjsg 	/* Disable watchdog, with a reload before for safety */
166f6ad04e6Sjsg 	tcpcib_wdt_unlock(sc);
167f6ad04e6Sjsg 	bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_RR1,
168f6ad04e6Sjsg 	    E600_WDT_RR1_RELOAD);
169f6ad04e6Sjsg 	bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh, E600_WDT_WDTLR, 0);
170f6ad04e6Sjsg }
171f6ad04e6Sjsg 
172f6ad04e6Sjsg int
tcpcib_match(struct device * parent,void * match,void * aux)173f6ad04e6Sjsg tcpcib_match(struct device *parent, void *match, void *aux)
174f6ad04e6Sjsg {
175f6ad04e6Sjsg 	if (pci_matchbyid((struct pci_attach_args *)aux, tcpcib_devices,
176f6ad04e6Sjsg 	    sizeof(tcpcib_devices) / sizeof(tcpcib_devices[0])))
177f6ad04e6Sjsg 		return (2);
178f6ad04e6Sjsg 
179f6ad04e6Sjsg 	return (0);
180f6ad04e6Sjsg }
181f6ad04e6Sjsg 
182f6ad04e6Sjsg void
tcpcib_attach(struct device * parent,struct device * self,void * aux)183f6ad04e6Sjsg tcpcib_attach(struct device *parent, struct device *self, void *aux)
184f6ad04e6Sjsg {
185f6ad04e6Sjsg 	struct tcpcib_softc *sc = (struct tcpcib_softc *)self;
186f6ad04e6Sjsg 	struct pci_attach_args *pa = aux;
18718078679Skettenis 	struct timecounter *tc = &sc->sc_hpet_timecounter;
188f6ad04e6Sjsg 	u_int32_t reg, wdtbase;
189f6ad04e6Sjsg 
190f6ad04e6Sjsg 	sc->sc_active = 0;
191f6ad04e6Sjsg 
19218078679Skettenis 	/* High Precision Event Timer */
19318078679Skettenis 	sc->sc_hpet_iot = pa->pa_memt;
19418078679Skettenis 	if (bus_space_map(sc->sc_hpet_iot, E600_HPET_BASE, E600_HPET_SIZE, 0,
19518078679Skettenis 	    &sc->sc_hpet_ioh) == 0) {
19618078679Skettenis 		tc->tc_get_timecount = tcpcib_hpet_get_timecount;
19718078679Skettenis 		/* XXX 64-bit counter is not supported! */
19818078679Skettenis 		tc->tc_counter_mask = 0xffffffff;
19918078679Skettenis 
20018078679Skettenis 		reg = bus_space_read_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
20118078679Skettenis 		    E600_HPET_PERIOD);
20218078679Skettenis 		/* femtosecs -> Hz */
20318078679Skettenis 		tc->tc_frequency = 1000000000000000ULL / reg;
20418078679Skettenis 
20518078679Skettenis 		tc->tc_name = sc->sc_dev.dv_xname;
20618078679Skettenis 		tc->tc_quality = 2000;
20718078679Skettenis 		tc->tc_priv = sc;
20818078679Skettenis 		tc_init(tc);
20918078679Skettenis 
21018078679Skettenis 		/* Enable counting */
21118078679Skettenis 		bus_space_write_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
21218078679Skettenis 		    E600_HPET_GC, E600_HPET_GC_ENABLE);
21318078679Skettenis 
21418078679Skettenis 		sc->sc_active |= E600_HPET_ACTIVE;
21518078679Skettenis 
21618078679Skettenis 		printf(": %llu Hz timer", tc->tc_frequency);
21718078679Skettenis 	}
21818078679Skettenis 
219f6ad04e6Sjsg 	/* Map Watchdog I/O space */
220f6ad04e6Sjsg 	reg = pci_conf_read(pa->pa_pc, pa->pa_tag, E600_LPC_WDTBA);
221f6ad04e6Sjsg 	wdtbase = reg & 0xffff;
222f6ad04e6Sjsg 	sc->sc_wdt_iot = pa->pa_iot;
22361e87b28Sderaadt 	if (reg & (1U << 31) && wdtbase) {
224f6ad04e6Sjsg 		if (PCI_MAPREG_IO_ADDR(wdtbase) == 0 ||
225f6ad04e6Sjsg 		    bus_space_map(sc->sc_wdt_iot, PCI_MAPREG_IO_ADDR(wdtbase),
226f6ad04e6Sjsg 		    E600_WDT_SIZE, 0, &sc->sc_wdt_ioh)) {
22718078679Skettenis 			printf("%c can't map watchdog I/O space",
22818078679Skettenis 			    sc->sc_active ? ',' : ':');
229f6ad04e6Sjsg 			goto corepcib;
230f6ad04e6Sjsg 		}
23118078679Skettenis 		printf("%c watchdog", sc->sc_active ? ',' : ':');
232f6ad04e6Sjsg 
233f6ad04e6Sjsg 		/* Check for reboot on timeout */
234f6ad04e6Sjsg 		reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh,
235f6ad04e6Sjsg 		    E600_WDT_RR1);
236f6ad04e6Sjsg 		if (reg & E600_WDT_RR1_TIMEOUT) {
237f6ad04e6Sjsg 			printf(", reboot on timeout");
238f6ad04e6Sjsg 
239f6ad04e6Sjsg 			/* Clear timeout bit */
240f6ad04e6Sjsg 			tcpcib_wdt_unlock(sc);
241f6ad04e6Sjsg 			bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh,
242f6ad04e6Sjsg 			    E600_WDT_RR1, E600_WDT_RR1_TIMEOUT);
243f6ad04e6Sjsg 		}
244f6ad04e6Sjsg 
245f6ad04e6Sjsg 		/* Check it's not locked already */
246f6ad04e6Sjsg 		reg = bus_space_read_1(sc->sc_wdt_iot, sc->sc_wdt_ioh,
247f6ad04e6Sjsg 		    E600_WDT_WDTLR);
248f6ad04e6Sjsg 		if (reg & E600_WDT_WDTLR_LOCK) {
249f6ad04e6Sjsg 			printf(", locked");
250f6ad04e6Sjsg 			goto corepcib;
251f6ad04e6Sjsg 		}
252f6ad04e6Sjsg 
253f6ad04e6Sjsg 		/* Disable watchdog */
254f6ad04e6Sjsg 		tcpcib_wdt_stop(sc);
255f6ad04e6Sjsg 		sc->sc_wdt_period = 0;
256f6ad04e6Sjsg 
257f6ad04e6Sjsg 		sc->sc_active |= E600_WDT_ACTIVE;
258f6ad04e6Sjsg 
259f6ad04e6Sjsg 		/* Register new watchdog */
2602bc62decSderaadt 		wdog_register(tcpcib_wdt_cb, sc);
261f6ad04e6Sjsg 	}
262f6ad04e6Sjsg 
263f6ad04e6Sjsg corepcib:
264f6ad04e6Sjsg 	/* Provide core pcib(4) functionality */
265f6ad04e6Sjsg 	pcibattach(parent, self, aux);
266f6ad04e6Sjsg }
267f6ad04e6Sjsg 
268f6ad04e6Sjsg int
tcpcib_activate(struct device * self,int act)269f6ad04e6Sjsg tcpcib_activate(struct device *self, int act)
270f6ad04e6Sjsg {
271f6ad04e6Sjsg 	struct tcpcib_softc *sc = (struct tcpcib_softc *)self;
27237ecb596Sderaadt 	int rv = 0;
273f6ad04e6Sjsg 
274f6ad04e6Sjsg 	switch (act) {
275f6ad04e6Sjsg 	case DVACT_SUSPEND:
27637ecb596Sderaadt 		rv = config_activate_children(self, act);
277f6ad04e6Sjsg 		/* Watchdog is running, disable it */
278f6ad04e6Sjsg 		if (sc->sc_active & E600_WDT_ACTIVE && sc->sc_wdt_period != 0)
279f6ad04e6Sjsg 			tcpcib_wdt_stop(sc);
280f6ad04e6Sjsg 		break;
281f6ad04e6Sjsg 	case DVACT_RESUME:
282f6ad04e6Sjsg 		if (sc->sc_active & E600_WDT_ACTIVE) {
283f6ad04e6Sjsg 			/*
284f6ad04e6Sjsg 			 * Watchdog was running prior to suspend so reenable
285f6ad04e6Sjsg 			 * it, otherwise make sure it stays disabled
286f6ad04e6Sjsg 			 */
287f6ad04e6Sjsg 			if (sc->sc_wdt_period != 0) {
288f6ad04e6Sjsg 				tcpcib_wdt_init(sc, sc->sc_wdt_period);
289f6ad04e6Sjsg 				tcpcib_wdt_start(sc);
290f6ad04e6Sjsg 			} else
291f6ad04e6Sjsg 				tcpcib_wdt_stop(sc);
292f6ad04e6Sjsg 		}
29318078679Skettenis 		if (sc->sc_active & E600_HPET_ACTIVE)
29418078679Skettenis 			bus_space_write_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
29518078679Skettenis 			    E600_HPET_GC, E600_HPET_GC_ENABLE);
29637ecb596Sderaadt 		rv = config_activate_children(self, act);
297c06fda6dSderaadt 		break;
2983b06f262Smikeb 	case DVACT_POWERDOWN:
2993b06f262Smikeb 		if (sc->sc_active & E600_WDT_ACTIVE)
3003b06f262Smikeb 			wdog_shutdown(self);
3013b06f262Smikeb 		rv = config_activate_children(self, act);
3023b06f262Smikeb 		break;
303c06fda6dSderaadt 	default:
30437ecb596Sderaadt 		rv = config_activate_children(self, act);
305f6ad04e6Sjsg 		break;
306f6ad04e6Sjsg 	}
30737ecb596Sderaadt 	return (rv);
308f6ad04e6Sjsg }
309f6ad04e6Sjsg 
310f6ad04e6Sjsg int
tcpcib_wdt_cb(void * arg,int period)311f6ad04e6Sjsg tcpcib_wdt_cb(void *arg, int period)
312f6ad04e6Sjsg {
313f6ad04e6Sjsg 	struct tcpcib_softc *sc = arg;
314f6ad04e6Sjsg 
315f6ad04e6Sjsg 	if (period == 0) {
316f6ad04e6Sjsg 		if (sc->sc_wdt_period != 0)
317f6ad04e6Sjsg 			tcpcib_wdt_stop(sc);
318f6ad04e6Sjsg 	} else {
319f6ad04e6Sjsg 		/* 600 seconds is the maximum supported timeout value */
320f6ad04e6Sjsg 		if (period > 600)
321f6ad04e6Sjsg 			period = 600;
322f6ad04e6Sjsg 		if (sc->sc_wdt_period != period)
323f6ad04e6Sjsg 			tcpcib_wdt_init(sc, period);
324f6ad04e6Sjsg 		if (sc->sc_wdt_period == 0) {
325f6ad04e6Sjsg 			tcpcib_wdt_start(sc);
326f6ad04e6Sjsg 		} else {
327f6ad04e6Sjsg 			/* Reset timer */
328f6ad04e6Sjsg 			tcpcib_wdt_unlock(sc);
329f6ad04e6Sjsg 			bus_space_write_1(sc->sc_wdt_iot, sc->sc_wdt_ioh,
330f6ad04e6Sjsg 			    E600_WDT_RR1, E600_WDT_RR1_RELOAD);
331f6ad04e6Sjsg 		}
332f6ad04e6Sjsg 	}
333f6ad04e6Sjsg 	sc->sc_wdt_period = period;
334f6ad04e6Sjsg 
335f6ad04e6Sjsg 	return (period);
336f6ad04e6Sjsg }
33718078679Skettenis 
33818078679Skettenis u_int
tcpcib_hpet_get_timecount(struct timecounter * tc)33918078679Skettenis tcpcib_hpet_get_timecount(struct timecounter *tc)
34018078679Skettenis {
34118078679Skettenis 	struct tcpcib_softc *sc = tc->tc_priv;
34218078679Skettenis 
34318078679Skettenis 	/* XXX 64-bit counter is not supported! */
34418078679Skettenis 	return bus_space_read_4(sc->sc_hpet_iot, sc->sc_hpet_ioh,
34518078679Skettenis 	    E600_HPET_MCV);
34618078679Skettenis }
347