linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 0/3] Qualcomm Resource Power Manager
@ 2014-11-26 21:50 Bjorn Andersson
  2014-11-26 21:50 ` [PATCH v8 1/3] mfd: devicetree: bindings: Add Qualcomm RPM DT binding Bjorn Andersson
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Bjorn Andersson @ 2014-11-26 21:50 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Mark Brown
  Cc: Josh Cartwright, devicetree, linux-kernel, linux-arm-kernel,
	linux-arm-msm

In order to support the SoC assisted power save features of the Qualcomm
platform some changes are most likely needed to the regulator part of the DT
bindings provided before.

This version of the patchset carries the RPM core part, which allows us to move
forward with merging Josh's patches [1] as well as aiding the discussion and
development of the additional patches needed to properly implement the power
save features being discussed.

It also carries the patch to the already merged regulator driver, to make it
compile.

[1] https://lkml.org/lkml/2014/11/20/629

Changes since v7:
  - Mark merged the regulator part of the previous series
  - Removed regulator part of dt binding, for further discussions

Changes since v6:
  - Changed filenames from qcom,rpm.{txt,h} to qcom-rpm.{txt,h}

Changes since v5:
  - Clarified dt binding
  - Converted regulator qcom,force-mode to enum instead of multi-boolean
  - Remove unecessary version handshake
  - Cleaned up naming of RPM resources between different RPM versions
  - Updated regulator qcom,force-mode parsing
  - Updated regulator qcom,power-mode-* parsing
  - Cleanups in rpm driver
  - Dropped dev_get_qcom_rpm helper function

Changes since v4:
  - Moved RPM driver to mfd

Changes since v3:
  - IPC register is acquired through syscon, as it's shared with others

Changes since v2:
  - Fix copy-paste error in dt binding
  - Correct incomplete move from mfd to soc
  - Correct const mistake in regulator driver

Changes since v1:
  - Moved rpm driver to drivers/soc
  - Extracted resource table structs from rpm struct, as per Srinivas request
  - Dropped mode setting support for the regulators for now. Unsure if we need
    it and it requires some rework from the codeaurora solution.
  - Using set_voltage_sel instead of rolling my own "snapping", as per Marks
    request
  - Split regulator ops in mV, uV and swtich versions as per Marks request.
  - Added devicetree property to enable pull down.

Bjorn Andersson (3):
  mfd: devicetree: bindings: Add Qualcomm RPM DT binding
  mfd: qcom-rpm: Driver for the Qualcomm RPM
  regulator: qcom-rpm: Add missing state flag in call to RPM

 Documentation/devicetree/bindings/mfd/qcom-rpm.txt |  70 +++
 drivers/mfd/Kconfig                                |  14 +
 drivers/mfd/Makefile                               |   1 +
 drivers/mfd/qcom_rpm.c                             | 581 +++++++++++++++++++++
 drivers/regulator/qcom_rpm-regulator.c             |   1 +
 include/dt-bindings/mfd/qcom-rpm.h                 | 154 ++++++
 include/linux/mfd/qcom_rpm.h                       |  13 +
 7 files changed, 834 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/qcom-rpm.txt
 create mode 100644 drivers/mfd/qcom_rpm.c
 create mode 100644 include/dt-bindings/mfd/qcom-rpm.h
 create mode 100644 include/linux/mfd/qcom_rpm.h

--
1.8.2.2


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v8 1/3] mfd: devicetree: bindings: Add Qualcomm RPM DT binding
  2014-11-26 21:50 [PATCH v8 0/3] Qualcomm Resource Power Manager Bjorn Andersson
@ 2014-11-26 21:50 ` Bjorn Andersson
  2015-01-20 17:01   ` Lee Jones
  2014-11-26 21:51 ` [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM Bjorn Andersson
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Bjorn Andersson @ 2014-11-26 21:50 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Mark Brown
  Cc: Josh Cartwright, devicetree, linux-kernel, linux-arm-kernel,
	linux-arm-msm

Add binding for the Qualcomm Resource Power Manager (RPM) found in 8660,
8960 and 8064 based devices.

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---

Removed regulator definition from this patch, as these needs more discussion to
be able to implement SoC assisted power save features of the Qualcomm
platforms. No other changes.

 Documentation/devicetree/bindings/mfd/qcom-rpm.txt |  70 ++++++++++
 include/dt-bindings/mfd/qcom-rpm.h                 | 154 +++++++++++++++++++++
 2 files changed, 224 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mfd/qcom-rpm.txt
 create mode 100644 include/dt-bindings/mfd/qcom-rpm.h

diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
new file mode 100644
index 0000000..85e3198
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
@@ -0,0 +1,70 @@
+Qualcomm Resource Power Manager (RPM)
+
+This driver is used to interface with the Resource Power Manager (RPM) found in
+various Qualcomm platforms. The RPM allows each component in the system to vote
+for state of the system resources, such as clocks, regulators and bus
+frequencies.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be one of:
+		    "qcom,rpm-apq8064"
+		    "qcom,rpm-msm8660"
+		    "qcom,rpm-msm8960"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: base address and size of the RPM's message ram
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: three entries specifying the RPM's:
+		    1. acknowledgement interrupt
+		    2. error interrupt
+		    3. wakeup interrupt
+
+- interrupt-names:
+	Usage: required
+	Value type: <string-array>
+	Definition: must be the three strings "ack", "err" and "wakeup", in order
+
+- #address-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 1
+
+- #size-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 0
+
+- qcom,ipc:
+	Usage: required
+	Value type: <prop-encoded-array>
+
+	Definition: three entries specifying the outgoing ipc bit used for
+		    signaling the RPM:
+		    - phandle to a syscon node representing the apcs registers
+		    - u32 representing offset to the register within the syscon
+		    - u32 representing the ipc bit within the register
+
+
+= EXAMPLE
+
+	#include <dt-bindings/mfd/qcom-rpm.h>
+
+	rpm@108000 {
+		compatible = "qcom,rpm-msm8960";
+		reg = <0x108000 0x1000>;
+		qcom,ipc = <&apcs 0x8 2>;
+
+		interrupts = <0 19 0>, <0 21 0>, <0 22 0>;
+		interrupt-names = "ack", "err", "wakeup";
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+	};
+
diff --git a/include/dt-bindings/mfd/qcom-rpm.h b/include/dt-bindings/mfd/qcom-rpm.h
new file mode 100644
index 0000000..388a6f3
--- /dev/null
+++ b/include/dt-bindings/mfd/qcom-rpm.h
@@ -0,0 +1,154 @@
+/*
+ * This header provides constants for the Qualcomm RPM bindings.
+ */
+
+#ifndef _DT_BINDINGS_MFD_QCOM_RPM_H
+#define _DT_BINDINGS_MFD_QCOM_RPM_H
+
+/*
+ * Constants use to identify individual resources in the RPM.
+ */
+#define QCOM_RPM_APPS_FABRIC_ARB		1
+#define QCOM_RPM_APPS_FABRIC_CLK		2
+#define QCOM_RPM_APPS_FABRIC_HALT		3
+#define QCOM_RPM_APPS_FABRIC_IOCTL		4
+#define QCOM_RPM_APPS_FABRIC_MODE		5
+#define QCOM_RPM_APPS_L2_CACHE_CTL		6
+#define QCOM_RPM_CFPB_CLK			7
+#define QCOM_RPM_CXO_BUFFERS			8
+#define QCOM_RPM_CXO_CLK			9
+#define QCOM_RPM_DAYTONA_FABRIC_CLK		10
+#define QCOM_RPM_DDR_DMM			11
+#define QCOM_RPM_EBI1_CLK			12
+#define QCOM_RPM_HDMI_SWITCH			13
+#define QCOM_RPM_MMFPB_CLK			14
+#define QCOM_RPM_MM_FABRIC_ARB			15
+#define QCOM_RPM_MM_FABRIC_CLK			16
+#define QCOM_RPM_MM_FABRIC_HALT			17
+#define QCOM_RPM_MM_FABRIC_IOCTL		18
+#define QCOM_RPM_MM_FABRIC_MODE			19
+#define QCOM_RPM_PLL_4				20
+#define QCOM_RPM_PM8058_LDO0			21
+#define QCOM_RPM_PM8058_LDO1			22
+#define QCOM_RPM_PM8058_LDO2			23
+#define QCOM_RPM_PM8058_LDO3			24
+#define QCOM_RPM_PM8058_LDO4			25
+#define QCOM_RPM_PM8058_LDO5			26
+#define QCOM_RPM_PM8058_LDO6			27
+#define QCOM_RPM_PM8058_LDO7			28
+#define QCOM_RPM_PM8058_LDO8			29
+#define QCOM_RPM_PM8058_LDO9			30
+#define QCOM_RPM_PM8058_LDO10			31
+#define QCOM_RPM_PM8058_LDO11			32
+#define QCOM_RPM_PM8058_LDO12			33
+#define QCOM_RPM_PM8058_LDO13			34
+#define QCOM_RPM_PM8058_LDO14			35
+#define QCOM_RPM_PM8058_LDO15			36
+#define QCOM_RPM_PM8058_LDO16			37
+#define QCOM_RPM_PM8058_LDO17			38
+#define QCOM_RPM_PM8058_LDO18			39
+#define QCOM_RPM_PM8058_LDO19			40
+#define QCOM_RPM_PM8058_LDO20			41
+#define QCOM_RPM_PM8058_LDO21			42
+#define QCOM_RPM_PM8058_LDO22			43
+#define QCOM_RPM_PM8058_LDO23			44
+#define QCOM_RPM_PM8058_LDO24			45
+#define QCOM_RPM_PM8058_LDO25			46
+#define QCOM_RPM_PM8058_LVS0			47
+#define QCOM_RPM_PM8058_LVS1			48
+#define QCOM_RPM_PM8058_NCP			49
+#define QCOM_RPM_PM8058_SMPS0			50
+#define QCOM_RPM_PM8058_SMPS1			51
+#define QCOM_RPM_PM8058_SMPS2			52
+#define QCOM_RPM_PM8058_SMPS3			53
+#define QCOM_RPM_PM8058_SMPS4			54
+#define QCOM_RPM_PM8821_LDO1			55
+#define QCOM_RPM_PM8821_SMPS1			56
+#define QCOM_RPM_PM8821_SMPS2			57
+#define QCOM_RPM_PM8901_LDO0			58
+#define QCOM_RPM_PM8901_LDO1			59
+#define QCOM_RPM_PM8901_LDO2			60
+#define QCOM_RPM_PM8901_LDO3			61
+#define QCOM_RPM_PM8901_LDO4			62
+#define QCOM_RPM_PM8901_LDO5			63
+#define QCOM_RPM_PM8901_LDO6			64
+#define QCOM_RPM_PM8901_LVS0			65
+#define QCOM_RPM_PM8901_LVS1			66
+#define QCOM_RPM_PM8901_LVS2			67
+#define QCOM_RPM_PM8901_LVS3			68
+#define QCOM_RPM_PM8901_MVS			69
+#define QCOM_RPM_PM8901_SMPS0			70
+#define QCOM_RPM_PM8901_SMPS1			71
+#define QCOM_RPM_PM8901_SMPS2			72
+#define QCOM_RPM_PM8901_SMPS3			73
+#define QCOM_RPM_PM8901_SMPS4			74
+#define QCOM_RPM_PM8921_CLK1			75
+#define QCOM_RPM_PM8921_CLK2			76
+#define QCOM_RPM_PM8921_LDO1			77
+#define QCOM_RPM_PM8921_LDO2			78
+#define QCOM_RPM_PM8921_LDO3			79
+#define QCOM_RPM_PM8921_LDO4			80
+#define QCOM_RPM_PM8921_LDO5			81
+#define QCOM_RPM_PM8921_LDO6			82
+#define QCOM_RPM_PM8921_LDO7			83
+#define QCOM_RPM_PM8921_LDO8			84
+#define QCOM_RPM_PM8921_LDO9			85
+#define QCOM_RPM_PM8921_LDO10			86
+#define QCOM_RPM_PM8921_LDO11			87
+#define QCOM_RPM_PM8921_LDO12			88
+#define QCOM_RPM_PM8921_LDO13			89
+#define QCOM_RPM_PM8921_LDO14			90
+#define QCOM_RPM_PM8921_LDO15			91
+#define QCOM_RPM_PM8921_LDO16			92
+#define QCOM_RPM_PM8921_LDO17			93
+#define QCOM_RPM_PM8921_LDO18			94
+#define QCOM_RPM_PM8921_LDO19			95
+#define QCOM_RPM_PM8921_LDO20			96
+#define QCOM_RPM_PM8921_LDO21			97
+#define QCOM_RPM_PM8921_LDO22			98
+#define QCOM_RPM_PM8921_LDO23			99
+#define QCOM_RPM_PM8921_LDO24			100
+#define QCOM_RPM_PM8921_LDO25			101
+#define QCOM_RPM_PM8921_LDO26			102
+#define QCOM_RPM_PM8921_LDO27			103
+#define QCOM_RPM_PM8921_LDO28			104
+#define QCOM_RPM_PM8921_LDO29			105
+#define QCOM_RPM_PM8921_LVS1			106
+#define QCOM_RPM_PM8921_LVS2			107
+#define QCOM_RPM_PM8921_LVS3			108
+#define QCOM_RPM_PM8921_LVS4			109
+#define QCOM_RPM_PM8921_LVS5			110
+#define QCOM_RPM_PM8921_LVS6			111
+#define QCOM_RPM_PM8921_LVS7			112
+#define QCOM_RPM_PM8921_MVS			113
+#define QCOM_RPM_PM8921_NCP			114
+#define QCOM_RPM_PM8921_SMPS1			115
+#define QCOM_RPM_PM8921_SMPS2			116
+#define QCOM_RPM_PM8921_SMPS3			117
+#define QCOM_RPM_PM8921_SMPS4			118
+#define QCOM_RPM_PM8921_SMPS5			119
+#define QCOM_RPM_PM8921_SMPS6			120
+#define QCOM_RPM_PM8921_SMPS7			121
+#define QCOM_RPM_PM8921_SMPS8			122
+#define QCOM_RPM_PXO_CLK			123
+#define QCOM_RPM_QDSS_CLK			124
+#define QCOM_RPM_SFPB_CLK			125
+#define QCOM_RPM_SMI_CLK			126
+#define QCOM_RPM_SYS_FABRIC_ARB			127
+#define QCOM_RPM_SYS_FABRIC_CLK			128
+#define QCOM_RPM_SYS_FABRIC_HALT		129
+#define QCOM_RPM_SYS_FABRIC_IOCTL		130
+#define QCOM_RPM_SYS_FABRIC_MODE		131
+#define QCOM_RPM_USB_OTG_SWITCH			132
+#define QCOM_RPM_VDDMIN_GPIO			133
+
+/*
+ * Constants used to select force mode for regulators.
+ */
+#define QCOM_RPM_FORCE_MODE_NONE		0
+#define QCOM_RPM_FORCE_MODE_LPM			1
+#define QCOM_RPM_FORCE_MODE_HPM			2
+#define QCOM_RPM_FORCE_MODE_AUTO		3
+#define QCOM_RPM_FORCE_MODE_BYPASS		4
+
+#endif
-- 
1.8.2.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM
  2014-11-26 21:50 [PATCH v8 0/3] Qualcomm Resource Power Manager Bjorn Andersson
  2014-11-26 21:50 ` [PATCH v8 1/3] mfd: devicetree: bindings: Add Qualcomm RPM DT binding Bjorn Andersson
@ 2014-11-26 21:51 ` Bjorn Andersson
  2014-12-22 10:50   ` Paul Bolle
  2015-01-20 17:02   ` Lee Jones
  2014-11-26 21:51 ` [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM Bjorn Andersson
  2014-12-02 14:25 ` [PATCH v8 0/3] Qualcomm Resource Power Manager Srinivas Kandagatla
  3 siblings, 2 replies; 13+ messages in thread
From: Bjorn Andersson @ 2014-11-26 21:51 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Mark Brown
  Cc: Josh Cartwright, devicetree, linux-kernel, linux-arm-kernel,
	linux-arm-msm

Driver for the Resource Power Manager (RPM) found in Qualcomm 8660, 8960
and 8064 based devices. The driver exposes resources that child drivers
can operate on; to implementing regulator, clock and bus frequency
drivers.

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---

Lee, since your Acked-by earlier I've folded in the part of the RFC where I add
an extra parameter to qcom_rpm_write(). Part of that this is unchanged.

 drivers/mfd/Kconfig          |  14 ++
 drivers/mfd/Makefile         |   1 +
 drivers/mfd/qcom_rpm.c       | 581 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/qcom_rpm.h |  13 +
 4 files changed, 609 insertions(+)
 create mode 100644 drivers/mfd/qcom_rpm.c
 create mode 100644 include/linux/mfd/qcom_rpm.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1456ea7..b6bcb79 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -567,6 +567,20 @@ config MFD_PM8921_CORE
 	  Say M here if you want to include support for PM8921 chip as a module.
 	  This will build a module called "pm8921-core".
 
+config MFD_QCOM_RPM
+	tristate "Qualcomm Resource Power Manager (RPM)"
+	depends on ARCH_QCOM && OF
+	help
+	  If you say yes to this option, support will be included for the
+	  Resource Power Manager system found in the Qualcomm 8660, 8960 and
+	  8064 based devices.
+
+	  This is required to access many regulators, clocks and bus
+	  frequencies controlled by the RPM on these devices.
+
+	  Say M here if you want to include support for the Qualcomm RPM as a
+	  module. This will build a module called "qcom_rpm".
+
 config MFD_SPMI_PMIC
 	tristate "Qualcomm SPMI PMICs"
 	depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 8bd54b1..3364bbc 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -153,6 +153,7 @@ obj-$(CONFIG_MFD_SI476X_CORE)	+= si476x-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
 obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
 obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o ssbi.o
+obj-$(CONFIG_MFD_QCOM_RPM)	+= qcom_rpm.o
 obj-$(CONFIG_MFD_SPMI_PMIC)	+= qcom-spmi-pmic.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
 obj-$(CONFIG_MFD_TPS65090)	+= tps65090.o
diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
new file mode 100644
index 0000000..f696328
--- /dev/null
+++ b/drivers/mfd/qcom_rpm.c
@@ -0,0 +1,581 @@
+/*
+ * Copyright (c) 2014, Sony Mobile Communications AB.
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Author: Bjorn Andersson <bjorn.andersson@sonymobile.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 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/platform_device.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/qcom_rpm.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/mfd/qcom-rpm.h>
+
+struct qcom_rpm_resource {
+	unsigned target_id;
+	unsigned status_id;
+	unsigned select_id;
+	unsigned size;
+};
+
+struct qcom_rpm_data {
+	u32 version;
+	const struct qcom_rpm_resource *resource_table;
+	unsigned n_resources;
+};
+
+struct qcom_rpm {
+	struct device *dev;
+	struct regmap *ipc_regmap;
+	unsigned ipc_offset;
+	unsigned ipc_bit;
+
+	struct completion ack;
+	struct mutex lock;
+
+	void __iomem *status_regs;
+	void __iomem *ctrl_regs;
+	void __iomem *req_regs;
+
+	u32 ack_status;
+
+	const struct qcom_rpm_data *data;
+};
+
+#define RPM_STATUS_REG(rpm, i)	((rpm)->status_regs + (i) * 4)
+#define RPM_CTRL_REG(rpm, i)	((rpm)->ctrl_regs + (i) * 4)
+#define RPM_REQ_REG(rpm, i)	((rpm)->req_regs + (i) * 4)
+
+#define RPM_REQUEST_TIMEOUT	(5 * HZ)
+
+#define RPM_REQUEST_CONTEXT	3
+#define RPM_REQ_SELECT		11
+#define RPM_ACK_CONTEXT		15
+#define RPM_ACK_SELECTOR	23
+#define RPM_SELECT_SIZE		7
+
+#define RPM_NOTIFICATION	BIT(30)
+#define RPM_REJECTED		BIT(31)
+
+#define RPM_SIGNAL		BIT(2)
+
+static const struct qcom_rpm_resource apq8064_rpm_resource_table[] = {
+	[QCOM_RPM_CXO_CLK] =			{ 25, 9, 5, 1 },
+	[QCOM_RPM_PXO_CLK] =			{ 26, 10, 6, 1 },
+	[QCOM_RPM_APPS_FABRIC_CLK] =		{ 27, 11, 8, 1 },
+	[QCOM_RPM_SYS_FABRIC_CLK] =		{ 28, 12, 9, 1 },
+	[QCOM_RPM_MM_FABRIC_CLK] =		{ 29, 13, 10, 1 },
+	[QCOM_RPM_DAYTONA_FABRIC_CLK] =		{ 30, 14, 11, 1 },
+	[QCOM_RPM_SFPB_CLK] =			{ 31, 15, 12, 1 },
+	[QCOM_RPM_CFPB_CLK] =			{ 32, 16, 13, 1 },
+	[QCOM_RPM_MMFPB_CLK] =			{ 33, 17, 14, 1 },
+	[QCOM_RPM_EBI1_CLK] =			{ 34, 18, 16, 1 },
+	[QCOM_RPM_APPS_FABRIC_HALT] =		{ 35, 19, 18, 1 },
+	[QCOM_RPM_APPS_FABRIC_MODE] =		{ 37, 20, 19, 1 },
+	[QCOM_RPM_APPS_FABRIC_IOCTL] =		{ 40, 21, 20, 1 },
+	[QCOM_RPM_APPS_FABRIC_ARB] =		{ 41, 22, 21, 12 },
+	[QCOM_RPM_SYS_FABRIC_HALT] =		{ 53, 23, 22, 1 },
+	[QCOM_RPM_SYS_FABRIC_MODE] =		{ 55, 24, 23, 1 },
+	[QCOM_RPM_SYS_FABRIC_IOCTL] =		{ 58, 25, 24, 1 },
+	[QCOM_RPM_SYS_FABRIC_ARB] =		{ 59, 26, 25, 30 },
+	[QCOM_RPM_MM_FABRIC_HALT] =		{ 89, 27, 26, 1 },
+	[QCOM_RPM_MM_FABRIC_MODE] =		{ 91, 28, 27, 1 },
+	[QCOM_RPM_MM_FABRIC_IOCTL] =		{ 94, 29, 28, 1 },
+	[QCOM_RPM_MM_FABRIC_ARB] =		{ 95, 30, 29, 21 },
+	[QCOM_RPM_PM8921_SMPS1] =		{ 116, 31, 30, 2 },
+	[QCOM_RPM_PM8921_SMPS2] =		{ 118, 33, 31, 2 },
+	[QCOM_RPM_PM8921_SMPS3] =		{ 120, 35, 32, 2 },
+	[QCOM_RPM_PM8921_SMPS4] =		{ 122, 37, 33, 2 },
+	[QCOM_RPM_PM8921_SMPS5] =		{ 124, 39, 34, 2 },
+	[QCOM_RPM_PM8921_SMPS6] =		{ 126, 41, 35, 2 },
+	[QCOM_RPM_PM8921_SMPS7] =		{ 128, 43, 36, 2 },
+	[QCOM_RPM_PM8921_SMPS8] =		{ 130, 45, 37, 2 },
+	[QCOM_RPM_PM8921_LDO1] =		{ 132, 47, 38, 2 },
+	[QCOM_RPM_PM8921_LDO2] =		{ 134, 49, 39, 2 },
+	[QCOM_RPM_PM8921_LDO3] =		{ 136, 51, 40, 2 },
+	[QCOM_RPM_PM8921_LDO4] =		{ 138, 53, 41, 2 },
+	[QCOM_RPM_PM8921_LDO5] =		{ 140, 55, 42, 2 },
+	[QCOM_RPM_PM8921_LDO6] =		{ 142, 57, 43, 2 },
+	[QCOM_RPM_PM8921_LDO7] =		{ 144, 59, 44, 2 },
+	[QCOM_RPM_PM8921_LDO8] =		{ 146, 61, 45, 2 },
+	[QCOM_RPM_PM8921_LDO9] =		{ 148, 63, 46, 2 },
+	[QCOM_RPM_PM8921_LDO10] =		{ 150, 65, 47, 2 },
+	[QCOM_RPM_PM8921_LDO11] =		{ 152, 67, 48, 2 },
+	[QCOM_RPM_PM8921_LDO12] =		{ 154, 69, 49, 2 },
+	[QCOM_RPM_PM8921_LDO13] =		{ 156, 71, 50, 2 },
+	[QCOM_RPM_PM8921_LDO14] =		{ 158, 73, 51, 2 },
+	[QCOM_RPM_PM8921_LDO15] =		{ 160, 75, 52, 2 },
+	[QCOM_RPM_PM8921_LDO16] =		{ 162, 77, 53, 2 },
+	[QCOM_RPM_PM8921_LDO17] =		{ 164, 79, 54, 2 },
+	[QCOM_RPM_PM8921_LDO18] =		{ 166, 81, 55, 2 },
+	[QCOM_RPM_PM8921_LDO19] =		{ 168, 83, 56, 2 },
+	[QCOM_RPM_PM8921_LDO20] =		{ 170, 85, 57, 2 },
+	[QCOM_RPM_PM8921_LDO21] =		{ 172, 87, 58, 2 },
+	[QCOM_RPM_PM8921_LDO22] =		{ 174, 89, 59, 2 },
+	[QCOM_RPM_PM8921_LDO23] =		{ 176, 91, 60, 2 },
+	[QCOM_RPM_PM8921_LDO24] =		{ 178, 93, 61, 2 },
+	[QCOM_RPM_PM8921_LDO25] =		{ 180, 95, 62, 2 },
+	[QCOM_RPM_PM8921_LDO26] =		{ 182, 97, 63, 2 },
+	[QCOM_RPM_PM8921_LDO27] =		{ 184, 99, 64, 2 },
+	[QCOM_RPM_PM8921_LDO28] =		{ 186, 101, 65, 2 },
+	[QCOM_RPM_PM8921_LDO29] =		{ 188, 103, 66, 2 },
+	[QCOM_RPM_PM8921_CLK1] =		{ 190, 105, 67, 2 },
+	[QCOM_RPM_PM8921_CLK2] =		{ 192, 107, 68, 2 },
+	[QCOM_RPM_PM8921_LVS1] =		{ 194, 109, 69, 1 },
+	[QCOM_RPM_PM8921_LVS2] =		{ 195, 110, 70, 1 },
+	[QCOM_RPM_PM8921_LVS3] =		{ 196, 111, 71, 1 },
+	[QCOM_RPM_PM8921_LVS4] =		{ 197, 112, 72, 1 },
+	[QCOM_RPM_PM8921_LVS5] =		{ 198, 113, 73, 1 },
+	[QCOM_RPM_PM8921_LVS6] =		{ 199, 114, 74, 1 },
+	[QCOM_RPM_PM8921_LVS7] =		{ 200, 115, 75, 1 },
+	[QCOM_RPM_PM8821_SMPS1] =		{ 201, 116, 76, 2 },
+	[QCOM_RPM_PM8821_SMPS2] =		{ 203, 118, 77, 2 },
+	[QCOM_RPM_PM8821_LDO1] =		{ 205, 120, 78, 2 },
+	[QCOM_RPM_PM8921_NCP] =			{ 207, 122, 80, 2 },
+	[QCOM_RPM_CXO_BUFFERS] =		{ 209, 124, 81, 1 },
+	[QCOM_RPM_USB_OTG_SWITCH] =		{ 210, 125, 82, 1 },
+	[QCOM_RPM_HDMI_SWITCH] =		{ 211, 126, 83, 1 },
+	[QCOM_RPM_DDR_DMM] =			{ 212, 127, 84, 2 },
+	[QCOM_RPM_VDDMIN_GPIO] =		{ 215, 131, 89, 1 },
+};
+
+static const struct qcom_rpm_data apq8064_template = {
+	.version = 3,
+	.resource_table = apq8064_rpm_resource_table,
+	.n_resources = ARRAY_SIZE(apq8064_rpm_resource_table),
+};
+
+static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = {
+	[QCOM_RPM_CXO_CLK] =			{ 32, 12, 5, 1 },
+	[QCOM_RPM_PXO_CLK] =			{ 33, 13, 6, 1 },
+	[QCOM_RPM_PLL_4] =			{ 34, 14, 7, 1 },
+	[QCOM_RPM_APPS_FABRIC_CLK] =		{ 35, 15, 8, 1 },
+	[QCOM_RPM_SYS_FABRIC_CLK] =		{ 36, 16, 9, 1 },
+	[QCOM_RPM_MM_FABRIC_CLK] =		{ 37, 17, 10, 1 },
+	[QCOM_RPM_DAYTONA_FABRIC_CLK] =		{ 38, 18, 11, 1 },
+	[QCOM_RPM_SFPB_CLK] =			{ 39, 19, 12, 1 },
+	[QCOM_RPM_CFPB_CLK] =			{ 40, 20, 13, 1 },
+	[QCOM_RPM_MMFPB_CLK] =			{ 41, 21, 14, 1 },
+	[QCOM_RPM_SMI_CLK] =			{ 42, 22, 15, 1 },
+	[QCOM_RPM_EBI1_CLK] =			{ 43, 23, 16, 1 },
+	[QCOM_RPM_APPS_L2_CACHE_CTL] =		{ 44, 24, 17, 1 },
+	[QCOM_RPM_APPS_FABRIC_HALT] =		{ 45, 25, 18, 2 },
+	[QCOM_RPM_APPS_FABRIC_MODE] =		{ 47, 26, 19, 3 },
+	[QCOM_RPM_APPS_FABRIC_ARB] =		{ 51, 28, 21, 6 },
+	[QCOM_RPM_SYS_FABRIC_HALT] =		{ 63, 29, 22, 2 },
+	[QCOM_RPM_SYS_FABRIC_MODE] =		{ 65, 30, 23, 3 },
+	[QCOM_RPM_SYS_FABRIC_ARB] =		{ 69, 32, 25, 22 },
+	[QCOM_RPM_MM_FABRIC_HALT] =		{ 105, 33, 26, 2 },
+	[QCOM_RPM_MM_FABRIC_MODE] =		{ 107, 34, 27, 3 },
+	[QCOM_RPM_MM_FABRIC_ARB] =		{ 111, 36, 29, 23 },
+	[QCOM_RPM_PM8901_SMPS0] =		{ 134, 37, 30, 2 },
+	[QCOM_RPM_PM8901_SMPS1] =		{ 136, 39, 31, 2 },
+	[QCOM_RPM_PM8901_SMPS2] =		{ 138, 41, 32, 2 },
+	[QCOM_RPM_PM8901_SMPS3] =		{ 140, 43, 33, 2 },
+	[QCOM_RPM_PM8901_SMPS4] =		{ 142, 45, 34, 2 },
+	[QCOM_RPM_PM8901_LDO0] =		{ 144, 47, 35, 2 },
+	[QCOM_RPM_PM8901_LDO1] =		{ 146, 49, 36, 2 },
+	[QCOM_RPM_PM8901_LDO2] =		{ 148, 51, 37, 2 },
+	[QCOM_RPM_PM8901_LDO3] =		{ 150, 53, 38, 2 },
+	[QCOM_RPM_PM8901_LDO4] =		{ 152, 55, 39, 2 },
+	[QCOM_RPM_PM8901_LDO5] =		{ 154, 57, 40, 2 },
+	[QCOM_RPM_PM8901_LDO6] =		{ 156, 59, 41, 2 },
+	[QCOM_RPM_PM8901_LVS0] =		{ 158, 61, 42, 1 },
+	[QCOM_RPM_PM8901_LVS1] =		{ 159, 62, 43, 1 },
+	[QCOM_RPM_PM8901_LVS2] =		{ 160, 63, 44, 1 },
+	[QCOM_RPM_PM8901_LVS3] =		{ 161, 64, 45, 1 },
+	[QCOM_RPM_PM8901_MVS] =			{ 162, 65, 46, 1 },
+	[QCOM_RPM_PM8058_SMPS0] =		{ 163, 66, 47, 2 },
+	[QCOM_RPM_PM8058_SMPS1] =		{ 165, 68, 48, 2 },
+	[QCOM_RPM_PM8058_SMPS2] =		{ 167, 70, 49, 2 },
+	[QCOM_RPM_PM8058_SMPS3] =		{ 169, 72, 50, 2 },
+	[QCOM_RPM_PM8058_SMPS4] =		{ 171, 74, 51, 2 },
+	[QCOM_RPM_PM8058_LDO0] =		{ 173, 76, 52, 2 },
+	[QCOM_RPM_PM8058_LDO1] =		{ 175, 78, 53, 2 },
+	[QCOM_RPM_PM8058_LDO2] =		{ 177, 80, 54, 2 },
+	[QCOM_RPM_PM8058_LDO3] =		{ 179, 82, 55, 2 },
+	[QCOM_RPM_PM8058_LDO4] =		{ 181, 84, 56, 2 },
+	[QCOM_RPM_PM8058_LDO5] =		{ 183, 86, 57, 2 },
+	[QCOM_RPM_PM8058_LDO6] =		{ 185, 88, 58, 2 },
+	[QCOM_RPM_PM8058_LDO7] =		{ 187, 90, 59, 2 },
+	[QCOM_RPM_PM8058_LDO8] =		{ 189, 92, 60, 2 },
+	[QCOM_RPM_PM8058_LDO9] =		{ 191, 94, 61, 2 },
+	[QCOM_RPM_PM8058_LDO10] =		{ 193, 96, 62, 2 },
+	[QCOM_RPM_PM8058_LDO11] =		{ 195, 98, 63, 2 },
+	[QCOM_RPM_PM8058_LDO12] =		{ 197, 100, 64, 2 },
+	[QCOM_RPM_PM8058_LDO13] =		{ 199, 102, 65, 2 },
+	[QCOM_RPM_PM8058_LDO14] =		{ 201, 104, 66, 2 },
+	[QCOM_RPM_PM8058_LDO15] =		{ 203, 106, 67, 2 },
+	[QCOM_RPM_PM8058_LDO16] =		{ 205, 108, 68, 2 },
+	[QCOM_RPM_PM8058_LDO17] =		{ 207, 110, 69, 2 },
+	[QCOM_RPM_PM8058_LDO18] =		{ 209, 112, 70, 2 },
+	[QCOM_RPM_PM8058_LDO19] =		{ 211, 114, 71, 2 },
+	[QCOM_RPM_PM8058_LDO20] =		{ 213, 116, 72, 2 },
+	[QCOM_RPM_PM8058_LDO21] =		{ 215, 118, 73, 2 },
+	[QCOM_RPM_PM8058_LDO22] =		{ 217, 120, 74, 2 },
+	[QCOM_RPM_PM8058_LDO23] =		{ 219, 122, 75, 2 },
+	[QCOM_RPM_PM8058_LDO24] =		{ 221, 124, 76, 2 },
+	[QCOM_RPM_PM8058_LDO25] =		{ 223, 126, 77, 2 },
+	[QCOM_RPM_PM8058_LVS0] =		{ 225, 128, 78, 1 },
+	[QCOM_RPM_PM8058_LVS1] =		{ 226, 129, 79, 1 },
+	[QCOM_RPM_PM8058_NCP] =			{ 227, 130, 80, 2 },
+	[QCOM_RPM_CXO_BUFFERS] =		{ 229, 132, 81, 1 },
+};
+
+static const struct qcom_rpm_data msm8660_template = {
+	.version = 2,
+	.resource_table = msm8660_rpm_resource_table,
+	.n_resources = ARRAY_SIZE(msm8660_rpm_resource_table),
+};
+
+static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = {
+	[QCOM_RPM_CXO_CLK] =			{ 25, 9, 5, 1 },
+	[QCOM_RPM_PXO_CLK] =			{ 26, 10, 6, 1 },
+	[QCOM_RPM_APPS_FABRIC_CLK] =		{ 27, 11, 8, 1 },
+	[QCOM_RPM_SYS_FABRIC_CLK] =		{ 28, 12, 9, 1 },
+	[QCOM_RPM_MM_FABRIC_CLK] =		{ 29, 13, 10, 1 },
+	[QCOM_RPM_DAYTONA_FABRIC_CLK] =		{ 30, 14, 11, 1 },
+	[QCOM_RPM_SFPB_CLK] =			{ 31, 15, 12, 1 },
+	[QCOM_RPM_CFPB_CLK] =			{ 32, 16, 13, 1 },
+	[QCOM_RPM_MMFPB_CLK] =			{ 33, 17, 14, 1 },
+	[QCOM_RPM_EBI1_CLK] =			{ 34, 18, 16, 1 },
+	[QCOM_RPM_APPS_FABRIC_HALT] =		{ 35, 19, 18, 1 },
+	[QCOM_RPM_APPS_FABRIC_MODE] =		{ 37, 20, 19, 1 },
+	[QCOM_RPM_APPS_FABRIC_IOCTL] =		{ 40, 21, 20, 1 },
+	[QCOM_RPM_APPS_FABRIC_ARB] =		{ 41, 22, 21, 12 },
+	[QCOM_RPM_SYS_FABRIC_HALT] =		{ 53, 23, 22, 1 },
+	[QCOM_RPM_SYS_FABRIC_MODE] =		{ 55, 24, 23, 1 },
+	[QCOM_RPM_SYS_FABRIC_IOCTL] =		{ 58, 25, 24, 1 },
+	[QCOM_RPM_SYS_FABRIC_ARB] =		{ 59, 26, 25, 29 },
+	[QCOM_RPM_MM_FABRIC_HALT] =		{ 88, 27, 26, 1 },
+	[QCOM_RPM_MM_FABRIC_MODE] =		{ 90, 28, 27, 1 },
+	[QCOM_RPM_MM_FABRIC_IOCTL] =		{ 93, 29, 28, 1 },
+	[QCOM_RPM_MM_FABRIC_ARB] =		{ 94, 30, 29, 23 },
+	[QCOM_RPM_PM8921_SMPS1] =		{ 117, 31, 30, 2 },
+	[QCOM_RPM_PM8921_SMPS2] =		{ 119, 33, 31, 2 },
+	[QCOM_RPM_PM8921_SMPS3] =		{ 121, 35, 32, 2 },
+	[QCOM_RPM_PM8921_SMPS4] =		{ 123, 37, 33, 2 },
+	[QCOM_RPM_PM8921_SMPS5] =		{ 125, 39, 34, 2 },
+	[QCOM_RPM_PM8921_SMPS6] =		{ 127, 41, 35, 2 },
+	[QCOM_RPM_PM8921_SMPS7] =		{ 129, 43, 36, 2 },
+	[QCOM_RPM_PM8921_SMPS8] =		{ 131, 45, 37, 2 },
+	[QCOM_RPM_PM8921_LDO1] =		{ 133, 47, 38, 2 },
+	[QCOM_RPM_PM8921_LDO2] =		{ 135, 49, 39, 2 },
+	[QCOM_RPM_PM8921_LDO3] =		{ 137, 51, 40, 2 },
+	[QCOM_RPM_PM8921_LDO4] =		{ 139, 53, 41, 2 },
+	[QCOM_RPM_PM8921_LDO5] =		{ 141, 55, 42, 2 },
+	[QCOM_RPM_PM8921_LDO6] =		{ 143, 57, 43, 2 },
+	[QCOM_RPM_PM8921_LDO7] =		{ 145, 59, 44, 2 },
+	[QCOM_RPM_PM8921_LDO8] =		{ 147, 61, 45, 2 },
+	[QCOM_RPM_PM8921_LDO9] =		{ 149, 63, 46, 2 },
+	[QCOM_RPM_PM8921_LDO10] =		{ 151, 65, 47, 2 },
+	[QCOM_RPM_PM8921_LDO11] =		{ 153, 67, 48, 2 },
+	[QCOM_RPM_PM8921_LDO12] =		{ 155, 69, 49, 2 },
+	[QCOM_RPM_PM8921_LDO13] =		{ 157, 71, 50, 2 },
+	[QCOM_RPM_PM8921_LDO14] =		{ 159, 73, 51, 2 },
+	[QCOM_RPM_PM8921_LDO15] =		{ 161, 75, 52, 2 },
+	[QCOM_RPM_PM8921_LDO16] =		{ 163, 77, 53, 2 },
+	[QCOM_RPM_PM8921_LDO17] =		{ 165, 79, 54, 2 },
+	[QCOM_RPM_PM8921_LDO18] =		{ 167, 81, 55, 2 },
+	[QCOM_RPM_PM8921_LDO19] =		{ 169, 83, 56, 2 },
+	[QCOM_RPM_PM8921_LDO20] =		{ 171, 85, 57, 2 },
+	[QCOM_RPM_PM8921_LDO21] =		{ 173, 87, 58, 2 },
+	[QCOM_RPM_PM8921_LDO22] =		{ 175, 89, 59, 2 },
+	[QCOM_RPM_PM8921_LDO23] =		{ 177, 91, 60, 2 },
+	[QCOM_RPM_PM8921_LDO24] =		{ 179, 93, 61, 2 },
+	[QCOM_RPM_PM8921_LDO25] =		{ 181, 95, 62, 2 },
+	[QCOM_RPM_PM8921_LDO26] =		{ 183, 97, 63, 2 },
+	[QCOM_RPM_PM8921_LDO27] =		{ 185, 99, 64, 2 },
+	[QCOM_RPM_PM8921_LDO28] =		{ 187, 101, 65, 2 },
+	[QCOM_RPM_PM8921_LDO29] =		{ 189, 103, 66, 2 },
+	[QCOM_RPM_PM8921_CLK1] =		{ 191, 105, 67, 2 },
+	[QCOM_RPM_PM8921_CLK2] =		{ 193, 107, 68, 2 },
+	[QCOM_RPM_PM8921_LVS1] =		{ 195, 109, 69, 1 },
+	[QCOM_RPM_PM8921_LVS2] =		{ 196, 110, 70, 1 },
+	[QCOM_RPM_PM8921_LVS3] =		{ 197, 111, 71, 1 },
+	[QCOM_RPM_PM8921_LVS4] =		{ 198, 112, 72, 1 },
+	[QCOM_RPM_PM8921_LVS5] =		{ 199, 113, 73, 1 },
+	[QCOM_RPM_PM8921_LVS6] =		{ 200, 114, 74, 1 },
+	[QCOM_RPM_PM8921_LVS7] =		{ 201, 115, 75, 1 },
+	[QCOM_RPM_PM8921_NCP] =			{ 202, 116, 80, 2 },
+	[QCOM_RPM_CXO_BUFFERS] =		{ 204, 118, 81, 1 },
+	[QCOM_RPM_USB_OTG_SWITCH] =		{ 205, 119, 82, 1 },
+	[QCOM_RPM_HDMI_SWITCH] =		{ 206, 120, 83, 1 },
+	[QCOM_RPM_DDR_DMM] =			{ 207, 121, 84, 2 },
+};
+
+static const struct qcom_rpm_data msm8960_template = {
+	.version = 3,
+	.resource_table = msm8960_rpm_resource_table,
+	.n_resources = ARRAY_SIZE(msm8960_rpm_resource_table),
+};
+
+static const struct of_device_id qcom_rpm_of_match[] = {
+	{ .compatible = "qcom,rpm-apq8064", .data = &apq8064_template },
+	{ .compatible = "qcom,rpm-msm8660", .data = &msm8660_template },
+	{ .compatible = "qcom,rpm-msm8960", .data = &msm8960_template },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, qcom_rpm_of_match);
+
+int qcom_rpm_write(struct qcom_rpm *rpm,
+		   int state,
+		   int resource,
+		   u32 *buf, size_t count)
+{
+	const struct qcom_rpm_resource *res;
+	const struct qcom_rpm_data *data = rpm->data;
+	u32 sel_mask[RPM_SELECT_SIZE] = { 0 };
+	int left;
+	int ret = 0;
+	int i;
+
+	if (WARN_ON(resource < 0 || resource >= data->n_resources))
+		return -EINVAL;
+
+	res = &data->resource_table[resource];
+	if (WARN_ON(res->size != count))
+		return -EINVAL;
+
+	mutex_lock(&rpm->lock);
+
+	for (i = 0; i < res->size; i++)
+		writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i));
+
+	bitmap_set((unsigned long *)sel_mask, res->select_id, 1);
+	for (i = 0; i < ARRAY_SIZE(sel_mask); i++) {
+		writel_relaxed(sel_mask[i],
+			       RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
+	}
+
+	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
+
+	reinit_completion(&rpm->ack);
+	regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit));
+
+	left = wait_for_completion_timeout(&rpm->ack, RPM_REQUEST_TIMEOUT);
+	if (!left)
+		ret = -ETIMEDOUT;
+	else if (rpm->ack_status & RPM_REJECTED)
+		ret = -EIO;
+
+	mutex_unlock(&rpm->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(qcom_rpm_write);
+
+static irqreturn_t qcom_rpm_ack_interrupt(int irq, void *dev)
+{
+	struct qcom_rpm *rpm = dev;
+	u32 ack;
+	int i;
+
+	ack = readl_relaxed(RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT));
+	for (i = 0; i < RPM_SELECT_SIZE; i++)
+		writel_relaxed(0, RPM_CTRL_REG(rpm, RPM_ACK_SELECTOR + i));
+	writel(0, RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT));
+
+	if (ack & RPM_NOTIFICATION) {
+		dev_warn(rpm->dev, "ignoring notification!\n");
+	} else {
+		rpm->ack_status = ack;
+		complete(&rpm->ack);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t qcom_rpm_err_interrupt(int irq, void *dev)
+{
+	struct qcom_rpm *rpm = dev;
+
+	regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit));
+	dev_err(rpm->dev, "RPM triggered fatal error\n");
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t qcom_rpm_wakeup_interrupt(int irq, void *dev)
+{
+	return IRQ_HANDLED;
+}
+
+static int qcom_rpm_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	struct device_node *syscon_np;
+	struct resource *res;
+	struct qcom_rpm *rpm;
+	u32 fw_version[3];
+	int irq_wakeup;
+	int irq_ack;
+	int irq_err;
+	int ret;
+
+	rpm = devm_kzalloc(&pdev->dev, sizeof(*rpm), GFP_KERNEL);
+	if (!rpm)
+		return -ENOMEM;
+
+	rpm->dev = &pdev->dev;
+	mutex_init(&rpm->lock);
+	init_completion(&rpm->ack);
+
+	irq_ack = platform_get_irq_byname(pdev, "ack");
+	if (irq_ack < 0) {
+		dev_err(&pdev->dev, "required ack interrupt missing\n");
+		return irq_ack;
+	}
+
+	irq_err = platform_get_irq_byname(pdev, "err");
+	if (irq_err < 0) {
+		dev_err(&pdev->dev, "required err interrupt missing\n");
+		return irq_err;
+	}
+
+	irq_wakeup = platform_get_irq_byname(pdev, "wakeup");
+	if (irq_wakeup < 0) {
+		dev_err(&pdev->dev, "required wakeup interrupt missing\n");
+		return irq_wakeup;
+	}
+
+	match = of_match_device(qcom_rpm_of_match, &pdev->dev);
+	rpm->data = match->data;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	rpm->status_regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(rpm->status_regs))
+		return PTR_ERR(rpm->status_regs);
+	rpm->ctrl_regs = rpm->status_regs + 0x400;
+	rpm->req_regs = rpm->status_regs + 0x600;
+
+	syscon_np = of_parse_phandle(pdev->dev.of_node, "qcom,ipc", 0);
+	if (!syscon_np) {
+		dev_err(&pdev->dev, "no qcom,ipc node\n");
+		return -ENODEV;
+	}
+
+	rpm->ipc_regmap = syscon_node_to_regmap(syscon_np);
+	if (IS_ERR(rpm->ipc_regmap))
+		return PTR_ERR(rpm->ipc_regmap);
+
+	ret = of_property_read_u32_index(pdev->dev.of_node, "qcom,ipc", 1,
+					 &rpm->ipc_offset);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "no offset in qcom,ipc\n");
+		return -EINVAL;
+	}
+
+	ret = of_property_read_u32_index(pdev->dev.of_node, "qcom,ipc", 2,
+					 &rpm->ipc_bit);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "no bit in qcom,ipc\n");
+		return -EINVAL;
+	}
+
+	dev_set_drvdata(&pdev->dev, rpm);
+
+	fw_version[0] = readl(RPM_STATUS_REG(rpm, 0));
+	fw_version[1] = readl(RPM_STATUS_REG(rpm, 1));
+	fw_version[2] = readl(RPM_STATUS_REG(rpm, 2));
+	if (fw_version[0] != rpm->data->version) {
+		dev_err(&pdev->dev,
+			"RPM version %u.%u.%u incompatible with driver version %u",
+			fw_version[0],
+			fw_version[1],
+			fw_version[2],
+			rpm->data->version);
+		return -EFAULT;
+	}
+
+	dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0],
+							fw_version[1],
+							fw_version[2]);
+
+	ret = devm_request_irq(&pdev->dev,
+			       irq_ack,
+			       qcom_rpm_ack_interrupt,
+			       IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
+			       "qcom_rpm_ack",
+			       rpm);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request ack interrupt\n");
+		return ret;
+	}
+
+	ret = irq_set_irq_wake(irq_ack, 1);
+	if (ret)
+		dev_warn(&pdev->dev, "failed to mark ack irq as wakeup\n");
+
+	ret = devm_request_irq(&pdev->dev,
+			       irq_err,
+			       qcom_rpm_err_interrupt,
+			       IRQF_TRIGGER_RISING,
+			       "qcom_rpm_err",
+			       rpm);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request err interrupt\n");
+		return ret;
+	}
+
+	ret = devm_request_irq(&pdev->dev,
+			       irq_wakeup,
+			       qcom_rpm_wakeup_interrupt,
+			       IRQF_TRIGGER_RISING,
+			       "qcom_rpm_wakeup",
+			       rpm);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request wakeup interrupt\n");
+		return ret;
+	}
+
+	ret = irq_set_irq_wake(irq_wakeup, 1);
+	if (ret)
+		dev_warn(&pdev->dev, "failed to mark wakeup irq as wakeup\n");
+
+	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+}
+
+static int qcom_rpm_remove(struct platform_device *pdev)
+{
+	of_platform_depopulate(&pdev->dev);
+	return 0;
+}
+
+static struct platform_driver qcom_rpm_driver = {
+	.probe = qcom_rpm_probe,
+	.remove = qcom_rpm_remove,
+	.driver  = {
+		.name  = "qcom_rpm",
+		.of_match_table = qcom_rpm_of_match,
+	},
+};
+
+static int __init qcom_rpm_init(void)
+{
+	return platform_driver_register(&qcom_rpm_driver);
+}
+arch_initcall(qcom_rpm_init);
+
+static void __exit qcom_rpm_exit(void)
+{
+	platform_driver_unregister(&qcom_rpm_driver);
+}
+module_exit(qcom_rpm_exit)
+
+MODULE_DESCRIPTION("Qualcomm Resource Power Manager driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
diff --git a/include/linux/mfd/qcom_rpm.h b/include/linux/mfd/qcom_rpm.h
new file mode 100644
index 0000000..742ebf1
--- /dev/null
+++ b/include/linux/mfd/qcom_rpm.h
@@ -0,0 +1,13 @@
+#ifndef __QCOM_RPM_H__
+#define __QCOM_RPM_H__
+
+#include <linux/types.h>
+
+struct qcom_rpm;
+
+#define QCOM_RPM_ACTIVE_STATE	0
+#define QCOM_RPM_SLEEP_STATE	1
+
+int qcom_rpm_write(struct qcom_rpm *rpm, int state, int resource, u32 *buf, size_t count);
+
+#endif
-- 
1.8.2.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM
  2014-11-26 21:50 [PATCH v8 0/3] Qualcomm Resource Power Manager Bjorn Andersson
  2014-11-26 21:50 ` [PATCH v8 1/3] mfd: devicetree: bindings: Add Qualcomm RPM DT binding Bjorn Andersson
  2014-11-26 21:51 ` [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM Bjorn Andersson
@ 2014-11-26 21:51 ` Bjorn Andersson
  2014-11-27 11:07   ` Mark Brown
                     ` (2 more replies)
  2014-12-02 14:25 ` [PATCH v8 0/3] Qualcomm Resource Power Manager Srinivas Kandagatla
  3 siblings, 3 replies; 13+ messages in thread
From: Bjorn Andersson @ 2014-11-26 21:51 UTC (permalink / raw)
  To: Lee Jones, Rob Herring, Mark Brown
  Cc: Josh Cartwright, devicetree, linux-kernel, linux-arm-kernel,
	linux-arm-msm

This adds the missing state parameter to the call down to the RPM. This
is currently hard coded to the active state, as that's all we're
supporting at this moment.

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---
 drivers/regulator/qcom_rpm-regulator.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
index b55cd5b..8f66040 100644
--- a/drivers/regulator/qcom_rpm-regulator.c
+++ b/drivers/regulator/qcom_rpm-regulator.c
@@ -198,6 +198,7 @@ static int rpm_reg_write(struct qcom_rpm_reg *vreg,
 	vreg->val[req->word] |= value << req->shift;
 
 	return qcom_rpm_write(vreg->rpm,
+			      QCOM_RPM_ACTIVE_STATE,
 			      vreg->resource,
 			      vreg->val,
 			      vreg->parts->request_len);
-- 
1.8.2.2


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM
  2014-11-26 21:51 ` [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM Bjorn Andersson
@ 2014-11-27 11:07   ` Mark Brown
  2015-01-20 14:19   ` Lee Jones
  2015-01-20 17:02   ` Lee Jones
  2 siblings, 0 replies; 13+ messages in thread
From: Mark Brown @ 2014-11-27 11:07 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Lee Jones, Rob Herring, Josh Cartwright, devicetree,
	linux-kernel, linux-arm-kernel, linux-arm-msm

[-- Attachment #1: Type: text/plain, Size: 278 bytes --]

On Wed, Nov 26, 2014 at 01:51:01PM -0800, Bjorn Andersson wrote:
> This adds the missing state parameter to the call down to the RPM. This
> is currently hard coded to the active state, as that's all we're
> supporting at this moment.

Acked-by: Mark Brown <broonie@kernel.org>

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 0/3] Qualcomm Resource Power Manager
  2014-11-26 21:50 [PATCH v8 0/3] Qualcomm Resource Power Manager Bjorn Andersson
                   ` (2 preceding siblings ...)
  2014-11-26 21:51 ` [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM Bjorn Andersson
@ 2014-12-02 14:25 ` Srinivas Kandagatla
  3 siblings, 0 replies; 13+ messages in thread
From: Srinivas Kandagatla @ 2014-12-02 14:25 UTC (permalink / raw)
  To: Bjorn Andersson, Lee Jones, Rob Herring, Mark Brown
  Cc: Josh Cartwright, devicetree, linux-kernel, linux-arm-kernel,
	linux-arm-msm

Hi Bjorn,

Thanks for the patches, I tested few regulators which are connected to 
IO devices with this series on IFC6410 with APQ8064 and they work fine. 
Except one issue which you already are aware of "regulator dependencies 
on each other" I guess this is another topic which can be discussed 
separately to this patchset.

Tested-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>


--srini
On 26/11/14 21:50, Bjorn Andersson wrote:
> In order to support the SoC assisted power save features of the Qualcomm
> platform some changes are most likely needed to the regulator part of the DT
> bindings provided before.
>
> This version of the patchset carries the RPM core part, which allows us to move
> forward with merging Josh's patches [1] as well as aiding the discussion and
> development of the additional patches needed to properly implement the power
> save features being discussed.
>
> It also carries the patch to the already merged regulator driver, to make it
> compile.
>
> [1] https://lkml.org/lkml/2014/11/20/629
>
> Changes since v7:
>    - Mark merged the regulator part of the previous series
>    - Removed regulator part of dt binding, for further discussions
>
> Changes since v6:
>    - Changed filenames from qcom,rpm.{txt,h} to qcom-rpm.{txt,h}
>
> Changes since v5:
>    - Clarified dt binding
>    - Converted regulator qcom,force-mode to enum instead of multi-boolean
>    - Remove unecessary version handshake
>    - Cleaned up naming of RPM resources between different RPM versions
>    - Updated regulator qcom,force-mode parsing
>    - Updated regulator qcom,power-mode-* parsing
>    - Cleanups in rpm driver
>    - Dropped dev_get_qcom_rpm helper function
>
> Changes since v4:
>    - Moved RPM driver to mfd
>
> Changes since v3:
>    - IPC register is acquired through syscon, as it's shared with others
>
> Changes since v2:
>    - Fix copy-paste error in dt binding
>    - Correct incomplete move from mfd to soc
>    - Correct const mistake in regulator driver
>
> Changes since v1:
>    - Moved rpm driver to drivers/soc
>    - Extracted resource table structs from rpm struct, as per Srinivas request
>    - Dropped mode setting support for the regulators for now. Unsure if we need
>      it and it requires some rework from the codeaurora solution.
>    - Using set_voltage_sel instead of rolling my own "snapping", as per Marks
>      request
>    - Split regulator ops in mV, uV and swtich versions as per Marks request.
>    - Added devicetree property to enable pull down.
>
> Bjorn Andersson (3):
>    mfd: devicetree: bindings: Add Qualcomm RPM DT binding
>    mfd: qcom-rpm: Driver for the Qualcomm RPM
>    regulator: qcom-rpm: Add missing state flag in call to RPM
>
>   Documentation/devicetree/bindings/mfd/qcom-rpm.txt |  70 +++
>   drivers/mfd/Kconfig                                |  14 +
>   drivers/mfd/Makefile                               |   1 +
>   drivers/mfd/qcom_rpm.c                             | 581 +++++++++++++++++++++
>   drivers/regulator/qcom_rpm-regulator.c             |   1 +
>   include/dt-bindings/mfd/qcom-rpm.h                 | 154 ++++++
>   include/linux/mfd/qcom_rpm.h                       |  13 +
>   7 files changed, 834 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/mfd/qcom-rpm.txt
>   create mode 100644 drivers/mfd/qcom_rpm.c
>   create mode 100644 include/dt-bindings/mfd/qcom-rpm.h
>   create mode 100644 include/linux/mfd/qcom_rpm.h
>
> --
> 1.8.2.2
>
> --
> 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
>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM
  2014-11-26 21:51 ` [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM Bjorn Andersson
@ 2014-12-22 10:50   ` Paul Bolle
  2014-12-26 20:11     ` Bjorn Andersson
  2015-01-20 17:02   ` Lee Jones
  1 sibling, 1 reply; 13+ messages in thread
From: Paul Bolle @ 2014-12-22 10:50 UTC (permalink / raw)
  To: Bjorn Andersson, Mark Brown
  Cc: Valentin Rothberg, Lee Jones, Rob Herring, Josh Cartwright,
	devicetree, linux-kernel, linux-arm-kernel, linux-arm-msm

Hi Bjorn,

On Wed, 2014-11-26 at 13:51 -0800, Bjorn Andersson wrote:
> Driver for the Resource Power Manager (RPM) found in Qualcomm 8660, 8960
> and 8064 based devices. The driver exposes resources that child drivers
> can operate on; to implementing regulator, clock and bus frequency
> drivers.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
> 
> Lee, since your Acked-by earlier I've folded in the part of the RFC where I add
> an extra parameter to qcom_rpm_write(). Part of that this is unchanged.
> 
>  drivers/mfd/Kconfig          |  14 ++
>  drivers/mfd/Makefile         |   1 +
>  drivers/mfd/qcom_rpm.c       | 581 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/qcom_rpm.h |  13 +
>  4 files changed, 609 insertions(+)
>  create mode 100644 drivers/mfd/qcom_rpm.c
>  create mode 100644 include/linux/mfd/qcom_rpm.h
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 1456ea7..b6bcb79 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -567,6 +567,20 @@ config MFD_PM8921_CORE
>  	  Say M here if you want to include support for PM8921 chip as a module.
>  	  This will build a module called "pm8921-core".
>  
> +config MFD_QCOM_RPM
> +	tristate "Qualcomm Resource Power Manager (RPM)"
> +	depends on ARCH_QCOM && OF
> +	help
> +	  If you say yes to this option, support will be included for the
> +	  Resource Power Manager system found in the Qualcomm 8660, 8960 and
> +	  8064 based devices.
> +
> +	  This is required to access many regulators, clocks and bus
> +	  frequencies controlled by the RPM on these devices.
> +
> +	  Say M here if you want to include support for the Qualcomm RPM as a
> +	  module. This will build a module called "qcom_rpm".
> +

The Qualcomm RPM regulator driver (see Kconfig symbol
REGULATOR_QCOM_RPM) was added in v3.18. It depends on the above symbol,
so it has not yet gotten build coverage. Even manual hacks like
    make -C ../.. M=$PWD CONFIG_REGULATOR_QCOM_RPM=m qcom_rpm-regulator.ko

won't work for that driver, because it includes linux/mfd/qcom_rpm.h,
which is not part of the tree.

It seems there's no generally agreed upon guideline for situations like
this. So I guess it's up to Mark to decide how long the tree should
include an unbuildable driver.


Paul Bolle


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM
  2014-12-22 10:50   ` Paul Bolle
@ 2014-12-26 20:11     ` Bjorn Andersson
  0 siblings, 0 replies; 13+ messages in thread
From: Bjorn Andersson @ 2014-12-26 20:11 UTC (permalink / raw)
  To: Paul Bolle, Lee Jones
  Cc: Bjorn Andersson, Mark Brown, Valentin Rothberg, Rob Herring,
	Josh Cartwright, devicetree, linux-kernel, linux-arm-kernel,
	linux-arm-msm

On Mon, Dec 22, 2014 at 2:50 AM, Paul Bolle <pebolle@tiscali.nl> wrote:
> Hi Bjorn,
>

Hi Paul

[..]
>
> The Qualcomm RPM regulator driver (see Kconfig symbol
> REGULATOR_QCOM_RPM) was added in v3.18. It depends on the above symbol,
> so it has not yet gotten build coverage. Even manual hacks like
>     make -C ../.. M=$PWD CONFIG_REGULATOR_QCOM_RPM=m qcom_rpm-regulator.ko
>
> won't work for that driver, because it includes linux/mfd/qcom_rpm.h,
> which is not part of the tree.
>

Correct, but unfortunately Lee Jones awaits devicetree maintainers ack
(or any comment) and have been doing so for months now. I did send out
a ping a few weeks ago, but might have done so when they where
occupied by the merge window.


Lee, the Qualcomm RPM binding is not for a subsystem and is limited to
Qualcomm devices. Could we apply this in accordance with II.2 in
Documentation/devicetree/bindings/submitting-patches.txt or is there
anything I could do to make you feel comfortable doing so?

> It seems there's no generally agreed upon guideline for situations like
> this. So I guess it's up to Mark to decide how long the tree should
> include an unbuildable driver.
>

I haven't seen any guidelines, but appreciate Mark's way of working in
this matter - as we've been able to run our devices with fewer
out-of-tree patches.

Regards,
Bjorn

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM
  2014-11-26 21:51 ` [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM Bjorn Andersson
  2014-11-27 11:07   ` Mark Brown
@ 2015-01-20 14:19   ` Lee Jones
  2015-01-20 16:14     ` Mark Brown
  2015-01-20 17:02   ` Lee Jones
  2 siblings, 1 reply; 13+ messages in thread
From: Lee Jones @ 2015-01-20 14:19 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Herring, Mark Brown, Josh Cartwright, devicetree,
	linux-kernel, linux-arm-kernel, linux-arm-msm

Mark,

Do you want a pull-request for this, or can I absorb it right into my
tree?

> This adds the missing state parameter to the call down to the RPM. This
> is currently hard coded to the active state, as that's all we're
> supporting at this moment.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
>  drivers/regulator/qcom_rpm-regulator.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
> index b55cd5b..8f66040 100644
> --- a/drivers/regulator/qcom_rpm-regulator.c
> +++ b/drivers/regulator/qcom_rpm-regulator.c
> @@ -198,6 +198,7 @@ static int rpm_reg_write(struct qcom_rpm_reg *vreg,
>  	vreg->val[req->word] |= value << req->shift;
>  
>  	return qcom_rpm_write(vreg->rpm,
> +			      QCOM_RPM_ACTIVE_STATE,
>  			      vreg->resource,
>  			      vreg->val,
>  			      vreg->parts->request_len);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM
  2015-01-20 14:19   ` Lee Jones
@ 2015-01-20 16:14     ` Mark Brown
  0 siblings, 0 replies; 13+ messages in thread
From: Mark Brown @ 2015-01-20 16:14 UTC (permalink / raw)
  To: Lee Jones
  Cc: Bjorn Andersson, Rob Herring, Josh Cartwright, devicetree,
	linux-kernel, linux-arm-kernel, linux-arm-msm

[-- Attachment #1: Type: text/plain, Size: 156 bytes --]

On Tue, Jan 20, 2015 at 02:19:54PM +0000, Lee Jones wrote:

> Do you want a pull-request for this, or can I absorb it right into my
> tree?

Just apply it.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 1/3] mfd: devicetree: bindings: Add Qualcomm RPM DT binding
  2014-11-26 21:50 ` [PATCH v8 1/3] mfd: devicetree: bindings: Add Qualcomm RPM DT binding Bjorn Andersson
@ 2015-01-20 17:01   ` Lee Jones
  0 siblings, 0 replies; 13+ messages in thread
From: Lee Jones @ 2015-01-20 17:01 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Herring, Mark Brown, Josh Cartwright, devicetree,
	linux-kernel, linux-arm-kernel, linux-arm-msm

On Wed, 26 Nov 2014, Bjorn Andersson wrote:

> Add binding for the Qualcomm Resource Power Manager (RPM) found in 8660,
> 8960 and 8064 based devices.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
> 
> Removed regulator definition from this patch, as these needs more discussion to
> be able to implement SoC assisted power save features of the Qualcomm
> platforms. No other changes.
> 
>  Documentation/devicetree/bindings/mfd/qcom-rpm.txt |  70 ++++++++++
>  include/dt-bindings/mfd/qcom-rpm.h                 | 154 +++++++++++++++++++++
>  2 files changed, 224 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mfd/qcom-rpm.txt
>  create mode 100644 include/dt-bindings/mfd/qcom-rpm.h

Applied, thanks.

> diff --git a/Documentation/devicetree/bindings/mfd/qcom-rpm.txt b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> new file mode 100644
> index 0000000..85e3198
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mfd/qcom-rpm.txt
> @@ -0,0 +1,70 @@
> +Qualcomm Resource Power Manager (RPM)
> +
> +This driver is used to interface with the Resource Power Manager (RPM) found in
> +various Qualcomm platforms. The RPM allows each component in the system to vote
> +for state of the system resources, such as clocks, regulators and bus
> +frequencies.
> +
> +- compatible:
> +	Usage: required
> +	Value type: <string>
> +	Definition: must be one of:
> +		    "qcom,rpm-apq8064"
> +		    "qcom,rpm-msm8660"
> +		    "qcom,rpm-msm8960"
> +
> +- reg:
> +	Usage: required
> +	Value type: <prop-encoded-array>
> +	Definition: base address and size of the RPM's message ram
> +
> +- interrupts:
> +	Usage: required
> +	Value type: <prop-encoded-array>
> +	Definition: three entries specifying the RPM's:
> +		    1. acknowledgement interrupt
> +		    2. error interrupt
> +		    3. wakeup interrupt
> +
> +- interrupt-names:
> +	Usage: required
> +	Value type: <string-array>
> +	Definition: must be the three strings "ack", "err" and "wakeup", in order
> +
> +- #address-cells:
> +	Usage: required
> +	Value type: <u32>
> +	Definition: must be 1
> +
> +- #size-cells:
> +	Usage: required
> +	Value type: <u32>
> +	Definition: must be 0
> +
> +- qcom,ipc:
> +	Usage: required
> +	Value type: <prop-encoded-array>
> +
> +	Definition: three entries specifying the outgoing ipc bit used for
> +		    signaling the RPM:
> +		    - phandle to a syscon node representing the apcs registers
> +		    - u32 representing offset to the register within the syscon
> +		    - u32 representing the ipc bit within the register
> +
> +
> += EXAMPLE
> +
> +	#include <dt-bindings/mfd/qcom-rpm.h>
> +
> +	rpm@108000 {
> +		compatible = "qcom,rpm-msm8960";
> +		reg = <0x108000 0x1000>;
> +		qcom,ipc = <&apcs 0x8 2>;
> +
> +		interrupts = <0 19 0>, <0 21 0>, <0 22 0>;
> +		interrupt-names = "ack", "err", "wakeup";
> +
> +		#address-cells = <1>;
> +		#size-cells = <0>;
> +	};
> +
> diff --git a/include/dt-bindings/mfd/qcom-rpm.h b/include/dt-bindings/mfd/qcom-rpm.h
> new file mode 100644
> index 0000000..388a6f3
> --- /dev/null
> +++ b/include/dt-bindings/mfd/qcom-rpm.h
> @@ -0,0 +1,154 @@
> +/*
> + * This header provides constants for the Qualcomm RPM bindings.
> + */
> +
> +#ifndef _DT_BINDINGS_MFD_QCOM_RPM_H
> +#define _DT_BINDINGS_MFD_QCOM_RPM_H
> +
> +/*
> + * Constants use to identify individual resources in the RPM.
> + */
> +#define QCOM_RPM_APPS_FABRIC_ARB		1
> +#define QCOM_RPM_APPS_FABRIC_CLK		2
> +#define QCOM_RPM_APPS_FABRIC_HALT		3
> +#define QCOM_RPM_APPS_FABRIC_IOCTL		4
> +#define QCOM_RPM_APPS_FABRIC_MODE		5
> +#define QCOM_RPM_APPS_L2_CACHE_CTL		6
> +#define QCOM_RPM_CFPB_CLK			7
> +#define QCOM_RPM_CXO_BUFFERS			8
> +#define QCOM_RPM_CXO_CLK			9
> +#define QCOM_RPM_DAYTONA_FABRIC_CLK		10
> +#define QCOM_RPM_DDR_DMM			11
> +#define QCOM_RPM_EBI1_CLK			12
> +#define QCOM_RPM_HDMI_SWITCH			13
> +#define QCOM_RPM_MMFPB_CLK			14
> +#define QCOM_RPM_MM_FABRIC_ARB			15
> +#define QCOM_RPM_MM_FABRIC_CLK			16
> +#define QCOM_RPM_MM_FABRIC_HALT			17
> +#define QCOM_RPM_MM_FABRIC_IOCTL		18
> +#define QCOM_RPM_MM_FABRIC_MODE			19
> +#define QCOM_RPM_PLL_4				20
> +#define QCOM_RPM_PM8058_LDO0			21
> +#define QCOM_RPM_PM8058_LDO1			22
> +#define QCOM_RPM_PM8058_LDO2			23
> +#define QCOM_RPM_PM8058_LDO3			24
> +#define QCOM_RPM_PM8058_LDO4			25
> +#define QCOM_RPM_PM8058_LDO5			26
> +#define QCOM_RPM_PM8058_LDO6			27
> +#define QCOM_RPM_PM8058_LDO7			28
> +#define QCOM_RPM_PM8058_LDO8			29
> +#define QCOM_RPM_PM8058_LDO9			30
> +#define QCOM_RPM_PM8058_LDO10			31
> +#define QCOM_RPM_PM8058_LDO11			32
> +#define QCOM_RPM_PM8058_LDO12			33
> +#define QCOM_RPM_PM8058_LDO13			34
> +#define QCOM_RPM_PM8058_LDO14			35
> +#define QCOM_RPM_PM8058_LDO15			36
> +#define QCOM_RPM_PM8058_LDO16			37
> +#define QCOM_RPM_PM8058_LDO17			38
> +#define QCOM_RPM_PM8058_LDO18			39
> +#define QCOM_RPM_PM8058_LDO19			40
> +#define QCOM_RPM_PM8058_LDO20			41
> +#define QCOM_RPM_PM8058_LDO21			42
> +#define QCOM_RPM_PM8058_LDO22			43
> +#define QCOM_RPM_PM8058_LDO23			44
> +#define QCOM_RPM_PM8058_LDO24			45
> +#define QCOM_RPM_PM8058_LDO25			46
> +#define QCOM_RPM_PM8058_LVS0			47
> +#define QCOM_RPM_PM8058_LVS1			48
> +#define QCOM_RPM_PM8058_NCP			49
> +#define QCOM_RPM_PM8058_SMPS0			50
> +#define QCOM_RPM_PM8058_SMPS1			51
> +#define QCOM_RPM_PM8058_SMPS2			52
> +#define QCOM_RPM_PM8058_SMPS3			53
> +#define QCOM_RPM_PM8058_SMPS4			54
> +#define QCOM_RPM_PM8821_LDO1			55
> +#define QCOM_RPM_PM8821_SMPS1			56
> +#define QCOM_RPM_PM8821_SMPS2			57
> +#define QCOM_RPM_PM8901_LDO0			58
> +#define QCOM_RPM_PM8901_LDO1			59
> +#define QCOM_RPM_PM8901_LDO2			60
> +#define QCOM_RPM_PM8901_LDO3			61
> +#define QCOM_RPM_PM8901_LDO4			62
> +#define QCOM_RPM_PM8901_LDO5			63
> +#define QCOM_RPM_PM8901_LDO6			64
> +#define QCOM_RPM_PM8901_LVS0			65
> +#define QCOM_RPM_PM8901_LVS1			66
> +#define QCOM_RPM_PM8901_LVS2			67
> +#define QCOM_RPM_PM8901_LVS3			68
> +#define QCOM_RPM_PM8901_MVS			69
> +#define QCOM_RPM_PM8901_SMPS0			70
> +#define QCOM_RPM_PM8901_SMPS1			71
> +#define QCOM_RPM_PM8901_SMPS2			72
> +#define QCOM_RPM_PM8901_SMPS3			73
> +#define QCOM_RPM_PM8901_SMPS4			74
> +#define QCOM_RPM_PM8921_CLK1			75
> +#define QCOM_RPM_PM8921_CLK2			76
> +#define QCOM_RPM_PM8921_LDO1			77
> +#define QCOM_RPM_PM8921_LDO2			78
> +#define QCOM_RPM_PM8921_LDO3			79
> +#define QCOM_RPM_PM8921_LDO4			80
> +#define QCOM_RPM_PM8921_LDO5			81
> +#define QCOM_RPM_PM8921_LDO6			82
> +#define QCOM_RPM_PM8921_LDO7			83
> +#define QCOM_RPM_PM8921_LDO8			84
> +#define QCOM_RPM_PM8921_LDO9			85
> +#define QCOM_RPM_PM8921_LDO10			86
> +#define QCOM_RPM_PM8921_LDO11			87
> +#define QCOM_RPM_PM8921_LDO12			88
> +#define QCOM_RPM_PM8921_LDO13			89
> +#define QCOM_RPM_PM8921_LDO14			90
> +#define QCOM_RPM_PM8921_LDO15			91
> +#define QCOM_RPM_PM8921_LDO16			92
> +#define QCOM_RPM_PM8921_LDO17			93
> +#define QCOM_RPM_PM8921_LDO18			94
> +#define QCOM_RPM_PM8921_LDO19			95
> +#define QCOM_RPM_PM8921_LDO20			96
> +#define QCOM_RPM_PM8921_LDO21			97
> +#define QCOM_RPM_PM8921_LDO22			98
> +#define QCOM_RPM_PM8921_LDO23			99
> +#define QCOM_RPM_PM8921_LDO24			100
> +#define QCOM_RPM_PM8921_LDO25			101
> +#define QCOM_RPM_PM8921_LDO26			102
> +#define QCOM_RPM_PM8921_LDO27			103
> +#define QCOM_RPM_PM8921_LDO28			104
> +#define QCOM_RPM_PM8921_LDO29			105
> +#define QCOM_RPM_PM8921_LVS1			106
> +#define QCOM_RPM_PM8921_LVS2			107
> +#define QCOM_RPM_PM8921_LVS3			108
> +#define QCOM_RPM_PM8921_LVS4			109
> +#define QCOM_RPM_PM8921_LVS5			110
> +#define QCOM_RPM_PM8921_LVS6			111
> +#define QCOM_RPM_PM8921_LVS7			112
> +#define QCOM_RPM_PM8921_MVS			113
> +#define QCOM_RPM_PM8921_NCP			114
> +#define QCOM_RPM_PM8921_SMPS1			115
> +#define QCOM_RPM_PM8921_SMPS2			116
> +#define QCOM_RPM_PM8921_SMPS3			117
> +#define QCOM_RPM_PM8921_SMPS4			118
> +#define QCOM_RPM_PM8921_SMPS5			119
> +#define QCOM_RPM_PM8921_SMPS6			120
> +#define QCOM_RPM_PM8921_SMPS7			121
> +#define QCOM_RPM_PM8921_SMPS8			122
> +#define QCOM_RPM_PXO_CLK			123
> +#define QCOM_RPM_QDSS_CLK			124
> +#define QCOM_RPM_SFPB_CLK			125
> +#define QCOM_RPM_SMI_CLK			126
> +#define QCOM_RPM_SYS_FABRIC_ARB			127
> +#define QCOM_RPM_SYS_FABRIC_CLK			128
> +#define QCOM_RPM_SYS_FABRIC_HALT		129
> +#define QCOM_RPM_SYS_FABRIC_IOCTL		130
> +#define QCOM_RPM_SYS_FABRIC_MODE		131
> +#define QCOM_RPM_USB_OTG_SWITCH			132
> +#define QCOM_RPM_VDDMIN_GPIO			133
> +
> +/*
> + * Constants used to select force mode for regulators.
> + */
> +#define QCOM_RPM_FORCE_MODE_NONE		0
> +#define QCOM_RPM_FORCE_MODE_LPM			1
> +#define QCOM_RPM_FORCE_MODE_HPM			2
> +#define QCOM_RPM_FORCE_MODE_AUTO		3
> +#define QCOM_RPM_FORCE_MODE_BYPASS		4
> +
> +#endif

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM
  2014-11-26 21:51 ` [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM Bjorn Andersson
  2014-12-22 10:50   ` Paul Bolle
@ 2015-01-20 17:02   ` Lee Jones
  1 sibling, 0 replies; 13+ messages in thread
From: Lee Jones @ 2015-01-20 17:02 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Herring, Mark Brown, Josh Cartwright, devicetree,
	linux-kernel, linux-arm-kernel, linux-arm-msm

On Wed, 26 Nov 2014, Bjorn Andersson wrote:

> Driver for the Resource Power Manager (RPM) found in Qualcomm 8660, 8960
> and 8064 based devices. The driver exposes resources that child drivers
> can operate on; to implementing regulator, clock and bus frequency
> drivers.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
> 
> Lee, since your Acked-by earlier I've folded in the part of the RFC where I add
> an extra parameter to qcom_rpm_write(). Part of that this is unchanged.
> 
>  drivers/mfd/Kconfig          |  14 ++
>  drivers/mfd/Makefile         |   1 +
>  drivers/mfd/qcom_rpm.c       | 581 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/qcom_rpm.h |  13 +
>  4 files changed, 609 insertions(+)
>  create mode 100644 drivers/mfd/qcom_rpm.c
>  create mode 100644 include/linux/mfd/qcom_rpm.h

Applied, thanks.

> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 1456ea7..b6bcb79 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -567,6 +567,20 @@ config MFD_PM8921_CORE
>  	  Say M here if you want to include support for PM8921 chip as a module.
>  	  This will build a module called "pm8921-core".
>  
> +config MFD_QCOM_RPM
> +	tristate "Qualcomm Resource Power Manager (RPM)"
> +	depends on ARCH_QCOM && OF
> +	help
> +	  If you say yes to this option, support will be included for the
> +	  Resource Power Manager system found in the Qualcomm 8660, 8960 and
> +	  8064 based devices.
> +
> +	  This is required to access many regulators, clocks and bus
> +	  frequencies controlled by the RPM on these devices.
> +
> +	  Say M here if you want to include support for the Qualcomm RPM as a
> +	  module. This will build a module called "qcom_rpm".
> +
>  config MFD_SPMI_PMIC
>  	tristate "Qualcomm SPMI PMICs"
>  	depends on ARCH_QCOM || COMPILE_TEST
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 8bd54b1..3364bbc 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -153,6 +153,7 @@ obj-$(CONFIG_MFD_SI476X_CORE)	+= si476x-core.o
>  obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
>  obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o omap-usb-tll.o
>  obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o ssbi.o
> +obj-$(CONFIG_MFD_QCOM_RPM)	+= qcom_rpm.o
>  obj-$(CONFIG_MFD_SPMI_PMIC)	+= qcom-spmi-pmic.o
>  obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
>  obj-$(CONFIG_MFD_TPS65090)	+= tps65090.o
> diff --git a/drivers/mfd/qcom_rpm.c b/drivers/mfd/qcom_rpm.c
> new file mode 100644
> index 0000000..f696328
> --- /dev/null
> +++ b/drivers/mfd/qcom_rpm.c
> @@ -0,0 +1,581 @@
> +/*
> + * Copyright (c) 2014, Sony Mobile Communications AB.
> + * Copyright (c) 2013, The Linux Foundation. All rights reserved.
> + * Author: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 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/platform_device.h>
> +#include <linux/of_platform.h>
> +#include <linux/io.h>
> +#include <linux/interrupt.h>
> +#include <linux/mfd/qcom_rpm.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +
> +#include <dt-bindings/mfd/qcom-rpm.h>
> +
> +struct qcom_rpm_resource {
> +	unsigned target_id;
> +	unsigned status_id;
> +	unsigned select_id;
> +	unsigned size;
> +};
> +
> +struct qcom_rpm_data {
> +	u32 version;
> +	const struct qcom_rpm_resource *resource_table;
> +	unsigned n_resources;
> +};
> +
> +struct qcom_rpm {
> +	struct device *dev;
> +	struct regmap *ipc_regmap;
> +	unsigned ipc_offset;
> +	unsigned ipc_bit;
> +
> +	struct completion ack;
> +	struct mutex lock;
> +
> +	void __iomem *status_regs;
> +	void __iomem *ctrl_regs;
> +	void __iomem *req_regs;
> +
> +	u32 ack_status;
> +
> +	const struct qcom_rpm_data *data;
> +};
> +
> +#define RPM_STATUS_REG(rpm, i)	((rpm)->status_regs + (i) * 4)
> +#define RPM_CTRL_REG(rpm, i)	((rpm)->ctrl_regs + (i) * 4)
> +#define RPM_REQ_REG(rpm, i)	((rpm)->req_regs + (i) * 4)
> +
> +#define RPM_REQUEST_TIMEOUT	(5 * HZ)
> +
> +#define RPM_REQUEST_CONTEXT	3
> +#define RPM_REQ_SELECT		11
> +#define RPM_ACK_CONTEXT		15
> +#define RPM_ACK_SELECTOR	23
> +#define RPM_SELECT_SIZE		7
> +
> +#define RPM_NOTIFICATION	BIT(30)
> +#define RPM_REJECTED		BIT(31)
> +
> +#define RPM_SIGNAL		BIT(2)
> +
> +static const struct qcom_rpm_resource apq8064_rpm_resource_table[] = {
> +	[QCOM_RPM_CXO_CLK] =			{ 25, 9, 5, 1 },
> +	[QCOM_RPM_PXO_CLK] =			{ 26, 10, 6, 1 },
> +	[QCOM_RPM_APPS_FABRIC_CLK] =		{ 27, 11, 8, 1 },
> +	[QCOM_RPM_SYS_FABRIC_CLK] =		{ 28, 12, 9, 1 },
> +	[QCOM_RPM_MM_FABRIC_CLK] =		{ 29, 13, 10, 1 },
> +	[QCOM_RPM_DAYTONA_FABRIC_CLK] =		{ 30, 14, 11, 1 },
> +	[QCOM_RPM_SFPB_CLK] =			{ 31, 15, 12, 1 },
> +	[QCOM_RPM_CFPB_CLK] =			{ 32, 16, 13, 1 },
> +	[QCOM_RPM_MMFPB_CLK] =			{ 33, 17, 14, 1 },
> +	[QCOM_RPM_EBI1_CLK] =			{ 34, 18, 16, 1 },
> +	[QCOM_RPM_APPS_FABRIC_HALT] =		{ 35, 19, 18, 1 },
> +	[QCOM_RPM_APPS_FABRIC_MODE] =		{ 37, 20, 19, 1 },
> +	[QCOM_RPM_APPS_FABRIC_IOCTL] =		{ 40, 21, 20, 1 },
> +	[QCOM_RPM_APPS_FABRIC_ARB] =		{ 41, 22, 21, 12 },
> +	[QCOM_RPM_SYS_FABRIC_HALT] =		{ 53, 23, 22, 1 },
> +	[QCOM_RPM_SYS_FABRIC_MODE] =		{ 55, 24, 23, 1 },
> +	[QCOM_RPM_SYS_FABRIC_IOCTL] =		{ 58, 25, 24, 1 },
> +	[QCOM_RPM_SYS_FABRIC_ARB] =		{ 59, 26, 25, 30 },
> +	[QCOM_RPM_MM_FABRIC_HALT] =		{ 89, 27, 26, 1 },
> +	[QCOM_RPM_MM_FABRIC_MODE] =		{ 91, 28, 27, 1 },
> +	[QCOM_RPM_MM_FABRIC_IOCTL] =		{ 94, 29, 28, 1 },
> +	[QCOM_RPM_MM_FABRIC_ARB] =		{ 95, 30, 29, 21 },
> +	[QCOM_RPM_PM8921_SMPS1] =		{ 116, 31, 30, 2 },
> +	[QCOM_RPM_PM8921_SMPS2] =		{ 118, 33, 31, 2 },
> +	[QCOM_RPM_PM8921_SMPS3] =		{ 120, 35, 32, 2 },
> +	[QCOM_RPM_PM8921_SMPS4] =		{ 122, 37, 33, 2 },
> +	[QCOM_RPM_PM8921_SMPS5] =		{ 124, 39, 34, 2 },
> +	[QCOM_RPM_PM8921_SMPS6] =		{ 126, 41, 35, 2 },
> +	[QCOM_RPM_PM8921_SMPS7] =		{ 128, 43, 36, 2 },
> +	[QCOM_RPM_PM8921_SMPS8] =		{ 130, 45, 37, 2 },
> +	[QCOM_RPM_PM8921_LDO1] =		{ 132, 47, 38, 2 },
> +	[QCOM_RPM_PM8921_LDO2] =		{ 134, 49, 39, 2 },
> +	[QCOM_RPM_PM8921_LDO3] =		{ 136, 51, 40, 2 },
> +	[QCOM_RPM_PM8921_LDO4] =		{ 138, 53, 41, 2 },
> +	[QCOM_RPM_PM8921_LDO5] =		{ 140, 55, 42, 2 },
> +	[QCOM_RPM_PM8921_LDO6] =		{ 142, 57, 43, 2 },
> +	[QCOM_RPM_PM8921_LDO7] =		{ 144, 59, 44, 2 },
> +	[QCOM_RPM_PM8921_LDO8] =		{ 146, 61, 45, 2 },
> +	[QCOM_RPM_PM8921_LDO9] =		{ 148, 63, 46, 2 },
> +	[QCOM_RPM_PM8921_LDO10] =		{ 150, 65, 47, 2 },
> +	[QCOM_RPM_PM8921_LDO11] =		{ 152, 67, 48, 2 },
> +	[QCOM_RPM_PM8921_LDO12] =		{ 154, 69, 49, 2 },
> +	[QCOM_RPM_PM8921_LDO13] =		{ 156, 71, 50, 2 },
> +	[QCOM_RPM_PM8921_LDO14] =		{ 158, 73, 51, 2 },
> +	[QCOM_RPM_PM8921_LDO15] =		{ 160, 75, 52, 2 },
> +	[QCOM_RPM_PM8921_LDO16] =		{ 162, 77, 53, 2 },
> +	[QCOM_RPM_PM8921_LDO17] =		{ 164, 79, 54, 2 },
> +	[QCOM_RPM_PM8921_LDO18] =		{ 166, 81, 55, 2 },
> +	[QCOM_RPM_PM8921_LDO19] =		{ 168, 83, 56, 2 },
> +	[QCOM_RPM_PM8921_LDO20] =		{ 170, 85, 57, 2 },
> +	[QCOM_RPM_PM8921_LDO21] =		{ 172, 87, 58, 2 },
> +	[QCOM_RPM_PM8921_LDO22] =		{ 174, 89, 59, 2 },
> +	[QCOM_RPM_PM8921_LDO23] =		{ 176, 91, 60, 2 },
> +	[QCOM_RPM_PM8921_LDO24] =		{ 178, 93, 61, 2 },
> +	[QCOM_RPM_PM8921_LDO25] =		{ 180, 95, 62, 2 },
> +	[QCOM_RPM_PM8921_LDO26] =		{ 182, 97, 63, 2 },
> +	[QCOM_RPM_PM8921_LDO27] =		{ 184, 99, 64, 2 },
> +	[QCOM_RPM_PM8921_LDO28] =		{ 186, 101, 65, 2 },
> +	[QCOM_RPM_PM8921_LDO29] =		{ 188, 103, 66, 2 },
> +	[QCOM_RPM_PM8921_CLK1] =		{ 190, 105, 67, 2 },
> +	[QCOM_RPM_PM8921_CLK2] =		{ 192, 107, 68, 2 },
> +	[QCOM_RPM_PM8921_LVS1] =		{ 194, 109, 69, 1 },
> +	[QCOM_RPM_PM8921_LVS2] =		{ 195, 110, 70, 1 },
> +	[QCOM_RPM_PM8921_LVS3] =		{ 196, 111, 71, 1 },
> +	[QCOM_RPM_PM8921_LVS4] =		{ 197, 112, 72, 1 },
> +	[QCOM_RPM_PM8921_LVS5] =		{ 198, 113, 73, 1 },
> +	[QCOM_RPM_PM8921_LVS6] =		{ 199, 114, 74, 1 },
> +	[QCOM_RPM_PM8921_LVS7] =		{ 200, 115, 75, 1 },
> +	[QCOM_RPM_PM8821_SMPS1] =		{ 201, 116, 76, 2 },
> +	[QCOM_RPM_PM8821_SMPS2] =		{ 203, 118, 77, 2 },
> +	[QCOM_RPM_PM8821_LDO1] =		{ 205, 120, 78, 2 },
> +	[QCOM_RPM_PM8921_NCP] =			{ 207, 122, 80, 2 },
> +	[QCOM_RPM_CXO_BUFFERS] =		{ 209, 124, 81, 1 },
> +	[QCOM_RPM_USB_OTG_SWITCH] =		{ 210, 125, 82, 1 },
> +	[QCOM_RPM_HDMI_SWITCH] =		{ 211, 126, 83, 1 },
> +	[QCOM_RPM_DDR_DMM] =			{ 212, 127, 84, 2 },
> +	[QCOM_RPM_VDDMIN_GPIO] =		{ 215, 131, 89, 1 },
> +};
> +
> +static const struct qcom_rpm_data apq8064_template = {
> +	.version = 3,
> +	.resource_table = apq8064_rpm_resource_table,
> +	.n_resources = ARRAY_SIZE(apq8064_rpm_resource_table),
> +};
> +
> +static const struct qcom_rpm_resource msm8660_rpm_resource_table[] = {
> +	[QCOM_RPM_CXO_CLK] =			{ 32, 12, 5, 1 },
> +	[QCOM_RPM_PXO_CLK] =			{ 33, 13, 6, 1 },
> +	[QCOM_RPM_PLL_4] =			{ 34, 14, 7, 1 },
> +	[QCOM_RPM_APPS_FABRIC_CLK] =		{ 35, 15, 8, 1 },
> +	[QCOM_RPM_SYS_FABRIC_CLK] =		{ 36, 16, 9, 1 },
> +	[QCOM_RPM_MM_FABRIC_CLK] =		{ 37, 17, 10, 1 },
> +	[QCOM_RPM_DAYTONA_FABRIC_CLK] =		{ 38, 18, 11, 1 },
> +	[QCOM_RPM_SFPB_CLK] =			{ 39, 19, 12, 1 },
> +	[QCOM_RPM_CFPB_CLK] =			{ 40, 20, 13, 1 },
> +	[QCOM_RPM_MMFPB_CLK] =			{ 41, 21, 14, 1 },
> +	[QCOM_RPM_SMI_CLK] =			{ 42, 22, 15, 1 },
> +	[QCOM_RPM_EBI1_CLK] =			{ 43, 23, 16, 1 },
> +	[QCOM_RPM_APPS_L2_CACHE_CTL] =		{ 44, 24, 17, 1 },
> +	[QCOM_RPM_APPS_FABRIC_HALT] =		{ 45, 25, 18, 2 },
> +	[QCOM_RPM_APPS_FABRIC_MODE] =		{ 47, 26, 19, 3 },
> +	[QCOM_RPM_APPS_FABRIC_ARB] =		{ 51, 28, 21, 6 },
> +	[QCOM_RPM_SYS_FABRIC_HALT] =		{ 63, 29, 22, 2 },
> +	[QCOM_RPM_SYS_FABRIC_MODE] =		{ 65, 30, 23, 3 },
> +	[QCOM_RPM_SYS_FABRIC_ARB] =		{ 69, 32, 25, 22 },
> +	[QCOM_RPM_MM_FABRIC_HALT] =		{ 105, 33, 26, 2 },
> +	[QCOM_RPM_MM_FABRIC_MODE] =		{ 107, 34, 27, 3 },
> +	[QCOM_RPM_MM_FABRIC_ARB] =		{ 111, 36, 29, 23 },
> +	[QCOM_RPM_PM8901_SMPS0] =		{ 134, 37, 30, 2 },
> +	[QCOM_RPM_PM8901_SMPS1] =		{ 136, 39, 31, 2 },
> +	[QCOM_RPM_PM8901_SMPS2] =		{ 138, 41, 32, 2 },
> +	[QCOM_RPM_PM8901_SMPS3] =		{ 140, 43, 33, 2 },
> +	[QCOM_RPM_PM8901_SMPS4] =		{ 142, 45, 34, 2 },
> +	[QCOM_RPM_PM8901_LDO0] =		{ 144, 47, 35, 2 },
> +	[QCOM_RPM_PM8901_LDO1] =		{ 146, 49, 36, 2 },
> +	[QCOM_RPM_PM8901_LDO2] =		{ 148, 51, 37, 2 },
> +	[QCOM_RPM_PM8901_LDO3] =		{ 150, 53, 38, 2 },
> +	[QCOM_RPM_PM8901_LDO4] =		{ 152, 55, 39, 2 },
> +	[QCOM_RPM_PM8901_LDO5] =		{ 154, 57, 40, 2 },
> +	[QCOM_RPM_PM8901_LDO6] =		{ 156, 59, 41, 2 },
> +	[QCOM_RPM_PM8901_LVS0] =		{ 158, 61, 42, 1 },
> +	[QCOM_RPM_PM8901_LVS1] =		{ 159, 62, 43, 1 },
> +	[QCOM_RPM_PM8901_LVS2] =		{ 160, 63, 44, 1 },
> +	[QCOM_RPM_PM8901_LVS3] =		{ 161, 64, 45, 1 },
> +	[QCOM_RPM_PM8901_MVS] =			{ 162, 65, 46, 1 },
> +	[QCOM_RPM_PM8058_SMPS0] =		{ 163, 66, 47, 2 },
> +	[QCOM_RPM_PM8058_SMPS1] =		{ 165, 68, 48, 2 },
> +	[QCOM_RPM_PM8058_SMPS2] =		{ 167, 70, 49, 2 },
> +	[QCOM_RPM_PM8058_SMPS3] =		{ 169, 72, 50, 2 },
> +	[QCOM_RPM_PM8058_SMPS4] =		{ 171, 74, 51, 2 },
> +	[QCOM_RPM_PM8058_LDO0] =		{ 173, 76, 52, 2 },
> +	[QCOM_RPM_PM8058_LDO1] =		{ 175, 78, 53, 2 },
> +	[QCOM_RPM_PM8058_LDO2] =		{ 177, 80, 54, 2 },
> +	[QCOM_RPM_PM8058_LDO3] =		{ 179, 82, 55, 2 },
> +	[QCOM_RPM_PM8058_LDO4] =		{ 181, 84, 56, 2 },
> +	[QCOM_RPM_PM8058_LDO5] =		{ 183, 86, 57, 2 },
> +	[QCOM_RPM_PM8058_LDO6] =		{ 185, 88, 58, 2 },
> +	[QCOM_RPM_PM8058_LDO7] =		{ 187, 90, 59, 2 },
> +	[QCOM_RPM_PM8058_LDO8] =		{ 189, 92, 60, 2 },
> +	[QCOM_RPM_PM8058_LDO9] =		{ 191, 94, 61, 2 },
> +	[QCOM_RPM_PM8058_LDO10] =		{ 193, 96, 62, 2 },
> +	[QCOM_RPM_PM8058_LDO11] =		{ 195, 98, 63, 2 },
> +	[QCOM_RPM_PM8058_LDO12] =		{ 197, 100, 64, 2 },
> +	[QCOM_RPM_PM8058_LDO13] =		{ 199, 102, 65, 2 },
> +	[QCOM_RPM_PM8058_LDO14] =		{ 201, 104, 66, 2 },
> +	[QCOM_RPM_PM8058_LDO15] =		{ 203, 106, 67, 2 },
> +	[QCOM_RPM_PM8058_LDO16] =		{ 205, 108, 68, 2 },
> +	[QCOM_RPM_PM8058_LDO17] =		{ 207, 110, 69, 2 },
> +	[QCOM_RPM_PM8058_LDO18] =		{ 209, 112, 70, 2 },
> +	[QCOM_RPM_PM8058_LDO19] =		{ 211, 114, 71, 2 },
> +	[QCOM_RPM_PM8058_LDO20] =		{ 213, 116, 72, 2 },
> +	[QCOM_RPM_PM8058_LDO21] =		{ 215, 118, 73, 2 },
> +	[QCOM_RPM_PM8058_LDO22] =		{ 217, 120, 74, 2 },
> +	[QCOM_RPM_PM8058_LDO23] =		{ 219, 122, 75, 2 },
> +	[QCOM_RPM_PM8058_LDO24] =		{ 221, 124, 76, 2 },
> +	[QCOM_RPM_PM8058_LDO25] =		{ 223, 126, 77, 2 },
> +	[QCOM_RPM_PM8058_LVS0] =		{ 225, 128, 78, 1 },
> +	[QCOM_RPM_PM8058_LVS1] =		{ 226, 129, 79, 1 },
> +	[QCOM_RPM_PM8058_NCP] =			{ 227, 130, 80, 2 },
> +	[QCOM_RPM_CXO_BUFFERS] =		{ 229, 132, 81, 1 },
> +};
> +
> +static const struct qcom_rpm_data msm8660_template = {
> +	.version = 2,
> +	.resource_table = msm8660_rpm_resource_table,
> +	.n_resources = ARRAY_SIZE(msm8660_rpm_resource_table),
> +};
> +
> +static const struct qcom_rpm_resource msm8960_rpm_resource_table[] = {
> +	[QCOM_RPM_CXO_CLK] =			{ 25, 9, 5, 1 },
> +	[QCOM_RPM_PXO_CLK] =			{ 26, 10, 6, 1 },
> +	[QCOM_RPM_APPS_FABRIC_CLK] =		{ 27, 11, 8, 1 },
> +	[QCOM_RPM_SYS_FABRIC_CLK] =		{ 28, 12, 9, 1 },
> +	[QCOM_RPM_MM_FABRIC_CLK] =		{ 29, 13, 10, 1 },
> +	[QCOM_RPM_DAYTONA_FABRIC_CLK] =		{ 30, 14, 11, 1 },
> +	[QCOM_RPM_SFPB_CLK] =			{ 31, 15, 12, 1 },
> +	[QCOM_RPM_CFPB_CLK] =			{ 32, 16, 13, 1 },
> +	[QCOM_RPM_MMFPB_CLK] =			{ 33, 17, 14, 1 },
> +	[QCOM_RPM_EBI1_CLK] =			{ 34, 18, 16, 1 },
> +	[QCOM_RPM_APPS_FABRIC_HALT] =		{ 35, 19, 18, 1 },
> +	[QCOM_RPM_APPS_FABRIC_MODE] =		{ 37, 20, 19, 1 },
> +	[QCOM_RPM_APPS_FABRIC_IOCTL] =		{ 40, 21, 20, 1 },
> +	[QCOM_RPM_APPS_FABRIC_ARB] =		{ 41, 22, 21, 12 },
> +	[QCOM_RPM_SYS_FABRIC_HALT] =		{ 53, 23, 22, 1 },
> +	[QCOM_RPM_SYS_FABRIC_MODE] =		{ 55, 24, 23, 1 },
> +	[QCOM_RPM_SYS_FABRIC_IOCTL] =		{ 58, 25, 24, 1 },
> +	[QCOM_RPM_SYS_FABRIC_ARB] =		{ 59, 26, 25, 29 },
> +	[QCOM_RPM_MM_FABRIC_HALT] =		{ 88, 27, 26, 1 },
> +	[QCOM_RPM_MM_FABRIC_MODE] =		{ 90, 28, 27, 1 },
> +	[QCOM_RPM_MM_FABRIC_IOCTL] =		{ 93, 29, 28, 1 },
> +	[QCOM_RPM_MM_FABRIC_ARB] =		{ 94, 30, 29, 23 },
> +	[QCOM_RPM_PM8921_SMPS1] =		{ 117, 31, 30, 2 },
> +	[QCOM_RPM_PM8921_SMPS2] =		{ 119, 33, 31, 2 },
> +	[QCOM_RPM_PM8921_SMPS3] =		{ 121, 35, 32, 2 },
> +	[QCOM_RPM_PM8921_SMPS4] =		{ 123, 37, 33, 2 },
> +	[QCOM_RPM_PM8921_SMPS5] =		{ 125, 39, 34, 2 },
> +	[QCOM_RPM_PM8921_SMPS6] =		{ 127, 41, 35, 2 },
> +	[QCOM_RPM_PM8921_SMPS7] =		{ 129, 43, 36, 2 },
> +	[QCOM_RPM_PM8921_SMPS8] =		{ 131, 45, 37, 2 },
> +	[QCOM_RPM_PM8921_LDO1] =		{ 133, 47, 38, 2 },
> +	[QCOM_RPM_PM8921_LDO2] =		{ 135, 49, 39, 2 },
> +	[QCOM_RPM_PM8921_LDO3] =		{ 137, 51, 40, 2 },
> +	[QCOM_RPM_PM8921_LDO4] =		{ 139, 53, 41, 2 },
> +	[QCOM_RPM_PM8921_LDO5] =		{ 141, 55, 42, 2 },
> +	[QCOM_RPM_PM8921_LDO6] =		{ 143, 57, 43, 2 },
> +	[QCOM_RPM_PM8921_LDO7] =		{ 145, 59, 44, 2 },
> +	[QCOM_RPM_PM8921_LDO8] =		{ 147, 61, 45, 2 },
> +	[QCOM_RPM_PM8921_LDO9] =		{ 149, 63, 46, 2 },
> +	[QCOM_RPM_PM8921_LDO10] =		{ 151, 65, 47, 2 },
> +	[QCOM_RPM_PM8921_LDO11] =		{ 153, 67, 48, 2 },
> +	[QCOM_RPM_PM8921_LDO12] =		{ 155, 69, 49, 2 },
> +	[QCOM_RPM_PM8921_LDO13] =		{ 157, 71, 50, 2 },
> +	[QCOM_RPM_PM8921_LDO14] =		{ 159, 73, 51, 2 },
> +	[QCOM_RPM_PM8921_LDO15] =		{ 161, 75, 52, 2 },
> +	[QCOM_RPM_PM8921_LDO16] =		{ 163, 77, 53, 2 },
> +	[QCOM_RPM_PM8921_LDO17] =		{ 165, 79, 54, 2 },
> +	[QCOM_RPM_PM8921_LDO18] =		{ 167, 81, 55, 2 },
> +	[QCOM_RPM_PM8921_LDO19] =		{ 169, 83, 56, 2 },
> +	[QCOM_RPM_PM8921_LDO20] =		{ 171, 85, 57, 2 },
> +	[QCOM_RPM_PM8921_LDO21] =		{ 173, 87, 58, 2 },
> +	[QCOM_RPM_PM8921_LDO22] =		{ 175, 89, 59, 2 },
> +	[QCOM_RPM_PM8921_LDO23] =		{ 177, 91, 60, 2 },
> +	[QCOM_RPM_PM8921_LDO24] =		{ 179, 93, 61, 2 },
> +	[QCOM_RPM_PM8921_LDO25] =		{ 181, 95, 62, 2 },
> +	[QCOM_RPM_PM8921_LDO26] =		{ 183, 97, 63, 2 },
> +	[QCOM_RPM_PM8921_LDO27] =		{ 185, 99, 64, 2 },
> +	[QCOM_RPM_PM8921_LDO28] =		{ 187, 101, 65, 2 },
> +	[QCOM_RPM_PM8921_LDO29] =		{ 189, 103, 66, 2 },
> +	[QCOM_RPM_PM8921_CLK1] =		{ 191, 105, 67, 2 },
> +	[QCOM_RPM_PM8921_CLK2] =		{ 193, 107, 68, 2 },
> +	[QCOM_RPM_PM8921_LVS1] =		{ 195, 109, 69, 1 },
> +	[QCOM_RPM_PM8921_LVS2] =		{ 196, 110, 70, 1 },
> +	[QCOM_RPM_PM8921_LVS3] =		{ 197, 111, 71, 1 },
> +	[QCOM_RPM_PM8921_LVS4] =		{ 198, 112, 72, 1 },
> +	[QCOM_RPM_PM8921_LVS5] =		{ 199, 113, 73, 1 },
> +	[QCOM_RPM_PM8921_LVS6] =		{ 200, 114, 74, 1 },
> +	[QCOM_RPM_PM8921_LVS7] =		{ 201, 115, 75, 1 },
> +	[QCOM_RPM_PM8921_NCP] =			{ 202, 116, 80, 2 },
> +	[QCOM_RPM_CXO_BUFFERS] =		{ 204, 118, 81, 1 },
> +	[QCOM_RPM_USB_OTG_SWITCH] =		{ 205, 119, 82, 1 },
> +	[QCOM_RPM_HDMI_SWITCH] =		{ 206, 120, 83, 1 },
> +	[QCOM_RPM_DDR_DMM] =			{ 207, 121, 84, 2 },
> +};
> +
> +static const struct qcom_rpm_data msm8960_template = {
> +	.version = 3,
> +	.resource_table = msm8960_rpm_resource_table,
> +	.n_resources = ARRAY_SIZE(msm8960_rpm_resource_table),
> +};
> +
> +static const struct of_device_id qcom_rpm_of_match[] = {
> +	{ .compatible = "qcom,rpm-apq8064", .data = &apq8064_template },
> +	{ .compatible = "qcom,rpm-msm8660", .data = &msm8660_template },
> +	{ .compatible = "qcom,rpm-msm8960", .data = &msm8960_template },
> +	{ }
> +};
> +MODULE_DEVICE_TABLE(of, qcom_rpm_of_match);
> +
> +int qcom_rpm_write(struct qcom_rpm *rpm,
> +		   int state,
> +		   int resource,
> +		   u32 *buf, size_t count)
> +{
> +	const struct qcom_rpm_resource *res;
> +	const struct qcom_rpm_data *data = rpm->data;
> +	u32 sel_mask[RPM_SELECT_SIZE] = { 0 };
> +	int left;
> +	int ret = 0;
> +	int i;
> +
> +	if (WARN_ON(resource < 0 || resource >= data->n_resources))
> +		return -EINVAL;
> +
> +	res = &data->resource_table[resource];
> +	if (WARN_ON(res->size != count))
> +		return -EINVAL;
> +
> +	mutex_lock(&rpm->lock);
> +
> +	for (i = 0; i < res->size; i++)
> +		writel_relaxed(buf[i], RPM_REQ_REG(rpm, res->target_id + i));
> +
> +	bitmap_set((unsigned long *)sel_mask, res->select_id, 1);
> +	for (i = 0; i < ARRAY_SIZE(sel_mask); i++) {
> +		writel_relaxed(sel_mask[i],
> +			       RPM_CTRL_REG(rpm, RPM_REQ_SELECT + i));
> +	}
> +
> +	writel_relaxed(BIT(state), RPM_CTRL_REG(rpm, RPM_REQUEST_CONTEXT));
> +
> +	reinit_completion(&rpm->ack);
> +	regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit));
> +
> +	left = wait_for_completion_timeout(&rpm->ack, RPM_REQUEST_TIMEOUT);
> +	if (!left)
> +		ret = -ETIMEDOUT;
> +	else if (rpm->ack_status & RPM_REJECTED)
> +		ret = -EIO;
> +
> +	mutex_unlock(&rpm->lock);
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL(qcom_rpm_write);
> +
> +static irqreturn_t qcom_rpm_ack_interrupt(int irq, void *dev)
> +{
> +	struct qcom_rpm *rpm = dev;
> +	u32 ack;
> +	int i;
> +
> +	ack = readl_relaxed(RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT));
> +	for (i = 0; i < RPM_SELECT_SIZE; i++)
> +		writel_relaxed(0, RPM_CTRL_REG(rpm, RPM_ACK_SELECTOR + i));
> +	writel(0, RPM_CTRL_REG(rpm, RPM_ACK_CONTEXT));
> +
> +	if (ack & RPM_NOTIFICATION) {
> +		dev_warn(rpm->dev, "ignoring notification!\n");
> +	} else {
> +		rpm->ack_status = ack;
> +		complete(&rpm->ack);
> +	}
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t qcom_rpm_err_interrupt(int irq, void *dev)
> +{
> +	struct qcom_rpm *rpm = dev;
> +
> +	regmap_write(rpm->ipc_regmap, rpm->ipc_offset, BIT(rpm->ipc_bit));
> +	dev_err(rpm->dev, "RPM triggered fatal error\n");
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t qcom_rpm_wakeup_interrupt(int irq, void *dev)
> +{
> +	return IRQ_HANDLED;
> +}
> +
> +static int qcom_rpm_probe(struct platform_device *pdev)
> +{
> +	const struct of_device_id *match;
> +	struct device_node *syscon_np;
> +	struct resource *res;
> +	struct qcom_rpm *rpm;
> +	u32 fw_version[3];
> +	int irq_wakeup;
> +	int irq_ack;
> +	int irq_err;
> +	int ret;
> +
> +	rpm = devm_kzalloc(&pdev->dev, sizeof(*rpm), GFP_KERNEL);
> +	if (!rpm)
> +		return -ENOMEM;
> +
> +	rpm->dev = &pdev->dev;
> +	mutex_init(&rpm->lock);
> +	init_completion(&rpm->ack);
> +
> +	irq_ack = platform_get_irq_byname(pdev, "ack");
> +	if (irq_ack < 0) {
> +		dev_err(&pdev->dev, "required ack interrupt missing\n");
> +		return irq_ack;
> +	}
> +
> +	irq_err = platform_get_irq_byname(pdev, "err");
> +	if (irq_err < 0) {
> +		dev_err(&pdev->dev, "required err interrupt missing\n");
> +		return irq_err;
> +	}
> +
> +	irq_wakeup = platform_get_irq_byname(pdev, "wakeup");
> +	if (irq_wakeup < 0) {
> +		dev_err(&pdev->dev, "required wakeup interrupt missing\n");
> +		return irq_wakeup;
> +	}
> +
> +	match = of_match_device(qcom_rpm_of_match, &pdev->dev);
> +	rpm->data = match->data;
> +
> +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	rpm->status_regs = devm_ioremap_resource(&pdev->dev, res);
> +	if (IS_ERR(rpm->status_regs))
> +		return PTR_ERR(rpm->status_regs);
> +	rpm->ctrl_regs = rpm->status_regs + 0x400;
> +	rpm->req_regs = rpm->status_regs + 0x600;
> +
> +	syscon_np = of_parse_phandle(pdev->dev.of_node, "qcom,ipc", 0);
> +	if (!syscon_np) {
> +		dev_err(&pdev->dev, "no qcom,ipc node\n");
> +		return -ENODEV;
> +	}
> +
> +	rpm->ipc_regmap = syscon_node_to_regmap(syscon_np);
> +	if (IS_ERR(rpm->ipc_regmap))
> +		return PTR_ERR(rpm->ipc_regmap);
> +
> +	ret = of_property_read_u32_index(pdev->dev.of_node, "qcom,ipc", 1,
> +					 &rpm->ipc_offset);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "no offset in qcom,ipc\n");
> +		return -EINVAL;
> +	}
> +
> +	ret = of_property_read_u32_index(pdev->dev.of_node, "qcom,ipc", 2,
> +					 &rpm->ipc_bit);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "no bit in qcom,ipc\n");
> +		return -EINVAL;
> +	}
> +
> +	dev_set_drvdata(&pdev->dev, rpm);
> +
> +	fw_version[0] = readl(RPM_STATUS_REG(rpm, 0));
> +	fw_version[1] = readl(RPM_STATUS_REG(rpm, 1));
> +	fw_version[2] = readl(RPM_STATUS_REG(rpm, 2));
> +	if (fw_version[0] != rpm->data->version) {
> +		dev_err(&pdev->dev,
> +			"RPM version %u.%u.%u incompatible with driver version %u",
> +			fw_version[0],
> +			fw_version[1],
> +			fw_version[2],
> +			rpm->data->version);
> +		return -EFAULT;
> +	}
> +
> +	dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0],
> +							fw_version[1],
> +							fw_version[2]);
> +
> +	ret = devm_request_irq(&pdev->dev,
> +			       irq_ack,
> +			       qcom_rpm_ack_interrupt,
> +			       IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
> +			       "qcom_rpm_ack",
> +			       rpm);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to request ack interrupt\n");
> +		return ret;
> +	}
> +
> +	ret = irq_set_irq_wake(irq_ack, 1);
> +	if (ret)
> +		dev_warn(&pdev->dev, "failed to mark ack irq as wakeup\n");
> +
> +	ret = devm_request_irq(&pdev->dev,
> +			       irq_err,
> +			       qcom_rpm_err_interrupt,
> +			       IRQF_TRIGGER_RISING,
> +			       "qcom_rpm_err",
> +			       rpm);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to request err interrupt\n");
> +		return ret;
> +	}
> +
> +	ret = devm_request_irq(&pdev->dev,
> +			       irq_wakeup,
> +			       qcom_rpm_wakeup_interrupt,
> +			       IRQF_TRIGGER_RISING,
> +			       "qcom_rpm_wakeup",
> +			       rpm);
> +	if (ret) {
> +		dev_err(&pdev->dev, "failed to request wakeup interrupt\n");
> +		return ret;
> +	}
> +
> +	ret = irq_set_irq_wake(irq_wakeup, 1);
> +	if (ret)
> +		dev_warn(&pdev->dev, "failed to mark wakeup irq as wakeup\n");
> +
> +	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
> +}
> +
> +static int qcom_rpm_remove(struct platform_device *pdev)
> +{
> +	of_platform_depopulate(&pdev->dev);
> +	return 0;
> +}
> +
> +static struct platform_driver qcom_rpm_driver = {
> +	.probe = qcom_rpm_probe,
> +	.remove = qcom_rpm_remove,
> +	.driver  = {
> +		.name  = "qcom_rpm",
> +		.of_match_table = qcom_rpm_of_match,
> +	},
> +};
> +
> +static int __init qcom_rpm_init(void)
> +{
> +	return platform_driver_register(&qcom_rpm_driver);
> +}
> +arch_initcall(qcom_rpm_init);
> +
> +static void __exit qcom_rpm_exit(void)
> +{
> +	platform_driver_unregister(&qcom_rpm_driver);
> +}
> +module_exit(qcom_rpm_exit)
> +
> +MODULE_DESCRIPTION("Qualcomm Resource Power Manager driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
> diff --git a/include/linux/mfd/qcom_rpm.h b/include/linux/mfd/qcom_rpm.h
> new file mode 100644
> index 0000000..742ebf1
> --- /dev/null
> +++ b/include/linux/mfd/qcom_rpm.h
> @@ -0,0 +1,13 @@
> +#ifndef __QCOM_RPM_H__
> +#define __QCOM_RPM_H__
> +
> +#include <linux/types.h>
> +
> +struct qcom_rpm;
> +
> +#define QCOM_RPM_ACTIVE_STATE	0
> +#define QCOM_RPM_SLEEP_STATE	1
> +
> +int qcom_rpm_write(struct qcom_rpm *rpm, int state, int resource, u32 *buf, size_t count);
> +
> +#endif

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM
  2014-11-26 21:51 ` [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM Bjorn Andersson
  2014-11-27 11:07   ` Mark Brown
  2015-01-20 14:19   ` Lee Jones
@ 2015-01-20 17:02   ` Lee Jones
  2 siblings, 0 replies; 13+ messages in thread
From: Lee Jones @ 2015-01-20 17:02 UTC (permalink / raw)
  To: Bjorn Andersson
  Cc: Rob Herring, Mark Brown, Josh Cartwright, devicetree,
	linux-kernel, linux-arm-kernel, linux-arm-msm

On Wed, 26 Nov 2014, Bjorn Andersson wrote:

> This adds the missing state parameter to the call down to the RPM. This
> is currently hard coded to the active state, as that's all we're
> supporting at this moment.
> 
> Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
> ---
>  drivers/regulator/qcom_rpm-regulator.c | 1 +
>  1 file changed, 1 insertion(+)

Applied with Mark's Ack, thanks.

> diff --git a/drivers/regulator/qcom_rpm-regulator.c b/drivers/regulator/qcom_rpm-regulator.c
> index b55cd5b..8f66040 100644
> --- a/drivers/regulator/qcom_rpm-regulator.c
> +++ b/drivers/regulator/qcom_rpm-regulator.c
> @@ -198,6 +198,7 @@ static int rpm_reg_write(struct qcom_rpm_reg *vreg,
>  	vreg->val[req->word] |= value << req->shift;
>  
>  	return qcom_rpm_write(vreg->rpm,
> +			      QCOM_RPM_ACTIVE_STATE,
>  			      vreg->resource,
>  			      vreg->val,
>  			      vreg->parts->request_len);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-01-20 17:03 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-26 21:50 [PATCH v8 0/3] Qualcomm Resource Power Manager Bjorn Andersson
2014-11-26 21:50 ` [PATCH v8 1/3] mfd: devicetree: bindings: Add Qualcomm RPM DT binding Bjorn Andersson
2015-01-20 17:01   ` Lee Jones
2014-11-26 21:51 ` [PATCH v8 2/3] mfd: qcom-rpm: Driver for the Qualcomm RPM Bjorn Andersson
2014-12-22 10:50   ` Paul Bolle
2014-12-26 20:11     ` Bjorn Andersson
2015-01-20 17:02   ` Lee Jones
2014-11-26 21:51 ` [PATCH v8 3/3] regulator: qcom-rpm: Add missing state flag in call to RPM Bjorn Andersson
2014-11-27 11:07   ` Mark Brown
2015-01-20 14:19   ` Lee Jones
2015-01-20 16:14     ` Mark Brown
2015-01-20 17:02   ` Lee Jones
2014-12-02 14:25 ` [PATCH v8 0/3] Qualcomm Resource Power Manager Srinivas Kandagatla

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).