Commit 6dfae59d authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branch 'regulator/for-next' into tmp

parents 1ba0b52e 24bd2afd
Monolithic Power Systems MP8867/MP8869 voltage regulator
Required properties:
- compatible: Must be one of the following.
"mps,mp8867"
"mps,mp8869"
- reg: I2C slave address.
- enable-gpios: enable gpios.
- mps,fb-voltage-divider: An array of two integers containing the resistor
values R1 and R2 of the feedback voltage divider in kilo ohms.
Any property defined as part of the core regulator binding, defined in
./regulator.txt, can also be used.
Example:
vcpu: regulator@62 {
compatible = "mps,mp8869";
regulator-name = "vcpu";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <850000>;
regulator-always-on;
regulator-boot-on;
enable-gpios = <&porta 1 GPIO_ACTIVE_LOW>;
mps,fb-voltage-divider = <80 240>;
reg = <0x62>;
};
...@@ -26,6 +26,7 @@ Regulator nodes are identified by their compatible: ...@@ -26,6 +26,7 @@ Regulator nodes are identified by their compatible:
"qcom,rpm-pm8994-regulators" "qcom,rpm-pm8994-regulators"
"qcom,rpm-pm8998-regulators" "qcom,rpm-pm8998-regulators"
"qcom,rpm-pma8084-regulators" "qcom,rpm-pma8084-regulators"
"qcom,rpm-pmi8994-regulators"
"qcom,rpm-pmi8998-regulators" "qcom,rpm-pmi8998-regulators"
"qcom,rpm-pms405-regulators" "qcom,rpm-pms405-regulators"
...@@ -143,6 +144,15 @@ Regulator nodes are identified by their compatible: ...@@ -143,6 +144,15 @@ Regulator nodes are identified by their compatible:
Definition: reference to regulator supplying the input pin, as Definition: reference to regulator supplying the input pin, as
described in the data sheet described in the data sheet
- vdd_s1-supply:
- vdd_s2-supply:
- vdd_s3-supply:
- vdd_bst_byp-supply:
Usage: optional (pmi8994 only)
Value type: <phandle>
Definition: reference to regulator supplying the input pin, as
described in the data sheet
- vdd_s1-supply: - vdd_s1-supply:
- vdd_s2-supply: - vdd_s2-supply:
- vdd_s3-supply: - vdd_s3-supply:
...@@ -259,6 +269,9 @@ pma8084: ...@@ -259,6 +269,9 @@ pma8084:
l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20, l6, l7, l8, l9, l10, l11, l12, l13, l14, l15, l16, l17, l18, l19, l20,
l21, l22, l23, l24, l25, l26, l27, lvs1, lvs2, lvs3, lvs4, 5vs1 l21, l22, l23, l24, l25, l26, l27, lvs1, lvs2, lvs3, lvs4, 5vs1
pmi8994:
s1, s2, s3, boost-bypass
pmi8998: pmi8998:
bob bob
......
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
$id: http://devicetree.org/schemas/regulator/vqmmc-ipq4019-regulator.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm IPQ4019 VQMMC SD LDO regulator
maintainers:
- Robert Marko <robert.marko@sartura.hr>
description: |
Qualcomm IPQ4019 SoC-s feature a built a build SD/EMMC controller,
in order to support both 1.8 and 3V I/O voltage levels an LDO
controller is also embedded.
allOf:
- $ref: "regulator.yaml#"
properties:
compatible:
const: qcom,vqmmc-ipq4019-regulator
reg:
maxItems: 1
required:
- compatible
- reg
examples:
- |
regulator@1948000 {
compatible = "qcom,vqmmc-ipq4019-regulator";
reg = <0x01948000 0x4>;
regulator-name = "vqmmc";
regulator-min-microvolt = <1500000>;
regulator-max-microvolt = <3000000>;
regulator-always-on;
status = "disabled";
};
...
...@@ -635,6 +635,13 @@ config REGULATOR_MP8859 ...@@ -635,6 +635,13 @@ config REGULATOR_MP8859
Say M here if you want to include support for the regulator as a Say M here if you want to include support for the regulator as a
module. The module will be named "mp8859". module. The module will be named "mp8859".
config REGULATOR_MP886X
tristate "MPS MP8869 regulator driver"
depends on I2C && (OF || COMPILE_TEST)
select REGMAP_I2C
help
This driver supports the MP8869 voltage regulator.
config REGULATOR_MPQ7920 config REGULATOR_MPQ7920
tristate "Monolithic MPQ7920 PMIC" tristate "Monolithic MPQ7920 PMIC"
depends on I2C && OF depends on I2C && OF
......
...@@ -80,6 +80,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o ...@@ -80,6 +80,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o obj-$(CONFIG_REGULATOR_MCP16502) += mcp16502.o
obj-$(CONFIG_REGULATOR_MP5416) += mp5416.o obj-$(CONFIG_REGULATOR_MP5416) += mp5416.o
obj-$(CONFIG_REGULATOR_MP8859) += mp8859.o obj-$(CONFIG_REGULATOR_MP8859) += mp8859.o
obj-$(CONFIG_REGULATOR_MP886X) += mp886x.o
obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o obj-$(CONFIG_REGULATOR_MPQ7920) += mpq7920.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
......
...@@ -1849,7 +1849,6 @@ struct regulator *_regulator_get(struct device *dev, const char *id, ...@@ -1849,7 +1849,6 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
{ {
struct regulator_dev *rdev; struct regulator_dev *rdev;
struct regulator *regulator; struct regulator *regulator;
const char *devname = dev ? dev_name(dev) : "deviceless";
struct device_link *link; struct device_link *link;
int ret; int ret;
...@@ -1887,9 +1886,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id, ...@@ -1887,9 +1886,7 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
* enabled, even if it isn't hooked up, and just * enabled, even if it isn't hooked up, and just
* provide a dummy. * provide a dummy.
*/ */
dev_warn(dev, dev_warn(dev, "supply %s not found, using dummy regulator\n", id);
"%s supply %s not found, using dummy regulator\n",
devname, id);
rdev = dummy_regulator_rdev; rdev = dummy_regulator_rdev;
get_device(&rdev->dev); get_device(&rdev->dev);
break; break;
......
...@@ -100,6 +100,7 @@ struct da9063_regulator_info { ...@@ -100,6 +100,7 @@ struct da9063_regulator_info {
.desc.vsel_mask = DA9063_V##regl_name##_MASK, \ .desc.vsel_mask = DA9063_V##regl_name##_MASK, \
.desc.linear_min_sel = DA9063_V##regl_name##_BIAS, \ .desc.linear_min_sel = DA9063_V##regl_name##_BIAS, \
.sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_LDO_SL), \ .sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_LDO_SL), \
.suspend = BFIELD(DA9063_REG_##regl_name##_CONT, DA9063_LDO_CONF), \
.suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_LDO_SL), \ .suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_LDO_SL), \
.suspend_vsel_reg = DA9063_REG_V##regl_name##_B .suspend_vsel_reg = DA9063_REG_V##regl_name##_B
...@@ -124,6 +125,7 @@ struct da9063_regulator_info { ...@@ -124,6 +125,7 @@ struct da9063_regulator_info {
.desc.vsel_mask = DA9063_VBUCK_MASK, \ .desc.vsel_mask = DA9063_VBUCK_MASK, \
.desc.linear_min_sel = DA9063_VBUCK_BIAS, \ .desc.linear_min_sel = DA9063_VBUCK_BIAS, \
.sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_BUCK_SL), \ .sleep = BFIELD(DA9063_REG_V##regl_name##_A, DA9063_BUCK_SL), \
.suspend = BFIELD(DA9063_REG_##regl_name##_CONT, DA9063_BUCK_CONF), \
.suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_BUCK_SL), \ .suspend_sleep = BFIELD(DA9063_REG_V##regl_name##_B, DA9063_BUCK_SL), \
.suspend_vsel_reg = DA9063_REG_V##regl_name##_B, \ .suspend_vsel_reg = DA9063_REG_V##regl_name##_B, \
.mode = BFIELD(DA9063_REG_##regl_name##_CFG, DA9063_BUCK_MODE_MASK) .mode = BFIELD(DA9063_REG_##regl_name##_CFG, DA9063_BUCK_MODE_MASK)
...@@ -232,7 +234,6 @@ static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) ...@@ -232,7 +234,6 @@ static int da9063_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
static unsigned int da9063_buck_get_mode(struct regulator_dev *rdev) static unsigned int da9063_buck_get_mode(struct regulator_dev *rdev)
{ {
struct da9063_regulator *regl = rdev_get_drvdata(rdev); struct da9063_regulator *regl = rdev_get_drvdata(rdev);
struct regmap_field *field;
unsigned int val; unsigned int val;
int ret; int ret;
...@@ -253,18 +254,7 @@ static unsigned int da9063_buck_get_mode(struct regulator_dev *rdev) ...@@ -253,18 +254,7 @@ static unsigned int da9063_buck_get_mode(struct regulator_dev *rdev)
return REGULATOR_MODE_NORMAL; return REGULATOR_MODE_NORMAL;
} }
/* Detect current regulator state */ ret = regmap_field_read(regl->sleep, &val);
ret = regmap_field_read(regl->suspend, &val);
if (ret < 0)
return 0;
/* Read regulator mode from proper register, depending on state */
if (val)
field = regl->suspend_sleep;
else
field = regl->sleep;
ret = regmap_field_read(field, &val);
if (ret < 0) if (ret < 0)
return 0; return 0;
...@@ -301,21 +291,9 @@ static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode) ...@@ -301,21 +291,9 @@ static int da9063_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
static unsigned int da9063_ldo_get_mode(struct regulator_dev *rdev) static unsigned int da9063_ldo_get_mode(struct regulator_dev *rdev)
{ {
struct da9063_regulator *regl = rdev_get_drvdata(rdev); struct da9063_regulator *regl = rdev_get_drvdata(rdev);
struct regmap_field *field;
int ret, val; int ret, val;
/* Detect current regulator state */ ret = regmap_field_read(regl->sleep, &val);
ret = regmap_field_read(regl->suspend, &val);
if (ret < 0)
return 0;
/* Read regulator mode from proper register, depending on state */
if (val)
field = regl->suspend_sleep;
else
field = regl->sleep;
ret = regmap_field_read(field, &val);
if (ret < 0) if (ret < 0)
return 0; return 0;
...@@ -475,42 +453,36 @@ static const struct da9063_regulator_info da9063_regulator_info[] = { ...@@ -475,42 +453,36 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
da9063_buck_a_limits, da9063_buck_a_limits,
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK), DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BCORE1), DA9063_BUCK_COMMON_FIELDS(BCORE1),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE1_SEL),
}, },
{ {
DA9063_BUCK(DA9063, BCORE2, 300, 10, 1570, DA9063_BUCK(DA9063, BCORE2, 300, 10, 1570,
da9063_buck_a_limits, da9063_buck_a_limits,
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE2_ILIM_MASK), DA9063_REG_BUCK_ILIM_C, DA9063_BCORE2_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BCORE2), DA9063_BUCK_COMMON_FIELDS(BCORE2),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE2_SEL),
}, },
{ {
DA9063_BUCK(DA9063, BPRO, 530, 10, 1800, DA9063_BUCK(DA9063, BPRO, 530, 10, 1800,
da9063_buck_a_limits, da9063_buck_a_limits,
DA9063_REG_BUCK_ILIM_B, DA9063_BPRO_ILIM_MASK), DA9063_REG_BUCK_ILIM_B, DA9063_BPRO_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BPRO), DA9063_BUCK_COMMON_FIELDS(BPRO),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBPRO_SEL),
}, },
{ {
DA9063_BUCK(DA9063, BMEM, 800, 20, 3340, DA9063_BUCK(DA9063, BMEM, 800, 20, 3340,
da9063_buck_b_limits, da9063_buck_b_limits,
DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK), DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BMEM), DA9063_BUCK_COMMON_FIELDS(BMEM),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBMEM_SEL),
}, },
{ {
DA9063_BUCK(DA9063, BIO, 800, 20, 3340, DA9063_BUCK(DA9063, BIO, 800, 20, 3340,
da9063_buck_b_limits, da9063_buck_b_limits,
DA9063_REG_BUCK_ILIM_A, DA9063_BIO_ILIM_MASK), DA9063_REG_BUCK_ILIM_A, DA9063_BIO_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BIO), DA9063_BUCK_COMMON_FIELDS(BIO),
.suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VBIO_SEL),
}, },
{ {
DA9063_BUCK(DA9063, BPERI, 800, 20, 3340, DA9063_BUCK(DA9063, BPERI, 800, 20, 3340,
da9063_buck_b_limits, da9063_buck_b_limits,
DA9063_REG_BUCK_ILIM_B, DA9063_BPERI_ILIM_MASK), DA9063_REG_BUCK_ILIM_B, DA9063_BPERI_ILIM_MASK),
DA9063_BUCK_COMMON_FIELDS(BPERI), DA9063_BUCK_COMMON_FIELDS(BPERI),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBPERI_SEL),
}, },
{ {
DA9063_BUCK(DA9063, BCORES_MERGED, 300, 10, 1570, DA9063_BUCK(DA9063, BCORES_MERGED, 300, 10, 1570,
...@@ -518,7 +490,6 @@ static const struct da9063_regulator_info da9063_regulator_info[] = { ...@@ -518,7 +490,6 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK), DA9063_REG_BUCK_ILIM_C, DA9063_BCORE1_ILIM_MASK),
/* BCORES_MERGED uses the same register fields as BCORE1 */ /* BCORES_MERGED uses the same register fields as BCORE1 */
DA9063_BUCK_COMMON_FIELDS(BCORE1), DA9063_BUCK_COMMON_FIELDS(BCORE1),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBCORE1_SEL),
}, },
{ {
DA9063_BUCK(DA9063, BMEM_BIO_MERGED, 800, 20, 3340, DA9063_BUCK(DA9063, BMEM_BIO_MERGED, 800, 20, 3340,
...@@ -526,21 +497,17 @@ static const struct da9063_regulator_info da9063_regulator_info[] = { ...@@ -526,21 +497,17 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK), DA9063_REG_BUCK_ILIM_A, DA9063_BMEM_ILIM_MASK),
/* BMEM_BIO_MERGED uses the same register fields as BMEM */ /* BMEM_BIO_MERGED uses the same register fields as BMEM */
DA9063_BUCK_COMMON_FIELDS(BMEM), DA9063_BUCK_COMMON_FIELDS(BMEM),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VBMEM_SEL),
}, },
{ {
DA9063_LDO(DA9063, LDO3, 900, 20, 3440), DA9063_LDO(DA9063, LDO3, 900, 20, 3440),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO3_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO3_LIM),
}, },
{ {
DA9063_LDO(DA9063, LDO7, 900, 50, 3600), DA9063_LDO(DA9063, LDO7, 900, 50, 3600),
.suspend = BFIELD(DA9063_REG_LDO7_CONT, DA9063_VLDO7_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO7_LIM),
}, },
{ {
DA9063_LDO(DA9063, LDO8, 900, 50, 3600), DA9063_LDO(DA9063, LDO8, 900, 50, 3600),
.suspend = BFIELD(DA9063_REG_LDO8_CONT, DA9063_VLDO8_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO8_LIM),
}, },
{ {
...@@ -549,36 +516,29 @@ static const struct da9063_regulator_info da9063_regulator_info[] = { ...@@ -549,36 +516,29 @@ static const struct da9063_regulator_info da9063_regulator_info[] = {
}, },
{ {
DA9063_LDO(DA9063, LDO11, 900, 50, 3600), DA9063_LDO(DA9063, LDO11, 900, 50, 3600),
.suspend = BFIELD(DA9063_REG_LDO11_CONT, DA9063_VLDO11_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO11_LIM),
}, },
/* The following LDOs are present only on DA9063, not on DA9063L */ /* The following LDOs are present only on DA9063, not on DA9063L */
{ {
DA9063_LDO(DA9063, LDO1, 600, 20, 1860), DA9063_LDO(DA9063, LDO1, 600, 20, 1860),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO1_SEL),
}, },
{ {
DA9063_LDO(DA9063, LDO2, 600, 20, 1860), DA9063_LDO(DA9063, LDO2, 600, 20, 1860),
.suspend = BFIELD(DA9063_REG_DVC_1, DA9063_VLDO2_SEL),
}, },
{ {
DA9063_LDO(DA9063, LDO4, 900, 20, 3440), DA9063_LDO(DA9063, LDO4, 900, 20, 3440),
.suspend = BFIELD(DA9063_REG_DVC_2, DA9063_VLDO4_SEL),
.oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM), .oc_event = BFIELD(DA9063_REG_STATUS_D, DA9063_LDO4_LIM),
}, },
{ {
DA9063_LDO(DA9063, LDO5, 900, 50, 3600), DA9063_LDO(DA9063, LDO5, 900, 50, 3600),
.suspend = BFIELD(DA9063_REG_LDO5_CONT, DA9063_VLDO5_SEL),
}, },
{ {
DA9063_LDO(DA9063, LDO6, 900, 50, 3600), DA9063_LDO(DA9063, LDO6, 900, 50, 3600),
.suspend = BFIELD(DA9063_REG_LDO6_CONT, DA9063_VLDO6_SEL),
}, },
{ {
DA9063_LDO(DA9063, LDO10, 900, 50, 3600), DA9063_LDO(DA9063, LDO10, 900, 50, 3600),
.suspend = BFIELD(DA9063_REG_LDO10_CONT, DA9063_VLDO10_SEL),
}, },
}; };
......
// SPDX-License-Identifier: GPL-2.0
//
// MP8867/MP8869 regulator driver
//
// Copyright (C) 2020 Synaptics Incorporated
//
// Author: Jisheng Zhang <jszhang@kernel.org>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
#define MP886X_VSEL 0x00
#define MP886X_V_BOOT (1 << 7)
#define MP886X_SYSCNTLREG1 0x01
#define MP886X_MODE (1 << 0)
#define MP886X_GO (1 << 6)
#define MP886X_EN (1 << 7)
struct mp886x_device_info {
struct device *dev;
struct regulator_desc desc;
struct regulator_init_data *regulator;
struct gpio_desc *en_gpio;
u32 r[2];
unsigned int sel;
};
static int mp886x_set_mode(struct regulator_dev *rdev, unsigned int mode)
{
switch (mode) {
case REGULATOR_MODE_FAST:
regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
MP886X_MODE, MP886X_MODE);
break;
case REGULATOR_MODE_NORMAL:
regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
MP886X_MODE, 0);
break;
default:
return -EINVAL;
}
return 0;
}
static unsigned int mp886x_get_mode(struct regulator_dev *rdev)
{
u32 val;
int ret;
ret = regmap_read(rdev->regmap, MP886X_SYSCNTLREG1, &val);
if (ret < 0)
return ret;
if (val & MP886X_MODE)
return REGULATOR_MODE_FAST;
else
return REGULATOR_MODE_NORMAL;
}
static int mp8869_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
{
int ret;
ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
MP886X_GO, MP886X_GO);
if (ret < 0)
return ret;
sel <<= ffs(rdev->desc->vsel_mask) - 1;
return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
MP886X_V_BOOT | rdev->desc->vsel_mask, sel);
}
static inline unsigned int mp8869_scale(unsigned int uv, u32 r1, u32 r2)
{
u32 tmp = uv * r1 / r2;
return uv + tmp;
}
static int mp8869_get_voltage_sel(struct regulator_dev *rdev)
{
struct mp886x_device_info *di = rdev_get_drvdata(rdev);
int ret, uv;
unsigned int val;
bool fbloop;
ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
if (ret)
return ret;
fbloop = val & MP886X_V_BOOT;
if (fbloop) {
uv = rdev->desc->min_uV;
uv = mp8869_scale(uv, di->r[0], di->r[1]);
return regulator_map_voltage_linear(rdev, uv, uv);
}
val &= rdev->desc->vsel_mask;
val >>= ffs(rdev->desc->vsel_mask) - 1;
return val;
}
static const struct regulator_ops mp8869_regulator_ops = {
.set_voltage_sel = mp8869_set_voltage_sel,
.get_voltage_sel = mp8869_get_voltage_sel,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.map_voltage = regulator_map_voltage_linear,
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_mode = mp886x_set_mode,
.get_mode = mp886x_get_mode,
};
static int mp8867_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
{
struct mp886x_device_info *di = rdev_get_drvdata(rdev);
int ret, delta;
ret = mp8869_set_voltage_sel(rdev, sel);
if (ret < 0)
return ret;
delta = di->sel - sel;
if (abs(delta) <= 5)
ret = regmap_update_bits(rdev->regmap, MP886X_SYSCNTLREG1,
MP886X_GO, 0);
di->sel = sel;
return ret;
}
static int mp8867_get_voltage_sel(struct regulator_dev *rdev)
{
struct mp886x_device_info *di = rdev_get_drvdata(rdev);
int ret, uv;
unsigned int val;
bool fbloop;
ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
if (ret)
return ret;
fbloop = val & MP886X_V_BOOT;
val &= rdev->desc->vsel_mask;
val >>= ffs(rdev->desc->vsel_mask) - 1;
if (fbloop) {
uv = regulator_list_voltage_linear(rdev, val);
uv = mp8869_scale(uv, di->r[0], di->r[1]);
return regulator_map_voltage_linear(rdev, uv, uv);
}
return val;
}
static const struct regulator_ops mp8867_regulator_ops = {
.set_voltage_sel = mp8867_set_voltage_sel,
.get_voltage_sel = mp8867_get_voltage_sel,
.set_voltage_time_sel = regulator_set_voltage_time_sel,
.map_voltage = regulator_map_voltage_linear,
.list_voltage = regulator_list_voltage_linear,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.set_mode = mp886x_set_mode,
.get_mode = mp886x_get_mode,
};
static int mp886x_regulator_register(struct mp886x_device_info *di,
struct regulator_config *config)
{
struct regulator_desc *rdesc = &di->desc;
struct regulator_dev *rdev;
rdesc->name = "mp886x-reg";
rdesc->supply_name = "vin";
rdesc->ops = of_device_get_match_data(di->dev);
rdesc->type = REGULATOR_VOLTAGE;
rdesc->n_voltages = 128;
rdesc->enable_reg = MP886X_SYSCNTLREG1;
rdesc->enable_mask = MP886X_EN;
rdesc->min_uV = 600000;
rdesc->uV_step = 10000;
rdesc->vsel_reg = MP886X_VSEL;
rdesc->vsel_mask = 0x3f;
rdesc->owner = THIS_MODULE;
rdev = devm_regulator_register(di->dev, &di->desc, config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
di->sel = rdesc->ops->get_voltage_sel(rdev);
return 0;
}
static const struct regmap_config mp886x_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int mp886x_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct device *dev = &client->dev;
struct device_node *np = dev->of_node;
struct mp886x_device_info *di;
struct regulator_config config = { };
struct regmap *regmap;
int ret;
di = devm_kzalloc(dev, sizeof(struct mp886x_device_info), GFP_KERNEL);
if (!di)
return -ENOMEM;
di->regulator = of_get_regulator_init_data(dev, np, &di->desc);
if (!di->regulator) {
dev_err(dev, "Platform data not found!\n");
return -EINVAL;
}
ret = of_property_read_u32_array(np, "mps,fb-voltage-divider",
di->r, 2);
if (ret)
return ret;
di->en_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(di->en_gpio))
return PTR_ERR(di->en_gpio);
di->dev = dev;
regmap = devm_regmap_init_i2c(client, &mp886x_regmap_config);
if (IS_ERR(regmap)) {
dev_err(dev, "Failed to allocate regmap!\n");
return PTR_ERR(regmap);
}
i2c_set_clientdata(client, di);
config.dev = di->dev;
config.init_data = di->regulator;
config.regmap = regmap;
config.driver_data = di;
config.of_node = np;
ret = mp886x_regulator_register(di, &config);
if (ret < 0)
dev_err(dev, "Failed to register regulator!\n");
return ret;
}
static const struct of_device_id mp886x_dt_ids[] = {
{
.compatible = "mps,mp8867",
.data = &mp8867_regulator_ops
},
{
.compatible = "mps,mp8869",
.data = &mp8869_regulator_ops
},
{ }
};
MODULE_DEVICE_TABLE(of, mp886x_dt_ids);
static const struct i2c_device_id mp886x_id[] = {
{ "mp886x", },
{ },
};
MODULE_DEVICE_TABLE(i2c, mp886x_id);
static struct i2c_driver mp886x_regulator_driver = {
.driver = {
.name = "mp886x-regulator",
.of_match_table = of_match_ptr(mp886x_dt_ids),
},
.probe = mp886x_i2c_probe,
.id_table = mp886x_id,
};
module_i2c_driver(mp886x_regulator_driver);
MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");
MODULE_DESCRIPTION("MP886x regulator driver");
MODULE_LICENSE("GPL v2");
...@@ -445,6 +445,44 @@ static const struct regulator_desc pm8994_lnldo = { ...@@ -445,6 +445,44 @@ static const struct regulator_desc pm8994_lnldo = {
.ops = &rpm_smps_ldo_ops_fixed, .ops = &rpm_smps_ldo_ops_fixed,
}; };
static const struct regulator_desc pmi8994_ftsmps = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(350000, 0, 199, 5000),
REGULATOR_LINEAR_RANGE(700000, 200, 349, 10000),
},
.n_linear_ranges = 2,
.n_voltages = 350,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pmi8994_hfsmps = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(350000, 0, 80, 12500),
REGULATOR_LINEAR_RANGE(700000, 81, 141, 25000),
},
.n_linear_ranges = 2,
.n_voltages = 142,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pmi8994_bby = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(3000000, 0, 44, 50000),
},
.n_linear_ranges = 1,
.n_voltages = 45,
.ops = &rpm_bob_ops,
};
static const struct regulator_desc pmi8994_boost = {
.linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(4000000, 0, 30, 50000),
},
.n_linear_ranges = 1,
.n_voltages = 31,
.ops = &rpm_smps_ldo_ops,
};
static const struct regulator_desc pm8998_ftsmps = { static const struct regulator_desc pm8998_ftsmps = {
.linear_ranges = (struct regulator_linear_range[]) { .linear_ranges = (struct regulator_linear_range[]) {
REGULATOR_LINEAR_RANGE(320000, 0, 258, 4000), REGULATOR_LINEAR_RANGE(320000, 0, 258, 4000),
...@@ -780,6 +818,14 @@ static const struct rpm_regulator_data rpm_pm8994_regulators[] = { ...@@ -780,6 +818,14 @@ static const struct rpm_regulator_data rpm_pm8994_regulators[] = {
{} {}
}; };
static const struct rpm_regulator_data rpm_pmi8994_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPB, 1, &pmi8994_ftsmps, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPB, 2, &pmi8994_hfsmps, "vdd_s2" },
{ "s2", QCOM_SMD_RPM_SMPB, 3, &pmi8994_hfsmps, "vdd_s3" },
{ "boost-bypass", QCOM_SMD_RPM_BBYB, 1, &pmi8994_bby, "vdd_bst_byp" },
{}
};
static const struct rpm_regulator_data rpm_pm8998_regulators[] = { static const struct rpm_regulator_data rpm_pm8998_regulators[] = {
{ "s1", QCOM_SMD_RPM_SMPA, 1, &pm8998_ftsmps, "vdd_s1" }, { "s1", QCOM_SMD_RPM_SMPA, 1, &pm8998_ftsmps, "vdd_s1" },
{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8998_ftsmps, "vdd_s2" }, { "s2", QCOM_SMD_RPM_SMPA, 2, &pm8998_ftsmps, "vdd_s2" },
...@@ -862,6 +908,7 @@ static const struct of_device_id rpm_of_match[] = { ...@@ -862,6 +908,7 @@ static const struct of_device_id rpm_of_match[] = {
{ .compatible = "qcom,rpm-pm8994-regulators", .data = &rpm_pm8994_regulators }, { .compatible = "qcom,rpm-pm8994-regulators", .data = &rpm_pm8994_regulators },
{ .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators }, { .compatible = "qcom,rpm-pm8998-regulators", .data = &rpm_pm8998_regulators },
{ .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators }, { .compatible = "qcom,rpm-pma8084-regulators", .data = &rpm_pma8084_regulators },
{ .compatible = "qcom,rpm-pmi8994-regulators", .data = &rpm_pmi8994_regulators },
{ .compatible = "qcom,rpm-pmi8998-regulators", .data = &rpm_pmi8998_regulators }, { .compatible = "qcom,rpm-pmi8998-regulators", .data = &rpm_pmi8998_regulators },
{ .compatible = "qcom,rpm-pms405-regulators", .data = &rpm_pms405_regulators }, { .compatible = "qcom,rpm-pms405-regulators", .data = &rpm_pms405_regulators },
{} {}
......
...@@ -277,9 +277,9 @@ enum regulator_type { ...@@ -277,9 +277,9 @@ enum regulator_type {
* @curr_table: Current limit mapping table (if table based mapping) * @curr_table: Current limit mapping table (if table based mapping)
* *
* @vsel_range_reg: Register for range selector when using pickable ranges * @vsel_range_reg: Register for range selector when using pickable ranges
* and regulator_regmap_X_voltage_X_pickable functions. * and ``regulator_map_*_voltage_*_pickable`` functions.
* @vsel_range_mask: Mask for register bitfield used for range selector * @vsel_range_mask: Mask for register bitfield used for range selector
* @vsel_reg: Register for selector when using regulator_regmap_X_voltage_ * @vsel_reg: Register for selector when using ``regulator_map_*_voltage_*``
* @vsel_mask: Mask for register bitfield used for selector * @vsel_mask: Mask for register bitfield used for selector
* @vsel_step: Specify the resolution of selector stepping when setting * @vsel_step: Specify the resolution of selector stepping when setting
* voltage. If 0, then no stepping is done (requested selector is * voltage. If 0, then no stepping is done (requested selector is
......
...@@ -10,6 +10,7 @@ struct qcom_smd_rpm; ...@@ -10,6 +10,7 @@ struct qcom_smd_rpm;
/* /*
* Constants used for addressing resources in the RPM. * Constants used for addressing resources in the RPM.
*/ */
#define QCOM_SMD_RPM_BBYB 0x62796262
#define QCOM_SMD_RPM_BOBB 0x62626f62 #define QCOM_SMD_RPM_BOBB 0x62626f62
#define QCOM_SMD_RPM_BOOST 0x61747362 #define QCOM_SMD_RPM_BOOST 0x61747362
#define QCOM_SMD_RPM_BUS_CLK 0x316b6c63 #define QCOM_SMD_RPM_BUS_CLK 0x316b6c63
......
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