mirror of https://github.com/torvalds/linux.git
regulator: Updates for v6.19
This is a relatively busy release for the regulator API, as well as a
good collection of new drivers we've got a little bit of core work and a
bunch of cleanup throughout the subsystem:
- Support for propagating undervoltage events to child regulators.
- Undo enables done on supplies when setting enabling regulators via
constraints fails.
- Pull in some gpiolib changes adding support for shared GPIOs to
the gpiolib core, using them to replace the open coded variant of this
that we've had in the regulator API for a long time.
- Support for Fitipower FP9931 and JD9330, Mediatek MT6316, MT6363 and
MT6373, NXP PF1550 and Qualcomm PMH01XX and PMCX0102
The PF1550 support was originally going to go via the MFD tree but
Krzysztof's cleanup work overlapped with it so I pulled in Lee's signed
tag with support for the device.
-----BEGIN PGP SIGNATURE-----
iQEzBAABCgAdFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAmkt72UACgkQJNaLcl1U
h9Dm2wf+JhjBLxviOozOhSv17wKnCYpApL12vPIHhv3lGu4J9wPiqqe3eB6PrTPo
xkuIb8u68wOveh7uLgr/kprH/YUxofrkCEwZjy57geSanuqIEzVoqU//4NKca9ND
UeoDiTYLx5JQVzlo12tSFhLCvDsFgdnemWFfubRPQGTJA/RElMxrNySf3yUQbYBE
ODpTGbXqt4LnYQTJRvVM8/0KzREpxD0X8fSISKpA3KYBFntMexZcgrs5pqijwfMS
Euxff2UpFzjodmYEusWfKOFeZXmd/cClF26Tol7oaeaurr1pNu1i0nBUprbd/rzL
YTV8QeiftLqER/h2iDX4f8iTmvVhzA==
=9IkF
-----END PGP SIGNATURE-----
Merge tag 'regulator-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown:
"This is a relatively busy release for the regulator API, as well as a
good collection of new drivers we've got a little bit of core work and
a bunch of cleanup throughout the subsystem:
- Support for propagating undervoltage events to child regulators
- Undo enables done on supplies when setting enabling regulators via
constraints fails
- Pull in some gpiolib changes adding support for shared GPIOs to the
gpiolib core, using them to replace the open coded variant of this
that we've had in the regulator API for a long time
- Support for Fitipower FP9931 and JD9330, Mediatek MT6316, MT6363
and MT6373, NXP PF1550 and Qualcomm PMH01XX and PMCX0102
The PF1550 support was originally going to go via the MFD tree but
Krzysztof's cleanup work overlapped with it so I pulled in Lee's
signed tag with support for the device"
* tag 'regulator-v6.19' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (50 commits)
regulator: fp9931: Fix spelling mistake "failid" -> "failed"
regulator: core: Protect regulator_supply_alias_list with regulator_list_mutex
regulator: pf9453: Constify pointers to 'regulator_desc' wrap struct
regulator: pca9450: Constify pointers to 'regulator_desc' wrap struct
regulator: mt6358: Constify pointers to 'regulator_desc' wrap struct
regulator: bd96801: Constify pointers to 'regulator_desc' wrap struct
regulator: bd718x7: Constify pointers to 'regulator_desc' wrap struct
regulator: bd71828: Constify pointers to 'regulator_desc' wrap struct
regulator: bd71815: Constify pointers to 'regulator_desc' wrap struct
regulator: Use container_of_const() when all types are const
regulator: pca9450: Fix error code in probe()
regulator: qcomm-labibb: replace use of system_wq with system_dfl_wq
regulator: Add FP9931/JD9930 driver
dt-bindings: regulator: Add Fitipower FP9931/JD9930
dt-bindings: vendor-prefixes: Add Fitipower
regulator: make the subsystem aware of shared GPIOs
regulator: renesas-usb-vbus-regulator: Remove unused headers
regulator: pca9450: Add support for setting debounce settings
regulator: dt-bindings: pca9540: add debounce timer configuration
regulator: core: disable supply if enabling main regulator fails
...
This commit is contained in:
commit
0a9431fa74
|
|
@ -0,0 +1,161 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/mfd/nxp,pf1550.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: NXP PF1550 Power Management IC
|
||||
|
||||
maintainers:
|
||||
- Samuel Kayode <samuel.kayode@savoirfairelinux.com>
|
||||
|
||||
description:
|
||||
PF1550 PMIC provides battery charging and power supply for low power IoT and
|
||||
wearable applications. This device consists of an i2c controlled MFD that
|
||||
includes regulators, battery charging and an onkey/power button.
|
||||
|
||||
$ref: /schemas/power/supply/power-supply.yaml
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: nxp,pf1550
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
wakeup-source: true
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^(ldo[1-3]|sw[1-3]|vrefddr)$":
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml
|
||||
description:
|
||||
regulator configuration for ldo1-3, buck converters(sw1-3)
|
||||
and DDR termination reference voltage (vrefddr)
|
||||
unevaluatedProperties: false
|
||||
|
||||
monitored-battery:
|
||||
description: |
|
||||
A phandle to a monitored battery node that contains a valid value
|
||||
for:
|
||||
constant-charge-voltage-max-microvolt.
|
||||
|
||||
nxp,thermal-regulation-celsius:
|
||||
description:
|
||||
Temperature threshold for thermal regulation of charger in celsius.
|
||||
enum: [ 80, 95, 110, 125 ]
|
||||
|
||||
nxp,min-system-microvolt:
|
||||
description:
|
||||
System specific lower limit voltage.
|
||||
enum: [ 3500000, 3700000, 4300000 ]
|
||||
|
||||
nxp,disable-key-power:
|
||||
type: boolean
|
||||
description:
|
||||
Disable power-down using a long key-press. The onkey driver will remove
|
||||
support for the KEY_POWER key press when triggered using a long press of
|
||||
the onkey.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/interrupt-controller/irq.h>
|
||||
#include <dt-bindings/input/linux-event-codes.h>
|
||||
|
||||
battery: battery-cell {
|
||||
compatible = "simple-battery";
|
||||
constant-charge-voltage-max-microvolt = <4400000>;
|
||||
};
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@8 {
|
||||
compatible = "nxp,pf1550";
|
||||
reg = <0x8>;
|
||||
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
|
||||
wakeup-source;
|
||||
monitored-battery = <&battery>;
|
||||
nxp,min-system-microvolt = <4300000>;
|
||||
nxp,thermal-regulation-celsius = <80>;
|
||||
|
||||
regulators {
|
||||
sw1_reg: sw1 {
|
||||
regulator-name = "sw1";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1387500>;
|
||||
regulator-always-on;
|
||||
regulator-ramp-delay = <6250>;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-min-microvolt = <1270000>;
|
||||
};
|
||||
};
|
||||
|
||||
sw2_reg: sw2 {
|
||||
regulator-name = "sw2";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1387500>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
sw3_reg: sw3 {
|
||||
regulator-name = "sw3";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vldo1_reg: ldo1 {
|
||||
regulator-name = "ldo1";
|
||||
regulator-min-microvolt = <750000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vldo2_reg: ldo2 {
|
||||
regulator-name = "ldo2";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
vldo3_reg: ldo3 {
|
||||
regulator-name = "ldo3";
|
||||
regulator-min-microvolt = <750000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -1,205 +0,0 @@
|
|||
* Dialog Semiconductor DA9211/DA9212/DA9213/DA9223/DA9214/DA9224/DA9215/DA9225
|
||||
Voltage Regulator
|
||||
|
||||
Required properties:
|
||||
- compatible: "dlg,da9211" or "dlg,da9212" or "dlg,da9213" or "dlg,da9223"
|
||||
or "dlg,da9214" or "dlg,da9224" or "dlg,da9215" or "dlg,da9225"
|
||||
- reg: I2C slave address, usually 0x68.
|
||||
- interrupts: the interrupt outputs of the controller
|
||||
- regulators: A node that houses a sub-node for each regulator within the
|
||||
device. Each sub-node is identified using the node's name, with valid
|
||||
values listed below. The content of each sub-node is defined by the
|
||||
standard binding for regulators; see regulator.txt.
|
||||
BUCKA and BUCKB.
|
||||
|
||||
Optional properties:
|
||||
- enable-gpios: platform gpio for control of BUCKA/BUCKB.
|
||||
- Any optional property defined in regulator.txt
|
||||
- regulator-initial-mode and regulator-allowed-modes may be specified using
|
||||
mode values from dt-bindings/regulator/dlg,da9211-regulator.h
|
||||
|
||||
Example 1) DA9211
|
||||
pmic: da9211@68 {
|
||||
compatible = "dlg,da9211";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <2000000>;
|
||||
regulator-max-microamp = <5000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
regulator-allowed-modes = <DA9211_BUCK_MODE_SYNC
|
||||
DA9211_BUCK_MODE_AUTO>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 2) DA9212
|
||||
pmic: da9212@68 {
|
||||
compatible = "dlg,da9212";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <2000000>;
|
||||
regulator-max-microamp = <5000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
};
|
||||
BUCKB {
|
||||
regulator-name = "VBUCKB";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <2000000>;
|
||||
regulator-max-microamp = <5000000>;
|
||||
enable-gpios = <&gpio 17 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 3) DA9213
|
||||
pmic: da9213@68 {
|
||||
compatible = "dlg,da9213";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <3000000>;
|
||||
regulator-max-microamp = <6000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 4) DA9223
|
||||
pmic: da9223@68 {
|
||||
compatible = "dlg,da9223";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <3000000>;
|
||||
regulator-max-microamp = <6000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 5) DA9214
|
||||
pmic: da9214@68 {
|
||||
compatible = "dlg,da9214";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <3000000>;
|
||||
regulator-max-microamp = <6000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
};
|
||||
BUCKB {
|
||||
regulator-name = "VBUCKB";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <3000000>;
|
||||
regulator-max-microamp = <6000000>;
|
||||
enable-gpios = <&gpio 17 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 6) DA9224
|
||||
pmic: da9224@68 {
|
||||
compatible = "dlg,da9224";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <3000000>;
|
||||
regulator-max-microamp = <6000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
};
|
||||
BUCKB {
|
||||
regulator-name = "VBUCKB";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <3000000>;
|
||||
regulator-max-microamp = <6000000>;
|
||||
enable-gpios = <&gpio 17 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 7) DA9215
|
||||
pmic: da9215@68 {
|
||||
compatible = "dlg,da9215";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <4000000>;
|
||||
regulator-max-microamp = <7000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
};
|
||||
BUCKB {
|
||||
regulator-name = "VBUCKB";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <4000000>;
|
||||
regulator-max-microamp = <7000000>;
|
||||
enable-gpios = <&gpio 17 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 8) DA9225
|
||||
pmic: da9225@68 {
|
||||
compatible = "dlg,da9225";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <4000000>;
|
||||
regulator-max-microamp = <7000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
};
|
||||
BUCKB {
|
||||
regulator-name = "VBUCKB";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <4000000>;
|
||||
regulator-max-microamp = <7000000>;
|
||||
enable-gpios = <&gpio 17 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/dlg,da9211.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title:
|
||||
Dialog Semiconductor DA9211-9215, DA9223-9225 Voltage Regulators
|
||||
|
||||
maintainers:
|
||||
- Ariel D'Alessandro <ariel.dalessandro@collabora.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- dlg,da9211
|
||||
- dlg,da9212
|
||||
- dlg,da9213
|
||||
- dlg,da9214
|
||||
- dlg,da9215
|
||||
- dlg,da9223
|
||||
- dlg,da9224
|
||||
- dlg,da9225
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description:
|
||||
List of regulators provided by the device
|
||||
|
||||
patternProperties:
|
||||
"^BUCK([AB])$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
Properties for a single BUCK regulator
|
||||
|
||||
properties:
|
||||
regulator-initial-mode:
|
||||
items:
|
||||
enum: [ 1, 2, 3 ]
|
||||
description:
|
||||
Defined in include/dt-bindings/regulator/dlg,da9211-regulator.h
|
||||
|
||||
regulator-allowed-modes:
|
||||
items:
|
||||
enum: [ 1, 2, 3 ]
|
||||
description:
|
||||
Defined in include/dt-bindings/regulator/dlg,da9211-regulator.h
|
||||
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- regulators
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/regulator/dlg,da9211-regulator.h>
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
regulator@68 {
|
||||
compatible = "dlg,da9212";
|
||||
reg = <0x68>;
|
||||
interrupts = <3 27>;
|
||||
|
||||
regulators {
|
||||
BUCKA {
|
||||
regulator-name = "VBUCKA";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <2000000>;
|
||||
regulator-max-microamp = <5000000>;
|
||||
enable-gpios = <&gpio 27 0>;
|
||||
};
|
||||
BUCKB {
|
||||
regulator-name = "VBUCKB";
|
||||
regulator-min-microvolt = < 300000>;
|
||||
regulator-max-microvolt = <1570000>;
|
||||
regulator-min-microamp = <2000000>;
|
||||
regulator-max-microamp = <5000000>;
|
||||
enable-gpios = <&gpio 17 0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/fitipower,fp9931.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: FitiPower FP9931/JD9930 Power Management Integrated Circuit
|
||||
|
||||
maintainers:
|
||||
- Andreas Kemnade <andreas@kemnade.info>
|
||||
|
||||
description:
|
||||
FP9931 is a Power Management IC to provide Power for EPDs with one 3.3V
|
||||
switch, 2 symmetric LDOs behind 2 DC/DC converters, and one unsymmetric
|
||||
regulator for a compensation voltage.
|
||||
JD9930 has in addition some kind of night mode.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- const: fitipower,fp9931
|
||||
|
||||
- items:
|
||||
- const: fitipower,jd9930
|
||||
- const: fitipower,fp9931
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
enable-gpios:
|
||||
maxItems: 1
|
||||
|
||||
pg-gpios:
|
||||
maxItems: 1
|
||||
|
||||
en-ts-gpios:
|
||||
maxItems: 1
|
||||
|
||||
xon-gpios:
|
||||
maxItems: 1
|
||||
|
||||
vin-supply:
|
||||
description:
|
||||
Supply for the whole chip. Some vendor kernels and devicetrees
|
||||
declare this as a non-existing GPIO named "pwrall".
|
||||
|
||||
fitipower,tdly-ms:
|
||||
description:
|
||||
Power up soft start delay settings tDLY1-4 bitfields in the
|
||||
POWERON_DELAY register
|
||||
items:
|
||||
- enum: [0, 1, 2, 4]
|
||||
- enum: [0, 1, 2, 4]
|
||||
- enum: [0, 1, 2, 4]
|
||||
- enum: [0, 1, 2, 4]
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
patternProperties:
|
||||
"^(vcom|vposneg|v3p3)$":
|
||||
unevaluatedProperties: false
|
||||
type: object
|
||||
$ref: /schemas/regulator/regulator.yaml
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- pg-gpios
|
||||
- enable-gpios
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@18 {
|
||||
compatible = "fitipower,fp9931";
|
||||
reg = <0x18>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pinctrl_fp9931_gpio>;
|
||||
vin-supply = <&epd_pmic_supply>;
|
||||
pg-gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>;
|
||||
en-ts-gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>;
|
||||
enable-gpios = <&gpio2 8 GPIO_ACTIVE_HIGH>;
|
||||
fitipower,tdly-ms = <2 2 4 4>;
|
||||
|
||||
regulators {
|
||||
vcom {
|
||||
regulator-name = "vcom";
|
||||
regulator-min-microvolt = <2352840>;
|
||||
regulator-max-microvolt = <2352840>;
|
||||
};
|
||||
|
||||
vposneg {
|
||||
regulator-name = "vposneg";
|
||||
regulator-min-microvolt = <15060000>;
|
||||
regulator-max-microvolt = <15060000>;
|
||||
};
|
||||
|
||||
v3p3 {
|
||||
regulator-name = "v3p3";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/mediatek,mt6316b-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT6316 BP/VP SPMI PMIC Regulators
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
|
||||
description:
|
||||
The MediaTek MT6316BP/VP PMICs are fully controlled by SPMI interface, both
|
||||
feature four step-down DC/DC (buck) converters, and provides 2+2 Phases,
|
||||
joining Buck 1+2 for the first phase, and Buck 3+4 for the second phase.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6316b-regulator
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^vbuck(12|34)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
description: |
|
||||
Allowed Buck regulator operating modes allowed. Valid values below.
|
||||
0 - Normal mode with automatic power saving, reducing the switching
|
||||
frequency when light load conditions are detected
|
||||
1 - Forced Continuous Conduction mode (FCCM) for improved voltage
|
||||
regulation accuracy with constant switching frequency but lower
|
||||
regulator efficiency
|
||||
2 - Forced Low Power mode for improved regulator efficiency, used
|
||||
when no heavy load is expected, will shut down unnecessary IP
|
||||
blocks and secondary phases to reduce quiescent current.
|
||||
This mode does not limit the maximum output current but unless
|
||||
only a light load is applied, there will be regulation accuracy
|
||||
and efficiency losses.
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
items:
|
||||
enum: [ 0, 1, 2 ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
spmi {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@8 {
|
||||
compatible = "mediatek,mt6316b-regulator";
|
||||
reg = <0x8 SPMI_USID>;
|
||||
|
||||
vbuck12 {
|
||||
regulator-name = "dvdd_core";
|
||||
regulator-min-microvolt = <450000>;
|
||||
regulator-max-microvolt = <965000>;
|
||||
regulator-allowed-modes = <0 1 2>;
|
||||
regulator-enable-ramp-delay = <256>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/mediatek,mt6316c-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT6316 CP/HP/KP SPMI PMIC Regulators
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
|
||||
description:
|
||||
The MediaTek MT6316CP/HP/KP PMICs are fully controlled by SPMI interface,
|
||||
features four step-down DC/DC (buck) converters, and provides 3+1 Phases,
|
||||
joining Buck 1+2+4 for the first phase, and uses Buck 3 for the second.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6316c-regulator
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
patternProperties:
|
||||
"^vbuck(124|3)$":
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
description: |
|
||||
Allowed Buck regulator operating modes allowed. Valid values below.
|
||||
0 - Normal mode with automatic power saving, reducing the switching
|
||||
frequency when light load conditions are detected
|
||||
1 - Forced Continuous Conduction mode (FCCM) for improved voltage
|
||||
regulation accuracy with constant switching frequency but lower
|
||||
regulator efficiency
|
||||
2 - Forced Low Power mode for improved regulator efficiency, used
|
||||
when no heavy load is expected, will shut down unnecessary IP
|
||||
blocks and secondary phases to reduce quiescent current.
|
||||
This mode does not limit the maximum output current but unless
|
||||
only a light load is applied, there will be regulation accuracy
|
||||
and efficiency losses.
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
items:
|
||||
enum: [ 0, 1, 2 ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
spmi {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@6 {
|
||||
compatible = "mediatek,mt6316c-regulator";
|
||||
reg = <0x6 SPMI_USID>;
|
||||
|
||||
vbuck124 {
|
||||
regulator-name = "dvdd_proc_m";
|
||||
regulator-min-microvolt = <450000>;
|
||||
regulator-max-microvolt = <1277500>;
|
||||
regulator-allowed-modes = <0 1 2>;
|
||||
regulator-enable-ramp-delay = <256>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/mediatek,mt6316d-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT6316 DP/TP SPMI PMIC Regulators
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
|
||||
description:
|
||||
The MediaTek MT6316DP/TP PMICs are fully controlled by SPMI interface, both
|
||||
feature four step-down DC/DC (buck) converters, and provides a single Phase,
|
||||
joining Buck 1+2+3+4.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6316d-regulator
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vbuck1234:
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
description: |
|
||||
Allowed Buck regulator operating modes allowed. Valid values below.
|
||||
0 - Normal mode with automatic power saving, reducing the switching
|
||||
frequency when light load conditions are detected
|
||||
1 - Forced Continuous Conduction mode (FCCM) for improved voltage
|
||||
regulation accuracy with constant switching frequency but lower
|
||||
regulator efficiency
|
||||
2 - Forced Low Power mode for improved regulator efficiency, used
|
||||
when no heavy load is expected, will shut down unnecessary IP
|
||||
blocks and secondary phases to reduce quiescent current.
|
||||
This mode does not limit the maximum output current but unless
|
||||
only a light load is applied, there will be regulation accuracy
|
||||
and efficiency losses.
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
items:
|
||||
enum: [ 0, 1, 2 ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/spmi/spmi.h>
|
||||
|
||||
spmi {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <0>;
|
||||
|
||||
pmic@7 {
|
||||
compatible = "mediatek,mt6316d-regulator";
|
||||
reg = <0x7 SPMI_USID>;
|
||||
|
||||
vbuck1234 {
|
||||
regulator-name = "dvdd_gpustack";
|
||||
regulator-min-microvolt = <400000>;
|
||||
regulator-max-microvolt = <1277500>;
|
||||
regulator-allowed-modes = <0 1 2>;
|
||||
regulator-enable-ramp-delay = <256>;
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/regulator/mediatek,mt6363-regulator.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: MediaTek MT6363 PMIC Regulators
|
||||
|
||||
maintainers:
|
||||
- AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
|
||||
description:
|
||||
The MT6363 SPMI PMIC provides 10 BUCK and 25 LDO (Low DropOut) regulators
|
||||
and can optionally provide overcurrent warnings with one ocp interrupt
|
||||
for each voltage regulator.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: mediatek,mt6363-regulator
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
vsys-vbuck1-supply:
|
||||
description: Input supply for vbuck1
|
||||
|
||||
vsys-vbuck2-supply:
|
||||
description: Input supply for vbuck2
|
||||
|
||||
vsys-vbuck3-supply:
|
||||
description: Input supply for vbuck3
|
||||
|
||||
vsys-vbuck4-supply:
|
||||
description: Input supply for vbuck4
|
||||
|
||||
vsys-vbuck5-supply:
|
||||
description: Input supply for vbuck5
|
||||
|
||||
vsys-vbuck6-supply:
|
||||
description: Input supply for vbuck6
|
||||
|
||||
vsys-vbuck7-supply:
|
||||
description: Input supply for vbuck7
|
||||
|
||||
vsys-vs1-supply:
|
||||
description: Input supply for vs1
|
||||
|
||||
vsys-vs2-supply:
|
||||
description: Input supply for vs2
|
||||
|
||||
vsys-vs3-supply:
|
||||
description: Input supply for vs3
|
||||
|
||||
vs1-ldo1-supply:
|
||||
description: Input supply for va15, vio0p75, vm18, vrf18, vrf-io18
|
||||
|
||||
vs1-ldo2-supply:
|
||||
description: Input supply for vcn15, vio18, vufs18
|
||||
|
||||
vs2-ldo1-supply:
|
||||
description: Input supply for vsram-cpub, vsram-cpum, vrf12, vrf13, vufs12
|
||||
|
||||
vs2-ldo2-supply:
|
||||
description: Input supply for va12-1, va12-2, vcn13, vsram-cpul
|
||||
|
||||
vs3-ldo1-supply:
|
||||
description: Input supply for vsram-apu, vsram-digrf, vsram-mdfe
|
||||
|
||||
vs3-ldo2-supply:
|
||||
description: Input supply for vsram-modem, vrf0p9
|
||||
|
||||
vsys-ldo1-supply:
|
||||
description: Input supply for vaux18, vemc, vtref18
|
||||
|
||||
patternProperties:
|
||||
"^v(buck[1-7]|s[1-3])$":
|
||||
description: Buck regulators
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
description: |
|
||||
Allowed Buck regulator operating modes allowed. Valid values below.
|
||||
0 - Normal mode with automatic power saving, reducing the switching
|
||||
frequency when light load conditions are detected
|
||||
1 - Forced Continuous Conduction mode (FCCM) for improved voltage
|
||||
regulation accuracy with constant switching frequency but lower
|
||||
regulator efficiency
|
||||
2 - Forced Low Power mode for improved regulator efficiency, used
|
||||
when no heavy load is expected, does not limit the maximum out
|
||||
current but unless only a light load is applied, there will be
|
||||
regulation accuracy and efficiency losses.
|
||||
3 - Forced Ultra Low Power mode for ultra low load, this greatly
|
||||
reduces the maximum output power, makes the regulator to be
|
||||
efficient only for ultra light load, and greatly reduces the
|
||||
quiescent current (Iq) of the buck.
|
||||
maxItems: 3
|
||||
items:
|
||||
enum: [ 0, 1, 2, 3 ]
|
||||
|
||||
"^va(12-1|12-2|15)$":
|
||||
$ref: "#/$defs/ldo-common"
|
||||
|
||||
"^v(aux|m|rf-io|tref)18$":
|
||||
$ref: "#/$defs/ldo-common"
|
||||
|
||||
"^v(cn13|cn15|emc)$":
|
||||
$ref: "#/$defs/ldo-common"
|
||||
|
||||
"^vio(0p75|18)$":
|
||||
$ref: "#/$defs/ldo-common"
|
||||
|
||||
"^vrf(0p9|12|13|18)$":
|
||||
$ref: "#/$defs/ldo-common"
|
||||
|
||||
"^vsram-(apu|cpub|cpum|cpul|digrf|mdfe|modem)$":
|
||||
$ref: "#/$defs/ldo-common"
|
||||
|
||||
"^vufs(12|18)$":
|
||||
$ref: "#/$defs/ldo-common"
|
||||
|
||||
$defs:
|
||||
ldo-common:
|
||||
type: object
|
||||
$ref: regulator.yaml#
|
||||
unevaluatedProperties: false
|
||||
properties:
|
||||
regulator-allowed-modes:
|
||||
description: |
|
||||
Allowed LDO regulator operating modes allowed. Valid values below.
|
||||
0 - Normal mode with automatic power saving, reducing the switching
|
||||
frequency when light load conditions are detected
|
||||
2 - Forced Low Power mode for improved regulator efficiency, used
|
||||
when no heavy load is expected, does not limit the maximum out
|
||||
current but unless only a light load is applied, there will be
|
||||
regulation accuracy and efficiency losses.
|
||||
maxItems: 2
|
||||
items:
|
||||
enum: [ 0, 2 ]
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
||||
additionalProperties: false
|
||||
|
|
@ -41,6 +41,21 @@ properties:
|
|||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
inl1-supply:
|
||||
description: Regulator supply for the INL1 pin group, powering LDOx
|
||||
|
||||
inb13-supply:
|
||||
description:
|
||||
Regulator supply for the INB13 pin group, powering BUCK1 and BUCK3.
|
||||
|
||||
inb26-supply:
|
||||
description:
|
||||
Regulator supply for the INB26 pin group, powering BUCK2 and BUCK6.
|
||||
|
||||
inb45-supply:
|
||||
description:
|
||||
Regulator supply for the INB45 pin group, powering BUCK4 and BUCK5.
|
||||
|
||||
regulators:
|
||||
type: object
|
||||
description: |
|
||||
|
|
@ -124,6 +139,30 @@ properties:
|
|||
When WDOG_B signal is asserted a warm reset will be done instead of cold
|
||||
reset.
|
||||
|
||||
nxp,pmic-on-req-on-debounce-us:
|
||||
enum: [ 120, 20000, 100000, 750000 ]
|
||||
description: Debounce time for PMIC_ON_REQ high.
|
||||
|
||||
nxp,pmic-on-req-off-debounce-us:
|
||||
enum: [ 120, 2000 ]
|
||||
description: Debounce time for PMIC_ON_REQ is asserted low
|
||||
|
||||
nxp,power-on-step-ms:
|
||||
enum: [ 1, 2, 4, 8]
|
||||
description: Time step configuration during power on sequence
|
||||
|
||||
nxp,power-down-step-ms:
|
||||
enum: [ 2, 4, 8, 16 ]
|
||||
description: Time step configuration during power down sequence
|
||||
|
||||
nxp,restart-ms:
|
||||
enum: [ 250, 500 ]
|
||||
description: Time to stay off regulators during Cold reset
|
||||
|
||||
npx,pmic-rst-b-debounce-ms:
|
||||
enum: [ 10, 50, 100, 500, 1000, 2000, 4000, 8000 ]
|
||||
description: PMIC_RST_B debounce time
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
|||
|
|
@ -51,10 +51,15 @@ description: |
|
|||
For PM8450, smps1 - smps6, ldo1 - ldo4
|
||||
For PM8550, smps1 - smps6, ldo1 - ldo17, bob1 - bob2
|
||||
For PM8998, smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2
|
||||
For PMH0101, ldo1 - ldo18, bob1 - bob2
|
||||
For PMH0104, smps1 - smps4
|
||||
For PMH0110, smps1 - smps10, ldo1 - ldo4
|
||||
For PMI8998, bob
|
||||
For PMC8380, smps1 - smps8, ldo1 - lodo3
|
||||
For PMCX0102, smps1 - smps10, ldo1 - ldo4
|
||||
For PMR735A, smps1 - smps3, ldo1 - ldo7
|
||||
For PMR735B, ldo1 - ldo12
|
||||
For PMR735D, ldo1 - ldo7
|
||||
For PMX55, smps1 - smps7, ldo1 - ldo16
|
||||
For PMX65, smps1 - smps8, ldo1 - ldo21
|
||||
For PMX75, smps1 - smps10, ldo1 - ldo21
|
||||
|
|
@ -85,12 +90,17 @@ properties:
|
|||
- qcom,pmc8180-rpmh-regulators
|
||||
- qcom,pmc8180c-rpmh-regulators
|
||||
- qcom,pmc8380-rpmh-regulators
|
||||
- qcom,pmcx0102-rpmh-regulators
|
||||
- qcom,pmg1110-rpmh-regulators
|
||||
- qcom,pmh0101-rpmh-regulators
|
||||
- qcom,pmh0104-rpmh-regulators
|
||||
- qcom,pmh0110-rpmh-regulators
|
||||
- qcom,pmi8998-rpmh-regulators
|
||||
- qcom,pmm8155au-rpmh-regulators
|
||||
- qcom,pmm8654au-rpmh-regulators
|
||||
- qcom,pmr735a-rpmh-regulators
|
||||
- qcom,pmr735b-rpmh-regulators
|
||||
- qcom,pmr735d-rpmh-regulators
|
||||
- qcom,pmx55-rpmh-regulators
|
||||
- qcom,pmx65-rpmh-regulators
|
||||
- qcom,pmx75-rpmh-regulators
|
||||
|
|
@ -100,7 +110,7 @@ properties:
|
|||
RPMh resource name suffix used for the regulators found
|
||||
on this PMIC.
|
||||
$ref: /schemas/types.yaml#/definitions/string
|
||||
enum: [a, b, c, d, e, f, g, h, i, j, k, l, m, n]
|
||||
pattern: "^[a-n]|[A-N]_E[0-3]+$"
|
||||
|
||||
qcom,always-wait-for-ack:
|
||||
description: |
|
||||
|
|
@ -246,6 +256,7 @@ allOf:
|
|||
compatible:
|
||||
enum:
|
||||
- qcom,pm8005-rpmh-regulators
|
||||
- qcom,pmh0104-rpmh-regulators
|
||||
then:
|
||||
patternProperties:
|
||||
"^vdd-s[1-4]-supply$": true
|
||||
|
|
@ -422,6 +433,34 @@ allOf:
|
|||
properties:
|
||||
vdd-s1-supply: true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pmh0101-rpmh-regulators
|
||||
then:
|
||||
properties:
|
||||
vdd-l1-l4-l10-supply: true
|
||||
vdd-l2-l13-l14-supply: true
|
||||
vdd-l3-l11-supply: true
|
||||
vdd-l5-l16-supply: true
|
||||
vdd-l6-l7-supply: true
|
||||
vdd-l8-l9-supply: true
|
||||
patternProperties:
|
||||
"^vdd-l(1[2578])-supply$": true
|
||||
"^vdd-bob[1-2]-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pmcx0102-rpmh-regulators
|
||||
- qcom,pmh0110-rpmh-regulators
|
||||
then:
|
||||
patternProperties:
|
||||
"^vdd-l[1-4]-supply$": true
|
||||
"^vdd-s([1-9]|10)-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
@ -459,6 +498,18 @@ allOf:
|
|||
patternProperties:
|
||||
"^vdd-l([3-6]|9|1[0-2])-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- qcom,pmr735d-rpmh-regulators
|
||||
then:
|
||||
properties:
|
||||
vdd-l1-l2-l5-supply: true
|
||||
vdd-l3-l4-supply: true
|
||||
patternProperties:
|
||||
"^vdd-l[6-7]-supply$": true
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
|
|
|
|||
|
|
@ -572,6 +572,8 @@ patternProperties:
|
|||
description: Foxconn Industrial Internet
|
||||
"^firefly,.*":
|
||||
description: Firefly
|
||||
"^fitipower,.*":
|
||||
description: Fitipower Integrated Technology Inc.
|
||||
"^flipkart,.*":
|
||||
description: Flipkart Inc.
|
||||
"^focaltech,.*":
|
||||
|
|
|
|||
12
MAINTAINERS
12
MAINTAINERS
|
|
@ -7223,7 +7223,6 @@ F: Documentation/devicetree/bindings/input/dlg,da72??.yaml
|
|||
F: Documentation/devicetree/bindings/input/dlg,da9062-onkey.yaml
|
||||
F: Documentation/devicetree/bindings/mfd/da90*.txt
|
||||
F: Documentation/devicetree/bindings/mfd/dlg,da90*.yaml
|
||||
F: Documentation/devicetree/bindings/regulator/da92*.txt
|
||||
F: Documentation/devicetree/bindings/regulator/dlg,da9*.yaml
|
||||
F: Documentation/devicetree/bindings/regulator/dlg,slg51000.yaml
|
||||
F: Documentation/devicetree/bindings/sound/da[79]*.txt
|
||||
|
|
@ -18710,6 +18709,17 @@ S: Maintained
|
|||
F: Documentation/devicetree/bindings/regulator/nxp,pf5300.yaml
|
||||
F: drivers/regulator/pf530x-regulator.c
|
||||
|
||||
NXP PF1550 PMIC MFD DRIVER
|
||||
M: Samuel Kayode <samuel.kayode@savoirfairelinux.com>
|
||||
L: imx@lists.linux.dev
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/mfd/nxp,pf1550.yaml
|
||||
F: drivers/input/misc/pf1550-onkey.c
|
||||
F: drivers/mfd/pf1550.c
|
||||
F: drivers/power/supply/pf1550-charger.c
|
||||
F: drivers/regulator/pf1550-regulator.c
|
||||
F: include/linux/mfd/pfd1550.h
|
||||
|
||||
NXP PF8100/PF8121A/PF8200 PMIC REGULATOR DEVICE DRIVER
|
||||
M: Jagan Teki <jagan@amarulasolutions.com>
|
||||
S: Maintained
|
||||
|
|
|
|||
|
|
@ -190,6 +190,17 @@ config INPUT_PCSPKR
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called pcspkr.
|
||||
|
||||
config INPUT_PF1550_ONKEY
|
||||
tristate "NXP PF1550 Onkey support"
|
||||
depends on MFD_PF1550
|
||||
help
|
||||
Say Y here if you want support for PF1550 PMIC. Onkey can trigger
|
||||
release and 1s(push hold), 2s, 3s, 4s, 8s interrupt for long press
|
||||
detect.
|
||||
|
||||
To compile this driver as a module, choose M here. The module will be
|
||||
called pf1550-onkey.
|
||||
|
||||
config INPUT_PM8941_PWRKEY
|
||||
tristate "Qualcomm PM8941 power key support"
|
||||
depends on MFD_SPMI_PMIC
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ obj-$(CONFIG_INPUT_PALMAS_PWRBUTTON) += palmas-pwrbutton.o
|
|||
obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o
|
||||
obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o
|
||||
obj-$(CONFIG_INPUT_PCSPKR) += pcspkr.o
|
||||
obj-$(CONFIG_INPUT_PF1550_ONKEY) += pf1550-onkey.o
|
||||
obj-$(CONFIG_INPUT_PM8941_PWRKEY) += pm8941-pwrkey.o
|
||||
obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR) += pm8xxx-vibrator.o
|
||||
obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY) += pmic8xxx-pwrkey.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,197 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for the PF1550 ONKEY
|
||||
* Copyright (C) 2016 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||
*
|
||||
* Portions Copyright (c) 2025 Savoir-faire Linux Inc.
|
||||
* Samuel Kayode <samuel.kayode@savoirfairelinux.com>
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mfd/pf1550.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#define PF1550_ONKEY_IRQ_NR 6
|
||||
|
||||
struct onkey_drv_data {
|
||||
struct device *dev;
|
||||
const struct pf1550_ddata *pf1550;
|
||||
bool wakeup;
|
||||
struct input_dev *input;
|
||||
};
|
||||
|
||||
static irqreturn_t pf1550_onkey_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct onkey_drv_data *onkey = data;
|
||||
struct platform_device *pdev = to_platform_device(onkey->dev);
|
||||
int i, state, irq_type = -1;
|
||||
|
||||
for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++)
|
||||
if (irq == platform_get_irq(pdev, i))
|
||||
irq_type = i;
|
||||
|
||||
switch (irq_type) {
|
||||
case PF1550_ONKEY_IRQ_PUSHI:
|
||||
state = 0;
|
||||
break;
|
||||
case PF1550_ONKEY_IRQ_1SI:
|
||||
case PF1550_ONKEY_IRQ_2SI:
|
||||
case PF1550_ONKEY_IRQ_3SI:
|
||||
case PF1550_ONKEY_IRQ_4SI:
|
||||
case PF1550_ONKEY_IRQ_8SI:
|
||||
state = 1;
|
||||
break;
|
||||
default:
|
||||
dev_err(onkey->dev, "onkey interrupt: irq %d occurred\n",
|
||||
irq_type);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
input_event(onkey->input, EV_KEY, KEY_POWER, state);
|
||||
input_sync(onkey->input);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int pf1550_onkey_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct onkey_drv_data *onkey;
|
||||
struct input_dev *input;
|
||||
bool key_power = false;
|
||||
int i, irq, error;
|
||||
|
||||
onkey = devm_kzalloc(&pdev->dev, sizeof(*onkey), GFP_KERNEL);
|
||||
if (!onkey)
|
||||
return -ENOMEM;
|
||||
|
||||
onkey->dev = &pdev->dev;
|
||||
|
||||
onkey->pf1550 = dev_get_drvdata(pdev->dev.parent);
|
||||
if (!onkey->pf1550->regmap)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV,
|
||||
"failed to get regmap\n");
|
||||
|
||||
onkey->wakeup = device_property_read_bool(pdev->dev.parent,
|
||||
"wakeup-source");
|
||||
|
||||
if (device_property_read_bool(pdev->dev.parent,
|
||||
"nxp,disable-key-power")) {
|
||||
error = regmap_clear_bits(onkey->pf1550->regmap,
|
||||
PF1550_PMIC_REG_PWRCTRL1,
|
||||
PF1550_ONKEY_RST_EN);
|
||||
if (error)
|
||||
return dev_err_probe(&pdev->dev, error,
|
||||
"failed: disable turn system off");
|
||||
} else {
|
||||
key_power = true;
|
||||
}
|
||||
|
||||
input = devm_input_allocate_device(&pdev->dev);
|
||||
if (!input)
|
||||
return dev_err_probe(&pdev->dev, -ENOMEM,
|
||||
"failed to allocate the input device\n");
|
||||
|
||||
input->name = pdev->name;
|
||||
input->phys = "pf1550-onkey/input0";
|
||||
input->id.bustype = BUS_HOST;
|
||||
|
||||
if (key_power)
|
||||
input_set_capability(input, EV_KEY, KEY_POWER);
|
||||
|
||||
onkey->input = input;
|
||||
platform_set_drvdata(pdev, onkey);
|
||||
|
||||
for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
error = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
pf1550_onkey_irq_handler,
|
||||
IRQF_NO_SUSPEND,
|
||||
"pf1550-onkey", onkey);
|
||||
if (error)
|
||||
return dev_err_probe(&pdev->dev, error,
|
||||
"failed: irq request (IRQ: %d)\n",
|
||||
i);
|
||||
}
|
||||
|
||||
error = input_register_device(input);
|
||||
if (error)
|
||||
return dev_err_probe(&pdev->dev, error,
|
||||
"failed to register input device\n");
|
||||
|
||||
device_init_wakeup(&pdev->dev, onkey->wakeup);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pf1550_onkey_suspend(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
|
||||
int i, irq;
|
||||
|
||||
if (!device_may_wakeup(&pdev->dev))
|
||||
regmap_write(onkey->pf1550->regmap,
|
||||
PF1550_PMIC_REG_ONKEY_INT_MASK0,
|
||||
ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI | ONKEY_IRQ_2SI |
|
||||
ONKEY_IRQ_3SI | ONKEY_IRQ_4SI | ONKEY_IRQ_8SI);
|
||||
else
|
||||
for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq > 0)
|
||||
enable_irq_wake(irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pf1550_onkey_resume(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct onkey_drv_data *onkey = platform_get_drvdata(pdev);
|
||||
int i, irq;
|
||||
|
||||
if (!device_may_wakeup(&pdev->dev))
|
||||
regmap_write(onkey->pf1550->regmap,
|
||||
PF1550_PMIC_REG_ONKEY_INT_MASK0,
|
||||
~((u8)(ONKEY_IRQ_PUSHI | ONKEY_IRQ_1SI |
|
||||
ONKEY_IRQ_2SI | ONKEY_IRQ_3SI | ONKEY_IRQ_4SI |
|
||||
ONKEY_IRQ_8SI)));
|
||||
else
|
||||
for (i = 0; i < PF1550_ONKEY_IRQ_NR; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq > 0)
|
||||
disable_irq_wake(irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(pf1550_onkey_pm_ops, pf1550_onkey_suspend,
|
||||
pf1550_onkey_resume);
|
||||
|
||||
static const struct platform_device_id pf1550_onkey_id[] = {
|
||||
{ "pf1550-onkey", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, pf1550_onkey_id);
|
||||
|
||||
static struct platform_driver pf1550_onkey_driver = {
|
||||
.driver = {
|
||||
.name = "pf1550-onkey",
|
||||
.pm = pm_sleep_ptr(&pf1550_onkey_pm_ops),
|
||||
},
|
||||
.probe = pf1550_onkey_probe,
|
||||
.id_table = pf1550_onkey_id,
|
||||
};
|
||||
module_platform_driver(pf1550_onkey_driver);
|
||||
|
||||
MODULE_AUTHOR("Freescale Semiconductor");
|
||||
MODULE_DESCRIPTION("PF1550 onkey Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -605,6 +605,22 @@ config MFD_MX25_TSADC
|
|||
i.MX25 processors. They consist of a conversion queue for general
|
||||
purpose ADC and a queue for Touchscreens.
|
||||
|
||||
config MFD_PF1550
|
||||
tristate "NXP PF1550 PMIC Support"
|
||||
depends on I2C=y && OF
|
||||
select MFD_CORE
|
||||
select REGMAP_I2C
|
||||
select REGMAP_IRQ
|
||||
help
|
||||
Say yes here to add support for NXP PF1550. This is a companion Power
|
||||
Management IC with regulators, onkey, and charger control on chip.
|
||||
This driver provides common support for accessing the device;
|
||||
additional drivers must be enabled in order to use the functionality
|
||||
of the device.
|
||||
|
||||
This driver can also be built as a module and if so will be called
|
||||
pf1550.
|
||||
|
||||
config MFD_HI6421_PMIC
|
||||
tristate "HiSilicon Hi6421 PMU/Codec IC"
|
||||
depends on OF
|
||||
|
|
|
|||
|
|
@ -122,6 +122,8 @@ obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
|
|||
obj-$(CONFIG_MFD_MC13XXX_SPI) += mc13xxx-spi.o
|
||||
obj-$(CONFIG_MFD_MC13XXX_I2C) += mc13xxx-i2c.o
|
||||
|
||||
obj-$(CONFIG_MFD_PF1550) += pf1550.o
|
||||
|
||||
obj-$(CONFIG_MFD_NCT6694) += nct6694.o
|
||||
|
||||
obj-$(CONFIG_MFD_CORE) += mfd-core.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,367 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Core driver for the PF1550
|
||||
*
|
||||
* Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
* Robin Gong <yibin.gong@freescale.com>
|
||||
*
|
||||
* Portions Copyright (c) 2025 Savoir-faire Linux Inc.
|
||||
* Samuel Kayode <samuel.kayode@savoirfairelinux.com>
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/core.h>
|
||||
#include <linux/mfd/pf1550.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
static const struct regmap_config pf1550_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = PF1550_PMIC_REG_END,
|
||||
};
|
||||
|
||||
static const struct regmap_irq pf1550_irqs[] = {
|
||||
REGMAP_IRQ_REG(PF1550_IRQ_CHG, 0, IRQ_CHG),
|
||||
REGMAP_IRQ_REG(PF1550_IRQ_REGULATOR, 0, IRQ_REGULATOR),
|
||||
REGMAP_IRQ_REG(PF1550_IRQ_ONKEY, 0, IRQ_ONKEY),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip pf1550_irq_chip = {
|
||||
.name = "pf1550",
|
||||
.status_base = PF1550_PMIC_REG_INT_CATEGORY,
|
||||
.init_ack_masked = 1,
|
||||
.num_regs = 1,
|
||||
.irqs = pf1550_irqs,
|
||||
.num_irqs = ARRAY_SIZE(pf1550_irqs),
|
||||
};
|
||||
|
||||
static const struct regmap_irq pf1550_regulator_irqs[] = {
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW1_LS, 0, PMIC_IRQ_SW1_LS),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW2_LS, 0, PMIC_IRQ_SW2_LS),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW3_LS, 0, PMIC_IRQ_SW3_LS),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW1_HS, 3, PMIC_IRQ_SW1_HS),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW2_HS, 3, PMIC_IRQ_SW2_HS),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_SW3_HS, 3, PMIC_IRQ_SW3_HS),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO1_FAULT, 16, PMIC_IRQ_LDO1_FAULT),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO2_FAULT, 16, PMIC_IRQ_LDO2_FAULT),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_LDO3_FAULT, 16, PMIC_IRQ_LDO3_FAULT),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_TEMP_110, 24, PMIC_IRQ_TEMP_110),
|
||||
REGMAP_IRQ_REG(PF1550_PMIC_IRQ_TEMP_125, 24, PMIC_IRQ_TEMP_125),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip pf1550_regulator_irq_chip = {
|
||||
.name = "pf1550-regulator",
|
||||
.status_base = PF1550_PMIC_REG_SW_INT_STAT0,
|
||||
.ack_base = PF1550_PMIC_REG_SW_INT_STAT0,
|
||||
.mask_base = PF1550_PMIC_REG_SW_INT_MASK0,
|
||||
.use_ack = 1,
|
||||
.init_ack_masked = 1,
|
||||
.num_regs = 25,
|
||||
.irqs = pf1550_regulator_irqs,
|
||||
.num_irqs = ARRAY_SIZE(pf1550_regulator_irqs),
|
||||
};
|
||||
|
||||
static const struct resource regulator_resources[] = {
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW1_LS),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW2_LS),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW3_LS),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW1_HS),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW2_HS),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_SW3_HS),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO1_FAULT),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO2_FAULT),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_LDO3_FAULT),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_TEMP_110),
|
||||
DEFINE_RES_IRQ(PF1550_PMIC_IRQ_TEMP_125),
|
||||
};
|
||||
|
||||
static const struct regmap_irq pf1550_onkey_irqs[] = {
|
||||
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_PUSHI, 0, ONKEY_IRQ_PUSHI),
|
||||
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_1SI, 0, ONKEY_IRQ_1SI),
|
||||
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_2SI, 0, ONKEY_IRQ_2SI),
|
||||
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_3SI, 0, ONKEY_IRQ_3SI),
|
||||
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_4SI, 0, ONKEY_IRQ_4SI),
|
||||
REGMAP_IRQ_REG(PF1550_ONKEY_IRQ_8SI, 0, ONKEY_IRQ_8SI),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip pf1550_onkey_irq_chip = {
|
||||
.name = "pf1550-onkey",
|
||||
.status_base = PF1550_PMIC_REG_ONKEY_INT_STAT0,
|
||||
.ack_base = PF1550_PMIC_REG_ONKEY_INT_STAT0,
|
||||
.mask_base = PF1550_PMIC_REG_ONKEY_INT_MASK0,
|
||||
.use_ack = 1,
|
||||
.init_ack_masked = 1,
|
||||
.num_regs = 1,
|
||||
.irqs = pf1550_onkey_irqs,
|
||||
.num_irqs = ARRAY_SIZE(pf1550_onkey_irqs),
|
||||
};
|
||||
|
||||
static const struct resource onkey_resources[] = {
|
||||
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_PUSHI),
|
||||
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_1SI),
|
||||
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_2SI),
|
||||
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_3SI),
|
||||
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_4SI),
|
||||
DEFINE_RES_IRQ(PF1550_ONKEY_IRQ_8SI),
|
||||
};
|
||||
|
||||
static const struct regmap_irq pf1550_charger_irqs[] = {
|
||||
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_BAT2SOCI, 0, CHARG_IRQ_BAT2SOCI),
|
||||
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_BATI, 0, CHARG_IRQ_BATI),
|
||||
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_CHGI, 0, CHARG_IRQ_CHGI),
|
||||
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_VBUSI, 0, CHARG_IRQ_VBUSI),
|
||||
REGMAP_IRQ_REG(PF1550_CHARG_IRQ_THMI, 0, CHARG_IRQ_THMI),
|
||||
};
|
||||
|
||||
static const struct regmap_irq_chip pf1550_charger_irq_chip = {
|
||||
.name = "pf1550-charger",
|
||||
.status_base = PF1550_CHARG_REG_CHG_INT,
|
||||
.ack_base = PF1550_CHARG_REG_CHG_INT,
|
||||
.mask_base = PF1550_CHARG_REG_CHG_INT_MASK,
|
||||
.use_ack = 1,
|
||||
.init_ack_masked = 1,
|
||||
.num_regs = 1,
|
||||
.irqs = pf1550_charger_irqs,
|
||||
.num_irqs = ARRAY_SIZE(pf1550_charger_irqs),
|
||||
};
|
||||
|
||||
static const struct resource charger_resources[] = {
|
||||
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_BAT2SOCI),
|
||||
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_BATI),
|
||||
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_CHGI),
|
||||
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_VBUSI),
|
||||
DEFINE_RES_IRQ(PF1550_CHARG_IRQ_THMI),
|
||||
};
|
||||
|
||||
static const struct mfd_cell pf1550_regulator_cell = {
|
||||
.name = "pf1550-regulator",
|
||||
.num_resources = ARRAY_SIZE(regulator_resources),
|
||||
.resources = regulator_resources,
|
||||
};
|
||||
|
||||
static const struct mfd_cell pf1550_onkey_cell = {
|
||||
.name = "pf1550-onkey",
|
||||
.num_resources = ARRAY_SIZE(onkey_resources),
|
||||
.resources = onkey_resources,
|
||||
};
|
||||
|
||||
static const struct mfd_cell pf1550_charger_cell = {
|
||||
.name = "pf1550-charger",
|
||||
.num_resources = ARRAY_SIZE(charger_resources),
|
||||
.resources = charger_resources,
|
||||
};
|
||||
|
||||
/*
|
||||
* The PF1550 is shipped in variants of A0, A1,...A9. Each variant defines a
|
||||
* configuration of the PMIC in a One-Time Programmable (OTP) memory.
|
||||
* This memory is accessed indirectly by writing valid keys to specific
|
||||
* registers of the PMIC. To read the OTP memory after writing the valid keys,
|
||||
* the OTP register address to be read is written to pf1550 register 0xc4 and
|
||||
* its value read from pf1550 register 0xc5.
|
||||
*/
|
||||
static int pf1550_read_otp(const struct pf1550_ddata *pf1550, unsigned int index,
|
||||
unsigned int *val)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = regmap_write(pf1550->regmap, PF1550_PMIC_REG_KEY, PF1550_OTP_PMIC_KEY);
|
||||
if (ret)
|
||||
goto read_err;
|
||||
|
||||
ret = regmap_write(pf1550->regmap, PF1550_CHARG_REG_CHGR_KEY2, PF1550_OTP_CHGR_KEY);
|
||||
if (ret)
|
||||
goto read_err;
|
||||
|
||||
ret = regmap_write(pf1550->regmap, PF1550_TEST_REG_KEY3, PF1550_OTP_TEST_KEY);
|
||||
if (ret)
|
||||
goto read_err;
|
||||
|
||||
ret = regmap_write(pf1550->regmap, PF1550_TEST_REG_FMRADDR, index);
|
||||
if (ret)
|
||||
goto read_err;
|
||||
|
||||
ret = regmap_read(pf1550->regmap, PF1550_TEST_REG_FMRDATA, val);
|
||||
if (ret)
|
||||
goto read_err;
|
||||
|
||||
return 0;
|
||||
|
||||
read_err:
|
||||
return dev_err_probe(pf1550->dev, ret, "OTP reg %x not found!\n", index);
|
||||
}
|
||||
|
||||
static int pf1550_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
const struct mfd_cell *regulator = &pf1550_regulator_cell;
|
||||
const struct mfd_cell *charger = &pf1550_charger_cell;
|
||||
const struct mfd_cell *onkey = &pf1550_onkey_cell;
|
||||
unsigned int reg_data = 0, otp_data = 0;
|
||||
struct pf1550_ddata *pf1550;
|
||||
struct irq_domain *domain;
|
||||
int irq, ret = 0;
|
||||
|
||||
pf1550 = devm_kzalloc(&i2c->dev, sizeof(*pf1550), GFP_KERNEL);
|
||||
if (!pf1550)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(i2c, pf1550);
|
||||
pf1550->dev = &i2c->dev;
|
||||
pf1550->irq = i2c->irq;
|
||||
|
||||
pf1550->regmap = devm_regmap_init_i2c(i2c, &pf1550_regmap_config);
|
||||
if (IS_ERR(pf1550->regmap))
|
||||
return dev_err_probe(pf1550->dev, PTR_ERR(pf1550->regmap),
|
||||
"failed to allocate register map\n");
|
||||
|
||||
ret = regmap_read(pf1550->regmap, PF1550_PMIC_REG_DEVICE_ID, ®_data);
|
||||
if (ret < 0)
|
||||
return dev_err_probe(pf1550->dev, ret, "cannot read chip ID\n");
|
||||
if (reg_data != PF1550_DEVICE_ID)
|
||||
return dev_err_probe(pf1550->dev, -ENODEV, "invalid device ID: 0x%02x\n", reg_data);
|
||||
|
||||
/* Regulator DVS for SW2 */
|
||||
ret = pf1550_read_otp(pf1550, PF1550_OTP_SW2_SW3, &otp_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* When clear, DVS should be enabled */
|
||||
if (!(otp_data & OTP_SW2_DVS_ENB))
|
||||
pf1550->dvs2_enable = true;
|
||||
|
||||
/* Regulator DVS for SW1 */
|
||||
ret = pf1550_read_otp(pf1550, PF1550_OTP_SW1_SW2, &otp_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(otp_data & OTP_SW1_DVS_ENB))
|
||||
pf1550->dvs1_enable = true;
|
||||
|
||||
/* Add top level interrupts */
|
||||
ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, pf1550->irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED |
|
||||
IRQF_TRIGGER_FALLING,
|
||||
0, &pf1550_irq_chip,
|
||||
&pf1550->irq_data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Add regulator */
|
||||
irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_REGULATOR);
|
||||
if (irq < 0)
|
||||
return dev_err_probe(pf1550->dev, irq,
|
||||
"Failed to get parent vIRQ(%d) for chip %s\n",
|
||||
PF1550_IRQ_REGULATOR, pf1550_irq_chip.name);
|
||||
|
||||
ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED |
|
||||
IRQF_TRIGGER_FALLING, 0,
|
||||
&pf1550_regulator_irq_chip,
|
||||
&pf1550->irq_data_regulator);
|
||||
if (ret)
|
||||
return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
|
||||
pf1550_regulator_irq_chip.name);
|
||||
|
||||
domain = regmap_irq_get_domain(pf1550->irq_data_regulator);
|
||||
|
||||
ret = devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, regulator, 1, NULL, 0, domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Add onkey */
|
||||
irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_ONKEY);
|
||||
if (irq < 0)
|
||||
return dev_err_probe(pf1550->dev, irq,
|
||||
"Failed to get parent vIRQ(%d) for chip %s\n",
|
||||
PF1550_IRQ_ONKEY, pf1550_irq_chip.name);
|
||||
|
||||
ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED |
|
||||
IRQF_TRIGGER_FALLING, 0,
|
||||
&pf1550_onkey_irq_chip,
|
||||
&pf1550->irq_data_onkey);
|
||||
if (ret)
|
||||
return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
|
||||
pf1550_onkey_irq_chip.name);
|
||||
|
||||
domain = regmap_irq_get_domain(pf1550->irq_data_onkey);
|
||||
|
||||
ret = devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, onkey, 1, NULL, 0, domain);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Add battery charger */
|
||||
irq = regmap_irq_get_virq(pf1550->irq_data, PF1550_IRQ_CHG);
|
||||
if (irq < 0)
|
||||
return dev_err_probe(pf1550->dev, irq,
|
||||
"Failed to get parent vIRQ(%d) for chip %s\n",
|
||||
PF1550_IRQ_CHG, pf1550_irq_chip.name);
|
||||
|
||||
ret = devm_regmap_add_irq_chip(pf1550->dev, pf1550->regmap, irq,
|
||||
IRQF_ONESHOT | IRQF_SHARED |
|
||||
IRQF_TRIGGER_FALLING, 0,
|
||||
&pf1550_charger_irq_chip,
|
||||
&pf1550->irq_data_charger);
|
||||
if (ret)
|
||||
return dev_err_probe(pf1550->dev, ret, "Failed to add %s IRQ chip\n",
|
||||
pf1550_charger_irq_chip.name);
|
||||
|
||||
domain = regmap_irq_get_domain(pf1550->irq_data_charger);
|
||||
|
||||
return devm_mfd_add_devices(pf1550->dev, PLATFORM_DEVID_NONE, charger, 1, NULL, 0, domain);
|
||||
}
|
||||
|
||||
static int pf1550_suspend(struct device *dev)
|
||||
{
|
||||
struct pf1550_ddata *pf1550 = dev_get_drvdata(dev);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
enable_irq_wake(pf1550->irq);
|
||||
disable_irq(pf1550->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pf1550_resume(struct device *dev)
|
||||
{
|
||||
struct pf1550_ddata *pf1550 = dev_get_drvdata(dev);
|
||||
|
||||
if (device_may_wakeup(dev)) {
|
||||
disable_irq_wake(pf1550->irq);
|
||||
enable_irq(pf1550->irq);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static DEFINE_SIMPLE_DEV_PM_OPS(pf1550_pm, pf1550_suspend, pf1550_resume);
|
||||
|
||||
static const struct i2c_device_id pf1550_i2c_id[] = {
|
||||
{ "pf1550" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, pf1550_i2c_id);
|
||||
|
||||
static const struct of_device_id pf1550_dt_match[] = {
|
||||
{ .compatible = "nxp,pf1550" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, pf1550_dt_match);
|
||||
|
||||
static struct i2c_driver pf1550_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "pf1550",
|
||||
.pm = pm_sleep_ptr(&pf1550_pm),
|
||||
.of_match_table = pf1550_dt_match,
|
||||
},
|
||||
.probe = pf1550_i2c_probe,
|
||||
.id_table = pf1550_i2c_id,
|
||||
};
|
||||
module_i2c_driver(pf1550_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("NXP PF1550 core driver");
|
||||
MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -486,6 +486,17 @@ config CHARGER_88PM860X
|
|||
help
|
||||
Say Y here to enable charger for Marvell 88PM860x chip.
|
||||
|
||||
config CHARGER_PF1550
|
||||
tristate "NXP PF1550 battery charger driver"
|
||||
depends on MFD_PF1550
|
||||
help
|
||||
Say Y to enable support for the NXP PF1550 battery charger.
|
||||
The device is a single cell Li-Ion/Li-Polymer battery charger for
|
||||
portable application.
|
||||
|
||||
This driver can also be built as a module. If so, the module will be
|
||||
called pf1550-charger.
|
||||
|
||||
config BATTERY_RX51
|
||||
tristate "Nokia RX-51 (N900) battery driver"
|
||||
depends on TWL4030_MADC
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ obj-$(CONFIG_CHARGER_RT9467) += rt9467-charger.o
|
|||
obj-$(CONFIG_CHARGER_RT9471) += rt9471.o
|
||||
obj-$(CONFIG_BATTERY_TWL4030_MADC) += twl4030_madc_battery.o
|
||||
obj-$(CONFIG_CHARGER_88PM860X) += 88pm860x_charger.o
|
||||
obj-$(CONFIG_CHARGER_PF1550) += pf1550-charger.o
|
||||
obj-$(CONFIG_BATTERY_RX51) += rx51_battery.o
|
||||
obj-$(CONFIG_AB8500_BM) += ab8500_bmdata.o ab8500_charger.o ab8500_fg.o ab8500_btemp.o ab8500_chargalg.o
|
||||
obj-$(CONFIG_CHARGER_CPCAP) += cpcap-charger.o
|
||||
|
|
|
|||
|
|
@ -0,0 +1,641 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* charger driver for the PF1550
|
||||
*
|
||||
* Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
* Robin Gong <yibin.gong@freescale.com>
|
||||
*
|
||||
* Portions Copyright (c) 2025 Savoir-faire Linux Inc.
|
||||
* Samuel Kayode <samuel.kayode@savoirfairelinux.com>
|
||||
*/
|
||||
|
||||
#include <linux/devm-helpers.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/pf1550.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
|
||||
#define PF1550_DEFAULT_CONSTANT_VOLT 4200000
|
||||
#define PF1550_DEFAULT_MIN_SYSTEM_VOLT 3500000
|
||||
#define PF1550_DEFAULT_THERMAL_TEMP 95
|
||||
#define PF1550_CHARGER_IRQ_NR 5
|
||||
|
||||
struct pf1550_charger {
|
||||
struct device *dev;
|
||||
const struct pf1550_ddata *pf1550;
|
||||
struct power_supply *charger;
|
||||
struct power_supply *battery;
|
||||
struct delayed_work vbus_sense_work;
|
||||
struct delayed_work chg_sense_work;
|
||||
struct delayed_work bat_sense_work;
|
||||
int virqs[PF1550_CHARGER_IRQ_NR];
|
||||
|
||||
u32 constant_volt;
|
||||
u32 min_system_volt;
|
||||
u32 thermal_regulation_temp;
|
||||
};
|
||||
|
||||
static int pf1550_get_charger_state(struct regmap *regmap, int *val)
|
||||
{
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PF1550_CHARG_REG_CHG_SNS, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data &= PF1550_CHG_SNS_MASK;
|
||||
|
||||
switch (data) {
|
||||
case PF1550_CHG_PRECHARGE:
|
||||
case PF1550_CHG_CONSTANT_CURRENT:
|
||||
case PF1550_CHG_CONSTANT_VOL:
|
||||
case PF1550_CHG_EOC:
|
||||
*val = POWER_SUPPLY_STATUS_CHARGING;
|
||||
break;
|
||||
case PF1550_CHG_DONE:
|
||||
*val = POWER_SUPPLY_STATUS_FULL;
|
||||
break;
|
||||
case PF1550_CHG_TIMER_FAULT:
|
||||
case PF1550_CHG_SUSPEND:
|
||||
*val = POWER_SUPPLY_STATUS_NOT_CHARGING;
|
||||
break;
|
||||
case PF1550_CHG_OFF_INV:
|
||||
case PF1550_CHG_OFF_TEMP:
|
||||
case PF1550_CHG_LINEAR_ONLY:
|
||||
*val = POWER_SUPPLY_STATUS_DISCHARGING;
|
||||
break;
|
||||
default:
|
||||
*val = POWER_SUPPLY_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pf1550_get_charge_type(struct regmap *regmap, int *val)
|
||||
{
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PF1550_CHARG_REG_CHG_SNS, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data &= PF1550_CHG_SNS_MASK;
|
||||
|
||||
switch (data) {
|
||||
case PF1550_CHG_SNS_MASK:
|
||||
*val = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
|
||||
break;
|
||||
case PF1550_CHG_CONSTANT_CURRENT:
|
||||
case PF1550_CHG_CONSTANT_VOL:
|
||||
case PF1550_CHG_EOC:
|
||||
*val = POWER_SUPPLY_CHARGE_TYPE_FAST;
|
||||
break;
|
||||
case PF1550_CHG_DONE:
|
||||
case PF1550_CHG_TIMER_FAULT:
|
||||
case PF1550_CHG_SUSPEND:
|
||||
case PF1550_CHG_OFF_INV:
|
||||
case PF1550_CHG_BAT_OVER:
|
||||
case PF1550_CHG_OFF_TEMP:
|
||||
case PF1550_CHG_LINEAR_ONLY:
|
||||
*val = POWER_SUPPLY_CHARGE_TYPE_NONE;
|
||||
break;
|
||||
default:
|
||||
*val = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Supported health statuses:
|
||||
* - POWER_SUPPLY_HEALTH_DEAD
|
||||
* - POWER_SUPPLY_HEALTH_GOOD
|
||||
* - POWER_SUPPLY_HEALTH_OVERVOLTAGE
|
||||
* - POWER_SUPPLY_HEALTH_UNKNOWN
|
||||
*/
|
||||
static int pf1550_get_battery_health(struct regmap *regmap, int *val)
|
||||
{
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PF1550_CHARG_REG_BATT_SNS, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data &= PF1550_BAT_SNS_MASK;
|
||||
|
||||
switch (data) {
|
||||
case PF1550_BAT_NO_DETECT:
|
||||
*val = POWER_SUPPLY_HEALTH_NO_BATTERY;
|
||||
break;
|
||||
case PF1550_BAT_NO_VBUS:
|
||||
case PF1550_BAT_LOW_THAN_PRECHARG:
|
||||
case PF1550_BAT_CHARG_FAIL:
|
||||
case PF1550_BAT_HIGH_THAN_PRECHARG:
|
||||
*val = POWER_SUPPLY_HEALTH_GOOD;
|
||||
break;
|
||||
case PF1550_BAT_OVER_VOL:
|
||||
*val = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
|
||||
break;
|
||||
default:
|
||||
*val = POWER_SUPPLY_HEALTH_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pf1550_get_present(struct regmap *regmap, int *val)
|
||||
{
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PF1550_CHARG_REG_BATT_SNS, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
data &= PF1550_BAT_SNS_MASK;
|
||||
*val = (data == PF1550_BAT_NO_DETECT) ? 0 : 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pf1550_get_online(struct regmap *regmap, int *val)
|
||||
{
|
||||
unsigned int data;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(regmap, PF1550_CHARG_REG_VBUS_SNS, &data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*val = (data & PF1550_VBUS_VALID) ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pf1550_chg_bat_work(struct work_struct *work)
|
||||
{
|
||||
struct pf1550_charger *chg = container_of(to_delayed_work(work),
|
||||
struct pf1550_charger,
|
||||
bat_sense_work);
|
||||
unsigned int data;
|
||||
|
||||
if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_BATT_SNS, &data)) {
|
||||
dev_err(chg->dev, "Read BATT_SNS error.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (data & PF1550_BAT_SNS_MASK) {
|
||||
case PF1550_BAT_NO_VBUS:
|
||||
dev_dbg(chg->dev, "No valid VBUS input.\n");
|
||||
break;
|
||||
case PF1550_BAT_LOW_THAN_PRECHARG:
|
||||
dev_dbg(chg->dev, "VBAT < VPRECHG.LB.\n");
|
||||
break;
|
||||
case PF1550_BAT_CHARG_FAIL:
|
||||
dev_dbg(chg->dev, "Battery charging failed.\n");
|
||||
break;
|
||||
case PF1550_BAT_HIGH_THAN_PRECHARG:
|
||||
dev_dbg(chg->dev, "VBAT > VPRECHG.LB.\n");
|
||||
break;
|
||||
case PF1550_BAT_OVER_VOL:
|
||||
dev_dbg(chg->dev, "VBAT > VBATOV.\n");
|
||||
break;
|
||||
case PF1550_BAT_NO_DETECT:
|
||||
dev_dbg(chg->dev, "Battery not detected.\n");
|
||||
break;
|
||||
default:
|
||||
dev_err(chg->dev, "Unknown value read:%x\n",
|
||||
data & PF1550_CHG_SNS_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
static void pf1550_chg_chg_work(struct work_struct *work)
|
||||
{
|
||||
struct pf1550_charger *chg = container_of(to_delayed_work(work),
|
||||
struct pf1550_charger,
|
||||
chg_sense_work);
|
||||
unsigned int data;
|
||||
|
||||
if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_SNS, &data)) {
|
||||
dev_err(chg->dev, "Read CHG_SNS error.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (data & PF1550_CHG_SNS_MASK) {
|
||||
case PF1550_CHG_PRECHARGE:
|
||||
dev_dbg(chg->dev, "In pre-charger mode.\n");
|
||||
break;
|
||||
case PF1550_CHG_CONSTANT_CURRENT:
|
||||
dev_dbg(chg->dev, "In fast-charge constant current mode.\n");
|
||||
break;
|
||||
case PF1550_CHG_CONSTANT_VOL:
|
||||
dev_dbg(chg->dev, "In fast-charge constant voltage mode.\n");
|
||||
break;
|
||||
case PF1550_CHG_EOC:
|
||||
dev_dbg(chg->dev, "In EOC mode.\n");
|
||||
break;
|
||||
case PF1550_CHG_DONE:
|
||||
dev_dbg(chg->dev, "In DONE mode.\n");
|
||||
break;
|
||||
case PF1550_CHG_TIMER_FAULT:
|
||||
dev_info(chg->dev, "In timer fault mode.\n");
|
||||
break;
|
||||
case PF1550_CHG_SUSPEND:
|
||||
dev_info(chg->dev, "In thermistor suspend mode.\n");
|
||||
break;
|
||||
case PF1550_CHG_OFF_INV:
|
||||
dev_info(chg->dev, "Input invalid, charger off.\n");
|
||||
break;
|
||||
case PF1550_CHG_BAT_OVER:
|
||||
dev_warn(chg->dev, "Battery over-voltage.\n");
|
||||
break;
|
||||
case PF1550_CHG_OFF_TEMP:
|
||||
dev_info(chg->dev, "Temp high, charger off.\n");
|
||||
break;
|
||||
case PF1550_CHG_LINEAR_ONLY:
|
||||
dev_dbg(chg->dev, "In Linear mode, not charging.\n");
|
||||
break;
|
||||
default:
|
||||
dev_err(chg->dev, "Unknown value read:%x\n",
|
||||
data & PF1550_CHG_SNS_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
static void pf1550_chg_vbus_work(struct work_struct *work)
|
||||
{
|
||||
struct pf1550_charger *chg = container_of(to_delayed_work(work),
|
||||
struct pf1550_charger,
|
||||
vbus_sense_work);
|
||||
unsigned int data;
|
||||
|
||||
if (regmap_read(chg->pf1550->regmap, PF1550_CHARG_REG_VBUS_SNS, &data)) {
|
||||
dev_err(chg->dev, "Read VBUS_SNS error.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (data & PF1550_VBUS_UVLO) {
|
||||
dev_dbg(chg->dev, "VBUS detached.\n");
|
||||
power_supply_changed(chg->battery);
|
||||
}
|
||||
if (data & PF1550_VBUS_IN2SYS)
|
||||
dev_dbg(chg->dev, "VBUS_IN2SYS_SNS.\n");
|
||||
if (data & PF1550_VBUS_OVLO)
|
||||
dev_dbg(chg->dev, "VBUS_OVLO_SNS.\n");
|
||||
if (data & PF1550_VBUS_VALID) {
|
||||
dev_dbg(chg->dev, "VBUS attached.\n");
|
||||
power_supply_changed(chg->charger);
|
||||
}
|
||||
}
|
||||
|
||||
static irqreturn_t pf1550_charger_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct pf1550_charger *chg = data;
|
||||
struct device *dev = chg->dev;
|
||||
int i, irq_type = -1;
|
||||
|
||||
for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++)
|
||||
if (irq == chg->virqs[i])
|
||||
irq_type = i;
|
||||
|
||||
switch (irq_type) {
|
||||
case PF1550_CHARG_IRQ_BAT2SOCI:
|
||||
dev_info(dev, "BAT to SYS Overcurrent interrupt.\n");
|
||||
break;
|
||||
case PF1550_CHARG_IRQ_BATI:
|
||||
schedule_delayed_work(&chg->bat_sense_work,
|
||||
msecs_to_jiffies(10));
|
||||
break;
|
||||
case PF1550_CHARG_IRQ_CHGI:
|
||||
schedule_delayed_work(&chg->chg_sense_work,
|
||||
msecs_to_jiffies(10));
|
||||
break;
|
||||
case PF1550_CHARG_IRQ_VBUSI:
|
||||
schedule_delayed_work(&chg->vbus_sense_work,
|
||||
msecs_to_jiffies(10));
|
||||
break;
|
||||
case PF1550_CHARG_IRQ_THMI:
|
||||
dev_info(dev, "Thermal interrupt.\n");
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "unknown interrupt occurred.\n");
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static enum power_supply_property pf1550_charger_props[] = {
|
||||
POWER_SUPPLY_PROP_ONLINE,
|
||||
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||
};
|
||||
|
||||
static enum power_supply_property pf1550_battery_props[] = {
|
||||
POWER_SUPPLY_PROP_STATUS,
|
||||
POWER_SUPPLY_PROP_CHARGE_TYPE,
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||
};
|
||||
|
||||
static int pf1550_charger_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct pf1550_charger *chg = power_supply_get_drvdata(psy);
|
||||
struct regmap *regmap = chg->pf1550->regmap;
|
||||
int ret = 0;
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_STATUS:
|
||||
ret = pf1550_get_charger_state(regmap, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGE_TYPE:
|
||||
ret = pf1550_get_charge_type(regmap, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
ret = pf1550_get_battery_health(regmap, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
ret = pf1550_get_present(regmap, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_ONLINE:
|
||||
ret = pf1550_get_online(regmap, &val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||
val->strval = "PF1550";
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_MANUFACTURER:
|
||||
val->strval = "NXP";
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct power_supply_desc pf1550_charger_desc = {
|
||||
.name = "pf1550-charger",
|
||||
.type = POWER_SUPPLY_TYPE_MAINS,
|
||||
.properties = pf1550_charger_props,
|
||||
.num_properties = ARRAY_SIZE(pf1550_charger_props),
|
||||
.get_property = pf1550_charger_get_property,
|
||||
};
|
||||
|
||||
static const struct power_supply_desc pf1550_battery_desc = {
|
||||
.name = "pf1550-battery",
|
||||
.type = POWER_SUPPLY_TYPE_BATTERY,
|
||||
.properties = pf1550_battery_props,
|
||||
.num_properties = ARRAY_SIZE(pf1550_battery_props),
|
||||
.get_property = pf1550_charger_get_property,
|
||||
};
|
||||
|
||||
static int pf1550_set_constant_volt(struct pf1550_charger *chg,
|
||||
unsigned int uvolt)
|
||||
{
|
||||
unsigned int data;
|
||||
|
||||
if (uvolt >= 3500000 && uvolt <= 4440000)
|
||||
data = 8 + (uvolt - 3500000) / 20000;
|
||||
else
|
||||
return dev_err_probe(chg->dev, -EINVAL,
|
||||
"Wrong value for constant voltage\n");
|
||||
|
||||
dev_dbg(chg->dev, "Charging constant voltage: %u (0x%x)\n", uvolt,
|
||||
data);
|
||||
|
||||
return regmap_update_bits(chg->pf1550->regmap,
|
||||
PF1550_CHARG_REG_BATT_REG,
|
||||
PF1550_CHARG_REG_BATT_REG_CHGCV_MASK, data);
|
||||
}
|
||||
|
||||
static int pf1550_set_min_system_volt(struct pf1550_charger *chg,
|
||||
unsigned int uvolt)
|
||||
{
|
||||
unsigned int data;
|
||||
|
||||
switch (uvolt) {
|
||||
case 3500000:
|
||||
data = 0x0;
|
||||
break;
|
||||
case 3700000:
|
||||
data = 0x1;
|
||||
break;
|
||||
case 4300000:
|
||||
data = 0x2;
|
||||
break;
|
||||
default:
|
||||
return dev_err_probe(chg->dev, -EINVAL,
|
||||
"Wrong value for minimum system voltage\n");
|
||||
}
|
||||
|
||||
data <<= PF1550_CHARG_REG_BATT_REG_VMINSYS_SHIFT;
|
||||
|
||||
dev_dbg(chg->dev, "Minimum system regulation voltage: %u (0x%x)\n",
|
||||
uvolt, data);
|
||||
|
||||
return regmap_update_bits(chg->pf1550->regmap,
|
||||
PF1550_CHARG_REG_BATT_REG,
|
||||
PF1550_CHARG_REG_BATT_REG_VMINSYS_MASK, data);
|
||||
}
|
||||
|
||||
static int pf1550_set_thermal_regulation_temp(struct pf1550_charger *chg,
|
||||
unsigned int cells)
|
||||
{
|
||||
unsigned int data;
|
||||
|
||||
switch (cells) {
|
||||
case 80:
|
||||
data = 0x0;
|
||||
break;
|
||||
case 95:
|
||||
data = 0x1;
|
||||
break;
|
||||
case 110:
|
||||
data = 0x2;
|
||||
break;
|
||||
case 125:
|
||||
data = 0x3;
|
||||
break;
|
||||
default:
|
||||
return dev_err_probe(chg->dev, -EINVAL,
|
||||
"Wrong value for thermal temperature\n");
|
||||
}
|
||||
|
||||
data <<= PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_SHIFT;
|
||||
|
||||
dev_dbg(chg->dev, "Thermal regulation loop temperature: %u (0x%x)\n",
|
||||
cells, data);
|
||||
|
||||
return regmap_update_bits(chg->pf1550->regmap,
|
||||
PF1550_CHARG_REG_THM_REG_CNFG,
|
||||
PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_MASK,
|
||||
data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets charger registers to proper and safe default values.
|
||||
*/
|
||||
static int pf1550_reg_init(struct pf1550_charger *chg)
|
||||
{
|
||||
struct power_supply_battery_info *info;
|
||||
struct device *dev = chg->dev;
|
||||
int ret;
|
||||
|
||||
/* Unmask charger interrupt, mask DPMI and reserved bit */
|
||||
ret = regmap_write(chg->pf1550->regmap, PF1550_CHARG_REG_CHG_INT_MASK,
|
||||
PF1550_CHG_INT_MASK);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Error unmask charger interrupt\n");
|
||||
|
||||
ret = pf1550_set_constant_volt(chg, chg->constant_volt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pf1550_set_min_system_volt(chg, chg->min_system_volt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = pf1550_set_thermal_regulation_temp(chg,
|
||||
chg->thermal_regulation_temp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* The PF1550 charger has 3 modes of operation. By default, the charger
|
||||
* is in mode 1; it remains off. Appropriate for applications not using
|
||||
* a battery. The other supported mode is mode 2, the charger is turned
|
||||
* on to charge a battery when present.
|
||||
*/
|
||||
if (power_supply_get_battery_info(chg->charger, &info)) {
|
||||
ret = regmap_write(chg->pf1550->regmap,
|
||||
PF1550_CHARG_REG_CHG_OPER,
|
||||
PF1550_CHG_BAT_ON);
|
||||
if (ret)
|
||||
return dev_err_probe(dev, ret,
|
||||
"Error turn on charger\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pf1550_dt_parse_dev_info(struct pf1550_charger *chg)
|
||||
{
|
||||
struct power_supply_battery_info *info;
|
||||
struct device *dev = chg->dev;
|
||||
|
||||
if (device_property_read_u32(dev->parent, "nxp,min-system-microvolt",
|
||||
&chg->min_system_volt))
|
||||
chg->min_system_volt = PF1550_DEFAULT_MIN_SYSTEM_VOLT;
|
||||
|
||||
if (device_property_read_u32(dev->parent,
|
||||
"nxp,thermal-regulation-celsius",
|
||||
&chg->thermal_regulation_temp))
|
||||
chg->thermal_regulation_temp = PF1550_DEFAULT_THERMAL_TEMP;
|
||||
|
||||
if (power_supply_get_battery_info(chg->charger, &info))
|
||||
chg->constant_volt = PF1550_DEFAULT_CONSTANT_VOLT;
|
||||
else
|
||||
chg->constant_volt = info->constant_charge_voltage_max_uv;
|
||||
}
|
||||
|
||||
static int pf1550_charger_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct pf1550_ddata *pf1550 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct power_supply_config psy_cfg = {};
|
||||
struct pf1550_charger *chg;
|
||||
int i, irq, ret;
|
||||
|
||||
chg = devm_kzalloc(&pdev->dev, sizeof(*chg), GFP_KERNEL);
|
||||
if (!chg)
|
||||
return -ENOMEM;
|
||||
|
||||
chg->dev = &pdev->dev;
|
||||
chg->pf1550 = pf1550;
|
||||
|
||||
if (!chg->pf1550->regmap)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV,
|
||||
"failed to get regmap\n");
|
||||
|
||||
platform_set_drvdata(pdev, chg);
|
||||
|
||||
ret = devm_delayed_work_autocancel(chg->dev, &chg->vbus_sense_work,
|
||||
pf1550_chg_vbus_work);
|
||||
if (ret)
|
||||
return dev_err_probe(chg->dev, ret,
|
||||
"failed to add vbus sense work\n");
|
||||
|
||||
ret = devm_delayed_work_autocancel(chg->dev, &chg->chg_sense_work,
|
||||
pf1550_chg_chg_work);
|
||||
if (ret)
|
||||
return dev_err_probe(chg->dev, ret,
|
||||
"failed to add charger sense work\n");
|
||||
|
||||
ret = devm_delayed_work_autocancel(chg->dev, &chg->bat_sense_work,
|
||||
pf1550_chg_bat_work);
|
||||
if (ret)
|
||||
return dev_err_probe(chg->dev, ret,
|
||||
"failed to add battery sense work\n");
|
||||
|
||||
for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
chg->virqs[i] = irq;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
pf1550_charger_irq_handler,
|
||||
IRQF_NO_SUSPEND,
|
||||
"pf1550-charger", chg);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"failed irq request\n");
|
||||
}
|
||||
|
||||
psy_cfg.drv_data = chg;
|
||||
|
||||
chg->charger = devm_power_supply_register(&pdev->dev,
|
||||
&pf1550_charger_desc,
|
||||
&psy_cfg);
|
||||
if (IS_ERR(chg->charger))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(chg->charger),
|
||||
"failed: power supply register\n");
|
||||
|
||||
chg->battery = devm_power_supply_register(&pdev->dev,
|
||||
&pf1550_battery_desc,
|
||||
&psy_cfg);
|
||||
if (IS_ERR(chg->battery))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(chg->battery),
|
||||
"failed: power supply register\n");
|
||||
|
||||
pf1550_dt_parse_dev_info(chg);
|
||||
|
||||
return pf1550_reg_init(chg);
|
||||
}
|
||||
|
||||
static const struct platform_device_id pf1550_charger_id[] = {
|
||||
{ "pf1550-charger", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, pf1550_charger_id);
|
||||
|
||||
static struct platform_driver pf1550_charger_driver = {
|
||||
.driver = {
|
||||
.name = "pf1550-charger",
|
||||
},
|
||||
.probe = pf1550_charger_probe,
|
||||
.id_table = pf1550_charger_id,
|
||||
};
|
||||
module_platform_driver(pf1550_charger_driver);
|
||||
|
||||
MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
|
||||
MODULE_DESCRIPTION("PF1550 charger driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -500,6 +500,16 @@ config REGULATOR_ISL6271A
|
|||
help
|
||||
This driver supports ISL6271A voltage regulator chip.
|
||||
|
||||
config REGULATOR_FP9931
|
||||
tristate "FitiPower FP9931/JD9930 EPD regulator"
|
||||
depends on I2C
|
||||
select REGMAP_I2C
|
||||
help
|
||||
This driver supports the FP9931/JD9930 voltage regulator chip
|
||||
which is used to provide power to Electronic Paper Displays
|
||||
so it is found in E-Book readers.
|
||||
If HWWON is enabled, it also provides temperature measurement.
|
||||
|
||||
config REGULATOR_LM363X
|
||||
tristate "TI LM363X voltage regulators"
|
||||
depends on MFD_TI_LMU
|
||||
|
|
@ -881,6 +891,16 @@ config REGULATOR_MT6315
|
|||
This driver supports the control of different power rails of device
|
||||
through regulator interface.
|
||||
|
||||
config REGULATOR_MT6316
|
||||
tristate "MT6316 SPMI PMIC regulator driver"
|
||||
depends on SPMI
|
||||
select REGMAP_SPMI
|
||||
help
|
||||
Say Y here to enable support for 2+2, 3+1 and 4 phase regulators
|
||||
found in the MediaTek MT6316 BP, CP, DP, HP, VP and TP SPMI PMICs.
|
||||
This driver supports the control of different power rails of device
|
||||
through regulator interface.
|
||||
|
||||
config REGULATOR_MT6323
|
||||
tristate "MediaTek MT6323 PMIC"
|
||||
depends on MFD_MT6397
|
||||
|
|
@ -944,6 +964,16 @@ config REGULATOR_MT6360
|
|||
2-channel buck with Thermal Shutdown and Overload Protection
|
||||
6-channel High PSRR and Low Dropout LDO.
|
||||
|
||||
config REGULATOR_MT6363
|
||||
tristate "MT6363 SPMI PMIC regulator driver"
|
||||
depends on SPMI
|
||||
select REGMAP_SPMI
|
||||
help
|
||||
Say Y here to enable support for regulators found in the MediaTek
|
||||
MT6363 SPMI PMIC.
|
||||
This driver supports the control of different power rails of device
|
||||
through regulator interface.
|
||||
|
||||
config REGULATOR_MT6370
|
||||
tristate "MT6370 SubPMIC Regulator"
|
||||
depends on MFD_MT6370
|
||||
|
|
@ -1086,6 +1116,15 @@ config REGULATOR_PV88090
|
|||
Say y here to support the voltage regulators and convertors
|
||||
on PV88090
|
||||
|
||||
config REGULATOR_PF1550
|
||||
tristate "NXP PF1550 regulator"
|
||||
depends on MFD_PF1550
|
||||
help
|
||||
Say y here to select this option to enable the regulators on
|
||||
the PF1550 PMICs.
|
||||
This driver controls the PF1550 regulators via I2C bus.
|
||||
The regulators include three bucks and three ldos.
|
||||
|
||||
config REGULATOR_PWM
|
||||
tristate "PWM voltage regulator"
|
||||
depends on PWM
|
||||
|
|
@ -1181,6 +1220,7 @@ config REGULATOR_RAA215300
|
|||
|
||||
config REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY
|
||||
tristate "Raspberry Pi 7-inch touchscreen panel ATTINY regulator"
|
||||
depends on ARM || ARM64 || COMPILE_TEST
|
||||
depends on BACKLIGHT_CLASS_DEVICE
|
||||
depends on I2C
|
||||
depends on OF_GPIO
|
||||
|
|
@ -1192,6 +1232,7 @@ config REGULATOR_RASPBERRYPI_TOUCHSCREEN_ATTINY
|
|||
|
||||
config REGULATOR_RASPBERRYPI_TOUCHSCREEN_V2
|
||||
tristate "Raspberry Pi 7-inch touchscreen panel V2 regulator"
|
||||
depends on ARM || ARM64 || COMPILE_TEST
|
||||
depends on GPIOLIB
|
||||
depends on I2C && OF
|
||||
select GPIO_REGMAP
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ obj-$(CONFIG_REGULATOR_HI6421V600) += hi6421v600-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_HI655X) += hi655x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_ISL9305) += isl9305.o
|
||||
obj-$(CONFIG_REGULATOR_FP9931) += fp9931.o
|
||||
obj-$(CONFIG_REGULATOR_LM363X) += lm363x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_LOCHNAGAR) += lochnagar-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
|
||||
|
|
@ -105,6 +106,7 @@ obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o
|
|||
obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
|
||||
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6315) += mt6315-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6315) += mt6316-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6331) += mt6331-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6332) += mt6332-regulator.o
|
||||
|
|
@ -112,6 +114,7 @@ obj-$(CONFIG_REGULATOR_MT6357) += mt6357-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_MT6358) += mt6358-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6359) += mt6359-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6360) += mt6360-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6363) += mt6363-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6370) += mt6370-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
|
||||
|
|
@ -128,6 +131,7 @@ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
|
|||
obj-$(CONFIG_REGULATOR_PCA9450) += pca9450-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PF0900) += pf0900-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PF9453) += pf9453-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PF1550) += pf1550-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PF530X) += pf530x-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PF8X00) += pf8x00-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
|
||||
|
|
|
|||
|
|
@ -173,9 +173,9 @@ static int set_hw_dvs_levels(struct device_node *np,
|
|||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
struct bd71815_regulator *data;
|
||||
const struct bd71815_regulator *data;
|
||||
|
||||
data = container_of(desc, struct bd71815_regulator, desc);
|
||||
data = container_of_const(desc, struct bd71815_regulator, desc);
|
||||
return rohm_regulator_set_dvs_levels(data->dvs, np, desc, cfg->regmap);
|
||||
}
|
||||
|
||||
|
|
@ -195,10 +195,10 @@ static int buck12_set_hw_dvs_levels(struct device_node *np,
|
|||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
struct bd71815_regulator *data;
|
||||
const struct bd71815_regulator *data;
|
||||
int ret = 0, val;
|
||||
|
||||
data = container_of(desc, struct bd71815_regulator, desc);
|
||||
data = container_of_const(desc, struct bd71815_regulator, desc);
|
||||
|
||||
if (of_property_present(np, "rohm,dvs-run-voltage") ||
|
||||
of_property_present(np, "rohm,dvs-suspend-voltage") ||
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@ static int buck_set_hw_dvs_levels(struct device_node *np,
|
|||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
struct bd71828_regulator_data *data;
|
||||
const struct bd71828_regulator_data *data;
|
||||
|
||||
data = container_of(desc, struct bd71828_regulator_data, desc);
|
||||
data = container_of_const(desc, struct bd71828_regulator_data, desc);
|
||||
|
||||
return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -698,9 +698,9 @@ static int buck_set_hw_dvs_levels(struct device_node *np,
|
|||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
struct bd718xx_regulator_data *data;
|
||||
const struct bd718xx_regulator_data *data;
|
||||
|
||||
data = container_of(desc, struct bd718xx_regulator_data, desc);
|
||||
data = container_of_const(desc, struct bd718xx_regulator_data, desc);
|
||||
|
||||
return rohm_regulator_set_dvs_levels(&data->dvs, np, desc, cfg->regmap);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,12 +337,12 @@ static int ldo_map_notif(int irq, struct regulator_irq_data *rid,
|
|||
int i;
|
||||
|
||||
for (i = 0; i < rid->num_states; i++) {
|
||||
struct bd96801_regulator_data *rdata;
|
||||
const struct bd96801_regulator_data *rdata;
|
||||
struct regulator_dev *rdev;
|
||||
|
||||
rdev = rid->states[i].rdev;
|
||||
rdata = container_of(rdev->desc, struct bd96801_regulator_data,
|
||||
desc);
|
||||
rdata = container_of_const(rdev->desc, struct bd96801_regulator_data,
|
||||
desc);
|
||||
rid->states[i].notifs = regulator_err2notif(rdata->ldo_errs);
|
||||
rid->states[i].errors = rdata->ldo_errs;
|
||||
*dev_mask |= BIT(i);
|
||||
|
|
@ -354,9 +354,9 @@ static int bd96801_list_voltage_lr(struct regulator_dev *rdev,
|
|||
unsigned int selector)
|
||||
{
|
||||
int voltage;
|
||||
struct bd96801_regulator_data *data;
|
||||
const struct bd96801_regulator_data *data;
|
||||
|
||||
data = container_of(rdev->desc, struct bd96801_regulator_data, desc);
|
||||
data = container_of_const(rdev->desc, struct bd96801_regulator_data, desc);
|
||||
|
||||
/*
|
||||
* The BD096801 has voltage setting in two registers. One giving the
|
||||
|
|
|
|||
|
|
@ -83,6 +83,19 @@ struct regulator_supply_alias {
|
|||
const char *alias_supply;
|
||||
};
|
||||
|
||||
/*
|
||||
* Work item used to forward regulator events.
|
||||
*
|
||||
* @work: workqueue entry
|
||||
* @rdev: regulator device to notify (consumer receiving the forwarded event)
|
||||
* @event: event code to be forwarded
|
||||
*/
|
||||
struct regulator_event_work {
|
||||
struct work_struct work;
|
||||
struct regulator_dev *rdev;
|
||||
unsigned long event;
|
||||
};
|
||||
|
||||
static int _regulator_is_enabled(struct regulator_dev *rdev);
|
||||
static int _regulator_disable(struct regulator *regulator);
|
||||
static int _regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags);
|
||||
|
|
@ -1618,6 +1631,8 @@ static int set_machine_constraints(struct regulator_dev *rdev)
|
|||
* and we have control then make sure it is enabled.
|
||||
*/
|
||||
if (rdev->constraints->always_on || rdev->constraints->boot_on) {
|
||||
bool supply_enabled = false;
|
||||
|
||||
/* If we want to enable this regulator, make sure that we know
|
||||
* the supplying regulator.
|
||||
*/
|
||||
|
|
@ -1637,11 +1652,14 @@ static int set_machine_constraints(struct regulator_dev *rdev)
|
|||
rdev->supply = NULL;
|
||||
return ret;
|
||||
}
|
||||
supply_enabled = true;
|
||||
}
|
||||
|
||||
ret = _regulator_do_enable(rdev);
|
||||
if (ret < 0 && ret != -EINVAL) {
|
||||
rdev_err(rdev, "failed to enable: %pe\n", ERR_PTR(ret));
|
||||
if (supply_enabled)
|
||||
regulator_disable(rdev->supply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -1658,6 +1676,104 @@ static int set_machine_constraints(struct regulator_dev *rdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* regulator_event_work_fn - process a deferred regulator event
|
||||
* @work: work_struct queued by the notifier
|
||||
*
|
||||
* Calls the regulator's notifier chain in process context while holding
|
||||
* the rdev lock, then releases the device reference.
|
||||
*/
|
||||
static void regulator_event_work_fn(struct work_struct *work)
|
||||
{
|
||||
struct regulator_event_work *rew =
|
||||
container_of(work, struct regulator_event_work, work);
|
||||
struct regulator_dev *rdev = rew->rdev;
|
||||
int ret;
|
||||
|
||||
regulator_lock(rdev);
|
||||
ret = regulator_notifier_call_chain(rdev, rew->event, NULL);
|
||||
regulator_unlock(rdev);
|
||||
if (ret == NOTIFY_BAD)
|
||||
dev_err(rdev_get_dev(rdev), "failed to forward regulator event\n");
|
||||
|
||||
put_device(rdev_get_dev(rdev));
|
||||
kfree(rew);
|
||||
}
|
||||
|
||||
/**
|
||||
* regulator_event_forward_notifier - notifier callback for supply events
|
||||
* @nb: notifier block embedded in the regulator
|
||||
* @event: regulator event code
|
||||
* @data: unused
|
||||
*
|
||||
* Packages the event into a work item and schedules it in process context.
|
||||
* Takes a reference on @rdev->dev to pin the regulator until the work
|
||||
* completes (see put_device() in the worker).
|
||||
*
|
||||
* Return: NOTIFY_OK on success, NOTIFY_DONE for events that are not forwarded.
|
||||
*/
|
||||
static int regulator_event_forward_notifier(struct notifier_block *nb,
|
||||
unsigned long event,
|
||||
void __always_unused *data)
|
||||
{
|
||||
struct regulator_dev *rdev = container_of(nb, struct regulator_dev,
|
||||
supply_fwd_nb);
|
||||
struct regulator_event_work *rew;
|
||||
|
||||
switch (event) {
|
||||
case REGULATOR_EVENT_UNDER_VOLTAGE:
|
||||
break;
|
||||
default:
|
||||
/* Only forward allowed events downstream. */
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
rew = kmalloc(sizeof(*rew), GFP_ATOMIC);
|
||||
if (!rew)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
get_device(rdev_get_dev(rdev));
|
||||
rew->rdev = rdev;
|
||||
rew->event = event;
|
||||
INIT_WORK(&rew->work, regulator_event_work_fn);
|
||||
|
||||
queue_work(system_highpri_wq, &rew->work);
|
||||
|
||||
return NOTIFY_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* register_regulator_event_forwarding - enable supply event forwarding
|
||||
* @rdev: regulator device
|
||||
*
|
||||
* Registers a notifier on the regulator's supply so that supply events
|
||||
* are forwarded to the consumer regulator via the deferred work handler.
|
||||
*
|
||||
* Return: 0 on success, -EALREADY if already enabled, or a negative error code.
|
||||
*/
|
||||
static int register_regulator_event_forwarding(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!rdev->supply)
|
||||
return 0; /* top-level regulator: nothing to forward */
|
||||
|
||||
if (rdev->supply_fwd_nb.notifier_call)
|
||||
return -EALREADY;
|
||||
|
||||
rdev->supply_fwd_nb.notifier_call = regulator_event_forward_notifier;
|
||||
|
||||
ret = regulator_register_notifier(rdev->supply, &rdev->supply_fwd_nb);
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "failed to register supply notifier: %pe\n",
|
||||
ERR_PTR(ret));
|
||||
rdev->supply_fwd_nb.notifier_call = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set_supply - set regulator supply regulator
|
||||
* @rdev: regulator (locked)
|
||||
|
|
@ -1942,6 +2058,7 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
|
|||
{
|
||||
struct regulator_supply_alias *map;
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
map = regulator_find_supply_alias(*dev, *supply);
|
||||
if (map) {
|
||||
dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
|
||||
|
|
@ -1950,6 +2067,7 @@ static void regulator_supply_alias(struct device **dev, const char **supply)
|
|||
*dev = map->alias_dev;
|
||||
*supply = map->alias_supply;
|
||||
}
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
}
|
||||
|
||||
static int regulator_match(struct device *dev, const void *data)
|
||||
|
|
@ -2144,6 +2262,16 @@ static int regulator_resolve_supply(struct regulator_dev *rdev)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Automatically register for event forwarding from the new supply.
|
||||
* This creates the downstream propagation link for events like
|
||||
* under-voltage.
|
||||
*/
|
||||
ret = register_regulator_event_forwarding(rdev);
|
||||
if (ret < 0)
|
||||
rdev_warn(rdev, "Failed to register event forwarding: %pe\n",
|
||||
ERR_PTR(ret));
|
||||
|
||||
regulator_unlock_two(rdev, r, &ww_ctx);
|
||||
|
||||
/* rdev->supply was created in set_supply() */
|
||||
|
|
@ -2492,22 +2620,26 @@ int regulator_register_supply_alias(struct device *dev, const char *id,
|
|||
const char *alias_id)
|
||||
{
|
||||
struct regulator_supply_alias *map;
|
||||
struct regulator_supply_alias *new_map;
|
||||
|
||||
map = regulator_find_supply_alias(dev, id);
|
||||
if (map)
|
||||
return -EEXIST;
|
||||
|
||||
map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
|
||||
if (!map)
|
||||
new_map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
|
||||
if (!new_map)
|
||||
return -ENOMEM;
|
||||
|
||||
map->src_dev = dev;
|
||||
map->src_supply = id;
|
||||
map->alias_dev = alias_dev;
|
||||
map->alias_supply = alias_id;
|
||||
|
||||
list_add(&map->list, ®ulator_supply_alias_list);
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
map = regulator_find_supply_alias(dev, id);
|
||||
if (map) {
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
kfree(new_map);
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
new_map->src_dev = dev;
|
||||
new_map->src_supply = id;
|
||||
new_map->alias_dev = alias_dev;
|
||||
new_map->alias_supply = alias_id;
|
||||
list_add(&new_map->list, ®ulator_supply_alias_list);
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
pr_info("Adding alias for supply %s,%s -> %s,%s\n",
|
||||
id, dev_name(dev), alias_id, dev_name(alias_dev));
|
||||
|
||||
|
|
@ -2527,11 +2659,13 @@ void regulator_unregister_supply_alias(struct device *dev, const char *id)
|
|||
{
|
||||
struct regulator_supply_alias *map;
|
||||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
map = regulator_find_supply_alias(dev, id);
|
||||
if (map) {
|
||||
list_del(&map->list);
|
||||
kfree(map);
|
||||
}
|
||||
mutex_unlock(®ulator_list_mutex);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
|
||||
|
||||
|
|
@ -2616,6 +2750,13 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
|
|||
|
||||
mutex_lock(®ulator_list_mutex);
|
||||
|
||||
if (gpiod_is_shared(gpiod))
|
||||
/*
|
||||
* The sharing of this GPIO pin is managed internally by
|
||||
* GPIOLIB. We don't need to keep track of its enable count.
|
||||
*/
|
||||
goto skip_compare;
|
||||
|
||||
list_for_each_entry(pin, ®ulator_ena_gpio_list, list) {
|
||||
if (gpiod_is_equal(pin->gpiod, gpiod)) {
|
||||
rdev_dbg(rdev, "GPIO is already used\n");
|
||||
|
|
@ -2628,6 +2769,7 @@ static int regulator_ena_gpio_request(struct regulator_dev *rdev,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
skip_compare:
|
||||
pin = new_pin;
|
||||
new_pin = NULL;
|
||||
|
||||
|
|
@ -6031,6 +6173,9 @@ void regulator_unregister(struct regulator_dev *rdev)
|
|||
return;
|
||||
|
||||
if (rdev->supply) {
|
||||
regulator_unregister_notifier(rdev->supply,
|
||||
&rdev->supply_fwd_nb);
|
||||
|
||||
while (rdev->use_count--)
|
||||
regulator_disable(rdev->supply);
|
||||
regulator_put(rdev->supply);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,551 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
// Copyright (C) 2025 Andreas Kemnade
|
||||
|
||||
/* Datasheet: https://www.fitipower.com/dl/file/flXa6hIchVeu0W3K */
|
||||
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/hwmon.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define FP9931_REG_TMST_VALUE 0
|
||||
#define FP9931_REG_VCOM_SETTING 1
|
||||
#define FP9931_REG_VPOSNEG_SETTING 2
|
||||
#define FP9931_REG_PWRON_DELAY 3
|
||||
#define FP9931_REG_CONTROL_REG1 11
|
||||
|
||||
#define PGOOD_TIMEOUT_MSECS 200
|
||||
|
||||
struct fp9931_data {
|
||||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct regulator *vin_reg;
|
||||
struct gpio_desc *pgood_gpio;
|
||||
struct gpio_desc *en_gpio;
|
||||
struct gpio_desc *en_ts_gpio;
|
||||
struct completion pgood_completion;
|
||||
int pgood_irq;
|
||||
};
|
||||
|
||||
static const unsigned int VPOSNEG_table[] = {
|
||||
7040000,
|
||||
7040000,
|
||||
7040000,
|
||||
7040000,
|
||||
7040000,
|
||||
7040000,
|
||||
7260000,
|
||||
7490000,
|
||||
7710000,
|
||||
7930000,
|
||||
8150000,
|
||||
8380000,
|
||||
8600000,
|
||||
8820000,
|
||||
9040000,
|
||||
9270000,
|
||||
9490000,
|
||||
9710000,
|
||||
9940000,
|
||||
10160000,
|
||||
10380000,
|
||||
10600000,
|
||||
10830000,
|
||||
11050000,
|
||||
11270000,
|
||||
11490000,
|
||||
11720000,
|
||||
11940000,
|
||||
12160000,
|
||||
12380000,
|
||||
12610000,
|
||||
12830000,
|
||||
13050000,
|
||||
13280000,
|
||||
13500000,
|
||||
13720000,
|
||||
13940000,
|
||||
14170000,
|
||||
14390000,
|
||||
14610000,
|
||||
14830000,
|
||||
15060000,
|
||||
};
|
||||
|
||||
static const struct hwmon_channel_info *fp9931_info[] = {
|
||||
HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
|
||||
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
|
||||
NULL
|
||||
};
|
||||
|
||||
static int setup_timings(struct fp9931_data *data)
|
||||
{
|
||||
u32 tdly[4];
|
||||
u8 tdlys = 0;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
ret = device_property_count_u32(data->dev, "fitipower,tdly-ms");
|
||||
if (ret == -EINVAL) /* property is optional */
|
||||
return 0;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (ret != ARRAY_SIZE(tdly)) {
|
||||
dev_err(data->dev, "invalid delay specification");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = device_property_read_u32_array(data->dev, "fitipower,tdly-ms",
|
||||
tdly, ARRAY_SIZE(tdly));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = ARRAY_SIZE(tdly) - 1; i >= 0; i--) {
|
||||
if (tdly[i] > 4 || tdly[i] == 3)
|
||||
return -EINVAL;
|
||||
|
||||
if (tdly[i] == 4) /* convert from ms */
|
||||
tdly[i] = 3;
|
||||
|
||||
tdlys <<= 2;
|
||||
tdlys |= tdly[i];
|
||||
}
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_write(data->regmap, FP9931_REG_PWRON_DELAY, tdlys);
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fp9931_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
|
||||
u32 attr, int channel, long *temp)
|
||||
{
|
||||
struct fp9931_data *data = dev_get_drvdata(dev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(data->regmap, FP9931_REG_TMST_VALUE, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
*temp = (s8)val * 1000;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static umode_t fp9931_hwmon_is_visible(const void *data,
|
||||
enum hwmon_sensor_types type,
|
||||
u32 attr, int channel)
|
||||
{
|
||||
return 0444;
|
||||
}
|
||||
|
||||
static const struct hwmon_ops fp9931_hwmon_ops = {
|
||||
.is_visible = fp9931_hwmon_is_visible,
|
||||
.read = fp9931_hwmon_read,
|
||||
};
|
||||
|
||||
static const struct hwmon_chip_info fp9931_chip_info = {
|
||||
.ops = &fp9931_hwmon_ops,
|
||||
.info = fp9931_info,
|
||||
};
|
||||
|
||||
static int fp9931_runtime_suspend(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct fp9931_data *data = dev_get_drvdata(dev);
|
||||
|
||||
if (data->en_ts_gpio)
|
||||
gpiod_set_value_cansleep(data->en_ts_gpio, 0);
|
||||
|
||||
if (data->vin_reg) {
|
||||
ret = regulator_disable(data->vin_reg);
|
||||
regcache_mark_dirty(data->regmap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fp9931_runtime_resume(struct device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct fp9931_data *data = dev_get_drvdata(dev);
|
||||
|
||||
if (data->vin_reg)
|
||||
ret = regulator_enable(data->vin_reg);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (data->en_ts_gpio) {
|
||||
gpiod_set_value_cansleep(data->en_ts_gpio, 1);
|
||||
/* wait for one ADC conversion to have sane temperature */
|
||||
usleep_range(10000, 15000);
|
||||
}
|
||||
|
||||
ret = regcache_sync(data->regmap);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool fp9931_volatile_reg(struct device *dev, unsigned int reg)
|
||||
{
|
||||
return reg == FP9931_REG_TMST_VALUE;
|
||||
}
|
||||
|
||||
static const struct reg_default fp9931_reg_default = {
|
||||
.reg = FP9931_REG_VCOM_SETTING,
|
||||
.def = 0x80,
|
||||
};
|
||||
|
||||
static const struct regmap_config regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
.max_register = 12,
|
||||
.cache_type = REGCACHE_FLAT,
|
||||
.volatile_reg = fp9931_volatile_reg,
|
||||
.reg_defaults = &fp9931_reg_default,
|
||||
.num_reg_defaults = 1,
|
||||
};
|
||||
|
||||
static void disable_nopm(void *d)
|
||||
{
|
||||
struct fp9931_data *data = d;
|
||||
|
||||
fp9931_runtime_suspend(data->dev);
|
||||
}
|
||||
|
||||
static int fp9931_v3p3_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct fp9931_data *data = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regulator_enable_regmap(rdev);
|
||||
if (ret < 0)
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fp9931_v3p3_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct fp9931_data *data = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = regulator_disable_regmap(rdev);
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fp9931_v3p3_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct fp9931_data *data = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
if (pm_runtime_status_suspended(data->dev))
|
||||
return 0;
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
ret = regulator_is_enabled_regmap(rdev);
|
||||
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct regulator_ops fp9931_v3p3ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.enable = fp9931_v3p3_enable,
|
||||
.disable = fp9931_v3p3_disable,
|
||||
.is_enabled = fp9931_v3p3_is_enabled,
|
||||
};
|
||||
|
||||
static int fp9931_check_powergood(struct regulator_dev *rdev)
|
||||
{
|
||||
struct fp9931_data *data = rdev_get_drvdata(rdev);
|
||||
|
||||
if (pm_runtime_status_suspended(data->dev))
|
||||
return 0;
|
||||
|
||||
return gpiod_get_value_cansleep(data->pgood_gpio);
|
||||
}
|
||||
|
||||
static int fp9931_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct fp9931_data *data = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regulator_get_voltage_sel_regmap(rdev);
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fp9931_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector)
|
||||
{
|
||||
struct fp9931_data *data = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = regulator_set_voltage_sel_regmap(rdev, selector);
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t pgood_handler(int irq, void *dev_id)
|
||||
{
|
||||
struct fp9931_data *data = dev_id;
|
||||
|
||||
complete(&data->pgood_completion);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int fp9931_set_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct fp9931_data *data = rdev_get_drvdata(rdev);
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_resume_and_get(data->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
reinit_completion(&data->pgood_completion);
|
||||
gpiod_set_value_cansleep(data->en_gpio, 1);
|
||||
dev_dbg(data->dev, "turning on...");
|
||||
wait_for_completion_timeout(&data->pgood_completion,
|
||||
msecs_to_jiffies(PGOOD_TIMEOUT_MSECS));
|
||||
dev_dbg(data->dev, "turned on");
|
||||
if (gpiod_get_value_cansleep(data->pgood_gpio) != 1) {
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fp9931_clear_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct fp9931_data *data = rdev_get_drvdata(rdev);
|
||||
|
||||
gpiod_set_value_cansleep(data->en_gpio, 0);
|
||||
pm_runtime_put_autosuspend(data->dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct regulator_ops fp9931_vcom_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.enable = fp9931_set_enable,
|
||||
.disable = fp9931_clear_enable,
|
||||
.is_enabled = fp9931_check_powergood,
|
||||
.set_voltage_sel = fp9931_set_voltage_sel,
|
||||
.get_voltage_sel = fp9931_get_voltage_sel,
|
||||
};
|
||||
|
||||
static const struct regulator_ops fp9931_vposneg_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.map_voltage = regulator_map_voltage_ascend,
|
||||
/* gets enabled by enabling vcom, too */
|
||||
.is_enabled = fp9931_check_powergood,
|
||||
.set_voltage_sel = fp9931_set_voltage_sel,
|
||||
.get_voltage_sel = fp9931_get_voltage_sel,
|
||||
};
|
||||
|
||||
static const struct regulator_desc regulators[] = {
|
||||
{
|
||||
.name = "v3p3",
|
||||
.of_match = of_match_ptr("v3p3"),
|
||||
.id = 0,
|
||||
.ops = &fp9931_v3p3ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = FP9931_REG_CONTROL_REG1,
|
||||
.enable_mask = BIT(1),
|
||||
.n_voltages = 1,
|
||||
.min_uV = 3300000
|
||||
},
|
||||
{
|
||||
.name = "vposneg",
|
||||
.of_match = of_match_ptr("vposneg"),
|
||||
.id = 1,
|
||||
.ops = &fp9931_vposneg_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(VPOSNEG_table),
|
||||
.vsel_reg = FP9931_REG_VPOSNEG_SETTING,
|
||||
.vsel_mask = 0x3F,
|
||||
.volt_table = VPOSNEG_table,
|
||||
},
|
||||
{
|
||||
.name = "vcom",
|
||||
.of_match = of_match_ptr("vcom"),
|
||||
.id = 2,
|
||||
.ops = &fp9931_vcom_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 255,
|
||||
.min_uV = 0,
|
||||
.uV_step = 5000000 / 255,
|
||||
.vsel_reg = FP9931_REG_VCOM_SETTING,
|
||||
.vsel_mask = 0xFF
|
||||
},
|
||||
};
|
||||
|
||||
static int fp9931_probe(struct i2c_client *client)
|
||||
{
|
||||
struct fp9931_data *data;
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev *rdev;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
data->regmap = devm_regmap_init_i2c(client, ®map_config);
|
||||
if (IS_ERR(data->regmap))
|
||||
return dev_err_probe(&client->dev, PTR_ERR(data->regmap),
|
||||
"failed to allocate regmap!\n");
|
||||
|
||||
data->vin_reg = devm_regulator_get_optional(&client->dev, "vin");
|
||||
if (IS_ERR(data->vin_reg))
|
||||
return dev_err_probe(&client->dev, PTR_ERR(data->vin_reg),
|
||||
"failed to get vin regulator\n");
|
||||
|
||||
data->pgood_gpio = devm_gpiod_get(&client->dev, "pg", GPIOD_IN);
|
||||
if (IS_ERR(data->pgood_gpio))
|
||||
return dev_err_probe(&client->dev,
|
||||
PTR_ERR(data->pgood_gpio),
|
||||
"failed to get power good gpio\n");
|
||||
|
||||
data->pgood_irq = gpiod_to_irq(data->pgood_gpio);
|
||||
if (data->pgood_irq < 0)
|
||||
return data->pgood_irq;
|
||||
|
||||
data->en_gpio = devm_gpiod_get(&client->dev, "enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(data->en_gpio))
|
||||
return dev_err_probe(&client->dev, PTR_ERR(data->en_gpio),
|
||||
"failed to get en gpio\n");
|
||||
|
||||
data->en_ts_gpio = devm_gpiod_get_optional(&client->dev, "en-ts", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(data->en_ts_gpio))
|
||||
return dev_err_probe(&client->dev,
|
||||
PTR_ERR(data->en_ts_gpio),
|
||||
"failed to get en gpio\n");
|
||||
|
||||
data->dev = &client->dev;
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
init_completion(&data->pgood_completion);
|
||||
|
||||
ret = devm_request_threaded_irq(&client->dev, data->pgood_irq, NULL,
|
||||
pgood_handler,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
"PGOOD", data);
|
||||
if (ret)
|
||||
return dev_err_probe(&client->dev, ret,
|
||||
"failed to request irq\n");
|
||||
|
||||
if (IS_ENABLED(CONFIG_PM)) {
|
||||
devm_pm_runtime_enable(&client->dev);
|
||||
pm_runtime_set_autosuspend_delay(&client->dev, 4000);
|
||||
pm_runtime_use_autosuspend(&client->dev);
|
||||
} else {
|
||||
ret = fp9931_runtime_resume(&client->dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
devm_add_action_or_reset(&client->dev, disable_nopm, data);
|
||||
}
|
||||
|
||||
ret = setup_timings(data);
|
||||
if (ret)
|
||||
return dev_err_probe(&client->dev, ret, "failed to setup timings\n");
|
||||
|
||||
config.driver_data = data;
|
||||
config.dev = &client->dev;
|
||||
config.regmap = data->regmap;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regulators); i++) {
|
||||
rdev = devm_regulator_register(&client->dev, ®ulators[i],
|
||||
&config);
|
||||
if (IS_ERR(rdev))
|
||||
return dev_err_probe(&client->dev, PTR_ERR(rdev),
|
||||
"failed to register %s regulator\n",
|
||||
regulators[i].name);
|
||||
}
|
||||
|
||||
if (IS_REACHABLE(CONFIG_HWMON)) {
|
||||
struct device *hwmon_dev;
|
||||
|
||||
hwmon_dev = devm_hwmon_device_register_with_info(&client->dev, "fp9931", data,
|
||||
&fp9931_chip_info, NULL);
|
||||
if (IS_ERR(hwmon_dev))
|
||||
dev_notice(&client->dev, "failed to register hwmon\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops fp9931_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(fp9931_runtime_suspend, fp9931_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id fp9931_dt_ids[] = {
|
||||
{
|
||||
.compatible = "fitipower,fp9931",
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, fp9931_dt_ids);
|
||||
|
||||
static struct i2c_driver fp9931_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "fp9931",
|
||||
.of_match_table = fp9931_dt_ids,
|
||||
.pm = &fp9931_pm_ops,
|
||||
},
|
||||
.probe = fp9931_probe,
|
||||
};
|
||||
|
||||
module_i2c_driver(fp9931_i2c_driver);
|
||||
|
||||
/* Module information */
|
||||
MODULE_DESCRIPTION("FP9931 regulator driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
|
@ -387,7 +387,7 @@ static unsigned int hi6421_regulator_ldo_get_mode(struct regulator_dev *rdev)
|
|||
const struct hi6421_regulator_info *info;
|
||||
unsigned int reg_val;
|
||||
|
||||
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val);
|
||||
if (reg_val & info->mode_mask)
|
||||
return REGULATOR_MODE_IDLE;
|
||||
|
|
@ -400,7 +400,7 @@ static unsigned int hi6421_regulator_buck_get_mode(struct regulator_dev *rdev)
|
|||
const struct hi6421_regulator_info *info;
|
||||
unsigned int reg_val;
|
||||
|
||||
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val);
|
||||
if (reg_val & info->mode_mask)
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
|
|
@ -414,7 +414,7 @@ static int hi6421_regulator_ldo_set_mode(struct regulator_dev *rdev,
|
|||
const struct hi6421_regulator_info *info;
|
||||
unsigned int new_mode;
|
||||
|
||||
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
new_mode = 0;
|
||||
|
|
@ -439,7 +439,7 @@ static int hi6421_regulator_buck_set_mode(struct regulator_dev *rdev,
|
|||
const struct hi6421_regulator_info *info;
|
||||
unsigned int new_mode;
|
||||
|
||||
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
new_mode = 0;
|
||||
|
|
@ -464,7 +464,7 @@ hi6421_regulator_ldo_get_optimum_mode(struct regulator_dev *rdev,
|
|||
{
|
||||
const struct hi6421_regulator_info *info;
|
||||
|
||||
info = container_of(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
info = container_of_const(rdev->desc, struct hi6421_regulator_info, desc);
|
||||
|
||||
if (load_uA > info->eco_microamp)
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ static unsigned int hi6421v530_regulator_ldo_get_mode(
|
|||
const struct hi6421v530_regulator_info *info;
|
||||
unsigned int reg_val;
|
||||
|
||||
info = container_of(rdev->desc, struct hi6421v530_regulator_info, rdesc);
|
||||
info = container_of_const(rdev->desc, struct hi6421v530_regulator_info, rdesc);
|
||||
regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val);
|
||||
|
||||
if (reg_val & (info->mode_mask))
|
||||
|
|
@ -125,7 +125,7 @@ static int hi6421v530_regulator_ldo_set_mode(struct regulator_dev *rdev,
|
|||
const struct hi6421v530_regulator_info *info;
|
||||
unsigned int new_mode;
|
||||
|
||||
info = container_of(rdev->desc, struct hi6421v530_regulator_info, rdesc);
|
||||
info = container_of_const(rdev->desc, struct hi6421v530_regulator_info, rdesc);
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
new_mode = 0;
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ static unsigned int hi6421_spmi_regulator_get_mode(struct regulator_dev *rdev)
|
|||
const struct hi6421_spmi_reg_info *sreg;
|
||||
unsigned int reg_val;
|
||||
|
||||
sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc);
|
||||
sreg = container_of_const(rdev->desc, struct hi6421_spmi_reg_info, desc);
|
||||
regmap_read(rdev->regmap, rdev->desc->enable_reg, ®_val);
|
||||
|
||||
if (reg_val & sreg->eco_mode_mask)
|
||||
|
|
@ -136,7 +136,7 @@ static int hi6421_spmi_regulator_set_mode(struct regulator_dev *rdev,
|
|||
const struct hi6421_spmi_reg_info *sreg;
|
||||
unsigned int val;
|
||||
|
||||
sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc);
|
||||
sreg = container_of_const(rdev->desc, struct hi6421_spmi_reg_info, desc);
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = 0;
|
||||
|
|
@ -162,7 +162,7 @@ hi6421_spmi_regulator_get_optimum_mode(struct regulator_dev *rdev,
|
|||
{
|
||||
const struct hi6421_spmi_reg_info *sreg;
|
||||
|
||||
sreg = container_of(rdev->desc, struct hi6421_spmi_reg_info, desc);
|
||||
sreg = container_of_const(rdev->desc, struct hi6421_spmi_reg_info, desc);
|
||||
|
||||
if (!sreg->eco_uA || ((unsigned int)load_uA > sreg->eco_uA))
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ static void regulator_notifier_isr_work(struct work_struct *work)
|
|||
|
||||
reschedule:
|
||||
if (!d->high_prio)
|
||||
mod_delayed_work(system_wq, &h->isr_work,
|
||||
mod_delayed_work(system_dfl_wq, &h->isr_work,
|
||||
msecs_to_jiffies(tmo));
|
||||
else
|
||||
mod_delayed_work(system_highpri_wq, &h->isr_work,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ static int max77650_regulator_is_enabled(struct regulator_dev *rdev)
|
|||
struct regmap *map;
|
||||
int val, rv, en;
|
||||
|
||||
rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
|
||||
rdesc = container_of_const(rdev->desc, struct max77650_regulator_desc, desc);
|
||||
map = rdev_get_regmap(rdev);
|
||||
|
||||
rv = regmap_read(map, rdesc->regB, &val);
|
||||
|
|
@ -85,7 +85,7 @@ static int max77650_regulator_enable(struct regulator_dev *rdev)
|
|||
const struct max77650_regulator_desc *rdesc;
|
||||
struct regmap *map;
|
||||
|
||||
rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
|
||||
rdesc = container_of_const(rdev->desc, struct max77650_regulator_desc, desc);
|
||||
map = rdev_get_regmap(rdev);
|
||||
|
||||
return regmap_update_bits(map, rdesc->regB,
|
||||
|
|
@ -98,7 +98,7 @@ static int max77650_regulator_disable(struct regulator_dev *rdev)
|
|||
const struct max77650_regulator_desc *rdesc;
|
||||
struct regmap *map;
|
||||
|
||||
rdesc = container_of(rdev->desc, struct max77650_regulator_desc, desc);
|
||||
rdesc = container_of_const(rdev->desc, struct max77650_regulator_desc, desc);
|
||||
map = rdev_get_regmap(rdev);
|
||||
|
||||
return regmap_update_bits(map, rdesc->regB,
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ static unsigned int mt6315_regulator_get_mode(struct regulator_dev *rdev)
|
|||
int ret, regval;
|
||||
u32 modeset_mask;
|
||||
|
||||
info = container_of(rdev->desc, struct mt6315_regulator_info, desc);
|
||||
info = container_of_const(rdev->desc, struct mt6315_regulator_info, desc);
|
||||
modeset_mask = init->modeset_mask[rdev_get_id(rdev)];
|
||||
ret = regmap_read(rdev->regmap, MT6315_BUCK_TOP_4PHASE_ANA_CON42, ®val);
|
||||
if (ret != 0) {
|
||||
|
|
@ -111,7 +111,7 @@ static int mt6315_regulator_set_mode(struct regulator_dev *rdev,
|
|||
int ret, val, curr_mode;
|
||||
u32 modeset_mask;
|
||||
|
||||
info = container_of(rdev->desc, struct mt6315_regulator_info, desc);
|
||||
info = container_of_const(rdev->desc, struct mt6315_regulator_info, desc);
|
||||
modeset_mask = init->modeset_mask[rdev_get_id(rdev)];
|
||||
curr_mode = mt6315_regulator_get_mode(rdev);
|
||||
switch (mode) {
|
||||
|
|
@ -165,7 +165,7 @@ static int mt6315_get_status(struct regulator_dev *rdev)
|
|||
int ret;
|
||||
u32 regval;
|
||||
|
||||
info = container_of(rdev->desc, struct mt6315_regulator_info, desc);
|
||||
info = container_of_const(rdev->desc, struct mt6315_regulator_info, desc);
|
||||
ret = regmap_read(rdev->regmap, info->status_reg, ®val);
|
||||
if (ret < 0) {
|
||||
dev_err(&rdev->dev, "Failed to get enable reg: %d\n", ret);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,345 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Copyright (c) 2024 MediaTek Inc.
|
||||
// Copyright (c) 2025 Collabora Ltd
|
||||
// AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spmi.h>
|
||||
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
#define MT6316_BUCK_MODE_AUTO 0
|
||||
#define MT6316_BUCK_MODE_FORCE_PWM 1
|
||||
#define MT6316_BUCK_MODE_LP 2
|
||||
|
||||
#define MT6316_CHIP_ID 0x20b
|
||||
#define MT6316_BUCK_TOP_CON0 0x1440
|
||||
#define EN_SET_OFFSET 0x1
|
||||
#define EN_CLR_OFFSET 0x2
|
||||
|
||||
#define MT6316_BUCK_TOP_CON1 0x1443
|
||||
|
||||
#define MT6316_BUCK_TOP_ELR0 0x1448
|
||||
#define MT6316_BUCK_TOP_ELR2 0x144a
|
||||
#define MT6316_BUCK_TOP_ELR4 0x144c
|
||||
#define MT6316_BUCK_TOP_ELR6 0x144e
|
||||
#define MT6316_VSEL_MASK GENMASK(8, 0)
|
||||
|
||||
#define MT6316_VBUCK1_DBG 0x14a8
|
||||
#define MT6316_VBUCK2_DBG 0x1528
|
||||
#define MT6316_VBUCK3_DBG 0x15a8
|
||||
#define MT6316_VBUCK4_DBG 0x1628
|
||||
#define MT6316_BUCK_QI BIT(0)
|
||||
|
||||
#define MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0 0x1688
|
||||
#define MT6316_BUCK_TOP_4PHASE_TOP_ELR_0 0x1690
|
||||
|
||||
enum mt6316_type {
|
||||
MT6316_TYPE_2PHASE,
|
||||
MT6316_TYPE_3PHASE,
|
||||
MT6316_TYPE_4PHASE
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mt6316_regulator_info - MT6316 regulators information
|
||||
* @desc: Regulator description structure
|
||||
* @debug_reg: Debug register for regulator status
|
||||
* @lp_mode_reg: Low Power mode register (normal/idle)
|
||||
* @lp_mode_mask: Low Power mode regulator mask
|
||||
* @modeset_reg: AUTO/PWM mode register
|
||||
* @modeset_mask: AUTO/PWM regulator mask
|
||||
*/
|
||||
struct mt6316_regulator_info {
|
||||
struct regulator_desc desc;
|
||||
u16 debug_reg;
|
||||
u16 lp_mode_reg;
|
||||
u16 lp_mode_mask;
|
||||
u16 modeset_reg;
|
||||
u16 modeset_mask;
|
||||
};
|
||||
|
||||
#define MT6316_BUCK(match, vreg_id, min, max, step, vs_reg) \
|
||||
{ \
|
||||
.desc = { \
|
||||
.name = match, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.ops = &mt6316_vreg_setclr_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = (max - min) / step + 1, \
|
||||
.min_uV = min, \
|
||||
.uV_step = step, \
|
||||
.enable_reg = MT6316_BUCK_TOP_CON0, \
|
||||
.enable_mask = BIT(vreg_id - 1), \
|
||||
.vsel_reg = vs_reg, \
|
||||
.vsel_mask = MT6316_VSEL_MASK, \
|
||||
.of_map_mode = mt6316_map_mode, \
|
||||
}, \
|
||||
.lp_mode_reg = MT6316_BUCK_TOP_CON1, \
|
||||
.lp_mode_mask = BIT(vreg_id - 1), \
|
||||
.modeset_reg = MT6316_BUCK_TOP_4PHASE_TOP_ANA_CON0, \
|
||||
.modeset_mask = BIT(vreg_id - 1), \
|
||||
.debug_reg = MT6316_VBUCK##vreg_id##_DBG, \
|
||||
}
|
||||
|
||||
/* Values in some MT6316 registers are big endian, 9 bits long... */
|
||||
static inline u16 mt6316_be9_to_cpu(u16 val)
|
||||
{
|
||||
return ((val >> 8) & BIT(0)) | ((val & GENMASK(7, 0)) << 1);
|
||||
}
|
||||
|
||||
static inline u16 mt6316_cpu_to_be9(u16 val)
|
||||
{
|
||||
return ((val & BIT(0)) << 8) | (val >> 1);
|
||||
}
|
||||
|
||||
static unsigned int mt6316_map_mode(u32 mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case MT6316_BUCK_MODE_AUTO:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
case MT6316_BUCK_MODE_FORCE_PWM:
|
||||
return REGULATOR_MODE_FAST;
|
||||
case MT6316_BUCK_MODE_LP:
|
||||
return REGULATOR_MODE_IDLE;
|
||||
default:
|
||||
return REGULATOR_MODE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static int mt6316_vreg_enable_setclr(struct regulator_dev *rdev)
|
||||
{
|
||||
return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_SET_OFFSET,
|
||||
rdev->desc->enable_mask);
|
||||
}
|
||||
|
||||
static int mt6316_vreg_disable_setclr(struct regulator_dev *rdev)
|
||||
{
|
||||
return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_CLR_OFFSET,
|
||||
rdev->desc->enable_mask);
|
||||
}
|
||||
|
||||
static int mt6316_regulator_set_voltage_sel(struct regulator_dev *rdev, unsigned int selector)
|
||||
{
|
||||
u16 val = mt6316_cpu_to_be9(selector);
|
||||
|
||||
return regmap_bulk_write(rdev->regmap, rdev->desc->vsel_reg, &val, sizeof(val));
|
||||
}
|
||||
|
||||
static int mt6316_regulator_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
u16 val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_bulk_read(rdev->regmap, rdev->desc->vsel_reg, &val, sizeof(val));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return mt6316_be9_to_cpu(val & rdev->desc->vsel_mask);
|
||||
}
|
||||
|
||||
static int mt6316_regulator_get_status(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mt6316_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->debug_reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return val & MT6316_BUCK_QI ? REGULATOR_STATUS_ON : REGULATOR_STATUS_OFF;
|
||||
}
|
||||
|
||||
static unsigned int mt6316_regulator_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mt6316_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Failed to get mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((val & info->modeset_mask) == info->modeset_mask)
|
||||
return REGULATOR_MODE_FAST;
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->lp_mode_reg, &val);
|
||||
val &= info->lp_mode_mask;
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Failed to get lp mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return val ? REGULATOR_MODE_IDLE : REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static int mt6316_regulator_set_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct mt6316_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
struct regmap *regmap = rdev->regmap;
|
||||
int cur_mode, ret;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
ret = regmap_set_bits(regmap, info->modeset_reg, info->modeset_mask);
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
cur_mode = mt6316_regulator_get_mode(rdev);
|
||||
if (cur_mode < 0) {
|
||||
ret = cur_mode;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cur_mode == REGULATOR_MODE_FAST) {
|
||||
ret = regmap_clear_bits(regmap, info->modeset_reg, info->modeset_mask);
|
||||
break;
|
||||
} else if (cur_mode == REGULATOR_MODE_IDLE) {
|
||||
ret = regmap_clear_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
|
||||
if (ret == 0)
|
||||
usleep_range(100, 200);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case REGULATOR_MODE_IDLE:
|
||||
ret = regmap_set_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Failed to set mode %u: %d\n", mode, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct regulator_ops mt6316_vreg_setclr_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_voltage_sel = mt6316_regulator_set_voltage_sel,
|
||||
.get_voltage_sel = mt6316_regulator_get_voltage_sel,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = mt6316_vreg_enable_setclr,
|
||||
.disable = mt6316_vreg_disable_setclr,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.get_status = mt6316_regulator_get_status,
|
||||
.set_mode = mt6316_regulator_set_mode,
|
||||
.get_mode = mt6316_regulator_get_mode,
|
||||
};
|
||||
|
||||
/* MT6316BP/VP - 2+2 phase buck */
|
||||
static struct mt6316_regulator_info mt6316bv_regulators[] = {
|
||||
MT6316_BUCK("vbuck12", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
|
||||
MT6316_BUCK("vbuck34", 3, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR4),
|
||||
};
|
||||
|
||||
/* MT6316CP/HP/KP - 3+1 phase buck */
|
||||
static struct mt6316_regulator_info mt6316chk_regulators[] = {
|
||||
MT6316_BUCK("vbuck124", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
|
||||
MT6316_BUCK("vbuck3", 3, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR4),
|
||||
};
|
||||
|
||||
/* MT6316DP/TP - 4 phase buck */
|
||||
static struct mt6316_regulator_info mt6316dt_regulators[] = {
|
||||
MT6316_BUCK("vbuck1234", 1, 0, 1277500, 2500, MT6316_BUCK_TOP_ELR0),
|
||||
};
|
||||
|
||||
static const struct regmap_config mt6316_spmi_regmap_config = {
|
||||
.reg_bits = 16,
|
||||
.val_bits = 8,
|
||||
.max_register = 0x1700,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static int mt6316_regulator_probe(struct spmi_device *sdev)
|
||||
{
|
||||
struct regulator_config config = {};
|
||||
struct mt6316_regulator_info *info;
|
||||
struct regulator_dev *rdev;
|
||||
enum mt6316_type type;
|
||||
int num_vregs, ret;
|
||||
unsigned int i;
|
||||
u32 chip_id;
|
||||
|
||||
config.regmap = devm_regmap_init_spmi_ext(sdev, &mt6316_spmi_regmap_config);
|
||||
if (IS_ERR(config.regmap))
|
||||
return PTR_ERR(config.regmap);
|
||||
|
||||
/*
|
||||
* The first read is expected to fail: this PMIC needs to be woken up
|
||||
* and that can be done with any activity over the SPMI bus.
|
||||
*/
|
||||
regmap_read(config.regmap, MT6316_CHIP_ID, &chip_id);
|
||||
|
||||
/* The second read, instead, shall not fail! */
|
||||
ret = regmap_read(config.regmap, MT6316_CHIP_ID, &chip_id);
|
||||
if (ret) {
|
||||
dev_err(&sdev->dev, "Cannot read Chip ID!\n");
|
||||
return ret;
|
||||
}
|
||||
dev_dbg(&sdev->dev, "Chip ID: 0x%x\n", chip_id);
|
||||
|
||||
config.dev = &sdev->dev;
|
||||
|
||||
type = (uintptr_t)device_get_match_data(&sdev->dev);
|
||||
switch (type) {
|
||||
case MT6316_TYPE_2PHASE:
|
||||
info = mt6316bv_regulators;
|
||||
num_vregs = ARRAY_SIZE(mt6316bv_regulators);
|
||||
break;
|
||||
case MT6316_TYPE_3PHASE:
|
||||
info = mt6316chk_regulators;
|
||||
num_vregs = ARRAY_SIZE(mt6316chk_regulators);
|
||||
break;
|
||||
case MT6316_TYPE_4PHASE:
|
||||
info = mt6316dt_regulators;
|
||||
num_vregs = ARRAY_SIZE(mt6316dt_regulators);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_vregs; i++) {
|
||||
config.driver_data = &info[i];
|
||||
|
||||
rdev = devm_regulator_register(&sdev->dev, &info[i].desc, &config);
|
||||
if (IS_ERR(rdev))
|
||||
return dev_err_probe(&sdev->dev, PTR_ERR(rdev),
|
||||
"failed to register %s\n", info[i].desc.name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id mt6316_regulator_match[] = {
|
||||
{ .compatible = "mediatek,mt6316b-regulator", .data = (void *)MT6316_TYPE_2PHASE },
|
||||
{ .compatible = "mediatek,mt6316c-regulator", .data = (void *)MT6316_TYPE_3PHASE },
|
||||
{ .compatible = "mediatek,mt6316d-regulator", .data = (void *)MT6316_TYPE_4PHASE },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct spmi_driver mt6316_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "mt6316-regulator",
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
.of_match_table = mt6316_regulator_match,
|
||||
},
|
||||
.probe = mt6316_regulator_probe,
|
||||
};
|
||||
module_spmi_driver(mt6316_regulator_driver);
|
||||
|
||||
MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
|
||||
MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6316 PMIC");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -31,7 +31,7 @@ struct mt6358_regulator_info {
|
|||
u32 modeset_mask;
|
||||
};
|
||||
|
||||
#define to_regulator_info(x) container_of((x), struct mt6358_regulator_info, desc)
|
||||
#define to_regulator_info(x) container_of_const((x), struct mt6358_regulator_info, desc)
|
||||
|
||||
#define MT6358_BUCK(match, vreg, supply, min, max, step, \
|
||||
vosel_mask, _da_vsel_reg, _da_vsel_mask, \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,938 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// Copyright (c) 2024 MediaTek Inc.
|
||||
// Copyright (c) 2025 Collabora Ltd
|
||||
// AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/devm-helpers.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/spmi.h>
|
||||
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/mt6363-regulator.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
#define MT6363_REGULATOR_MODE_NORMAL 0
|
||||
#define MT6363_REGULATOR_MODE_FCCM 1
|
||||
#define MT6363_REGULATOR_MODE_LP 2
|
||||
#define MT6363_REGULATOR_MODE_ULP 3
|
||||
|
||||
#define EN_SET_OFFSET 0x1
|
||||
#define EN_CLR_OFFSET 0x2
|
||||
#define OP_CFG_OFFSET 0x5
|
||||
|
||||
#define NORMAL_OP_CFG 0x10
|
||||
#define NORMAL_OP_EN 0x800000
|
||||
|
||||
#define OC_IRQ_ENABLE_DELAY_MS 10
|
||||
|
||||
/* Unlock keys for TMA and BUCK_TOP */
|
||||
#define MT6363_TMA_UNLOCK_VALUE 0x9c9c
|
||||
#define MT6363_BUCK_TOP_UNLOCK_VALUE 0x5543
|
||||
|
||||
enum {
|
||||
MT6363_ID_VBUCK1,
|
||||
MT6363_ID_VBUCK2,
|
||||
MT6363_ID_VBUCK3,
|
||||
MT6363_ID_VBUCK4,
|
||||
MT6363_ID_VBUCK5,
|
||||
MT6363_ID_VBUCK6,
|
||||
MT6363_ID_VBUCK7,
|
||||
MT6363_ID_VS1,
|
||||
MT6363_ID_VS2,
|
||||
MT6363_ID_VS3,
|
||||
MT6363_ID_VA12_1,
|
||||
MT6363_ID_VA12_2,
|
||||
MT6363_ID_VA15,
|
||||
MT6363_ID_VAUX18,
|
||||
MT6363_ID_VCN13,
|
||||
MT6363_ID_VCN15,
|
||||
MT6363_ID_VEMC,
|
||||
MT6363_ID_VIO075,
|
||||
MT6363_ID_VIO18,
|
||||
MT6363_ID_VM18,
|
||||
MT6363_ID_VSRAM_APU,
|
||||
MT6363_ID_VSRAM_CPUB,
|
||||
MT6363_ID_VSRAM_CPUM,
|
||||
MT6363_ID_VSRAM_CPUL,
|
||||
MT6363_ID_VSRAM_DIGRF,
|
||||
MT6363_ID_VSRAM_MDFE,
|
||||
MT6363_ID_VSRAM_MODEM,
|
||||
MT6363_ID_VRF09,
|
||||
MT6363_ID_VRF12,
|
||||
MT6363_ID_VRF13,
|
||||
MT6363_ID_VRF18,
|
||||
MT6363_ID_VRFIO18,
|
||||
MT6363_ID_VTREF18,
|
||||
MT6363_ID_VUFS12,
|
||||
MT6363_ID_VUFS18,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mt6363_regulator_info - MT6363 regulators information
|
||||
* @desc: Regulator description structure
|
||||
* @lp_mode_reg: Low Power mode register (normal/idle)
|
||||
* @lp_mode_mask: Low Power mode regulator mask
|
||||
* @hw_lp_mode_reg: Hardware voted Low Power mode register (normal/idle)
|
||||
* @hw_lp_mode_mask: Hardware voted Low Power mode regulator mask
|
||||
* @modeset_reg: AUTO/PWM mode register
|
||||
* @modeset_mask: AUTO/PWM regulator mask
|
||||
* @lp_imax_uA: Maximum load current (microamps), for Low Power mode only
|
||||
* @op_en_reg: Operation mode enablement register
|
||||
* @orig_op_en: Backup of a regulator's operation mode enablement register
|
||||
* @orig_op_cfg: Backup of a regulator's operation mode configuration register
|
||||
* @oc_work: Delayed work for enabling overcurrent IRQ
|
||||
* @hwirq: PMIC-Internal HW Interrupt for overcurrent event
|
||||
* @virq: Mapped Interrupt for overcurrent event
|
||||
*/
|
||||
struct mt6363_regulator_info {
|
||||
struct regulator_desc desc;
|
||||
u16 lp_mode_reg;
|
||||
u16 lp_mode_mask;
|
||||
u16 hw_lp_mode_reg;
|
||||
u16 hw_lp_mode_mask;
|
||||
u16 modeset_reg;
|
||||
u16 modeset_mask;
|
||||
int lp_imax_uA;
|
||||
u16 op_en_reg;
|
||||
u32 orig_op_en;
|
||||
u8 orig_op_cfg;
|
||||
struct delayed_work oc_work;
|
||||
u8 hwirq;
|
||||
int virq;
|
||||
};
|
||||
|
||||
#define MT6363_BUCK(match, vreg, min, max, step, en_reg, lp_reg, \
|
||||
mset_reg, ocp_intn) \
|
||||
[MT6363_ID_##vreg] = { \
|
||||
.desc = { \
|
||||
.name = match, \
|
||||
.supply_name = "vsys-"match, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.ops = &mt6363_vreg_setclr_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MT6363_ID_##vreg, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = (max - min) / step + 1, \
|
||||
.min_uV = min, \
|
||||
.uV_step = step, \
|
||||
.enable_reg = en_reg, \
|
||||
.enable_mask = BIT(MT6363_RG_BUCK_##vreg##_EN_BIT), \
|
||||
.vsel_reg = MT6363_RG_BUCK_##vreg##_VOSEL_ADDR, \
|
||||
.vsel_mask = MT6363_RG_BUCK_##vreg##_VOSEL_MASK, \
|
||||
.of_map_mode = mt6363_map_mode, \
|
||||
}, \
|
||||
.lp_mode_reg = lp_reg, \
|
||||
.lp_mode_mask = BIT(MT6363_RG_BUCK_##vreg##_LP_BIT), \
|
||||
.hw_lp_mode_reg = MT6363_BUCK_##vreg##_HW_LP_MODE, \
|
||||
.hw_lp_mode_mask = 0xc, \
|
||||
.modeset_reg = mset_reg, \
|
||||
.modeset_mask = BIT(MT6363_RG_##vreg##_FCCM_BIT), \
|
||||
.lp_imax_uA = 100000, \
|
||||
.op_en_reg = MT6363_BUCK_##vreg##_OP_EN_0, \
|
||||
.hwirq = ocp_intn, \
|
||||
}
|
||||
|
||||
#define MT6363_LDO_LINEAR_OPS(match, vreg, in_sup, vops, min, max, \
|
||||
step, buck_reg, ocp_intn) \
|
||||
[MT6363_ID_##vreg] = { \
|
||||
.desc = { \
|
||||
.name = match, \
|
||||
.supply_name = in_sup, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.ops = &vops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MT6363_ID_##vreg, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = (max - min) / step + 1, \
|
||||
.min_uV = min, \
|
||||
.uV_step = step, \
|
||||
.enable_reg = MT6363_RG_##buck_reg##_EN_ADDR, \
|
||||
.enable_mask = BIT(MT6363_RG_LDO_##vreg##_EN_BIT), \
|
||||
.vsel_reg = MT6363_RG_LDO_##vreg##_VOSEL_ADDR, \
|
||||
.vsel_mask = MT6363_RG_LDO_##vreg##_VOSEL_MASK, \
|
||||
.of_map_mode = mt6363_map_mode, \
|
||||
}, \
|
||||
.lp_mode_reg = MT6363_RG_##buck_reg##_LP_ADDR, \
|
||||
.lp_mode_mask = BIT(MT6363_RG_LDO_##vreg##_LP_BIT), \
|
||||
.hw_lp_mode_reg = MT6363_LDO_##vreg##_HW_LP_MODE, \
|
||||
.hw_lp_mode_mask = 0x4, \
|
||||
.hwirq = ocp_intn, \
|
||||
}
|
||||
|
||||
#define MT6363_LDO_L_SC(match, vreg, inp, min, max, step, buck_reg, \
|
||||
ocp_intn) \
|
||||
MT6363_LDO_LINEAR_OPS(match, vreg, inp, mt6363_vreg_setclr_ops, \
|
||||
min, max, step, buck_reg, ocp_intn)
|
||||
|
||||
#define MT6363_LDO_L(match, vreg, inp, min, max, step, buck_reg, \
|
||||
ocp_intn) \
|
||||
MT6363_LDO_LINEAR_OPS(match, vreg, inp, mt6363_ldo_linear_ops, \
|
||||
min, max, step, buck_reg, ocp_intn)
|
||||
|
||||
#define MT6363_LDO_LINEAR_CAL_OPS(match, vreg, in_sup, vops, vrnum, \
|
||||
ocp_intn) \
|
||||
[MT6363_ID_##vreg] = { \
|
||||
.desc = { \
|
||||
.name = match, \
|
||||
.supply_name = in_sup, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.ops = &vops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MT6363_ID_##vreg, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = ARRAY_SIZE(ldo_volt_ranges##vrnum) * 11, \
|
||||
.linear_ranges = ldo_volt_ranges##vrnum, \
|
||||
.n_linear_ranges = ARRAY_SIZE(ldo_volt_ranges##vrnum), \
|
||||
.linear_range_selectors_bitfield = ldos_cal_selectors, \
|
||||
.enable_reg = MT6363_RG_LDO_##vreg##_ADDR, \
|
||||
.enable_mask = BIT(MT6363_RG_LDO_##vreg##_EN_BIT), \
|
||||
.vsel_reg = MT6363_RG_##vreg##_VOCAL_ADDR, \
|
||||
.vsel_mask = MT6363_RG_##vreg##_VOCAL_MASK, \
|
||||
.vsel_range_reg = MT6363_RG_##vreg##_VOSEL_ADDR, \
|
||||
.vsel_range_mask = MT6363_RG_##vreg##_VOSEL_MASK, \
|
||||
.of_map_mode = mt6363_map_mode, \
|
||||
}, \
|
||||
.lp_mode_reg = MT6363_RG_LDO_##vreg##_ADDR, \
|
||||
.lp_mode_mask = BIT(MT6363_RG_LDO_##vreg##_LP_BIT), \
|
||||
.hw_lp_mode_reg = MT6363_LDO_##vreg##_HW_LP_MODE, \
|
||||
.hw_lp_mode_mask = 0x4, \
|
||||
.lp_imax_uA = 10000, \
|
||||
.op_en_reg = MT6363_LDO_##vreg##_OP_EN0, \
|
||||
.hwirq = ocp_intn, \
|
||||
}
|
||||
|
||||
#define MT6363_LDO_VT(match, vreg, inp, vranges_num, ocp_intn) \
|
||||
MT6363_LDO_LINEAR_CAL_OPS(match, vreg, inp, mt6363_ldo_vtable_ops,\
|
||||
vranges_num, ocp_intn)
|
||||
|
||||
static const unsigned int ldos_cal_selectors[] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
||||
};
|
||||
|
||||
static const struct linear_range ldo_volt_ranges0[] = {
|
||||
REGULATOR_LINEAR_RANGE(1200000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1300000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1500000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1700000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2000000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2500000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2600000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2700000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2800000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2900000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3100000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3300000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3400000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3500000, 0, 10, 10000)
|
||||
};
|
||||
|
||||
static const struct linear_range ldo_volt_ranges1[] = {
|
||||
REGULATOR_LINEAR_RANGE(900000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1000000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1100000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1200000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1300000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1700000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1810000, 0, 10, 10000)
|
||||
};
|
||||
|
||||
static const struct linear_range ldo_volt_ranges2[] = {
|
||||
REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1900000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2000000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2100000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2200000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2300000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2400000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2500000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2600000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2700000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2800000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2900000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3000000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3100000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3200000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(3300000, 0, 10, 10000)
|
||||
};
|
||||
|
||||
static const struct linear_range ldo_volt_ranges3[] = {
|
||||
REGULATOR_LINEAR_RANGE(600000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(700000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(800000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(900000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1000000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1100000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1200000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1300000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1400000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1500000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1600000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1700000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1800000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(1900000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2000000, 0, 10, 10000),
|
||||
REGULATOR_LINEAR_RANGE(2100000, 0, 10, 10000)
|
||||
};
|
||||
|
||||
static const struct linear_range ldo_volt_ranges4[] = {
|
||||
REGULATOR_LINEAR_RANGE(550000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(600000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(650000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(700000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(750000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(800000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(900000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(950000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(1000000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(1050000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(1100000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(1150000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(1700000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(1750000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(1800000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(1850000, 0, 10, 5000)
|
||||
};
|
||||
|
||||
static const struct linear_range ldo_volt_ranges5[] = {
|
||||
REGULATOR_LINEAR_RANGE(600000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(650000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(700000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(750000, 0, 10, 5000),
|
||||
REGULATOR_LINEAR_RANGE(800000, 0, 10, 5000)
|
||||
};
|
||||
|
||||
static int mt6363_vreg_enable_setclr(struct regulator_dev *rdev)
|
||||
{
|
||||
return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_SET_OFFSET,
|
||||
rdev->desc->enable_mask);
|
||||
}
|
||||
|
||||
static int mt6363_vreg_disable_setclr(struct regulator_dev *rdev)
|
||||
{
|
||||
return regmap_write(rdev->regmap, rdev->desc->enable_reg + EN_CLR_OFFSET,
|
||||
rdev->desc->enable_mask);
|
||||
}
|
||||
|
||||
static inline unsigned int mt6363_map_mode(unsigned int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case MT6363_REGULATOR_MODE_NORMAL:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
case MT6363_REGULATOR_MODE_FCCM:
|
||||
return REGULATOR_MODE_FAST;
|
||||
case MT6363_REGULATOR_MODE_LP:
|
||||
return REGULATOR_MODE_IDLE;
|
||||
case MT6363_REGULATOR_MODE_ULP:
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
default:
|
||||
return REGULATOR_MODE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int mt6363_regulator_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned int val;
|
||||
int ret;
|
||||
|
||||
if (info->modeset_reg) {
|
||||
ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Failed to get mt6363 mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (val & info->modeset_mask)
|
||||
return REGULATOR_MODE_FAST;
|
||||
} else {
|
||||
val = 0;
|
||||
}
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->hw_lp_mode_reg, &val);
|
||||
val &= info->hw_lp_mode_mask;
|
||||
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Failed to get lp mode: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (val)
|
||||
return REGULATOR_MODE_IDLE;
|
||||
else
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static int mt6363_buck_unlock(struct regmap *map, bool unlock)
|
||||
{
|
||||
u16 buf = unlock ? MT6363_BUCK_TOP_UNLOCK_VALUE : 0;
|
||||
|
||||
return regmap_bulk_write(map, MT6363_BUCK_TOP_KEY_PROT_LO, &buf, sizeof(buf));
|
||||
}
|
||||
|
||||
static int mt6363_regulator_set_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
struct regmap *regmap = rdev->regmap;
|
||||
int cur_mode, ret;
|
||||
|
||||
if (!info->modeset_reg && mode == REGULATOR_MODE_FAST)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
ret = mt6363_buck_unlock(regmap, true);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = regmap_set_bits(regmap, info->modeset_reg, info->modeset_mask);
|
||||
|
||||
mt6363_buck_unlock(regmap, false);
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
cur_mode = mt6363_regulator_get_mode(rdev);
|
||||
if (cur_mode < 0) {
|
||||
ret = cur_mode;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cur_mode == REGULATOR_MODE_FAST) {
|
||||
ret = mt6363_buck_unlock(regmap, true);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
ret = regmap_clear_bits(regmap, info->modeset_reg, info->modeset_mask);
|
||||
|
||||
mt6363_buck_unlock(regmap, false);
|
||||
break;
|
||||
} else if (cur_mode == REGULATOR_MODE_IDLE) {
|
||||
ret = regmap_clear_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
|
||||
if (ret == 0)
|
||||
usleep_range(100, 200);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
break;
|
||||
case REGULATOR_MODE_IDLE:
|
||||
ret = regmap_set_bits(regmap, info->lp_mode_reg, info->lp_mode_mask);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Failed to set mode %u: %d\n", mode, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt6363_regulator_set_load(struct regulator_dev *rdev, int load_uA)
|
||||
{
|
||||
struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
unsigned int opmode_cfg, opmode_en;
|
||||
int i, ret;
|
||||
|
||||
if (!info->lp_imax_uA)
|
||||
return -EINVAL;
|
||||
|
||||
if (load_uA >= info->lp_imax_uA) {
|
||||
ret = mt6363_regulator_set_mode(rdev, REGULATOR_MODE_NORMAL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
opmode_cfg = NORMAL_OP_CFG;
|
||||
opmode_en = NORMAL_OP_EN;
|
||||
} else {
|
||||
opmode_cfg = info->orig_op_cfg;
|
||||
opmode_en = info->orig_op_en;
|
||||
}
|
||||
|
||||
ret = regmap_write(rdev->regmap, info->op_en_reg + OP_CFG_OFFSET, opmode_cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = regmap_write(rdev->regmap, info->op_en_reg + i,
|
||||
(opmode_en >> (i * 8)) & GENMASK(7, 0));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mt6363_vemc_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
|
||||
{
|
||||
const u16 tma_unlock_key = MT6363_TMA_UNLOCK_VALUE;
|
||||
const struct regulator_desc *rdesc = rdev->desc;
|
||||
struct regmap *regmap = rdev->regmap;
|
||||
unsigned int range, val;
|
||||
int i, ret;
|
||||
u16 mask;
|
||||
|
||||
for (i = 0; i < rdesc->n_linear_ranges; i++) {
|
||||
const struct linear_range *r = &rdesc->linear_ranges[i];
|
||||
unsigned int voltages_in_range = linear_range_values_in_range(r);
|
||||
|
||||
if (sel < voltages_in_range)
|
||||
break;
|
||||
sel -= voltages_in_range;
|
||||
}
|
||||
|
||||
if (i == rdesc->n_linear_ranges)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_read(rdev->regmap, MT6363_TOP_TRAP, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val > 1)
|
||||
return -EINVAL;
|
||||
|
||||
/* Unlock TMA for writing */
|
||||
ret = regmap_bulk_write(rdev->regmap, MT6363_TOP_TMA_KEY_L,
|
||||
&tma_unlock_key, sizeof(tma_unlock_key));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If HW trapping value is 1, use VEMC_VOSEL_1 instead of VEMC_VOSEL_0 */
|
||||
if (val == 1) {
|
||||
mask = MT6363_RG_VEMC_VOSEL_1_MASK;
|
||||
sel = FIELD_PREP(MT6363_RG_VEMC_VOSEL_1_MASK, sel);
|
||||
} else {
|
||||
mask = rdesc->vsel_mask;
|
||||
}
|
||||
|
||||
sel <<= ffs(rdesc->vsel_mask) - 1;
|
||||
sel += rdesc->linear_ranges[i].min_sel;
|
||||
|
||||
range = rdesc->linear_range_selectors_bitfield[i];
|
||||
range <<= ffs(rdesc->vsel_range_mask) - 1;
|
||||
|
||||
/* Write to the vreg calibration register for voltage finetuning */
|
||||
ret = regmap_update_bits(regmap, rdesc->vsel_range_reg,
|
||||
rdesc->vsel_range_mask, range);
|
||||
if (ret)
|
||||
goto lock_tma;
|
||||
|
||||
/* Function must return the result of this write operation */
|
||||
ret = regmap_update_bits(regmap, rdesc->vsel_reg, mask, sel);
|
||||
|
||||
lock_tma:
|
||||
/* Unconditionally re-lock TMA */
|
||||
val = 0;
|
||||
regmap_bulk_write(rdev->regmap, MT6363_TOP_TMA_KEY_L, &val, 2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mt6363_vemc_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
const struct regulator_desc *rdesc = rdev->desc;
|
||||
unsigned int vosel, trap, calsel;
|
||||
int vcal, vsel, range, ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, rdesc->vsel_reg, &vosel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_read(rdev->regmap, rdesc->vsel_range_reg, &calsel);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
calsel &= rdesc->vsel_range_mask;
|
||||
for (range = 0; range < rdesc->n_linear_ranges; range++)
|
||||
if (rdesc->linear_range_selectors_bitfield[range] != calsel)
|
||||
break;
|
||||
|
||||
if (range == rdesc->n_linear_ranges)
|
||||
return -EINVAL;
|
||||
|
||||
ret = regmap_read(rdev->regmap, MT6363_TOP_TRAP, &trap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If HW trapping value is 1, use VEMC_VOSEL_1 instead of VEMC_VOSEL_0 */
|
||||
if (trap > 1)
|
||||
return -EINVAL;
|
||||
else if (trap == 1)
|
||||
vsel = FIELD_GET(MT6363_RG_VEMC_VOSEL_1_MASK, vosel);
|
||||
else
|
||||
vsel = vosel & rdesc->vsel_mask;
|
||||
|
||||
vcal = linear_range_values_in_range_array(rdesc->linear_ranges, range);
|
||||
|
||||
return vsel + vcal;
|
||||
}
|
||||
|
||||
static int mt6363_va15_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
|
||||
{
|
||||
struct regmap *regmap = rdev->regmap;
|
||||
int ret;
|
||||
|
||||
ret = mt6363_buck_unlock(regmap, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regulator_set_voltage_sel_pickable_regmap(rdev, sel);
|
||||
if (ret)
|
||||
goto va15_unlock;
|
||||
|
||||
ret = regmap_update_bits(regmap, MT6363_RG_BUCK_EFUSE_RSV1,
|
||||
MT6363_RG_BUCK_EFUSE_RSV1_MASK, sel);
|
||||
if (ret)
|
||||
goto va15_unlock;
|
||||
|
||||
va15_unlock:
|
||||
mt6363_buck_unlock(rdev->regmap, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void mt6363_oc_irq_enable_work(struct work_struct *work)
|
||||
{
|
||||
struct delayed_work *dwork = to_delayed_work(work);
|
||||
struct mt6363_regulator_info *info =
|
||||
container_of(dwork, struct mt6363_regulator_info, oc_work);
|
||||
|
||||
enable_irq(info->virq);
|
||||
}
|
||||
|
||||
static irqreturn_t mt6363_oc_isr(int irq, void *data)
|
||||
{
|
||||
struct regulator_dev *rdev = (struct regulator_dev *)data;
|
||||
struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
disable_irq_nosync(info->virq);
|
||||
|
||||
if (regulator_is_enabled_regmap(rdev))
|
||||
regulator_notifier_call_chain(rdev, REGULATOR_EVENT_OVER_CURRENT, NULL);
|
||||
|
||||
schedule_delayed_work(&info->oc_work, msecs_to_jiffies(OC_IRQ_ENABLE_DELAY_MS));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int mt6363_set_ocp(struct regulator_dev *rdev, int lim, int severity, bool enable)
|
||||
{
|
||||
struct mt6363_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
/* MT6363 supports only enabling protection and does not support limits */
|
||||
if (lim || severity != REGULATOR_SEVERITY_PROT || !enable)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* If there is no OCP interrupt, there's nothing to set */
|
||||
if (info->virq <= 0)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return devm_request_threaded_irq(&rdev->dev, info->virq, NULL,
|
||||
mt6363_oc_isr, IRQF_ONESHOT,
|
||||
info->desc.name, rdev);
|
||||
}
|
||||
|
||||
static const struct regulator_ops mt6363_vreg_setclr_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = mt6363_vreg_enable_setclr,
|
||||
.disable = mt6363_vreg_disable_setclr,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_mode = mt6363_regulator_set_mode,
|
||||
.get_mode = mt6363_regulator_get_mode,
|
||||
.set_load = mt6363_regulator_set_load,
|
||||
.set_over_current_protection = mt6363_set_ocp,
|
||||
};
|
||||
|
||||
static const struct regulator_ops mt6363_ldo_linear_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_mode = mt6363_regulator_set_mode,
|
||||
.get_mode = mt6363_regulator_get_mode,
|
||||
.set_over_current_protection = mt6363_set_ocp,
|
||||
};
|
||||
|
||||
static const struct regulator_ops mt6363_ldo_vtable_ops = {
|
||||
.list_voltage = regulator_list_voltage_pickable_linear_range,
|
||||
.map_voltage = regulator_map_voltage_pickable_linear_range,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_pickable_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_mode = mt6363_regulator_set_mode,
|
||||
.get_mode = mt6363_regulator_get_mode,
|
||||
.set_load = mt6363_regulator_set_load,
|
||||
.set_over_current_protection = mt6363_set_ocp,
|
||||
};
|
||||
|
||||
static const struct regulator_ops mt6363_ldo_vemc_ops = {
|
||||
.list_voltage = regulator_list_voltage_pickable_linear_range,
|
||||
.map_voltage = regulator_map_voltage_pickable_linear_range,
|
||||
.set_voltage_sel = mt6363_vemc_set_voltage_sel,
|
||||
.get_voltage_sel = mt6363_vemc_get_voltage_sel,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_mode = mt6363_regulator_set_mode,
|
||||
.get_mode = mt6363_regulator_get_mode,
|
||||
.set_load = mt6363_regulator_set_load,
|
||||
.set_over_current_protection = mt6363_set_ocp,
|
||||
};
|
||||
|
||||
static const struct regulator_ops mt6363_ldo_va15_ops = {
|
||||
.list_voltage = regulator_list_voltage_pickable_linear_range,
|
||||
.map_voltage = regulator_map_voltage_pickable_linear_range,
|
||||
.set_voltage_sel = mt6363_va15_set_voltage_sel,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_mode = mt6363_regulator_set_mode,
|
||||
.get_mode = mt6363_regulator_get_mode,
|
||||
.set_load = mt6363_regulator_set_load,
|
||||
.set_over_current_protection = mt6363_set_ocp,
|
||||
};
|
||||
|
||||
/* The array is indexed by id(MT6363_ID_XXX) */
|
||||
static struct mt6363_regulator_info mt6363_regulators[] = {
|
||||
MT6363_BUCK("vbuck1", VBUCK1, 0, 1193750, 6250, MT6363_RG_BUCK0_EN_ADDR,
|
||||
MT6363_RG_BUCK0_LP_ADDR, MT6363_RG_BUCK0_FCCM_ADDR, 1),
|
||||
MT6363_BUCK("vbuck2", VBUCK2, 0, 1193750, 6250, MT6363_RG_BUCK0_EN_ADDR,
|
||||
MT6363_RG_BUCK0_LP_ADDR, MT6363_RG_BUCK0_FCCM_ADDR, 2),
|
||||
MT6363_BUCK("vbuck3", VBUCK3, 0, 1193750, 6250, MT6363_RG_BUCK0_EN_ADDR,
|
||||
MT6363_RG_BUCK0_LP_ADDR, MT6363_RG_BUCK0_FCCM_ADDR, 3),
|
||||
MT6363_BUCK("vbuck4", VBUCK4, 0, 1193750, 6250, MT6363_RG_BUCK0_EN_ADDR,
|
||||
MT6363_RG_BUCK0_LP_ADDR, MT6363_RG_BUCK0_1_FCCM_ADDR, 4),
|
||||
MT6363_BUCK("vbuck5", VBUCK5, 0, 1193750, 6250, MT6363_RG_BUCK0_EN_ADDR,
|
||||
MT6363_RG_BUCK0_LP_ADDR, MT6363_RG_BUCK0_1_FCCM_ADDR, 5),
|
||||
MT6363_BUCK("vbuck6", VBUCK6, 0, 1193750, 6250, MT6363_RG_BUCK0_EN_ADDR,
|
||||
MT6363_RG_BUCK0_LP_ADDR, MT6363_RG_BUCK0_1_FCCM_ADDR, 6),
|
||||
MT6363_BUCK("vbuck7", VBUCK7, 0, 1193750, 6250, MT6363_RG_BUCK0_EN_ADDR,
|
||||
MT6363_RG_BUCK0_LP_ADDR, MT6363_RG_BUCK0_1_FCCM_ADDR, 7),
|
||||
MT6363_BUCK("vs1", VS1, 0, 2200000, 12500, MT6363_RG_BUCK1_EN_ADDR,
|
||||
MT6363_RG_BUCK1_LP_ADDR, MT6363_RG_VS1_FCCM_ADDR, 8),
|
||||
MT6363_BUCK("vs2", VS2, 0, 1600000, 12500, MT6363_RG_BUCK0_EN_ADDR,
|
||||
MT6363_RG_BUCK0_LP_ADDR, MT6363_RG_BUCK0_FCCM_ADDR, 0),
|
||||
MT6363_BUCK("vs3", VS3, 0, 1193750, 6250, MT6363_RG_BUCK1_EN_ADDR,
|
||||
MT6363_RG_BUCK1_LP_ADDR, MT6363_RG_VS3_FCCM_ADDR, 9),
|
||||
MT6363_LDO_VT("va12-1", VA12_1, "vs2-ldo2", 3, 37),
|
||||
MT6363_LDO_VT("va12-2", VA12_2, "vs2-ldo2", 3, 38),
|
||||
MT6363_LDO_LINEAR_CAL_OPS("va15", VA15, "vs1-ldo1", mt6363_ldo_va15_ops, 3, 39),
|
||||
MT6363_LDO_VT("vaux18", VAUX18, "vsys-ldo1", 2, 31),
|
||||
MT6363_LDO_VT("vcn13", VCN13, "vs2-ldo2", 1, 17),
|
||||
MT6363_LDO_VT("vcn15", VCN15, "vs1-ldo2", 3, 16),
|
||||
MT6363_LDO_LINEAR_CAL_OPS("vemc", VEMC, "vsys-ldo1", mt6363_ldo_vemc_ops, 0, 32),
|
||||
MT6363_LDO_VT("vio0p75", VIO075, "vs1-ldo1", 5, 36),
|
||||
MT6363_LDO_VT("vio18", VIO18, "vs1-ldo2", 3, 35),
|
||||
MT6363_LDO_VT("vm18", VM18, "vs1-ldo1", 4, 40),
|
||||
MT6363_LDO_L("vsram-apu", VSRAM_APU, "vs3-ldo1", 400000, 1193750, 6250, BUCK1, 30),
|
||||
MT6363_LDO_L("vsram-cpub", VSRAM_CPUB, "vs2-ldo1", 400000, 1193750, 6250, BUCK1, 27),
|
||||
MT6363_LDO_L("vsram-cpum", VSRAM_CPUM, "vs2-ldo1", 400000, 1193750, 6250, BUCK1, 28),
|
||||
MT6363_LDO_L("vsram-cpul", VSRAM_CPUL, "vs2-ldo2", 400000, 1193750, 6250, BUCK1, 29),
|
||||
MT6363_LDO_L_SC("vsram-digrf", VSRAM_DIGRF, "vs3-ldo1", 400000, 1193750, 6250, BUCK1, 23),
|
||||
MT6363_LDO_L_SC("vsram-mdfe", VSRAM_MDFE, "vs3-ldo1", 400000, 1193750, 6250, BUCK1, 24),
|
||||
MT6363_LDO_L_SC("vsram-modem", VSRAM_MODEM, "vs3-ldo2", 400000, 1193750, 6250, BUCK1, 25),
|
||||
MT6363_LDO_VT("vrf0p9", VRF09, "vs3-ldo2", 1, 18),
|
||||
MT6363_LDO_VT("vrf12", VRF12, "vs2-ldo1", 3, 19),
|
||||
MT6363_LDO_VT("vrf13", VRF13, "vs2-ldo1", 1, 20),
|
||||
MT6363_LDO_VT("vrf18", VRF18, "vs1-ldo1", 3, 21),
|
||||
MT6363_LDO_VT("vrf-io18", VRFIO18, "vs1-ldo1", 3, 22),
|
||||
MT6363_LDO_VT("vtref18", VTREF18, "vsys-ldo1", 2, 26),
|
||||
MT6363_LDO_VT("vufs12", VUFS12, "vs2-ldo1", 4, 33),
|
||||
MT6363_LDO_VT("vufs18", VUFS18, "vs1-ldo2", 3, 34),
|
||||
};
|
||||
|
||||
static int mt6363_backup_op_setting(struct regmap *map, struct mt6363_regulator_info *info)
|
||||
{
|
||||
unsigned int i, val;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(map, info->op_en_reg + OP_CFG_OFFSET, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
info->orig_op_cfg = val;
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = regmap_read(map, info->op_en_reg + i, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
info->orig_op_en |= val << (i * 8);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mt6363_irq_remove(void *data)
|
||||
{
|
||||
int *virq = data;
|
||||
|
||||
irq_dispose_mapping(*virq);
|
||||
}
|
||||
|
||||
static void mt6363_spmi_remove(void *data)
|
||||
{
|
||||
struct spmi_device *sdev = data;
|
||||
|
||||
spmi_device_remove(sdev);
|
||||
};
|
||||
|
||||
static struct regmap *mt6363_spmi_register_regmap(struct device *dev)
|
||||
{
|
||||
struct regmap_config mt6363_regmap_config = {
|
||||
.reg_bits = 16,
|
||||
.val_bits = 16,
|
||||
.max_register = 0x1f90,
|
||||
.fast_io = true,
|
||||
};
|
||||
struct spmi_device *sdev, *sparent;
|
||||
u32 base;
|
||||
int ret;
|
||||
|
||||
if (!dev->parent)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
ret = device_property_read_u32(dev, "reg", &base);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
sparent = to_spmi_device(dev->parent);
|
||||
if (!sparent)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
sdev = spmi_device_alloc(sparent->ctrl);
|
||||
if (!sdev)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
sdev->usid = sparent->usid;
|
||||
dev_set_name(&sdev->dev, "%d-%02x-regulator", sdev->ctrl->nr, sdev->usid);
|
||||
ret = device_add(&sdev->dev);
|
||||
if (ret) {
|
||||
put_device(&sdev->dev);
|
||||
return ERR_PTR(ret);
|
||||
};
|
||||
|
||||
ret = devm_add_action_or_reset(dev, mt6363_spmi_remove, sdev);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
mt6363_regmap_config.reg_base = base;
|
||||
|
||||
return devm_regmap_init_spmi_ext(sdev, &mt6363_regmap_config);
|
||||
}
|
||||
|
||||
static int mt6363_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *interrupt_parent;
|
||||
struct regulator_config config = {};
|
||||
struct mt6363_regulator_info *info;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct regulator_dev *rdev;
|
||||
struct irq_domain *domain;
|
||||
struct irq_fwspec fwspec;
|
||||
struct spmi_device *sdev;
|
||||
int i, ret;
|
||||
|
||||
config.regmap = mt6363_spmi_register_regmap(dev);
|
||||
if (IS_ERR(config.regmap))
|
||||
return dev_err_probe(dev, PTR_ERR(config.regmap),
|
||||
"Cannot get regmap\n");
|
||||
config.dev = dev;
|
||||
sdev = to_spmi_device(dev->parent);
|
||||
|
||||
interrupt_parent = of_irq_find_parent(dev->of_node);
|
||||
if (!interrupt_parent)
|
||||
return dev_err_probe(dev, -EINVAL, "Cannot find IRQ parent\n");
|
||||
|
||||
domain = irq_find_host(interrupt_parent);
|
||||
of_node_put(interrupt_parent);
|
||||
fwspec.fwnode = domain->fwnode;
|
||||
|
||||
fwspec.param_count = 3;
|
||||
fwspec.param[0] = sdev->usid;
|
||||
fwspec.param[2] = IRQ_TYPE_LEVEL_HIGH;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(mt6363_regulators); i++) {
|
||||
info = &mt6363_regulators[i];
|
||||
|
||||
fwspec.param[1] = info->hwirq;
|
||||
info->virq = irq_create_fwspec_mapping(&fwspec);
|
||||
if (!info->virq)
|
||||
return dev_err_probe(dev, -EINVAL,
|
||||
"Failed to map IRQ%d\n", info->hwirq);
|
||||
|
||||
ret = devm_add_action_or_reset(dev, mt6363_irq_remove, &info->virq);
|
||||
if (ret) {
|
||||
irq_dispose_mapping(info->hwirq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
config.driver_data = info;
|
||||
INIT_DELAYED_WORK(&info->oc_work, mt6363_oc_irq_enable_work);
|
||||
|
||||
rdev = devm_regulator_register(dev, &info->desc, &config);
|
||||
if (IS_ERR(rdev))
|
||||
return dev_err_probe(dev, PTR_ERR(rdev),
|
||||
"failed to register %s\n", info->desc.name);
|
||||
|
||||
if (info->lp_imax_uA) {
|
||||
ret = mt6363_backup_op_setting(config.regmap, info);
|
||||
if (ret) {
|
||||
dev_warn(dev, "Failed to backup op_setting for %s\n",
|
||||
info->desc.name);
|
||||
info->lp_imax_uA = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id mt6363_regulator_match[] = {
|
||||
{ .compatible = "mediatek,mt6363-regulator" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static struct platform_driver mt6363_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "mt6363-regulator",
|
||||
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
|
||||
.of_match_table = mt6363_regulator_match,
|
||||
},
|
||||
.probe = mt6363_regulator_probe,
|
||||
};
|
||||
module_platform_driver(mt6363_regulator_driver);
|
||||
|
||||
MODULE_AUTHOR("AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>");
|
||||
MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6363 PMIC");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -79,10 +79,10 @@ static void of_get_regulator_prot_limits(struct device_node *np,
|
|||
|
||||
static int of_get_regulation_constraints(struct device *dev,
|
||||
struct device_node *np,
|
||||
struct regulator_init_data **init_data,
|
||||
struct regulator_init_data *init_data,
|
||||
const struct regulator_desc *desc)
|
||||
{
|
||||
struct regulation_constraints *constraints = &(*init_data)->constraints;
|
||||
struct regulation_constraints *constraints = &init_data->constraints;
|
||||
struct regulator_state *suspend_state;
|
||||
struct device_node *suspend_np;
|
||||
unsigned int mode;
|
||||
|
|
@ -359,7 +359,7 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
|
|||
if (!init_data)
|
||||
return NULL; /* Out of memory? */
|
||||
|
||||
if (of_get_regulation_constraints(dev, node, &init_data, desc))
|
||||
if (of_get_regulation_constraints(dev, node, init_data, desc))
|
||||
return NULL;
|
||||
|
||||
return init_data;
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ static int buck_set_dvs(const struct regulator_desc *desc,
|
|||
}
|
||||
|
||||
if (ret == 0) {
|
||||
struct pca9450_regulator_desc *regulator = container_of(desc,
|
||||
const struct pca9450_regulator_desc *regulator = container_of_const(desc,
|
||||
struct pca9450_regulator_desc, desc);
|
||||
|
||||
/* Enable DVS control through PMIC_STBY_REQ for this BUCK */
|
||||
|
|
@ -263,7 +263,7 @@ static int pca9450_set_dvs_levels(struct device_node *np,
|
|||
const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
struct pca9450_regulator_desc *data = container_of(desc,
|
||||
const struct pca9450_regulator_desc *data = container_of_const(desc,
|
||||
struct pca9450_regulator_desc, desc);
|
||||
const struct pc9450_dvs_config *dvs = &data->dvs;
|
||||
unsigned int reg, mask;
|
||||
|
|
@ -308,7 +308,7 @@ static inline unsigned int pca9450_map_mode(unsigned int mode)
|
|||
|
||||
static int pca9450_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
||||
{
|
||||
struct pca9450_regulator_desc *desc = container_of(rdev->desc,
|
||||
const struct pca9450_regulator_desc *desc = container_of_const(rdev->desc,
|
||||
struct pca9450_regulator_desc, desc);
|
||||
const struct pc9450_dvs_config *dvs = &desc->dvs;
|
||||
int val;
|
||||
|
|
@ -333,7 +333,7 @@ static int pca9450_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
|
|||
|
||||
static unsigned int pca9450_buck_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct pca9450_regulator_desc *desc = container_of(rdev->desc,
|
||||
const struct pca9450_regulator_desc *desc = container_of_const(rdev->desc,
|
||||
struct pca9450_regulator_desc, desc);
|
||||
const struct pc9450_dvs_config *dvs = &desc->dvs;
|
||||
int ret = 0, regval;
|
||||
|
|
@ -355,6 +355,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck1",
|
||||
.supply_name = "inb13",
|
||||
.of_match = of_match_ptr("BUCK1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK1,
|
||||
|
|
@ -388,6 +389,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck2",
|
||||
.supply_name = "inb26",
|
||||
.of_match = of_match_ptr("BUCK2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK2,
|
||||
|
|
@ -421,6 +423,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck3",
|
||||
.supply_name = "inb13",
|
||||
.of_match = of_match_ptr("BUCK3"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK3,
|
||||
|
|
@ -454,6 +457,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck4",
|
||||
.supply_name = "inb45",
|
||||
.of_match = of_match_ptr("BUCK4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK4,
|
||||
|
|
@ -478,6 +482,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck5",
|
||||
.supply_name = "inb45",
|
||||
.of_match = of_match_ptr("BUCK5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK5,
|
||||
|
|
@ -502,6 +507,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck6",
|
||||
.supply_name = "inb26",
|
||||
.of_match = of_match_ptr("BUCK6"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK6,
|
||||
|
|
@ -526,6 +532,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo1",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO1,
|
||||
|
|
@ -544,6 +551,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo2",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO2,
|
||||
|
|
@ -562,6 +570,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo3",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO3"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO3,
|
||||
|
|
@ -580,6 +589,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo4",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO4,
|
||||
|
|
@ -598,6 +608,7 @@ static struct pca9450_regulator_desc pca9450a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo5",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO5,
|
||||
|
|
@ -623,6 +634,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck1",
|
||||
.supply_name = "inb13",
|
||||
.of_match = of_match_ptr("BUCK1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK1,
|
||||
|
|
@ -656,6 +668,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck2",
|
||||
.supply_name = "inb26",
|
||||
.of_match = of_match_ptr("BUCK2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK2,
|
||||
|
|
@ -689,6 +702,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck4",
|
||||
.supply_name = "inb45",
|
||||
.of_match = of_match_ptr("BUCK4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK4,
|
||||
|
|
@ -713,6 +727,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck5",
|
||||
.supply_name = "inb45",
|
||||
.of_match = of_match_ptr("BUCK5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK5,
|
||||
|
|
@ -737,6 +752,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck6",
|
||||
.supply_name = "inb26",
|
||||
.of_match = of_match_ptr("BUCK6"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK6,
|
||||
|
|
@ -761,6 +777,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo1",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO1,
|
||||
|
|
@ -779,6 +796,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo2",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO2,
|
||||
|
|
@ -797,6 +815,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo3",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO3"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO3,
|
||||
|
|
@ -815,6 +834,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo4",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO4,
|
||||
|
|
@ -833,6 +853,7 @@ static struct pca9450_regulator_desc pca9450bc_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo5",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO5,
|
||||
|
|
@ -854,6 +875,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck1",
|
||||
.supply_name = "inb13",
|
||||
.of_match = of_match_ptr("BUCK1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK1,
|
||||
|
|
@ -886,6 +908,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck2",
|
||||
.supply_name = "inb26",
|
||||
.of_match = of_match_ptr("BUCK2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK2,
|
||||
|
|
@ -918,6 +941,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck4",
|
||||
.supply_name = "inb45",
|
||||
.of_match = of_match_ptr("BUCK4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK4,
|
||||
|
|
@ -942,6 +966,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck5",
|
||||
.supply_name = "inb45",
|
||||
.of_match = of_match_ptr("BUCK5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK5,
|
||||
|
|
@ -966,6 +991,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "buck6",
|
||||
.supply_name = "inb26",
|
||||
.of_match = of_match_ptr("BUCK6"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_BUCK6,
|
||||
|
|
@ -990,6 +1016,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo1",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO1,
|
||||
|
|
@ -1008,6 +1035,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo3",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO3"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO3,
|
||||
|
|
@ -1026,6 +1054,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo4",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO4"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO4,
|
||||
|
|
@ -1044,6 +1073,7 @@ static struct pca9450_regulator_desc pca9451a_regulators[] = {
|
|||
{
|
||||
.desc = {
|
||||
.name = "ldo5",
|
||||
.supply_name = "inl1",
|
||||
.of_match = of_match_ptr("LDO5"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = PCA9450_LDO5,
|
||||
|
|
@ -1117,6 +1147,143 @@ static int pca9450_i2c_restart_handler(struct sys_off_data *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pca9450_of_init(struct pca9450 *pca9450)
|
||||
{
|
||||
struct i2c_client *i2c = container_of(pca9450->dev, struct i2c_client, dev);
|
||||
int ret;
|
||||
unsigned int val;
|
||||
unsigned int reset_ctrl;
|
||||
unsigned int rstb_deb_ctrl;
|
||||
unsigned int t_on_deb, t_off_deb;
|
||||
unsigned int t_on_step, t_off_step;
|
||||
unsigned int t_restart;
|
||||
|
||||
if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset"))
|
||||
reset_ctrl = WDOG_B_CFG_WARM;
|
||||
else
|
||||
reset_ctrl = WDOG_B_CFG_COLD_LDO12;
|
||||
|
||||
/* Set reset behavior on assertion of WDOG_B signal */
|
||||
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
|
||||
WDOG_B_CFG_MASK, reset_ctrl);
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret, "Failed to set WDOG_B reset behavior\n");
|
||||
|
||||
ret = of_property_read_u32(i2c->dev.of_node, "npx,pmic-rst-b-debounce-ms", &val);
|
||||
if (ret == -EINVAL)
|
||||
rstb_deb_ctrl = T_PMIC_RST_DEB_50MS;
|
||||
else if (ret)
|
||||
return ret;
|
||||
else {
|
||||
switch (val) {
|
||||
case 10: rstb_deb_ctrl = T_PMIC_RST_DEB_10MS; break;
|
||||
case 50: rstb_deb_ctrl = T_PMIC_RST_DEB_50MS; break;
|
||||
case 100: rstb_deb_ctrl = T_PMIC_RST_DEB_100MS; break;
|
||||
case 500: rstb_deb_ctrl = T_PMIC_RST_DEB_500MS; break;
|
||||
case 1000: rstb_deb_ctrl = T_PMIC_RST_DEB_1S; break;
|
||||
case 2000: rstb_deb_ctrl = T_PMIC_RST_DEB_2S; break;
|
||||
case 4000: rstb_deb_ctrl = T_PMIC_RST_DEB_4S; break;
|
||||
case 8000: rstb_deb_ctrl = T_PMIC_RST_DEB_8S; break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
}
|
||||
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
|
||||
T_PMIC_RST_DEB_MASK, rstb_deb_ctrl);
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret, "Failed to set PMIC_RST_B debounce time\n");
|
||||
|
||||
ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-on-debounce-us", &val);
|
||||
if (ret == -EINVAL)
|
||||
t_on_deb = T_ON_DEB_20MS;
|
||||
else if (ret)
|
||||
return ret;
|
||||
else {
|
||||
switch (val) {
|
||||
case 120: t_on_deb = T_ON_DEB_120US; break;
|
||||
case 20000: t_on_deb = T_ON_DEB_20MS; break;
|
||||
case 100000: t_on_deb = T_ON_DEB_100MS; break;
|
||||
case 750000: t_on_deb = T_ON_DEB_750MS; break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(i2c->dev.of_node, "nxp,pmic-on-req-off-debounce-us", &val);
|
||||
if (ret == -EINVAL)
|
||||
t_off_deb = T_OFF_DEB_120US;
|
||||
else if (ret)
|
||||
return ret;
|
||||
else {
|
||||
switch (val) {
|
||||
case 120: t_off_deb = T_OFF_DEB_120US; break;
|
||||
case 2000: t_off_deb = T_OFF_DEB_2MS; break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(i2c->dev.of_node, "nxp,power-on-step-ms", &val);
|
||||
if (ret == -EINVAL)
|
||||
t_on_step = T_ON_STEP_2MS;
|
||||
else if (ret)
|
||||
return ret;
|
||||
else {
|
||||
switch (val) {
|
||||
case 1: t_on_step = T_ON_STEP_1MS; break;
|
||||
case 2: t_on_step = T_ON_STEP_2MS; break;
|
||||
case 4: t_on_step = T_ON_STEP_4MS; break;
|
||||
case 8: t_on_step = T_ON_STEP_8MS; break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(i2c->dev.of_node, "nxp,power-down-step-ms", &val);
|
||||
if (ret == -EINVAL)
|
||||
t_off_step = T_OFF_STEP_8MS;
|
||||
else if (ret)
|
||||
return ret;
|
||||
else {
|
||||
switch (val) {
|
||||
case 2: t_off_step = T_OFF_STEP_2MS; break;
|
||||
case 4: t_off_step = T_OFF_STEP_4MS; break;
|
||||
case 8: t_off_step = T_OFF_STEP_8MS; break;
|
||||
case 16: t_off_step = T_OFF_STEP_16MS; break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(i2c->dev.of_node, "nxp,restart-ms", &val);
|
||||
if (ret == -EINVAL)
|
||||
t_restart = T_RESTART_250MS;
|
||||
else if (ret)
|
||||
return ret;
|
||||
else {
|
||||
switch (val) {
|
||||
case 250: t_restart = T_RESTART_250MS; break;
|
||||
case 500: t_restart = T_RESTART_500MS; break;
|
||||
default: return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_PWRCTRL,
|
||||
T_ON_DEB_MASK | T_OFF_DEB_MASK | T_ON_STEP_MASK |
|
||||
T_OFF_STEP_MASK | T_RESTART_MASK,
|
||||
t_on_deb | t_off_deb | t_on_step |
|
||||
t_off_step | t_restart);
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret,
|
||||
"Failed to set PWR_CTRL debounce configuration\n");
|
||||
|
||||
if (of_property_read_bool(i2c->dev.of_node, "nxp,i2c-lt-enable")) {
|
||||
/* Enable I2C Level Translator */
|
||||
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_CONFIG2,
|
||||
I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN);
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret,
|
||||
"Failed to enable I2C level translator\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pca9450_i2c_probe(struct i2c_client *i2c)
|
||||
{
|
||||
enum pca9450_chip_type type = (unsigned int)(uintptr_t)
|
||||
|
|
@ -1126,7 +1293,6 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
|
|||
struct regulator_dev *ldo5;
|
||||
struct pca9450 *pca9450;
|
||||
unsigned int device_id, i;
|
||||
unsigned int reset_ctrl;
|
||||
int ret;
|
||||
|
||||
pca9450 = devm_kzalloc(&i2c->dev, sizeof(struct pca9450), GFP_KERNEL);
|
||||
|
|
@ -1224,25 +1390,9 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
|
|||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret, "Failed to clear PRESET_EN bit\n");
|
||||
|
||||
if (of_property_read_bool(i2c->dev.of_node, "nxp,wdog_b-warm-reset"))
|
||||
reset_ctrl = WDOG_B_CFG_WARM;
|
||||
else
|
||||
reset_ctrl = WDOG_B_CFG_COLD_LDO12;
|
||||
|
||||
/* Set reset behavior on assertion of WDOG_B signal */
|
||||
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_RESET_CTRL,
|
||||
WDOG_B_CFG_MASK, reset_ctrl);
|
||||
ret = pca9450_of_init(pca9450);
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret, "Failed to set WDOG_B reset behavior\n");
|
||||
|
||||
if (of_property_read_bool(i2c->dev.of_node, "nxp,i2c-lt-enable")) {
|
||||
/* Enable I2C Level Translator */
|
||||
ret = regmap_update_bits(pca9450->regmap, PCA9450_REG_CONFIG2,
|
||||
I2C_LT_MASK, I2C_LT_ON_STANDBY_RUN);
|
||||
if (ret)
|
||||
return dev_err_probe(&i2c->dev, ret,
|
||||
"Failed to enable I2C level translator\n");
|
||||
}
|
||||
return dev_err_probe(&i2c->dev, ret, "Unable to parse OF data\n");
|
||||
|
||||
/*
|
||||
* For LDO5 we need to be able to check the status of the SD_VSEL input in
|
||||
|
|
@ -1251,10 +1401,9 @@ static int pca9450_i2c_probe(struct i2c_client *i2c)
|
|||
* to this signal (if SION bit is set in IOMUX).
|
||||
*/
|
||||
pca9450->sd_vsel_gpio = gpiod_get_optional(&ldo5->dev, "sd-vsel", GPIOD_IN);
|
||||
if (IS_ERR(pca9450->sd_vsel_gpio)) {
|
||||
dev_err(&i2c->dev, "Failed to get SD_VSEL GPIO\n");
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(pca9450->sd_vsel_gpio))
|
||||
return dev_err_probe(&i2c->dev, PTR_ERR(pca9450->sd_vsel_gpio),
|
||||
"Failed to get SD_VSEL GPIO\n");
|
||||
|
||||
pca9450->sd_vsel_fixed_low =
|
||||
of_property_read_bool(ldo5->dev.of_node, "nxp,sd-vsel-fixed-low");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,429 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
//
|
||||
// regulator driver for the PF1550
|
||||
//
|
||||
// Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
// Robin Gong <yibin.gong@freescale.com>
|
||||
//
|
||||
// Portions Copyright (c) 2025 Savoir-faire Linux Inc.
|
||||
// Samuel Kayode <samuel.kayode@savoirfairelinux.com>
|
||||
//
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mfd/pf1550.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
|
||||
#define PF1550_REGULATOR_IRQ_NR 11
|
||||
#define PF1550_MAX_REGULATOR 7
|
||||
|
||||
struct pf1550_desc {
|
||||
struct regulator_desc desc;
|
||||
unsigned char stby_reg;
|
||||
unsigned char stby_mask;
|
||||
unsigned char stby_enable_reg;
|
||||
unsigned char stby_enable_mask;
|
||||
};
|
||||
|
||||
struct pf1550_regulator_info {
|
||||
struct device *dev;
|
||||
const struct pf1550_ddata *pf1550;
|
||||
struct pf1550_desc regulator_descs[PF1550_MAX_REGULATOR];
|
||||
struct regulator_dev *rdevs[PF1550_MAX_REGULATOR];
|
||||
};
|
||||
|
||||
static const int pf1550_sw12_volts[] = {
|
||||
1100000, 1200000, 1350000, 1500000, 1800000, 2500000, 3000000, 3300000,
|
||||
};
|
||||
|
||||
static const int pf1550_ldo13_volts[] = {
|
||||
750000, 800000, 850000, 900000, 950000, 1000000, 1050000, 1100000,
|
||||
1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
|
||||
1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
|
||||
2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
|
||||
};
|
||||
|
||||
static int pf1550_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
|
||||
{
|
||||
int id = rdev_get_id(rdev);
|
||||
unsigned int ramp_bits = 0;
|
||||
int ret;
|
||||
|
||||
if (id > PF1550_VREFDDR)
|
||||
return -EACCES;
|
||||
|
||||
if (ramp_delay < 0 || ramp_delay > 6250)
|
||||
return -EINVAL;
|
||||
|
||||
ramp_delay = 6250 / ramp_delay;
|
||||
ramp_bits = ramp_delay >> 1;
|
||||
|
||||
ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg + 4, 0x10,
|
||||
ramp_bits << 4);
|
||||
if (ret < 0)
|
||||
dev_err(&rdev->dev, "ramp failed, err %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pf1550_set_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
const struct pf1550_desc *desc = container_of_const(rdev->desc,
|
||||
struct pf1550_desc,
|
||||
desc);
|
||||
unsigned int val = desc->stby_enable_mask;
|
||||
|
||||
return regmap_update_bits(rdev->regmap, desc->stby_enable_reg,
|
||||
desc->stby_enable_mask, val);
|
||||
}
|
||||
|
||||
static int pf1550_set_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
const struct pf1550_desc *desc = container_of_const(rdev->desc,
|
||||
struct pf1550_desc,
|
||||
desc);
|
||||
|
||||
return regmap_update_bits(rdev->regmap, desc->stby_enable_reg,
|
||||
desc->stby_enable_mask, 0);
|
||||
}
|
||||
|
||||
static int pf1550_buck_set_table_suspend_voltage(struct regulator_dev *rdev,
|
||||
int uV)
|
||||
{
|
||||
const struct pf1550_desc *desc = container_of_const(rdev->desc,
|
||||
struct pf1550_desc,
|
||||
desc);
|
||||
int ret;
|
||||
|
||||
ret = regulator_map_voltage_ascend(rdev, uV, uV);
|
||||
if (ret < 0) {
|
||||
dev_err(rdev_get_dev(rdev), "failed to map %i uV\n", uV);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, desc->stby_reg,
|
||||
desc->stby_mask, ret);
|
||||
}
|
||||
|
||||
static int pf1550_buck_set_linear_suspend_voltage(struct regulator_dev *rdev,
|
||||
int uV)
|
||||
{
|
||||
const struct pf1550_desc *desc = container_of_const(rdev->desc,
|
||||
struct pf1550_desc,
|
||||
desc);
|
||||
int ret;
|
||||
|
||||
ret = regulator_map_voltage_linear(rdev, uV, uV);
|
||||
if (ret < 0) {
|
||||
dev_err(rdev_get_dev(rdev), "failed to map %i uV\n", uV);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, desc->stby_reg,
|
||||
desc->stby_mask, ret);
|
||||
}
|
||||
|
||||
static const struct regulator_ops pf1550_sw1_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.set_suspend_enable = pf1550_set_suspend_enable,
|
||||
.set_suspend_disable = pf1550_set_suspend_disable,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_suspend_voltage = pf1550_buck_set_table_suspend_voltage,
|
||||
.map_voltage = regulator_map_voltage_ascend,
|
||||
.set_ramp_delay = pf1550_set_ramp_delay,
|
||||
};
|
||||
|
||||
static const struct regulator_ops pf1550_sw2_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.set_suspend_enable = pf1550_set_suspend_enable,
|
||||
.set_suspend_disable = pf1550_set_suspend_disable,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_suspend_voltage = pf1550_buck_set_linear_suspend_voltage,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.set_ramp_delay = pf1550_set_ramp_delay,
|
||||
};
|
||||
|
||||
static const struct regulator_ops pf1550_ldo1_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.set_suspend_enable = pf1550_set_suspend_enable,
|
||||
.set_suspend_disable = pf1550_set_suspend_disable,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.map_voltage = regulator_map_voltage_ascend,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
};
|
||||
|
||||
static const struct regulator_ops pf1550_ldo2_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.set_suspend_enable = pf1550_set_suspend_enable,
|
||||
.set_suspend_disable = pf1550_set_suspend_disable,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
};
|
||||
|
||||
static const struct regulator_ops pf1550_fixed_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.set_suspend_enable = pf1550_set_suspend_enable,
|
||||
.set_suspend_disable = pf1550_set_suspend_disable,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
};
|
||||
|
||||
#define PF_VREF(_chip, match, _name, voltage) { \
|
||||
.desc = { \
|
||||
.name = #_name, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.n_voltages = 1, \
|
||||
.ops = &pf1550_fixed_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = _chip ## _ ## _name, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = (voltage), \
|
||||
.enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
|
||||
.enable_mask = 0x1, \
|
||||
}, \
|
||||
.stby_enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
|
||||
.stby_enable_mask = 0x2, \
|
||||
}
|
||||
|
||||
#define PF_SW(_chip, match, _name, min, max, mask, step) { \
|
||||
.desc = { \
|
||||
.name = #_name, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.n_voltages = ((max) - (min)) / (step) + 1, \
|
||||
.ops = &pf1550_sw2_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = _chip ## _ ## _name, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = (min), \
|
||||
.uV_step = (step), \
|
||||
.linear_min_sel = 0, \
|
||||
.vsel_reg = _chip ## _PMIC_REG_ ## _name ## _VOLT, \
|
||||
.vsel_mask = (mask), \
|
||||
.enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
|
||||
.enable_mask = 0x1, \
|
||||
}, \
|
||||
.stby_reg = _chip ## _PMIC_REG_ ## _name ## _STBY_VOLT, \
|
||||
.stby_mask = (mask), \
|
||||
.stby_enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
|
||||
.stby_enable_mask = 0x2, \
|
||||
}
|
||||
|
||||
#define PF_LDO1(_chip, match, _name, mask, voltages) { \
|
||||
.desc = { \
|
||||
.name = #_name, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.n_voltages = ARRAY_SIZE(voltages), \
|
||||
.ops = &pf1550_ldo1_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = _chip ## _ ## _name, \
|
||||
.owner = THIS_MODULE, \
|
||||
.volt_table = voltages, \
|
||||
.vsel_reg = _chip ## _PMIC_REG_ ## _name ## _VOLT, \
|
||||
.vsel_mask = (mask), \
|
||||
.enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
|
||||
.enable_mask = 0x1, \
|
||||
}, \
|
||||
.stby_enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
|
||||
.stby_enable_mask = 0x2, \
|
||||
}
|
||||
|
||||
#define PF_LDO2(_chip, match, _name, mask, min, max, step) { \
|
||||
.desc = { \
|
||||
.name = #_name, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.n_voltages = ((max) - (min)) / (step) + 1, \
|
||||
.ops = &pf1550_ldo2_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = _chip ## _ ## _name, \
|
||||
.owner = THIS_MODULE, \
|
||||
.min_uV = (min), \
|
||||
.uV_step = (step), \
|
||||
.linear_min_sel = 0, \
|
||||
.vsel_reg = _chip ## _PMIC_REG_ ## _name ## _VOLT, \
|
||||
.vsel_mask = (mask), \
|
||||
.enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
|
||||
.enable_mask = 0x1, \
|
||||
}, \
|
||||
.stby_enable_reg = _chip ## _PMIC_REG_ ## _name ## _CTRL, \
|
||||
.stby_enable_mask = 0x2, \
|
||||
}
|
||||
|
||||
static struct pf1550_desc pf1550_regulators[] = {
|
||||
PF_SW(PF1550, "sw1", SW1, 600000, 1387500, 0x3f, 12500),
|
||||
PF_SW(PF1550, "sw2", SW2, 600000, 1387500, 0x3f, 12500),
|
||||
PF_SW(PF1550, "sw3", SW3, 1800000, 3300000, 0xf, 100000),
|
||||
PF_VREF(PF1550, "vrefddr", VREFDDR, 1200000),
|
||||
PF_LDO1(PF1550, "ldo1", LDO1, 0x1f, pf1550_ldo13_volts),
|
||||
PF_LDO2(PF1550, "ldo2", LDO2, 0xf, 1800000, 3300000, 100000),
|
||||
PF_LDO1(PF1550, "ldo3", LDO3, 0x1f, pf1550_ldo13_volts),
|
||||
};
|
||||
|
||||
static irqreturn_t pf1550_regulator_irq_handler(int irq, void *data)
|
||||
{
|
||||
struct pf1550_regulator_info *info = data;
|
||||
struct device *dev = info->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
int i, irq_type = -1;
|
||||
unsigned int event;
|
||||
|
||||
for (i = 0; i < PF1550_REGULATOR_IRQ_NR; i++)
|
||||
if (irq == platform_get_irq(pdev, i))
|
||||
irq_type = i;
|
||||
|
||||
switch (irq_type) {
|
||||
/* The _LS interrupts indicate over-current event. The _HS interrupts
|
||||
* which are more accurate and can detect catastrophic faults, issue
|
||||
* an error event. The current limit FAULT interrupt is similar to the
|
||||
* _HS'
|
||||
*/
|
||||
case PF1550_PMIC_IRQ_SW1_LS:
|
||||
case PF1550_PMIC_IRQ_SW2_LS:
|
||||
case PF1550_PMIC_IRQ_SW3_LS:
|
||||
event = REGULATOR_EVENT_OVER_CURRENT_WARN;
|
||||
for (i = 0; i < PF1550_MAX_REGULATOR; i++)
|
||||
if (!strcmp(rdev_get_name(info->rdevs[i]), "SW3"))
|
||||
regulator_notifier_call_chain(info->rdevs[i],
|
||||
event, NULL);
|
||||
break;
|
||||
case PF1550_PMIC_IRQ_SW1_HS:
|
||||
case PF1550_PMIC_IRQ_SW2_HS:
|
||||
case PF1550_PMIC_IRQ_SW3_HS:
|
||||
event = REGULATOR_EVENT_OVER_CURRENT;
|
||||
for (i = 0; i < PF1550_MAX_REGULATOR; i++)
|
||||
if (!strcmp(rdev_get_name(info->rdevs[i]), "SW3"))
|
||||
regulator_notifier_call_chain(info->rdevs[i],
|
||||
event, NULL);
|
||||
break;
|
||||
case PF1550_PMIC_IRQ_LDO1_FAULT:
|
||||
case PF1550_PMIC_IRQ_LDO2_FAULT:
|
||||
case PF1550_PMIC_IRQ_LDO3_FAULT:
|
||||
event = REGULATOR_EVENT_OVER_CURRENT;
|
||||
for (i = 0; i < PF1550_MAX_REGULATOR; i++)
|
||||
if (!strcmp(rdev_get_name(info->rdevs[i]), "LDO3"))
|
||||
regulator_notifier_call_chain(info->rdevs[i],
|
||||
event, NULL);
|
||||
break;
|
||||
case PF1550_PMIC_IRQ_TEMP_110:
|
||||
case PF1550_PMIC_IRQ_TEMP_125:
|
||||
event = REGULATOR_EVENT_OVER_TEMP;
|
||||
for (i = 0; i < PF1550_MAX_REGULATOR; i++)
|
||||
regulator_notifier_call_chain(info->rdevs[i],
|
||||
event, NULL);
|
||||
break;
|
||||
default:
|
||||
dev_err(dev, "regulator interrupt: irq %d occurred\n",
|
||||
irq_type);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int pf1550_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct pf1550_ddata *pf1550 = dev_get_drvdata(pdev->dev.parent);
|
||||
struct regulator_config config = { };
|
||||
struct pf1550_regulator_info *info;
|
||||
int i, irq = -1, ret = 0;
|
||||
|
||||
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
config.regmap = dev_get_regmap(pf1550->dev, NULL);
|
||||
if (!config.regmap)
|
||||
return dev_err_probe(&pdev->dev, -ENODEV,
|
||||
"failed to get parent regmap\n");
|
||||
|
||||
config.dev = pf1550->dev;
|
||||
config.regmap = pf1550->regmap;
|
||||
info->dev = &pdev->dev;
|
||||
info->pf1550 = pf1550;
|
||||
|
||||
memcpy(info->regulator_descs, pf1550_regulators,
|
||||
sizeof(info->regulator_descs));
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pf1550_regulators); i++) {
|
||||
struct regulator_desc *desc;
|
||||
|
||||
desc = &info->regulator_descs[i].desc;
|
||||
|
||||
if ((desc->id == PF1550_SW2 && !pf1550->dvs2_enable) ||
|
||||
(desc->id == PF1550_SW1 && !pf1550->dvs1_enable)) {
|
||||
/* OTP_SW2_DVS_ENB == 1? or OTP_SW1_DVS_ENB == 1? */
|
||||
desc->volt_table = pf1550_sw12_volts;
|
||||
desc->n_voltages = ARRAY_SIZE(pf1550_sw12_volts);
|
||||
desc->ops = &pf1550_sw1_ops;
|
||||
}
|
||||
|
||||
info->rdevs[i] = devm_regulator_register(&pdev->dev, desc,
|
||||
&config);
|
||||
if (IS_ERR(info->rdevs[i]))
|
||||
return dev_err_probe(&pdev->dev,
|
||||
PTR_ERR(info->rdevs[i]),
|
||||
"failed to initialize regulator-%d\n",
|
||||
i);
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, info);
|
||||
|
||||
for (i = 0; i < PF1550_REGULATOR_IRQ_NR; i++) {
|
||||
irq = platform_get_irq(pdev, i);
|
||||
if (irq < 0)
|
||||
return irq;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
pf1550_regulator_irq_handler,
|
||||
IRQF_NO_SUSPEND,
|
||||
"pf1550-regulator", info);
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"failed: irq request (IRQ: %d)\n",
|
||||
i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id pf1550_regulator_id[] = {
|
||||
{ "pf1550-regulator", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, pf1550_regulator_id);
|
||||
|
||||
static struct platform_driver pf1550_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "pf1550-regulator",
|
||||
},
|
||||
.probe = pf1550_regulator_probe,
|
||||
.id_table = pf1550_regulator_id,
|
||||
};
|
||||
module_platform_driver(pf1550_regulator_driver);
|
||||
|
||||
MODULE_DESCRIPTION("NXP PF1550 regulator driver");
|
||||
MODULE_AUTHOR("Robin Gong <yibin.gong@freescale.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
|
@ -65,8 +65,7 @@ enum {
|
|||
#define PF9453_LDOSNVS_VOLTAGE_NUM 0x59
|
||||
|
||||
enum {
|
||||
PF9453_REG_DEV_ID = 0x00,
|
||||
PF9453_REG_OTP_VER = 0x01,
|
||||
PF9453_REG_DEV_ID = 0x01,
|
||||
PF9453_REG_INT1 = 0x02,
|
||||
PF9453_REG_INT1_MASK = 0x03,
|
||||
PF9453_REG_INT1_STATUS = 0x04,
|
||||
|
|
@ -120,7 +119,6 @@ enum {
|
|||
#define LDO_ENMODE_ONREQ_STBY_DPSTBY 0x03
|
||||
|
||||
/* PF9453_REG_BUCK1_CTRL bits */
|
||||
#define BUCK1_LPMODE 0x30
|
||||
#define BUCK1_AD 0x08
|
||||
#define BUCK1_FPWM 0x04
|
||||
#define BUCK1_ENMODE_MASK GENMASK(1, 0)
|
||||
|
|
@ -131,19 +129,16 @@ enum {
|
|||
#define BUCK2_RAMP_12P5MV 0x1
|
||||
#define BUCK2_RAMP_6P25MV 0x2
|
||||
#define BUCK2_RAMP_3P125MV 0x3
|
||||
#define BUCK2_LPMODE 0x30
|
||||
#define BUCK2_AD 0x08
|
||||
#define BUCK2_FPWM 0x04
|
||||
#define BUCK2_ENMODE_MASK GENMASK(1, 0)
|
||||
|
||||
/* PF9453_REG_BUCK3_CTRL bits */
|
||||
#define BUCK3_LPMODE 0x30
|
||||
#define BUCK3_AD 0x08
|
||||
#define BUCK3_FPWM 0x04
|
||||
#define BUCK3_ENMODE_MASK GENMASK(1, 0)
|
||||
|
||||
/* PF9453_REG_BUCK4_CTRL bits */
|
||||
#define BUCK4_LPMODE 0x30
|
||||
#define BUCK4_AD 0x08
|
||||
#define BUCK4_FPWM 0x04
|
||||
#define BUCK4_ENMODE_MASK GENMASK(1, 0)
|
||||
|
|
@ -192,13 +187,6 @@ enum {
|
|||
#define WDOG_B_CFG_WARM 0x40
|
||||
#define WDOG_B_CFG_COLD 0x80
|
||||
|
||||
/* PF9453_REG_CONFIG2 bits */
|
||||
#define I2C_LT_MASK GENMASK(1, 0)
|
||||
#define I2C_LT_FORCE_DISABLE 0x00
|
||||
#define I2C_LT_ON_STANDBY_RUN 0x01
|
||||
#define I2C_LT_ON_RUN 0x02
|
||||
#define I2C_LT_FORCE_ENABLE 0x03
|
||||
|
||||
static const struct regmap_range pf9453_status_range = {
|
||||
.range_min = PF9453_REG_INT1,
|
||||
.range_max = PF9453_REG_PWRON_STAT,
|
||||
|
|
@ -301,13 +289,15 @@ static int pf9453_pmic_write(struct pf9453 *pf9453, unsigned int reg, u8 mask, u
|
|||
}
|
||||
|
||||
/**
|
||||
* pf9453_regulator_enable_regmap for regmap users
|
||||
* pf9453_regulator_enable_regmap - enable regulator for regmap users
|
||||
*
|
||||
* @rdev: regulator to operate on
|
||||
*
|
||||
* Regulators that use regmap for their register I/O can set the
|
||||
* enable_reg and enable_mask fields in their descriptor and then use
|
||||
* this as their enable() operation, saving some code.
|
||||
*
|
||||
* Return: %0 on success, or negative errno.
|
||||
*/
|
||||
static int pf9453_regulator_enable_regmap(struct regulator_dev *rdev)
|
||||
{
|
||||
|
|
@ -326,13 +316,15 @@ static int pf9453_regulator_enable_regmap(struct regulator_dev *rdev)
|
|||
}
|
||||
|
||||
/**
|
||||
* pf9453_regulator_disable_regmap for regmap users
|
||||
* pf9453_regulator_disable_regmap - disable regulator for regmap users
|
||||
*
|
||||
* @rdev: regulator to operate on
|
||||
*
|
||||
* Regulators that use regmap for their register I/O can set the
|
||||
* enable_reg and enable_mask fields in their descriptor and then use
|
||||
* this as their disable() operation, saving some code.
|
||||
*
|
||||
* Return: %0 on success, or negative errno.
|
||||
*/
|
||||
static int pf9453_regulator_disable_regmap(struct regulator_dev *rdev)
|
||||
{
|
||||
|
|
@ -351,7 +343,7 @@ static int pf9453_regulator_disable_regmap(struct regulator_dev *rdev)
|
|||
}
|
||||
|
||||
/**
|
||||
* pf9453_regulator_set_voltage_sel_regmap for regmap users
|
||||
* pf9453_regulator_set_voltage_sel_regmap - set voltage for regmap users
|
||||
*
|
||||
* @rdev: regulator to operate on
|
||||
* @sel: Selector to set
|
||||
|
|
@ -359,6 +351,8 @@ static int pf9453_regulator_disable_regmap(struct regulator_dev *rdev)
|
|||
* Regulators that use regmap for their register I/O can set the
|
||||
* vsel_reg and vsel_mask fields in their descriptor and then use this
|
||||
* as their set_voltage_vsel operation, saving some code.
|
||||
*
|
||||
* Return: %0 on success, or negative errno.
|
||||
*/
|
||||
static int pf9453_regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned int sel)
|
||||
{
|
||||
|
|
@ -409,7 +403,7 @@ static int find_closest_bigger(unsigned int target, const unsigned int *table,
|
|||
}
|
||||
|
||||
/**
|
||||
* pf9453_regulator_set_ramp_delay_regmap
|
||||
* pf9453_regulator_set_ramp_delay_regmap - set ramp delay for regmap users
|
||||
*
|
||||
* @rdev: regulator to operate on
|
||||
* @ramp_delay: desired ramp delay value in microseconds
|
||||
|
|
@ -417,6 +411,8 @@ static int find_closest_bigger(unsigned int target, const unsigned int *table,
|
|||
* Regulators that use regmap for their register I/O can set the ramp_reg
|
||||
* and ramp_mask fields in their descriptor and then use this as their
|
||||
* set_ramp_delay operation, saving some code.
|
||||
*
|
||||
* Return: %0 on success, or negative errno.
|
||||
*/
|
||||
static int pf9453_regulator_set_ramp_delay_regmap(struct regulator_dev *rdev, int ramp_delay)
|
||||
{
|
||||
|
|
@ -536,21 +532,15 @@ static int buck_set_dvs(const struct regulator_desc *desc,
|
|||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
struct pf9453_regulator_desc *regulator = container_of(desc,
|
||||
struct pf9453_regulator_desc, desc);
|
||||
|
||||
/* Enable DVS control through PMIC_STBY_REQ for this BUCK */
|
||||
ret = pf9453_pmic_write(pf9453, regulator->desc.enable_reg,
|
||||
BUCK2_LPMODE, BUCK2_LPMODE);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pf9453_set_dvs_levels(struct device_node *np, const struct regulator_desc *desc,
|
||||
struct regulator_config *cfg)
|
||||
{
|
||||
struct pf9453_regulator_desc *data = container_of(desc, struct pf9453_regulator_desc, desc);
|
||||
const struct pf9453_regulator_desc *data = container_of_const(desc,
|
||||
struct pf9453_regulator_desc,
|
||||
desc);
|
||||
struct pf9453 *pf9453 = dev_get_drvdata(cfg->dev);
|
||||
const struct pf9453_dvs_config *dvs = &data->dvs;
|
||||
unsigned int reg, mask;
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ static void qcom_labibb_ocp_recovery_worker(struct work_struct *work)
|
|||
return;
|
||||
|
||||
reschedule:
|
||||
mod_delayed_work(system_wq, &vreg->ocp_recovery_work,
|
||||
mod_delayed_work(system_dfl_wq, &vreg->ocp_recovery_work,
|
||||
msecs_to_jiffies(OCP_RECOVERY_INTERVAL_MS));
|
||||
}
|
||||
|
||||
|
|
@ -510,7 +510,7 @@ static void qcom_labibb_sc_recovery_worker(struct work_struct *work)
|
|||
* taking action is not truly urgent anymore.
|
||||
*/
|
||||
vreg->sc_count++;
|
||||
mod_delayed_work(system_wq, &vreg->sc_recovery_work,
|
||||
mod_delayed_work(system_dfl_wq, &vreg->sc_recovery_work,
|
||||
msecs_to_jiffies(SC_RECOVERY_INTERVAL_MS));
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,12 +7,10 @@
|
|||
|
||||
#include <linux/module.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
static const struct regulator_ops rzg2l_usb_vbus_reg_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
#include <linux/mfd/sy7636a.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regmap.h>
|
||||
|
|
@ -19,6 +20,8 @@
|
|||
struct sy7636a_data {
|
||||
struct regmap *regmap;
|
||||
struct gpio_desc *pgood_gpio;
|
||||
struct gpio_desc *en_gpio;
|
||||
struct gpio_desc *vcom_en_gpio;
|
||||
};
|
||||
|
||||
static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev)
|
||||
|
|
@ -98,6 +101,30 @@ static int sy7636a_regulator_probe(struct platform_device *pdev)
|
|||
data->regmap = regmap;
|
||||
data->pgood_gpio = gdp;
|
||||
|
||||
ret = devm_regulator_get_enable_optional(&pdev->dev, "vin");
|
||||
if (ret)
|
||||
return dev_err_probe(&pdev->dev, ret,
|
||||
"failed to get vin regulator\n");
|
||||
|
||||
data->en_gpio = devm_gpiod_get_optional(&pdev->dev, "enable",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(data->en_gpio))
|
||||
return dev_err_probe(&pdev->dev,
|
||||
PTR_ERR(data->en_gpio),
|
||||
"failed to get en gpio\n");
|
||||
|
||||
/* Let VCOM just follow the default power on sequence */
|
||||
data->vcom_en_gpio = devm_gpiod_get_optional(&pdev->dev,
|
||||
"vcom-en", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(data->vcom_en_gpio))
|
||||
return dev_err_probe(&pdev->dev,
|
||||
PTR_ERR(data->vcom_en_gpio),
|
||||
"failed to get vcom-en gpio\n");
|
||||
|
||||
/* if chip was not enabled, give it time to wake up */
|
||||
if (data->en_gpio)
|
||||
usleep_range(2500, 4000);
|
||||
|
||||
platform_set_drvdata(pdev, data);
|
||||
|
||||
ret = regmap_write(regmap, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,273 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Declarations for the PF1550 PMIC
|
||||
*
|
||||
* Copyright (C) 2016 Freescale Semiconductor, Inc.
|
||||
* Robin Gong <yibin.gong@freescale.com>
|
||||
*
|
||||
* Portions Copyright (c) 2025 Savoir-faire Linux Inc.
|
||||
* Samuel Kayode <samuel.kayode@savoirfairelinux.com>
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_MFD_PF1550_H
|
||||
#define __LINUX_MFD_PF1550_H
|
||||
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
enum pf1550_pmic_reg {
|
||||
/* PMIC regulator part */
|
||||
PF1550_PMIC_REG_DEVICE_ID = 0x00,
|
||||
PF1550_PMIC_REG_OTP_FLAVOR = 0x01,
|
||||
PF1550_PMIC_REG_SILICON_REV = 0x02,
|
||||
|
||||
PF1550_PMIC_REG_INT_CATEGORY = 0x06,
|
||||
PF1550_PMIC_REG_SW_INT_STAT0 = 0x08,
|
||||
PF1550_PMIC_REG_SW_INT_MASK0 = 0x09,
|
||||
PF1550_PMIC_REG_SW_INT_SENSE0 = 0x0a,
|
||||
PF1550_PMIC_REG_SW_INT_STAT1 = 0x0b,
|
||||
PF1550_PMIC_REG_SW_INT_MASK1 = 0x0c,
|
||||
PF1550_PMIC_REG_SW_INT_SENSE1 = 0x0d,
|
||||
PF1550_PMIC_REG_SW_INT_STAT2 = 0x0e,
|
||||
PF1550_PMIC_REG_SW_INT_MASK2 = 0x0f,
|
||||
PF1550_PMIC_REG_SW_INT_SENSE2 = 0x10,
|
||||
PF1550_PMIC_REG_LDO_INT_STAT0 = 0x18,
|
||||
PF1550_PMIC_REG_LDO_INT_MASK0 = 0x19,
|
||||
PF1550_PMIC_REG_LDO_INT_SENSE0 = 0x1a,
|
||||
PF1550_PMIC_REG_TEMP_INT_STAT0 = 0x20,
|
||||
PF1550_PMIC_REG_TEMP_INT_MASK0 = 0x21,
|
||||
PF1550_PMIC_REG_TEMP_INT_SENSE0 = 0x22,
|
||||
PF1550_PMIC_REG_ONKEY_INT_STAT0 = 0x24,
|
||||
PF1550_PMIC_REG_ONKEY_INT_MASK0 = 0x25,
|
||||
PF1550_PMIC_REG_ONKEY_INT_SENSE0 = 0x26,
|
||||
PF1550_PMIC_REG_MISC_INT_STAT0 = 0x28,
|
||||
PF1550_PMIC_REG_MISC_INT_MASK0 = 0x29,
|
||||
PF1550_PMIC_REG_MISC_INT_SENSE0 = 0x2a,
|
||||
|
||||
PF1550_PMIC_REG_COINCELL_CONTROL = 0x30,
|
||||
|
||||
PF1550_PMIC_REG_SW1_VOLT = 0x32,
|
||||
PF1550_PMIC_REG_SW1_STBY_VOLT = 0x33,
|
||||
PF1550_PMIC_REG_SW1_SLP_VOLT = 0x34,
|
||||
PF1550_PMIC_REG_SW1_CTRL = 0x35,
|
||||
PF1550_PMIC_REG_SW1_CTRL1 = 0x36,
|
||||
PF1550_PMIC_REG_SW2_VOLT = 0x38,
|
||||
PF1550_PMIC_REG_SW2_STBY_VOLT = 0x39,
|
||||
PF1550_PMIC_REG_SW2_SLP_VOLT = 0x3a,
|
||||
PF1550_PMIC_REG_SW2_CTRL = 0x3b,
|
||||
PF1550_PMIC_REG_SW2_CTRL1 = 0x3c,
|
||||
PF1550_PMIC_REG_SW3_VOLT = 0x3e,
|
||||
PF1550_PMIC_REG_SW3_STBY_VOLT = 0x3f,
|
||||
PF1550_PMIC_REG_SW3_SLP_VOLT = 0x40,
|
||||
PF1550_PMIC_REG_SW3_CTRL = 0x41,
|
||||
PF1550_PMIC_REG_SW3_CTRL1 = 0x42,
|
||||
PF1550_PMIC_REG_VSNVS_CTRL = 0x48,
|
||||
PF1550_PMIC_REG_VREFDDR_CTRL = 0x4a,
|
||||
PF1550_PMIC_REG_LDO1_VOLT = 0x4c,
|
||||
PF1550_PMIC_REG_LDO1_CTRL = 0x4d,
|
||||
PF1550_PMIC_REG_LDO2_VOLT = 0x4f,
|
||||
PF1550_PMIC_REG_LDO2_CTRL = 0x50,
|
||||
PF1550_PMIC_REG_LDO3_VOLT = 0x52,
|
||||
PF1550_PMIC_REG_LDO3_CTRL = 0x53,
|
||||
PF1550_PMIC_REG_PWRCTRL0 = 0x58,
|
||||
PF1550_PMIC_REG_PWRCTRL1 = 0x59,
|
||||
PF1550_PMIC_REG_PWRCTRL2 = 0x5a,
|
||||
PF1550_PMIC_REG_PWRCTRL3 = 0x5b,
|
||||
PF1550_PMIC_REG_SW1_PWRDN_SEQ = 0x5f,
|
||||
PF1550_PMIC_REG_SW2_PWRDN_SEQ = 0x60,
|
||||
PF1550_PMIC_REG_SW3_PWRDN_SEQ = 0x61,
|
||||
PF1550_PMIC_REG_LDO1_PWRDN_SEQ = 0x62,
|
||||
PF1550_PMIC_REG_LDO2_PWRDN_SEQ = 0x63,
|
||||
PF1550_PMIC_REG_LDO3_PWRDN_SEQ = 0x64,
|
||||
PF1550_PMIC_REG_VREFDDR_PWRDN_SEQ = 0x65,
|
||||
|
||||
PF1550_PMIC_REG_STATE_INFO = 0x67,
|
||||
PF1550_PMIC_REG_I2C_ADDR = 0x68,
|
||||
PF1550_PMIC_REG_IO_DRV0 = 0x69,
|
||||
PF1550_PMIC_REG_IO_DRV1 = 0x6a,
|
||||
PF1550_PMIC_REG_RC_16MHZ = 0x6b,
|
||||
PF1550_PMIC_REG_KEY = 0x6f,
|
||||
|
||||
/* Charger part */
|
||||
PF1550_CHARG_REG_CHG_INT = 0x80,
|
||||
PF1550_CHARG_REG_CHG_INT_MASK = 0x82,
|
||||
PF1550_CHARG_REG_CHG_INT_OK = 0x84,
|
||||
PF1550_CHARG_REG_VBUS_SNS = 0x86,
|
||||
PF1550_CHARG_REG_CHG_SNS = 0x87,
|
||||
PF1550_CHARG_REG_BATT_SNS = 0x88,
|
||||
PF1550_CHARG_REG_CHG_OPER = 0x89,
|
||||
PF1550_CHARG_REG_CHG_TMR = 0x8a,
|
||||
PF1550_CHARG_REG_CHG_EOC_CNFG = 0x8d,
|
||||
PF1550_CHARG_REG_CHG_CURR_CNFG = 0x8e,
|
||||
PF1550_CHARG_REG_BATT_REG = 0x8f,
|
||||
PF1550_CHARG_REG_BATFET_CNFG = 0x91,
|
||||
PF1550_CHARG_REG_THM_REG_CNFG = 0x92,
|
||||
PF1550_CHARG_REG_VBUS_INLIM_CNFG = 0x94,
|
||||
PF1550_CHARG_REG_VBUS_LIN_DPM = 0x95,
|
||||
PF1550_CHARG_REG_USB_PHY_LDO_CNFG = 0x96,
|
||||
PF1550_CHARG_REG_DBNC_DELAY_TIME = 0x98,
|
||||
PF1550_CHARG_REG_CHG_INT_CNFG = 0x99,
|
||||
PF1550_CHARG_REG_THM_ADJ_SETTING = 0x9a,
|
||||
PF1550_CHARG_REG_VBUS2SYS_CNFG = 0x9b,
|
||||
PF1550_CHARG_REG_LED_PWM = 0x9c,
|
||||
PF1550_CHARG_REG_FAULT_BATFET_CNFG = 0x9d,
|
||||
PF1550_CHARG_REG_LED_CNFG = 0x9e,
|
||||
PF1550_CHARG_REG_CHGR_KEY2 = 0x9f,
|
||||
|
||||
PF1550_TEST_REG_FMRADDR = 0xc4,
|
||||
PF1550_TEST_REG_FMRDATA = 0xc5,
|
||||
PF1550_TEST_REG_KEY3 = 0xdf,
|
||||
|
||||
PF1550_PMIC_REG_END = 0xff,
|
||||
};
|
||||
|
||||
/* One-Time Programmable(OTP) memory */
|
||||
enum pf1550_otp_reg {
|
||||
PF1550_OTP_SW1_SW2 = 0x1e,
|
||||
PF1550_OTP_SW2_SW3 = 0x1f,
|
||||
};
|
||||
|
||||
#define PF1550_DEVICE_ID 0x7c
|
||||
|
||||
/* Keys for reading OTP */
|
||||
#define PF1550_OTP_PMIC_KEY 0x15
|
||||
#define PF1550_OTP_CHGR_KEY 0x50
|
||||
#define PF1550_OTP_TEST_KEY 0xab
|
||||
|
||||
/* Supported charger modes */
|
||||
#define PF1550_CHG_BAT_OFF 1
|
||||
#define PF1550_CHG_BAT_ON 2
|
||||
|
||||
#define PF1550_CHG_PRECHARGE 0
|
||||
#define PF1550_CHG_CONSTANT_CURRENT 1
|
||||
#define PF1550_CHG_CONSTANT_VOL 2
|
||||
#define PF1550_CHG_EOC 3
|
||||
#define PF1550_CHG_DONE 4
|
||||
#define PF1550_CHG_TIMER_FAULT 6
|
||||
#define PF1550_CHG_SUSPEND 7
|
||||
#define PF1550_CHG_OFF_INV 8
|
||||
#define PF1550_CHG_BAT_OVER 9
|
||||
#define PF1550_CHG_OFF_TEMP 10
|
||||
#define PF1550_CHG_LINEAR_ONLY 12
|
||||
#define PF1550_CHG_SNS_MASK 0xf
|
||||
#define PF1550_CHG_INT_MASK 0x51
|
||||
|
||||
#define PF1550_BAT_NO_VBUS 0
|
||||
#define PF1550_BAT_LOW_THAN_PRECHARG 1
|
||||
#define PF1550_BAT_CHARG_FAIL 2
|
||||
#define PF1550_BAT_HIGH_THAN_PRECHARG 4
|
||||
#define PF1550_BAT_OVER_VOL 5
|
||||
#define PF1550_BAT_NO_DETECT 6
|
||||
#define PF1550_BAT_SNS_MASK 0x7
|
||||
|
||||
#define PF1550_VBUS_UVLO BIT(2)
|
||||
#define PF1550_VBUS_IN2SYS BIT(3)
|
||||
#define PF1550_VBUS_OVLO BIT(4)
|
||||
#define PF1550_VBUS_VALID BIT(5)
|
||||
|
||||
#define PF1550_CHARG_REG_BATT_REG_CHGCV_MASK 0x3f
|
||||
#define PF1550_CHARG_REG_BATT_REG_VMINSYS_SHIFT 6
|
||||
#define PF1550_CHARG_REG_BATT_REG_VMINSYS_MASK GENMASK(7, 6)
|
||||
#define PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_SHIFT 2
|
||||
#define PF1550_CHARG_REG_THM_REG_CNFG_REGTEMP_MASK GENMASK(3, 2)
|
||||
|
||||
#define PF1550_ONKEY_RST_EN BIT(7)
|
||||
|
||||
/* DVS enable masks */
|
||||
#define OTP_SW1_DVS_ENB BIT(1)
|
||||
#define OTP_SW2_DVS_ENB BIT(3)
|
||||
|
||||
/* Top level interrupt masks */
|
||||
#define IRQ_REGULATOR (BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(6))
|
||||
#define IRQ_ONKEY BIT(5)
|
||||
#define IRQ_CHG BIT(0)
|
||||
|
||||
/* Regulator interrupt masks */
|
||||
#define PMIC_IRQ_SW1_LS BIT(0)
|
||||
#define PMIC_IRQ_SW2_LS BIT(1)
|
||||
#define PMIC_IRQ_SW3_LS BIT(2)
|
||||
#define PMIC_IRQ_SW1_HS BIT(0)
|
||||
#define PMIC_IRQ_SW2_HS BIT(1)
|
||||
#define PMIC_IRQ_SW3_HS BIT(2)
|
||||
#define PMIC_IRQ_LDO1_FAULT BIT(0)
|
||||
#define PMIC_IRQ_LDO2_FAULT BIT(1)
|
||||
#define PMIC_IRQ_LDO3_FAULT BIT(2)
|
||||
#define PMIC_IRQ_TEMP_110 BIT(0)
|
||||
#define PMIC_IRQ_TEMP_125 BIT(1)
|
||||
|
||||
/* Onkey interrupt masks */
|
||||
#define ONKEY_IRQ_PUSHI BIT(0)
|
||||
#define ONKEY_IRQ_1SI BIT(1)
|
||||
#define ONKEY_IRQ_2SI BIT(2)
|
||||
#define ONKEY_IRQ_3SI BIT(3)
|
||||
#define ONKEY_IRQ_4SI BIT(4)
|
||||
#define ONKEY_IRQ_8SI BIT(5)
|
||||
|
||||
/* Charger interrupt masks */
|
||||
#define CHARG_IRQ_BAT2SOCI BIT(1)
|
||||
#define CHARG_IRQ_BATI BIT(2)
|
||||
#define CHARG_IRQ_CHGI BIT(3)
|
||||
#define CHARG_IRQ_VBUSI BIT(5)
|
||||
#define CHARG_IRQ_DPMI BIT(6)
|
||||
#define CHARG_IRQ_THMI BIT(7)
|
||||
|
||||
enum pf1550_irq {
|
||||
PF1550_IRQ_CHG,
|
||||
PF1550_IRQ_REGULATOR,
|
||||
PF1550_IRQ_ONKEY,
|
||||
};
|
||||
|
||||
enum pf1550_pmic_irq {
|
||||
PF1550_PMIC_IRQ_SW1_LS,
|
||||
PF1550_PMIC_IRQ_SW2_LS,
|
||||
PF1550_PMIC_IRQ_SW3_LS,
|
||||
PF1550_PMIC_IRQ_SW1_HS,
|
||||
PF1550_PMIC_IRQ_SW2_HS,
|
||||
PF1550_PMIC_IRQ_SW3_HS,
|
||||
PF1550_PMIC_IRQ_LDO1_FAULT,
|
||||
PF1550_PMIC_IRQ_LDO2_FAULT,
|
||||
PF1550_PMIC_IRQ_LDO3_FAULT,
|
||||
PF1550_PMIC_IRQ_TEMP_110,
|
||||
PF1550_PMIC_IRQ_TEMP_125,
|
||||
};
|
||||
|
||||
enum pf1550_onkey_irq {
|
||||
PF1550_ONKEY_IRQ_PUSHI,
|
||||
PF1550_ONKEY_IRQ_1SI,
|
||||
PF1550_ONKEY_IRQ_2SI,
|
||||
PF1550_ONKEY_IRQ_3SI,
|
||||
PF1550_ONKEY_IRQ_4SI,
|
||||
PF1550_ONKEY_IRQ_8SI,
|
||||
};
|
||||
|
||||
enum pf1550_charg_irq {
|
||||
PF1550_CHARG_IRQ_BAT2SOCI,
|
||||
PF1550_CHARG_IRQ_BATI,
|
||||
PF1550_CHARG_IRQ_CHGI,
|
||||
PF1550_CHARG_IRQ_VBUSI,
|
||||
PF1550_CHARG_IRQ_THMI,
|
||||
};
|
||||
|
||||
enum pf1550_regulators {
|
||||
PF1550_SW1,
|
||||
PF1550_SW2,
|
||||
PF1550_SW3,
|
||||
PF1550_VREFDDR,
|
||||
PF1550_LDO1,
|
||||
PF1550_LDO2,
|
||||
PF1550_LDO3,
|
||||
};
|
||||
|
||||
struct pf1550_ddata {
|
||||
struct regmap_irq_chip_data *irq_data_regulator;
|
||||
struct regmap_irq_chip_data *irq_data_charger;
|
||||
struct regmap_irq_chip_data *irq_data_onkey;
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
struct regmap *regmap;
|
||||
struct device *dev;
|
||||
bool dvs1_enable;
|
||||
bool dvs2_enable;
|
||||
int irq;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_MFD_PF1550_H */
|
||||
|
|
@ -658,6 +658,9 @@ struct regulator_dev {
|
|||
spinlock_t err_lock;
|
||||
|
||||
int pw_requested_mW;
|
||||
|
||||
/* regulator notification forwarding */
|
||||
struct notifier_block supply_fwd_nb;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,330 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2024 MediaTek Inc.
|
||||
* Copyright (c) 2025 Collabora Ltd
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
|
||||
#ifndef __LINUX_REGULATOR_MT6363_H
|
||||
#define __LINUX_REGULATOR_MT6363_H
|
||||
|
||||
/* Register */
|
||||
#define MT6363_TOP_TRAP 0x6
|
||||
#define MT6363_TOP_TMA_KEY_L 0x36e
|
||||
#define MT6363_RG_BUCK0_EN_ADDR 0x210
|
||||
#define MT6363_RG_BUCK_VS2_EN_BIT 0
|
||||
#define MT6363_RG_BUCK_VBUCK1_EN_BIT 1
|
||||
#define MT6363_RG_BUCK_VBUCK2_EN_BIT 2
|
||||
#define MT6363_RG_BUCK_VBUCK3_EN_BIT 3
|
||||
#define MT6363_RG_BUCK_VBUCK4_EN_BIT 4
|
||||
#define MT6363_RG_BUCK_VBUCK5_EN_BIT 5
|
||||
#define MT6363_RG_BUCK_VBUCK6_EN_BIT 6
|
||||
#define MT6363_RG_BUCK_VBUCK7_EN_BIT 7
|
||||
#define MT6363_RG_BUCK1_EN_ADDR 0x213
|
||||
#define MT6363_RG_BUCK_VS1_EN_BIT 0
|
||||
#define MT6363_RG_BUCK_VS3_EN_BIT 1
|
||||
#define MT6363_RG_LDO_VSRAM_DIGRF_EN_BIT 4
|
||||
#define MT6363_RG_LDO_VSRAM_MDFE_EN_BIT 5
|
||||
#define MT6363_RG_LDO_VSRAM_MODEM_EN_BIT 6
|
||||
#define MT6363_RG_BUCK0_LP_ADDR 0x216
|
||||
#define MT6363_RG_BUCK_VS2_LP_BIT 0
|
||||
#define MT6363_RG_BUCK_VBUCK1_LP_BIT 1
|
||||
#define MT6363_RG_BUCK_VBUCK2_LP_BIT 2
|
||||
#define MT6363_RG_BUCK_VBUCK3_LP_BIT 3
|
||||
#define MT6363_RG_BUCK_VBUCK4_LP_BIT 4
|
||||
#define MT6363_RG_BUCK_VBUCK5_LP_BIT 5
|
||||
#define MT6363_RG_BUCK_VBUCK6_LP_BIT 6
|
||||
#define MT6363_RG_BUCK_VBUCK7_LP_BIT 7
|
||||
#define MT6363_RG_BUCK1_LP_ADDR 0x219
|
||||
#define MT6363_RG_BUCK_VS1_LP_BIT 0
|
||||
#define MT6363_RG_BUCK_VS3_LP_BIT 1
|
||||
#define MT6363_RG_LDO_VSRAM_DIGRF_LP_BIT 4
|
||||
#define MT6363_RG_LDO_VSRAM_MDFE_LP_BIT 5
|
||||
#define MT6363_RG_LDO_VSRAM_MODEM_LP_BIT 6
|
||||
#define MT6363_RG_BUCK_VS2_VOSEL_ADDR 0x21c
|
||||
#define MT6363_RG_BUCK_VS2_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VBUCK1_VOSEL_ADDR 0x21d
|
||||
#define MT6363_RG_BUCK_VBUCK1_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VBUCK2_VOSEL_ADDR 0x21e
|
||||
#define MT6363_RG_BUCK_VBUCK2_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VBUCK3_VOSEL_ADDR 0x21f
|
||||
#define MT6363_RG_BUCK_VBUCK3_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VBUCK4_VOSEL_ADDR 0x220
|
||||
#define MT6363_RG_BUCK_VBUCK4_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VBUCK5_VOSEL_ADDR 0x221
|
||||
#define MT6363_RG_BUCK_VBUCK5_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VBUCK6_VOSEL_ADDR 0x222
|
||||
#define MT6363_RG_BUCK_VBUCK6_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VBUCK7_VOSEL_ADDR 0x223
|
||||
#define MT6363_RG_BUCK_VBUCK7_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VS1_VOSEL_ADDR 0x224
|
||||
#define MT6363_RG_BUCK_VS1_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_BUCK_VS3_VOSEL_ADDR 0x225
|
||||
#define MT6363_RG_BUCK_VS3_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_RG_LDO_VSRAM_DIGRF_VOSEL_ADDR 0x228
|
||||
#define MT6363_RG_LDO_VSRAM_DIGRF_VOSEL_MASK GENMASK(6, 0)
|
||||
#define MT6363_RG_LDO_VSRAM_MDFE_VOSEL_ADDR 0x229
|
||||
#define MT6363_RG_LDO_VSRAM_MDFE_VOSEL_MASK GENMASK(6, 0)
|
||||
#define MT6363_RG_LDO_VSRAM_MODEM_VOSEL_ADDR 0x22a
|
||||
#define MT6363_RG_LDO_VSRAM_MODEM_VOSEL_MASK GENMASK(6, 0)
|
||||
#define MT6363_BUCK_TOP_KEY_PROT_LO 0x13fa
|
||||
#define MT6363_BUCK_VS2_WDTDBG_VOSEL_ADDR 0x13fc
|
||||
#define MT6363_BUCK_VBUCK1_WDTDBG_VOSEL_ADDR 0x13fd
|
||||
#define MT6363_BUCK_VBUCK2_WDTDBG_VOSEL_ADDR 0x13fe
|
||||
#define MT6363_BUCK_VBUCK3_WDTDBG_VOSEL_ADDR 0x13ff
|
||||
#define MT6363_BUCK_VBUCK4_WDTDBG_VOSEL_ADDR 0x1400
|
||||
#define MT6363_BUCK_VBUCK5_WDTDBG_VOSEL_ADDR 0x1401
|
||||
#define MT6363_BUCK_VBUCK6_WDTDBG_VOSEL_ADDR 0x1402
|
||||
#define MT6363_BUCK_VBUCK7_WDTDBG_VOSEL_ADDR 0x1403
|
||||
#define MT6363_BUCK_VS1_WDTDBG_VOSEL_ADDR 0x1404
|
||||
#define MT6363_BUCK_VS3_WDTDBG_VOSEL_ADDR 0x1405
|
||||
#define MT6363_RG_BUCK_EFUSE_RSV1 0x1417
|
||||
#define MT6363_RG_BUCK_EFUSE_RSV1_MASK GENMASK(7, 4)
|
||||
#define MT6363_BUCK_VS2_OP_EN_0 0x145d
|
||||
#define MT6363_BUCK_VS2_HW_LP_MODE 0x1468
|
||||
#define MT6363_BUCK_VBUCK1_OP_EN_0 0x14dd
|
||||
#define MT6363_BUCK_VBUCK1_HW_LP_MODE 0x14e8
|
||||
#define MT6363_RG_BUCK_VBUCK1_SSHUB_EN_ADDR 0x14ea
|
||||
#define MT6363_RG_BUCK_VBUCK1_SSHUB_VOSEL_ADDR 0x14eb
|
||||
#define MT6363_RG_BUCK_VBUCK1_SSHUB_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_BUCK_VBUCK2_OP_EN_0 0x155d
|
||||
#define MT6363_BUCK_VBUCK2_HW_LP_MODE 0x1568
|
||||
#define MT6363_RG_BUCK_VBUCK2_SSHUB_EN_ADDR 0x156a
|
||||
#define MT6363_RG_BUCK_VBUCK2_SSHUB_VOSEL_ADDR 0x156b
|
||||
#define MT6363_RG_BUCK_VBUCK2_SSHUB_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_BUCK_VBUCK3_OP_EN_0 0x15dd
|
||||
#define MT6363_BUCK_VBUCK3_HW_LP_MODE 0x15e8
|
||||
#define MT6363_BUCK_VBUCK4_OP_EN_0 0x165d
|
||||
#define MT6363_BUCK_VBUCK4_HW_LP_MODE 0x1668
|
||||
#define MT6363_RG_BUCK_VBUCK4_SSHUB_EN_ADDR 0x166a
|
||||
#define MT6363_RG_BUCK_VBUCK4_SSHUB_VOSEL_ADDR 0x166b
|
||||
#define MT6363_RG_BUCK_VBUCK4_SSHUB_VOSEL_MASK GENMASK(7, 0)
|
||||
#define MT6363_BUCK_VBUCK5_OP_EN_0 0x16dd
|
||||
#define MT6363_BUCK_VBUCK5_HW_LP_MODE 0x16e8
|
||||
#define MT6363_BUCK_VBUCK6_OP_EN_0 0x175d
|
||||
#define MT6363_BUCK_VBUCK6_HW_LP_MODE 0x1768
|
||||
#define MT6363_BUCK_VBUCK7_OP_EN_0 0x17dd
|
||||
#define MT6363_BUCK_VBUCK7_HW_LP_MODE 0x17e8
|
||||
#define MT6363_BUCK_VS1_OP_EN_0 0x185d
|
||||
#define MT6363_BUCK_VS1_HW_LP_MODE 0x1868
|
||||
#define MT6363_BUCK_VS3_OP_EN_0 0x18dd
|
||||
#define MT6363_BUCK_VS3_HW_LP_MODE 0x18e8
|
||||
#define MT6363_RG_VS1_FCCM_ADDR 0x1964
|
||||
#define MT6363_RG_VS1_FCCM_BIT 0
|
||||
#define MT6363_RG_VS3_FCCM_ADDR 0x1973
|
||||
#define MT6363_RG_VS3_FCCM_BIT 0
|
||||
#define MT6363_RG_BUCK0_FCCM_ADDR 0x1a02
|
||||
#define MT6363_RG_VBUCK1_FCCM_BIT 0
|
||||
#define MT6363_RG_VBUCK2_FCCM_BIT 1
|
||||
#define MT6363_RG_VBUCK3_FCCM_BIT 2
|
||||
#define MT6363_RG_VS2_FCCM_BIT 3
|
||||
#define MT6363_RG_BUCK0_1_FCCM_ADDR 0x1a82
|
||||
#define MT6363_RG_VBUCK4_FCCM_BIT 0
|
||||
#define MT6363_RG_VBUCK5_FCCM_BIT 1
|
||||
#define MT6363_RG_VBUCK6_FCCM_BIT 2
|
||||
#define MT6363_RG_VBUCK7_FCCM_BIT 3
|
||||
#define MT6363_RG_VCN13_VOSEL_ADDR 0x1b0f
|
||||
#define MT6363_RG_VCN13_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VEMC_VOSEL_ADDR 0x1b10
|
||||
#define MT6363_RG_VEMC_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VEMC_VOSEL_1_MASK GENMASK(7, 4)
|
||||
#define MT6363_RG_LDO_VSRAM_CPUB_VOSEL_ADDR 0x1b14
|
||||
#define MT6363_RG_LDO_VSRAM_CPUB_VOSEL_MASK GENMASK(6, 0)
|
||||
#define MT6363_RG_LDO_VSRAM_CPUM_VOSEL_ADDR 0x1b15
|
||||
#define MT6363_RG_LDO_VSRAM_CPUM_VOSEL_MASK GENMASK(6, 0)
|
||||
#define MT6363_RG_LDO_VSRAM_CPUL_VOSEL_ADDR 0x1b16
|
||||
#define MT6363_RG_LDO_VSRAM_CPUL_VOSEL_MASK GENMASK(6, 0)
|
||||
#define MT6363_RG_LDO_VSRAM_APU_VOSEL_ADDR 0x1b17
|
||||
#define MT6363_RG_LDO_VSRAM_APU_VOSEL_MASK GENMASK(6, 0)
|
||||
#define MT6363_RG_VEMC_VOCAL_ADDR 0x1b1b
|
||||
#define MT6363_RG_VEMC_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_LDO_VCN15_ADDR 0x1b57
|
||||
#define MT6363_RG_LDO_VCN15_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VCN15_LP_BIT 1
|
||||
#define MT6363_LDO_VCN15_HW_LP_MODE 0x1b5b
|
||||
#define MT6363_LDO_VCN15_OP_EN0 0x1b5c
|
||||
#define MT6363_RG_LDO_VRF09_ADDR 0x1b65
|
||||
#define MT6363_RG_LDO_VRF09_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VRF09_LP_BIT 1
|
||||
#define MT6363_LDO_VRF09_HW_LP_MODE 0x1b69
|
||||
#define MT6363_LDO_VRF09_OP_EN0 0x1b6a
|
||||
#define MT6363_RG_LDO_VRF12_ADDR 0x1b73
|
||||
#define MT6363_RG_LDO_VRF12_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VRF12_LP_BIT 1
|
||||
#define MT6363_LDO_VRF12_HW_LP_MODE 0x1b77
|
||||
#define MT6363_LDO_VRF12_OP_EN0 0x1b78
|
||||
#define MT6363_RG_LDO_VRF13_ADDR 0x1b81
|
||||
#define MT6363_RG_LDO_VRF13_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VRF13_LP_BIT 1
|
||||
#define MT6363_LDO_VRF13_HW_LP_MODE 0x1b85
|
||||
#define MT6363_LDO_VRF13_OP_EN0 0x1b86
|
||||
#define MT6363_RG_LDO_VRF18_ADDR 0x1b8f
|
||||
#define MT6363_RG_LDO_VRF18_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VRF18_LP_BIT 1
|
||||
#define MT6363_LDO_VRF18_HW_LP_MODE 0x1b93
|
||||
#define MT6363_LDO_VRF18_OP_EN0 0x1b94
|
||||
#define MT6363_RG_LDO_VRFIO18_ADDR 0x1b9d
|
||||
#define MT6363_RG_LDO_VRFIO18_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VRFIO18_LP_BIT 1
|
||||
#define MT6363_LDO_VRFIO18_HW_LP_MODE 0x1ba1
|
||||
#define MT6363_LDO_VRFIO18_OP_EN0 0x1ba2
|
||||
#define MT6363_RG_LDO_VTREF18_ADDR 0x1bd7
|
||||
#define MT6363_RG_LDO_VTREF18_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VTREF18_LP_BIT 1
|
||||
#define MT6363_LDO_VTREF18_HW_LP_MODE 0x1bdb
|
||||
#define MT6363_LDO_VTREF18_OP_EN0 0x1bdc
|
||||
#define MT6363_RG_LDO_VAUX18_ADDR 0x1be5
|
||||
#define MT6363_RG_LDO_VAUX18_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VAUX18_LP_BIT 1
|
||||
#define MT6363_LDO_VAUX18_HW_LP_MODE 0x1be9
|
||||
#define MT6363_LDO_VAUX18_OP_EN0 0x1bea
|
||||
#define MT6363_RG_LDO_VEMC_ADDR 0x1bf3
|
||||
#define MT6363_RG_LDO_VEMC_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VEMC_LP_BIT 1
|
||||
#define MT6363_LDO_VEMC_HW_LP_MODE 0x1bf7
|
||||
#define MT6363_LDO_VEMC_OP_EN0 0x1bf8
|
||||
#define MT6363_RG_LDO_VUFS12_ADDR 0x1c01
|
||||
#define MT6363_RG_LDO_VUFS12_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VUFS12_LP_BIT 1
|
||||
#define MT6363_LDO_VUFS12_HW_LP_MODE 0x1c05
|
||||
#define MT6363_LDO_VUFS12_OP_EN0 0x1c06
|
||||
#define MT6363_RG_LDO_VUFS18_ADDR 0x1c0f
|
||||
#define MT6363_RG_LDO_VUFS18_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VUFS18_LP_BIT 1
|
||||
#define MT6363_LDO_VUFS18_HW_LP_MODE 0x1c13
|
||||
#define MT6363_LDO_VUFS18_OP_EN0 0x1c14
|
||||
#define MT6363_RG_LDO_VIO18_ADDR 0x1c1d
|
||||
#define MT6363_RG_LDO_VIO18_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VIO18_LP_BIT 1
|
||||
#define MT6363_LDO_VIO18_HW_LP_MODE 0x1c21
|
||||
#define MT6363_LDO_VIO18_OP_EN0 0x1c22
|
||||
#define MT6363_RG_LDO_VIO075_ADDR 0x1c57
|
||||
#define MT6363_RG_LDO_VIO075_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VIO075_LP_BIT 1
|
||||
#define MT6363_LDO_VIO075_HW_LP_MODE 0x1c5b
|
||||
#define MT6363_LDO_VIO075_OP_EN0 0x1c5c
|
||||
#define MT6363_RG_LDO_VA12_1_ADDR 0x1c65
|
||||
#define MT6363_RG_LDO_VA12_1_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VA12_1_LP_BIT 1
|
||||
#define MT6363_LDO_VA12_1_HW_LP_MODE 0x1c69
|
||||
#define MT6363_LDO_VA12_1_OP_EN0 0x1c6a
|
||||
#define MT6363_RG_LDO_VA12_2_ADDR 0x1c73
|
||||
#define MT6363_RG_LDO_VA12_2_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VA12_2_LP_BIT 1
|
||||
#define MT6363_LDO_VA12_2_HW_LP_MODE 0x1c77
|
||||
#define MT6363_LDO_VA12_2_OP_EN0 0x1c78
|
||||
#define MT6363_RG_LDO_VA15_ADDR 0x1c81
|
||||
#define MT6363_RG_LDO_VA15_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VA15_LP_BIT 1
|
||||
#define MT6363_LDO_VA15_HW_LP_MODE 0x1c85
|
||||
#define MT6363_LDO_VA15_OP_EN0 0x1c86
|
||||
#define MT6363_RG_LDO_VM18_ADDR 0x1c8f
|
||||
#define MT6363_RG_LDO_VM18_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VM18_LP_BIT 1
|
||||
#define MT6363_LDO_VM18_HW_LP_MODE 0x1c93
|
||||
#define MT6363_LDO_VM18_OP_EN0 0x1c94
|
||||
#define MT6363_RG_LDO_VCN13_ADDR 0x1cd7
|
||||
#define MT6363_RG_LDO_VCN13_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VCN13_LP_BIT 1
|
||||
#define MT6363_LDO_VCN13_HW_LP_MODE 0x1cdb
|
||||
#define MT6363_LDO_VCN13_OP_EN0 0x1ce4
|
||||
#define MT6363_LDO_VSRAM_DIGRF_HW_LP_MODE 0x1cf1
|
||||
#define MT6363_LDO_VSRAM_DIGRF_OP_EN0 0x1cfa
|
||||
#define MT6363_LDO_VSRAM_MDFE_HW_LP_MODE 0x1d5b
|
||||
#define MT6363_LDO_VSRAM_MDFE_OP_EN0 0x1d64
|
||||
#define MT6363_LDO_VSRAM_MODEM_HW_LP_MODE 0x1d76
|
||||
#define MT6363_LDO_VSRAM_MODEM_OP_EN0 0x1d7f
|
||||
#define MT6363_RG_LDO_VSRAM_CPUB_ADDR 0x1dd7
|
||||
#define MT6363_RG_LDO_VSRAM_CPUB_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VSRAM_CPUB_LP_BIT 1
|
||||
#define MT6363_LDO_VSRAM_CPUB_HW_LP_MODE 0x1ddb
|
||||
#define MT6363_LDO_VSRAM_CPUB_OP_EN0 0x1de4
|
||||
#define MT6363_RG_LDO_VSRAM_CPUM_ADDR 0x1ded
|
||||
#define MT6363_RG_LDO_VSRAM_CPUM_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VSRAM_CPUM_LP_BIT 1
|
||||
#define MT6363_LDO_VSRAM_CPUM_HW_LP_MODE 0x1df1
|
||||
#define MT6363_LDO_VSRAM_CPUM_OP_EN0 0x1dfa
|
||||
#define MT6363_RG_LDO_VSRAM_CPUL_ADDR 0x1e57
|
||||
#define MT6363_RG_LDO_VSRAM_CPUL_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VSRAM_CPUL_LP_BIT 1
|
||||
#define MT6363_LDO_VSRAM_CPUL_HW_LP_MODE 0x1e5b
|
||||
#define MT6363_LDO_VSRAM_CPUL_OP_EN0 0x1e64
|
||||
#define MT6363_RG_LDO_VSRAM_APU_ADDR 0x1e6d
|
||||
#define MT6363_RG_LDO_VSRAM_APU_EN_BIT 0
|
||||
#define MT6363_RG_LDO_VSRAM_APU_LP_BIT 1
|
||||
#define MT6363_LDO_VSRAM_APU_HW_LP_MODE 0x1e71
|
||||
#define MT6363_LDO_VSRAM_APU_OP_EN0 0x1e7a
|
||||
#define MT6363_RG_VTREF18_VOCAL_ADDR 0x1ed8
|
||||
#define MT6363_RG_VTREF18_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VTREF18_VOSEL_ADDR 0x1ed9
|
||||
#define MT6363_RG_VTREF18_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VAUX18_VOCAL_ADDR 0x1edc
|
||||
#define MT6363_RG_VAUX18_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VAUX18_VOSEL_ADDR 0x1edd
|
||||
#define MT6363_RG_VAUX18_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VCN15_VOCAL_ADDR 0x1ee3
|
||||
#define MT6363_RG_VCN15_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VCN15_VOSEL_ADDR 0x1ee4
|
||||
#define MT6363_RG_VCN15_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VUFS18_VOCAL_ADDR 0x1ee7
|
||||
#define MT6363_RG_VUFS18_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VUFS18_VOSEL_ADDR 0x1ee8
|
||||
#define MT6363_RG_VUFS18_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VIO18_VOCAL_ADDR 0x1eeb
|
||||
#define MT6363_RG_VIO18_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VIO18_VOSEL_ADDR 0x1eec
|
||||
#define MT6363_RG_VIO18_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VM18_VOCAL_ADDR 0x1eef
|
||||
#define MT6363_RG_VM18_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VM18_VOSEL_ADDR 0x1ef0
|
||||
#define MT6363_RG_VM18_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VA15_VOCAL_ADDR 0x1ef3
|
||||
#define MT6363_RG_VA15_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VA15_VOSEL_ADDR 0x1ef4
|
||||
#define MT6363_RG_VA15_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRF18_VOCAL_ADDR 0x1ef7
|
||||
#define MT6363_RG_VRF18_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRF18_VOSEL_ADDR 0x1ef8
|
||||
#define MT6363_RG_VRF18_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRFIO18_VOCAL_ADDR 0x1efb
|
||||
#define MT6363_RG_VRFIO18_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRFIO18_VOSEL_ADDR 0x1efc
|
||||
#define MT6363_RG_VRFIO18_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VIO075_VOCFG_ADDR 0x1f01
|
||||
#define MT6363_RG_VIO075_VOCAL_ADDR MT6363_RG_VIO075_VOCFG_ADDR
|
||||
#define MT6363_RG_VIO075_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VIO075_VOSEL_ADDR MT6363_RG_VIO075_VOCFG_ADDR
|
||||
#define MT6363_RG_VIO075_VOSEL_MASK GENMASK(6, 4)
|
||||
#define MT6363_RG_VCN13_VOCAL_ADDR 0x1f58
|
||||
#define MT6363_RG_VCN13_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VUFS12_VOCAL_ADDR 0x1f61
|
||||
#define MT6363_RG_VUFS12_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VUFS12_VOSEL_ADDR 0x1f62
|
||||
#define MT6363_RG_VUFS12_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VA12_1_VOCAL_ADDR 0x1f65
|
||||
#define MT6363_RG_VA12_1_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VA12_1_VOSEL_ADDR 0x1f66
|
||||
#define MT6363_RG_VA12_1_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VA12_2_VOCAL_ADDR 0x1f69
|
||||
#define MT6363_RG_VA12_2_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VA12_2_VOSEL_ADDR 0x1f6a
|
||||
#define MT6363_RG_VA12_2_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRF12_VOCAL_ADDR 0x1f6d
|
||||
#define MT6363_RG_VRF12_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRF12_VOSEL_ADDR 0x1f6e
|
||||
#define MT6363_RG_VRF12_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRF13_VOCAL_ADDR 0x1f71
|
||||
#define MT6363_RG_VRF13_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRF13_VOSEL_ADDR 0x1f72
|
||||
#define MT6363_RG_VRF13_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRF09_VOCAL_ADDR 0x1f78
|
||||
#define MT6363_RG_VRF09_VOCAL_MASK GENMASK(3, 0)
|
||||
#define MT6363_RG_VRF09_VOSEL_ADDR 0x1f79
|
||||
#define MT6363_RG_VRF09_VOSEL_MASK GENMASK(3, 0)
|
||||
#define MT6363_ISINK_EN_CTRL0 0x21db
|
||||
#define MT6363_ISINK_CTRL0_MASK GENMASK(7, 0)
|
||||
#define MT6363_ISINK_EN_CTRL1 0x21dc
|
||||
#define MT6363_ISINK_CTRL1_MASK GENMASK(7, 4)
|
||||
|
||||
#endif /* __LINUX_REGULATOR_MT6363_H */
|
||||
|
|
@ -223,12 +223,44 @@ enum {
|
|||
#define IRQ_THERM_105 0x02
|
||||
#define IRQ_THERM_125 0x01
|
||||
|
||||
/* PCA9450_REG_PWRCTRL bits */
|
||||
#define T_ON_DEB_MASK 0xC0
|
||||
#define T_ON_DEB_120US (0 << 6)
|
||||
#define T_ON_DEB_20MS (1 << 6)
|
||||
#define T_ON_DEB_100MS (2 << 6)
|
||||
#define T_ON_DEB_750MS (3 << 6)
|
||||
#define T_OFF_DEB_MASK 0x20
|
||||
#define T_OFF_DEB_120US (0 << 5)
|
||||
#define T_OFF_DEB_2MS (1 << 5)
|
||||
#define T_ON_STEP_MASK 0x18
|
||||
#define T_ON_STEP_1MS (0 << 3)
|
||||
#define T_ON_STEP_2MS (1 << 3)
|
||||
#define T_ON_STEP_4MS (2 << 3)
|
||||
#define T_ON_STEP_8MS (3 << 3)
|
||||
#define T_OFF_STEP_MASK 0x06
|
||||
#define T_OFF_STEP_2MS (0 << 1)
|
||||
#define T_OFF_STEP_4MS (1 << 1)
|
||||
#define T_OFF_STEP_8MS (2 << 1)
|
||||
#define T_OFF_STEP_16MS (3 << 1)
|
||||
#define T_RESTART_MASK 0x01
|
||||
#define T_RESTART_250MS 0
|
||||
#define T_RESTART_500MS 1
|
||||
|
||||
/* PCA9450_REG_RESET_CTRL bits */
|
||||
#define WDOG_B_CFG_MASK 0xC0
|
||||
#define WDOG_B_CFG_NONE 0x00
|
||||
#define WDOG_B_CFG_WARM 0x40
|
||||
#define WDOG_B_CFG_COLD_LDO12 0x80
|
||||
#define WDOG_B_CFG_COLD 0xC0
|
||||
#define T_PMIC_RST_DEB_MASK 0x07
|
||||
#define T_PMIC_RST_DEB_10MS 0x00
|
||||
#define T_PMIC_RST_DEB_50MS 0x01
|
||||
#define T_PMIC_RST_DEB_100MS 0x02
|
||||
#define T_PMIC_RST_DEB_500MS 0x03
|
||||
#define T_PMIC_RST_DEB_1S 0x04
|
||||
#define T_PMIC_RST_DEB_2S 0x05
|
||||
#define T_PMIC_RST_DEB_4S 0x06
|
||||
#define T_PMIC_RST_DEB_8S 0x07
|
||||
|
||||
/* PCA9450_REG_CONFIG2 bits */
|
||||
#define I2C_LT_MASK 0x03
|
||||
|
|
|
|||
Loading…
Reference in New Issue