regulator: Updates for v5.18
Quite a quiet release for the regulator API, mainly a few new drivers plus a lot of fixes for the Raspberry Pi panel driver. There's also a SPI commit in here which I managed to apply to the wrong tree and then didn't notice until there were too many commits on top of it, sorry about that. - Make it easier to use the virtual consumer test driver with DT systems. - Substantial overhaul providing various fixes and robustness improvements for the Raspberry Pi panel driver. - Support for Qualcomm PMX65 and SDX65, Richtek RT5190A, and Texas Instruments TPS62864x -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmI4bYcACgkQJNaLcl1U h9B0sQf+NvpOeni3N2z1vRS+b2k7r/qX0GU2X2Bs3FnulYRsLqGp9eg4dZvNCc1Z XhVVqSWZUvI9TEpG5RRuGmTkb/3cwYzURkL1P4EXMrSNCmImRgZ9aTfF7Dc3wNg8 UcomWtsVEHMGNmfvU7Kazk4fVGtb+I1/lYf1i/jjB21108Qzk59CDdhEjQl0DMuZ 3ZNu7YC5MQN6QbjmEMdn3mSNilVyn67WBsCVePi4ebSK/GFZXUtxOtRWAQYTtej8 t0XOd5Z5iGpszohmKi78CdZvA4NtugPoavLbvpd1pRA/9A0PgMZq5vkmJdwW5Nwe oMMMvJP1yBVLknl0pl7gTibdizoHzQ== =U2e/ -----END PGP SIGNATURE----- Merge tag 'regulator-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator Pull regulator updates from Mark Brown: "Quite a quiet release for the regulator API, mainly a few new drivers plus a lot of fixes for the Raspberry Pi panel driver. There's also a SPI commit in here which I managed to apply to the wrong tree and then didn't notice until there were too many commits on top of it, sorry about that. - Make it easier to use the virtual consumer test driver with DT systems. - Substantial overhaul providing various fixes and robustness improvements for the Raspberry Pi panel driver. - Support for Qualcomm PMX65 and SDX65, Richtek RT5190A, and Texas Instruments TPS62864x" * tag 'regulator-v5.18' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (26 commits) regulator: qcom-rpmh: Add support for SDX65 regulator: dt-bindings: Add PMX65 compatibles regulator: vctrl: Use min() instead of doing it manually regulator: rt5190a: Add support for Richtek RT5190A PMIC regulator: Add bindings for Richtek RT5190A PMIC regulator: Convert TPS62360 binding to json-schema regulator: cleanup comments regulator: virtual: add devicetree support regulator: virtual: warn against production use regulator: virtual: use dev_err_probe() regulator: tps62864: Fix bindings for SW property regulator: Add support for TPS6286x regulator: Add bindings for TPS62864x regulator/rpi-panel-attiny: Use two transactions for I2C read regulator/rpi-panel-attiny: Use the regmap cache regulator: rpi-panel: Remove get_brightness hook regulator: rpi-panel: Add GPIO control for panel and touch resets regulator: rpi-panel: Convert to drive lines directly regulator: rpi-panel: Ensure the backlight is off during probe. regulator: rpi-panel: Serialise operations. ...
This commit is contained in:
commit
d6ccf45113
|
@ -113,7 +113,7 @@ examples:
|
|||
};
|
||||
|
||||
- |
|
||||
#include <dt-bindings/gpio/tegra-gpio.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
|
||||
i2c {
|
||||
|
@ -123,8 +123,7 @@ examples:
|
|||
regulator@1b {
|
||||
compatible = "maxim,max77621";
|
||||
reg = <0x1b>;
|
||||
interrupt-parent = <&gpio>;
|
||||
interrupts = <TEGRA_GPIO(Y, 1) IRQ_TYPE_LEVEL_LOW>;
|
||||
interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
|
||||
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
|
|
|
@ -70,7 +70,11 @@ properties:
|
|||
$ref: "regulator.yaml#"
|
||||
type: object
|
||||
|
||||
"^(vsnvs|vref|vrefddr|swbst|coin)$":
|
||||
"^vldo[1-4]$":
|
||||
$ref: "regulator.yaml#"
|
||||
type: object
|
||||
|
||||
"^(vsnvs|vref|vrefddr|swbst|coin|v33|vccsd)$":
|
||||
$ref: "regulator.yaml#"
|
||||
type: object
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ description: |
|
|||
For PMI8998, bob
|
||||
For PMR735A, smps1 - smps3, ldo1 - ldo7
|
||||
For PMX55, smps1 - smps7, ldo1 - ldo16
|
||||
For PMX65, smps1 - smps8, ldo1 - ldo21
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
|
@ -70,6 +71,7 @@ properties:
|
|||
- qcom,pmm8155au-rpmh-regulators
|
||||
- qcom,pmr735a-rpmh-regulators
|
||||
- qcom,pmx55-rpmh-regulators
|
||||
- qcom,pmx65-rpmh-regulators
|
||||
|
||||
qcom,pmic-id:
|
||||
description: |
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/richtek,rt5190a-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Richtek RT5190A PMIC Regulator
|
||||
|
||||
maintainers:
|
||||
- ChiYuan Huang <cy_huang@richtek.com>
|
||||
|
||||
description: |
|
||||
The RT5190A integrates 1 channel buck controller, 3 channels high efficiency
|
||||
synchronous buck converters, 1 LDO, I2C control interface and peripherial
|
||||
logical control.
|
||||
|
||||
It also supports mute AC OFF depop sound and quick setting storage while
|
||||
input power is removed.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- richtek,rt5190a
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
vin2-supply:
|
||||
description: phandle to buck2 input voltage.
|
||||
|
||||
vin3-supply:
|
||||
description: phandle to buck3 input voltage.
|
||||
|
||||
vin4-supply:
|
||||
description: phandle to buck4 input voltage.
|
||||
|
||||
vinldo-supply:
|
||||
description: phandle to ldo input voltage
|
||||
|
||||
richtek,mute-enable:
|
||||
description: |
|
||||
The mute function uses 'mutein', 'muteout', and 'vdet' pins as the control
|
||||
signal. When enabled, The normal behavior is to bypass the 'mutein' signal
|
||||
'muteout'. But if the power source removal is detected from 'vdet',
|
||||
whatever the 'mutein' signal is, it will pull down the 'muteout' to force
|
||||
speakers mute. this function is commonly used to prevent the speaker pop
|
||||
noise during AC power turned off in the modern TV system design.
|
||||
type: boolean
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
|
||||
patternProperties:
|
||||
"^buck[1-4]$|^ldo$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
description: |
|
||||
regulator description for buck1 and buck4.
|
||||
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
description: |
|
||||
buck operating mode, only buck1/4 support mode operating.
|
||||
0: auto mode
|
||||
1: force pwm mode
|
||||
items:
|
||||
enum: [0, 1]
|
||||
|
||||
richtek,latchup-enable:
|
||||
type: boolean
|
||||
description: |
|
||||
If specified, undervolt protection mode changes from the default
|
||||
hiccup to latchup.
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- regulators
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/regulator/richtek,rt5190a-regulator.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@64 {
|
||||
compatible = "richtek,rt5190a";
|
||||
reg = <0x64>;
|
||||
interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;
|
||||
vin2-supply = <&rt5190_buck1>;
|
||||
vin3-supply = <&rt5190_buck1>;
|
||||
vin4-supply = <&rt5190_buck1>;
|
||||
|
||||
regulators {
|
||||
rt5190_buck1: buck1 {
|
||||
regulator-name = "rt5190a-buck1";
|
||||
regulator-min-microvolt = <5090000>;
|
||||
regulator-max-microvolt = <5090000>;
|
||||
regulator-allowed-modes = <RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
buck2 {
|
||||
regulator-name = "rt5190a-buck2";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
buck3 {
|
||||
regulator-name = "rt5190a-buck3";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
buck4 {
|
||||
regulator-name = "rt5190a-buck4";
|
||||
regulator-min-microvolt = <850000>;
|
||||
regulator-max-microvolt = <850000>;
|
||||
regulator-allowed-modes = <RT5190A_OPMODE_AUTO RT5190A_OPMODE_FPWM>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
ldo {
|
||||
regulator-name = "rt5190a-ldo";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1200000>;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,98 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/ti,tps62360.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Texas Instruments TPS6236x Voltage Regulators
|
||||
|
||||
maintainers:
|
||||
- Laxman Dewangan <ldewangan@nvidia.com>
|
||||
|
||||
description: |
|
||||
The TPS6236x are a family of step down dc-dc converter with
|
||||
an input voltage range of 2.5V to 5.5V. The devices provide
|
||||
up to 3A peak load current, and an output voltage range of
|
||||
0.77V to 1.4V (TPS62360/62) and 0.5V to 1.77V (TPS62361B/63).
|
||||
|
||||
Datasheet is available at:
|
||||
https://www.ti.com/lit/gpn/tps62360
|
||||
|
||||
allOf:
|
||||
- $ref: "regulator.yaml#"
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,tps62360
|
||||
- ti,tps62361
|
||||
- ti,tps62362
|
||||
- ti,tps62363
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
ti,vsel0-gpio:
|
||||
description: |
|
||||
GPIO for controlling VSEL0 line. If this property
|
||||
is missing, then assume that there is no GPIO for
|
||||
VSEL0 control.
|
||||
maxItems: 1
|
||||
|
||||
ti,vsel1-gpio:
|
||||
description: |
|
||||
GPIO for controlling VSEL1 line. If this property
|
||||
is missing, then assume that there is no GPIO for
|
||||
VSEL1 control.
|
||||
maxItems: 1
|
||||
|
||||
ti,enable-vout-discharge:
|
||||
description: Enable output discharge.
|
||||
type: boolean
|
||||
|
||||
ti,enable-pull-down:
|
||||
description: Enable pull down.
|
||||
type: boolean
|
||||
|
||||
ti,vsel0-state-high:
|
||||
description: |
|
||||
Initial state of VSEL0 input is high. If this property
|
||||
is missing, then assume the state as low.
|
||||
type: boolean
|
||||
|
||||
ti,vsel1-state-high:
|
||||
description: |
|
||||
Initial state of VSEL1 input is high. If this property
|
||||
is missing, then assume the state as low.
|
||||
type: boolean
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
regulator@60 {
|
||||
compatible = "ti,tps62361";
|
||||
reg = <0x60>;
|
||||
regulator-name = "tps62361-vout";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-boot-on;
|
||||
ti,vsel0-gpio = <&gpio1 16 GPIO_ACTIVE_HIGH>;
|
||||
ti,vsel1-gpio = <&gpio1 17 GPIO_ACTIVE_HIGH>;
|
||||
ti,vsel0-state-high;
|
||||
ti,vsel1-state-high;
|
||||
ti,enable-pull-down;
|
||||
ti,enable-vout-discharge;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -0,0 +1,63 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/ti,tps62864.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: TI TPS62864/TPS6286/TPS62868/TPS62869 voltage regulator
|
||||
|
||||
maintainers:
|
||||
- Vincent Whitchurch <vincent.whitchurch@axis.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- ti,tps62864
|
||||
- ti,tps62866
|
||||
- ti,tps62868
|
||||
- ti,tps62869
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
"SW":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- regulators
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/regulator/ti,tps62864.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
regulator@48 {
|
||||
compatible = "ti,tps62864";
|
||||
reg = <0x48>;
|
||||
|
||||
regulators {
|
||||
SW {
|
||||
regulator-name = "+0.85V";
|
||||
regulator-min-microvolt = <800000>;
|
||||
regulator-max-microvolt = <890000>;
|
||||
regulator-initial-mode = <TPS62864_MODE_FPWM>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -1,44 +0,0 @@
|
|||
TPS62360 Voltage regulators
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be one of the following.
|
||||
"ti,tps62360"
|
||||
"ti,tps62361",
|
||||
"ti,tps62362",
|
||||
"ti,tps62363",
|
||||
- reg: I2C slave address
|
||||
|
||||
Optional properties:
|
||||
- ti,enable-vout-discharge: Enable output discharge. This is boolean value.
|
||||
- ti,enable-pull-down: Enable pull down. This is boolean value.
|
||||
- ti,vsel0-gpio: GPIO for controlling VSEL0 line.
|
||||
If this property is missing, then assume that there is no GPIO
|
||||
for vsel0 control.
|
||||
- ti,vsel1-gpio: Gpio for controlling VSEL1 line.
|
||||
If this property is missing, then assume that there is no GPIO
|
||||
for vsel1 control.
|
||||
- ti,vsel0-state-high: Initial state of vsel0 input is high.
|
||||
If this property is missing, then assume the state as low (0).
|
||||
- ti,vsel1-state-high: Initial state of vsel1 input is high.
|
||||
If this property is missing, then assume the state as low (0).
|
||||
|
||||
Any property defined as part of the core regulator binding, defined in
|
||||
regulator.txt, can also be used.
|
||||
|
||||
Example:
|
||||
|
||||
abc: tps62360 {
|
||||
compatible = "ti,tps62361";
|
||||
reg = <0x60>;
|
||||
regulator-name = "tps62361-vout";
|
||||
regulator-min-microvolt = <500000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-boot-on
|
||||
ti,vsel0-gpio = <&gpio1 16 0>;
|
||||
ti,vsel1-gpio = <&gpio1 17 0>;
|
||||
ti,vsel0-state-high;
|
||||
ti,vsel1-state-high;
|
||||
ti,enable-pull-down;
|
||||
ti,enable-force-pwm;
|
||||
ti,enable-vout-discharge;
|
||||
};
|
|
@ -984,6 +984,7 @@ config REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY
|
|||
tristate "Raspberry Pi 7-inch touchscreen panel ATTINY regulator"
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
depends on I2C
|
||||
depends on OF_GPIO
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports ATTINY regulator on the Raspberry Pi 7-inch
|
||||
|
@ -1046,6 +1047,16 @@ config REGULATOR_RT5033
|
|||
RT5033 PMIC. The device supports multiple regulators like
|
||||
current source, LDO and Buck.
|
||||
|
||||
config REGULATOR_RT5190A
|
||||
tristate "Richtek RT5190A PMIC"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This adds support for voltage regulator in Richtek RT5190A PMIC.
|
||||
It integratas 1 channel buck controller, 3 channels high efficiency
|
||||
buck converters, 1 LDO, mute AC OFF depop function, with the general
|
||||
I2C control interface.
|
||||
|
||||
config REGULATOR_RT6160
|
||||
tristate "Richtek RT6160 BuckBoost voltage regulator"
|
||||
depends on I2C
|
||||
|
@ -1263,6 +1274,15 @@ config REGULATOR_TPS62360
|
|||
high-frequency synchronous step down dc-dc converter optimized
|
||||
for battery-powered portable applications.
|
||||
|
||||
config REGULATOR_TPS6286X
|
||||
tristate "TI TPS6286x Power Regulator"
|
||||
depends on I2C && OF
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports TPS6236x voltage regulator chips. These are
|
||||
high-frequency synchronous step-down converters with an I2C
|
||||
interface.
|
||||
|
||||
config REGULATOR_TPS65023
|
||||
tristate "TI TPS65023 Power regulators"
|
||||
depends on I2C
|
||||
|
|
|
@ -126,6 +126,7 @@ obj-$(CONFIG_REGULATOR_ROHM) += rohm-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_RT4801) += rt4801-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RT4831) += rt4831-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RT5190A) += rt5190a-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o
|
||||
|
@ -149,6 +150,7 @@ obj-$(CONFIG_REGULATOR_SY8827N) += sy8827n.o
|
|||
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6286X) += tps6286x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS65086) += tps65086-regulator.o
|
||||
|
|
|
@ -459,7 +459,7 @@ static int max8973_thermal_read_temp(void *data, int *temp)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* +1 degC to trigger cool devive */
|
||||
/* +1 degC to trigger cool device */
|
||||
if (val & MAX77621_CHIPID_TJINT_S)
|
||||
*temp = mchip->junction_temp_warning + 1000;
|
||||
else
|
||||
|
|
|
@ -1121,6 +1121,39 @@ static const struct rpmh_vreg_init_data pmx55_vreg_data[] = {
|
|||
{}
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_init_data pmx65_vreg_data[] = {
|
||||
RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"),
|
||||
RPMH_VREG("smps2", "smp%s2", &pmic5_hfsmps510, "vdd-s2"),
|
||||
RPMH_VREG("smps3", "smp%s3", &pmic5_hfsmps510, "vdd-s3"),
|
||||
RPMH_VREG("smps4", "smp%s4", &pmic5_hfsmps510, "vdd-s4"),
|
||||
RPMH_VREG("smps5", "smp%s5", &pmic5_hfsmps510, "vdd-s5"),
|
||||
RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"),
|
||||
RPMH_VREG("smps7", "smp%s7", &pmic5_hfsmps510, "vdd-s7"),
|
||||
RPMH_VREG("smps8", "smp%s8", &pmic5_hfsmps510, "vdd-s8"),
|
||||
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"),
|
||||
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l18"),
|
||||
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l3"),
|
||||
RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4"),
|
||||
RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l6-l16"),
|
||||
RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l5-l6-l16"),
|
||||
RPMH_VREG("ldo7", "ldo%s7", &pmic5_nldo, "vdd-l7"),
|
||||
RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l8-l9"),
|
||||
RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l8-l9"),
|
||||
RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l10"),
|
||||
RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l11-l13"),
|
||||
RPMH_VREG("ldo12", "ldo%s12", &pmic5_nldo, "vdd-l12"),
|
||||
RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l11-l13"),
|
||||
RPMH_VREG("ldo14", "ldo%s14", &pmic5_nldo, "vdd-l14"),
|
||||
RPMH_VREG("ldo15", "ldo%s15", &pmic5_nldo, "vdd-l15"),
|
||||
RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l5-l6-l16"),
|
||||
RPMH_VREG("ldo17", "ldo%s17", &pmic5_nldo, "vdd-l17"),
|
||||
/* ldo18 not configured */
|
||||
RPMH_VREG("ldo19", "ldo%s19", &pmic5_nldo, "vdd-l19"),
|
||||
RPMH_VREG("ldo20", "ldo%s20", &pmic5_nldo, "vdd-l20"),
|
||||
RPMH_VREG("ldo21", "ldo%s21", &pmic5_nldo, "vdd-l21"),
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_init_data pm7325_vreg_data[] = {
|
||||
RPMH_VREG("smps1", "smp%s1", &pmic5_hfsmps510, "vdd-s1"),
|
||||
RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps520, "vdd-s2"),
|
||||
|
@ -1276,6 +1309,10 @@ static const struct of_device_id __maybe_unused rpmh_regulator_match_table[] = {
|
|||
.compatible = "qcom,pmx55-rpmh-regulators",
|
||||
.data = pmx55_vreg_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,pmx65-rpmh-regulators",
|
||||
.data = pmx65_vreg_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,pm7325-rpmh-regulators",
|
||||
.data = pm7325_vreg_data,
|
||||
|
|
|
@ -1317,8 +1317,10 @@ static int rpm_reg_probe(struct platform_device *pdev)
|
|||
|
||||
for_each_available_child_of_node(dev->of_node, node) {
|
||||
vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
|
||||
if (!vreg)
|
||||
if (!vreg) {
|
||||
of_node_put(node);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = rpm_regulator_init_vreg(vreg, dev, node, rpm, vreg_data);
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/backlight.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
@ -21,63 +22,146 @@
|
|||
/* I2C registers of the Atmel microcontroller. */
|
||||
#define REG_ID 0x80
|
||||
#define REG_PORTA 0x81
|
||||
#define REG_PORTA_HF BIT(2)
|
||||
#define REG_PORTA_VF BIT(3)
|
||||
#define REG_PORTB 0x82
|
||||
#define REG_PORTC 0x83
|
||||
#define REG_POWERON 0x85
|
||||
#define REG_PWM 0x86
|
||||
#define REG_ADDR_L 0x8c
|
||||
#define REG_ADDR_H 0x8d
|
||||
#define REG_WRITE_DATA_H 0x90
|
||||
#define REG_WRITE_DATA_L 0x91
|
||||
|
||||
#define PA_LCD_DITHB BIT(0)
|
||||
#define PA_LCD_MODE BIT(1)
|
||||
#define PA_LCD_LR BIT(2)
|
||||
#define PA_LCD_UD BIT(3)
|
||||
|
||||
#define PB_BRIDGE_PWRDNX_N BIT(0)
|
||||
#define PB_LCD_VCC_N BIT(1)
|
||||
#define PB_LCD_MAIN BIT(7)
|
||||
|
||||
#define PC_LED_EN BIT(0)
|
||||
#define PC_RST_TP_N BIT(1)
|
||||
#define PC_RST_LCD_N BIT(2)
|
||||
#define PC_RST_BRIDGE_N BIT(3)
|
||||
|
||||
enum gpio_signals {
|
||||
RST_BRIDGE_N, /* TC358762 bridge reset */
|
||||
RST_TP_N, /* Touch controller reset */
|
||||
NUM_GPIO
|
||||
};
|
||||
|
||||
struct gpio_signal_mappings {
|
||||
unsigned int reg;
|
||||
unsigned int mask;
|
||||
};
|
||||
|
||||
static const struct gpio_signal_mappings mappings[NUM_GPIO] = {
|
||||
[RST_BRIDGE_N] = { REG_PORTC, PC_RST_BRIDGE_N | PC_RST_LCD_N },
|
||||
[RST_TP_N] = { REG_PORTC, PC_RST_TP_N },
|
||||
};
|
||||
|
||||
struct attiny_lcd {
|
||||
/* lock to serialise overall accesses to the Atmel */
|
||||
struct mutex lock;
|
||||
struct regmap *regmap;
|
||||
bool gpio_states[NUM_GPIO];
|
||||
u8 port_states[3];
|
||||
|
||||
struct gpio_chip gc;
|
||||
};
|
||||
|
||||
static const struct regmap_config attiny_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = REG_PWM,
|
||||
.cache_type = REGCACHE_NONE,
|
||||
.disable_locking = 1,
|
||||
.max_register = REG_WRITE_DATA_L,
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static int attiny_set_port_state(struct attiny_lcd *state, int reg, u8 val)
|
||||
{
|
||||
state->port_states[reg - REG_PORTA] = val;
|
||||
return regmap_write(state->regmap, reg, val);
|
||||
};
|
||||
|
||||
static u8 attiny_get_port_state(struct attiny_lcd *state, int reg)
|
||||
{
|
||||
return state->port_states[reg - REG_PORTA];
|
||||
};
|
||||
|
||||
static int attiny_lcd_power_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int data;
|
||||
struct attiny_lcd *state = rdev_get_drvdata(rdev);
|
||||
|
||||
regmap_write(rdev->regmap, REG_POWERON, 1);
|
||||
/* Wait for nPWRDWN to go low to indicate poweron is done. */
|
||||
regmap_read_poll_timeout(rdev->regmap, REG_PORTB, data,
|
||||
data & BIT(0), 10, 1000000);
|
||||
mutex_lock(&state->lock);
|
||||
|
||||
/* Ensure bridge, and tp stay in reset */
|
||||
attiny_set_port_state(state, REG_PORTC, 0);
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
/* Default to the same orientation as the closed source
|
||||
* firmware used for the panel. Runtime rotation
|
||||
* configuration will be supported using VC4's plane
|
||||
* orientation bits.
|
||||
*/
|
||||
regmap_write(rdev->regmap, REG_PORTA, BIT(2));
|
||||
attiny_set_port_state(state, REG_PORTA, PA_LCD_LR);
|
||||
usleep_range(5000, 10000);
|
||||
/* Main regulator on, and power to the panel (LCD_VCC_N) */
|
||||
attiny_set_port_state(state, REG_PORTB, PB_LCD_MAIN);
|
||||
usleep_range(5000, 10000);
|
||||
/* Bring controllers out of reset */
|
||||
attiny_set_port_state(state, REG_PORTC, PC_LED_EN);
|
||||
|
||||
msleep(80);
|
||||
|
||||
mutex_unlock(&state->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int attiny_lcd_power_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct attiny_lcd *state = rdev_get_drvdata(rdev);
|
||||
|
||||
mutex_lock(&state->lock);
|
||||
|
||||
regmap_write(rdev->regmap, REG_PWM, 0);
|
||||
regmap_write(rdev->regmap, REG_POWERON, 0);
|
||||
udelay(1);
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
attiny_set_port_state(state, REG_PORTA, 0);
|
||||
usleep_range(5000, 10000);
|
||||
attiny_set_port_state(state, REG_PORTB, PB_LCD_VCC_N);
|
||||
usleep_range(5000, 10000);
|
||||
attiny_set_port_state(state, REG_PORTC, 0);
|
||||
msleep(30);
|
||||
|
||||
mutex_unlock(&state->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int attiny_lcd_power_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct attiny_lcd *state = rdev_get_drvdata(rdev);
|
||||
unsigned int data;
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&state->lock);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
ret = regmap_read(rdev->regmap, REG_PORTC, &data);
|
||||
if (!ret)
|
||||
break;
|
||||
usleep_range(10000, 12000);
|
||||
}
|
||||
|
||||
mutex_unlock(&state->lock);
|
||||
|
||||
ret = regmap_read(rdev->regmap, REG_POWERON, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!(data & BIT(0)))
|
||||
return 0;
|
||||
|
||||
ret = regmap_read(rdev->regmap, REG_PORTB, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return data & BIT(0);
|
||||
return data & PC_RST_BRIDGE_N;
|
||||
}
|
||||
|
||||
static const struct regulator_init_data attiny_regulator_default = {
|
||||
|
@ -101,33 +185,104 @@ static const struct regulator_desc attiny_regulator = {
|
|||
|
||||
static int attiny_update_status(struct backlight_device *bl)
|
||||
{
|
||||
struct regmap *regmap = bl_get_data(bl);
|
||||
struct attiny_lcd *state = bl_get_data(bl);
|
||||
struct regmap *regmap = state->regmap;
|
||||
int brightness = bl->props.brightness;
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&state->lock);
|
||||
|
||||
if (bl->props.power != FB_BLANK_UNBLANK ||
|
||||
bl->props.fb_blank != FB_BLANK_UNBLANK)
|
||||
brightness = 0;
|
||||
|
||||
return regmap_write(regmap, REG_PWM, brightness);
|
||||
}
|
||||
for (i = 0; i < 10; i++) {
|
||||
ret = regmap_write(regmap, REG_PWM, brightness);
|
||||
if (!ret)
|
||||
break;
|
||||
}
|
||||
|
||||
static int attiny_get_brightness(struct backlight_device *bl)
|
||||
{
|
||||
struct regmap *regmap = bl_get_data(bl);
|
||||
int ret, brightness;
|
||||
mutex_unlock(&state->lock);
|
||||
|
||||
ret = regmap_read(regmap, REG_PWM, &brightness);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return brightness;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct backlight_ops attiny_bl = {
|
||||
.update_status = attiny_update_status,
|
||||
.get_brightness = attiny_get_brightness,
|
||||
};
|
||||
|
||||
static int attiny_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
|
||||
{
|
||||
return GPIO_LINE_DIRECTION_OUT;
|
||||
}
|
||||
|
||||
static void attiny_gpio_set(struct gpio_chip *gc, unsigned int off, int val)
|
||||
{
|
||||
struct attiny_lcd *state = gpiochip_get_data(gc);
|
||||
u8 last_val;
|
||||
|
||||
if (off >= NUM_GPIO)
|
||||
return;
|
||||
|
||||
mutex_lock(&state->lock);
|
||||
|
||||
last_val = attiny_get_port_state(state, mappings[off].reg);
|
||||
if (val)
|
||||
last_val |= mappings[off].mask;
|
||||
else
|
||||
last_val &= ~mappings[off].mask;
|
||||
|
||||
attiny_set_port_state(state, mappings[off].reg, last_val);
|
||||
|
||||
if (off == RST_BRIDGE_N && val) {
|
||||
usleep_range(5000, 8000);
|
||||
regmap_write(state->regmap, REG_ADDR_H, 0x04);
|
||||
usleep_range(5000, 8000);
|
||||
regmap_write(state->regmap, REG_ADDR_L, 0x7c);
|
||||
usleep_range(5000, 8000);
|
||||
regmap_write(state->regmap, REG_WRITE_DATA_H, 0x00);
|
||||
usleep_range(5000, 8000);
|
||||
regmap_write(state->regmap, REG_WRITE_DATA_L, 0x00);
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
mutex_unlock(&state->lock);
|
||||
}
|
||||
|
||||
static int attiny_i2c_read(struct i2c_client *client, u8 reg, unsigned int *buf)
|
||||
{
|
||||
struct i2c_msg msgs[1];
|
||||
u8 addr_buf[1] = { reg };
|
||||
u8 data_buf[1] = { 0, };
|
||||
int ret;
|
||||
|
||||
/* Write register address */
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = 0;
|
||||
msgs[0].len = ARRAY_SIZE(addr_buf);
|
||||
msgs[0].buf = addr_buf;
|
||||
|
||||
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret != ARRAY_SIZE(msgs))
|
||||
return -EIO;
|
||||
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
/* Read data from register */
|
||||
msgs[0].addr = client->addr;
|
||||
msgs[0].flags = I2C_M_RD;
|
||||
msgs[0].len = 1;
|
||||
msgs[0].buf = data_buf;
|
||||
|
||||
ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
|
||||
if (ret != ARRAY_SIZE(msgs))
|
||||
return -EIO;
|
||||
|
||||
*buf = data_buf[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* I2C driver interface functions
|
||||
*/
|
||||
|
@ -138,22 +293,30 @@ static int attiny_i2c_probe(struct i2c_client *i2c,
|
|||
struct regulator_config config = { };
|
||||
struct backlight_device *bl;
|
||||
struct regulator_dev *rdev;
|
||||
struct attiny_lcd *state;
|
||||
struct regmap *regmap;
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
state = devm_kzalloc(&i2c->dev, sizeof(*state), GFP_KERNEL);
|
||||
if (!state)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&state->lock);
|
||||
i2c_set_clientdata(i2c, state);
|
||||
|
||||
regmap = devm_regmap_init_i2c(i2c, &attiny_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret = regmap_read(regmap, REG_ID, &data);
|
||||
ret = attiny_i2c_read(i2c, REG_ID, &data);
|
||||
if (ret < 0) {
|
||||
dev_err(&i2c->dev, "Failed to read REG_ID reg: %d\n", ret);
|
||||
return ret;
|
||||
goto error;
|
||||
}
|
||||
|
||||
switch (data) {
|
||||
|
@ -162,34 +325,73 @@ static int attiny_i2c_probe(struct i2c_client *i2c,
|
|||
break;
|
||||
default:
|
||||
dev_err(&i2c->dev, "Unknown Atmel firmware revision: 0x%02x\n", data);
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto error;
|
||||
}
|
||||
|
||||
regmap_write(regmap, REG_POWERON, 0);
|
||||
mdelay(1);
|
||||
msleep(30);
|
||||
regmap_write(regmap, REG_PWM, 0);
|
||||
|
||||
config.dev = &i2c->dev;
|
||||
config.regmap = regmap;
|
||||
config.of_node = i2c->dev.of_node;
|
||||
config.init_data = &attiny_regulator_default;
|
||||
config.driver_data = state;
|
||||
|
||||
rdev = devm_regulator_register(&i2c->dev, &attiny_regulator, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&i2c->dev, "Failed to register ATTINY regulator\n");
|
||||
return PTR_ERR(rdev);
|
||||
ret = PTR_ERR(rdev);
|
||||
goto error;
|
||||
}
|
||||
|
||||
props.type = BACKLIGHT_RAW;
|
||||
props.max_brightness = 0xff;
|
||||
bl = devm_backlight_device_register(&i2c->dev,
|
||||
"7inch-touchscreen-panel-bl",
|
||||
&i2c->dev, regmap, &attiny_bl,
|
||||
|
||||
state->regmap = regmap;
|
||||
|
||||
bl = devm_backlight_device_register(&i2c->dev, dev_name(&i2c->dev),
|
||||
&i2c->dev, state, &attiny_bl,
|
||||
&props);
|
||||
if (IS_ERR(bl))
|
||||
return PTR_ERR(bl);
|
||||
if (IS_ERR(bl)) {
|
||||
ret = PTR_ERR(bl);
|
||||
goto error;
|
||||
}
|
||||
|
||||
bl->props.brightness = 0xff;
|
||||
|
||||
state->gc.parent = &i2c->dev;
|
||||
state->gc.label = i2c->name;
|
||||
state->gc.owner = THIS_MODULE;
|
||||
state->gc.of_node = i2c->dev.of_node;
|
||||
state->gc.base = -1;
|
||||
state->gc.ngpio = NUM_GPIO;
|
||||
|
||||
state->gc.set = attiny_gpio_set;
|
||||
state->gc.get_direction = attiny_gpio_get_direction;
|
||||
state->gc.can_sleep = true;
|
||||
|
||||
ret = devm_gpiochip_add_data(&i2c->dev, &state->gc, state);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "Failed to create gpiochip: %d\n", ret);
|
||||
goto error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
mutex_destroy(&state->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int attiny_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct attiny_lcd *state = i2c_get_clientdata(client);
|
||||
|
||||
mutex_destroy(&state->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -205,6 +407,7 @@ static struct i2c_driver attiny_regulator_driver = {
|
|||
.of_match_table = of_match_ptr(attiny_dt_ids),
|
||||
},
|
||||
.probe = attiny_i2c_probe,
|
||||
.remove = attiny_i2c_remove,
|
||||
};
|
||||
|
||||
module_i2c_driver(attiny_regulator_driver);
|
||||
|
|
|
@ -0,0 +1,513 @@
|
|||
// SPDX-License-Identifier: GPL-2.0+
|
||||
|
||||
#include <dt-bindings/regulator/richtek,rt5190a-regulator.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
#define RT5190A_REG_MANUFACTURE 0x00
|
||||
#define RT5190A_REG_BUCK2VSEL 0x04
|
||||
#define RT5190A_REG_BUCK3VSEL 0x05
|
||||
#define RT5190A_REG_DCDCCNTL 0x06
|
||||
#define RT5190A_REG_ENABLE 0x07
|
||||
#define RT5190A_REG_DISCHARGE 0x09
|
||||
#define RT5190A_REG_PROTMODE 0x0A
|
||||
#define RT5190A_REG_MUTECNTL 0x0B
|
||||
#define RT5190A_REG_PGSTAT 0x0F
|
||||
#define RT5190A_REG_OVINT 0x10
|
||||
#define RT5190A_REG_HOTDIEMASK 0x17
|
||||
|
||||
#define RT5190A_VSEL_MASK GENMASK(6, 0)
|
||||
#define RT5190A_RID_BITMASK(rid) BIT(rid + 1)
|
||||
#define RT5190A_BUCK1_DISCHG_MASK GENMASK(1, 0)
|
||||
#define RT5190A_BUCK1_DISCHG_ONVAL 0x01
|
||||
#define RT5190A_OVERVOLT_MASK GENMASK(7, 0)
|
||||
#define RT5190A_UNDERVOLT_MASK GENMASK(15, 8)
|
||||
#define RT5190A_CH234OT_MASK BIT(29)
|
||||
#define RT5190A_CHIPOT_MASK BIT(28)
|
||||
|
||||
#define RT5190A_BUCK23_MINUV 600000
|
||||
#define RT5190A_BUCK23_MAXUV 1400000
|
||||
#define RT5190A_BUCK23_STEPUV 10000
|
||||
#define RT5190A_BUCK23_STEPNUM ((1400000 - 600000) / 10000 + 1)
|
||||
|
||||
enum {
|
||||
RT5190A_IDX_BUCK1 = 0,
|
||||
RT5190A_IDX_BUCK2,
|
||||
RT5190A_IDX_BUCK3,
|
||||
RT5190A_IDX_BUCK4,
|
||||
RT5190A_IDX_LDO,
|
||||
RT5190A_MAX_IDX
|
||||
};
|
||||
|
||||
struct rt5190a_priv {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct regulator_desc rdesc[RT5190A_MAX_IDX];
|
||||
struct regulator_dev *rdev[RT5190A_MAX_IDX];
|
||||
};
|
||||
|
||||
static int rt5190a_get_error_flags(struct regulator_dev *rdev,
|
||||
unsigned int *flags)
|
||||
{
|
||||
struct regmap *regmap = rdev_get_regmap(rdev);
|
||||
int rid = rdev_get_id(rdev);
|
||||
unsigned int pgood_stat;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, RT5190A_REG_PGSTAT, &pgood_stat);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(pgood_stat & RT5190A_RID_BITMASK(rid)))
|
||||
*flags = REGULATOR_ERROR_FAIL;
|
||||
else
|
||||
*flags = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5190a_fixed_buck_set_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct regmap *regmap = rdev_get_regmap(rdev);
|
||||
int rid = rdev_get_id(rdev);
|
||||
unsigned int mask = RT5190A_RID_BITMASK(rid), val;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = mask;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = 0;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(regmap, RT5190A_REG_DCDCCNTL, mask, val);
|
||||
}
|
||||
|
||||
static unsigned int rt5190a_fixed_buck_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct regmap *regmap = rdev_get_regmap(rdev);
|
||||
int rid = rdev_get_id(rdev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, RT5190A_REG_DCDCCNTL, &val);
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Failed to get mode [%d]\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (val & RT5190A_RID_BITMASK(rid))
|
||||
return REGULATOR_MODE_FAST;
|
||||
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static const struct regulator_ops rt5190a_ranged_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_active_discharge = regulator_set_active_discharge_regmap,
|
||||
.get_error_flags = rt5190a_get_error_flags,
|
||||
};
|
||||
|
||||
static const struct regulator_ops rt5190a_fixed_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_active_discharge = regulator_set_active_discharge_regmap,
|
||||
.set_mode = rt5190a_fixed_buck_set_mode,
|
||||
.get_mode = rt5190a_fixed_buck_get_mode,
|
||||
.get_error_flags = rt5190a_get_error_flags,
|
||||
};
|
||||
|
||||
static const struct regulator_ops rt5190a_fixed_ldo_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_active_discharge = regulator_set_active_discharge_regmap,
|
||||
.get_error_flags = rt5190a_get_error_flags,
|
||||
};
|
||||
|
||||
static irqreturn_t rt5190a_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct rt5190a_priv *priv = data;
|
||||
__le32 raws;
|
||||
unsigned int events, fields;
|
||||
static const struct {
|
||||
unsigned int bitmask;
|
||||
unsigned int report;
|
||||
} event_tbl[] = {
|
||||
{ RT5190A_OVERVOLT_MASK, REGULATOR_ERROR_REGULATION_OUT },
|
||||
{ RT5190A_UNDERVOLT_MASK, REGULATOR_ERROR_UNDER_VOLTAGE }
|
||||
};
|
||||
int i, j, ret;
|
||||
|
||||
ret = regmap_raw_read(priv->regmap, RT5190A_REG_OVINT, &raws,
|
||||
sizeof(raws));
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to read events\n");
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
events = le32_to_cpu(raws);
|
||||
|
||||
ret = regmap_raw_write(priv->regmap, RT5190A_REG_OVINT, &raws,
|
||||
sizeof(raws));
|
||||
if (ret)
|
||||
dev_err(priv->dev, "Failed to write-clear events\n");
|
||||
|
||||
/* Handle OV,UV events */
|
||||
for (i = 0; i < ARRAY_SIZE(event_tbl); i++) {
|
||||
fields = events & event_tbl[i].bitmask;
|
||||
fields >>= ffs(event_tbl[i].bitmask) - 1;
|
||||
|
||||
for (j = 0; j < RT5190A_MAX_IDX; j++) {
|
||||
if (!(fields & RT5190A_RID_BITMASK(j)))
|
||||
continue;
|
||||
|
||||
regulator_notifier_call_chain(priv->rdev[j],
|
||||
event_tbl[i].report,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle CH234 OT event */
|
||||
if (events & RT5190A_CH234OT_MASK) {
|
||||
for (j = RT5190A_IDX_BUCK2; j < RT5190A_IDX_LDO; j++) {
|
||||
regulator_notifier_call_chain(priv->rdev[j],
|
||||
REGULATOR_ERROR_OVER_TEMP,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Warning if CHIP OT occur */
|
||||
if (events & RT5190A_CHIPOT_MASK)
|
||||
dev_warn(priv->dev, "CHIP overheat\n");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static unsigned int rt5190a_of_map_mode(unsigned int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case RT5190A_OPMODE_AUTO:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
case RT5190A_OPMODE_FPWM:
|
||||
return REGULATOR_MODE_FAST;
|
||||
default:
|
||||
return REGULATOR_MODE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static int rt5190a_of_parse_cb(struct rt5190a_priv *priv, int rid,
|
||||
struct of_regulator_match *match)
|
||||
{
|
||||
struct regulator_desc *desc = priv->rdesc + rid;
|
||||
struct regulator_init_data *init_data = match->init_data;
|
||||
struct device_node *np = match->of_node;
|
||||
bool latchup_enable;
|
||||
unsigned int mask = RT5190A_RID_BITMASK(rid), val;
|
||||
|
||||
switch (rid) {
|
||||
case RT5190A_IDX_BUCK1:
|
||||
case RT5190A_IDX_BUCK4:
|
||||
case RT5190A_IDX_LDO:
|
||||
init_data->constraints.apply_uV = 0;
|
||||
|
||||
if (init_data->constraints.min_uV ==
|
||||
init_data->constraints.max_uV)
|
||||
desc->fixed_uV = init_data->constraints.min_uV;
|
||||
else {
|
||||
dev_err(priv->dev,
|
||||
"Variable voltage for fixed regulator\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
latchup_enable = of_property_read_bool(np, "richtek,latchup-enable");
|
||||
|
||||
/* latchup: 0, default hiccup: 1 */
|
||||
val = !latchup_enable ? mask : 0;
|
||||
|
||||
return regmap_update_bits(priv->regmap, RT5190A_REG_PROTMODE, mask, val);
|
||||
}
|
||||
|
||||
static void rt5190a_fillin_regulator_desc(struct regulator_desc *desc, int rid)
|
||||
{
|
||||
static const char * const regu_name[] = { "buck1", "buck2",
|
||||
"buck3", "buck4",
|
||||
"ldo" };
|
||||
static const char * const supply[] = { NULL, "vin2", "vin3", "vin4",
|
||||
"vinldo" };
|
||||
|
||||
desc->name = regu_name[rid];
|
||||
desc->supply_name = supply[rid];
|
||||
desc->owner = THIS_MODULE;
|
||||
desc->type = REGULATOR_VOLTAGE;
|
||||
desc->id = rid;
|
||||
desc->enable_reg = RT5190A_REG_ENABLE;
|
||||
desc->enable_mask = RT5190A_RID_BITMASK(rid);
|
||||
desc->active_discharge_reg = RT5190A_REG_DISCHARGE;
|
||||
desc->active_discharge_mask = RT5190A_RID_BITMASK(rid);
|
||||
desc->active_discharge_on = RT5190A_RID_BITMASK(rid);
|
||||
|
||||
switch (rid) {
|
||||
case RT5190A_IDX_BUCK1:
|
||||
desc->active_discharge_mask = RT5190A_BUCK1_DISCHG_MASK;
|
||||
desc->active_discharge_on = RT5190A_BUCK1_DISCHG_ONVAL;
|
||||
desc->n_voltages = 1;
|
||||
desc->ops = &rt5190a_fixed_buck_ops;
|
||||
desc->of_map_mode = rt5190a_of_map_mode;
|
||||
break;
|
||||
case RT5190A_IDX_BUCK2:
|
||||
desc->vsel_reg = RT5190A_REG_BUCK2VSEL;
|
||||
desc->vsel_mask = RT5190A_VSEL_MASK;
|
||||
desc->min_uV = RT5190A_BUCK23_MINUV;
|
||||
desc->uV_step = RT5190A_BUCK23_STEPUV;
|
||||
desc->n_voltages = RT5190A_BUCK23_STEPNUM;
|
||||
desc->ops = &rt5190a_ranged_buck_ops;
|
||||
break;
|
||||
case RT5190A_IDX_BUCK3:
|
||||
desc->vsel_reg = RT5190A_REG_BUCK3VSEL;
|
||||
desc->vsel_mask = RT5190A_VSEL_MASK;
|
||||
desc->min_uV = RT5190A_BUCK23_MINUV;
|
||||
desc->uV_step = RT5190A_BUCK23_STEPUV;
|
||||
desc->n_voltages = RT5190A_BUCK23_STEPNUM;
|
||||
desc->ops = &rt5190a_ranged_buck_ops;
|
||||
break;
|
||||
case RT5190A_IDX_BUCK4:
|
||||
desc->n_voltages = 1;
|
||||
desc->ops = &rt5190a_fixed_buck_ops;
|
||||
desc->of_map_mode = rt5190a_of_map_mode;
|
||||
break;
|
||||
case RT5190A_IDX_LDO:
|
||||
desc->n_voltages = 1;
|
||||
desc->ops = &rt5190a_fixed_ldo_ops;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct of_regulator_match rt5190a_regulator_match[] = {
|
||||
{ .name = "buck1", },
|
||||
{ .name = "buck2", },
|
||||
{ .name = "buck3", },
|
||||
{ .name = "buck4", },
|
||||
{ .name = "ldo", }
|
||||
};
|
||||
|
||||
static int rt5190a_parse_regulator_dt_data(struct rt5190a_priv *priv)
|
||||
{
|
||||
struct device_node *regulator_np;
|
||||
struct regulator_desc *reg_desc;
|
||||
struct of_regulator_match *match;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < RT5190A_MAX_IDX; i++) {
|
||||
reg_desc = priv->rdesc + i;
|
||||
match = rt5190a_regulator_match + i;
|
||||
|
||||
rt5190a_fillin_regulator_desc(reg_desc, i);
|
||||
|
||||
match->desc = reg_desc;
|
||||
}
|
||||
|
||||
regulator_np = of_get_child_by_name(priv->dev->of_node, "regulators");
|
||||
if (!regulator_np) {
|
||||
dev_err(priv->dev, "Could not find 'regulators' node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = of_regulator_match(priv->dev, regulator_np,
|
||||
rt5190a_regulator_match,
|
||||
ARRAY_SIZE(rt5190a_regulator_match));
|
||||
|
||||
of_node_put(regulator_np);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(priv->dev,
|
||||
"Error parsing regulator init data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < RT5190A_MAX_IDX; i++) {
|
||||
match = rt5190a_regulator_match + i;
|
||||
|
||||
ret = rt5190a_of_parse_cb(priv, i, match);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed in [%d] of_parse_cb\n", i);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct reg_sequence rt5190a_init_patch[] = {
|
||||
{ 0x09, 0x3d, },
|
||||
{ 0x0a, 0x3e, },
|
||||
{ 0x0b, 0x01, },
|
||||
{ 0x10, 0xff, },
|
||||
{ 0x11, 0xff, },
|
||||
{ 0x12, 0xff, },
|
||||
{ 0x13, 0xff, },
|
||||
{ 0x14, 0, },
|
||||
{ 0x15, 0, },
|
||||
{ 0x16, 0x3e, },
|
||||
{ 0x17, 0, }
|
||||
};
|
||||
|
||||
static int rt5190a_device_initialize(struct rt5190a_priv *priv)
|
||||
{
|
||||
bool mute_enable;
|
||||
int ret;
|
||||
|
||||
ret = regmap_register_patch(priv->regmap, rt5190a_init_patch,
|
||||
ARRAY_SIZE(rt5190a_init_patch));
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to do register patch\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
mute_enable = device_property_read_bool(priv->dev,
|
||||
"richtek,mute-enable");
|
||||
|
||||
if (mute_enable) {
|
||||
ret = regmap_write(priv->regmap, RT5190A_REG_MUTECNTL, 0x00);
|
||||
if (ret) {
|
||||
dev_err(priv->dev, "Failed to enable mute function\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rt5190a_device_check(struct rt5190a_priv *priv)
|
||||
{
|
||||
u16 devid;
|
||||
int ret;
|
||||
|
||||
ret = regmap_raw_read(priv->regmap, RT5190A_REG_MANUFACTURE, &devid,
|
||||
sizeof(devid));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (devid) {
|
||||
dev_err(priv->dev, "Incorrect device id 0x%04x\n", devid);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct regmap_config rt5190a_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = RT5190A_REG_HOTDIEMASK,
|
||||
};
|
||||
|
||||
static int rt5190a_probe(struct i2c_client *i2c)
|
||||
{
|
||||
struct rt5190a_priv *priv;
|
||||
struct regulator_config cfg = {};
|
||||
int i, ret;
|
||||
|
||||
priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev = &i2c->dev;
|
||||
|
||||
priv->regmap = devm_regmap_init_i2c(i2c, &rt5190a_regmap_config);
|
||||
if (IS_ERR(priv->regmap)) {
|
||||
dev_err(&i2c->dev, "Failed to allocate regmap\n");
|
||||
return PTR_ERR(priv->regmap);
|
||||
}
|
||||
|
||||
ret = rt5190a_device_check(priv);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "Failed to check device %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rt5190a_device_initialize(priv);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "Failed to initialize the device\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = rt5190a_parse_regulator_dt_data(priv);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "Failed to parse regulator dt\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
cfg.dev = &i2c->dev;
|
||||
cfg.regmap = priv->regmap;
|
||||
|
||||
for (i = 0; i < RT5190A_MAX_IDX; i++) {
|
||||
struct regulator_desc *desc = priv->rdesc + i;
|
||||
struct of_regulator_match *match = rt5190a_regulator_match + i;
|
||||
|
||||
cfg.init_data = match->init_data;
|
||||
cfg.of_node = match->of_node;
|
||||
|
||||
priv->rdev[i] = devm_regulator_register(&i2c->dev, desc, &cfg);
|
||||
if (IS_ERR(priv->rdev[i])) {
|
||||
dev_err(&i2c->dev, "Failed to register regulator %s\n",
|
||||
desc->name);
|
||||
return PTR_ERR(priv->rdev[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (i2c->irq) {
|
||||
ret = devm_request_threaded_irq(&i2c->dev, i2c->irq, NULL,
|
||||
rt5190a_irq_handler,
|
||||
IRQF_ONESHOT,
|
||||
dev_name(&i2c->dev), priv);
|
||||
if (ret) {
|
||||
dev_err(&i2c->dev, "Failed to register interrupt\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id __maybe_unused rt5190a_device_table[] = {
|
||||
{ .compatible = "richtek,rt5190a", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rt5190a_device_table);
|
||||
|
||||
static struct i2c_driver rt5190a_driver = {
|
||||
.driver = {
|
||||
.name = "rt5190a",
|
||||
.of_match_table = rt5190a_device_table,
|
||||
},
|
||||
.probe_new = rt5190a_probe,
|
||||
};
|
||||
module_i2c_driver(rt5190a_driver);
|
||||
|
||||
MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
|
||||
MODULE_DESCRIPTION("Richtek RT5190A Regulator Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -1,4 +1,4 @@
|
|||
//SPDX-License-Identifier: GPL-2.0
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2017 Spreadtrum Communications Inc.
|
||||
*/
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
/**
|
||||
* struct ti_abb_info - ABB information per voltage setting
|
||||
* @opp_sel: one of TI_ABB macro
|
||||
* @vset: (optional) vset value that LDOVBB needs to be overriden with.
|
||||
* @vset: (optional) vset value that LDOVBB needs to be overridden with.
|
||||
*
|
||||
* Array of per voltage entries organized in the same order as regulator_desc's
|
||||
* volt_table list. (selector is used to index from this array)
|
||||
|
@ -484,7 +484,7 @@ static int ti_abb_init_timings(struct device *dev, struct ti_abb *abb)
|
|||
/* Calculate cycle rate */
|
||||
cycle_rate = DIV_ROUND_CLOSEST(clock_cycles * 10, clk_rate);
|
||||
|
||||
/* Calulate SR2_WTCNT_VALUE */
|
||||
/* Calculate SR2_WTCNT_VALUE */
|
||||
sr2_wt_cnt_val = DIV_ROUND_CLOSEST(abb->settling_time * 10, cycle_rate);
|
||||
|
||||
dev_dbg(dev, "%s: Clk_rate=%ld, sr2_cnt=0x%08x\n", __func__,
|
||||
|
@ -688,7 +688,7 @@ MODULE_DEVICE_TABLE(of, ti_abb_of_match);
|
|||
* @pdev: ABB platform device
|
||||
*
|
||||
* Initializes an individual ABB LDO for required Body-Bias. ABB is used to
|
||||
* addional bias supply to SoC modules for power savings or mandatory stability
|
||||
* additional bias supply to SoC modules for power savings or mandatory stability
|
||||
* configuration at certain Operating Performance Points(OPPs).
|
||||
*
|
||||
* Return: 0 on success or appropriate error value when fails
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright Axis Communications AB
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
|
||||
#include <dt-bindings/regulator/ti,tps62864.h>
|
||||
|
||||
#define TPS6286X_VOUT1 0x01
|
||||
#define TPS6286X_VOUT1_VO1_SET GENMASK(7, 0)
|
||||
|
||||
#define TPS6286X_CONTROL 0x03
|
||||
#define TPS6286X_CONTROL_FPWM BIT(4)
|
||||
#define TPS6286X_CONTROL_SWEN BIT(5)
|
||||
|
||||
#define TPS6286X_MIN_MV 400
|
||||
#define TPS6286X_MAX_MV 1675
|
||||
#define TPS6286X_STEP_MV 5
|
||||
|
||||
static const struct regmap_config tps6286x_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int tps6286x_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = 0;
|
||||
break;
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = TPS6286X_CONTROL_FPWM;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, TPS6286X_CONTROL,
|
||||
TPS6286X_CONTROL_FPWM, val);
|
||||
}
|
||||
|
||||
static unsigned int tps6286x_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, TPS6286X_CONTROL, &val);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
return (val & TPS6286X_CONTROL_FPWM) ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static const struct regulator_ops tps6286x_regulator_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.set_mode = tps6286x_set_mode,
|
||||
.get_mode = tps6286x_get_mode,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
};
|
||||
|
||||
static unsigned int tps6286x_of_map_mode(unsigned int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case TPS62864_MODE_NORMAL:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
case TPS62864_MODE_FPWM:
|
||||
return REGULATOR_MODE_FAST;
|
||||
default:
|
||||
return REGULATOR_MODE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct regulator_desc tps6286x_reg = {
|
||||
.name = "tps6286x",
|
||||
.of_match = of_match_ptr("SW"),
|
||||
.owner = THIS_MODULE,
|
||||
.ops = &tps6286x_regulator_ops,
|
||||
.of_map_mode = tps6286x_of_map_mode,
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.n_voltages = ((TPS6286X_MAX_MV - TPS6286X_MIN_MV) / TPS6286X_STEP_MV) + 1,
|
||||
.min_uV = TPS6286X_MIN_MV * 1000,
|
||||
.uV_step = TPS6286X_STEP_MV * 1000,
|
||||
.vsel_reg = TPS6286X_VOUT1,
|
||||
.vsel_mask = TPS6286X_VOUT1_VO1_SET,
|
||||
.enable_reg = TPS6286X_CONTROL,
|
||||
.enable_mask = TPS6286X_CONTROL_SWEN,
|
||||
.ramp_delay = 1000,
|
||||
/* tDelay + tRamp, rounded up */
|
||||
.enable_time = 3000,
|
||||
};
|
||||
|
||||
static const struct of_device_id tps6286x_dt_ids[] = {
|
||||
{ .compatible = "ti,tps62864", },
|
||||
{ .compatible = "ti,tps62866", },
|
||||
{ .compatible = "ti,tps62868", },
|
||||
{ .compatible = "ti,tps62869", },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, tps6286x_dt_ids);
|
||||
|
||||
static int tps6286x_i2c_probe(struct i2c_client *i2c,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &i2c->dev;
|
||||
struct regulator_config config = {};
|
||||
struct regulator_dev *rdev;
|
||||
struct regmap *regmap;
|
||||
|
||||
regmap = devm_regmap_init_i2c(i2c, &tps6286x_regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
config.dev = &i2c->dev;
|
||||
config.of_node = dev->of_node;
|
||||
config.regmap = regmap;
|
||||
|
||||
rdev = devm_regulator_register(&i2c->dev, &tps6286x_reg, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&i2c->dev, "Failed to register tps6286x regulator\n");
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id tps6286x_i2c_id[] = {
|
||||
{ "tps62864", 0 },
|
||||
{ "tps62866", 0 },
|
||||
{ "tps62868", 0 },
|
||||
{ "tps62869", 0 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, tps6286x_i2c_id);
|
||||
|
||||
static struct i2c_driver tps6286x_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "tps6286x",
|
||||
.of_match_table = of_match_ptr(tps6286x_dt_ids),
|
||||
},
|
||||
.probe = tps6286x_i2c_probe,
|
||||
.id_table = tps6286x_i2c_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(tps6286x_regulator_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -185,10 +185,7 @@ static int vctrl_set_voltage_sel(struct regulator_dev *rdev,
|
|||
unsigned int next_sel;
|
||||
int delay;
|
||||
|
||||
if (selector >= vctrl->vtable[vctrl->sel].ovp_min_sel)
|
||||
next_sel = selector;
|
||||
else
|
||||
next_sel = vctrl->vtable[vctrl->sel].ovp_min_sel;
|
||||
next_sel = max_t(unsigned int, selector, vctrl->vtable[vctrl->sel].ovp_min_sel);
|
||||
|
||||
ret = regulator_set_voltage_rdev(rdev->supply->rdev,
|
||||
vctrl->vtable[next_sel].ctrl,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
struct virtual_consumer_data {
|
||||
struct mutex lock;
|
||||
|
@ -281,26 +282,53 @@ static const struct attribute_group regulator_virtual_attr_group = {
|
|||
.attrs = regulator_virtual_attributes,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id regulator_virtual_consumer_of_match[] = {
|
||||
{ .compatible = "regulator-virtual-consumer" },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, regulator_virtual_consumer_of_match);
|
||||
#endif
|
||||
|
||||
static int regulator_virtual_probe(struct platform_device *pdev)
|
||||
{
|
||||
char *reg_id = dev_get_platdata(&pdev->dev);
|
||||
struct virtual_consumer_data *drvdata;
|
||||
static bool warned;
|
||||
int ret;
|
||||
|
||||
if (!warned) {
|
||||
warned = true;
|
||||
pr_warn("**********************************************************\n");
|
||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** regulator-virtual-consumer is only for testing and **\n");
|
||||
pr_warn("** debugging. Do not use it in a production kernel. **\n");
|
||||
pr_warn("** **\n");
|
||||
pr_warn("** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE **\n");
|
||||
pr_warn("**********************************************************\n");
|
||||
}
|
||||
|
||||
drvdata = devm_kzalloc(&pdev->dev, sizeof(struct virtual_consumer_data),
|
||||
GFP_KERNEL);
|
||||
if (drvdata == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* This virtual consumer does not have any hardware-defined supply
|
||||
* name, so just allow the regulator to be specified in a property
|
||||
* named "default-supply" when we're being probed from devicetree.
|
||||
*/
|
||||
if (!reg_id && pdev->dev.of_node)
|
||||
reg_id = "default";
|
||||
|
||||
mutex_init(&drvdata->lock);
|
||||
|
||||
drvdata->regulator = devm_regulator_get(&pdev->dev, reg_id);
|
||||
if (IS_ERR(drvdata->regulator)) {
|
||||
ret = PTR_ERR(drvdata->regulator);
|
||||
dev_err(&pdev->dev, "Failed to obtain supply '%s': %d\n",
|
||||
reg_id, ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(drvdata->regulator))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(drvdata->regulator),
|
||||
"Failed to obtain supply '%s'\n",
|
||||
reg_id);
|
||||
|
||||
ret = sysfs_create_group(&pdev->dev.kobj,
|
||||
®ulator_virtual_attr_group);
|
||||
|
@ -334,6 +362,7 @@ static struct platform_driver regulator_virtual_consumer_driver = {
|
|||
.remove = regulator_virtual_remove,
|
||||
.driver = {
|
||||
.name = "reg-virt-consumer",
|
||||
.of_match_table = of_match_ptr(regulator_virtual_consumer_of_match),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -1112,7 +1112,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
|
|||
if (pdev->id < WM8350_DCDC_1 || pdev->id > WM8350_ISINK_B)
|
||||
return -ENODEV;
|
||||
|
||||
/* do any regulatior specific init */
|
||||
/* do any regulator specific init */
|
||||
switch (pdev->id) {
|
||||
case WM8350_DCDC_1:
|
||||
val = wm8350_reg_read(wm8350, WM8350_DCDC1_LOW_POWER);
|
||||
|
|
|
@ -898,11 +898,8 @@ static int spi_geni_probe(struct platform_device *pdev)
|
|||
return irq;
|
||||
|
||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
|
||||
if (ret) {
|
||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "could not set DMA mask\n");
|
||||
}
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret, "could not set DMA mask\n");
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(base))
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __DT_BINDINGS_RICHTEK_RT5190A_REGULATOR_H__
|
||||
#define __DT_BINDINGS_RICHTEK_RT5190A_REGULATOR_H__
|
||||
|
||||
/*
|
||||
* BUCK/LDO mode constants which may be used in devicetree properties
|
||||
* (eg. regulator-allowed-modes).
|
||||
* See the manufacturer's datasheet for more information on these modes.
|
||||
*/
|
||||
|
||||
#define RT5190A_OPMODE_AUTO 0
|
||||
#define RT5190A_OPMODE_FPWM 1
|
||||
|
||||
#endif
|
|
@ -0,0 +1,9 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
|
||||
|
||||
#ifndef _DT_BINDINGS_REGULATOR_TI_TPS62864_H
|
||||
#define _DT_BINDINGS_REGULATOR_TI_TPS62864_H
|
||||
|
||||
#define TPS62864_MODE_NORMAL 0
|
||||
#define TPS62864_MODE_FPWM 1
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue