Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'regulator-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator updates from Mark Brown:
"The big change in this release is the addition of Rust bindings from
Daniel Almeida, allowing fairly basic consumer use with support for
enable and voltage setting operations. This should be good for the
vast majority of consumers.

Otherwise it's been quite quiet, a few new devices supported, plus
some cleanups and fixes.

Summary:

- Basic Rust bindings

- A fix for making large voltage changes on regulators where we limit
the size of voltage change we will do in one step, previously we
just got as close as we could in one step

- Cleanups of our usage of the PM autosuspend functions, this pulls
in some PM core changes on a shared tag

- Mode setting support for PCA9450

- Support for Mediatek MT6893 and MT8196 DVFSRC, Qualcomm PM7550 and
PMR735B, Raspberry Pi displays and TI TPS652G1

The TI driver pulls in the MFD portion of the support for the device
and the pinctrl driver which was in the same tag"

* tag 'regulator-v6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (40 commits)
regulator: mt6370: Fix spelling mistake in mt6370_regualtor_register
regulator: Kconfig: Fix spelling mistake "regualtor" -> "regulator"
regulator: core: repeat voltage setting request for stepped regulators
regulator: rt6160: Add rt6166 vout min_uV setting for compatible
MAINTAINERS: add regulator.rs to the regulator API entry
rust: regulator: add a bare minimum regulator abstraction
regulator: tps6286x-regulator: Fix a copy & paste error
regulator: qcom-rpmh: add support for pm7550 regulators
regulator: qcom-rpmh: add support for pmr735b regulators
regulator: dt-bindings: qcom,rpmh: Add PMR735B compatible
regulator: dt-bindings: qcom,rpmh: Add PM7550 compatible
regulator: tps6594-regulator: Add TI TPS652G1 PMIC regulators
regulator: tps6594-regulator: refactor variant descriptions
regulator: tps6594-regulator: remove hardcoded buck config
regulator: tps6594-regulator: remove interrupt_count
dt-bindings: mfd: ti,tps6594: Add TI TPS652G1 PMIC
pinctrl: pinctrl-tps6594: Add TPS652G1 PMIC pinctrl and GPIO
misc: tps6594-pfsm: Add TI TPS652G1 PMIC PFSM
mfd: tps6594: Add TI TPS652G1 support
regulator: sy8827n: make enable gpio NONEXCLUSIVE
...

+1326 -170
+1
Documentation/devicetree/bindings/mfd/ti,tps6594.yaml
··· 22 22 - ti,tps6593-q1 23 23 - ti,tps6594-q1 24 24 - ti,tps65224-q1 25 + - ti,tps652g1 25 26 26 27 reg: 27 28 description: I2C slave address or SPI chip select number.
+2
Documentation/devicetree/bindings/regulator/mediatek,mt6873-dvfsrc-regulator.yaml
··· 17 17 compatible: 18 18 enum: 19 19 - mediatek,mt6873-dvfsrc-regulator 20 + - mediatek,mt6893-dvfsrc-regulator 20 21 - mediatek,mt8183-dvfsrc-regulator 21 22 - mediatek,mt8192-dvfsrc-regulator 22 23 - mediatek,mt8195-dvfsrc-regulator 24 + - mediatek,mt8196-dvfsrc-regulator 23 25 24 26 dvfsrc-vcore: 25 27 description: DVFSRC-controlled SoC Vcore regulator
+14
Documentation/devicetree/bindings/regulator/nxp,pca9450-regulator.yaml
··· 100 100 PMIC default "STANDBY" state voltage in uV. Only Buck1~3 have such 101 101 dvs(dynamic voltage scaling) property. 102 102 103 + regulator-allowed-modes: 104 + description: | 105 + Buck regulator operating modes allowed. Valid values below. 106 + Users should use the macros from dt-bindings/regulator/nxp,pca9450-regulator.h 107 + 0 (PCA9450_BUCK_MODE_AUTO): Auto PFM/PWM mode 108 + 1 (PCA9450_BUCK_MODE_FORCE_PWM): Forced PWM mode 109 + items: 110 + enum: [ 0, 1 ] 111 + 103 112 unevaluatedProperties: false 104 113 105 114 additionalProperties: false ··· 152 143 examples: 153 144 - | 154 145 #include <dt-bindings/interrupt-controller/irq.h> 146 + #include <dt-bindings/regulator/nxp,pca9450-regulator.h> 155 147 156 148 i2c { 157 149 #address-cells = <1>; ··· 189 179 regulator-max-microvolt = <3400000>; 190 180 regulator-boot-on; 191 181 regulator-always-on; 182 + regulator-initial-mode = <PCA9450_BUCK_MODE_FORCE_PWM>; 183 + regulator-allowed-modes = <PCA9450_BUCK_MODE_FORCE_PWM>; 192 184 }; 193 185 buck5: BUCK5 { 194 186 regulator-name = "BUCK5"; ··· 198 186 regulator-max-microvolt = <3400000>; 199 187 regulator-boot-on; 200 188 regulator-always-on; 189 + regulator-allowed-modes = <PCA9450_BUCK_MODE_AUTO 190 + PCA9450_BUCK_MODE_FORCE_PWM>; 201 191 }; 202 192 buck6: BUCK6 { 203 193 regulator-name = "BUCK6";
+35
Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
··· 40 40 For PM660, smps1 - smps6, ldo1 - ldo3, ldo5 - ldo19 41 41 For PM660L, smps1 - smps3, smps5, ldo1 - ldo8, bob 42 42 For PM7325, smps1 - smps8, ldo1 - ldo19 43 + For PM7550, smps1 - smps6, ldo1 - ldo23, bob 43 44 For PM8005, smps1 - smps4 44 45 For PM8009, smps1 - smps2, ldo1 - ldo7 45 46 For PM8010, ldo1 - ldo7 ··· 54 53 For PMI8998, bob 55 54 For PMC8380, smps1 - smps8, ldo1 - lodo3 56 55 For PMR735A, smps1 - smps3, ldo1 - ldo7 56 + For PMR735B, ldo1 - ldo12 57 57 For PMX55, smps1 - smps7, ldo1 - ldo16 58 58 For PMX65, smps1 - smps8, ldo1 - ldo21 59 59 For PMX75, smps1 - smps10, ldo1 - ldo21 ··· 68 66 - qcom,pm660-rpmh-regulators 69 67 - qcom,pm660l-rpmh-regulators 70 68 - qcom,pm7325-rpmh-regulators 69 + - qcom,pm7550-rpmh-regulators 71 70 - qcom,pm8005-rpmh-regulators 72 71 - qcom,pm8009-rpmh-regulators 73 72 - qcom,pm8009-1-rpmh-regulators ··· 90 87 - qcom,pmm8155au-rpmh-regulators 91 88 - qcom,pmm8654au-rpmh-regulators 92 89 - qcom,pmr735a-rpmh-regulators 90 + - qcom,pmr735b-rpmh-regulators 93 91 - qcom,pmx55-rpmh-regulators 94 92 - qcom,pmx65-rpmh-regulators 95 93 - qcom,pmx75-rpmh-regulators ··· 221 217 patternProperties: 222 218 "^vdd-l[358]-supply$": true 223 219 "^vdd-s[1-8]-supply$": true 220 + 221 + - if: 222 + properties: 223 + compatible: 224 + enum: 225 + - qcom,pm7550-rpmh-regulators 226 + then: 227 + properties: 228 + vdd-bob-supply: 229 + description: BOB regulator parent supply phandle. 230 + vdd-l2-l3-supply: true 231 + vdd-l4-l5-supply: true 232 + vdd-l9-l10-supply: true 233 + vdd-l12-l14-supply: true 234 + vdd-l13-l16-supply: true 235 + vdd-l15-l17-l18-l19-l20-l21-l22-l23-supply: true 236 + patternProperties: 237 + "^vdd-l(1|[6-8]|11)-supply$": true 238 + "^vdd-s[1-6]-supply$": true 224 239 225 240 - if: 226 241 properties: ··· 446 423 vdd-l7-bob-supply: true 447 424 patternProperties: 448 425 "^vdd-s[1-3]-supply$": true 426 + 427 + - if: 428 + properties: 429 + compatible: 430 + enum: 431 + - qcom,pmr735b-rpmh-regulators 432 + then: 433 + properties: 434 + vdd-l1-l2-supply: true 435 + vdd-l7-l8-supply: true 436 + patternProperties: 437 + "^vdd-l([3-6]|9|1[0-2])-supply$": true 449 438 450 439 - if: 451 440 properties:
+5 -2
Documentation/devicetree/bindings/regulator/raspberrypi,7inch-touchscreen-panel-regulator.yaml
··· 12 12 description: | 13 13 The RaspberryPi 7" display has an ATTINY88-based regulator/backlight 14 14 controller on the PCB, which is used to turn the display unit on/off 15 - and control the backlight. 15 + and control the backlight. The V2 supports 5" and 7" panels and also 16 + offers PWM backlight control. 16 17 17 18 allOf: 18 19 - $ref: regulator.yaml# 19 20 20 21 properties: 21 22 compatible: 22 - const: raspberrypi,7inch-touchscreen-panel-regulator 23 + enum: 24 + - raspberrypi,7inch-touchscreen-panel-regulator 25 + - raspberrypi,touchscreen-panel-regulator-v2 23 26 24 27 reg: 25 28 maxItems: 1
+1
MAINTAINERS
··· 26582 26582 F: Documentation/devicetree/bindings/regulator/ 26583 26583 F: Documentation/power/regulator/ 26584 26584 F: drivers/regulator/ 26585 + F: rust/kernel/regulator.rs 26585 26586 F: include/dt-bindings/regulator/ 26586 26587 F: include/linux/regulator/ 26587 26588 K: regulator_get_optional
+82 -6
drivers/mfd/tps6594-core.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * Core functions for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs 3 + * Core functions for following TI PMICs: 4 + * - LP8764 5 + * - TPS65224 6 + * - TPS652G1 7 + * - TPS6593 8 + * - TPS6594 4 9 * 5 10 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 6 11 */ ··· 419 414 TPS6594_REG_INT_FSM_ERR, 420 415 }; 421 416 417 + /* TPS652G1 Resources */ 418 + 419 + static const struct mfd_cell tps652g1_common_cells[] = { 420 + MFD_CELL_RES("tps6594-pfsm", tps65224_pfsm_resources), 421 + MFD_CELL_RES("tps6594-pinctrl", tps65224_pinctrl_resources), 422 + MFD_CELL_NAME("tps6594-regulator"), 423 + }; 424 + 425 + static const struct regmap_irq tps652g1_irqs[] = { 426 + /* INT_GPIO register */ 427 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO1, 2, TPS65224_BIT_GPIO1_INT), 428 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO2, 2, TPS65224_BIT_GPIO2_INT), 429 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO3, 2, TPS65224_BIT_GPIO3_INT), 430 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO4, 2, TPS65224_BIT_GPIO4_INT), 431 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO5, 2, TPS65224_BIT_GPIO5_INT), 432 + REGMAP_IRQ_REG(TPS65224_IRQ_GPIO6, 2, TPS65224_BIT_GPIO6_INT), 433 + 434 + /* INT_STARTUP register */ 435 + REGMAP_IRQ_REG(TPS65224_IRQ_VSENSE, 3, TPS65224_BIT_VSENSE_INT), 436 + REGMAP_IRQ_REG(TPS65224_IRQ_ENABLE, 3, TPS6594_BIT_ENABLE_INT), 437 + REGMAP_IRQ_REG(TPS65224_IRQ_PB_SHORT, 3, TPS65224_BIT_PB_SHORT_INT), 438 + REGMAP_IRQ_REG(TPS65224_IRQ_FSD, 3, TPS6594_BIT_FSD_INT), 439 + REGMAP_IRQ_REG(TPS65224_IRQ_SOFT_REBOOT, 3, TPS6594_BIT_SOFT_REBOOT_INT), 440 + 441 + /* INT_MISC register */ 442 + REGMAP_IRQ_REG(TPS65224_IRQ_BIST_PASS, 4, TPS6594_BIT_BIST_PASS_INT), 443 + REGMAP_IRQ_REG(TPS65224_IRQ_EXT_CLK, 4, TPS6594_BIT_EXT_CLK_INT), 444 + REGMAP_IRQ_REG(TPS65224_IRQ_REG_UNLOCK, 4, TPS65224_BIT_REG_UNLOCK_INT), 445 + REGMAP_IRQ_REG(TPS65224_IRQ_TWARN, 4, TPS6594_BIT_TWARN_INT), 446 + REGMAP_IRQ_REG(TPS65224_IRQ_PB_LONG, 4, TPS65224_BIT_PB_LONG_INT), 447 + REGMAP_IRQ_REG(TPS65224_IRQ_PB_FALL, 4, TPS65224_BIT_PB_FALL_INT), 448 + REGMAP_IRQ_REG(TPS65224_IRQ_PB_RISE, 4, TPS65224_BIT_PB_RISE_INT), 449 + REGMAP_IRQ_REG(TPS65224_IRQ_ADC_CONV_READY, 4, TPS65224_BIT_ADC_CONV_READY_INT), 450 + 451 + /* INT_MODERATE_ERR register */ 452 + REGMAP_IRQ_REG(TPS65224_IRQ_TSD_ORD, 5, TPS6594_BIT_TSD_ORD_INT), 453 + REGMAP_IRQ_REG(TPS65224_IRQ_BIST_FAIL, 5, TPS6594_BIT_BIST_FAIL_INT), 454 + REGMAP_IRQ_REG(TPS65224_IRQ_REG_CRC_ERR, 5, TPS6594_BIT_REG_CRC_ERR_INT), 455 + REGMAP_IRQ_REG(TPS65224_IRQ_RECOV_CNT, 5, TPS6594_BIT_RECOV_CNT_INT), 456 + 457 + /* INT_SEVERE_ERR register */ 458 + REGMAP_IRQ_REG(TPS65224_IRQ_TSD_IMM, 6, TPS6594_BIT_TSD_IMM_INT), 459 + REGMAP_IRQ_REG(TPS65224_IRQ_VCCA_OVP, 6, TPS6594_BIT_VCCA_OVP_INT), 460 + REGMAP_IRQ_REG(TPS65224_IRQ_PFSM_ERR, 6, TPS6594_BIT_PFSM_ERR_INT), 461 + REGMAP_IRQ_REG(TPS65224_IRQ_BG_XMON, 6, TPS65224_BIT_BG_XMON_INT), 462 + 463 + /* INT_FSM_ERR register */ 464 + REGMAP_IRQ_REG(TPS65224_IRQ_IMM_SHUTDOWN, 7, TPS6594_BIT_IMM_SHUTDOWN_INT), 465 + REGMAP_IRQ_REG(TPS65224_IRQ_ORD_SHUTDOWN, 7, TPS6594_BIT_ORD_SHUTDOWN_INT), 466 + REGMAP_IRQ_REG(TPS65224_IRQ_MCU_PWR_ERR, 7, TPS6594_BIT_MCU_PWR_ERR_INT), 467 + REGMAP_IRQ_REG(TPS65224_IRQ_SOC_PWR_ERR, 7, TPS6594_BIT_SOC_PWR_ERR_INT), 468 + REGMAP_IRQ_REG(TPS65224_IRQ_COMM_ERR, 7, TPS6594_BIT_COMM_ERR_INT), 469 + REGMAP_IRQ_REG(TPS65224_IRQ_I2C2_ERR, 7, TPS65224_BIT_I2C2_ERR_INT), 470 + }; 471 + 422 472 static inline unsigned int tps6594_get_irq_reg(struct regmap_irq_chip_data *data, 423 473 unsigned int base, int index) 424 474 { ··· 503 443 * a new interrupt. 504 444 */ 505 445 if (tps->use_crc) { 506 - if (tps->chip_id == TPS65224) { 446 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) { 507 447 regmap_reg = TPS6594_REG_INT_FSM_ERR; 508 448 mask_val = TPS6594_BIT_COMM_ERR_INT; 509 449 } else { ··· 541 481 .handle_post_irq = tps6594_handle_post_irq, 542 482 }; 543 483 484 + static struct regmap_irq_chip tps652g1_irq_chip = { 485 + .ack_base = TPS6594_REG_INT_BUCK, 486 + .ack_invert = 1, 487 + .clear_ack = 1, 488 + .init_ack_masked = 1, 489 + .num_regs = ARRAY_SIZE(tps65224_irq_reg), 490 + .irqs = tps652g1_irqs, 491 + .num_irqs = ARRAY_SIZE(tps652g1_irqs), 492 + .get_irq_reg = tps65224_get_irq_reg, 493 + .handle_post_irq = tps6594_handle_post_irq, 494 + }; 495 + 544 496 static const struct regmap_range tps6594_volatile_ranges[] = { 545 497 regmap_reg_range(TPS6594_REG_INT_TOP, TPS6594_REG_STAT_READBACK_ERR), 546 498 regmap_reg_range(TPS6594_REG_RTC_STATUS, TPS6594_REG_RTC_STATUS), ··· 579 507 int ret; 580 508 unsigned int regmap_reg, mask_val; 581 509 582 - if (tps->chip_id == TPS65224) { 510 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) { 583 511 regmap_reg = TPS6594_REG_CONFIG_2; 584 512 mask_val = TPS65224_BIT_I2C1_SPI_CRC_EN; 585 513 } else { ··· 609 537 int ret; 610 538 unsigned int regmap_reg, mask_val; 611 539 612 - if (tps->chip_id == TPS65224) { 540 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) { 613 541 regmap_reg = TPS6594_REG_CONFIG_2; 614 542 mask_val = TPS65224_BIT_I2C1_SPI_CRC_EN; 615 543 } else { ··· 700 628 irq_chip = &tps65224_irq_chip; 701 629 n_cells = ARRAY_SIZE(tps65224_common_cells); 702 630 cells = tps65224_common_cells; 631 + } else if (tps->chip_id == TPS652G1) { 632 + irq_chip = &tps652g1_irq_chip; 633 + n_cells = ARRAY_SIZE(tps652g1_common_cells); 634 + cells = tps652g1_common_cells; 703 635 } else { 704 636 irq_chip = &tps6594_irq_chip; 705 637 n_cells = ARRAY_SIZE(tps6594_common_cells); ··· 727 651 if (ret) 728 652 return dev_err_probe(dev, ret, "Failed to add common child devices\n"); 729 653 730 - /* No RTC for LP8764 and TPS65224 */ 731 - if (tps->chip_id != LP8764 && tps->chip_id != TPS65224) { 654 + /* No RTC for LP8764, TPS65224 and TPS652G1 */ 655 + if (tps->chip_id != LP8764 && tps->chip_id != TPS65224 && tps->chip_id != TPS652G1) { 732 656 ret = devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, tps6594_rtc_cells, 733 657 ARRAY_SIZE(tps6594_rtc_cells), NULL, 0, 734 658 regmap_irq_get_domain(tps->irq_data));
+8 -2
drivers/mfd/tps6594-i2c.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * I2C access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs 3 + * I2C access driver for the following TI PMICs: 4 + * - LP8764 5 + * - TPS65224 6 + * - TPS652G1 7 + * - TPS6593 8 + * - TPS6594 4 9 * 5 10 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 6 11 */ ··· 202 197 { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, }, 203 198 { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, }, 204 199 { .compatible = "ti,tps65224-q1", .data = (void *)TPS65224, }, 200 + { .compatible = "ti,tps652g1", .data = (void *)TPS652G1, }, 205 201 {} 206 202 }; 207 203 MODULE_DEVICE_TABLE(of, tps6594_i2c_of_match_table); ··· 228 222 return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n"); 229 223 tps->chip_id = (unsigned long)match->data; 230 224 231 - if (tps->chip_id == TPS65224) 225 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) 232 226 tps6594_i2c_regmap_config.volatile_table = &tps65224_volatile_table; 233 227 234 228 tps->regmap = devm_regmap_init(dev, NULL, client, &tps6594_i2c_regmap_config);
+8 -2
drivers/mfd/tps6594-spi.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * SPI access driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs 3 + * SPI access driver for the following TI PMICs: 4 + * - LP8764 5 + * - TPS65224 6 + * - TPS652G1 7 + * - TPS6593 8 + * - TPS6594 4 9 * 5 10 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 6 11 */ ··· 87 82 { .compatible = "ti,tps6593-q1", .data = (void *)TPS6593, }, 88 83 { .compatible = "ti,lp8764-q1", .data = (void *)LP8764, }, 89 84 { .compatible = "ti,tps65224-q1", .data = (void *)TPS65224, }, 85 + { .compatible = "ti,tps652g1", .data = (void *)TPS652G1, }, 90 86 {} 91 87 }; 92 88 MODULE_DEVICE_TABLE(of, tps6594_spi_of_match_table); ··· 113 107 return dev_err_probe(dev, -EINVAL, "Failed to find matching chip ID\n"); 114 108 tps->chip_id = (unsigned long)match->data; 115 109 116 - if (tps->chip_id == TPS65224) 110 + if (tps->chip_id == TPS65224 || tps->chip_id == TPS652G1) 117 111 tps6594_spi_regmap_config.volatile_table = &tps65224_volatile_table; 118 112 119 113 tps->regmap = devm_regmap_init(dev, NULL, spi, &tps6594_spi_regmap_config);
+21 -10
drivers/misc/tps6594-pfsm.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* 3 - * PFSM (Pre-configurable Finite State Machine) driver for TI TPS65224/TPS6594/TPS6593/LP8764 PMICs 3 + * PFSM (Pre-configurable Finite State Machine) driver for the following 4 + * PMICs: 5 + * - LP8764 6 + * - TPS65224 7 + * - TPS652G1 8 + * - TPS6594 9 + * - TPS6593 4 10 * 5 11 * Copyright (C) 2023 BayLibre Incorporated - https://www.baylibre.com/ 6 12 */ ··· 147 141 switch (cmd) { 148 142 case PMIC_GOTO_STANDBY: 149 143 /* Disable LP mode on TPS6594 Family PMIC */ 150 - if (pfsm->chip_id != TPS65224) { 144 + if (pfsm->chip_id != TPS65224 && pfsm->chip_id != TPS652G1) { 151 145 ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_RTC_CTRL_2, 152 146 TPS6594_BIT_LP_STANDBY_SEL); 153 147 ··· 160 154 TPS6594_BIT_TRIGGER_I2C(0), TPS6594_BIT_TRIGGER_I2C(0)); 161 155 break; 162 156 case PMIC_GOTO_LP_STANDBY: 163 - /* TPS65224 does not support LP STANDBY */ 164 - if (pfsm->chip_id == TPS65224) 157 + /* TPS65224/TPS652G1 does not support LP STANDBY */ 158 + if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 165 159 return ret; 166 160 167 161 /* Enable LP mode */ ··· 185 179 TPS6594_BIT_NSLEEP1B | TPS6594_BIT_NSLEEP2B); 186 180 break; 187 181 case PMIC_SET_MCU_ONLY_STATE: 188 - /* TPS65224 does not support MCU_ONLY_STATE */ 189 - if (pfsm->chip_id == TPS65224) 182 + /* TPS65224/TPS652G1 does not support MCU_ONLY_STATE */ 183 + if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 190 184 return ret; 191 185 192 186 if (copy_from_user(&state_opt, argp, sizeof(state_opt))) ··· 212 206 return -EFAULT; 213 207 214 208 /* Configure wake-up destination */ 215 - if (pfsm->chip_id == TPS65224) { 209 + if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) { 216 210 regmap_reg = TPS65224_REG_STARTUP_CTRL; 217 211 mask = TPS65224_MASK_STARTUP_DEST; 218 212 } else { ··· 236 230 return ret; 237 231 238 232 /* Modify NSLEEP1-2 bits */ 239 - ret = regmap_clear_bits(pfsm->regmap, TPS6594_REG_FSM_NSLEEP_TRIGGERS, 240 - pfsm->chip_id == TPS65224 ? 241 - TPS6594_BIT_NSLEEP1B : TPS6594_BIT_NSLEEP2B); 233 + if (pfsm->chip_id == TPS65224 || pfsm->chip_id == TPS652G1) 234 + ret = regmap_clear_bits(pfsm->regmap, 235 + TPS6594_REG_FSM_NSLEEP_TRIGGERS, 236 + TPS6594_BIT_NSLEEP1B); 237 + else 238 + ret = regmap_clear_bits(pfsm->regmap, 239 + TPS6594_REG_FSM_NSLEEP_TRIGGERS, 240 + TPS6594_BIT_NSLEEP2B); 242 241 break; 243 242 } 244 243
+35
drivers/pinctrl/pinctrl-tps6594.c
··· 226 226 "GPIO5", 227 227 }; 228 228 229 + static const char *const tps652g1_cs_spi_func_group_names[] = { 230 + "GPIO1", 231 + }; 232 + 229 233 struct tps6594_pinctrl_function { 230 234 struct pinfunction pinfunction; 231 235 u8 muxval; ··· 291 287 FUNCTION(tps65224, nerr_mcu, TPS65224_PINCTRL_NERR_MCU_FUNCTION), 292 288 }; 293 289 290 + static const struct tps6594_pinctrl_function tps652g1_pinctrl_functions[] = { 291 + FUNCTION(tps65224, gpio, TPS6594_PINCTRL_GPIO_FUNCTION), 292 + FUNCTION(tps65224, sda_i2c2_sdo_spi, TPS65224_PINCTRL_SDA_I2C2_SDO_SPI_FUNCTION), 293 + FUNCTION(tps65224, nsleep2, TPS65224_PINCTRL_NSLEEP2_FUNCTION), 294 + FUNCTION(tps65224, nint, TPS65224_PINCTRL_NINT_FUNCTION), 295 + FUNCTION(tps652g1, cs_spi, TPS65224_PINCTRL_SCL_I2C2_CS_SPI_FUNCTION), 296 + FUNCTION(tps65224, nsleep1, TPS65224_PINCTRL_NSLEEP1_FUNCTION), 297 + FUNCTION(tps65224, pb, TPS65224_PINCTRL_PB_FUNCTION), 298 + FUNCTION(tps65224, wkup, TPS65224_PINCTRL_WKUP_FUNCTION), 299 + FUNCTION(tps65224, syncclkin, TPS65224_PINCTRL_SYNCCLKIN_FUNCTION), 300 + }; 301 + 294 302 struct tps6594_pinctrl { 295 303 struct tps6594 *tps; 296 304 struct gpio_regmap *gpio_regmap; ··· 314 298 u8 mux_sel_mask; 315 299 unsigned int remap_cnt; 316 300 struct muxval_remap *remap; 301 + }; 302 + 303 + static struct tps6594_pinctrl tps652g1_template_pinctrl = { 304 + .funcs = tps652g1_pinctrl_functions, 305 + .func_cnt = ARRAY_SIZE(tps652g1_pinctrl_functions), 306 + .pins = tps65224_pins, 307 + .num_pins = ARRAY_SIZE(tps65224_pins), 308 + .mux_sel_mask = TPS65224_MASK_GPIO_SEL, 309 + .remap = tps65224_muxval_remap, 310 + .remap_cnt = ARRAY_SIZE(tps65224_muxval_remap), 317 311 }; 318 312 319 313 static struct tps6594_pinctrl tps65224_template_pinctrl = { ··· 501 475 return -ENOMEM; 502 476 503 477 switch (tps->chip_id) { 478 + case TPS652G1: 479 + pctrl_desc->pins = tps65224_pins; 480 + pctrl_desc->npins = ARRAY_SIZE(tps65224_pins); 481 + 482 + *pinctrl = tps652g1_template_pinctrl; 483 + 484 + config.ngpio = ARRAY_SIZE(tps65224_gpio_func_group_names); 485 + config.ngpio_per_reg = TPS65224_NGPIO_PER_REG; 486 + break; 504 487 case TPS65224: 505 488 pctrl_desc->pins = tps65224_pins; 506 489 pctrl_desc->npins = ARRAY_SIZE(tps65224_pins);
+12 -1
drivers/regulator/Kconfig
··· 1153 1153 touchscreen unit. The regulator is used to enable power to the 1154 1154 TC358762, display and to control backlight. 1155 1155 1156 + config REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2 1157 + tristate "Raspberry Pi 7-inch touchscreen panel V2 regulator" 1158 + depends on GPIOLIB 1159 + depends on I2C && OF 1160 + select GPIO_REGMAP 1161 + select REGMAP_I2C 1162 + help 1163 + This driver supports regulator on the V2 Raspberry Pi touchscreen 1164 + unit. The regulator is used to enable power to the display and to 1165 + control backlight PWM. 1166 + 1156 1167 config REGULATOR_RC5T583 1157 1168 tristate "RICOH RC5T583 Power regulators" 1158 1169 depends on MFD_RC5T583 ··· 1203 1192 The device supports two regulators (DSVP/DSVN). 1204 1193 1205 1194 config REGULATOR_RT4803 1206 - tristate "Richtek RT4803 boost regualtor" 1195 + tristate "Richtek RT4803 boost regulator" 1207 1196 depends on I2C 1208 1197 select REGMAP_I2C 1209 1198 help
+1
drivers/regulator/Makefile
··· 136 136 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o 137 137 obj-$(CONFIG_REGULATOR_RAA215300) += raa215300.o 138 138 obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY) += rpi-panel-attiny-regulator.o 139 + obj-$(CONFIG_REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2) += rpi-panel-v2-regulator.o 139 140 obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o 140 141 obj-$(CONFIG_REGULATOR_RK808) += rk808-regulator.o 141 142 obj-$(CONFIG_REGULATOR_RN5T618) += rn5t618-regulator.o
+14 -13
drivers/regulator/bd718x7-regulator.c
··· 134 134 135 135 if (*mask) { 136 136 /* 137 - * Let's allow scheduling as we use I2C anyways. We just need to 138 - * guarantee minimum of 1ms sleep - it shouldn't matter if we 139 - * exceed it due to the scheduling. 137 + * We had fault detection disabled for the duration of the 138 + * voltage change. 139 + * 140 + * According to HW colleagues the maximum time it takes is 141 + * 1000us. I assume that on systems with light load this 142 + * might be less - and we could probably use DT to give 143 + * system specific delay value if performance matters. 144 + * 145 + * Well, knowing we use I2C here and can add scheduling delays 146 + * I don't think it is worth the hassle and I just add fixed 147 + * 1ms sleep here (and allow scheduling). If this turns out to 148 + * be a problem we can change it to delay and make the delay 149 + * time configurable. 140 150 */ 141 151 msleep(1); 142 152 ··· 183 173 /* 184 174 * If we increase LDO voltage when LDO is enabled we need to 185 175 * disable the power-good detection until voltage has reached 186 - * the new level. According to HW colleagues the maximum time 187 - * it takes is 1000us. I assume that on systems with light load 188 - * this might be less - and we could probably use DT to give 189 - * system specific delay value if performance matters. 190 - * 191 - * Well, knowing we use I2C here and can add scheduling delays 192 - * I don't think it is worth the hassle and I just add fixed 193 - * 1ms sleep here (and allow scheduling). If this turns out to 194 - * be a problem we can change it to delay and make the delay 195 - * time configurable. 176 + * the new level. 196 177 */ 197 178 if (new > now) { 198 179 int tmp;
+42 -1
drivers/regulator/core.c
··· 3797 3797 return 0; 3798 3798 } 3799 3799 3800 + static int regulator_get_voltage_delta(struct regulator_dev *rdev, int uV) 3801 + { 3802 + int current_uV = regulator_get_voltage_rdev(rdev); 3803 + 3804 + if (current_uV < 0) 3805 + return current_uV; 3806 + 3807 + return abs(current_uV - uV); 3808 + } 3809 + 3800 3810 static int regulator_set_voltage_unlocked(struct regulator *regulator, 3801 3811 int min_uV, int max_uV, 3802 3812 suspend_state_t state) ··· 3814 3804 struct regulator_dev *rdev = regulator->rdev; 3815 3805 struct regulator_voltage *voltage = &regulator->voltage[state]; 3816 3806 int ret = 0; 3807 + int current_uV, delta, new_delta; 3817 3808 int old_min_uV, old_max_uV; 3818 - int current_uV; 3819 3809 3820 3810 /* If we're setting the same range as last time the change 3821 3811 * should be a noop (some cpufreq implementations use the same ··· 3860 3850 if (ret < 0) { 3861 3851 voltage->min_uV = old_min_uV; 3862 3852 voltage->max_uV = old_max_uV; 3853 + } 3854 + 3855 + if (rdev->constraints->max_uV_step > 0) { 3856 + /* For regulators with a maximum voltage step, reaching the desired 3857 + * voltage might take a few retries. 3858 + */ 3859 + ret = regulator_get_voltage_delta(rdev, min_uV); 3860 + if (ret < 0) 3861 + goto out; 3862 + 3863 + delta = ret; 3864 + 3865 + while (delta > 0) { 3866 + ret = regulator_balance_voltage(rdev, state); 3867 + if (ret < 0) 3868 + goto out; 3869 + 3870 + ret = regulator_get_voltage_delta(rdev, min_uV); 3871 + if (ret < 0) 3872 + goto out; 3873 + 3874 + new_delta = ret; 3875 + 3876 + /* check that voltage is converging quickly enough */ 3877 + if (new_delta - delta > rdev->constraints->max_uV_step) { 3878 + ret = -EWOULDBLOCK; 3879 + goto out; 3880 + } 3881 + 3882 + delta = new_delta; 3883 + } 3863 3884 } 3864 3885 3865 3886 out:
+2 -2
drivers/regulator/mt6370-regulator.c
··· 320 320 return 0; 321 321 } 322 322 323 - static int mt6370_regualtor_register(struct mt6370_priv *priv) 323 + static int mt6370_regulator_register(struct mt6370_priv *priv) 324 324 { 325 325 struct regulator_dev *rdev; 326 326 struct regulator_config cfg = {}; ··· 363 363 return -ENODEV; 364 364 } 365 365 366 - ret = mt6370_regualtor_register(priv); 366 + ret = mt6370_regulator_register(priv); 367 367 if (ret) 368 368 return ret; 369 369
+38
drivers/regulator/mtk-dvfsrc-regulator.c
··· 117 117 .size = ARRAY_SIZE(mt6873_regulators), 118 118 }; 119 119 120 + static const unsigned int mt6893_voltages[] = { 121 + 575000, 122 + 600000, 123 + 650000, 124 + 725000, 125 + 750000, 126 + }; 127 + 128 + static const struct regulator_desc mt6893_regulators[] = { 129 + MTK_DVFSRC_VREG("dvfsrc-vcore", VCORE, mt6893_voltages), 130 + MTK_DVFSRC_VREG("dvfsrc-vscp", VSCP, mt6893_voltages), 131 + }; 132 + 133 + static const struct dvfsrc_regulator_pdata mt6893_data = { 134 + .descs = mt6893_regulators, 135 + .size = ARRAY_SIZE(mt6893_regulators), 136 + }; 137 + 120 138 static const unsigned int mt8183_voltages[] = { 121 139 725000, 122 140 800000, ··· 166 148 .size = ARRAY_SIZE(mt8195_regulators), 167 149 }; 168 150 151 + static const unsigned int mt8196_voltages[] = { 152 + 575000, 153 + 600000, 154 + 650000, 155 + 725000, 156 + 825000, 157 + 875000, 158 + }; 159 + 160 + static const struct regulator_desc mt8196_regulators[] = { 161 + MTK_DVFSRC_VREG("dvfsrc-vcore", VCORE, mt8196_voltages), 162 + }; 163 + 164 + static const struct dvfsrc_regulator_pdata mt8196_data = { 165 + .descs = mt8196_regulators, 166 + .size = ARRAY_SIZE(mt8196_regulators), 167 + }; 168 + 169 169 static int dvfsrc_vcore_regulator_probe(struct platform_device *pdev) 170 170 { 171 171 struct regulator_config config = { .dev = &pdev->dev }; ··· 209 173 210 174 static const struct of_device_id mtk_dvfsrc_regulator_match[] = { 211 175 { .compatible = "mediatek,mt6873-dvfsrc-regulator", .data = &mt6873_data }, 176 + { .compatible = "mediatek,mt6893-dvfsrc-regulator", .data = &mt6893_data }, 212 177 { .compatible = "mediatek,mt8183-dvfsrc-regulator", .data = &mt8183_data }, 213 178 { .compatible = "mediatek,mt8192-dvfsrc-regulator", .data = &mt6873_data }, 214 179 { .compatible = "mediatek,mt8195-dvfsrc-regulator", .data = &mt8195_data }, 180 + { .compatible = "mediatek,mt8196-dvfsrc-regulator", .data = &mt8196_data }, 215 181 { /* sentinel */ } 216 182 }; 217 183 MODULE_DEVICE_TABLE(of, mtk_dvfsrc_regulator_match);
+137 -4
drivers/regulator/pca9450-regulator.c
··· 17 17 #include <linux/regulator/machine.h> 18 18 #include <linux/regulator/of_regulator.h> 19 19 #include <linux/regulator/pca9450.h> 20 + #include <dt-bindings/regulator/nxp,pca9450-regulator.h> 21 + 22 + static unsigned int pca9450_buck_get_mode(struct regulator_dev *rdev); 23 + static int pca9450_buck_set_mode(struct regulator_dev *rdev, unsigned int mode); 20 24 21 25 struct pc9450_dvs_config { 22 26 unsigned int run_reg; /* dvs0 */ 23 27 unsigned int run_mask; 24 28 unsigned int standby_reg; /* dvs1 */ 25 29 unsigned int standby_mask; 30 + unsigned int mode_reg; /* ctrl */ 31 + unsigned int mode_mask; 26 32 }; 27 33 28 34 struct pca9450_regulator_desc { ··· 86 80 .get_voltage_sel = regulator_get_voltage_sel_regmap, 87 81 .set_voltage_time_sel = regulator_set_voltage_time_sel, 88 82 .set_ramp_delay = regulator_set_ramp_delay_regmap, 83 + .set_mode = pca9450_buck_set_mode, 84 + .get_mode = pca9450_buck_get_mode, 89 85 }; 90 86 91 87 static const struct regulator_ops pca9450_buck_regulator_ops = { ··· 98 90 .set_voltage_sel = regulator_set_voltage_sel_regmap, 99 91 .get_voltage_sel = regulator_get_voltage_sel_regmap, 100 92 .set_voltage_time_sel = regulator_set_voltage_time_sel, 93 + .set_mode = pca9450_buck_set_mode, 94 + .get_mode = pca9450_buck_get_mode, 101 95 }; 102 96 103 97 static const struct regulator_ops pca9450_ldo_regulator_ops = { ··· 295 285 return ret; 296 286 } 297 287 298 - static const struct pca9450_regulator_desc pca9450a_regulators[] = { 288 + static inline unsigned int pca9450_map_mode(unsigned int mode) 289 + { 290 + switch (mode) { 291 + case PCA9450_BUCK_MODE_AUTO: 292 + return REGULATOR_MODE_NORMAL; 293 + case PCA9450_BUCK_MODE_FORCE_PWM: 294 + return REGULATOR_MODE_FAST; 295 + default: 296 + return REGULATOR_MODE_INVALID; 297 + } 298 + } 299 + 300 + static int pca9450_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) 301 + { 302 + struct pca9450_regulator_desc *desc = container_of(rdev->desc, 303 + struct pca9450_regulator_desc, desc); 304 + const struct pc9450_dvs_config *dvs = &desc->dvs; 305 + int val; 306 + 307 + switch (mode) { 308 + case REGULATOR_MODE_FAST: 309 + val = dvs->mode_mask; 310 + break; 311 + case REGULATOR_MODE_NORMAL: 312 + val = 0; 313 + break; 314 + default: 315 + return -EINVAL; 316 + } 317 + 318 + dev_dbg(&rdev->dev, "pca9450 buck set_mode %#x, %#x, %#x\n", 319 + dvs->mode_reg, dvs->mode_mask, val); 320 + 321 + return regmap_update_bits(rdev->regmap, dvs->mode_reg, 322 + dvs->mode_mask, val); 323 + } 324 + 325 + static unsigned int pca9450_buck_get_mode(struct regulator_dev *rdev) 326 + { 327 + struct pca9450_regulator_desc *desc = container_of(rdev->desc, 328 + struct pca9450_regulator_desc, desc); 329 + const struct pc9450_dvs_config *dvs = &desc->dvs; 330 + int ret = 0, regval; 331 + 332 + ret = regmap_read(rdev->regmap, dvs->mode_reg, &regval); 333 + if (ret != 0) { 334 + dev_err(&rdev->dev, 335 + "Failed to get pca9450 buck mode: %d\n", ret); 336 + return ret; 337 + } 338 + 339 + if ((regval & dvs->mode_mask) == dvs->mode_mask) 340 + return REGULATOR_MODE_FAST; 341 + 342 + return REGULATOR_MODE_NORMAL; 343 + } 344 + 345 + static struct pca9450_regulator_desc pca9450a_regulators[] = { 299 346 { 300 347 .desc = { 301 348 .name = "buck1", ··· 375 308 .enable_val = BUCK_ENMODE_ONREQ, 376 309 .owner = THIS_MODULE, 377 310 .of_parse_cb = pca9450_set_dvs_levels, 311 + .of_map_mode = pca9450_map_mode, 378 312 }, 379 313 .dvs = { 380 314 .run_reg = PCA9450_REG_BUCK1OUT_DVS0, 381 315 .run_mask = BUCK1OUT_DVS0_MASK, 382 316 .standby_reg = PCA9450_REG_BUCK1OUT_DVS1, 383 317 .standby_mask = BUCK1OUT_DVS1_MASK, 318 + .mode_reg = PCA9450_REG_BUCK1CTRL, 319 + .mode_mask = BUCK1_FPWM, 384 320 }, 385 321 }, 386 322 { ··· 408 338 .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), 409 339 .owner = THIS_MODULE, 410 340 .of_parse_cb = pca9450_set_dvs_levels, 341 + .of_map_mode = pca9450_map_mode, 411 342 }, 412 343 .dvs = { 413 344 .run_reg = PCA9450_REG_BUCK2OUT_DVS0, 414 345 .run_mask = BUCK2OUT_DVS0_MASK, 415 346 .standby_reg = PCA9450_REG_BUCK2OUT_DVS1, 416 347 .standby_mask = BUCK2OUT_DVS1_MASK, 348 + .mode_reg = PCA9450_REG_BUCK2CTRL, 349 + .mode_mask = BUCK2_FPWM, 417 350 }, 418 351 }, 419 352 { ··· 441 368 .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), 442 369 .owner = THIS_MODULE, 443 370 .of_parse_cb = pca9450_set_dvs_levels, 371 + .of_map_mode = pca9450_map_mode, 444 372 }, 445 373 .dvs = { 446 374 .run_reg = PCA9450_REG_BUCK3OUT_DVS0, 447 375 .run_mask = BUCK3OUT_DVS0_MASK, 448 376 .standby_reg = PCA9450_REG_BUCK3OUT_DVS1, 449 377 .standby_mask = BUCK3OUT_DVS1_MASK, 378 + .mode_reg = PCA9450_REG_BUCK3CTRL, 379 + .mode_mask = BUCK3_FPWM, 450 380 }, 451 381 }, 452 382 { ··· 469 393 .enable_mask = BUCK4_ENMODE_MASK, 470 394 .enable_val = BUCK_ENMODE_ONREQ, 471 395 .owner = THIS_MODULE, 396 + .of_map_mode = pca9450_map_mode, 397 + }, 398 + .dvs = { 399 + .mode_reg = PCA9450_REG_BUCK4CTRL, 400 + .mode_mask = BUCK4_FPWM, 472 401 }, 473 402 }, 474 403 { ··· 493 412 .enable_mask = BUCK5_ENMODE_MASK, 494 413 .enable_val = BUCK_ENMODE_ONREQ, 495 414 .owner = THIS_MODULE, 415 + .of_map_mode = pca9450_map_mode, 416 + }, 417 + .dvs = { 418 + .mode_reg = PCA9450_REG_BUCK5CTRL, 419 + .mode_mask = BUCK5_FPWM, 496 420 }, 497 421 }, 498 422 { ··· 517 431 .enable_mask = BUCK6_ENMODE_MASK, 518 432 .enable_val = BUCK_ENMODE_ONREQ, 519 433 .owner = THIS_MODULE, 434 + .of_map_mode = pca9450_map_mode, 435 + }, 436 + .dvs = { 437 + .mode_reg = PCA9450_REG_BUCK6CTRL, 438 + .mode_mask = BUCK6_FPWM, 520 439 }, 521 440 }, 522 441 { ··· 620 529 * Buck3 removed on PCA9450B and connected with Buck1 internal for dual phase 621 530 * on PCA9450C as no Buck3. 622 531 */ 623 - static const struct pca9450_regulator_desc pca9450bc_regulators[] = { 532 + static struct pca9450_regulator_desc pca9450bc_regulators[] = { 624 533 { 625 534 .desc = { 626 535 .name = "buck1", ··· 643 552 .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), 644 553 .owner = THIS_MODULE, 645 554 .of_parse_cb = pca9450_set_dvs_levels, 555 + .of_map_mode = pca9450_map_mode, 646 556 }, 647 557 .dvs = { 648 558 .run_reg = PCA9450_REG_BUCK1OUT_DVS0, 649 559 .run_mask = BUCK1OUT_DVS0_MASK, 650 560 .standby_reg = PCA9450_REG_BUCK1OUT_DVS1, 651 561 .standby_mask = BUCK1OUT_DVS1_MASK, 562 + .mode_reg = PCA9450_REG_BUCK1CTRL, 563 + .mode_mask = BUCK1_FPWM, 652 564 }, 653 565 }, 654 566 { ··· 676 582 .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), 677 583 .owner = THIS_MODULE, 678 584 .of_parse_cb = pca9450_set_dvs_levels, 585 + .of_map_mode = pca9450_map_mode, 679 586 }, 680 587 .dvs = { 681 588 .run_reg = PCA9450_REG_BUCK2OUT_DVS0, 682 589 .run_mask = BUCK2OUT_DVS0_MASK, 683 590 .standby_reg = PCA9450_REG_BUCK2OUT_DVS1, 684 591 .standby_mask = BUCK2OUT_DVS1_MASK, 592 + .mode_reg = PCA9450_REG_BUCK2CTRL, 593 + .mode_mask = BUCK2_FPWM, 685 594 }, 686 595 }, 687 596 { ··· 704 607 .enable_mask = BUCK4_ENMODE_MASK, 705 608 .enable_val = BUCK_ENMODE_ONREQ, 706 609 .owner = THIS_MODULE, 610 + .of_map_mode = pca9450_map_mode, 611 + }, 612 + .dvs = { 613 + .mode_reg = PCA9450_REG_BUCK4CTRL, 614 + .mode_mask = BUCK4_FPWM, 707 615 }, 708 616 }, 709 617 { ··· 728 626 .enable_mask = BUCK5_ENMODE_MASK, 729 627 .enable_val = BUCK_ENMODE_ONREQ, 730 628 .owner = THIS_MODULE, 629 + .of_map_mode = pca9450_map_mode, 630 + }, 631 + .dvs = { 632 + .mode_reg = PCA9450_REG_BUCK5CTRL, 633 + .mode_mask = BUCK5_FPWM, 731 634 }, 732 635 }, 733 636 { ··· 752 645 .enable_mask = BUCK6_ENMODE_MASK, 753 646 .enable_val = BUCK_ENMODE_ONREQ, 754 647 .owner = THIS_MODULE, 648 + .of_map_mode = pca9450_map_mode, 649 + }, 650 + .dvs = { 651 + .mode_reg = PCA9450_REG_BUCK6CTRL, 652 + .mode_mask = BUCK6_FPWM, 755 653 }, 756 654 }, 757 655 { ··· 851 739 }, 852 740 }; 853 741 854 - static const struct pca9450_regulator_desc pca9451a_regulators[] = { 742 + static struct pca9450_regulator_desc pca9451a_regulators[] = { 855 743 { 856 744 .desc = { 857 745 .name = "buck1", ··· 873 761 .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), 874 762 .owner = THIS_MODULE, 875 763 .of_parse_cb = pca9450_set_dvs_levels, 764 + .of_map_mode = pca9450_map_mode, 876 765 }, 877 766 .dvs = { 878 767 .run_reg = PCA9450_REG_BUCK1OUT_DVS0, 879 768 .run_mask = BUCK1OUT_DVS0_MASK, 880 769 .standby_reg = PCA9450_REG_BUCK1OUT_DVS1, 881 770 .standby_mask = BUCK1OUT_DVS1_MASK, 771 + .mode_reg = PCA9450_REG_BUCK1CTRL, 772 + .mode_mask = BUCK1_FPWM, 882 773 }, 883 774 }, 884 775 { ··· 905 790 .n_ramp_values = ARRAY_SIZE(pca9450_dvs_buck_ramp_table), 906 791 .owner = THIS_MODULE, 907 792 .of_parse_cb = pca9450_set_dvs_levels, 793 + .of_map_mode = pca9450_map_mode, 908 794 }, 909 795 .dvs = { 910 796 .run_reg = PCA9450_REG_BUCK2OUT_DVS0, 911 797 .run_mask = BUCK2OUT_DVS0_MASK, 912 798 .standby_reg = PCA9450_REG_BUCK2OUT_DVS1, 913 799 .standby_mask = BUCK2OUT_DVS1_MASK, 800 + .mode_reg = PCA9450_REG_BUCK2CTRL, 801 + .mode_mask = BUCK2_FPWM, 914 802 }, 915 803 }, 916 804 { ··· 933 815 .enable_mask = BUCK4_ENMODE_MASK, 934 816 .enable_val = BUCK_ENMODE_ONREQ, 935 817 .owner = THIS_MODULE, 818 + .of_map_mode = pca9450_map_mode, 819 + }, 820 + .dvs = { 821 + .mode_reg = PCA9450_REG_BUCK4CTRL, 822 + .mode_mask = BUCK4_FPWM, 936 823 }, 937 824 }, 938 825 { ··· 957 834 .enable_mask = BUCK5_ENMODE_MASK, 958 835 .enable_val = BUCK_ENMODE_ONREQ, 959 836 .owner = THIS_MODULE, 837 + .of_map_mode = pca9450_map_mode, 838 + }, 839 + .dvs = { 840 + .mode_reg = PCA9450_REG_BUCK5CTRL, 841 + .mode_mask = BUCK5_FPWM, 960 842 }, 961 843 }, 962 844 { ··· 981 853 .enable_mask = BUCK6_ENMODE_MASK, 982 854 .enable_val = BUCK_ENMODE_ONREQ, 983 855 .owner = THIS_MODULE, 856 + .of_map_mode = pca9450_map_mode, 857 + }, 858 + .dvs = { 859 + .mode_reg = PCA9450_REG_BUCK6CTRL, 860 + .mode_mask = BUCK6_FPWM, 984 861 }, 985 862 }, 986 863 { ··· 1123 990 { 1124 991 enum pca9450_chip_type type = (unsigned int)(uintptr_t) 1125 992 of_device_get_match_data(&i2c->dev); 1126 - const struct pca9450_regulator_desc *regulator_desc; 993 + const struct pca9450_regulator_desc *regulator_desc; 1127 994 struct regulator_config config = { }; 1128 995 struct regulator_dev *ldo5; 1129 996 struct pca9450 *pca9450;
+58
drivers/regulator/qcom-rpmh-regulator.c
··· 1462 1462 {} 1463 1463 }; 1464 1464 1465 + static const struct rpmh_vreg_init_data pm7550_vreg_data[] = { 1466 + RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525, "vdd-s1"), 1467 + RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525, "vdd-s2"), 1468 + RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525, "vdd-s3"), 1469 + RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525, "vdd-s4"), 1470 + RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525, "vdd-s5"), 1471 + RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525, "vdd-s6"), 1472 + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"), 1473 + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2-l3"), 1474 + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l2-l3"), 1475 + RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo515, "vdd-l4-l5"), 1476 + RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo515, "vdd-l4-l5"), 1477 + RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo515, "vdd-l6"), 1478 + RPMH_VREG("ldo7", "ldo%s7", &pmic5_nldo515, "vdd-l7"), 1479 + RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo515, "vdd-l8"), 1480 + RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo515, "vdd-l9-l10"), 1481 + RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo515, "vdd-l9-l10"), 1482 + RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo515, "vdd-l11"), 1483 + RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo515_mv, "vdd-l12-l14"), 1484 + RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo515_mv, "vdd-l13-l16"), 1485 + RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo, "vdd-l12-l14"), 1486 + RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo, "vdd-l15-l17-l18-l19-l20-l21-l22-l23"), 1487 + RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l13-l16"), 1488 + RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l15-l17-l18-l19-l20-l21-l22-l23"), 1489 + RPMH_VREG("ldo18", "ldo%s18", &pmic5_pldo, "vdd-l15-l17-l18-l19-l20-l21-l22-l23"), 1490 + RPMH_VREG("ldo19", "ldo%s19", &pmic5_pldo, "vdd-l15-l17-l18-l19-l20-l21-l22-l23"), 1491 + RPMH_VREG("ldo20", "ldo%s20", &pmic5_pldo, "vdd-l15-l17-l18-l19-l20-l21-l22-l23"), 1492 + RPMH_VREG("ldo21", "ldo%s21", &pmic5_pldo, "vdd-l15-l17-l18-l19-l20-l21-l22-l23"), 1493 + RPMH_VREG("ldo22", "ldo%s22", &pmic5_pldo, "vdd-l15-l17-l18-l19-l20-l21-l22-l23"), 1494 + RPMH_VREG("ldo23", "ldo%s23", &pmic5_pldo, "vdd-l15-l17-l18-l19-l20-l21-l22-l23"), 1495 + RPMH_VREG("bob", "bob%s1", &pmic5_bob, "vdd-bob"), 1496 + {} 1497 + }; 1498 + 1465 1499 static const struct rpmh_vreg_init_data pmr735a_vreg_data[] = { 1466 1500 RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps520, "vdd-s1"), 1467 1501 RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"), ··· 1507 1473 RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l5-l6"), 1508 1474 RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l5-l6"), 1509 1475 RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-bob"), 1476 + {} 1477 + }; 1478 + 1479 + static const struct rpmh_vreg_init_data pmr735b_vreg_data[] = { 1480 + RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1-l2"), 1481 + RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l1-l2"), 1482 + RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"), 1483 + RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo_lv, "vdd-l4"), 1484 + RPMH_VREG("ldo5", "ldo%s5", &pmic5_nldo, "vdd-l5"), 1485 + RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6"), 1486 + RPMH_VREG("ldo7", "ldo%s7", &pmic5_nldo, "vdd-l7-l8"), 1487 + RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l7-l8"), 1488 + RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l9"), 1489 + RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo_lv, "vdd-l10"), 1490 + RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo, "vdd-l11"), 1491 + RPMH_VREG("ldo12", "ldo%s12", &pmic5_nldo, "vdd-l12"), 1510 1492 {} 1511 1493 }; 1512 1494 ··· 1714 1664 .data = pm7325_vreg_data, 1715 1665 }, 1716 1666 { 1667 + .compatible = "qcom,pm7550-rpmh-regulators", 1668 + .data = pm7550_vreg_data, 1669 + }, 1670 + { 1717 1671 .compatible = "qcom,pmr735a-rpmh-regulators", 1718 1672 .data = pmr735a_vreg_data, 1673 + }, 1674 + { 1675 + .compatible = "qcom,pmr735b-rpmh-regulators", 1676 + .data = pmr735b_vreg_data, 1719 1677 }, 1720 1678 { 1721 1679 .compatible = "qcom,pm660-rpmh-regulators",
+125
drivers/regulator/rpi-panel-v2-regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2022 Raspberry Pi Ltd. 4 + * Copyright (C) 2025 Marek Vasut 5 + */ 6 + 7 + #include <linux/err.h> 8 + #include <linux/gpio/driver.h> 9 + #include <linux/gpio/regmap.h> 10 + #include <linux/i2c.h> 11 + #include <linux/module.h> 12 + #include <linux/pwm.h> 13 + #include <linux/regmap.h> 14 + 15 + /* I2C registers of the microcontroller. */ 16 + #define REG_ID 0x01 17 + #define REG_POWERON 0x02 18 + #define REG_PWM 0x03 19 + 20 + /* Bits for poweron register */ 21 + #define LCD_RESET_BIT BIT(0) 22 + #define CTP_RESET_BIT BIT(1) 23 + 24 + /* Bits for the PWM register */ 25 + #define PWM_BL_ENABLE BIT(7) 26 + #define PWM_BL_MASK GENMASK(4, 0) 27 + 28 + /* Treat LCD_RESET and CTP_RESET as GPIOs */ 29 + #define NUM_GPIO 2 30 + 31 + static const struct regmap_config rpi_panel_regmap_config = { 32 + .reg_bits = 8, 33 + .val_bits = 8, 34 + .max_register = REG_PWM, 35 + .can_sleep = true, 36 + }; 37 + 38 + static int rpi_panel_v2_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 39 + const struct pwm_state *state) 40 + { 41 + struct regmap *regmap = pwmchip_get_drvdata(chip); 42 + unsigned int duty; 43 + 44 + if (state->polarity != PWM_POLARITY_NORMAL) 45 + return -EINVAL; 46 + 47 + if (!state->enabled) 48 + return regmap_write(regmap, REG_PWM, 0); 49 + 50 + duty = pwm_get_relative_duty_cycle(state, PWM_BL_MASK); 51 + return regmap_write(regmap, REG_PWM, duty | PWM_BL_ENABLE); 52 + } 53 + 54 + static const struct pwm_ops rpi_panel_v2_pwm_ops = { 55 + .apply = rpi_panel_v2_pwm_apply, 56 + }; 57 + 58 + /* 59 + * I2C driver interface functions 60 + */ 61 + static int rpi_panel_v2_i2c_probe(struct i2c_client *i2c) 62 + { 63 + struct gpio_regmap_config gconfig = { 64 + .ngpio = NUM_GPIO, 65 + .ngpio_per_reg = NUM_GPIO, 66 + .parent = &i2c->dev, 67 + .reg_set_base = REG_POWERON, 68 + }; 69 + struct regmap *regmap; 70 + struct pwm_chip *pc; 71 + int ret; 72 + 73 + pc = devm_pwmchip_alloc(&i2c->dev, 1, 0); 74 + if (IS_ERR(pc)) 75 + return PTR_ERR(pc); 76 + 77 + pc->ops = &rpi_panel_v2_pwm_ops; 78 + 79 + regmap = devm_regmap_init_i2c(i2c, &rpi_panel_regmap_config); 80 + if (IS_ERR(regmap)) 81 + return dev_err_probe(&i2c->dev, PTR_ERR(regmap), "Failed to allocate regmap\n"); 82 + 83 + pwmchip_set_drvdata(pc, regmap); 84 + 85 + regmap_write(regmap, REG_POWERON, 0); 86 + 87 + gconfig.regmap = regmap; 88 + ret = PTR_ERR_OR_ZERO(devm_gpio_regmap_register(&i2c->dev, &gconfig)); 89 + if (ret) 90 + return dev_err_probe(&i2c->dev, ret, "Failed to create gpiochip\n"); 91 + 92 + i2c_set_clientdata(i2c, regmap); 93 + 94 + return devm_pwmchip_add(&i2c->dev, pc); 95 + } 96 + 97 + static void rpi_panel_v2_i2c_shutdown(struct i2c_client *client) 98 + { 99 + struct regmap *regmap = i2c_get_clientdata(client); 100 + 101 + regmap_write(regmap, REG_PWM, 0); 102 + regmap_write(regmap, REG_POWERON, 0); 103 + } 104 + 105 + static const struct of_device_id rpi_panel_v2_dt_ids[] = { 106 + { .compatible = "raspberrypi,touchscreen-panel-regulator-v2" }, 107 + { }, 108 + }; 109 + MODULE_DEVICE_TABLE(of, rpi_panel_v2_dt_ids); 110 + 111 + static struct i2c_driver rpi_panel_v2_regulator_driver = { 112 + .driver = { 113 + .name = "rpi_touchscreen_v2", 114 + .probe_type = PROBE_PREFER_ASYNCHRONOUS, 115 + .of_match_table = rpi_panel_v2_dt_ids, 116 + }, 117 + .probe = rpi_panel_v2_i2c_probe, 118 + .shutdown = rpi_panel_v2_i2c_shutdown, 119 + }; 120 + 121 + module_i2c_driver(rpi_panel_v2_regulator_driver); 122 + 123 + MODULE_AUTHOR("Dave Stevenson <dave.stevenson@raspberrypi.com>"); 124 + MODULE_DESCRIPTION("Regulator device driver for Raspberry Pi 7-inch V2 touchscreen"); 125 + MODULE_LICENSE("GPL");
+9
drivers/regulator/rt5739.c
··· 24 24 #define RT5739_REG_NSEL1 0x01 25 25 #define RT5739_REG_CNTL1 0x02 26 26 #define RT5739_REG_ID1 0x03 27 + #define RT5739_REG_ID2 0x04 28 + #define RT5739_REG_MON 0x05 27 29 #define RT5739_REG_CNTL2 0x06 28 30 #define RT5739_REG_CNTL4 0x08 29 31 ··· 238 236 } 239 237 } 240 238 239 + static bool rt5739_volatile_reg(struct device *dev, unsigned int reg) 240 + { 241 + return reg == RT5739_REG_MON; 242 + } 243 + 241 244 static const struct regmap_config rt5739_regmap_config = { 242 245 .name = "rt5739", 243 246 .reg_bits = 8, 244 247 .val_bits = 8, 245 248 .max_register = RT5739_REG_CNTL4, 249 + .cache_type = REGCACHE_MAPLE, 250 + .volatile_reg = rt5739_volatile_reg, 246 251 }; 247 252 248 253 static int rt5739_probe(struct i2c_client *i2c)
+17 -2
drivers/regulator/rt6160-regulator.c
··· 31 31 #define RT6160_PGSTAT_MASK BIT(0) 32 32 33 33 #define RT6160_VENDOR_ID 0xA0 34 + #define RT6166_VENDOR_ID 0xB0 34 35 #define RT6160_VOUT_MINUV 2025000 35 36 #define RT6160_VOUT_MAXUV 5200000 37 + #define RT6166_VOUT_MINUV 1800000 38 + #define RT6166_VOUD_MAXUV 4950000 36 39 #define RT6160_VOUT_STPUV 25000 37 40 #define RT6160_N_VOUTS ((RT6160_VOUT_MAXUV - RT6160_VOUT_MINUV) / RT6160_VOUT_STPUV + 1) 38 41 ··· 46 43 struct gpio_desc *enable_gpio; 47 44 struct regmap *regmap; 48 45 bool enable_state; 46 + uint8_t devid; 49 47 }; 50 48 51 49 static const unsigned int rt6160_ramp_tables[] = { ··· 264 260 if (ret) 265 261 return ret; 266 262 267 - if ((devid & RT6160_VID_MASK) != RT6160_VENDOR_ID) { 263 + devid = devid & RT6160_VID_MASK; 264 + 265 + switch (devid) { 266 + case RT6166_VENDOR_ID: 267 + case RT6160_VENDOR_ID: 268 + break; 269 + default: 268 270 dev_err(&i2c->dev, "VID not correct [0x%02x]\n", devid); 269 271 return -ENODEV; 270 272 } 271 273 274 + priv->devid = devid; 275 + 272 276 priv->desc.name = "rt6160-buckboost"; 273 277 priv->desc.type = REGULATOR_VOLTAGE; 274 278 priv->desc.owner = THIS_MODULE; 275 - priv->desc.min_uV = RT6160_VOUT_MINUV; 279 + if (priv->devid == RT6166_VENDOR_ID) 280 + priv->desc.min_uV = RT6166_VOUT_MINUV; 281 + else 282 + priv->desc.min_uV = RT6160_VOUT_MINUV; 276 283 priv->desc.uV_step = RT6160_VOUT_STPUV; 277 284 if (vsel_active_low) 278 285 priv->desc.vsel_reg = RT6160_REG_VSELL;
-6
drivers/regulator/stm32-vrefbuf.c
··· 67 67 writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); 68 68 } 69 69 70 - pm_runtime_mark_last_busy(priv->dev); 71 70 pm_runtime_put_autosuspend(priv->dev); 72 71 73 72 return ret; ··· 86 87 val &= ~STM32_ENVR; 87 88 writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); 88 89 89 - pm_runtime_mark_last_busy(priv->dev); 90 90 pm_runtime_put_autosuspend(priv->dev); 91 91 92 92 return 0; ··· 102 104 103 105 ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR; 104 106 105 - pm_runtime_mark_last_busy(priv->dev); 106 107 pm_runtime_put_autosuspend(priv->dev); 107 108 108 109 return ret; ··· 122 125 val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel); 123 126 writel_relaxed(val, priv->base + STM32_VREFBUF_CSR); 124 127 125 - pm_runtime_mark_last_busy(priv->dev); 126 128 pm_runtime_put_autosuspend(priv->dev); 127 129 128 130 return 0; ··· 140 144 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR); 141 145 ret = FIELD_GET(STM32_VRS, val); 142 146 143 - pm_runtime_mark_last_busy(priv->dev); 144 147 pm_runtime_put_autosuspend(priv->dev); 145 148 146 149 return ret; ··· 213 218 } 214 219 platform_set_drvdata(pdev, rdev); 215 220 216 - pm_runtime_mark_last_busy(&pdev->dev); 217 221 pm_runtime_put_autosuspend(&pdev->dev); 218 222 219 223 return 0;
+2 -1
drivers/regulator/sy8827n.c
··· 140 140 return -EINVAL; 141 141 } 142 142 143 - di->en_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); 143 + di->en_gpio = devm_gpiod_get_optional(dev, "enable", 144 + GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE); 144 145 if (IS_ERR(di->en_gpio)) 145 146 return PTR_ERR(di->en_gpio); 146 147
+9
drivers/regulator/tps6286x-regulator.c
··· 19 19 #define TPS6286X_CONTROL_FPWM BIT(4) 20 20 #define TPS6286X_CONTROL_SWEN BIT(5) 21 21 22 + #define TPS6286X_STATUS 0x05 23 + 22 24 #define TPS6286X_MIN_MV 400 23 25 #define TPS6286X_MAX_MV 1675 24 26 #define TPS6286X_STEP_MV 5 25 27 28 + static bool tps6286x_volatile_reg(struct device *dev, unsigned int reg) 29 + { 30 + return reg == TPS6286X_STATUS; 31 + } 32 + 26 33 static const struct regmap_config tps6286x_regmap_config = { 27 34 .reg_bits = 8, 28 35 .val_bits = 8, 36 + .cache_type = REGCACHE_MAPLE, 37 + .volatile_reg = tps6286x_volatile_reg, 29 38 }; 30 39 31 40 static int tps6286x_set_mode(struct regulator_dev *rdev, unsigned int mode)
+7
drivers/regulator/tps6287x-regulator.c
··· 27 27 #define TPS6287X_CTRL3 0x03 28 28 #define TPS6287X_STATUS 0x04 29 29 30 + static bool tps6287x_volatile_reg(struct device *dev, unsigned int reg) 31 + { 32 + return reg == TPS6287X_STATUS; 33 + } 34 + 30 35 static const struct regmap_config tps6287x_regmap_config = { 31 36 .reg_bits = 8, 32 37 .val_bits = 8, 33 38 .max_register = TPS6287X_STATUS, 39 + .cache_type = REGCACHE_MAPLE, 40 + .volatile_reg = tps6287x_volatile_reg, 34 41 }; 35 42 36 43 static const struct linear_range tps6287x_voltage_ranges[] = {
+156 -117
drivers/regulator/tps6594-regulator.c
··· 21 21 #define BUCK_NB 5 22 22 #define LDO_NB 4 23 23 #define MULTI_PHASE_NB 4 24 - /* TPS6593 and LP8764 supports OV, UV, SC, ILIM */ 25 - #define REGS_INT_NB 4 26 - /* TPS65224 supports OV or UV */ 27 - #define TPS65224_REGS_INT_NB 1 28 24 29 25 enum tps6594_regulator_id { 30 26 /* DCDC's */ ··· 52 56 unsigned long event; 53 57 }; 54 58 55 - static struct tps6594_regulator_irq_type tps6594_ext_regulator_irq_types[] = { 59 + static const struct tps6594_regulator_irq_type tps6594_ext_regulator_irq_types[] = { 56 60 { TPS6594_IRQ_NAME_VCCA_OV, "VCCA", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 57 61 { TPS6594_IRQ_NAME_VCCA_UV, "VCCA", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 58 62 { TPS6594_IRQ_NAME_VMON1_OV, "VMON1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, ··· 65 69 REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 66 70 }; 67 71 68 - static struct tps6594_regulator_irq_type tps65224_ext_regulator_irq_types[] = { 72 + static const struct tps6594_regulator_irq_type tps65224_ext_regulator_irq_types[] = { 69 73 { TPS65224_IRQ_NAME_VCCA_UVOV, "VCCA", "voltage out of range", 70 74 REGULATOR_EVENT_REGULATION_OUT }, 71 75 { TPS65224_IRQ_NAME_VMON1_UVOV, "VMON1", "voltage out of range", ··· 76 80 77 81 struct tps6594_regulator_irq_data { 78 82 struct device *dev; 79 - struct tps6594_regulator_irq_type *type; 83 + const struct tps6594_regulator_irq_type *type; 80 84 struct regulator_dev *rdev; 81 85 }; 82 86 83 87 struct tps6594_ext_regulator_irq_data { 84 88 struct device *dev; 85 - struct tps6594_regulator_irq_type *type; 89 + const struct tps6594_regulator_irq_type *type; 86 90 }; 87 91 88 92 #define TPS6594_REGULATOR(_name, _of, _id, _type, _ops, _n, _vr, _vm, _er, \ ··· 188 192 .map_voltage = regulator_map_voltage_linear_range, 189 193 }; 190 194 191 - static const struct regulator_desc buck_regs[] = { 195 + static const struct regulator_desc tps6594_buck_regs[] = { 192 196 TPS6594_REGULATOR("BUCK1", "buck1", TPS6594_BUCK_1, 193 197 REGULATOR_VOLTAGE, tps6594_bucks_ops, TPS6594_MASK_BUCKS_VSET, 194 198 TPS6594_REG_BUCKX_VOUT_1(0), ··· 258 262 4, 0, 0, NULL, 0, 0), 259 263 }; 260 264 261 - static struct tps6594_regulator_irq_type tps6594_buck1_irq_types[] = { 265 + static const struct tps6594_regulator_irq_type tps6594_buck1_irq_types[] = { 262 266 { TPS6594_IRQ_NAME_BUCK1_OV, "BUCK1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 263 267 { TPS6594_IRQ_NAME_BUCK1_UV, "BUCK1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 264 268 { TPS6594_IRQ_NAME_BUCK1_SC, "BUCK1", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 266 270 REGULATOR_EVENT_OVER_CURRENT }, 267 271 }; 268 272 269 - static struct tps6594_regulator_irq_type tps6594_buck2_irq_types[] = { 273 + static const struct tps6594_regulator_irq_type tps6594_buck2_irq_types[] = { 270 274 { TPS6594_IRQ_NAME_BUCK2_OV, "BUCK2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 271 275 { TPS6594_IRQ_NAME_BUCK2_UV, "BUCK2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 272 276 { TPS6594_IRQ_NAME_BUCK2_SC, "BUCK2", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 274 278 REGULATOR_EVENT_OVER_CURRENT }, 275 279 }; 276 280 277 - static struct tps6594_regulator_irq_type tps6594_buck3_irq_types[] = { 281 + static const struct tps6594_regulator_irq_type tps6594_buck3_irq_types[] = { 278 282 { TPS6594_IRQ_NAME_BUCK3_OV, "BUCK3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 279 283 { TPS6594_IRQ_NAME_BUCK3_UV, "BUCK3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 280 284 { TPS6594_IRQ_NAME_BUCK3_SC, "BUCK3", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 282 286 REGULATOR_EVENT_OVER_CURRENT }, 283 287 }; 284 288 285 - static struct tps6594_regulator_irq_type tps6594_buck4_irq_types[] = { 289 + static const struct tps6594_regulator_irq_type tps6594_buck4_irq_types[] = { 286 290 { TPS6594_IRQ_NAME_BUCK4_OV, "BUCK4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 287 291 { TPS6594_IRQ_NAME_BUCK4_UV, "BUCK4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 288 292 { TPS6594_IRQ_NAME_BUCK4_SC, "BUCK4", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 290 294 REGULATOR_EVENT_OVER_CURRENT }, 291 295 }; 292 296 293 - static struct tps6594_regulator_irq_type tps6594_buck5_irq_types[] = { 297 + static const struct tps6594_regulator_irq_type tps6594_buck5_irq_types[] = { 294 298 { TPS6594_IRQ_NAME_BUCK5_OV, "BUCK5", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 295 299 { TPS6594_IRQ_NAME_BUCK5_UV, "BUCK5", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 296 300 { TPS6594_IRQ_NAME_BUCK5_SC, "BUCK5", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 298 302 REGULATOR_EVENT_OVER_CURRENT }, 299 303 }; 300 304 301 - static struct tps6594_regulator_irq_type tps6594_ldo1_irq_types[] = { 305 + static const struct tps6594_regulator_irq_type tps6594_ldo1_irq_types[] = { 302 306 { TPS6594_IRQ_NAME_LDO1_OV, "LDO1", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 303 307 { TPS6594_IRQ_NAME_LDO1_UV, "LDO1", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 304 308 { TPS6594_IRQ_NAME_LDO1_SC, "LDO1", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 306 310 REGULATOR_EVENT_OVER_CURRENT }, 307 311 }; 308 312 309 - static struct tps6594_regulator_irq_type tps6594_ldo2_irq_types[] = { 313 + static const struct tps6594_regulator_irq_type tps6594_ldo2_irq_types[] = { 310 314 { TPS6594_IRQ_NAME_LDO2_OV, "LDO2", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 311 315 { TPS6594_IRQ_NAME_LDO2_UV, "LDO2", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 312 316 { TPS6594_IRQ_NAME_LDO2_SC, "LDO2", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 314 318 REGULATOR_EVENT_OVER_CURRENT }, 315 319 }; 316 320 317 - static struct tps6594_regulator_irq_type tps6594_ldo3_irq_types[] = { 321 + static const struct tps6594_regulator_irq_type tps6594_ldo3_irq_types[] = { 318 322 { TPS6594_IRQ_NAME_LDO3_OV, "LDO3", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 319 323 { TPS6594_IRQ_NAME_LDO3_UV, "LDO3", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 320 324 { TPS6594_IRQ_NAME_LDO3_SC, "LDO3", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 322 326 REGULATOR_EVENT_OVER_CURRENT }, 323 327 }; 324 328 325 - static struct tps6594_regulator_irq_type tps6594_ldo4_irq_types[] = { 329 + static const struct tps6594_regulator_irq_type tps6594_ldo4_irq_types[] = { 326 330 { TPS6594_IRQ_NAME_LDO4_OV, "LDO4", "overvoltage", REGULATOR_EVENT_OVER_VOLTAGE_WARN }, 327 331 { TPS6594_IRQ_NAME_LDO4_UV, "LDO4", "undervoltage", REGULATOR_EVENT_UNDER_VOLTAGE }, 328 332 { TPS6594_IRQ_NAME_LDO4_SC, "LDO4", "short circuit", REGULATOR_EVENT_REGULATION_OUT }, ··· 330 334 REGULATOR_EVENT_OVER_CURRENT }, 331 335 }; 332 336 333 - static struct tps6594_regulator_irq_type tps65224_buck1_irq_types[] = { 337 + static const struct tps6594_regulator_irq_type tps65224_buck1_irq_types[] = { 334 338 { TPS65224_IRQ_NAME_BUCK1_UVOV, "BUCK1", "voltage out of range", 335 339 REGULATOR_EVENT_REGULATION_OUT }, 336 340 }; 337 341 338 - static struct tps6594_regulator_irq_type tps65224_buck2_irq_types[] = { 342 + static const struct tps6594_regulator_irq_type tps65224_buck2_irq_types[] = { 339 343 { TPS65224_IRQ_NAME_BUCK2_UVOV, "BUCK2", "voltage out of range", 340 344 REGULATOR_EVENT_REGULATION_OUT }, 341 345 }; 342 346 343 - static struct tps6594_regulator_irq_type tps65224_buck3_irq_types[] = { 347 + static const struct tps6594_regulator_irq_type tps65224_buck3_irq_types[] = { 344 348 { TPS65224_IRQ_NAME_BUCK3_UVOV, "BUCK3", "voltage out of range", 345 349 REGULATOR_EVENT_REGULATION_OUT }, 346 350 }; 347 351 348 - static struct tps6594_regulator_irq_type tps65224_buck4_irq_types[] = { 352 + static const struct tps6594_regulator_irq_type tps65224_buck4_irq_types[] = { 349 353 { TPS65224_IRQ_NAME_BUCK4_UVOV, "BUCK4", "voltage out of range", 350 354 REGULATOR_EVENT_REGULATION_OUT }, 351 355 }; 352 356 353 - static struct tps6594_regulator_irq_type tps65224_ldo1_irq_types[] = { 357 + static const struct tps6594_regulator_irq_type tps65224_ldo1_irq_types[] = { 354 358 { TPS65224_IRQ_NAME_LDO1_UVOV, "LDO1", "voltage out of range", 355 359 REGULATOR_EVENT_REGULATION_OUT }, 356 360 }; 357 361 358 - static struct tps6594_regulator_irq_type tps65224_ldo2_irq_types[] = { 362 + static const struct tps6594_regulator_irq_type tps65224_ldo2_irq_types[] = { 359 363 { TPS65224_IRQ_NAME_LDO2_UVOV, "LDO2", "voltage out of range", 360 364 REGULATOR_EVENT_REGULATION_OUT }, 361 365 }; 362 366 363 - static struct tps6594_regulator_irq_type tps65224_ldo3_irq_types[] = { 367 + static const struct tps6594_regulator_irq_type tps65224_ldo3_irq_types[] = { 364 368 { TPS65224_IRQ_NAME_LDO3_UVOV, "LDO3", "voltage out of range", 365 369 REGULATOR_EVENT_REGULATION_OUT }, 366 370 }; 367 371 368 - static struct tps6594_regulator_irq_type *tps6594_bucks_irq_types[] = { 372 + static const struct tps6594_regulator_irq_type *tps6594_bucks_irq_types[] = { 369 373 tps6594_buck1_irq_types, 370 374 tps6594_buck2_irq_types, 371 375 tps6594_buck3_irq_types, ··· 373 377 tps6594_buck5_irq_types, 374 378 }; 375 379 376 - static struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = { 380 + static const struct tps6594_regulator_irq_type *tps6594_ldos_irq_types[] = { 377 381 tps6594_ldo1_irq_types, 378 382 tps6594_ldo2_irq_types, 379 383 tps6594_ldo3_irq_types, 380 384 tps6594_ldo4_irq_types, 381 385 }; 382 386 383 - static struct tps6594_regulator_irq_type *tps65224_bucks_irq_types[] = { 387 + static const struct tps6594_regulator_irq_type *tps65224_bucks_irq_types[] = { 384 388 tps65224_buck1_irq_types, 385 389 tps65224_buck2_irq_types, 386 390 tps65224_buck3_irq_types, 387 391 tps65224_buck4_irq_types, 388 392 }; 389 393 390 - static struct tps6594_regulator_irq_type *tps65224_ldos_irq_types[] = { 394 + static const struct tps6594_regulator_irq_type *tps65224_ldos_irq_types[] = { 391 395 tps65224_ldo1_irq_types, 392 396 tps65224_ldo2_irq_types, 393 397 tps65224_ldo3_irq_types, ··· 512 516 static int tps6594_request_reg_irqs(struct platform_device *pdev, 513 517 struct regulator_dev *rdev, 514 518 struct tps6594_regulator_irq_data *irq_data, 515 - struct tps6594_regulator_irq_type *regs_irq_types, 519 + const struct tps6594_regulator_irq_type *regs_irq_types, 516 520 size_t interrupt_cnt, 517 521 int *irq_idx) 518 522 { 519 - struct tps6594_regulator_irq_type *irq_type; 523 + const struct tps6594_regulator_irq_type *irq_type; 520 524 struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); 521 525 size_t j; 522 526 int irq; ··· 545 549 return 0; 546 550 } 547 551 552 + struct tps6594_regulator_desc { 553 + const struct regulator_desc *multi_phase_regs; 554 + unsigned int num_multi_phase_regs; 555 + 556 + const struct regulator_desc *buck_regs; 557 + int num_buck_regs; 558 + 559 + const struct regulator_desc *ldo_regs; 560 + int num_ldo_regs; 561 + 562 + const struct tps6594_regulator_irq_type **bucks_irq_types; 563 + const struct tps6594_regulator_irq_type **ldos_irq_types; 564 + int num_irq_types; 565 + 566 + const struct tps6594_regulator_irq_type *ext_irq_types; 567 + int num_ext_irqs; 568 + }; 569 + 570 + static const struct tps6594_regulator_desc tps65224_reg_desc = { 571 + .multi_phase_regs = tps65224_multi_regs, 572 + .num_multi_phase_regs = ARRAY_SIZE(tps65224_multi_regs), 573 + .buck_regs = tps65224_buck_regs, 574 + .num_buck_regs = ARRAY_SIZE(tps65224_buck_regs), 575 + .ldo_regs = tps65224_ldo_regs, 576 + .num_ldo_regs = ARRAY_SIZE(tps65224_ldo_regs), 577 + .bucks_irq_types = tps65224_bucks_irq_types, 578 + .ldos_irq_types = tps65224_ldos_irq_types, 579 + .num_irq_types = 1, /* OV or UV */ 580 + .ext_irq_types = tps65224_ext_regulator_irq_types, 581 + .num_ext_irqs = ARRAY_SIZE(tps65224_ext_regulator_irq_types), 582 + }; 583 + 584 + static const struct tps6594_regulator_desc tps652g1_reg_desc = { 585 + .ldo_regs = tps65224_ldo_regs, 586 + .num_ldo_regs = ARRAY_SIZE(tps65224_ldo_regs), 587 + .buck_regs = tps65224_buck_regs, 588 + .num_buck_regs = ARRAY_SIZE(tps65224_buck_regs), 589 + }; 590 + 591 + static const struct tps6594_regulator_desc tps6594_reg_desc = { 592 + .multi_phase_regs = tps6594_multi_regs, 593 + .num_multi_phase_regs = ARRAY_SIZE(tps6594_multi_regs), 594 + .buck_regs = tps6594_buck_regs, 595 + .num_buck_regs = ARRAY_SIZE(tps6594_buck_regs), 596 + .ldo_regs = tps6594_ldo_regs, 597 + .num_ldo_regs = ARRAY_SIZE(tps6594_ldo_regs), 598 + .bucks_irq_types = tps6594_bucks_irq_types, 599 + .ldos_irq_types = tps6594_ldos_irq_types, 600 + .num_irq_types = 4, /* OV, UV, SC and ILIM */ 601 + .ext_irq_types = tps6594_ext_regulator_irq_types, 602 + .num_ext_irqs = 2, /* only VCCA OV and UV */ 603 + }; 604 + 605 + static const struct tps6594_regulator_desc lp8764_reg_desc = { 606 + .multi_phase_regs = tps6594_multi_regs, 607 + .num_multi_phase_regs = ARRAY_SIZE(tps6594_multi_regs), 608 + .buck_regs = tps6594_buck_regs, 609 + .num_buck_regs = ARRAY_SIZE(tps6594_buck_regs), 610 + .bucks_irq_types = tps6594_bucks_irq_types, 611 + .num_irq_types = 4, /* OV, UV, SC and ILIM */ 612 + .ext_irq_types = tps6594_ext_regulator_irq_types, 613 + .num_ext_irqs = ARRAY_SIZE(tps6594_ext_regulator_irq_types), 614 + }; 615 + 548 616 static int tps6594_regulator_probe(struct platform_device *pdev) 549 617 { 550 618 struct tps6594 *tps = dev_get_drvdata(pdev->dev.parent); ··· 618 558 struct regulator_config config = {}; 619 559 struct tps6594_regulator_irq_data *irq_data; 620 560 struct tps6594_ext_regulator_irq_data *irq_ext_reg_data; 621 - struct tps6594_regulator_irq_type *irq_type; 622 - struct tps6594_regulator_irq_type *irq_types; 561 + const struct tps6594_regulator_irq_type *irq_type; 623 562 bool buck_configured[BUCK_NB] = { false }; 624 563 bool buck_multi[MULTI_PHASE_NB] = { false }; 564 + const struct tps6594_regulator_desc *desc; 565 + const struct regulator_desc *multi_regs; 625 566 626 - static const char *npname; 567 + const char *npname; 627 568 int error, i, irq, multi; 628 569 int irq_idx = 0; 629 570 int buck_idx = 0; 630 - int nr_ldo; 631 - int nr_buck; 632 - int nr_types; 633 - unsigned int irq_count; 634 - unsigned int multi_phase_cnt; 635 571 size_t reg_irq_nb; 636 - struct tps6594_regulator_irq_type **bucks_irq_types; 637 - const struct regulator_desc *multi_regs; 638 - struct tps6594_regulator_irq_type **ldos_irq_types; 639 - const struct regulator_desc *ldo_regs; 640 - size_t interrupt_count; 641 572 642 - if (tps->chip_id == TPS65224) { 643 - bucks_irq_types = tps65224_bucks_irq_types; 644 - interrupt_count = ARRAY_SIZE(tps65224_buck1_irq_types); 645 - multi_regs = tps65224_multi_regs; 646 - ldos_irq_types = tps65224_ldos_irq_types; 647 - ldo_regs = tps65224_ldo_regs; 648 - multi_phase_cnt = ARRAY_SIZE(tps65224_multi_regs); 649 - } else { 650 - bucks_irq_types = tps6594_bucks_irq_types; 651 - interrupt_count = ARRAY_SIZE(tps6594_buck1_irq_types); 652 - multi_regs = tps6594_multi_regs; 653 - ldos_irq_types = tps6594_ldos_irq_types; 654 - ldo_regs = tps6594_ldo_regs; 655 - multi_phase_cnt = ARRAY_SIZE(tps6594_multi_regs); 656 - } 573 + switch (tps->chip_id) { 574 + case TPS65224: 575 + desc = &tps65224_reg_desc; 576 + break; 577 + case TPS652G1: 578 + desc = &tps652g1_reg_desc; 579 + break; 580 + case TPS6594: 581 + case TPS6593: 582 + desc = &tps6594_reg_desc; 583 + break; 584 + case LP8764: 585 + desc = &lp8764_reg_desc; 586 + break; 587 + default: 588 + dev_err(tps->dev, "unknown chip_id %lu\n", tps->chip_id); 589 + return -EINVAL; 590 + }; 657 591 658 592 enum { 659 593 MULTI_BUCK12, ··· 668 614 * In case of Multiphase configuration, value should be defined for 669 615 * buck_configured to avoid creating bucks for every buck in multiphase 670 616 */ 671 - for (multi = 0; multi < multi_phase_cnt; multi++) { 672 - np = of_find_node_by_name(tps->dev->of_node, multi_regs[multi].supply_name); 617 + for (multi = 0; multi < desc->num_multi_phase_regs; multi++) { 618 + multi_regs = &desc->multi_phase_regs[multi]; 619 + np = of_find_node_by_name(tps->dev->of_node, multi_regs->supply_name); 673 620 npname = of_node_full_name(np); 674 621 np_pmic_parent = of_get_parent(of_get_parent(np)); 675 622 if (of_node_cmp(of_node_full_name(np_pmic_parent), tps->dev->of_node->full_name)) 676 623 continue; 677 - if (strcmp(npname, multi_regs[multi].supply_name) == 0) { 624 + if (strcmp(npname, multi_regs->supply_name) == 0) { 678 625 switch (multi) { 679 626 case MULTI_BUCK12: 680 627 buck_multi[0] = true; ··· 708 653 } 709 654 } 710 655 711 - if (tps->chip_id == TPS65224) { 712 - nr_buck = ARRAY_SIZE(tps65224_buck_regs); 713 - nr_ldo = ARRAY_SIZE(tps65224_ldo_regs); 714 - nr_types = TPS65224_REGS_INT_NB; 715 - } else { 716 - nr_buck = ARRAY_SIZE(buck_regs); 717 - nr_ldo = (tps->chip_id == LP8764) ? 0 : ARRAY_SIZE(tps6594_ldo_regs); 718 - nr_types = REGS_INT_NB; 719 - } 720 - 721 - reg_irq_nb = nr_types * (nr_buck + nr_ldo); 656 + reg_irq_nb = desc->num_irq_types * (desc->num_buck_regs + desc->num_ldo_regs); 722 657 723 658 irq_data = devm_kmalloc_array(tps->dev, reg_irq_nb, 724 659 sizeof(struct tps6594_regulator_irq_data), GFP_KERNEL); 725 660 if (!irq_data) 726 661 return -ENOMEM; 727 662 728 - for (i = 0; i < multi_phase_cnt; i++) { 663 + for (i = 0; i < desc->num_multi_phase_regs; i++) { 729 664 if (!buck_multi[i]) 730 665 continue; 731 666 732 - rdev = devm_regulator_register(&pdev->dev, &multi_regs[i], &config); 667 + rdev = devm_regulator_register(&pdev->dev, &desc->multi_phase_regs[i], 668 + &config); 733 669 if (IS_ERR(rdev)) 734 670 return dev_err_probe(tps->dev, PTR_ERR(rdev), 735 671 "failed to register %s regulator\n", 736 672 pdev->name); 673 + 674 + if (!desc->num_irq_types) 675 + continue; 737 676 738 677 /* config multiphase buck12+buck34 */ 739 678 if (i == MULTI_BUCK12_34) 740 679 buck_idx = 2; 741 680 742 681 error = tps6594_request_reg_irqs(pdev, rdev, irq_data, 743 - bucks_irq_types[buck_idx], 744 - interrupt_count, &irq_idx); 682 + desc->bucks_irq_types[buck_idx], 683 + desc->num_irq_types, &irq_idx); 745 684 if (error) 746 685 return error; 747 686 748 687 error = tps6594_request_reg_irqs(pdev, rdev, irq_data, 749 - bucks_irq_types[buck_idx + 1], 750 - interrupt_count, &irq_idx); 688 + desc->bucks_irq_types[buck_idx + 1], 689 + desc->num_irq_types, &irq_idx); 751 690 if (error) 752 691 return error; 753 692 754 693 if (i == MULTI_BUCK123 || i == MULTI_BUCK1234) { 755 694 error = tps6594_request_reg_irqs(pdev, rdev, irq_data, 756 - tps6594_bucks_irq_types[buck_idx + 2], 757 - interrupt_count, 695 + desc->bucks_irq_types[buck_idx + 2], 696 + desc->num_irq_types, 758 697 &irq_idx); 759 698 if (error) 760 699 return error; 761 700 } 762 701 if (i == MULTI_BUCK1234) { 763 702 error = tps6594_request_reg_irqs(pdev, rdev, irq_data, 764 - tps6594_bucks_irq_types[buck_idx + 3], 765 - interrupt_count, 703 + desc->bucks_irq_types[buck_idx + 3], 704 + desc->num_irq_types, 766 705 &irq_idx); 767 706 if (error) 768 707 return error; 769 708 } 770 709 } 771 710 772 - for (i = 0; i < nr_buck; i++) { 711 + for (i = 0; i < desc->num_buck_regs; i++) { 773 712 if (buck_configured[i]) 774 713 continue; 775 714 776 - const struct regulator_desc *buck_cfg = (tps->chip_id == TPS65224) ? 777 - tps65224_buck_regs : buck_regs; 778 - 779 - rdev = devm_regulator_register(&pdev->dev, &buck_cfg[i], &config); 715 + rdev = devm_regulator_register(&pdev->dev, &desc->buck_regs[i], &config); 780 716 if (IS_ERR(rdev)) 781 717 return dev_err_probe(tps->dev, PTR_ERR(rdev), 782 718 "failed to register %s regulator\n", pdev->name); 783 719 720 + if (!desc->num_irq_types) 721 + continue; 722 + 784 723 error = tps6594_request_reg_irqs(pdev, rdev, irq_data, 785 - bucks_irq_types[i], interrupt_count, &irq_idx); 724 + desc->bucks_irq_types[i], 725 + desc->num_irq_types, &irq_idx); 786 726 if (error) 787 727 return error; 788 728 } 789 729 790 - /* LP8764 doesn't have LDO */ 791 - if (tps->chip_id != LP8764) { 792 - for (i = 0; i < nr_ldo; i++) { 793 - rdev = devm_regulator_register(&pdev->dev, &ldo_regs[i], &config); 794 - if (IS_ERR(rdev)) 795 - return dev_err_probe(tps->dev, PTR_ERR(rdev), 796 - "failed to register %s regulator\n", 797 - pdev->name); 730 + for (i = 0; i < desc->num_ldo_regs; i++) { 731 + rdev = devm_regulator_register(&pdev->dev, &desc->ldo_regs[i], &config); 732 + if (IS_ERR(rdev)) 733 + return dev_err_probe(tps->dev, PTR_ERR(rdev), 734 + "failed to register %s regulator\n", 735 + pdev->name); 798 736 799 - error = tps6594_request_reg_irqs(pdev, rdev, irq_data, 800 - ldos_irq_types[i], interrupt_count, 801 - &irq_idx); 802 - if (error) 803 - return error; 804 - } 805 - } 737 + if (!desc->num_irq_types) 738 + continue; 806 739 807 - if (tps->chip_id == TPS65224) { 808 - irq_types = tps65224_ext_regulator_irq_types; 809 - irq_count = ARRAY_SIZE(tps65224_ext_regulator_irq_types); 810 - } else { 811 - irq_types = tps6594_ext_regulator_irq_types; 812 - if (tps->chip_id == LP8764) 813 - irq_count = ARRAY_SIZE(tps6594_ext_regulator_irq_types); 814 - else 815 - /* TPS6593 supports only VCCA OV and UV */ 816 - irq_count = 2; 740 + error = tps6594_request_reg_irqs(pdev, rdev, irq_data, 741 + desc->ldos_irq_types[i], 742 + desc->num_irq_types, &irq_idx); 743 + if (error) 744 + return error; 817 745 } 818 746 819 747 irq_ext_reg_data = devm_kmalloc_array(tps->dev, 820 - irq_count, 748 + desc->num_ext_irqs, 821 749 sizeof(struct tps6594_ext_regulator_irq_data), 822 750 GFP_KERNEL); 823 751 if (!irq_ext_reg_data) 824 752 return -ENOMEM; 825 753 826 - for (i = 0; i < irq_count; ++i) { 827 - irq_type = &irq_types[i]; 754 + for (i = 0; i < desc->num_ext_irqs; ++i) { 755 + irq_type = &desc->ext_irq_types[i]; 828 756 irq = platform_get_irq_byname(pdev, irq_type->irq_name); 829 757 if (irq < 0) 830 758 return -EINVAL; ··· 825 787 "failed to request %s IRQ %d\n", 826 788 irq_type->irq_name, irq); 827 789 } 790 + 828 791 return 0; 829 792 } 830 793
+18
include/dt-bindings/regulator/nxp,pca9450-regulator.h
··· 1 + /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 2 + /* 3 + * Device Tree binding constants for the NXP PCA9450A/B/C PMIC regulators 4 + */ 5 + 6 + #ifndef _DT_BINDINGS_REGULATORS_NXP_PCA9450_H 7 + #define _DT_BINDINGS_REGULATORS_NXP_PCA9450_H 8 + 9 + /* 10 + * Buck mode constants which may be used in devicetree properties (eg. 11 + * regulator-initial-mode, regulator-allowed-modes). 12 + * See the manufacturer's datasheet for more information on these modes. 13 + */ 14 + 15 + #define PCA9450_BUCK_MODE_AUTO 0 16 + #define PCA9450_BUCK_MODE_FORCE_PWM 1 17 + 18 + #endif
+1
include/linux/mfd/tps6594.h
··· 19 19 TPS6593, 20 20 LP8764, 21 21 TPS65224, 22 + TPS652G1, 22 23 }; 23 24 24 25 /* Macro to get page index from register address */
+2 -1
include/linux/regulator/coupler.h
··· 8 8 #ifndef __LINUX_REGULATOR_COUPLER_H_ 9 9 #define __LINUX_REGULATOR_COUPLER_H_ 10 10 11 - #include <linux/kernel.h> 11 + #include <linux/errno.h> 12 + #include <linux/types.h> 12 13 #include <linux/suspend.h> 13 14 14 15 struct regulator_coupler;
+1
rust/bindings/bindings_helper.h
··· 65 65 #include <linux/poll.h> 66 66 #include <linux/property.h> 67 67 #include <linux/refcount.h> 68 + #include <linux/regulator/consumer.h> 68 69 #include <linux/sched.h> 69 70 #include <linux/security.h> 70 71 #include <linux/slab.h>
+1
rust/helpers/helpers.c
··· 34 34 #include "pid_namespace.c" 35 35 #include "poll.c" 36 36 #include "rbtree.c" 37 + #include "regulator.c" 37 38 #include "rcu.c" 38 39 #include "refcount.c" 39 40 #include "security.c"
+43
rust/helpers/regulator.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/regulator/consumer.h> 4 + 5 + #ifndef CONFIG_REGULATOR 6 + 7 + void rust_helper_regulator_put(struct regulator *regulator) 8 + { 9 + regulator_put(regulator); 10 + } 11 + 12 + int rust_helper_regulator_set_voltage(struct regulator *regulator, int min_uV, 13 + int max_uV) 14 + { 15 + return regulator_set_voltage(regulator, min_uV, max_uV); 16 + } 17 + 18 + int rust_helper_regulator_get_voltage(struct regulator *regulator) 19 + { 20 + return regulator_get_voltage(regulator); 21 + } 22 + 23 + struct regulator *rust_helper_regulator_get(struct device *dev, const char *id) 24 + { 25 + return regulator_get(dev, id); 26 + } 27 + 28 + int rust_helper_regulator_enable(struct regulator *regulator) 29 + { 30 + return regulator_enable(regulator); 31 + } 32 + 33 + int rust_helper_regulator_disable(struct regulator *regulator) 34 + { 35 + return regulator_disable(regulator); 36 + } 37 + 38 + int rust_helper_regulator_is_enabled(struct regulator *regulator) 39 + { 40 + return regulator_is_enabled(regulator); 41 + } 42 + 43 + #endif
+1
rust/kernel/lib.rs
··· 103 103 pub mod prelude; 104 104 pub mod print; 105 105 pub mod rbtree; 106 + pub mod regulator; 106 107 pub mod revocable; 107 108 pub mod security; 108 109 pub mod seq_file;
+418
rust/kernel/regulator.rs
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + //! Regulator abstractions, providing a standard kernel interface to control 4 + //! voltage and current regulators. 5 + //! 6 + //! The intention is to allow systems to dynamically control regulator power 7 + //! output in order to save power and prolong battery life. This applies to both 8 + //! voltage regulators (where voltage output is controllable) and current sinks 9 + //! (where current limit is controllable). 10 + //! 11 + //! C header: [`include/linux/regulator/consumer.h`](srctree/include/linux/regulator/consumer.h) 12 + //! 13 + //! Regulators are modeled in Rust with a collection of states. Each state may 14 + //! enforce a given invariant, and they may convert between each other where applicable. 15 + //! 16 + //! See [Voltage and current regulator API](https://docs.kernel.org/driver-api/regulator.html) 17 + //! for more information. 18 + 19 + use crate::{ 20 + bindings, 21 + device::Device, 22 + error::{from_err_ptr, to_result, Result}, 23 + prelude::*, 24 + }; 25 + 26 + use core::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull}; 27 + 28 + mod private { 29 + pub trait Sealed {} 30 + 31 + impl Sealed for super::Enabled {} 32 + impl Sealed for super::Disabled {} 33 + impl Sealed for super::Dynamic {} 34 + } 35 + 36 + /// A trait representing the different states a [`Regulator`] can be in. 37 + pub trait RegulatorState: private::Sealed + 'static { 38 + /// Whether the regulator should be disabled when dropped. 39 + const DISABLE_ON_DROP: bool; 40 + } 41 + 42 + /// A state where the [`Regulator`] is known to be enabled. 43 + /// 44 + /// The `enable` reference count held by this state is decremented when it is 45 + /// dropped. 46 + pub struct Enabled; 47 + 48 + /// A state where this [`Regulator`] handle has not specifically asked for the 49 + /// underlying regulator to be enabled. This means that this reference does not 50 + /// own an `enable` reference count, but the regulator may still be on. 51 + pub struct Disabled; 52 + 53 + /// A state that models the C API. The [`Regulator`] can be either enabled or 54 + /// disabled, and the user is in control of the reference count. This is also 55 + /// the default state. 56 + /// 57 + /// Use [`Regulator::is_enabled`] to check the regulator's current state. 58 + pub struct Dynamic; 59 + 60 + impl RegulatorState for Enabled { 61 + const DISABLE_ON_DROP: bool = true; 62 + } 63 + 64 + impl RegulatorState for Disabled { 65 + const DISABLE_ON_DROP: bool = false; 66 + } 67 + 68 + impl RegulatorState for Dynamic { 69 + const DISABLE_ON_DROP: bool = false; 70 + } 71 + 72 + /// A trait that abstracts the ability to check if a [`Regulator`] is enabled. 73 + pub trait IsEnabled: RegulatorState {} 74 + impl IsEnabled for Disabled {} 75 + impl IsEnabled for Dynamic {} 76 + 77 + /// An error that can occur when trying to convert a [`Regulator`] between states. 78 + pub struct Error<State: RegulatorState> { 79 + /// The error that occurred. 80 + pub error: kernel::error::Error, 81 + 82 + /// The regulator that caused the error, so that the operation may be retried. 83 + pub regulator: Regulator<State>, 84 + } 85 + 86 + /// A `struct regulator` abstraction. 87 + /// 88 + /// # Examples 89 + /// 90 + /// ## Enabling a regulator 91 + /// 92 + /// This example uses [`Regulator<Enabled>`], which is suitable for drivers that 93 + /// enable a regulator at probe time and leave them on until the device is 94 + /// removed or otherwise shutdown. 95 + /// 96 + /// These users can store [`Regulator<Enabled>`] directly in their driver's 97 + /// private data struct. 98 + /// 99 + /// ``` 100 + /// # use kernel::prelude::*; 101 + /// # use kernel::c_str; 102 + /// # use kernel::device::Device; 103 + /// # use kernel::regulator::{Voltage, Regulator, Disabled, Enabled}; 104 + /// fn enable(dev: &Device, min_voltage: Voltage, max_voltage: Voltage) -> Result { 105 + /// // Obtain a reference to a (fictitious) regulator. 106 + /// let regulator: Regulator<Disabled> = Regulator::<Disabled>::get(dev, c_str!("vcc"))?; 107 + /// 108 + /// // The voltage can be set before enabling the regulator if needed, e.g.: 109 + /// regulator.set_voltage(min_voltage, max_voltage)?; 110 + /// 111 + /// // The same applies for `get_voltage()`, i.e.: 112 + /// let voltage: Voltage = regulator.get_voltage()?; 113 + /// 114 + /// // Enables the regulator, consuming the previous value. 115 + /// // 116 + /// // From now on, the regulator is known to be enabled because of the type 117 + /// // `Enabled`. 118 + /// // 119 + /// // If this operation fails, the `Error` will contain the regulator 120 + /// // reference, so that the operation may be retried. 121 + /// let regulator: Regulator<Enabled> = 122 + /// regulator.try_into_enabled().map_err(|error| error.error)?; 123 + /// 124 + /// // The voltage can also be set after enabling the regulator, e.g.: 125 + /// regulator.set_voltage(min_voltage, max_voltage)?; 126 + /// 127 + /// // The same applies for `get_voltage()`, i.e.: 128 + /// let voltage: Voltage = regulator.get_voltage()?; 129 + /// 130 + /// // Dropping an enabled regulator will disable it. The refcount will be 131 + /// // decremented. 132 + /// drop(regulator); 133 + /// 134 + /// // ... 135 + /// 136 + /// Ok(()) 137 + /// } 138 + /// ``` 139 + /// 140 + /// A more concise shortcut is available for enabling a regulator. This is 141 + /// equivalent to `regulator_get_enable()`: 142 + /// 143 + /// ``` 144 + /// # use kernel::prelude::*; 145 + /// # use kernel::c_str; 146 + /// # use kernel::device::Device; 147 + /// # use kernel::regulator::{Voltage, Regulator, Enabled}; 148 + /// fn enable(dev: &Device) -> Result { 149 + /// // Obtain a reference to a (fictitious) regulator and enable it. 150 + /// let regulator: Regulator<Enabled> = Regulator::<Enabled>::get(dev, c_str!("vcc"))?; 151 + /// 152 + /// // Dropping an enabled regulator will disable it. The refcount will be 153 + /// // decremented. 154 + /// drop(regulator); 155 + /// 156 + /// // ... 157 + /// 158 + /// Ok(()) 159 + /// } 160 + /// ``` 161 + /// 162 + /// ## Disabling a regulator 163 + /// 164 + /// ``` 165 + /// # use kernel::prelude::*; 166 + /// # use kernel::device::Device; 167 + /// # use kernel::regulator::{Regulator, Enabled, Disabled}; 168 + /// fn disable(dev: &Device, regulator: Regulator<Enabled>) -> Result { 169 + /// // We can also disable an enabled regulator without reliquinshing our 170 + /// // refcount: 171 + /// // 172 + /// // If this operation fails, the `Error` will contain the regulator 173 + /// // reference, so that the operation may be retried. 174 + /// let regulator: Regulator<Disabled> = 175 + /// regulator.try_into_disabled().map_err(|error| error.error)?; 176 + /// 177 + /// // The refcount will be decremented when `regulator` is dropped. 178 + /// drop(regulator); 179 + /// 180 + /// // ... 181 + /// 182 + /// Ok(()) 183 + /// } 184 + /// ``` 185 + /// 186 + /// ## Using [`Regulator<Dynamic>`] 187 + /// 188 + /// This example mimics the behavior of the C API, where the user is in 189 + /// control of the enabled reference count. This is useful for drivers that 190 + /// might call enable and disable to manage the `enable` reference count at 191 + /// runtime, perhaps as a result of `open()` and `close()` calls or whatever 192 + /// other driver-specific or subsystem-specific hooks. 193 + /// 194 + /// ``` 195 + /// # use kernel::prelude::*; 196 + /// # use kernel::c_str; 197 + /// # use kernel::device::Device; 198 + /// # use kernel::regulator::{Regulator, Dynamic}; 199 + /// struct PrivateData { 200 + /// regulator: Regulator<Dynamic>, 201 + /// } 202 + /// 203 + /// // A fictictious probe function that obtains a regulator and sets it up. 204 + /// fn probe(dev: &Device) -> Result<PrivateData> { 205 + /// // Obtain a reference to a (fictitious) regulator. 206 + /// let mut regulator = Regulator::<Dynamic>::get(dev, c_str!("vcc"))?; 207 + /// 208 + /// Ok(PrivateData { regulator }) 209 + /// } 210 + /// 211 + /// // A fictictious function that indicates that the device is going to be used. 212 + /// fn open(dev: &Device, data: &mut PrivateData) -> Result { 213 + /// // Increase the `enabled` reference count. 214 + /// data.regulator.enable()?; 215 + /// 216 + /// Ok(()) 217 + /// } 218 + /// 219 + /// fn close(dev: &Device, data: &mut PrivateData) -> Result { 220 + /// // Decrease the `enabled` reference count. 221 + /// data.regulator.disable()?; 222 + /// 223 + /// Ok(()) 224 + /// } 225 + /// 226 + /// fn remove(dev: &Device, data: PrivateData) -> Result { 227 + /// // `PrivateData` is dropped here, which will drop the 228 + /// // `Regulator<Dynamic>` in turn. 229 + /// // 230 + /// // The reference that was obtained by `regulator_get()` will be 231 + /// // released, but it is up to the user to make sure that the number of calls 232 + /// // to `enable()` and `disabled()` are balanced before this point. 233 + /// Ok(()) 234 + /// } 235 + /// ``` 236 + /// 237 + /// # Invariants 238 + /// 239 + /// - `inner` is a non-null wrapper over a pointer to a `struct 240 + /// regulator` obtained from [`regulator_get()`]. 241 + /// 242 + /// [`regulator_get()`]: https://docs.kernel.org/driver-api/regulator.html#c.regulator_get 243 + pub struct Regulator<State = Dynamic> 244 + where 245 + State: RegulatorState, 246 + { 247 + inner: NonNull<bindings::regulator>, 248 + _phantom: PhantomData<State>, 249 + } 250 + 251 + impl<T: RegulatorState> Regulator<T> { 252 + /// Sets the voltage for the regulator. 253 + /// 254 + /// This can be used to ensure that the device powers up cleanly. 255 + pub fn set_voltage(&self, min_voltage: Voltage, max_voltage: Voltage) -> Result { 256 + // SAFETY: Safe as per the type invariants of `Regulator`. 257 + to_result(unsafe { 258 + bindings::regulator_set_voltage( 259 + self.inner.as_ptr(), 260 + min_voltage.as_microvolts(), 261 + max_voltage.as_microvolts(), 262 + ) 263 + }) 264 + } 265 + 266 + /// Gets the current voltage of the regulator. 267 + pub fn get_voltage(&self) -> Result<Voltage> { 268 + // SAFETY: Safe as per the type invariants of `Regulator`. 269 + let voltage = unsafe { bindings::regulator_get_voltage(self.inner.as_ptr()) }; 270 + if voltage < 0 { 271 + Err(kernel::error::Error::from_errno(voltage)) 272 + } else { 273 + Ok(Voltage::from_microvolts(voltage)) 274 + } 275 + } 276 + 277 + fn get_internal(dev: &Device, name: &CStr) -> Result<Regulator<T>> { 278 + // SAFETY: It is safe to call `regulator_get()`, on a device pointer 279 + // received from the C code. 280 + let inner = from_err_ptr(unsafe { bindings::regulator_get(dev.as_raw(), name.as_ptr()) })?; 281 + 282 + // SAFETY: We can safely trust `inner` to be a pointer to a valid 283 + // regulator if `ERR_PTR` was not returned. 284 + let inner = unsafe { NonNull::new_unchecked(inner) }; 285 + 286 + Ok(Self { 287 + inner, 288 + _phantom: PhantomData, 289 + }) 290 + } 291 + 292 + fn enable_internal(&mut self) -> Result { 293 + // SAFETY: Safe as per the type invariants of `Regulator`. 294 + to_result(unsafe { bindings::regulator_enable(self.inner.as_ptr()) }) 295 + } 296 + 297 + fn disable_internal(&mut self) -> Result { 298 + // SAFETY: Safe as per the type invariants of `Regulator`. 299 + to_result(unsafe { bindings::regulator_disable(self.inner.as_ptr()) }) 300 + } 301 + } 302 + 303 + impl Regulator<Disabled> { 304 + /// Obtains a [`Regulator`] instance from the system. 305 + pub fn get(dev: &Device, name: &CStr) -> Result<Self> { 306 + Regulator::get_internal(dev, name) 307 + } 308 + 309 + /// Attempts to convert the regulator to an enabled state. 310 + pub fn try_into_enabled(self) -> Result<Regulator<Enabled>, Error<Disabled>> { 311 + // We will be transferring the ownership of our `regulator_get()` count to 312 + // `Regulator<Enabled>`. 313 + let mut regulator = ManuallyDrop::new(self); 314 + 315 + regulator 316 + .enable_internal() 317 + .map(|()| Regulator { 318 + inner: regulator.inner, 319 + _phantom: PhantomData, 320 + }) 321 + .map_err(|error| Error { 322 + error, 323 + regulator: ManuallyDrop::into_inner(regulator), 324 + }) 325 + } 326 + } 327 + 328 + impl Regulator<Enabled> { 329 + /// Obtains a [`Regulator`] instance from the system and enables it. 330 + /// 331 + /// This is equivalent to calling `regulator_get_enable()` in the C API. 332 + pub fn get(dev: &Device, name: &CStr) -> Result<Self> { 333 + Regulator::<Disabled>::get_internal(dev, name)? 334 + .try_into_enabled() 335 + .map_err(|error| error.error) 336 + } 337 + 338 + /// Attempts to convert the regulator to a disabled state. 339 + pub fn try_into_disabled(self) -> Result<Regulator<Disabled>, Error<Enabled>> { 340 + // We will be transferring the ownership of our `regulator_get()` count 341 + // to `Regulator<Disabled>`. 342 + let mut regulator = ManuallyDrop::new(self); 343 + 344 + regulator 345 + .disable_internal() 346 + .map(|()| Regulator { 347 + inner: regulator.inner, 348 + _phantom: PhantomData, 349 + }) 350 + .map_err(|error| Error { 351 + error, 352 + regulator: ManuallyDrop::into_inner(regulator), 353 + }) 354 + } 355 + } 356 + 357 + impl Regulator<Dynamic> { 358 + /// Obtains a [`Regulator`] instance from the system. The current state of 359 + /// the regulator is unknown and it is up to the user to manage the enabled 360 + /// reference count. 361 + /// 362 + /// This closely mimics the behavior of the C API and can be used to 363 + /// dynamically manage the enabled reference count at runtime. 364 + pub fn get(dev: &Device, name: &CStr) -> Result<Self> { 365 + Regulator::get_internal(dev, name) 366 + } 367 + 368 + /// Increases the `enabled` reference count. 369 + pub fn enable(&mut self) -> Result { 370 + self.enable_internal() 371 + } 372 + 373 + /// Decreases the `enabled` reference count. 374 + pub fn disable(&mut self) -> Result { 375 + self.disable_internal() 376 + } 377 + } 378 + 379 + impl<T: IsEnabled> Regulator<T> { 380 + /// Checks if the regulator is enabled. 381 + pub fn is_enabled(&self) -> bool { 382 + // SAFETY: Safe as per the type invariants of `Regulator`. 383 + unsafe { bindings::regulator_is_enabled(self.inner.as_ptr()) != 0 } 384 + } 385 + } 386 + 387 + impl<T: RegulatorState> Drop for Regulator<T> { 388 + fn drop(&mut self) { 389 + if T::DISABLE_ON_DROP { 390 + // SAFETY: By the type invariants, we know that `self` owns a 391 + // reference on the enabled refcount, so it is safe to relinquish it 392 + // now. 393 + unsafe { bindings::regulator_disable(self.inner.as_ptr()) }; 394 + } 395 + // SAFETY: By the type invariants, we know that `self` owns a reference, 396 + // so it is safe to relinquish it now. 397 + unsafe { bindings::regulator_put(self.inner.as_ptr()) }; 398 + } 399 + } 400 + 401 + /// A voltage. 402 + /// 403 + /// This type represents a voltage value in microvolts. 404 + #[repr(transparent)] 405 + #[derive(Copy, Clone, PartialEq, Eq)] 406 + pub struct Voltage(i32); 407 + 408 + impl Voltage { 409 + /// Creates a new `Voltage` from a value in microvolts. 410 + pub fn from_microvolts(uv: i32) -> Self { 411 + Self(uv) 412 + } 413 + 414 + /// Returns the value of the voltage in microvolts as an [`i32`]. 415 + pub fn as_microvolts(self) -> i32 { 416 + self.0 417 + } 418 + }