regulator.c revision 308324
1/*- 2 * Copyright 2016 Michal Meloun <mmel@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/11/sys/dev/extres/regulator/regulator.c 308324 2016-11-05 04:17:32Z mmel $"); 29 30#include "opt_platform.h" 31#include <sys/param.h> 32#include <sys/conf.h> 33#include <sys/bus.h> 34#include <sys/kernel.h> 35#include <sys/queue.h> 36#include <sys/kobj.h> 37#include <sys/malloc.h> 38#include <sys/mutex.h> 39#include <sys/limits.h> 40#include <sys/lock.h> 41#include <sys/sysctl.h> 42#include <sys/systm.h> 43#include <sys/sx.h> 44 45#ifdef FDT 46#include <dev/fdt/fdt_common.h> 47#include <dev/ofw/ofw_bus.h> 48#include <dev/ofw/ofw_bus_subr.h> 49#endif 50#include <dev/extres/regulator/regulator.h> 51 52#include "regdev_if.h" 53 54MALLOC_DEFINE(M_REGULATOR, "regulator", "Regulator framework"); 55 56/* Forward declarations. */ 57struct regulator; 58struct regnode; 59 60typedef TAILQ_HEAD(regnode_list, regnode) regnode_list_t; 61typedef TAILQ_HEAD(regulator_list, regulator) regulator_list_t; 62 63/* Default regulator methods. */ 64static int regnode_method_enable(struct regnode *regnode, bool enable, 65 int *udelay); 66static int regnode_method_status(struct regnode *regnode, int *status); 67static int regnode_method_set_voltage(struct regnode *regnode, int min_uvolt, 68 int max_uvolt, int *udelay); 69static int regnode_method_get_voltage(struct regnode *regnode, int *uvolt); 70 71/* 72 * Regulator controller methods. 73 */ 74static regnode_method_t regnode_methods[] = { 75 REGNODEMETHOD(regnode_enable, regnode_method_enable), 76 REGNODEMETHOD(regnode_status, regnode_method_status), 77 REGNODEMETHOD(regnode_set_voltage, regnode_method_set_voltage), 78 REGNODEMETHOD(regnode_get_voltage, regnode_method_get_voltage), 79 80 REGNODEMETHOD_END 81}; 82DEFINE_CLASS_0(regnode, regnode_class, regnode_methods, 0); 83 84/* 85 * Regulator node - basic element for modelling SOC and bard power supply 86 * chains. Its contains producer data. 87 */ 88struct regnode { 89 KOBJ_FIELDS; 90 91 TAILQ_ENTRY(regnode) reglist_link; /* Global list entry */ 92 regulator_list_t consumers_list; /* Consumers list */ 93 94 /* Cache for already resolved names */ 95 struct regnode *parent; /* Resolved parent */ 96 97 /* Details of this device. */ 98 const char *name; /* Globally unique name */ 99 const char *parent_name; /* Parent name */ 100 101 device_t pdev; /* Producer device_t */ 102 void *softc; /* Producer softc */ 103 intptr_t id; /* Per producer unique id */ 104#ifdef FDT 105 phandle_t ofw_node; /* OFW node of regulator */ 106#endif 107 int flags; /* REGULATOR_FLAGS_ */ 108 struct sx lock; /* Lock for this regulator */ 109 int ref_cnt; /* Reference counter */ 110 int enable_cnt; /* Enabled counter */ 111 112 struct regnode_std_param std_param; /* Standard parameters */ 113}; 114 115/* 116 * Per consumer data, information about how a consumer is using a regulator 117 * node. 118 * A pointer to this structure is used as a handle in the consumer interface. 119 */ 120struct regulator { 121 device_t cdev; /* Consumer device */ 122 struct regnode *regnode; 123 TAILQ_ENTRY(regulator) link; /* Consumers list entry */ 124 125 int enable_cnt; 126 int min_uvolt; /* Requested uvolt range */ 127 int max_uvolt; 128}; 129 130/* 131 * Regulator names must be system wide unique. 132 */ 133static regnode_list_t regnode_list = TAILQ_HEAD_INITIALIZER(regnode_list); 134 135static struct sx regnode_topo_lock; 136SX_SYSINIT(regulator_topology, ®node_topo_lock, "Regulator topology lock"); 137 138#define REG_TOPO_SLOCK() sx_slock(®node_topo_lock) 139#define REG_TOPO_XLOCK() sx_xlock(®node_topo_lock) 140#define REG_TOPO_UNLOCK() sx_unlock(®node_topo_lock) 141#define REG_TOPO_ASSERT() sx_assert(®node_topo_lock, SA_LOCKED) 142#define REG_TOPO_XASSERT() sx_assert(®node_topo_lock, SA_XLOCKED) 143 144#define REGNODE_SLOCK(_sc) sx_slock(&((_sc)->lock)) 145#define REGNODE_XLOCK(_sc) sx_xlock(&((_sc)->lock)) 146#define REGNODE_UNLOCK(_sc) sx_unlock(&((_sc)->lock)) 147 148/* ---------------------------------------------------------------------------- 149 * 150 * Default regulator methods for base class. 151 * 152 */ 153static int 154regnode_method_enable(struct regnode *regnode, bool enable, int *udelay) 155{ 156 157 if (!enable) 158 return (ENXIO); 159 160 *udelay = 0; 161 return (0); 162} 163 164static int 165regnode_method_status(struct regnode *regnode, int *status) 166{ 167 *status = REGULATOR_STATUS_ENABLED; 168 return (0); 169} 170 171static int 172regnode_method_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt, 173 int *udelay) 174{ 175 176 if ((min_uvolt > regnode->std_param.max_uvolt) || 177 (max_uvolt < regnode->std_param.min_uvolt)) 178 return (ERANGE); 179 *udelay = 0; 180 return (0); 181} 182 183static int 184regnode_method_get_voltage(struct regnode *regnode, int *uvolt) 185{ 186 187 return (regnode->std_param.min_uvolt + 188 (regnode->std_param.max_uvolt - regnode->std_param.min_uvolt) / 2); 189} 190 191/* ---------------------------------------------------------------------------- 192 * 193 * Internal functions. 194 * 195 */ 196 197static struct regnode * 198regnode_find_by_name(const char *name) 199{ 200 struct regnode *entry; 201 202 REG_TOPO_ASSERT(); 203 204 TAILQ_FOREACH(entry, ®node_list, reglist_link) { 205 if (strcmp(entry->name, name) == 0) 206 return (entry); 207 } 208 return (NULL); 209} 210 211static struct regnode * 212regnode_find_by_id(device_t dev, intptr_t id) 213{ 214 struct regnode *entry; 215 216 REG_TOPO_ASSERT(); 217 218 TAILQ_FOREACH(entry, ®node_list, reglist_link) { 219 if ((entry->pdev == dev) && (entry->id == id)) 220 return (entry); 221 } 222 223 return (NULL); 224} 225 226/* 227 * Create and initialize regulator object, but do not register it. 228 */ 229struct regnode * 230regnode_create(device_t pdev, regnode_class_t regnode_class, 231 struct regnode_init_def *def) 232{ 233 struct regnode *regnode; 234 235 KASSERT(def->name != NULL, ("regulator name is NULL")); 236 KASSERT(def->name[0] != '\0', ("regulator name is empty")); 237 238 REG_TOPO_SLOCK(); 239 if (regnode_find_by_name(def->name) != NULL) 240 panic("Duplicated regulator registration: %s\n", def->name); 241 REG_TOPO_UNLOCK(); 242 243 /* Create object and initialize it. */ 244 regnode = malloc(sizeof(struct regnode), M_REGULATOR, 245 M_WAITOK | M_ZERO); 246 kobj_init((kobj_t)regnode, (kobj_class_t)regnode_class); 247 sx_init(®node->lock, "Regulator node lock"); 248 249 /* Allocate softc if required. */ 250 if (regnode_class->size > 0) { 251 regnode->softc = malloc(regnode_class->size, M_REGULATOR, 252 M_WAITOK | M_ZERO); 253 } 254 255 256 /* Copy all strings unless they're flagged as static. */ 257 if (def->flags & REGULATOR_FLAGS_STATIC) { 258 regnode->name = def->name; 259 regnode->parent_name = def->parent_name; 260 } else { 261 regnode->name = strdup(def->name, M_REGULATOR); 262 if (def->parent_name != NULL) 263 regnode->parent_name = strdup(def->parent_name, 264 M_REGULATOR); 265 } 266 267 /* Rest of init. */ 268 TAILQ_INIT(®node->consumers_list); 269 regnode->id = def->id; 270 regnode->pdev = pdev; 271 regnode->flags = def->flags; 272 regnode->parent = NULL; 273 regnode->std_param = def->std_param; 274#ifdef FDT 275 regnode->ofw_node = def->ofw_node; 276#endif 277 278 return (regnode); 279} 280 281/* Register regulator object. */ 282struct regnode * 283regnode_register(struct regnode *regnode) 284{ 285 int rv; 286 287#ifdef FDT 288 if (regnode->ofw_node <= 0) 289 regnode->ofw_node = ofw_bus_get_node(regnode->pdev); 290 if (regnode->ofw_node <= 0) 291 return (NULL); 292#endif 293 294 rv = REGNODE_INIT(regnode); 295 if (rv != 0) { 296 printf("REGNODE_INIT failed: %d\n", rv); 297 return (NULL); 298 } 299 300 REG_TOPO_XLOCK(); 301 TAILQ_INSERT_TAIL(®node_list, regnode, reglist_link); 302 REG_TOPO_UNLOCK(); 303#ifdef FDT 304 OF_device_register_xref(OF_xref_from_node(regnode->ofw_node), 305 regnode->pdev); 306#endif 307 return (regnode); 308} 309 310static int 311regnode_resolve_parent(struct regnode *regnode) 312{ 313 314 /* All ready resolved or no parent? */ 315 if ((regnode->parent != NULL) || 316 (regnode->parent_name == NULL)) 317 return (0); 318 319 regnode->parent = regnode_find_by_name(regnode->parent_name); 320 if (regnode->parent == NULL) 321 return (ENODEV); 322 return (0); 323} 324 325static void 326regnode_delay(int usec) 327{ 328 int ticks; 329 330 if (usec == 0) 331 return; 332 ticks = (usec * hz + 999999) / 1000000; 333 334 if (cold || ticks < 2) 335 DELAY(usec); 336 else 337 pause("REGULATOR", ticks); 338} 339 340/* -------------------------------------------------------------------------- 341 * 342 * Regulator providers interface 343 * 344 */ 345 346const char * 347regnode_get_name(struct regnode *regnode) 348{ 349 350 return (regnode->name); 351} 352 353const char * 354regnode_get_parent_name(struct regnode *regnode) 355{ 356 357 return (regnode->parent_name); 358} 359 360int 361regnode_get_flags(struct regnode *regnode) 362{ 363 364 return (regnode->flags); 365} 366 367void * 368regnode_get_softc(struct regnode *regnode) 369{ 370 371 return (regnode->softc); 372} 373 374device_t 375regnode_get_device(struct regnode *regnode) 376{ 377 378 return (regnode->pdev); 379} 380 381struct regnode_std_param *regnode_get_stdparam(struct regnode *regnode) 382{ 383 384 return (®node->std_param); 385} 386 387void regnode_topo_unlock(void) 388{ 389 390 REG_TOPO_UNLOCK(); 391} 392 393void regnode_topo_xlock(void) 394{ 395 396 REG_TOPO_XLOCK(); 397} 398 399void regnode_topo_slock(void) 400{ 401 402 REG_TOPO_SLOCK(); 403} 404 405 406/* -------------------------------------------------------------------------- 407 * 408 * Real consumers executive 409 * 410 */ 411struct regnode * 412regnode_get_parent(struct regnode *regnode) 413{ 414 int rv; 415 416 REG_TOPO_ASSERT(); 417 418 rv = regnode_resolve_parent(regnode); 419 if (rv != 0) 420 return (NULL); 421 422 return (regnode->parent); 423} 424 425/* 426 * Enable regulator. 427 */ 428int 429regnode_enable(struct regnode *regnode) 430{ 431 int udelay; 432 int rv; 433 434 REG_TOPO_ASSERT(); 435 436 /* Enable regulator for each node in chain, starting from source. */ 437 rv = regnode_resolve_parent(regnode); 438 if (rv != 0) 439 return (rv); 440 if (regnode->parent != NULL) { 441 rv = regnode_enable(regnode->parent); 442 if (rv != 0) 443 return (rv); 444 } 445 446 /* Handle this node. */ 447 REGNODE_XLOCK(regnode); 448 if (regnode->enable_cnt == 0) { 449 rv = REGNODE_ENABLE(regnode, true, &udelay); 450 if (rv != 0) { 451 REGNODE_UNLOCK(regnode); 452 return (rv); 453 } 454 regnode_delay(udelay); 455 } 456 regnode->enable_cnt++; 457 REGNODE_UNLOCK(regnode); 458 return (0); 459} 460 461/* 462 * Disable regulator. 463 */ 464int 465regnode_disable(struct regnode *regnode) 466{ 467 int udelay; 468 int rv; 469 470 REG_TOPO_ASSERT(); 471 rv = 0; 472 473 REGNODE_XLOCK(regnode); 474 /* Disable regulator for each node in chain, starting from consumer. */ 475 if ((regnode->enable_cnt == 1) && 476 ((regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0)) { 477 rv = REGNODE_ENABLE(regnode, false, &udelay); 478 if (rv != 0) { 479 REGNODE_UNLOCK(regnode); 480 return (rv); 481 } 482 regnode_delay(udelay); 483 } 484 regnode->enable_cnt--; 485 REGNODE_UNLOCK(regnode); 486 487 rv = regnode_resolve_parent(regnode); 488 if (rv != 0) 489 return (rv); 490 if (regnode->parent != NULL) 491 rv = regnode_disable(regnode->parent); 492 return (rv); 493} 494 495/* 496 * Stop regulator. 497 */ 498int 499regnode_stop(struct regnode *regnode, int depth) 500{ 501 int udelay; 502 int rv; 503 504 REG_TOPO_ASSERT(); 505 rv = 0; 506 507 REGNODE_XLOCK(regnode); 508 /* The first node must not be enabled. */ 509 if ((regnode->enable_cnt != 0) && (depth == 0)) { 510 REGNODE_UNLOCK(regnode); 511 return (EBUSY); 512 } 513 /* Disable regulator for each node in chain, starting from consumer */ 514 if ((regnode->enable_cnt == 0) && 515 ((regnode->flags & REGULATOR_FLAGS_NOT_DISABLE) == 0)) { 516 rv = REGNODE_ENABLE(regnode, false, &udelay); 517 if (rv != 0) { 518 REGNODE_UNLOCK(regnode); 519 return (rv); 520 } 521 regnode_delay(udelay); 522 } 523 REGNODE_UNLOCK(regnode); 524 525 rv = regnode_resolve_parent(regnode); 526 if (rv != 0) 527 return (rv); 528 if (regnode->parent != NULL) 529 rv = regnode_stop(regnode->parent, depth + 1); 530 return (rv); 531} 532 533/* 534 * Get regulator status. (REGULATOR_STATUS_*) 535 */ 536int 537regnode_status(struct regnode *regnode, int *status) 538{ 539 int rv; 540 541 REG_TOPO_ASSERT(); 542 543 REGNODE_XLOCK(regnode); 544 rv = REGNODE_STATUS(regnode, status); 545 REGNODE_UNLOCK(regnode); 546 return (rv); 547} 548 549/* 550 * Get actual regulator voltage. 551 */ 552int 553regnode_get_voltage(struct regnode *regnode, int *uvolt) 554{ 555 int rv; 556 557 REG_TOPO_ASSERT(); 558 559 REGNODE_XLOCK(regnode); 560 rv = REGNODE_GET_VOLTAGE(regnode, uvolt); 561 REGNODE_UNLOCK(regnode); 562 563 /* Pass call into parent, if regulator is in bypass mode. */ 564 if (rv == ENOENT) { 565 rv = regnode_resolve_parent(regnode); 566 if (rv != 0) 567 return (rv); 568 if (regnode->parent != NULL) 569 rv = regnode_get_voltage(regnode->parent, uvolt); 570 571 } 572 return (rv); 573} 574 575/* 576 * Set regulator voltage. 577 */ 578int 579regnode_set_voltage(struct regnode *regnode, int min_uvolt, int max_uvolt) 580{ 581 int udelay; 582 int rv; 583 584 REG_TOPO_ASSERT(); 585 586 REGNODE_XLOCK(regnode); 587 588 rv = REGNODE_SET_VOLTAGE(regnode, min_uvolt, max_uvolt, &udelay); 589 if (rv == 0) 590 regnode_delay(udelay); 591 REGNODE_UNLOCK(regnode); 592 return (rv); 593} 594 595/* 596 * Consumer variant of regnode_set_voltage(). 597 */ 598static int 599regnode_set_voltage_checked(struct regnode *regnode, struct regulator *reg, 600 int min_uvolt, int max_uvolt) 601{ 602 int udelay; 603 int all_max_uvolt; 604 int all_min_uvolt; 605 struct regulator *tmp; 606 int rv; 607 608 REG_TOPO_ASSERT(); 609 610 REGNODE_XLOCK(regnode); 611 /* Return error if requested range is outside of regulator range. */ 612 if ((min_uvolt > regnode->std_param.max_uvolt) || 613 (max_uvolt < regnode->std_param.min_uvolt)) { 614 REGNODE_UNLOCK(regnode); 615 return (ERANGE); 616 } 617 618 /* Get actual voltage range for all consumers. */ 619 all_min_uvolt = regnode->std_param.min_uvolt; 620 all_max_uvolt = regnode->std_param.max_uvolt; 621 TAILQ_FOREACH(tmp, ®node->consumers_list, link) { 622 /* Don't take requestor in account. */ 623 if (tmp == reg) 624 continue; 625 if (all_min_uvolt < tmp->min_uvolt) 626 all_min_uvolt = tmp->min_uvolt; 627 if (all_max_uvolt > tmp->max_uvolt) 628 all_max_uvolt = tmp->max_uvolt; 629 } 630 631 /* Test if request fits to actual contract. */ 632 if ((min_uvolt > all_max_uvolt) || 633 (max_uvolt < all_min_uvolt)) { 634 REGNODE_UNLOCK(regnode); 635 return (ERANGE); 636 } 637 638 /* Adjust new range.*/ 639 if (min_uvolt < all_min_uvolt) 640 min_uvolt = all_min_uvolt; 641 if (max_uvolt > all_max_uvolt) 642 max_uvolt = all_max_uvolt; 643 644 rv = REGNODE_SET_VOLTAGE(regnode, min_uvolt, max_uvolt, &udelay); 645 regnode_delay(udelay); 646 REGNODE_UNLOCK(regnode); 647 return (rv); 648} 649 650#ifdef FDT 651phandle_t 652regnode_get_ofw_node(struct regnode *regnode) 653{ 654 655 return (regnode->ofw_node); 656} 657#endif 658 659/* -------------------------------------------------------------------------- 660 * 661 * Regulator consumers interface. 662 * 663 */ 664/* Helper function for regulator_get*() */ 665static regulator_t 666regulator_create(struct regnode *regnode, device_t cdev) 667{ 668 struct regulator *reg; 669 670 REG_TOPO_ASSERT(); 671 672 reg = malloc(sizeof(struct regulator), M_REGULATOR, 673 M_WAITOK | M_ZERO); 674 reg->cdev = cdev; 675 reg->regnode = regnode; 676 reg->enable_cnt = 0; 677 678 REGNODE_XLOCK(regnode); 679 regnode->ref_cnt++; 680 TAILQ_INSERT_TAIL(®node->consumers_list, reg, link); 681 reg ->min_uvolt = regnode->std_param.min_uvolt; 682 reg ->max_uvolt = regnode->std_param.max_uvolt; 683 REGNODE_UNLOCK(regnode); 684 685 return (reg); 686} 687 688int 689regulator_enable(regulator_t reg) 690{ 691 int rv; 692 struct regnode *regnode; 693 694 regnode = reg->regnode; 695 KASSERT(regnode->ref_cnt > 0, 696 ("Attempt to access unreferenced regulator: %s\n", regnode->name)); 697 REG_TOPO_SLOCK(); 698 rv = regnode_enable(regnode); 699 if (rv == 0) 700 reg->enable_cnt++; 701 REG_TOPO_UNLOCK(); 702 return (rv); 703} 704 705int 706regulator_disable(regulator_t reg) 707{ 708 int rv; 709 struct regnode *regnode; 710 711 regnode = reg->regnode; 712 KASSERT(regnode->ref_cnt > 0, 713 ("Attempt to access unreferenced regulator: %s\n", regnode->name)); 714 KASSERT(reg->enable_cnt > 0, 715 ("Attempt to disable already disabled regulator: %s\n", 716 regnode->name)); 717 REG_TOPO_SLOCK(); 718 rv = regnode_disable(regnode); 719 if (rv == 0) 720 reg->enable_cnt--; 721 REG_TOPO_UNLOCK(); 722 return (rv); 723} 724 725int 726regulator_stop(regulator_t reg) 727{ 728 int rv; 729 struct regnode *regnode; 730 731 regnode = reg->regnode; 732 KASSERT(regnode->ref_cnt > 0, 733 ("Attempt to access unreferenced regulator: %s\n", regnode->name)); 734 KASSERT(reg->enable_cnt == 0, 735 ("Attempt to stop already enabled regulator: %s\n", regnode->name)); 736 737 REG_TOPO_SLOCK(); 738 rv = regnode_stop(regnode, 0); 739 REG_TOPO_UNLOCK(); 740 return (rv); 741} 742 743int 744regulator_status(regulator_t reg, int *status) 745{ 746 int rv; 747 struct regnode *regnode; 748 749 regnode = reg->regnode; 750 KASSERT(regnode->ref_cnt > 0, 751 ("Attempt to access unreferenced regulator: %s\n", regnode->name)); 752 753 REG_TOPO_SLOCK(); 754 rv = regnode_status(regnode, status); 755 REG_TOPO_UNLOCK(); 756 return (rv); 757} 758 759int 760regulator_get_voltage(regulator_t reg, int *uvolt) 761{ 762 int rv; 763 struct regnode *regnode; 764 765 regnode = reg->regnode; 766 KASSERT(regnode->ref_cnt > 0, 767 ("Attempt to access unreferenced regulator: %s\n", regnode->name)); 768 769 REG_TOPO_SLOCK(); 770 rv = regnode_get_voltage(regnode, uvolt); 771 REG_TOPO_UNLOCK(); 772 return (rv); 773} 774 775int 776regulator_set_voltage(regulator_t reg, int min_uvolt, int max_uvolt) 777{ 778 struct regnode *regnode; 779 int rv; 780 781 regnode = reg->regnode; 782 KASSERT(regnode->ref_cnt > 0, 783 ("Attempt to access unreferenced regulator: %s\n", regnode->name)); 784 785 REG_TOPO_SLOCK(); 786 787 rv = regnode_set_voltage_checked(regnode, reg, min_uvolt, max_uvolt); 788 if (rv == 0) { 789 reg->min_uvolt = min_uvolt; 790 reg->max_uvolt = max_uvolt; 791 } 792 REG_TOPO_UNLOCK(); 793 return (rv); 794} 795 796const char * 797regulator_get_name(regulator_t reg) 798{ 799 struct regnode *regnode; 800 801 regnode = reg->regnode; 802 KASSERT(regnode->ref_cnt > 0, 803 ("Attempt to access unreferenced regulator: %s\n", regnode->name)); 804 return (regnode->name); 805} 806 807int 808regulator_get_by_name(device_t cdev, const char *name, regulator_t *reg) 809{ 810 struct regnode *regnode; 811 812 REG_TOPO_SLOCK(); 813 regnode = regnode_find_by_name(name); 814 if (regnode == NULL) { 815 REG_TOPO_UNLOCK(); 816 return (ENODEV); 817 } 818 *reg = regulator_create(regnode, cdev); 819 REG_TOPO_UNLOCK(); 820 return (0); 821} 822 823int 824regulator_get_by_id(device_t cdev, device_t pdev, intptr_t id, regulator_t *reg) 825{ 826 struct regnode *regnode; 827 828 REG_TOPO_SLOCK(); 829 830 regnode = regnode_find_by_id(pdev, id); 831 if (regnode == NULL) { 832 REG_TOPO_UNLOCK(); 833 return (ENODEV); 834 } 835 *reg = regulator_create(regnode, cdev); 836 REG_TOPO_UNLOCK(); 837 838 return (0); 839} 840 841int 842regulator_release(regulator_t reg) 843{ 844 struct regnode *regnode; 845 846 regnode = reg->regnode; 847 KASSERT(regnode->ref_cnt > 0, 848 ("Attempt to access unreferenced regulator: %s\n", regnode->name)); 849 REG_TOPO_SLOCK(); 850 while (reg->enable_cnt > 0) { 851 regnode_disable(regnode); 852 reg->enable_cnt--; 853 } 854 REGNODE_XLOCK(regnode); 855 TAILQ_REMOVE(®node->consumers_list, reg, link); 856 regnode->ref_cnt--; 857 REGNODE_UNLOCK(regnode); 858 REG_TOPO_UNLOCK(); 859 860 free(reg, M_REGULATOR); 861 return (0); 862} 863 864#ifdef FDT 865/* Default DT mapper. */ 866int 867regdev_default_ofw_map(device_t dev, phandle_t xref, int ncells, 868 pcell_t *cells, intptr_t *id) 869{ 870 if (ncells == 0) 871 *id = 1; 872 else if (ncells == 1) 873 *id = cells[0]; 874 else 875 return (ERANGE); 876 877 return (0); 878} 879 880int 881regulator_parse_ofw_stdparam(device_t pdev, phandle_t node, 882 struct regnode_init_def *def) 883{ 884 phandle_t supply_xref; 885 struct regnode_std_param *par; 886 int rv; 887 888 par = &def->std_param; 889 rv = OF_getprop_alloc(node, "regulator-name", 1, 890 (void **)&def->name); 891 if (rv <= 0) { 892 device_printf(pdev, "%s: Missing regulator name\n", 893 __func__); 894 return (ENXIO); 895 } 896 897 rv = OF_getencprop(node, "regulator-min-microvolt", &par->min_uvolt, 898 sizeof(par->min_uvolt)); 899 if (rv <= 0) 900 par->min_uvolt = 0; 901 902 rv = OF_getencprop(node, "regulator-max-microvolt", &par->max_uvolt, 903 sizeof(par->max_uvolt)); 904 if (rv <= 0) 905 par->max_uvolt = 0; 906 907 rv = OF_getencprop(node, "regulator-min-microamp", &par->min_uamp, 908 sizeof(par->min_uamp)); 909 if (rv <= 0) 910 par->min_uamp = 0; 911 912 rv = OF_getencprop(node, "regulator-max-microamp", &par->max_uamp, 913 sizeof(par->max_uamp)); 914 if (rv <= 0) 915 par->max_uamp = 0; 916 917 rv = OF_getencprop(node, "regulator-ramp-delay", &par->ramp_delay, 918 sizeof(par->ramp_delay)); 919 if (rv <= 0) 920 par->ramp_delay = 0; 921 922 rv = OF_getencprop(node, "regulator-enable-ramp-delay", 923 &par->enable_delay, sizeof(par->enable_delay)); 924 if (rv <= 0) 925 par->enable_delay = 0; 926 927 if (OF_hasprop(node, "regulator-boot-on")) 928 par->boot_on = 1; 929 930 if (OF_hasprop(node, "regulator-always-on")) 931 par->always_on = 1; 932 933 if (OF_hasprop(node, "enable-active-high")) 934 par->enable_active_high = 1; 935 936 rv = OF_getencprop(node, "vin-supply", &supply_xref, 937 sizeof(supply_xref)); 938 if (rv >= 0) { 939 rv = OF_getprop_alloc(supply_xref, "regulator-name", 1, 940 (void **)&def->parent_name); 941 if (rv <= 0) 942 def->parent_name = NULL; 943 } 944 return (0); 945} 946 947int 948regulator_get_by_ofw_property(device_t cdev, phandle_t cnode, char *name, 949 regulator_t *reg) 950{ 951 phandle_t *cells; 952 device_t regdev; 953 int ncells, rv; 954 intptr_t id; 955 956 *reg = NULL; 957 958 if (cnode <= 0) 959 cnode = ofw_bus_get_node(cdev); 960 if (cnode <= 0) { 961 device_printf(cdev, "%s called on not ofw based device\n", 962 __func__); 963 return (ENXIO); 964 } 965 966 cells = NULL; 967 ncells = OF_getencprop_alloc(cnode, name, sizeof(*cells), 968 (void **)&cells); 969 if (ncells <= 0) 970 return (ENXIO); 971 972 /* Translate xref to device */ 973 regdev = OF_device_from_xref(cells[0]); 974 if (regdev == NULL) { 975 OF_prop_free(cells); 976 return (ENODEV); 977 } 978 979 /* Map regulator to number */ 980 rv = REGDEV_MAP(regdev, cells[0], ncells - 1, cells + 1, &id); 981 OF_prop_free(cells); 982 if (rv != 0) 983 return (rv); 984 return (regulator_get_by_id(cdev, regdev, id, reg)); 985} 986#endif 987