xref: /titanic_51/usr/src/uts/sun4u/io/pmugpio.c (revision d58fda4376e4bf67072ce2e69f6f47036f9dbb68)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23*d58fda43Sjbeloro  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/conf.h>
317c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
327c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
337c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
347c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
357c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
367c478bd9Sstevel@tonic-gate #include <sys/devops.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
39*d58fda43Sjbeloro  * The pmugpio driver supports ALOM GPIO bits for resetSC and
40*d58fda43Sjbeloro  * watchdog heartbeat on all relevant platforms.  Historically,
41*d58fda43Sjbeloro  * pmugpio is a leaf off the Chalupa pmubus.  In addition to
42*d58fda43Sjbeloro  * this support the pmugpio driver has been modified to support
43*d58fda43Sjbeloro  * Minneapolis/Boston Controller (MBC) FPGA GPIO and Seattle CPLD
44*d58fda43Sjbeloro  * GPIO.
45*d58fda43Sjbeloro  */
46*d58fda43Sjbeloro 
47*d58fda43Sjbeloro typedef enum {
48*d58fda43Sjbeloro 	PMUGPIO_MBC,		/* Boston MBC FPGA GPIO - 8-bit */
49*d58fda43Sjbeloro 	PMUGPIO_CPLD,		/* Seattle CPLD GPIO - 8-bit */
50*d58fda43Sjbeloro 	PMUGPIO_OTHER		/* Chalupa - 8-bit */
51*d58fda43Sjbeloro } pmugpio_access_type_t;
52*d58fda43Sjbeloro 
53*d58fda43Sjbeloro /*
54*d58fda43Sjbeloro  * CPLD GPIO Register defines.
55*d58fda43Sjbeloro  */
56*d58fda43Sjbeloro #define	CPLD_RESET_SC		0x01	/* Reset SC */
57*d58fda43Sjbeloro #define	CPLD_WATCHDOG		0x02	/* Watchdog */
58*d58fda43Sjbeloro 
59*d58fda43Sjbeloro #define	CPLD_RESET_DELAY	3	/* microsecond delay */
60*d58fda43Sjbeloro 
61*d58fda43Sjbeloro /*
62*d58fda43Sjbeloro  * MBC FPGA CSR defines.
63*d58fda43Sjbeloro  */
64*d58fda43Sjbeloro #define	MBC_PPC_RESET		0x10	/* Reset ALOM */
65*d58fda43Sjbeloro #define	MBC_WATCHDOG		0x40	/* Watchdog heartbeat bit */
66*d58fda43Sjbeloro 
67*d58fda43Sjbeloro /*
687c478bd9Sstevel@tonic-gate  * Time periods, in nanoseconds
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate #define	PMUGPIO_TWO_SEC		2000000000LL
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate static	dev_info_t	*pmugpio_dip;
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate typedef struct pmugpio_state {
757c478bd9Sstevel@tonic-gate 	uint8_t			*pmugpio_reset_reg;
767c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	pmugpio_reset_reg_handle;
777c478bd9Sstevel@tonic-gate 	uint8_t			*pmugpio_watchdog_reg;
787c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	pmugpio_watchdog_reg_handle;
797c478bd9Sstevel@tonic-gate 	hrtime_t		hw_last_pat;
80*d58fda43Sjbeloro 	pmugpio_access_type_t	access_type;
817c478bd9Sstevel@tonic-gate } pmugpio_state_t;
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate static void *pmugpio_statep;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate static int pmugpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
867c478bd9Sstevel@tonic-gate static int pmugpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
877c478bd9Sstevel@tonic-gate static int pmugpio_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
887c478bd9Sstevel@tonic-gate 		void **result);
897c478bd9Sstevel@tonic-gate static int pmugpio_map_regs(dev_info_t *, pmugpio_state_t *);
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate struct cb_ops pmugpio_cb_ops = {
927c478bd9Sstevel@tonic-gate 	nulldev,	/* open  */
937c478bd9Sstevel@tonic-gate 	nulldev,	/* close */
947c478bd9Sstevel@tonic-gate 	nulldev,	/* strategy */
957c478bd9Sstevel@tonic-gate 	nulldev,	/* print */
967c478bd9Sstevel@tonic-gate 	nulldev,	/* dump */
977c478bd9Sstevel@tonic-gate 	nulldev,	/* read */
987c478bd9Sstevel@tonic-gate 	nulldev,	/* write */
997c478bd9Sstevel@tonic-gate 	nulldev,	/* ioctl */
1007c478bd9Sstevel@tonic-gate 	nulldev,	/* devmap */
1017c478bd9Sstevel@tonic-gate 	nulldev,	/* mmap */
1027c478bd9Sstevel@tonic-gate 	nulldev,	/* segmap */
1037c478bd9Sstevel@tonic-gate 	nochpoll,	/* poll */
1047c478bd9Sstevel@tonic-gate 	ddi_prop_op,	/* cb_prop_op */
1057c478bd9Sstevel@tonic-gate 	NULL,		/* streamtab  */
1067c478bd9Sstevel@tonic-gate 	D_MP | D_NEW
1077c478bd9Sstevel@tonic-gate };
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate static struct dev_ops pmugpio_ops = {
1107c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* Devo_rev */
1117c478bd9Sstevel@tonic-gate 	0,			/* Refcnt */
1127c478bd9Sstevel@tonic-gate 	pmugpio_info,		/* Info */
1137c478bd9Sstevel@tonic-gate 	nulldev,		/* Identify */
1147c478bd9Sstevel@tonic-gate 	nulldev,		/* Probe */
1157c478bd9Sstevel@tonic-gate 	pmugpio_attach,		/* Attach */
1167c478bd9Sstevel@tonic-gate 	pmugpio_detach,		/* Detach */
1177c478bd9Sstevel@tonic-gate 	nodev,			/* Reset */
1187c478bd9Sstevel@tonic-gate 	&pmugpio_cb_ops,		/* Driver operations */
1197c478bd9Sstevel@tonic-gate 	0,			/* Bus operations */
1207c478bd9Sstevel@tonic-gate 	NULL			/* Power */
1217c478bd9Sstevel@tonic-gate };
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
1247c478bd9Sstevel@tonic-gate 	&mod_driverops, 		/* This one is a driver */
1257c478bd9Sstevel@tonic-gate 	"Pmugpio Driver %I%", 		/* Name of the module. */
1267c478bd9Sstevel@tonic-gate 	&pmugpio_ops,			/* Driver ops */
1277c478bd9Sstevel@tonic-gate };
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1307c478bd9Sstevel@tonic-gate 	MODREV_1, (void *)&modldrv, NULL
1317c478bd9Sstevel@tonic-gate };
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate int
1347c478bd9Sstevel@tonic-gate _init(void)
1357c478bd9Sstevel@tonic-gate {
1367c478bd9Sstevel@tonic-gate 	int error;
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 	/* Initialize the soft state structures */
1397c478bd9Sstevel@tonic-gate 	if ((error = ddi_soft_state_init(&pmugpio_statep,
1407c478bd9Sstevel@tonic-gate 	    sizeof (pmugpio_state_t), 1)) != 0) {
1417c478bd9Sstevel@tonic-gate 		return (error);
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	/* Install the loadable module */
1457c478bd9Sstevel@tonic-gate 	if ((error = mod_install(&modlinkage)) != 0) {
1467c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&pmugpio_statep);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 	return (error);
1497c478bd9Sstevel@tonic-gate }
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate int
1527c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1537c478bd9Sstevel@tonic-gate {
1547c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1557c478bd9Sstevel@tonic-gate }
1567c478bd9Sstevel@tonic-gate 
1577c478bd9Sstevel@tonic-gate int
1587c478bd9Sstevel@tonic-gate _fini(void)
1597c478bd9Sstevel@tonic-gate {
1607c478bd9Sstevel@tonic-gate 	int error;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	error = mod_remove(&modlinkage);
1637c478bd9Sstevel@tonic-gate 	if (error == 0) {
1647c478bd9Sstevel@tonic-gate 		/* Release per module resources */
1657c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&pmugpio_statep);
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 	return (error);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate static int
1717c478bd9Sstevel@tonic-gate pmugpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1727c478bd9Sstevel@tonic-gate {
1737c478bd9Sstevel@tonic-gate 	int		instance;
1747c478bd9Sstevel@tonic-gate 	pmugpio_state_t	*pmugpio_ptr = NULL;
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	switch (cmd) {
1777c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
1787c478bd9Sstevel@tonic-gate 		break;
1797c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
1807c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
1817c478bd9Sstevel@tonic-gate 	default:
1827c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1837c478bd9Sstevel@tonic-gate 	}
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	/* Get the instance and create soft state */
1867c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
1877c478bd9Sstevel@tonic-gate 	if (ddi_soft_state_zalloc(pmugpio_statep, instance) != 0) {
1887c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
1917c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
1927c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1937c478bd9Sstevel@tonic-gate 	}
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 	if (pmugpio_map_regs(dip, pmugpio_ptr) != DDI_SUCCESS) {
1967c478bd9Sstevel@tonic-gate 		ddi_soft_state_free(pmugpio_statep, instance);
1977c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	/* Display information in the banner */
2017c478bd9Sstevel@tonic-gate 	ddi_report_dev(dip);
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate 	/* Save the dip */
2047c478bd9Sstevel@tonic-gate 	pmugpio_dip = dip;
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /* ARGSUSED */
2107c478bd9Sstevel@tonic-gate static int
2117c478bd9Sstevel@tonic-gate pmugpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2127c478bd9Sstevel@tonic-gate {
2137c478bd9Sstevel@tonic-gate 	/* Pointer to soft state */
2147c478bd9Sstevel@tonic-gate 	switch (cmd) {
2157c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
2167c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
2177c478bd9Sstevel@tonic-gate 	default:
2187c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate /* ARGSUSED */
2237c478bd9Sstevel@tonic-gate static int
2247c478bd9Sstevel@tonic-gate pmugpio_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
2257c478bd9Sstevel@tonic-gate 		void *arg, void **result)
2267c478bd9Sstevel@tonic-gate {
2277c478bd9Sstevel@tonic-gate 	dev_t dev;
2287c478bd9Sstevel@tonic-gate 	int instance, error;
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate 	switch (infocmd) {
2317c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
2327c478bd9Sstevel@tonic-gate 		*result = (void *)pmugpio_dip;
2337c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
2347c478bd9Sstevel@tonic-gate 		break;
2357c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
2367c478bd9Sstevel@tonic-gate 		dev = (dev_t)arg;
2377c478bd9Sstevel@tonic-gate 		instance = getminor(dev);
2387c478bd9Sstevel@tonic-gate 		*result = (void *)(uintptr_t)instance;
2397c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
2407c478bd9Sstevel@tonic-gate 		break;
2417c478bd9Sstevel@tonic-gate 	default:
2427c478bd9Sstevel@tonic-gate 		error = DDI_FAILURE;
2437c478bd9Sstevel@tonic-gate 	}
2447c478bd9Sstevel@tonic-gate 	return (error);
2457c478bd9Sstevel@tonic-gate }
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate void
2487c478bd9Sstevel@tonic-gate pmugpio_watchdog_pat(void)
2497c478bd9Sstevel@tonic-gate {
2507c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pmugpio_dip;
2517c478bd9Sstevel@tonic-gate 	int instance;
2527c478bd9Sstevel@tonic-gate 	pmugpio_state_t *pmugpio_ptr;
2537c478bd9Sstevel@tonic-gate 	hrtime_t now;
2547c478bd9Sstevel@tonic-gate 	uint8_t value;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
2577c478bd9Sstevel@tonic-gate 		return;
2587c478bd9Sstevel@tonic-gate 	}
2597c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
2607c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
2617c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
2627c478bd9Sstevel@tonic-gate 		return;
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate 	/*
2657c478bd9Sstevel@tonic-gate 	 * The RMC can read interrupts either high to low OR low to high. As
2667c478bd9Sstevel@tonic-gate 	 * a result all that needs to happen is that when we hit the time to
2677c478bd9Sstevel@tonic-gate 	 * send an signal we simply need to change the state.
2687c478bd9Sstevel@tonic-gate 	 */
2697c478bd9Sstevel@tonic-gate 	now = gethrtime();
2707c478bd9Sstevel@tonic-gate 	if ((now - pmugpio_ptr->hw_last_pat) >= PMUGPIO_TWO_SEC) {
2717c478bd9Sstevel@tonic-gate 		/*
2727c478bd9Sstevel@tonic-gate 		 * fetch current reg value and invert it
2737c478bd9Sstevel@tonic-gate 		 */
274*d58fda43Sjbeloro 		switch (pmugpio_ptr->access_type) {
275*d58fda43Sjbeloro 		case PMUGPIO_CPLD:
276*d58fda43Sjbeloro 			value = (CPLD_WATCHDOG ^
277*d58fda43Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
278*d58fda43Sjbeloro 				pmugpio_ptr->pmugpio_watchdog_reg));
279*d58fda43Sjbeloro 
280*d58fda43Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
281*d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
282*d58fda43Sjbeloro 			break;
283*d58fda43Sjbeloro 
284*d58fda43Sjbeloro 		case PMUGPIO_MBC:
285*d58fda43Sjbeloro 			value = (uint8_t)(MBC_WATCHDOG ^
286*d58fda43Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
287*d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg));
288*d58fda43Sjbeloro 
289*d58fda43Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
290*d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
291*d58fda43Sjbeloro 			break;
292*d58fda43Sjbeloro 
293*d58fda43Sjbeloro 		case PMUGPIO_OTHER:
2947c478bd9Sstevel@tonic-gate 			value = (uint8_t)(0xff ^
2957c478bd9Sstevel@tonic-gate 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
2967c478bd9Sstevel@tonic-gate 			    pmugpio_ptr->pmugpio_watchdog_reg));
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
2997c478bd9Sstevel@tonic-gate 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
300*d58fda43Sjbeloro 			break;
301*d58fda43Sjbeloro 
302*d58fda43Sjbeloro 		default:
303*d58fda43Sjbeloro 			cmn_err(CE_WARN, "pmugpio_watchdog_pat: Invalid type");
304*d58fda43Sjbeloro 		}
3057c478bd9Sstevel@tonic-gate 		pmugpio_ptr->hw_last_pat = now;
3067c478bd9Sstevel@tonic-gate 	}
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate void
3107c478bd9Sstevel@tonic-gate pmugpio_reset(void)
3117c478bd9Sstevel@tonic-gate {
3127c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pmugpio_dip;
3137c478bd9Sstevel@tonic-gate 	int instance;
3147c478bd9Sstevel@tonic-gate 	pmugpio_state_t *pmugpio_ptr;
315*d58fda43Sjbeloro 	uint8_t value;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
3187c478bd9Sstevel@tonic-gate 		return;
3197c478bd9Sstevel@tonic-gate 	}
3207c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
3217c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
3227c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
3237c478bd9Sstevel@tonic-gate 		return;
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	/*
327*d58fda43Sjbeloro 	 * For Chalupa, turn all bits on then off again - pmubus nexus
328*d58fda43Sjbeloro 	 * will ensure that only unmasked bit is affected.
329*d58fda43Sjbeloro 	 * For CPLD and MBC, turn just reset bit on, then off.
3307c478bd9Sstevel@tonic-gate 	 */
331*d58fda43Sjbeloro 	switch (pmugpio_ptr->access_type) {
332*d58fda43Sjbeloro 	case PMUGPIO_CPLD:
333*d58fda43Sjbeloro 		value = ddi_get8(pmugpio_ptr->pmugpio_reset_reg_handle,
334*d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg);
335*d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
336*d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, (value | CPLD_RESET_SC));
337*d58fda43Sjbeloro 
338*d58fda43Sjbeloro 		drv_usecwait(CPLD_RESET_DELAY);
339*d58fda43Sjbeloro 
340*d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
341*d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, (value & ~CPLD_RESET_SC));
342*d58fda43Sjbeloro 		break;
343*d58fda43Sjbeloro 
344*d58fda43Sjbeloro 	case PMUGPIO_MBC:
345*d58fda43Sjbeloro 		value = ddi_get8(pmugpio_ptr->pmugpio_reset_reg_handle,
346*d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg);
347*d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
348*d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg,
349*d58fda43Sjbeloro 			(value | MBC_PPC_RESET));
350*d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
351*d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg,
352*d58fda43Sjbeloro 			(value & ~MBC_PPC_RESET));
353*d58fda43Sjbeloro 		break;
354*d58fda43Sjbeloro 
355*d58fda43Sjbeloro 	case PMUGPIO_OTHER:
3567c478bd9Sstevel@tonic-gate 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
3577c478bd9Sstevel@tonic-gate 		    pmugpio_ptr->pmugpio_reset_reg, ~0);
3587c478bd9Sstevel@tonic-gate 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
3597c478bd9Sstevel@tonic-gate 		    pmugpio_ptr->pmugpio_reset_reg, 0);
360*d58fda43Sjbeloro 		break;
361*d58fda43Sjbeloro 
362*d58fda43Sjbeloro 	default:
363*d58fda43Sjbeloro 		cmn_err(CE_WARN, "pmugpio_reset: Invalid type");
364*d58fda43Sjbeloro 	}
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate static int
3687c478bd9Sstevel@tonic-gate pmugpio_map_regs(dev_info_t *dip, pmugpio_state_t *pmugpio_ptr)
3697c478bd9Sstevel@tonic-gate {
3707c478bd9Sstevel@tonic-gate 	ddi_device_acc_attr_t attr;
371*d58fda43Sjbeloro 	char *binding_name;
3727c478bd9Sstevel@tonic-gate 
3737c478bd9Sstevel@tonic-gate 	/* The host controller will be little endian */
3747c478bd9Sstevel@tonic-gate 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3757c478bd9Sstevel@tonic-gate 	attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
3767c478bd9Sstevel@tonic-gate 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3777c478bd9Sstevel@tonic-gate 
378*d58fda43Sjbeloro 	binding_name = ddi_binding_name(dip);
379*d58fda43Sjbeloro 
380*d58fda43Sjbeloro 	/*
381*d58fda43Sjbeloro 	 * Determine access type.
382*d58fda43Sjbeloro 	 */
383*d58fda43Sjbeloro 	if (strcmp(binding_name, "mbcgpio") == 0)
384*d58fda43Sjbeloro 		pmugpio_ptr->access_type = PMUGPIO_MBC;
385*d58fda43Sjbeloro 	else if (strcmp(binding_name, "cpldgpio") == 0)
386*d58fda43Sjbeloro 		pmugpio_ptr->access_type = PMUGPIO_CPLD;
387*d58fda43Sjbeloro 	else
388*d58fda43Sjbeloro 		pmugpio_ptr->access_type = PMUGPIO_OTHER;
389*d58fda43Sjbeloro 
390*d58fda43Sjbeloro 	switch (pmugpio_ptr->access_type) {
391*d58fda43Sjbeloro 	case PMUGPIO_CPLD:
392*d58fda43Sjbeloro 	case PMUGPIO_MBC:
393*d58fda43Sjbeloro 		if (ddi_regs_map_setup(dip, 0,
394*d58fda43Sjbeloro 		    (caddr_t *)&pmugpio_ptr->pmugpio_reset_reg, 0, 1, &attr,
395*d58fda43Sjbeloro 		    &pmugpio_ptr->pmugpio_reset_reg_handle) != DDI_SUCCESS)
396*d58fda43Sjbeloro 			return (DDI_FAILURE);
397*d58fda43Sjbeloro 		/* MBC and CPLD have reset and watchdog bits in same reg. */
398*d58fda43Sjbeloro 		pmugpio_ptr->pmugpio_watchdog_reg_handle =
399*d58fda43Sjbeloro 			pmugpio_ptr->pmugpio_reset_reg_handle;
400*d58fda43Sjbeloro 		pmugpio_ptr->pmugpio_watchdog_reg =
401*d58fda43Sjbeloro 			pmugpio_ptr->pmugpio_reset_reg;
402*d58fda43Sjbeloro 		break;
403*d58fda43Sjbeloro 
404*d58fda43Sjbeloro 	case PMUGPIO_OTHER:
4057c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 1,
4067c478bd9Sstevel@tonic-gate 		    (caddr_t *)&pmugpio_ptr->pmugpio_watchdog_reg, 0, 1, &attr,
4077c478bd9Sstevel@tonic-gate 		    &pmugpio_ptr->pmugpio_watchdog_reg_handle) != DDI_SUCCESS) {
4087c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4097c478bd9Sstevel@tonic-gate 		}
4107c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 0,
4117c478bd9Sstevel@tonic-gate 		    (caddr_t *)&pmugpio_ptr->pmugpio_reset_reg, 0, 1, &attr,
4127c478bd9Sstevel@tonic-gate 		    &pmugpio_ptr->pmugpio_reset_reg_handle) != DDI_SUCCESS) {
413*d58fda43Sjbeloro 			ddi_regs_map_free(
414*d58fda43Sjbeloro 				&pmugpio_ptr->pmugpio_watchdog_reg_handle);
4157c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4167c478bd9Sstevel@tonic-gate 		}
417*d58fda43Sjbeloro 		break;
418*d58fda43Sjbeloro 
419*d58fda43Sjbeloro 	default:
420*d58fda43Sjbeloro 		cmn_err(CE_WARN, "pmugpio_map_regs: Invalid type");
421*d58fda43Sjbeloro 		return (DDI_FAILURE);
422*d58fda43Sjbeloro 	}
423*d58fda43Sjbeloro 
4247c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
4257c478bd9Sstevel@tonic-gate }
426