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