mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-22 20:23:57 +08:00
regulator: Updates for v4.20
This has been a very busy release for the core, some fixes, one large new feature and a big bit of refactoring to update the GPIO API: - Support for coupled regulators from Dmitry Osipenko based on a prior attempt by Maciej Purski, allowing us to handle situations where the voltages on two regulators can't be too far apart from each other. - Conversion of the GPIO support in both drivers and the core to use GPIO descriptors rather than numbers, part of the overall project to remove GPIO numbers. - Support for standby mode suspend states from Andrei Stefanescu. - New drivers for Allwinner AXP209, Cirrus Logic Lochnagar and Microchip MPC16502. -----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAlwhKkcTHGJyb29uaWVA a2VybmVsLm9yZwAKCRAk1otyXVSH0DFfB/91/ECmybKTP+RvwUTZ0rrqFFs2C9Vl 76vH242exyJuzv44inWi9gOcXFDn7c9hf7Vl4Jd5UVP53Nzm5I8ZwExQsxax9BsN hltlX01UpRAmHNkMNrnJH6YAntD3EicYGSUDjohkWItIDqpMAjhWpx/yGXTEjBir gvkV51bF3qAYQe0g6MmK3KeVw96QPNjUhoPbsqbpaXaF6fmyOVzMiFrffJGmUAyM J5qRv3OhsZiZy2/zxNLkUI6y4XKDEaFJ3RhSKoUwItGyKQt2saXMoJGyEEWm2b6X coTm0ZQk+EU+b659lDHErTM4YUx7p7tQt3VM09NoMD8B261TdZ0y99Oh =8Rxt -----END PGP SIGNATURE----- Merge tag 'regulator-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator Pull regulator updates from Mark Brown: "This has been a very busy release for the core, some fixes, one large new feature and a big bit of refactoring to update the GPIO API: - Support for coupled regulators from Dmitry Osipenko based on a prior attempt by Maciej Purski, allowing us to handle situations where the voltages on two regulators can't be too far apart from each other. - Conversion of the GPIO support in both drivers and the core to use GPIO descriptors rather than numbers, part of the overall project to remove GPIO numbers. - Support for standby mode suspend states from Andrei Stefanescu. - New drivers for Allwinner AXP209, Cirrus Logic Lochnagar and Microchip MPC16502" * tag 'regulator-v4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (90 commits) regulator: tps65910: fix a missing check of return value regulator: mcp16502: Select REGMAP_I2C to fix build error regulator: convert to DEFINE_SHOW_ATTRIBUTE regulator: mcp16502: Fix missing n_voltages setting regulator: mcp16502: Use #ifdef CONFIG_PM_SLEEP around mcp16502_suspend/resume_noirq regulator: mcp16502: code cleanup regulator: act8945a-regulator: make symbol act8945a_pm static drivers/regulator: fix a missing check of return value regulator: act8945a-regulator: fix 'defined but not used' compiler warning regulator: axp20x: fix set_ramp_delay for AXP209/dcdc2 regulator: mcp16502: add support for suspend mfd: axp20x: use explicit bit defines mfd: axp20x: Clean up included headers regulator: dts: enable soft-start and ramp delay for the OLinuXino Lime2 dt-bindings: mfd: axp20x: Add software based soft_start for AXP209 LDO3 regulator: axp20x: add software based soft_start for AXP209 LDO3 dt-bindings: mfd: axp20x: add support for regulator-ramp-delay for AXP209 regulator: axp20x: add support for set_ramp_delay for AXP209 mfd: axp20x: name voltage ramping define properly regulator: mcp16502: add regulator driver for MCP16502 ...
This commit is contained in:
commit
79f20778fb
@ -32,6 +32,15 @@ Required properties:
|
||||
- interrupt-controller: The PMIC has its own internal IRQs
|
||||
- #interrupt-cells: Should be set to 1
|
||||
|
||||
Supported common regulator properties, see ../regulator/regulator.txt for
|
||||
more information:
|
||||
- regulator-ramp-delay: sets the ramp up delay in uV/us
|
||||
AXP20x/DCDC2: 1600, 800
|
||||
AXP20x/LDO3: 1600, 800
|
||||
- regulator-soft-start: enable the output at the lowest possible voltage and
|
||||
only then set the desired voltage
|
||||
AXP20x/LDO3: software-based implementation
|
||||
|
||||
Optional properties:
|
||||
- x-powers,dcdc-freq: defines the work frequency of DC-DC in KHz
|
||||
AXP152/20X: range: 750-1875, Default: 1.5 MHz
|
||||
|
@ -15,11 +15,17 @@ Optional input supply properties:
|
||||
- inl67-supply: The input supply for REG_LDO3 and REG_LDO4
|
||||
|
||||
Any standard regulator properties can be used to configure the single regulator.
|
||||
regulator-initial-mode, regulator-allowed-modes and regulator-mode could be
|
||||
specified using mode values from dt-bindings/regulator/active-semi,8945a-regulator.h
|
||||
file.
|
||||
|
||||
The valid names for regulators are:
|
||||
REG_DCDC1, REG_DCDC2, REG_DCDC3, REG_LDO1, REG_LDO2, REG_LDO3, REG_LDO4.
|
||||
|
||||
Example:
|
||||
|
||||
#include <dt-bindings/regulator/active-semi,8945a-regulator.h>
|
||||
|
||||
pmic@5b {
|
||||
compatible = "active-semi,act8945a";
|
||||
reg = <0x5b>;
|
||||
@ -32,6 +38,18 @@ Example:
|
||||
regulator-min-microvolt = <1350000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_FIXED>,
|
||||
<ACT8945A_REGULATOR_MODE_LOWPOWER>;
|
||||
regulator-initial-mode = <ACT8945A_REGULATOR_MODE_FIXED>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-min-microvolt=<1400000>;
|
||||
regulator-suspend-max-microvolt=<1400000>;
|
||||
regulator-changeable-in-suspend;
|
||||
regulator-mode=<ACT8945A_REGULATOR_MODE_LOWPOWER>;
|
||||
};
|
||||
};
|
||||
|
||||
vdd_1v2_reg: REG_DCDC2 {
|
||||
@ -39,6 +57,14 @@ Example:
|
||||
regulator-min-microvolt = <1100000>;
|
||||
regulator-max-microvolt = <1300000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_FIXED>,
|
||||
<ACT8945A_REGULATOR_MODE_LOWPOWER>;
|
||||
regulator-initial-mode = <ACT8945A_REGULATOR_MODE_FIXED>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vdd_3v3_reg: REG_DCDC3 {
|
||||
@ -53,6 +79,14 @@ Example:
|
||||
regulator-min-microvolt = <2500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-allowed-modes = <ACT8945A_REGULATOR_MODE_NORMAL>,
|
||||
<ACT8945A_REGULATOR_MODE_LOWPOWER>;
|
||||
regulator-initial-mode = <ACT8945A_REGULATOR_MODE_NORMAL>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vdd_3v3_lp_reg: REG_LDO2 {
|
||||
|
@ -0,0 +1,82 @@
|
||||
Cirrus Logic Lochnagar Audio Development Board
|
||||
|
||||
Lochnagar is an evaluation and development board for Cirrus Logic
|
||||
Smart CODEC and Amp devices. It allows the connection of most Cirrus
|
||||
Logic devices on mini-cards, as well as allowing connection of
|
||||
various application processor systems to provide a full evaluation
|
||||
platform. Audio system topology, clocking and power can all be
|
||||
controlled through the Lochnagar, allowing the device under test
|
||||
to be used in a variety of possible use cases.
|
||||
|
||||
This binding document describes the binding for the regulator portion
|
||||
of the driver.
|
||||
|
||||
Also see these documents for generic binding information:
|
||||
[1] Regulator: ../regulator/regulator.txt
|
||||
|
||||
This binding must be part of the Lochnagar MFD binding:
|
||||
[2] ../mfd/cirrus,lochnagar.txt
|
||||
|
||||
Optional sub-nodes:
|
||||
|
||||
- VDDCORE : Initialisation data for the VDDCORE regulator, which
|
||||
supplies the CODECs digital core if it has no build regulator for that
|
||||
purpose.
|
||||
Required Properties:
|
||||
- compatible : One of the following strings:
|
||||
"cirrus,lochnagar2-vddcore"
|
||||
- SYSVDD-supply: Primary power supply for the Lochnagar.
|
||||
|
||||
- MICVDD : Initialisation data for the MICVDD regulator, which
|
||||
supplies the CODECs MICVDD.
|
||||
Required Properties:
|
||||
- compatible : One of the following strings:
|
||||
"cirrus,lochnagar2-micvdd"
|
||||
- SYSVDD-supply: Primary power supply for the Lochnagar.
|
||||
|
||||
- MIC1VDD, MIC2VDD : Initialisation data for the MICxVDD supplies.
|
||||
Required Properties:
|
||||
- compatible : One of the following strings:
|
||||
"cirrus,lochnagar2-mic1vdd", "cirrus,lochnagar2-mic2vdd"
|
||||
Optional Properties:
|
||||
- cirrus,micbias-input : A property selecting which of the CODEC
|
||||
minicard micbias outputs should be used, valid values are 1 - 4.
|
||||
- MICBIAS1-supply, MICBIAS2-supply: Regulator supplies for the
|
||||
MICxVDD outputs, supplying the digital microphones, normally
|
||||
supplied from the attached CODEC.
|
||||
|
||||
- VDD1V8 : Recommended fixed regulator for the VDD1V8 regulator, which supplies the
|
||||
CODECs analog and 1.8V digital supplies.
|
||||
Required Properties:
|
||||
- compatible : Should be set to "regulator-fixed"
|
||||
- regulator-min-microvolt : Should be set to 1.8V
|
||||
- regulator-max-microvolt : Should be set to 1.8V
|
||||
- regulator-boot-on
|
||||
- regulator-always-on
|
||||
- vin-supply : Should be set to same supply as SYSVDD
|
||||
|
||||
Example:
|
||||
|
||||
lochnagar {
|
||||
lochnagar-micvdd: MICVDD {
|
||||
compatible = "cirrus,lochnagar2-micvdd";
|
||||
|
||||
SYSVDD-supply = <&wallvdd>;
|
||||
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
};
|
||||
|
||||
lochnagar-vdd1v8: VDD1V8 {
|
||||
compatible = "regulator-fixed";
|
||||
|
||||
regulator-name = "VDD1V8";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-boot-on;
|
||||
regulator-always-on;
|
||||
|
||||
vin-supply = <&wallvdd>;
|
||||
};
|
||||
};
|
||||
|
@ -0,0 +1,143 @@
|
||||
MCP16502 PMIC
|
||||
|
||||
Required properties:
|
||||
- compatible: "microchip,mcp16502"
|
||||
- reg: I2C slave address
|
||||
- lpm-gpios: GPIO for LPM pin. Note that this GPIO *must* remain high during
|
||||
suspend-to-ram, keeping the PMIC into HIBERNATE mode.
|
||||
- regulators: A node that houses a sub-node for each regulator within
|
||||
the device. Each sub-node is identified using the node's
|
||||
name. The content of each sub-node is defined by the
|
||||
standard binding for regulators; see regulator.txt.
|
||||
|
||||
Regualtors of MCP16502 PMIC:
|
||||
1) VDD_IO - Buck (1.2 - 3.7 V)
|
||||
2) VDD_DDR - Buck (0.6 - 1.85 V)
|
||||
3) VDD_CORE - Buck (0.6 - 1.85 V)
|
||||
4) VDD_OTHER - BUCK (0.6 - 1.85 V)
|
||||
5) LDO1 - LDO (1.2 - 3.7 V)
|
||||
6) LDO2 - LDO (1.2 - 3.7 V)
|
||||
|
||||
Regulator modes:
|
||||
2 - FPWM: higher precision, higher consumption
|
||||
4 - AutoPFM: lower precision, lower consumption
|
||||
|
||||
Each regulator is defined using the standard binding for regulators.
|
||||
|
||||
Example:
|
||||
|
||||
mcp16502@5b {
|
||||
compatible = "microchip,mcp16502";
|
||||
reg = <0x5b>;
|
||||
status = "okay";
|
||||
lpm-gpios = <&pioBU 7 GPIO_ACTIVE_HIGH>;
|
||||
|
||||
regulators {
|
||||
VDD_IO {
|
||||
regulator-name = "VDD_IO";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
regulator-on-in-suspend;
|
||||
regulator-mode = <4>;
|
||||
};
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
regulator-mode = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
VDD_DDR {
|
||||
regulator-name = "VDD_DDR";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
regulator-on-in-suspend;
|
||||
regulator-mode = <4>;
|
||||
};
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-mode = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
VDD_CORE {
|
||||
regulator-name = "VDD_CORE";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
regulator-on-in-suspend;
|
||||
regulator-mode = <4>;
|
||||
};
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
regulator-mode = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
VDD_OTHER {
|
||||
regulator-name = "VDD_OTHER";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1850000>;
|
||||
regulator-initial-mode = <2>;
|
||||
regulator-allowed-modes = <2>, <4>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
regulator-on-in-suspend;
|
||||
regulator-mode = <4>;
|
||||
};
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
regulator-mode = <4>;
|
||||
};
|
||||
};
|
||||
|
||||
LDO1 {
|
||||
regulator-name = "LDO1";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
regulator-on-in-suspend;
|
||||
};
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
LDO2 {
|
||||
regulator-name = "LDO2";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <3700000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-standby {
|
||||
regulator-on-in-suspend;
|
||||
};
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
@ -33,13 +33,16 @@ Optional properties:
|
||||
decreases of any level. This is useful for regulators with exponential
|
||||
voltage changes.
|
||||
- regulator-soft-start: Enable soft start so that voltage ramps slowly
|
||||
- regulator-state-standby sub-root node for Standby mode
|
||||
: equivalent with standby Linux sleep state, which provides energy savings
|
||||
with a relatively quick transition back time.
|
||||
- regulator-state-mem sub-root node for Suspend-to-RAM mode
|
||||
: suspend to memory, the device goes to sleep, but all data stored in memory,
|
||||
only some external interrupt can wake the device.
|
||||
- regulator-state-disk sub-root node for Suspend-to-DISK mode
|
||||
: suspend to disk, this state operates similarly to Suspend-to-RAM,
|
||||
but includes a final step of writing memory contents to disk.
|
||||
- regulator-state-[mem/disk] node has following common properties:
|
||||
- regulator-state-[mem/disk/standby] node has following common properties:
|
||||
- regulator-on-in-suspend: regulator should be on in suspend state.
|
||||
- regulator-off-in-suspend: regulator should be off in suspend state.
|
||||
- regulator-suspend-min-microvolt: minimum voltage may be set in
|
||||
@ -76,8 +79,11 @@ Optional properties:
|
||||
- regulator-coupled-with: Regulators with which the regulator
|
||||
is coupled. The linkage is 2-way - all coupled regulators should be linked
|
||||
with each other. A regulator should not be coupled with its supplier.
|
||||
- regulator-coupled-max-spread: Max spread between voltages of coupled regulators
|
||||
in microvolts.
|
||||
- regulator-coupled-max-spread: Array of maximum spread between voltages of
|
||||
coupled regulators in microvolts, each value in the array relates to the
|
||||
corresponding couple specified by the regulator-coupled-with property.
|
||||
- regulator-max-step-microvolt: Maximum difference between current and target
|
||||
voltages that can be changed safely in a single step.
|
||||
|
||||
Deprecated properties:
|
||||
- regulator-compatible: If a regulator chip contains multiple
|
||||
|
@ -254,6 +254,7 @@ GPIO
|
||||
devm_gpiod_get_index_optional()
|
||||
devm_gpiod_get_optional()
|
||||
devm_gpiod_put()
|
||||
devm_gpiod_unhinge()
|
||||
devm_gpiochip_add_data()
|
||||
devm_gpiochip_remove()
|
||||
devm_gpio_request()
|
||||
|
@ -9891,6 +9891,13 @@ M: Ludovic Desroches <ludovic.desroches@microchip.com>
|
||||
S: Maintained
|
||||
F: drivers/mmc/host/atmel-mci.c
|
||||
|
||||
MICROCHIP MCP16502 PMIC DRIVER
|
||||
M: Andrei Stefanescu <andrei.stefanescu@microchip.com>
|
||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/regulator/mcp16502-regulator.txt
|
||||
F: drivers/regulator/mcp16502.c
|
||||
|
||||
MICROCHIP MCP3911 ADC DRIVER
|
||||
M: Marcus Folkesson <marcus.folkesson@gmail.com>
|
||||
M: Kent Gustavsson <kent@minoris.se>
|
||||
|
@ -245,6 +245,8 @@
|
||||
regulator-min-microvolt = <2800000>;
|
||||
regulator-max-microvolt = <2800000>;
|
||||
regulator-name = "vddio-csi0";
|
||||
regulator-soft-start;
|
||||
regulator-ramp-delay = <1600>;
|
||||
};
|
||||
|
||||
®_ldo4 {
|
||||
|
@ -194,8 +194,8 @@ static struct wm8994_pdata wm8994_pdata = {
|
||||
0x3, /* IRQ out, active high, CMOS */
|
||||
},
|
||||
.ldo = {
|
||||
{ .enable = S3C64XX_GPN(6), .init_data = &wm8994_ldo1, },
|
||||
{ .enable = S3C64XX_GPN(4), .init_data = &wm8994_ldo2, },
|
||||
{ .init_data = &wm8994_ldo1, },
|
||||
{ .init_data = &wm8994_ldo2, },
|
||||
},
|
||||
};
|
||||
|
||||
@ -203,6 +203,18 @@ static const struct i2c_board_info wm1277_devs[] = {
|
||||
{ I2C_BOARD_INFO("wm8958", 0x1a), /* WM8958 is the superset */
|
||||
.platform_data = &wm8994_pdata,
|
||||
.irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2,
|
||||
.dev_name = "wm8958",
|
||||
},
|
||||
};
|
||||
|
||||
static struct gpiod_lookup_table wm8994_gpiod_table = {
|
||||
.dev_id = "i2c-wm8958", /* I2C device name */
|
||||
.table = {
|
||||
GPIO_LOOKUP("GPION", 6,
|
||||
"wlf,ldo1ena", GPIO_ACTIVE_HIGH),
|
||||
GPIO_LOOKUP("GPION", 4,
|
||||
"wlf,ldo2ena", GPIO_ACTIVE_HIGH),
|
||||
{ },
|
||||
},
|
||||
};
|
||||
|
||||
@ -381,6 +393,7 @@ static int wlf_gf_module_probe(struct i2c_client *i2c,
|
||||
|
||||
gpiod_add_lookup_table(&wm5102_reva_gpiod_table);
|
||||
gpiod_add_lookup_table(&wm5102_gpiod_table);
|
||||
gpiod_add_lookup_table(&wm8994_gpiod_table);
|
||||
|
||||
if (i < ARRAY_SIZE(gf_mods)) {
|
||||
dev_info(&i2c->dev, "%s revision %d\n",
|
||||
|
@ -98,15 +98,28 @@ struct gpio_desc *__must_check devm_gpiod_get_index(struct device *dev,
|
||||
struct gpio_desc **dr;
|
||||
struct gpio_desc *desc;
|
||||
|
||||
desc = gpiod_get_index(dev, con_id, idx, flags);
|
||||
if (IS_ERR(desc))
|
||||
return desc;
|
||||
|
||||
/*
|
||||
* For non-exclusive GPIO descriptors, check if this descriptor is
|
||||
* already under resource management by this device.
|
||||
*/
|
||||
if (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
|
||||
struct devres *dres;
|
||||
|
||||
dres = devres_find(dev, devm_gpiod_release,
|
||||
devm_gpiod_match, &desc);
|
||||
if (dres)
|
||||
return desc;
|
||||
}
|
||||
|
||||
dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
|
||||
GFP_KERNEL);
|
||||
if (!dr)
|
||||
if (!dr) {
|
||||
gpiod_put(desc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
desc = gpiod_get_index(dev, con_id, idx, flags);
|
||||
if (IS_ERR(desc)) {
|
||||
devres_free(dr);
|
||||
return desc;
|
||||
}
|
||||
|
||||
*dr = desc;
|
||||
@ -140,15 +153,28 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
|
||||
struct gpio_desc **dr;
|
||||
struct gpio_desc *desc;
|
||||
|
||||
desc = gpiod_get_from_of_node(node, propname, index, dflags, label);
|
||||
if (IS_ERR(desc))
|
||||
return desc;
|
||||
|
||||
/*
|
||||
* For non-exclusive GPIO descriptors, check if this descriptor is
|
||||
* already under resource management by this device.
|
||||
*/
|
||||
if (dflags & GPIOD_FLAGS_BIT_NONEXCLUSIVE) {
|
||||
struct devres *dres;
|
||||
|
||||
dres = devres_find(dev, devm_gpiod_release,
|
||||
devm_gpiod_match, &desc);
|
||||
if (dres)
|
||||
return desc;
|
||||
}
|
||||
|
||||
dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
|
||||
GFP_KERNEL);
|
||||
if (!dr)
|
||||
if (!dr) {
|
||||
gpiod_put(desc);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
desc = gpiod_get_from_of_node(node, propname, index, dflags, label);
|
||||
if (IS_ERR(desc)) {
|
||||
devres_free(dr);
|
||||
return desc;
|
||||
}
|
||||
|
||||
*dr = desc;
|
||||
@ -320,6 +346,36 @@ void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
|
||||
}
|
||||
EXPORT_SYMBOL(devm_gpiod_put);
|
||||
|
||||
/**
|
||||
* devm_gpiod_unhinge - Remove resource management from a gpio descriptor
|
||||
* @dev: GPIO consumer
|
||||
* @desc: GPIO descriptor to remove resource management from
|
||||
*
|
||||
* Remove resource management from a GPIO descriptor. This is needed when
|
||||
* you want to hand over lifecycle management of a descriptor to another
|
||||
* mechanism.
|
||||
*/
|
||||
|
||||
void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (IS_ERR_OR_NULL(desc))
|
||||
return;
|
||||
ret = devres_destroy(dev, devm_gpiod_release,
|
||||
devm_gpiod_match, &desc);
|
||||
/*
|
||||
* If the GPIO descriptor is requested as nonexclusive, we
|
||||
* may call this function several times on the same descriptor
|
||||
* so it is OK if devres_destroy() returns -ENOENT.
|
||||
*/
|
||||
if (ret == -ENOENT)
|
||||
return;
|
||||
/* Anything else we should warn about */
|
||||
WARN_ON(ret);
|
||||
}
|
||||
EXPORT_SYMBOL(devm_gpiod_unhinge);
|
||||
|
||||
/**
|
||||
* devm_gpiod_put_array - Resource-managed gpiod_put_array()
|
||||
* @dev: GPIO consumer
|
||||
|
@ -4205,6 +4205,8 @@ struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
transitory = flags & OF_GPIO_TRANSITORY;
|
||||
|
||||
ret = gpiod_request(desc, label);
|
||||
if (ret == -EBUSY && (flags & GPIOD_FLAGS_BIT_NONEXCLUSIVE))
|
||||
return desc;
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -201,12 +201,6 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep,
|
||||
struct gpio_array *array_info,
|
||||
unsigned long *value_bitmap);
|
||||
|
||||
/* This is just passed between gpiolib and devres */
|
||||
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label);
|
||||
|
||||
extern struct spinlock gpio_lock;
|
||||
extern struct list_head gpio_devices;
|
||||
|
||||
|
@ -16,20 +16,21 @@
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/axp20x.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/mfd/axp20x.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#define AXP20X_OFF 0x80
|
||||
#define AXP20X_OFF BIT(7)
|
||||
|
||||
#define AXP806_REG_ADDR_EXT_ADDR_MASTER_MODE 0
|
||||
#define AXP806_REG_ADDR_EXT_ADDR_SLAVE_MODE BIT(4)
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
@ -306,14 +305,6 @@ static int wm8994_set_pdata_from_of(struct wm8994 *wm8994)
|
||||
|
||||
pdata->csnaddr_pd = of_property_read_bool(np, "wlf,csnaddr-pd");
|
||||
|
||||
pdata->ldo[0].enable = of_get_named_gpio(np, "wlf,ldo1ena", 0);
|
||||
if (pdata->ldo[0].enable < 0)
|
||||
pdata->ldo[0].enable = 0;
|
||||
|
||||
pdata->ldo[1].enable = of_get_named_gpio(np, "wlf,ldo2ena", 0);
|
||||
if (pdata->ldo[1].enable < 0)
|
||||
pdata->ldo[1].enable = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
|
@ -328,7 +328,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
|
||||
return -ENODEV;
|
||||
}
|
||||
for_each_child_of_node(nproot, np) {
|
||||
if (!of_node_cmp(np->name, info->desc.name)) {
|
||||
if (of_node_name_eq(np, info->desc.name)) {
|
||||
config->init_data =
|
||||
of_get_regulator_init_data(&pdev->dev, np,
|
||||
&info->desc);
|
||||
|
@ -567,6 +567,16 @@ config REGULATOR_MC13892
|
||||
Say y here to support the regulators found on the Freescale MC13892
|
||||
PMIC.
|
||||
|
||||
config REGULATOR_MCP16502
|
||||
tristate "Microchip MCP16502 PMIC"
|
||||
depends on I2C && OF
|
||||
select REGMAP_I2C
|
||||
help
|
||||
Say y here to support the MCP16502 PMIC. This driver supports
|
||||
basic operations (get/set voltage, get/set operating mode)
|
||||
through the regulator interface. In addition it enables
|
||||
suspend-to-ram/standby transition.
|
||||
|
||||
config REGULATOR_MT6311
|
||||
tristate "MediaTek MT6311 PMIC"
|
||||
depends on I2C
|
||||
|
@ -74,6 +74,7 @@ obj-$(CONFIG_REGULATOR_MAX77802) += max77802-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
|
||||
obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o
|
||||
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
|
||||
|
@ -15,31 +15,41 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <dt-bindings/regulator/active-semi,8945a-regulator.h>
|
||||
|
||||
/**
|
||||
* ACT8945A Global Register Map.
|
||||
*/
|
||||
#define ACT8945A_SYS_MODE 0x00
|
||||
#define ACT8945A_SYS_CTRL 0x01
|
||||
#define ACT8945A_SYS_UNLK_REGS 0x0b
|
||||
#define ACT8945A_DCDC1_VSET1 0x20
|
||||
#define ACT8945A_DCDC1_VSET2 0x21
|
||||
#define ACT8945A_DCDC1_CTRL 0x22
|
||||
#define ACT8945A_DCDC1_SUS 0x24
|
||||
#define ACT8945A_DCDC2_VSET1 0x30
|
||||
#define ACT8945A_DCDC2_VSET2 0x31
|
||||
#define ACT8945A_DCDC2_CTRL 0x32
|
||||
#define ACT8945A_DCDC2_SUS 0x34
|
||||
#define ACT8945A_DCDC3_VSET1 0x40
|
||||
#define ACT8945A_DCDC3_VSET2 0x41
|
||||
#define ACT8945A_DCDC3_CTRL 0x42
|
||||
#define ACT8945A_DCDC3_SUS 0x44
|
||||
#define ACT8945A_LDO1_VSET 0x50
|
||||
#define ACT8945A_LDO1_CTRL 0x51
|
||||
#define ACT8945A_LDO1_SUS 0x52
|
||||
#define ACT8945A_LDO2_VSET 0x54
|
||||
#define ACT8945A_LDO2_CTRL 0x55
|
||||
#define ACT8945A_LDO2_SUS 0x56
|
||||
#define ACT8945A_LDO3_VSET 0x60
|
||||
#define ACT8945A_LDO3_CTRL 0x61
|
||||
#define ACT8945A_LDO3_SUS 0x62
|
||||
#define ACT8945A_LDO4_VSET 0x64
|
||||
#define ACT8945A_LDO4_CTRL 0x65
|
||||
#define ACT8945A_LDO4_SUS 0x66
|
||||
|
||||
/**
|
||||
* Field Definitions.
|
||||
@ -60,7 +70,12 @@ enum {
|
||||
ACT8945A_ID_LDO2,
|
||||
ACT8945A_ID_LDO3,
|
||||
ACT8945A_ID_LDO4,
|
||||
ACT8945A_REG_NUM,
|
||||
ACT8945A_ID_MAX,
|
||||
};
|
||||
|
||||
struct act8945a_pmic {
|
||||
struct regmap *regmap;
|
||||
u32 op_mode[ACT8945A_ID_MAX];
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range act8945a_voltage_ranges[] = {
|
||||
@ -69,6 +84,143 @@ static const struct regulator_linear_range act8945a_voltage_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000),
|
||||
};
|
||||
|
||||
static int act8945a_set_suspend_state(struct regulator_dev *rdev, bool enable)
|
||||
{
|
||||
struct regmap *regmap = rdev->regmap;
|
||||
int id = rdev->desc->id, reg, val;
|
||||
|
||||
switch (id) {
|
||||
case ACT8945A_ID_DCDC1:
|
||||
reg = ACT8945A_DCDC1_SUS;
|
||||
val = 0xa8;
|
||||
break;
|
||||
case ACT8945A_ID_DCDC2:
|
||||
reg = ACT8945A_DCDC2_SUS;
|
||||
val = 0xa8;
|
||||
break;
|
||||
case ACT8945A_ID_DCDC3:
|
||||
reg = ACT8945A_DCDC3_SUS;
|
||||
val = 0xa8;
|
||||
break;
|
||||
case ACT8945A_ID_LDO1:
|
||||
reg = ACT8945A_LDO1_SUS;
|
||||
val = 0xe8;
|
||||
break;
|
||||
case ACT8945A_ID_LDO2:
|
||||
reg = ACT8945A_LDO2_SUS;
|
||||
val = 0xe8;
|
||||
break;
|
||||
case ACT8945A_ID_LDO3:
|
||||
reg = ACT8945A_LDO3_SUS;
|
||||
val = 0xe8;
|
||||
break;
|
||||
case ACT8945A_ID_LDO4:
|
||||
reg = ACT8945A_LDO4_SUS;
|
||||
val = 0xe8;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (enable)
|
||||
val |= BIT(4);
|
||||
|
||||
/*
|
||||
* Ask the PMIC to enable/disable this output when entering hibernate
|
||||
* mode.
|
||||
*/
|
||||
return regmap_write(regmap, reg, val);
|
||||
}
|
||||
|
||||
static int act8945a_set_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
return act8945a_set_suspend_state(rdev, true);
|
||||
}
|
||||
|
||||
static int act8945a_set_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
return act8945a_set_suspend_state(rdev, false);
|
||||
}
|
||||
|
||||
static unsigned int act8945a_of_map_mode(unsigned int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case ACT8945A_REGULATOR_MODE_FIXED:
|
||||
case ACT8945A_REGULATOR_MODE_NORMAL:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
case ACT8945A_REGULATOR_MODE_LOWPOWER:
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
default:
|
||||
return REGULATOR_MODE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static int act8945a_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev);
|
||||
struct regmap *regmap = rdev->regmap;
|
||||
int id = rdev->desc->id;
|
||||
int reg, ret, val = 0;
|
||||
|
||||
switch (id) {
|
||||
case ACT8945A_ID_DCDC1:
|
||||
reg = ACT8945A_DCDC1_CTRL;
|
||||
break;
|
||||
case ACT8945A_ID_DCDC2:
|
||||
reg = ACT8945A_DCDC2_CTRL;
|
||||
break;
|
||||
case ACT8945A_ID_DCDC3:
|
||||
reg = ACT8945A_DCDC3_CTRL;
|
||||
break;
|
||||
case ACT8945A_ID_LDO1:
|
||||
reg = ACT8945A_LDO1_SUS;
|
||||
break;
|
||||
case ACT8945A_ID_LDO2:
|
||||
reg = ACT8945A_LDO2_SUS;
|
||||
break;
|
||||
case ACT8945A_ID_LDO3:
|
||||
reg = ACT8945A_LDO3_SUS;
|
||||
break;
|
||||
case ACT8945A_ID_LDO4:
|
||||
reg = ACT8945A_LDO4_SUS;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
if (rdev->desc->id > ACT8945A_ID_DCDC3)
|
||||
val = BIT(5);
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
if (rdev->desc->id <= ACT8945A_ID_DCDC3)
|
||||
val = BIT(5);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(regmap, reg, BIT(5), val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
act8945a->op_mode[id] = mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int act8945a_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct act8945a_pmic *act8945a = rdev_get_drvdata(rdev);
|
||||
int id = rdev->desc->id;
|
||||
|
||||
if (id < ACT8945A_ID_DCDC1 || id >= ACT8945A_ID_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
return act8945a->op_mode[id];
|
||||
}
|
||||
|
||||
static const struct regulator_ops act8945a_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
@ -76,7 +228,11 @@ static const struct regulator_ops act8945a_ops = {
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.set_mode = act8945a_set_mode,
|
||||
.get_mode = act8945a_get_mode,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_suspend_enable = act8945a_set_suspend_enable,
|
||||
.set_suspend_disable = act8945a_set_suspend_disable,
|
||||
};
|
||||
|
||||
#define ACT89xx_REG(_name, _family, _id, _vsel_reg, _supply) \
|
||||
@ -84,6 +240,7 @@ static const struct regulator_ops act8945a_ops = {
|
||||
.name = _name, \
|
||||
.supply_name = _supply, \
|
||||
.of_match = of_match_ptr("REG_"#_id), \
|
||||
.of_map_mode = act8945a_of_map_mode, \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = _family##_ID_##_id, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
@ -122,10 +279,22 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_config config = { };
|
||||
const struct regulator_desc *regulators;
|
||||
struct act8945a_pmic *act8945a;
|
||||
struct regulator_dev *rdev;
|
||||
int i, num_regulators;
|
||||
bool voltage_select;
|
||||
|
||||
act8945a = devm_kzalloc(&pdev->dev, sizeof(*act8945a), GFP_KERNEL);
|
||||
if (!act8945a)
|
||||
return -ENOMEM;
|
||||
|
||||
act8945a->regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
if (!act8945a->regmap) {
|
||||
dev_err(&pdev->dev,
|
||||
"could not retrieve regmap from parent device\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
voltage_select = of_property_read_bool(pdev->dev.parent->of_node,
|
||||
"active-semi,vsel-high");
|
||||
|
||||
@ -139,8 +308,10 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.dev->of_node = pdev->dev.parent->of_node;
|
||||
config.driver_data = act8945a;
|
||||
for (i = 0; i < num_regulators; i++) {
|
||||
rdev = devm_regulator_register(&pdev->dev, ®ulators[i], &config);
|
||||
rdev = devm_regulator_register(&pdev->dev, ®ulators[i],
|
||||
&config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to register %s regulator\n",
|
||||
@ -149,14 +320,42 @@ static int act8945a_pmic_probe(struct platform_device *pdev)
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
platform_set_drvdata(pdev, act8945a);
|
||||
|
||||
/* Unlock expert registers. */
|
||||
return regmap_write(act8945a->regmap, ACT8945A_SYS_UNLK_REGS, 0xef);
|
||||
}
|
||||
|
||||
static int __maybe_unused act8945a_suspend(struct device *pdev)
|
||||
{
|
||||
struct act8945a_pmic *act8945a = dev_get_drvdata(pdev);
|
||||
|
||||
/*
|
||||
* Ask the PMIC to enter the suspend mode on the next PWRHLD
|
||||
* transition.
|
||||
*/
|
||||
return regmap_write(act8945a->regmap, ACT8945A_SYS_CTRL, 0x42);
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(act8945a_pm, act8945a_suspend, NULL);
|
||||
|
||||
static void act8945a_pmic_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct act8945a_pmic *act8945a = platform_get_drvdata(pdev);
|
||||
|
||||
/*
|
||||
* Ask the PMIC to shutdown everything on the next PWRHLD transition.
|
||||
*/
|
||||
regmap_write(act8945a->regmap, ACT8945A_SYS_CTRL, 0x0);
|
||||
}
|
||||
|
||||
static struct platform_driver act8945a_pmic_driver = {
|
||||
.driver = {
|
||||
.name = "act8945a-regulator",
|
||||
.pm = &act8945a_pm,
|
||||
},
|
||||
.probe = act8945a_pmic_probe,
|
||||
.shutdown = act8945a_pmic_shutdown,
|
||||
};
|
||||
module_platform_driver(act8945a_pmic_driver);
|
||||
|
||||
|
@ -283,9 +283,6 @@ static int arizona_ldo1_common_init(struct platform_device *pdev,
|
||||
of_node_put(config.of_node);
|
||||
|
||||
if (IS_ERR(ldo1->regulator)) {
|
||||
if (config.ena_gpiod)
|
||||
gpiod_put(config.ena_gpiod);
|
||||
|
||||
ret = PTR_ERR(ldo1->regulator);
|
||||
dev_err(&pdev->dev, "Failed to register LDO1 supply: %d\n",
|
||||
ret);
|
||||
|
@ -1,12 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
|
||||
*
|
||||
* Copyright (C) 2012 Renesas Electronics Corporation
|
||||
* Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,6 +9,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mfd/rohm-bd718x7.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
@ -130,6 +131,7 @@ static struct regulator_ops bd718xx_buck_regulator_nolinear_ops = {
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.map_voltage = regulator_map_voltage_ascend,
|
||||
.set_voltage_sel = bd718xx_set_voltage_sel_restricted,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
@ -1007,7 +1009,7 @@ static const struct bd718xx_regulator_data bd71837_regulators[] = {
|
||||
};
|
||||
|
||||
struct bd718xx_pmic_inits {
|
||||
const struct bd718xx_regulator_data (*r_datas)[];
|
||||
const struct bd718xx_regulator_data *r_datas;
|
||||
unsigned int r_amount;
|
||||
};
|
||||
|
||||
@ -1017,11 +1019,11 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
struct regulator_config config = { 0 };
|
||||
struct bd718xx_pmic_inits pmic_regulators[] = {
|
||||
[BD718XX_TYPE_BD71837] = {
|
||||
.r_datas = &bd71837_regulators,
|
||||
.r_datas = bd71837_regulators,
|
||||
.r_amount = ARRAY_SIZE(bd71837_regulators),
|
||||
},
|
||||
[BD718XX_TYPE_BD71847] = {
|
||||
.r_datas = &bd71847_regulators,
|
||||
.r_datas = bd71847_regulators,
|
||||
.r_amount = ARRAY_SIZE(bd71847_regulators),
|
||||
},
|
||||
};
|
||||
@ -1053,13 +1055,36 @@ static int bd718xx_probe(struct platform_device *pdev)
|
||||
BD718XX_REG_REGLOCK);
|
||||
}
|
||||
|
||||
/* At poweroff transition PMIC HW disables EN bit for regulators but
|
||||
* leaves SEL bit untouched. So if state transition from POWEROFF
|
||||
* is done to SNVS - then all power rails controlled by SW (having
|
||||
* SEL bit set) stay disabled as EN is cleared. This may result boot
|
||||
* failure if any crucial systems are powered by these rails.
|
||||
*
|
||||
* Change the next stage from poweroff to be READY instead of SNVS
|
||||
* for all reset types because OTP loading at READY will clear SEL
|
||||
* bit allowing HW defaults for power rails to be used
|
||||
*/
|
||||
err = regmap_update_bits(mfd->regmap, BD718XX_REG_TRANS_COND1,
|
||||
BD718XX_ON_REQ_POWEROFF_MASK |
|
||||
BD718XX_SWRESET_POWEROFF_MASK |
|
||||
BD718XX_WDOG_POWEROFF_MASK |
|
||||
BD718XX_KEY_L_POWEROFF_MASK,
|
||||
BD718XX_POWOFF_TO_RDY);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to change reset target\n");
|
||||
goto err;
|
||||
} else {
|
||||
dev_dbg(&pdev->dev, "Changed all resets from SVNS to READY\n");
|
||||
}
|
||||
|
||||
for (i = 0; i < pmic_regulators[mfd->chip_type].r_amount; i++) {
|
||||
|
||||
const struct regulator_desc *desc;
|
||||
struct regulator_dev *rdev;
|
||||
const struct bd718xx_regulator_data *r;
|
||||
|
||||
r = &(*pmic_regulators[mfd->chip_type].r_datas)[i];
|
||||
r = &pmic_regulators[mfd->chip_type].r_datas[i];
|
||||
desc = &r->desc;
|
||||
|
||||
config.dev = pdev->dev.parent;
|
||||
|
@ -1,17 +1,9 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* ROHM BD9571MWV-M regulator driver
|
||||
*
|
||||
* Copyright (C) 2017 Marek Vasut <marek.vasut+renesas@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether expressed or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License version 2 for more details.
|
||||
*
|
||||
* Based on the TPS65086 driver
|
||||
*
|
||||
* NOTE: VD09 is missing
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -435,7 +435,7 @@ static int da9052_regulator_probe(struct platform_device *pdev)
|
||||
return -ENODEV;
|
||||
|
||||
for_each_child_of_node(nproot, np) {
|
||||
if (!of_node_cmp(np->name,
|
||||
if (of_node_name_eq(np,
|
||||
regulator->info->reg_desc.name)) {
|
||||
config.init_data = of_get_regulator_init_data(
|
||||
&pdev->dev, np,
|
||||
|
@ -131,7 +131,7 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
|
||||
if (error < 0)
|
||||
goto error_i2c;
|
||||
|
||||
mutex_lock(&chip->rdev->mutex);
|
||||
regulator_lock(chip->rdev);
|
||||
|
||||
if (val & DA9210_E_OVCURR) {
|
||||
regulator_notifier_call_chain(chip->rdev,
|
||||
@ -157,7 +157,7 @@ static irqreturn_t da9210_irq_handler(int irq, void *data)
|
||||
handled |= DA9210_E_VMAX;
|
||||
}
|
||||
|
||||
mutex_unlock(&chip->rdev->mutex);
|
||||
regulator_unlock(chip->rdev);
|
||||
|
||||
if (handled) {
|
||||
/* Clear handled events */
|
||||
|
@ -389,6 +389,12 @@ static int da9211_regulator_init(struct da9211 *chip)
|
||||
else
|
||||
config.ena_gpiod = NULL;
|
||||
|
||||
/*
|
||||
* Hand the GPIO descriptor management over to the regulator
|
||||
* core, remove it from GPIO devres management.
|
||||
*/
|
||||
if (config.ena_gpiod)
|
||||
devm_gpiod_unhinge(chip->dev, config.ena_gpiod);
|
||||
chip->rdev[i] = devm_regulator_register(chip->dev,
|
||||
&da9211_regulators[i], &config);
|
||||
if (IS_ERR(chip->rdev[i])) {
|
||||
|
@ -75,7 +75,7 @@ static struct ux500_regulator_debug {
|
||||
u8 *state_after_suspend;
|
||||
} rdebug;
|
||||
|
||||
static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
|
||||
static int ux500_regulator_power_state_cnt_show(struct seq_file *s, void *p)
|
||||
{
|
||||
/* print power state count */
|
||||
seq_printf(s, "ux500-regulator power state count: %i\n",
|
||||
@ -83,23 +83,9 @@ static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p)
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(ux500_regulator_power_state_cnt);
|
||||
|
||||
static int ux500_regulator_power_state_cnt_open(struct inode *inode,
|
||||
struct file *file)
|
||||
{
|
||||
return single_open(file, ux500_regulator_power_state_cnt_print,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations ux500_regulator_power_state_cnt_fops = {
|
||||
.open = ux500_regulator_power_state_cnt_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int ux500_regulator_status_print(struct seq_file *s, void *p)
|
||||
static int ux500_regulator_status_show(struct seq_file *s, void *p)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -122,20 +108,7 @@ static int ux500_regulator_status_print(struct seq_file *s, void *p)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ux500_regulator_status_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, ux500_regulator_status_print,
|
||||
inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations ux500_regulator_status_fops = {
|
||||
.open = ux500_regulator_status_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
DEFINE_SHOW_ATTRIBUTE(ux500_regulator_status);
|
||||
|
||||
int __attribute__((weak)) dbx500_regulator_testcase(
|
||||
struct dbx500_regulator_info *regulator_info,
|
||||
|
@ -183,7 +183,11 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
|
||||
*/
|
||||
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
|
||||
|
||||
cfg.ena_gpiod = devm_gpiod_get_optional(&pdev->dev, NULL, gflags);
|
||||
/*
|
||||
* Do not use devm* here: the regulator core takes over the
|
||||
* lifecycle management of the GPIO descriptor.
|
||||
*/
|
||||
cfg.ena_gpiod = gpiod_get_optional(&pdev->dev, NULL, gflags);
|
||||
if (IS_ERR(cfg.ena_gpiod))
|
||||
return PTR_ERR(cfg.ena_gpiod);
|
||||
|
||||
|
@ -42,6 +42,8 @@ struct regulator {
|
||||
unsigned int always_on:1;
|
||||
unsigned int bypass:1;
|
||||
int uA_load;
|
||||
unsigned int enable_count;
|
||||
unsigned int deferred_disables;
|
||||
struct regulator_voltage voltage[REGULATOR_STATES_NUM];
|
||||
const char *supply_name;
|
||||
struct device_attribute dev_attr;
|
||||
|
@ -224,13 +224,15 @@ static struct gpio_desc *lm363x_regulator_of_get_enable_gpio(struct device *dev,
|
||||
/*
|
||||
* Check LCM_EN1/2_GPIO is configured.
|
||||
* Those pins are used for enabling VPOS/VNEG LDOs.
|
||||
* Do not use devm* here: the regulator core takes over the
|
||||
* lifecycle management of the GPIO descriptor.
|
||||
*/
|
||||
switch (id) {
|
||||
case LM3632_LDO_POS:
|
||||
return devm_gpiod_get_index_optional(dev, "enable", 0,
|
||||
return gpiod_get_index_optional(dev, "enable", 0,
|
||||
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
|
||||
case LM3632_LDO_NEG:
|
||||
return devm_gpiod_get_index_optional(dev, "enable", 1,
|
||||
return gpiod_get_index_optional(dev, "enable", 1,
|
||||
GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE);
|
||||
default:
|
||||
return NULL;
|
||||
@ -263,6 +265,8 @@ static int lm363x_regulator_probe(struct platform_device *pdev)
|
||||
LM3632_EXT_EN_MASK,
|
||||
LM3632_EXT_EN_MASK);
|
||||
if (ret) {
|
||||
if (gpiod)
|
||||
gpiod_put(gpiod);
|
||||
dev_err(dev, "External pin err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
@ -20,6 +21,8 @@
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
#include <linux/mfd/lochnagar.h>
|
||||
#include <linux/mfd/lochnagar1_regs.h>
|
||||
#include <linux/mfd/lochnagar2_regs.h>
|
||||
|
||||
static const struct regulator_ops lochnagar_micvdd_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
@ -212,28 +215,52 @@ static const struct regulator_desc lochnagar_regulators[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct of_device_id lochnagar_of_match[] = {
|
||||
{
|
||||
.compatible = "cirrus,lochnagar2-micvdd",
|
||||
.data = &lochnagar_regulators[LOCHNAGAR_MICVDD],
|
||||
},
|
||||
{
|
||||
.compatible = "cirrus,lochnagar2-mic1vdd",
|
||||
.data = &lochnagar_regulators[LOCHNAGAR_MIC1VDD],
|
||||
},
|
||||
{
|
||||
.compatible = "cirrus,lochnagar2-mic2vdd",
|
||||
.data = &lochnagar_regulators[LOCHNAGAR_MIC1VDD],
|
||||
},
|
||||
{
|
||||
.compatible = "cirrus,lochnagar2-vddcore",
|
||||
.data = &lochnagar_regulators[LOCHNAGAR_VDDCORE],
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static int lochnagar_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct lochnagar *lochnagar = dev_get_drvdata(dev->parent);
|
||||
struct regulator_config config = { };
|
||||
const struct of_device_id *of_id;
|
||||
const struct regulator_desc *desc;
|
||||
struct regulator_dev *rdev;
|
||||
int ret, i;
|
||||
int ret;
|
||||
|
||||
config.dev = lochnagar->dev;
|
||||
config.dev = dev;
|
||||
config.regmap = lochnagar->regmap;
|
||||
config.driver_data = lochnagar;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(lochnagar_regulators); i++) {
|
||||
const struct regulator_desc *desc = &lochnagar_regulators[i];
|
||||
of_id = of_match_device(lochnagar_of_match, dev);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
rdev = devm_regulator_register(dev, desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(dev, "Failed to register %s regulator: %d\n",
|
||||
desc->name, ret);
|
||||
return ret;
|
||||
}
|
||||
desc = of_id->data;
|
||||
|
||||
rdev = devm_regulator_register(dev, desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(dev, "Failed to register %s regulator: %d\n",
|
||||
desc->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -242,6 +269,7 @@ static int lochnagar_regulator_probe(struct platform_device *pdev)
|
||||
static struct platform_driver lochnagar_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "lochnagar-regulator",
|
||||
.of_match_table = of_match_ptr(lochnagar_of_match),
|
||||
},
|
||||
|
||||
.probe = lochnagar_regulator_probe,
|
||||
|
@ -501,8 +501,12 @@ static int lp8788_config_ldo_enable_mode(struct platform_device *pdev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* FIXME: check default mode for GPIO here: high or low? */
|
||||
ldo->ena_gpiod = devm_gpiod_get_index_optional(&pdev->dev,
|
||||
/*
|
||||
* Do not use devm* here: the regulator core takes over the
|
||||
* lifecycle management of the GPIO descriptor.
|
||||
* FIXME: check default mode for GPIO here: high or low?
|
||||
*/
|
||||
ldo->ena_gpiod = gpiod_get_index_optional(&pdev->dev,
|
||||
"enable",
|
||||
enable_id,
|
||||
GPIOD_OUT_HIGH |
|
||||
|
@ -11,8 +11,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
@ -76,6 +75,7 @@ enum max77686_ramp_rate {
|
||||
};
|
||||
|
||||
struct max77686_data {
|
||||
struct device *dev;
|
||||
DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS);
|
||||
|
||||
/* Array indexed by regulator id */
|
||||
@ -250,26 +250,34 @@ static int max77686_of_parse_cb(struct device_node *np,
|
||||
struct regulator_config *config)
|
||||
{
|
||||
struct max77686_data *max77686 = config->driver_data;
|
||||
int ret;
|
||||
|
||||
switch (desc->id) {
|
||||
case MAX77686_BUCK8:
|
||||
case MAX77686_BUCK9:
|
||||
case MAX77686_LDO20 ... MAX77686_LDO22:
|
||||
config->ena_gpio = of_get_named_gpio(np,
|
||||
"maxim,ena-gpios", 0);
|
||||
config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
|
||||
config->ena_gpio_initialized = true;
|
||||
config->ena_gpiod = gpiod_get_from_of_node(np,
|
||||
"maxim,ena",
|
||||
0,
|
||||
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
|
||||
"max77686-regulator");
|
||||
if (IS_ERR(config->ena_gpiod))
|
||||
config->ena_gpiod = NULL;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(config->ena_gpio)) {
|
||||
if (config->ena_gpiod) {
|
||||
set_bit(desc->id, max77686->gpio_enabled);
|
||||
|
||||
return regmap_update_bits(config->regmap, desc->enable_reg,
|
||||
desc->enable_mask,
|
||||
MAX77686_GPIO_CONTROL);
|
||||
ret = regmap_update_bits(config->regmap, desc->enable_reg,
|
||||
desc->enable_mask,
|
||||
MAX77686_GPIO_CONTROL);
|
||||
if (ret) {
|
||||
gpiod_put(config->ena_gpiod);
|
||||
config->ena_gpiod = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -507,6 +515,7 @@ static int max77686_pmic_probe(struct platform_device *pdev)
|
||||
if (!max77686)
|
||||
return -ENOMEM;
|
||||
|
||||
max77686->dev = &pdev->dev;
|
||||
config.dev = iodev->dev;
|
||||
config.regmap = iodev->regmap;
|
||||
config.driver_data = max77686;
|
||||
|
@ -231,9 +231,13 @@ static int max8952_pmic_probe(struct i2c_client *client,
|
||||
else
|
||||
gflags = GPIOD_OUT_LOW;
|
||||
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
|
||||
gpiod = devm_gpiod_get_optional(&client->dev,
|
||||
"max8952,en",
|
||||
gflags);
|
||||
/*
|
||||
* Do not use devm* here: the regulator core takes over the
|
||||
* lifecycle management of the GPIO descriptor.
|
||||
*/
|
||||
gpiod = gpiod_get_optional(&client->dev,
|
||||
"max8952,en",
|
||||
gflags);
|
||||
if (IS_ERR(gpiod))
|
||||
return PTR_ERR(gpiod);
|
||||
if (gpiod)
|
||||
|
@ -808,7 +808,13 @@ static int max8973_probe(struct i2c_client *client,
|
||||
config.of_node = client->dev.of_node;
|
||||
config.regmap = max->regmap;
|
||||
|
||||
/* Register the regulators */
|
||||
/*
|
||||
* Register the regulators
|
||||
* Turn the GPIO descriptor over to the regulator core for
|
||||
* lifecycle management if we pass an ena_gpiod.
|
||||
*/
|
||||
if (config.ena_gpiod)
|
||||
devm_gpiod_unhinge(&client->dev, config.ena_gpiod);
|
||||
rdev = devm_regulator_register(&client->dev, &max->desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
|
@ -925,7 +925,7 @@ static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev,
|
||||
pdata->regulators = rdata;
|
||||
for_each_child_of_node(regulators_np, reg_np) {
|
||||
for (i = 0; i < ARRAY_SIZE(regulators); i++)
|
||||
if (!of_node_cmp(reg_np->name, regulators[i].name))
|
||||
if (of_node_name_eq(reg_np, regulators[i].name))
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(regulators)) {
|
||||
|
@ -186,7 +186,7 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
|
||||
for (i = 0; i < num_regulators; i++) {
|
||||
if (!regulators[i].desc.name)
|
||||
continue;
|
||||
if (!of_node_cmp(child->name,
|
||||
if (of_node_name_eq(child,
|
||||
regulators[i].desc.name)) {
|
||||
p->id = i;
|
||||
p->init_data = of_get_regulator_init_data(
|
||||
|
552
drivers/regulator/mcp16502.c
Normal file
552
drivers/regulator/mcp16502.c
Normal file
@ -0,0 +1,552 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// MCP16502 PMIC driver
|
||||
//
|
||||
// Copyright (C) 2018 Microchip Technology Inc. and its subsidiaries
|
||||
//
|
||||
// Author: Andrei Stefanescu <andrei.stefanescu@microchip.com>
|
||||
//
|
||||
// Inspired from tps65086-regulator.c
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#define VDD_LOW_SEL 0x0D
|
||||
#define VDD_HIGH_SEL 0x3F
|
||||
|
||||
#define MCP16502_FLT BIT(7)
|
||||
#define MCP16502_ENS BIT(0)
|
||||
|
||||
/*
|
||||
* The PMIC has four sets of registers corresponding to four power modes:
|
||||
* Performance, Active, Low-power, Hibernate.
|
||||
*
|
||||
* Registers:
|
||||
* Each regulator has a register for each power mode. To access a register
|
||||
* for a specific regulator and mode BASE_* and OFFSET_* need to be added.
|
||||
*
|
||||
* Operating modes:
|
||||
* In order for the PMIC to transition to operating modes it has to be
|
||||
* controlled via GPIO lines called LPM and HPM.
|
||||
*
|
||||
* The registers are fully configurable such that you can put all regulators in
|
||||
* a low-power state while the PMIC is in Active mode. They are supposed to be
|
||||
* configured at startup and then simply transition to/from a global low-power
|
||||
* state by setting the GPIO lpm pin high/low.
|
||||
*
|
||||
* This driver keeps the PMIC in Active mode, Low-power state is set for the
|
||||
* regulators by enabling/disabling operating mode (FPWM or Auto PFM).
|
||||
*
|
||||
* The PMIC's Low-power and Hibernate modes are used during standby/suspend.
|
||||
* To enter standby/suspend the PMIC will go to Low-power mode. From there, it
|
||||
* will transition to Hibernate when the PWRHLD line is set to low by the MPU.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function is useful for iterating over all regulators and accessing their
|
||||
* registers in a generic way or accessing a regulator device by its id.
|
||||
*/
|
||||
#define MCP16502_BASE(i) (((i) + 1) << 4)
|
||||
#define MCP16502_STAT_BASE(i) ((i) + 5)
|
||||
|
||||
#define MCP16502_OFFSET_MODE_A 0
|
||||
#define MCP16502_OFFSET_MODE_LPM 1
|
||||
#define MCP16502_OFFSET_MODE_HIB 2
|
||||
|
||||
#define MCP16502_OPMODE_ACTIVE REGULATOR_MODE_NORMAL
|
||||
#define MCP16502_OPMODE_LPM REGULATOR_MODE_IDLE
|
||||
#define MCP16502_OPMODE_HIB REGULATOR_MODE_STANDBY
|
||||
|
||||
#define MCP16502_MODE_AUTO_PFM 0
|
||||
#define MCP16502_MODE_FPWM BIT(6)
|
||||
|
||||
#define MCP16502_VSEL 0x3F
|
||||
#define MCP16502_EN BIT(7)
|
||||
#define MCP16502_MODE BIT(6)
|
||||
|
||||
#define MCP16502_MIN_REG 0x0
|
||||
#define MCP16502_MAX_REG 0x65
|
||||
|
||||
static unsigned int mcp16502_of_map_mode(unsigned int mode)
|
||||
{
|
||||
if (mode == REGULATOR_MODE_NORMAL || mode == REGULATOR_MODE_IDLE)
|
||||
return mode;
|
||||
|
||||
return REGULATOR_MODE_INVALID;
|
||||
}
|
||||
|
||||
#define MCP16502_REGULATOR(_name, _id, _ranges, _ops) \
|
||||
[_id] = { \
|
||||
.name = _name, \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = _id, \
|
||||
.ops = &(_ops), \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = MCP16502_VSEL + 1, \
|
||||
.linear_ranges = _ranges, \
|
||||
.n_linear_ranges = ARRAY_SIZE(_ranges), \
|
||||
.of_match = of_match_ptr(_name), \
|
||||
.of_map_mode = mcp16502_of_map_mode, \
|
||||
.vsel_reg = (((_id) + 1) << 4), \
|
||||
.vsel_mask = MCP16502_VSEL, \
|
||||
.enable_reg = (((_id) + 1) << 4), \
|
||||
.enable_mask = MCP16502_EN, \
|
||||
}
|
||||
|
||||
enum {
|
||||
BUCK1 = 0,
|
||||
BUCK2,
|
||||
BUCK3,
|
||||
BUCK4,
|
||||
LDO1,
|
||||
LDO2,
|
||||
NUM_REGULATORS
|
||||
};
|
||||
|
||||
/*
|
||||
* struct mcp16502 - PMIC representation
|
||||
* @rdev: the regulators belonging to this chip
|
||||
* @rmap: regmap to be used for I2C communication
|
||||
* @lpm: LPM GPIO descriptor
|
||||
*/
|
||||
struct mcp16502 {
|
||||
struct regulator_dev *rdev[NUM_REGULATORS];
|
||||
struct regmap *rmap;
|
||||
struct gpio_desc *lpm;
|
||||
};
|
||||
|
||||
/*
|
||||
* mcp16502_gpio_set_mode() - set the GPIO corresponding value
|
||||
*
|
||||
* Used to prepare transitioning into hibernate or resuming from it.
|
||||
*/
|
||||
static void mcp16502_gpio_set_mode(struct mcp16502 *mcp, int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case MCP16502_OPMODE_ACTIVE:
|
||||
gpiod_set_value(mcp->lpm, 0);
|
||||
break;
|
||||
case MCP16502_OPMODE_LPM:
|
||||
case MCP16502_OPMODE_HIB:
|
||||
gpiod_set_value(mcp->lpm, 1);
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: %d invalid\n", __func__, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mcp16502_get_reg() - get the PMIC's configuration register for opmode
|
||||
*
|
||||
* @rdev: the regulator whose register we are searching
|
||||
* @opmode: the PMIC's operating mode ACTIVE, Low-power, Hibernate
|
||||
*/
|
||||
static int mcp16502_get_reg(struct regulator_dev *rdev, int opmode)
|
||||
{
|
||||
int reg = MCP16502_BASE(rdev_get_id(rdev));
|
||||
|
||||
switch (opmode) {
|
||||
case MCP16502_OPMODE_ACTIVE:
|
||||
return reg + MCP16502_OFFSET_MODE_A;
|
||||
case MCP16502_OPMODE_LPM:
|
||||
return reg + MCP16502_OFFSET_MODE_LPM;
|
||||
case MCP16502_OPMODE_HIB:
|
||||
return reg + MCP16502_OFFSET_MODE_HIB;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mcp16502_get_mode() - return the current operating mode of a regulator
|
||||
*
|
||||
* Note: all functions that are not part of entering/exiting standby/suspend
|
||||
* use the Active mode registers.
|
||||
*
|
||||
* Note: this is different from the PMIC's operatig mode, it is the
|
||||
* MODE bit from the regulator's register.
|
||||
*/
|
||||
static unsigned int mcp16502_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret, reg;
|
||||
struct mcp16502 *mcp = rdev_get_drvdata(rdev);
|
||||
|
||||
reg = mcp16502_get_reg(rdev, MCP16502_OPMODE_ACTIVE);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
ret = regmap_read(mcp->rmap, reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
switch (val & MCP16502_MODE) {
|
||||
case MCP16502_MODE_FPWM:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
case MCP16502_MODE_AUTO_PFM:
|
||||
return REGULATOR_MODE_IDLE;
|
||||
default:
|
||||
return REGULATOR_MODE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* _mcp16502_set_mode() - helper for set_mode and set_suspend_mode
|
||||
*
|
||||
* @rdev: the regulator for which we are setting the mode
|
||||
* @mode: the regulator's mode (the one from MODE bit)
|
||||
* @opmode: the PMIC's operating mode: Active/Low-power/Hibernate
|
||||
*/
|
||||
static int _mcp16502_set_mode(struct regulator_dev *rdev, unsigned int mode,
|
||||
unsigned int op_mode)
|
||||
{
|
||||
int val;
|
||||
int reg;
|
||||
struct mcp16502 *mcp = rdev_get_drvdata(rdev);
|
||||
|
||||
reg = mcp16502_get_reg(rdev, op_mode);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = MCP16502_MODE_FPWM;
|
||||
break;
|
||||
case REGULATOR_MODE_IDLE:
|
||||
val = MCP16502_MODE_AUTO_PFM;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
reg = regmap_update_bits(mcp->rmap, reg, MCP16502_MODE, val);
|
||||
return reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* mcp16502_set_mode() - regulator_ops set_mode
|
||||
*/
|
||||
static int mcp16502_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_ACTIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* mcp16502_get_status() - regulator_ops get_status
|
||||
*/
|
||||
static int mcp16502_get_status(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret;
|
||||
unsigned int val;
|
||||
struct mcp16502 *mcp = rdev_get_drvdata(rdev);
|
||||
|
||||
ret = regmap_read(mcp->rmap, MCP16502_STAT_BASE(rdev_get_id(rdev)),
|
||||
&val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & MCP16502_FLT)
|
||||
return REGULATOR_STATUS_ERROR;
|
||||
else if (val & MCP16502_ENS)
|
||||
return REGULATOR_STATUS_ON;
|
||||
else if (!(val & MCP16502_ENS))
|
||||
return REGULATOR_STATUS_OFF;
|
||||
|
||||
return REGULATOR_STATUS_UNDEFINED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
/*
|
||||
* mcp16502_suspend_get_target_reg() - get the reg of the target suspend PMIC
|
||||
* mode
|
||||
*/
|
||||
static int mcp16502_suspend_get_target_reg(struct regulator_dev *rdev)
|
||||
{
|
||||
switch (pm_suspend_target_state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
return mcp16502_get_reg(rdev, MCP16502_OPMODE_LPM);
|
||||
case PM_SUSPEND_ON:
|
||||
case PM_SUSPEND_MEM:
|
||||
return mcp16502_get_reg(rdev, MCP16502_OPMODE_HIB);
|
||||
default:
|
||||
dev_err(&rdev->dev, "invalid suspend target: %d\n",
|
||||
pm_suspend_target_state);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* mcp16502_set_suspend_voltage() - regulator_ops set_suspend_voltage
|
||||
*/
|
||||
static int mcp16502_set_suspend_voltage(struct regulator_dev *rdev, int uV)
|
||||
{
|
||||
struct mcp16502 *mcp = rdev_get_drvdata(rdev);
|
||||
int sel = regulator_map_voltage_linear_range(rdev, uV, uV);
|
||||
int reg = mcp16502_suspend_get_target_reg(rdev);
|
||||
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
return regmap_update_bits(mcp->rmap, reg, MCP16502_VSEL, sel);
|
||||
}
|
||||
|
||||
/*
|
||||
* mcp16502_set_suspend_mode() - regulator_ops set_suspend_mode
|
||||
*/
|
||||
static int mcp16502_set_suspend_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
switch (pm_suspend_target_state) {
|
||||
case PM_SUSPEND_STANDBY:
|
||||
return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_LPM);
|
||||
case PM_SUSPEND_ON:
|
||||
case PM_SUSPEND_MEM:
|
||||
return _mcp16502_set_mode(rdev, mode, MCP16502_OPMODE_HIB);
|
||||
default:
|
||||
dev_err(&rdev->dev, "invalid suspend target: %d\n",
|
||||
pm_suspend_target_state);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* mcp16502_set_suspend_enable() - regulator_ops set_suspend_enable
|
||||
*/
|
||||
static int mcp16502_set_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mcp16502 *mcp = rdev_get_drvdata(rdev);
|
||||
int reg = mcp16502_suspend_get_target_reg(rdev);
|
||||
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
return regmap_update_bits(mcp->rmap, reg, MCP16502_EN, MCP16502_EN);
|
||||
}
|
||||
|
||||
/*
|
||||
* mcp16502_set_suspend_disable() - regulator_ops set_suspend_disable
|
||||
*/
|
||||
static int mcp16502_set_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mcp16502 *mcp = rdev_get_drvdata(rdev);
|
||||
int reg = mcp16502_suspend_get_target_reg(rdev);
|
||||
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
return regmap_update_bits(mcp->rmap, reg, MCP16502_EN, 0);
|
||||
}
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
|
||||
static const struct regulator_ops mcp16502_buck_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.get_status = mcp16502_get_status,
|
||||
|
||||
.set_mode = mcp16502_set_mode,
|
||||
.get_mode = mcp16502_get_mode,
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
.set_suspend_voltage = mcp16502_set_suspend_voltage,
|
||||
.set_suspend_mode = mcp16502_set_suspend_mode,
|
||||
.set_suspend_enable = mcp16502_set_suspend_enable,
|
||||
.set_suspend_disable = mcp16502_set_suspend_disable,
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
};
|
||||
|
||||
/*
|
||||
* LDOs cannot change operating modes.
|
||||
*/
|
||||
static const struct regulator_ops mcp16502_ldo_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_voltage_linear_range,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.get_status = mcp16502_get_status,
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
.set_suspend_voltage = mcp16502_set_suspend_voltage,
|
||||
.set_suspend_enable = mcp16502_set_suspend_enable,
|
||||
.set_suspend_disable = mcp16502_set_suspend_disable,
|
||||
#endif /* CONFIG_SUSPEND */
|
||||
};
|
||||
|
||||
static const struct of_device_id mcp16502_ids[] = {
|
||||
{ .compatible = "microchip,mcp16502", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mcp16502_ids);
|
||||
|
||||
static const struct regulator_linear_range b1l12_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(1200000, VDD_LOW_SEL, VDD_HIGH_SEL, 50000),
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range b234_ranges[] = {
|
||||
REGULATOR_LINEAR_RANGE(600000, VDD_LOW_SEL, VDD_HIGH_SEL, 25000),
|
||||
};
|
||||
|
||||
static const struct regulator_desc mcp16502_desc[] = {
|
||||
/* MCP16502_REGULATOR(_name, _id, ranges, regulator_ops) */
|
||||
MCP16502_REGULATOR("VDD_IO", BUCK1, b1l12_ranges, mcp16502_buck_ops),
|
||||
MCP16502_REGULATOR("VDD_DDR", BUCK2, b234_ranges, mcp16502_buck_ops),
|
||||
MCP16502_REGULATOR("VDD_CORE", BUCK3, b234_ranges, mcp16502_buck_ops),
|
||||
MCP16502_REGULATOR("VDD_OTHER", BUCK4, b234_ranges, mcp16502_buck_ops),
|
||||
MCP16502_REGULATOR("LDO1", LDO1, b1l12_ranges, mcp16502_ldo_ops),
|
||||
MCP16502_REGULATOR("LDO2", LDO2, b1l12_ranges, mcp16502_ldo_ops)
|
||||
};
|
||||
|
||||
static const struct regmap_range mcp16502_ranges[] = {
|
||||
regmap_reg_range(MCP16502_MIN_REG, MCP16502_MAX_REG)
|
||||
};
|
||||
|
||||
static const struct regmap_access_table mcp16502_yes_reg_table = {
|
||||
.yes_ranges = mcp16502_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(mcp16502_ranges),
|
||||
};
|
||||
|
||||
static const struct regmap_config mcp16502_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = MCP16502_MAX_REG,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
.rd_table = &mcp16502_yes_reg_table,
|
||||
.wr_table = &mcp16502_yes_reg_table,
|
||||
};
|
||||
|
||||
/*
|
||||
* set_up_regulators() - initialize all regulators
|
||||
*/
|
||||
static int setup_regulators(struct mcp16502 *mcp, struct device *dev,
|
||||
struct regulator_config config)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_REGULATORS; i++) {
|
||||
mcp->rdev[i] = devm_regulator_register(dev,
|
||||
&mcp16502_desc[i],
|
||||
&config);
|
||||
if (IS_ERR(mcp->rdev[i])) {
|
||||
dev_err(dev,
|
||||
"failed to register %s regulator %ld\n",
|
||||
mcp16502_desc[i].name, PTR_ERR(mcp->rdev[i]));
|
||||
return PTR_ERR(mcp->rdev[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcp16502_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct regulator_config config = { };
|
||||
struct device *dev;
|
||||
struct mcp16502 *mcp;
|
||||
int ret = 0;
|
||||
|
||||
dev = &client->dev;
|
||||
config.dev = dev;
|
||||
|
||||
mcp = devm_kzalloc(dev, sizeof(*mcp), GFP_KERNEL);
|
||||
if (!mcp)
|
||||
return -ENOMEM;
|
||||
|
||||
mcp->rmap = devm_regmap_init_i2c(client, &mcp16502_regmap_config);
|
||||
if (IS_ERR(mcp->rmap)) {
|
||||
ret = PTR_ERR(mcp->rmap);
|
||||
dev_err(dev, "regmap init failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, mcp);
|
||||
config.regmap = mcp->rmap;
|
||||
config.driver_data = mcp;
|
||||
|
||||
mcp->lpm = devm_gpiod_get(dev, "lpm", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(mcp->lpm)) {
|
||||
dev_err(dev, "failed to get lpm pin: %ld\n", PTR_ERR(mcp->lpm));
|
||||
return PTR_ERR(mcp->lpm);
|
||||
}
|
||||
|
||||
ret = setup_regulators(mcp, dev, config);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_ACTIVE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int mcp16502_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct mcp16502 *mcp = i2c_get_clientdata(client);
|
||||
|
||||
mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_LPM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mcp16502_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct mcp16502 *mcp = i2c_get_clientdata(client);
|
||||
|
||||
mcp16502_gpio_set_mode(mcp, MCP16502_OPMODE_ACTIVE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static const struct dev_pm_ops mcp16502_pm_ops = {
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mcp16502_suspend_noirq,
|
||||
mcp16502_resume_noirq)
|
||||
};
|
||||
#endif
|
||||
static const struct i2c_device_id mcp16502_i2c_id[] = {
|
||||
{ "mcp16502", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, mcp16502_i2c_id);
|
||||
|
||||
static struct i2c_driver mcp16502_drv = {
|
||||
.probe = mcp16502_probe,
|
||||
.driver = {
|
||||
.name = "mcp16502-regulator",
|
||||
.of_match_table = of_match_ptr(mcp16502_ids),
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &mcp16502_pm_ops,
|
||||
#endif
|
||||
},
|
||||
.id_table = mcp16502_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(mcp16502_drv);
|
||||
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("MCP16502 PMIC driver");
|
||||
MODULE_AUTHOR("Andrei Stefanescu andrei.stefanescu@microchip.com");
|
@ -20,6 +20,7 @@
|
||||
#include "internal.h"
|
||||
|
||||
static const char *const regulator_states[PM_SUSPEND_MAX + 1] = {
|
||||
[PM_SUSPEND_STANDBY] = "regulator-state-standby",
|
||||
[PM_SUSPEND_MEM] = "regulator-state-mem",
|
||||
[PM_SUSPEND_MAX] = "regulator-state-disk",
|
||||
};
|
||||
@ -170,6 +171,10 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
&pval))
|
||||
constraints->max_spread = pval;
|
||||
|
||||
if (!of_property_read_u32(np, "regulator-max-step-microvolt",
|
||||
&pval))
|
||||
constraints->max_uV_step = pval;
|
||||
|
||||
constraints->over_current_protection = of_property_read_bool(np,
|
||||
"regulator-over-current-protection");
|
||||
|
||||
@ -181,9 +186,11 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
case PM_SUSPEND_MAX:
|
||||
suspend_state = &constraints->state_disk;
|
||||
break;
|
||||
case PM_SUSPEND_STANDBY:
|
||||
suspend_state = &constraints->state_standby;
|
||||
break;
|
||||
case PM_SUSPEND_ON:
|
||||
case PM_SUSPEND_TO_IDLE:
|
||||
case PM_SUSPEND_STANDBY:
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -364,24 +371,25 @@ int of_regulator_match(struct device *dev, struct device_node *node,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_regulator_match);
|
||||
|
||||
struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *config,
|
||||
struct device_node **node)
|
||||
struct device_node *regulator_of_get_init_node(struct device *dev,
|
||||
const struct regulator_desc *desc)
|
||||
{
|
||||
struct device_node *search, *child;
|
||||
struct regulator_init_data *init_data = NULL;
|
||||
const char *name;
|
||||
|
||||
if (!dev->of_node || !desc->of_match)
|
||||
return NULL;
|
||||
|
||||
if (desc->regulators_node)
|
||||
if (desc->regulators_node) {
|
||||
search = of_get_child_by_name(dev->of_node,
|
||||
desc->regulators_node);
|
||||
else
|
||||
} else {
|
||||
search = of_node_get(dev->of_node);
|
||||
|
||||
if (!strcmp(desc->of_match, search->name))
|
||||
return search;
|
||||
}
|
||||
|
||||
if (!search) {
|
||||
dev_dbg(dev, "Failed to find regulator container node '%s'\n",
|
||||
desc->regulators_node);
|
||||
@ -393,35 +401,48 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
|
||||
if (!name)
|
||||
name = child->name;
|
||||
|
||||
if (strcmp(desc->of_match, name))
|
||||
continue;
|
||||
|
||||
init_data = of_get_regulator_init_data(dev, child, desc);
|
||||
if (!init_data) {
|
||||
dev_err(dev,
|
||||
"failed to parse DT for regulator %pOFn\n",
|
||||
child);
|
||||
break;
|
||||
}
|
||||
|
||||
if (desc->of_parse_cb) {
|
||||
if (desc->of_parse_cb(child, desc, config)) {
|
||||
dev_err(dev,
|
||||
"driver callback failed to parse DT for regulator %pOFn\n",
|
||||
child);
|
||||
init_data = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
of_node_get(child);
|
||||
*node = child;
|
||||
break;
|
||||
if (!strcmp(desc->of_match, name))
|
||||
return of_node_get(child);
|
||||
}
|
||||
|
||||
of_node_put(search);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
|
||||
const struct regulator_desc *desc,
|
||||
struct regulator_config *config,
|
||||
struct device_node **node)
|
||||
{
|
||||
struct device_node *child;
|
||||
struct regulator_init_data *init_data = NULL;
|
||||
|
||||
child = regulator_of_get_init_node(dev, desc);
|
||||
if (!child)
|
||||
return NULL;
|
||||
|
||||
init_data = of_get_regulator_init_data(dev, child, desc);
|
||||
if (!init_data) {
|
||||
dev_err(dev, "failed to parse DT for regulator %pOFn\n", child);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (desc->of_parse_cb && desc->of_parse_cb(child, desc, config)) {
|
||||
dev_err(dev,
|
||||
"driver callback failed to parse DT for regulator %pOFn\n",
|
||||
child);
|
||||
goto error;
|
||||
}
|
||||
|
||||
*node = child;
|
||||
|
||||
return init_data;
|
||||
|
||||
error:
|
||||
of_node_put(child);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int of_node_match(struct device *dev, const void *data)
|
||||
|
@ -443,13 +443,16 @@ static int palmas_ldo_write(struct palmas *palmas, unsigned int reg,
|
||||
static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
|
||||
{
|
||||
int id = rdev_get_id(dev);
|
||||
int ret;
|
||||
struct palmas_pmic *pmic = rdev_get_drvdata(dev);
|
||||
struct palmas_pmic_driver_data *ddata = pmic->palmas->pmic_ddata;
|
||||
struct palmas_regs_info *rinfo = &ddata->palmas_regs_info[id];
|
||||
unsigned int reg;
|
||||
bool rail_enable = true;
|
||||
|
||||
palmas_smps_read(pmic->palmas, rinfo->ctrl_addr, ®);
|
||||
ret = palmas_smps_read(pmic->palmas, rinfo->ctrl_addr, ®);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
|
||||
|
||||
|
@ -370,6 +370,7 @@ static struct pfuze_regulator pfuze100_regulators[] = {
|
||||
PFUZE100_VGEN_REG(PFUZE100, VGEN4, PFUZE100_VGEN4VOL, 1800000, 3300000, 100000),
|
||||
PFUZE100_VGEN_REG(PFUZE100, VGEN5, PFUZE100_VGEN5VOL, 1800000, 3300000, 100000),
|
||||
PFUZE100_VGEN_REG(PFUZE100, VGEN6, PFUZE100_VGEN6VOL, 1800000, 3300000, 100000),
|
||||
PFUZE100_COIN_REG(PFUZE100, COIN, PFUZE100_COINVOL, 0x7, pfuze100_coin),
|
||||
};
|
||||
|
||||
static struct pfuze_regulator pfuze200_regulators[] = {
|
||||
@ -436,6 +437,7 @@ static struct of_regulator_match pfuze100_matches[] = {
|
||||
{ .name = "vgen4", },
|
||||
{ .name = "vgen5", },
|
||||
{ .name = "vgen6", },
|
||||
{ .name = "coin", },
|
||||
};
|
||||
|
||||
/* PFUZE200 */
|
||||
|
@ -410,7 +410,7 @@ static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
|
||||
vreg->dev = dev;
|
||||
|
||||
for (rpmh_data = pmic_rpmh_data; rpmh_data->name; rpmh_data++)
|
||||
if (!strcmp(rpmh_data->name, node->name))
|
||||
if (of_node_name_eq(node, rpmh_data->name))
|
||||
break;
|
||||
|
||||
if (!rpmh_data->name) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
@ -14,7 +14,6 @@
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/mfd/samsung/core.h>
|
||||
#include <linux/mfd/samsung/s2mps11.h>
|
||||
#include <linux/mfd/samsung/s2mps13.h>
|
||||
@ -44,7 +43,7 @@ struct s2mps11_info {
|
||||
* Array (size: number of regulators) with GPIO-s for external
|
||||
* sleep control.
|
||||
*/
|
||||
int *ext_control_gpio;
|
||||
struct gpio_desc **ext_control_gpiod;
|
||||
};
|
||||
|
||||
static int get_ramp_delay(int ramp_delay)
|
||||
@ -511,7 +510,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
|
||||
case S2MPS14X:
|
||||
if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state))
|
||||
val = S2MPS14_ENABLE_SUSPEND;
|
||||
else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
|
||||
else if (s2mps11->ext_control_gpiod[rdev_get_id(rdev)])
|
||||
val = S2MPS14_ENABLE_EXT_CONTROL;
|
||||
else
|
||||
val = rdev->desc->enable_mask;
|
||||
@ -805,7 +804,7 @@ static int s2mps14_pmic_enable_ext_control(struct s2mps11_info *s2mps11,
|
||||
static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
|
||||
struct of_regulator_match *rdata, struct s2mps11_info *s2mps11)
|
||||
{
|
||||
int *gpio = s2mps11->ext_control_gpio;
|
||||
struct gpio_desc **gpio = s2mps11->ext_control_gpiod;
|
||||
unsigned int i;
|
||||
unsigned int valid_regulators[3] = { S2MPS14_LDO10, S2MPS14_LDO11,
|
||||
S2MPS14_LDO12 };
|
||||
@ -816,11 +815,20 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
|
||||
if (!rdata[reg].init_data || !rdata[reg].of_node)
|
||||
continue;
|
||||
|
||||
gpio[reg] = of_get_named_gpio(rdata[reg].of_node,
|
||||
"samsung,ext-control-gpios", 0);
|
||||
if (gpio_is_valid(gpio[reg]))
|
||||
dev_dbg(&pdev->dev, "Using GPIO %d for ext-control over %d/%s\n",
|
||||
gpio[reg], reg, rdata[reg].name);
|
||||
gpio[reg] = devm_gpiod_get_from_of_node(&pdev->dev,
|
||||
rdata[reg].of_node,
|
||||
"samsung,ext-control-gpios",
|
||||
0,
|
||||
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
|
||||
"s2mps11-regulator");
|
||||
if (IS_ERR(gpio[reg])) {
|
||||
dev_err(&pdev->dev, "Failed to get control GPIO for %d/%s\n",
|
||||
reg, rdata[reg].name);
|
||||
continue;
|
||||
}
|
||||
if (gpio[reg])
|
||||
dev_dbg(&pdev->dev, "Using GPIO for ext-control over %d/%s\n",
|
||||
reg, rdata[reg].name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1126,17 +1134,10 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
s2mps11->ext_control_gpio = devm_kmalloc_array(&pdev->dev,
|
||||
rdev_num, sizeof(*s2mps11->ext_control_gpio),
|
||||
GFP_KERNEL);
|
||||
if (!s2mps11->ext_control_gpio)
|
||||
s2mps11->ext_control_gpiod = devm_kcalloc(&pdev->dev, rdev_num,
|
||||
sizeof(*s2mps11->ext_control_gpiod), GFP_KERNEL);
|
||||
if (!s2mps11->ext_control_gpiod)
|
||||
return -ENOMEM;
|
||||
/*
|
||||
* 0 is a valid GPIO so initialize all GPIO-s to negative value
|
||||
* to indicate that external control won't be used for this regulator.
|
||||
*/
|
||||
for (i = 0; i < rdev_num; i++)
|
||||
s2mps11->ext_control_gpio[i] = -EINVAL;
|
||||
|
||||
if (!iodev->dev->of_node) {
|
||||
if (iodev->pdata) {
|
||||
@ -1166,8 +1167,6 @@ common_reg:
|
||||
config.dev = &pdev->dev;
|
||||
config.regmap = iodev->regmap_pmic;
|
||||
config.driver_data = s2mps11;
|
||||
config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
|
||||
config.ena_gpio_initialized = true;
|
||||
for (i = 0; i < rdev_num; i++) {
|
||||
struct regulator_dev *regulator;
|
||||
|
||||
@ -1178,8 +1177,13 @@ common_reg:
|
||||
config.init_data = rdata[i].init_data;
|
||||
config.of_node = rdata[i].of_node;
|
||||
}
|
||||
config.ena_gpio = s2mps11->ext_control_gpio[i];
|
||||
|
||||
config.ena_gpiod = s2mps11->ext_control_gpiod[i];
|
||||
/*
|
||||
* Hand the GPIO descriptor management over to the regulator
|
||||
* core, remove it from devres management.
|
||||
*/
|
||||
if (config.ena_gpiod)
|
||||
devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod);
|
||||
regulator = devm_regulator_register(&pdev->dev,
|
||||
®ulators[i], &config);
|
||||
if (IS_ERR(regulator)) {
|
||||
@ -1189,7 +1193,7 @@ common_reg:
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(s2mps11->ext_control_gpio[i])) {
|
||||
if (s2mps11->ext_control_gpiod[i]) {
|
||||
ret = s2mps14_pmic_enable_ext_control(s2mps11,
|
||||
regulator);
|
||||
if (ret < 0) {
|
||||
|
@ -561,7 +561,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
|
||||
pdata->opmode = rmode;
|
||||
for_each_child_of_node(regulators_np, reg_np) {
|
||||
for (i = 0; i < ARRAY_SIZE(regulators); i++)
|
||||
if (!of_node_cmp(reg_np->name, regulators[i].name))
|
||||
if (of_node_name_eq(reg_np, regulators[i].name))
|
||||
break;
|
||||
|
||||
if (i == ARRAY_SIZE(regulators)) {
|
||||
@ -956,10 +956,17 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
|
||||
config.regmap = iodev->regmap_pmic;
|
||||
config.of_node = pdata->regulators[i].reg_node;
|
||||
config.ena_gpiod = NULL;
|
||||
if (pdata->regulators[i].ext_control_gpiod)
|
||||
if (pdata->regulators[i].ext_control_gpiod) {
|
||||
/* Assigns config.ena_gpiod */
|
||||
s5m8767_regulator_config_ext_control(s5m8767,
|
||||
&pdata->regulators[i], &config);
|
||||
|
||||
/*
|
||||
* Hand the GPIO descriptor management over to the
|
||||
* regulator core, remove it from devres management.
|
||||
*/
|
||||
devm_gpiod_unhinge(s5m8767->dev, config.ena_gpiod);
|
||||
}
|
||||
rdev = devm_regulator_register(&pdev->dev, ®ulators[id],
|
||||
&config);
|
||||
if (IS_ERR(rdev)) {
|
||||
|
@ -489,14 +489,14 @@ static irqreturn_t stpmic1_curlim_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct regulator_dev *rdev = (struct regulator_dev *)data;
|
||||
|
||||
mutex_lock(&rdev->mutex);
|
||||
regulator_lock(rdev);
|
||||
|
||||
/* Send an overcurrent notification */
|
||||
regulator_notifier_call_chain(rdev,
|
||||
REGULATOR_EVENT_OVER_CURRENT,
|
||||
NULL);
|
||||
|
||||
mutex_unlock(&rdev->mutex);
|
||||
regulator_unlock(rdev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -480,6 +480,12 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
|
||||
else
|
||||
config.of_node = NULL;
|
||||
|
||||
/*
|
||||
* Hand the GPIO descriptor management over to the regulator
|
||||
* core, remove it from devres management.
|
||||
*/
|
||||
if (config.ena_gpiod)
|
||||
devm_gpiod_unhinge(&pdev->dev, config.ena_gpiod);
|
||||
rdev = devm_regulator_register(&pdev->dev, ri->desc, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register regulator %s\n",
|
||||
|
@ -1102,8 +1102,10 @@ static int tps65910_probe(struct platform_device *pdev)
|
||||
platform_set_drvdata(pdev, pmic);
|
||||
|
||||
/* Give control of all register to control port */
|
||||
tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
|
||||
err = tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
|
||||
DEVCTRL_SR_CTL_I2C_SEL_MASK);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
switch (tps65910_chip_id(tps65910)) {
|
||||
case TPS65910:
|
||||
|
@ -1153,7 +1153,7 @@ static irqreturn_t pmic_uv_handler(int irq, void *data)
|
||||
{
|
||||
struct regulator_dev *rdev = (struct regulator_dev *)data;
|
||||
|
||||
mutex_lock(&rdev->mutex);
|
||||
regulator_lock(rdev);
|
||||
if (irq == WM8350_IRQ_CS1 || irq == WM8350_IRQ_CS2)
|
||||
regulator_notifier_call_chain(rdev,
|
||||
REGULATOR_EVENT_REGULATION_OUT,
|
||||
@ -1162,7 +1162,7 @@ static irqreturn_t pmic_uv_handler(int irq, void *data)
|
||||
regulator_notifier_call_chain(rdev,
|
||||
REGULATOR_EVENT_UNDER_VOLTAGE,
|
||||
NULL);
|
||||
mutex_unlock(&rdev->mutex);
|
||||
regulator_unlock(rdev);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/mfd/wm8994/core.h>
|
||||
@ -129,6 +129,7 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
int id = pdev->id % ARRAY_SIZE(pdata->ldo);
|
||||
struct regulator_config config = { };
|
||||
struct wm8994_ldo *ldo;
|
||||
struct gpio_desc *gpiod;
|
||||
int ret;
|
||||
|
||||
dev_dbg(&pdev->dev, "Probing LDO%d\n", id + 1);
|
||||
@ -145,12 +146,18 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
config.driver_data = ldo;
|
||||
config.regmap = wm8994->regmap;
|
||||
config.init_data = &ldo->init_data;
|
||||
if (pdata) {
|
||||
config.ena_gpio = pdata->ldo[id].enable;
|
||||
} else if (wm8994->dev->of_node) {
|
||||
config.ena_gpio = wm8994->pdata.ldo[id].enable;
|
||||
config.ena_gpio_initialized = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up LDO enable GPIO from the parent device node, we don't
|
||||
* use devm because the regulator core will free the GPIO
|
||||
*/
|
||||
gpiod = gpiod_get_optional(pdev->dev.parent,
|
||||
id ? "wlf,ldo2ena" : "wlf,ldo1ena",
|
||||
GPIOD_OUT_LOW |
|
||||
GPIOD_FLAGS_BIT_NONEXCLUSIVE);
|
||||
if (IS_ERR(gpiod))
|
||||
return PTR_ERR(gpiod);
|
||||
config.ena_gpiod = gpiod;
|
||||
|
||||
/* Use default constraints if none set up */
|
||||
if (!pdata || !pdata->ldo[id].init_data || wm8994->dev->of_node) {
|
||||
@ -159,12 +166,17 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
|
||||
ldo->init_data = wm8994_ldo_default[id];
|
||||
ldo->init_data.consumer_supplies = &ldo->supply;
|
||||
if (!config.ena_gpio)
|
||||
if (!gpiod)
|
||||
ldo->init_data.constraints.valid_ops_mask = 0;
|
||||
} else {
|
||||
ldo->init_data = *pdata->ldo[id].init_data;
|
||||
}
|
||||
|
||||
/*
|
||||
* At this point the GPIO descriptor is handled over to the
|
||||
* regulator core and we need not worry about it on the
|
||||
* error path.
|
||||
*/
|
||||
ldo->regulator = devm_regulator_register(&pdev->dev,
|
||||
&wm8994_ldo_desc[id],
|
||||
&config);
|
||||
@ -172,15 +184,12 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
|
||||
ret = PTR_ERR(ldo->regulator);
|
||||
dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
|
||||
id + 1, ret);
|
||||
goto err;
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, ldo);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct platform_driver wm8994_ldo_driver = {
|
||||
|
@ -90,6 +90,9 @@
|
||||
#define PIO_DATAOUT_1B 0x0020
|
||||
#define PIO_DATAOUT_4B 0x0024
|
||||
|
||||
#define RD_FIFO_CFG 0x0028
|
||||
#define CONTINUOUS_MODE BIT(0)
|
||||
|
||||
#define RD_FIFO_STATUS 0x002c
|
||||
#define FIFO_EMPTY BIT(11)
|
||||
#define WR_CNTS_MSK 0x7f0
|
||||
@ -99,9 +102,6 @@
|
||||
#define RDY_16BYTE BIT(1)
|
||||
#define FIFO_RDY BIT(0)
|
||||
|
||||
#define RD_FIFO_CFG 0x0028
|
||||
#define CONTINUOUS_MODE BIT(0)
|
||||
|
||||
#define RD_FIFO_RESET 0x0030
|
||||
#define RESET_FIFO BIT(0)
|
||||
|
||||
@ -139,7 +139,7 @@ struct qcom_qspi {
|
||||
struct device *dev;
|
||||
struct clk_bulk_data clks[QSPI_NUM_CLKS];
|
||||
struct qspi_xfer xfer;
|
||||
/* Lock to protect data accessed by IRQs */
|
||||
/* Lock to protect xfer and IRQ accessed registers */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
|
30
include/dt-bindings/regulator/active-semi,8945a-regulator.h
Normal file
30
include/dt-bindings/regulator/active-semi,8945a-regulator.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2018 Microchip Technology, Inc. All rights reserved.
|
||||
*
|
||||
* Device Tree binding constants for the ACT8945A PMIC regulators
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_REGULATOR_ACT8945A_H
|
||||
#define _DT_BINDINGS_REGULATOR_ACT8945A_H
|
||||
|
||||
/*
|
||||
* These constants should be used to specify regulator modes in device tree for
|
||||
* ACT8945A regulators as follows:
|
||||
* ACT8945A_REGULATOR_MODE_FIXED: It is specific to DCDC regulators and it
|
||||
* specifies the usage of fixed-frequency
|
||||
* PWM.
|
||||
*
|
||||
* ACT8945A_REGULATOR_MODE_NORMAL: It is specific to LDO regulators and it
|
||||
* specifies the usage of normal mode.
|
||||
*
|
||||
* ACT8945A_REGULATOR_MODE_LOWPOWER: For DCDC and LDO regulators; it specify
|
||||
* the usage of proprietary power-saving
|
||||
* mode.
|
||||
*/
|
||||
|
||||
#define ACT8945A_REGULATOR_MODE_FIXED 1
|
||||
#define ACT8945A_REGULATOR_MODE_NORMAL 2
|
||||
#define ACT8945A_REGULATOR_MODE_LOWPOWER 3
|
||||
|
||||
#endif
|
@ -104,6 +104,7 @@ struct gpio_descs *__must_check
|
||||
devm_gpiod_get_array_optional(struct device *dev, const char *con_id,
|
||||
enum gpiod_flags flags);
|
||||
void devm_gpiod_put(struct device *dev, struct gpio_desc *desc);
|
||||
void devm_gpiod_unhinge(struct device *dev, struct gpio_desc *desc);
|
||||
void devm_gpiod_put_array(struct device *dev, struct gpio_descs *descs);
|
||||
|
||||
int gpiod_get_direction(struct gpio_desc *desc);
|
||||
@ -172,6 +173,10 @@ int desc_to_gpio(const struct gpio_desc *desc);
|
||||
struct device_node;
|
||||
struct fwnode_handle;
|
||||
|
||||
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label);
|
||||
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
|
||||
struct device_node *node,
|
||||
const char *propname, int index,
|
||||
@ -245,6 +250,15 @@ static inline void gpiod_put(struct gpio_desc *desc)
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
static inline void devm_gpiod_unhinge(struct device *dev,
|
||||
struct gpio_desc *desc)
|
||||
{
|
||||
might_sleep();
|
||||
|
||||
/* GPIO can never have been requested */
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
static inline void gpiod_put_array(struct gpio_descs *descs)
|
||||
{
|
||||
might_sleep();
|
||||
@ -517,6 +531,15 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
|
||||
struct device_node;
|
||||
struct fwnode_handle;
|
||||
|
||||
static inline
|
||||
struct gpio_desc *gpiod_get_from_of_node(struct device_node *node,
|
||||
const char *propname, int index,
|
||||
enum gpiod_flags dflags,
|
||||
const char *label)
|
||||
{
|
||||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
|
||||
struct device_node *node,
|
||||
|
@ -35,7 +35,7 @@ enum axp20x_variants {
|
||||
#define AXP152_ALDO_OP_MODE 0x13
|
||||
#define AXP152_LDO0_CTRL 0x15
|
||||
#define AXP152_DCDC2_V_OUT 0x23
|
||||
#define AXP152_DCDC2_V_SCAL 0x25
|
||||
#define AXP152_DCDC2_V_RAMP 0x25
|
||||
#define AXP152_DCDC1_V_OUT 0x26
|
||||
#define AXP152_DCDC3_V_OUT 0x27
|
||||
#define AXP152_ALDO12_V_OUT 0x28
|
||||
@ -53,7 +53,7 @@ enum axp20x_variants {
|
||||
#define AXP20X_USB_OTG_STATUS 0x02
|
||||
#define AXP20X_PWR_OUT_CTRL 0x12
|
||||
#define AXP20X_DCDC2_V_OUT 0x23
|
||||
#define AXP20X_DCDC2_LDO3_V_SCAL 0x25
|
||||
#define AXP20X_DCDC2_LDO3_V_RAMP 0x25
|
||||
#define AXP20X_DCDC3_V_OUT 0x27
|
||||
#define AXP20X_LDO24_V_OUT 0x28
|
||||
#define AXP20X_LDO3_V_OUT 0x29
|
||||
|
@ -20,9 +20,6 @@
|
||||
#define WM8994_NUM_AIF 3
|
||||
|
||||
struct wm8994_ldo_pdata {
|
||||
/** GPIOs to enable regulator, 0 or less if not available */
|
||||
int enable;
|
||||
|
||||
const struct regulator_init_data *init_data;
|
||||
};
|
||||
|
||||
|
@ -508,7 +508,7 @@ static inline int regulator_get_error_flags(struct regulator *regulator,
|
||||
|
||||
static inline int regulator_set_load(struct regulator *regulator, int load_uA)
|
||||
{
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int regulator_allow_bypass(struct regulator *regulator,
|
||||
|
@ -15,11 +15,12 @@
|
||||
#ifndef __LINUX_REGULATOR_DRIVER_H_
|
||||
#define __LINUX_REGULATOR_DRIVER_H_
|
||||
|
||||
#define MAX_COUPLED 4
|
||||
#define MAX_COUPLED 2
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/ww_mutex.h>
|
||||
|
||||
struct gpio_desc;
|
||||
struct regmap;
|
||||
@ -462,7 +463,7 @@ struct regulator_dev {
|
||||
struct coupling_desc coupling_desc;
|
||||
|
||||
struct blocking_notifier_head notifier;
|
||||
struct mutex mutex; /* consumer lock */
|
||||
struct ww_mutex mutex; /* consumer lock */
|
||||
struct task_struct *mutex_owner;
|
||||
int ref_cnt;
|
||||
struct module *owner;
|
||||
@ -473,7 +474,6 @@ struct regulator_dev {
|
||||
struct regmap *regmap;
|
||||
|
||||
struct delayed_work disable_work;
|
||||
int deferred_disables;
|
||||
|
||||
void *reg_data; /* regulator_dev data */
|
||||
|
||||
@ -545,4 +545,7 @@ int regulator_set_active_discharge_regmap(struct regulator_dev *rdev,
|
||||
bool enable);
|
||||
void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
|
||||
|
||||
void regulator_lock(struct regulator_dev *rdev);
|
||||
void regulator_unlock(struct regulator_dev *rdev);
|
||||
|
||||
#endif
|
||||
|
@ -158,6 +158,9 @@ struct regulation_constraints {
|
||||
/* used for coupled regulators */
|
||||
int max_spread;
|
||||
|
||||
/* used for changing voltage in steps */
|
||||
int max_uV_step;
|
||||
|
||||
/* valid regulator operating modes for this machine */
|
||||
unsigned int valid_modes_mask;
|
||||
|
||||
|
@ -33,7 +33,8 @@
|
||||
#define PFUZE100_VGEN4 12
|
||||
#define PFUZE100_VGEN5 13
|
||||
#define PFUZE100_VGEN6 14
|
||||
#define PFUZE100_MAX_REGULATOR 15
|
||||
#define PFUZE100_COIN 15
|
||||
#define PFUZE100_MAX_REGULATOR 16
|
||||
|
||||
#define PFUZE200_SW1AB 0
|
||||
#define PFUZE200_SW2 1
|
||||
|
Loading…
Reference in New Issue
Block a user