regulator: Updates for v4.2
Another fairly quiet release, some new drivers with generic handling for minor features but nothing that makes a substantial difference outside of the subsystem or for most boards: - Support for a bunch of new parameters which are present on enough regulators to be worth having generic handling for in the framework. - Fixes for some issues with printing constraints during boot which should probably have gone in for v4.1 but didn't. - New drivers for Dialog DA9062, Maxim MAX77621 and Qualcomm SPMI regulators. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJViYM8AAoJECTWi3JdVIfQxBkH/iWXaFGXaH4N42jKbo0RnKWT JtKCQwVEilVDFjixt9fNDzlEX0ErZ9wuYvYYRkCGZqhwFwhZe2Pg1BGmN/e5o8dk 6OS3ZNiybBuUNHHio+toZyhJsJoSJubP7MZsWBpJ5evWYmnmqGS589LnlsZwJ7Ez 5W5YUU8GmwyUk2dEa+WpnT3jBJqfccuCzET68jtZz+koRIO0l/gpAgwhVoC/iF2J LYn1r4Cvp0hOcvPJsbTsXUKDIeMk4jfvuYDzBXUyC21fsG2qPlvuYo3nKjhTnMBC gxQcPzbUbfakRH6R5GFdFx+rhvzSKc4dlula5cOF9n++eVFQ6jwHqBk/XvSKRVc= =e9Ij -----END PGP SIGNATURE----- Merge tag 'regulator-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator Pull regulator updates from Mark Brown: "Another fairly quiet release, some new drivers with generic handling for minor features but nothing that makes a substantial difference outside of the subsystem or for most boards: - support for a bunch of new parameters which are present on enough regulators to be worth having generic handling for in the framework. - fixes for some issues with printing constraints during boot which should probably have gone in for v4.1 but didn't. - new drivers for Dialog DA9062, Maxim MAX77621 and Qualcomm SPMI regulators" * tag 'regulator-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (45 commits) regulator: qcom_spmi: Fix calculating number of voltages regulator: qcom_spmi: Add missing braces for aligned code regulator: fix simple_return.cocci warnings regulator: Add QCOM SPMI regulator driver regulator: Add docbook for soft start regulator: Add input current limit support regulator: Add soft start support regulator: Add pull down support regulator: Add system_load constraint regulator: max8973: Fix up ramp_delay for MAX8973_RAMP_25mV_PER_US case regulator: core: replace sprintf with scnprintf regulator: core: fix constraints output buffer regulator: core: Don't corrupt display when printing uV offsets regulator: max8973: add support for MAX77621 regulator: max8973: configure ramp delay through callback regulator: pwm-regulator: Diffientiate between dev (device) and rdev (regulator_dev) regulator: pwm-regulator: Remove superfluous is_enabled check regulator: pwm-regulator: Remove unnecessary descriptor attribute from ddata regulator: core: Don't spew backtraces on duplicate sysfs regulator: da9063: Fix up irq leak ...
This commit is contained in:
commit
7fe0bf908d
@ -2,12 +2,30 @@
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: must be "maxim,max8973"
|
||||
- compatible: must be one of following:
|
||||
"maxim,max8973"
|
||||
"maxim,max77621".
|
||||
- reg: the i2c slave address of the regulator. It should be 0x1b.
|
||||
|
||||
Any standard regulator properties can be used to configure the single max8973
|
||||
DCDC.
|
||||
|
||||
Optional properties:
|
||||
|
||||
-maxim,externally-enable: boolean, externally control the regulator output
|
||||
enable/disable.
|
||||
-maxim,enable-gpio: GPIO for enable control. If the valid GPIO is provided
|
||||
then externally enable control will be considered.
|
||||
-maxim,dvs-gpio: GPIO which is connected to DVS pin of device.
|
||||
-maxim,dvs-default-state: Default state of GPIO during initialisation.
|
||||
1 for HIGH and 0 for LOW.
|
||||
-maxim,enable-remote-sense: boolean, enable reote sense.
|
||||
-maxim,enable-falling-slew-rate: boolean, enable falling slew rate.
|
||||
-maxim,enable-active-discharge: boolean: enable active discharge.
|
||||
-maxim,enable-frequency-shift: boolean, enable 9% frequency shift.
|
||||
-maxim,enable-bias-control: boolean, enable bias control. By enabling this
|
||||
startup delay can be reduce to 20us from 220us.
|
||||
|
||||
Example:
|
||||
|
||||
max8973@1b {
|
||||
|
@ -0,0 +1,121 @@
|
||||
Qualcomm SPMI Regulators
|
||||
|
||||
- compatible:
|
||||
Usage: required
|
||||
Value type: <string>
|
||||
Definition: must be one of:
|
||||
"qcom,pm8841-regulators"
|
||||
"qcom,pm8916-regulators"
|
||||
"qcom,pm8941-regulators"
|
||||
|
||||
- interrupts:
|
||||
Usage: optional
|
||||
Value type: <prop-encoded-array>
|
||||
Definition: List of OCP interrupts.
|
||||
|
||||
- interrupt-names:
|
||||
Usage: required if 'interrupts' property present
|
||||
Value type: <string-array>
|
||||
Definition: List of strings defining the names of the
|
||||
interrupts in the 'interrupts' property 1-to-1.
|
||||
Supported values are "ocp-<regulator_name>", where
|
||||
<regulator_name> corresponds to a voltage switch
|
||||
type regulator.
|
||||
|
||||
- vdd_s1-supply:
|
||||
- vdd_s2-supply:
|
||||
- vdd_s3-supply:
|
||||
- vdd_s4-supply:
|
||||
- vdd_s5-supply:
|
||||
- vdd_s6-supply:
|
||||
- vdd_s7-supply:
|
||||
- vdd_s8-supply:
|
||||
Usage: optional (pm8841 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:
|
||||
- vdd_s4-supply:
|
||||
- vdd_l1_l3-supply:
|
||||
- vdd_l2-supply:
|
||||
- vdd_l4_l5_l6-supply:
|
||||
- vdd_l7-supply:
|
||||
- vdd_l8_l11_l14_l15_l16-supply:
|
||||
- vdd_l9_l10_l12_l13_l17_l18-supply:
|
||||
Usage: optional (pm8916 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:
|
||||
- vdd_l1_l3-supply:
|
||||
- vdd_l2_lvs_1_2_3-supply:
|
||||
- vdd_l4_l11-supply:
|
||||
- vdd_l5_l7-supply:
|
||||
- vdd_l6_l12_l14_l15-supply:
|
||||
- vdd_l8_l16_l18_19-supply:
|
||||
- vdd_l9_l10_l17_l22-supply:
|
||||
- vdd_l13_l20_l23_l24-supply:
|
||||
- vdd_l21-supply:
|
||||
- vin_5vs-supply:
|
||||
Usage: optional (pm8941 only)
|
||||
Value type: <phandle>
|
||||
Definition: Reference to regulator supplying the input pin, as
|
||||
described in the data sheet.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
pm8841:
|
||||
s1, s2, s3, s4, s5, s6, s7, s8
|
||||
|
||||
pm8916:
|
||||
s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13,
|
||||
l14, l15, l16, l17, l18
|
||||
|
||||
pm8941:
|
||||
s1, s2, s3, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13, l14,
|
||||
l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2, lvs3,
|
||||
mvs1, mvs2
|
||||
|
||||
The content of each sub-node is defined by the standard binding for regulators -
|
||||
see regulator.txt - with additional custom properties described below:
|
||||
|
||||
- regulator-initial-mode:
|
||||
Usage: optional
|
||||
Value type: <u32>
|
||||
Descrption: 1 = Set initial mode to high power mode (HPM), also referred
|
||||
to as NPM. HPM consumes more ground current than LPM, but
|
||||
it can source significantly higher load current. HPM is not
|
||||
available on boost type regulators. For voltage switch type
|
||||
regulators, HPM implies that over current protection and
|
||||
soft start are active all the time. 0 = Set initial mode to
|
||||
low power mode (LPM).
|
||||
|
||||
Example:
|
||||
|
||||
regulators {
|
||||
compatible = "qcom,pm8941-regulators";
|
||||
vdd_l1_l3-supply = <&s1>;
|
||||
|
||||
s1: s1 {
|
||||
regulator-min-microvolt = <1300000>;
|
||||
regulator-max-microvolt = <1400000>;
|
||||
};
|
||||
|
||||
...
|
||||
|
||||
l1: l1 {
|
||||
regulator-min-microvolt = <1225000>;
|
||||
regulator-max-microvolt = <1300000>;
|
||||
};
|
||||
|
||||
....
|
||||
};
|
@ -7,18 +7,20 @@ Optional properties:
|
||||
- regulator-microvolt-offset: Offset applied to voltages to compensate for voltage drops
|
||||
- regulator-min-microamp: smallest current consumers may set
|
||||
- regulator-max-microamp: largest current consumers may set
|
||||
- regulator-input-current-limit-microamp: maximum input current regulator allows
|
||||
- regulator-always-on: boolean, regulator should never be disabled
|
||||
- regulator-boot-on: bootloader/firmware enabled regulator
|
||||
- regulator-allow-bypass: allow the regulator to go into bypass mode
|
||||
- <name>-supply: phandle to the parent supply/regulator node
|
||||
- regulator-ramp-delay: ramp delay for regulator(in uV/uS)
|
||||
For hardware which supports disabling ramp rate, it should be explicitly
|
||||
intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
|
||||
initialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
|
||||
- regulator-enable-ramp-delay: The time taken, in microseconds, for the supply
|
||||
rail to reach the target voltage, plus/minus whatever tolerance the board
|
||||
design requires. This property describes the total system ramp time
|
||||
required due to the combination of internal ramping of the regulator itself,
|
||||
and board design issues such as trace capacitance and load on the supply.
|
||||
- regulator-soft-start: Enable soft start so that voltage ramps slowly
|
||||
- regulator-state-mem sub-root node for Suspend-to-RAM mode
|
||||
: suspend to memory, the device goes to sleep, but all data stored in memory,
|
||||
only some external interrupt can wake the device.
|
||||
@ -37,6 +39,9 @@ Optional properties:
|
||||
- regulator-initial-mode: initial operating mode. The set of possible operating
|
||||
modes depends on the capabilities of every hardware so each device binding
|
||||
documentation explains which values the regulator supports.
|
||||
- regulator-system-load: Load in uA present on regulator that is not captured by
|
||||
any consumer request.
|
||||
- regulator-pull-down: Enable pull down resistor when the regulator is disabled.
|
||||
|
||||
Deprecated properties:
|
||||
- regulator-compatible: If a regulator chip contains multiple
|
||||
|
@ -404,7 +404,7 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_device_id pm8607_regulator_driver_ids[] = {
|
||||
static const struct platform_device_id pm8607_regulator_driver_ids[] = {
|
||||
{
|
||||
.name = "88pm860x-regulator",
|
||||
.driver_data = 0,
|
||||
|
@ -178,6 +178,16 @@ config REGULATOR_DA9055
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called da9055-regulator.
|
||||
|
||||
config REGULATOR_DA9062
|
||||
tristate "Dialog Semiconductor DA9062 regulators"
|
||||
depends on MFD_DA9062
|
||||
help
|
||||
Say y here to support the BUCKs and LDOs regulators found on
|
||||
DA9062 PMICs.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called da9062-regulator.
|
||||
|
||||
config REGULATOR_DA9063
|
||||
tristate "Dialog Semiconductor DA9063 regulators"
|
||||
depends on MFD_DA9063
|
||||
@ -233,7 +243,7 @@ config REGULATOR_FAN53555
|
||||
|
||||
config REGULATOR_GPIO
|
||||
tristate "GPIO regulator support"
|
||||
depends on GPIOLIB
|
||||
depends on GPIOLIB || COMPILE_TEST
|
||||
help
|
||||
This driver provides support for regulators that can be
|
||||
controlled via gpios.
|
||||
@ -512,6 +522,17 @@ config REGULATOR_QCOM_RPM
|
||||
Qualcomm RPM as a module. The module will be named
|
||||
"qcom_rpm-regulator".
|
||||
|
||||
config REGULATOR_QCOM_SPMI
|
||||
tristate "Qualcomm SPMI regulator driver"
|
||||
depends on SPMI || COMPILE_TEST
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
regulators found in Qualcomm SPMI PMICs.
|
||||
|
||||
Say M here if you want to include support for the regulators on the
|
||||
Qualcomm SPMI PMICs as a module. The module will be named
|
||||
"qcom_spmi-regulator".
|
||||
|
||||
config REGULATOR_RC5T583
|
||||
tristate "RICOH RC5T583 Power regulators"
|
||||
depends on MFD_RC5T583
|
||||
|
@ -25,6 +25,7 @@ obj-$(CONFIG_REGULATOR_BCM590XX) += bcm590xx-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
|
||||
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA9062) += da9062-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA9063) += da9063-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA9210) += da9210-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_DA9211) += da9211-regulator.o
|
||||
@ -61,6 +62,7 @@ obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
|
||||
obj-$(CONFIG_REGULATOR_MT6397) += mt6397-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
|
||||
obj-$(CONFIG_REGULATOR_PWM) += pwm-regulator.o
|
||||
|
@ -178,6 +178,16 @@ static const struct regulator_init_data arizona_ldo1_default = {
|
||||
.num_consumer_supplies = 1,
|
||||
};
|
||||
|
||||
static const struct regulator_init_data arizona_ldo1_wm5110 = {
|
||||
.constraints = {
|
||||
.min_uV = 1175000,
|
||||
.max_uV = 1200000,
|
||||
.valid_ops_mask = REGULATOR_CHANGE_STATUS |
|
||||
REGULATOR_CHANGE_VOLTAGE,
|
||||
},
|
||||
.num_consumer_supplies = 1,
|
||||
};
|
||||
|
||||
static int arizona_ldo1_of_get_pdata(struct arizona *arizona,
|
||||
struct regulator_config *config,
|
||||
const struct regulator_desc *desc)
|
||||
@ -243,6 +253,11 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
|
||||
desc = &arizona_ldo1_hc;
|
||||
ldo1->init_data = arizona_ldo1_dvfs;
|
||||
break;
|
||||
case WM5110:
|
||||
case WM8280:
|
||||
desc = &arizona_ldo1;
|
||||
ldo1->init_data = arizona_ldo1_wm5110;
|
||||
break;
|
||||
default:
|
||||
desc = &arizona_ldo1;
|
||||
ldo1->init_data = arizona_ldo1_default;
|
||||
|
@ -678,6 +678,8 @@ static int drms_uA_update(struct regulator_dev *rdev)
|
||||
list_for_each_entry(sibling, &rdev->consumer_list, list)
|
||||
current_uA += sibling->uA_load;
|
||||
|
||||
current_uA += rdev->constraints->system_load;
|
||||
|
||||
if (rdev->desc->ops->set_load) {
|
||||
/* set the optimum mode for our new total regulator load */
|
||||
err = rdev->desc->ops->set_load(rdev, current_uA);
|
||||
@ -779,59 +781,64 @@ static int suspend_prepare(struct regulator_dev *rdev, suspend_state_t state)
|
||||
static void print_constraints(struct regulator_dev *rdev)
|
||||
{
|
||||
struct regulation_constraints *constraints = rdev->constraints;
|
||||
char buf[80] = "";
|
||||
char buf[160] = "";
|
||||
size_t len = sizeof(buf) - 1;
|
||||
int count = 0;
|
||||
int ret;
|
||||
|
||||
if (constraints->min_uV && constraints->max_uV) {
|
||||
if (constraints->min_uV == constraints->max_uV)
|
||||
count += sprintf(buf + count, "%d mV ",
|
||||
constraints->min_uV / 1000);
|
||||
count += scnprintf(buf + count, len - count, "%d mV ",
|
||||
constraints->min_uV / 1000);
|
||||
else
|
||||
count += sprintf(buf + count, "%d <--> %d mV ",
|
||||
constraints->min_uV / 1000,
|
||||
constraints->max_uV / 1000);
|
||||
count += scnprintf(buf + count, len - count,
|
||||
"%d <--> %d mV ",
|
||||
constraints->min_uV / 1000,
|
||||
constraints->max_uV / 1000);
|
||||
}
|
||||
|
||||
if (!constraints->min_uV ||
|
||||
constraints->min_uV != constraints->max_uV) {
|
||||
ret = _regulator_get_voltage(rdev);
|
||||
if (ret > 0)
|
||||
count += sprintf(buf + count, "at %d mV ", ret / 1000);
|
||||
count += scnprintf(buf + count, len - count,
|
||||
"at %d mV ", ret / 1000);
|
||||
}
|
||||
|
||||
if (constraints->uV_offset)
|
||||
count += sprintf(buf, "%dmV offset ",
|
||||
constraints->uV_offset / 1000);
|
||||
count += scnprintf(buf + count, len - count, "%dmV offset ",
|
||||
constraints->uV_offset / 1000);
|
||||
|
||||
if (constraints->min_uA && constraints->max_uA) {
|
||||
if (constraints->min_uA == constraints->max_uA)
|
||||
count += sprintf(buf + count, "%d mA ",
|
||||
constraints->min_uA / 1000);
|
||||
count += scnprintf(buf + count, len - count, "%d mA ",
|
||||
constraints->min_uA / 1000);
|
||||
else
|
||||
count += sprintf(buf + count, "%d <--> %d mA ",
|
||||
constraints->min_uA / 1000,
|
||||
constraints->max_uA / 1000);
|
||||
count += scnprintf(buf + count, len - count,
|
||||
"%d <--> %d mA ",
|
||||
constraints->min_uA / 1000,
|
||||
constraints->max_uA / 1000);
|
||||
}
|
||||
|
||||
if (!constraints->min_uA ||
|
||||
constraints->min_uA != constraints->max_uA) {
|
||||
ret = _regulator_get_current_limit(rdev);
|
||||
if (ret > 0)
|
||||
count += sprintf(buf + count, "at %d mA ", ret / 1000);
|
||||
count += scnprintf(buf + count, len - count,
|
||||
"at %d mA ", ret / 1000);
|
||||
}
|
||||
|
||||
if (constraints->valid_modes_mask & REGULATOR_MODE_FAST)
|
||||
count += sprintf(buf + count, "fast ");
|
||||
count += scnprintf(buf + count, len - count, "fast ");
|
||||
if (constraints->valid_modes_mask & REGULATOR_MODE_NORMAL)
|
||||
count += sprintf(buf + count, "normal ");
|
||||
count += scnprintf(buf + count, len - count, "normal ");
|
||||
if (constraints->valid_modes_mask & REGULATOR_MODE_IDLE)
|
||||
count += sprintf(buf + count, "idle ");
|
||||
count += scnprintf(buf + count, len - count, "idle ");
|
||||
if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY)
|
||||
count += sprintf(buf + count, "standby");
|
||||
count += scnprintf(buf + count, len - count, "standby");
|
||||
|
||||
if (!count)
|
||||
sprintf(buf, "no parameters");
|
||||
scnprintf(buf, len, "no parameters");
|
||||
|
||||
rdev_dbg(rdev, "%s\n", buf);
|
||||
|
||||
@ -1006,6 +1013,15 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
|
||||
if (rdev->constraints->ilim_uA && ops->set_input_current_limit) {
|
||||
ret = ops->set_input_current_limit(rdev,
|
||||
rdev->constraints->ilim_uA);
|
||||
if (ret < 0) {
|
||||
rdev_err(rdev, "failed to set input limit\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* do we need to setup our suspend state */
|
||||
if (rdev->constraints->initial_state) {
|
||||
ret = suspend_prepare(rdev, rdev->constraints->initial_state);
|
||||
@ -1049,6 +1065,22 @@ static int set_machine_constraints(struct regulator_dev *rdev,
|
||||
}
|
||||
}
|
||||
|
||||
if (rdev->constraints->pull_down && ops->set_pull_down) {
|
||||
ret = ops->set_pull_down(rdev);
|
||||
if (ret < 0) {
|
||||
rdev_err(rdev, "failed to set pull down\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (rdev->constraints->soft_start && ops->set_soft_start) {
|
||||
ret = ops->set_soft_start(rdev);
|
||||
if (ret < 0) {
|
||||
rdev_err(rdev, "failed to set soft start\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
print_constraints(rdev);
|
||||
return 0;
|
||||
out:
|
||||
@ -1192,10 +1224,10 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
|
||||
if (regulator->supply_name == NULL)
|
||||
goto overflow_err;
|
||||
|
||||
err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
|
||||
err = sysfs_create_link_nowarn(&rdev->dev.kobj, &dev->kobj,
|
||||
buf);
|
||||
if (err) {
|
||||
rdev_warn(rdev, "could not add device link %s err %d\n",
|
||||
rdev_dbg(rdev, "could not add device link %s err %d\n",
|
||||
dev->kobj.name, err);
|
||||
/* non-fatal */
|
||||
}
|
||||
|
842
drivers/regulator/da9062-regulator.c
Normal file
842
drivers/regulator/da9062-regulator.c
Normal file
@ -0,0 +1,842 @@
|
||||
/*
|
||||
* da9062-regulator.c - REGULATOR device driver for DA9062
|
||||
* Copyright (C) 2015 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/slab.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/of_regulator.h>
|
||||
#include <linux/mfd/da9062/core.h>
|
||||
#include <linux/mfd/da9062/registers.h>
|
||||
|
||||
/* Regulator IDs */
|
||||
enum {
|
||||
DA9062_ID_BUCK1,
|
||||
DA9062_ID_BUCK2,
|
||||
DA9062_ID_BUCK3,
|
||||
DA9062_ID_BUCK4,
|
||||
DA9062_ID_LDO1,
|
||||
DA9062_ID_LDO2,
|
||||
DA9062_ID_LDO3,
|
||||
DA9062_ID_LDO4,
|
||||
DA9062_MAX_REGULATORS,
|
||||
};
|
||||
|
||||
/* Regulator capabilities and registers description */
|
||||
struct da9062_regulator_info {
|
||||
struct regulator_desc desc;
|
||||
/* Current limiting */
|
||||
unsigned int n_current_limits;
|
||||
const int *current_limits;
|
||||
/* Main register fields */
|
||||
struct reg_field mode;
|
||||
struct reg_field suspend;
|
||||
struct reg_field sleep;
|
||||
struct reg_field suspend_sleep;
|
||||
unsigned int suspend_vsel_reg;
|
||||
struct reg_field ilimit;
|
||||
/* Event detection bit */
|
||||
struct reg_field oc_event;
|
||||
};
|
||||
|
||||
/* Single regulator settings */
|
||||
struct da9062_regulator {
|
||||
struct regulator_desc desc;
|
||||
struct regulator_dev *rdev;
|
||||
struct da9062 *hw;
|
||||
const struct da9062_regulator_info *info;
|
||||
|
||||
struct regmap_field *mode;
|
||||
struct regmap_field *suspend;
|
||||
struct regmap_field *sleep;
|
||||
struct regmap_field *suspend_sleep;
|
||||
struct regmap_field *ilimit;
|
||||
};
|
||||
|
||||
/* Encapsulates all information for the regulators driver */
|
||||
struct da9062_regulators {
|
||||
int irq_ldo_lim;
|
||||
unsigned n_regulators;
|
||||
/* Array size to be defined during init. Keep at end. */
|
||||
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) BUCK1 and BUCK3.
|
||||
Entry indexes corresponds to register values. */
|
||||
static const int da9062_buck_a_limits[] = {
|
||||
500000, 600000, 700000, 800000, 900000, 1000000, 1100000, 1200000,
|
||||
1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000
|
||||
};
|
||||
|
||||
/* Current limits array (in uA) for BUCK2.
|
||||
Entry indexes corresponds to register values. */
|
||||
static const int da9062_buck_b_limits[] = {
|
||||
1500000, 1600000, 1700000, 1800000, 1900000, 2000000, 2100000, 2200000,
|
||||
2300000, 2400000, 2500000, 2600000, 2700000, 2800000, 2900000, 3000000
|
||||
};
|
||||
|
||||
static int da9062_set_current_limit(struct regulator_dev *rdev,
|
||||
int min_ua, int max_ua)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
const struct da9062_regulator_info *rinfo = regl->info;
|
||||
int n, tval;
|
||||
|
||||
for (n = 0; n < rinfo->n_current_limits; n++) {
|
||||
tval = rinfo->current_limits[n];
|
||||
if (tval >= min_ua && tval <= max_ua)
|
||||
return regmap_field_write(regl->ilimit, n);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int da9062_get_current_limit(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
const struct da9062_regulator_info *rinfo = regl->info;
|
||||
unsigned int sel;
|
||||
int ret;
|
||||
|
||||
ret = regmap_field_read(regl->ilimit, &sel);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (sel >= rinfo->n_current_limits)
|
||||
sel = rinfo->n_current_limits - 1;
|
||||
|
||||
return rinfo->current_limits[sel];
|
||||
}
|
||||
|
||||
static int da9062_buck_set_mode(struct regulator_dev *rdev, unsigned mode)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
unsigned val;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = BUCK_MODE_SYNC;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = BUCK_MODE_AUTO;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = BUCK_MODE_SLEEP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_field_write(regl->mode, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bucks use single mode register field for normal operation
|
||||
* and suspend state.
|
||||
* There are 3 modes to map to: FAST, NORMAL, and STANDBY.
|
||||
*/
|
||||
|
||||
static unsigned da9062_buck_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
struct regmap_field *field;
|
||||
unsigned int val, mode = 0;
|
||||
int ret;
|
||||
|
||||
ret = regmap_field_read(regl->mode, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
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:
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
case BUCK_MODE_SYNC:
|
||||
return REGULATOR_MODE_FAST;
|
||||
case BUCK_MODE_AUTO:
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
/* Detect current regulator state */
|
||||
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)
|
||||
return 0;
|
||||
|
||||
if (val)
|
||||
mode &= REGULATOR_MODE_STANDBY;
|
||||
else
|
||||
mode &= REGULATOR_MODE_NORMAL | REGULATOR_MODE_FAST;
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* LDOs use sleep flags - one for normal and one for suspend state.
|
||||
* There are 2 modes to map to: NORMAL and STANDBY (sleep) for each state.
|
||||
*/
|
||||
|
||||
static int da9062_ldo_set_mode(struct regulator_dev *rdev, unsigned mode)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
unsigned val;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = 0;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = 1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_field_write(regl->sleep, val);
|
||||
}
|
||||
|
||||
static unsigned da9062_ldo_get_mode(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
struct regmap_field *field;
|
||||
int ret, val;
|
||||
|
||||
/* Detect current regulator state */
|
||||
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)
|
||||
return 0;
|
||||
|
||||
if (val)
|
||||
return REGULATOR_MODE_STANDBY;
|
||||
else
|
||||
return REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static int da9062_buck_get_status(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret = regulator_is_enabled_regmap(rdev);
|
||||
|
||||
if (ret == 0) {
|
||||
ret = REGULATOR_STATUS_OFF;
|
||||
} else if (ret > 0) {
|
||||
ret = da9062_buck_get_mode(rdev);
|
||||
if (ret > 0)
|
||||
ret = regulator_mode_to_status(ret);
|
||||
else if (ret == 0)
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da9062_ldo_get_status(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret = regulator_is_enabled_regmap(rdev);
|
||||
|
||||
if (ret == 0) {
|
||||
ret = REGULATOR_STATUS_OFF;
|
||||
} else if (ret > 0) {
|
||||
ret = da9062_ldo_get_mode(rdev);
|
||||
if (ret > 0)
|
||||
ret = regulator_mode_to_status(ret);
|
||||
else if (ret == 0)
|
||||
ret = -EIO;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da9062_set_suspend_voltage(struct regulator_dev *rdev, int uv)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
const struct da9062_regulator_info *rinfo = regl->info;
|
||||
int ret, sel;
|
||||
|
||||
sel = regulator_map_voltage_linear(rdev, uv, uv);
|
||||
if (sel < 0)
|
||||
return sel;
|
||||
|
||||
sel <<= ffs(rdev->desc->vsel_mask) - 1;
|
||||
|
||||
ret = regmap_update_bits(regl->hw->regmap, rinfo->suspend_vsel_reg,
|
||||
rdev->desc->vsel_mask, sel);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int da9062_suspend_enable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
|
||||
return regmap_field_write(regl->suspend, 1);
|
||||
}
|
||||
|
||||
static int da9062_suspend_disable(struct regulator_dev *rdev)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
|
||||
return regmap_field_write(regl->suspend, 0);
|
||||
}
|
||||
|
||||
static int da9062_buck_set_suspend_mode(struct regulator_dev *rdev,
|
||||
unsigned mode)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
int val;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_FAST:
|
||||
val = BUCK_MODE_SYNC;
|
||||
break;
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = BUCK_MODE_AUTO;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = BUCK_MODE_SLEEP;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_field_write(regl->mode, val);
|
||||
}
|
||||
|
||||
static int da9062_ldo_set_suspend_mode(struct regulator_dev *rdev,
|
||||
unsigned mode)
|
||||
{
|
||||
struct da9062_regulator *regl = rdev_get_drvdata(rdev);
|
||||
unsigned val;
|
||||
|
||||
switch (mode) {
|
||||
case REGULATOR_MODE_NORMAL:
|
||||
val = 0;
|
||||
break;
|
||||
case REGULATOR_MODE_STANDBY:
|
||||
val = 1;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return regmap_field_write(regl->suspend_sleep, val);
|
||||
}
|
||||
|
||||
static struct regulator_ops da9062_buck_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_current_limit = da9062_set_current_limit,
|
||||
.get_current_limit = da9062_get_current_limit,
|
||||
.set_mode = da9062_buck_set_mode,
|
||||
.get_mode = da9062_buck_get_mode,
|
||||
.get_status = da9062_buck_get_status,
|
||||
.set_suspend_voltage = da9062_set_suspend_voltage,
|
||||
.set_suspend_enable = da9062_suspend_enable,
|
||||
.set_suspend_disable = da9062_suspend_disable,
|
||||
.set_suspend_mode = da9062_buck_set_suspend_mode,
|
||||
};
|
||||
|
||||
static struct regulator_ops da9062_ldo_ops = {
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.get_voltage_sel = regulator_get_voltage_sel_regmap,
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_mode = da9062_ldo_set_mode,
|
||||
.get_mode = da9062_ldo_get_mode,
|
||||
.get_status = da9062_ldo_get_status,
|
||||
.set_suspend_voltage = da9062_set_suspend_voltage,
|
||||
.set_suspend_enable = da9062_suspend_enable,
|
||||
.set_suspend_disable = da9062_suspend_disable,
|
||||
.set_suspend_mode = da9062_ldo_set_suspend_mode,
|
||||
};
|
||||
|
||||
/* Regulator information */
|
||||
static const struct da9062_regulator_info local_regulator_info[] = {
|
||||
{
|
||||
.desc.id = DA9062_ID_BUCK1,
|
||||
.desc.name = "DA9062 BUCK1",
|
||||
.desc.of_match = of_match_ptr("buck1"),
|
||||
.desc.regulators_node = of_match_ptr("regulators"),
|
||||
.desc.ops = &da9062_buck_ops,
|
||||
.desc.min_uV = (300) * 1000,
|
||||
.desc.uV_step = (10) * 1000,
|
||||
.desc.n_voltages = ((1570) - (300))/(10) + 1,
|
||||
.current_limits = da9062_buck_a_limits,
|
||||
.n_current_limits = ARRAY_SIZE(da9062_buck_a_limits),
|
||||
.desc.enable_reg = DA9062AA_BUCK1_CONT,
|
||||
.desc.enable_mask = DA9062AA_BUCK1_EN_MASK,
|
||||
.desc.vsel_reg = DA9062AA_VBUCK1_A,
|
||||
.desc.vsel_mask = DA9062AA_VBUCK1_A_MASK,
|
||||
.desc.linear_min_sel = 0,
|
||||
.sleep = REG_FIELD(DA9062AA_VBUCK1_A,
|
||||
__builtin_ffs((int)DA9062AA_BUCK1_SL_A_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK1_SL_A_MASK)) - 1),
|
||||
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK1_B,
|
||||
__builtin_ffs((int)DA9062AA_BUCK1_SL_B_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK1_SL_B_MASK)) - 1),
|
||||
.suspend_vsel_reg = DA9062AA_VBUCK1_B,
|
||||
.mode = REG_FIELD(DA9062AA_BUCK1_CFG,
|
||||
__builtin_ffs((int)DA9062AA_BUCK1_MODE_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK1_MODE_MASK)) - 1),
|
||||
.suspend = REG_FIELD(DA9062AA_DVC_1,
|
||||
__builtin_ffs((int)DA9062AA_VBUCK1_SEL_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_VBUCK1_SEL_MASK)) - 1),
|
||||
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_C,
|
||||
__builtin_ffs((int)DA9062AA_BUCK1_ILIM_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK1_ILIM_MASK)) - 1),
|
||||
},
|
||||
{
|
||||
.desc.id = DA9062_ID_BUCK2,
|
||||
.desc.name = "DA9062 BUCK2",
|
||||
.desc.of_match = of_match_ptr("buck2"),
|
||||
.desc.regulators_node = of_match_ptr("regulators"),
|
||||
.desc.ops = &da9062_buck_ops,
|
||||
.desc.min_uV = (300) * 1000,
|
||||
.desc.uV_step = (10) * 1000,
|
||||
.desc.n_voltages = ((1570) - (300))/(10) + 1,
|
||||
.current_limits = da9062_buck_a_limits,
|
||||
.n_current_limits = ARRAY_SIZE(da9062_buck_a_limits),
|
||||
.desc.enable_reg = DA9062AA_BUCK2_CONT,
|
||||
.desc.enable_mask = DA9062AA_BUCK2_EN_MASK,
|
||||
.desc.vsel_reg = DA9062AA_VBUCK2_A,
|
||||
.desc.vsel_mask = DA9062AA_VBUCK2_A_MASK,
|
||||
.desc.linear_min_sel = 0,
|
||||
.sleep = REG_FIELD(DA9062AA_VBUCK2_A,
|
||||
__builtin_ffs((int)DA9062AA_BUCK2_SL_A_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK2_SL_A_MASK)) - 1),
|
||||
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK2_B,
|
||||
__builtin_ffs((int)DA9062AA_BUCK2_SL_B_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK2_SL_B_MASK)) - 1),
|
||||
.suspend_vsel_reg = DA9062AA_VBUCK2_B,
|
||||
.mode = REG_FIELD(DA9062AA_BUCK2_CFG,
|
||||
__builtin_ffs((int)DA9062AA_BUCK2_MODE_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK2_MODE_MASK)) - 1),
|
||||
.suspend = REG_FIELD(DA9062AA_DVC_1,
|
||||
__builtin_ffs((int)DA9062AA_VBUCK2_SEL_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_VBUCK2_SEL_MASK)) - 1),
|
||||
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_C,
|
||||
__builtin_ffs((int)DA9062AA_BUCK2_ILIM_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK2_ILIM_MASK)) - 1),
|
||||
},
|
||||
{
|
||||
.desc.id = DA9062_ID_BUCK3,
|
||||
.desc.name = "DA9062 BUCK3",
|
||||
.desc.of_match = of_match_ptr("buck3"),
|
||||
.desc.regulators_node = of_match_ptr("regulators"),
|
||||
.desc.ops = &da9062_buck_ops,
|
||||
.desc.min_uV = (800) * 1000,
|
||||
.desc.uV_step = (20) * 1000,
|
||||
.desc.n_voltages = ((3340) - (800))/(20) + 1,
|
||||
.current_limits = da9062_buck_b_limits,
|
||||
.n_current_limits = ARRAY_SIZE(da9062_buck_b_limits),
|
||||
.desc.enable_reg = DA9062AA_BUCK3_CONT,
|
||||
.desc.enable_mask = DA9062AA_BUCK3_EN_MASK,
|
||||
.desc.vsel_reg = DA9062AA_VBUCK3_A,
|
||||
.desc.vsel_mask = DA9062AA_VBUCK3_A_MASK,
|
||||
.desc.linear_min_sel = 0,
|
||||
.sleep = REG_FIELD(DA9062AA_VBUCK3_A,
|
||||
__builtin_ffs((int)DA9062AA_BUCK3_SL_A_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK3_SL_A_MASK)) - 1),
|
||||
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK3_B,
|
||||
__builtin_ffs((int)DA9062AA_BUCK3_SL_B_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK3_SL_B_MASK)) - 1),
|
||||
.suspend_vsel_reg = DA9062AA_VBUCK3_B,
|
||||
.mode = REG_FIELD(DA9062AA_BUCK3_CFG,
|
||||
__builtin_ffs((int)DA9062AA_BUCK3_MODE_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK3_MODE_MASK)) - 1),
|
||||
.suspend = REG_FIELD(DA9062AA_DVC_1,
|
||||
__builtin_ffs((int)DA9062AA_VBUCK3_SEL_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_VBUCK3_SEL_MASK)) - 1),
|
||||
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_A,
|
||||
__builtin_ffs((int)DA9062AA_BUCK3_ILIM_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK3_ILIM_MASK)) - 1),
|
||||
},
|
||||
{
|
||||
.desc.id = DA9062_ID_BUCK4,
|
||||
.desc.name = "DA9062 BUCK4",
|
||||
.desc.of_match = of_match_ptr("buck4"),
|
||||
.desc.regulators_node = of_match_ptr("regulators"),
|
||||
.desc.ops = &da9062_buck_ops,
|
||||
.desc.min_uV = (530) * 1000,
|
||||
.desc.uV_step = (10) * 1000,
|
||||
.desc.n_voltages = ((1800) - (530))/(10) + 1,
|
||||
.current_limits = da9062_buck_a_limits,
|
||||
.n_current_limits = ARRAY_SIZE(da9062_buck_a_limits),
|
||||
.desc.enable_reg = DA9062AA_BUCK4_CONT,
|
||||
.desc.enable_mask = DA9062AA_BUCK4_EN_MASK,
|
||||
.desc.vsel_reg = DA9062AA_VBUCK4_A,
|
||||
.desc.vsel_mask = DA9062AA_VBUCK4_A_MASK,
|
||||
.desc.linear_min_sel = 0,
|
||||
.sleep = REG_FIELD(DA9062AA_VBUCK4_A,
|
||||
__builtin_ffs((int)DA9062AA_BUCK4_SL_A_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK4_SL_A_MASK)) - 1),
|
||||
.suspend_sleep = REG_FIELD(DA9062AA_VBUCK4_B,
|
||||
__builtin_ffs((int)DA9062AA_BUCK4_SL_B_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK4_SL_B_MASK)) - 1),
|
||||
.suspend_vsel_reg = DA9062AA_VBUCK4_B,
|
||||
.mode = REG_FIELD(DA9062AA_BUCK4_CFG,
|
||||
__builtin_ffs((int)DA9062AA_BUCK4_MODE_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK4_MODE_MASK)) - 1),
|
||||
.suspend = REG_FIELD(DA9062AA_DVC_1,
|
||||
__builtin_ffs((int)DA9062AA_VBUCK4_SEL_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_VBUCK4_SEL_MASK)) - 1),
|
||||
.ilimit = REG_FIELD(DA9062AA_BUCK_ILIM_B,
|
||||
__builtin_ffs((int)DA9062AA_BUCK4_ILIM_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_BUCK4_ILIM_MASK)) - 1),
|
||||
},
|
||||
{
|
||||
.desc.id = DA9062_ID_LDO1,
|
||||
.desc.name = "DA9062 LDO1",
|
||||
.desc.of_match = of_match_ptr("ldo1"),
|
||||
.desc.regulators_node = of_match_ptr("regulators"),
|
||||
.desc.ops = &da9062_ldo_ops,
|
||||
.desc.min_uV = (900) * 1000,
|
||||
.desc.uV_step = (50) * 1000,
|
||||
.desc.n_voltages = ((3600) - (900))/(50) + 1,
|
||||
.desc.enable_reg = DA9062AA_LDO1_CONT,
|
||||
.desc.enable_mask = DA9062AA_LDO1_EN_MASK,
|
||||
.desc.vsel_reg = DA9062AA_VLDO1_A,
|
||||
.desc.vsel_mask = DA9062AA_VLDO1_A_MASK,
|
||||
.desc.linear_min_sel = 0,
|
||||
.sleep = REG_FIELD(DA9062AA_VLDO1_A,
|
||||
__builtin_ffs((int)DA9062AA_LDO1_SL_A_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO1_SL_A_MASK)) - 1),
|
||||
.suspend_sleep = REG_FIELD(DA9062AA_VLDO1_B,
|
||||
__builtin_ffs((int)DA9062AA_LDO1_SL_B_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO1_SL_B_MASK)) - 1),
|
||||
.suspend_vsel_reg = DA9062AA_VLDO1_B,
|
||||
.suspend = REG_FIELD(DA9062AA_DVC_1,
|
||||
__builtin_ffs((int)DA9062AA_VLDO1_SEL_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_VLDO1_SEL_MASK)) - 1),
|
||||
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
|
||||
__builtin_ffs((int)DA9062AA_LDO1_ILIM_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO1_ILIM_MASK)) - 1),
|
||||
},
|
||||
{
|
||||
.desc.id = DA9062_ID_LDO2,
|
||||
.desc.name = "DA9062 LDO2",
|
||||
.desc.of_match = of_match_ptr("ldo2"),
|
||||
.desc.regulators_node = of_match_ptr("regulators"),
|
||||
.desc.ops = &da9062_ldo_ops,
|
||||
.desc.min_uV = (900) * 1000,
|
||||
.desc.uV_step = (50) * 1000,
|
||||
.desc.n_voltages = ((3600) - (600))/(50) + 1,
|
||||
.desc.enable_reg = DA9062AA_LDO2_CONT,
|
||||
.desc.enable_mask = DA9062AA_LDO2_EN_MASK,
|
||||
.desc.vsel_reg = DA9062AA_VLDO2_A,
|
||||
.desc.vsel_mask = DA9062AA_VLDO2_A_MASK,
|
||||
.desc.linear_min_sel = 0,
|
||||
.sleep = REG_FIELD(DA9062AA_VLDO2_A,
|
||||
__builtin_ffs((int)DA9062AA_LDO2_SL_A_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO2_SL_A_MASK)) - 1),
|
||||
.suspend_sleep = REG_FIELD(DA9062AA_VLDO2_B,
|
||||
__builtin_ffs((int)DA9062AA_LDO2_SL_B_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO2_SL_B_MASK)) - 1),
|
||||
.suspend_vsel_reg = DA9062AA_VLDO2_B,
|
||||
.suspend = REG_FIELD(DA9062AA_DVC_1,
|
||||
__builtin_ffs((int)DA9062AA_VLDO2_SEL_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_VLDO2_SEL_MASK)) - 1),
|
||||
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
|
||||
__builtin_ffs((int)DA9062AA_LDO2_ILIM_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO2_ILIM_MASK)) - 1),
|
||||
},
|
||||
{
|
||||
.desc.id = DA9062_ID_LDO3,
|
||||
.desc.name = "DA9062 LDO3",
|
||||
.desc.of_match = of_match_ptr("ldo3"),
|
||||
.desc.regulators_node = of_match_ptr("regulators"),
|
||||
.desc.ops = &da9062_ldo_ops,
|
||||
.desc.min_uV = (900) * 1000,
|
||||
.desc.uV_step = (50) * 1000,
|
||||
.desc.n_voltages = ((3600) - (900))/(50) + 1,
|
||||
.desc.enable_reg = DA9062AA_LDO3_CONT,
|
||||
.desc.enable_mask = DA9062AA_LDO3_EN_MASK,
|
||||
.desc.vsel_reg = DA9062AA_VLDO3_A,
|
||||
.desc.vsel_mask = DA9062AA_VLDO3_A_MASK,
|
||||
.desc.linear_min_sel = 0,
|
||||
.sleep = REG_FIELD(DA9062AA_VLDO3_A,
|
||||
__builtin_ffs((int)DA9062AA_LDO3_SL_A_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO3_SL_A_MASK)) - 1),
|
||||
.suspend_sleep = REG_FIELD(DA9062AA_VLDO3_B,
|
||||
__builtin_ffs((int)DA9062AA_LDO3_SL_B_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO3_SL_B_MASK)) - 1),
|
||||
.suspend_vsel_reg = DA9062AA_VLDO3_B,
|
||||
.suspend = REG_FIELD(DA9062AA_DVC_1,
|
||||
__builtin_ffs((int)DA9062AA_VLDO3_SEL_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_VLDO3_SEL_MASK)) - 1),
|
||||
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
|
||||
__builtin_ffs((int)DA9062AA_LDO3_ILIM_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO3_ILIM_MASK)) - 1),
|
||||
},
|
||||
{
|
||||
.desc.id = DA9062_ID_LDO4,
|
||||
.desc.name = "DA9062 LDO4",
|
||||
.desc.of_match = of_match_ptr("ldo4"),
|
||||
.desc.regulators_node = of_match_ptr("regulators"),
|
||||
.desc.ops = &da9062_ldo_ops,
|
||||
.desc.min_uV = (900) * 1000,
|
||||
.desc.uV_step = (50) * 1000,
|
||||
.desc.n_voltages = ((3600) - (900))/(50) + 1,
|
||||
.desc.enable_reg = DA9062AA_LDO4_CONT,
|
||||
.desc.enable_mask = DA9062AA_LDO4_EN_MASK,
|
||||
.desc.vsel_reg = DA9062AA_VLDO4_A,
|
||||
.desc.vsel_mask = DA9062AA_VLDO4_A_MASK,
|
||||
.desc.linear_min_sel = 0,
|
||||
.sleep = REG_FIELD(DA9062AA_VLDO4_A,
|
||||
__builtin_ffs((int)DA9062AA_LDO4_SL_A_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO4_SL_A_MASK)) - 1),
|
||||
.suspend_sleep = REG_FIELD(DA9062AA_VLDO4_B,
|
||||
__builtin_ffs((int)DA9062AA_LDO4_SL_B_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO4_SL_B_MASK)) - 1),
|
||||
.suspend_vsel_reg = DA9062AA_VLDO4_B,
|
||||
.suspend = REG_FIELD(DA9062AA_DVC_1,
|
||||
__builtin_ffs((int)DA9062AA_VLDO4_SEL_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_VLDO4_SEL_MASK)) - 1),
|
||||
.oc_event = REG_FIELD(DA9062AA_STATUS_D,
|
||||
__builtin_ffs((int)DA9062AA_LDO4_ILIM_MASK) - 1,
|
||||
sizeof(unsigned int) * 8 -
|
||||
__builtin_clz((DA9062AA_LDO4_ILIM_MASK)) - 1),
|
||||
},
|
||||
};
|
||||
|
||||
/* Regulator interrupt handlers */
|
||||
static irqreturn_t da9062_ldo_lim_event(int irq, void *data)
|
||||
{
|
||||
struct da9062_regulators *regulators = data;
|
||||
struct da9062 *hw = regulators->regulator[0].hw;
|
||||
struct da9062_regulator *regl;
|
||||
int handled = IRQ_NONE;
|
||||
int bits, i, ret;
|
||||
|
||||
ret = regmap_read(hw->regmap, DA9062AA_STATUS_D, &bits);
|
||||
if (ret < 0) {
|
||||
dev_err(hw->dev,
|
||||
"Failed to read LDO overcurrent indicator\n");
|
||||
goto ldo_lim_error;
|
||||
}
|
||||
|
||||
for (i = regulators->n_regulators - 1; i >= 0; i--) {
|
||||
regl = ®ulators->regulator[i];
|
||||
if (regl->info->oc_event.reg != DA9062AA_STATUS_D)
|
||||
continue;
|
||||
|
||||
if (BIT(regl->info->oc_event.lsb) & bits) {
|
||||
regulator_notifier_call_chain(regl->rdev,
|
||||
REGULATOR_EVENT_OVER_CURRENT, NULL);
|
||||
handled = IRQ_HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
ldo_lim_error:
|
||||
return handled;
|
||||
}
|
||||
|
||||
static int da9062_regulator_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct da9062 *chip = dev_get_drvdata(pdev->dev.parent);
|
||||
struct da9062_regulators *regulators;
|
||||
struct da9062_regulator *regl;
|
||||
struct regulator_config config = { };
|
||||
int irq, n, ret;
|
||||
size_t size;
|
||||
|
||||
/* Allocate memory required by usable regulators */
|
||||
size = sizeof(struct da9062_regulators) +
|
||||
DA9062_MAX_REGULATORS * sizeof(struct da9062_regulator);
|
||||
regulators = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
|
||||
if (!regulators)
|
||||
return -ENOMEM;
|
||||
|
||||
regulators->n_regulators = DA9062_MAX_REGULATORS;
|
||||
platform_set_drvdata(pdev, regulators);
|
||||
|
||||
n = 0;
|
||||
while (n < regulators->n_regulators) {
|
||||
/* Initialise regulator structure */
|
||||
regl = ®ulators->regulator[n];
|
||||
regl->hw = chip;
|
||||
regl->info = &local_regulator_info[n];
|
||||
regl->desc = regl->info->desc;
|
||||
regl->desc.type = REGULATOR_VOLTAGE;
|
||||
regl->desc.owner = THIS_MODULE;
|
||||
|
||||
if (regl->info->mode.reg)
|
||||
regl->mode = devm_regmap_field_alloc(
|
||||
&pdev->dev,
|
||||
chip->regmap,
|
||||
regl->info->mode);
|
||||
if (regl->info->suspend.reg)
|
||||
regl->suspend = devm_regmap_field_alloc(
|
||||
&pdev->dev,
|
||||
chip->regmap,
|
||||
regl->info->suspend);
|
||||
if (regl->info->sleep.reg)
|
||||
regl->sleep = devm_regmap_field_alloc(
|
||||
&pdev->dev,
|
||||
chip->regmap,
|
||||
regl->info->sleep);
|
||||
if (regl->info->suspend_sleep.reg)
|
||||
regl->suspend_sleep = devm_regmap_field_alloc(
|
||||
&pdev->dev,
|
||||
chip->regmap,
|
||||
regl->info->suspend_sleep);
|
||||
if (regl->info->ilimit.reg)
|
||||
regl->ilimit = devm_regmap_field_alloc(
|
||||
&pdev->dev,
|
||||
chip->regmap,
|
||||
regl->info->ilimit);
|
||||
|
||||
/* Register regulator */
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.dev = chip->dev;
|
||||
config.driver_data = regl;
|
||||
config.regmap = chip->regmap;
|
||||
|
||||
regl->rdev = devm_regulator_register(&pdev->dev, ®l->desc,
|
||||
&config);
|
||||
if (IS_ERR(regl->rdev)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to register %s regulator\n",
|
||||
regl->desc.name);
|
||||
return PTR_ERR(regl->rdev);
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
/* LDOs overcurrent event support */
|
||||
irq = platform_get_irq_byname(pdev, "LDO_LIM");
|
||||
if (irq < 0) {
|
||||
dev_err(&pdev->dev, "Failed to get IRQ.\n");
|
||||
return irq;
|
||||
}
|
||||
regulators->irq_ldo_lim = irq;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq,
|
||||
NULL, da9062_ldo_lim_event,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"LDO_LIM", regulators);
|
||||
if (ret) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Failed to request LDO_LIM IRQ.\n");
|
||||
regulators->irq_ldo_lim = -ENXIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9062_regulator_driver = {
|
||||
.driver = {
|
||||
.name = "da9062-regulators",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = da9062_regulator_probe,
|
||||
};
|
||||
|
||||
static int __init da9062_regulator_init(void)
|
||||
{
|
||||
return platform_driver_register(&da9062_regulator_driver);
|
||||
}
|
||||
subsys_initcall(da9062_regulator_init);
|
||||
|
||||
static void __exit da9062_regulator_cleanup(void)
|
||||
{
|
||||
platform_driver_unregister(&da9062_regulator_driver);
|
||||
}
|
||||
module_exit(da9062_regulator_cleanup);
|
||||
|
||||
/* Module information */
|
||||
MODULE_AUTHOR("S Twiss <stwiss.opensource@diasemi.com>");
|
||||
MODULE_DESCRIPTION("REGULATOR device driver for Dialog DA9062");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:da9062-regulators");
|
@ -117,9 +117,6 @@ struct da9063_regulator {
|
||||
|
||||
/* Encapsulates all information for the regulators driver */
|
||||
struct da9063_regulators {
|
||||
int irq_ldo_lim;
|
||||
int irq_uvov;
|
||||
|
||||
unsigned n_regulators;
|
||||
/* Array size to be defined during init. Keep at end. */
|
||||
struct da9063_regulator regulator[0];
|
||||
@ -867,35 +864,23 @@ static int da9063_regulator_probe(struct platform_device *pdev)
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = request_threaded_irq(irq,
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq,
|
||||
NULL, da9063_ldo_lim_event,
|
||||
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
|
||||
"LDO_LIM", regulators);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev,
|
||||
"Failed to request LDO_LIM IRQ.\n");
|
||||
regulators->irq_ldo_lim = -ENXIO;
|
||||
dev_err(&pdev->dev, "Failed to request LDO_LIM IRQ.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da9063_regulator_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9063_regulators *regulators = platform_get_drvdata(pdev);
|
||||
|
||||
free_irq(regulators->irq_ldo_lim, regulators);
|
||||
free_irq(regulators->irq_uvov, regulators);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver da9063_regulator_driver = {
|
||||
.driver = {
|
||||
.name = DA9063_DRVNAME_REGULATORS,
|
||||
},
|
||||
.probe = da9063_regulator_probe,
|
||||
.remove = da9063_regulator_remove,
|
||||
};
|
||||
|
||||
static int __init da9063_regulator_init(void)
|
||||
|
@ -182,6 +182,7 @@ static int fan53555_set_ramp(struct regulator_dev *rdev, int ramp)
|
||||
static struct regulator_ops fan53555_regulator_ops = {
|
||||
.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,
|
||||
.map_voltage = regulator_map_voltage_linear,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_suspend_voltage = fan53555_set_suspend_voltage,
|
||||
|
@ -275,7 +275,7 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
|
||||
EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
|
||||
|
||||
/**
|
||||
* regulator_map_voltage_linear - map_voltage() for multiple linear ranges
|
||||
* regulator_map_voltage_linear_range - map_voltage() for multiple linear ranges
|
||||
*
|
||||
* @rdev: Regulator to operate on
|
||||
* @min_uV: Lower bound for voltage
|
||||
|
@ -419,20 +419,16 @@ static int lp8755_int_config(struct lp8755_chip *pchip)
|
||||
}
|
||||
|
||||
ret = lp8755_read(pchip, 0x0F, ®val);
|
||||
if (ret < 0)
|
||||
goto err_i2c;
|
||||
pchip->irqmask = regval;
|
||||
ret = request_threaded_irq(pchip->irq, NULL, lp8755_irq_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"lp8755-irq", pchip);
|
||||
if (ret)
|
||||
if (ret < 0) {
|
||||
dev_err(pchip->dev, "i2c acceess error %s\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
err_i2c:
|
||||
dev_err(pchip->dev, "i2c acceess error %s\n", __func__);
|
||||
return ret;
|
||||
pchip->irqmask = regval;
|
||||
return devm_request_threaded_irq(pchip->dev, pchip->irq, NULL,
|
||||
lp8755_irq_handler,
|
||||
IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
||||
"lp8755-irq", pchip);
|
||||
}
|
||||
|
||||
static const struct regmap_config lp8755_regmap = {
|
||||
@ -514,9 +510,6 @@ static int lp8755_remove(struct i2c_client *client)
|
||||
for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++)
|
||||
lp8755_write(pchip, icnt, 0x00);
|
||||
|
||||
if (pchip->irq != 0)
|
||||
free_irq(pchip->irq, pchip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -100,31 +100,34 @@ static struct regulator_ops max14577_charger_ops = {
|
||||
.set_current_limit = max14577_reg_set_current_limit,
|
||||
};
|
||||
|
||||
#define MAX14577_SAFEOUT_REG { \
|
||||
.name = "SAFEOUT", \
|
||||
.of_match = of_match_ptr("SAFEOUT"), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX14577_SAFEOUT, \
|
||||
.ops = &max14577_safeout_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = 1, \
|
||||
.min_uV = MAX14577_REGULATOR_SAFEOUT_VOLTAGE, \
|
||||
.enable_reg = MAX14577_REG_CONTROL2, \
|
||||
.enable_mask = CTRL2_SFOUTORD_MASK, \
|
||||
}
|
||||
#define MAX14577_CHARGER_REG { \
|
||||
.name = "CHARGER", \
|
||||
.of_match = of_match_ptr("CHARGER"), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX14577_CHARGER, \
|
||||
.ops = &max14577_charger_ops, \
|
||||
.type = REGULATOR_CURRENT, \
|
||||
.owner = THIS_MODULE, \
|
||||
.enable_reg = MAX14577_CHG_REG_CHG_CTRL2, \
|
||||
.enable_mask = CHGCTRL2_MBCHOSTEN_MASK, \
|
||||
}
|
||||
|
||||
static const struct regulator_desc max14577_supported_regulators[] = {
|
||||
[MAX14577_SAFEOUT] = {
|
||||
.name = "SAFEOUT",
|
||||
.of_match = of_match_ptr("SAFEOUT"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = MAX14577_SAFEOUT,
|
||||
.ops = &max14577_safeout_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = MAX14577_REGULATOR_SAFEOUT_VOLTAGE,
|
||||
.enable_reg = MAX14577_REG_CONTROL2,
|
||||
.enable_mask = CTRL2_SFOUTORD_MASK,
|
||||
},
|
||||
[MAX14577_CHARGER] = {
|
||||
.name = "CHARGER",
|
||||
.of_match = of_match_ptr("CHARGER"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = MAX14577_CHARGER,
|
||||
.ops = &max14577_charger_ops,
|
||||
.type = REGULATOR_CURRENT,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = MAX14577_CHG_REG_CHG_CTRL2,
|
||||
.enable_mask = CHGCTRL2_MBCHOSTEN_MASK,
|
||||
},
|
||||
[MAX14577_SAFEOUT] = MAX14577_SAFEOUT_REG,
|
||||
[MAX14577_CHARGER] = MAX14577_CHARGER_REG,
|
||||
};
|
||||
|
||||
static struct regulator_ops max77836_ldo_ops = {
|
||||
@ -138,63 +141,28 @@ static struct regulator_ops max77836_ldo_ops = {
|
||||
/* TODO: add .set_suspend_mode */
|
||||
};
|
||||
|
||||
#define MAX77836_LDO_REG(num) { \
|
||||
.name = "LDO" # num, \
|
||||
.of_match = of_match_ptr("LDO" # num), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.id = MAX77836_LDO ## num, \
|
||||
.ops = &max77836_ldo_ops, \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM, \
|
||||
.min_uV = MAX77836_REGULATOR_LDO_VOLTAGE_MIN, \
|
||||
.uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP, \
|
||||
.enable_reg = MAX77836_LDO_REG_CNFG1_LDO ## num, \
|
||||
.enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK, \
|
||||
.vsel_reg = MAX77836_LDO_REG_CNFG1_LDO ## num, \
|
||||
.vsel_mask = MAX77836_CNFG1_LDO_TV_MASK, \
|
||||
}
|
||||
|
||||
static const struct regulator_desc max77836_supported_regulators[] = {
|
||||
[MAX14577_SAFEOUT] = {
|
||||
.name = "SAFEOUT",
|
||||
.of_match = of_match_ptr("SAFEOUT"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = MAX14577_SAFEOUT,
|
||||
.ops = &max14577_safeout_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = 1,
|
||||
.min_uV = MAX14577_REGULATOR_SAFEOUT_VOLTAGE,
|
||||
.enable_reg = MAX14577_REG_CONTROL2,
|
||||
.enable_mask = CTRL2_SFOUTORD_MASK,
|
||||
},
|
||||
[MAX14577_CHARGER] = {
|
||||
.name = "CHARGER",
|
||||
.of_match = of_match_ptr("CHARGER"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = MAX14577_CHARGER,
|
||||
.ops = &max14577_charger_ops,
|
||||
.type = REGULATOR_CURRENT,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = MAX14577_CHG_REG_CHG_CTRL2,
|
||||
.enable_mask = CHGCTRL2_MBCHOSTEN_MASK,
|
||||
},
|
||||
[MAX77836_LDO1] = {
|
||||
.name = "LDO1",
|
||||
.of_match = of_match_ptr("LDO1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = MAX77836_LDO1,
|
||||
.ops = &max77836_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM,
|
||||
.min_uV = MAX77836_REGULATOR_LDO_VOLTAGE_MIN,
|
||||
.uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP,
|
||||
.enable_reg = MAX77836_LDO_REG_CNFG1_LDO1,
|
||||
.enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK,
|
||||
.vsel_reg = MAX77836_LDO_REG_CNFG1_LDO1,
|
||||
.vsel_mask = MAX77836_CNFG1_LDO_TV_MASK,
|
||||
},
|
||||
[MAX77836_LDO2] = {
|
||||
.name = "LDO2",
|
||||
.of_match = of_match_ptr("LDO2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.id = MAX77836_LDO2,
|
||||
.ops = &max77836_ldo_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = MAX77836_REGULATOR_LDO_VOLTAGE_STEPS_NUM,
|
||||
.min_uV = MAX77836_REGULATOR_LDO_VOLTAGE_MIN,
|
||||
.uV_step = MAX77836_REGULATOR_LDO_VOLTAGE_STEP,
|
||||
.enable_reg = MAX77836_LDO_REG_CNFG1_LDO2,
|
||||
.enable_mask = MAX77836_CNFG1_LDO_PWRMD_MASK,
|
||||
.vsel_reg = MAX77836_LDO_REG_CNFG1_LDO2,
|
||||
.vsel_mask = MAX77836_CNFG1_LDO_TV_MASK,
|
||||
},
|
||||
[MAX14577_SAFEOUT] = MAX14577_SAFEOUT_REG,
|
||||
[MAX14577_CHARGER] = MAX14577_CHARGER_REG,
|
||||
[MAX77836_LDO1] = MAX77836_LDO_REG(1),
|
||||
[MAX77836_LDO2] = MAX77836_LDO_REG(2),
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
@ -2,7 +2,7 @@
|
||||
* max77686.c - Regulator driver for the Maxim 77686
|
||||
*
|
||||
* Copyright (C) 2012 Samsung Electronics
|
||||
* Chiwoong Byun <woong.byun@smasung.com>
|
||||
* Chiwoong Byun <woong.byun@samsung.com>
|
||||
* Jonghwa Lee <jonghwa3.lee@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
@ -88,7 +88,7 @@ enum max77686_ramp_rate {
|
||||
};
|
||||
|
||||
struct max77686_data {
|
||||
u64 gpio_enabled:MAX77686_REGULATORS;
|
||||
DECLARE_BITMAP(gpio_enabled, MAX77686_REGULATORS);
|
||||
|
||||
/* Array indexed by regulator id */
|
||||
unsigned int opmode[MAX77686_REGULATORS];
|
||||
@ -121,7 +121,7 @@ static unsigned int max77686_map_normal_mode(struct max77686_data *max77686,
|
||||
case MAX77686_BUCK8:
|
||||
case MAX77686_BUCK9:
|
||||
case MAX77686_LDO20 ... MAX77686_LDO22:
|
||||
if (max77686->gpio_enabled & (1 << id))
|
||||
if (test_bit(id, max77686->gpio_enabled))
|
||||
return MAX77686_GPIO_CONTROL;
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ static int max77686_of_parse_cb(struct device_node *np,
|
||||
}
|
||||
|
||||
if (gpio_is_valid(config->ena_gpio)) {
|
||||
max77686->gpio_enabled |= (1 << desc->id);
|
||||
set_bit(desc->id, max77686->gpio_enabled);
|
||||
|
||||
return regmap_update_bits(config->regmap, desc->enable_reg,
|
||||
desc->enable_mask,
|
||||
|
@ -35,20 +35,6 @@
|
||||
|
||||
#define CHGIN_ILIM_STEP_20mA 20000
|
||||
|
||||
/* CHARGER regulator ops */
|
||||
/* CHARGER regulator uses two bits for enabling */
|
||||
static int max77693_chg_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
int ret;
|
||||
unsigned int val;
|
||||
|
||||
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return (val & rdev->desc->enable_mask) == rdev->desc->enable_mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA
|
||||
* 0x00, 0x01, 0x2, 0x03 = 60 mA
|
||||
@ -118,7 +104,7 @@ static struct regulator_ops max77693_safeout_ops = {
|
||||
};
|
||||
|
||||
static struct regulator_ops max77693_charger_ops = {
|
||||
.is_enabled = max77693_chg_is_enabled,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_current_limit = max77693_chg_get_current_limit,
|
||||
@ -155,6 +141,7 @@ static const struct regulator_desc regulators[] = {
|
||||
.enable_reg = MAX77693_CHG_REG_CHG_CNFG_00,
|
||||
.enable_mask = CHG_CNFG_00_CHG_MASK |
|
||||
CHG_CNFG_00_BUCK_MASK,
|
||||
.enable_val = CHG_CNFG_00_CHG_MASK | CHG_CNFG_00_BUCK_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -33,21 +33,6 @@ static const unsigned int max77843_safeout_voltage_table[] = {
|
||||
3300000,
|
||||
};
|
||||
|
||||
static int max77843_reg_is_enabled(struct regulator_dev *rdev)
|
||||
{
|
||||
struct regmap *regmap = rdev->regmap;
|
||||
int ret;
|
||||
unsigned int reg;
|
||||
|
||||
ret = regmap_read(regmap, rdev->desc->enable_reg, ®);
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Fialed to read charger register\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return (reg & rdev->desc->enable_mask) == rdev->desc->enable_mask;
|
||||
}
|
||||
|
||||
static int max77843_reg_get_current_limit(struct regulator_dev *rdev)
|
||||
{
|
||||
struct regmap *regmap = rdev->regmap;
|
||||
@ -96,7 +81,7 @@ static int max77843_reg_set_current_limit(struct regulator_dev *rdev,
|
||||
}
|
||||
|
||||
static struct regulator_ops max77843_charger_ops = {
|
||||
.is_enabled = max77843_reg_is_enabled,
|
||||
.is_enabled = regulator_is_enabled_regmap,
|
||||
.enable = regulator_enable_regmap,
|
||||
.disable = regulator_disable_regmap,
|
||||
.get_current_limit = max77843_reg_get_current_limit,
|
||||
@ -112,37 +97,25 @@ static struct regulator_ops max77843_regulator_ops = {
|
||||
.set_voltage_sel = regulator_set_voltage_sel_regmap,
|
||||
};
|
||||
|
||||
#define MAX77843_SAFEOUT(num) { \
|
||||
.name = "SAFEOUT" # num, \
|
||||
.id = MAX77843_SAFEOUT ## num, \
|
||||
.ops = &max77843_regulator_ops, \
|
||||
.of_match = of_match_ptr("SAFEOUT" # num), \
|
||||
.regulators_node = of_match_ptr("regulators"), \
|
||||
.type = REGULATOR_VOLTAGE, \
|
||||
.owner = THIS_MODULE, \
|
||||
.n_voltages = ARRAY_SIZE(max77843_safeout_voltage_table), \
|
||||
.volt_table = max77843_safeout_voltage_table, \
|
||||
.enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL, \
|
||||
.enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT ## num, \
|
||||
.vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL, \
|
||||
.vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT ## num ## _MASK, \
|
||||
}
|
||||
|
||||
static const struct regulator_desc max77843_supported_regulators[] = {
|
||||
[MAX77843_SAFEOUT1] = {
|
||||
.name = "SAFEOUT1",
|
||||
.id = MAX77843_SAFEOUT1,
|
||||
.ops = &max77843_regulator_ops,
|
||||
.of_match = of_match_ptr("SAFEOUT1"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(max77843_safeout_voltage_table),
|
||||
.volt_table = max77843_safeout_voltage_table,
|
||||
.enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL,
|
||||
.enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT1,
|
||||
.vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL,
|
||||
.vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT1_MASK,
|
||||
},
|
||||
[MAX77843_SAFEOUT2] = {
|
||||
.name = "SAFEOUT2",
|
||||
.id = MAX77843_SAFEOUT2,
|
||||
.ops = &max77843_regulator_ops,
|
||||
.of_match = of_match_ptr("SAFEOUT2"),
|
||||
.regulators_node = of_match_ptr("regulators"),
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
.owner = THIS_MODULE,
|
||||
.n_voltages = ARRAY_SIZE(max77843_safeout_voltage_table),
|
||||
.volt_table = max77843_safeout_voltage_table,
|
||||
.enable_reg = MAX77843_SYS_REG_SAFEOUTCTRL,
|
||||
.enable_mask = MAX77843_REG_SAFEOUTCTRL_ENSAFEOUT2,
|
||||
.vsel_reg = MAX77843_SYS_REG_SAFEOUTCTRL,
|
||||
.vsel_mask = MAX77843_REG_SAFEOUTCTRL_SAFEOUT2_MASK,
|
||||
},
|
||||
[MAX77843_SAFEOUT1] = MAX77843_SAFEOUT(1),
|
||||
[MAX77843_SAFEOUT2] = MAX77843_SAFEOUT(2),
|
||||
[MAX77843_CHARGER] = {
|
||||
.name = "CHARGER",
|
||||
.id = MAX77843_CHARGER,
|
||||
@ -152,7 +125,8 @@ static const struct regulator_desc max77843_supported_regulators[] = {
|
||||
.type = REGULATOR_CURRENT,
|
||||
.owner = THIS_MODULE,
|
||||
.enable_reg = MAX77843_CHG_REG_CHG_CNFG_00,
|
||||
.enable_mask = MAX77843_CHG_MASK,
|
||||
.enable_mask = MAX77843_CHG_MASK | MAX77843_CHG_BUCK_MASK,
|
||||
.enable_val = MAX77843_CHG_MASK | MAX77843_CHG_BUCK_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -27,12 +27,14 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/regulator/driver.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/regulator/max8973-regulator.h>
|
||||
#include <linux/regulator/of_regulator.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regmap.h>
|
||||
@ -66,6 +68,7 @@
|
||||
#define MAX8973_RAMP_25mV_PER_US 0x1
|
||||
#define MAX8973_RAMP_50mV_PER_US 0x2
|
||||
#define MAX8973_RAMP_200mV_PER_US 0x3
|
||||
#define MAX8973_RAMP_MASK 0x3
|
||||
|
||||
/* MAX8973_CONTROL2 */
|
||||
#define MAX8973_WDTMR_ENABLE BIT(6)
|
||||
@ -89,19 +92,25 @@
|
||||
#define MAX8973_VOLATGE_STEP 6250
|
||||
#define MAX8973_BUCK_N_VOLTAGE 0x80
|
||||
|
||||
enum device_id {
|
||||
MAX8973,
|
||||
MAX77621
|
||||
};
|
||||
|
||||
/* Maxim 8973 chip information */
|
||||
struct max8973_chip {
|
||||
struct device *dev;
|
||||
struct regulator_desc desc;
|
||||
struct regmap *regmap;
|
||||
bool enable_external_control;
|
||||
int enable_gpio;
|
||||
int dvs_gpio;
|
||||
int lru_index[MAX8973_MAX_VOUT_REG];
|
||||
int curr_vout_val[MAX8973_MAX_VOUT_REG];
|
||||
int curr_vout_reg;
|
||||
int curr_gpio_val;
|
||||
bool valid_dvs_gpio;
|
||||
struct regulator_ops ops;
|
||||
enum device_id id;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -174,7 +183,7 @@ static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev,
|
||||
* If gpios are available to select the VOUT register then least
|
||||
* recently used register for new configuration.
|
||||
*/
|
||||
if (max->valid_dvs_gpio)
|
||||
if (gpio_is_valid(max->dvs_gpio))
|
||||
found = find_voltage_set_register(max, vsel,
|
||||
&vout_reg, &gpio_val);
|
||||
|
||||
@ -191,7 +200,7 @@ static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev,
|
||||
}
|
||||
|
||||
/* Select proper VOUT register vio gpios */
|
||||
if (max->valid_dvs_gpio) {
|
||||
if (gpio_is_valid(max->dvs_gpio)) {
|
||||
gpio_set_value_cansleep(max->dvs_gpio, gpio_val & 0x1);
|
||||
max->curr_gpio_val = gpio_val;
|
||||
}
|
||||
@ -242,12 +251,45 @@ static unsigned int max8973_dcdc_get_mode(struct regulator_dev *rdev)
|
||||
REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
|
||||
}
|
||||
|
||||
static int max8973_set_ramp_delay(struct regulator_dev *rdev,
|
||||
int ramp_delay)
|
||||
{
|
||||
struct max8973_chip *max = rdev_get_drvdata(rdev);
|
||||
unsigned int control;
|
||||
int ret;
|
||||
int ret_val;
|
||||
|
||||
/* Set ramp delay */
|
||||
if (ramp_delay < 25000) {
|
||||
control = MAX8973_RAMP_12mV_PER_US;
|
||||
ret_val = 12000;
|
||||
} else if (ramp_delay < 50000) {
|
||||
control = MAX8973_RAMP_25mV_PER_US;
|
||||
ret_val = 25000;
|
||||
} else if (ramp_delay < 200000) {
|
||||
control = MAX8973_RAMP_50mV_PER_US;
|
||||
ret_val = 50000;
|
||||
} else {
|
||||
control = MAX8973_RAMP_200mV_PER_US;
|
||||
ret_val = 200000;
|
||||
}
|
||||
|
||||
ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1,
|
||||
MAX8973_RAMP_MASK, control);
|
||||
if (ret < 0)
|
||||
dev_err(max->dev, "register %d update failed, %d",
|
||||
MAX8973_CONTROL1, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct regulator_ops max8973_dcdc_ops = {
|
||||
.get_voltage_sel = max8973_dcdc_get_voltage_sel,
|
||||
.set_voltage_sel = max8973_dcdc_set_voltage_sel,
|
||||
.list_voltage = regulator_list_voltage_linear,
|
||||
.set_mode = max8973_dcdc_set_mode,
|
||||
.get_mode = max8973_dcdc_get_mode,
|
||||
.set_voltage_time_sel = regulator_set_voltage_time_sel,
|
||||
.set_ramp_delay = max8973_set_ramp_delay,
|
||||
};
|
||||
|
||||
static int max8973_init_dcdc(struct max8973_chip *max,
|
||||
@ -256,6 +298,29 @@ static int max8973_init_dcdc(struct max8973_chip *max,
|
||||
int ret;
|
||||
uint8_t control1 = 0;
|
||||
uint8_t control2 = 0;
|
||||
unsigned int data;
|
||||
|
||||
ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "register %d read failed, err = %d",
|
||||
MAX8973_CONTROL1, ret);
|
||||
return ret;
|
||||
}
|
||||
control1 = data & MAX8973_RAMP_MASK;
|
||||
switch (control1) {
|
||||
case MAX8973_RAMP_12mV_PER_US:
|
||||
max->desc.ramp_delay = 12000;
|
||||
break;
|
||||
case MAX8973_RAMP_25mV_PER_US:
|
||||
max->desc.ramp_delay = 25000;
|
||||
break;
|
||||
case MAX8973_RAMP_50mV_PER_US:
|
||||
max->desc.ramp_delay = 50000;
|
||||
break;
|
||||
case MAX8973_RAMP_200mV_PER_US:
|
||||
max->desc.ramp_delay = 200000;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE)
|
||||
control1 |= MAX8973_SNS_ENABLE;
|
||||
@ -266,28 +331,16 @@ static int max8973_init_dcdc(struct max8973_chip *max,
|
||||
if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE)
|
||||
control1 |= MAX8973_AD_ENABLE;
|
||||
|
||||
if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE)
|
||||
if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE) {
|
||||
control1 |= MAX8973_BIAS_ENABLE;
|
||||
max->desc.enable_time = 20;
|
||||
} else {
|
||||
max->desc.enable_time = 240;
|
||||
}
|
||||
|
||||
if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE)
|
||||
control1 |= MAX8973_FREQSHIFT_9PER;
|
||||
|
||||
/* Set ramp delay */
|
||||
if (pdata->reg_init_data &&
|
||||
pdata->reg_init_data->constraints.ramp_delay) {
|
||||
if (pdata->reg_init_data->constraints.ramp_delay < 25000)
|
||||
control1 |= MAX8973_RAMP_12mV_PER_US;
|
||||
else if (pdata->reg_init_data->constraints.ramp_delay < 50000)
|
||||
control1 |= MAX8973_RAMP_25mV_PER_US;
|
||||
else if (pdata->reg_init_data->constraints.ramp_delay < 200000)
|
||||
control1 |= MAX8973_RAMP_50mV_PER_US;
|
||||
else
|
||||
control1 |= MAX8973_RAMP_200mV_PER_US;
|
||||
} else {
|
||||
control1 |= MAX8973_RAMP_12mV_PER_US;
|
||||
max->desc.ramp_delay = 12500;
|
||||
}
|
||||
|
||||
if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE))
|
||||
control2 |= MAX8973_DISCH_ENBABLE;
|
||||
|
||||
@ -344,7 +397,7 @@ static int max8973_init_dcdc(struct max8973_chip *max,
|
||||
}
|
||||
|
||||
/* If external control is enabled then disable EN bit */
|
||||
if (max->enable_external_control) {
|
||||
if (max->enable_external_control && (max->id == MAX8973)) {
|
||||
ret = regmap_update_bits(max->regmap, MAX8973_VOUT,
|
||||
MAX8973_VOUT_ENABLE, 0);
|
||||
if (ret < 0)
|
||||
@ -361,22 +414,82 @@ static const struct regmap_config max8973_regmap_config = {
|
||||
.cache_type = REGCACHE_RBTREE,
|
||||
};
|
||||
|
||||
static struct max8973_regulator_platform_data *max8973_parse_dt(
|
||||
struct device *dev)
|
||||
{
|
||||
struct max8973_regulator_platform_data *pdata;
|
||||
struct device_node *np = dev->of_node;
|
||||
int ret;
|
||||
u32 pval;
|
||||
|
||||
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
|
||||
if (!pdata)
|
||||
return NULL;
|
||||
|
||||
pdata->enable_ext_control = of_property_read_bool(np,
|
||||
"maxim,externally-enable");
|
||||
pdata->enable_gpio = of_get_named_gpio(np, "maxim,enable-gpio", 0);
|
||||
pdata->dvs_gpio = of_get_named_gpio(np, "maxim,dvs-gpio", 0);
|
||||
|
||||
ret = of_property_read_u32(np, "maxim,dvs-default-state", &pval);
|
||||
if (!ret)
|
||||
pdata->dvs_def_state = pval;
|
||||
|
||||
if (of_property_read_bool(np, "maxim,enable-remote-sense"))
|
||||
pdata->control_flags |= MAX8973_CONTROL_REMOTE_SENSE_ENABLE;
|
||||
|
||||
if (of_property_read_bool(np, "maxim,enable-falling-slew-rate"))
|
||||
pdata->control_flags |=
|
||||
MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE;
|
||||
|
||||
if (of_property_read_bool(np, "maxim,enable-active-discharge"))
|
||||
pdata->control_flags |=
|
||||
MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE;
|
||||
|
||||
if (of_property_read_bool(np, "maxim,enable-frequency-shift"))
|
||||
pdata->control_flags |= MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE;
|
||||
|
||||
if (of_property_read_bool(np, "maxim,enable-bias-control"))
|
||||
pdata->control_flags |= MAX8973_BIAS_ENABLE;
|
||||
|
||||
return pdata;
|
||||
}
|
||||
|
||||
static const struct of_device_id of_max8973_match_tbl[] = {
|
||||
{ .compatible = "maxim,max8973", .data = (void *)MAX8973, },
|
||||
{ .compatible = "maxim,max77621", .data = (void *)MAX77621, },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, of_max8973_match_tbl);
|
||||
|
||||
static int max8973_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct max8973_regulator_platform_data *pdata;
|
||||
struct regulator_init_data *ridata;
|
||||
struct regulator_config config = { };
|
||||
struct regulator_dev *rdev;
|
||||
struct max8973_chip *max;
|
||||
bool pdata_from_dt = false;
|
||||
unsigned int chip_id;
|
||||
int ret;
|
||||
|
||||
pdata = dev_get_platdata(&client->dev);
|
||||
|
||||
if (!pdata && !client->dev.of_node) {
|
||||
if (!pdata && client->dev.of_node) {
|
||||
pdata = max8973_parse_dt(&client->dev);
|
||||
pdata_from_dt = true;
|
||||
}
|
||||
|
||||
if (!pdata) {
|
||||
dev_err(&client->dev, "No Platform data");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if ((pdata->dvs_gpio == -EPROBE_DEFER) ||
|
||||
(pdata->enable_gpio == -EPROBE_DEFER))
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
|
||||
if (!max)
|
||||
return -ENOMEM;
|
||||
@ -388,6 +501,27 @@ static int max8973_probe(struct i2c_client *client,
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (client->dev.of_node) {
|
||||
const struct of_device_id *match;
|
||||
|
||||
match = of_match_device(of_match_ptr(of_max8973_match_tbl),
|
||||
&client->dev);
|
||||
if (!match)
|
||||
return -ENODATA;
|
||||
max->id = (u32)((uintptr_t)match->data);
|
||||
} else {
|
||||
max->id = id->driver_data;
|
||||
}
|
||||
|
||||
ret = regmap_read(max->regmap, MAX8973_CHIPID1, &chip_id);
|
||||
if (ret < 0) {
|
||||
dev_err(&client->dev, "register CHIPID1 read failed, %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&client->dev, "CHIP-ID OTP: 0x%02x ID_M: 0x%02x\n",
|
||||
(chip_id >> 4) & 0xF, (chip_id >> 1) & 0x7);
|
||||
|
||||
i2c_set_clientdata(client, max);
|
||||
max->ops = max8973_dcdc_ops;
|
||||
max->dev = &client->dev;
|
||||
@ -400,23 +534,14 @@ static int max8973_probe(struct i2c_client *client,
|
||||
max->desc.uV_step = MAX8973_VOLATGE_STEP;
|
||||
max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE;
|
||||
|
||||
if (!pdata || !pdata->enable_ext_control) {
|
||||
max->desc.enable_reg = MAX8973_VOUT;
|
||||
max->desc.enable_mask = MAX8973_VOUT_ENABLE;
|
||||
max->ops.enable = regulator_enable_regmap;
|
||||
max->ops.disable = regulator_disable_regmap;
|
||||
max->ops.is_enabled = regulator_is_enabled_regmap;
|
||||
}
|
||||
max->dvs_gpio = (pdata->dvs_gpio) ? pdata->dvs_gpio : -EINVAL;
|
||||
max->enable_gpio = (pdata->enable_gpio) ? pdata->enable_gpio : -EINVAL;
|
||||
max->enable_external_control = pdata->enable_ext_control;
|
||||
max->curr_gpio_val = pdata->dvs_def_state;
|
||||
max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state;
|
||||
|
||||
if (pdata) {
|
||||
max->dvs_gpio = pdata->dvs_gpio;
|
||||
max->enable_external_control = pdata->enable_ext_control;
|
||||
max->curr_gpio_val = pdata->dvs_def_state;
|
||||
max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state;
|
||||
} else {
|
||||
max->dvs_gpio = -EINVAL;
|
||||
max->curr_vout_reg = MAX8973_VOUT;
|
||||
}
|
||||
if (gpio_is_valid(max->enable_gpio))
|
||||
max->enable_external_control = true;
|
||||
|
||||
max->lru_index[0] = max->curr_vout_reg;
|
||||
|
||||
@ -434,7 +559,6 @@ static int max8973_probe(struct i2c_client *client,
|
||||
max->dvs_gpio, ret);
|
||||
return ret;
|
||||
}
|
||||
max->valid_dvs_gpio = true;
|
||||
|
||||
/*
|
||||
* Initialize the lru index with vout_reg id
|
||||
@ -444,22 +568,64 @@ static int max8973_probe(struct i2c_client *client,
|
||||
max->lru_index[i] = i;
|
||||
max->lru_index[0] = max->curr_vout_reg;
|
||||
max->lru_index[max->curr_vout_reg] = 0;
|
||||
} else {
|
||||
max->valid_dvs_gpio = false;
|
||||
}
|
||||
|
||||
if (pdata) {
|
||||
ret = max8973_init_dcdc(max, pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
|
||||
return ret;
|
||||
if (pdata_from_dt)
|
||||
pdata->reg_init_data = of_get_regulator_init_data(&client->dev,
|
||||
client->dev.of_node, &max->desc);
|
||||
|
||||
ridata = pdata->reg_init_data;
|
||||
switch (max->id) {
|
||||
case MAX8973:
|
||||
if (!pdata->enable_ext_control) {
|
||||
max->desc.enable_reg = MAX8973_VOUT;
|
||||
max->desc.enable_mask = MAX8973_VOUT_ENABLE;
|
||||
max->ops.enable = regulator_enable_regmap;
|
||||
max->ops.disable = regulator_disable_regmap;
|
||||
max->ops.is_enabled = regulator_is_enabled_regmap;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(max->enable_gpio)) {
|
||||
config.ena_gpio_flags = GPIOF_OUT_INIT_LOW;
|
||||
if (ridata && (ridata->constraints.always_on ||
|
||||
ridata->constraints.boot_on))
|
||||
config.ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
|
||||
config.ena_gpio = max->enable_gpio;
|
||||
}
|
||||
break;
|
||||
|
||||
case MAX77621:
|
||||
if (gpio_is_valid(max->enable_gpio)) {
|
||||
ret = devm_gpio_request_one(&client->dev,
|
||||
max->enable_gpio, GPIOF_OUT_INIT_HIGH,
|
||||
"max8973-en-gpio");
|
||||
if (ret) {
|
||||
dev_err(&client->dev,
|
||||
"gpio_request for gpio %d failed: %d\n",
|
||||
max->enable_gpio, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
max->desc.enable_reg = MAX8973_VOUT;
|
||||
max->desc.enable_mask = MAX8973_VOUT_ENABLE;
|
||||
max->ops.enable = regulator_enable_regmap;
|
||||
max->ops.disable = regulator_disable_regmap;
|
||||
max->ops.is_enabled = regulator_is_enabled_regmap;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = max8973_init_dcdc(max, pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
config.dev = &client->dev;
|
||||
config.init_data = pdata ? pdata->reg_init_data :
|
||||
of_get_regulator_init_data(&client->dev, client->dev.of_node,
|
||||
&max->desc);
|
||||
config.init_data = pdata->reg_init_data;
|
||||
config.driver_data = max;
|
||||
config.of_node = client->dev.of_node;
|
||||
config.regmap = max->regmap;
|
||||
@ -476,15 +642,16 @@ static int max8973_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
static const struct i2c_device_id max8973_id[] = {
|
||||
{.name = "max8973",},
|
||||
{.name = "max8973", .driver_data = MAX8973},
|
||||
{.name = "max77621", .driver_data = MAX77621},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(i2c, max8973_id);
|
||||
|
||||
static struct i2c_driver max8973_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "max8973",
|
||||
.of_match_table = of_max8973_match_tbl,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = max8973_probe,
|
||||
|
@ -58,6 +58,10 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
if (!of_property_read_u32(np, "regulator-max-microamp", &pval))
|
||||
constraints->max_uA = pval;
|
||||
|
||||
if (!of_property_read_u32(np, "regulator-input-current-limit-microamp",
|
||||
&pval))
|
||||
constraints->ilim_uA = pval;
|
||||
|
||||
/* Current change possible? */
|
||||
if (constraints->min_uA != constraints->max_uA)
|
||||
constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT;
|
||||
@ -67,6 +71,8 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
if (!constraints->always_on) /* status change should be possible. */
|
||||
constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
|
||||
|
||||
constraints->pull_down = of_property_read_bool(np, "regulator-pull-down");
|
||||
|
||||
if (of_property_read_bool(np, "regulator-allow-bypass"))
|
||||
constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS;
|
||||
|
||||
@ -82,6 +88,9 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
if (!ret)
|
||||
constraints->enable_time = pval;
|
||||
|
||||
constraints->soft_start = of_property_read_bool(np,
|
||||
"regulator-soft-start");
|
||||
|
||||
if (!of_property_read_u32(np, "regulator-initial-mode", &pval)) {
|
||||
if (desc && desc->of_map_mode) {
|
||||
ret = desc->of_map_mode(pval);
|
||||
@ -95,6 +104,9 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
}
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(np, "regulator-system-load", &pval))
|
||||
constraints->system_load = pval;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(regulator_states); i++) {
|
||||
switch (i) {
|
||||
case PM_SUSPEND_MEM:
|
||||
@ -108,7 +120,7 @@ static void of_get_regulation_constraints(struct device_node *np,
|
||||
case PM_SUSPEND_STANDBY:
|
||||
default:
|
||||
continue;
|
||||
};
|
||||
}
|
||||
|
||||
suspend_np = of_get_child_by_name(np, regulator_states[i]);
|
||||
if (!suspend_np || !suspend_state)
|
||||
@ -292,7 +304,7 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for_each_child_of_node(search, child) {
|
||||
for_each_available_child_of_node(search, child) {
|
||||
name = of_get_property(child, "regulator-compatible", NULL);
|
||||
if (!name)
|
||||
name = child->name;
|
||||
|
@ -21,10 +21,8 @@
|
||||
#include <linux/pwm.h>
|
||||
|
||||
struct pwm_regulator_data {
|
||||
struct regulator_desc desc;
|
||||
struct pwm_voltages *duty_cycle_table;
|
||||
struct pwm_device *pwm;
|
||||
bool enabled;
|
||||
int state;
|
||||
};
|
||||
|
||||
@ -33,17 +31,17 @@ struct pwm_voltages {
|
||||
unsigned int dutycycle;
|
||||
};
|
||||
|
||||
static int pwm_regulator_get_voltage_sel(struct regulator_dev *dev)
|
||||
static int pwm_regulator_get_voltage_sel(struct regulator_dev *rdev)
|
||||
{
|
||||
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
|
||||
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
|
||||
|
||||
return drvdata->state;
|
||||
}
|
||||
|
||||
static int pwm_regulator_set_voltage_sel(struct regulator_dev *dev,
|
||||
static int pwm_regulator_set_voltage_sel(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
|
||||
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
|
||||
unsigned int pwm_reg_period;
|
||||
int dutycycle;
|
||||
int ret;
|
||||
@ -55,30 +53,27 @@ static int pwm_regulator_set_voltage_sel(struct regulator_dev *dev,
|
||||
|
||||
ret = pwm_config(drvdata->pwm, dutycycle, pwm_reg_period);
|
||||
if (ret) {
|
||||
dev_err(&dev->dev, "Failed to configure PWM\n");
|
||||
dev_err(&rdev->dev, "Failed to configure PWM\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
drvdata->state = selector;
|
||||
|
||||
if (!drvdata->enabled) {
|
||||
ret = pwm_enable(drvdata->pwm);
|
||||
if (ret) {
|
||||
dev_err(&dev->dev, "Failed to enable PWM\n");
|
||||
return ret;
|
||||
}
|
||||
drvdata->enabled = true;
|
||||
ret = pwm_enable(drvdata->pwm);
|
||||
if (ret) {
|
||||
dev_err(&rdev->dev, "Failed to enable PWM\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pwm_regulator_list_voltage(struct regulator_dev *dev,
|
||||
static int pwm_regulator_list_voltage(struct regulator_dev *rdev,
|
||||
unsigned selector)
|
||||
{
|
||||
struct pwm_regulator_data *drvdata = rdev_get_drvdata(dev);
|
||||
struct pwm_regulator_data *drvdata = rdev_get_drvdata(rdev);
|
||||
|
||||
if (selector >= drvdata->desc.n_voltages)
|
||||
if (selector >= rdev->desc->n_voltages)
|
||||
return -EINVAL;
|
||||
|
||||
return drvdata->duty_cycle_table[selector].uV;
|
||||
@ -91,7 +86,7 @@ static struct regulator_ops pwm_regulator_voltage_ops = {
|
||||
.map_voltage = regulator_map_voltage_iterate,
|
||||
};
|
||||
|
||||
static const struct regulator_desc pwm_regulator_desc = {
|
||||
static struct regulator_desc pwm_regulator_desc = {
|
||||
.name = "pwm-regulator",
|
||||
.ops = &pwm_regulator_voltage_ops,
|
||||
.type = REGULATOR_VOLTAGE,
|
||||
@ -117,8 +112,6 @@ static int pwm_regulator_probe(struct platform_device *pdev)
|
||||
if (!drvdata)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(&drvdata->desc, &pwm_regulator_desc, sizeof(pwm_regulator_desc));
|
||||
|
||||
/* determine the number of voltage-table */
|
||||
prop = of_find_property(np, "voltage-table", &length);
|
||||
if (!prop) {
|
||||
@ -133,7 +126,7 @@ static int pwm_regulator_probe(struct platform_device *pdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
drvdata->desc.n_voltages = length / sizeof(*drvdata->duty_cycle_table);
|
||||
pwm_regulator_desc.n_voltages = length / sizeof(*drvdata->duty_cycle_table);
|
||||
|
||||
drvdata->duty_cycle_table = devm_kzalloc(&pdev->dev,
|
||||
length, GFP_KERNEL);
|
||||
@ -150,7 +143,7 @@ static int pwm_regulator_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
config.init_data = of_get_regulator_init_data(&pdev->dev, np,
|
||||
&drvdata->desc);
|
||||
&pwm_regulator_desc);
|
||||
if (!config.init_data)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -165,10 +158,10 @@ static int pwm_regulator_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
regulator = devm_regulator_register(&pdev->dev,
|
||||
&drvdata->desc, &config);
|
||||
&pwm_regulator_desc, &config);
|
||||
if (IS_ERR(regulator)) {
|
||||
dev_err(&pdev->dev, "Failed to register regulator %s\n",
|
||||
drvdata->desc.name);
|
||||
pwm_regulator_desc.name);
|
||||
return PTR_ERR(regulator);
|
||||
}
|
||||
|
||||
|
1435
drivers/regulator/qcom_spmi-regulator.c
Normal file
1435
drivers/regulator/qcom_spmi-regulator.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -515,7 +515,7 @@ static int s2mps14_regulator_enable(struct regulator_dev *rdev)
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
|
||||
rdev->desc->enable_mask, val);
|
||||
@ -538,7 +538,7 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
|
||||
default:
|
||||
state = S2MPS14_ENABLE_SUSPEND;
|
||||
break;
|
||||
};
|
||||
}
|
||||
break;
|
||||
case S2MPU02:
|
||||
switch (rdev_id) {
|
||||
@ -552,11 +552,11 @@ static int s2mps14_regulator_set_suspend_disable(struct regulator_dev *rdev)
|
||||
default:
|
||||
state = S2MPU02_ENABLE_SUSPEND;
|
||||
break;
|
||||
};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
|
||||
if (ret < 0)
|
||||
@ -977,7 +977,7 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "Invalid device type: %u\n",
|
||||
s2mps11->dev_type);
|
||||
return -EINVAL;
|
||||
};
|
||||
}
|
||||
|
||||
s2mps11->ext_control_gpio = devm_kmalloc(&pdev->dev,
|
||||
sizeof(*s2mps11->ext_control_gpio) * s2mps11->rdev_num,
|
||||
|
@ -533,7 +533,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
|
||||
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
wm831x_dcdc_uv_irq,
|
||||
IRQF_TRIGGER_RISING, dcdc->name, dcdc);
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
dcdc->name, dcdc);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
|
||||
irq, ret);
|
||||
@ -543,7 +544,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
|
||||
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
wm831x_dcdc_oc_irq,
|
||||
IRQF_TRIGGER_RISING, dcdc->name, dcdc);
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
dcdc->name, dcdc);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",
|
||||
irq, ret);
|
||||
@ -669,7 +671,8 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
|
||||
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
wm831x_dcdc_uv_irq,
|
||||
IRQF_TRIGGER_RISING, dcdc->name, dcdc);
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
dcdc->name, dcdc);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
|
||||
irq, ret);
|
||||
@ -785,7 +788,8 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
|
||||
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
wm831x_dcdc_uv_irq,
|
||||
IRQF_TRIGGER_RISING, dcdc->name,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
dcdc->name,
|
||||
dcdc);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
|
||||
|
@ -204,7 +204,8 @@ static int wm831x_isink_probe(struct platform_device *pdev)
|
||||
irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
wm831x_isink_irq,
|
||||
IRQF_TRIGGER_RISING, isink->name,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
isink->name,
|
||||
isink);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
|
||||
|
@ -287,7 +287,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
|
||||
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
wm831x_ldo_uv_irq,
|
||||
IRQF_TRIGGER_RISING, ldo->name,
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
ldo->name,
|
||||
ldo);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
|
||||
@ -496,7 +497,8 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
|
||||
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
|
||||
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
wm831x_ldo_uv_irq,
|
||||
IRQF_TRIGGER_RISING, ldo->name, ldo);
|
||||
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
|
||||
ldo->name, ldo);
|
||||
if (ret != 0) {
|
||||
dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
|
||||
irq, ret);
|
||||
|
@ -91,6 +91,7 @@ struct regulator_linear_range {
|
||||
* @set_current_limit: Configure a limit for a current-limited regulator.
|
||||
* The driver should select the current closest to max_uA.
|
||||
* @get_current_limit: Get the configured limit for a current-limited regulator.
|
||||
* @set_input_current_limit: Configure an input limit.
|
||||
*
|
||||
* @set_mode: Set the configured operating mode for the regulator.
|
||||
* @get_mode: Get the configured operating mode for the regulator.
|
||||
@ -111,6 +112,7 @@ struct regulator_linear_range {
|
||||
* to stabilise after being set to a new value, in microseconds.
|
||||
* The function provides the from and to voltage selector, the
|
||||
* function should return the worst case.
|
||||
* @set_soft_start: Enable soft start for the regulator.
|
||||
*
|
||||
* @set_suspend_voltage: Set the voltage for the regulator when the system
|
||||
* is suspended.
|
||||
@ -121,6 +123,9 @@ struct regulator_linear_range {
|
||||
* @set_suspend_mode: Set the operating mode for the regulator when the
|
||||
* system is suspended.
|
||||
*
|
||||
* @set_pull_down: Configure the regulator to pull down when the regulator
|
||||
* is disabled.
|
||||
*
|
||||
* This struct describes regulator operations which can be implemented by
|
||||
* regulator chip drivers.
|
||||
*/
|
||||
@ -142,6 +147,8 @@ struct regulator_ops {
|
||||
int min_uA, int max_uA);
|
||||
int (*get_current_limit) (struct regulator_dev *);
|
||||
|
||||
int (*set_input_current_limit) (struct regulator_dev *, int lim_uA);
|
||||
|
||||
/* enable/disable regulator */
|
||||
int (*enable) (struct regulator_dev *);
|
||||
int (*disable) (struct regulator_dev *);
|
||||
@ -158,6 +165,8 @@ struct regulator_ops {
|
||||
unsigned int old_selector,
|
||||
unsigned int new_selector);
|
||||
|
||||
int (*set_soft_start) (struct regulator_dev *);
|
||||
|
||||
/* report regulator status ... most other accessors report
|
||||
* control inputs, this reports results of combining inputs
|
||||
* from Linux (and other sources) with the actual load.
|
||||
@ -187,6 +196,8 @@ struct regulator_ops {
|
||||
|
||||
/* set regulator suspend operating mode (defined in consumer.h) */
|
||||
int (*set_suspend_mode) (struct regulator_dev *, unsigned int mode);
|
||||
|
||||
int (*set_pull_down) (struct regulator_dev *);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -75,6 +75,8 @@ struct regulator_state {
|
||||
*
|
||||
* @min_uA: Smallest current consumers may set.
|
||||
* @max_uA: Largest current consumers may set.
|
||||
* @ilim_uA: Maximum input current.
|
||||
* @system_load: Load that isn't captured by any consumer requests.
|
||||
*
|
||||
* @valid_modes_mask: Mask of modes which may be configured by consumers.
|
||||
* @valid_ops_mask: Operations which may be performed by consumers.
|
||||
@ -86,6 +88,8 @@ struct regulator_state {
|
||||
* applied.
|
||||
* @apply_uV: Apply the voltage constraint when initialising.
|
||||
* @ramp_disable: Disable ramp delay when initialising or when setting voltage.
|
||||
* @soft_start: Enable soft start so that voltage ramps slowly.
|
||||
* @pull_down: Enable pull down when regulator is disabled.
|
||||
*
|
||||
* @input_uV: Input voltage for regulator when supplied by another regulator.
|
||||
*
|
||||
@ -111,6 +115,9 @@ struct regulation_constraints {
|
||||
/* current output range (inclusive) - for current control */
|
||||
int min_uA;
|
||||
int max_uA;
|
||||
int ilim_uA;
|
||||
|
||||
int system_load;
|
||||
|
||||
/* valid regulator operating modes for this machine */
|
||||
unsigned int valid_modes_mask;
|
||||
@ -138,6 +145,8 @@ struct regulation_constraints {
|
||||
unsigned boot_on:1; /* bootloader/firmware enabled regulator */
|
||||
unsigned apply_uV:1; /* apply uV constraint if min == max */
|
||||
unsigned ramp_disable:1; /* disable ramp delay */
|
||||
unsigned soft_start:1; /* ramp voltage slowly */
|
||||
unsigned pull_down:1; /* pull down resistor when regulator off */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -58,6 +58,9 @@
|
||||
* control signal from EN input pin. If it is false then
|
||||
* voltage output will be enabled/disabled through EN bit of
|
||||
* device register.
|
||||
* @enable_gpio: Enable GPIO. If EN pin is controlled through GPIO from host
|
||||
* then GPIO number can be provided. If no GPIO controlled then
|
||||
* it should be -1.
|
||||
* @dvs_gpio: GPIO for dvs. It should be -1 if this is tied with fixed logic.
|
||||
* @dvs_def_state: Default state of dvs. 1 if it is high else 0.
|
||||
*/
|
||||
@ -65,6 +68,7 @@ struct max8973_regulator_platform_data {
|
||||
struct regulator_init_data *reg_init_data;
|
||||
unsigned long control_flags;
|
||||
bool enable_ext_control;
|
||||
int enable_gpio;
|
||||
int dvs_gpio;
|
||||
unsigned dvs_def_state:1;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user