xref: /onnv-gate/usr/src/uts/sun4u/io/pmugpio.c (revision 7656:2621e50fdf4a)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7656SSherry.Moore@Sun.COM  * Common Development and Distribution License (the "License").
6*7656SSherry.Moore@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*7656SSherry.Moore@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <sys/types.h>
280Sstevel@tonic-gate #include <sys/conf.h>
290Sstevel@tonic-gate #include <sys/ddi.h>
300Sstevel@tonic-gate #include <sys/sunddi.h>
310Sstevel@tonic-gate #include <sys/modctl.h>
320Sstevel@tonic-gate #include <sys/ddi_impldefs.h>
330Sstevel@tonic-gate #include <sys/kmem.h>
340Sstevel@tonic-gate #include <sys/devops.h>
350Sstevel@tonic-gate 
360Sstevel@tonic-gate /*
37920Sjbeloro  * The pmugpio driver supports ALOM GPIO bits for resetSC and
38920Sjbeloro  * watchdog heartbeat on all relevant platforms.  Historically,
39920Sjbeloro  * pmugpio is a leaf off the Chalupa pmubus.  In addition to
40920Sjbeloro  * this support the pmugpio driver has been modified to support
41920Sjbeloro  * Minneapolis/Boston Controller (MBC) FPGA GPIO and Seattle CPLD
42920Sjbeloro  * GPIO.
43920Sjbeloro  */
44920Sjbeloro 
45920Sjbeloro typedef enum {
46920Sjbeloro 	PMUGPIO_MBC,		/* Boston MBC FPGA GPIO - 8-bit */
47920Sjbeloro 	PMUGPIO_CPLD,		/* Seattle CPLD GPIO - 8-bit */
48920Sjbeloro 	PMUGPIO_OTHER		/* Chalupa - 8-bit */
49920Sjbeloro } pmugpio_access_type_t;
50920Sjbeloro 
51920Sjbeloro /*
521084Sjroberts  * FWARC 2005/686: gpio device compatible property
531084Sjroberts  */
541084Sjroberts #define	PMUGPIO_DEVICE_TYPE "gpio-device-type"
551084Sjroberts 
561084Sjroberts /*
57920Sjbeloro  * CPLD GPIO Register defines.
58920Sjbeloro  */
59920Sjbeloro #define	CPLD_RESET_SC		0x01	/* Reset SC */
60920Sjbeloro #define	CPLD_WATCHDOG		0x02	/* Watchdog */
61920Sjbeloro 
62920Sjbeloro #define	CPLD_RESET_DELAY	3	/* microsecond delay */
63920Sjbeloro 
64920Sjbeloro /*
65920Sjbeloro  * MBC FPGA CSR defines.
66920Sjbeloro  */
67920Sjbeloro #define	MBC_PPC_RESET		0x10	/* Reset ALOM */
68920Sjbeloro #define	MBC_WATCHDOG		0x40	/* Watchdog heartbeat bit */
69920Sjbeloro 
70920Sjbeloro /*
710Sstevel@tonic-gate  * Time periods, in nanoseconds
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate #define	PMUGPIO_TWO_SEC		2000000000LL
740Sstevel@tonic-gate 
750Sstevel@tonic-gate static	dev_info_t	*pmugpio_dip;
760Sstevel@tonic-gate 
770Sstevel@tonic-gate typedef struct pmugpio_state {
780Sstevel@tonic-gate 	uint8_t			*pmugpio_reset_reg;
790Sstevel@tonic-gate 	ddi_acc_handle_t	pmugpio_reset_reg_handle;
800Sstevel@tonic-gate 	uint8_t			*pmugpio_watchdog_reg;
810Sstevel@tonic-gate 	ddi_acc_handle_t	pmugpio_watchdog_reg_handle;
820Sstevel@tonic-gate 	hrtime_t		hw_last_pat;
83920Sjbeloro 	pmugpio_access_type_t	access_type;
840Sstevel@tonic-gate } pmugpio_state_t;
850Sstevel@tonic-gate 
860Sstevel@tonic-gate static void *pmugpio_statep;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate static int pmugpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
890Sstevel@tonic-gate static int pmugpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
900Sstevel@tonic-gate static int pmugpio_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
910Sstevel@tonic-gate 		void **result);
920Sstevel@tonic-gate static int pmugpio_map_regs(dev_info_t *, pmugpio_state_t *);
930Sstevel@tonic-gate 
940Sstevel@tonic-gate struct cb_ops pmugpio_cb_ops = {
950Sstevel@tonic-gate 	nulldev,	/* open  */
960Sstevel@tonic-gate 	nulldev,	/* close */
970Sstevel@tonic-gate 	nulldev,	/* strategy */
980Sstevel@tonic-gate 	nulldev,	/* print */
990Sstevel@tonic-gate 	nulldev,	/* dump */
1000Sstevel@tonic-gate 	nulldev,	/* read */
1010Sstevel@tonic-gate 	nulldev,	/* write */
1020Sstevel@tonic-gate 	nulldev,	/* ioctl */
1030Sstevel@tonic-gate 	nulldev,	/* devmap */
1040Sstevel@tonic-gate 	nulldev,	/* mmap */
1050Sstevel@tonic-gate 	nulldev,	/* segmap */
1060Sstevel@tonic-gate 	nochpoll,	/* poll */
1070Sstevel@tonic-gate 	ddi_prop_op,	/* cb_prop_op */
1080Sstevel@tonic-gate 	NULL,		/* streamtab  */
1090Sstevel@tonic-gate 	D_MP | D_NEW
1100Sstevel@tonic-gate };
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate static struct dev_ops pmugpio_ops = {
1130Sstevel@tonic-gate 	DEVO_REV,		/* Devo_rev */
1140Sstevel@tonic-gate 	0,			/* Refcnt */
1150Sstevel@tonic-gate 	pmugpio_info,		/* Info */
1160Sstevel@tonic-gate 	nulldev,		/* Identify */
1170Sstevel@tonic-gate 	nulldev,		/* Probe */
1180Sstevel@tonic-gate 	pmugpio_attach,		/* Attach */
1190Sstevel@tonic-gate 	pmugpio_detach,		/* Detach */
1200Sstevel@tonic-gate 	nodev,			/* Reset */
1210Sstevel@tonic-gate 	&pmugpio_cb_ops,		/* Driver operations */
1220Sstevel@tonic-gate 	0,			/* Bus operations */
123*7656SSherry.Moore@Sun.COM 	NULL,			/* Power */
124*7656SSherry.Moore@Sun.COM 	ddi_quiesce_not_supported,	/* devo_quiesce */
1250Sstevel@tonic-gate };
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate static struct modldrv modldrv = {
1280Sstevel@tonic-gate 	&mod_driverops, 		/* This one is a driver */
129*7656SSherry.Moore@Sun.COM 	"Pmugpio Driver", 		/* Name of the module. */
1300Sstevel@tonic-gate 	&pmugpio_ops,			/* Driver ops */
1310Sstevel@tonic-gate };
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate static struct modlinkage modlinkage = {
1340Sstevel@tonic-gate 	MODREV_1, (void *)&modldrv, NULL
1350Sstevel@tonic-gate };
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate int
_init(void)1380Sstevel@tonic-gate _init(void)
1390Sstevel@tonic-gate {
1400Sstevel@tonic-gate 	int error;
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	/* Initialize the soft state structures */
1430Sstevel@tonic-gate 	if ((error = ddi_soft_state_init(&pmugpio_statep,
1440Sstevel@tonic-gate 	    sizeof (pmugpio_state_t), 1)) != 0) {
1450Sstevel@tonic-gate 		return (error);
1460Sstevel@tonic-gate 	}
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	/* Install the loadable module */
1490Sstevel@tonic-gate 	if ((error = mod_install(&modlinkage)) != 0) {
1500Sstevel@tonic-gate 		ddi_soft_state_fini(&pmugpio_statep);
1510Sstevel@tonic-gate 	}
1520Sstevel@tonic-gate 	return (error);
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate int
_info(struct modinfo * modinfop)1560Sstevel@tonic-gate _info(struct modinfo *modinfop)
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate 	return (mod_info(&modlinkage, modinfop));
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate int
_fini(void)1620Sstevel@tonic-gate _fini(void)
1630Sstevel@tonic-gate {
1640Sstevel@tonic-gate 	int error;
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 	error = mod_remove(&modlinkage);
1670Sstevel@tonic-gate 	if (error == 0) {
1680Sstevel@tonic-gate 		/* Release per module resources */
1690Sstevel@tonic-gate 		ddi_soft_state_fini(&pmugpio_statep);
1700Sstevel@tonic-gate 	}
1710Sstevel@tonic-gate 	return (error);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate static int
pmugpio_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1750Sstevel@tonic-gate pmugpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1760Sstevel@tonic-gate {
1770Sstevel@tonic-gate 	int		instance;
1780Sstevel@tonic-gate 	pmugpio_state_t	*pmugpio_ptr = NULL;
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	switch (cmd) {
1810Sstevel@tonic-gate 	case DDI_ATTACH:
1820Sstevel@tonic-gate 		break;
1830Sstevel@tonic-gate 	case DDI_RESUME:
1840Sstevel@tonic-gate 		return (DDI_SUCCESS);
1850Sstevel@tonic-gate 	default:
1860Sstevel@tonic-gate 		return (DDI_FAILURE);
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	/* Get the instance and create soft state */
1900Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
1910Sstevel@tonic-gate 	if (ddi_soft_state_zalloc(pmugpio_statep, instance) != 0) {
1920Sstevel@tonic-gate 		return (DDI_FAILURE);
1930Sstevel@tonic-gate 	}
1940Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
1950Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
1960Sstevel@tonic-gate 		return (DDI_FAILURE);
1970Sstevel@tonic-gate 	}
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	if (pmugpio_map_regs(dip, pmugpio_ptr) != DDI_SUCCESS) {
2000Sstevel@tonic-gate 		ddi_soft_state_free(pmugpio_statep, instance);
2010Sstevel@tonic-gate 		return (DDI_FAILURE);
2020Sstevel@tonic-gate 	}
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	/* Display information in the banner */
2050Sstevel@tonic-gate 	ddi_report_dev(dip);
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	/* Save the dip */
2080Sstevel@tonic-gate 	pmugpio_dip = dip;
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 	return (DDI_SUCCESS);
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate /* ARGSUSED */
2140Sstevel@tonic-gate static int
pmugpio_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)2150Sstevel@tonic-gate pmugpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
2160Sstevel@tonic-gate {
2170Sstevel@tonic-gate 	/* Pointer to soft state */
2180Sstevel@tonic-gate 	switch (cmd) {
2190Sstevel@tonic-gate 	case DDI_SUSPEND:
2200Sstevel@tonic-gate 		return (DDI_SUCCESS);
2210Sstevel@tonic-gate 	default:
2220Sstevel@tonic-gate 		return (DDI_FAILURE);
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate /* ARGSUSED */
2270Sstevel@tonic-gate static int
pmugpio_info(dev_info_t * dip,ddi_info_cmd_t infocmd,void * arg,void ** result)2280Sstevel@tonic-gate pmugpio_info(dev_info_t *dip, ddi_info_cmd_t infocmd,
2290Sstevel@tonic-gate 		void *arg, void **result)
2300Sstevel@tonic-gate {
2310Sstevel@tonic-gate 	dev_t dev;
2320Sstevel@tonic-gate 	int instance, error;
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	switch (infocmd) {
2350Sstevel@tonic-gate 	case DDI_INFO_DEVT2DEVINFO:
2360Sstevel@tonic-gate 		*result = (void *)pmugpio_dip;
2370Sstevel@tonic-gate 		error = DDI_SUCCESS;
2380Sstevel@tonic-gate 		break;
2390Sstevel@tonic-gate 	case DDI_INFO_DEVT2INSTANCE:
2400Sstevel@tonic-gate 		dev = (dev_t)arg;
2410Sstevel@tonic-gate 		instance = getminor(dev);
2420Sstevel@tonic-gate 		*result = (void *)(uintptr_t)instance;
2430Sstevel@tonic-gate 		error = DDI_SUCCESS;
2440Sstevel@tonic-gate 		break;
2450Sstevel@tonic-gate 	default:
2460Sstevel@tonic-gate 		error = DDI_FAILURE;
2470Sstevel@tonic-gate 	}
2480Sstevel@tonic-gate 	return (error);
2490Sstevel@tonic-gate }
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate void
pmugpio_watchdog_pat(void)2520Sstevel@tonic-gate pmugpio_watchdog_pat(void)
2530Sstevel@tonic-gate {
2540Sstevel@tonic-gate 	dev_info_t *dip = pmugpio_dip;
2550Sstevel@tonic-gate 	int instance;
2560Sstevel@tonic-gate 	pmugpio_state_t *pmugpio_ptr;
2570Sstevel@tonic-gate 	hrtime_t now;
2580Sstevel@tonic-gate 	uint8_t value;
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 	if (dip == NULL) {
2610Sstevel@tonic-gate 		return;
2620Sstevel@tonic-gate 	}
2630Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
2640Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
2650Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
2660Sstevel@tonic-gate 		return;
2670Sstevel@tonic-gate 	}
2680Sstevel@tonic-gate 	/*
2690Sstevel@tonic-gate 	 * The RMC can read interrupts either high to low OR low to high. As
2700Sstevel@tonic-gate 	 * a result all that needs to happen is that when we hit the time to
2710Sstevel@tonic-gate 	 * send an signal we simply need to change the state.
2720Sstevel@tonic-gate 	 */
2730Sstevel@tonic-gate 	now = gethrtime();
2740Sstevel@tonic-gate 	if ((now - pmugpio_ptr->hw_last_pat) >= PMUGPIO_TWO_SEC) {
2750Sstevel@tonic-gate 		/*
2760Sstevel@tonic-gate 		 * fetch current reg value and invert it
2770Sstevel@tonic-gate 		 */
278920Sjbeloro 		switch (pmugpio_ptr->access_type) {
279920Sjbeloro 		case PMUGPIO_CPLD:
280920Sjbeloro 			value = (CPLD_WATCHDOG ^
281920Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
282*7656SSherry.Moore@Sun.COM 			    pmugpio_ptr->pmugpio_watchdog_reg));
283920Sjbeloro 
284920Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
285920Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
286920Sjbeloro 			break;
287920Sjbeloro 
288920Sjbeloro 		case PMUGPIO_MBC:
289920Sjbeloro 			value = (uint8_t)(MBC_WATCHDOG ^
290920Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
291920Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg));
2920Sstevel@tonic-gate 
293920Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
294920Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
295920Sjbeloro 			break;
296920Sjbeloro 
297920Sjbeloro 		case PMUGPIO_OTHER:
298920Sjbeloro 			value = (uint8_t)(0xff ^
299920Sjbeloro 			    ddi_get8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
300920Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg));
301920Sjbeloro 
302920Sjbeloro 			ddi_put8(pmugpio_ptr->pmugpio_watchdog_reg_handle,
303920Sjbeloro 			    pmugpio_ptr->pmugpio_watchdog_reg, value);
304920Sjbeloro 			break;
305920Sjbeloro 
306920Sjbeloro 		default:
307920Sjbeloro 			cmn_err(CE_WARN, "pmugpio_watchdog_pat: Invalid type");
308920Sjbeloro 		}
3090Sstevel@tonic-gate 		pmugpio_ptr->hw_last_pat = now;
3100Sstevel@tonic-gate 	}
3110Sstevel@tonic-gate }
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate void
pmugpio_reset(void)3140Sstevel@tonic-gate pmugpio_reset(void)
3150Sstevel@tonic-gate {
3160Sstevel@tonic-gate 	dev_info_t *dip = pmugpio_dip;
3170Sstevel@tonic-gate 	int instance;
3180Sstevel@tonic-gate 	pmugpio_state_t *pmugpio_ptr;
319920Sjbeloro 	uint8_t value;
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 	if (dip == NULL) {
3220Sstevel@tonic-gate 		return;
3230Sstevel@tonic-gate 	}
3240Sstevel@tonic-gate 	instance = ddi_get_instance(dip);
3250Sstevel@tonic-gate 	pmugpio_ptr = ddi_get_soft_state(pmugpio_statep, instance);
3260Sstevel@tonic-gate 	if (pmugpio_ptr == NULL) {
3270Sstevel@tonic-gate 		return;
3280Sstevel@tonic-gate 	}
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate 	/*
331920Sjbeloro 	 * For Chalupa, turn all bits on then off again - pmubus nexus
332920Sjbeloro 	 * will ensure that only unmasked bit is affected.
333920Sjbeloro 	 * For CPLD and MBC, turn just reset bit on, then off.
3340Sstevel@tonic-gate 	 */
335920Sjbeloro 	switch (pmugpio_ptr->access_type) {
336920Sjbeloro 	case PMUGPIO_CPLD:
337920Sjbeloro 		value = ddi_get8(pmugpio_ptr->pmugpio_reset_reg_handle,
338920Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg);
339920Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
340920Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, (value | CPLD_RESET_SC));
341920Sjbeloro 
342920Sjbeloro 		drv_usecwait(CPLD_RESET_DELAY);
343920Sjbeloro 
344920Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
345920Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, (value & ~CPLD_RESET_SC));
346920Sjbeloro 		break;
347920Sjbeloro 
348920Sjbeloro 	case PMUGPIO_MBC:
349920Sjbeloro 		value = ddi_get8(pmugpio_ptr->pmugpio_reset_reg_handle,
350920Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg);
351920Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
352920Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg,
353*7656SSherry.Moore@Sun.COM 		    (value | MBC_PPC_RESET));
354920Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
355920Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg,
356*7656SSherry.Moore@Sun.COM 		    (value & ~MBC_PPC_RESET));
357920Sjbeloro 		break;
358920Sjbeloro 
359920Sjbeloro 	case PMUGPIO_OTHER:
360920Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
361920Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, ~0);
362920Sjbeloro 		ddi_put8(pmugpio_ptr->pmugpio_reset_reg_handle,
363920Sjbeloro 		    pmugpio_ptr->pmugpio_reset_reg, 0);
364920Sjbeloro 		break;
365920Sjbeloro 
366920Sjbeloro 	default:
367920Sjbeloro 		cmn_err(CE_WARN, "pmugpio_reset: Invalid type");
368920Sjbeloro 	}
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate static int
pmugpio_map_regs(dev_info_t * dip,pmugpio_state_t * pmugpio_ptr)3720Sstevel@tonic-gate pmugpio_map_regs(dev_info_t *dip, pmugpio_state_t *pmugpio_ptr)
3730Sstevel@tonic-gate {
3740Sstevel@tonic-gate 	ddi_device_acc_attr_t attr;
3751084Sjroberts 	char *pmugpio_type;
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	/* The host controller will be little endian */
3780Sstevel@tonic-gate 	attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
3790Sstevel@tonic-gate 	attr.devacc_attr_endian_flags  = DDI_STRUCTURE_LE_ACC;
3800Sstevel@tonic-gate 	attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
3810Sstevel@tonic-gate 
382920Sjbeloro 	/*
3831084Sjroberts 	 * Determine access type per FWARC 2005/686.
3841084Sjroberts 	 * For Boston and Seattle, the OBP gpio device contains a property
3851084Sjroberts 	 * named "gpio-device-type".
3861084Sjroberts 	 *
3871084Sjroberts 	 * Boston:  gpio-device-type = SUNW,mbc
3881084Sjroberts 	 * Seattle: gpio-device-type = SUNW,cpld
3891084Sjroberts 	 *
3901084Sjroberts 	 * If this property does not exist, we are a legacy Chalupa.
391920Sjbeloro 	 */
3921084Sjroberts 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
3931084Sjroberts 	    PMUGPIO_DEVICE_TYPE, &pmugpio_type) == DDI_PROP_SUCCESS) {
3941084Sjroberts 		if (strcmp(pmugpio_type, "SUNW,mbc") == 0)
3951084Sjroberts 			pmugpio_ptr->access_type = PMUGPIO_MBC;
3961084Sjroberts 		else if (strcmp(pmugpio_type, "SUNW,cpld") == 0)
3971084Sjroberts 			pmugpio_ptr->access_type = PMUGPIO_CPLD;
3981084Sjroberts 		else {
3991084Sjroberts 			cmn_err(CE_WARN, "unexpected gpio-device-type: %s\n",
4001084Sjroberts 			    pmugpio_type);
4011084Sjroberts 			ddi_prop_free(pmugpio_type);
4021084Sjroberts 			return (DDI_FAILURE);
4031084Sjroberts 		}
4041084Sjroberts 		ddi_prop_free(pmugpio_type);
4051084Sjroberts 	}
406920Sjbeloro 	else
407920Sjbeloro 		pmugpio_ptr->access_type = PMUGPIO_OTHER;
408920Sjbeloro 
409920Sjbeloro 	switch (pmugpio_ptr->access_type) {
410920Sjbeloro 	case PMUGPIO_CPLD:
411920Sjbeloro 	case PMUGPIO_MBC:
412920Sjbeloro 		if (ddi_regs_map_setup(dip, 0,
413920Sjbeloro 		    (caddr_t *)&pmugpio_ptr->pmugpio_reset_reg, 0, 1, &attr,
414920Sjbeloro 		    &pmugpio_ptr->pmugpio_reset_reg_handle) != DDI_SUCCESS)
415920Sjbeloro 			return (DDI_FAILURE);
416920Sjbeloro 		/* MBC and CPLD have reset and watchdog bits in same reg. */
417920Sjbeloro 		pmugpio_ptr->pmugpio_watchdog_reg_handle =
418*7656SSherry.Moore@Sun.COM 		    pmugpio_ptr->pmugpio_reset_reg_handle;
419920Sjbeloro 		pmugpio_ptr->pmugpio_watchdog_reg =
420*7656SSherry.Moore@Sun.COM 		    pmugpio_ptr->pmugpio_reset_reg;
421920Sjbeloro 		break;
422920Sjbeloro 
423920Sjbeloro 	case PMUGPIO_OTHER:
424920Sjbeloro 		if (ddi_regs_map_setup(dip, 1,
425920Sjbeloro 		    (caddr_t *)&pmugpio_ptr->pmugpio_watchdog_reg, 0, 1, &attr,
426920Sjbeloro 		    &pmugpio_ptr->pmugpio_watchdog_reg_handle) != DDI_SUCCESS) {
427920Sjbeloro 			return (DDI_FAILURE);
428920Sjbeloro 		}
429920Sjbeloro 		if (ddi_regs_map_setup(dip, 0,
430920Sjbeloro 		    (caddr_t *)&pmugpio_ptr->pmugpio_reset_reg, 0, 1, &attr,
431920Sjbeloro 		    &pmugpio_ptr->pmugpio_reset_reg_handle) != DDI_SUCCESS) {
432920Sjbeloro 			ddi_regs_map_free(
433*7656SSherry.Moore@Sun.COM 			    &pmugpio_ptr->pmugpio_watchdog_reg_handle);
434920Sjbeloro 			return (DDI_FAILURE);
435920Sjbeloro 		}
436920Sjbeloro 		break;
437920Sjbeloro 
438920Sjbeloro 	default:
439920Sjbeloro 		cmn_err(CE_WARN, "pmugpio_map_regs: Invalid type");
4400Sstevel@tonic-gate 		return (DDI_FAILURE);
4410Sstevel@tonic-gate 	}
442920Sjbeloro 
4430Sstevel@tonic-gate 	return (DDI_SUCCESS);
4440Sstevel@tonic-gate }
445