xref: /titanic_53/usr/src/uts/sun4u/io/pmc.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2001 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate /*
30*7c478bd9Sstevel@tonic-gate  * Driver for the Power Management Controller (logical unit 8) of the
31*7c478bd9Sstevel@tonic-gate  * PC87317 SuperI/O chip. The PMC contains the hardware watchdog timer.
32*7c478bd9Sstevel@tonic-gate  */
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
36*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
37*7c478bd9Sstevel@tonic-gate #include <sys/param.h>
38*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
39*7c478bd9Sstevel@tonic-gate #include <sys/conf.h>
40*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
41*7c478bd9Sstevel@tonic-gate #include <sys/clock.h>
42*7c478bd9Sstevel@tonic-gate #include <sys/reboot.h>
43*7c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
44*7c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
45*7c478bd9Sstevel@tonic-gate #include <sys/file.h>
46*7c478bd9Sstevel@tonic-gate #include <sys/note.h>
47*7c478bd9Sstevel@tonic-gate 
48*7c478bd9Sstevel@tonic-gate #ifdef	DEBUG
49*7c478bd9Sstevel@tonic-gate int pmc_debug_flag = 0;
50*7c478bd9Sstevel@tonic-gate #define	DPRINTF(ARGLIST) if (pmc_debug_flag) printf ARGLIST;
51*7c478bd9Sstevel@tonic-gate #else
52*7c478bd9Sstevel@tonic-gate #define	DPRINTF(ARGLIST)
53*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /* Driver soft state structure */
56*7c478bd9Sstevel@tonic-gate typedef struct pmc {
57*7c478bd9Sstevel@tonic-gate 	dev_info_t		*dip;
58*7c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	pmc_handle;
59*7c478bd9Sstevel@tonic-gate } pmc_t;
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate static void *pmc_soft_state;
62*7c478bd9Sstevel@tonic-gate static int instance = -1;
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /* dev_ops and cb_ops entry point function declarations */
65*7c478bd9Sstevel@tonic-gate static int pmc_attach(dev_info_t *, ddi_attach_cmd_t);
66*7c478bd9Sstevel@tonic-gate static int pmc_detach(dev_info_t *, ddi_detach_cmd_t);
67*7c478bd9Sstevel@tonic-gate static int pmc_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate /* hardware watchdog parameters */
70*7c478bd9Sstevel@tonic-gate static uint_t pmc_set_watchdog_timer(uint_t);
71*7c478bd9Sstevel@tonic-gate static uint_t pmc_clear_watchdog_timer(void);
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate extern volatile uint8_t	*v_pmc_addr_reg;
74*7c478bd9Sstevel@tonic-gate extern volatile uint8_t	*v_pmc_data_reg;
75*7c478bd9Sstevel@tonic-gate extern int		watchdog_enable;
76*7c478bd9Sstevel@tonic-gate extern int		watchdog_available;
77*7c478bd9Sstevel@tonic-gate extern int		watchdog_activated;
78*7c478bd9Sstevel@tonic-gate extern int		boothowto;
79*7c478bd9Sstevel@tonic-gate extern uint_t		watchdog_timeout_seconds;
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate /*
82*7c478bd9Sstevel@tonic-gate  * Power Management Registers and values
83*7c478bd9Sstevel@tonic-gate  */
84*7c478bd9Sstevel@tonic-gate #define	PMC_WDTO	0x05	/* Watchdog Time Out */
85*7c478bd9Sstevel@tonic-gate #define	PMC_CLEAR_WDTO	0x00
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate struct cb_ops pmc_cb_ops = {
88*7c478bd9Sstevel@tonic-gate 	nodev,
89*7c478bd9Sstevel@tonic-gate 	nodev,
90*7c478bd9Sstevel@tonic-gate 	nodev,
91*7c478bd9Sstevel@tonic-gate 	nodev,
92*7c478bd9Sstevel@tonic-gate 	nodev,			/* dump */
93*7c478bd9Sstevel@tonic-gate 	nodev,
94*7c478bd9Sstevel@tonic-gate 	nodev,
95*7c478bd9Sstevel@tonic-gate 	nodev,
96*7c478bd9Sstevel@tonic-gate 	nodev,			/* devmap */
97*7c478bd9Sstevel@tonic-gate 	nodev,
98*7c478bd9Sstevel@tonic-gate 	nodev,
99*7c478bd9Sstevel@tonic-gate 	nochpoll,
100*7c478bd9Sstevel@tonic-gate 	ddi_prop_op,
101*7c478bd9Sstevel@tonic-gate 	NULL,			/* for STREAMS drivers */
102*7c478bd9Sstevel@tonic-gate 	D_NEW | D_MP,		/* driver compatibility flag */
103*7c478bd9Sstevel@tonic-gate 	CB_REV,
104*7c478bd9Sstevel@tonic-gate 	nodev,
105*7c478bd9Sstevel@tonic-gate 	nodev
106*7c478bd9Sstevel@tonic-gate };
107*7c478bd9Sstevel@tonic-gate 
108*7c478bd9Sstevel@tonic-gate static struct dev_ops pmc_dev_ops = {
109*7c478bd9Sstevel@tonic-gate 	DEVO_REV,			/* driver build version */
110*7c478bd9Sstevel@tonic-gate 	0,				/* device reference count */
111*7c478bd9Sstevel@tonic-gate 	pmc_getinfo,
112*7c478bd9Sstevel@tonic-gate 	nulldev,
113*7c478bd9Sstevel@tonic-gate 	nulldev,			/* probe */
114*7c478bd9Sstevel@tonic-gate 	pmc_attach,
115*7c478bd9Sstevel@tonic-gate 	pmc_detach,
116*7c478bd9Sstevel@tonic-gate 	nulldev,			/* reset */
117*7c478bd9Sstevel@tonic-gate 	&pmc_cb_ops,
118*7c478bd9Sstevel@tonic-gate 	(struct bus_ops *)NULL,
119*7c478bd9Sstevel@tonic-gate 	nulldev				/* power */
120*7c478bd9Sstevel@tonic-gate };
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate /* module configuration stuff */
123*7c478bd9Sstevel@tonic-gate extern struct mod_ops mod_driverops;
124*7c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
125*7c478bd9Sstevel@tonic-gate 	&mod_driverops,
126*7c478bd9Sstevel@tonic-gate 	"pmc driver %I%",
127*7c478bd9Sstevel@tonic-gate 	&pmc_dev_ops
128*7c478bd9Sstevel@tonic-gate };
129*7c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
130*7c478bd9Sstevel@tonic-gate 	MODREV_1,
131*7c478bd9Sstevel@tonic-gate 	&modldrv,
132*7c478bd9Sstevel@tonic-gate 	0
133*7c478bd9Sstevel@tonic-gate };
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate int
137*7c478bd9Sstevel@tonic-gate _init(void)
138*7c478bd9Sstevel@tonic-gate {
139*7c478bd9Sstevel@tonic-gate 	int e;
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate 	e = ddi_soft_state_init(&pmc_soft_state, sizeof (pmc_t), 1);
142*7c478bd9Sstevel@tonic-gate 	if (e != 0) {
143*7c478bd9Sstevel@tonic-gate 		DPRINTF(("_init: ddi_soft_state_init failed\n"));
144*7c478bd9Sstevel@tonic-gate 		return (e);
145*7c478bd9Sstevel@tonic-gate 	}
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 	e = mod_install(&modlinkage);
148*7c478bd9Sstevel@tonic-gate 	if (e != 0) {
149*7c478bd9Sstevel@tonic-gate 		DPRINTF(("_init: mod_install failed\n"));
150*7c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&pmc_soft_state);
151*7c478bd9Sstevel@tonic-gate 		return (e);
152*7c478bd9Sstevel@tonic-gate 	}
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	if (v_pmc_addr_reg != NULL) {
155*7c478bd9Sstevel@tonic-gate 		tod_ops.tod_set_watchdog_timer = pmc_set_watchdog_timer;
156*7c478bd9Sstevel@tonic-gate 		tod_ops.tod_clear_watchdog_timer = pmc_clear_watchdog_timer;
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 		/*
159*7c478bd9Sstevel@tonic-gate 		 * See if the user has enabled the watchdog timer, and if
160*7c478bd9Sstevel@tonic-gate 		 * it's available.
161*7c478bd9Sstevel@tonic-gate 		 */
162*7c478bd9Sstevel@tonic-gate 		if (watchdog_enable) {
163*7c478bd9Sstevel@tonic-gate 			if (!watchdog_available) {
164*7c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "pmc: Hardware watchdog "
165*7c478bd9Sstevel@tonic-gate 					"unavailable");
166*7c478bd9Sstevel@tonic-gate 			} else if (boothowto & RB_DEBUG) {
167*7c478bd9Sstevel@tonic-gate 				watchdog_available = 0;
168*7c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "pmc: kernel debugger "
169*7c478bd9Sstevel@tonic-gate 					"detected: hardware watchdog disabled");
170*7c478bd9Sstevel@tonic-gate 			}
171*7c478bd9Sstevel@tonic-gate 		}
172*7c478bd9Sstevel@tonic-gate 	}
173*7c478bd9Sstevel@tonic-gate 	return (e);
174*7c478bd9Sstevel@tonic-gate }
175*7c478bd9Sstevel@tonic-gate 
176*7c478bd9Sstevel@tonic-gate int
177*7c478bd9Sstevel@tonic-gate _fini(void)
178*7c478bd9Sstevel@tonic-gate {
179*7c478bd9Sstevel@tonic-gate 	int e;
180*7c478bd9Sstevel@tonic-gate 
181*7c478bd9Sstevel@tonic-gate 	if (v_pmc_addr_reg != NULL)
182*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
183*7c478bd9Sstevel@tonic-gate 	else {
184*7c478bd9Sstevel@tonic-gate 		e = mod_remove(&modlinkage);
185*7c478bd9Sstevel@tonic-gate 		if (e != 0)
186*7c478bd9Sstevel@tonic-gate 			return (e);
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&pmc_soft_state);
189*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
190*7c478bd9Sstevel@tonic-gate 	}
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate int
195*7c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
196*7c478bd9Sstevel@tonic-gate {
197*7c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
198*7c478bd9Sstevel@tonic-gate }
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate static int
201*7c478bd9Sstevel@tonic-gate pmc_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
202*7c478bd9Sstevel@tonic-gate {
203*7c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(dip))
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate 	pmc_t	*pmcp;
206*7c478bd9Sstevel@tonic-gate 	int	instance;
207*7c478bd9Sstevel@tonic-gate 
208*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
209*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
210*7c478bd9Sstevel@tonic-gate 		instance = getminor((dev_t)arg);
211*7c478bd9Sstevel@tonic-gate 		pmcp = (pmc_t *)ddi_get_soft_state(pmc_soft_state, instance);
212*7c478bd9Sstevel@tonic-gate 		if (pmcp == NULL) {
213*7c478bd9Sstevel@tonic-gate 			*result = (void *)NULL;
214*7c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
215*7c478bd9Sstevel@tonic-gate 		}
216*7c478bd9Sstevel@tonic-gate 		*result = (void *)pmcp->dip;
217*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
220*7c478bd9Sstevel@tonic-gate 		*result = (void *)getminor((dev_t)arg);
221*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate 	default:
224*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
225*7c478bd9Sstevel@tonic-gate 	}
226*7c478bd9Sstevel@tonic-gate }
227*7c478bd9Sstevel@tonic-gate 
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate static int
230*7c478bd9Sstevel@tonic-gate pmc_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
231*7c478bd9Sstevel@tonic-gate {
232*7c478bd9Sstevel@tonic-gate 	pmc_t	*pmcp;
233*7c478bd9Sstevel@tonic-gate 	uint_t	wd_timout;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
236*7c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
237*7c478bd9Sstevel@tonic-gate 		break;
238*7c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
239*7c478bd9Sstevel@tonic-gate 		if (v_pmc_addr_reg != NULL && watchdog_enable) {
240*7c478bd9Sstevel@tonic-gate 			int ret = 0;
241*7c478bd9Sstevel@tonic-gate 			wd_timout = watchdog_timeout_seconds;
242*7c478bd9Sstevel@tonic-gate 			mutex_enter(&tod_lock);
243*7c478bd9Sstevel@tonic-gate 			ret = tod_ops.tod_set_watchdog_timer(wd_timout);
244*7c478bd9Sstevel@tonic-gate 			mutex_exit(&tod_lock);
245*7c478bd9Sstevel@tonic-gate 			if (ret == 0)
246*7c478bd9Sstevel@tonic-gate 				return (DDI_FAILURE);
247*7c478bd9Sstevel@tonic-gate 		}
248*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
249*7c478bd9Sstevel@tonic-gate 	default:
250*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
251*7c478bd9Sstevel@tonic-gate 	}
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	if (instance != -1) {
254*7c478bd9Sstevel@tonic-gate 		DPRINTF(("pmc_attach: Another instance is already attached."));
255*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
256*7c478bd9Sstevel@tonic-gate 	}
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	if (ddi_soft_state_zalloc(pmc_soft_state, instance) != DDI_SUCCESS) {
261*7c478bd9Sstevel@tonic-gate 		DPRINTF(("pmc_attach: Failed to allocate soft state."));
262*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	pmcp = (pmc_t *)ddi_get_soft_state(pmc_soft_state, instance);
266*7c478bd9Sstevel@tonic-gate 	pmcp->dip = dip;
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
269*7c478bd9Sstevel@tonic-gate }
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate static int
272*7c478bd9Sstevel@tonic-gate pmc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
273*7c478bd9Sstevel@tonic-gate {
274*7c478bd9Sstevel@tonic-gate 	_NOTE(ARGUNUSED(dip))
275*7c478bd9Sstevel@tonic-gate 
276*7c478bd9Sstevel@tonic-gate 	pmc_t	*pmcp;
277*7c478bd9Sstevel@tonic-gate 
278*7c478bd9Sstevel@tonic-gate 	switch (cmd) {
279*7c478bd9Sstevel@tonic-gate 	case DDI_DETACH:
280*7c478bd9Sstevel@tonic-gate 		/* allow detach if no hardware watchdog */
281*7c478bd9Sstevel@tonic-gate 		if (v_pmc_addr_reg == NULL || !watchdog_activated) {
282*7c478bd9Sstevel@tonic-gate 			pmcp = (pmc_t *)ddi_get_soft_state(pmc_soft_state,
283*7c478bd9Sstevel@tonic-gate 				instance);
284*7c478bd9Sstevel@tonic-gate 			if (pmcp == NULL)
285*7c478bd9Sstevel@tonic-gate 				return (ENXIO);
286*7c478bd9Sstevel@tonic-gate 			ddi_soft_state_free(pmc_soft_state, instance);
287*7c478bd9Sstevel@tonic-gate 			return (DDI_SUCCESS);
288*7c478bd9Sstevel@tonic-gate 		} else
289*7c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
290*7c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
291*7c478bd9Sstevel@tonic-gate 		if (v_pmc_addr_reg != NULL && watchdog_activated) {
292*7c478bd9Sstevel@tonic-gate 			mutex_enter(&tod_lock);
293*7c478bd9Sstevel@tonic-gate 			(void) tod_ops.tod_clear_watchdog_timer();
294*7c478bd9Sstevel@tonic-gate 			mutex_exit(&tod_lock);
295*7c478bd9Sstevel@tonic-gate 		}
296*7c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
297*7c478bd9Sstevel@tonic-gate 	default:
298*7c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
299*7c478bd9Sstevel@tonic-gate 	}
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate }
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate /*
304*7c478bd9Sstevel@tonic-gate  * Set the hardware watchdog timer; returning what we set it to.
305*7c478bd9Sstevel@tonic-gate  */
306*7c478bd9Sstevel@tonic-gate static uint_t
307*7c478bd9Sstevel@tonic-gate pmc_set_watchdog_timer(uint_t timeoutval)
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate 	uint_t timeoutval_minutes;
310*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&tod_lock));
311*7c478bd9Sstevel@tonic-gate 
312*7c478bd9Sstevel@tonic-gate 	/* sanity checks */
313*7c478bd9Sstevel@tonic-gate 	if (watchdog_enable == 0 || watchdog_available == 0 ||
314*7c478bd9Sstevel@tonic-gate 	    timeoutval == 0)
315*7c478bd9Sstevel@tonic-gate 		return (0);
316*7c478bd9Sstevel@tonic-gate 
317*7c478bd9Sstevel@tonic-gate 	/*
318*7c478bd9Sstevel@tonic-gate 	 * Historically the timer has been counted out in seconds.
319*7c478bd9Sstevel@tonic-gate 	 * The PC87317 counts the timeout in minutes. The default
320*7c478bd9Sstevel@tonic-gate 	 * timeout is 10 seconds; the least we can do is one minute.
321*7c478bd9Sstevel@tonic-gate 	 */
322*7c478bd9Sstevel@tonic-gate 	timeoutval_minutes = (timeoutval + 59) / 60;
323*7c478bd9Sstevel@tonic-gate 	if (timeoutval_minutes > UINT8_MAX)
324*7c478bd9Sstevel@tonic-gate 		return (0);
325*7c478bd9Sstevel@tonic-gate 
326*7c478bd9Sstevel@tonic-gate 	*v_pmc_addr_reg = (uint8_t)PMC_WDTO;
327*7c478bd9Sstevel@tonic-gate 	*v_pmc_data_reg = (uint8_t)timeoutval_minutes;
328*7c478bd9Sstevel@tonic-gate 	watchdog_activated = 1;
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	/* we'll still return seconds */
331*7c478bd9Sstevel@tonic-gate 	return (timeoutval_minutes * 60);
332*7c478bd9Sstevel@tonic-gate }
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate /*
335*7c478bd9Sstevel@tonic-gate  * Clear the hardware watchdog timer; returning what it was set to.
336*7c478bd9Sstevel@tonic-gate  */
337*7c478bd9Sstevel@tonic-gate static uint_t
338*7c478bd9Sstevel@tonic-gate pmc_clear_watchdog_timer(void)
339*7c478bd9Sstevel@tonic-gate {
340*7c478bd9Sstevel@tonic-gate 	uint_t	wd_timeout;
341*7c478bd9Sstevel@tonic-gate 
342*7c478bd9Sstevel@tonic-gate 	ASSERT(MUTEX_HELD(&tod_lock));
343*7c478bd9Sstevel@tonic-gate 	if (watchdog_activated == 0)
344*7c478bd9Sstevel@tonic-gate 		return (0);
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	*v_pmc_addr_reg = (uint8_t)PMC_WDTO;
347*7c478bd9Sstevel@tonic-gate 	wd_timeout = (uint_t)*v_pmc_data_reg;
348*7c478bd9Sstevel@tonic-gate 	*v_pmc_data_reg = (uint8_t)PMC_CLEAR_WDTO;
349*7c478bd9Sstevel@tonic-gate 	watchdog_activated = 0;
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	/* return seconds */
352*7c478bd9Sstevel@tonic-gate 	return (wd_timeout * 60);
353*7c478bd9Sstevel@tonic-gate }
354