diff mbox

[v3,5/5] regulator: Regulator driver for the Qualcomm RPM

Message ID 1438053633-6659-6-git-send-email-bjorn.andersson@sonymobile.com (mailing list archive)
State Not Applicable, archived
Delegated to: Andy Gross
Headers show

Commit Message

Bjorn Andersson July 28, 2015, 3:20 a.m. UTC
Driver for regulators exposed by the Resource Power Manager (RPM) found
in devices based on Qualcomm 8974 and newer platforms.

Reviewed-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---

Changes since v2:
- Updated Kconfig dependency to follow smd's move from mfd

 drivers/regulator/Kconfig              |  12 ++
 drivers/regulator/Makefile             |   1 +
 drivers/regulator/qcom_smd-regulator.c | 349 +++++++++++++++++++++++++++++++++
 3 files changed, 362 insertions(+)
 create mode 100644 drivers/regulator/qcom_smd-regulator.c

Comments

Andy Gross Aug. 14, 2015, 4:58 p.m. UTC | #1
On Mon, Jul 27, 2015 at 08:20:33PM -0700, Bjorn Andersson wrote:
> Driver for regulators exposed by the Resource Power Manager (RPM) found
> in devices based on Qualcomm 8974 and newer platforms.
> 
> Reviewed-by: Mark Brown <broonie@kernel.org>
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---

Mark/Liam, can you please pick this up.  The dependencies for this have been merged
in by the arm/soc maintainers.

Acked-by: Andy Gross <agross@codeaurora.org>
Tim Bird Aug. 14, 2015, 9:41 p.m. UTC | #2
On Fri, Aug 14, 2015 at 9:58 AM, Andy Gross <agross@codeaurora.org> wrote:
> On Mon, Jul 27, 2015 at 08:20:33PM -0700, Bjorn Andersson wrote:
>> Driver for regulators exposed by the Resource Power Manager (RPM) found
>> in devices based on Qualcomm 8974 and newer platforms.
>>
>> Reviewed-by: Mark Brown <broonie@kernel.org>
>> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
>> ---
>
> Mark/Liam, can you please pick this up.  The dependencies for this have been merged
> in by the arm/soc maintainers.
>
> Acked-by: Andy Gross <agross@codeaurora.org>

I'd like to see these go in as well, though I realize we're starting
to get pretty close to the merge window.
These regulators are the last thing outstanding to get the USB driver
working completely in mainline for
the Xperia Z1 and the dragonboard (800).

FWIW...

Tested-by: Tim Bird <tim.bird@sonymobile.com>
 -- Tim
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 15, 2015, 2:14 a.m. UTC | #3
On Fri, Aug 14, 2015 at 11:58:35AM -0500, Andy Gross wrote:
> On Mon, Jul 27, 2015 at 08:20:33PM -0700, Bjorn Andersson wrote:
> > Driver for regulators exposed by the Resource Power Manager (RPM) found
> > in devices based on Qualcomm 8974 and newer platforms.

> > Reviewed-by: Mark Brown <broonie@kernel.org>
> > Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>

> Mark/Liam, can you please pick this up.  The dependencies for this have been merged
> in by the arm/soc maintainers.

> Acked-by: Andy Gross <agross@codeaurora.org>

Please submit any patches you think should be included in the upstream
kernel using the process documented in SubmittingPatches.
Bjorn Andersson Aug. 15, 2015, 4:59 a.m. UTC | #4
On Fri 14 Aug 19:14 PDT 2015, Mark Brown wrote:

> On Fri, Aug 14, 2015 at 11:58:35AM -0500, Andy Gross wrote:
> > On Mon, Jul 27, 2015 at 08:20:33PM -0700, Bjorn Andersson wrote:
> > > Driver for regulators exposed by the Resource Power Manager (RPM) found
> > > in devices based on Qualcomm 8974 and newer platforms.
> 
> > > Reviewed-by: Mark Brown <broonie@kernel.org>
> > > Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> 
> > Mark/Liam, can you please pick this up.  The dependencies for this have been merged
> > in by the arm/soc maintainers.
> 
> > Acked-by: Andy Gross <agross@codeaurora.org>
> 
> Please submit any patches you think should be included in the upstream
> kernel using the process documented in SubmittingPatches.

I'm sorry, I thought I did and Andy's comment was to inform you that the
other 4 patches in this series have been merged.

Do you want me to resend this single patch on its own? Or is there
anything else you would like me to do with it?

Regards,
Bjorn
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Aug. 15, 2015, 2:05 p.m. UTC | #5
On Fri, Aug 14, 2015 at 09:59:50PM -0700, Bjorn Andersson wrote:
> On Fri 14 Aug 19:14 PDT 2015, Mark Brown wrote:

> > Please submit any patches you think should be included in the upstream
> > kernel using the process documented in SubmittingPatches.

> I'm sorry, I thought I did and Andy's comment was to inform you that the
> other 4 patches in this series have been merged.

> Do you want me to resend this single patch on its own? Or is there
> anything else you would like me to do with it?

Yes, you need to send patches to me if you want me to consider applying
them.  Sending me content free pings mostly just adds to the mail
volume, I can't apply a content free ping and given that it's a reply to
something with my Reviewed-by on it's not even something I replied to.

If I gave a Reviewed-by for the patch it's presumably because there are
some dependencies that prevented me just applying it and I was expecting
it to go in with the rest of the series, are there any actual
dependencies here or have the dependencies reached Linus' tree?
diff mbox

Patch

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index a7b81f0185b5..dd991d08d778 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -514,6 +514,18 @@  config REGULATOR_QCOM_RPM
 	  Qualcomm RPM as a module. The module will be named
 	  "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
 	tristate "Qualcomm SPMI regulator driver"
 	depends on SPMI || COMPILE_TEST
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 6429e629dcb6..a00cffcf6bf9 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -61,6 +61,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_SMD_RPM) += qcom_smd-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
diff --git a/drivers/regulator/qcom_smd-regulator.c b/drivers/regulator/qcom_smd-regulator.c
new file mode 100644
index 000000000000..9d093ae36ba7
--- /dev/null
+++ b/drivers/regulator/qcom_smd-regulator.c
@@ -0,0 +1,349 @@ 
+/*
+ * 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,
+	.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");