xref: /titanic_50/usr/src/uts/sun4u/io/pmugpio.c (revision 193974072f41a843678abf5f61979c748687e66b)
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
5*19397407SSherry Moore  * Common Development and Distribution License (the "License").
6*19397407SSherry Moore  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*19397407SSherry Moore  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <sys/types.h>
287c478bd9Sstevel@tonic-gate #include <sys/conf.h>
297c478bd9Sstevel@tonic-gate #include <sys/ddi.h>
307c478bd9Sstevel@tonic-gate #include <sys/sunddi.h>
317c478bd9Sstevel@tonic-gate #include <sys/modctl.h>
327c478bd9Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
337c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
347c478bd9Sstevel@tonic-gate #include <sys/devops.h>
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate /*
37d58fda43Sjbeloro  * The pmugpio driver supports ALOM GPIO bits for resetSC and
38d58fda43Sjbeloro  * watchdog heartbeat on all relevant platforms.  Historically,
39d58fda43Sjbeloro  * pmugpio is a leaf off the Chalupa pmubus.  In addition to
40d58fda43Sjbeloro  * this support the pmugpio driver has been modified to support
41d58fda43Sjbeloro  * Minneapolis/Boston Controller (MBC) FPGA GPIO and Seattle CPLD
42d58fda43Sjbeloro  * GPIO.
43d58fda43Sjbeloro  */
44d58fda43Sjbeloro 
45d58fda43Sjbeloro typedef enum {
46d58fda43Sjbeloro 	PMUGPIO_MBC,		/* Boston MBC FPGA GPIO - 8-bit */
47d58fda43Sjbeloro 	PMUGPIO_CPLD,		/* Seattle CPLD GPIO - 8-bit */
48d58fda43Sjbeloro 	PMUGPIO_OTHER		/* Chalupa - 8-bit */
49d58fda43Sjbeloro } pmugpio_access_type_t;
50d58fda43Sjbeloro 
51d58fda43Sjbeloro /*
521bde0be8Sjroberts  * FWARC 2005/686: gpio device compatible property
531bde0be8Sjroberts  */
541bde0be8Sjroberts #define	PMUGPIO_DEVICE_TYPE "gpio-device-type"
551bde0be8Sjroberts 
561bde0be8Sjroberts /*
57d58fda43Sjbeloro  * CPLD GPIO Register defines.
58d58fda43Sjbeloro  */
59d58fda43Sjbeloro #define	CPLD_RESET_SC		0x01	/* Reset SC */
60d58fda43Sjbeloro #define	CPLD_WATCHDOG		0x02	/* Watchdog */
61d58fda43Sjbeloro 
62d58fda43Sjbeloro #define	CPLD_RESET_DELAY	3	/* microsecond delay */
63d58fda43Sjbeloro 
64d58fda43Sjbeloro /*
65d58fda43Sjbeloro  * MBC FPGA CSR defines.
66d58fda43Sjbeloro  */
67d58fda43Sjbeloro #define	MBC_PPC_RESET		0x10	/* Reset ALOM */
68d58fda43Sjbeloro #define	MBC_WATCHDOG		0x40	/* Watchdog heartbeat bit */
69d58fda43Sjbeloro 
70d58fda43Sjbeloro /*
717c478bd9Sstevel@tonic-gate  * Time periods, in nanoseconds
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate #define	PMUGPIO_TWO_SEC		2000000000LL
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static	dev_info_t	*pmugpio_dip;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate typedef struct pmugpio_state {
787c478bd9Sstevel@tonic-gate 	uint8_t			*pmugpio_reset_reg;
797c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	pmugpio_reset_reg_handle;
807c478bd9Sstevel@tonic-gate 	uint8_t			*pmugpio_watchdog_reg;
817c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	pmugpio_watchdog_reg_handle;
827c478bd9Sstevel@tonic-gate 	hrtime_t		hw_last_pat;
83d58fda43Sjbeloro 	pmugpio_access_type_t	access_type;
847c478bd9Sstevel@tonic-gate } pmugpio_state_t;
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate static void *pmugpio_statep;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static int pmugpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
897c478bd9Sstevel@tonic-gate static int pmugpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
907c478bd9Sstevel@tonic-gate static int pmugpio_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
917c478bd9Sstevel@tonic-gate 		void **result);
927c478bd9Sstevel@tonic-gate static int pmugpio_map_regs(dev_info_t *, pmugpio_state_t *);
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate struct cb_ops pmugpio_cb_ops = {
957c478bd9Sstevel@tonic-gate 	nulldev,	/* open  */
967c478bd9Sstevel@tonic-gate 	nulldev,	/* close */
977c478bd9Sstevel@tonic-gate 	nulldev,	/* strategy */
987c478bd9Sstevel@tonic-gate 	nulldev,	/* print */
997c478bd9Sstevel@tonic-gate 	nulldev,	/* dump */
1007c478bd9Sstevel@tonic-gate 	nulldev,	/* read */
1017c478bd9Sstevel@tonic-gate 	nulldev,	/* write */
1027c478bd9Sstevel@tonic-gate 	nulldev,	/* ioctl */
1037c478bd9Sstevel@tonic-gate 	nulldev,	/* devmap */
1047c478bd9Sstevel@tonic-gate 	nulldev,	/* mmap */
1057c478bd9Sstevel@tonic-gate 	nulldev,	/* segmap */
1067c478bd9Sstevel@tonic-gate 	nochpoll,	/* poll */
1077c478bd9Sstevel@tonic-gate 	ddi_prop_op,	/* cb_prop_op */
1087c478bd9Sstevel@tonic-gate 	NULL,		/* streamtab  */
1097c478bd9Sstevel@tonic-gate 	D_MP | D_NEW
1107c478bd9Sstevel@tonic-gate };
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate static struct dev_ops pmugpio_ops = {
1137c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* Devo_rev */
1147c478bd9Sstevel@tonic-gate 	0,			/* Refcnt */
1157c478bd9Sstevel@tonic-gate 	pmugpio_info,		/* Info */
1167c478bd9Sstevel@tonic-gate 	nulldev,		/* Identify */
1177c478bd9Sstevel@tonic-gate 	nulldev,		/* Probe */
1187c478bd9Sstevel@tonic-gate 	pmugpio_attach,		/* Attach */
1197c478bd9Sstevel@tonic-gate 	pmugpio_detach,		/* Detach */
1207c478bd9Sstevel@tonic-gate 	nodev,			/* Reset */
1217c478bd9Sstevel@tonic-gate 	&pmugpio_cb_ops,		/* Driver operations */
1227c478bd9Sstevel@tonic-gate 	0,			/* Bus operations */
123*19397407SSherry Moore 	NULL,			/* Power */
124*19397407SSherry Moore 	ddi_quiesce_not_supported,	/* devo_quiesce */
1257c478bd9Sstevel@tonic-gate };
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
1287c478bd9Sstevel@tonic-gate 	&mod_driverops, 		/* This one is a driver */
129*19397407SSherry Moore 	"Pmugpio Driver", 		/* Name of the module. */
1307c478bd9Sstevel@tonic-gate 	&pmugpio_ops,			/* Driver ops */
1317c478bd9Sstevel@tonic-gate };
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1347c478bd9Sstevel@tonic-gate 	MODREV_1, (void *)&modldrv, NULL
1357c478bd9Sstevel@tonic-gate };
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate int
_init(void)1387c478bd9Sstevel@tonic-gate _init(void)
1397c478bd9Sstevel@tonic-gate {
1407c478bd9Sstevel@tonic-gate 	int error;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	/* Initialize the soft state structures */
1437c478bd9Sstevel@tonic-gate 	if ((error = ddi_soft_state_init(&pmugpio_statep,
1447c478bd9Sstevel@tonic-gate 	    sizeof (pmugpio_state_t), 1)) != 0) {
1457c478bd9Sstevel@tonic-gate 		return (error);
1467c478bd9Sstevel@tonic-gate 	}
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	/* Install the loadable module */
1497c478bd9Sstevel@tonic-gate 	if ((error = mod_install(&modlinkage)) != 0) {
1507c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&pmugpio_statep);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 	return (error);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1567c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1577c478bd9Sstevel@tonic-gate {
1587c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate int
_fini(void)1627c478bd9Sstevel@tonic-gate _fini(void)
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate 	int error;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	error = mod_remove(&modlinkage);
1677c478bd9Sstevel@tonic-gate 	if (error == 0) {
1687c478bd9Sstevel@tonic-gate 		/* Release per module resources */
1697c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&pmugpio_statep);
1707c478bd9Sstevel@tonic-gate 	}
1717c478bd9Sstevel@tonic-gate 	return (error);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate static int
pmugpio_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1757c478bd9Sstevel@tonic-gate pmugpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1767c478bd9Sstevel@tonic-gate {
1777c478bd9Sstevel@tonic-gate 	int		instance;
1787c478bd9Sstevel@tonic-gate 	pmugpio_state_t	*pmugpio_ptr = NULL;
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate 	switch (cmd) {
1817c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
1827c478bd9Sstevel@tonic-gate 		break;
1837c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
1847c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
1857c478bd9Sstevel@tonic-gate 	default:
1867c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	/* Get the instance and create soft state */
1907c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
1917c478bd9Sstevel@tonic-gate 	if (ddi_soft_state_zalloc(pmugpio_statep, instance) != 0) {
1927c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1937c478bd9Sstevel@tonic-gate 	}
1947c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
1957c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
1967c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1977c478bd9Sstevel@tonic-gate 	}
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	if (pmugpio_map_regs(dip, pmugpio_ptr) != DDI_SUCCESS) {
2007c478bd9Sstevel@tonic-gate 		ddi_soft_state_free(pmugpio_statep, instance);
2017c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	/* Display information in the banner */
2057c478bd9Sstevel@tonic-gate 	ddi_report_dev(dip);
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	/* Save the dip */
2087c478bd9Sstevel@tonic-gate 	pmugpio_dip = dip;
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate /* ARGSUSED */
2147c478bd9Sstevel@tonic-gate static int
pmugpio_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2157c478bd9Sstevel@tonic-gate pmugpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2167c478bd9Sstevel@tonic-gate {
2177c478bd9Sstevel@tonic-gate 	/* Pointer to soft state */
2187c478bd9Sstevel@tonic-gate 	switch (cmd) {
2197c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
2207c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
2217c478bd9Sstevel@tonic-gate 	default:
2227c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2237c478bd9Sstevel@tonic-gate 	}
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate /* ARGSUSED */
2277c478bd9Sstevel@tonic-gate static int
pmugpio_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)2287c478bd9Sstevel@tonic-gate pmugpio_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
2297c478bd9Sstevel@tonic-gate 		void *arg, void **result)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	dev_t dev;
2327c478bd9Sstevel@tonic-gate 	int instance, error;
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	switch (infocmd) {
2357c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
2367c478bd9Sstevel@tonic-gate 		*result = (void *)pmugpio_dip;
2377c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
2387c478bd9Sstevel@tonic-gate 		break;
2397c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
2407c478bd9Sstevel@tonic-gate 		dev = (dev_t)arg;
2417c478bd9Sstevel@tonic-gate 		instance = getminor(dev);
2427c478bd9Sstevel@tonic-gate 		*result = (void *)(uintptr_t)instance;
2437c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
2447c478bd9Sstevel@tonic-gate 		break;
2457c478bd9Sstevel@tonic-gate 	default:
2467c478bd9Sstevel@tonic-gate 		error = DDI_FAILURE;
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate 	return (error);
2497c478bd9Sstevel@tonic-gate }
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate void
pmugpio_watchdog_pat(void)2527c478bd9Sstevel@tonic-gate pmugpio_watchdog_pat(void)
2537c478bd9Sstevel@tonic-gate {
2547c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pmugpio_dip;
2557c478bd9Sstevel@tonic-gate 	int instance;
2567c478bd9Sstevel@tonic-gate 	pmugpio_state_t *pmugpio_ptr;
2577c478bd9Sstevel@tonic-gate 	hrtime_t now;
2587c478bd9Sstevel@tonic-gate 	uint8_t value;
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
2617c478bd9Sstevel@tonic-gate 		return;
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
2647c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
2657c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
2667c478bd9Sstevel@tonic-gate 		return;
2677c478bd9Sstevel@tonic-gate 	}
2687c478bd9Sstevel@tonic-gate 	/*
2697c478bd9Sstevel@tonic-gate 	 * The RMC can read interrupts either high to low OR low to high. As
2707c478bd9Sstevel@tonic-gate 	 * a result all that needs to happen is that when we hit the time to
2717c478bd9Sstevel@tonic-gate 	 * send an signal we simply need to change the state.
2727c478bd9Sstevel@tonic-gate 	 */
2737c478bd9Sstevel@tonic-gate 	now = gethrtime();
2747c478bd9Sstevel@tonic-gate 	if ((now - pmugpio_ptr->hw_last_pat) >= PMUGPIO_TWO_SEC) {
2757c478bd9Sstevel@tonic-gate 		/*
2767c478bd9Sstevel@tonic-gate 		 * fetch current reg value and invert it
2777c478bd9Sstevel@tonic-gate 		 */
278d58fda43Sjbeloro 		switch (pmugpio_ptr->access_type) {
279d58fda43Sjbeloro 		case PMUGPIO_CPLD:
280d58fda43Sjbeloro 			value = (CPLD_WATCHDOG ^
281d58fda43Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
282d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg));
283d58fda43Sjbeloro 
284d58fda43Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
285d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
286d58fda43Sjbeloro 			break;
287d58fda43Sjbeloro 
288d58fda43Sjbeloro 		case PMUGPIO_MBC:
289d58fda43Sjbeloro 			value = (uint8_t)(MBC_WATCHDOG ^
290d58fda43Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
291d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg));
292d58fda43Sjbeloro 
293d58fda43Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
294d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
295d58fda43Sjbeloro 			break;
296d58fda43Sjbeloro 
297d58fda43Sjbeloro 		case PMUGPIO_OTHER:
2987c478bd9Sstevel@tonic-gate 			value = (uint8_t)(0xff ^
2997c478bd9Sstevel@tonic-gate 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
3007c478bd9Sstevel@tonic-gate 			    pmugpio_ptr->pmugpio_watchdog_reg));
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
3037c478bd9Sstevel@tonic-gate 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
304d58fda43Sjbeloro 			break;
305d58fda43Sjbeloro 
306d58fda43Sjbeloro 		default:
307d58fda43Sjbeloro 			cmn_err(CE_WARN, "pmugpio_watchdog_pat: Invalid type");
308d58fda43Sjbeloro 		}
3097c478bd9Sstevel@tonic-gate 		pmugpio_ptr->hw_last_pat = now;
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate void
pmugpio_reset(void)3147c478bd9Sstevel@tonic-gate pmugpio_reset(void)
3157c478bd9Sstevel@tonic-gate {
3167c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pmugpio_dip;
3177c478bd9Sstevel@tonic-gate 	int instance;
3187c478bd9Sstevel@tonic-gate 	pmugpio_state_t *pmugpio_ptr;
319d58fda43Sjbeloro 	uint8_t value;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
3227c478bd9Sstevel@tonic-gate 		return;
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
3257c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
3267c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
3277c478bd9Sstevel@tonic-gate 		return;
3287c478bd9Sstevel@tonic-gate 	}
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/*
331d58fda43Sjbeloro 	 * For Chalupa, turn all bits on then off again - pmubus nexus
332d58fda43Sjbeloro 	 * will ensure that only unmasked bit is affected.
333d58fda43Sjbeloro 	 * For CPLD and MBC, turn just reset bit on, then off.
3347c478bd9Sstevel@tonic-gate 	 */
335d58fda43Sjbeloro 	switch (pmugpio_ptr->access_type) {
336d58fda43Sjbeloro 	case PMUGPIO_CPLD:
337d58fda43Sjbeloro 		value = ddi_get8(pmugpio_ptr->pmugpio_reset_reg_handle,
338d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg);
339d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
340d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, (value | CPLD_RESET_SC));
341d58fda43Sjbeloro 
342d58fda43Sjbeloro 		drv_usecwait(CPLD_RESET_DELAY);
343d58fda43Sjbeloro 
344d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
345d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, (value & ~CPLD_RESET_SC));
346d58fda43Sjbeloro 		break;
347d58fda43Sjbeloro 
348d58fda43Sjbeloro 	case PMUGPIO_MBC:
349d58fda43Sjbeloro 		value = ddi_get8(pmugpio_ptr->pmugpio_reset_reg_handle,
350d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg);
351d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
352d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg,
353d58fda43Sjbeloro 		    (value | MBC_PPC_RESET));
354d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
355d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg,
356d58fda43Sjbeloro 		    (value & ~MBC_PPC_RESET));
357d58fda43Sjbeloro 		break;
358d58fda43Sjbeloro 
359d58fda43Sjbeloro 	case PMUGPIO_OTHER:
3607c478bd9Sstevel@tonic-gate 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
3617c478bd9Sstevel@tonic-gate 		    pmugpio_ptr->pmugpio_reset_reg, ~0);
3627c478bd9Sstevel@tonic-gate 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
3637c478bd9Sstevel@tonic-gate 		    pmugpio_ptr->pmugpio_reset_reg, 0);
364d58fda43Sjbeloro 		break;
365d58fda43Sjbeloro 
366d58fda43Sjbeloro 	default:
367d58fda43Sjbeloro 		cmn_err(CE_WARN, "pmugpio_reset: Invalid type");
368d58fda43Sjbeloro 	}
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate static int
pmugpio_map_regs(dev_info_t * dip,pmugpio_state_t * pmugpio_ptr)3727c478bd9Sstevel@tonic-gate pmugpio_map_regs(dev_info_t *dip, pmugpio_state_t *pmugpio_ptr)
3737c478bd9Sstevel@tonic-gate {
3747c478bd9Sstevel@tonic-gate 	ddi_device_acc_attr_t attr;
3751bde0be8Sjroberts 	char *pmugpio_type;
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	/* The host controller will be little endian */
3787c478bd9Sstevel@tonic-gate 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3797c478bd9Sstevel@tonic-gate 	attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
3807c478bd9Sstevel@tonic-gate 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3817c478bd9Sstevel@tonic-gate 
382d58fda43Sjbeloro 	/*
3831bde0be8Sjroberts 	 * Determine access type per FWARC 2005/686.
3841bde0be8Sjroberts 	 * For Boston and Seattle, the OBP gpio device contains a property
3851bde0be8Sjroberts 	 * named "gpio-device-type".
3861bde0be8Sjroberts 	 *
3871bde0be8Sjroberts 	 * Boston:  gpio-device-type = SUNW,mbc
3881bde0be8Sjroberts 	 * Seattle: gpio-device-type = SUNW,cpld
3891bde0be8Sjroberts 	 *
3901bde0be8Sjroberts 	 * If this property does not exist, we are a legacy Chalupa.
391d58fda43Sjbeloro 	 */
3921bde0be8Sjroberts 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3931bde0be8Sjroberts 	    PMUGPIO_DEVICE_TYPE, &pmugpio_type) == DDI_PROP_SUCCESS) {
3941bde0be8Sjroberts 		if (strcmp(pmugpio_type, "SUNW,mbc") == 0)
395d58fda43Sjbeloro 			pmugpio_ptr->access_type = PMUGPIO_MBC;
3961bde0be8Sjroberts 		else if (strcmp(pmugpio_type, "SUNW,cpld") == 0)
397d58fda43Sjbeloro 			pmugpio_ptr->access_type = PMUGPIO_CPLD;
3981bde0be8Sjroberts 		else {
3991bde0be8Sjroberts 			cmn_err(CE_WARN, "unexpected gpio-device-type: %s\n",
4001bde0be8Sjroberts 			    pmugpio_type);
4011bde0be8Sjroberts 			ddi_prop_free(pmugpio_type);
4021bde0be8Sjroberts 			return (DDI_FAILURE);
4031bde0be8Sjroberts 		}
4041bde0be8Sjroberts 		ddi_prop_free(pmugpio_type);
4051bde0be8Sjroberts 	}
406d58fda43Sjbeloro 	else
407d58fda43Sjbeloro 		pmugpio_ptr->access_type = PMUGPIO_OTHER;
408d58fda43Sjbeloro 
409d58fda43Sjbeloro 	switch (pmugpio_ptr->access_type) {
410d58fda43Sjbeloro 	case PMUGPIO_CPLD:
411d58fda43Sjbeloro 	case PMUGPIO_MBC:
412d58fda43Sjbeloro 		if (ddi_regs_map_setup(dip, 0,
413d58fda43Sjbeloro 		    (caddr_t *)&pmugpio_ptr->pmugpio_reset_reg, 0, 1, &attr,
414d58fda43Sjbeloro 		    &pmugpio_ptr->pmugpio_reset_reg_handle) != DDI_SUCCESS)
415d58fda43Sjbeloro 			return (DDI_FAILURE);
416d58fda43Sjbeloro 		/* MBC and CPLD have reset and watchdog bits in same reg. */
417d58fda43Sjbeloro 		pmugpio_ptr->pmugpio_watchdog_reg_handle =
418d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg_handle;
419d58fda43Sjbeloro 		pmugpio_ptr->pmugpio_watchdog_reg =
420d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg;
421d58fda43Sjbeloro 		break;
422d58fda43Sjbeloro 
423d58fda43Sjbeloro 	case PMUGPIO_OTHER:
4247c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 1,
4257c478bd9Sstevel@tonic-gate 		    (caddr_t *)&pmugpio_ptr->pmugpio_watchdog_reg, 0, 1, &attr,
4267c478bd9Sstevel@tonic-gate 		    &pmugpio_ptr->pmugpio_watchdog_reg_handle) != DDI_SUCCESS) {
4277c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4287c478bd9Sstevel@tonic-gate 		}
4297c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 0,
4307c478bd9Sstevel@tonic-gate 		    (caddr_t *)&pmugpio_ptr->pmugpio_reset_reg, 0, 1, &attr,
4317c478bd9Sstevel@tonic-gate 		    &pmugpio_ptr->pmugpio_reset_reg_handle) != DDI_SUCCESS) {
432d58fda43Sjbeloro 			ddi_regs_map_free(
433d58fda43Sjbeloro 			    &pmugpio_ptr->pmugpio_watchdog_reg_handle);
4347c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4357c478bd9Sstevel@tonic-gate 		}
436d58fda43Sjbeloro 		break;
437d58fda43Sjbeloro 
438d58fda43Sjbeloro 	default:
439d58fda43Sjbeloro 		cmn_err(CE_WARN, "pmugpio_map_regs: Invalid type");
440d58fda43Sjbeloro 		return (DDI_FAILURE);
441d58fda43Sjbeloro 	}
442d58fda43Sjbeloro 
4437c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
4447c478bd9Sstevel@tonic-gate }
445