1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright (c) 2000 by Sun Microsystems, Inc. 24*0Sstevel@tonic-gate * All rights reserved. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/time.h> 31*0Sstevel@tonic-gate #include <sys/errno.h> 32*0Sstevel@tonic-gate #include <sys/cmn_err.h> 33*0Sstevel@tonic-gate #include <sys/param.h> 34*0Sstevel@tonic-gate #include <sys/modctl.h> 35*0Sstevel@tonic-gate #include <sys/conf.h> 36*0Sstevel@tonic-gate #include <sys/open.h> 37*0Sstevel@tonic-gate #include <sys/stat.h> 38*0Sstevel@tonic-gate #include <sys/clock.h> 39*0Sstevel@tonic-gate #include <sys/gpio_87317.h> 40*0Sstevel@tonic-gate #include <sys/ddi.h> 41*0Sstevel@tonic-gate #include <sys/sunddi.h> 42*0Sstevel@tonic-gate #include <sys/file.h> 43*0Sstevel@tonic-gate #ifdef DEBUG 44*0Sstevel@tonic-gate #include <sys/promif.h> 45*0Sstevel@tonic-gate #endif 46*0Sstevel@tonic-gate 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate /* a non zero value causes debug info to be displayed */ 49*0Sstevel@tonic-gate uint_t gpio_debug_flag = 0; 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate #ifdef DEBUG 53*0Sstevel@tonic-gate static void gpio_debug(dev_info_t *dip, char *format, uint_t arg1, uint_t arg2, 54*0Sstevel@tonic-gate uint_t arg3, uint_t arg4, uint_t arg5); 55*0Sstevel@tonic-gate 56*0Sstevel@tonic-gate #define DBG(dip, format, arg1, arg2, arg3, arg4, arg5) \ 57*0Sstevel@tonic-gate gpio_debug(dip, format, (uint_t)arg1, (uint_t)arg2, (uint_t)arg3, \ 58*0Sstevel@tonic-gate (uint_t)arg4, (uint_t)arg5) 59*0Sstevel@tonic-gate #else 60*0Sstevel@tonic-gate #define DBG(dip, format, arg1, arg2, arg3, arg4, arg5) 61*0Sstevel@tonic-gate #endif 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate 64*0Sstevel@tonic-gate /* Driver soft state structure */ 65*0Sstevel@tonic-gate struct gpio_softc { 66*0Sstevel@tonic-gate dev_info_t *gp_dip; 67*0Sstevel@tonic-gate kmutex_t gp_mutex; 68*0Sstevel@tonic-gate int gp_state; 69*0Sstevel@tonic-gate ddi_acc_handle_t gp_handle; 70*0Sstevel@tonic-gate uint8_t *gp_regs; 71*0Sstevel@tonic-gate }; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate #define getsoftc(minor) \ 74*0Sstevel@tonic-gate ((struct gpio_softc *)ddi_get_soft_state(statep, (minor))) 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate /* dev_ops and cb_ops entry point function declarations */ 77*0Sstevel@tonic-gate static int gpio_attach(dev_info_t *, ddi_attach_cmd_t); 78*0Sstevel@tonic-gate static int gpio_detach(dev_info_t *, ddi_detach_cmd_t); 79*0Sstevel@tonic-gate static int gpio_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **); 80*0Sstevel@tonic-gate static int gpio_open(dev_t *, int, int, cred_t *); 81*0Sstevel@tonic-gate static int gpio_close(dev_t, int, int, cred_t *); 82*0Sstevel@tonic-gate static int gpio_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 83*0Sstevel@tonic-gate 84*0Sstevel@tonic-gate struct cb_ops gpio_cb_ops = { 85*0Sstevel@tonic-gate gpio_open, 86*0Sstevel@tonic-gate gpio_close, 87*0Sstevel@tonic-gate nodev, 88*0Sstevel@tonic-gate nodev, 89*0Sstevel@tonic-gate nodev, /* dump */ 90*0Sstevel@tonic-gate nodev, 91*0Sstevel@tonic-gate nodev, 92*0Sstevel@tonic-gate gpio_ioctl, 93*0Sstevel@tonic-gate nodev, /* devmap */ 94*0Sstevel@tonic-gate nodev, 95*0Sstevel@tonic-gate nodev, 96*0Sstevel@tonic-gate nochpoll, 97*0Sstevel@tonic-gate ddi_prop_op, 98*0Sstevel@tonic-gate NULL, /* for STREAMS drivers */ 99*0Sstevel@tonic-gate D_NEW | D_MP, /* driver compatibility flag */ 100*0Sstevel@tonic-gate CB_REV, 101*0Sstevel@tonic-gate nodev, 102*0Sstevel@tonic-gate nodev 103*0Sstevel@tonic-gate }; 104*0Sstevel@tonic-gate 105*0Sstevel@tonic-gate static struct dev_ops gpio_dev_ops = { 106*0Sstevel@tonic-gate DEVO_REV, /* driver build version */ 107*0Sstevel@tonic-gate 0, /* device reference count */ 108*0Sstevel@tonic-gate gpio_getinfo, 109*0Sstevel@tonic-gate nulldev, 110*0Sstevel@tonic-gate nulldev, /* probe */ 111*0Sstevel@tonic-gate gpio_attach, 112*0Sstevel@tonic-gate gpio_detach, 113*0Sstevel@tonic-gate nulldev, /* reset */ 114*0Sstevel@tonic-gate &gpio_cb_ops, 115*0Sstevel@tonic-gate (struct bus_ops *)NULL, 116*0Sstevel@tonic-gate nulldev /* power */ 117*0Sstevel@tonic-gate }; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* module configuration stuff */ 120*0Sstevel@tonic-gate static void *statep; 121*0Sstevel@tonic-gate extern struct mod_ops mod_driverops; 122*0Sstevel@tonic-gate static struct modldrv modldrv = { 123*0Sstevel@tonic-gate &mod_driverops, 124*0Sstevel@tonic-gate "gpio driver 1.0", 125*0Sstevel@tonic-gate &gpio_dev_ops 126*0Sstevel@tonic-gate }; 127*0Sstevel@tonic-gate static struct modlinkage modlinkage = { 128*0Sstevel@tonic-gate MODREV_1, 129*0Sstevel@tonic-gate &modldrv, 130*0Sstevel@tonic-gate 0 131*0Sstevel@tonic-gate }; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate int 135*0Sstevel@tonic-gate _init(void) 136*0Sstevel@tonic-gate { 137*0Sstevel@tonic-gate int e; 138*0Sstevel@tonic-gate 139*0Sstevel@tonic-gate if (e = ddi_soft_state_init(&statep, sizeof (struct gpio_softc), 1)) { 140*0Sstevel@tonic-gate return (e); 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate if ((e = mod_install(&modlinkage)) != 0) { 143*0Sstevel@tonic-gate ddi_soft_state_fini(&statep); 144*0Sstevel@tonic-gate } 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate return (e); 147*0Sstevel@tonic-gate } 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate 150*0Sstevel@tonic-gate int 151*0Sstevel@tonic-gate _fini(void) 152*0Sstevel@tonic-gate { 153*0Sstevel@tonic-gate int e; 154*0Sstevel@tonic-gate 155*0Sstevel@tonic-gate if ((e = mod_remove(&modlinkage)) != 0) { 156*0Sstevel@tonic-gate return (e); 157*0Sstevel@tonic-gate } 158*0Sstevel@tonic-gate ddi_soft_state_fini(&statep); 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate return (DDI_SUCCESS); 161*0Sstevel@tonic-gate } 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gate int 165*0Sstevel@tonic-gate _info(struct modinfo *modinfop) 166*0Sstevel@tonic-gate { 167*0Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 168*0Sstevel@tonic-gate } 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate /* ARGSUSED */ 172*0Sstevel@tonic-gate static int 173*0Sstevel@tonic-gate gpio_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result) 174*0Sstevel@tonic-gate { 175*0Sstevel@tonic-gate int instance = getminor((dev_t)arg); 176*0Sstevel@tonic-gate int retval = DDI_SUCCESS; 177*0Sstevel@tonic-gate struct gpio_softc *softc; 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate switch (cmd) { 180*0Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 181*0Sstevel@tonic-gate if ((softc = getsoftc(instance)) == NULL) { 182*0Sstevel@tonic-gate *result = (void *)NULL; 183*0Sstevel@tonic-gate retval = DDI_FAILURE; 184*0Sstevel@tonic-gate } else 185*0Sstevel@tonic-gate *result = (void *)softc->gp_dip; 186*0Sstevel@tonic-gate break; 187*0Sstevel@tonic-gate 188*0Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 189*0Sstevel@tonic-gate *result = (void *)instance; 190*0Sstevel@tonic-gate break; 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate default: 193*0Sstevel@tonic-gate retval = DDI_FAILURE; 194*0Sstevel@tonic-gate } 195*0Sstevel@tonic-gate 196*0Sstevel@tonic-gate return (retval); 197*0Sstevel@tonic-gate } 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate static int 201*0Sstevel@tonic-gate gpio_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 202*0Sstevel@tonic-gate { 203*0Sstevel@tonic-gate 204*0Sstevel@tonic-gate int instance; 205*0Sstevel@tonic-gate struct gpio_softc *softc = NULL; 206*0Sstevel@tonic-gate ddi_device_acc_attr_t dev_attr; 207*0Sstevel@tonic-gate 208*0Sstevel@tonic-gate switch (cmd) { 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate case DDI_ATTACH: 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate /* Allocate and get the soft state structure for this instance. */ 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate instance = ddi_get_instance(dip); 215*0Sstevel@tonic-gate DBG(dip, "attach: instance is %d", instance, 0, 0, 0, 0); 216*0Sstevel@tonic-gate if (ddi_soft_state_zalloc(statep, instance) != DDI_SUCCESS) 217*0Sstevel@tonic-gate goto attach_failed; 218*0Sstevel@tonic-gate softc = getsoftc(instance); 219*0Sstevel@tonic-gate softc->gp_dip = dip; 220*0Sstevel@tonic-gate softc->gp_state = 0; 221*0Sstevel@tonic-gate mutex_init(&softc->gp_mutex, NULL, MUTEX_DRIVER, NULL); 222*0Sstevel@tonic-gate 223*0Sstevel@tonic-gate /* Map in the gpio device registers. */ 224*0Sstevel@tonic-gate 225*0Sstevel@tonic-gate dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 226*0Sstevel@tonic-gate dev_attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 227*0Sstevel@tonic-gate dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 228*0Sstevel@tonic-gate if (ddi_regs_map_setup(dip, 0, (caddr_t *)&softc->gp_regs, 0, 0, 229*0Sstevel@tonic-gate &dev_attr, &softc->gp_handle) != DDI_SUCCESS) 230*0Sstevel@tonic-gate goto attach_failed; 231*0Sstevel@tonic-gate DBG(dip, "attach: regs=0x%x", softc->gp_regs, 0, 0, 0, 0); 232*0Sstevel@tonic-gate DBG(dip, "attach: port 1 data is %x", 233*0Sstevel@tonic-gate ddi_get8(softc->gp_handle, &softc->gp_regs[0]), 0, 0, 0, 0); 234*0Sstevel@tonic-gate DBG(dip, "attach: port 1 direction is %x", 235*0Sstevel@tonic-gate ddi_get8(softc->gp_handle, &softc->gp_regs[1]), 0, 0, 0, 0); 236*0Sstevel@tonic-gate DBG(dip, "attach: port 1 output type is %x", 237*0Sstevel@tonic-gate ddi_get8(softc->gp_handle, &softc->gp_regs[2]), 0, 0, 0, 0); 238*0Sstevel@tonic-gate DBG(dip, "attach: port 1 pull up control type is %x", 239*0Sstevel@tonic-gate ddi_get8(softc->gp_handle, &softc->gp_regs[3]), 0, 0, 0, 0); 240*0Sstevel@tonic-gate DBG(dip, "attach: port 2 data is %x", 241*0Sstevel@tonic-gate ddi_get8(softc->gp_handle, &softc->gp_regs[4]), 0, 0, 0, 0); 242*0Sstevel@tonic-gate DBG(dip, "attach: port 2 direction is %x", 243*0Sstevel@tonic-gate ddi_get8(softc->gp_handle, &softc->gp_regs[5]), 0, 0, 0, 0); 244*0Sstevel@tonic-gate DBG(dip, "attach: port 2 output type is %x", 245*0Sstevel@tonic-gate ddi_get8(softc->gp_handle, &softc->gp_regs[6]), 0, 0, 0, 0); 246*0Sstevel@tonic-gate DBG(dip, "attach: port 2 pull up control type is %x", 247*0Sstevel@tonic-gate ddi_get8(softc->gp_handle, &softc->gp_regs[7]), 0, 0, 0, 0); 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate /* Create device minor nodes. */ 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate if (ddi_create_minor_node(dip, "gpio", S_IFCHR, 252*0Sstevel@tonic-gate instance, NULL, NULL) == DDI_FAILURE) { 253*0Sstevel@tonic-gate ddi_regs_map_free(&softc->gp_handle); 254*0Sstevel@tonic-gate goto attach_failed; 255*0Sstevel@tonic-gate } 256*0Sstevel@tonic-gate 257*0Sstevel@tonic-gate ddi_report_dev(dip); 258*0Sstevel@tonic-gate return (DDI_SUCCESS); 259*0Sstevel@tonic-gate 260*0Sstevel@tonic-gate case DDI_RESUME: 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate /* Nothing to do for a resume. */ 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate return (DDI_SUCCESS); 265*0Sstevel@tonic-gate 266*0Sstevel@tonic-gate default: 267*0Sstevel@tonic-gate return (DDI_FAILURE); 268*0Sstevel@tonic-gate } 269*0Sstevel@tonic-gate 270*0Sstevel@tonic-gate attach_failed: 271*0Sstevel@tonic-gate if (softc) { 272*0Sstevel@tonic-gate mutex_destroy(&softc->gp_mutex); 273*0Sstevel@tonic-gate if (softc->gp_handle) 274*0Sstevel@tonic-gate ddi_regs_map_free(&softc->gp_handle); 275*0Sstevel@tonic-gate ddi_soft_state_free(statep, instance); 276*0Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate return (DDI_FAILURE); 279*0Sstevel@tonic-gate } 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate 282*0Sstevel@tonic-gate static int 283*0Sstevel@tonic-gate gpio_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 284*0Sstevel@tonic-gate { 285*0Sstevel@tonic-gate int instance; 286*0Sstevel@tonic-gate struct gpio_softc *softc; 287*0Sstevel@tonic-gate 288*0Sstevel@tonic-gate switch (cmd) { 289*0Sstevel@tonic-gate case DDI_DETACH: 290*0Sstevel@tonic-gate instance = ddi_get_instance(dip); 291*0Sstevel@tonic-gate DBG(dip, "detach: instance is %d", instance, 0, 0, 0, 0); 292*0Sstevel@tonic-gate if ((softc = getsoftc(instance)) == NULL) 293*0Sstevel@tonic-gate return (ENXIO); 294*0Sstevel@tonic-gate mutex_destroy(&softc->gp_mutex); 295*0Sstevel@tonic-gate ddi_regs_map_free(&softc->gp_handle); 296*0Sstevel@tonic-gate ddi_soft_state_free(statep, instance); 297*0Sstevel@tonic-gate ddi_remove_minor_node(dip, NULL); 298*0Sstevel@tonic-gate return (DDI_SUCCESS); 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate case DDI_SUSPEND: 301*0Sstevel@tonic-gate /* Nothing to do in the suspend case. */ 302*0Sstevel@tonic-gate return (DDI_SUCCESS); 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate default: 305*0Sstevel@tonic-gate return (DDI_FAILURE); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate } 308*0Sstevel@tonic-gate 309*0Sstevel@tonic-gate 310*0Sstevel@tonic-gate /* ARGSUSED */ 311*0Sstevel@tonic-gate static int 312*0Sstevel@tonic-gate gpio_open(dev_t *devp, int flag, int otyp, cred_t *credp) 313*0Sstevel@tonic-gate { 314*0Sstevel@tonic-gate int instance = getminor(*devp); 315*0Sstevel@tonic-gate 316*0Sstevel@tonic-gate DBG(NULL, "open: instance is %d", instance, 0, 0, 0, 0); 317*0Sstevel@tonic-gate return (getsoftc(instance) == NULL ? ENXIO : 0); 318*0Sstevel@tonic-gate } 319*0Sstevel@tonic-gate 320*0Sstevel@tonic-gate 321*0Sstevel@tonic-gate /* ARGSUSED */ 322*0Sstevel@tonic-gate static int 323*0Sstevel@tonic-gate gpio_close(dev_t dev, int flag, int otyp, cred_t *credp) 324*0Sstevel@tonic-gate { 325*0Sstevel@tonic-gate int instance = getminor(dev); 326*0Sstevel@tonic-gate 327*0Sstevel@tonic-gate DBG(NULL, "close: instance is %d", instance, 0, 0, 0, 0); 328*0Sstevel@tonic-gate return (getsoftc(instance) == NULL ? ENXIO : 0); 329*0Sstevel@tonic-gate } 330*0Sstevel@tonic-gate 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate /* ARGSUSED */ 333*0Sstevel@tonic-gate static int 334*0Sstevel@tonic-gate gpio_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 335*0Sstevel@tonic-gate int *rvalp) 336*0Sstevel@tonic-gate { 337*0Sstevel@tonic-gate int instance = getminor(dev); 338*0Sstevel@tonic-gate struct gpio_softc *softc = getsoftc(instance); 339*0Sstevel@tonic-gate gpio_87317_op_t info; 340*0Sstevel@tonic-gate uint8_t byte; 341*0Sstevel@tonic-gate 342*0Sstevel@tonic-gate DBG(softc->gp_dip, "ioctl: instance is %d", instance, 0, 0, 0, 0); 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate if (softc == NULL) 345*0Sstevel@tonic-gate return (ENXIO); 346*0Sstevel@tonic-gate 347*0Sstevel@tonic-gate /* Copy the command from user space. */ 348*0Sstevel@tonic-gate if (ddi_copyin((caddr_t)arg, (caddr_t)&info, sizeof (gpio_87317_op_t), 349*0Sstevel@tonic-gate mode) != 0) 350*0Sstevel@tonic-gate return (EFAULT); 351*0Sstevel@tonic-gate 352*0Sstevel@tonic-gate /* Check the command arguments. We only support port 1 in bank 0. */ 353*0Sstevel@tonic-gate if ((info.gpio_bank != 0) || 354*0Sstevel@tonic-gate (info.gpio_offset != GPIO_87317_PORT1_DATA)) { 355*0Sstevel@tonic-gate return (EINVAL); 356*0Sstevel@tonic-gate } 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate /* Grap the instance's mutex to insure exclusive access. */ 359*0Sstevel@tonic-gate mutex_enter(&softc->gp_mutex); 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate /* Get the contents of the GPIO register we're suppose to modify. */ 362*0Sstevel@tonic-gate byte = ddi_get8(softc->gp_handle, &softc->gp_regs[info.gpio_offset]); 363*0Sstevel@tonic-gate 364*0Sstevel@tonic-gate switch (cmd) { 365*0Sstevel@tonic-gate case GPIO_CMD_SET_BITS: 366*0Sstevel@tonic-gate DBG(softc->gp_dip, "ioctl: SET_BITS, byte is %x", byte, 0, 0, 367*0Sstevel@tonic-gate 0, 0); 368*0Sstevel@tonic-gate byte |= info.gpio_data; 369*0Sstevel@tonic-gate ddi_put8(softc->gp_handle, &softc->gp_regs[info.gpio_offset], 370*0Sstevel@tonic-gate byte); 371*0Sstevel@tonic-gate byte = ddi_get8(softc->gp_handle, 372*0Sstevel@tonic-gate &softc->gp_regs[info.gpio_offset]); 373*0Sstevel@tonic-gate DBG(softc->gp_dip, "ioctl: SET_BITS, byte is %x", byte, 0, 0, 374*0Sstevel@tonic-gate 0, 0); 375*0Sstevel@tonic-gate break; 376*0Sstevel@tonic-gate 377*0Sstevel@tonic-gate case GPIO_CMD_CLR_BITS: 378*0Sstevel@tonic-gate DBG(softc->gp_dip, "ioctl: CLR_BITS, byte is %x", byte, 0, 0, 379*0Sstevel@tonic-gate 0, 0); 380*0Sstevel@tonic-gate byte &= ~info.gpio_data; 381*0Sstevel@tonic-gate ddi_put8(softc->gp_handle, &softc->gp_regs[info.gpio_offset], 382*0Sstevel@tonic-gate byte); 383*0Sstevel@tonic-gate byte = ddi_get8(softc->gp_handle, 384*0Sstevel@tonic-gate &softc->gp_regs[info.gpio_offset]); 385*0Sstevel@tonic-gate DBG(softc->gp_dip, "ioctl: CLR_BITS, byte is %x", byte, 0, 0, 386*0Sstevel@tonic-gate 0, 0); 387*0Sstevel@tonic-gate break; 388*0Sstevel@tonic-gate 389*0Sstevel@tonic-gate case GPIO_CMD_GET: 390*0Sstevel@tonic-gate DBG(softc->gp_dip, "ioctl: GPIO_CMD_GET", 0, 0, 0, 0, 0); 391*0Sstevel@tonic-gate info.gpio_data = byte; 392*0Sstevel@tonic-gate if (ddi_copyout((caddr_t)&info, (caddr_t)arg, 393*0Sstevel@tonic-gate sizeof (gpio_87317_op_t), mode) != 0) { 394*0Sstevel@tonic-gate mutex_exit(&softc->gp_mutex); 395*0Sstevel@tonic-gate return (EFAULT); 396*0Sstevel@tonic-gate } 397*0Sstevel@tonic-gate break; 398*0Sstevel@tonic-gate 399*0Sstevel@tonic-gate case GPIO_CMD_SET: 400*0Sstevel@tonic-gate DBG(softc->gp_dip, "ioctl: GPIO_CMD_SET", 0, 0, 0, 0, 0); 401*0Sstevel@tonic-gate ddi_put8(softc->gp_handle, &softc->gp_regs[info.gpio_offset], 402*0Sstevel@tonic-gate info.gpio_data); 403*0Sstevel@tonic-gate break; 404*0Sstevel@tonic-gate 405*0Sstevel@tonic-gate default: 406*0Sstevel@tonic-gate mutex_exit(&softc->gp_mutex); 407*0Sstevel@tonic-gate return (EINVAL); 408*0Sstevel@tonic-gate } 409*0Sstevel@tonic-gate 410*0Sstevel@tonic-gate mutex_exit(&softc->gp_mutex); 411*0Sstevel@tonic-gate return (0); 412*0Sstevel@tonic-gate } 413*0Sstevel@tonic-gate 414*0Sstevel@tonic-gate 415*0Sstevel@tonic-gate #ifdef DEBUG 416*0Sstevel@tonic-gate void 417*0Sstevel@tonic-gate gpio_debug(dev_info_t *dip, char *format, uint_t arg1, uint_t arg2, uint_t arg3, 418*0Sstevel@tonic-gate uint_t arg4, uint_t arg5) 419*0Sstevel@tonic-gate { 420*0Sstevel@tonic-gate if (gpio_debug_flag == 0) { 421*0Sstevel@tonic-gate return; 422*0Sstevel@tonic-gate } 423*0Sstevel@tonic-gate 424*0Sstevel@tonic-gate if (dip == NULL) { 425*0Sstevel@tonic-gate prom_printf("gpio: "); 426*0Sstevel@tonic-gate } else { 427*0Sstevel@tonic-gate prom_printf("%s%d: ", ddi_driver_name(dip), 428*0Sstevel@tonic-gate ddi_get_instance(dip)); 429*0Sstevel@tonic-gate } 430*0Sstevel@tonic-gate prom_printf(format, arg1, arg2, arg3, arg4, arg5); 431*0Sstevel@tonic-gate prom_printf("\n"); 432*0Sstevel@tonic-gate } 433*0Sstevel@tonic-gate #endif 434