Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aaa9b649 authored by Mark Brown's avatar Mark Brown
Browse files

Merge remote-tracking branches 'regulator/topic/qcom-smd',...

Merge remote-tracking branches 'regulator/topic/qcom-smd', 'regulator/topic/qcom-spmi', 'regulator/topic/rk808', 'regulator/topic/stub' and 'regulator/topic/tol' into regulator-next
Loading
Loading
Loading
Loading
+7 −1
Original line number Original line Diff line number Diff line
@@ -24,6 +24,10 @@ Optional properties:
- vcc10-supply: The input supply for LDO_REG6
- vcc10-supply: The input supply for LDO_REG6
- vcc11-supply: The input supply for LDO_REG8
- vcc11-supply: The input supply for LDO_REG8
- vcc12-supply: The input supply for SWITCH_REG2
- vcc12-supply: The input supply for SWITCH_REG2
- dvs-gpios:  buck1/2 can be controlled by gpio dvs, this is GPIO specifiers
  for 2 host gpio's used for dvs. The format of the gpio specifier depends in
  the gpio controller. If DVS GPIOs aren't present, voltage changes will happen
  very quickly with no slow ramp time.


Regulators: All the regulators of RK808 to be instantiated shall be
Regulators: All the regulators of RK808 to be instantiated shall be
listed in a child node named 'regulators'. Each regulator is represented
listed in a child node named 'regulators'. Each regulator is represented
@@ -55,7 +59,9 @@ Example:
		interrupt-parent = <&gpio0>;
		interrupt-parent = <&gpio0>;
		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
		interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
		pinctrl-names = "default";
		pinctrl-names = "default";
		pinctrl-0 = <&pmic_int>;
		pinctrl-0 = <&pmic_int &dvs_1 &dvs_2>;
		dvs-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>,
			    <&gpio7 15 GPIO_ACTIVE_HIGH>;
		reg = <0x1b>;
		reg = <0x1b>;
		rockchip,system-power-controller;
		rockchip,system-power-controller;
		wakeup-source;
		wakeup-source;
+56 −4
Original line number Original line Diff line number Diff line
@@ -91,13 +91,65 @@ see regulator.txt - with additional custom properties described below:
- regulator-initial-mode:
- regulator-initial-mode:
	Usage: optional
	Usage: optional
	Value type: <u32>
	Value type: <u32>
	Descrption: 1 = Set initial mode to high power mode (HPM), also referred
	Description: 2 = Set initial mode to auto mode (automatically select
		    between HPM and LPM); not available on boost type
		    regulators.

		    1 = Set initial mode to high power mode (HPM), also referred
		    to as NPM. HPM consumes more ground current than LPM, but
		    to as NPM. HPM consumes more ground current than LPM, but
		    it can source significantly higher load current. HPM is not
		    it can source significantly higher load current. HPM is not
		    available on boost type regulators. For voltage switch type
		    available on boost type regulators. For voltage switch type
		    regulators, HPM implies that over current protection and
		    regulators, HPM implies that over current protection and
		    soft start are active all the time. 0 = Set initial mode to
		    soft start are active all the time.
		    low power mode (LPM).

		    0 = Set initial mode to low power mode (LPM).

- qcom,ocp-max-retries:
	Usage: optional
	Value type: <u32>
	Description: Maximum number of times to try toggling a voltage switch
		     off and back on as a result of consecutive over current
		     events.

- qcom,ocp-retry-delay:
	Usage: optional
	Value type: <u32>
	Description: Time to delay in milliseconds between each voltage switch
		     toggle after an over current event takes place.

- qcom,pin-ctrl-enable:
	Usage: optional
	Value type: <u32>
	Description: Bit mask specifying which hardware pins should be used to
		     enable the regulator, if any; supported bits are:
			0 = ignore all hardware enable signals
			BIT(0) = follow HW0_EN signal
			BIT(1) = follow HW1_EN signal
			BIT(2) = follow HW2_EN signal
			BIT(3) = follow HW3_EN signal

- qcom,pin-ctrl-hpm:
	Usage: optional
	Value type: <u32>
	Description: Bit mask specifying which hardware pins should be used to
		     force the regulator into high power mode, if any;
		     supported bits are:
			0 = ignore all hardware enable signals
			BIT(0) = follow HW0_EN signal
			BIT(1) = follow HW1_EN signal
			BIT(2) = follow HW2_EN signal
			BIT(3) = follow HW3_EN signal
			BIT(4) = follow PMIC awake state

- qcom,vs-soft-start-strength:
	Usage: optional
	Value type: <u32>
	Description: This property sets the soft start strength for voltage
		     switch type regulators; supported values are:
			0 = 0.05 uA
			1 = 0.25 uA
			2 = 0.55 uA
			3 = 0.75 uA


Example:
Example:


+12 −0
Original line number Original line Diff line number Diff line
@@ -523,6 +523,18 @@ config REGULATOR_QCOM_RPM
	  Qualcomm RPM as a module. The module will be named
	  Qualcomm RPM as a module. The module will be named
	  "qcom_rpm-regulator".
	  "qcom_rpm-regulator".


config REGULATOR_QCOM_SMD_RPM
	tristate "Qualcomm SMD based RPM regulator driver"
	depends on QCOM_SMD_RPM
	help
	  If you say yes to this option, support will be included for the
	  regulators exposed by the Resource Power Manager found in Qualcomm
	  8974 based devices.

	  Say M here if you want to include support for the regulators on the
	  Qualcomm RPM as a module. The module will be named
	  "qcom_smd-regulator".

config REGULATOR_QCOM_SPMI
config REGULATOR_QCOM_SPMI
	tristate "Qualcomm SPMI regulator driver"
	tristate "Qualcomm SPMI regulator driver"
	depends on SPMI || COMPILE_TEST
	depends on SPMI || COMPILE_TEST
+1 −0
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
obj-$(CONFIG_REGULATOR_MT6397)	+= mt6397-regulator.o
obj-$(CONFIG_REGULATOR_MT6397)	+= mt6397-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SMD_RPM) += qcom_smd-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
obj-$(CONFIG_REGULATOR_QCOM_SPMI) += qcom_spmi-regulator.o
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
+350 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (c) 2015, Sony Mobile Communications AB.
 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/soc/qcom/smd-rpm.h>

struct qcom_rpm_reg {
	struct device *dev;

	struct qcom_smd_rpm *rpm;

	u32 type;
	u32 id;

	struct regulator_desc desc;

	int is_enabled;
	int uV;
};

struct rpm_regulator_req {
	u32 key;
	u32 nbytes;
	u32 value;
};

#define RPM_KEY_SWEN	0x6e657773 /* "swen" */
#define RPM_KEY_UV	0x00007675 /* "uv" */
#define RPM_KEY_MA	0x0000616d /* "ma" */

static int rpm_reg_write_active(struct qcom_rpm_reg *vreg,
				struct rpm_regulator_req *req,
				size_t size)
{
	return qcom_rpm_smd_write(vreg->rpm,
				  QCOM_SMD_RPM_ACTIVE_STATE,
				  vreg->type,
				  vreg->id,
				  req, size);
}

static int rpm_reg_enable(struct regulator_dev *rdev)
{
	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
	struct rpm_regulator_req req;
	int ret;

	req.key = RPM_KEY_SWEN;
	req.nbytes = sizeof(u32);
	req.value = 1;

	ret = rpm_reg_write_active(vreg, &req, sizeof(req));
	if (!ret)
		vreg->is_enabled = 1;

	return ret;
}

static int rpm_reg_is_enabled(struct regulator_dev *rdev)
{
	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);

	return vreg->is_enabled;
}

static int rpm_reg_disable(struct regulator_dev *rdev)
{
	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
	struct rpm_regulator_req req;
	int ret;

	req.key = RPM_KEY_SWEN;
	req.nbytes = sizeof(u32);
	req.value = 0;

	ret = rpm_reg_write_active(vreg, &req, sizeof(req));
	if (!ret)
		vreg->is_enabled = 0;

	return ret;
}

static int rpm_reg_get_voltage(struct regulator_dev *rdev)
{
	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);

	return vreg->uV;
}

static int rpm_reg_set_voltage(struct regulator_dev *rdev,
			       int min_uV,
			       int max_uV,
			       unsigned *selector)
{
	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
	struct rpm_regulator_req req;
	int ret = 0;

	req.key = RPM_KEY_UV;
	req.nbytes = sizeof(u32);
	req.value = min_uV;

	ret = rpm_reg_write_active(vreg, &req, sizeof(req));
	if (!ret)
		vreg->uV = min_uV;

	return ret;
}

static int rpm_reg_set_load(struct regulator_dev *rdev, int load_uA)
{
	struct qcom_rpm_reg *vreg = rdev_get_drvdata(rdev);
	struct rpm_regulator_req req;

	req.key = RPM_KEY_MA;
	req.nbytes = sizeof(u32);
	req.value = load_uA;

	return rpm_reg_write_active(vreg, &req, sizeof(req));
}

static const struct regulator_ops rpm_smps_ldo_ops = {
	.enable = rpm_reg_enable,
	.disable = rpm_reg_disable,
	.is_enabled = rpm_reg_is_enabled,

	.get_voltage = rpm_reg_get_voltage,
	.set_voltage = rpm_reg_set_voltage,

	.set_load = rpm_reg_set_load,
};

static const struct regulator_ops rpm_switch_ops = {
	.enable = rpm_reg_enable,
	.disable = rpm_reg_disable,
	.is_enabled = rpm_reg_is_enabled,
};

static const struct regulator_desc pm8x41_hfsmps = {
	.linear_ranges = (struct regulator_linear_range[]) {
		REGULATOR_LINEAR_RANGE( 375000,  0,  95, 12500),
		REGULATOR_LINEAR_RANGE(1550000, 96, 158, 25000),
	},
	.n_linear_ranges = 2,
	.n_voltages = 159,
	.ops = &rpm_smps_ldo_ops,
};

static const struct regulator_desc pm8841_ftsmps = {
	.linear_ranges = (struct regulator_linear_range[]) {
		REGULATOR_LINEAR_RANGE(350000,  0, 184, 5000),
		REGULATOR_LINEAR_RANGE(700000, 185, 339, 10000),
	},
	.n_linear_ranges = 2,
	.n_voltages = 340,
	.ops = &rpm_smps_ldo_ops,
};

static const struct regulator_desc pm8941_boost = {
	.linear_ranges = (struct regulator_linear_range[]) {
		REGULATOR_LINEAR_RANGE(4000000, 0, 15, 100000),
	},
	.n_linear_ranges = 1,
	.n_voltages = 16,
	.ops = &rpm_smps_ldo_ops,
};

static const struct regulator_desc pm8941_pldo = {
	.linear_ranges = (struct regulator_linear_range[]) {
		REGULATOR_LINEAR_RANGE( 750000,  0,  30, 25000),
		REGULATOR_LINEAR_RANGE(1500000, 31, 99, 50000),
	},
	.n_linear_ranges = 2,
	.n_voltages = 100,
	.ops = &rpm_smps_ldo_ops,
};

static const struct regulator_desc pm8941_nldo = {
	.linear_ranges = (struct regulator_linear_range[]) {
		REGULATOR_LINEAR_RANGE(750000, 0, 63, 12500),
	},
	.n_linear_ranges = 1,
	.n_voltages = 64,
	.ops = &rpm_smps_ldo_ops,
};

static const struct regulator_desc pm8941_lnldo = {
	.fixed_uV = 1740000,
	.n_voltages = 1,
	.ops = &rpm_smps_ldo_ops,
};

static const struct regulator_desc pm8941_switch = {
	.ops = &rpm_switch_ops,
};

struct rpm_regulator_data {
	const char *name;
	u32 type;
	u32 id;
	const struct regulator_desc *desc;
	const char *supply;
};

static const struct rpm_regulator_data rpm_pm8841_regulators[] = {
	{ "s1", QCOM_SMD_RPM_SMPB, 1, &pm8x41_hfsmps, "vdd_s1" },
	{ "s2", QCOM_SMD_RPM_SMPB, 2, &pm8841_ftsmps, "vdd_s2" },
	{ "s3", QCOM_SMD_RPM_SMPB, 3, &pm8x41_hfsmps, "vdd_s3" },
	{ "s4", QCOM_SMD_RPM_SMPB, 4, &pm8841_ftsmps, "vdd_s4" },
	{ "s5", QCOM_SMD_RPM_SMPB, 5, &pm8841_ftsmps, "vdd_s5" },
	{ "s6", QCOM_SMD_RPM_SMPB, 6, &pm8841_ftsmps, "vdd_s6" },
	{ "s7", QCOM_SMD_RPM_SMPB, 7, &pm8841_ftsmps, "vdd_s7" },
	{ "s8", QCOM_SMD_RPM_SMPB, 8, &pm8841_ftsmps, "vdd_s8" },
	{}
};

static const struct rpm_regulator_data rpm_pm8941_regulators[] = {
	{ "s1", QCOM_SMD_RPM_SMPA, 1, &pm8x41_hfsmps, "vdd_s1" },
	{ "s2", QCOM_SMD_RPM_SMPA, 2, &pm8x41_hfsmps, "vdd_s2" },
	{ "s3", QCOM_SMD_RPM_SMPA, 3, &pm8x41_hfsmps, "vdd_s3" },
	{ "s4", QCOM_SMD_RPM_BOOST, 1, &pm8941_boost },

	{ "l1", QCOM_SMD_RPM_LDOA, 1, &pm8941_nldo, "vdd_l1_l3" },
	{ "l2", QCOM_SMD_RPM_LDOA, 2, &pm8941_nldo, "vdd_l2_lvs1_2_3" },
	{ "l3", QCOM_SMD_RPM_LDOA, 3, &pm8941_nldo, "vdd_l1_l3" },
	{ "l4", QCOM_SMD_RPM_LDOA, 4, &pm8941_nldo, "vdd_l4_l11" },
	{ "l5", QCOM_SMD_RPM_LDOA, 5, &pm8941_lnldo, "vdd_l5_l7" },
	{ "l6", QCOM_SMD_RPM_LDOA, 6, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
	{ "l7", QCOM_SMD_RPM_LDOA, 7, &pm8941_lnldo, "vdd_l5_l7" },
	{ "l8", QCOM_SMD_RPM_LDOA, 8, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
	{ "l9", QCOM_SMD_RPM_LDOA, 9, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
	{ "l10", QCOM_SMD_RPM_LDOA, 10, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
	{ "l11", QCOM_SMD_RPM_LDOA, 11, &pm8941_nldo, "vdd_l4_l11" },
	{ "l12", QCOM_SMD_RPM_LDOA, 12, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
	{ "l13", QCOM_SMD_RPM_LDOA, 13, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
	{ "l14", QCOM_SMD_RPM_LDOA, 14, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
	{ "l15", QCOM_SMD_RPM_LDOA, 15, &pm8941_pldo, "vdd_l6_l12_l14_l15" },
	{ "l16", QCOM_SMD_RPM_LDOA, 16, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
	{ "l17", QCOM_SMD_RPM_LDOA, 17, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
	{ "l18", QCOM_SMD_RPM_LDOA, 18, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
	{ "l19", QCOM_SMD_RPM_LDOA, 19, &pm8941_pldo, "vdd_l8_l16_l18_l19" },
	{ "l20", QCOM_SMD_RPM_LDOA, 20, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
	{ "l21", QCOM_SMD_RPM_LDOA, 21, &pm8941_pldo, "vdd_l21" },
	{ "l22", QCOM_SMD_RPM_LDOA, 22, &pm8941_pldo, "vdd_l9_l10_l17_l22" },
	{ "l23", QCOM_SMD_RPM_LDOA, 23, &pm8941_pldo, "vdd_l13_l20_l23_l24" },
	{ "l24", QCOM_SMD_RPM_LDOA, 24, &pm8941_pldo, "vdd_l13_l20_l23_l24" },

	{ "lvs1", QCOM_SMD_RPM_VSA, 1, &pm8941_switch, "vdd_l2_lvs1_2_3" },
	{ "lvs2", QCOM_SMD_RPM_VSA, 2, &pm8941_switch, "vdd_l2_lvs1_2_3" },
	{ "lvs3", QCOM_SMD_RPM_VSA, 3, &pm8941_switch, "vdd_l2_lvs1_2_3" },

	{ "5vs1", QCOM_SMD_RPM_VSA, 4, &pm8941_switch, "vin_5vs" },
	{ "5vs2", QCOM_SMD_RPM_VSA, 5, &pm8941_switch, "vin_5vs" },

	{}
};

static const struct of_device_id rpm_of_match[] = {
	{ .compatible = "qcom,rpm-pm8841-regulators", .data = &rpm_pm8841_regulators },
	{ .compatible = "qcom,rpm-pm8941-regulators", .data = &rpm_pm8941_regulators },
	{}
};
MODULE_DEVICE_TABLE(of, rpm_of_match);

static int rpm_reg_probe(struct platform_device *pdev)
{
	const struct rpm_regulator_data *reg;
	const struct of_device_id *match;
	struct regulator_config config = { };
	struct regulator_dev *rdev;
	struct qcom_rpm_reg *vreg;
	struct qcom_smd_rpm *rpm;

	rpm = dev_get_drvdata(pdev->dev.parent);
	if (!rpm) {
		dev_err(&pdev->dev, "unable to retrieve handle to rpm\n");
		return -ENODEV;
	}

	match = of_match_device(rpm_of_match, &pdev->dev);
	for (reg = match->data; reg->name; reg++) {
		vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
		if (!vreg)
			return -ENOMEM;

		vreg->dev = &pdev->dev;
		vreg->type = reg->type;
		vreg->id = reg->id;
		vreg->rpm = rpm;

		memcpy(&vreg->desc, reg->desc, sizeof(vreg->desc));

		vreg->desc.id = -1;
		vreg->desc.owner = THIS_MODULE;
		vreg->desc.type = REGULATOR_VOLTAGE;
		vreg->desc.name = reg->name;
		vreg->desc.supply_name = reg->supply;
		vreg->desc.of_match = reg->name;

		config.dev = &pdev->dev;
		config.driver_data = vreg;
		rdev = devm_regulator_register(&pdev->dev, &vreg->desc, &config);
		if (IS_ERR(rdev)) {
			dev_err(&pdev->dev, "failed to register %s\n", reg->name);
			return PTR_ERR(rdev);
		}
	}

	return 0;
}

static struct platform_driver rpm_reg_driver = {
	.probe = rpm_reg_probe,
	.driver = {
		.name  = "qcom_rpm_smd_regulator",
		.of_match_table = rpm_of_match,
	},
};

static int __init rpm_reg_init(void)
{
	return platform_driver_register(&rpm_reg_driver);
}
subsys_initcall(rpm_reg_init);

static void __exit rpm_reg_exit(void)
{
	platform_driver_unregister(&rpm_reg_driver);
}
module_exit(rpm_reg_exit)

MODULE_DESCRIPTION("Qualcomm RPM regulator driver");
MODULE_LICENSE("GPL v2");
Loading