xref: /titanic_50/usr/src/uts/sun4u/io/pmugpio.c (revision 1bde0be88b435e0d708ac4f377f1a521530f2ebd)
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 /*
23d58fda43Sjbeloro  * 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 /*
39d58fda43Sjbeloro  * The pmugpio driver supports ALOM GPIO bits for resetSC and
40d58fda43Sjbeloro  * watchdog heartbeat on all relevant platforms.  Historically,
41d58fda43Sjbeloro  * pmugpio is a leaf off the Chalupa pmubus.  In addition to
42d58fda43Sjbeloro  * this support the pmugpio driver has been modified to support
43d58fda43Sjbeloro  * Minneapolis/Boston Controller (MBC) FPGA GPIO and Seattle CPLD
44d58fda43Sjbeloro  * GPIO.
45d58fda43Sjbeloro  */
46d58fda43Sjbeloro 
47d58fda43Sjbeloro typedef enum {
48d58fda43Sjbeloro 	PMUGPIO_MBC,		/* Boston MBC FPGA GPIO - 8-bit */
49d58fda43Sjbeloro 	PMUGPIO_CPLD,		/* Seattle CPLD GPIO - 8-bit */
50d58fda43Sjbeloro 	PMUGPIO_OTHER		/* Chalupa - 8-bit */
51d58fda43Sjbeloro } pmugpio_access_type_t;
52d58fda43Sjbeloro 
53d58fda43Sjbeloro /*
54*1bde0be8Sjroberts  * FWARC 2005/686: gpio device compatible property
55*1bde0be8Sjroberts  */
56*1bde0be8Sjroberts #define	PMUGPIO_DEVICE_TYPE "gpio-device-type"
57*1bde0be8Sjroberts 
58*1bde0be8Sjroberts /*
59d58fda43Sjbeloro  * CPLD GPIO Register defines.
60d58fda43Sjbeloro  */
61d58fda43Sjbeloro #define	CPLD_RESET_SC		0x01	/* Reset SC */
62d58fda43Sjbeloro #define	CPLD_WATCHDOG		0x02	/* Watchdog */
63d58fda43Sjbeloro 
64d58fda43Sjbeloro #define	CPLD_RESET_DELAY	3	/* microsecond delay */
65d58fda43Sjbeloro 
66d58fda43Sjbeloro /*
67d58fda43Sjbeloro  * MBC FPGA CSR defines.
68d58fda43Sjbeloro  */
69d58fda43Sjbeloro #define	MBC_PPC_RESET		0x10	/* Reset ALOM */
70d58fda43Sjbeloro #define	MBC_WATCHDOG		0x40	/* Watchdog heartbeat bit */
71d58fda43Sjbeloro 
72d58fda43Sjbeloro /*
737c478bd9Sstevel@tonic-gate  * Time periods, in nanoseconds
747c478bd9Sstevel@tonic-gate  */
757c478bd9Sstevel@tonic-gate #define	PMUGPIO_TWO_SEC		2000000000LL
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate static	dev_info_t	*pmugpio_dip;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate typedef struct pmugpio_state {
807c478bd9Sstevel@tonic-gate 	uint8_t			*pmugpio_reset_reg;
817c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	pmugpio_reset_reg_handle;
827c478bd9Sstevel@tonic-gate 	uint8_t			*pmugpio_watchdog_reg;
837c478bd9Sstevel@tonic-gate 	ddi_acc_handle_t	pmugpio_watchdog_reg_handle;
847c478bd9Sstevel@tonic-gate 	hrtime_t		hw_last_pat;
85d58fda43Sjbeloro 	pmugpio_access_type_t	access_type;
867c478bd9Sstevel@tonic-gate } pmugpio_state_t;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate static void *pmugpio_statep;
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate static int pmugpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
917c478bd9Sstevel@tonic-gate static int pmugpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
927c478bd9Sstevel@tonic-gate static int pmugpio_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
937c478bd9Sstevel@tonic-gate 		void **result);
947c478bd9Sstevel@tonic-gate static int pmugpio_map_regs(dev_info_t *, pmugpio_state_t *);
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate struct cb_ops pmugpio_cb_ops = {
977c478bd9Sstevel@tonic-gate 	nulldev,	/* open  */
987c478bd9Sstevel@tonic-gate 	nulldev,	/* close */
997c478bd9Sstevel@tonic-gate 	nulldev,	/* strategy */
1007c478bd9Sstevel@tonic-gate 	nulldev,	/* print */
1017c478bd9Sstevel@tonic-gate 	nulldev,	/* dump */
1027c478bd9Sstevel@tonic-gate 	nulldev,	/* read */
1037c478bd9Sstevel@tonic-gate 	nulldev,	/* write */
1047c478bd9Sstevel@tonic-gate 	nulldev,	/* ioctl */
1057c478bd9Sstevel@tonic-gate 	nulldev,	/* devmap */
1067c478bd9Sstevel@tonic-gate 	nulldev,	/* mmap */
1077c478bd9Sstevel@tonic-gate 	nulldev,	/* segmap */
1087c478bd9Sstevel@tonic-gate 	nochpoll,	/* poll */
1097c478bd9Sstevel@tonic-gate 	ddi_prop_op,	/* cb_prop_op */
1107c478bd9Sstevel@tonic-gate 	NULL,		/* streamtab  */
1117c478bd9Sstevel@tonic-gate 	D_MP | D_NEW
1127c478bd9Sstevel@tonic-gate };
1137c478bd9Sstevel@tonic-gate 
1147c478bd9Sstevel@tonic-gate static struct dev_ops pmugpio_ops = {
1157c478bd9Sstevel@tonic-gate 	DEVO_REV,		/* Devo_rev */
1167c478bd9Sstevel@tonic-gate 	0,			/* Refcnt */
1177c478bd9Sstevel@tonic-gate 	pmugpio_info,		/* Info */
1187c478bd9Sstevel@tonic-gate 	nulldev,		/* Identify */
1197c478bd9Sstevel@tonic-gate 	nulldev,		/* Probe */
1207c478bd9Sstevel@tonic-gate 	pmugpio_attach,		/* Attach */
1217c478bd9Sstevel@tonic-gate 	pmugpio_detach,		/* Detach */
1227c478bd9Sstevel@tonic-gate 	nodev,			/* Reset */
1237c478bd9Sstevel@tonic-gate 	&pmugpio_cb_ops,		/* Driver operations */
1247c478bd9Sstevel@tonic-gate 	0,			/* Bus operations */
1257c478bd9Sstevel@tonic-gate 	NULL			/* Power */
1267c478bd9Sstevel@tonic-gate };
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate static struct modldrv modldrv = {
1297c478bd9Sstevel@tonic-gate 	&mod_driverops, 		/* This one is a driver */
1307c478bd9Sstevel@tonic-gate 	"Pmugpio Driver %I%", 		/* Name of the module. */
1317c478bd9Sstevel@tonic-gate 	&pmugpio_ops,			/* Driver ops */
1327c478bd9Sstevel@tonic-gate };
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate static struct modlinkage modlinkage = {
1357c478bd9Sstevel@tonic-gate 	MODREV_1, (void *)&modldrv, NULL
1367c478bd9Sstevel@tonic-gate };
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate int
1397c478bd9Sstevel@tonic-gate _init(void)
1407c478bd9Sstevel@tonic-gate {
1417c478bd9Sstevel@tonic-gate 	int error;
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 	/* Initialize the soft state structures */
1447c478bd9Sstevel@tonic-gate 	if ((error = ddi_soft_state_init(&pmugpio_statep,
1457c478bd9Sstevel@tonic-gate 	    sizeof (pmugpio_state_t), 1)) != 0) {
1467c478bd9Sstevel@tonic-gate 		return (error);
1477c478bd9Sstevel@tonic-gate 	}
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	/* Install the loadable module */
1507c478bd9Sstevel@tonic-gate 	if ((error = mod_install(&modlinkage)) != 0) {
1517c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&pmugpio_statep);
1527c478bd9Sstevel@tonic-gate 	}
1537c478bd9Sstevel@tonic-gate 	return (error);
1547c478bd9Sstevel@tonic-gate }
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate int
1577c478bd9Sstevel@tonic-gate _info(struct modinfo *modinfop)
1587c478bd9Sstevel@tonic-gate {
1597c478bd9Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate int
1637c478bd9Sstevel@tonic-gate _fini(void)
1647c478bd9Sstevel@tonic-gate {
1657c478bd9Sstevel@tonic-gate 	int error;
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	error = mod_remove(&modlinkage);
1687c478bd9Sstevel@tonic-gate 	if (error == 0) {
1697c478bd9Sstevel@tonic-gate 		/* Release per module resources */
1707c478bd9Sstevel@tonic-gate 		ddi_soft_state_fini(&pmugpio_statep);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 	return (error);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate static int
1767c478bd9Sstevel@tonic-gate pmugpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1777c478bd9Sstevel@tonic-gate {
1787c478bd9Sstevel@tonic-gate 	int		instance;
1797c478bd9Sstevel@tonic-gate 	pmugpio_state_t	*pmugpio_ptr = NULL;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	switch (cmd) {
1827c478bd9Sstevel@tonic-gate 	case DDI_ATTACH:
1837c478bd9Sstevel@tonic-gate 		break;
1847c478bd9Sstevel@tonic-gate 	case DDI_RESUME:
1857c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
1867c478bd9Sstevel@tonic-gate 	default:
1877c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1887c478bd9Sstevel@tonic-gate 	}
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 	/* Get the instance and create soft state */
1917c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
1927c478bd9Sstevel@tonic-gate 	if (ddi_soft_state_zalloc(pmugpio_statep, instance) != 0) {
1937c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
1967c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
1977c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
1987c478bd9Sstevel@tonic-gate 	}
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	if (pmugpio_map_regs(dip, pmugpio_ptr) != DDI_SUCCESS) {
2017c478bd9Sstevel@tonic-gate 		ddi_soft_state_free(pmugpio_statep, instance);
2027c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	/* Display information in the banner */
2067c478bd9Sstevel@tonic-gate 	ddi_report_dev(dip);
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 	/* Save the dip */
2097c478bd9Sstevel@tonic-gate 	pmugpio_dip = dip;
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
2127c478bd9Sstevel@tonic-gate }
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate /* ARGSUSED */
2157c478bd9Sstevel@tonic-gate static int
2167c478bd9Sstevel@tonic-gate pmugpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2177c478bd9Sstevel@tonic-gate {
2187c478bd9Sstevel@tonic-gate 	/* Pointer to soft state */
2197c478bd9Sstevel@tonic-gate 	switch (cmd) {
2207c478bd9Sstevel@tonic-gate 	case DDI_SUSPEND:
2217c478bd9Sstevel@tonic-gate 		return (DDI_SUCCESS);
2227c478bd9Sstevel@tonic-gate 	default:
2237c478bd9Sstevel@tonic-gate 		return (DDI_FAILURE);
2247c478bd9Sstevel@tonic-gate 	}
2257c478bd9Sstevel@tonic-gate }
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate /* ARGSUSED */
2287c478bd9Sstevel@tonic-gate static int
2297c478bd9Sstevel@tonic-gate pmugpio_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
2307c478bd9Sstevel@tonic-gate 		void *arg, void **result)
2317c478bd9Sstevel@tonic-gate {
2327c478bd9Sstevel@tonic-gate 	dev_t dev;
2337c478bd9Sstevel@tonic-gate 	int instance, error;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	switch (infocmd) {
2367c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
2377c478bd9Sstevel@tonic-gate 		*result = (void *)pmugpio_dip;
2387c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
2397c478bd9Sstevel@tonic-gate 		break;
2407c478bd9Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
2417c478bd9Sstevel@tonic-gate 		dev = (dev_t)arg;
2427c478bd9Sstevel@tonic-gate 		instance = getminor(dev);
2437c478bd9Sstevel@tonic-gate 		*result = (void *)(uintptr_t)instance;
2447c478bd9Sstevel@tonic-gate 		error = DDI_SUCCESS;
2457c478bd9Sstevel@tonic-gate 		break;
2467c478bd9Sstevel@tonic-gate 	default:
2477c478bd9Sstevel@tonic-gate 		error = DDI_FAILURE;
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 	return (error);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate void
2537c478bd9Sstevel@tonic-gate pmugpio_watchdog_pat(void)
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pmugpio_dip;
2567c478bd9Sstevel@tonic-gate 	int instance;
2577c478bd9Sstevel@tonic-gate 	pmugpio_state_t *pmugpio_ptr;
2587c478bd9Sstevel@tonic-gate 	hrtime_t now;
2597c478bd9Sstevel@tonic-gate 	uint8_t value;
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
2627c478bd9Sstevel@tonic-gate 		return;
2637c478bd9Sstevel@tonic-gate 	}
2647c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
2657c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
2667c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
2677c478bd9Sstevel@tonic-gate 		return;
2687c478bd9Sstevel@tonic-gate 	}
2697c478bd9Sstevel@tonic-gate 	/*
2707c478bd9Sstevel@tonic-gate 	 * The RMC can read interrupts either high to low OR low to high. As
2717c478bd9Sstevel@tonic-gate 	 * a result all that needs to happen is that when we hit the time to
2727c478bd9Sstevel@tonic-gate 	 * send an signal we simply need to change the state.
2737c478bd9Sstevel@tonic-gate 	 */
2747c478bd9Sstevel@tonic-gate 	now = gethrtime();
2757c478bd9Sstevel@tonic-gate 	if ((now - pmugpio_ptr->hw_last_pat) >= PMUGPIO_TWO_SEC) {
2767c478bd9Sstevel@tonic-gate 		/*
2777c478bd9Sstevel@tonic-gate 		 * fetch current reg value and invert it
2787c478bd9Sstevel@tonic-gate 		 */
279d58fda43Sjbeloro 		switch (pmugpio_ptr->access_type) {
280d58fda43Sjbeloro 		case PMUGPIO_CPLD:
281d58fda43Sjbeloro 			value = (CPLD_WATCHDOG ^
282d58fda43Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
283d58fda43Sjbeloro 				pmugpio_ptr->pmugpio_watchdog_reg));
284d58fda43Sjbeloro 
285d58fda43Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
286d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
287d58fda43Sjbeloro 			break;
288d58fda43Sjbeloro 
289d58fda43Sjbeloro 		case PMUGPIO_MBC:
290d58fda43Sjbeloro 			value = (uint8_t)(MBC_WATCHDOG ^
291d58fda43Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
292d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg));
293d58fda43Sjbeloro 
294d58fda43Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
295d58fda43Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
296d58fda43Sjbeloro 			break;
297d58fda43Sjbeloro 
298d58fda43Sjbeloro 		case PMUGPIO_OTHER:
2997c478bd9Sstevel@tonic-gate 			value = (uint8_t)(0xff ^
3007c478bd9Sstevel@tonic-gate 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
3017c478bd9Sstevel@tonic-gate 			    pmugpio_ptr->pmugpio_watchdog_reg));
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
3047c478bd9Sstevel@tonic-gate 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
305d58fda43Sjbeloro 			break;
306d58fda43Sjbeloro 
307d58fda43Sjbeloro 		default:
308d58fda43Sjbeloro 			cmn_err(CE_WARN, "pmugpio_watchdog_pat: Invalid type");
309d58fda43Sjbeloro 		}
3107c478bd9Sstevel@tonic-gate 		pmugpio_ptr->hw_last_pat = now;
3117c478bd9Sstevel@tonic-gate 	}
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate void
3157c478bd9Sstevel@tonic-gate pmugpio_reset(void)
3167c478bd9Sstevel@tonic-gate {
3177c478bd9Sstevel@tonic-gate 	dev_info_t *dip = pmugpio_dip;
3187c478bd9Sstevel@tonic-gate 	int instance;
3197c478bd9Sstevel@tonic-gate 	pmugpio_state_t *pmugpio_ptr;
320d58fda43Sjbeloro 	uint8_t value;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	if (dip == NULL) {
3237c478bd9Sstevel@tonic-gate 		return;
3247c478bd9Sstevel@tonic-gate 	}
3257c478bd9Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
3267c478bd9Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
3277c478bd9Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
3287c478bd9Sstevel@tonic-gate 		return;
3297c478bd9Sstevel@tonic-gate 	}
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	/*
332d58fda43Sjbeloro 	 * For Chalupa, turn all bits on then off again - pmubus nexus
333d58fda43Sjbeloro 	 * will ensure that only unmasked bit is affected.
334d58fda43Sjbeloro 	 * For CPLD and MBC, turn just reset bit on, then off.
3357c478bd9Sstevel@tonic-gate 	 */
336d58fda43Sjbeloro 	switch (pmugpio_ptr->access_type) {
337d58fda43Sjbeloro 	case PMUGPIO_CPLD:
338d58fda43Sjbeloro 		value = ddi_get8(pmugpio_ptr->pmugpio_reset_reg_handle,
339d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg);
340d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
341d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, (value | CPLD_RESET_SC));
342d58fda43Sjbeloro 
343d58fda43Sjbeloro 		drv_usecwait(CPLD_RESET_DELAY);
344d58fda43Sjbeloro 
345d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
346d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, (value & ~CPLD_RESET_SC));
347d58fda43Sjbeloro 		break;
348d58fda43Sjbeloro 
349d58fda43Sjbeloro 	case PMUGPIO_MBC:
350d58fda43Sjbeloro 		value = ddi_get8(pmugpio_ptr->pmugpio_reset_reg_handle,
351d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg);
352d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
353d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg,
354d58fda43Sjbeloro 			(value | MBC_PPC_RESET));
355d58fda43Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
356d58fda43Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg,
357d58fda43Sjbeloro 			(value & ~MBC_PPC_RESET));
358d58fda43Sjbeloro 		break;
359d58fda43Sjbeloro 
360d58fda43Sjbeloro 	case PMUGPIO_OTHER:
3617c478bd9Sstevel@tonic-gate 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
3627c478bd9Sstevel@tonic-gate 		    pmugpio_ptr->pmugpio_reset_reg, ~0);
3637c478bd9Sstevel@tonic-gate 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
3647c478bd9Sstevel@tonic-gate 		    pmugpio_ptr->pmugpio_reset_reg, 0);
365d58fda43Sjbeloro 		break;
366d58fda43Sjbeloro 
367d58fda43Sjbeloro 	default:
368d58fda43Sjbeloro 		cmn_err(CE_WARN, "pmugpio_reset: Invalid type");
369d58fda43Sjbeloro 	}
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate static int
3737c478bd9Sstevel@tonic-gate pmugpio_map_regs(dev_info_t *dip, pmugpio_state_t *pmugpio_ptr)
3747c478bd9Sstevel@tonic-gate {
3757c478bd9Sstevel@tonic-gate 	ddi_device_acc_attr_t attr;
376*1bde0be8Sjroberts 	char *pmugpio_type;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	/* The host controller will be little endian */
3797c478bd9Sstevel@tonic-gate 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3807c478bd9Sstevel@tonic-gate 	attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
3817c478bd9Sstevel@tonic-gate 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3827c478bd9Sstevel@tonic-gate 
383d58fda43Sjbeloro 	/*
384*1bde0be8Sjroberts 	 * Determine access type per FWARC 2005/686.
385*1bde0be8Sjroberts 	 * For Boston and Seattle, the OBP gpio device contains a property
386*1bde0be8Sjroberts 	 * named "gpio-device-type".
387*1bde0be8Sjroberts 	 *
388*1bde0be8Sjroberts 	 * Boston:  gpio-device-type = SUNW,mbc
389*1bde0be8Sjroberts 	 * Seattle: gpio-device-type = SUNW,cpld
390*1bde0be8Sjroberts 	 *
391*1bde0be8Sjroberts 	 * If this property does not exist, we are a legacy Chalupa.
392d58fda43Sjbeloro 	 */
393*1bde0be8Sjroberts 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
394*1bde0be8Sjroberts 	    PMUGPIO_DEVICE_TYPE, &pmugpio_type) == DDI_PROP_SUCCESS) {
395*1bde0be8Sjroberts 		if (strcmp(pmugpio_type, "SUNW,mbc") == 0)
396d58fda43Sjbeloro 			pmugpio_ptr->access_type = PMUGPIO_MBC;
397*1bde0be8Sjroberts 		else if (strcmp(pmugpio_type, "SUNW,cpld") == 0)
398d58fda43Sjbeloro 			pmugpio_ptr->access_type = PMUGPIO_CPLD;
399*1bde0be8Sjroberts 		else {
400*1bde0be8Sjroberts 			cmn_err(CE_WARN, "unexpected gpio-device-type: %s\n",
401*1bde0be8Sjroberts 			    pmugpio_type);
402*1bde0be8Sjroberts 			ddi_prop_free(pmugpio_type);
403*1bde0be8Sjroberts 			return (DDI_FAILURE);
404*1bde0be8Sjroberts 		}
405*1bde0be8Sjroberts 		ddi_prop_free(pmugpio_type);
406*1bde0be8Sjroberts 	}
407d58fda43Sjbeloro 	else
408d58fda43Sjbeloro 		pmugpio_ptr->access_type = PMUGPIO_OTHER;
409d58fda43Sjbeloro 
410d58fda43Sjbeloro 	switch (pmugpio_ptr->access_type) {
411d58fda43Sjbeloro 	case PMUGPIO_CPLD:
412d58fda43Sjbeloro 	case PMUGPIO_MBC:
413d58fda43Sjbeloro 		if (ddi_regs_map_setup(dip, 0,
414d58fda43Sjbeloro 		    (caddr_t *)&pmugpio_ptr->pmugpio_reset_reg, 0, 1, &attr,
415d58fda43Sjbeloro 		    &pmugpio_ptr->pmugpio_reset_reg_handle) != DDI_SUCCESS)
416d58fda43Sjbeloro 			return (DDI_FAILURE);
417d58fda43Sjbeloro 		/* MBC and CPLD have reset and watchdog bits in same reg. */
418d58fda43Sjbeloro 		pmugpio_ptr->pmugpio_watchdog_reg_handle =
419d58fda43Sjbeloro 			pmugpio_ptr->pmugpio_reset_reg_handle;
420d58fda43Sjbeloro 		pmugpio_ptr->pmugpio_watchdog_reg =
421d58fda43Sjbeloro 			pmugpio_ptr->pmugpio_reset_reg;
422d58fda43Sjbeloro 		break;
423d58fda43Sjbeloro 
424d58fda43Sjbeloro 	case PMUGPIO_OTHER:
4257c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 1,
4267c478bd9Sstevel@tonic-gate 		    (caddr_t *)&pmugpio_ptr->pmugpio_watchdog_reg, 0, 1, &attr,
4277c478bd9Sstevel@tonic-gate 		    &pmugpio_ptr->pmugpio_watchdog_reg_handle) != DDI_SUCCESS) {
4287c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4297c478bd9Sstevel@tonic-gate 		}
4307c478bd9Sstevel@tonic-gate 		if (ddi_regs_map_setup(dip, 0,
4317c478bd9Sstevel@tonic-gate 		    (caddr_t *)&pmugpio_ptr->pmugpio_reset_reg, 0, 1, &attr,
4327c478bd9Sstevel@tonic-gate 		    &pmugpio_ptr->pmugpio_reset_reg_handle) != DDI_SUCCESS) {
433d58fda43Sjbeloro 			ddi_regs_map_free(
434d58fda43Sjbeloro 				&pmugpio_ptr->pmugpio_watchdog_reg_handle);
4357c478bd9Sstevel@tonic-gate 			return (DDI_FAILURE);
4367c478bd9Sstevel@tonic-gate 		}
437d58fda43Sjbeloro 		break;
438d58fda43Sjbeloro 
439d58fda43Sjbeloro 	default:
440d58fda43Sjbeloro 		cmn_err(CE_WARN, "pmugpio_map_regs: Invalid type");
441d58fda43Sjbeloro 		return (DDI_FAILURE);
442d58fda43Sjbeloro 	}
443d58fda43Sjbeloro 
4447c478bd9Sstevel@tonic-gate 	return (DDI_SUCCESS);
4457c478bd9Sstevel@tonic-gate }
446