linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC WIP 0/2] Qualcomm family A RPM driver and example client
@ 2014-04-22 18:20 Bjorn Andersson
  2014-04-22 18:20 ` [RFC WIP 1/2] mfd: msm_rpm: Initial driver for the Qualcomm RPM Bjorn Andersson
  2014-04-22 18:20 ` [RFC WIP 2/2] regulator: msm_rpm: Initial regulator driver for " Bjorn Andersson
  0 siblings, 2 replies; 3+ messages in thread
From: Bjorn Andersson @ 2014-04-22 18:20 UTC (permalink / raw)
  To: joshc, linux-arm-msm

To be used for reference in the design discussion related to RPM driver
implementation for family A.

Regulator driver is a not even close to the shape it should be, but shows a
user of the api. Instead of having every regulator exposed as it's own
compatible, I would now have it take a resource id as reg and just be
compatible with the specific resource consumer.

The difference with Josh's proposal is the mapping table in msm_rpm.c, that
makes the rpm driver expose logical resources and therefor hides the details of
the rpm communication from its clients. This gives, in my mind, a cleaner
abstraction and api.

Bjorn Andersson (2):
  mfd: msm_rpm: Initial driver for the Qualcomm RPM
  regulator: msm_rpm: Initial regulator driver for Qualcomm RPM

 drivers/mfd/Kconfig                   |   7 +
 drivers/mfd/Makefile                  |   1 +
 drivers/mfd/msm_rpm-8064.h            | 420 +++++++++++++++++++++++++++
 drivers/mfd/msm_rpm-8960.h            | 400 ++++++++++++++++++++++++++
 drivers/mfd/msm_rpm.c                 | 525 ++++++++++++++++++++++++++++++++++
 drivers/regulator/Kconfig             |   7 +
 drivers/regulator/Makefile            |   1 +
 drivers/regulator/msm_rpm-regulator.c | 467 ++++++++++++++++++++++++++++++
 include/linux/mfd/msm_rpm.h           |  87 ++++++
 9 files changed, 1915 insertions(+)
 create mode 100644 drivers/mfd/msm_rpm-8064.h
 create mode 100644 drivers/mfd/msm_rpm-8960.h
 create mode 100644 drivers/mfd/msm_rpm.c
 create mode 100644 drivers/regulator/msm_rpm-regulator.c
 create mode 100644 include/linux/mfd/msm_rpm.h

-- 
1.8.2.2

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

* [RFC WIP 1/2] mfd: msm_rpm: Initial driver for the Qualcomm RPM
  2014-04-22 18:20 [RFC WIP 0/2] Qualcomm family A RPM driver and example client Bjorn Andersson
@ 2014-04-22 18:20 ` Bjorn Andersson
  2014-04-22 18:20 ` [RFC WIP 2/2] regulator: msm_rpm: Initial regulator driver for " Bjorn Andersson
  1 sibling, 0 replies; 3+ messages in thread
From: Bjorn Andersson @ 2014-04-22 18:20 UTC (permalink / raw)
  To: joshc, linux-arm-msm

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---
 drivers/mfd/Kconfig         |   7 +
 drivers/mfd/Makefile        |   1 +
 drivers/mfd/msm_rpm-8064.h  | 420 +++++++++++++++++++++++++++++++++++
 drivers/mfd/msm_rpm-8960.h  | 400 +++++++++++++++++++++++++++++++++
 drivers/mfd/msm_rpm.c       | 525 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/msm_rpm.h |  87 ++++++++
 6 files changed, 1440 insertions(+)
 create mode 100644 drivers/mfd/msm_rpm-8064.h
 create mode 100644 drivers/mfd/msm_rpm-8960.h
 create mode 100644 drivers/mfd/msm_rpm.c
 create mode 100644 include/linux/mfd/msm_rpm.h

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 49bb445..e8395b1 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -468,6 +468,13 @@ config UCB1400_CORE
 	  To compile this driver as a module, choose M here: the
 	  module will be called ucb1400_core.
 
+config MFD_MSM_RPM
+	tristate "Qualcomm RPM"
+	depends on ARCH_MSM
+	select MFD_CORE
+	help
+	  Select this option to enable the Qualcomm RPM driver.
+
 config MFD_PM8XXX
 	tristate
 
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5aea5ef..b371ec9 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -149,6 +149,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_MSM_RPM)	+= msm_rpm.o
 obj-$(CONFIG_MFD_PM8921_CORE) 	+= pm8921-core.o ssbi.o
 obj-$(CONFIG_MFD_PM8XXX_IRQ) 	+= pm8xxx-irq.o
 obj-$(CONFIG_TPS65911_COMPARATOR)	+= tps65911-comparator.o
diff --git a/drivers/mfd/msm_rpm-8064.h b/drivers/mfd/msm_rpm-8064.h
new file mode 100644
index 0000000..ef762f4
--- /dev/null
+++ b/drivers/mfd/msm_rpm-8064.h
@@ -0,0 +1,420 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_RPM_8064_H
+#define __ARCH_ARM_MACH_MSM_RPM_8064_H
+
+/* RPM resource select enums defined for RPM core
+   NOT IN SEQUENTIAL ORDER */
+enum {
+	MSM_RPM_8064_SEL_NOTIFICATION					= 0,
+	MSM_RPM_8064_SEL_INVALIDATE					= 1,
+	MSM_RPM_8064_SEL_TRIGGER_TIMED					= 2,
+	MSM_RPM_8064_SEL_RPM_CTL					= 3,
+
+	MSM_RPM_8064_SEL_CXO_CLK					= 5,
+	MSM_RPM_8064_SEL_PXO_CLK					= 6,
+	MSM_RPM_8064_SEL_QDSS_CLK					= 7,
+	MSM_RPM_8064_SEL_APPS_FABRIC_CLK				= 8,
+	MSM_RPM_8064_SEL_SYSTEM_FABRIC_CLK				= 9,
+	MSM_RPM_8064_SEL_MM_FABRIC_CLK					= 10,
+	MSM_RPM_8064_SEL_DAYTONA_FABRIC_CLK				= 11,
+	MSM_RPM_8064_SEL_SFPB_CLK					= 12,
+	MSM_RPM_8064_SEL_CFPB_CLK					= 13,
+	MSM_RPM_8064_SEL_MMFPB_CLK					= 14,
+	MSM_RPM_8064_SEL_EBI1_CLK					= 16,
+
+	MSM_RPM_8064_SEL_APPS_FABRIC_CFG_HALT				= 18,
+	MSM_RPM_8064_SEL_APPS_FABRIC_CFG_CLKMOD				= 19,
+	MSM_RPM_8064_SEL_APPS_FABRIC_CFG_IOCTL				= 20,
+	MSM_RPM_8064_SEL_APPS_FABRIC_ARB				= 21,
+
+	MSM_RPM_8064_SEL_SYS_FABRIC_CFG_HALT				= 22,
+	MSM_RPM_8064_SEL_SYS_FABRIC_CFG_CLKMOD				= 23,
+	MSM_RPM_8064_SEL_SYS_FABRIC_CFG_IOCTL				= 24,
+	MSM_RPM_8064_SEL_SYSTEM_FABRIC_ARB				= 25,
+
+	MSM_RPM_8064_SEL_MMSS_FABRIC_CFG_HALT				= 26,
+	MSM_RPM_8064_SEL_MMSS_FABRIC_CFG_CLKMOD				= 27,
+	MSM_RPM_8064_SEL_MMSS_FABRIC_CFG_IOCTL				= 28,
+	MSM_RPM_8064_SEL_MM_FABRIC_ARB					= 29,
+
+	MSM_RPM_8064_SEL_PM8921_S1					= 30,
+	MSM_RPM_8064_SEL_PM8921_S2					= 31,
+	MSM_RPM_8064_SEL_PM8921_S3					= 32,
+	MSM_RPM_8064_SEL_PM8921_S4					= 33,
+	MSM_RPM_8064_SEL_PM8921_S5					= 34,
+	MSM_RPM_8064_SEL_PM8921_S6					= 35,
+	MSM_RPM_8064_SEL_PM8921_S7					= 36,
+	MSM_RPM_8064_SEL_PM8921_S8					= 37,
+	MSM_RPM_8064_SEL_PM8921_L1					= 38,
+	MSM_RPM_8064_SEL_PM8921_L2					= 39,
+	MSM_RPM_8064_SEL_PM8921_L3					= 40,
+	MSM_RPM_8064_SEL_PM8921_L4					= 41,
+	MSM_RPM_8064_SEL_PM8921_L5					= 42,
+	MSM_RPM_8064_SEL_PM8921_L6					= 43,
+	MSM_RPM_8064_SEL_PM8921_L7					= 44,
+	MSM_RPM_8064_SEL_PM8921_L8					= 45,
+	MSM_RPM_8064_SEL_PM8921_L9					= 46,
+	MSM_RPM_8064_SEL_PM8921_L10					= 47,
+	MSM_RPM_8064_SEL_PM8921_L11					= 48,
+	MSM_RPM_8064_SEL_PM8921_L12					= 49,
+	MSM_RPM_8064_SEL_PM8921_L13					= 50,
+	MSM_RPM_8064_SEL_PM8921_L14					= 51,
+	MSM_RPM_8064_SEL_PM8921_L15					= 52,
+	MSM_RPM_8064_SEL_PM8921_L16					= 53,
+	MSM_RPM_8064_SEL_PM8921_L17					= 54,
+	MSM_RPM_8064_SEL_PM8921_L18					= 55,
+	MSM_RPM_8064_SEL_PM8921_L19					= 56,
+	MSM_RPM_8064_SEL_PM8921_L20					= 57,
+	MSM_RPM_8064_SEL_PM8921_L21					= 58,
+	MSM_RPM_8064_SEL_PM8921_L22					= 59,
+	MSM_RPM_8064_SEL_PM8921_L23					= 60,
+	MSM_RPM_8064_SEL_PM8921_L24					= 61,
+	MSM_RPM_8064_SEL_PM8921_L25					= 62,
+	MSM_RPM_8064_SEL_PM8921_L26					= 63,
+	MSM_RPM_8064_SEL_PM8921_L27					= 64,
+	MSM_RPM_8064_SEL_PM8921_L28					= 65,
+	MSM_RPM_8064_SEL_PM8921_L29					= 66,
+	MSM_RPM_8064_SEL_PM8921_CLK1					= 67,
+	MSM_RPM_8064_SEL_PM8921_CLK2					= 68,
+	MSM_RPM_8064_SEL_PM8921_LVS1					= 69,
+	MSM_RPM_8064_SEL_PM8921_LVS2					= 70,
+	MSM_RPM_8064_SEL_PM8921_LVS3					= 71,
+	MSM_RPM_8064_SEL_PM8921_LVS4					= 72,
+	MSM_RPM_8064_SEL_PM8921_LVS5					= 73,
+	MSM_RPM_8064_SEL_PM8921_LVS6					= 74,
+	MSM_RPM_8064_SEL_PM8921_LVS7					= 75,
+	MSM_RPM_8064_SEL_PM8821_S1					= 76,
+	MSM_RPM_8064_SEL_PM8821_S2					= 77,
+	MSM_RPM_8064_SEL_PM8821_L1					= 78,
+
+	MSM_RPM_8064_SEL_NCP						= 80,
+	MSM_RPM_8064_SEL_CXO_BUFFERS					= 81,
+	MSM_RPM_8064_SEL_USB_OTG_SWITCH					= 82,
+	MSM_RPM_8064_SEL_HDMI_SWITCH					= 83,
+	MSM_RPM_8064_SEL_DDR_DMM					= 84,
+
+	MSM_RPM_8064_SEL_VDDMIN_GPIO					= 89,
+
+	MSM_RPM_8064_SEL_LAST = MSM_RPM_8064_SEL_VDDMIN_GPIO,
+};
+
+/* RPM resource (4 byte) word ID enum */
+enum {
+	MSM_RPM_8064_ID_NOTIFICATION_CONFIGURED				= 0,
+	MSM_RPM_8064_ID_NOTIFICATION_CONFIGURED_3 =
+		MSM_RPM_8064_ID_NOTIFICATION_CONFIGURED + 3,
+
+	MSM_RPM_8064_ID_NOTIFICATION_REGISTERED				= 4,
+	MSM_RPM_8064_ID_NOTIFICATION_REGISTERED_3 =
+		MSM_RPM_8064_ID_NOTIFICATION_REGISTERED + 3,
+
+	MSM_RPM_8064_ID_INVALIDATE					= 8,
+	MSM_RPM_8064_ID_INVALIDATE_7 =
+		MSM_RPM_8064_ID_INVALIDATE + 7,
+
+	MSM_RPM_8064_ID_TRIGGER_TIMED_TO				= 16,
+	MSM_RPM_8064_ID_TRIGGER_TIMED_SCLK_COUNT			= 17,
+
+	MSM_RPM_8064_ID_RPM_CTL						= 18,
+
+	/* TRIGGER_CLEAR/SET deprecated in these 24 RESERVED bytes */
+	MSM_RPM_8064_ID_RESERVED					= 19,
+	MSM_RPM_8064_ID_RESERVED_5 =
+		MSM_RPM_8064_ID_RESERVED + 5,
+
+	MSM_RPM_8064_ID_CXO_CLK						= 25,
+	MSM_RPM_8064_ID_PXO_CLK						= 26,
+	MSM_RPM_8064_ID_APPS_FABRIC_CLK					= 27,
+	MSM_RPM_8064_ID_SYSTEM_FABRIC_CLK				= 28,
+	MSM_RPM_8064_ID_MM_FABRIC_CLK					= 29,
+	MSM_RPM_8064_ID_DAYTONA_FABRIC_CLK				= 30,
+	MSM_RPM_8064_ID_SFPB_CLK					= 31,
+	MSM_RPM_8064_ID_CFPB_CLK					= 32,
+	MSM_RPM_8064_ID_MMFPB_CLK					= 33,
+	MSM_RPM_8064_ID_EBI1_CLK					= 34,
+
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_HALT				= 35,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_HALT_1				= 36,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_CLKMOD				= 37,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_CLKMOD_1			= 38,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_CLKMOD_2			= 39,
+	MSM_RPM_8064_ID_APPS_FABRIC_CFG_IOCTL				= 40,
+	MSM_RPM_8064_ID_APPS_FABRIC_ARB					= 41,
+	MSM_RPM_8064_ID_APPS_FABRIC_ARB_11 =
+		MSM_RPM_8064_ID_APPS_FABRIC_ARB + 11,
+
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_HALT				= 53,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_HALT_1				= 54,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_CLKMOD				= 55,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_CLKMOD_1				= 56,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_CLKMOD_2				= 57,
+	MSM_RPM_8064_ID_SYS_FABRIC_CFG_IOCTL				= 58,
+	MSM_RPM_8064_ID_SYSTEM_FABRIC_ARB				= 59,
+	MSM_RPM_8064_ID_SYSTEM_FABRIC_ARB_29 =
+		MSM_RPM_8064_ID_SYSTEM_FABRIC_ARB + 29,
+
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_HALT				= 89,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_HALT_1				= 90,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_CLKMOD				= 91,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_CLKMOD_1			= 92,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_CLKMOD_2			= 93,
+	MSM_RPM_8064_ID_MMSS_FABRIC_CFG_IOCTL				= 94,
+	MSM_RPM_8064_ID_MM_FABRIC_ARB					= 95,
+	MSM_RPM_8064_ID_MM_FABRIC_ARB_20 =
+		MSM_RPM_8064_ID_MM_FABRIC_ARB + 20,
+
+	MSM_RPM_8064_ID_PM8921_S1					= 116,
+	MSM_RPM_8064_ID_PM8921_S1_1					= 117,
+	MSM_RPM_8064_ID_PM8921_S2					= 118,
+	MSM_RPM_8064_ID_PM8921_S2_1					= 119,
+	MSM_RPM_8064_ID_PM8921_S3					= 120,
+	MSM_RPM_8064_ID_PM8921_S3_1					= 121,
+	MSM_RPM_8064_ID_PM8921_S4					= 122,
+	MSM_RPM_8064_ID_PM8921_S4_1					= 123,
+	MSM_RPM_8064_ID_PM8921_S5					= 124,
+	MSM_RPM_8064_ID_PM8921_S5_1					= 125,
+	MSM_RPM_8064_ID_PM8921_S6					= 126,
+	MSM_RPM_8064_ID_PM8921_S6_1					= 127,
+	MSM_RPM_8064_ID_PM8921_S7					= 128,
+	MSM_RPM_8064_ID_PM8921_S7_1					= 129,
+	MSM_RPM_8064_ID_PM8921_S8					= 130,
+	MSM_RPM_8064_ID_PM8921_S8_1					= 131,
+	MSM_RPM_8064_ID_PM8921_L1					= 132,
+	MSM_RPM_8064_ID_PM8921_L1_1					= 133,
+	MSM_RPM_8064_ID_PM8921_L2					= 134,
+	MSM_RPM_8064_ID_PM8921_L2_1					= 135,
+	MSM_RPM_8064_ID_PM8921_L3					= 136,
+	MSM_RPM_8064_ID_PM8921_L3_1					= 137,
+	MSM_RPM_8064_ID_PM8921_L4					= 138,
+	MSM_RPM_8064_ID_PM8921_L4_1					= 139,
+	MSM_RPM_8064_ID_PM8921_L5					= 140,
+	MSM_RPM_8064_ID_PM8921_L5_1					= 141,
+	MSM_RPM_8064_ID_PM8921_L6					= 142,
+	MSM_RPM_8064_ID_PM8921_L6_1					= 143,
+	MSM_RPM_8064_ID_PM8921_L7					= 144,
+	MSM_RPM_8064_ID_PM8921_L7_1					= 145,
+	MSM_RPM_8064_ID_PM8921_L8					= 146,
+	MSM_RPM_8064_ID_PM8921_L8_1					= 147,
+	MSM_RPM_8064_ID_PM8921_L9					= 148,
+	MSM_RPM_8064_ID_PM8921_L9_1					= 149,
+	MSM_RPM_8064_ID_PM8921_L10					= 150,
+	MSM_RPM_8064_ID_PM8921_L10_1					= 151,
+	MSM_RPM_8064_ID_PM8921_L11					= 152,
+	MSM_RPM_8064_ID_PM8921_L11_1					= 153,
+	MSM_RPM_8064_ID_PM8921_L12					= 154,
+	MSM_RPM_8064_ID_PM8921_L12_1					= 155,
+	MSM_RPM_8064_ID_PM8921_L13					= 156,
+	MSM_RPM_8064_ID_PM8921_L13_1					= 157,
+	MSM_RPM_8064_ID_PM8921_L14					= 158,
+	MSM_RPM_8064_ID_PM8921_L14_1					= 159,
+	MSM_RPM_8064_ID_PM8921_L15					= 160,
+	MSM_RPM_8064_ID_PM8921_L15_1					= 161,
+	MSM_RPM_8064_ID_PM8921_L16					= 162,
+	MSM_RPM_8064_ID_PM8921_L16_1					= 163,
+	MSM_RPM_8064_ID_PM8921_L17					= 164,
+	MSM_RPM_8064_ID_PM8921_L17_1					= 165,
+	MSM_RPM_8064_ID_PM8921_L18					= 166,
+	MSM_RPM_8064_ID_PM8921_L18_1					= 167,
+	MSM_RPM_8064_ID_PM8921_L19					= 168,
+	MSM_RPM_8064_ID_PM8921_L19_1					= 169,
+	MSM_RPM_8064_ID_PM8921_L20					= 170,
+	MSM_RPM_8064_ID_PM8921_L20_1					= 171,
+	MSM_RPM_8064_ID_PM8921_L21					= 172,
+	MSM_RPM_8064_ID_PM8921_L21_1					= 173,
+	MSM_RPM_8064_ID_PM8921_L22					= 174,
+	MSM_RPM_8064_ID_PM8921_L22_1					= 175,
+	MSM_RPM_8064_ID_PM8921_L23					= 176,
+	MSM_RPM_8064_ID_PM8921_L23_1					= 177,
+	MSM_RPM_8064_ID_PM8921_L24					= 178,
+	MSM_RPM_8064_ID_PM8921_L24_1					= 179,
+	MSM_RPM_8064_ID_PM8921_L25					= 180,
+	MSM_RPM_8064_ID_PM8921_L25_1					= 181,
+	MSM_RPM_8064_ID_PM8921_L26					= 182,
+	MSM_RPM_8064_ID_PM8921_L26_1					= 183,
+	MSM_RPM_8064_ID_PM8921_L27					= 184,
+	MSM_RPM_8064_ID_PM8921_L27_1					= 185,
+	MSM_RPM_8064_ID_PM8921_L28					= 186,
+	MSM_RPM_8064_ID_PM8921_L28_1					= 187,
+	MSM_RPM_8064_ID_PM8921_L29					= 188,
+	MSM_RPM_8064_ID_PM8921_L29_1					= 189,
+	MSM_RPM_8064_ID_PM8921_CLK1					= 190,
+	MSM_RPM_8064_ID_PM8921_CLK1_1					= 191,
+	MSM_RPM_8064_ID_PM8921_CLK2					= 192,
+	MSM_RPM_8064_ID_PM8921_CLK2_1					= 193,
+	MSM_RPM_8064_ID_PM8921_LVS1					= 194,
+	MSM_RPM_8064_ID_PM8921_LVS2					= 195,
+	MSM_RPM_8064_ID_PM8921_LVS3					= 196,
+	MSM_RPM_8064_ID_PM8921_LVS4					= 197,
+	MSM_RPM_8064_ID_PM8921_LVS5					= 198,
+	MSM_RPM_8064_ID_PM8921_LVS6					= 199,
+	MSM_RPM_8064_ID_PM8921_LVS7					= 200,
+	MSM_RPM_8064_ID_PM8821_S1					= 201,
+	MSM_RPM_8064_ID_PM8821_S1_1					= 202,
+	MSM_RPM_8064_ID_PM8821_S2					= 203,
+	MSM_RPM_8064_ID_PM8821_S2_1					= 204,
+	MSM_RPM_8064_ID_PM8821_L1					= 205,
+	MSM_RPM_8064_ID_PM8821_L1_1					= 206,
+	MSM_RPM_8064_ID_NCP						= 207,
+	MSM_RPM_8064_ID_NCP_1						= 208,
+	MSM_RPM_8064_ID_CXO_BUFFERS					= 209,
+	MSM_RPM_8064_ID_USB_OTG_SWITCH					= 210,
+	MSM_RPM_8064_ID_HDMI_SWITCH					= 211,
+	MSM_RPM_8064_ID_DDR_DMM						= 212,
+	MSM_RPM_8064_ID_DDR_DMM_1					= 213,
+	MSM_RPM_8064_ID_QDSS_CLK					= 214,
+	MSM_RPM_8064_ID_VDDMIN_GPIO					= 215,
+
+	MSM_RPM_8064_ID_LAST = MSM_RPM_8064_ID_VDDMIN_GPIO,
+};
+
+
+/* RPM status ID enum */
+enum {
+	MSM_RPM_8064_STATUS_ID_VERSION_MAJOR				= 0,
+	MSM_RPM_8064_STATUS_ID_VERSION_MINOR				= 1,
+	MSM_RPM_8064_STATUS_ID_VERSION_BUILD				= 2,
+	MSM_RPM_8064_STATUS_ID_SUPPORTED_RESOURCES			= 3,
+	MSM_RPM_8064_STATUS_ID_SUPPORTED_RESOURCES_1			= 4,
+	MSM_RPM_8064_STATUS_ID_SUPPORTED_RESOURCES_2			= 5,
+	MSM_RPM_8064_STATUS_ID_RESERVED_SUPPORTED_RESOURCES		= 6,
+	MSM_RPM_8064_STATUS_ID_SEQUENCE					= 7,
+	MSM_RPM_8064_STATUS_ID_RPM_CTL					= 8,
+	MSM_RPM_8064_STATUS_ID_CXO_CLK					= 9,
+	MSM_RPM_8064_STATUS_ID_PXO_CLK					= 10,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_CLK				= 11,
+	MSM_RPM_8064_STATUS_ID_SYSTEM_FABRIC_CLK			= 12,
+	MSM_RPM_8064_STATUS_ID_MM_FABRIC_CLK				= 13,
+	MSM_RPM_8064_STATUS_ID_DAYTONA_FABRIC_CLK			= 14,
+	MSM_RPM_8064_STATUS_ID_SFPB_CLK					= 15,
+	MSM_RPM_8064_STATUS_ID_CFPB_CLK					= 16,
+	MSM_RPM_8064_STATUS_ID_MMFPB_CLK				= 17,
+	MSM_RPM_8064_STATUS_ID_EBI1_CLK					= 18,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_CFG_HALT			= 19,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_CFG_CLKMOD			= 20,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_CFG_IOCTL			= 21,
+	MSM_RPM_8064_STATUS_ID_APPS_FABRIC_ARB				= 22,
+	MSM_RPM_8064_STATUS_ID_SYS_FABRIC_CFG_HALT			= 23,
+	MSM_RPM_8064_STATUS_ID_SYS_FABRIC_CFG_CLKMOD			= 24,
+	MSM_RPM_8064_STATUS_ID_SYS_FABRIC_CFG_IOCTL			= 25,
+	MSM_RPM_8064_STATUS_ID_SYSTEM_FABRIC_ARB			= 26,
+	MSM_RPM_8064_STATUS_ID_MMSS_FABRIC_CFG_HALT			= 27,
+	MSM_RPM_8064_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD			= 28,
+	MSM_RPM_8064_STATUS_ID_MMSS_FABRIC_CFG_IOCTL			= 29,
+	MSM_RPM_8064_STATUS_ID_MM_FABRIC_ARB				= 30,
+	MSM_RPM_8064_STATUS_ID_PM8921_S1				= 31,
+	MSM_RPM_8064_STATUS_ID_PM8921_S1_1				= 32,
+	MSM_RPM_8064_STATUS_ID_PM8921_S2				= 33,
+	MSM_RPM_8064_STATUS_ID_PM8921_S2_1				= 34,
+	MSM_RPM_8064_STATUS_ID_PM8921_S3				= 35,
+	MSM_RPM_8064_STATUS_ID_PM8921_S3_1				= 36,
+	MSM_RPM_8064_STATUS_ID_PM8921_S4				= 37,
+	MSM_RPM_8064_STATUS_ID_PM8921_S4_1				= 38,
+	MSM_RPM_8064_STATUS_ID_PM8921_S5				= 39,
+	MSM_RPM_8064_STATUS_ID_PM8921_S5_1				= 40,
+	MSM_RPM_8064_STATUS_ID_PM8921_S6				= 41,
+	MSM_RPM_8064_STATUS_ID_PM8921_S6_1				= 42,
+	MSM_RPM_8064_STATUS_ID_PM8921_S7				= 43,
+	MSM_RPM_8064_STATUS_ID_PM8921_S7_1				= 44,
+	MSM_RPM_8064_STATUS_ID_PM8921_S8				= 45,
+	MSM_RPM_8064_STATUS_ID_PM8921_S8_1				= 46,
+	MSM_RPM_8064_STATUS_ID_PM8921_L1				= 47,
+	MSM_RPM_8064_STATUS_ID_PM8921_L1_1				= 48,
+	MSM_RPM_8064_STATUS_ID_PM8921_L2				= 49,
+	MSM_RPM_8064_STATUS_ID_PM8921_L2_1				= 50,
+	MSM_RPM_8064_STATUS_ID_PM8921_L3				= 51,
+	MSM_RPM_8064_STATUS_ID_PM8921_L3_1				= 52,
+	MSM_RPM_8064_STATUS_ID_PM8921_L4				= 53,
+	MSM_RPM_8064_STATUS_ID_PM8921_L4_1				= 54,
+	MSM_RPM_8064_STATUS_ID_PM8921_L5				= 55,
+	MSM_RPM_8064_STATUS_ID_PM8921_L5_1				= 56,
+	MSM_RPM_8064_STATUS_ID_PM8921_L6				= 57,
+	MSM_RPM_8064_STATUS_ID_PM8921_L6_1				= 58,
+	MSM_RPM_8064_STATUS_ID_PM8921_L7				= 59,
+	MSM_RPM_8064_STATUS_ID_PM8921_L7_1				= 60,
+	MSM_RPM_8064_STATUS_ID_PM8921_L8				= 61,
+	MSM_RPM_8064_STATUS_ID_PM8921_L8_1				= 62,
+	MSM_RPM_8064_STATUS_ID_PM8921_L9				= 63,
+	MSM_RPM_8064_STATUS_ID_PM8921_L9_1				= 64,
+	MSM_RPM_8064_STATUS_ID_PM8921_L10				= 65,
+	MSM_RPM_8064_STATUS_ID_PM8921_L10_1				= 66,
+	MSM_RPM_8064_STATUS_ID_PM8921_L11				= 67,
+	MSM_RPM_8064_STATUS_ID_PM8921_L11_1				= 68,
+	MSM_RPM_8064_STATUS_ID_PM8921_L12				= 69,
+	MSM_RPM_8064_STATUS_ID_PM8921_L12_1				= 70,
+	MSM_RPM_8064_STATUS_ID_PM8921_L13				= 71,
+	MSM_RPM_8064_STATUS_ID_PM8921_L13_1				= 72,
+	MSM_RPM_8064_STATUS_ID_PM8921_L14				= 73,
+	MSM_RPM_8064_STATUS_ID_PM8921_L14_1				= 74,
+	MSM_RPM_8064_STATUS_ID_PM8921_L15				= 75,
+	MSM_RPM_8064_STATUS_ID_PM8921_L15_1				= 76,
+	MSM_RPM_8064_STATUS_ID_PM8921_L16				= 77,
+	MSM_RPM_8064_STATUS_ID_PM8921_L16_1				= 78,
+	MSM_RPM_8064_STATUS_ID_PM8921_L17				= 79,
+	MSM_RPM_8064_STATUS_ID_PM8921_L17_1				= 80,
+	MSM_RPM_8064_STATUS_ID_PM8921_L18				= 81,
+	MSM_RPM_8064_STATUS_ID_PM8921_L18_1				= 82,
+	MSM_RPM_8064_STATUS_ID_PM8921_L19				= 83,
+	MSM_RPM_8064_STATUS_ID_PM8921_L19_1				= 84,
+	MSM_RPM_8064_STATUS_ID_PM8921_L20				= 85,
+	MSM_RPM_8064_STATUS_ID_PM8921_L20_1				= 86,
+	MSM_RPM_8064_STATUS_ID_PM8921_L21				= 87,
+	MSM_RPM_8064_STATUS_ID_PM8921_L21_1				= 88,
+	MSM_RPM_8064_STATUS_ID_PM8921_L22				= 89,
+	MSM_RPM_8064_STATUS_ID_PM8921_L22_1				= 90,
+	MSM_RPM_8064_STATUS_ID_PM8921_L23				= 91,
+	MSM_RPM_8064_STATUS_ID_PM8921_L23_1				= 92,
+	MSM_RPM_8064_STATUS_ID_PM8921_L24				= 93,
+	MSM_RPM_8064_STATUS_ID_PM8921_L24_1				= 94,
+	MSM_RPM_8064_STATUS_ID_PM8921_L25				= 95,
+	MSM_RPM_8064_STATUS_ID_PM8921_L25_1				= 96,
+	MSM_RPM_8064_STATUS_ID_PM8921_L26				= 97,
+	MSM_RPM_8064_STATUS_ID_PM8921_L26_1				= 98,
+	MSM_RPM_8064_STATUS_ID_PM8921_L27				= 99,
+	MSM_RPM_8064_STATUS_ID_PM8921_L27_1				= 100,
+	MSM_RPM_8064_STATUS_ID_PM8921_L28				= 101,
+	MSM_RPM_8064_STATUS_ID_PM8921_L28_1				= 102,
+	MSM_RPM_8064_STATUS_ID_PM8921_L29				= 103,
+	MSM_RPM_8064_STATUS_ID_PM8921_L29_1				= 104,
+	MSM_RPM_8064_STATUS_ID_PM8921_CLK1				= 105,
+	MSM_RPM_8064_STATUS_ID_PM8921_CLK1_1				= 106,
+	MSM_RPM_8064_STATUS_ID_PM8921_CLK2				= 107,
+	MSM_RPM_8064_STATUS_ID_PM8921_CLK2_1				= 108,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS1				= 109,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS2				= 110,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS3				= 111,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS4				= 112,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS5				= 113,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS6				= 114,
+	MSM_RPM_8064_STATUS_ID_PM8921_LVS7				= 115,
+	MSM_RPM_8064_STATUS_ID_PM8821_S1				= 116,
+	MSM_RPM_8064_STATUS_ID_PM8821_S1_1				= 117,
+	MSM_RPM_8064_STATUS_ID_PM8821_S2				= 118,
+	MSM_RPM_8064_STATUS_ID_PM8821_S2_1				= 119,
+	MSM_RPM_8064_STATUS_ID_PM8821_L1				= 120,
+	MSM_RPM_8064_STATUS_ID_PM8821_L1_1				= 121,
+	MSM_RPM_8064_STATUS_ID_NCP					= 122,
+	MSM_RPM_8064_STATUS_ID_NCP_1					= 123,
+	MSM_RPM_8064_STATUS_ID_CXO_BUFFERS				= 124,
+	MSM_RPM_8064_STATUS_ID_USB_OTG_SWITCH				= 125,
+	MSM_RPM_8064_STATUS_ID_HDMI_SWITCH				= 126,
+	MSM_RPM_8064_STATUS_ID_DDR_DMM					= 127,
+	MSM_RPM_8064_STATUS_ID_DDR_DMM_1				= 128,
+	MSM_RPM_8064_STATUS_ID_EBI1_CH0_RANGE				= 129,
+	MSM_RPM_8064_STATUS_ID_EBI1_CH1_RANGE				= 130,
+	MSM_RPM_8064_STATUS_ID_VDDMIN_GPIO				= 131,
+
+	MSM_RPM_8064_STATUS_ID_LAST = MSM_RPM_8064_STATUS_ID_VDDMIN_GPIO,
+};
+
+#endif /* __ARCH_ARM_MACH_MSM_RPM_8064_H */
diff --git a/drivers/mfd/msm_rpm-8960.h b/drivers/mfd/msm_rpm-8960.h
new file mode 100644
index 0000000..6513037
--- /dev/null
+++ b/drivers/mfd/msm_rpm-8960.h
@@ -0,0 +1,400 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_RPM_8960_H
+#define __ARCH_ARM_MACH_MSM_RPM_8960_H
+
+/* RPM resource select enums defined for RPM core
+   NOT IN SEQUENTIAL ORDER */
+enum {
+	MSM_RPM_8960_SEL_NOTIFICATION					= 0,
+	MSM_RPM_8960_SEL_INVALIDATE					= 1,
+	MSM_RPM_8960_SEL_TRIGGER_TIMED					= 2,
+	MSM_RPM_8960_SEL_RPM_CTL					= 3,
+
+	MSM_RPM_8960_SEL_CXO_CLK					= 5,
+	MSM_RPM_8960_SEL_PXO_CLK					= 6,
+	MSM_RPM_8960_SEL_QDSS_CLK					= 7,
+	MSM_RPM_8960_SEL_APPS_FABRIC_CLK				= 8,
+	MSM_RPM_8960_SEL_SYSTEM_FABRIC_CLK				= 9,
+	MSM_RPM_8960_SEL_MM_FABRIC_CLK					= 10,
+	MSM_RPM_8960_SEL_DAYTONA_FABRIC_CLK				= 11,
+	MSM_RPM_8960_SEL_SFPB_CLK					= 12,
+	MSM_RPM_8960_SEL_CFPB_CLK					= 13,
+	MSM_RPM_8960_SEL_MMFPB_CLK					= 14,
+	MSM_RPM_8960_SEL_EBI1_CLK					= 16,
+
+	MSM_RPM_8960_SEL_APPS_FABRIC_CFG_HALT				= 18,
+	MSM_RPM_8960_SEL_APPS_FABRIC_CFG_CLKMOD				= 19,
+	MSM_RPM_8960_SEL_APPS_FABRIC_CFG_IOCTL				= 20,
+	MSM_RPM_8960_SEL_APPS_FABRIC_ARB				= 21,
+
+	MSM_RPM_8960_SEL_SYS_FABRIC_CFG_HALT				= 22,
+	MSM_RPM_8960_SEL_SYS_FABRIC_CFG_CLKMOD				= 23,
+	MSM_RPM_8960_SEL_SYS_FABRIC_CFG_IOCTL				= 24,
+	MSM_RPM_8960_SEL_SYSTEM_FABRIC_ARB				= 25,
+
+	MSM_RPM_8960_SEL_MMSS_FABRIC_CFG_HALT				= 26,
+	MSM_RPM_8960_SEL_MMSS_FABRIC_CFG_CLKMOD				= 27,
+	MSM_RPM_8960_SEL_MMSS_FABRIC_CFG_IOCTL				= 28,
+	MSM_RPM_8960_SEL_MM_FABRIC_ARB					= 29,
+
+	MSM_RPM_8960_SEL_PM8921_S1					= 30,
+	MSM_RPM_8960_SEL_PM8921_S2					= 31,
+	MSM_RPM_8960_SEL_PM8921_S3					= 32,
+	MSM_RPM_8960_SEL_PM8921_S4					= 33,
+	MSM_RPM_8960_SEL_PM8921_S5					= 34,
+	MSM_RPM_8960_SEL_PM8921_S6					= 35,
+	MSM_RPM_8960_SEL_PM8921_S7					= 36,
+	MSM_RPM_8960_SEL_PM8921_S8					= 37,
+	MSM_RPM_8960_SEL_PM8921_L1					= 38,
+	MSM_RPM_8960_SEL_PM8921_L2					= 39,
+	MSM_RPM_8960_SEL_PM8921_L3					= 40,
+	MSM_RPM_8960_SEL_PM8921_L4					= 41,
+	MSM_RPM_8960_SEL_PM8921_L5					= 42,
+	MSM_RPM_8960_SEL_PM8921_L6					= 43,
+	MSM_RPM_8960_SEL_PM8921_L7					= 44,
+	MSM_RPM_8960_SEL_PM8921_L8					= 45,
+	MSM_RPM_8960_SEL_PM8921_L9					= 46,
+	MSM_RPM_8960_SEL_PM8921_L10					= 47,
+	MSM_RPM_8960_SEL_PM8921_L11					= 48,
+	MSM_RPM_8960_SEL_PM8921_L12					= 49,
+	MSM_RPM_8960_SEL_PM8921_L13					= 50,
+	MSM_RPM_8960_SEL_PM8921_L14					= 51,
+	MSM_RPM_8960_SEL_PM8921_L15					= 52,
+	MSM_RPM_8960_SEL_PM8921_L16					= 53,
+	MSM_RPM_8960_SEL_PM8921_L17					= 54,
+	MSM_RPM_8960_SEL_PM8921_L18					= 55,
+	MSM_RPM_8960_SEL_PM8921_L19					= 56,
+	MSM_RPM_8960_SEL_PM8921_L20					= 57,
+	MSM_RPM_8960_SEL_PM8921_L21					= 58,
+	MSM_RPM_8960_SEL_PM8921_L22					= 59,
+	MSM_RPM_8960_SEL_PM8921_L23					= 60,
+	MSM_RPM_8960_SEL_PM8921_L24					= 61,
+	MSM_RPM_8960_SEL_PM8921_L25					= 62,
+	MSM_RPM_8960_SEL_PM8921_L26					= 63,
+	MSM_RPM_8960_SEL_PM8921_L27					= 64,
+	MSM_RPM_8960_SEL_PM8921_L28					= 65,
+	MSM_RPM_8960_SEL_PM8921_L29					= 66,
+	MSM_RPM_8960_SEL_PM8921_CLK1					= 67,
+	MSM_RPM_8960_SEL_PM8921_CLK2					= 68,
+	MSM_RPM_8960_SEL_PM8921_LVS1					= 69,
+	MSM_RPM_8960_SEL_PM8921_LVS2					= 70,
+	MSM_RPM_8960_SEL_PM8921_LVS3					= 71,
+	MSM_RPM_8960_SEL_PM8921_LVS4					= 72,
+	MSM_RPM_8960_SEL_PM8921_LVS5					= 73,
+	MSM_RPM_8960_SEL_PM8921_LVS6					= 74,
+	MSM_RPM_8960_SEL_PM8921_LVS7					= 75,
+
+	MSM_RPM_8960_SEL_NCP						= 80,
+	MSM_RPM_8960_SEL_CXO_BUFFERS					= 81,
+	MSM_RPM_8960_SEL_USB_OTG_SWITCH					= 82,
+	MSM_RPM_8960_SEL_HDMI_SWITCH					= 83,
+	MSM_RPM_8960_SEL_DDR_DMM					= 84,
+
+	MSM_RPM_8960_SEL_LAST = MSM_RPM_8960_SEL_DDR_DMM,
+};
+
+/* RPM resource (4 byte) word ID enum */
+enum {
+	MSM_RPM_8960_ID_NOTIFICATION_CONFIGURED				= 0,
+	MSM_RPM_8960_ID_NOTIFICATION_CONFIGURED_3 =
+		MSM_RPM_8960_ID_NOTIFICATION_CONFIGURED + 3,
+
+	MSM_RPM_8960_ID_NOTIFICATION_REGISTERED				= 4,
+	MSM_RPM_8960_ID_NOTIFICATION_REGISTERED_3 =
+		MSM_RPM_8960_ID_NOTIFICATION_REGISTERED + 3,
+
+	MSM_RPM_8960_ID_INVALIDATE					= 8,
+	MSM_RPM_8960_ID_INVALIDATE_7 =
+		MSM_RPM_8960_ID_INVALIDATE + 7,
+
+	MSM_RPM_8960_ID_TRIGGER_TIMED_TO				= 16,
+	MSM_RPM_8960_ID_TRIGGER_TIMED_SCLK_COUNT			= 17,
+
+	MSM_RPM_8960_ID_RPM_CTL						= 18,
+
+	/* TRIGGER_CLEAR/SET deprecated in these 24 RESERVED bytes */
+	MSM_RPM_8960_ID_RESERVED					= 19,
+	MSM_RPM_8960_ID_RESERVED_5 =
+		MSM_RPM_8960_ID_RESERVED + 5,
+
+	MSM_RPM_8960_ID_CXO_CLK						= 25,
+	MSM_RPM_8960_ID_PXO_CLK						= 26,
+	MSM_RPM_8960_ID_APPS_FABRIC_CLK					= 27,
+	MSM_RPM_8960_ID_SYSTEM_FABRIC_CLK				= 28,
+	MSM_RPM_8960_ID_MM_FABRIC_CLK					= 29,
+	MSM_RPM_8960_ID_DAYTONA_FABRIC_CLK				= 30,
+	MSM_RPM_8960_ID_SFPB_CLK					= 31,
+	MSM_RPM_8960_ID_CFPB_CLK					= 32,
+	MSM_RPM_8960_ID_MMFPB_CLK					= 33,
+	MSM_RPM_8960_ID_EBI1_CLK					= 34,
+
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_HALT				= 35,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_HALT_1				= 36,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_CLKMOD				= 37,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_CLKMOD_1			= 38,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_CLKMOD_2			= 39,
+	MSM_RPM_8960_ID_APPS_FABRIC_CFG_IOCTL				= 40,
+	MSM_RPM_8960_ID_APPS_FABRIC_ARB					= 41,
+	MSM_RPM_8960_ID_APPS_FABRIC_ARB_11 =
+		MSM_RPM_8960_ID_APPS_FABRIC_ARB + 11,
+
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_HALT				= 53,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_HALT_1				= 54,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_CLKMOD				= 55,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_CLKMOD_1				= 56,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_CLKMOD_2				= 57,
+	MSM_RPM_8960_ID_SYS_FABRIC_CFG_IOCTL				= 58,
+	MSM_RPM_8960_ID_SYSTEM_FABRIC_ARB				= 59,
+	MSM_RPM_8960_ID_SYSTEM_FABRIC_ARB_28 =
+		MSM_RPM_8960_ID_SYSTEM_FABRIC_ARB + 28,
+
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_HALT				= 88,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_HALT_1				= 89,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_CLKMOD				= 90,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_CLKMOD_1			= 91,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_CLKMOD_2			= 92,
+	MSM_RPM_8960_ID_MMSS_FABRIC_CFG_IOCTL				= 93,
+	MSM_RPM_8960_ID_MM_FABRIC_ARB					= 94,
+	MSM_RPM_8960_ID_MM_FABRIC_ARB_22 =
+		MSM_RPM_8960_ID_MM_FABRIC_ARB + 22,
+
+	MSM_RPM_8960_ID_PM8921_S1					= 117,
+	MSM_RPM_8960_ID_PM8921_S1_1					= 118,
+	MSM_RPM_8960_ID_PM8921_S2					= 119,
+	MSM_RPM_8960_ID_PM8921_S2_1					= 120,
+	MSM_RPM_8960_ID_PM8921_S3					= 121,
+	MSM_RPM_8960_ID_PM8921_S3_1					= 122,
+	MSM_RPM_8960_ID_PM8921_S4					= 123,
+	MSM_RPM_8960_ID_PM8921_S4_1					= 124,
+	MSM_RPM_8960_ID_PM8921_S5					= 125,
+	MSM_RPM_8960_ID_PM8921_S5_1					= 126,
+	MSM_RPM_8960_ID_PM8921_S6					= 127,
+	MSM_RPM_8960_ID_PM8921_S6_1					= 128,
+	MSM_RPM_8960_ID_PM8921_S7					= 129,
+	MSM_RPM_8960_ID_PM8921_S7_1					= 130,
+	MSM_RPM_8960_ID_PM8921_S8					= 131,
+	MSM_RPM_8960_ID_PM8921_S8_1					= 132,
+	MSM_RPM_8960_ID_PM8921_L1					= 133,
+	MSM_RPM_8960_ID_PM8921_L1_1					= 134,
+	MSM_RPM_8960_ID_PM8921_L2					= 135,
+	MSM_RPM_8960_ID_PM8921_L2_1					= 136,
+	MSM_RPM_8960_ID_PM8921_L3					= 137,
+	MSM_RPM_8960_ID_PM8921_L3_1					= 138,
+	MSM_RPM_8960_ID_PM8921_L4					= 139,
+	MSM_RPM_8960_ID_PM8921_L4_1					= 140,
+	MSM_RPM_8960_ID_PM8921_L5					= 141,
+	MSM_RPM_8960_ID_PM8921_L5_1					= 142,
+	MSM_RPM_8960_ID_PM8921_L6					= 143,
+	MSM_RPM_8960_ID_PM8921_L6_1					= 144,
+	MSM_RPM_8960_ID_PM8921_L7					= 145,
+	MSM_RPM_8960_ID_PM8921_L7_1					= 146,
+	MSM_RPM_8960_ID_PM8921_L8					= 147,
+	MSM_RPM_8960_ID_PM8921_L8_1					= 148,
+	MSM_RPM_8960_ID_PM8921_L9					= 149,
+	MSM_RPM_8960_ID_PM8921_L9_1					= 150,
+	MSM_RPM_8960_ID_PM8921_L10					= 151,
+	MSM_RPM_8960_ID_PM8921_L10_1					= 152,
+	MSM_RPM_8960_ID_PM8921_L11					= 153,
+	MSM_RPM_8960_ID_PM8921_L11_1					= 154,
+	MSM_RPM_8960_ID_PM8921_L12					= 155,
+	MSM_RPM_8960_ID_PM8921_L12_1					= 156,
+	MSM_RPM_8960_ID_PM8921_L13					= 157,
+	MSM_RPM_8960_ID_PM8921_L13_1					= 158,
+	MSM_RPM_8960_ID_PM8921_L14					= 159,
+	MSM_RPM_8960_ID_PM8921_L14_1					= 160,
+	MSM_RPM_8960_ID_PM8921_L15					= 161,
+	MSM_RPM_8960_ID_PM8921_L15_1					= 162,
+	MSM_RPM_8960_ID_PM8921_L16					= 163,
+	MSM_RPM_8960_ID_PM8921_L16_1					= 164,
+	MSM_RPM_8960_ID_PM8921_L17					= 165,
+	MSM_RPM_8960_ID_PM8921_L17_1					= 166,
+	MSM_RPM_8960_ID_PM8921_L18					= 167,
+	MSM_RPM_8960_ID_PM8921_L18_1					= 168,
+	MSM_RPM_8960_ID_PM8921_L19					= 169,
+	MSM_RPM_8960_ID_PM8921_L19_1					= 170,
+	MSM_RPM_8960_ID_PM8921_L20					= 171,
+	MSM_RPM_8960_ID_PM8921_L20_1					= 172,
+	MSM_RPM_8960_ID_PM8921_L21					= 173,
+	MSM_RPM_8960_ID_PM8921_L21_1					= 174,
+	MSM_RPM_8960_ID_PM8921_L22					= 175,
+	MSM_RPM_8960_ID_PM8921_L22_1					= 176,
+	MSM_RPM_8960_ID_PM8921_L23					= 177,
+	MSM_RPM_8960_ID_PM8921_L23_1					= 178,
+	MSM_RPM_8960_ID_PM8921_L24					= 179,
+	MSM_RPM_8960_ID_PM8921_L24_1					= 180,
+	MSM_RPM_8960_ID_PM8921_L25					= 181,
+	MSM_RPM_8960_ID_PM8921_L25_1					= 182,
+	MSM_RPM_8960_ID_PM8921_L26					= 183,
+	MSM_RPM_8960_ID_PM8921_L26_1					= 184,
+	MSM_RPM_8960_ID_PM8921_L27					= 185,
+	MSM_RPM_8960_ID_PM8921_L27_1					= 186,
+	MSM_RPM_8960_ID_PM8921_L28					= 187,
+	MSM_RPM_8960_ID_PM8921_L28_1					= 188,
+	MSM_RPM_8960_ID_PM8921_L29					= 189,
+	MSM_RPM_8960_ID_PM8921_L29_1					= 190,
+	MSM_RPM_8960_ID_PM8921_CLK1					= 191,
+	MSM_RPM_8960_ID_PM8921_CLK1_1					= 192,
+	MSM_RPM_8960_ID_PM8921_CLK2					= 193,
+	MSM_RPM_8960_ID_PM8921_CLK2_1					= 194,
+	MSM_RPM_8960_ID_PM8921_LVS1					= 195,
+	MSM_RPM_8960_ID_PM8921_LVS2					= 196,
+	MSM_RPM_8960_ID_PM8921_LVS3					= 197,
+	MSM_RPM_8960_ID_PM8921_LVS4					= 198,
+	MSM_RPM_8960_ID_PM8921_LVS5					= 199,
+	MSM_RPM_8960_ID_PM8921_LVS6					= 200,
+	MSM_RPM_8960_ID_PM8921_LVS7					= 201,
+	MSM_RPM_8960_ID_NCP						= 202,
+	MSM_RPM_8960_ID_NCP_1						= 203,
+	MSM_RPM_8960_ID_CXO_BUFFERS					= 204,
+	MSM_RPM_8960_ID_USB_OTG_SWITCH					= 205,
+	MSM_RPM_8960_ID_HDMI_SWITCH					= 206,
+	MSM_RPM_8960_ID_DDR_DMM						= 207,
+	MSM_RPM_8960_ID_DDR_DMM_1					= 208,
+	MSM_RPM_8960_ID_QDSS_CLK					= 209,
+
+	MSM_RPM_8960_ID_LAST = MSM_RPM_8960_ID_QDSS_CLK,
+};
+
+/* RPM status ID enum */
+enum {
+	MSM_RPM_8960_STATUS_ID_VERSION_MAJOR				= 0,
+	MSM_RPM_8960_STATUS_ID_VERSION_MINOR				= 1,
+	MSM_RPM_8960_STATUS_ID_VERSION_BUILD				= 2,
+	MSM_RPM_8960_STATUS_ID_SUPPORTED_RESOURCES			= 3,
+	MSM_RPM_8960_STATUS_ID_SUPPORTED_RESOURCES_1			= 4,
+	MSM_RPM_8960_STATUS_ID_SUPPORTED_RESOURCES_2			= 5,
+	MSM_RPM_8960_STATUS_ID_RESERVED_SUPPORTED_RESOURCES		= 6,
+	MSM_RPM_8960_STATUS_ID_SEQUENCE					= 7,
+	MSM_RPM_8960_STATUS_ID_RPM_CTL					= 8,
+	MSM_RPM_8960_STATUS_ID_CXO_CLK					= 9,
+	MSM_RPM_8960_STATUS_ID_PXO_CLK					= 10,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_CLK				= 11,
+	MSM_RPM_8960_STATUS_ID_SYSTEM_FABRIC_CLK			= 12,
+	MSM_RPM_8960_STATUS_ID_MM_FABRIC_CLK				= 13,
+	MSM_RPM_8960_STATUS_ID_DAYTONA_FABRIC_CLK			= 14,
+	MSM_RPM_8960_STATUS_ID_SFPB_CLK					= 15,
+	MSM_RPM_8960_STATUS_ID_CFPB_CLK					= 16,
+	MSM_RPM_8960_STATUS_ID_MMFPB_CLK				= 17,
+	MSM_RPM_8960_STATUS_ID_EBI1_CLK					= 18,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_CFG_HALT			= 19,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_CFG_CLKMOD			= 20,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_CFG_IOCTL			= 21,
+	MSM_RPM_8960_STATUS_ID_APPS_FABRIC_ARB				= 22,
+	MSM_RPM_8960_STATUS_ID_SYS_FABRIC_CFG_HALT			= 23,
+	MSM_RPM_8960_STATUS_ID_SYS_FABRIC_CFG_CLKMOD			= 24,
+	MSM_RPM_8960_STATUS_ID_SYS_FABRIC_CFG_IOCTL			= 25,
+	MSM_RPM_8960_STATUS_ID_SYSTEM_FABRIC_ARB			= 26,
+	MSM_RPM_8960_STATUS_ID_MMSS_FABRIC_CFG_HALT			= 27,
+	MSM_RPM_8960_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD			= 28,
+	MSM_RPM_8960_STATUS_ID_MMSS_FABRIC_CFG_IOCTL			= 29,
+	MSM_RPM_8960_STATUS_ID_MM_FABRIC_ARB				= 30,
+	MSM_RPM_8960_STATUS_ID_PM8921_S1				= 31,
+	MSM_RPM_8960_STATUS_ID_PM8921_S1_1				= 32,
+	MSM_RPM_8960_STATUS_ID_PM8921_S2				= 33,
+	MSM_RPM_8960_STATUS_ID_PM8921_S2_1				= 34,
+	MSM_RPM_8960_STATUS_ID_PM8921_S3				= 35,
+	MSM_RPM_8960_STATUS_ID_PM8921_S3_1				= 36,
+	MSM_RPM_8960_STATUS_ID_PM8921_S4				= 37,
+	MSM_RPM_8960_STATUS_ID_PM8921_S4_1				= 38,
+	MSM_RPM_8960_STATUS_ID_PM8921_S5				= 39,
+	MSM_RPM_8960_STATUS_ID_PM8921_S5_1				= 40,
+	MSM_RPM_8960_STATUS_ID_PM8921_S6				= 41,
+	MSM_RPM_8960_STATUS_ID_PM8921_S6_1				= 42,
+	MSM_RPM_8960_STATUS_ID_PM8921_S7				= 43,
+	MSM_RPM_8960_STATUS_ID_PM8921_S7_1				= 44,
+	MSM_RPM_8960_STATUS_ID_PM8921_S8				= 45,
+	MSM_RPM_8960_STATUS_ID_PM8921_S8_1				= 46,
+	MSM_RPM_8960_STATUS_ID_PM8921_L1				= 47,
+	MSM_RPM_8960_STATUS_ID_PM8921_L1_1				= 48,
+	MSM_RPM_8960_STATUS_ID_PM8921_L2				= 49,
+	MSM_RPM_8960_STATUS_ID_PM8921_L2_1				= 50,
+	MSM_RPM_8960_STATUS_ID_PM8921_L3				= 51,
+	MSM_RPM_8960_STATUS_ID_PM8921_L3_1				= 52,
+	MSM_RPM_8960_STATUS_ID_PM8921_L4				= 53,
+	MSM_RPM_8960_STATUS_ID_PM8921_L4_1				= 54,
+	MSM_RPM_8960_STATUS_ID_PM8921_L5				= 55,
+	MSM_RPM_8960_STATUS_ID_PM8921_L5_1				= 56,
+	MSM_RPM_8960_STATUS_ID_PM8921_L6				= 57,
+	MSM_RPM_8960_STATUS_ID_PM8921_L6_1				= 58,
+	MSM_RPM_8960_STATUS_ID_PM8921_L7				= 59,
+	MSM_RPM_8960_STATUS_ID_PM8921_L7_1				= 60,
+	MSM_RPM_8960_STATUS_ID_PM8921_L8				= 61,
+	MSM_RPM_8960_STATUS_ID_PM8921_L8_1				= 62,
+	MSM_RPM_8960_STATUS_ID_PM8921_L9				= 63,
+	MSM_RPM_8960_STATUS_ID_PM8921_L9_1				= 64,
+	MSM_RPM_8960_STATUS_ID_PM8921_L10				= 65,
+	MSM_RPM_8960_STATUS_ID_PM8921_L10_1				= 66,
+	MSM_RPM_8960_STATUS_ID_PM8921_L11				= 67,
+	MSM_RPM_8960_STATUS_ID_PM8921_L11_1				= 68,
+	MSM_RPM_8960_STATUS_ID_PM8921_L12				= 69,
+	MSM_RPM_8960_STATUS_ID_PM8921_L12_1				= 70,
+	MSM_RPM_8960_STATUS_ID_PM8921_L13				= 71,
+	MSM_RPM_8960_STATUS_ID_PM8921_L13_1				= 72,
+	MSM_RPM_8960_STATUS_ID_PM8921_L14				= 73,
+	MSM_RPM_8960_STATUS_ID_PM8921_L14_1				= 74,
+	MSM_RPM_8960_STATUS_ID_PM8921_L15				= 75,
+	MSM_RPM_8960_STATUS_ID_PM8921_L15_1				= 76,
+	MSM_RPM_8960_STATUS_ID_PM8921_L16				= 77,
+	MSM_RPM_8960_STATUS_ID_PM8921_L16_1				= 78,
+	MSM_RPM_8960_STATUS_ID_PM8921_L17				= 79,
+	MSM_RPM_8960_STATUS_ID_PM8921_L17_1				= 80,
+	MSM_RPM_8960_STATUS_ID_PM8921_L18				= 81,
+	MSM_RPM_8960_STATUS_ID_PM8921_L18_1				= 82,
+	MSM_RPM_8960_STATUS_ID_PM8921_L19				= 83,
+	MSM_RPM_8960_STATUS_ID_PM8921_L19_1				= 84,
+	MSM_RPM_8960_STATUS_ID_PM8921_L20				= 85,
+	MSM_RPM_8960_STATUS_ID_PM8921_L20_1				= 86,
+	MSM_RPM_8960_STATUS_ID_PM8921_L21				= 87,
+	MSM_RPM_8960_STATUS_ID_PM8921_L21_1				= 88,
+	MSM_RPM_8960_STATUS_ID_PM8921_L22				= 89,
+	MSM_RPM_8960_STATUS_ID_PM8921_L22_1				= 90,
+	MSM_RPM_8960_STATUS_ID_PM8921_L23				= 91,
+	MSM_RPM_8960_STATUS_ID_PM8921_L23_1				= 92,
+	MSM_RPM_8960_STATUS_ID_PM8921_L24				= 93,
+	MSM_RPM_8960_STATUS_ID_PM8921_L24_1				= 94,
+	MSM_RPM_8960_STATUS_ID_PM8921_L25				= 95,
+	MSM_RPM_8960_STATUS_ID_PM8921_L25_1				= 96,
+	MSM_RPM_8960_STATUS_ID_PM8921_L26				= 97,
+	MSM_RPM_8960_STATUS_ID_PM8921_L26_1				= 98,
+	MSM_RPM_8960_STATUS_ID_PM8921_L27				= 99,
+	MSM_RPM_8960_STATUS_ID_PM8921_L27_1				= 100,
+	MSM_RPM_8960_STATUS_ID_PM8921_L28				= 101,
+	MSM_RPM_8960_STATUS_ID_PM8921_L28_1				= 102,
+	MSM_RPM_8960_STATUS_ID_PM8921_L29				= 103,
+	MSM_RPM_8960_STATUS_ID_PM8921_L29_1				= 104,
+	MSM_RPM_8960_STATUS_ID_PM8921_CLK1				= 105,
+	MSM_RPM_8960_STATUS_ID_PM8921_CLK1_1				= 106,
+	MSM_RPM_8960_STATUS_ID_PM8921_CLK2				= 107,
+	MSM_RPM_8960_STATUS_ID_PM8921_CLK2_1				= 108,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS1				= 109,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS2				= 110,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS3				= 111,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS4				= 112,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS5				= 113,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS6				= 114,
+	MSM_RPM_8960_STATUS_ID_PM8921_LVS7				= 115,
+	MSM_RPM_8960_STATUS_ID_NCP					= 116,
+	MSM_RPM_8960_STATUS_ID_NCP_1					= 117,
+	MSM_RPM_8960_STATUS_ID_CXO_BUFFERS				= 118,
+	MSM_RPM_8960_STATUS_ID_USB_OTG_SWITCH				= 119,
+	MSM_RPM_8960_STATUS_ID_HDMI_SWITCH				= 120,
+	MSM_RPM_8960_STATUS_ID_DDR_DMM					= 121,
+	MSM_RPM_8960_STATUS_ID_DDR_DMM_1				= 122,
+	MSM_RPM_8960_STATUS_ID_EBI1_CH0_RANGE				= 123,
+	MSM_RPM_8960_STATUS_ID_EBI1_CH1_RANGE				= 124,
+
+	MSM_RPM_8960_STATUS_ID_LAST = MSM_RPM_8960_STATUS_ID_EBI1_CH1_RANGE,
+};
+
+#endif /* __ARCH_ARM_MACH_MSM_RPM_8960_H */
diff --git a/drivers/mfd/msm_rpm.c b/drivers/mfd/msm_rpm.c
new file mode 100644
index 0000000..63df2e2
--- /dev/null
+++ b/drivers/mfd/msm_rpm.c
@@ -0,0 +1,525 @@
+/*
+ * Copyright (c) 2013, Sony Mobile Communications AB.
+ *
+ * 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/msm_rpm.h>
+
+#include "msm_rpm-8064.h"
+#include "msm_rpm-8960.h"
+
+struct msm_rpm_resource;
+
+struct msm_rpm {
+	struct device *dev;
+	struct completion ack;
+	struct mutex lock;
+
+	int irq_ack;
+	int irq_err;
+	int irq_wakeup;
+
+	void __iomem *status_regs;
+	void __iomem *ctrl_regs;
+	void __iomem *req_regs;
+	void __iomem *ack_regs;
+
+	void __iomem *ipc_rpm_reg;
+
+	unsigned long ack_status;
+
+	u32 version[3];
+
+	const struct msm_rpm_resource *resource_table;
+	unsigned nresources;
+};
+
+#define MSM_STATUS_REG(rpm, i) ((rpm)->status_regs + (i) * 4)
+#define MSM_CTRL_REG(rpm, i) ((rpm)->ctrl_regs + (i) * 4)
+#define MSM_REQ_REG(rpm, i) ((rpm)->req_regs + (i) * 4)
+#define MSM_ACK_REG(rpm, i) ((rpm)->ack_regs + (i) * 4)
+
+struct msm_rpm_resource {
+	unsigned target_id;
+	unsigned status_id;
+	unsigned select_id;
+	unsigned size;
+};
+
+#define MSM_RPM_VERSION		0
+#define MSM_RPM_REQ_CTX		3
+#define MSM_RPM_REQ_SEL		11
+#define MSM_RPM_REQ_SEL_COUNT	7
+#define MSM_RPM_ACK_CTX		15
+#define MSM_RPM_ACK_SEL		23
+#define MSM_RPM_ACK_SEL_COUNT	7
+
+/*
+ * APQ8064 data
+ */
+#define APQ8064_RESOURCE(id, size)		\
+	[MSM_RPM_ ## id] = {			\
+		MSM_RPM_8064_ID_ ## id,		\
+		MSM_RPM_8064_STATUS_ID_ ## id,	\
+		MSM_RPM_8064_SEL_ ## id,	\
+		size				\
+	}
+
+static const struct msm_rpm_resource apq8064_rpm_resource_table[] = {
+	APQ8064_RESOURCE(CXO_CLK, 1),
+	APQ8064_RESOURCE(PXO_CLK, 1),
+	APQ8064_RESOURCE(APPS_FABRIC_CLK, 1),
+	APQ8064_RESOURCE(SYSTEM_FABRIC_CLK, 1),
+	APQ8064_RESOURCE(MM_FABRIC_CLK, 1),
+	APQ8064_RESOURCE(DAYTONA_FABRIC_CLK, 1),
+	APQ8064_RESOURCE(SFPB_CLK, 1),
+	APQ8064_RESOURCE(CFPB_CLK, 1),
+	APQ8064_RESOURCE(MMFPB_CLK, 1),
+	APQ8064_RESOURCE(EBI1_CLK, 1),
+
+	APQ8064_RESOURCE(APPS_FABRIC_CFG_HALT, 1),
+	APQ8064_RESOURCE(APPS_FABRIC_CFG_CLKMOD, 1),
+	APQ8064_RESOURCE(APPS_FABRIC_CFG_IOCTL, 1),
+	APQ8064_RESOURCE(APPS_FABRIC_ARB, 12),
+
+	APQ8064_RESOURCE(SYS_FABRIC_CFG_HALT, 1),
+	APQ8064_RESOURCE(SYS_FABRIC_CFG_CLKMOD, 1),
+	APQ8064_RESOURCE(SYS_FABRIC_CFG_IOCTL, 1),
+	APQ8064_RESOURCE(SYSTEM_FABRIC_ARB, 30),
+
+	APQ8064_RESOURCE(MMSS_FABRIC_CFG_HALT, 1),
+	APQ8064_RESOURCE(MMSS_FABRIC_CFG_CLKMOD, 1),
+	APQ8064_RESOURCE(MMSS_FABRIC_CFG_IOCTL, 1),
+	APQ8064_RESOURCE(MM_FABRIC_ARB, 21),
+
+	APQ8064_RESOURCE(PM8921_S1, 2),
+	APQ8064_RESOURCE(PM8921_S2, 2),
+	APQ8064_RESOURCE(PM8921_S3, 2),
+	APQ8064_RESOURCE(PM8921_S4, 2),
+	APQ8064_RESOURCE(PM8921_S5, 2),
+	APQ8064_RESOURCE(PM8921_S6, 2),
+	APQ8064_RESOURCE(PM8921_S7, 2),
+	APQ8064_RESOURCE(PM8921_S8, 2),
+
+	APQ8064_RESOURCE(PM8921_L1, 2),
+	APQ8064_RESOURCE(PM8921_L2, 2),
+	APQ8064_RESOURCE(PM8921_L3, 2),
+	APQ8064_RESOURCE(PM8921_L4, 2),
+	APQ8064_RESOURCE(PM8921_L5, 2),
+	APQ8064_RESOURCE(PM8921_L6, 2),
+	APQ8064_RESOURCE(PM8921_L7, 2),
+	APQ8064_RESOURCE(PM8921_L8, 2),
+	APQ8064_RESOURCE(PM8921_L9, 2),
+	APQ8064_RESOURCE(PM8921_L10, 2),
+	APQ8064_RESOURCE(PM8921_L11, 2),
+	APQ8064_RESOURCE(PM8921_L12, 2),
+	APQ8064_RESOURCE(PM8921_L13, 2),
+	APQ8064_RESOURCE(PM8921_L14, 2),
+	APQ8064_RESOURCE(PM8921_L15, 2),
+	APQ8064_RESOURCE(PM8921_L16, 2),
+	APQ8064_RESOURCE(PM8921_L17, 2),
+	APQ8064_RESOURCE(PM8921_L18, 2),
+	APQ8064_RESOURCE(PM8921_L19, 2),
+	APQ8064_RESOURCE(PM8921_L20, 2),
+	APQ8064_RESOURCE(PM8921_L21, 2),
+	APQ8064_RESOURCE(PM8921_L22, 2),
+	APQ8064_RESOURCE(PM8921_L23, 2),
+	APQ8064_RESOURCE(PM8921_L24, 2),
+	APQ8064_RESOURCE(PM8921_L25, 2),
+	APQ8064_RESOURCE(PM8921_L26, 2),
+	APQ8064_RESOURCE(PM8921_L27, 2),
+	APQ8064_RESOURCE(PM8921_L28, 2),
+	APQ8064_RESOURCE(PM8921_L29, 2),
+
+	APQ8064_RESOURCE(PM8921_CLK1, 2),
+	APQ8064_RESOURCE(PM8921_CLK2, 2),
+
+	APQ8064_RESOURCE(PM8921_LVS1, 1),
+	APQ8064_RESOURCE(PM8921_LVS2, 1),
+	APQ8064_RESOURCE(PM8921_LVS3, 1),
+	APQ8064_RESOURCE(PM8921_LVS4, 1),
+	APQ8064_RESOURCE(PM8921_LVS5, 1),
+	APQ8064_RESOURCE(PM8921_LVS6, 1),
+	APQ8064_RESOURCE(PM8921_LVS7, 1),
+
+	APQ8064_RESOURCE(PM8821_S1, 2),
+	APQ8064_RESOURCE(PM8821_S2, 2),
+
+	APQ8064_RESOURCE(PM8821_L1, 2),
+
+	APQ8064_RESOURCE(NCP, 2),
+
+	APQ8064_RESOURCE(CXO_BUFFERS, 1),
+
+	APQ8064_RESOURCE(USB_OTG_SWITCH, 1),
+	APQ8064_RESOURCE(HDMI_SWITCH, 1),
+
+	APQ8064_RESOURCE(DDR_DMM, 2),
+	APQ8064_RESOURCE(VDDMIN_GPIO, 1),
+};
+
+static const struct msm_rpm apq8064_template = {
+	.version = { 3, 0, 0 },
+	.resource_table = apq8064_rpm_resource_table,
+	.nresources = ARRAY_SIZE(apq8064_rpm_resource_table),
+};
+
+/*
+ * MSM8960 data
+ */
+#define MSM8960_RESOURCE(id, size)		\
+	[MSM_RPM_ ## id] = {			\
+		MSM_RPM_8960_ID_ ## id,		\
+		MSM_RPM_8960_STATUS_ID_ ## id,	\
+		MSM_RPM_8960_SEL_ ## id,	\
+		size				\
+	}
+
+static const struct msm_rpm_resource msm8960_rpm_resource_table[] = {
+	MSM8960_RESOURCE(CXO_CLK, 1),
+	MSM8960_RESOURCE(PXO_CLK, 1),
+	MSM8960_RESOURCE(APPS_FABRIC_CLK, 1),
+	MSM8960_RESOURCE(SYSTEM_FABRIC_CLK, 1),
+	MSM8960_RESOURCE(MM_FABRIC_CLK, 1),
+	MSM8960_RESOURCE(DAYTONA_FABRIC_CLK, 1),
+	MSM8960_RESOURCE(SFPB_CLK, 1),
+	MSM8960_RESOURCE(CFPB_CLK, 1),
+	MSM8960_RESOURCE(MMFPB_CLK, 1),
+	MSM8960_RESOURCE(EBI1_CLK, 1),
+
+	MSM8960_RESOURCE(APPS_FABRIC_CFG_HALT, 1),
+	MSM8960_RESOURCE(APPS_FABRIC_CFG_CLKMOD, 1),
+	MSM8960_RESOURCE(APPS_FABRIC_CFG_IOCTL, 1),
+	MSM8960_RESOURCE(APPS_FABRIC_ARB, 12),
+
+	MSM8960_RESOURCE(SYS_FABRIC_CFG_HALT, 1),
+	MSM8960_RESOURCE(SYS_FABRIC_CFG_CLKMOD, 1),
+	MSM8960_RESOURCE(SYS_FABRIC_CFG_IOCTL, 1),
+	MSM8960_RESOURCE(SYSTEM_FABRIC_ARB, 29),
+
+	MSM8960_RESOURCE(MMSS_FABRIC_CFG_HALT, 1),
+	MSM8960_RESOURCE(MMSS_FABRIC_CFG_CLKMOD, 1),
+	MSM8960_RESOURCE(MMSS_FABRIC_CFG_IOCTL, 1),
+	MSM8960_RESOURCE(MM_FABRIC_ARB, 23),
+
+	MSM8960_RESOURCE(PM8921_S1, 2),
+	MSM8960_RESOURCE(PM8921_S2, 2),
+	MSM8960_RESOURCE(PM8921_S3, 2),
+	MSM8960_RESOURCE(PM8921_S4, 2),
+	MSM8960_RESOURCE(PM8921_S5, 2),
+	MSM8960_RESOURCE(PM8921_S6, 2),
+	MSM8960_RESOURCE(PM8921_S7, 2),
+	MSM8960_RESOURCE(PM8921_S8, 2),
+	MSM8960_RESOURCE(PM8921_L1, 2),
+	MSM8960_RESOURCE(PM8921_L2, 2),
+	MSM8960_RESOURCE(PM8921_L3, 2),
+	MSM8960_RESOURCE(PM8921_L4, 2),
+	MSM8960_RESOURCE(PM8921_L5, 2),
+	MSM8960_RESOURCE(PM8921_L6, 2),
+	MSM8960_RESOURCE(PM8921_L7, 2),
+	MSM8960_RESOURCE(PM8921_L8, 2),
+	MSM8960_RESOURCE(PM8921_L9, 2),
+	MSM8960_RESOURCE(PM8921_L10, 2),
+	MSM8960_RESOURCE(PM8921_L11, 2),
+	MSM8960_RESOURCE(PM8921_L12, 2),
+	MSM8960_RESOURCE(PM8921_L13, 2),
+	MSM8960_RESOURCE(PM8921_L14, 2),
+	MSM8960_RESOURCE(PM8921_L15, 2),
+	MSM8960_RESOURCE(PM8921_L16, 2),
+	MSM8960_RESOURCE(PM8921_L17, 2),
+	MSM8960_RESOURCE(PM8921_L18, 2),
+	MSM8960_RESOURCE(PM8921_L19, 2),
+	MSM8960_RESOURCE(PM8921_L20, 2),
+	MSM8960_RESOURCE(PM8921_L21, 2),
+	MSM8960_RESOURCE(PM8921_L22, 2),
+	MSM8960_RESOURCE(PM8921_L23, 2),
+	MSM8960_RESOURCE(PM8921_L24, 2),
+	MSM8960_RESOURCE(PM8921_L25, 2),
+	MSM8960_RESOURCE(PM8921_L26, 2),
+	MSM8960_RESOURCE(PM8921_L27, 2),
+	MSM8960_RESOURCE(PM8921_L28, 2),
+	MSM8960_RESOURCE(PM8921_L29, 2),
+	MSM8960_RESOURCE(PM8921_CLK1, 2),
+	MSM8960_RESOURCE(PM8921_CLK2, 2),
+	MSM8960_RESOURCE(PM8921_LVS1, 1),
+	MSM8960_RESOURCE(PM8921_LVS2, 1),
+	MSM8960_RESOURCE(PM8921_LVS3, 1),
+	MSM8960_RESOURCE(PM8921_LVS4, 1),
+	MSM8960_RESOURCE(PM8921_LVS5, 1),
+	MSM8960_RESOURCE(PM8921_LVS6, 1),
+	MSM8960_RESOURCE(PM8921_LVS7, 1),
+
+	MSM8960_RESOURCE(NCP, 2),
+	MSM8960_RESOURCE(CXO_BUFFERS, 1),
+	MSM8960_RESOURCE(USB_OTG_SWITCH, 1),
+	MSM8960_RESOURCE(HDMI_SWITCH, 1),
+	MSM8960_RESOURCE(DDR_DMM, 2),
+};
+
+static const struct msm_rpm msm8960_template = {
+	.version = { 3, 0, 0 },
+	.resource_table = msm8960_rpm_resource_table,
+	.nresources = ARRAY_SIZE(msm8960_rpm_resource_table),
+};
+
+static const struct of_device_id msm_rpm_of_match[] = {
+	{ .compatible = "qcom,apq8064-rpm", .data = &apq8064_template },
+	{ .compatible = "qcom,msm8960-rpm", .data = &msm8960_template },
+};
+MODULE_DEVICE_TABLE(of, msm_rpm_of_match);
+
+int msm_rpm_write(const struct device *dev, enum msm_rpm_resource_id resource, u32 *buf, size_t size)
+{
+	const struct msm_rpm_resource *res;
+	struct msm_rpm *rpm = dev_get_drvdata(dev);
+	unsigned long sel_mask[MSM_RPM_REQ_SEL_COUNT] = { 0 };
+	int ret = 0;
+	int i;
+
+	if (WARN_ON(resource < 0 || resource >= rpm->nresources))
+		return -EINVAL;
+
+	res = &rpm->resource_table[resource];
+	if (WARN_ON(res->size != size))
+		return -EINVAL;
+
+	mutex_lock(&rpm->lock);
+
+	for (i = 0; i < res->size; i++)
+		writel(buf[i], MSM_REQ_REG(rpm, res->target_id + i));
+
+	bitmap_set(sel_mask, res->select_id, 1);
+	for (i = 0; i < ARRAY_SIZE(sel_mask); i++)
+		writel(sel_mask[i], MSM_CTRL_REG(rpm, MSM_RPM_REQ_SEL + i));
+
+	/* BIT(0) is active mode */
+	writel(BIT(0), MSM_CTRL_REG(rpm, MSM_RPM_REQ_CTX));
+
+	reinit_completion(&rpm->ack);
+
+	writel(4, rpm->ipc_rpm_reg);
+
+	wait_for_completion(&rpm->ack);
+
+	/* BIT(31) is rejected */
+	if (rpm->ack_status & BIT(31))
+		ret = -EIO;
+
+	mutex_unlock(&rpm->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(msm_rpm_write);
+
+static irqreturn_t msm_rpm_ack_interrupt(int irq, void *dev)
+{
+	struct msm_rpm *rpm = dev;
+	unsigned long sel[MSM_RPM_ACK_SEL_COUNT];
+	unsigned long ack;
+	int i;
+
+	ack = readl(MSM_CTRL_REG(rpm, MSM_RPM_ACK_CTX));
+	for (i = 0; i < MSM_RPM_ACK_SEL_COUNT; i++) {
+		sel[i] = readl(MSM_CTRL_REG(rpm, MSM_RPM_ACK_SEL + i));
+		writel(0, MSM_CTRL_REG(rpm, MSM_RPM_ACK_SEL + i));
+	}
+	writel(0, MSM_CTRL_REG(rpm, MSM_RPM_ACK_CTX));
+
+	/* BIT(30) is notification */
+	if (ack & BIT(30)) {
+		dev_err(rpm->dev, "notification!\n");
+	} else {
+		rpm->ack_status = ack;
+		complete(&rpm->ack);
+		dev_dbg(rpm->dev, "completed ack\n");
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t msm_rpm_err_interrupt(int irq, void *dev)
+{
+	struct msm_rpm *rpm = dev;
+
+	writel(0x1, rpm->ipc_rpm_reg);
+	panic("Fatal RPM error");
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t msm_rpm_wakeup_interrupt(int irq, void *dev)
+{
+	return IRQ_HANDLED;
+}
+
+static int msm_rpm_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	const struct msm_rpm *template;
+	struct resource *res;
+	struct msm_rpm *rpm;
+	u32 fw_version[3];
+	int ret;
+
+	dev_dbg(&pdev->dev, "================ msm_rpm_probe ================\n");
+
+	rpm = devm_kzalloc(&pdev->dev, sizeof(*rpm), GFP_KERNEL);
+	if (!rpm) {
+		dev_err(&pdev->dev, "Can't allocate msm_rpm\n");
+		return -ENOMEM;
+	}
+	rpm->dev = &pdev->dev;
+	mutex_init(&rpm->lock);
+	init_completion(&rpm->ack);
+
+	rpm->irq_ack = platform_get_irq_byname(pdev, "ack");
+	if (rpm->irq_ack < 0) {
+		dev_err(&pdev->dev, "required ack interrupt missing\n");
+		return -EINVAL;
+	}
+
+	rpm->irq_err = platform_get_irq_byname(pdev, "err");
+	if (rpm->irq_err < 0) {
+		dev_err(&pdev->dev, "required err interrupt missing\n");
+		return -EINVAL;
+	}
+
+	rpm->irq_wakeup = platform_get_irq_byname(pdev, "wakeup");
+	if (rpm->irq_wakeup < 0) {
+		dev_err(&pdev->dev, "required wakeup interrupt missing\n");
+		return -EINVAL;
+	}
+
+	match = of_match_device(msm_rpm_of_match, &pdev->dev);
+	template = match->data;
+	memcpy(rpm->version, template->version, sizeof(rpm->version));
+	rpm->resource_table = template->resource_table;
+	rpm->nresources = template->nresources;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	rpm->status_regs = devm_ioremap_resource(&pdev->dev, res);
+	rpm->ctrl_regs = rpm->status_regs + 0x400;
+	rpm->req_regs = rpm->status_regs + 0x600;
+	rpm->ack_regs = rpm->status_regs + 0xa00;
+	if (IS_ERR(rpm->status_regs))
+		return PTR_ERR(rpm->status_regs);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	rpm->ipc_rpm_reg = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(rpm->ipc_rpm_reg))
+		return PTR_ERR(rpm->ipc_rpm_reg);
+
+	dev_set_drvdata(&pdev->dev, rpm);
+
+	fw_version[0] = readl(MSM_STATUS_REG(rpm, MSM_RPM_VERSION + 0));
+	fw_version[1] = readl(MSM_STATUS_REG(rpm, MSM_RPM_VERSION + 1));
+	fw_version[2] = readl(MSM_STATUS_REG(rpm, MSM_RPM_VERSION + 2));
+	if (fw_version[0] != rpm->version[0]) {
+		dev_err(&pdev->dev, "RPM version %u.%u.%u incompatible with "
+				    "this driver version %u.%u.%u\n",
+				    fw_version[0],
+				    fw_version[1],
+				    fw_version[2],
+				    rpm->version[0],
+				    rpm->version[1],
+				    rpm->version[2]);
+		return -EFAULT;
+	}
+
+	dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0],
+							fw_version[1],
+							fw_version[2]);
+
+	writel(fw_version[0], MSM_CTRL_REG(rpm, MSM_RPM_VERSION + 0));
+	writel(fw_version[1], MSM_CTRL_REG(rpm, MSM_RPM_VERSION + 1));
+	writel(fw_version[2], MSM_CTRL_REG(rpm, MSM_RPM_VERSION + 2));
+
+	ret = devm_request_irq(&pdev->dev,
+			       rpm->irq_ack,
+			       msm_rpm_ack_interrupt,
+			       IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND,
+			       "msm_rpm ack",
+			       rpm);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request ack interrupt\n");
+		return ret;
+	}
+
+#if 0
+	ret = irq_set_irq_wake(rpm->irq_ack, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable wakeup for ack interrupt\n");
+		return ret;
+	}
+#endif
+
+	ret = devm_request_irq(&pdev->dev,
+			       rpm->irq_err,
+			       msm_rpm_err_interrupt,
+			       IRQF_TRIGGER_RISING,
+			       "msm_rpm err",
+			       rpm);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request err interrupt\n");
+		return ret;
+	}
+
+	ret = devm_request_irq(&pdev->dev,
+			       rpm->irq_wakeup,
+			       msm_rpm_wakeup_interrupt,
+			       IRQF_TRIGGER_RISING,
+			       "msm_rpm wakeup",
+			       rpm);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request wakeup interrupt\n");
+		return ret;
+	}
+
+#if 0
+	ret = irq_set_irq_wake(rpm->irq_wakeup, 1);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable wakeup for wakeup interrupt\n");
+		return ret;
+	}
+#endif
+
+	return of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
+}
+
+static struct platform_driver msm_rpm_driver = {
+	.probe          = msm_rpm_probe,
+	.driver  = {
+		.name  = "msm_rpm",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_rpm_of_match,
+	},
+};
+
+static int __init msm_rpm_init(void)
+{
+	return platform_driver_register(&msm_rpm_driver);
+}
+arch_initcall(msm_rpm_init);
+
+static void __exit msm_rpm_exit(void)
+{
+	platform_driver_unregister(&msm_rpm_driver);
+}
+module_exit(msm_rpm_exit)
+
+MODULE_DESCRIPTION("MSM RPM driver");
+MODULE_LICENSE("GPLv2");
diff --git a/include/linux/mfd/msm_rpm.h b/include/linux/mfd/msm_rpm.h
new file mode 100644
index 0000000..26d78bc
--- /dev/null
+++ b/include/linux/mfd/msm_rpm.h
@@ -0,0 +1,87 @@
+#ifndef __MSM_RPM_H__
+#define __MSM_RPM_H__
+
+enum msm_rpm_resource_id {
+	MSM_RPM_APPS_FABRIC_ARB = 1,
+	MSM_RPM_APPS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_APPS_FABRIC_CFG_HALT,
+	MSM_RPM_APPS_FABRIC_CFG_IOCTL,
+	MSM_RPM_APPS_FABRIC_CLK,
+	MSM_RPM_CFPB_CLK,
+	MSM_RPM_CXO_BUFFERS,
+	MSM_RPM_CXO_CLK,
+	MSM_RPM_DAYTONA_FABRIC_CLK,
+	MSM_RPM_DDR_DMM,
+	MSM_RPM_EBI1_CLK,
+	MSM_RPM_HDMI_SWITCH,
+	MSM_RPM_MMFPB_CLK,
+	MSM_RPM_MMSS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_MMSS_FABRIC_CFG_HALT,
+	MSM_RPM_MMSS_FABRIC_CFG_IOCTL,
+	MSM_RPM_MM_FABRIC_ARB,
+	MSM_RPM_MM_FABRIC_CLK,
+	MSM_RPM_NCP,
+	MSM_RPM_PM8821_L1,
+	MSM_RPM_PM8821_S1,
+	MSM_RPM_PM8821_S2,
+	MSM_RPM_PM8921_CLK1,
+	MSM_RPM_PM8921_CLK2,
+	MSM_RPM_PM8921_L1,
+	MSM_RPM_PM8921_L2,
+	MSM_RPM_PM8921_L3,
+	MSM_RPM_PM8921_L4,
+	MSM_RPM_PM8921_L5,
+	MSM_RPM_PM8921_L6,
+	MSM_RPM_PM8921_L7,
+	MSM_RPM_PM8921_L8,
+	MSM_RPM_PM8921_L9,
+	MSM_RPM_PM8921_L10,
+	MSM_RPM_PM8921_L11,
+	MSM_RPM_PM8921_L12,
+	MSM_RPM_PM8921_L13,
+	MSM_RPM_PM8921_L14,
+	MSM_RPM_PM8921_L15,
+	MSM_RPM_PM8921_L16,
+	MSM_RPM_PM8921_L17,
+	MSM_RPM_PM8921_L18,
+	MSM_RPM_PM8921_L19,
+	MSM_RPM_PM8921_L20,
+	MSM_RPM_PM8921_L21,
+	MSM_RPM_PM8921_L22,
+	MSM_RPM_PM8921_L23,
+	MSM_RPM_PM8921_L24,
+	MSM_RPM_PM8921_L25,
+	MSM_RPM_PM8921_L26,
+	MSM_RPM_PM8921_L27,
+	MSM_RPM_PM8921_L28,
+	MSM_RPM_PM8921_L29,
+	MSM_RPM_PM8921_LVS1,
+	MSM_RPM_PM8921_LVS2,
+	MSM_RPM_PM8921_LVS3,
+	MSM_RPM_PM8921_LVS4,
+	MSM_RPM_PM8921_LVS5,
+	MSM_RPM_PM8921_LVS6,
+	MSM_RPM_PM8921_LVS7,
+	MSM_RPM_PM8921_S1,
+	MSM_RPM_PM8921_S2,
+	MSM_RPM_PM8921_S3,
+	MSM_RPM_PM8921_S4,
+	MSM_RPM_PM8921_S5,
+	MSM_RPM_PM8921_S6,
+	MSM_RPM_PM8921_S7,
+	MSM_RPM_PM8921_S8,
+	MSM_RPM_PXO_CLK,
+	MSM_RPM_QDSS_CLK,
+	MSM_RPM_SFPB_CLK,
+	MSM_RPM_SYSTEM_FABRIC_ARB,
+	MSM_RPM_SYSTEM_FABRIC_CLK,
+	MSM_RPM_SYS_FABRIC_CFG_CLKMOD,
+	MSM_RPM_SYS_FABRIC_CFG_HALT,
+	MSM_RPM_SYS_FABRIC_CFG_IOCTL,
+	MSM_RPM_USB_OTG_SWITCH,
+	MSM_RPM_VDDMIN_GPIO,
+};
+
+int msm_rpm_write(const struct device *dev, enum msm_rpm_resource_id resource, u32 *buf, size_t count);
+
+#endif
-- 
1.8.2.2

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

* [RFC WIP 2/2] regulator: msm_rpm: Initial regulator driver for Qualcomm RPM
  2014-04-22 18:20 [RFC WIP 0/2] Qualcomm family A RPM driver and example client Bjorn Andersson
  2014-04-22 18:20 ` [RFC WIP 1/2] mfd: msm_rpm: Initial driver for the Qualcomm RPM Bjorn Andersson
@ 2014-04-22 18:20 ` Bjorn Andersson
  1 sibling, 0 replies; 3+ messages in thread
From: Bjorn Andersson @ 2014-04-22 18:20 UTC (permalink / raw)
  To: joshc, linux-arm-msm

Initial regulator driver for ldos on the pm8921 controlled by RPM.

Signed-off-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
---
 drivers/regulator/Kconfig             |   7 +
 drivers/regulator/Makefile            |   1 +
 drivers/regulator/msm_rpm-regulator.c | 467 ++++++++++++++++++++++++++++++++++
 3 files changed, 475 insertions(+)
 create mode 100644 drivers/regulator/msm_rpm-regulator.c

diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 6a79328..a1d35316 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -372,6 +372,13 @@ config REGULATOR_MC13892
 	  Say y here to support the regulators found on the Freescale MC13892
 	  PMIC.
 
+config REGULATOR_MSM_RPM
+	tristate "Qualcomm RPM regulator driver"
+	depends on MFD_MSM_RPM
+	help
+	  This driver provides support for regulators controlled by the
+	  Qualcomm RPM.
+
 config REGULATOR_PALMAS
 	tristate "TI Palmas PMIC Regulators"
 	depends on MFD_PALMAS
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 979f9dd..c1cb250 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o
 obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
+obj-$(CONFIG_REGULATOR_MSM_RPM) += msm_rpm-regulator.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
 obj-$(CONFIG_REGULATOR_PFUZE100) += pfuze100-regulator.o
 obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
diff --git a/drivers/regulator/msm_rpm-regulator.c b/drivers/regulator/msm_rpm-regulator.c
new file mode 100644
index 0000000..4c1cd6a
--- /dev/null
+++ b/drivers/regulator/msm_rpm-regulator.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2013, Sony Mobile Communications AB.
+ *
+ * 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.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+
+#include <linux/mfd/msm_rpm.h>
+
+struct rpm_vreg_parts;
+struct vreg_range;
+
+struct msm_rpm_reg {
+	struct mutex lock;
+	struct device *dev;
+	struct regulator_desc desc;
+
+	const struct rpm_vreg_parts *parts;
+	const struct vreg_range *ranges;
+	int n_ranges;
+
+	const int resource;
+
+	int is_enabled;
+
+	u32 val[2];
+
+	int uV;
+	const int hpm_min_load;
+};
+
+#define REQUEST_MEMBER(_word, _mask, _shift)	\
+{						\
+	.word   = _word,			\
+	.mask   = _mask,			\
+	.shift  = _shift,			\
+}
+
+struct request_member {
+	int		word;
+	unsigned int	mask;
+	int		shift;
+};
+
+/* Possible RPM regulator request members */
+struct rpm_vreg_parts {
+	struct request_member   mV;     /* voltage: used if voltage is in mV */
+	struct request_member   uV;     /* voltage: used if voltage is in uV */
+	struct request_member   ip;             /* peak current in mA */
+	struct request_member   pd;             /* pull down enable */
+	struct request_member   ia;             /* average current in mA */
+	struct request_member   fm;             /* force mode */
+	struct request_member   pm;             /* power mode */
+	struct request_member   pc;             /* pin control */
+	struct request_member   pf;             /* pin function */
+	struct request_member   enable_state;   /* NCP and switch */
+	struct request_member   comp_mode;      /* NCP */
+	struct request_member   freq;           /* frequency: NCP and SMPS */
+	struct request_member   freq_clk_src;   /* clock source: SMPS */
+	struct request_member   hpm;            /* switch: control OCP and SS */
+	int                     request_len;
+};
+
+struct vreg_range {
+	int min_uV;
+	int max_uV;
+	int step_uV;
+};
+
+#define VOLTAGE_RANGE(_min_uV, _max_uV, _step_uV)	\
+{							\
+	.min_uV  = _min_uV,				\
+	.max_uV  = _max_uV,				\
+	.step_uV = _step_uV,				\
+}
+
+#define SET_POINTS(_ranges)		\
+{ 					\
+	.range  = _ranges,		\
+	.count  = ARRAY_SIZE(_ranges),	\
+};
+
+/* Minimum high power mode loads in uA. */
+#define RPM_VREG_8960_LDO_50_HPM_MIN_LOAD               5000
+#define RPM_VREG_8960_LDO_150_HPM_MIN_LOAD              10000
+#define RPM_VREG_8960_LDO_300_HPM_MIN_LOAD              10000
+#define RPM_VREG_8960_LDO_600_HPM_MIN_LOAD              10000
+#define RPM_VREG_8960_LDO_1200_HPM_MIN_LOAD             10000
+#define RPM_VREG_8960_SMPS_1500_HPM_MIN_LOAD            100000
+#define RPM_VREG_8960_SMPS_2000_HPM_MIN_LOAD            100000
+
+/*
+ * Physically available PMIC regulator voltage setpoint ranges
+ */
+static const struct vreg_range pldo_ranges[] = {
+	VOLTAGE_RANGE( 750000, 1487500, 12500),
+	VOLTAGE_RANGE(1500000, 3075000, 25000),
+	VOLTAGE_RANGE(3100000, 4900000, 50000),
+};
+
+static const struct vreg_range nldo_ranges[] = {
+	VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static const struct vreg_range nldo1200_ranges[] = {
+	VOLTAGE_RANGE( 375000,  743750,  6250),
+	VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static const struct vreg_range ln_ldo_ranges[] = {
+	VOLTAGE_RANGE( 690000, 1110000,  60000),
+	VOLTAGE_RANGE(1380000, 2220000, 120000),
+};
+
+static const struct vreg_range smps_ranges[] = {
+	VOLTAGE_RANGE( 375000,  737500, 12500),
+	VOLTAGE_RANGE( 750000, 1487500, 12500),
+	VOLTAGE_RANGE(1500000, 3075000, 25000),
+};
+
+static const struct vreg_range ftsmps_ranges[] = {
+	VOLTAGE_RANGE( 350000,  650000, 50000),
+	VOLTAGE_RANGE( 700000, 1400000, 12500),
+	VOLTAGE_RANGE(1500000, 3300000, 50000),
+};
+
+static const struct vreg_range ncp_ranges[] = {
+	VOLTAGE_RANGE(1500000, 3050000, 50000),
+};
+
+/*
+ * RPM regulator request formats for MSM8660
+ */
+static const struct rpm_vreg_parts ldo_parts_8660 = {
+	.request_len    = 2,
+	.mV             = REQUEST_MEMBER(0, 0x00000FFF,  0),
+	.ip             = REQUEST_MEMBER(0, 0x00FFF000, 12),
+	.fm             = REQUEST_MEMBER(0, 0x03000000, 24),
+	.pc             = REQUEST_MEMBER(0, 0x3C000000, 26),
+	.pf             = REQUEST_MEMBER(0, 0xC0000000, 30),
+	.pd             = REQUEST_MEMBER(1, 0x00000001,  0),
+	.ia             = REQUEST_MEMBER(1, 0x00001FFE,  1),
+};
+
+static const struct rpm_vreg_parts smps_parts_8660 = {
+	.request_len    = 2,
+	.mV             = REQUEST_MEMBER(0, 0x00000FFF,  0),
+	.ip             = REQUEST_MEMBER(0, 0x00FFF000, 12),
+	.fm             = REQUEST_MEMBER(0, 0x03000000, 24),
+	.pc             = REQUEST_MEMBER(0, 0x3C000000, 26),
+	.pf             = REQUEST_MEMBER(0, 0xC0000000, 30),
+	.pd             = REQUEST_MEMBER(1, 0x00000001,  0),
+	.ia             = REQUEST_MEMBER(1, 0x00001FFE,  1),
+	.freq           = REQUEST_MEMBER(1, 0x001FE000, 13),
+	.freq_clk_src   = REQUEST_MEMBER(1, 0x00600000, 21),
+};
+
+static const struct rpm_vreg_parts switch_parts_8660 = {
+	.request_len    = 1,
+	.enable_state   = REQUEST_MEMBER(0, 0x00000001,  0),
+	.pd             = REQUEST_MEMBER(0, 0x00000002,  1),
+	.pc             = REQUEST_MEMBER(0, 0x0000003C,  2),
+	.pf             = REQUEST_MEMBER(0, 0x000000C0,  6),
+	.hpm            = REQUEST_MEMBER(0, 0x00000300,  8),
+};
+
+static const struct rpm_vreg_parts ncp_parts_8660 = {
+	.request_len    = 1,
+	.mV             = REQUEST_MEMBER(0, 0x00000FFF,  0),
+	.enable_state   = REQUEST_MEMBER(0, 0x00001000, 12),
+	.comp_mode      = REQUEST_MEMBER(0, 0x00002000, 13),
+	.freq           = REQUEST_MEMBER(0, 0x003FC000, 14),
+};
+
+/*
+ * RPM regulator request formats for MSM8960 and APQ8064
+ */
+static const struct rpm_vreg_parts ldo_parts_8960 = {
+	.request_len    = 2,
+	.uV             = REQUEST_MEMBER(0, 0x007FFFFF,  0),
+	.pd             = REQUEST_MEMBER(0, 0x00800000, 23),
+	.pc             = REQUEST_MEMBER(0, 0x0F000000, 24),
+	.pf             = REQUEST_MEMBER(0, 0xF0000000, 28),
+	.ip             = REQUEST_MEMBER(1, 0x000003FF,  0),
+	.ia             = REQUEST_MEMBER(1, 0x000FFC00, 10),
+	.fm             = REQUEST_MEMBER(1, 0x00700000, 20),
+};
+
+static const struct rpm_vreg_parts smps_parts_8960 = {
+	.request_len    = 2,
+	.uV             = REQUEST_MEMBER(0, 0x007FFFFF,  0),
+	.pd             = REQUEST_MEMBER(0, 0x00800000, 23),
+	.pc             = REQUEST_MEMBER(0, 0x0F000000, 24),
+	.pf             = REQUEST_MEMBER(0, 0xF0000000, 28),
+	.ip             = REQUEST_MEMBER(1, 0x000003FF,  0),
+	.ia             = REQUEST_MEMBER(1, 0x000FFC00, 10),
+	.fm             = REQUEST_MEMBER(1, 0x00700000, 20),
+	.pm             = REQUEST_MEMBER(1, 0x00800000, 23),
+	.freq           = REQUEST_MEMBER(1, 0x1F000000, 24),
+	.freq_clk_src   = REQUEST_MEMBER(1, 0x60000000, 29),
+};
+
+static const struct rpm_vreg_parts switch_parts_8960 = {
+	.request_len    = 1,
+	.enable_state   = REQUEST_MEMBER(0, 0x00000001,  0),
+	.pd             = REQUEST_MEMBER(0, 0x00000002,  1),
+	.pc             = REQUEST_MEMBER(0, 0x0000003C,  2),
+	.pf             = REQUEST_MEMBER(0, 0x000003C0,  6),
+	.hpm            = REQUEST_MEMBER(0, 0x00000C00, 10),
+};
+
+static const struct rpm_vreg_parts ncp_parts_8960 = {
+	.request_len    = 1,
+	.uV             = REQUEST_MEMBER(0, 0x007FFFFF,  0),
+	.enable_state   = REQUEST_MEMBER(0, 0x00800000, 23),
+	.comp_mode      = REQUEST_MEMBER(0, 0x01000000, 24),
+	.freq           = REQUEST_MEMBER(0, 0x3E000000, 25),
+};
+
+static const struct msm_rpm_reg msm8960_ldo16 = {
+	.resource = MSM_RPM_PM8921_L16,
+
+	.desc.name = "pm8921_ldo16",
+	.ranges = pldo_ranges,
+	.n_ranges = ARRAY_SIZE(pldo_ranges),
+	.parts = &ldo_parts_8960,
+	.hpm_min_load = RPM_VREG_8960_LDO_300_HPM_MIN_LOAD,
+};
+
+static const struct msm_rpm_reg msm8960_ldo17 = {
+	.resource = MSM_RPM_PM8921_L17,
+
+	.desc.name = "pm8921_ldo17",
+	.ranges = pldo_ranges,
+	.n_ranges = ARRAY_SIZE(pldo_ranges),
+	.parts = &ldo_parts_8960,
+	.hpm_min_load = RPM_VREG_8960_LDO_300_HPM_MIN_LOAD,
+};
+
+static const struct msm_rpm_reg msm8960_ldo29 = {
+	.resource = MSM_RPM_PM8921_L29,
+
+	.desc.name = "pm8921_ldo29",
+	.ranges = pldo_ranges,
+	.n_ranges = ARRAY_SIZE(pldo_ranges),
+	.parts = &ldo_parts_8960,
+	.hpm_min_load = RPM_VREG_8960_LDO_300_HPM_MIN_LOAD,
+};
+
+static const struct of_device_id rpm_of_match[] = {
+	{ .compatible = "qcom,msm8960-regulator-l16", .data = &msm8960_ldo16 },
+	{ .compatible = "qcom,apq8064-regulator-l17", .data = &msm8960_ldo17 },
+	{ .compatible = "qcom,apq8064-regulator-l29", .data = &msm8960_ldo29 },
+};
+MODULE_DEVICE_TABLE(of, rpm_of_match);
+
+static int rpm_reg_write(struct msm_rpm_reg *vreg,
+			 const struct request_member *req,
+			 const int value)
+{
+	vreg->val[req->word] &= ~req->mask;
+	vreg->val[req->word] |= value << req->shift;
+
+	return msm_rpm_write(vreg->dev->parent,
+			     vreg->resource,
+			     vreg->val,
+			     vreg->parts->request_len);
+}
+
+static int rpm_reg_enable(struct regulator_dev *rdev)
+{
+	struct msm_rpm_reg *vreg = rdev_get_drvdata(rdev);
+	const struct rpm_vreg_parts *parts = vreg->parts;
+	int ret;
+
+	mutex_lock(&vreg->lock);
+	ret = rpm_reg_write(vreg, &parts->uV, vreg->uV);
+	if (!ret)
+		vreg->is_enabled = 1;
+	mutex_unlock(&vreg->lock);
+
+	return ret;
+}
+
+static int rpm_reg_is_enabled(struct regulator_dev *rdev)
+{
+	struct msm_rpm_reg *vreg = rdev_get_drvdata(rdev);
+
+	return vreg->is_enabled;
+}
+
+static int rpm_reg_disable(struct regulator_dev *rdev)
+{
+	struct msm_rpm_reg *vreg = rdev_get_drvdata(rdev);
+	const struct rpm_vreg_parts *parts = vreg->parts;
+	int ret;
+
+	mutex_lock(&vreg->lock);
+	ret = rpm_reg_write(vreg, &parts->uV, 0);
+	if (!ret)
+		vreg->is_enabled = 0;
+	mutex_unlock(&vreg->lock);
+
+	return ret;
+}
+
+static int rpm_reg_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
+			       unsigned *selector)
+{
+	struct msm_rpm_reg *vreg = rdev_get_drvdata(rdev);
+	const struct rpm_vreg_parts *parts = vreg->parts;
+	const struct vreg_range *range = NULL;
+	int ret = 0;
+	int uV;
+	int i;
+
+	dev_dbg(vreg->dev, "set_voltage(%d, %d)\n", min_uV, max_uV);
+
+	/*
+	 * Snap to the voltage to a supported level.
+	 */
+	for (i = 0; i < vreg->n_ranges; i++) {
+		range = &vreg->ranges[i];
+		if (min_uV <= range->max_uV && max_uV >= range->min_uV)
+			break;
+	}
+
+	if (i == vreg->n_ranges) {
+		dev_err(vreg->dev,
+			"requested voltage %d-%d outside possible ranges\n",
+			min_uV, max_uV);
+		return -EINVAL;
+	}
+
+	if (min_uV < range->min_uV)
+		uV = range->min_uV;
+	else
+		uV = min_uV;
+
+	uV = roundup(uV, range->step_uV);
+
+	dev_dbg(vreg->dev, "snapped voltage %duV\n", uV);
+
+	/*
+	 * Update the register.
+	 */
+	mutex_lock(&vreg->lock);
+	vreg->uV = uV;
+	if (vreg->is_enabled)
+		ret = rpm_reg_write(vreg, &parts->uV, vreg->uV);
+	mutex_unlock(&vreg->lock);
+
+	return ret;
+}
+
+static int rpm_reg_get_voltage(struct regulator_dev *rdev)
+{
+	struct msm_rpm_reg *vreg = rdev_get_drvdata(rdev);
+	return vreg->uV;
+}
+
+static struct regulator_ops ldo_ops = {
+	.enable = rpm_reg_enable,
+	.disable = rpm_reg_disable,
+	.is_enabled = rpm_reg_is_enabled,
+
+	.set_voltage = rpm_reg_set_voltage,
+	.get_voltage = rpm_reg_get_voltage,
+};
+
+static int rpm_reg_probe(struct platform_device *pdev)
+{
+	struct regulator_init_data *initdata;
+	const struct msm_rpm_reg *template;
+	const struct of_device_id *match;
+	struct regulator_config config = { };
+	struct regulator_desc *desc;
+	struct regulator_dev *rdev;
+	struct msm_rpm_reg *vreg;
+
+	match = of_match_device(rpm_of_match, &pdev->dev);
+	template = match->data;
+
+	initdata = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+	if (!initdata)
+		return -EINVAL;
+
+	vreg = devm_kmalloc(&pdev->dev, sizeof(*vreg), GFP_KERNEL);
+	if (!vreg) {
+		dev_err(&pdev->dev, "failed to allocate vreg\n");
+		return -ENOMEM;
+	}
+	memcpy(vreg, template, sizeof(*vreg));
+
+	mutex_init(&vreg->lock);
+	vreg->dev = &pdev->dev;
+
+	/* XXX:
+	 * tighten constraints of initdata
+	 * round min_uV and max_uV to step values
+	 */
+
+	desc = &vreg->desc;
+	desc->id = -1;
+	desc->ops = &ldo_ops;
+	desc->owner = THIS_MODULE;
+	desc->type = REGULATOR_VOLTAGE;
+
+	config.dev = &pdev->dev;
+	config.init_data = initdata;
+	config.driver_data = vreg;
+	config.of_node = pdev->dev.of_node;
+        rdev = devm_regulator_register(&pdev->dev, desc, &config);
+	if (IS_ERR(rdev)) {
+		dev_err(&pdev->dev, "can't register regulator\n");
+		return PTR_ERR(rdev);
+	}
+
+	platform_set_drvdata(pdev, rdev);
+
+	return 0;
+}
+
+static int rpm_reg_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static struct platform_driver rpm_reg_driver = {
+	.probe          = rpm_reg_probe,
+	.remove         = rpm_reg_remove,
+	.driver  = {
+		.name  = "msm_rpm_reg",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(rpm_of_match),
+	},
+};
+
+static int __init rpm_reg_init(void)
+{
+	return platform_driver_register(&rpm_reg_driver);
+}
+arch_initcall(rpm_reg_init);
+
+static void __exit rpm_reg_exit(void)
+{
+	platform_driver_unregister(&rpm_reg_driver);
+}
+module_exit(rpm_reg_exit)
+
+MODULE_DESCRIPTION("MSM RPM regulator driver");
+MODULE_LICENSE("GPLv2");
+
-- 
1.8.2.2

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

end of thread, other threads:[~2014-04-22 18:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-22 18:20 [RFC WIP 0/2] Qualcomm family A RPM driver and example client Bjorn Andersson
2014-04-22 18:20 ` [RFC WIP 1/2] mfd: msm_rpm: Initial driver for the Qualcomm RPM Bjorn Andersson
2014-04-22 18:20 ` [RFC WIP 2/2] regulator: msm_rpm: Initial regulator driver for " Bjorn Andersson

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).