forked from Minki/linux
regulator: Updates for v4.14
This is an extremely quiet release for the regulator subsystem, it's all fairly minor fixes and cleanups plus a few new drivers and ddevice ID additions: - Support for MediaTek MT6380, Ricoh RC5T619 and ST Voltage Reference Buffers. -----BEGIN PGP SIGNATURE----- iQFHBAABCAAxFiEEreZoqmdXGLWf4p/qJNaLcl1Uh9AFAlmthW0THGJyb29uaWVA a2VybmVsLm9yZwAKCRAk1otyXVSH0BhAB/4/twIBnHSwqyNgt/HX8N0gdalejYIY lrCushBDAEp3CAV/ODfjCQlL2V2DOA5scx9iQxiiri6owbGcpdB7mNDMfyR9tT2f hkUPEMK6gyCHQdKubmnpFXKBrmPXo6wYrPGYx8HWHYCSiL3lTQPwd+n1iKt4NsLT mQRzjXqFahKS/UKqPcur+wP1gpVGY5DUifDjSiNTQzenM4EY/Yu0DzTohAta5qb7 8bR+teC90I2u7VBQUnslNdVm1y8CtSyUVAOP2aOkTVu/8h/r9DDL1EL6w3efScna 60FZGcsnqVuEjUsF/5PtKes/9QD+/MS1qTKBK5eo+UzcbqQfhpZgBo4d =EUUb -----END PGP SIGNATURE----- Merge tag 'regulator-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator Pull regulator updates from Mark Brown: "This is an extremely quiet release for the regulator subsystem, it's all fairly minor fixes and cleanups plus a few new drivers and ddevice ID additions: - Support for MediaTek MT6380, Ricoh RC5T619 and ST Voltage Reference Buffers" * tag 'regulator-v4.14' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (24 commits) regulator: Add support for stm32-vrefbuf regulator: Add STM32 Voltage Reference Buffer regulator: pv88090: Exception handling for out of bounds regulator: da9063: Return an error code on probe failure regulator: rn5t618: add RC5T619 PMIC support regulator: ltc3589: constify i2c_device_id regulator: fan53555: fix I2C device ids regulator: add fixes with MT6397 dt-bindings shouldn't reference driver regulator: add fixes with MT6323 dt-bindings shouldn't reference driver regulator: add fixes with MT6311 dt-bindings shouldn't reference driver regulator: Add document for MediaTek MT6380 regulator regulator: mt6380: Add support for MT6380 regulator: pwm-regulator: Remove unneeded gpiod NULL check regulator: core: fix a possible race in disable_work handling regulator: fan53555: Use of_device_get_match_data() to simplify probe regulator: of: regulator_of_get_init_data() missing of_node_get() regulator: pwm-regulator: fix example syntax regulator: Convert to using %pOF instead of full_name regulator: cpcap: Add OF mode mapping regulator: cpcap: Fix standby mode ...
This commit is contained in:
commit
fe9e31383e
@ -1,4 +1,4 @@
|
||||
Mediatek MT6311 Regulator Driver
|
||||
Mediatek MT6311 Regulator
|
||||
|
||||
Required properties:
|
||||
- compatible: "mediatek,mt6311-regulator"
|
||||
|
@ -1,4 +1,4 @@
|
||||
Mediatek MT6323 Regulator Driver
|
||||
Mediatek MT6323 Regulator
|
||||
|
||||
All voltage regulators are defined as subnodes of the regulators node. A list
|
||||
of regulators provided by this controller are defined as subnodes of the
|
||||
|
@ -0,0 +1,89 @@
|
||||
MediaTek MT6380 Regulator
|
||||
|
||||
All voltage regulators provided by the MT6380 PMIC are described as the
|
||||
subnodes of the MT6380 regulators node. Each regulator is named according
|
||||
to its regulator type, buck-<name> and ldo-<name>. The definition for each
|
||||
of these nodes is defined using the standard binding for regulators at
|
||||
Documentation/devicetree/bindings/regulator/regulator.txt.
|
||||
|
||||
The valid names for regulators are:
|
||||
BUCK:
|
||||
buck-core1, buck-vcore, buck-vrf
|
||||
LDO:
|
||||
ldo-vm ,ldo-va , ldo-vphy, ldo-vddr, ldo-vt
|
||||
|
||||
Example:
|
||||
|
||||
regulators {
|
||||
compatible = "mediatek,mt6380-regulator";
|
||||
|
||||
mt6380_vcpu_reg: buck-vcore1 {
|
||||
regulator-name = "vcore1";
|
||||
regulator-min-microvolt = < 600000>;
|
||||
regulator-max-microvolt = <1393750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
mt6380_vcore_reg: buck-vcore {
|
||||
regulator-name = "vcore";
|
||||
regulator-min-microvolt = <600000>;
|
||||
regulator-max-microvolt = <1393750>;
|
||||
regulator-ramp-delay = <6250>;
|
||||
};
|
||||
|
||||
mt6380_vrf_reg: buck-vrf {
|
||||
regulator-name = "vrf";
|
||||
regulator-min-microvolt = <1200000>;
|
||||
regulator-max-microvolt = <1575000>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
mt6380_vm_reg: ldo-vm {
|
||||
regulator-name = "vm";
|
||||
regulator-min-microvolt = <1050000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
mt6380_va_reg: ldo-va {
|
||||
regulator-name = "va";
|
||||
regulator-min-microvolt = <2200000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
mt6380_vphy_reg: ldo-vphy {
|
||||
regulator-name = "vphy";
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
mt6380_vddr_reg: ldo-vddr {
|
||||
regulator-name = "vddr";
|
||||
regulator-min-microvolt = <1240000>;
|
||||
regulator-max-microvolt = <1840000>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
|
||||
mt6380_vt_reg: ldo-vt {
|
||||
regulator-name = "vt";
|
||||
regulator-min-microvolt = <2200000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-ramp-delay = <0>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
};
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
Mediatek MT6397 Regulator Driver
|
||||
Mediatek MT6397 Regulator
|
||||
|
||||
Required properties:
|
||||
- compatible: "mediatek,mt6397-regulator"
|
||||
|
@ -71,7 +71,7 @@ Continuous Voltage With Enable GPIO Example:
|
||||
* Inverted PWM logic, and the duty cycle range is limited
|
||||
* to 30%-70%.
|
||||
*/
|
||||
pwm-dutycycle-range <700 300>; /* */
|
||||
pwm-dutycycle-range = <700 300>; /* */
|
||||
};
|
||||
|
||||
Voltage Table Example:
|
||||
|
@ -0,0 +1,20 @@
|
||||
STM32 VREFBUF - Voltage reference buffer
|
||||
|
||||
Some STM32 devices embed a voltage reference buffer which can be used as
|
||||
voltage reference for ADCs, DACs and also as voltage reference for external
|
||||
components through the dedicated VREF+ pin.
|
||||
|
||||
Required properties:
|
||||
- compatible: Must be "st,stm32-vrefbuf".
|
||||
- reg: Offset and length of VREFBUF register set.
|
||||
- clocks: Must contain an entry for peripheral clock.
|
||||
|
||||
Example:
|
||||
vrefbuf: regulator@58003C00 {
|
||||
compatible = "st,stm32-vrefbuf";
|
||||
reg = <0x58003C00 0x8>;
|
||||
clocks = <&rcc VREF_CK>;
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <2500000>;
|
||||
vdda-supply = <&vdda>;
|
||||
};
|
@ -559,6 +559,15 @@ config REGULATOR_MT6323
|
||||
This driver supports the control of different power rails of device
|
||||
through regulator interface.
|
||||
|
||||
config REGULATOR_MT6380
|
||||
tristate "MediaTek MT6380 PMIC"
|
||||
depends on MTK_PMIC_WRAP
|
||||
help
|
||||
Say y here to select this option to enable the power regulator of
|
||||
MediaTek MT6380 PMIC.
|
||||
This driver supports the control of different power rails of device
|
||||
through regulator interface.
|
||||
|
||||
config REGULATOR_MT6397
|
||||
tristate "MediaTek MT6397 PMIC"
|
||||
depends on MFD_MT6397
|
||||
@ -700,8 +709,8 @@ config REGULATOR_RN5T618
|
||||
tristate "Ricoh RN5T567/618 voltage regulators"
|
||||
depends on MFD_RN5T618
|
||||
help
|
||||
Say y here to support the regulators found on Ricoh RN5T567 or
|
||||
RN5T618 PMIC.
|
||||
Say y here to support the regulators found on Ricoh RN5T567,
|
||||
RN5T618 or RC5T619 PMIC.
|
||||
|
||||
config REGULATOR_RT5033
|
||||
tristate "Richtek RT5033 Regulators"
|
||||
@ -746,6 +755,18 @@ config REGULATOR_SKY81452
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called sky81452-regulator.
|
||||
|
||||
config REGULATOR_STM32_VREFBUF
|
||||
tristate "STMicroelectronics STM32 VREFBUF"
|
||||
depends on ARCH_STM32 || COMPILE_TEST
|
||||
help
|
||||
This driver supports STMicroelectronics STM32 VREFBUF (voltage
|
||||
reference buffer) which can be used as voltage reference for
|
||||
internal ADCs, DACs and also for external components through
|
||||
dedicated Vref+ pin.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called stm32-vrefbuf.
|
||||
|
||||
config REGULATOR_TI_ABB
|
||||
tristate "TI Adaptive Body Bias on-chip LDO"
|
||||
depends on ARCH_OMAP
|
||||
|
@ -72,6 +72,7 @@ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
|
||||
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6323) += mt6323-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6380) += mt6380-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
|
||||
@ -94,6 +95,7 @@ obj-$(CONFIG_REGULATOR_S2MPA01) += s2mpa01.o
|
||||
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
|
||||
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
|
||||
obj-$(CONFIG_REGULATOR_SKY81452) += sky81452-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_STM32_VREFBUF) += stm32-vrefbuf.o
|
||||
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
|
||||
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
|
||||
|
@ -691,6 +691,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
|
||||
(regulators == axp809_regulators && i == AXP809_DC1SW)) {
|
||||
new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
|
||||
GFP_KERNEL);
|
||||
if (!new_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
*new_desc = regulators[i];
|
||||
new_desc->supply_name = dcdc1_name;
|
||||
desc = new_desc;
|
||||
@ -700,6 +703,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
|
||||
(regulators == axp809_regulators && i == AXP809_DC5LDO)) {
|
||||
new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
|
||||
GFP_KERNEL);
|
||||
if (!new_desc)
|
||||
return -ENOMEM;
|
||||
|
||||
*new_desc = regulators[i];
|
||||
new_desc->supply_name = dcdc5_name;
|
||||
desc = new_desc;
|
||||
|
@ -204,8 +204,8 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp
|
||||
regnode = of_parse_phandle(dev->of_node, prop_name, 0);
|
||||
|
||||
if (!regnode) {
|
||||
dev_dbg(dev, "Looking up %s property in node %s failed\n",
|
||||
prop_name, dev->of_node->full_name);
|
||||
dev_dbg(dev, "Looking up %s property in node %pOF failed\n",
|
||||
prop_name, dev->of_node);
|
||||
return NULL;
|
||||
}
|
||||
return regnode;
|
||||
@ -2396,6 +2396,14 @@ static void regulator_disable_work(struct work_struct *work)
|
||||
count = rdev->deferred_disables;
|
||||
rdev->deferred_disables = 0;
|
||||
|
||||
/*
|
||||
* Workqueue functions queue the new work instance while the previous
|
||||
* work instance is being processed. Cancel the queued work instance
|
||||
* as the work instance under processing does the job of the queued
|
||||
* work instance.
|
||||
*/
|
||||
cancel_delayed_work(&rdev->disable_work);
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
ret = _regulator_disable(rdev);
|
||||
if (ret != 0)
|
||||
@ -2439,10 +2447,10 @@ int regulator_disable_deferred(struct regulator *regulator, int ms)
|
||||
|
||||
mutex_lock(&rdev->mutex);
|
||||
rdev->deferred_disables++;
|
||||
mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
|
||||
msecs_to_jiffies(ms));
|
||||
mutex_unlock(&rdev->mutex);
|
||||
|
||||
queue_delayed_work(system_power_efficient_wq, &rdev->disable_work,
|
||||
msecs_to_jiffies(ms));
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(regulator_disable_deferred);
|
||||
|
@ -77,6 +77,8 @@
|
||||
#define CPCAP_BIT_VAUDIO_MODE0 BIT(1)
|
||||
#define CPCAP_BIT_V_AUDIO_EN BIT(0)
|
||||
|
||||
#define CPCAP_BIT_AUDIO_NORMAL_MODE 0x00
|
||||
|
||||
/*
|
||||
* Off mode configuration bit. Used currently only by SW5 on omap4. There's
|
||||
* the following comment in Motorola Linux kernel tree for it:
|
||||
@ -121,6 +123,7 @@ struct cpcap_regulator {
|
||||
.enable_val = (mode_val), \
|
||||
.disable_val = (off_val), \
|
||||
.ramp_delay = (volt_trans_time), \
|
||||
.of_map_mode = cpcap_map_mode, \
|
||||
}, \
|
||||
.assign_reg = (assignment_reg), \
|
||||
.assign_mask = (assignment_mask), \
|
||||
@ -211,13 +214,25 @@ static int cpcap_regulator_disable(struct regulator_dev *rdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
static unsigned int cpcap_map_mode(unsigned int mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case CPCAP_BIT_AUDIO_NORMAL_MODE:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
case CPCAP_BIT_AUDIO_LOW_PWR:
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int cpcap_regulator_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
int value;
|
||||
|
||||
regmap_read(rdev->regmap, rdev->desc->enable_reg, &value);
|
||||
|
||||
if (!(value & CPCAP_BIT_AUDIO_LOW_PWR))
|
||||
if (value & CPCAP_BIT_AUDIO_LOW_PWR)
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
@ -230,10 +245,10 @@ static int cpcap_regulator_set_mode(struct regulator_dev *rdev,
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
value = CPCAP_BIT_AUDIO_LOW_PWR;
|
||||
value = CPCAP_BIT_AUDIO_NORMAL_MODE;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
value = 0;
|
||||
value = CPCAP_BIT_AUDIO_LOW_PWR;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
@ -736,7 +736,7 @@ static int da9063_regulator_probe(struct platform_device *pdev)
|
||||
if (IS_ERR(regl_pdata) || regl_pdata->n_regulators == 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"No regulators defined for the platform\n");
|
||||
return PTR_ERR(regl_pdata);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Find regulators set for particular device model */
|
||||
|
@ -407,14 +407,8 @@ static int fan53555_regulator_probe(struct i2c_client *client,
|
||||
|
||||
di->regulator = pdata->regulator;
|
||||
if (client->dev.of_node) {
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_device(of_match_ptr(fan53555_dt_ids),
|
||||
&client->dev);
|
||||
if (!match)
|
||||
return -ENODEV;
|
||||
|
||||
di->vendor = (unsigned long) match->data;
|
||||
di->vendor =
|
||||
(unsigned long)of_device_get_match_data(&client->dev);
|
||||
} else {
|
||||
/* if no ramp constraint set, get the pdata ramp_delay */
|
||||
if (!di->regulator->constraints.ramp_delay) {
|
||||
@ -476,7 +470,10 @@ static const struct i2c_device_id fan53555_id[] = {
|
||||
.name = "fan53555",
|
||||
.driver_data = FAN53555_VENDOR_FAIRCHILD
|
||||
}, {
|
||||
.name = "syr82x",
|
||||
.name = "syr827",
|
||||
.driver_data = FAN53555_VENDOR_SILERGY
|
||||
}, {
|
||||
.name = "syr828",
|
||||
.driver_data = FAN53555_VENDOR_SILERGY
|
||||
},
|
||||
{ },
|
||||
|
@ -539,7 +539,7 @@ static int ltc3589_probe(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct i2c_device_id ltc3589_i2c_id[] = {
|
||||
static const struct i2c_device_id ltc3589_i2c_id[] = {
|
||||
{ "ltc3589", LTC3589 },
|
||||
{ "ltc3589-1", LTC3589_1 },
|
||||
{ "ltc3589-2", LTC3589_2 },
|
||||
|
@ -169,7 +169,7 @@ static int of_get_max1586_platform_data(struct device *dev,
|
||||
|
||||
if (of_property_read_u32(np, "v3-gain",
|
||||
&pdata->v3_gain) < 0) {
|
||||
dev_err(dev, "%s has no 'v3-gain' property\n", np->full_name);
|
||||
dev_err(dev, "%pOF has no 'v3-gain' property\n", np);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
352
drivers/regulator/mt6380-regulator.c
Normal file
352
drivers/regulator/mt6380-regulator.c
Normal file
@ -0,0 +1,352 @@
|
||||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Chenglin Xu <chenglin.xu@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/mt6380-regulator.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
/* PMIC Registers */
|
||||
#define MT6380_ALDO_CON_0 0x0000
|
||||
#define MT6380_BTLDO_CON_0 0x0004
|
||||
#define MT6380_COMP_CON_0 0x0008
|
||||
#define MT6380_CPUBUCK_CON_0 0x000C
|
||||
#define MT6380_CPUBUCK_CON_1 0x0010
|
||||
#define MT6380_CPUBUCK_CON_2 0x0014
|
||||
#define MT6380_DDRLDO_CON_0 0x0018
|
||||
#define MT6380_MLDO_CON_0 0x001C
|
||||
#define MT6380_PALDO_CON_0 0x0020
|
||||
#define MT6380_PHYLDO_CON_0 0x0024
|
||||
#define MT6380_SIDO_CON_0 0x0028
|
||||
#define MT6380_SIDO_CON_1 0x002C
|
||||
#define MT6380_SIDO_CON_2 0x0030
|
||||
#define MT6380_SLDO_CON_0 0x0034
|
||||
#define MT6380_TLDO_CON_0 0x0038
|
||||
#define MT6380_STARTUP_CON_0 0x003C
|
||||
#define MT6380_STARTUP_CON_1 0x0040
|
||||
#define MT6380_SMPS_TOP_CON_0 0x0044
|
||||
#define MT6380_SMPS_TOP_CON_1 0x0048
|
||||
#define MT6380_ANA_CTRL_0 0x0050
|
||||
#define MT6380_ANA_CTRL_1 0x0054
|
||||
#define MT6380_ANA_CTRL_2 0x0058
|
||||
#define MT6380_ANA_CTRL_3 0x005C
|
||||
#define MT6380_ANA_CTRL_4 0x0060
|
||||
#define MT6380_SPK_CON9 0x0064
|
||||
#define MT6380_SPK_CON11 0x0068
|
||||
#define MT6380_SPK_CON12 0x006A
|
||||
#define MT6380_CLK_CTRL 0x0070
|
||||
#define MT6380_PINMUX_CTRL 0x0074
|
||||
#define MT6380_IO_CTRL 0x0078
|
||||
#define MT6380_SLP_MODE_CTRL_0 0x007C
|
||||
#define MT6380_SLP_MODE_CTRL_1 0x0080
|
||||
#define MT6380_SLP_MODE_CTRL_2 0x0084
|
||||
#define MT6380_SLP_MODE_CTRL_3 0x0088
|
||||
#define MT6380_SLP_MODE_CTRL_4 0x008C
|
||||
#define MT6380_SLP_MODE_CTRL_5 0x0090
|
||||
#define MT6380_SLP_MODE_CTRL_6 0x0094
|
||||
#define MT6380_SLP_MODE_CTRL_7 0x0098
|
||||
#define MT6380_SLP_MODE_CTRL_8 0x009C
|
||||
#define MT6380_FCAL_CTRL_0 0x00A0
|
||||
#define MT6380_FCAL_CTRL_1 0x00A4
|
||||
#define MT6380_LDO_CTRL_0 0x00A8
|
||||
#define MT6380_LDO_CTRL_1 0x00AC
|
||||
#define MT6380_LDO_CTRL_2 0x00B0
|
||||
#define MT6380_LDO_CTRL_3 0x00B4
|
||||
#define MT6380_LDO_CTRL_4 0x00B8
|
||||
#define MT6380_DEBUG_CTRL_0 0x00BC
|
||||
#define MT6380_EFU_CTRL_0 0x0200
|
||||
#define MT6380_EFU_CTRL_1 0x0201
|
||||
#define MT6380_EFU_CTRL_2 0x0202
|
||||
#define MT6380_EFU_CTRL_3 0x0203
|
||||
#define MT6380_EFU_CTRL_4 0x0204
|
||||
#define MT6380_EFU_CTRL_5 0x0205
|
||||
#define MT6380_EFU_CTRL_6 0x0206
|
||||
#define MT6380_EFU_CTRL_7 0x0207
|
||||
#define MT6380_EFU_CTRL_8 0x0208
|
||||
|
||||
#define MT6380_REGULATOR_MODE_AUTO 0
|
||||
#define MT6380_REGULATOR_MODE_FORCE_PWM 1
|
||||
|
||||
/*
|
||||
* mt6380 regulators' information
|
||||
*
|
||||
* @desc: standard fields of regulator description
|
||||
* @vselon_reg: Register sections for hardware control mode of bucks
|
||||
* @modeset_reg: Register for controlling the buck/LDO control mode
|
||||
* @modeset_mask: Mask for controlling the buck/LDO control mode
|
||||
*/
|
||||
struct mt6380_regulator_info {
|
||||
struct regulator_desc desc;
|
||||
u32 vselon_reg;
|
||||
u32 modeset_reg;
|
||||
u32 modeset_mask;
|
||||
};
|
||||
|
||||
#define MT6380_BUCK(match, vreg, min, max, step, volt_ranges, enreg, \
|
||||
vosel, vosel_mask, enbit, voselon, _modeset_reg, \
|
||||
_modeset_mask) \
|
||||
[MT6380_ID_##vreg] = { \
|
||||
.desc = { \
|
||||
.name = #vreg, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.ops = &mt6380_volt_range_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MT6380_ID_##vreg, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = ((max) - (min)) / (step) + 1, \
|
||||
.linear_ranges = volt_ranges, \
|
||||
.n_linear_ranges = ARRAY_SIZE(volt_ranges), \
|
||||
.vsel_reg = vosel, \
|
||||
.vsel_mask = vosel_mask, \
|
||||
.enable_reg = enreg, \
|
||||
.enable_mask = BIT(enbit), \
|
||||
}, \
|
||||
.vselon_reg = voselon, \
|
||||
.modeset_reg = _modeset_reg, \
|
||||
.modeset_mask = _modeset_mask, \
|
||||
}
|
||||
|
||||
#define MT6380_LDO(match, vreg, ldo_volt_table, enreg, enbit, vosel, \
|
||||
vosel_mask, _modeset_reg, _modeset_mask) \
|
||||
[MT6380_ID_##vreg] = { \
|
||||
.desc = { \
|
||||
.name = #vreg, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.ops = &mt6380_volt_table_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MT6380_ID_##vreg, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = ARRAY_SIZE(ldo_volt_table), \
|
||||
.volt_table = ldo_volt_table, \
|
||||
.vsel_reg = vosel, \
|
||||
.vsel_mask = vosel_mask, \
|
||||
.enable_reg = enreg, \
|
||||
.enable_mask = BIT(enbit), \
|
||||
}, \
|
||||
.modeset_reg = _modeset_reg, \
|
||||
.modeset_mask = _modeset_mask, \
|
||||
}
|
||||
|
||||
#define MT6380_REG_FIXED(match, vreg, enreg, enbit, volt, \
|
||||
_modeset_reg, _modeset_mask) \
|
||||
[MT6380_ID_##vreg] = { \
|
||||
.desc = { \
|
||||
.name = #vreg, \
|
||||
.of_match = of_match_ptr(match), \
|
||||
.ops = &mt6380_volt_fixed_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.id = MT6380_ID_##vreg, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = 1, \
|
||||
.enable_reg = enreg, \
|
||||
.enable_mask = BIT(enbit), \
|
||||
.min_uV = volt, \
|
||||
}, \
|
||||
.modeset_reg = _modeset_reg, \
|
||||
.modeset_mask = _modeset_mask, \
|
||||
}
|
||||
|
||||
static const struct regulator_linear_range buck_volt_range1[] = {
|
||||
REGULATOR_LINEAR_RANGE(600000, 0, 0xfe, 6250),
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range buck_volt_range2[] = {
|
||||
REGULATOR_LINEAR_RANGE(600000, 0, 0xfe, 6250),
|
||||
};
|
||||
|
||||
static const struct regulator_linear_range buck_volt_range3[] = {
|
||||
REGULATOR_LINEAR_RANGE(1200000, 0, 0x3c, 25000),
|
||||
};
|
||||
|
||||
static const u32 ldo_volt_table1[] = {
|
||||
1400000, 1350000, 1300000, 1250000, 1200000, 1150000, 1100000, 1050000,
|
||||
};
|
||||
|
||||
static const u32 ldo_volt_table2[] = {
|
||||
2200000, 3300000,
|
||||
};
|
||||
|
||||
static const u32 ldo_volt_table3[] = {
|
||||
1240000, 1390000, 1540000, 1840000,
|
||||
};
|
||||
|
||||
static const u32 ldo_volt_table4[] = {
|
||||
2200000, 3300000,
|
||||
};
|
||||
|
||||
static int mt6380_regulator_set_mode(struct regulator_dev *rdev,
|
||||
unsigned int mode)
|
||||
{
|
||||
int ret, val = 0;
|
||||
struct mt6380_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = MT6380_REGULATOR_MODE_AUTO;
|
||||
break;
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = MT6380_REGULATOR_MODE_FORCE_PWM;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
val <<= ffs(info->modeset_mask) - 1;
|
||||
|
||||
ret = regmap_update_bits(rdev->regmap, info->modeset_reg,
|
||||
info->modeset_mask, val);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int mt6380_regulator_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
unsigned int val;
|
||||
unsigned int mode;
|
||||
int ret;
|
||||
struct mt6380_regulator_info *info = rdev_get_drvdata(rdev);
|
||||
|
||||
ret = regmap_read(rdev->regmap, info->modeset_reg, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
val &= info->modeset_mask;
|
||||
val >>= ffs(info->modeset_mask) - 1;
|
||||
|
||||
switch (val) {
|
||||
case MT6380_REGULATOR_MODE_AUTO:
|
||||
mode = REGULATOR_MODE_NORMAL;
|
||||
break;
|
||||
case MT6380_REGULATOR_MODE_FORCE_PWM:
|
||||
mode = REGULATOR_MODE_FAST;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static const struct regulator_ops mt6380_volt_range_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear_range,
|
||||
.map_voltage = regulator_map_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,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_mode = mt6380_regulator_set_mode,
|
||||
.get_mode = mt6380_regulator_get_mode,
|
||||
};
|
||||
|
||||
static const struct regulator_ops mt6380_volt_table_ops = {
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
.map_voltage = regulator_map_voltage_iterate,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_mode = mt6380_regulator_set_mode,
|
||||
.get_mode = mt6380_regulator_get_mode,
|
||||
};
|
||||
|
||||
static const struct regulator_ops mt6380_volt_fixed_ops = {
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.set_mode = mt6380_regulator_set_mode,
|
||||
.get_mode = mt6380_regulator_get_mode,
|
||||
};
|
||||
|
||||
/* The array is indexed by id(MT6380_ID_XXX) */
|
||||
static struct mt6380_regulator_info mt6380_regulators[] = {
|
||||
MT6380_BUCK("buck-vcore1", VCPU, 600000, 1393750, 6250,
|
||||
buck_volt_range1, MT6380_ANA_CTRL_3, MT6380_ANA_CTRL_1,
|
||||
0xfe, 3, MT6380_ANA_CTRL_1,
|
||||
MT6380_CPUBUCK_CON_0, 0x8000000),
|
||||
MT6380_BUCK("buck-vcore", VCORE, 600000, 1393750, 6250,
|
||||
buck_volt_range2, MT6380_ANA_CTRL_3, MT6380_ANA_CTRL_2,
|
||||
0xfe, 2, MT6380_ANA_CTRL_2, MT6380_SIDO_CON_0, 0x1000000),
|
||||
MT6380_BUCK("buck-vrf", VRF, 1200000, 1575000, 25000,
|
||||
buck_volt_range3, MT6380_ANA_CTRL_3, MT6380_SIDO_CON_0,
|
||||
0x78, 1, MT6380_SIDO_CON_0, MT6380_SIDO_CON_0, 0x8000),
|
||||
MT6380_LDO("ldo-vm", VMLDO, ldo_volt_table1, MT6380_LDO_CTRL_0,
|
||||
1, MT6380_MLDO_CON_0, 0xE000, MT6380_ANA_CTRL_1, 0x4000000),
|
||||
MT6380_LDO("ldo-va", VALDO, ldo_volt_table2, MT6380_LDO_CTRL_0,
|
||||
2, MT6380_ALDO_CON_0, 0x400, MT6380_ALDO_CON_0, 0x20),
|
||||
MT6380_REG_FIXED("ldo-vphy", VPHYLDO, MT6380_LDO_CTRL_0, 7, 1800000,
|
||||
MT6380_PHYLDO_CON_0, 0x80),
|
||||
MT6380_LDO("ldo-vddr", VDDRLDO, ldo_volt_table3, MT6380_LDO_CTRL_0,
|
||||
8, MT6380_DDRLDO_CON_0, 0x3000, MT6380_DDRLDO_CON_0, 0x80),
|
||||
MT6380_LDO("ldo-vt", VTLDO, ldo_volt_table4, MT6380_LDO_CTRL_0, 3,
|
||||
MT6380_TLDO_CON_0, 0x400, MT6380_TLDO_CON_0, 0x20),
|
||||
};
|
||||
|
||||
static int mt6380_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct regmap *regmap = dev_get_regmap(pdev->dev.parent, NULL);
|
||||
struct regulator_config config = {};
|
||||
struct regulator_dev *rdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MT6380_MAX_REGULATOR; i++) {
|
||||
config.dev = &pdev->dev;
|
||||
config.driver_data = &mt6380_regulators[i];
|
||||
config.regmap = regmap;
|
||||
rdev = devm_regulator_register(&pdev->dev,
|
||||
&mt6380_regulators[i].desc,
|
||||
&config);
|
||||
if (IS_ERR(rdev)) {
|
||||
dev_err(&pdev->dev, "failed to register %s\n",
|
||||
mt6380_regulators[i].desc.name);
|
||||
return PTR_ERR(rdev);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id mt6380_platform_ids[] = {
|
||||
{"mt6380-regulator", 0},
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(platform, mt6380_platform_ids);
|
||||
|
||||
static const struct of_device_id mt6380_of_match[] = {
|
||||
{ .compatible = "mediatek,mt6380-regulator", },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mt6380_of_match);
|
||||
|
||||
static struct platform_driver mt6380_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "mt6380-regulator",
|
||||
.of_match_table = of_match_ptr(mt6380_of_match),
|
||||
},
|
||||
.probe = mt6380_regulator_probe,
|
||||
.id_table = mt6380_platform_ids,
|
||||
};
|
||||
|
||||
module_platform_driver(mt6380_regulator_driver);
|
||||
|
||||
MODULE_AUTHOR("Chenglin Xu <chenglin.xu@mediatek.com>");
|
||||
MODULE_DESCRIPTION("Regulator Driver for MediaTek MT6380 PMIC");
|
||||
MODULE_LICENSE("GPL v2");
|
@ -333,7 +333,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
|
||||
search = of_get_child_by_name(dev->of_node,
|
||||
desc->regulators_node);
|
||||
else
|
||||
search = dev->of_node;
|
||||
search = of_node_get(dev->of_node);
|
||||
|
||||
if (!search) {
|
||||
dev_dbg(dev, "Failed to find regulator container node '%s'\n",
|
||||
|
@ -43,7 +43,7 @@ enum {
|
||||
struct pv88090_regulator {
|
||||
struct regulator_desc desc;
|
||||
/* Current limiting */
|
||||
unsigned n_current_limits;
|
||||
unsigned int n_current_limits;
|
||||
const int *current_limits;
|
||||
unsigned int limit_mask;
|
||||
unsigned int conf;
|
||||
@ -398,9 +398,14 @@ static int pv88090_i2c_probe(struct i2c_client *i2c,
|
||||
return ret;
|
||||
|
||||
range = (range >>
|
||||
(PV88080_BUCK_VRANGE_GAIN_SHIFT + i - 1)) &
|
||||
PV88080_BUCK_VRANGE_GAIN_MASK;
|
||||
(PV88090_BUCK_VRANGE_GAIN_SHIFT + i - 1)) &
|
||||
PV88090_BUCK_VRANGE_GAIN_MASK;
|
||||
index = ((range << 1) | conf2);
|
||||
if (index > PV88090_ID_BUCK3) {
|
||||
dev_err(chip->dev,
|
||||
"Invalid index(%d)\n", index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pv88090_regulator_info[i].desc.min_uV
|
||||
= pv88090_buck_vol[index].min_uV;
|
||||
|
@ -89,10 +89,10 @@
|
||||
#define PV88090_BUCK_VDAC_RANGE_2 0x01
|
||||
|
||||
/* PV88090_REG_BUCK_FOLD_RANGE (addr=0x61) */
|
||||
#define PV88080_BUCK_VRANGE_GAIN_SHIFT 3
|
||||
#define PV88080_BUCK_VRANGE_GAIN_MASK 0x01
|
||||
#define PV88090_BUCK_VRANGE_GAIN_SHIFT 3
|
||||
#define PV88090_BUCK_VRANGE_GAIN_MASK 0x01
|
||||
|
||||
#define PV88080_BUCK_VRANGE_GAIN_1 0x00
|
||||
#define PV88080_BUCK_VRANGE_GAIN_2 0x01
|
||||
#define PV88090_BUCK_VRANGE_GAIN_1 0x00
|
||||
#define PV88090_BUCK_VRANGE_GAIN_2 0x01
|
||||
|
||||
#endif /* __PV88090_REGISTERS_H__ */
|
||||
|
@ -122,8 +122,7 @@ static int pwm_regulator_enable(struct regulator_dev *dev)
|
||||
{
|
||||
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
|
||||
|
||||
if (drvdata->enb_gpio)
|
||||
gpiod_set_value_cansleep(drvdata->enb_gpio, 1);
|
||||
gpiod_set_value_cansleep(drvdata->enb_gpio, 1);
|
||||
|
||||
return pwm_enable(drvdata->pwm);
|
||||
}
|
||||
@ -134,8 +133,7 @@ static int pwm_regulator_disable(struct regulator_dev *dev)
|
||||
|
||||
pwm_disable(drvdata->pwm);
|
||||
|
||||
if (drvdata->enb_gpio)
|
||||
gpiod_set_value_cansleep(drvdata->enb_gpio, 0);
|
||||
gpiod_set_value_cansleep(drvdata->enb_gpio, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -959,6 +959,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
match = of_match_device(rpm_of_match, &pdev->dev);
|
||||
if (!match) {
|
||||
dev_err(&pdev->dev, "failed to match device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (reg = match->data; reg->name; reg++) {
|
||||
vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
|
||||
if (!vreg)
|
||||
|
@ -570,6 +570,11 @@ static int rpm_reg_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
match = of_match_device(rpm_of_match, &pdev->dev);
|
||||
if (!match) {
|
||||
dev_err(&pdev->dev, "failed to match device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (reg = match->data; reg->name; reg++) {
|
||||
vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
|
||||
if (!vreg)
|
||||
|
@ -79,6 +79,29 @@ static struct regulator_desc rn5t618_regulators[] = {
|
||||
REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
|
||||
};
|
||||
|
||||
static struct regulator_desc rc5t619_regulators[] = {
|
||||
/* DCDC */
|
||||
REG(DCDC1, DC1CTL, BIT(0), DC1DAC, 0xff, 600000, 3500000, 12500),
|
||||
REG(DCDC2, DC2CTL, BIT(0), DC2DAC, 0xff, 600000, 3500000, 12500),
|
||||
REG(DCDC3, DC3CTL, BIT(0), DC3DAC, 0xff, 600000, 3500000, 12500),
|
||||
REG(DCDC4, DC4CTL, BIT(0), DC4DAC, 0xff, 600000, 3500000, 12500),
|
||||
REG(DCDC5, DC5CTL, BIT(0), DC5DAC, 0xff, 600000, 3500000, 12500),
|
||||
/* LDO */
|
||||
REG(LDO1, LDOEN1, BIT(0), LDO1DAC, 0x7f, 900000, 3500000, 25000),
|
||||
REG(LDO2, LDOEN1, BIT(1), LDO2DAC, 0x7f, 900000, 3500000, 25000),
|
||||
REG(LDO3, LDOEN1, BIT(2), LDO3DAC, 0x7f, 900000, 3500000, 25000),
|
||||
REG(LDO4, LDOEN1, BIT(3), LDO4DAC, 0x7f, 900000, 3500000, 25000),
|
||||
REG(LDO5, LDOEN1, BIT(4), LDO5DAC, 0x7f, 600000, 3500000, 25000),
|
||||
REG(LDO6, LDOEN1, BIT(5), LDO6DAC, 0x7f, 600000, 3500000, 25000),
|
||||
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),
|
||||
/* LDO RTC */
|
||||
REG(LDORTC1, LDOEN2, BIT(4), LDORTCDAC, 0x7f, 1700000, 3500000, 25000),
|
||||
REG(LDORTC2, LDOEN2, BIT(5), LDORTC2DAC, 0x7f, 900000, 3500000, 25000),
|
||||
};
|
||||
|
||||
static int rn5t618_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct rn5t618 *rn5t618 = dev_get_drvdata(pdev->dev.parent);
|
||||
@ -86,13 +109,20 @@ static int rn5t618_regulator_probe(struct platform_device *pdev)
|
||||
struct regulator_dev *rdev;
|
||||
struct regulator_desc *regulators;
|
||||
int i;
|
||||
int num_regulators = 0;
|
||||
|
||||
switch (rn5t618->variant) {
|
||||
case RN5T567:
|
||||
regulators = rn5t567_regulators;
|
||||
num_regulators = ARRAY_SIZE(rn5t567_regulators);
|
||||
break;
|
||||
case RN5T618:
|
||||
regulators = rn5t618_regulators;
|
||||
num_regulators = ARRAY_SIZE(rn5t618_regulators);
|
||||
break;
|
||||
case RC5T619:
|
||||
regulators = rc5t619_regulators;
|
||||
num_regulators = ARRAY_SIZE(rc5t619_regulators);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@ -101,10 +131,7 @@ static int rn5t618_regulator_probe(struct platform_device *pdev)
|
||||
config.dev = pdev->dev.parent;
|
||||
config.regmap = rn5t618->regmap;
|
||||
|
||||
for (i = 0; i < RN5T618_REG_NUM; i++) {
|
||||
if (!regulators[i].name)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < num_regulators; i++) {
|
||||
rdev = devm_regulator_register(&pdev->dev,
|
||||
®ulators[i],
|
||||
&config);
|
||||
|
@ -590,8 +590,8 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
|
||||
if (of_property_read_u32(reg_np, "op_mode",
|
||||
&rmode->mode)) {
|
||||
dev_warn(iodev->dev,
|
||||
"no op_mode property property at %s\n",
|
||||
reg_np->full_name);
|
||||
"no op_mode property property at %pOF\n",
|
||||
reg_np);
|
||||
|
||||
rmode->mode = S5M8767_OPMODE_NORMAL_MODE;
|
||||
}
|
||||
|
202
drivers/regulator/stm32-vrefbuf.c
Normal file
202
drivers/regulator/stm32-vrefbuf.c
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (C) STMicroelectronics 2017
|
||||
*
|
||||
* Author: Fabrice Gasnier <fabrice.gasnier@st.com>
|
||||
*
|
||||
* License terms: GNU General Public License (GPL), version 2
|
||||
*/
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
|
||||
/* STM32 VREFBUF registers */
|
||||
#define STM32_VREFBUF_CSR 0x00
|
||||
|
||||
/* STM32 VREFBUF CSR bitfields */
|
||||
#define STM32_VRS GENMASK(6, 4)
|
||||
#define STM32_VRR BIT(3)
|
||||
#define STM32_HIZ BIT(1)
|
||||
#define STM32_ENVR BIT(0)
|
||||
|
||||
struct stm32_vrefbuf {
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static const unsigned int stm32_vrefbuf_voltages[] = {
|
||||
/* Matches resp. VRS = 000b, 001b, 010b, 011b */
|
||||
2500000, 2048000, 1800000, 1500000,
|
||||
};
|
||||
|
||||
static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
|
||||
u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
|
||||
int ret;
|
||||
|
||||
val = (val & ~STM32_HIZ) | STM32_ENVR;
|
||||
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
|
||||
|
||||
/*
|
||||
* Vrefbuf startup time depends on external capacitor: wait here for
|
||||
* VRR to be set. That means output has reached expected value.
|
||||
* ~650us sleep should be enough for caps up to 1.5uF. Use 10ms as
|
||||
* arbitrary timeout.
|
||||
*/
|
||||
ret = readl_poll_timeout(priv->base + STM32_VREFBUF_CSR, val,
|
||||
!(val & STM32_VRR), 650, 10000);
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "stm32 vrefbuf timed out!\n");
|
||||
val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
|
||||
val = (val & ~STM32_ENVR) | STM32_HIZ;
|
||||
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_vrefbuf_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
|
||||
u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
|
||||
|
||||
val = (val & ~STM32_ENVR) | STM32_HIZ;
|
||||
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
|
||||
|
||||
return readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
|
||||
}
|
||||
|
||||
static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned sel)
|
||||
{
|
||||
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
|
||||
u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
|
||||
|
||||
val = (val & ~STM32_VRS) | FIELD_PREP(STM32_VRS, sel);
|
||||
writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stm32_vrefbuf_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
|
||||
u32 val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
|
||||
|
||||
return FIELD_GET(STM32_VRS, val);
|
||||
}
|
||||
|
||||
static const struct regulator_ops stm32_vrefbuf_volt_ops = {
|
||||
.enable = stm32_vrefbuf_enable,
|
||||
.disable = stm32_vrefbuf_disable,
|
||||
.is_enabled = stm32_vrefbuf_is_enabled,
|
||||
.get_voltage_sel = stm32_vrefbuf_get_voltage_sel,
|
||||
.set_voltage_sel = stm32_vrefbuf_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_table,
|
||||
};
|
||||
|
||||
static const struct regulator_desc stm32_vrefbuf_regu = {
|
||||
.name = "vref",
|
||||
.supply_name = "vdda",
|
||||
.volt_table = stm32_vrefbuf_voltages,
|
||||
.n_voltages = ARRAY_SIZE(stm32_vrefbuf_voltages),
|
||||
.ops = &stm32_vrefbuf_volt_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int stm32_vrefbuf_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res;
|
||||
struct stm32_vrefbuf *priv;
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev *rdev;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
priv->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(priv->clk))
|
||||
return PTR_ERR(priv->clk);
|
||||
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "clk prepare failed with error %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
config.dev = &pdev->dev;
|
||||
config.driver_data = priv;
|
||||
config.of_node = pdev->dev.of_node;
|
||||
config.init_data = of_get_regulator_init_data(&pdev->dev,
|
||||
pdev->dev.of_node,
|
||||
&stm32_vrefbuf_regu);
|
||||
|
||||
rdev = regulator_register(&stm32_vrefbuf_regu, &config);
|
||||
if (IS_ERR(rdev)) {
|
||||
ret = PTR_ERR(rdev);
|
||||
dev_err(&pdev->dev, "register failed with error %d\n", ret);
|
||||
goto err_clk_dis;
|
||||
}
|
||||
platform_set_drvdata(pdev, rdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err_clk_dis:
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stm32_vrefbuf_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct regulator_dev *rdev = platform_get_drvdata(pdev);
|
||||
struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
|
||||
|
||||
regulator_unregister(rdev);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static const struct of_device_id stm32_vrefbuf_of_match[] = {
|
||||
{ .compatible = "st,stm32-vrefbuf", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, stm32_vrefbuf_of_match);
|
||||
|
||||
static struct platform_driver stm32_vrefbuf_driver = {
|
||||
.probe = stm32_vrefbuf_probe,
|
||||
.remove = stm32_vrefbuf_remove,
|
||||
.driver = {
|
||||
.name = "stm32-vrefbuf",
|
||||
.of_match_table = of_match_ptr(stm32_vrefbuf_of_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(stm32_vrefbuf_driver);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
|
||||
MODULE_DESCRIPTION("STMicroelectronics STM32 VREFBUF driver");
|
||||
MODULE_ALIAS("platform:stm32-vrefbuf");
|
@ -109,8 +109,8 @@ static int socfpga_reset_probe(struct platform_device *pdev)
|
||||
* Do not continue, when we encounter an old DT.
|
||||
*/
|
||||
if (!of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) {
|
||||
dev_err(&pdev->dev, "%s missing #reset-cells property\n",
|
||||
pdev->dev.of_node->full_name);
|
||||
dev_err(&pdev->dev, "%pOF missing #reset-cells property\n",
|
||||
pdev->dev.of_node);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -226,11 +226,17 @@ enum {
|
||||
RN5T618_DCDC2,
|
||||
RN5T618_DCDC3,
|
||||
RN5T618_DCDC4,
|
||||
RN5T618_DCDC5,
|
||||
RN5T618_LDO1,
|
||||
RN5T618_LDO2,
|
||||
RN5T618_LDO3,
|
||||
RN5T618_LDO4,
|
||||
RN5T618_LDO5,
|
||||
RN5T618_LDO6,
|
||||
RN5T618_LDO7,
|
||||
RN5T618_LDO8,
|
||||
RN5T618_LDO9,
|
||||
RN5T618_LDO10,
|
||||
RN5T618_LDORTC1,
|
||||
RN5T618_LDORTC2,
|
||||
RN5T618_REG_NUM,
|
||||
|
32
include/linux/regulator/mt6380-regulator.h
Normal file
32
include/linux/regulator/mt6380-regulator.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2017 MediaTek Inc.
|
||||
* Author: Chenglin Xu <chenglin.xu@mediatek.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_REGULATOR_mt6380_H
|
||||
#define __LINUX_REGULATOR_mt6380_H
|
||||
|
||||
enum {
|
||||
MT6380_ID_VCPU = 0,
|
||||
MT6380_ID_VCORE,
|
||||
MT6380_ID_VRF,
|
||||
MT6380_ID_VMLDO,
|
||||
MT6380_ID_VALDO,
|
||||
MT6380_ID_VPHYLDO,
|
||||
MT6380_ID_VDDRLDO,
|
||||
MT6380_ID_VTLDO,
|
||||
MT6380_ID_RG_MAX,
|
||||
};
|
||||
|
||||
#define MT6380_MAX_REGULATOR MT6380_ID_RG_MAX
|
||||
|
||||
#endif /* __LINUX_REGULATOR_mt6380_H */
|
Loading…
Reference in New Issue
Block a user