1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/stat.h> /* ddi_create_minor_node S_IFCHR */ 27 #include <sys/modctl.h> /* for modldrv */ 28 #include <sys/open.h> /* for open params. */ 29 #include <sys/types.h> 30 #include <sys/kmem.h> 31 #include <sys/sunddi.h> 32 #include <sys/conf.h> /* req. by dev_ops flags MTSAFE etc. */ 33 #include <sys/ddi.h> 34 #include <sys/file.h> 35 #include <sys/note.h> 36 #include <sys/i2c/clients/i2c_gpio.h> 37 #include <sys/i2c/clients/adm1026_impl.h> 38 39 /* 40 * This driver supports the GPIO subset of the full ADM1026 register set. 41 * The driver is designed to allow modifying and reading the Polarity and 42 * Direction bits of the ADM1026's 16 GPIO pins via the 4 GPIO Config 43 * registers. In addition, the driver supports modifying and reading 44 * the 16 GPIO pins via the 2 GPIO input/output registers. 45 * 46 * The 4 GPIO Config registers configure the direction and polarity of 47 * the 16 GPIO pins. When a Polarity bit is set to 0, the GPIO pin is 48 * active low, otherwise, it is active high. When a Direction bit is set 49 * to 0, the GPIO pin configured as an input; otherwise, it is an output. 50 * 51 * The 2 GPIO input/output registers (Status Register 5 & 6 ) behave as follows. 52 * When a GPIO pin is configured as an input, the bit is set when its GPIO 53 * pin is asserted. When a GPIO pin is configured as an output, the bit 54 * asserts the GPIO pin. 55 * 56 * The commands supported in the ioctl routine are: 57 * GPIO_GET_OUTPUT -- Read GPIO0-GPIO15 bits in Status Register 5 & 6 58 * GPIO_SET_OUTPUT -- Modify GPIO0-GPIO15 bits in Status Register 5 & 6 59 * GPIO_GET_POLARITY -- Read GPIO0-GPIO15 Polarity bits in GPIO Config 1-4 60 * GPIO_SET_POLARITY -- Modify GPIO0-GPIO15 Polarity bits in GPIO Config 1-4 61 * GPIO_GET_CONFIG -- Read GPIO0-GPIO15 Direction bits in GPIO Config 1-4 62 * GPIO_SET_CONFIG -- Modify GPIO0-GPIO15 Direction bits in GPIO Config 1-4 63 * 64 * A pointer to the i2c_gpio_t data structure is sent as the third argument 65 * in the ioctl call. The reg_mask and reg_val members of i2c_gpio_t are 66 * used to logically represent the 16 GPIO pins, thus only the lower 16 bits 67 * of each member is used. The reg_mask member identifies the GPIO pin(s) 68 * that the user wants to read or modify and reg_val has the actual value of 69 * what the corresponding GPIO pin should be set to. 70 * 71 * For example, a reg_mask of 0x8001 indicates that the ioctl should only 72 * access GPIO15 and GPIO0. 73 */ 74 75 static void *adm1026soft_statep; 76 77 static int adm1026_do_attach(dev_info_t *); 78 static int adm1026_do_detach(dev_info_t *); 79 static int adm1026_do_resume(void); 80 static int adm1026_do_suspend(void); 81 static int adm1026_get8(adm1026_unit_t *unitp, uint8_t reg, uint8_t *val); 82 static int adm1026_put8(adm1026_unit_t *unitp, uint8_t reg, uint8_t val); 83 84 /* 85 * cb ops (only need ioctl) 86 */ 87 static int adm1026_open(dev_t *, int, int, cred_t *); 88 static int adm1026_close(dev_t, int, int, cred_t *); 89 static int adm1026_ioctl(dev_t, int, intptr_t, int, cred_t *, int *); 90 91 static struct cb_ops adm1026_cbops = { 92 adm1026_open, /* open */ 93 adm1026_close, /* close */ 94 nodev, /* strategy */ 95 nodev, /* print */ 96 nodev, /* dump */ 97 nodev, /* read */ 98 nodev, /* write */ 99 adm1026_ioctl, /* ioctl */ 100 nodev, /* devmap */ 101 nodev, /* mmap */ 102 nodev, /* segmap */ 103 nochpoll, /* poll */ 104 ddi_prop_op, /* cb_prop_op */ 105 NULL, /* streamtab */ 106 D_NEW | D_MP | D_HOTPLUG, /* Driver compatibility flag */ 107 CB_REV, /* rev */ 108 nodev, /* int (*cb_aread)() */ 109 nodev /* int (*cb_awrite)() */ 110 }; 111 112 /* 113 * dev ops 114 */ 115 static int adm1026_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 116 static int adm1026_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 117 118 static struct dev_ops adm1026_ops = { 119 DEVO_REV, 120 0, 121 ddi_getinfo_1to1, 122 nulldev, 123 nulldev, 124 adm1026_attach, 125 adm1026_detach, 126 nodev, 127 &adm1026_cbops, 128 NULL, 129 NULL, 130 ddi_quiesce_not_needed, /* quiesce */ 131 }; 132 133 extern struct mod_ops mod_driverops; 134 135 static struct modldrv adm1026_modldrv = { 136 &mod_driverops, /* type of module - driver */ 137 "ADM1026 i2c device driver", 138 &adm1026_ops 139 }; 140 141 static struct modlinkage adm1026_modlinkage = { 142 MODREV_1, 143 &adm1026_modldrv, 144 0 145 }; 146 147 148 int 149 _init(void) 150 { 151 int error; 152 153 error = mod_install(&adm1026_modlinkage); 154 155 if (!error) 156 (void) ddi_soft_state_init(&adm1026soft_statep, 157 sizeof (struct adm1026_unit), 1); 158 return (error); 159 } 160 161 int 162 _fini(void) 163 { 164 int error; 165 166 error = mod_remove(&adm1026_modlinkage); 167 if (!error) 168 ddi_soft_state_fini(&adm1026soft_statep); 169 170 return (error); 171 } 172 173 int 174 _info(struct modinfo *modinfop) 175 { 176 return (mod_info(&adm1026_modlinkage, modinfop)); 177 } 178 179 static int 180 adm1026_open(dev_t *devp, int flags, int otyp, cred_t *credp) 181 { 182 _NOTE(ARGUNUSED(credp)) 183 184 adm1026_unit_t *unitp; 185 int instance; 186 int error = 0; 187 188 instance = getminor(*devp); 189 190 D2CMN_ERR((CE_WARN, "adm1026_open: instance=%d\n", instance)); 191 192 if (instance < 0) { 193 return (ENXIO); 194 } 195 196 unitp = (struct adm1026_unit *) 197 ddi_get_soft_state(adm1026soft_statep, instance); 198 199 if (unitp == NULL) { 200 return (ENXIO); 201 } 202 203 if (otyp != OTYP_CHR) { 204 return (EINVAL); 205 } 206 207 mutex_enter(&unitp->adm1026_mutex); 208 209 if (flags & FEXCL) { 210 if (unitp->adm1026_oflag != 0) { 211 error = EBUSY; 212 } else { 213 unitp->adm1026_oflag = FEXCL; 214 } 215 } else { 216 if (unitp->adm1026_oflag == FEXCL) { 217 error = EBUSY; 218 } else { 219 unitp->adm1026_oflag = FOPEN; 220 } 221 } 222 223 mutex_exit(&unitp->adm1026_mutex); 224 225 return (error); 226 } 227 228 static int 229 adm1026_close(dev_t dev, int flags, int otyp, cred_t *credp) 230 { 231 _NOTE(ARGUNUSED(flags, otyp, credp)) 232 233 adm1026_unit_t *unitp; 234 int instance; 235 236 instance = getminor(dev); 237 238 D2CMN_ERR((CE_WARN, "adm1026_close: instance=%d\n", instance)); 239 240 if (instance < 0) { 241 return (ENXIO); 242 } 243 244 unitp = (struct adm1026_unit *) 245 ddi_get_soft_state(adm1026soft_statep, instance); 246 247 if (unitp == NULL) { 248 return (ENXIO); 249 } 250 251 mutex_enter(&unitp->adm1026_mutex); 252 253 unitp->adm1026_oflag = 0; 254 255 mutex_exit(&unitp->adm1026_mutex); 256 return (DDI_SUCCESS); 257 } 258 259 static int 260 adm1026_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 261 { 262 D2CMN_ERR((CE_WARN, "adm1026_attach: cmd=%x\n", cmd)); 263 264 switch (cmd) { 265 case DDI_ATTACH: 266 return (adm1026_do_attach(dip)); 267 case DDI_RESUME: 268 return (adm1026_do_resume()); 269 default: 270 return (DDI_FAILURE); 271 } 272 } 273 274 static int 275 adm1026_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 276 { 277 D2CMN_ERR((CE_WARN, "adm1026_detach: cmd=%x\n", cmd)); 278 switch (cmd) { 279 case DDI_DETACH: 280 return (adm1026_do_detach(dip)); 281 case DDI_SUSPEND: 282 return (adm1026_do_suspend()); 283 default: 284 return (DDI_FAILURE); 285 } 286 } 287 288 static int 289 adm1026_do_attach(dev_info_t *dip) 290 { 291 adm1026_unit_t *unitp; 292 int instance; 293 294 instance = ddi_get_instance(dip); 295 296 D2CMN_ERR((CE_WARN, "adm1026_do_attach: instance=%d, dip=%p", 297 instance, (void *)dip)); 298 299 if (ddi_soft_state_zalloc(adm1026soft_statep, instance) != 0) { 300 cmn_err(CE_WARN, "%s%d: ddi_soft_state_zalloc() failed", 301 ddi_get_name(dip), instance); 302 return (DDI_FAILURE); 303 } 304 305 unitp = ddi_get_soft_state(adm1026soft_statep, instance); 306 307 if (unitp == NULL) { 308 cmn_err(CE_WARN, "%s%d: ddi_get_soft_state(), no memory", 309 ddi_get_name(dip), instance); 310 return (ENOMEM); 311 } 312 313 D2CMN_ERR((CE_WARN, "adm1026_do_attach: ddi_create_minor_node")); 314 if (ddi_create_minor_node(dip, "adm1026", S_IFCHR, instance, 315 "ddi_i2c:led_control", NULL) == DDI_FAILURE) { 316 cmn_err(CE_WARN, 317 "adm1026_do_attach: ddi_create_minor_node failed"); 318 ddi_soft_state_free(adm1026soft_statep, instance); 319 320 return (DDI_FAILURE); 321 } 322 323 D2CMN_ERR((CE_WARN, "adm1026_do_attach: i2c_client_register")); 324 if (i2c_client_register(dip, &unitp->adm1026_hdl) != I2C_SUCCESS) { 325 ddi_remove_minor_node(dip, NULL); 326 ddi_soft_state_free(adm1026soft_statep, instance); 327 cmn_err(CE_WARN, 328 "adm1026_do_attach: i2c_client_register failed"); 329 330 return (DDI_FAILURE); 331 } 332 333 mutex_init(&unitp->adm1026_mutex, NULL, MUTEX_DRIVER, NULL); 334 335 D2CMN_ERR((CE_WARN, "adm1026_do_attach: DDI_SUCCESS")); 336 return (DDI_SUCCESS); 337 } 338 339 static int 340 adm1026_do_resume(void) 341 { 342 int ret = DDI_SUCCESS; 343 344 return (ret); 345 } 346 347 static int 348 adm1026_do_suspend() 349 { 350 int ret = DDI_SUCCESS; 351 352 return (ret); 353 } 354 355 static int 356 adm1026_do_detach(dev_info_t *dip) 357 { 358 adm1026_unit_t *unitp; 359 int instance; 360 361 instance = ddi_get_instance(dip); 362 363 unitp = ddi_get_soft_state(adm1026soft_statep, instance); 364 365 if (unitp == NULL) { 366 cmn_err(CE_WARN, 367 "adm1026_do_detach: ddi_get_soft_state failed"); 368 return (ENOMEM); 369 } 370 371 i2c_client_unregister(unitp->adm1026_hdl); 372 373 ddi_remove_minor_node(dip, NULL); 374 375 mutex_destroy(&unitp->adm1026_mutex); 376 ddi_soft_state_free(adm1026soft_statep, instance); 377 378 return (DDI_SUCCESS); 379 } 380 381 static int 382 adm1026_get8(adm1026_unit_t *unitp, uint8_t reg, uint8_t *val) 383 { 384 i2c_transfer_t *i2c_tran_pointer = NULL; 385 int err = DDI_SUCCESS; 386 387 (void) i2c_transfer_alloc(unitp->adm1026_hdl, &i2c_tran_pointer, 388 1, 1, I2C_SLEEP); 389 if (i2c_tran_pointer == NULL) 390 return (ENOMEM); 391 392 i2c_tran_pointer->i2c_flags = I2C_WR_RD; 393 i2c_tran_pointer->i2c_wbuf[0] = (uchar_t)reg; 394 err = i2c_transfer(unitp->adm1026_hdl, i2c_tran_pointer); 395 if (err) { 396 D1CMN_ERR((CE_WARN, 397 "adm1026_get8: I2C_WR_RD reg=0x%x failed", reg)); 398 } else { 399 *val = i2c_tran_pointer->i2c_rbuf[0]; 400 D1CMN_ERR((CE_WARN, "adm1026_get8: reg=%02x, val=%02x", 401 reg, *val)); 402 } 403 i2c_transfer_free(unitp->adm1026_hdl, i2c_tran_pointer); 404 405 return (err); 406 } 407 408 static int 409 adm1026_put8(adm1026_unit_t *unitp, uint8_t reg, uint8_t val) 410 { 411 i2c_transfer_t *i2c_tran_pointer = NULL; 412 int err = DDI_SUCCESS; 413 414 D1CMN_ERR((CE_WARN, "adm1026_put8: reg=%02x, val=%02x\n", reg, val)); 415 416 (void) i2c_transfer_alloc(unitp->adm1026_hdl, &i2c_tran_pointer, 417 2, 0, I2C_SLEEP); 418 if (i2c_tran_pointer == NULL) 419 return (ENOMEM); 420 421 i2c_tran_pointer->i2c_flags = I2C_WR; 422 i2c_tran_pointer->i2c_wbuf[0] = reg; 423 i2c_tran_pointer->i2c_wbuf[1] = val; 424 425 err = i2c_transfer(unitp->adm1026_hdl, i2c_tran_pointer); 426 if (err) 427 D2CMN_ERR((CE_WARN, "adm1026_put8: return=%x", err)); 428 429 i2c_transfer_free(unitp->adm1026_hdl, i2c_tran_pointer); 430 431 return (err); 432 } 433 434 /* 435 * adm1026_send8: 436 * Read the i2c register, apply the mask to contents so that only 437 * bits in mask affected. Or in value and write it back to the i2c register. 438 */ 439 static int 440 adm1026_send8(adm1026_unit_t *unitp, uint8_t reg, uint8_t reg_val, 441 uint8_t reg_mask) 442 { 443 uint8_t val = 0; 444 int err; 445 446 if ((err = adm1026_get8(unitp, reg, &val)) != I2C_SUCCESS) 447 return (err); 448 val &= ~reg_mask; 449 val |= (reg_val & reg_mask); 450 451 return (adm1026_put8(unitp, reg, val)); 452 } 453 454 /* 455 * adm1026_set_output: 456 * The low 16 bits of the mask is a 1:1 mask indicating which of the 457 * 16 GPIO pin(s) to set. 458 */ 459 static int 460 adm1026_set_output(adm1026_unit_t *unitp, uint32_t val, uint32_t mask) 461 { 462 int err = I2C_SUCCESS; 463 464 if (mask & 0xff) 465 err = adm1026_send8(unitp, ADM1026_STS_REG5, (uint8_t)val, 466 (uint8_t)mask); 467 468 if ((err == I2C_SUCCESS) && (mask & 0xff00)) 469 err = adm1026_send8(unitp, ADM1026_STS_REG6, 470 (uint8_t)(val >> OUTPUT_SHIFT), 471 (uint8_t)(mask >> OUTPUT_SHIFT)); 472 473 return (err); 474 } 475 476 /* 477 * adm1026_get_output: 478 * The low 16 bits of the mask is a 1:1 mask indicating which of the 479 * 16 GPIO pin(s) to get. 480 */ 481 static int 482 adm1026_get_output(adm1026_unit_t *unitp, uint32_t mask, uint32_t *val) 483 { 484 uint8_t reg_val = 0; 485 int err = I2C_SUCCESS; 486 487 if (mask & 0xff) { 488 err = adm1026_get8(unitp, ADM1026_STS_REG5, ®_val); 489 if (err != I2C_SUCCESS) 490 return (err); 491 492 *val = reg_val; 493 } 494 495 if (mask & 0xff00) { 496 err = adm1026_get8(unitp, ADM1026_STS_REG6, ®_val); 497 if (err != I2C_SUCCESS) 498 return (err); 499 500 *val |= ((reg_val << OUTPUT_SHIFT) & (mask & 0xff00)); 501 } 502 503 return (err); 504 } 505 506 /* 507 * adm1026_set_config: 508 * The low 16 bits of the mask is a 1:1 mask indicating which of the 509 * 16 GPIO pin(s) to set the polarity or direction configuration for. 510 * Each GPIO pin has 2 bits of configuration - 1 polarity bit and 1 511 * direction bit. Traverse the mask 4 bits at a time to determine 512 * which of the 4 GPIO Config registers to access and apply the value 513 * based on whether cmd is GPIO_SET_CONFIG (set Direction) or 514 * GPIO_SET_POLARITY. 515 */ 516 static int 517 adm1026_set_config(adm1026_unit_t *unitp, int cmd, uint32_t val, uint32_t mask) 518 { 519 int i; 520 uint8_t r; 521 uint32_t m = mask, v = val; 522 int err = I2C_SUCCESS; 523 524 for (i = 0, r = ADM1026_GPIO_CFG1; i < BYTES_PER_CONFIG; i++, r++) { 525 if (m & GPIO_CFG_MASK) { 526 int j; 527 uint8_t mm = 0, vv = 0; 528 uint8_t bit = (cmd == GPIO_SET_CONFIG) ? 529 DIR_BIT : POLARITY_BIT; 530 531 for (j = 0; j < GPIOS_PER_CFG_BYTE; j++) { 532 if (m & (1 << j)) { 533 mm |= (bit << (j * BITSPERCFG)); 534 } 535 if (v & (1 << j)) { 536 vv |= (bit << (j * BITSPERCFG)); 537 } 538 } 539 D2CMN_ERR((CE_WARN, "adm1026_set_config: r=%02x, " 540 "vv=%02x, mm=%02x, m=%02x", r, vv, mm, m)); 541 err = adm1026_send8(unitp, r, vv, mm); 542 if (err != I2C_SUCCESS) 543 return (err); 544 } 545 m >>= GPIOS_PER_CFG_BYTE; 546 v >>= GPIOS_PER_CFG_BYTE; 547 } 548 return (err); 549 } 550 551 /* 552 * adm1026_get_config: 553 * The low 16 bits of the mask is a 1:1 mask indicating which of the 554 * 16 GPIO pin(s) to get the polarity or direction configuration for. 555 * Each GPIO pin has 2 bits of configuration - 1 polarity bit and 1 556 * direction bit. Traverse the mask 4 bits at a time to determine 557 * which of the 4 GPIO Config registers to access and build the return 558 * value based on whether cmd is GPIO_GET_CONFIG (get Direction) or 559 * GPIO_GET_POLARITY. 560 */ 561 static int 562 adm1026_get_config(adm1026_unit_t *unitp, int cmd, uint32_t mask, uint32_t *val) 563 { 564 int i, j; 565 uint8_t r; 566 int err = I2C_SUCCESS; 567 568 *val = 0; 569 570 for (i = 0, r = ADM1026_GPIO_CFG1; i < BYTES_PER_CONFIG; i++, r++) { 571 if (mask & GPIO_CFG_MASK) { 572 uint8_t newval = 0, x; 573 uint8_t bit = (cmd == GPIO_GET_CONFIG) ? 574 DIR_BIT : POLARITY_BIT; 575 576 err = adm1026_get8(unitp, r, &x); 577 if (err != I2C_SUCCESS) 578 return (err); 579 for (j = 0; j < GPIOS_PER_CFG_BYTE; j++) { 580 if (mask & (1 << j)) { 581 if (x & (bit << (j * BITSPERCFG))) 582 newval |= (1 << j); 583 } 584 } 585 *val |= (newval << (i * GPIOS_PER_CFG_BYTE)); 586 } else 587 *val <<= GPIOS_PER_CFG_BYTE; 588 589 mask >>= GPIOS_PER_CFG_BYTE; 590 } 591 return (err); 592 } 593 594 static int 595 adm1026_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 596 int *rvalp) 597 { 598 _NOTE(ARGUNUSED(credp, rvalp)) 599 600 adm1026_unit_t *unitp; 601 int instance; 602 int err = DDI_SUCCESS; 603 i2c_gpio_t g_buf; 604 605 instance = getminor(dev); 606 607 D2CMN_ERR((CE_WARN, "adm1026_ioctl: instance=%d, cmd=%x\n", 608 instance, cmd)); 609 610 unitp = (struct adm1026_unit *) 611 ddi_get_soft_state(adm1026soft_statep, instance); 612 613 if (unitp == NULL) { 614 cmn_err(CE_WARN, "adm1026_ioctl: ddi_get_soft_state failed"); 615 err = ENOMEM; 616 return (err); 617 } 618 619 mutex_enter(&unitp->adm1026_mutex); 620 621 if (ddi_copyin((caddr_t)arg, &g_buf, 622 sizeof (i2c_gpio_t), mode) != DDI_SUCCESS) { 623 624 mutex_exit(&unitp->adm1026_mutex); 625 return (EFAULT); 626 } 627 if (g_buf.reg_mask & 0xffff0000) { 628 cmn_err(CE_WARN, 629 "adm1026_ioctl: reg_mask too large. " 630 "Only bits 15-0 supported"); 631 mutex_exit(&unitp->adm1026_mutex); 632 return (EINVAL); 633 } 634 switch (cmd) { 635 case GPIO_SET_OUTPUT: 636 err = adm1026_set_output(unitp, g_buf.reg_val, g_buf.reg_mask); 637 break; 638 639 case GPIO_GET_OUTPUT: 640 err = adm1026_get_output(unitp, g_buf.reg_mask, &g_buf.reg_val); 641 if (err == DDI_SUCCESS) 642 err = ddi_copyout(&g_buf, (caddr_t)arg, 643 sizeof (i2c_gpio_t), mode); 644 break; 645 646 case GPIO_SET_CONFIG: 647 case GPIO_SET_POLARITY: 648 err = adm1026_set_config(unitp, cmd, g_buf.reg_val, 649 g_buf.reg_mask); 650 break; 651 652 case GPIO_GET_CONFIG: 653 case GPIO_GET_POLARITY: 654 err = adm1026_get_config(unitp, cmd, g_buf.reg_mask, 655 &g_buf.reg_val); 656 if (err == DDI_SUCCESS) 657 err = ddi_copyout(&g_buf, (caddr_t)arg, 658 sizeof (i2c_gpio_t), mode); 659 break; 660 default: 661 D2CMN_ERR((CE_WARN, 662 "adm1026_ioctl: Invalid ioctl cmd %x\n", cmd)); 663 err = EINVAL; 664 } 665 mutex_exit(&unitp->adm1026_mutex); 666 667 if (err) { 668 D2CMN_ERR((CE_WARN, 669 "adm1026_ioctl: failed, err=%x\n", err)); 670 if (err == DDI_FAILURE) 671 err = EIO; 672 } 673 674 return (err); 675 } 676