Commit d873a0cd authored by Linus Torvalds's avatar Linus Torvalds

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

Pull regulator updates from Mark Brown:
 "Another fairly quiet release for the regulator API, some work all
  around including some core work but mostly in specialist or driver
  specific code:

   - Fix for powering off boot-on regulators

   - Enhancements to the coupled regulator support introduced in the
     last release

   - Conversion of a bunch of drivers to the fwnode API for GPIOs

   - Mode support for DA9062

   - New device support for Qualcomm PM1650, PM8004 and PM895 and
     Silergy SR83X

   - Removal of obsolete AB8505 support"

* tag 'regulator-v5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (49 commits)
  regulator: da9062: Return REGULATOR_MODE_INVALID for invalid mode
  regulator: Fix Kconfig indentation
  regulator: tps6105x: add optional devicetree support
  tps6105x: add optional devicetree support
  regulator: rn5t618: fix rc5t619 ldo10 enable
  regulator: vexpress: Use PTR_ERR_OR_ZERO() to simplify code
  dt-bindings: mfd: da9062: describe buck modes
  regulator: da9062: add of_map_mode support for bucks
  regulator: da9062: refactor buck modes into header
  regulator: stpmic1: Set a default ramp delay value
  regulator: core: Let boot-on regulators be powered off
  regulator: core: Don't try to remove device links if add failed
  regulator: ab8500: Remove SYSCLKREQ from enum ab8505_regulator_id
  regulator: ab8500: Remove AB8505 USB regulator
  regulator: fan53555: add chip id for Silergy SYR83X
  regulator: fixed: add off-on-delay
  dt-bindings: regulator: fixed: add off-on-delay-us property
  regulator: core: Allow generic coupling only for always-on regulators
  regulator: core: Release coupled_rdevs on regulator_init_coupling() error
  regulator: bd70528: Add MODULE_ALIAS to allow module auto loading
  ...
parents 3b397c7c a21da94f
......@@ -66,6 +66,9 @@ Sub-nodes:
details of individual regulator device can be found in:
Documentation/devicetree/bindings/regulator/regulator.txt
regulator-initial-mode may be specified for buck regulators using mode values
from include/dt-bindings/regulator/dlg,da9063-regulator.h.
- rtc : This node defines settings required for the Real-Time Clock associated
with the DA9062. There are currently no entries in this binding, however
compatible = "dlg,da9062-rtc" should be added if a node is created.
......@@ -96,6 +99,7 @@ Example:
regulator-max-microvolt = <1570000>;
regulator-min-microamp = <500000>;
regulator-max-microamp = <2000000>;
regulator-initial-mode = <DA9063_BUCK_MODE_SYNC>;
regulator-boot-on;
};
DA9062_LDO1: ldo1 {
......
......@@ -50,6 +50,10 @@ properties:
description: startup time in microseconds
$ref: /schemas/types.yaml#/definitions/uint32
off-on-delay-us:
description: off delay time in microseconds
$ref: /schemas/types.yaml#/definitions/uint32
enable-active-high:
description:
Polarity of GPIO is Active high. If this property is missing,
......
......@@ -28,6 +28,8 @@ Supported regulator node names:
PM8150L: smps1 - smps8, ldo1 - ldo11, bob, flash, rgb
PM8998: smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2
PMI8998: bob
PM6150: smps1 - smps5, ldo1 - ldo19
PM6150L: smps1 - smps8, ldo1 - ldo11, bob
========================
First Level Nodes - PMIC
......@@ -43,6 +45,8 @@ First Level Nodes - PMIC
"qcom,pm8150l-rpmh-regulators"
"qcom,pm8998-rpmh-regulators"
"qcom,pmi8998-rpmh-regulators"
"qcom,pm6150-rpmh-regulators"
"qcom,pm6150l-rpmh-regulators"
- qcom,pmic-id
Usage: required
......
......@@ -22,6 +22,7 @@ Regulator nodes are identified by their compatible:
"qcom,rpm-pm8841-regulators"
"qcom,rpm-pm8916-regulators"
"qcom,rpm-pm8941-regulators"
"qcom,rpm-pm8950-regulators"
"qcom,rpm-pm8994-regulators"
"qcom,rpm-pm8998-regulators"
"qcom,rpm-pma8084-regulators"
......@@ -54,6 +55,26 @@ Regulator nodes are identified by their compatible:
Definition: reference to regulator supplying the input pin, as
described in the data sheet
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
- vdd_s4-supply:
- vdd_s4-supply:
- vdd_s5-supply:
- vdd_s6-supply:
- vdd_l1_l19-supply:
- vdd_l2_l23-supply:
- vdd_l3-supply:
- vdd_l4_l5_l6_l7_l16-supply:
- vdd_l8_l11_l12_l17_l22-supply:
- vdd_l9_l10_l13_l14_l15_l18-supply:
- vdd_l20-supply:
- vdd_l21-supply:
Usage: optional (pm8950 only)
Value type: <phandle>
Definition: reference to regulator supplying the input pin, as
described in the data sheet
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
......
......@@ -4,10 +4,12 @@ Qualcomm SPMI Regulators
Usage: required
Value type: <string>
Definition: must be one of:
"qcom,pm8004-regulators"
"qcom,pm8005-regulators"
"qcom,pm8841-regulators"
"qcom,pm8916-regulators"
"qcom,pm8941-regulators"
"qcom,pm8950-regulators"
"qcom,pm8994-regulators"
"qcom,pmi8994-regulators"
"qcom,pms405-regulators"
......@@ -72,6 +74,26 @@ Qualcomm SPMI Regulators
Definition: Reference to regulator supplying the input pin, as
described in the data sheet.
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
- vdd_s4-supply:
- vdd_s4-supply:
- vdd_s5-supply:
- vdd_s6-supply:
- vdd_l1_l19-supply:
- vdd_l2_l23-supply:
- vdd_l3-supply:
- vdd_l4_l5_l6_l7_l16-supply:
- vdd_l8_l11_l12_l17_l22-supply:
- vdd_l9_l10_l13_l14_l15_l18-supply:
- vdd_l20-supply:
- vdd_l21-supply:
Usage: optional (pm8950 only)
Value type: <phandle>
Definition: reference to regulator supplying the input pin, as
described in the data sheet
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
......@@ -139,6 +161,9 @@ The regulator node houses sub-nodes for each regulator within the device. Each
sub-node is identified using the node's name, with valid values listed for each
of the PMICs below.
pm8005:
s2, s5
pm8005:
s1, s2, s3, s4
......
......@@ -38,7 +38,12 @@ properties:
type: boolean
regulator-boot-on:
description: bootloader/firmware enabled regulator
description: bootloader/firmware enabled regulator.
It's expected that this regulator was left on by the bootloader.
If the bootloader didn't leave it on then OS should turn it on
at boot but shouldn't prevent it from being turned off later.
This property is intended to only be used for regulators where
software cannot read the state of the regulator.
type: boolean
regulator-allow-bypass:
......
......@@ -185,12 +185,11 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
/**
* devm_fwnode_get_index_gpiod_from_child - get a GPIO descriptor from a
* device's child node
* devm_fwnode_gpiod_get_index - get a GPIO descriptor from a given node
* @dev: GPIO consumer
* @fwnode: firmware node containing GPIO reference
* @con_id: function within the GPIO consumer
* @index: index of the GPIO to obtain in the consumer
* @child: firmware node (child of @dev)
* @flags: GPIO initialization flags
* @label: label to attach to the requested GPIO
*
......@@ -200,35 +199,21 @@ EXPORT_SYMBOL_GPL(devm_gpiod_get_from_of_node);
* On successful request the GPIO pin is configured in accordance with
* provided @flags.
*/
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
const char *con_id, int index,
struct fwnode_handle *child,
enum gpiod_flags flags,
const char *label)
struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
struct fwnode_handle *fwnode,
const char *con_id, int index,
enum gpiod_flags flags,
const char *label)
{
char prop_name[32]; /* 32 is max size of property name */
struct gpio_desc **dr;
struct gpio_desc *desc;
unsigned int i;
dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
GFP_KERNEL);
if (!dr)
return ERR_PTR(-ENOMEM);
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s",
con_id, gpio_suffixes[i]);
else
snprintf(prop_name, sizeof(prop_name), "%s",
gpio_suffixes[i]);
desc = fwnode_get_named_gpiod(child, prop_name, index, flags,
label);
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
break;
}
desc = fwnode_gpiod_get_index(fwnode, con_id, index, flags, label);
if (IS_ERR(desc)) {
devres_free(dr);
return desc;
......@@ -239,7 +224,7 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
return desc;
}
EXPORT_SYMBOL_GPL(devm_fwnode_get_index_gpiod_from_child);
EXPORT_SYMBOL_GPL(devm_fwnode_gpiod_get_index);
/**
* devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
......
......@@ -4355,6 +4355,54 @@ static int platform_gpio_count(struct device *dev, const char *con_id)
return count;
}
/**
* fwnode_gpiod_get_index - obtain a GPIO from firmware node
* @fwnode: handle of the firmware node
* @con_id: function within the GPIO consumer
* @index: index of the GPIO to obtain for the consumer
* @flags: GPIO initialization flags
* @label: label to attach to the requested GPIO
*
* This function can be used for drivers that get their configuration
* from opaque firmware.
*
* The function properly finds the corresponding GPIO using whatever is the
* underlying firmware interface and then makes sure that the GPIO
* descriptor is requested before it is returned to the caller.
*
* Returns:
* On successful request the GPIO pin is configured in accordance with
* provided @flags.
*
* In case of error an ERR_PTR() is returned.
*/
struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
const char *con_id, int index,
enum gpiod_flags flags,
const char *label)
{
struct gpio_desc *desc;
char prop_name[32]; /* 32 is max size of property name */
unsigned int i;
for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
if (con_id)
snprintf(prop_name, sizeof(prop_name), "%s-%s",
con_id, gpio_suffixes[i]);
else
snprintf(prop_name, sizeof(prop_name), "%s",
gpio_suffixes[i]);
desc = fwnode_get_named_gpiod(fwnode, prop_name, index, flags,
label);
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT))
break;
}
return desc;
}
EXPORT_SYMBOL_GPL(fwnode_gpiod_get_index);
/**
* gpiod_count - return the number of GPIOs associated with a device / function
* or -ENOENT if no GPIO has been assigned to the requested function
......
......@@ -91,6 +91,32 @@ static int tps6105x_add_device(struct tps6105x *tps6105x,
PLATFORM_DEVID_AUTO, cell, 1, NULL, 0, NULL);
}
static struct tps6105x_platform_data *tps6105x_parse_dt(struct device *dev)
{
struct device_node *np = dev->of_node;
struct tps6105x_platform_data *pdata;
struct device_node *child;
if (!np)
return ERR_PTR(-EINVAL);
if (of_get_available_child_count(np) > 1) {
dev_err(dev, "cannot support multiple operational modes");
return ERR_PTR(-EINVAL);
}
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
pdata->mode = TPS6105X_MODE_SHUTDOWN;
for_each_available_child_of_node(np, child) {
if (child->name && !of_node_cmp(child->name, "regulator"))
pdata->mode = TPS6105X_MODE_VOLTAGE;
else if (child->name && !of_node_cmp(child->name, "led"))
pdata->mode = TPS6105X_MODE_TORCH;
}
return pdata;
}
static int tps6105x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
......@@ -99,9 +125,11 @@ static int tps6105x_probe(struct i2c_client *client,
int ret;
pdata = dev_get_platdata(&client->dev);
if (!pdata) {
dev_err(&client->dev, "missing platform data\n");
return -ENODEV;
if (!pdata)
pdata = tps6105x_parse_dt(&client->dev);
if (IS_ERR(pdata)) {
dev_err(&client->dev, "No platform data or DT found");
return PTR_ERR(pdata);
}
tps6105x = devm_kmalloc(&client->dev, sizeof(*tps6105x), GFP_KERNEL);
......
......@@ -841,10 +841,10 @@ config REGULATOR_SKY81452
will be called sky81452-regulator.
config REGULATOR_SLG51000
tristate "Dialog Semiconductor SLG51000 regulators"
depends on I2C
select REGMAP_I2C
help
tristate "Dialog Semiconductor SLG51000 regulators"
depends on I2C
select REGMAP_I2C
help
Say y here to support for the Dialog Semiconductor SLG51000.
The SLG51000 is seven compact and customizable low dropout
regulators.
......
......@@ -953,23 +953,6 @@ static struct ab8500_regulator_info
.update_val_idle = 0x82,
.update_val_normal = 0x02,
},
[AB8505_LDO_USB] = {
.desc = {
.name = "LDO-USB",
.ops = &ab8500_regulator_mode_ops,
.type = REGULATOR_VOLTAGE,
.id = AB8505_LDO_USB,
.owner = THIS_MODULE,
.n_voltages = 1,
.volt_table = fixed_3300000_voltage,
},
.update_bank = 0x03,
.update_reg = 0x82,
.update_mask = 0x03,
.update_val = 0x01,
.update_val_idle = 0x03,
.update_val_normal = 0x01,
},
[AB8505_LDO_AUDIO] = {
.desc = {
.name = "LDO-AUDIO",
......
......@@ -286,3 +286,4 @@ module_platform_driver(bd70528_regulator);
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_DESCRIPTION("BD70528 voltage regulator driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:bd70528-pmic");
......@@ -1293,3 +1293,4 @@ module_platform_driver(bd718xx_regulator);
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_DESCRIPTION("BD71837/BD71847 voltage regulator driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:bd718xx-pmic");
......@@ -1403,7 +1403,9 @@ static int set_machine_constraints(struct regulator_dev *rdev,
rdev_err(rdev, "failed to enable\n");
return ret;
}
rdev->use_count++;
if (rdev->constraints->always_on)
rdev->use_count++;
}
print_constraints(rdev);
......@@ -1844,6 +1846,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
struct regulator_dev *rdev;
struct regulator *regulator;
const char *devname = dev ? dev_name(dev) : "deviceless";
struct device_link *link;
int ret;
if (get_type >= MAX_GET_TYPE) {
......@@ -1951,7 +1954,9 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
rdev->use_count = 0;
}
device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
link = device_link_add(dev, &rdev->dev, DL_FLAG_STATELESS);
if (!IS_ERR_OR_NULL(link))
regulator->device_link = true;
return regulator;
}
......@@ -2046,7 +2051,8 @@ static void _regulator_put(struct regulator *regulator)
debugfs_remove_recursive(regulator->debugfs);
if (regulator->dev) {
device_link_remove(regulator->dev, &rdev->dev);
if (regulator->device_link)
device_link_remove(regulator->dev, &rdev->dev);
/* remove any sysfs entries */
sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
......@@ -4963,6 +4969,12 @@ static int generic_coupler_attach(struct regulator_coupler *coupler,
return -EPERM;
}
if (!rdev->constraints->always_on) {
rdev_err(rdev,
"Coupling of a non always-on regulator is unimplemented\n");
return -ENOTSUPP;
}
return 0;
}
......@@ -5198,6 +5210,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
regulator_remove_coupling(rdev);
mutex_unlock(&regulator_list_mutex);
wash:
kfree(rdev->coupling_desc.coupled_rdevs);
kfree(rdev->constraints);
mutex_lock(&regulator_list_mutex);
regulator_ena_gpio_free(rdev);
......
......@@ -16,6 +16,7 @@
#include <linux/regulator/of_regulator.h>
#include <linux/mfd/da9062/core.h>
#include <linux/mfd/da9062/registers.h>
#include <dt-bindings/regulator/dlg,da9063-regulator.h>
/* Regulator IDs */
enum {
......@@ -75,14 +76,6 @@ struct da9062_regulators {
struct da9062_regulator regulator[0];
};
/* BUCK modes */
enum {
BUCK_MODE_MANUAL, /* 0 */
BUCK_MODE_SLEEP, /* 1 */
BUCK_MODE_SYNC, /* 2 */
BUCK_MODE_AUTO /* 3 */
};
/* Regulator operations */
/* Current limits array (in uA)
......@@ -105,6 +98,20 @@ static const unsigned int da9062_buck_b_limits[] = {
2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000
};
static unsigned int da9062_map_buck_mode(unsigned int mode)
{
switch (mode) {
case DA9063_BUCK_MODE_SLEEP:
return REGULATOR_MODE_STANDBY;
case DA9063_BUCK_MODE_SYNC:
return REGULATOR_MODE_FAST;
case DA9063_BUCK_MODE_AUTO:
return REGULATOR_MODE_NORMAL;
default:
return REGULATOR_MODE_INVALID;
}
}
static int da9062_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
{
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
......@@ -112,13 +119,13 @@ static int da9062_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
switch (mode) {
case REGULATOR_MODE_FAST:
val = BUCK_MODE_SYNC;
val = DA9063_BUCK_MODE_SYNC;
break;
case REGULATOR_MODE_NORMAL:
val = BUCK_MODE_AUTO;
val = DA9063_BUCK_MODE_AUTO;
break;
case REGULATOR_MODE_STANDBY:
val = BUCK_MODE_SLEEP;
val = DA9063_BUCK_MODE_SLEEP;
break;
default:
return -EINVAL;
......@@ -136,7 +143,7 @@ static int da9062_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
static unsigned da9062_buck_get_mode(struct regulator_dev *rdev)
{
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
unsigned int val, mode = 0;
unsigned int val;
int ret;
ret = regmap_field_read(regl->mode, &val);
......@@ -145,15 +152,13 @@ static unsigned da9062_buck_get_mode(struct regulator_dev *rdev)
switch (val) {
default:
case BUCK_MODE_MANUAL:
mode = REGULATOR_MODE_FAST | REGULATOR_MODE_STANDBY;
/* Sleep flag bit decides the mode */
break;
case BUCK_MODE_SLEEP:
case DA9063_BUCK_MODE_SLEEP:
return REGULATOR_MODE_STANDBY;
case BUCK_MODE_SYNC:
case DA9063_BUCK_MODE_SYNC:
return REGULATOR_MODE_FAST;
case BUCK_MODE_AUTO:
case DA9063_BUCK_MODE_AUTO:
return REGULATOR_MODE_NORMAL;
}
......@@ -162,11 +167,9 @@ static unsigned da9062_buck_get_mode(struct regulator_dev *rdev)
return 0;
if (val)
mode &= REGULATOR_MODE_STANDBY;
return REGULATOR_MODE_STANDBY;
else
mode &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST;
return mode;
return REGULATOR_MODE_FAST;
}
/*
......@@ -282,13 +285,13 @@ static int da9062_buck_set_suspend_mode(struct regulator_dev *rdev,
switch (mode) {
case REGULATOR_MODE_FAST:
val = BUCK_MODE_SYNC;
val = DA9063_BUCK_MODE_SYNC;
break;
case REGULATOR_MODE_NORMAL:
val = BUCK_MODE_AUTO;
val = DA9063_BUCK_MODE_AUTO;
break;
case REGULATOR_MODE_STANDBY:
val = BUCK_MODE_SLEEP;
val = DA9063_BUCK_MODE_SLEEP;
break;
default:
return -EINVAL;
......@@ -371,6 +374,7 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.vsel_reg = DA9062AA_VBUCK1_A,
.desc.vsel_mask = DA9062AA_VBUCK1_A_MASK,
.desc.linear_min_sel = 0,
.desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK1_A,
__builtin_ffs((int)DA9062AA_BUCK1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
......@@ -407,6 +411,7 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.vsel_reg = DA9062AA_VBUCK3_A,
.desc.vsel_mask = DA9062AA_VBUCK3_A_MASK,
.desc.linear_min_sel = 0,
.desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK3_A,
__builtin_ffs((int)DA9062AA_BUCK3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
......@@ -443,6 +448,7 @@ static const struct da9062_regulator_info local_da9061_regulator_info[] = {
.desc.vsel_reg = DA9062AA_VBUCK4_A,
.desc.vsel_mask = DA9062AA_VBUCK4_A_MASK,
.desc.linear_min_sel = 0,
.desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK4_A,
__builtin_ffs((int)DA9062AA_BUCK4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
......@@ -615,6 +621,7 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.vsel_reg = DA9062AA_VBUCK1_A,
.desc.vsel_mask = DA9062AA_VBUCK1_A_MASK,
.desc.linear_min_sel = 0,
.desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK1_A,
__builtin_ffs((int)DA9062AA_BUCK1_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
......@@ -651,6 +658,7 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.vsel_reg = DA9062AA_VBUCK2_A,
.desc.vsel_mask = DA9062AA_VBUCK2_A_MASK,
.desc.linear_min_sel = 0,
.desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK2_A,
__builtin_ffs((int)DA9062AA_BUCK2_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
......@@ -687,6 +695,7 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.vsel_reg = DA9062AA_VBUCK3_A,
.desc.vsel_mask = DA9062AA_VBUCK3_A_MASK,
.desc.linear_min_sel = 0,
.desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK3_A,
__builtin_ffs((int)DA9062AA_BUCK3_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
......@@ -723,6 +732,7 @@ static const struct da9062_regulator_info local_da9062_regulator_info[] = {
.desc.vsel_reg = DA9062AA_VBUCK4_A,
.desc.vsel_mask = DA9062AA_VBUCK4_A_MASK,
.desc.linear_min_sel = 0,
.desc.of_map_mode = da9062_map_buck_mode,
.sleep = REG_FIELD(DA9062AA_VBUCK4_A,
__builtin_ffs((int)DA9062AA_BUCK4_SL_A_MASK) - 1,
sizeof(unsigned int) * 8 -
......@@ -942,8 +952,7 @@ static int da9062_regulator_probe(struct platform_device *pdev)
regulators->n_regulators = max_regulators;
platform_set_drvdata(pdev, regulators);
n = 0;
while (n < regulators->n_regulators) {
for (n = 0; n < regulators->n_regulators; n++) {
/* Initialise regulator structure */
regl = &regulators->regulator[n];
regl->hw = chip;
......@@ -1002,8 +1011,6 @@ static int da9062_regulator_probe(struct platform_device *pdev)
regl->desc.name);
return PTR_ERR(regl->rdev);
}
n++;
}
/* LDOs overcurrent event support */
......
......@@ -225,7 +225,7 @@ static unsigned da9063_buck_get_mode(struct regulator_dev *rdev)
{
struct da9063_regulator *regl = rdev_get_drvdata(rdev);
struct regmap_field *field;
unsigned int val, mode = 0;
unsigned int val;
int ret;
ret = regmap_field_read(regl->mode, &val);
......@@ -235,7 +235,6 @@ static unsigned da9063_buck_get_mode(struct regulator_dev *rdev)
switch (val) {
default:
case BUCK_MODE_MANUAL:
mode = REGULATOR_MODE_FAST | REGULATOR_MODE_STANDBY;
/* Sleep flag bit decides the mode */
break;
case BUCK_MODE_SLEEP:
......@@ -262,11 +261,9 @@ static unsigned da9063_buck_get_mode(struct regulator_dev *rdev)
return 0;
if (val)
mode &= REGULATOR_MODE_STANDBY;
return REGULATOR_MODE_STANDBY;
else
mode &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST;
return mode;
return REGULATOR_MODE_FAST;
}
/*
......
......@@ -283,12 +283,12 @@ static struct da9211_pdata *da9211_parse_regulators_dt(
pdata->init_data[n] = da9211_matches[i].init_data;
pdata->reg_node[n] = da9211_matches[i].of_node;
pdata->gpiod_ren[n] = devm_gpiod_get_from_of_node(dev,
da9211_matches[i].of_node,
"enable-gpios",
0,
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"da9211-enable");
pdata->gpiod_ren[n] = devm_fwnode_gpiod_get(dev,
of_fwnode_handle(pdata->reg_node[n]),
"enable",
GPIOD_OUT_HIGH |
GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"da9211-enable");
if (IS_ERR(pdata->gpiod_ren[n]))
pdata->gpiod_ren[n] = NULL;
n++;
......
......@@ -83,6 +83,7 @@ enum {
enum {
SILERGY_SYR82X = 8,
SILERGY_SYR83X = 9,
};
struct fan53555_device_info {
......@@ -302,6 +303,7 @@ static int fan53555_voltages_setup_silergy(struct fan53555_device_info *di)
/* Init voltage range and step */
switch (di->chip_id) {
case SILERGY_SYR82X:
case SILERGY_SYR83X:
di->vsel_min = 712500;
di->vsel_step = 12500;
break;
......
......@@ -123,6 +123,7 @@ of_get_fixed_voltage_config(struct device *dev,
config->enabled_at_boot = true;
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
of_property_read_u32(np, "off-on-delay-us", &config->off_on_delay);
if (of_find_property(np, "vin-supply", NULL))
config->input_supply = "vin";
......@@ -189,6 +190,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
}
drvdata->desc.enable_time = config->startup_delay;
drvdata->desc.off_on_delay = config->off_on_delay;
if (config->input_supply) {
drvdata->desc.supply_name = devm_kstrdup(&pdev->dev,
......
......@@ -36,6 +36,7 @@ struct regulator {
struct list_head list;
unsigned int always_on:1;
unsigned int bypass:1;
unsigned int device_link:1;
int uA_load;
unsigned int enable_count;
unsigned int deferred_disables;
......
......@@ -256,8 +256,9 @@ static int max77686_of_parse_cb(struct device_node *np,
case MAX77686_BUCK8:
case MAX77686_BUCK9:
case MAX77686_LDO20 ... MAX77686_LDO22:
config->ena_gpiod = gpiod_get_from_of_node(np,
"maxim,ena-gpios",
config->ena_gpiod = fwnode_gpiod_get_index(
of_fwnode_handle(np),
"maxim,ena",
0,
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"max77686-regulator");
......
......@@ -296,7 +296,10 @@ static int max8907_regulator_probe(struct platform_device *pdev)
memcpy(pmic->desc, max8907_regulators, sizeof(pmic->desc));
/* Backwards compatibility with MAX8907B; SD1 uses different voltages */
regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
ret = regmap_read(max8907->regmap_gen, MAX8907_REG_II2RR, &val);
if (ret)
return ret;
if ((val & MAX8907_II2RR_VERSION_MASK) ==
MAX8907_II2RR_VERSION_REV_B) {
pmic->desc[MAX8907_SD1].min_uV = 637500;
......@@ -333,14 +336,20 @@ static int max8907_regulator_probe(struct platform_device *pdev)
}
if (pmic->desc[i].ops == &max8907_ldo_ops) {
regmap_read(config.regmap, pmic->desc[i].enable_reg,
ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
&val);
if (ret)
return ret;
if ((val & MAX8907_MASK_LDO_SEQ) !=
MAX8907_MASK_LDO_SEQ)
pmic->desc[i].ops = &max8907_ldo_hwctl_ops;
} else if (pmic->desc[i].ops == &max8907_out5v_ops) {
regmap_read(config.regmap, pmic->desc[i].enable_reg,
ret = regmap_read(config.regmap, pmic->desc[i].enable_reg,
&val);
if (ret)
return ret;
if ((val & (MAX8907_MASK_OUT5V_VINEN |
MAX8907_MASK_OUT5V_ENSRC)) !=
MAX8907_MASK_OUT5V_ENSRC)
......
......@@ -38,15 +38,6 @@ struct pbias_reg_info {
int n_voltages;
};
struct pbias_regulator_data {
struct regulator_desc desc;
void __iomem *pbias_addr;
struct regulator_dev *dev;
struct regmap *syscon;
const struct pbias_reg_info *info;
int voltage;
};
struct pbias_of_data {
unsigned int offset;
};
......@@ -157,14 +148,13 @@ MODULE_DEVICE_TABLE(of, pbias_of_match);
static int pbias_regulator_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct pbias_regulator_data *drvdata;
struct resource *res;
struct regulator_config cfg = { };
struct regulator_desc *desc;
struct regulator_dev *rdev;
struct regmap *syscon;
const struct pbias_reg_info *info;
int ret = 0;
int count, idx, data_idx = 0;
const struct of_device_id *match;
int ret, count, idx;
const struct pbias_of_data *data;
unsigned int offset;
......@@ -173,19 +163,16 @@ static int pbias_regulator_probe(struct platform_device *pdev)
if (count < 0)
return count;
drvdata = devm_kcalloc(&pdev->dev,
count, sizeof(struct pbias_regulator_data),
GFP_KERNEL);
if (!drvdata)
desc = devm_kcalloc(&pdev->dev, count, sizeof(*desc), GFP_KERNEL);
if (!desc)
return -ENOMEM;
syscon = syscon_regmap_lookup_by_phandle(np, "syscon");
if (IS_ERR(syscon))
return PTR_ERR(syscon);
match = of_match_device(of_match_ptr(pbias_of_match), &pdev->dev);
if (match && match->data) {
data = match->data;
data = of_device_get_match_data(&pdev->dev);
if (data) {
offset = data->offset;
} else {
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
......@@ -200,7 +187,7 @@ static int pbias_regulator_probe(struct platform_device *pdev)
cfg.regmap = syscon;
cfg.dev = &pdev->dev;
for (idx = 0; idx < PBIAS_NUM_REGS && data_idx < count; idx++) {
for (idx = 0; idx < PBIAS_NUM_REGS && count; idx++) {
if (!pbias_matches[idx].init_data ||
!pbias_matches[idx].of_node)
continue;
......@@ -209,41 +196,35 @@ static int pbias_regulator_probe(struct platform_device *pdev)
if (!info)
return -ENODEV;
drvdata[data_idx].syscon = syscon;
drvdata[data_idx].info = info;
drvdata[data_idx].desc.name = info->name;
drvdata[data_idx].desc.owner = THIS_MODULE;
drvdata[data_idx].desc.type = REGULATOR_VOLTAGE;
drvdata[data_idx].desc.ops = &pbias_regulator_voltage_ops;
drvdata[data_idx].desc.volt_table = info->pbias_volt_table;
drvdata[data_idx].desc.n_voltages = info->n_voltages;
drvdata[data_idx].desc.enable_time = info->enable_time;
drvdata[data_idx].desc.vsel_reg = offset;
drvdata[data_idx].desc.vsel_mask = info->vmode;
drvdata[data_idx].desc.enable_reg = offset;
drvdata[data_idx].desc.enable_mask = info->enable_mask;
drvdata[data_idx].desc.enable_val = info->enable;
drvdata[data_idx].desc.disable_val = info->disable_val;
desc->name = info->name;
desc->owner = THIS_MODULE;
desc->type = REGULATOR_VOLTAGE;
desc->ops = &pbias_regulator_voltage_ops;
desc->volt_table = info->pbias_volt_table;
desc->n_voltages = info->n_voltages;
desc->enable_time = info->enable_time;
desc->vsel_reg = offset;
desc->vsel_mask = info->vmode;
desc->enable_reg = offset;
desc->enable_mask = info->enable_mask;
desc->enable_val = info->enable;
desc->disable_val = info->disable_val;
cfg.init_data = pbias_matches[idx].init_data;
cfg.driver_data = &drvdata[data_idx];
cfg.of_node = pbias_matches[idx].of_node;
drvdata[data_idx].dev = devm_regulator_register(&pdev->dev,
&drvdata[data_idx].desc, &cfg);
if (IS_ERR(drvdata[data_idx].dev)) {
ret = PTR_ERR(drvdata[data_idx].dev);
rdev = devm_regulator_register(&pdev->dev, desc, &cfg);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(&pdev->dev,
"Failed to register regulator: %d\n", ret);
goto err_regulator;
return ret;
}
data_idx++;
desc++;
count--;
}
platform_set_drvdata(pdev, drvdata);
err_regulator:
return ret;
return 0;
}
static struct platform_driver pbias_regulator_driver = {
......
......@@ -86,10 +86,6 @@ static const unsigned int SW1_table[] = {
#define SW2_table SW1_table
static const unsigned int SW3_table[] = {
4000000, 4500000, 5000000, 5500000,
};
struct pcap_regulator {
const u8 reg;
const u8 en;
......
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018, The Linux Foundation. All rights reserved.
// Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
#define pr_fmt(fmt) "%s: " fmt, __func__
......@@ -878,6 +878,58 @@ static const struct rpmh_vreg_init_data pm8009_vreg_data[] = {
{},
};
static const struct rpmh_vreg_init_data pm6150_vreg_data[] = {
RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"),
RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"),
RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"),
RPMH_VREG("smps4", "smp%s4", &pmic5_hfsmps510, "vdd-s4"),
RPMH_VREG("smps5", "smp%s5", &pmic5_hfsmps510, "vdd-s5"),
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo, "vdd-l1"),
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l3"),
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l2-l3"),
RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo, "vdd-l4-l7-l8"),
RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
RPMH_VREG("ldo6", "ldo%s6", &pmic5_nldo, "vdd-l6"),
RPMH_VREG("ldo7", "ldo%s7", &pmic5_nldo, "vdd-l4-l7-l8"),
RPMH_VREG("ldo8", "ldo%s8", &pmic5_nldo, "vdd-l4-l7-l8"),
RPMH_VREG("ldo9", "ldo%s9", &pmic5_nldo, "vdd-l9"),
RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo_lv, "vdd-l10-l14-l15"),
RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo_lv, "vdd-l11-l12-l13"),
RPMH_VREG("ldo12", "ldo%s12", &pmic5_pldo_lv, "vdd-l11-l12-l13"),
RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo_lv, "vdd-l11-l12-l13"),
RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo_lv, "vdd-l10-l14-l15"),
RPMH_VREG("ldo15", "ldo%s15", &pmic5_pldo_lv, "vdd-l10-l14-l15"),
RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
RPMH_VREG("ldo18", "ldo%s18", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
RPMH_VREG("ldo19", "ldo%s19", &pmic5_pldo, "vdd-l5-l16-l17-l18-l19"),
{},
};
static const struct rpmh_vreg_init_data pm6150l_vreg_data[] = {
RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps510, "vdd-s1"),
RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps510, "vdd-s2"),
RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps510, "vdd-s3"),
RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps510, "vdd-s4"),
RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps510, "vdd-s5"),
RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps510, "vdd-s6"),
RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps510, "vdd-s7"),
RPMH_VREG("smps8", "smp%s8", &pmic5_hfsmps510, "vdd-s8"),
RPMH_VREG("ldo1", "ldo%s1", &pmic5_pldo_lv, "vdd-l1-l8"),
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo, "vdd-l2-l3"),
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo, "vdd-l2-l3"),
RPMH_VREG("ldo4", "ldo%s4", &pmic5_pldo, "vdd-l4-l5-l6"),
RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l4-l5-l6"),
RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l4-l5-l6"),
RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l7-l11"),
RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo, "vdd-l1-l8"),
RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l9-l10"),
RPMH_VREG("ldo10", "ldo%s10", &pmic5_pldo, "vdd-l9-l10"),
RPMH_VREG("ldo11", "ldo%s11", &pmic5_pldo, "vdd-l7-l11"),
RPMH_VREG("bob", "bob%s1", &pmic5_bob, "vdd-bob"),
{},
};
static int rpmh_regulator_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
......@@ -940,6 +992,14 @@ static const struct of_device_id rpmh_regulator_match_table[] = {
.compatible = "qcom,pmi8998-rpmh-regulators",
.data = pmi8998_vreg_data,
},
{
.compatible = "qcom,pm6150-rpmh-regulators",
.data = pm6150_vreg_data,
},
{
.compatible = "qcom,pm6150l-rpmh-regulators",
.data = pm6150l_vreg_data,
},
{}
};
MODULE_DEVICE_TABLE(of, rpmh_regulator_match_table);
......
......@@ -338,6 +338,63 @@ static const struct regulator_desc pm8916_buck_hvo_smps = {
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8950_hfsmps = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(375000, 0, 95, 12500),
REGULATOR_LINEAR_RANGE(1550000, 96, 127, 25000),
},
.n_linear_ranges = 2,
.n_voltages = 128,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8950_ftsmps2p5 = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(80000, 0, 255, 5000),
REGULATOR_LINEAR_RANGE(160000, 256, 460, 10000),
},
.n_linear_ranges = 2,
.n_voltages = 461,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8950_ult_nldo = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(375000, 0, 202, 12500),
},
.n_linear_ranges = 1,
.n_voltages = 203,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8950_ult_pldo = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(1750000, 0, 127, 12500),
},
.n_linear_ranges = 1,
.n_voltages = 128,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8950_pldo_lv = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(1500000, 0, 16, 25000),
},
.n_linear_ranges = 1,
.n_voltages = 17,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8950_pldo = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(975000, 0, 164, 12500),
},
.n_linear_ranges = 1,
.n_voltages = 165,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8994_hfsmps = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE( 375000, 0, 95, 12500),
......@@ -638,6 +695,40 @@ static const struct rpm_regulator_data rpm_pma8084_regulators[] = {
{}
};
static const struct rpm_regulator_data rpm_pm8950_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pm8950_hfsmps, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8950_hfsmps, "vdd_s2" },
{ "s3", QCOM_SMD_RPM_SMPA, 3, &pm8950_hfsmps, "vdd_s3" },
{ "s4", QCOM_SMD_RPM_SMPA, 4, &pm8950_hfsmps, "vdd_s4" },
{ "s5", QCOM_SMD_RPM_SMPA, 5, &pm8950_ftsmps2p5, "vdd_s5" },
{ "s6", QCOM_SMD_RPM_SMPA, 6, &pm8950_hfsmps, "vdd_s6" },
{ "l1", QCOM_SMD_RPM_LDOA, 1, &pm8950_ult_nldo, "vdd_l1_l19" },
{ "l2", QCOM_SMD_RPM_LDOA, 2, &pm8950_ult_nldo, "vdd_l2_l23" },
{ "l3", QCOM_SMD_RPM_LDOA, 3, &pm8950_ult_nldo, "vdd_l3" },
{ "l4", QCOM_SMD_RPM_LDOA, 4, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16" },
{ "l5", QCOM_SMD_RPM_LDOA, 5, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
{ "l6", QCOM_SMD_RPM_LDOA, 6, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
{ "l7", QCOM_SMD_RPM_LDOA, 7, &pm8950_pldo_lv, "vdd_l4_l5_l6_l7_l16" },
{ "l8", QCOM_SMD_RPM_LDOA, 8, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22" },
{ "l9", QCOM_SMD_RPM_LDOA, 9, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18" },
{ "l10", QCOM_SMD_RPM_LDOA, 10, &pm8950_ult_nldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l11", QCOM_SMD_RPM_LDOA, 11, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
{ "l12", QCOM_SMD_RPM_LDOA, 12, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
{ "l13", QCOM_SMD_RPM_LDOA, 13, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l14", QCOM_SMD_RPM_LDOA, 14, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l15", QCOM_SMD_RPM_LDOA, 15, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l16", QCOM_SMD_RPM_LDOA, 16, &pm8950_ult_pldo, "vdd_l4_l5_l6_l7_l16"},
{ "l17", QCOM_SMD_RPM_LDOA, 17, &pm8950_ult_pldo, "vdd_l8_l11_l12_l17_l22"},
{ "l18", QCOM_SMD_RPM_LDOA, 18, &pm8950_ult_pldo, "vdd_l9_l10_l13_l14_l15_l18"},
{ "l19", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l1_l19"},
{ "l20", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l20"},
{ "l21", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l21"},
{ "l22", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l8_l11_l12_l17_l22"},
{ "l23", QCOM_SMD_RPM_LDOA, 18, &pm8950_pldo, "vdd_l2_l23"},
{}
};
static const struct rpm_regulator_data rpm_pm8994_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pm8994_ftsmps, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8994_ftsmps, "vdd_s2" },
......@@ -767,6 +858,7 @@ static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators },
{ .compatible = "qcom,rpm-pm8916-regulators", .data = &rpm_pm8916_regulators },
{ .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators },
{ .compatible = "qcom,rpm-pm8950-regulators", .data = &rpm_pm8950_regulators },
{ .compatible = "qcom,rpm-pm8994-regulators", .data = &rpm_pm8994_regulators },
{ .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators },
{ .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators },
......
......@@ -1869,6 +1869,39 @@ static const struct spmi_regulator_data pm8916_regulators[] = {
{ }
};
static const struct spmi_regulator_data pm8950_regulators[] = {
{ "s1", 0x1400, "vdd_s1", },
{ "s2", 0x1700, "vdd_s2", },
{ "s3", 0x1a00, "vdd_s3", },
{ "s4", 0x1d00, "vdd_s4", },
{ "s5", 0x2000, "vdd_s5", },
{ "s6", 0x2300, "vdd_s6", },
{ "l1", 0x4000, "vdd_l1_l19", },
{ "l2", 0x4100, "vdd_l2_l23", },
{ "l3", 0x4200, "vdd_l3", },
{ "l4", 0x4300, "vdd_l4_l5_l6_l7_l16", },
{ "l5", 0x4400, "vdd_l4_l5_l6_l7_l16", },
{ "l6", 0x4500, "vdd_l4_l5_l6_l7_l16", },
{ "l7", 0x4600, "vdd_l4_l5_l6_l7_l16", },
{ "l8", 0x4700, "vdd_l8_l11_l12_l17_l22", },
{ "l9", 0x4800, "vdd_l9_l10_l13_l14_l15_l18", },
{ "l10", 0x4900, "vdd_l9_l10_l13_l14_l15_l18", },
{ "l11", 0x4a00, "vdd_l8_l11_l12_l17_l22", },
{ "l12", 0x4b00, "vdd_l8_l11_l12_l17_l22", },
{ "l13", 0x4c00, "vdd_l9_l10_l13_l14_l15_l18", },
{ "l14", 0x4d00, "vdd_l9_l10_l13_l14_l15_l18", },
{ "l15", 0x4e00, "vdd_l9_l10_l13_l14_l15_l18", },
{ "l16", 0x4f00, "vdd_l4_l5_l6_l7_l16", },
{ "l17", 0x5000, "vdd_l8_l11_l12_l17_l22", },
{ "l18", 0x5100, "vdd_l9_l10_l13_l14_l15_l18", },
{ "l19", 0x5200, "vdd_l1_l19", },
{ "l20", 0x5300, "vdd_l20", },
{ "l21", 0x5400, "vdd_l21", },
{ "l22", 0x5500, "vdd_l8_l11_l12_l17_l22", },
{ "l23", 0x5600, "vdd_l2_l23", },
{ }
};
static const struct spmi_regulator_data pm8994_regulators[] = {
{ "s1", 0x1400, "vdd_s1", },
{ "s2", 0x1700, "vdd_s2", },
......@@ -1927,6 +1960,12 @@ static const struct spmi_regulator_data pmi8994_regulators[] = {
{ }
};
static const struct spmi_regulator_data pm8004_regulators[] = {
{ "s2", 0x1700, "vdd_s2", },
{ "s5", 0x2000, "vdd_s5", },
{ }
};
static const struct spmi_regulator_data pm8005_regulators[] = {
{ "s1", 0x1400, "vdd_s1", },
{ "s2", 0x1700, "vdd_s2", },
......@@ -1941,10 +1980,12 @@ static const struct spmi_regulator_data pms405_regulators[] = {
};
static const struct of_device_id qcom_spmi_regulator_match[] = {
{ .compatible = "qcom,pm8004-regulators", .data = &pm8004_regulators },
{ .compatible = "qcom,pm8005-regulators", .data = &pm8005_regulators },
{ .compatible = "qcom,pm8841-regulators", .data = &pm8841_regulators },
{ .compatible = "qcom,pm8916-regulators", .data = &pm8916_regulators },
{ .compatible = "qcom,pm8941-regulators", .data = &pm8941_regulators },
{ .compatible = "qcom,pm8950-regulators", .data = &pm8950_regulators },
{ .compatible = "qcom,pm8994-regulators", .data = &pm8994_regulators },
{ .compatible = "qcom,pmi8994-regulators", .data = &pmi8994_regulators },
{ .compatible = "qcom,pms405-regulators", .data = &pms405_regulators },
......
......@@ -388,7 +388,7 @@ static int rk817_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
break;
default:
dev_warn(&rdev->dev,
"%s ramp_delay: %d not supported, setting 10000\n",
"%s ramp_delay: %d not supported, setting 25000\n",
rdev->desc->name, ramp_delay);
}
......@@ -411,21 +411,6 @@ static int rk808_set_suspend_voltage(struct regulator_dev *rdev, int uv)
sel);
}
static int rk817_set_suspend_voltage(struct regulator_dev *rdev, int uv)
{
unsigned int reg;
int sel = regulator_map_voltage_linear(rdev, uv, uv);
/* only ldo1~ldo9 */
if (sel < 0)
return -EINVAL;
reg = rdev->desc->vsel_reg + RK808_SLP_REG_OFFSET;
return regmap_update_bits(rdev->regmap, reg,
rdev->desc->vsel_mask,
sel);
}
static int rk808_set_suspend_voltage_range(struct regulator_dev *rdev, int uv)
{
unsigned int reg;
......@@ -686,7 +671,7 @@ static const struct regulator_linear_range rk805_buck_1_2_voltage_ranges[] = {
REGULATOR_LINEAR_RANGE(2300000, 63, 63, 0),
};
static struct regulator_ops rk809_buck5_ops_range = {
static const struct regulator_ops rk809_buck5_ops_range = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
......@@ -700,7 +685,7 @@ static struct regulator_ops rk809_buck5_ops_range = {
.set_suspend_disable = rk817_set_suspend_disable,
};
static struct regulator_ops rk817_reg_ops = {
static const struct regulator_ops rk817_reg_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
......@@ -708,12 +693,12 @@ static struct regulator_ops rk817_reg_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
.set_suspend_voltage = rk817_set_suspend_voltage,
.set_suspend_voltage = rk808_set_suspend_voltage,
.set_suspend_enable = rk817_set_suspend_enable,
.set_suspend_disable = rk817_set_suspend_disable,
};
static struct regulator_ops rk817_boost_ops = {
static const struct regulator_ops rk817_boost_ops = {
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
......@@ -725,7 +710,7 @@ static struct regulator_ops rk817_boost_ops = {
.set_suspend_disable = rk817_set_suspend_disable,
};
static struct regulator_ops rk817_buck_ops_range = {
static const struct regulator_ops rk817_buck_ops_range = {
.list_voltage = regulator_list_voltage_linear_range,
.map_voltage = regulator_map_voltage_linear_range,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
......@@ -743,7 +728,7 @@ static struct regulator_ops rk817_buck_ops_range = {
.set_suspend_disable = rk817_set_suspend_disable,
};
static struct regulator_ops rk817_switch_ops = {
static const struct regulator_ops rk817_switch_ops = {
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = rk8xx_is_enabled_wmsk_regmap,
......
......@@ -90,7 +90,7 @@ static const struct regulator_desc rc5t619_regulators[] = {
REG(LDO7, LDOEN1, BIT(6), LDO7DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO8, LDOEN1, BIT(7), LDO8DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO9, LDOEN2, BIT(0), LDO9DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO10, LDOEN2, BIT(0), LDO10DAC, 0x7f, 900000, 3500000, 25000),
REG(LDO10, LDOEN2, BIT(1), LDO10DAC, 0x7f, 900000, 3500000, 25000),
/* LDO RTC */
REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1700000, 3500000, 25000),
REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
......
......@@ -844,10 +844,9 @@ static void s2mps14_pmic_dt_parse_ext_control_gpio(struct platform_device *pdev,
if (!rdata[reg].init_data || !rdata[reg].of_node)
continue;
gpio[reg] = devm_gpiod_get_from_of_node(&pdev->dev,
rdata[reg].of_node,
"samsung,ext-control-gpios",
0,
gpio[reg] = devm_fwnode_gpiod_get(&pdev->dev,
of_fwnode_handle(rdata[reg].of_node),
"samsung,ext-control",
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"s2mps11-regulator");
if (PTR_ERR(gpio[reg]) == -ENOENT)
......
......@@ -567,11 +567,10 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
continue;
}
rdata->ext_control_gpiod = devm_gpiod_get_from_of_node(
rdata->ext_control_gpiod = devm_fwnode_gpiod_get(
&pdev->dev,
reg_np,
"s5m8767,pmic-ext-control-gpios",
0,
of_fwnode_handle(reg_np),
"s5m8767,pmic-ext-control",
GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"s5m8767");
if (PTR_ERR(rdata->ext_control_gpiod) == -ENOENT)
......
......@@ -198,17 +198,14 @@ static int slg51000_of_parse_cb(struct device_node *np,
const struct regulator_desc *desc,
struct regulator_config *config)
{
struct slg51000 *chip = config->driver_data;
struct gpio_desc *ena_gpiod;
enum gpiod_flags gflags = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_NONEXCLUSIVE;
ena_gpiod = devm_gpiod_get_from_of_node(chip->dev, np,
"enable-gpios", 0,
gflags, "gpio-en-ldo");
if (!IS_ERR(ena_gpiod)) {
ena_gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), "enable", 0,
GPIOD_OUT_LOW |
GPIOD_FLAGS_BIT_NONEXCLUSIVE,
"gpio-en-ldo");
if (!IS_ERR(ena_gpiod))
config->ena_gpiod = ena_gpiod;
devm_gpiod_unhinge(chip->dev, config->ena_gpiod);
}
return 0;
}
......
......@@ -181,7 +181,6 @@ static const struct regulator_desc stm32_vrefbuf_regu = {
static int stm32_vrefbuf_probe(struct platform_device *pdev)
{
struct resource *res;
struct stm32_vrefbuf *priv;
struct regulator_config config = { };
struct regulator_dev *rdev;
......@@ -192,8 +191,7 @@ static int stm32_vrefbuf_probe(struct platform_device *pdev)
return -ENOMEM;
priv->dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(&pdev->dev, res);
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
......
......@@ -54,6 +54,8 @@ enum {
/* Enable time worst case is 5000mV/(2250uV/uS) */
#define PMIC_ENABLE_TIME_US 2200
/* Ramp delay worst case is (2250uV/uS) */
#define PMIC_RAMP_DELAY 2200
static const struct regulator_linear_range buck1_ranges[] = {
REGULATOR_LINEAR_RANGE(725000, 0, 4, 0),
......@@ -208,6 +210,7 @@ static const struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
.ramp_delay = PMIC_RAMP_DELAY, \
.supply_name = #base, \
}
......@@ -227,6 +230,7 @@ static const struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
.ramp_delay = PMIC_RAMP_DELAY, \
.bypass_reg = LDO3_ACTIVE_CR, \
.bypass_mask = LDO_BYPASS_MASK, \
.bypass_val_on = LDO_BYPASS_MASK, \
......@@ -248,6 +252,7 @@ static const struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
.ramp_delay = PMIC_RAMP_DELAY, \
.supply_name = #base, \
}
......@@ -267,6 +272,7 @@ static const struct regulator_ops stpmic1_switch_regul_ops = {
.enable_val = 1, \
.disable_val = 0, \
.enable_time = PMIC_ENABLE_TIME_US, \
.ramp_delay = PMIC_RAMP_DELAY, \
.of_map_mode = stpmic1_map_mode, \
.pull_down_reg = ids##_PULL_DOWN_REG, \
.pull_down_mask = ids##_PULL_DOWN_MASK, \
......
......@@ -37,6 +37,7 @@ static struct regulator_ops tps6105x_regulator_ops = {
static const struct regulator_desc tps6105x_regulator_desc = {
.name = "tps6105x-boost",
.of_match = of_match_ptr("regulator"),
.ops = &tps6105x_regulator_ops,
.type = REGULATOR_VOLTAGE,
.id = 0,
......@@ -71,6 +72,7 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
config.dev = &tps6105x->client->dev;
config.init_data = pdata->regulator_data;
config.driver_data = tps6105x;
config.of_node = pdev->dev.parent->of_node;
config.regmap = tps6105x->regmap;
/* Register regulator with framework */
......
......@@ -346,16 +346,20 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
for (idx = 0; idx < ARRAY_SIZE(tps65090_matches); idx++) {
struct regulator_init_data *ri_data;
struct tps65090_regulator_plat_data *rpdata;
struct device_node *np;
rpdata = &reg_pdata[idx];
ri_data = tps65090_matches[idx].init_data;
if (!ri_data || !tps65090_matches[idx].of_node)
if (!ri_data)
continue;
np = tps65090_matches[idx].of_node;
if (!np)
continue;
rpdata->reg_init_data = ri_data;
rpdata->enable_ext_control = of_property_read_bool(
tps65090_matches[idx].of_node,
"ti,enable-ext-control");
rpdata->enable_ext_control = of_property_read_bool(np,
"ti,enable-ext-control");
if (rpdata->enable_ext_control) {
enum gpiod_flags gflags;
......@@ -366,11 +370,12 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
gflags = GPIOD_OUT_LOW;
gflags |= GPIOD_FLAGS_BIT_NONEXCLUSIVE;
rpdata->gpiod = devm_gpiod_get_from_of_node(&pdev->dev,
tps65090_matches[idx].of_node,
"dcdc-ext-control-gpios", 0,
gflags,
"tps65090");
rpdata->gpiod = devm_fwnode_gpiod_get(
&pdev->dev,
of_fwnode_handle(np),
"dcdc-ext-control",
gflags,
"tps65090");
if (PTR_ERR(rpdata->gpiod) == -ENOENT) {
dev_err(&pdev->dev,
"could not find DCDC external control GPIO\n");
......@@ -379,8 +384,7 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
return ERR_CAST(rpdata->gpiod);
}
if (of_property_read_u32(tps65090_matches[idx].of_node,
"ti,overcurrent-wait",
if (of_property_read_u32(np, "ti,overcurrent-wait",
&rpdata->overcurrent_wait) == 0)
rpdata->overcurrent_wait_valid = true;
......
......@@ -136,9 +136,10 @@ static int tps65132_of_parse_cb(struct device_node *np,
struct tps65132_reg_pdata *rpdata = &tps->reg_pdata[desc->id];
int ret;
rpdata->en_gpiod = devm_fwnode_get_index_gpiod_from_child(tps->dev,
"enable", 0, &np->fwnode, 0, "enable");
if (IS_ERR_OR_NULL(rpdata->en_gpiod)) {
rpdata->en_gpiod = devm_fwnode_gpiod_get(tps->dev, of_fwnode_handle(np),
"enable", GPIOD_ASIS,
"enable");
if (IS_ERR(rpdata->en_gpiod)) {
ret = PTR_ERR(rpdata->en_gpiod);
/* Ignore the error other than probe defer */
......@@ -147,10 +148,12 @@ static int tps65132_of_parse_cb(struct device_node *np,
return 0;
}
rpdata->act_dis_gpiod = devm_fwnode_get_index_gpiod_from_child(
tps->dev, "active-discharge", 0,
&np->fwnode, 0, "active-discharge");
if (IS_ERR_OR_NULL(rpdata->act_dis_gpiod)) {
rpdata->act_dis_gpiod = devm_fwnode_gpiod_get(tps->dev,
of_fwnode_handle(np),
"active-discharge",
GPIOD_ASIS,
"active-discharge");
if (IS_ERR(rpdata->act_dis_gpiod)) {
ret = PTR_ERR(rpdata->act_dis_gpiod);
/* Ignore the error other than probe defer */
......
......@@ -45,7 +45,6 @@ static int uniphier_regulator_probe(struct platform_device *pdev)
struct regulator_config config = { };
struct regulator_dev *rdev;
struct regmap *regmap;
struct resource *res;
void __iomem *base;
const char *name;
int i, ret, nr;
......@@ -58,8 +57,7 @@ static int uniphier_regulator_probe(struct platform_device *pdev)
if (WARN_ON(!priv->data))
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(dev, res);
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return PTR_ERR(base);
......
......@@ -75,10 +75,7 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
config.of_node = pdev->dev.of_node;
rdev = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
return 0;
return PTR_ERR_OR_ZERO(rdev);
}
static const struct of_device_id vexpress_regulator_of_match[] = {
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _DT_BINDINGS_REGULATOR_DLG_DA9063_H
#define _DT_BINDINGS_REGULATOR_DLG_DA9063_H
/*
* These buck mode constants may be used to specify values in device tree
* properties (e.g. regulator-initial-mode).
* A description of the following modes is in the manufacturers datasheet.
*/
#define DA9063_BUCK_MODE_SLEEP 1
#define DA9063_BUCK_MODE_SYNC 2
#define DA9063_BUCK_MODE_AUTO 3
#endif
......@@ -176,11 +176,15 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
const char *propname, int index,
enum gpiod_flags dflags,
const char *label);
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
const char *con_id, int index,
struct fwnode_handle *child,
enum gpiod_flags flags,
const char *label);
struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
const char *con_id, int index,
enum gpiod_flags flags,
const char *label);
struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
struct fwnode_handle *child,
const char *con_id, int index,
enum gpiod_flags flags,
const char *label);
#else /* CONFIG_GPIOLIB */
......@@ -531,6 +535,38 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
return ERR_PTR(-ENOSYS);
}
static inline
struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode,
const char *con_id, int index,
enum gpiod_flags flags,
const char *label)
{
return ERR_PTR(-ENOSYS);
}
static inline
struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev,
struct fwnode_handle *fwnode,
const char *con_id, int index,
enum gpiod_flags flags,
const char *label)
{
return ERR_PTR(-ENOSYS);
}
#endif /* CONFIG_GPIOLIB */
static inline
struct gpio_desc *devm_fwnode_gpiod_get(struct device *dev,
struct fwnode_handle *fwnode,
const char *con_id,
enum gpiod_flags flags,
const char *label)
{
return devm_fwnode_gpiod_get_index(dev, fwnode, con_id, 0,
flags, label);
}
static inline
struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
const char *con_id, int index,
......@@ -538,11 +574,10 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
enum gpiod_flags flags,
const char *label)
{
return ERR_PTR(-ENOSYS);
return devm_fwnode_gpiod_get_index(dev, child, con_id, index,
flags, label);
}
#endif /* CONFIG_GPIOLIB */
static inline
struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
const char *con_id,
......@@ -550,8 +585,7 @@ struct gpio_desc *devm_fwnode_get_gpiod_from_child(struct device *dev,
enum gpiod_flags flags,
const char *label)
{
return devm_fwnode_get_index_gpiod_from_child(dev, con_id, 0, child,
flags, label);
return devm_fwnode_gpiod_get_index(dev, child, con_id, 0, flags, label);
}
#if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_OF_GPIO)
......
......@@ -37,14 +37,11 @@ enum ab8505_regulator_id {
AB8505_LDO_AUX6,
AB8505_LDO_INTCORE,
AB8505_LDO_ADC,
AB8505_LDO_USB,
AB8505_LDO_AUDIO,
AB8505_LDO_ANAMIC1,
AB8505_LDO_ANAMIC2,
AB8505_LDO_AUX8,
AB8505_LDO_ANA,
AB8505_SYSCLKREQ_2,
AB8505_SYSCLKREQ_4,
AB8505_NUM_REGULATORS,
};
......
......@@ -36,6 +36,7 @@ struct fixed_voltage_config {
const char *input_supply;
int microvolts;
unsigned startup_delay;
unsigned int off_on_delay;
unsigned enabled_at_boot:1;
struct regulator_init_data *init_data;
};
......
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