lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <E1aflHs-0005ac-Az@debutante>
Date:	Tue, 15 Mar 2016 09:29:12 +0000
From:	Mark Brown <broonie@...nel.org>
To:	Georgi Djakov <georgi.djakov@...aro.org>,
	Mark Brown <broonie@...nel.org>
Cc:	linux-kernel@...r.kernel.org
Subject: Applied "regulator: qcom-saw: Add support for SAW regulators" to the regulator tree

The patch

   regulator: qcom-saw: Add support for SAW regulators

has been applied to the regulator tree at

   git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git 

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.  

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark

>From 18bba3b503556a5e2e00538cbf2cd014fe4a417c Mon Sep 17 00:00:00 2001
From: Georgi Djakov <georgi.djakov@...aro.org>
Date: Tue, 9 Feb 2016 15:12:29 +0200
Subject: [PATCH] regulator: qcom-saw: Add support for SAW regulators

The SAW (Subsystem Power Manager and Adaptive Voltage Scaling Wrapper)
is part of the SPM subsystem. It is a hardware block in the Qualcomm
chipsets that regulates the power to the CPU cores on platform such as
apq8064, msm8974, apq8084 and others.

Signed-off-by: Georgi Djakov <georgi.djakov@...aro.org>
Signed-off-by: Mark Brown <broonie@...nel.org>
---
 .../bindings/regulator/qcom,saw-regulator.txt      |  31 +++
 drivers/regulator/Kconfig                          |  12 ++
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/qcom_saw-regulator.c             | 229 +++++++++++++++++++++
 4 files changed, 273 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/qcom,saw-regulator.txt
 create mode 100644 drivers/regulator/qcom_saw-regulator.c

diff --git a/Documentation/devicetree/bindings/regulator/qcom,saw-regulator.txt b/Documentation/devicetree/bindings/regulator/qcom,saw-regulator.txt
new file mode 100644
index 000000000000..977fec08b2ae
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/qcom,saw-regulator.txt
@@ -0,0 +1,31 @@
+Qualcomm SAW Regulators
+
+SAW (Subsystem Power Manager and Adaptive Voltage Scaling Wrapper) is a hardware
+block in the Qualcomm chipsets that regulates the power to the CPU cores on devices
+such as APQ8064, MSM8974, APQ8084 and others.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be one of:
+			"qcom,apq8064-saw2-v1.1-regulator"
+
+Example:
+                saw0: power-controller@...9000 {
+			compatible = "qcom,apq8064-saw2-v1.1-cpu", "qcom,saw2", "syscon", "simple-mfd";
+			reg = <0x02089000 0x1000>, <0x02009000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			saw0_regulator: regulator@...9000 {
+				compatible = "qcom,apq8064-saw2-v1.1-regulator";
+				regulator-always-on;
+				regulator-min-microvolt = <825000>;
+				regulator-max-microvolt = <1250000>;
+			};
+		};
+
+
+		&CPU0 {
+			cpu-supply = <&saw0_regulator>;
+		};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8155e80dd3f8..3a61e0ccced3 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -549,6 +549,18 @@ config REGULATOR_QCOM_RPM
 	  Qualcomm RPM as a module. The module will be named
 	  "qcom_rpm-regulator".
 
+config REGULATOR_QCOM_SAW
+	tristate "Qualcomm SAW regulator driver"
+	depends on (ARCH_QCOM || COMPILE_TEST) && MFD_SYSCON
+	help
+	  If you say yes to this option, support will be included for the
+	  regulators providing power to the CPU cores on devices such as
+	  APQ8064.
+
+	  Say M here if you want to include support for the CPU core voltage
+	  regulators as a module. The module will be named
+	  "qcom_saw-regulator".
+
 config REGULATOR_QCOM_SMD_RPM
 	tristate "Qualcomm SMD based RPM regulator driver"
 	depends on QCOM_SMD_RPM
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 980b1943fa81..af928cc15c23 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -63,6 +63,7 @@ obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_MT6311) += mt6311-regulator.o
 obj-$(CONFIG_REGULATOR_MT6397)	+= mt6397-regulator.o
 obj-$(CONFIG_REGULATOR_QCOM_RPM) += qcom_rpm-regulator.o
+obj-$(CONFIG_REGULATOR_QCOM_SAW)+= qcom_saw-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
diff --git a/drivers/regulator/qcom_saw-regulator.c b/drivers/regulator/qcom_saw-regulator.c
new file mode 100644
index 000000000000..c800f16adaf0
--- /dev/null
+++ b/drivers/regulator/qcom_saw-regulator.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2016, Linaro Limited. 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/delay.h>
+#include <linux/kernel.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/of_regulator.h>
+
+#define	SPM_REG_STS_1			0x10
+#define	SPM_REG_VCTL			0x14
+#define	SPM_REG_PMIC_DATA_0		0x28
+#define	SPM_REG_PMIC_DATA_1		0x2c
+#define	SPM_REG_RST			0x30
+
+struct saw_vreg {
+	struct device		*dev;
+	struct regmap		*regmap;
+	struct regulator_desc	rdesc;
+	struct regulator_dev	*rdev;
+	unsigned int		sel;
+};
+
+struct spm_vlevel_data {
+	struct saw_vreg *vreg;
+	unsigned int sel;
+};
+
+static int saw_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct saw_vreg *vreg = rdev_get_drvdata(rdev);
+
+	return vreg->sel;
+}
+
+static void smp_set_vdd(void *data)
+{
+	struct spm_vlevel_data *vdata = (struct spm_vlevel_data *)data;
+	struct saw_vreg *vreg = vdata->vreg;
+	unsigned long new_sel = vdata->sel;
+	u32 val, new_val;
+	u32 vctl, data0, data1;
+	unsigned long timeout;
+
+	if (vreg->sel == new_sel)
+		return;
+
+	regmap_read(vreg->regmap, SPM_REG_VCTL, &vctl);
+	regmap_read(vreg->regmap, SPM_REG_PMIC_DATA_0, &data0);
+	regmap_read(vreg->regmap, SPM_REG_PMIC_DATA_1, &data1);
+
+	/* select the band */
+	val = 0x80 | new_sel;
+
+	vctl &= ~0xff;
+	vctl |= val;
+
+	data0 &= ~0xff;
+	data0 |= val;
+
+	data1 &= ~0x3f;
+	data1 |= val & 0x3f;
+	data1 &= ~0x3f0000;
+	data1 |= ((val & 0x3f) << 16);
+
+	regmap_write(vreg->regmap, SPM_REG_RST, 1);
+	regmap_write(vreg->regmap, SPM_REG_VCTL, vctl);
+	regmap_write(vreg->regmap, SPM_REG_PMIC_DATA_0, data0);
+	regmap_write(vreg->regmap, SPM_REG_PMIC_DATA_1, data1);
+
+	timeout = jiffies + usecs_to_jiffies(100);
+	do {
+		regmap_read(vreg->regmap, SPM_REG_STS_1, &new_val);
+		new_val &= 0xff;
+		if (new_val == val) {
+			vreg->sel = new_sel;
+			return;
+		}
+
+		cpu_relax();
+
+	} while (time_before(jiffies, timeout));
+
+	pr_err("%s: Voltage not changed: %#x\n", __func__, new_val);
+}
+
+static int saw_regulator_set_voltage_sel(struct regulator_dev *rdev,
+					 unsigned selector)
+{
+	struct saw_vreg *vreg = rdev_get_drvdata(rdev);
+	struct spm_vlevel_data data;
+	int cpu = rdev_get_id(rdev);
+
+	data.vreg = vreg;
+	data.sel = selector;
+
+	return smp_call_function_single(cpu, smp_set_vdd, &data, true);
+}
+
+static struct regulator_ops saw_regulator_ops = {
+	.list_voltage = regulator_list_voltage_linear_range,
+	.set_voltage_sel = saw_regulator_set_voltage_sel,
+	.get_voltage_sel = saw_regulator_get_voltage_sel,
+	.set_voltage_time_sel = regulator_set_voltage_time_sel,
+};
+
+static struct regulator_desc saw_regulator = {
+	.owner = THIS_MODULE,
+	.type = REGULATOR_VOLTAGE,
+	.ops  = &saw_regulator_ops,
+	.linear_ranges = (struct regulator_linear_range[]) {
+		REGULATOR_LINEAR_RANGE(700000, 0, 56, 12500),
+	},
+	.n_linear_ranges = 1,
+	.n_voltages = 57,
+	.ramp_delay = 1250,
+};
+
+static struct saw_vreg *saw_get_drv(struct platform_device *pdev,
+				    int *vreg_cpu)
+{
+	struct saw_vreg *vreg = NULL;
+	struct device_node *cpu_node, *saw_node;
+	int cpu;
+	bool found;
+
+	for_each_possible_cpu(cpu) {
+		cpu_node = of_cpu_device_node_get(cpu);
+		if (!cpu_node)
+			continue;
+		saw_node = of_parse_phandle(cpu_node, "qcom,saw", 0);
+		found = (saw_node == pdev->dev.of_node->parent);
+		of_node_put(saw_node);
+		of_node_put(cpu_node);
+		if (found)
+			break;
+	}
+
+	if (found) {
+		vreg = devm_kzalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
+		if (vreg)
+			*vreg_cpu = cpu;
+	}
+
+	return vreg;
+}
+
+static const struct of_device_id qcom_saw_regulator_match[] = {
+	{ .compatible = "qcom,apq8064-saw2-v1.1-regulator" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, qcom_saw_regulator_match);
+
+static int qcom_saw_regulator_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct device_node *saw_np;
+	struct saw_vreg *vreg;
+	struct regulator_config config = { };
+	int ret = 0, cpu = 0;
+	char name[] = "kraitXX";
+
+	vreg = saw_get_drv(pdev, &cpu);
+	if (!vreg)
+		return -EINVAL;
+
+	saw_np = of_get_parent(np);
+	if (!saw_np)
+		return -ENODEV;
+
+	vreg->regmap = syscon_node_to_regmap(saw_np);
+	of_node_put(saw_np);
+	if (IS_ERR(config.regmap))
+		return PTR_ERR(config.regmap);
+
+	snprintf(name, sizeof(name), "krait%d", cpu);
+
+	config.regmap = vreg->regmap;
+	config.dev = &pdev->dev;
+	config.of_node = np;
+	config.driver_data = vreg;
+
+	vreg->rdesc = saw_regulator;
+	vreg->rdesc.id = cpu;
+	vreg->rdesc.name = name;
+	config.init_data = of_get_regulator_init_data(&pdev->dev,
+						      pdev->dev.of_node,
+						      &vreg->rdesc);
+
+	vreg->rdev = devm_regulator_register(&pdev->dev, &vreg->rdesc, &config);
+	if (IS_ERR(vreg->rdev)) {
+		ret = PTR_ERR(vreg->rdev);
+		dev_err(dev, "failed to register SAW regulator: %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct platform_driver qcom_saw_regulator_driver = {
+	.driver = {
+		.name = "qcom-saw-regulator",
+		.of_match_table = qcom_saw_regulator_match,
+	},
+	.probe = qcom_saw_regulator_probe,
+};
+
+module_platform_driver(qcom_saw_regulator_driver);
+
+MODULE_ALIAS("platform:qcom-saw-regulator");
+MODULE_DESCRIPTION("Qualcomm SAW regulator driver");
+MODULE_AUTHOR("Georgi Djakov <georgi.djakov@...aro.org>");
+MODULE_LICENSE("GPL v2");
-- 
2.7.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ