Commit d46e0d33 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull regulator updates from Mark Brown:
 "A very quiet releases, some fixes and cleanups but not really that
  many of them. There were a couple of new driver specific pieces:

   - Support for controlling the over/under voltage protection on
     BD718xx devices

   - New drivers for Richtek RTQ2134, and RTQ6752"

* tag 'regulator-v5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (37 commits)
  regulator: vctrl: Avoid lockdep warning in enable/disable ops
  regulator: vctrl: Use locked regulator_get_voltage in probe path
  regulator: Documentation fix for regulator error notification helper
  regulator: Minor regulator documentation fixes.
  regulator: sy7636a: Use the regmap directly
  regulator: sy7636a: Store the epd-pwr-good GPIO locally
  regulator: sy7636a: Use the parent driver data
  regulator: sy7636a: Remove the poll_enable_time
  regulator: sy8827n: Enable REGCACHE_FLAT
  regulator: sy8824x: Enable REGCACHE_FLAT
  regulator: rtq2134: Fix coding style
  regulator: hi6421v600: rename voltage range arrays
  regulator: hi6421v600: use lowercase for ldo
  regulator: fixed: use dev_err_probe for register
  regulator: rtq2134: Add support for Richtek RTQ2134 SubPMIC
  regulator: rtq2134: Add binding document for Richtek RTQ2134 SubPMIC
  regulator: Fix a couple of spelling mistakes in Kconfig
  regulator: rtq6752: fix reg reset behavior
  regulator: da9063: Add support for full-current mode.
  regulator: rt6245: make a const array func_base static, makes object smaller
  ...
parents 4aed6ee5 7aa6d700
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/richtek,rtq2134-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Richtek RTQ2134 SubPMIC Regulator
maintainers:
- ChiYuan Huang <cy_huang@richtek.com>
description: |
The RTQ2134 is a multi-phase, programmable power management IC that
integrates with four high efficient, synchronous step-down converter cores.
Datasheet is available at
https://www.richtek.com/assets/product_file/RTQ2134-QA/DSQ2134-QA-01.pdf
properties:
compatible:
enum:
- richtek,rtq2134
reg:
maxItems: 1
regulators:
type: object
patternProperties:
"^buck[1-3]$":
type: object
$ref: regulator.yaml#
description: |
regulator description for buck[1-3].
properties:
richtek,use-vsel-dvs:
type: boolean
description: |
If specified, buck will listen to 'vsel' pin for dvs config.
Else, use dvs0 voltage by default.
richtek,uv-shutdown:
type: boolean
description: |
If specified, use shutdown as UV action. Else, hiccup by default.
unevaluatedProperties: false
additionalProperties: false
required:
- compatible
- reg
- regulators
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtq2134@18 {
compatible = "richtek,rtq2134";
reg = <0x18>;
regulators {
buck1 {
regulator-name = "rtq2134-buck1";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1850000>;
regulator-always-on;
richtek,use-vsel-dvs;
regulator-state-mem {
regulator-suspend-min-microvolt = <550000>;
regulator-suspend-max-microvolt = <550000>;
};
};
buck2 {
regulator-name = "rtq2134-buck2";
regulator-min-microvolt = <1120000>;
regulator-max-microvolt = <1120000>;
regulator-always-on;
richtek,use-vsel-dvs;
regulator-state-mem {
regulator-suspend-min-microvolt = <1120000>;
regulator-suspend-max-microvolt = <1120000>;
};
};
buck3 {
regulator-name = "rtq2134-buck3";
regulator-min-microvolt = <600000>;
regulator-max-microvolt = <600000>;
regulator-always-on;
richtek,use-vsel-dvs;
regulator-state-mem {
regulator-suspend-min-microvolt = <600000>;
regulator-suspend-max-microvolt = <600000>;
};
};
};
};
};
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/richtek,rtq6752-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Richtek RTQ6752 TFT LCD Voltage Regulator
maintainers:
- ChiYuan Huang <cy_huang@richtek.com>
description: |
The RTQ6752 is an I2C interface pgorammable power management IC. It includes
two synchronous boost converter for PAVDD, and one synchronous NAVDD
buck-boost. The device is suitable for automotive TFT-LCD panel.
properties:
compatible:
enum:
- richtek,rtq6752
reg:
maxItems: 1
enable-gpios:
description: |
A connection of the chip 'enable' gpio line. If not provided, treat it as
external pull up.
maxItems: 1
regulators:
type: object
patternProperties:
"^(p|n)avdd$":
type: object
$ref: regulator.yaml#
description: |
regulator description for pavdd and navdd.
additionalProperties: false
required:
- compatible
- reg
- regulators
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtq6752@6b {
compatible = "richtek,rtq6752";
reg = <0x6b>;
enable-gpios = <&gpio26 2 0>;
regulators {
pavdd {
regulator-name = "rtq6752-pavdd";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <7300000>;
regulator-boot-on;
};
navdd {
regulator-name = "rtq6752-navdd";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <7300000>;
regulator-boot-on;
};
};
};
};
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/socionext,uniphier-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Socionext UniPhier regulator controller
description: |
This regulator controls VBUS and belongs to USB3 glue layer. Before using
the regulator, it is necessary to control the clocks and resets to enable
this layer. These clocks and resets should be described in each property.
maintainers:
- Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
allOf:
- $ref: "regulator.yaml#"
# USB3 Controller
properties:
compatible:
enum:
- socionext,uniphier-pro4-usb3-regulator
- socionext,uniphier-pro5-usb3-regulator
- socionext,uniphier-pxs2-usb3-regulator
- socionext,uniphier-ld20-usb3-regulator
- socionext,uniphier-pxs3-usb3-regulator
reg:
maxItems: 1
clocks:
minItems: 1
maxItems: 2
clock-names:
oneOf:
- items: # for Pro4, Pro5
- const: gio
- const: link
- items: # for others
- const: link
resets:
minItems: 1
maxItems: 2
reset-names:
oneOf:
- items: # for Pro4, Pro5
- const: gio
- const: link
- items:
- const: link
additionalProperties: false
required:
- compatible
- reg
- clocks
- clock-names
- resets
- reset-names
examples:
- |
usb-glue@65b00000 {
compatible = "simple-mfd";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x65b00000 0x400>;
usb_vbus0: regulators@100 {
compatible = "socionext,uniphier-ld20-usb3-regulator";
reg = <0x100 0x10>;
clock-names = "link";
clocks = <&sys_clk 14>;
reset-names = "link";
resets = <&sys_rst 14>;
};
};
Socionext UniPhier Regulator Controller
This describes the devicetree bindings for regulator controller implemented
on Socionext UniPhier SoCs.
USB3 Controller
---------------
This regulator controls VBUS and belongs to USB3 glue layer. Before using
the regulator, it is necessary to control the clocks and resets to enable
this layer. These clocks and resets should be described in each property.
Required properties:
- compatible: Should be
"socionext,uniphier-pro4-usb3-regulator" - for Pro4 SoC
"socionext,uniphier-pro5-usb3-regulator" - for Pro5 SoC
"socionext,uniphier-pxs2-usb3-regulator" - for PXs2 SoC
"socionext,uniphier-ld20-usb3-regulator" - for LD20 SoC
"socionext,uniphier-pxs3-usb3-regulator" - for PXs3 SoC
- reg: Specifies offset and length of the register set for the device.
- clocks: A list of phandles to the clock gate for USB3 glue layer.
According to the clock-names, appropriate clocks are required.
- clock-names: Should contain
"gio", "link" - for Pro4 and Pro5 SoCs
"link" - for others
- resets: A list of phandles to the reset control for USB3 glue layer.
According to the reset-names, appropriate resets are required.
- reset-names: Should contain
"gio", "link" - for Pro4 and Pro5 SoCs
"link" - for others
See Documentation/devicetree/bindings/regulator/regulator.txt
for more details about the regulator properties.
Example:
usb-glue@65b00000 {
compatible = "socionext,uniphier-ld20-dwc3-glue",
"simple-mfd";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x65b00000 0x400>;
usb_vbus0: regulators@100 {
compatible = "socionext,uniphier-ld20-usb3-regulator";
reg = <0x100 0x10>;
clock-names = "link";
clocks = <&sys_clk 14>;
reset-names = "link";
resets = <&sys_rst 14>;
};
phy {
...
phy-supply = <&usb_vbus0>;
};
...
};
......@@ -1044,7 +1044,7 @@ config REGULATOR_RT6160
help
This adds support for voltage regulator in Richtek RT6160.
This device automatically change voltage output mode from
Buck or Boost. The mode transistion depend on the input source voltage.
Buck or Boost. The mode transition depend on the input source voltage.
The wide output range is from 2025mV to 5200mV and can be used on most
common application scenario.
......@@ -1053,10 +1053,21 @@ config REGULATOR_RT6245
depends on I2C
select REGMAP_I2C
help
This adds supprot for Richtek RT6245 voltage regulator.
This adds support for Richtek RT6245 voltage regulator.
It can support up to 14A output current and adjustable output voltage
from 0.4375V to 1.3875V, per step 12.5mV.
config REGULATOR_RTQ2134
tristate "Richtek RTQ2134 SubPMIC Regulator"
depends on I2C
select REGMAP_I2C
help
This driver adds support for RTQ2134 SubPMIC regulators.
The RTQ2134 is a multi-phase, programmable power management IC that
integrate with four high efficient, synchronous step-down converter
cores. It features wide output voltage range and the capability to
configure the corresponding power stages.
config REGULATOR_RTMV20
tristate "Richtek RTMV20 Laser Diode Regulator"
depends on I2C
......@@ -1066,6 +1077,15 @@ config REGULATOR_RTMV20
the Richtek RTMV20. It can support the load current up to 6A and
integrate strobe/vsync/fsin signal to synchronize the IR camera.
config REGULATOR_RTQ6752
tristate "Richtek RTQ6752 TFT LCD voltage regulator"
depends on I2C
select REGMAP_I2C
help
This driver adds support for Richtek RTQ6752. RTQ6752 includes two
synchronous boost converters for PAVDD, and one synchronous NAVDD
buck-boost. This device is suitable for automotive TFT-LCD panel.
config REGULATOR_S2MPA01
tristate "Samsung S2MPA01 voltage regulator"
depends on MFD_SEC_CORE || COMPILE_TEST
......
......@@ -128,6 +128,8 @@ obj-$(CONFIG_REGULATOR_RT5033) += rt5033-regulator.o
obj-$(CONFIG_REGULATOR_RT6160) += rt6160-regulator.o
obj-$(CONFIG_REGULATOR_RT6245) += rt6245-regulator.o
obj-$(CONFIG_REGULATOR_RTMV20) += rtmv20-regulator.o
obj-$(CONFIG_REGULATOR_RTQ2134) += rtq2134-regulator.o
obj-$(CONFIG_REGULATOR_RTQ6752) += rtq6752-regulator.o
obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
......
......@@ -55,7 +55,8 @@
#define BD718XX_HWOPNAME(swopname) swopname##_hwcontrol
#define BD718XX_OPS(name, _list_voltage, _map_voltage, _set_voltage_sel, \
_get_voltage_sel, _set_voltage_time_sel, _set_ramp_delay) \
_get_voltage_sel, _set_voltage_time_sel, _set_ramp_delay, \
_set_uvp, _set_ovp) \
static const struct regulator_ops name = { \
.enable = regulator_enable_regmap, \
.disable = regulator_disable_regmap, \
......@@ -66,6 +67,8 @@ static const struct regulator_ops name = { \
.get_voltage_sel = (_get_voltage_sel), \
.set_voltage_time_sel = (_set_voltage_time_sel), \
.set_ramp_delay = (_set_ramp_delay), \
.set_under_voltage_protection = (_set_uvp), \
.set_over_voltage_protection = (_set_ovp), \
}; \
\
static const struct regulator_ops BD718XX_HWOPNAME(name) = { \
......@@ -76,6 +79,8 @@ static const struct regulator_ops BD718XX_HWOPNAME(name) = { \
.get_voltage_sel = (_get_voltage_sel), \
.set_voltage_time_sel = (_set_voltage_time_sel), \
.set_ramp_delay = (_set_ramp_delay), \
.set_under_voltage_protection = (_set_uvp), \
.set_over_voltage_protection = (_set_ovp), \
} \
/*
......@@ -154,17 +159,9 @@ static void voltage_change_done(struct regulator_dev *rdev, unsigned int sel,
* exceed it due to the scheduling.
*/
msleep(1);
/*
* Note for next hacker. The PWRGOOD should not be masked on
* BD71847 so we will just unconditionally enable detection
* when voltage is set.
* If someone want's to disable PWRGOOD he must implement
* caching and restoring the old value here. I am not
* aware of such use-cases so for the sake of the simplicity
* we just always enable PWRGOOD here.
*/
ret = regmap_update_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
*mask, 0);
ret = regmap_clear_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
*mask);
if (ret)
dev_err(&rdev->dev,
"Failed to re-enable voltage monitoring (%d)\n",
......@@ -208,12 +205,27 @@ static int voltage_change_prepare(struct regulator_dev *rdev, unsigned int sel,
* time configurable.
*/
if (new > now) {
int tmp;
int prot_bit;
int ldo_offset = rdev->desc->id - BD718XX_LDO1;
*mask = BD718XX_LDO1_VRMON80 << ldo_offset;
ret = regmap_update_bits(rdev->regmap,
BD718XX_REG_MVRFLTMASK2,
*mask, *mask);
prot_bit = BD718XX_LDO1_VRMON80 << ldo_offset;
ret = regmap_read(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
&tmp);
if (ret) {
dev_err(&rdev->dev,
"Failed to read voltage monitoring state\n");
return ret;
}
if (!(tmp & prot_bit)) {
/* We disable protection if it was enabled... */
ret = regmap_set_bits(rdev->regmap,
BD718XX_REG_MVRFLTMASK2,
prot_bit);
/* ...and we also want to re-enable it */
*mask = prot_bit;
}
if (ret) {
dev_err(&rdev->dev,
"Failed to stop voltage monitoring\n");
......@@ -266,99 +278,6 @@ static int bd71837_set_voltage_sel_pickable_restricted(
return regulator_set_voltage_sel_pickable_regmap(rdev, sel);
}
/*
* OPS common for BD71847 and BD71850
*/
BD718XX_OPS(bd718xx_pickable_range_ldo_ops,
regulator_list_voltage_pickable_linear_range, NULL,
bd718xx_set_voltage_sel_pickable_restricted,
regulator_get_voltage_sel_pickable_regmap, NULL, NULL);
/* BD71847 and BD71850 LDO 5 is by default OFF at RUN state */
static const struct regulator_ops bd718xx_ldo5_ops_hwstate = {
.is_enabled = never_enabled_by_hwstate,
.list_voltage = regulator_list_voltage_pickable_linear_range,
.set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted,
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
};
BD718XX_OPS(bd718xx_pickable_range_buck_ops,
regulator_list_voltage_pickable_linear_range, NULL,
regulator_set_voltage_sel_pickable_regmap,
regulator_get_voltage_sel_pickable_regmap,
regulator_set_voltage_time_sel, NULL);
BD718XX_OPS(bd718xx_ldo_regulator_ops, regulator_list_voltage_linear_range,
NULL, bd718xx_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, NULL, NULL);
BD718XX_OPS(bd718xx_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
NULL, bd718xx_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, NULL, NULL);
BD718XX_OPS(bd718xx_buck_regulator_ops, regulator_list_voltage_linear_range,
NULL, regulator_set_voltage_sel_regmap,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
NULL);
BD718XX_OPS(bd718xx_buck_regulator_nolinear_ops, regulator_list_voltage_table,
regulator_map_voltage_ascend, regulator_set_voltage_sel_regmap,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
NULL);
/*
* OPS for BD71837
*/
BD718XX_OPS(bd71837_pickable_range_ldo_ops,
regulator_list_voltage_pickable_linear_range, NULL,
bd71837_set_voltage_sel_pickable_restricted,
regulator_get_voltage_sel_pickable_regmap, NULL, NULL);
BD718XX_OPS(bd71837_pickable_range_buck_ops,
regulator_list_voltage_pickable_linear_range, NULL,
bd71837_set_voltage_sel_pickable_restricted,
regulator_get_voltage_sel_pickable_regmap,
regulator_set_voltage_time_sel, NULL);
BD718XX_OPS(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range,
NULL, bd71837_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, NULL, NULL);
BD718XX_OPS(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
NULL, bd71837_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, NULL, NULL);
BD718XX_OPS(bd71837_buck_regulator_ops, regulator_list_voltage_linear_range,
NULL, bd71837_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
NULL);
BD718XX_OPS(bd71837_buck_regulator_nolinear_ops, regulator_list_voltage_table,
regulator_map_voltage_ascend, bd71837_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
NULL);
/*
* BD71837 bucks 3 and 4 support defining their enable/disable state also
* when buck enable state is under HW state machine control. In that case the
* bit [2] in CTRL register is used to indicate if regulator should be ON.
*/
static const struct regulator_ops bd71837_buck34_ops_hwctrl = {
.is_enabled = bd71837_get_buck34_enable_hwctrl,
.list_voltage = regulator_list_voltage_linear_range,
.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_ramp_delay = regulator_set_ramp_delay_regmap,
};
/*
* OPS for all of the ICs - BD718(37/47/50)
*/
BD718XX_OPS(bd718xx_dvs_buck_regulator_ops, regulator_list_voltage_linear_range,
NULL, regulator_set_voltage_sel_regmap,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
/* bd718xx_buck1234_set_ramp_delay */ regulator_set_ramp_delay_regmap);
/*
* BD71837 BUCK1/2/3/4
* BD71847 BUCK1/2
......@@ -536,6 +455,238 @@ struct bd718xx_regulator_data {
int additional_init_amnt;
};
static int bd718x7_xvp_sanity_check(struct regulator_dev *rdev, int lim_uV,
int severity)
{
/*
* BD71837/47/50 ... (ICs supported by this driver) do not provide
* warnings, only protection
*/
if (severity != REGULATOR_SEVERITY_PROT) {
dev_err(&rdev->dev,
"Unsupported Under Voltage protection level\n");
return -EINVAL;
}
/*
* And protection limit is not changeable. It can only be enabled
* or disabled
*/
if (lim_uV)
return -EINVAL;
return 0;
}
static int bd718x7_set_ldo_uvp(struct regulator_dev *rdev, int lim_uV,
int severity, bool enable)
{
int ldo_offset = rdev->desc->id - BD718XX_LDO1;
int prot_bit, ret;
ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity);
if (ret)
return ret;
prot_bit = BD718XX_LDO1_VRMON80 << ldo_offset;
if (enable)
return regmap_clear_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
prot_bit);
return regmap_set_bits(rdev->regmap, BD718XX_REG_MVRFLTMASK2,
prot_bit);
}
static int bd718x7_get_buck_prot_reg(int id, int *reg)
{
if (id > BD718XX_BUCK8) {
WARN_ON(id > BD718XX_BUCK8);
return -EINVAL;
}
if (id > BD718XX_BUCK4)
*reg = BD718XX_REG_MVRFLTMASK0;
else
*reg = BD718XX_REG_MVRFLTMASK1;
return 0;
}
static int bd718x7_get_buck_ovp_info(int id, int *reg, int *bit)
{
int ret;
ret = bd718x7_get_buck_prot_reg(id, reg);
if (ret)
return ret;
*bit = BIT((id % 4) * 2 + 1);
return 0;
}
static int bd718x7_get_buck_uvp_info(int id, int *reg, int *bit)
{
int ret;
ret = bd718x7_get_buck_prot_reg(id, reg);
if (ret)
return ret;
*bit = BIT((id % 4) * 2);
return 0;
}
static int bd718x7_set_buck_uvp(struct regulator_dev *rdev, int lim_uV,
int severity, bool enable)
{
int bit, reg, ret;
ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity);
if (ret)
return ret;
ret = bd718x7_get_buck_uvp_info(rdev->desc->id, &reg, &bit);
if (ret)
return ret;
if (enable)
return regmap_clear_bits(rdev->regmap, reg, bit);
return regmap_set_bits(rdev->regmap, reg, bit);
}
static int bd718x7_set_buck_ovp(struct regulator_dev *rdev, int lim_uV,
int severity,
bool enable)
{
int bit, reg, ret;
ret = bd718x7_xvp_sanity_check(rdev, lim_uV, severity);
if (ret)
return ret;
ret = bd718x7_get_buck_ovp_info(rdev->desc->id, &reg, &bit);
if (ret)
return ret;
if (enable)
return regmap_clear_bits(rdev->regmap, reg, bit);
return regmap_set_bits(rdev->regmap, reg, bit);
}
/*
* OPS common for BD71847 and BD71850
*/
BD718XX_OPS(bd718xx_pickable_range_ldo_ops,
regulator_list_voltage_pickable_linear_range, NULL,
bd718xx_set_voltage_sel_pickable_restricted,
regulator_get_voltage_sel_pickable_regmap, NULL, NULL,
bd718x7_set_ldo_uvp, NULL);
/* BD71847 and BD71850 LDO 5 is by default OFF at RUN state */
static const struct regulator_ops bd718xx_ldo5_ops_hwstate = {
.is_enabled = never_enabled_by_hwstate,
.list_voltage = regulator_list_voltage_pickable_linear_range,
.set_voltage_sel = bd718xx_set_voltage_sel_pickable_restricted,
.get_voltage_sel = regulator_get_voltage_sel_pickable_regmap,
.set_under_voltage_protection = bd718x7_set_ldo_uvp,
};
BD718XX_OPS(bd718xx_pickable_range_buck_ops,
regulator_list_voltage_pickable_linear_range, NULL,
regulator_set_voltage_sel_pickable_regmap,
regulator_get_voltage_sel_pickable_regmap,
regulator_set_voltage_time_sel, NULL, bd718x7_set_buck_uvp,
bd718x7_set_buck_ovp);
BD718XX_OPS(bd718xx_ldo_regulator_ops, regulator_list_voltage_linear_range,
NULL, bd718xx_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp,
NULL);
BD718XX_OPS(bd718xx_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
NULL, bd718xx_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp,
NULL);
BD718XX_OPS(bd718xx_buck_regulator_ops, regulator_list_voltage_linear_range,
NULL, regulator_set_voltage_sel_regmap,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp);
BD718XX_OPS(bd718xx_buck_regulator_nolinear_ops, regulator_list_voltage_table,
regulator_map_voltage_ascend, regulator_set_voltage_sel_regmap,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp);
/*
* OPS for BD71837
*/
BD718XX_OPS(bd71837_pickable_range_ldo_ops,
regulator_list_voltage_pickable_linear_range, NULL,
bd71837_set_voltage_sel_pickable_restricted,
regulator_get_voltage_sel_pickable_regmap, NULL, NULL,
bd718x7_set_ldo_uvp, NULL);
BD718XX_OPS(bd71837_pickable_range_buck_ops,
regulator_list_voltage_pickable_linear_range, NULL,
bd71837_set_voltage_sel_pickable_restricted,
regulator_get_voltage_sel_pickable_regmap,
regulator_set_voltage_time_sel, NULL, bd718x7_set_buck_uvp,
bd718x7_set_buck_ovp);
BD718XX_OPS(bd71837_ldo_regulator_ops, regulator_list_voltage_linear_range,
NULL, bd71837_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp,
NULL);
BD718XX_OPS(bd71837_ldo_regulator_nolinear_ops, regulator_list_voltage_table,
NULL, bd71837_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, NULL, NULL, bd718x7_set_ldo_uvp,
NULL);
BD718XX_OPS(bd71837_buck_regulator_ops, regulator_list_voltage_linear_range,
NULL, bd71837_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp);
BD718XX_OPS(bd71837_buck_regulator_nolinear_ops, regulator_list_voltage_table,
regulator_map_voltage_ascend, bd71837_set_voltage_sel_restricted,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
NULL, bd718x7_set_buck_uvp, bd718x7_set_buck_ovp);
/*
* BD71837 bucks 3 and 4 support defining their enable/disable state also
* when buck enable state is under HW state machine control. In that case the
* bit [2] in CTRL register is used to indicate if regulator should be ON.
*/
static const struct regulator_ops bd71837_buck34_ops_hwctrl = {
.is_enabled = bd71837_get_buck34_enable_hwctrl,
.list_voltage = regulator_list_voltage_linear_range,
.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_ramp_delay = regulator_set_ramp_delay_regmap,
.set_under_voltage_protection = bd718x7_set_buck_uvp,
.set_over_voltage_protection = bd718x7_set_buck_ovp,
};
/*
* OPS for all of the ICs - BD718(37/47/50)
*/
BD718XX_OPS(bd718xx_dvs_buck_regulator_ops, regulator_list_voltage_linear_range,
NULL, regulator_set_voltage_sel_regmap,
regulator_get_voltage_sel_regmap, regulator_set_voltage_time_sel,
regulator_set_ramp_delay_regmap, bd718x7_set_buck_uvp,
bd718x7_set_buck_ovp);
/*
* There is a HW quirk in BD71837. The shutdown sequence timings for
* bucks/LDOs which are controlled via register interface are changed.
......
......@@ -412,6 +412,134 @@ static int da9063_ldo_set_suspend_mode(struct regulator_dev *rdev,
return regmap_field_write(regl->suspend_sleep, val);
}
static unsigned int da9063_get_overdrive_mask(const struct regulator_desc *desc)
{
switch (desc->id) {
case DA9063_ID_BCORES_MERGED:
case DA9063_ID_BCORE1:
return DA9063_BCORE1_OD;
case DA9063_ID_BCORE2:
return DA9063_BCORE2_OD;
case DA9063_ID_BPRO:
return DA9063_BPRO_OD;
default:
return 0;
}
}
static int da9063_buck_set_limit_set_overdrive(struct regulator_dev *rdev,
int min_uA, int max_uA,
unsigned int overdrive_mask)
{
/*
* When enabling overdrive, do it before changing the current limit to
* ensure sufficient supply throughout the switch.
*/
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
int ret;
unsigned int orig_overdrive;
ret = regmap_read(regl->hw->regmap, DA9063_REG_CONFIG_H,
&orig_overdrive);
if (ret < 0)
return ret;
orig_overdrive &= overdrive_mask;
if (orig_overdrive == 0) {
ret = regmap_set_bits(regl->hw->regmap, DA9063_REG_CONFIG_H,
overdrive_mask);
if (ret < 0)
return ret;
}
ret = regulator_set_current_limit_regmap(rdev, min_uA / 2, max_uA / 2);
if (ret < 0 && orig_overdrive == 0)
/*
* regulator_set_current_limit_regmap may have rejected the
* change because of unusable min_uA and/or max_uA inputs.
* Attempt to restore original overdrive state, ignore failure-
* on-failure.
*/
regmap_clear_bits(regl->hw->regmap, DA9063_REG_CONFIG_H,
overdrive_mask);
return ret;
}
static int da9063_buck_set_limit_clear_overdrive(struct regulator_dev *rdev,
int min_uA, int max_uA,
unsigned int overdrive_mask)
{
/*
* When disabling overdrive, do it after changing the current limit to
* ensure sufficient supply throughout the switch.
*/
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
int ret, orig_limit;
ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &orig_limit);
if (ret < 0)
return ret;
ret = regulator_set_current_limit_regmap(rdev, min_uA, max_uA);
if (ret < 0)
return ret;
ret = regmap_clear_bits(regl->hw->regmap, DA9063_REG_CONFIG_H,
overdrive_mask);
if (ret < 0)
/*
* Attempt to restore original current limit, ignore failure-
* on-failure.
*/
regmap_write(rdev->regmap, rdev->desc->csel_reg, orig_limit);
return ret;
}
static int da9063_buck_set_current_limit(struct regulator_dev *rdev,
int min_uA, int max_uA)
{
unsigned int overdrive_mask, n_currents;
overdrive_mask = da9063_get_overdrive_mask(rdev->desc);
if (overdrive_mask) {
n_currents = rdev->desc->n_current_limits;
if (n_currents == 0)
return -EINVAL;
if (max_uA > rdev->desc->curr_table[n_currents - 1])
return da9063_buck_set_limit_set_overdrive(rdev, min_uA,
max_uA,
overdrive_mask);
return da9063_buck_set_limit_clear_overdrive(rdev, min_uA,
max_uA,
overdrive_mask);
}
return regulator_set_current_limit_regmap(rdev, min_uA, max_uA);
}
static int da9063_buck_get_current_limit(struct regulator_dev *rdev)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
int val, ret, limit;
unsigned int mask;
limit = regulator_get_current_limit_regmap(rdev);
if (limit < 0)
return limit;
mask = da9063_get_overdrive_mask(rdev->desc);
if (mask) {
ret = regmap_read(regl->hw->regmap, DA9063_REG_CONFIG_H, &val);
if (ret < 0)
return ret;
if (val & mask)
limit *= 2;
}
return limit;
}
static const struct regulator_ops da9063_buck_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
......@@ -419,8 +547,8 @@ static const struct regulator_ops da9063_buck_ops = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
.set_current_limit = regulator_set_current_limit_regmap,
.get_current_limit = regulator_get_current_limit_regmap,
.set_current_limit = da9063_buck_set_current_limit,
.get_current_limit = da9063_buck_get_current_limit,
.set_mode = da9063_buck_set_mode,
.get_mode = da9063_buck_get_mode,
.get_status = da9063_buck_get_status,
......
......@@ -117,11 +117,11 @@ ux500_regulator_debug_init(struct platform_device *pdev,
rdebug.dir = debugfs_create_dir("ux500-regulator", NULL);
/* create "status" file */
debugfs_create_file("status", S_IRUGO, rdebug.dir, &pdev->dev,
debugfs_create_file("status", 0444, rdebug.dir, &pdev->dev,
&ux500_regulator_status_fops);
/* create "power-state-count" file */
debugfs_create_file("power-state-count", S_IRUGO, rdebug.dir,
debugfs_create_file("power-state-count", 0444, rdebug.dir,
&pdev->dev, &ux500_regulator_power_state_cnt_fops);
rdebug.regulator_array = regulator_info;
......
......@@ -205,35 +205,6 @@ struct regulator_dev *devm_regulator_register(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_regulator_register);
static int devm_rdev_match(struct device *dev, void *res, void *data)
{
struct regulator_dev **r = res;
if (!r || !*r) {
WARN_ON(!r || !*r);
return 0;
}
return *r == data;
}
/**
* devm_regulator_unregister - Resource managed regulator_unregister()
* @dev: device to supply
* @rdev: regulator to free
*
* Unregister a regulator registered with devm_regulator_register().
* Normally this function will not need to be called and the resource
* management code will ensure that the resource is freed.
*/
void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
{
int rc;
rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
if (rc != 0)
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_regulator_unregister);
struct regulator_supply_alias_match {
struct device *dev;
const char *id;
......@@ -296,19 +267,8 @@ int devm_regulator_register_supply_alias(struct device *dev, const char *id,
}
EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
/**
* devm_regulator_unregister_supply_alias - Resource managed
* regulator_unregister_supply_alias()
*
* @dev: device to supply
* @id: supply name or regulator ID
*
* Unregister an alias registered with
* devm_regulator_register_supply_alias(). Normally this function
* will not need to be called and the resource management code
* will ensure that the resource is freed.
*/
void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
static void devm_regulator_unregister_supply_alias(struct device *dev,
const char *id)
{
struct regulator_supply_alias_match match;
int rc;
......@@ -321,7 +281,6 @@ void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
if (rc != 0)
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
/**
* devm_regulator_bulk_register_supply_alias - Managed register
......@@ -373,30 +332,6 @@ int devm_regulator_bulk_register_supply_alias(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
/**
* devm_regulator_bulk_unregister_supply_alias - Managed unregister
* multiple aliases
*
* @dev: device to supply
* @id: list of supply names or regulator IDs
* @num_id: number of aliases to unregister
*
* Unregister aliases registered with
* devm_regulator_bulk_register_supply_alias(). Normally this function
* will not need to be called and the resource management code
* will ensure that the resource is freed.
*/
void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
const char *const *id,
int num_id)
{
int i;
for (i = 0; i < num_id; ++i)
devm_regulator_unregister_supply_alias(dev, id[i]);
}
EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
struct regulator_notifier_match {
struct regulator *regulator;
struct notifier_block *nb;
......
......@@ -287,8 +287,9 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
drvdata->dev = devm_regulator_register(&pdev->dev, &drvdata->desc,
&cfg);
if (IS_ERR(drvdata->dev)) {
ret = PTR_ERR(drvdata->dev);
dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
ret = dev_err_probe(&pdev->dev, PTR_ERR(drvdata->dev),
"Failed to register regulator: %ld\n",
PTR_ERR(drvdata->dev));
return ret;
}
......
......@@ -4,7 +4,7 @@
//
// Copyright (c) 2013 Linaro Ltd.
// Copyright (c) 2011 HiSilicon Ltd.
// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd
// Copyright (c) 2020-2021 Huawei Technologies Co., Ltd.
//
// Guodong Xu <guodong.xu@linaro.org>
......@@ -27,34 +27,34 @@ struct hi6421_spmi_reg_info {
u32 eco_uA;
};
static const unsigned int ldo3_voltages[] = {
static const unsigned int range_1v5_to_2v0[] = {
1500000, 1550000, 1600000, 1650000,
1700000, 1725000, 1750000, 1775000,
1800000, 1825000, 1850000, 1875000,
1900000, 1925000, 1950000, 2000000
};
static const unsigned int ldo4_voltages[] = {
static const unsigned int range_1v725_to_1v9[] = {
1725000, 1750000, 1775000, 1800000,
1825000, 1850000, 1875000, 1900000
};
static const unsigned int ldo9_voltages[] = {
static const unsigned int range_1v75_to_3v3[] = {
1750000, 1800000, 1825000, 2800000,
2850000, 2950000, 3000000, 3300000
};
static const unsigned int ldo15_voltages[] = {
static const unsigned int range_1v8_to_3v0[] = {
1800000, 1850000, 2400000, 2600000,
2700000, 2850000, 2950000, 3000000
};
static const unsigned int ldo17_voltages[] = {
static const unsigned int range_2v5_to_3v3[] = {
2500000, 2600000, 2700000, 2800000,
3000000, 3100000, 3200000, 3300000
};
static const unsigned int ldo34_voltages[] = {
static const unsigned int range_2v6_to_3v3[] = {
2600000, 2700000, 2800000, 2900000,
3000000, 3100000, 3200000, 3300000
};
......@@ -73,14 +73,14 @@ static const unsigned int ldo34_voltages[] = {
*/
#define HI6421V600_LDO(_id, vtable, ereg, emask, vreg, \
odelay, etime, ecomask, ecoamp) \
[HI6421V600_##_id] = { \
[hi6421v600_##_id] = { \
.desc = { \
.name = #_id, \
.of_match = of_match_ptr(#_id), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &hi6421_spmi_ldo_rops, \
.type = REGULATOR_VOLTAGE, \
.id = HI6421V600_##_id, \
.id = hi6421v600_##_id, \
.owner = THIS_MODULE, \
.volt_table = vtable, \
.n_voltages = ARRAY_SIZE(vtable), \
......@@ -185,46 +185,46 @@ static const struct regulator_ops hi6421_spmi_ldo_rops = {
/* HI6421v600 regulators with known registers */
enum hi6421_spmi_regulator_id {
HI6421V600_LDO3,
HI6421V600_LDO4,
HI6421V600_LDO9,
HI6421V600_LDO15,
HI6421V600_LDO16,
HI6421V600_LDO17,
HI6421V600_LDO33,
HI6421V600_LDO34,
hi6421v600_ldo3,
hi6421v600_ldo4,
hi6421v600_ldo9,
hi6421v600_ldo15,
hi6421v600_ldo16,
hi6421v600_ldo17,
hi6421v600_ldo33,
hi6421v600_ldo34,
};
static struct hi6421_spmi_reg_info regulator_info[] = {
HI6421V600_LDO(LDO3, ldo3_voltages,
HI6421V600_LDO(ldo3, range_1v5_to_2v0,
0x16, 0x01, 0x51,
20000, 120,
0, 0),
HI6421V600_LDO(LDO4, ldo4_voltages,
HI6421V600_LDO(ldo4, range_1v725_to_1v9,
0x17, 0x01, 0x52,
20000, 120,
0x10, 10000),
HI6421V600_LDO(LDO9, ldo9_voltages,
HI6421V600_LDO(ldo9, range_1v75_to_3v3,
0x1c, 0x01, 0x57,
20000, 360,
0x10, 10000),
HI6421V600_LDO(LDO15, ldo15_voltages,
HI6421V600_LDO(ldo15, range_1v8_to_3v0,
0x21, 0x01, 0x5c,
20000, 360,
0x10, 10000),
HI6421V600_LDO(LDO16, ldo15_voltages,
HI6421V600_LDO(ldo16, range_1v8_to_3v0,
0x22, 0x01, 0x5d,
20000, 360,
0x10, 10000),
HI6421V600_LDO(LDO17, ldo17_voltages,
HI6421V600_LDO(ldo17, range_2v5_to_3v3,
0x23, 0x01, 0x5e,
20000, 120,
0x10, 10000),
HI6421V600_LDO(LDO33, ldo17_voltages,
HI6421V600_LDO(ldo33, range_2v5_to_3v3,
0x32, 0x01, 0x6d,
20000, 120,
0, 0),
HI6421V600_LDO(LDO34, ldo34_voltages,
HI6421V600_LDO(ldo34, range_2v6_to_3v3,
0x33, 0x01, 0x6e,
20000, 120,
0, 0),
......
......@@ -184,7 +184,7 @@ static irqreturn_t regulator_notifier_isr(int irq, void *data)
* If retry_count exceeds the given safety limit we call IC specific die
* handler which can try disabling regulator(s).
*
* If no die handler is given we will just bug() as a last resort.
* If no die handler is given we will just power-off as a last resort.
*
* We could try disabling all associated rdevs - but we might shoot
* ourselves in the head and leave the problematic regulator enabled. So
......
......@@ -28,18 +28,15 @@ struct mt6358_regulator_info {
u32 qi;
const u32 *index_table;
unsigned int n_table;
u32 vsel_shift;
u32 da_vsel_reg;
u32 da_vsel_mask;
u32 da_vsel_shift;
u32 modeset_reg;
u32 modeset_mask;
u32 modeset_shift;
};
#define MT6358_BUCK(match, vreg, min, max, step, \
volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \
_da_vsel_shift, _modeset_reg, _modeset_shift) \
_modeset_reg, _modeset_shift) \
[MT6358_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
......@@ -61,15 +58,13 @@ struct mt6358_regulator_info {
.qi = BIT(0), \
.da_vsel_reg = _da_vsel_reg, \
.da_vsel_mask = _da_vsel_mask, \
.da_vsel_shift = _da_vsel_shift, \
.modeset_reg = _modeset_reg, \
.modeset_mask = BIT(_modeset_shift), \
.modeset_shift = _modeset_shift \
}
#define MT6358_LDO(match, vreg, ldo_volt_table, \
ldo_index_table, enreg, enbit, vosel, \
vosel_mask, vosel_shift) \
vosel_mask) \
[MT6358_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
......@@ -89,12 +84,11 @@ struct mt6358_regulator_info {
.qi = BIT(15), \
.index_table = ldo_index_table, \
.n_table = ARRAY_SIZE(ldo_index_table), \
.vsel_shift = vosel_shift, \
}
#define MT6358_LDO1(match, vreg, min, max, step, \
volt_ranges, _da_vsel_reg, _da_vsel_mask, \
_da_vsel_shift, vosel, vosel_mask) \
vosel, vosel_mask) \
[MT6358_ID_##vreg] = { \
.desc = { \
.name = #vreg, \
......@@ -113,7 +107,6 @@ struct mt6358_regulator_info {
}, \
.da_vsel_reg = _da_vsel_reg, \
.da_vsel_mask = _da_vsel_mask, \
.da_vsel_shift = _da_vsel_shift, \
.status_reg = MT6358_LDO_##vreg##_DBG1, \
.qi = BIT(0), \
}
......@@ -260,9 +253,9 @@ static int mt6358_set_voltage_sel(struct regulator_dev *rdev,
pvol = info->index_table;
idx = pvol[selector];
idx <<= ffs(info->desc.vsel_mask) - 1;
ret = regmap_update_bits(rdev->regmap, info->desc.vsel_reg,
info->desc.vsel_mask,
idx << info->vsel_shift);
info->desc.vsel_mask, idx);
return ret;
}
......@@ -282,7 +275,8 @@ static int mt6358_get_voltage_sel(struct regulator_dev *rdev)
return ret;
}
selector = (selector & info->desc.vsel_mask) >> info->vsel_shift;
selector = (selector & info->desc.vsel_mask) >>
(ffs(info->desc.vsel_mask) - 1);
pvol = info->index_table;
for (idx = 0; idx < info->desc.n_voltages; idx++) {
if (pvol[idx] == selector)
......@@ -305,7 +299,7 @@ static int mt6358_get_buck_voltage_sel(struct regulator_dev *rdev)
return ret;
}
ret = (regval >> info->da_vsel_shift) & info->da_vsel_mask;
ret = (regval & info->da_vsel_mask) >> (ffs(info->da_vsel_mask) - 1);
return ret;
}
......@@ -342,11 +336,10 @@ static int mt6358_regulator_set_mode(struct regulator_dev *rdev,
return -EINVAL;
}
dev_dbg(&rdev->dev, "mt6358 buck set_mode %#x, %#x, %#x, %#x\n",
info->modeset_reg, info->modeset_mask,
info->modeset_shift, val);
dev_dbg(&rdev->dev, "mt6358 buck set_mode %#x, %#x, %#x\n",
info->modeset_reg, info->modeset_mask, val);
val <<= info->modeset_shift;
val <<= ffs(info->modeset_mask) - 1;
return regmap_update_bits(rdev->regmap, info->modeset_reg,
info->modeset_mask, val);
......@@ -364,7 +357,7 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev)
return ret;
}
switch ((regval & info->modeset_mask) >> info->modeset_shift) {
switch ((regval & info->modeset_mask) >> (ffs(info->modeset_mask) - 1)) {
case MT6358_BUCK_MODE_AUTO:
return REGULATOR_MODE_NORMAL;
case MT6358_BUCK_MODE_FORCE_PWM:
......@@ -412,30 +405,30 @@ static const struct regulator_ops mt6358_volt_fixed_ops = {
static struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500,
buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f,
0, MT6358_VDRAM1_ANA_CON0, 8),
MT6358_VDRAM1_ANA_CON0, 8),
MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f,
0, MT6358_VCORE_VGPU_ANA_CON0, 1),
MT6358_VCORE_VGPU_ANA_CON0, 1),
MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000,
buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, 0,
buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f,
MT6358_VPA_ANA_CON0, 3),
MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f,
0, MT6358_VPROC_ANA_CON0, 1),
MT6358_VPROC_ANA_CON0, 1),
MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f,
0, MT6358_VPROC_ANA_CON0, 2),
MT6358_VPROC_ANA_CON0, 2),
MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, 0,
buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f,
MT6358_VCORE_VGPU_ANA_CON0, 2),
MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500,
buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, 0,
buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f,
MT6358_VS2_ANA_CON0, 8),
MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250,
buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f,
0, MT6358_VMODEM_ANA_CON0, 8),
MT6358_VMODEM_ANA_CON0, 8),
MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500,
buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, 0,
buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f,
MT6358_VS1_ANA_CON0, 8),
MT6358_REG_FIXED("ldo_vrf12", VRF12,
MT6358_LDO_VRF12_CON0, 0, 1200000),
......@@ -457,49 +450,49 @@ static struct mt6358_regulator_info mt6358_regulators[] = {
MT6358_REG_FIXED("ldo_vaud28", VAUD28,
MT6358_LDO_VAUD28_CON0, 0, 2800000),
MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx,
MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0xf, 0),
MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0xf),
MT6358_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx,
MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00, 8),
MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx,
MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00, 8),
MT6358_LDO_VIBR_CON0, 0, MT6358_VIBR_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vusb", VUSB, vusb_voltages, vusb_idx,
MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700, 8),
MT6358_LDO_VUSB_CON0_0, 0, MT6358_VUSB_ANA_CON0, 0x700),
MT6358_LDO("ldo_vcamd", VCAMD, vcamd_voltages, vcamd_idx,
MT6358_LDO_VCAMD_CON0, 0, MT6358_VCAMD_ANA_CON0, 0xf00, 8),
MT6358_LDO_VCAMD_CON0, 0, MT6358_VCAMD_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vefuse", VEFUSE, vefuse_voltages, vefuse_idx,
MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00, 8),
MT6358_LDO_VEFUSE_CON0, 0, MT6358_VEFUSE_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vmch", VMCH, vmch_vemc_voltages, vmch_vemc_idx,
MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700, 8),
MT6358_LDO_VMCH_CON0, 0, MT6358_VMCH_ANA_CON0, 0x700),
MT6358_LDO("ldo_vcama1", VCAMA1, vcama_voltages, vcama_idx,
MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00, 8),
MT6358_LDO_VCAMA1_CON0, 0, MT6358_VCAMA1_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vemc", VEMC, vmch_vemc_voltages, vmch_vemc_idx,
MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700, 8),
MT6358_LDO_VEMC_CON0, 0, MT6358_VEMC_ANA_CON0, 0x700),
MT6358_LDO("ldo_vcn33_bt", VCN33_BT, vcn33_bt_wifi_voltages,
vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_0,
0, MT6358_VCN33_ANA_CON0, 0x300, 8),
0, MT6358_VCN33_ANA_CON0, 0x300),
MT6358_LDO("ldo_vcn33_wifi", VCN33_WIFI, vcn33_bt_wifi_voltages,
vcn33_bt_wifi_idx, MT6358_LDO_VCN33_CON0_1,
0, MT6358_VCN33_ANA_CON0, 0x300, 8),
0, MT6358_VCN33_ANA_CON0, 0x300),
MT6358_LDO("ldo_vcama2", VCAMA2, vcama_voltages, vcama_idx,
MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00, 8),
MT6358_LDO_VCAMA2_CON0, 0, MT6358_VCAMA2_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vmc", VMC, vmc_voltages, vmc_idx,
MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00, 8),
MT6358_LDO_VMC_CON0, 0, MT6358_VMC_ANA_CON0, 0xf00),
MT6358_LDO("ldo_vldo28", VLDO28, vldo28_voltages, vldo28_idx,
MT6358_LDO_VLDO28_CON0_0, 0,
MT6358_VLDO28_ANA_CON0, 0x300, 8),
MT6358_VLDO28_ANA_CON0, 0x300),
MT6358_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx,
MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00, 8),
MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00),
MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f, 8,
buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON0, 0x7f),
MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f, 8,
buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON2, 0x7f),
MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f, 8,
buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON3, 0x7f),
MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250,
buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f, 8,
buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00,
MT6358_LDO_VSRAM_CON1, 0x7f),
};
......
......@@ -27,7 +27,6 @@
* @qi: Mask for query enable signal status of regulators.
* @modeset_reg: for operating AUTO/PWM mode register.
* @modeset_mask: MASK for operating modeset register.
* @modeset_shift: SHIFT for operating modeset register.
*/
struct mt6359_regulator_info {
struct regulator_desc desc;
......@@ -35,10 +34,8 @@ struct mt6359_regulator_info {
u32 qi;
u32 modeset_reg;
u32 modeset_mask;
u32 modeset_shift;
u32 lp_mode_reg;
u32 lp_mode_mask;
u32 lp_mode_shift;
};
#define MT6359_BUCK(match, _name, min, max, step, \
......@@ -68,10 +65,8 @@ struct mt6359_regulator_info {
.qi = BIT(0), \
.lp_mode_reg = _lp_mode_reg, \
.lp_mode_mask = BIT(_lp_mode_shift), \
.lp_mode_shift = _lp_mode_shift, \
.modeset_reg = _modeset_reg, \
.modeset_mask = BIT(_modeset_shift), \
.modeset_shift = _modeset_shift \
}
#define MT6359_LDO_LINEAR(match, _name, min, max, step, \
......@@ -282,8 +277,10 @@ static unsigned int mt6359_regulator_get_mode(struct regulator_dev *rdev)
return ret;
}
if ((regval & info->modeset_mask) >> info->modeset_shift ==
MT6359_BUCK_MODE_FORCE_PWM)
regval &= info->modeset_mask;
regval >>= ffs(info->modeset_mask) - 1;
if (regval == MT6359_BUCK_MODE_FORCE_PWM)
return REGULATOR_MODE_FAST;
ret = regmap_read(rdev->regmap, info->lp_mode_reg, &regval);
......@@ -310,7 +307,7 @@ static int mt6359_regulator_set_mode(struct regulator_dev *rdev,
switch (mode) {
case REGULATOR_MODE_FAST:
val = MT6359_BUCK_MODE_FORCE_PWM;
val <<= info->modeset_shift;
val <<= ffs(info->modeset_mask) - 1;
ret = regmap_update_bits(rdev->regmap,
info->modeset_reg,
info->modeset_mask,
......@@ -319,14 +316,14 @@ static int mt6359_regulator_set_mode(struct regulator_dev *rdev,
case REGULATOR_MODE_NORMAL:
if (curr_mode == REGULATOR_MODE_FAST) {
val = MT6359_BUCK_MODE_AUTO;
val <<= info->modeset_shift;
val <<= ffs(info->modeset_mask) - 1;
ret = regmap_update_bits(rdev->regmap,
info->modeset_reg,
info->modeset_mask,
val);
} else if (curr_mode == REGULATOR_MODE_IDLE) {
val = MT6359_BUCK_MODE_NORMAL;
val <<= info->lp_mode_shift;
val <<= ffs(info->lp_mode_mask) - 1;
ret = regmap_update_bits(rdev->regmap,
info->lp_mode_reg,
info->lp_mode_mask,
......@@ -336,7 +333,7 @@ static int mt6359_regulator_set_mode(struct regulator_dev *rdev,
break;
case REGULATOR_MODE_IDLE:
val = MT6359_BUCK_MODE_LP >> 1;
val <<= info->lp_mode_shift;
val <<= ffs(info->lp_mode_mask) - 1;
ret = regmap_update_bits(rdev->regmap,
info->lp_mode_reg,
info->lp_mode_mask,
......
......@@ -32,7 +32,6 @@ struct mt6397_regulator_info {
u32 vselctrl_mask;
u32 modeset_reg;
u32 modeset_mask;
u32 modeset_shift;
};
#define MT6397_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
......@@ -61,7 +60,6 @@ struct mt6397_regulator_info {
.vselctrl_mask = BIT(1), \
.modeset_reg = _modeset_reg, \
.modeset_mask = BIT(_modeset_shift), \
.modeset_shift = _modeset_shift \
}
#define MT6397_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
......@@ -175,11 +173,11 @@ static int mt6397_regulator_set_mode(struct regulator_dev *rdev,
goto err_mode;
}
dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x, %#x\n",
info->modeset_reg, info->modeset_mask,
info->modeset_shift, val);
dev_dbg(&rdev->dev, "mt6397 buck set_mode %#x, %#x, %#x\n",
info->modeset_reg, info->modeset_mask, val);
val <<= ffs(info->modeset_mask) - 1;
val <<= info->modeset_shift;
ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
info->modeset_mask, val);
err_mode:
......@@ -204,7 +202,10 @@ static unsigned int mt6397_regulator_get_mode(struct regulator_dev *rdev)
return ret;
}
switch ((regval & info->modeset_mask) >> info->modeset_shift) {
regval &= info->modeset_mask;
regval >>= ffs(info->modeset_mask) - 1;
switch (regval) {
case MT6397_BUCK_MODE_AUTO:
return REGULATOR_MODE_NORMAL;
case MT6397_BUCK_MODE_FORCE_PWM:
......
......@@ -13,6 +13,16 @@
#include <linux/mfd/rt5033-private.h>
#include <linux/regulator/of_regulator.h>
static const struct linear_range rt5033_buck_ranges[] = {
REGULATOR_LINEAR_RANGE(1000000, 0, 20, 100000),
REGULATOR_LINEAR_RANGE(3000000, 21, 31, 0),
};
static const struct linear_range rt5033_ldo_ranges[] = {
REGULATOR_LINEAR_RANGE(1200000, 0, 18, 100000),
REGULATOR_LINEAR_RANGE(3000000, 19, 31, 0),
};
static const struct regulator_ops rt5033_safe_ldo_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
......@@ -24,8 +34,7 @@ static const struct regulator_ops rt5033_buck_ops = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.list_voltage = regulator_list_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
......@@ -40,8 +49,8 @@ static const struct regulator_desc rt5033_supported_regulators[] = {
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.n_voltages = RT5033_REGULATOR_BUCK_VOLTAGE_STEP_NUM,
.min_uV = RT5033_REGULATOR_BUCK_VOLTAGE_MIN,
.uV_step = RT5033_REGULATOR_BUCK_VOLTAGE_STEP,
.linear_ranges = rt5033_buck_ranges,
.n_linear_ranges = ARRAY_SIZE(rt5033_buck_ranges),
.enable_reg = RT5033_REG_CTRL,
.enable_mask = RT5033_CTRL_EN_BUCK_MASK,
.vsel_reg = RT5033_REG_BUCK_CTRL,
......@@ -56,8 +65,8 @@ static const struct regulator_desc rt5033_supported_regulators[] = {
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.n_voltages = RT5033_REGULATOR_LDO_VOLTAGE_STEP_NUM,
.min_uV = RT5033_REGULATOR_LDO_VOLTAGE_MIN,
.uV_step = RT5033_REGULATOR_LDO_VOLTAGE_STEP,
.linear_ranges = rt5033_ldo_ranges,
.n_linear_ranges = ARRAY_SIZE(rt5033_ldo_ranges),
.enable_reg = RT5033_REG_CTRL,
.enable_mask = RT5033_CTRL_EN_LDO_MASK,
.vsel_reg = RT5033_REG_LDO_CTRL,
......
......@@ -144,7 +144,7 @@ static int rt6245_init_device_properties(struct device *dev)
static int rt6245_reg_write(void *context, unsigned int reg, unsigned int val)
{
struct i2c_client *i2c = context;
const u8 func_base[] = { 0x6F, 0x73, 0x78, 0x61, 0x7C, 0 };
static const u8 func_base[] = { 0x6F, 0x73, 0x78, 0x61, 0x7C, 0 };
unsigned int code, bit_count;
code = func_base[reg];
......
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitops.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
enum {
RTQ2134_IDX_BUCK1 = 0,
RTQ2134_IDX_BUCK2,
RTQ2134_IDX_BUCK3,
RTQ2134_IDX_MAX
};
#define RTQ2134_AUTO_MODE 0
#define RTQ2134_FCCM_MODE 1
#define RTQ2134_BUCK_DVS0_CTRL 0
#define RTQ2134_BUCK_VSEL_CTRL 2
#define RTQ2134_REG_IO_CHIPNAME 0x01
#define RTQ2134_REG_FLT_RECORDTEMP 0x13
#define RTQ2134_REG_FLT_RECORDBUCK(_id) (0x14 + (_id))
#define RTQ2134_REG_FLT_BUCKCTRL(_id) (0x37 + (_id))
#define RTQ2134_REG_BUCK1_CFG0 0x42
#define RTQ2134_REG_BUCK1_DVS0CFG1 0x48
#define RTQ2134_REG_BUCK1_DVS0CFG0 0x49
#define RTQ2134_REG_BUCK1_DVS1CFG1 0x4A
#define RTQ2134_REG_BUCK1_DVS1CFG0 0x4B
#define RTQ2134_REG_BUCK1_DVSCFG 0x52
#define RTQ2134_REG_BUCK1_RSPCFG 0x54
#define RTQ2134_REG_BUCK2_CFG0 0x5F
#define RTQ2134_REG_BUCK2_DVS0CFG1 0x62
#define RTQ2134_REG_BUCK2_DVS0CFG0 0x63
#define RTQ2134_REG_BUCK2_DVS1CFG1 0x64
#define RTQ2134_REG_BUCK2_DVS1CFG0 0x65
#define RTQ2134_REG_BUCK2_DVSCFG 0x6C
#define RTQ2134_REG_BUCK2_RSPCFG 0x6E
#define RTQ2134_REG_BUCK3_CFG0 0x79
#define RTQ2134_REG_BUCK3_DVS0CFG1 0x7C
#define RTQ2134_REG_BUCK3_DVS0CFG0 0x7D
#define RTQ2134_REG_BUCK3_DVS1CFG1 0x7E
#define RTQ2134_REG_BUCK3_DVS1CFG0 0x7F
#define RTQ2134_REG_BUCK3_DVSCFG 0x86
#define RTQ2134_REG_BUCK3_RSPCFG 0x88
#define RTQ2134_REG_BUCK3_SLEWCTRL 0x89
#define RTQ2134_VOUT_MAXNUM 256
#define RTQ2134_VOUT_MASK 0xFF
#define RTQ2134_VOUTEN_MASK BIT(0)
#define RTQ2134_ACTDISCHG_MASK BIT(0)
#define RTQ2134_RSPUP_MASK GENMASK(6, 4)
#define RTQ2134_FCCM_MASK BIT(5)
#define RTQ2134_UVHICCUP_MASK BIT(3)
#define RTQ2134_BUCKDVS_CTRL_MASK GENMASK(1, 0)
#define RTQ2134_CHIPOT_MASK BIT(2)
#define RTQ2134_BUCKOV_MASK BIT(5)
#define RTQ2134_BUCKUV_MASK BIT(4)
struct rtq2134_regulator_desc {
struct regulator_desc desc;
/* Extension for proprietary register and mask */
unsigned int mode_reg;
unsigned int mode_mask;
unsigned int suspend_enable_reg;
unsigned int suspend_enable_mask;
unsigned int suspend_vsel_reg;
unsigned int suspend_vsel_mask;
unsigned int suspend_mode_reg;
unsigned int suspend_mode_mask;
unsigned int dvs_ctrl_reg;
};
static int rtq2134_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
struct rtq2134_regulator_desc *desc =
(struct rtq2134_regulator_desc *)rdev->desc;
unsigned int val;
if (mode == REGULATOR_MODE_NORMAL)
val = RTQ2134_AUTO_MODE;
else if (mode == REGULATOR_MODE_FAST)
val = RTQ2134_FCCM_MODE;
else
return -EINVAL;
val <<= ffs(desc->mode_mask) - 1;
return regmap_update_bits(rdev->regmap, desc->mode_reg, desc->mode_mask,
val);
}
static unsigned int rtq2134_buck_get_mode(struct regulator_dev *rdev)
{
struct rtq2134_regulator_desc *desc =
(struct rtq2134_regulator_desc *)rdev->desc;
unsigned int mode;
int ret;
ret = regmap_read(rdev->regmap, desc->mode_reg, &mode);
if (ret)
return ret;
if (mode & desc->mode_mask)
return REGULATOR_MODE_FAST;
return REGULATOR_MODE_NORMAL;
}
static int rtq2134_buck_set_suspend_voltage(struct regulator_dev *rdev, int uV)
{
struct rtq2134_regulator_desc *desc =
(struct rtq2134_regulator_desc *)rdev->desc;
int sel;
sel = regulator_map_voltage_linear_range(rdev, uV, uV);
if (sel < 0)
return sel;
sel <<= ffs(desc->suspend_vsel_mask) - 1;
return regmap_update_bits(rdev->regmap, desc->suspend_vsel_reg,
desc->suspend_vsel_mask, sel);
}
static int rtq2134_buck_set_suspend_enable(struct regulator_dev *rdev)
{
struct rtq2134_regulator_desc *desc =
(struct rtq2134_regulator_desc *)rdev->desc;
unsigned int val = desc->suspend_enable_mask;
return regmap_update_bits(rdev->regmap, desc->suspend_enable_reg,
desc->suspend_enable_mask, val);
}
static int rtq2134_buck_set_suspend_disable(struct regulator_dev *rdev)
{
struct rtq2134_regulator_desc *desc =
(struct rtq2134_regulator_desc *)rdev->desc;
return regmap_update_bits(rdev->regmap, desc->suspend_enable_reg,
desc->suspend_enable_mask, 0);
}
static int rtq2134_buck_set_suspend_mode(struct regulator_dev *rdev,
unsigned int mode)
{
struct rtq2134_regulator_desc *desc =
(struct rtq2134_regulator_desc *)rdev->desc;
unsigned int val;
if (mode == REGULATOR_MODE_NORMAL)
val = RTQ2134_AUTO_MODE;
else if (mode == REGULATOR_MODE_FAST)
val = RTQ2134_FCCM_MODE;
else
return -EINVAL;
val <<= ffs(desc->suspend_mode_mask) - 1;
return regmap_update_bits(rdev->regmap, desc->suspend_mode_reg,
desc->suspend_mode_mask, val);
}
static int rtq2134_buck_get_error_flags(struct regulator_dev *rdev,
unsigned int *flags)
{
int rid = rdev_get_id(rdev);
unsigned int chip_error, buck_error, events = 0;
int ret;
ret = regmap_read(rdev->regmap, RTQ2134_REG_FLT_RECORDTEMP,
&chip_error);
if (ret) {
dev_err(&rdev->dev, "Failed to get chip error flag\n");
return ret;
}
ret = regmap_read(rdev->regmap, RTQ2134_REG_FLT_RECORDBUCK(rid),
&buck_error);
if (ret) {
dev_err(&rdev->dev, "Failed to get buck error flag\n");
return ret;
}
if (chip_error & RTQ2134_CHIPOT_MASK)
events |= REGULATOR_ERROR_OVER_TEMP;
if (buck_error & RTQ2134_BUCKUV_MASK)
events |= REGULATOR_ERROR_UNDER_VOLTAGE;
if (buck_error & RTQ2134_BUCKOV_MASK)
events |= REGULATOR_ERROR_REGULATION_OUT;
*flags = events;
return 0;
}
static const struct regulator_ops rtq2134_buck_ops = {
.list_voltage = regulator_list_voltage_linear_range,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_active_discharge = regulator_set_active_discharge_regmap,
.set_ramp_delay = regulator_set_ramp_delay_regmap,
.set_mode = rtq2134_buck_set_mode,
.get_mode = rtq2134_buck_get_mode,
.set_suspend_voltage = rtq2134_buck_set_suspend_voltage,
.set_suspend_enable = rtq2134_buck_set_suspend_enable,
.set_suspend_disable = rtq2134_buck_set_suspend_disable,
.set_suspend_mode = rtq2134_buck_set_suspend_mode,
.get_error_flags = rtq2134_buck_get_error_flags,
};
static const struct linear_range rtq2134_buck_vout_ranges[] = {
REGULATOR_LINEAR_RANGE(300000, 0, 200, 5000),
REGULATOR_LINEAR_RANGE(1310000, 201, 255, 10000)
};
static unsigned int rtq2134_buck_of_map_mode(unsigned int mode)
{
switch (mode) {
case RTQ2134_AUTO_MODE:
return REGULATOR_MODE_NORMAL;
case RTQ2134_FCCM_MODE:
return REGULATOR_MODE_FAST;
}
return REGULATOR_MODE_INVALID;
}
static int rtq2134_buck_of_parse_cb(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *cfg)
{
struct rtq2134_regulator_desc *rdesc =
(struct rtq2134_regulator_desc *)desc;
int rid = desc->id;
bool uv_shutdown, vsel_dvs;
unsigned int val;
int ret;
vsel_dvs = of_property_read_bool(np, "richtek,use-vsel-dvs");
if (vsel_dvs)
val = RTQ2134_BUCK_VSEL_CTRL;
else
val = RTQ2134_BUCK_DVS0_CTRL;
ret = regmap_update_bits(cfg->regmap, rdesc->dvs_ctrl_reg,
RTQ2134_BUCKDVS_CTRL_MASK, val);
if (ret)
return ret;
uv_shutdown = of_property_read_bool(np, "richtek,uv-shutdown");
if (uv_shutdown)
val = 0;
else
val = RTQ2134_UVHICCUP_MASK;
return regmap_update_bits(cfg->regmap, RTQ2134_REG_FLT_BUCKCTRL(rid),
RTQ2134_UVHICCUP_MASK, val);
}
static const unsigned int rtq2134_buck_ramp_delay_table[] = {
0, 16000, 0, 8000, 4000, 2000, 1000, 500
};
#define RTQ2134_BUCK_DESC(_id) { \
.desc = { \
.name = "rtq2134_buck" #_id, \
.of_match = of_match_ptr("buck" #_id), \
.regulators_node = of_match_ptr("regulators"), \
.id = RTQ2134_IDX_BUCK##_id, \
.type = REGULATOR_VOLTAGE, \
.owner = THIS_MODULE, \
.ops = &rtq2134_buck_ops, \
.n_voltages = RTQ2134_VOUT_MAXNUM, \
.linear_ranges = rtq2134_buck_vout_ranges, \
.n_linear_ranges = ARRAY_SIZE(rtq2134_buck_vout_ranges), \
.vsel_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG1, \
.vsel_mask = RTQ2134_VOUT_MASK, \
.enable_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG0, \
.enable_mask = RTQ2134_VOUTEN_MASK, \
.active_discharge_reg = RTQ2134_REG_BUCK##_id##_CFG0, \
.active_discharge_mask = RTQ2134_ACTDISCHG_MASK, \
.ramp_reg = RTQ2134_REG_BUCK##_id##_RSPCFG, \
.ramp_mask = RTQ2134_RSPUP_MASK, \
.ramp_delay_table = rtq2134_buck_ramp_delay_table, \
.n_ramp_values = ARRAY_SIZE(rtq2134_buck_ramp_delay_table), \
.of_map_mode = rtq2134_buck_of_map_mode, \
.of_parse_cb = rtq2134_buck_of_parse_cb, \
}, \
.mode_reg = RTQ2134_REG_BUCK##_id##_DVS0CFG0, \
.mode_mask = RTQ2134_FCCM_MASK, \
.suspend_mode_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG0, \
.suspend_mode_mask = RTQ2134_FCCM_MASK, \
.suspend_enable_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG0, \
.suspend_enable_mask = RTQ2134_VOUTEN_MASK, \
.suspend_vsel_reg = RTQ2134_REG_BUCK##_id##_DVS1CFG1, \
.suspend_vsel_mask = RTQ2134_VOUT_MASK, \
.dvs_ctrl_reg = RTQ2134_REG_BUCK##_id##_DVSCFG, \
}
static const struct rtq2134_regulator_desc rtq2134_regulator_descs[] = {
RTQ2134_BUCK_DESC(1),
RTQ2134_BUCK_DESC(2),
RTQ2134_BUCK_DESC(3)
};
static bool rtq2134_is_accissible_reg(struct device *dev, unsigned int reg)
{
if (reg >= RTQ2134_REG_IO_CHIPNAME && reg <= RTQ2134_REG_BUCK3_SLEWCTRL)
return true;
return false;
}
static const struct regmap_config rtq2134_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = RTQ2134_REG_BUCK3_SLEWCTRL,
.readable_reg = rtq2134_is_accissible_reg,
.writeable_reg = rtq2134_is_accissible_reg,
};
static int rtq2134_probe(struct i2c_client *i2c)
{
struct regmap *regmap;
struct regulator_dev *rdev;
struct regulator_config regulator_cfg = {};
int i;
regmap = devm_regmap_init_i2c(i2c, &rtq2134_regmap_config);
if (IS_ERR(regmap)) {
dev_err(&i2c->dev, "Failed to allocate regmap\n");
return PTR_ERR(regmap);
}
regulator_cfg.dev = &i2c->dev;
regulator_cfg.regmap = regmap;
for (i = 0; i < ARRAY_SIZE(rtq2134_regulator_descs); i++) {
rdev = devm_regulator_register(&i2c->dev,
&rtq2134_regulator_descs[i].desc,
&regulator_cfg);
if (IS_ERR(rdev)) {
dev_err(&i2c->dev, "Failed to init %d regulator\n", i);
return PTR_ERR(rdev);
}
}
return 0;
}
static const struct of_device_id __maybe_unused rtq2134_device_tables[] = {
{ .compatible = "richtek,rtq2134", },
{}
};
MODULE_DEVICE_TABLE(of, rtq2134_device_tables);
static struct i2c_driver rtq2134_driver = {
.driver = {
.name = "rtq2134",
.of_match_table = rtq2134_device_tables,
},
.probe_new = rtq2134_probe,
};
module_i2c_driver(rtq2134_driver);
MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
MODULE_DESCRIPTION("Richtek RTQ2134 Regulator Driver");
MODULE_LICENSE("GPL v2");
// SPDX-License-Identifier: GPL-2.0+
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
enum {
RTQ6752_IDX_PAVDD = 0,
RTQ6752_IDX_NAVDD = 1,
RTQ6752_IDX_MAX
};
#define RTQ6752_REG_PAVDD 0x00
#define RTQ6752_REG_NAVDD 0x01
#define RTQ6752_REG_PAVDDONDLY 0x07
#define RTQ6752_REG_PAVDDSSTIME 0x08
#define RTQ6752_REG_NAVDDONDLY 0x0D
#define RTQ6752_REG_NAVDDSSTIME 0x0E
#define RTQ6752_REG_OPTION1 0x12
#define RTQ6752_REG_CHSWITCH 0x16
#define RTQ6752_REG_FAULT 0x1D
#define RTQ6752_VOUT_MASK GENMASK(5, 0)
#define RTQ6752_NAVDDEN_MASK BIT(3)
#define RTQ6752_PAVDDEN_MASK BIT(0)
#define RTQ6752_PAVDDAD_MASK BIT(4)
#define RTQ6752_NAVDDAD_MASK BIT(3)
#define RTQ6752_PAVDDF_MASK BIT(3)
#define RTQ6752_NAVDDF_MASK BIT(0)
#define RTQ6752_ENABLE_MASK (BIT(RTQ6752_IDX_MAX) - 1)
#define RTQ6752_VOUT_MINUV 5000000
#define RTQ6752_VOUT_STEPUV 50000
#define RTQ6752_VOUT_NUM 47
#define RTQ6752_I2CRDY_TIMEUS 1000
#define RTQ6752_MINSS_TIMEUS 5000
struct rtq6752_priv {
struct regmap *regmap;
struct gpio_desc *enable_gpio;
struct mutex lock;
unsigned char enable_flag;
};
static int rtq6752_set_vdd_enable(struct regulator_dev *rdev)
{
struct rtq6752_priv *priv = rdev_get_drvdata(rdev);
int rid = rdev_get_id(rdev), ret;
mutex_lock(&priv->lock);
if (priv->enable_gpio) {
gpiod_set_value(priv->enable_gpio, 1);
usleep_range(RTQ6752_I2CRDY_TIMEUS,
RTQ6752_I2CRDY_TIMEUS + 100);
}
if (!priv->enable_flag) {
regcache_cache_only(priv->regmap, false);
ret = regcache_sync(priv->regmap);
if (ret) {
mutex_unlock(&priv->lock);
return ret;
}
}
priv->enable_flag |= BIT(rid);
mutex_unlock(&priv->lock);
return regulator_enable_regmap(rdev);
}
static int rtq6752_set_vdd_disable(struct regulator_dev *rdev)
{
struct rtq6752_priv *priv = rdev_get_drvdata(rdev);
int rid = rdev_get_id(rdev), ret;
ret = regulator_disable_regmap(rdev);
if (ret)
return ret;
mutex_lock(&priv->lock);
priv->enable_flag &= ~BIT(rid);
if (!priv->enable_flag) {
regcache_cache_only(priv->regmap, true);
regcache_mark_dirty(priv->regmap);
}
if (priv->enable_gpio)
gpiod_set_value(priv->enable_gpio, 0);
mutex_unlock(&priv->lock);
return 0;
}
static int rtq6752_get_error_flags(struct regulator_dev *rdev,
unsigned int *flags)
{
unsigned int val, events = 0;
const unsigned int fault_mask[] = {
RTQ6752_PAVDDF_MASK, RTQ6752_NAVDDF_MASK };
int rid = rdev_get_id(rdev), ret;
ret = regmap_read(rdev->regmap, RTQ6752_REG_FAULT, &val);
if (ret)
return ret;
if (val & fault_mask[rid])
events = REGULATOR_ERROR_REGULATION_OUT;
*flags = events;
return 0;
}
static const struct regulator_ops rtq6752_regulator_ops = {
.list_voltage = regulator_list_voltage_linear,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.enable = rtq6752_set_vdd_enable,
.disable = rtq6752_set_vdd_disable,
.is_enabled = regulator_is_enabled_regmap,
.set_active_discharge = regulator_set_active_discharge_regmap,
.get_error_flags = rtq6752_get_error_flags,
};
static const struct regulator_desc rtq6752_regulator_descs[] = {
{
.name = "rtq6752-pavdd",
.of_match = of_match_ptr("pavdd"),
.regulators_node = of_match_ptr("regulators"),
.id = RTQ6752_IDX_PAVDD,
.n_voltages = RTQ6752_VOUT_NUM,
.ops = &rtq6752_regulator_ops,
.owner = THIS_MODULE,
.min_uV = RTQ6752_VOUT_MINUV,
.uV_step = RTQ6752_VOUT_STEPUV,
.enable_time = RTQ6752_MINSS_TIMEUS,
.vsel_reg = RTQ6752_REG_PAVDD,
.vsel_mask = RTQ6752_VOUT_MASK,
.enable_reg = RTQ6752_REG_CHSWITCH,
.enable_mask = RTQ6752_PAVDDEN_MASK,
.active_discharge_reg = RTQ6752_REG_OPTION1,
.active_discharge_mask = RTQ6752_PAVDDAD_MASK,
.active_discharge_off = RTQ6752_PAVDDAD_MASK,
},
{
.name = "rtq6752-navdd",
.of_match = of_match_ptr("navdd"),
.regulators_node = of_match_ptr("regulators"),
.id = RTQ6752_IDX_NAVDD,
.n_voltages = RTQ6752_VOUT_NUM,
.ops = &rtq6752_regulator_ops,
.owner = THIS_MODULE,
.min_uV = RTQ6752_VOUT_MINUV,
.uV_step = RTQ6752_VOUT_STEPUV,
.enable_time = RTQ6752_MINSS_TIMEUS,
.vsel_reg = RTQ6752_REG_NAVDD,
.vsel_mask = RTQ6752_VOUT_MASK,
.enable_reg = RTQ6752_REG_CHSWITCH,
.enable_mask = RTQ6752_NAVDDEN_MASK,
.active_discharge_reg = RTQ6752_REG_OPTION1,
.active_discharge_mask = RTQ6752_NAVDDAD_MASK,
.active_discharge_off = RTQ6752_NAVDDAD_MASK,
}
};
static int rtq6752_init_device_properties(struct rtq6752_priv *priv)
{
u8 raw_vals[] = { 0, 0 };
int ret;
/* Configure PAVDD on and softstart delay time to the minimum */
ret = regmap_raw_write(priv->regmap, RTQ6752_REG_PAVDDONDLY, raw_vals,
ARRAY_SIZE(raw_vals));
if (ret)
return ret;
/* Configure NAVDD on and softstart delay time to the minimum */
return regmap_raw_write(priv->regmap, RTQ6752_REG_NAVDDONDLY, raw_vals,
ARRAY_SIZE(raw_vals));
}
static bool rtq6752_is_volatile_reg(struct device *dev, unsigned int reg)
{
if (reg == RTQ6752_REG_FAULT)
return true;
return false;
}
static const struct reg_default rtq6752_reg_defaults[] = {
{ RTQ6752_REG_PAVDD, 0x14 },
{ RTQ6752_REG_NAVDD, 0x14 },
{ RTQ6752_REG_PAVDDONDLY, 0x01 },
{ RTQ6752_REG_PAVDDSSTIME, 0x01 },
{ RTQ6752_REG_NAVDDONDLY, 0x01 },
{ RTQ6752_REG_NAVDDSSTIME, 0x01 },
{ RTQ6752_REG_OPTION1, 0x07 },
{ RTQ6752_REG_CHSWITCH, 0x29 },
};
static const struct regmap_config rtq6752_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.cache_type = REGCACHE_RBTREE,
.max_register = RTQ6752_REG_FAULT,
.reg_defaults = rtq6752_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(rtq6752_reg_defaults),
.volatile_reg = rtq6752_is_volatile_reg,
};
static int rtq6752_probe(struct i2c_client *i2c)
{
struct rtq6752_priv *priv;
struct regulator_config reg_cfg = {};
struct regulator_dev *rdev;
int i, ret;
priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
mutex_init(&priv->lock);
priv->enable_gpio = devm_gpiod_get_optional(&i2c->dev, "enable",
GPIOD_OUT_HIGH);
if (IS_ERR(priv->enable_gpio)) {
dev_err(&i2c->dev, "Failed to get 'enable' gpio\n");
return PTR_ERR(priv->enable_gpio);
}
usleep_range(RTQ6752_I2CRDY_TIMEUS, RTQ6752_I2CRDY_TIMEUS + 100);
/* Default EN pin to high, PAVDD and NAVDD will be on */
priv->enable_flag = RTQ6752_ENABLE_MASK;
priv->regmap = devm_regmap_init_i2c(i2c, &rtq6752_regmap_config);
if (IS_ERR(priv->regmap)) {
dev_err(&i2c->dev, "Failed to init regmap\n");
return PTR_ERR(priv->regmap);
}
ret = rtq6752_init_device_properties(priv);
if (ret) {
dev_err(&i2c->dev, "Failed to init device properties\n");
return ret;
}
reg_cfg.dev = &i2c->dev;
reg_cfg.regmap = priv->regmap;
reg_cfg.driver_data = priv;
for (i = 0; i < ARRAY_SIZE(rtq6752_regulator_descs); i++) {
rdev = devm_regulator_register(&i2c->dev,
rtq6752_regulator_descs + i,
&reg_cfg);
if (IS_ERR(rdev)) {
dev_err(&i2c->dev, "Failed to init %d regulator\n", i);
return PTR_ERR(rdev);
}
}
return 0;
}
static const struct of_device_id __maybe_unused rtq6752_device_table[] = {
{ .compatible = "richtek,rtq6752", },
{}
};
MODULE_DEVICE_TABLE(of, rtq6752_device_table);
static struct i2c_driver rtq6752_driver = {
.driver = {
.name = "rtq6752",
.of_match_table = rtq6752_device_table,
},
.probe_new = rtq6752_probe,
};
module_i2c_driver(rtq6752_driver);
MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
MODULE_DESCRIPTION("Richtek RTQ6752 Regulator Driver");
MODULE_LICENSE("GPL v2");
......@@ -13,7 +13,10 @@
#include <linux/gpio/consumer.h>
#include <linux/mfd/sy7636a.h>
#define SY7636A_POLL_ENABLED_TIME 500
struct sy7636a_data {
struct regmap *regmap;
struct gpio_desc *pgood_gpio;
};
static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev)
{
......@@ -35,10 +38,10 @@ static int sy7636a_get_vcom_voltage_op(struct regulator_dev *rdev)
static int sy7636a_get_status(struct regulator_dev *rdev)
{
struct sy7636a *sy7636a = rdev_get_drvdata(rdev);
struct sy7636a_data *data = dev_get_drvdata(rdev->dev.parent);
int ret = 0;
ret = gpiod_get_value_cansleep(sy7636a->pgood_gpio);
ret = gpiod_get_value_cansleep(data->pgood_gpio);
if (ret < 0)
dev_err(&rdev->dev, "Failed to read pgood gpio: %d\n", ret);
......@@ -61,46 +64,50 @@ static const struct regulator_desc desc = {
.owner = THIS_MODULE,
.enable_reg = SY7636A_REG_OPERATION_MODE_CRL,
.enable_mask = SY7636A_OPERATION_MODE_CRL_ONOFF,
.poll_enabled_time = SY7636A_POLL_ENABLED_TIME,
.regulators_node = of_match_ptr("regulators"),
.of_match = of_match_ptr("vcom"),
};
static int sy7636a_regulator_probe(struct platform_device *pdev)
{
struct sy7636a *sy7636a = dev_get_drvdata(pdev->dev.parent);
struct regmap *regmap = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
struct regulator_dev *rdev;
struct gpio_desc *gdp;
struct sy7636a_data *data;
int ret;
if (!sy7636a)
if (!regmap)
return -EPROBE_DEFER;
platform_set_drvdata(pdev, sy7636a);
gdp = devm_gpiod_get(sy7636a->dev, "epd-pwr-good", GPIOD_IN);
gdp = devm_gpiod_get(pdev->dev.parent, "epd-pwr-good", GPIOD_IN);
if (IS_ERR(gdp)) {
dev_err(sy7636a->dev, "Power good GPIO fault %ld\n", PTR_ERR(gdp));
dev_err(pdev->dev.parent, "Power good GPIO fault %ld\n", PTR_ERR(gdp));
return PTR_ERR(gdp);
}
sy7636a->pgood_gpio = gdp;
data = devm_kzalloc(&pdev->dev, sizeof(struct sy7636a_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->regmap = regmap;
data->pgood_gpio = gdp;
platform_set_drvdata(pdev, data);
ret = regmap_write(sy7636a->regmap, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0);
ret = regmap_write(regmap, SY7636A_REG_POWER_ON_DELAY_TIME, 0x0);
if (ret) {
dev_err(sy7636a->dev, "Failed to initialize regulator: %d\n", ret);
dev_err(pdev->dev.parent, "Failed to initialize regulator: %d\n", ret);
return ret;
}
config.dev = &pdev->dev;
config.dev->of_node = sy7636a->dev->of_node;
config.driver_data = sy7636a;
config.regmap = sy7636a->regmap;
config.dev->of_node = pdev->dev.parent->of_node;
config.regmap = regmap;
rdev = devm_regulator_register(&pdev->dev, &desc, &config);
if (IS_ERR(rdev)) {
dev_err(sy7636a->dev, "Failed to register %s regulator\n",
dev_err(pdev->dev.parent, "Failed to register %s regulator\n",
pdev->name);
return PTR_ERR(rdev);
}
......
......@@ -25,6 +25,7 @@ struct sy8824_config {
unsigned int vsel_min;
unsigned int vsel_step;
unsigned int vsel_count;
const struct regmap_config *config;
};
struct sy8824_device_info {
......@@ -110,6 +111,15 @@ static int sy8824_regulator_register(struct sy8824_device_info *di,
static const struct regmap_config sy8824_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.num_reg_defaults_raw = 1,
.cache_type = REGCACHE_FLAT,
};
static const struct regmap_config sy20276_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.num_reg_defaults_raw = 2,
.cache_type = REGCACHE_FLAT,
};
static int sy8824_i2c_probe(struct i2c_client *client)
......@@ -134,7 +144,7 @@ static int sy8824_i2c_probe(struct i2c_client *client)
di->dev = dev;
di->cfg = of_device_get_match_data(dev);
regmap = devm_regmap_init_i2c(client, &sy8824_regmap_config);
regmap = devm_regmap_init_i2c(client, di->cfg->config);
if (IS_ERR(regmap)) {
dev_err(dev, "Failed to allocate regmap!\n");
return PTR_ERR(regmap);
......@@ -160,6 +170,7 @@ static const struct sy8824_config sy8824c_cfg = {
.vsel_min = 762500,
.vsel_step = 12500,
.vsel_count = 64,
.config = &sy8824_regmap_config,
};
static const struct sy8824_config sy8824e_cfg = {
......@@ -169,6 +180,7 @@ static const struct sy8824_config sy8824e_cfg = {
.vsel_min = 700000,
.vsel_step = 12500,
.vsel_count = 64,
.config = &sy8824_regmap_config,
};
static const struct sy8824_config sy20276_cfg = {
......@@ -178,6 +190,7 @@ static const struct sy8824_config sy20276_cfg = {
.vsel_min = 600000,
.vsel_step = 10000,
.vsel_count = 128,
.config = &sy20276_regmap_config,
};
static const struct sy8824_config sy20278_cfg = {
......@@ -187,6 +200,7 @@ static const struct sy8824_config sy20278_cfg = {
.vsel_min = 762500,
.vsel_step = 12500,
.vsel_count = 64,
.config = &sy20276_regmap_config,
};
static const struct of_device_id sy8824_dt_ids[] = {
......
......@@ -19,6 +19,10 @@
#define SY8827N_MODE (1 << 6)
#define SY8827N_VSEL1 1
#define SY8827N_CTRL 2
#define SY8827N_ID1 3
#define SY8827N_ID2 4
#define SY8827N_PGOOD 5
#define SY8827N_MAX (SY8827N_PGOOD + 1)
#define SY8827N_NVOLTAGES 64
#define SY8827N_VSELMIN 600000
......@@ -102,9 +106,19 @@ static int sy8827n_regulator_register(struct sy8827n_device_info *di,
return PTR_ERR_OR_ZERO(rdev);
}
static bool sy8827n_volatile_reg(struct device *dev, unsigned int reg)
{
if (reg == SY8827N_PGOOD)
return true;
return false;
}
static const struct regmap_config sy8827n_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.volatile_reg = sy8827n_volatile_reg,
.num_reg_defaults_raw = SY8827N_MAX,
.cache_type = REGCACHE_FLAT,
};
static int sy8827n_i2c_probe(struct i2c_client *client)
......
......@@ -1211,12 +1211,10 @@ static int tps65910_probe(struct platform_device *pdev)
rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
&config);
if (IS_ERR(rdev)) {
dev_err(tps65910->dev,
"failed to register %s regulator\n",
pdev->name);
return PTR_ERR(rdev);
}
if (IS_ERR(rdev))
return dev_err_probe(tps65910->dev, PTR_ERR(rdev),
"failed to register %s regulator\n",
pdev->name);
/* Save regulator for cleanup */
pmic->rdev[i] = rdev;
......
......@@ -37,7 +37,6 @@ struct vctrl_voltage_table {
struct vctrl_data {
struct regulator_dev *rdev;
struct regulator_desc desc;
struct regulator *ctrl_reg;
bool enabled;
unsigned int min_slew_down_rate;
unsigned int ovp_threshold;
......@@ -82,7 +81,12 @@ static int vctrl_calc_output_voltage(struct vctrl_data *vctrl, int ctrl_uV)
static int vctrl_get_voltage(struct regulator_dev *rdev)
{
struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
int ctrl_uV = regulator_get_voltage_rdev(vctrl->ctrl_reg->rdev);
int ctrl_uV;
if (!rdev->supply)
return -EPROBE_DEFER;
ctrl_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
return vctrl_calc_output_voltage(vctrl, ctrl_uV);
}
......@@ -92,14 +96,19 @@ static int vctrl_set_voltage(struct regulator_dev *rdev,
unsigned int *selector)
{
struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
struct regulator *ctrl_reg = vctrl->ctrl_reg;
int orig_ctrl_uV = regulator_get_voltage_rdev(ctrl_reg->rdev);
int uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV);
int orig_ctrl_uV;
int uV;
int ret;
if (!rdev->supply)
return -EPROBE_DEFER;
orig_ctrl_uV = regulator_get_voltage_rdev(rdev->supply->rdev);
uV = vctrl_calc_output_voltage(vctrl, orig_ctrl_uV);
if (req_min_uV >= uV || !vctrl->ovp_threshold)
/* voltage rising or no OVP */
return regulator_set_voltage_rdev(ctrl_reg->rdev,
return regulator_set_voltage_rdev(rdev->supply->rdev,
vctrl_calc_ctrl_voltage(vctrl, req_min_uV),
vctrl_calc_ctrl_voltage(vctrl, req_max_uV),
PM_SUSPEND_ON);
......@@ -117,7 +126,7 @@ static int vctrl_set_voltage(struct regulator_dev *rdev,
next_uV = max_t(int, req_min_uV, uV - max_drop_uV);
next_ctrl_uV = vctrl_calc_ctrl_voltage(vctrl, next_uV);
ret = regulator_set_voltage_rdev(ctrl_reg->rdev,
ret = regulator_set_voltage_rdev(rdev->supply->rdev,
next_ctrl_uV,
next_ctrl_uV,
PM_SUSPEND_ON);
......@@ -134,7 +143,7 @@ static int vctrl_set_voltage(struct regulator_dev *rdev,
err:
/* Try to go back to original voltage */
regulator_set_voltage_rdev(ctrl_reg->rdev, orig_ctrl_uV, orig_ctrl_uV,
regulator_set_voltage_rdev(rdev->supply->rdev, orig_ctrl_uV, orig_ctrl_uV,
PM_SUSPEND_ON);
return ret;
......@@ -151,16 +160,18 @@ static int vctrl_set_voltage_sel(struct regulator_dev *rdev,
unsigned int selector)
{
struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
struct regulator *ctrl_reg = vctrl->ctrl_reg;
unsigned int orig_sel = vctrl->sel;
int ret;
if (!rdev->supply)
return -EPROBE_DEFER;
if (selector >= rdev->desc->n_voltages)
return -EINVAL;
if (selector >= vctrl->sel || !vctrl->ovp_threshold) {
/* voltage rising or no OVP */
ret = regulator_set_voltage_rdev(ctrl_reg->rdev,
ret = regulator_set_voltage_rdev(rdev->supply->rdev,
vctrl->vtable[selector].ctrl,
vctrl->vtable[selector].ctrl,
PM_SUSPEND_ON);
......@@ -179,7 +190,7 @@ static int vctrl_set_voltage_sel(struct regulator_dev *rdev,
else
next_sel = vctrl->vtable[vctrl->sel].ovp_min_sel;
ret = regulator_set_voltage_rdev(ctrl_reg->rdev,
ret = regulator_set_voltage_rdev(rdev->supply->rdev,
vctrl->vtable[next_sel].ctrl,
vctrl->vtable[next_sel].ctrl,
PM_SUSPEND_ON);
......@@ -202,7 +213,7 @@ static int vctrl_set_voltage_sel(struct regulator_dev *rdev,
err:
if (vctrl->sel != orig_sel) {
/* Try to go back to original voltage */
if (!regulator_set_voltage_rdev(ctrl_reg->rdev,
if (!regulator_set_voltage_rdev(rdev->supply->rdev,
vctrl->vtable[orig_sel].ctrl,
vctrl->vtable[orig_sel].ctrl,
PM_SUSPEND_ON))
......@@ -234,10 +245,6 @@ static int vctrl_parse_dt(struct platform_device *pdev,
u32 pval;
u32 vrange_ctrl[2];
vctrl->ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl");
if (IS_ERR(vctrl->ctrl_reg))
return PTR_ERR(vctrl->ctrl_reg);
ret = of_property_read_u32(np, "ovp-threshold-percent", &pval);
if (!ret) {
vctrl->ovp_threshold = pval;
......@@ -315,11 +322,11 @@ static int vctrl_cmp_ctrl_uV(const void *a, const void *b)
return at->ctrl - bt->ctrl;
}
static int vctrl_init_vtable(struct platform_device *pdev)
static int vctrl_init_vtable(struct platform_device *pdev,
struct regulator *ctrl_reg)
{
struct vctrl_data *vctrl = platform_get_drvdata(pdev);
struct regulator_desc *rdesc = &vctrl->desc;
struct regulator *ctrl_reg = vctrl->ctrl_reg;
struct vctrl_voltage_range *vrange_ctrl = &vctrl->vrange.ctrl;
int n_voltages;
int ctrl_uV;
......@@ -395,23 +402,19 @@ static int vctrl_init_vtable(struct platform_device *pdev)
static int vctrl_enable(struct regulator_dev *rdev)
{
struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
int ret = regulator_enable(vctrl->ctrl_reg);
if (!ret)
vctrl->enabled = true;
vctrl->enabled = true;
return ret;
return 0;
}
static int vctrl_disable(struct regulator_dev *rdev)
{
struct vctrl_data *vctrl = rdev_get_drvdata(rdev);
int ret = regulator_disable(vctrl->ctrl_reg);
if (!ret)
vctrl->enabled = false;
vctrl->enabled = false;
return ret;
return 0;
}
static int vctrl_is_enabled(struct regulator_dev *rdev)
......@@ -447,6 +450,7 @@ static int vctrl_probe(struct platform_device *pdev)
struct regulator_desc *rdesc;
struct regulator_config cfg = { };
struct vctrl_voltage_range *vrange_ctrl;
struct regulator *ctrl_reg;
int ctrl_uV;
int ret;
......@@ -461,15 +465,20 @@ static int vctrl_probe(struct platform_device *pdev)
if (ret)
return ret;
ctrl_reg = devm_regulator_get(&pdev->dev, "ctrl");
if (IS_ERR(ctrl_reg))
return PTR_ERR(ctrl_reg);
vrange_ctrl = &vctrl->vrange.ctrl;
rdesc = &vctrl->desc;
rdesc->name = "vctrl";
rdesc->type = REGULATOR_VOLTAGE;
rdesc->owner = THIS_MODULE;
rdesc->supply_name = "ctrl";
if ((regulator_get_linear_step(vctrl->ctrl_reg) == 1) ||
(regulator_count_voltages(vctrl->ctrl_reg) == -EINVAL)) {
if ((regulator_get_linear_step(ctrl_reg) == 1) ||
(regulator_count_voltages(ctrl_reg) == -EINVAL)) {
rdesc->continuous_voltage_range = true;
rdesc->ops = &vctrl_ops_cont;
} else {
......@@ -486,11 +495,12 @@ static int vctrl_probe(struct platform_device *pdev)
cfg.init_data = init_data;
if (!rdesc->continuous_voltage_range) {
ret = vctrl_init_vtable(pdev);
ret = vctrl_init_vtable(pdev, ctrl_reg);
if (ret)
return ret;
ctrl_uV = regulator_get_voltage_rdev(vctrl->ctrl_reg->rdev);
/* Use locked consumer API when not in regulator framework */
ctrl_uV = regulator_get_voltage(ctrl_reg);
if (ctrl_uV < 0) {
dev_err(&pdev->dev, "failed to get control voltage\n");
return ctrl_uV;
......@@ -513,6 +523,9 @@ static int vctrl_probe(struct platform_device *pdev)
}
}
/* Drop ctrl-supply here in favor of regulator core managed supply */
devm_regulator_put(ctrl_reg);
vctrl->rdev = devm_regulator_register(&pdev->dev, rdesc, &cfg);
if (IS_ERR(vctrl->rdev)) {
ret = PTR_ERR(vctrl->rdev);
......
......@@ -200,13 +200,13 @@ enum rt5033_reg {
#define RT5033_REGULATOR_BUCK_VOLTAGE_MIN 1000000U
#define RT5033_REGULATOR_BUCK_VOLTAGE_MAX 3000000U
#define RT5033_REGULATOR_BUCK_VOLTAGE_STEP 100000U
#define RT5033_REGULATOR_BUCK_VOLTAGE_STEP_NUM 21
#define RT5033_REGULATOR_BUCK_VOLTAGE_STEP_NUM 32
/* RT5033 regulator LDO output voltage uV */
#define RT5033_REGULATOR_LDO_VOLTAGE_MIN 1200000U
#define RT5033_REGULATOR_LDO_VOLTAGE_MAX 3000000U
#define RT5033_REGULATOR_LDO_VOLTAGE_STEP 100000U
#define RT5033_REGULATOR_LDO_VOLTAGE_STEP_NUM 19
#define RT5033_REGULATOR_LDO_VOLTAGE_STEP_NUM 32
/* RT5033 regulator SAFE LDO output voltage uV */
#define RT5033_REGULATOR_SAFE_LDO_VOLTAGE 4900000U
......
......@@ -222,17 +222,12 @@ void regulator_bulk_unregister_supply_alias(struct device *dev,
int devm_regulator_register_supply_alias(struct device *dev, const char *id,
struct device *alias_dev,
const char *alias_id);
void devm_regulator_unregister_supply_alias(struct device *dev,
const char *id);
int devm_regulator_bulk_register_supply_alias(struct device *dev,
const char *const *id,
struct device *alias_dev,
const char *const *alias_id,
int num_id);
void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
const char *const *id,
int num_id);
/* regulator output control and status */
int __must_check regulator_enable(struct regulator *regulator);
......@@ -408,11 +403,6 @@ static inline int devm_regulator_register_supply_alias(struct device *dev,
return 0;
}
static inline void devm_regulator_unregister_supply_alias(struct device *dev,
const char *id)
{
}
static inline int devm_regulator_bulk_register_supply_alias(struct device *dev,
const char *const *id,
struct device *alias_dev,
......@@ -422,11 +412,6 @@ static inline int devm_regulator_bulk_register_supply_alias(struct device *dev,
return 0;
}
static inline void devm_regulator_bulk_unregister_supply_alias(
struct device *dev, const char *const *id, int num_id)
{
}
static inline int regulator_enable(struct regulator *regulator)
{
return 0;
......
......@@ -337,6 +337,12 @@ enum regulator_type {
* @pull_down_val_on: Enabling value for control when using regmap
* set_pull_down
*
* @ramp_reg: Register for controlling the regulator ramp-rate.
* @ramp_mask: Bitmask for the ramp-rate control register.
* @ramp_delay_table: Table for mapping the regulator ramp-rate values. Values
* should be given in units of V/S (uV/uS). See the
* regulator_set_ramp_delay_regmap().
*
* @enable_time: Time taken for initial enable of regulator (in uS).
* @off_on_delay: guard time (in uS), before re-enabling a regulator
*
......@@ -462,7 +468,7 @@ struct regulator_err_state {
};
/**
* struct regulator_irq_data - regulator error/notification status date
* struct regulator_irq_data - regulator error/notification status data
*
* @states: Status structs for each of the associated regulators.
* @num_states: Amount of associated regulators.
......@@ -521,8 +527,8 @@ struct regulator_irq_data {
* active events as core does not clean the map data.
* REGULATOR_FAILED_RETRY can be returned to indicate that the
* status reading from IC failed. If this is repeated for
* fatal_cnt times the core will call die() callback or BUG()
* as a last resort to protect the HW.
* fatal_cnt times the core will call die() callback or power-off
* the system as a last resort to protect the HW.
* @renable: Optional callback to check status (if HW supports that) before
* re-enabling IRQ. If implemented this should clear the error
* flags so that errors fetched by regulator_get_error_flags()
......@@ -531,7 +537,8 @@ struct regulator_irq_data {
* REGULATOR_FAILED_RETRY can be returned to
* indicate that the status reading from IC failed. If this is
* repeated for 'fatal_cnt' times the core will call die()
* callback or BUG() as a last resort to protect the HW.
* callback or if die() is not populated then attempt to power-off
* the system as a last resort to protect the HW.
* Returning zero indicates that the problem in HW has been solved
* and IRQ will be re-enabled. Returning REGULATOR_ERROR_ON
* indicates the error condition is still active and keeps IRQ
......@@ -645,7 +652,6 @@ devm_regulator_register(struct device *dev,
const struct regulator_desc *regulator_desc,
const struct regulator_config *config);
void regulator_unregister(struct regulator_dev *rdev);
void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev);
int regulator_notifier_call_chain(struct regulator_dev *rdev,
unsigned long event, void *data);
......
......@@ -112,7 +112,7 @@ struct notification_limit {
* @over_voltage_limits: Limits for acting on over voltage.
* @under_voltage_limits: Limits for acting on under voltage.
* @temp_limits: Limits for acting on over temperature.
*
* @max_spread: Max possible spread between coupled regulators
* @max_uV_step: Max possible step change in voltage
* @valid_modes_mask: Mask of modes which may be configured by consumers.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment