Merge commit 'AU_LINUX_ANDROID_ICS.04.00.04.00.126' into msm-3.4

AU_LINUX_ANDROID_ICS.04.00.04.00.126 from msm-3.0.
First parent is from google/android-3.4.

* commit 'AU_LINUX_ANDROID_ICS.04.00.04.00.126': (8712 commits)
  PRNG: Device tree entry for qrng device.
  vidc:1080p: Set video core timeout value for Thumbnail mode
  msm: sps: improve the debugging support in SPS driver
  board-8064 msm: Overlap secure and non secure video firmware heaps.
  msm: clock: Add handoff ops for 7x30 and copper XO clocks
  msm_fb: display: Wait for external vsync before DTV IOMMU unmap
  msm: Fix ciruclar dependency in debug UART settings
  msm: gdsc: Add GDSC regulator driver for msm-copper
  defconfig: Enable Mobicore Driver.
  mobicore: Add mobicore driver.
  mobicore: rename variable to lower case.
  mobicore: rename folder.
  mobicore: add makefiles
  mobicore: initial import of kernel driver
  ASoC: msm: Add SLIMBUS_2_RX CPU DAI
  board-8064-gpio: Update FUNC for EPM SPI CS
  msm_fb: display: Remove chicken bit config during video playback
  mmc: msm_sdcc: enable the sanitize capability
  msm-fb: display: lm2 writeback support on mpq platfroms
  msm_fb: display: Disable LVDS phy & pll during panel off
  ...

Signed-off-by: Steve Muckle <smuckle@codeaurora.org>
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 8c8377d..fc0d02a 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -94,6 +94,23 @@
 
 	  If unsure, say Y.
 
+config RTC_INTF_ALARM
+	bool "Android alarm driver"
+	depends on RTC_CLASS
+	default y
+	help
+	  Provides non-wakeup and rtc backed wakeup alarms based on rtc or
+	  elapsed realtime, and a non-wakeup alarm on the monotonic clock.
+	  Also provides an interface to set the wall time which must be used
+	  for elapsed realtime to work.
+
+config RTC_INTF_ALARM_DEV
+	bool "Android alarm device"
+	depends on RTC_INTF_ALARM
+	default y
+	help
+	  Exports the alarm interface to user-space.
+
 config RTC_INTF_DEV_UIE_EMUL
 	bool "RTC UIE emulation on dev interface"
 	depends on RTC_INTF_DEV
@@ -106,6 +123,24 @@
 	  clock several times per second, please enable this option
 	  only if you know that you really need it.
 
+config RTC_INTF_ALARM
+	bool "Android alarm driver"
+	depends on RTC_CLASS
+	default y
+	help
+	  Provides non-wakeup and rtc backed wakeup alarms based on rtc or
+	  elapsed realtime, and a non-wakeup alarm on the monotonic clock.
+	  Also provides an interface to set the wall time which must be used
+	  for elapsed realtime to work.
+
+config RTC_INTF_ALARM_DEV
+	bool "Android alarm device"
+	depends on RTC_INTF_ALARM
+	default y
+	help
+	  Exports the alarm interface to user-space.
+
+
 config RTC_DRV_TEST
 	tristate "Test driver/device"
 	help
@@ -728,6 +763,37 @@
 
 comment "on-CPU RTC drivers"
 
+config RTC_DRV_MSM
+	tristate "RTC on Qualcomm Chipsets"
+	depends on ARCH_MSM
+	default y
+	help
+	  RTC driver for Qualcomm chipsets
+
+
+config RTC_SECURE_TIME_SUPPORT
+        bool "Support for secure time on Qualcomm Chipsets"
+        depends on RTC_DRV_MSM = y
+        default y
+        help
+          Say yes here to have additional handle for reading secure time
+          maintained by ARM9.
+
+config RTC_ASYNC_MODEM_SUPPORT
+	bool "Support for time update on async modem boot"
+        depends on RTC_DRV_MSM && (ARCH_MSM8X60 || ARCH_QSD8X50)
+	default n
+	help
+	 Say yes here to have the system time updated if there is
+	 an asynchronous MODEM boot.
+
+config RTC_DRV_MSM7X00A
+	tristate "MSM7X00A"
+	depends on ARCH_MSM
+	default n
+	help
+	  RTC driver for Qualcomm MSM7K chipsets
+
 config RTC_DRV_DAVINCI
 	tristate "TI DaVinci RTC"
 	depends on ARCH_DAVINCI_DM365
@@ -738,6 +804,13 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-davinci.
 
+config RTC_DRV_MSM7X00A
+	tristate "MSM7X00A"
+	depends on ARCH_MSM
+	default y
+	help
+	  RTC driver for Qualcomm MSM7K chipsets
+
 config RTC_DRV_OMAP
 	tristate "TI OMAP1"
 	depends on ARCH_OMAP15XX || ARCH_OMAP16XX || ARCH_OMAP730 || ARCH_DAVINCI_DA8XX
@@ -1077,6 +1150,15 @@
 	  This drive can also be built as a module. If so, the module
 	  will be called rtc-puv3.
 
+config RTC_DRV_PM8XXX
+	tristate "Qualcomm PMIC8XXX RTC"
+	depends on MFD_PM8XXX
+	help
+	  Say Y here if you want to support the Qualcomm PMIC8XXX RTC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called rtc-pm8xxx.
+
 config RTC_DRV_LOONGSON1
 	tristate "loongson1 RTC support"
 	depends on MACH_LOONGSON1
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 727ae77..8a3cecd 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -9,6 +9,8 @@
 obj-$(CONFIG_RTC_CLASS)		+= rtc-core.o
 rtc-core-y			:= class.o interface.o
 
+obj-$(CONFIG_RTC_INTF_ALARM) += alarm.o
+obj-$(CONFIG_RTC_INTF_ALARM_DEV) += alarm-dev.o
 rtc-core-$(CONFIG_RTC_INTF_DEV)	+= rtc-dev.o
 rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
 rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
@@ -67,6 +69,8 @@
 obj-$(CONFIG_RTC_DRV_MAX8998)	+= rtc-max8998.o
 obj-$(CONFIG_RTC_DRV_MAX6902)	+= rtc-max6902.o
 obj-$(CONFIG_RTC_DRV_MC13XXX)	+= rtc-mc13xxx.o
+obj-$(CONFIG_RTC_DRV_MSM)	+= rtc-msm.o
+obj-$(CONFIG_RTC_DRV_MSM7X00A)	+= rtc-msm7x00a.o
 obj-$(CONFIG_RTC_DRV_MSM6242)	+= rtc-msm6242.o
 obj-$(CONFIG_RTC_DRV_MPC5121)	+= rtc-mpc5121.o
 obj-$(CONFIG_RTC_DRV_MV)	+= rtc-mv.o
@@ -77,6 +81,7 @@
 obj-$(CONFIG_RTC_DRV_PCF8583)	+= rtc-pcf8583.o
 obj-$(CONFIG_RTC_DRV_PCF2123)	+= rtc-pcf2123.o
 obj-$(CONFIG_RTC_DRV_PCF50633)	+= rtc-pcf50633.o
+obj-$(CONFIG_RTC_DRV_PM8XXX)    += rtc-pm8xxx.o
 obj-$(CONFIG_RTC_DRV_PL030)	+= rtc-pl030.o
 obj-$(CONFIG_RTC_DRV_PL031)	+= rtc-pl031.o
 obj-$(CONFIG_RTC_DRV_PM8XXX)	+= rtc-pm8xxx.o
diff --git a/drivers/rtc/alarm-dev.c b/drivers/rtc/alarm-dev.c
new file mode 100644
index 0000000..bfcaebc
--- /dev/null
+++ b/drivers/rtc/alarm-dev.c
@@ -0,0 +1,287 @@
+/* drivers/rtc/alarm-dev.c
+ *
+ * Copyright (C) 2007-2009 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/android_alarm.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/wakelock.h>
+
+#include <asm/mach/time.h>
+
+#define ANDROID_ALARM_PRINT_INFO (1U << 0)
+#define ANDROID_ALARM_PRINT_IO (1U << 1)
+#define ANDROID_ALARM_PRINT_INT (1U << 2)
+
+static int debug_mask = ANDROID_ALARM_PRINT_INFO;
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define pr_alarm(debug_level_mask, args...) \
+	do { \
+		if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \
+			pr_info(args); \
+		} \
+	} while (0)
+
+#define ANDROID_ALARM_WAKEUP_MASK ( \
+	ANDROID_ALARM_RTC_WAKEUP_MASK | \
+	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
+
+/* support old usespace code */
+#define ANDROID_ALARM_SET_OLD               _IOW('a', 2, time_t) /* set alarm */
+#define ANDROID_ALARM_SET_AND_WAIT_OLD      _IOW('a', 3, time_t)
+
+static int alarm_opened;
+static DEFINE_SPINLOCK(alarm_slock);
+static struct wake_lock alarm_wake_lock;
+static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue);
+static uint32_t alarm_pending;
+static uint32_t alarm_enabled;
+static uint32_t wait_pending;
+
+static struct alarm alarms[ANDROID_ALARM_TYPE_COUNT];
+
+static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int rv = 0;
+	unsigned long flags;
+	struct timespec new_alarm_time;
+	struct timespec new_rtc_time;
+	struct timespec tmp_time;
+	enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
+	uint32_t alarm_type_mask = 1U << alarm_type;
+
+	if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
+		return -EINVAL;
+
+	if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
+		if ((file->f_flags & O_ACCMODE) == O_RDONLY)
+			return -EPERM;
+		if (file->private_data == NULL &&
+		    cmd != ANDROID_ALARM_SET_RTC) {
+			spin_lock_irqsave(&alarm_slock, flags);
+			if (alarm_opened) {
+				spin_unlock_irqrestore(&alarm_slock, flags);
+				return -EBUSY;
+			}
+			alarm_opened = 1;
+			file->private_data = (void *)1;
+			spin_unlock_irqrestore(&alarm_slock, flags);
+		}
+	}
+
+	switch (ANDROID_ALARM_BASE_CMD(cmd)) {
+	case ANDROID_ALARM_CLEAR(0):
+		spin_lock_irqsave(&alarm_slock, flags);
+		pr_alarm(IO, "alarm %d clear\n", alarm_type);
+		alarm_try_to_cancel(&alarms[alarm_type]);
+		if (alarm_pending) {
+			alarm_pending &= ~alarm_type_mask;
+			if (!alarm_pending && !wait_pending)
+				wake_unlock(&alarm_wake_lock);
+		}
+		alarm_enabled &= ~alarm_type_mask;
+		spin_unlock_irqrestore(&alarm_slock, flags);
+		break;
+
+	case ANDROID_ALARM_SET_OLD:
+	case ANDROID_ALARM_SET_AND_WAIT_OLD:
+		if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
+			rv = -EFAULT;
+			goto err1;
+		}
+		new_alarm_time.tv_nsec = 0;
+		goto from_old_alarm_set;
+
+	case ANDROID_ALARM_SET_AND_WAIT(0):
+	case ANDROID_ALARM_SET(0):
+		if (copy_from_user(&new_alarm_time, (void __user *)arg,
+		    sizeof(new_alarm_time))) {
+			rv = -EFAULT;
+			goto err1;
+		}
+from_old_alarm_set:
+		spin_lock_irqsave(&alarm_slock, flags);
+		pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type,
+			new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
+		alarm_enabled |= alarm_type_mask;
+		alarm_start_range(&alarms[alarm_type],
+			timespec_to_ktime(new_alarm_time),
+			timespec_to_ktime(new_alarm_time));
+		spin_unlock_irqrestore(&alarm_slock, flags);
+		if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
+		    && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
+			break;
+		/* fall though */
+	case ANDROID_ALARM_WAIT:
+		spin_lock_irqsave(&alarm_slock, flags);
+		pr_alarm(IO, "alarm wait\n");
+		if (!alarm_pending && wait_pending) {
+			wake_unlock(&alarm_wake_lock);
+			wait_pending = 0;
+		}
+		spin_unlock_irqrestore(&alarm_slock, flags);
+		rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
+		if (rv)
+			goto err1;
+		spin_lock_irqsave(&alarm_slock, flags);
+		rv = alarm_pending;
+		wait_pending = 1;
+		alarm_pending = 0;
+		spin_unlock_irqrestore(&alarm_slock, flags);
+		break;
+	case ANDROID_ALARM_SET_RTC:
+		if (copy_from_user(&new_rtc_time, (void __user *)arg,
+		    sizeof(new_rtc_time))) {
+			rv = -EFAULT;
+			goto err1;
+		}
+		rv = alarm_set_rtc(new_rtc_time);
+		spin_lock_irqsave(&alarm_slock, flags);
+		alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
+		wake_up(&alarm_wait_queue);
+		spin_unlock_irqrestore(&alarm_slock, flags);
+		if (rv < 0)
+			goto err1;
+		break;
+	case ANDROID_ALARM_GET_TIME(0):
+		switch (alarm_type) {
+		case ANDROID_ALARM_RTC_WAKEUP:
+		case ANDROID_ALARM_RTC:
+			getnstimeofday(&tmp_time);
+			break;
+		case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
+		case ANDROID_ALARM_ELAPSED_REALTIME:
+			tmp_time =
+				ktime_to_timespec(alarm_get_elapsed_realtime());
+			break;
+		case ANDROID_ALARM_TYPE_COUNT:
+		case ANDROID_ALARM_SYSTEMTIME:
+			ktime_get_ts(&tmp_time);
+			break;
+		}
+		if (copy_to_user((void __user *)arg, &tmp_time,
+		    sizeof(tmp_time))) {
+			rv = -EFAULT;
+			goto err1;
+		}
+		break;
+
+	default:
+		rv = -EINVAL;
+		goto err1;
+	}
+err1:
+	return rv;
+}
+
+static int alarm_open(struct inode *inode, struct file *file)
+{
+	file->private_data = NULL;
+	return 0;
+}
+
+static int alarm_release(struct inode *inode, struct file *file)
+{
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&alarm_slock, flags);
+	if (file->private_data != 0) {
+		for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
+			uint32_t alarm_type_mask = 1U << i;
+			if (alarm_enabled & alarm_type_mask) {
+				pr_alarm(INFO, "alarm_release: clear alarm, "
+					"pending %d\n",
+					!!(alarm_pending & alarm_type_mask));
+				alarm_enabled &= ~alarm_type_mask;
+			}
+			spin_unlock_irqrestore(&alarm_slock, flags);
+			alarm_cancel(&alarms[i]);
+			spin_lock_irqsave(&alarm_slock, flags);
+		}
+		if (alarm_pending | wait_pending) {
+			if (alarm_pending)
+				pr_alarm(INFO, "alarm_release: clear "
+					"pending alarms %x\n", alarm_pending);
+			wake_unlock(&alarm_wake_lock);
+			wait_pending = 0;
+			alarm_pending = 0;
+		}
+		alarm_opened = 0;
+	}
+	spin_unlock_irqrestore(&alarm_slock, flags);
+	return 0;
+}
+
+static void alarm_triggered(struct alarm *alarm)
+{
+	unsigned long flags;
+	uint32_t alarm_type_mask = 1U << alarm->type;
+
+	pr_alarm(INT, "alarm_triggered type %d\n", alarm->type);
+	spin_lock_irqsave(&alarm_slock, flags);
+	if (alarm_enabled & alarm_type_mask) {
+		wake_lock_timeout(&alarm_wake_lock, 5 * HZ);
+		alarm_enabled &= ~alarm_type_mask;
+		alarm_pending |= alarm_type_mask;
+		wake_up(&alarm_wait_queue);
+	}
+	spin_unlock_irqrestore(&alarm_slock, flags);
+}
+
+static const struct file_operations alarm_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = alarm_ioctl,
+	.open = alarm_open,
+	.release = alarm_release,
+};
+
+static struct miscdevice alarm_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "alarm",
+	.fops = &alarm_fops,
+};
+
+static int __init alarm_dev_init(void)
+{
+	int err;
+	int i;
+
+	err = misc_register(&alarm_device);
+	if (err)
+		return err;
+
+	for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++)
+		alarm_init(&alarms[i], i, alarm_triggered);
+	wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm");
+
+	return 0;
+}
+
+static void  __exit alarm_dev_exit(void)
+{
+	misc_deregister(&alarm_device);
+	wake_lock_destroy(&alarm_wake_lock);
+}
+
+module_init(alarm_dev_init);
+module_exit(alarm_dev_exit);
+
diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c
new file mode 100644
index 0000000..9340af7
--- /dev/null
+++ b/drivers/rtc/alarm.c
@@ -0,0 +1,615 @@
+/* drivers/rtc/alarm.c
+ *
+ * Copyright (C) 2007-2009 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/android_alarm.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/wakelock.h>
+
+#include <asm/mach/time.h>
+
+#define ANDROID_ALARM_PRINT_ERROR (1U << 0)
+#define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1)
+#define ANDROID_ALARM_PRINT_TSET (1U << 2)
+#define ANDROID_ALARM_PRINT_CALL (1U << 3)
+#define ANDROID_ALARM_PRINT_SUSPEND (1U << 4)
+#define ANDROID_ALARM_PRINT_INT (1U << 5)
+#define ANDROID_ALARM_PRINT_FLOW (1U << 6)
+
+static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \
+			ANDROID_ALARM_PRINT_INIT_STATUS;
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define pr_alarm(debug_level_mask, args...) \
+	do { \
+		if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \
+			pr_info(args); \
+		} \
+	} while (0)
+
+#define ANDROID_ALARM_WAKEUP_MASK ( \
+	ANDROID_ALARM_RTC_WAKEUP_MASK | \
+	ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
+
+/* support old usespace code */
+#define ANDROID_ALARM_SET_OLD               _IOW('a', 2, time_t) /* set alarm */
+#define ANDROID_ALARM_SET_AND_WAIT_OLD      _IOW('a', 3, time_t)
+
+struct alarm_queue {
+	struct rb_root alarms;
+	struct rb_node *first;
+	struct hrtimer timer;
+	ktime_t delta;
+	bool stopped;
+	ktime_t stopped_time;
+};
+
+static struct rtc_device *alarm_rtc_dev;
+static DEFINE_SPINLOCK(alarm_slock);
+static DEFINE_MUTEX(alarm_setrtc_mutex);
+static struct wake_lock alarm_rtc_wake_lock;
+static struct platform_device *alarm_platform_dev;
+struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT];
+static bool suspended;
+
+static void update_timer_locked(struct alarm_queue *base, bool head_removed)
+{
+	struct alarm *alarm;
+	bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] ||
+			base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
+
+	if (base->stopped) {
+		pr_alarm(FLOW, "changed alarm while setting the wall time\n");
+		return;
+	}
+
+	if (is_wakeup && !suspended && head_removed)
+		wake_unlock(&alarm_rtc_wake_lock);
+
+	if (!base->first)
+		return;
+
+	alarm = container_of(base->first, struct alarm, node);
+
+	pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n",
+		alarm->type, alarm->function, ktime_to_ns(alarm->expires));
+
+	if (is_wakeup && suspended) {
+		pr_alarm(FLOW, "changed alarm while suspened\n");
+		wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
+		return;
+	}
+
+	hrtimer_try_to_cancel(&base->timer);
+	base->timer.node.expires = ktime_add(base->delta, alarm->expires);
+	base->timer._softexpires = ktime_add(base->delta, alarm->softexpires);
+	hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS);
+}
+
+static void alarm_enqueue_locked(struct alarm *alarm)
+{
+	struct alarm_queue *base = &alarms[alarm->type];
+	struct rb_node **link = &base->alarms.rb_node;
+	struct rb_node *parent = NULL;
+	struct alarm *entry;
+	int leftmost = 1;
+	bool was_first = false;
+
+	pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n",
+		alarm->type, alarm->function, ktime_to_ns(alarm->expires));
+
+	if (base->first == &alarm->node) {
+		base->first = rb_next(&alarm->node);
+		was_first = true;
+	}
+	if (!RB_EMPTY_NODE(&alarm->node)) {
+		rb_erase(&alarm->node, &base->alarms);
+		RB_CLEAR_NODE(&alarm->node);
+	}
+
+	while (*link) {
+		parent = *link;
+		entry = rb_entry(parent, struct alarm, node);
+		/*
+		* We dont care about collisions. Nodes with
+		* the same expiry time stay together.
+		*/
+		if (alarm->expires.tv64 < entry->expires.tv64) {
+			link = &(*link)->rb_left;
+		} else {
+			link = &(*link)->rb_right;
+			leftmost = 0;
+		}
+	}
+	if (leftmost)
+		base->first = &alarm->node;
+	if (leftmost || was_first)
+		update_timer_locked(base, was_first);
+
+	rb_link_node(&alarm->node, parent, link);
+	rb_insert_color(&alarm->node, &base->alarms);
+}
+
+/**
+ * alarm_init - initialize an alarm
+ * @alarm:	the alarm to be initialized
+ * @type:	the alarm type to be used
+ * @function:	alarm callback function
+ */
+void alarm_init(struct alarm *alarm,
+	enum android_alarm_type type, void (*function)(struct alarm *))
+{
+	RB_CLEAR_NODE(&alarm->node);
+	alarm->type = type;
+	alarm->function = function;
+
+	pr_alarm(FLOW, "created alarm, type %d, func %pF\n", type, function);
+}
+
+
+/**
+ * alarm_start_range - (re)start an alarm
+ * @alarm:	the alarm to be added
+ * @start:	earliest expiry time
+ * @end:	expiry time
+ */
+void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&alarm_slock, flags);
+	alarm->softexpires = start;
+	alarm->expires = end;
+	alarm_enqueue_locked(alarm);
+	spin_unlock_irqrestore(&alarm_slock, flags);
+}
+
+/**
+ * alarm_try_to_cancel - try to deactivate an alarm
+ * @alarm:	alarm to stop
+ *
+ * Returns:
+ *  0 when the alarm was not active
+ *  1 when the alarm was active
+ * -1 when the alarm may currently be excuting the callback function and
+ *    cannot be stopped (it may also be inactive)
+ */
+int alarm_try_to_cancel(struct alarm *alarm)
+{
+	struct alarm_queue *base = &alarms[alarm->type];
+	unsigned long flags;
+	bool first = false;
+	int ret = 0;
+
+	spin_lock_irqsave(&alarm_slock, flags);
+	if (!RB_EMPTY_NODE(&alarm->node)) {
+		pr_alarm(FLOW, "canceled alarm, type %d, func %pF at %lld\n",
+			alarm->type, alarm->function,
+			ktime_to_ns(alarm->expires));
+		ret = 1;
+		if (base->first == &alarm->node) {
+			base->first = rb_next(&alarm->node);
+			first = true;
+		}
+		rb_erase(&alarm->node, &base->alarms);
+		RB_CLEAR_NODE(&alarm->node);
+		if (first)
+			update_timer_locked(base, true);
+	} else
+		pr_alarm(FLOW, "tried to cancel alarm, type %d, func %pF\n",
+			alarm->type, alarm->function);
+	spin_unlock_irqrestore(&alarm_slock, flags);
+	if (!ret && hrtimer_callback_running(&base->timer))
+		ret = -1;
+	return ret;
+}
+
+/**
+ * alarm_cancel - cancel an alarm and wait for the handler to finish.
+ * @alarm:	the alarm to be cancelled
+ *
+ * Returns:
+ *  0 when the alarm was not active
+ *  1 when the alarm was active
+ */
+int alarm_cancel(struct alarm *alarm)
+{
+	for (;;) {
+		int ret = alarm_try_to_cancel(alarm);
+		if (ret >= 0)
+			return ret;
+		cpu_relax();
+	}
+}
+
+/**
+ * alarm_set_rtc - set the kernel and rtc walltime
+ * @new_time:	timespec value containing the new time
+ */
+int alarm_set_rtc(struct timespec new_time)
+{
+	int i;
+	int ret;
+	unsigned long flags;
+	struct rtc_time rtc_new_rtc_time;
+	struct timespec tmp_time;
+
+	rtc_time_to_tm(new_time.tv_sec, &rtc_new_rtc_time);
+
+	pr_alarm(TSET, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
+		new_time.tv_sec, new_time.tv_nsec,
+		rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min,
+		rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1,
+		rtc_new_rtc_time.tm_mday,
+		rtc_new_rtc_time.tm_year + 1900);
+
+	mutex_lock(&alarm_setrtc_mutex);
+	spin_lock_irqsave(&alarm_slock, flags);
+	wake_lock(&alarm_rtc_wake_lock);
+	getnstimeofday(&tmp_time);
+	for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
+		hrtimer_try_to_cancel(&alarms[i].timer);
+		alarms[i].stopped = true;
+		alarms[i].stopped_time = timespec_to_ktime(tmp_time);
+	}
+	alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
+		alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
+		ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta,
+			timespec_to_ktime(timespec_sub(tmp_time, new_time)));
+	spin_unlock_irqrestore(&alarm_slock, flags);
+	ret = do_settimeofday(&new_time);
+	spin_lock_irqsave(&alarm_slock, flags);
+	for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
+		alarms[i].stopped = false;
+		update_timer_locked(&alarms[i], false);
+	}
+	spin_unlock_irqrestore(&alarm_slock, flags);
+	if (ret < 0) {
+		pr_alarm(ERROR, "alarm_set_rtc: Failed to set time\n");
+		goto err;
+	}
+	if (!alarm_rtc_dev) {
+		pr_alarm(ERROR,
+			"alarm_set_rtc: no RTC, time will be lost on reboot\n");
+		goto err;
+	}
+	ret = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);
+	if (ret < 0)
+		pr_alarm(ERROR, "alarm_set_rtc: "
+			"Failed to set RTC, time will be lost on reboot\n");
+err:
+	wake_unlock(&alarm_rtc_wake_lock);
+	mutex_unlock(&alarm_setrtc_mutex);
+	return ret;
+}
+
+
+void
+alarm_update_timedelta(struct timespec tmp_time, struct timespec new_time)
+{
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&alarm_slock, flags);
+	for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
+		hrtimer_try_to_cancel(&alarms[i].timer);
+		alarms[i].stopped = true;
+		alarms[i].stopped_time = timespec_to_ktime(tmp_time);
+	}
+	alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
+		alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
+		ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta,
+			timespec_to_ktime(timespec_sub(tmp_time, new_time)));
+	for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
+		alarms[i].stopped = false;
+		update_timer_locked(&alarms[i], false);
+	}
+	spin_unlock_irqrestore(&alarm_slock, flags);
+}
+
+/**
+ * alarm_get_elapsed_realtime - get the elapsed real time in ktime_t format
+ *
+ * returns the time in ktime_t format
+ */
+ktime_t alarm_get_elapsed_realtime(void)
+{
+	ktime_t now;
+	unsigned long flags;
+	struct alarm_queue *base = &alarms[ANDROID_ALARM_ELAPSED_REALTIME];
+
+	spin_lock_irqsave(&alarm_slock, flags);
+	now = base->stopped ? base->stopped_time : ktime_get_real();
+	now = ktime_sub(now, base->delta);
+	spin_unlock_irqrestore(&alarm_slock, flags);
+	return now;
+}
+
+static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer)
+{
+	struct alarm_queue *base;
+	struct alarm *alarm;
+	unsigned long flags;
+	ktime_t now;
+
+	spin_lock_irqsave(&alarm_slock, flags);
+
+	base = container_of(timer, struct alarm_queue, timer);
+	now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer);
+	now = ktime_sub(now, base->delta);
+
+	pr_alarm(INT, "alarm_timer_triggered type %d at %lld\n",
+		base - alarms, ktime_to_ns(now));
+
+	while (base->first) {
+		alarm = container_of(base->first, struct alarm, node);
+		if (alarm->softexpires.tv64 > now.tv64) {
+			pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n",
+				alarm->function, ktime_to_ns(alarm->expires),
+				ktime_to_ns(alarm->softexpires));
+			break;
+		}
+		base->first = rb_next(&alarm->node);
+		rb_erase(&alarm->node, &base->alarms);
+		RB_CLEAR_NODE(&alarm->node);
+		pr_alarm(CALL, "call alarm, type %d, func %pF, %lld (s %lld)\n",
+			alarm->type, alarm->function,
+			ktime_to_ns(alarm->expires),
+			ktime_to_ns(alarm->softexpires));
+		spin_unlock_irqrestore(&alarm_slock, flags);
+		alarm->function(alarm);
+		spin_lock_irqsave(&alarm_slock, flags);
+	}
+	if (!base->first)
+		pr_alarm(FLOW, "no more alarms of type %d\n", base - alarms);
+	update_timer_locked(base, true);
+	spin_unlock_irqrestore(&alarm_slock, flags);
+	return HRTIMER_NORESTART;
+}
+
+static void alarm_triggered_func(void *p)
+{
+	struct rtc_device *rtc = alarm_rtc_dev;
+	if (!(rtc->irq_data & RTC_AF))
+		return;
+	pr_alarm(INT, "rtc alarm triggered\n");
+	wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
+}
+
+static int alarm_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	int                 err = 0;
+	unsigned long       flags;
+	struct rtc_wkalrm   rtc_alarm;
+	struct rtc_time     rtc_current_rtc_time;
+	unsigned long       rtc_current_time;
+	unsigned long       rtc_alarm_time;
+	struct timespec     rtc_delta;
+	struct timespec     wall_time;
+	struct alarm_queue *wakeup_queue = NULL;
+	struct alarm_queue *tmp_queue = NULL;
+
+	pr_alarm(SUSPEND, "alarm_suspend(%p, %d)\n", pdev, state.event);
+
+	spin_lock_irqsave(&alarm_slock, flags);
+	suspended = true;
+	spin_unlock_irqrestore(&alarm_slock, flags);
+
+	hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer);
+	hrtimer_cancel(&alarms[
+			ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].timer);
+
+	tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP];
+	if (tmp_queue->first)
+		wakeup_queue = tmp_queue;
+	tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
+	if (tmp_queue->first && (!wakeup_queue ||
+				hrtimer_get_expires(&tmp_queue->timer).tv64 <
+				hrtimer_get_expires(&wakeup_queue->timer).tv64))
+		wakeup_queue = tmp_queue;
+	if (wakeup_queue) {
+		rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
+		getnstimeofday(&wall_time);
+		rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
+		set_normalized_timespec(&rtc_delta,
+					wall_time.tv_sec - rtc_current_time,
+					wall_time.tv_nsec);
+
+		rtc_alarm_time = timespec_sub(ktime_to_timespec(
+			hrtimer_get_expires(&wakeup_queue->timer)),
+			rtc_delta).tv_sec;
+
+		rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time);
+		rtc_alarm.enabled = 1;
+		rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
+		rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
+		rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
+		pr_alarm(SUSPEND,
+			"rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n",
+			rtc_alarm_time, rtc_current_time,
+			rtc_delta.tv_sec, rtc_delta.tv_nsec);
+		if (rtc_current_time + 1 >= rtc_alarm_time) {
+			pr_alarm(SUSPEND, "alarm about to go off\n");
+			memset(&rtc_alarm, 0, sizeof(rtc_alarm));
+			rtc_alarm.enabled = 0;
+			rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
+
+			spin_lock_irqsave(&alarm_slock, flags);
+			suspended = false;
+			wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ);
+			update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP],
+									false);
+			update_timer_locked(&alarms[
+				ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false);
+			err = -EBUSY;
+			spin_unlock_irqrestore(&alarm_slock, flags);
+		}
+	}
+	return err;
+}
+
+static int alarm_resume(struct platform_device *pdev)
+{
+	struct rtc_wkalrm alarm;
+	unsigned long       flags;
+
+	pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev);
+
+	memset(&alarm, 0, sizeof(alarm));
+	alarm.enabled = 0;
+	rtc_set_alarm(alarm_rtc_dev, &alarm);
+
+	spin_lock_irqsave(&alarm_slock, flags);
+	suspended = false;
+	update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false);
+	update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP],
+									false);
+	spin_unlock_irqrestore(&alarm_slock, flags);
+
+	return 0;
+}
+
+static struct rtc_task alarm_rtc_task = {
+	.func = alarm_triggered_func
+};
+
+static int rtc_alarm_add_device(struct device *dev,
+				struct class_interface *class_intf)
+{
+	int err;
+	struct rtc_device *rtc = to_rtc_device(dev);
+
+	mutex_lock(&alarm_setrtc_mutex);
+
+	if (alarm_rtc_dev) {
+		err = -EBUSY;
+		goto err1;
+	}
+
+	alarm_platform_dev =
+		platform_device_register_simple("alarm", -1, NULL, 0);
+	if (IS_ERR(alarm_platform_dev)) {
+		err = PTR_ERR(alarm_platform_dev);
+		goto err2;
+	}
+	err = rtc_irq_register(rtc, &alarm_rtc_task);
+	if (err)
+		goto err3;
+	alarm_rtc_dev = rtc;
+	pr_alarm(INIT_STATUS, "using rtc device, %s, for alarms", rtc->name);
+	mutex_unlock(&alarm_setrtc_mutex);
+
+	return 0;
+
+err3:
+	platform_device_unregister(alarm_platform_dev);
+err2:
+err1:
+	mutex_unlock(&alarm_setrtc_mutex);
+	return err;
+}
+
+static void rtc_alarm_remove_device(struct device *dev,
+				    struct class_interface *class_intf)
+{
+	if (dev == &alarm_rtc_dev->dev) {
+		pr_alarm(INIT_STATUS, "lost rtc device for alarms");
+		rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task);
+		platform_device_unregister(alarm_platform_dev);
+		alarm_rtc_dev = NULL;
+	}
+}
+
+static struct class_interface rtc_alarm_interface = {
+	.add_dev = &rtc_alarm_add_device,
+	.remove_dev = &rtc_alarm_remove_device,
+};
+
+static struct platform_driver alarm_driver = {
+	.suspend = alarm_suspend,
+	.resume = alarm_resume,
+	.driver = {
+		.name = "alarm"
+	}
+};
+
+static int __init alarm_late_init(void)
+{
+	unsigned long   flags;
+	struct timespec tmp_time, system_time;
+
+	/* this needs to run after the rtc is read at boot */
+	spin_lock_irqsave(&alarm_slock, flags);
+	/* We read the current rtc and system time so we can later calulate
+	 * elasped realtime to be (boot_systemtime + rtc - boot_rtc) ==
+	 * (rtc - (boot_rtc - boot_systemtime))
+	 */
+	getnstimeofday(&tmp_time);
+	ktime_get_ts(&system_time);
+	alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta =
+		alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta =
+			timespec_to_ktime(timespec_sub(tmp_time, system_time));
+
+	spin_unlock_irqrestore(&alarm_slock, flags);
+	return 0;
+}
+
+static int __init alarm_driver_init(void)
+{
+	int err;
+	int i;
+
+	for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
+		hrtimer_init(&alarms[i].timer,
+				CLOCK_REALTIME, HRTIMER_MODE_ABS);
+		alarms[i].timer.function = alarm_timer_triggered;
+	}
+	hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].timer,
+		     CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
+	alarms[ANDROID_ALARM_SYSTEMTIME].timer.function = alarm_timer_triggered;
+	err = platform_driver_register(&alarm_driver);
+	if (err < 0)
+		goto err1;
+	wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc");
+	rtc_alarm_interface.class = rtc_class;
+	err = class_interface_register(&rtc_alarm_interface);
+	if (err < 0)
+		goto err2;
+
+	return 0;
+
+err2:
+	wake_lock_destroy(&alarm_rtc_wake_lock);
+	platform_driver_unregister(&alarm_driver);
+err1:
+	return err;
+}
+
+static void  __exit alarm_exit(void)
+{
+	class_interface_unregister(&rtc_alarm_interface);
+	wake_lock_destroy(&alarm_rtc_wake_lock);
+	platform_driver_unregister(&alarm_driver);
+}
+
+late_initcall(alarm_late_init);
+module_init(alarm_driver_init);
+module_exit(alarm_exit);
+
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
index bc90b09..29735c2 100644
--- a/drivers/rtc/hctosys.c
+++ b/drivers/rtc/hctosys.c
@@ -24,7 +24,7 @@
 
 int rtc_hctosys_ret = -ENODEV;
 
-static int __init rtc_hctosys(void)
+int rtc_hctosys(void)
 {
 	int err = -ENODEV;
 	struct rtc_time tm;
diff --git a/drivers/rtc/rtc-msm.c b/drivers/rtc/rtc-msm.c
new file mode 100644
index 0000000..c17e461
--- /dev/null
+++ b/drivers/rtc/rtc-msm.c
@@ -0,0 +1,819 @@
+/*
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (c) 2009-2011 Code Aurora Forum. All rights reserved.
+ * Author: San Mehat <san@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/version.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/android_alarm.h>
+
+#include <linux/rtc.h>
+#include <linux/rtc-msm.h>
+#include <linux/msm_rpcrouter.h>
+#include <mach/msm_rpcrouter.h>
+
+#define APP_TIMEREMOTE_PDEV_NAME "rs00000000"
+
+#define TIMEREMOTE_PROCEEDURE_SET_JULIAN	6
+#define TIMEREMOTE_PROCEEDURE_GET_JULIAN	7
+#ifdef CONFIG_RTC_SECURE_TIME_SUPPORT
+#define TIMEREMOTE_PROCEEDURE_GET_SECURE_JULIAN	11
+#define TIMEREMOTE_PROCEEDURE_SET_SECURE_JULIAN	16
+#endif
+#define TIMEREMOTE_PROG_NUMBER 0x30000048
+#define TIMEREMOTE_PROG_VER_1 0x00010001
+#define TIMEREMOTE_PROG_VER_2 0x00040001
+
+#define RTC_REQUEST_CB_PROC		0x17
+#define RTC_CLIENT_INIT_PROC		0x12
+#define RTC_EVENT_CB_PROC		0x1
+#define RTC_CB_ID			0x1
+
+/* Client request errors */
+enum rtc_rpc_err {
+	ERR_NONE,
+	ERR_CLIENT_ID_PTR,		/* Invalid client ID pointer */
+	ERR_CLIENT_TYPE,		/* Invalid client type */
+	ERR_CLIENT_ID,			/* Invalid client ID */
+	ERR_TASK_NOT_READY,		/* task is not ready for clients */
+	ERR_INVALID_PROCESSOR,		/* Invalid processor id */
+	ERR_UNSUPPORTED,		/* Unsupported request */
+	ERR_GENERAL,			/* Any General Error */
+	ERR_RPC,			/* Any ONCRPC Error */
+	ERR_ALREADY_REG,		/* Client already registered */
+	ERR_MAX
+};
+
+enum processor_type {
+	CLIENT_PROCESSOR_NONE   = 0,
+	CLIENT_PROCESSOR_MODEM,
+	CLIENT_PROCESSOR_APP1,
+	CLIENT_PROCESSOR_APP2,
+	CLIENT_PROCESSOR_MAX
+};
+
+/* Client types */
+enum client_type {
+	CLIENT_TYPE_GEN1 = 0,
+	CLIENT_FLOATING1,
+	CLIENT_FLOATING2,
+	CLIENT_TYPE_INTERNAL,
+	CLIENT_TYPE_GENOFF_UPDATE,
+	CLIENT_TYPE_MAX
+};
+
+/* Event types */
+enum event_type {
+	EVENT_TOD_CHANGE = 0,
+	EVENT_GENOFF_CHANGE,
+	EVENT_MAX
+};
+
+struct tod_update_info {
+	uint32_t	tick;
+	uint64_t	stamp;
+	uint32_t	freq;
+};
+
+enum time_bases_info {
+	TIME_RTC = 0,
+	TIME_TOD,
+	TIME_USER,
+	TIME_SECURE,
+	TIME_INVALID
+};
+
+struct genoff_update_info {
+	enum time_bases_info time_base;
+	uint64_t	offset;
+};
+
+union cb_info {
+	struct tod_update_info tod_update;
+	struct genoff_update_info genoff_update;
+};
+
+struct rtc_cb_recv {
+	uint32_t client_cb_id;
+	enum event_type event;
+	uint32_t cb_info_ptr;
+	union cb_info cb_info_data;
+};
+
+struct msm_rtc {
+	int proc;
+	struct msm_rpc_client *rpc_client;
+	u8 client_id;
+	struct rtc_device *rtc;
+#ifdef CONFIG_RTC_SECURE_TIME_SUPPORT
+	struct rtc_device *rtcsecure;
+#endif
+	unsigned long rtcalarm_time;
+};
+
+struct rpc_time_julian {
+	uint32_t year;
+	uint32_t month;
+	uint32_t day;
+	uint32_t hour;
+	uint32_t minute;
+	uint32_t second;
+	uint32_t day_of_week;
+};
+
+struct rtc_tod_args {
+	int proc;
+	struct rtc_time *tm;
+};
+
+#ifdef CONFIG_PM
+struct suspend_state_info {
+	atomic_t state;
+	int64_t tick_at_suspend;
+};
+
+static struct suspend_state_info suspend_state = {ATOMIC_INIT(0), 0};
+
+void msmrtc_updateatsuspend(struct timespec *ts)
+{
+	int64_t now, sleep, sclk_max;
+
+	if (atomic_read(&suspend_state.state)) {
+		now = msm_timer_get_sclk_time(&sclk_max);
+
+		if (now && suspend_state.tick_at_suspend) {
+			if (now < suspend_state.tick_at_suspend) {
+				sleep = sclk_max -
+					suspend_state.tick_at_suspend + now;
+			} else
+				sleep = now - suspend_state.tick_at_suspend;
+
+			timespec_add_ns(ts, sleep);
+			suspend_state.tick_at_suspend = now;
+		} else
+			pr_err("%s: Invalid ticks from SCLK now=%lld"
+				"tick_at_suspend=%lld", __func__, now,
+				suspend_state.tick_at_suspend);
+	}
+
+}
+#else
+void msmrtc_updateatsuspend(struct timespec *ts) { }
+#endif
+EXPORT_SYMBOL(msmrtc_updateatsuspend);
+
+static int msmrtc_tod_proc_args(struct msm_rpc_client *client, void *buff,
+							void *data)
+{
+	struct rtc_tod_args *rtc_args = data;
+
+	if ((rtc_args->proc == TIMEREMOTE_PROCEEDURE_SET_JULIAN)
+#ifdef CONFIG_RTC_SECURE_TIME_SUPPORT
+	|| (rtc_args->proc == TIMEREMOTE_PROCEEDURE_SET_SECURE_JULIAN)
+#endif
+	) {
+		struct timeremote_set_julian_req {
+			uint32_t opt_arg;
+			struct rpc_time_julian time;
+		};
+		struct timeremote_set_julian_req *set_req = buff;
+
+		set_req->opt_arg = cpu_to_be32(0x1);
+		set_req->time.year = cpu_to_be32(rtc_args->tm->tm_year);
+		set_req->time.month = cpu_to_be32(rtc_args->tm->tm_mon + 1);
+		set_req->time.day = cpu_to_be32(rtc_args->tm->tm_mday);
+		set_req->time.hour = cpu_to_be32(rtc_args->tm->tm_hour);
+		set_req->time.minute = cpu_to_be32(rtc_args->tm->tm_min);
+		set_req->time.second = cpu_to_be32(rtc_args->tm->tm_sec);
+		set_req->time.day_of_week = cpu_to_be32(rtc_args->tm->tm_wday);
+
+		return sizeof(*set_req);
+
+	} else if ((rtc_args->proc == TIMEREMOTE_PROCEEDURE_GET_JULIAN)
+#ifdef CONFIG_RTC_SECURE_TIME_SUPPORT
+	|| (rtc_args->proc == TIMEREMOTE_PROCEEDURE_GET_SECURE_JULIAN)
+#endif
+	) {
+		*(uint32_t *)buff = (uint32_t) cpu_to_be32(0x1);
+
+		return sizeof(uint32_t);
+	} else
+		return 0;
+}
+
+static bool rtc_check_overflow(struct rtc_time *tm)
+{
+	if (tm->tm_year < 138)
+		return false;
+
+	if (tm->tm_year > 138)
+		return true;
+
+	if ((tm->tm_year == 138) && (tm->tm_mon == 0) && (tm->tm_mday < 19))
+		return false;
+
+	return true;
+}
+
+static int msmrtc_tod_proc_result(struct msm_rpc_client *client, void *buff,
+							void *data)
+{
+	struct rtc_tod_args *rtc_args = data;
+
+	if ((rtc_args->proc == TIMEREMOTE_PROCEEDURE_GET_JULIAN)
+#ifdef CONFIG_RTC_SECURE_TIME_SUPPORT
+	|| (rtc_args->proc == TIMEREMOTE_PROCEEDURE_GET_SECURE_JULIAN)
+#endif
+	)  {
+		struct timeremote_get_julian_rep {
+			uint32_t opt_arg;
+			struct rpc_time_julian time;
+		};
+		struct timeremote_get_julian_rep *result = buff;
+
+		if (be32_to_cpu(result->opt_arg) != 0x1)
+			return -ENODATA;
+
+		rtc_args->tm->tm_year = be32_to_cpu(result->time.year);
+		rtc_args->tm->tm_mon = be32_to_cpu(result->time.month);
+		rtc_args->tm->tm_mday = be32_to_cpu(result->time.day);
+		rtc_args->tm->tm_hour = be32_to_cpu(result->time.hour);
+		rtc_args->tm->tm_min = be32_to_cpu(result->time.minute);
+		rtc_args->tm->tm_sec = be32_to_cpu(result->time.second);
+		rtc_args->tm->tm_wday = be32_to_cpu(result->time.day_of_week);
+
+		pr_debug("%s: %.2u/%.2u/%.4u %.2u:%.2u:%.2u (%.2u)\n",
+			__func__, rtc_args->tm->tm_mon, rtc_args->tm->tm_mday,
+			rtc_args->tm->tm_year, rtc_args->tm->tm_hour,
+			rtc_args->tm->tm_min, rtc_args->tm->tm_sec,
+			rtc_args->tm->tm_wday);
+
+		/* RTC layer expects years to start at 1900 */
+		rtc_args->tm->tm_year -= 1900;
+		/* RTC layer expects mons to be 0 based */
+		rtc_args->tm->tm_mon--;
+
+		if (rtc_valid_tm(rtc_args->tm) < 0) {
+			pr_err("%s: Retrieved data/time not valid\n", __func__);
+			rtc_time_to_tm(0, rtc_args->tm);
+		}
+
+		/*
+		 * Check if the time received is > 01-19-2038, to prevent
+		 * overflow. In such a case, return the EPOCH time.
+		 */
+		if (rtc_check_overflow(rtc_args->tm) == true) {
+			pr_err("Invalid time (year > 2038)\n");
+			rtc_time_to_tm(0, rtc_args->tm);
+		}
+
+		return 0;
+	} else
+		return 0;
+}
+
+static int
+msmrtc_timeremote_set_time(struct device *dev, struct rtc_time *tm)
+{
+	int rc;
+	struct rtc_tod_args rtc_args;
+	struct msm_rtc *rtc_pdata = dev_get_drvdata(dev);
+
+	if (tm->tm_year < 1900)
+		tm->tm_year += 1900;
+
+	if (tm->tm_year < 1970)
+		return -EINVAL;
+
+	dev_dbg(dev, "%s: %.2u/%.2u/%.4u %.2u:%.2u:%.2u (%.2u)\n",
+	       __func__, tm->tm_mon, tm->tm_mday, tm->tm_year,
+	       tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
+
+	rtc_args.proc = TIMEREMOTE_PROCEEDURE_SET_JULIAN;
+	rtc_args.tm = tm;
+	rc = msm_rpc_client_req(rtc_pdata->rpc_client,
+				TIMEREMOTE_PROCEEDURE_SET_JULIAN,
+				msmrtc_tod_proc_args, &rtc_args,
+				NULL, NULL, -1);
+	if (rc) {
+		dev_err(dev, "%s: rtc time (TOD) could not be set\n", __func__);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int
+msmrtc_timeremote_read_time(struct device *dev, struct rtc_time *tm)
+{
+	int rc;
+	struct rtc_tod_args rtc_args;
+	struct msm_rtc *rtc_pdata = dev_get_drvdata(dev);
+
+	rtc_args.proc = TIMEREMOTE_PROCEEDURE_GET_JULIAN;
+	rtc_args.tm = tm;
+
+	rc = msm_rpc_client_req(rtc_pdata->rpc_client,
+				TIMEREMOTE_PROCEEDURE_GET_JULIAN,
+				msmrtc_tod_proc_args, &rtc_args,
+				msmrtc_tod_proc_result, &rtc_args, -1);
+
+	if (rc) {
+		dev_err(dev, "%s: Error retrieving rtc (TOD) time\n", __func__);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int
+msmrtc_virtual_alarm_set(struct device *dev, struct rtc_wkalrm *a)
+{
+	struct msm_rtc *rtc_pdata = dev_get_drvdata(dev);
+	unsigned long now = get_seconds();
+
+	if (!a->enabled) {
+		rtc_pdata->rtcalarm_time = 0;
+		return 0;
+	} else
+		rtc_tm_to_time(&a->time, &(rtc_pdata->rtcalarm_time));
+
+	if (now > rtc_pdata->rtcalarm_time) {
+		dev_err(dev, "%s: Attempt to set alarm in the past\n",
+		       __func__);
+		rtc_pdata->rtcalarm_time = 0;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct rtc_class_ops msm_rtc_ops = {
+	.read_time	= msmrtc_timeremote_read_time,
+	.set_time	= msmrtc_timeremote_set_time,
+	.set_alarm	= msmrtc_virtual_alarm_set,
+};
+
+#ifdef CONFIG_RTC_SECURE_TIME_SUPPORT
+static int
+msmrtc_timeremote_set_time_secure(struct device *dev, struct rtc_time *tm)
+{
+	int rc;
+	struct rtc_tod_args rtc_args;
+	struct msm_rtc *rtc_pdata = dev_get_drvdata(dev);
+
+	if (tm->tm_year < 1900)
+		tm->tm_year += 1900;
+
+	if (tm->tm_year < 1970)
+		return -EINVAL;
+
+	dev_dbg(dev, "%s: %.2u/%.2u/%.4u %.2u:%.2u:%.2u (%.2u)\n",
+	       __func__, tm->tm_mon, tm->tm_mday, tm->tm_year,
+	       tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
+
+	rtc_args.proc = TIMEREMOTE_PROCEEDURE_SET_SECURE_JULIAN;
+	rtc_args.tm = tm;
+
+	rc = msm_rpc_client_req(rtc_pdata->rpc_client,
+			TIMEREMOTE_PROCEEDURE_SET_SECURE_JULIAN,
+				msmrtc_tod_proc_args, &rtc_args,
+				NULL, NULL, -1);
+	if (rc) {
+		dev_err(dev,
+			"%s: rtc secure time could not be set\n", __func__);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int
+msmrtc_timeremote_read_time_secure(struct device *dev, struct rtc_time *tm)
+{
+	int rc;
+	struct rtc_tod_args rtc_args;
+	struct msm_rtc *rtc_pdata = dev_get_drvdata(dev);
+	rtc_args.proc = TIMEREMOTE_PROCEEDURE_GET_SECURE_JULIAN;
+	rtc_args.tm = tm;
+
+	rc = msm_rpc_client_req(rtc_pdata->rpc_client,
+		TIMEREMOTE_PROCEEDURE_GET_SECURE_JULIAN, msmrtc_tod_proc_args,
+		&rtc_args, msmrtc_tod_proc_result, &rtc_args, -1);
+
+	if (rc) {
+		dev_err(dev,
+			"%s: Error retrieving secure rtc time\n", __func__);
+		return rc;
+	}
+
+	return 0;
+}
+
+static struct rtc_class_ops msm_rtc_ops_secure = {
+	.read_time	= msmrtc_timeremote_read_time_secure,
+	.set_time	= msmrtc_timeremote_set_time_secure,
+};
+#endif
+
+static void process_cb_request(void *buffer)
+{
+	struct rtc_cb_recv *rtc_cb = buffer;
+	struct timespec ts, tv;
+
+	rtc_cb->client_cb_id = be32_to_cpu(rtc_cb->client_cb_id);
+	rtc_cb->event = be32_to_cpu(rtc_cb->event);
+	rtc_cb->cb_info_ptr = be32_to_cpu(rtc_cb->cb_info_ptr);
+
+	if (rtc_cb->event == EVENT_TOD_CHANGE) {
+		/* A TOD update has been received from the Modem */
+		rtc_cb->cb_info_data.tod_update.tick =
+			be32_to_cpu(rtc_cb->cb_info_data.tod_update.tick);
+		rtc_cb->cb_info_data.tod_update.stamp =
+			be64_to_cpu(rtc_cb->cb_info_data.tod_update.stamp);
+		rtc_cb->cb_info_data.tod_update.freq =
+			be32_to_cpu(rtc_cb->cb_info_data.tod_update.freq);
+		pr_info("RPC CALL -- TOD TIME UPDATE: ttick = %d\n"
+			"stamp=%lld, freq = %d\n",
+			rtc_cb->cb_info_data.tod_update.tick,
+			rtc_cb->cb_info_data.tod_update.stamp,
+			rtc_cb->cb_info_data.tod_update.freq);
+
+		getnstimeofday(&ts);
+		msmrtc_updateatsuspend(&ts);
+		rtc_hctosys();
+		getnstimeofday(&tv);
+		/* Update the alarm information with the new time info. */
+		alarm_update_timedelta(ts, tv);
+
+	} else
+		pr_err("%s: Unknown event EVENT=%x\n",
+					__func__, rtc_cb->event);
+}
+
+static int msmrtc_cb_func(struct msm_rpc_client *client, void *buffer, int size)
+{
+	int rc = -1;
+	struct rpc_request_hdr *recv = buffer;
+
+	recv->xid = be32_to_cpu(recv->xid);
+	recv->type = be32_to_cpu(recv->type);
+	recv->rpc_vers = be32_to_cpu(recv->rpc_vers);
+	recv->prog = be32_to_cpu(recv->prog);
+	recv->vers = be32_to_cpu(recv->vers);
+	recv->procedure = be32_to_cpu(recv->procedure);
+
+	if (recv->procedure == RTC_EVENT_CB_PROC)
+		process_cb_request((void *) (recv + 1));
+
+	msm_rpc_start_accepted_reply(client, recv->xid,
+				RPC_ACCEPTSTAT_SUCCESS);
+
+	rc = msm_rpc_send_accepted_reply(client, 0);
+	if (rc) {
+		pr_debug("%s: sending reply failed: %d\n", __func__, rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int msmrtc_rpc_proc_args(struct msm_rpc_client *client, void *buff,
+							void *data)
+{
+	struct msm_rtc *rtc_pdata = data;
+
+	if (rtc_pdata->proc == RTC_CLIENT_INIT_PROC) {
+		/* arguments passed to the client_init function */
+		struct rtc_client_init_req {
+			enum client_type client;
+			uint32_t client_id_ptr;
+			u8 client_id;
+			enum processor_type processor;
+		};
+		struct rtc_client_init_req *req_1 = buff;
+
+		req_1->client = cpu_to_be32(CLIENT_TYPE_INTERNAL);
+		req_1->client_id_ptr = cpu_to_be32(0x1);
+		req_1->client_id = (u8) cpu_to_be32(0x1);
+		req_1->processor = cpu_to_be32(CLIENT_PROCESSOR_APP1);
+
+		return sizeof(*req_1);
+
+	} else if (rtc_pdata->proc == RTC_REQUEST_CB_PROC) {
+		/* arguments passed to the request_cb function */
+		struct rtc_event_req {
+			u8 client_id;
+			uint32_t rtc_cb_id;
+		};
+		struct rtc_event_req *req_2 = buff;
+
+		req_2->client_id =  (u8) cpu_to_be32(rtc_pdata->client_id);
+		req_2->rtc_cb_id = cpu_to_be32(RTC_CB_ID);
+
+		return sizeof(*req_2);
+	} else
+		return 0;
+}
+
+static int msmrtc_rpc_proc_result(struct msm_rpc_client *client, void *buff,
+							void *data)
+{
+	uint32_t result = -EINVAL;
+	struct msm_rtc *rtc_pdata = data;
+
+	if (rtc_pdata->proc == RTC_CLIENT_INIT_PROC) {
+		/* process reply received from client_init function */
+		uint32_t client_id_ptr;
+		result = be32_to_cpu(*(uint32_t *)buff);
+		buff += sizeof(uint32_t);
+		client_id_ptr = be32_to_cpu(*(uint32_t *)(buff));
+		buff += sizeof(uint32_t);
+		if (client_id_ptr == 1)
+			rtc_pdata->client_id = (u8)
+					be32_to_cpu(*(uint32_t *)(buff));
+		else {
+			pr_debug("%s: Client-id not received from Modem\n",
+								__func__);
+			return -EINVAL;
+		}
+	} else if (rtc_pdata->proc == RTC_REQUEST_CB_PROC) {
+		/* process reply received from request_cb function */
+		result = be32_to_cpu(*(uint32_t *)buff);
+	}
+
+	if (result == ERR_NONE) {
+		pr_debug("%s: RPC client reply for PROC=%x success\n",
+					 __func__, rtc_pdata->proc);
+		return 0;
+	}
+
+	pr_debug("%s: RPC client registration failed ERROR=%x\n",
+						__func__, result);
+	return -EINVAL;
+}
+
+static int msmrtc_setup_cb(struct msm_rtc *rtc_pdata)
+{
+	int rc;
+
+	/* Register with the server with client specific info */
+	rtc_pdata->proc = RTC_CLIENT_INIT_PROC;
+	rc = msm_rpc_client_req(rtc_pdata->rpc_client, RTC_CLIENT_INIT_PROC,
+				msmrtc_rpc_proc_args, rtc_pdata,
+				msmrtc_rpc_proc_result, rtc_pdata, -1);
+	if (rc) {
+		pr_debug("%s: RPC client registration for PROC:%x failed\n",
+					__func__, RTC_CLIENT_INIT_PROC);
+		return rc;
+	}
+
+	/* Register with server for the callback event */
+	rtc_pdata->proc = RTC_REQUEST_CB_PROC;
+	rc = msm_rpc_client_req(rtc_pdata->rpc_client, RTC_REQUEST_CB_PROC,
+				msmrtc_rpc_proc_args, rtc_pdata,
+				msmrtc_rpc_proc_result, rtc_pdata, -1);
+	if (rc) {
+		pr_debug("%s: RPC client registration for PROC:%x failed\n",
+					__func__, RTC_REQUEST_CB_PROC);
+	}
+
+	return rc;
+}
+
+static int __devinit
+msmrtc_probe(struct platform_device *pdev)
+{
+	int rc;
+	struct msm_rtc *rtc_pdata = NULL;
+	struct rpcsvr_platform_device *rdev =
+		container_of(pdev, struct rpcsvr_platform_device, base);
+	uint32_t prog_version;
+
+
+	if (pdev->id == (TIMEREMOTE_PROG_VER_1 & RPC_VERSION_MAJOR_MASK))
+		prog_version = TIMEREMOTE_PROG_VER_1;
+	else if (pdev->id == (TIMEREMOTE_PROG_VER_2 &
+			      RPC_VERSION_MAJOR_MASK))
+		prog_version = TIMEREMOTE_PROG_VER_2;
+	else
+		return -EINVAL;
+
+	rtc_pdata = kzalloc(sizeof(*rtc_pdata), GFP_KERNEL);
+	if (rtc_pdata == NULL) {
+		dev_err(&pdev->dev,
+			"%s: Unable to allocate memory\n", __func__);
+		return -ENOMEM;
+	}
+	rtc_pdata->rpc_client = msm_rpc_register_client("rtc", rdev->prog,
+				prog_version, 1, msmrtc_cb_func);
+	if (IS_ERR(rtc_pdata->rpc_client)) {
+		dev_err(&pdev->dev,
+			 "%s: init RPC failed! VERS = %x\n", __func__,
+					prog_version);
+		rc = PTR_ERR(rtc_pdata->rpc_client);
+		kfree(rtc_pdata);
+		return rc;
+	}
+
+	/*
+	 * Set up the callback client.
+	 * For older targets this initialization will fail
+	 */
+	rc = msmrtc_setup_cb(rtc_pdata);
+	if (rc)
+		dev_dbg(&pdev->dev, "%s: Could not initialize RPC callback\n",
+								__func__);
+
+	rtc_pdata->rtcalarm_time = 0;
+	platform_set_drvdata(pdev, rtc_pdata);
+
+	rtc_pdata->rtc = rtc_device_register("msm_rtc",
+				  &pdev->dev,
+				  &msm_rtc_ops,
+				  THIS_MODULE);
+	if (IS_ERR(rtc_pdata->rtc)) {
+		dev_err(&pdev->dev, "%s: Can't register RTC device (%ld)\n",
+		       pdev->name, PTR_ERR(rtc_pdata->rtc));
+		rc = PTR_ERR(rtc_pdata->rtc);
+		goto fail_cb_setup;
+	}
+
+#ifdef CONFIG_RTC_SECURE_TIME_SUPPORT
+	rtc_pdata->rtcsecure = rtc_device_register("msm_rtc_secure",
+				  &pdev->dev,
+				  &msm_rtc_ops_secure,
+				  THIS_MODULE);
+
+	if (IS_ERR(rtc_pdata->rtcsecure)) {
+		dev_err(&pdev->dev,
+			"%s: Can't register RTC Secure device (%ld)\n",
+		       pdev->name, PTR_ERR(rtc_pdata->rtcsecure));
+		rtc_device_unregister(rtc_pdata->rtc);
+		rc = PTR_ERR(rtc_pdata->rtcsecure);
+		goto fail_cb_setup;
+	}
+#endif
+
+#ifdef CONFIG_RTC_ASYNC_MODEM_SUPPORT
+	rtc_hctosys();
+#endif
+
+	return 0;
+
+fail_cb_setup:
+	msm_rpc_unregister_client(rtc_pdata->rpc_client);
+	kfree(rtc_pdata);
+	return rc;
+}
+
+
+#ifdef CONFIG_PM
+
+static void
+msmrtc_alarmtimer_expired(unsigned long _data,
+				struct msm_rtc *rtc_pdata)
+{
+	pr_debug("%s: Generating alarm event (src %lu)\n",
+	       rtc_pdata->rtc->name, _data);
+
+	rtc_update_irq(rtc_pdata->rtc, 1, RTC_IRQF | RTC_AF);
+	rtc_pdata->rtcalarm_time = 0;
+}
+
+static int
+msmrtc_suspend(struct platform_device *dev, pm_message_t state)
+{
+	int rc, diff;
+	struct rtc_time tm;
+	unsigned long now;
+	struct msm_rtc *rtc_pdata = platform_get_drvdata(dev);
+
+	suspend_state.tick_at_suspend = msm_timer_get_sclk_time(NULL);
+	if (rtc_pdata->rtcalarm_time) {
+		rc = msmrtc_timeremote_read_time(&dev->dev, &tm);
+		if (rc) {
+			dev_err(&dev->dev,
+				"%s: Unable to read from RTC\n", __func__);
+			return rc;
+		}
+		rtc_tm_to_time(&tm, &now);
+		diff = rtc_pdata->rtcalarm_time - now;
+		if (diff <= 0) {
+			msmrtc_alarmtimer_expired(1 , rtc_pdata);
+			msm_pm_set_max_sleep_time(0);
+			atomic_inc(&suspend_state.state);
+			return 0;
+		}
+		msm_pm_set_max_sleep_time((int64_t)
+			((int64_t) diff * NSEC_PER_SEC));
+	} else
+		msm_pm_set_max_sleep_time(0);
+	atomic_inc(&suspend_state.state);
+	return 0;
+}
+
+static int
+msmrtc_resume(struct platform_device *dev)
+{
+	int rc, diff;
+	struct rtc_time tm;
+	unsigned long now;
+	struct msm_rtc *rtc_pdata = platform_get_drvdata(dev);
+
+	if (rtc_pdata->rtcalarm_time) {
+		rc = msmrtc_timeremote_read_time(&dev->dev, &tm);
+		if (rc) {
+			dev_err(&dev->dev,
+				"%s: Unable to read from RTC\n", __func__);
+			return rc;
+		}
+		rtc_tm_to_time(&tm, &now);
+		diff = rtc_pdata->rtcalarm_time - now;
+		if (diff <= 0)
+			msmrtc_alarmtimer_expired(2 , rtc_pdata);
+	}
+	suspend_state.tick_at_suspend = 0;
+	atomic_dec(&suspend_state.state);
+	return 0;
+}
+#else
+#define msmrtc_suspend NULL
+#define msmrtc_resume  NULL
+#endif
+
+static int __devexit msmrtc_remove(struct platform_device *pdev)
+{
+	struct msm_rtc *rtc_pdata = platform_get_drvdata(pdev);
+
+	rtc_device_unregister(rtc_pdata->rtc);
+#ifdef CONFIG_RTC_SECURE_TIME_SUPPORT
+	rtc_device_unregister(rtc_pdata->rtcsecure);
+#endif
+	msm_rpc_unregister_client(rtc_pdata->rpc_client);
+	kfree(rtc_pdata);
+
+	return 0;
+}
+
+static struct platform_driver msmrtc_driver = {
+	.probe		= msmrtc_probe,
+	.suspend	= msmrtc_suspend,
+	.resume		= msmrtc_resume,
+	.remove		= __devexit_p(msmrtc_remove),
+	.driver	= {
+		.name	= APP_TIMEREMOTE_PDEV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init msmrtc_init(void)
+{
+	int rc;
+
+	/*
+	 * For backward compatibility, register multiple platform
+	 * drivers with the RPC PROG_VERS to be supported.
+	 *
+	 * Explicit cast away of 'constness' for driver.name in order to
+	 * initialize it here.
+	 */
+	snprintf((char *)msmrtc_driver.driver.name,
+		 strlen(msmrtc_driver.driver.name)+1,
+		 "rs%08x", TIMEREMOTE_PROG_NUMBER);
+	pr_debug("RTC Registering with %s\n", msmrtc_driver.driver.name);
+
+	rc = platform_driver_register(&msmrtc_driver);
+	if (rc)
+		pr_err("%s: platfrom_driver_register failed\n", __func__);
+
+	return rc;
+}
+
+static void __exit msmrtc_exit(void)
+{
+	platform_driver_unregister(&msmrtc_driver);
+}
+
+module_init(msmrtc_init);
+module_exit(msmrtc_exit);
+
+MODULE_DESCRIPTION("RTC driver for Qualcomm MSM7x00a chipsets");
+MODULE_AUTHOR("San Mehat <san@android.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-msm7x00a.c b/drivers/rtc/rtc-msm7x00a.c
new file mode 100644
index 0000000..690bc39
--- /dev/null
+++ b/drivers/rtc/rtc-msm7x00a.c
@@ -0,0 +1,280 @@
+/* drivers/rtc/rtc-msm7x00a.c
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: San Mehat <san@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/version.h>
+
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/rtc.h>
+#include <linux/msm_rpcrouter.h>
+
+#include <mach/msm_rpcrouter.h>
+
+#define RTC_DEBUG 0
+
+extern void msm_pm_set_max_sleep_time(int64_t sleep_time_ns);
+
+#if CONFIG_MSM_AMSS_VERSION >= 6350 || defined(CONFIG_ARCH_QSD8X50)
+#define APP_TIMEREMOTE_PDEV_NAME "rs30000048:00010000"
+#else
+#define APP_TIMEREMOTE_PDEV_NAME "rs30000048:0da5b528"
+#endif
+
+#define TIMEREMOTE_PROCEEDURE_SET_JULIAN	6
+#define TIMEREMOTE_PROCEEDURE_GET_JULIAN	7
+
+struct rpc_time_julian {
+	uint32_t year;
+	uint32_t month;
+	uint32_t day;
+	uint32_t hour;
+	uint32_t minute;
+	uint32_t second;
+	uint32_t day_of_week;
+};
+
+static struct msm_rpc_endpoint *ep;
+static struct rtc_device *rtc;
+static unsigned long rtcalarm_time;
+
+static int
+msmrtc_timeremote_set_time(struct device *dev, struct rtc_time *tm)
+{
+	int rc;
+
+	struct timeremote_set_julian_req {
+		struct rpc_request_hdr hdr;
+		uint32_t opt_arg;
+
+		struct rpc_time_julian time;
+	} req;
+
+	struct timeremote_set_julian_rep {
+		struct rpc_reply_hdr hdr;
+	} rep;
+
+	if (tm->tm_year < 1900)
+		tm->tm_year += 1900;
+
+	if (tm->tm_year < 1970)
+		return -EINVAL;
+
+#if RTC_DEBUG
+	printk(KERN_DEBUG "%s: %.2u/%.2u/%.4u %.2u:%.2u:%.2u (%.2u)\n",
+	       __func__, tm->tm_mon, tm->tm_mday, tm->tm_year,
+	       tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
+#endif
+
+	req.opt_arg = cpu_to_be32(1);
+	req.time.year = cpu_to_be32(tm->tm_year);
+	req.time.month = cpu_to_be32(tm->tm_mon + 1);
+	req.time.day = cpu_to_be32(tm->tm_mday);
+	req.time.hour = cpu_to_be32(tm->tm_hour);
+	req.time.minute = cpu_to_be32(tm->tm_min);
+	req.time.second = cpu_to_be32(tm->tm_sec);
+	req.time.day_of_week = cpu_to_be32(tm->tm_wday);
+
+
+	rc = msm_rpc_call_reply(ep, TIMEREMOTE_PROCEEDURE_SET_JULIAN,
+				&req, sizeof(req),
+				&rep, sizeof(rep),
+				5 * HZ);
+	return rc;
+}
+
+static int
+msmrtc_timeremote_read_time(struct device *dev, struct rtc_time *tm)
+{
+	int rc;
+
+	struct timeremote_get_julian_req {
+		struct rpc_request_hdr hdr;
+		uint32_t julian_time_not_null;
+	} req;
+
+	struct timeremote_get_julian_rep {
+		struct rpc_reply_hdr hdr;
+		uint32_t opt_arg;
+		struct rpc_time_julian time;
+	} rep;
+
+	req.julian_time_not_null = cpu_to_be32(1);
+
+	rc = msm_rpc_call_reply(ep, TIMEREMOTE_PROCEEDURE_GET_JULIAN,
+				&req, sizeof(req),
+				&rep, sizeof(rep),
+				5 * HZ);
+	if (rc < 0)
+		return rc;
+
+	if (!be32_to_cpu(rep.opt_arg)) {
+		printk(KERN_ERR "%s: No data from RTC\n", __func__);
+		return -ENODATA;
+	}
+
+	tm->tm_year = be32_to_cpu(rep.time.year);
+	tm->tm_mon = be32_to_cpu(rep.time.month);
+	tm->tm_mday = be32_to_cpu(rep.time.day);
+	tm->tm_hour = be32_to_cpu(rep.time.hour);
+	tm->tm_min = be32_to_cpu(rep.time.minute);
+	tm->tm_sec = be32_to_cpu(rep.time.second);
+	tm->tm_wday = be32_to_cpu(rep.time.day_of_week);
+
+#if RTC_DEBUG
+	printk(KERN_DEBUG "%s: %.2u/%.2u/%.4u %.2u:%.2u:%.2u (%.2u)\n",
+	       __func__, tm->tm_mon, tm->tm_mday, tm->tm_year,
+	       tm->tm_hour, tm->tm_min, tm->tm_sec, tm->tm_wday);
+#endif
+
+	tm->tm_year -= 1900;	/* RTC layer expects years to start at 1900 */
+	tm->tm_mon--;		/* RTC layer expects mons to be 0 based */
+
+	if (rtc_valid_tm(tm) < 0) {
+		dev_err(dev, "retrieved date/time is not valid.\n");
+		rtc_time_to_tm(0, tm);
+	}
+
+	return 0;
+}
+
+
+static int
+msmrtc_virtual_alarm_set(struct device *dev, struct rtc_wkalrm *a)
+{
+	unsigned long now = get_seconds();
+
+	if (!a->enabled) {
+		rtcalarm_time = 0;
+		return 0;
+	} else
+		rtc_tm_to_time(&a->time, &rtcalarm_time);
+
+	if (now > rtcalarm_time) {
+		printk(KERN_ERR "%s: Attempt to set alarm in the past\n",
+		       __func__);
+		rtcalarm_time = 0;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct rtc_class_ops msm_rtc_ops = {
+	.read_time	= msmrtc_timeremote_read_time,
+	.set_time	= msmrtc_timeremote_set_time,
+	.set_alarm	= msmrtc_virtual_alarm_set,
+};
+
+static void
+msmrtc_alarmtimer_expired(unsigned long _data)
+{
+#if RTC_DEBUG
+	printk(KERN_DEBUG "%s: Generating alarm event (src %lu)\n",
+	       rtc->name, _data);
+#endif
+	rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
+	rtcalarm_time = 0;
+}
+
+static int
+msmrtc_probe(struct platform_device *pdev)
+{
+	struct rpcsvr_platform_device *rdev =
+		container_of(pdev, struct rpcsvr_platform_device, base);
+
+	ep = msm_rpc_connect(rdev->prog, rdev->vers, 0);
+	if (IS_ERR(ep)) {
+		printk(KERN_ERR "%s: init rpc failed! rc = %ld\n",
+		       __func__, PTR_ERR(ep));
+		return PTR_ERR(ep);
+	}
+
+	rtc = rtc_device_register("msm_rtc",
+				  &pdev->dev,
+				  &msm_rtc_ops,
+				  THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		printk(KERN_ERR "%s: Can't register RTC device (%ld)\n",
+		       pdev->name, PTR_ERR(rtc));
+		return PTR_ERR(rtc);
+	}
+	return 0;
+}
+
+
+static unsigned long msmrtc_get_seconds(void)
+{
+	struct rtc_time tm;
+	unsigned long now;
+
+	msmrtc_timeremote_read_time(NULL, &tm);
+	rtc_tm_to_time(&tm, &now);
+	return now;
+}
+
+static int
+msmrtc_suspend(struct platform_device *dev, pm_message_t state)
+{
+	if (rtcalarm_time) {
+		unsigned long now = msmrtc_get_seconds();
+		int diff = rtcalarm_time - now;
+		if (diff <= 0) {
+			msmrtc_alarmtimer_expired(1);
+			msm_pm_set_max_sleep_time(0);
+			return 0;
+		}
+		msm_pm_set_max_sleep_time((int64_t) ((int64_t) diff * NSEC_PER_SEC));
+	} else
+		msm_pm_set_max_sleep_time(0);
+	return 0;
+}
+
+static int
+msmrtc_resume(struct platform_device *dev)
+{
+	if (rtcalarm_time) {
+		unsigned long now = msmrtc_get_seconds();
+		int diff = rtcalarm_time - now;
+		if (diff <= 0)
+			msmrtc_alarmtimer_expired(2);
+	}
+	return 0;
+}
+
+static struct platform_driver msmrtc_driver = {
+	.probe		= msmrtc_probe,
+	.suspend	= msmrtc_suspend,
+	.resume		= msmrtc_resume,
+	.driver	= {
+		.name	= APP_TIMEREMOTE_PDEV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init msmrtc_init(void)
+{
+	rtcalarm_time = 0;
+	return platform_driver_register(&msmrtc_driver);
+}
+
+module_init(msmrtc_init);
+
+MODULE_DESCRIPTION("RTC driver for Qualcomm MSM7x00a chipsets");
+MODULE_AUTHOR("San Mehat <san@android.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index d00bd24..e53374e 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -15,36 +15,31 @@
 #include <linux/rtc.h>
 #include <linux/pm.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
+#include<linux/spinlock.h>
 
 #include <linux/mfd/pm8xxx/core.h>
 #include <linux/mfd/pm8xxx/rtc.h>
 
 
 /* RTC Register offsets from RTC CTRL REG */
-#define PM8XXX_ALARM_CTRL_OFFSET	0x01
-#define PM8XXX_RTC_WRITE_OFFSET		0x02
-#define PM8XXX_RTC_READ_OFFSET		0x06
-#define PM8XXX_ALARM_RW_OFFSET		0x0A
+#define PM8XXX_ALARM_CTRL_OFFSET 0x01
+#define PM8XXX_RTC_WRITE_OFFSET 0x02
+#define PM8XXX_RTC_READ_OFFSET 0x06
+#define PM8XXX_ALARM_RW_OFFSET 0x0A
 
 /* RTC_CTRL register bit fields */
-#define PM8xxx_RTC_ENABLE		BIT(7)
-#define PM8xxx_RTC_ALARM_ENABLE		BIT(1)
-#define PM8xxx_RTC_ALARM_CLEAR		BIT(0)
+#define PM8xxx_RTC_ENABLE	BIT(7)
+#define PM8xxx_RTC_ALARM_ENABLE	BIT(1)
+#define PM8xxx_RTC_ABORT_ENABLE BIT(0)
 
-#define NUM_8_BIT_RTC_REGS		0x4
+#define PM8xxx_RTC_ALARM_CLEAR  BIT(0)
+
+#define NUM_8_BIT_RTC_REGS	0x4
 
 /**
- * struct pm8xxx_rtc -  rtc driver internal structure
- * @rtc:		rtc device for this driver.
- * @rtc_alarm_irq:	rtc alarm irq number.
- * @rtc_base:		address of rtc control register.
- * @rtc_read_base:	base address of read registers.
- * @rtc_write_base:	base address of write registers.
- * @alarm_rw_base:	base address of alarm registers.
- * @ctrl_reg:		rtc control register.
- * @rtc_dev:		device structure.
- * @ctrl_reg_lock:	spinlock protecting access to ctrl_reg.
+ * struct pm8xxx_rtc - rtc driver internal structure
+ * @rtc: rtc device for this driver
+ * @rtc_alarm_irq: rtc alarm irq number
  */
 struct pm8xxx_rtc {
 	struct rtc_device *rtc;
@@ -62,8 +57,9 @@
  * The RTC registers need to be read/written one byte at a time. This is a
  * hardware limitation.
  */
+
 static int pm8xxx_read_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val,
-		int base, int count)
+			int base, int count)
 {
 	int i, rc;
 	struct device *parent = rtc_dd->rtc_dev->parent;
@@ -71,7 +67,7 @@
 	for (i = 0; i < count; i++) {
 		rc = pm8xxx_readb(parent, base + i, &rtc_val[i]);
 		if (rc < 0) {
-			dev_err(rtc_dd->rtc_dev, "PMIC read failed\n");
+			dev_err(rtc_dd->rtc_dev, "PM8xxx read failed\n");
 			return rc;
 		}
 	}
@@ -80,7 +76,7 @@
 }
 
 static int pm8xxx_write_wrapper(struct pm8xxx_rtc *rtc_dd, u8 *rtc_val,
-		int base, int count)
+			int base, int count)
 {
 	int i, rc;
 	struct device *parent = rtc_dd->rtc_dev->parent;
@@ -88,7 +84,7 @@
 	for (i = 0; i < count; i++) {
 		rc = pm8xxx_writeb(parent, base + i, rtc_val[i]);
 		if (rc < 0) {
-			dev_err(rtc_dd->rtc_dev, "PMIC write failed\n");
+			dev_err(rtc_dd->rtc_dev, "PM8xxx write failed\n");
 			return rc;
 		}
 	}
@@ -96,6 +92,7 @@
 	return 0;
 }
 
+
 /*
  * Steps to write the RTC registers.
  * 1. Disable alarm if enabled.
@@ -103,19 +100,20 @@
  * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0].
  * 4. Enable alarm if disabled in step 1.
  */
-static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
+static int
+pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
-	int rc, i;
+	int rc;
 	unsigned long secs, irq_flags;
-	u8 value[NUM_8_BIT_RTC_REGS], reg = 0, alarm_enabled = 0, ctrl_reg;
+	u8 value[4], reg = 0, alarm_enabled = 0, ctrl_reg;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
 
 	rtc_tm_to_time(tm, &secs);
 
-	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
-		value[i] = secs & 0xFF;
-		secs >>= 8;
-	}
+	value[0] = secs & 0xFF;
+	value[1] = (secs >> 8) & 0xFF;
+	value[2] = (secs >> 16) & 0xFF;
+	value[3] = (secs >> 24) & 0xFF;
 
 	dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
 
@@ -126,21 +124,20 @@
 		alarm_enabled = 1;
 		ctrl_reg &= ~PM8xxx_RTC_ALARM_ENABLE;
 		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
-				1);
+									1);
 		if (rc < 0) {
-			dev_err(dev, "Write to RTC control register "
-								"failed\n");
+			dev_err(dev, "PM8xxx write failed\n");
 			goto rtc_rw_fail;
 		}
-		rtc_dd->ctrl_reg = ctrl_reg;
 	} else
 		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
 
+	/* Write Byte[1], Byte[2], Byte[3], Byte[0] */
 	/* Write 0 to Byte[0] */
 	reg = 0;
 	rc = pm8xxx_write_wrapper(rtc_dd, &reg, rtc_dd->rtc_write_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC write data register failed\n");
+		dev_err(dev, "PM8xxx write failed\n");
 		goto rtc_rw_fail;
 	}
 
@@ -148,14 +145,14 @@
 	rc = pm8xxx_write_wrapper(rtc_dd, value + 1,
 					rtc_dd->rtc_write_base + 1, 3);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC write data register failed\n");
+		dev_err(dev, "Write to RTC registers failed\n");
 		goto rtc_rw_fail;
 	}
 
 	/* Write Byte[0] */
 	rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->rtc_write_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC write data register failed\n");
+		dev_err(dev, "Write to RTC register failed\n");
 		goto rtc_rw_fail;
 	}
 
@@ -164,13 +161,13 @@
 		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
 									1);
 		if (rc < 0) {
-			dev_err(dev, "Write to RTC control register "
-								"failed\n");
+			dev_err(dev, "PM8xxx write failed\n");
 			goto rtc_rw_fail;
 		}
-		rtc_dd->ctrl_reg = ctrl_reg;
 	}
 
+	rtc_dd->ctrl_reg = ctrl_reg;
+
 rtc_rw_fail:
 	if (alarm_enabled)
 		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
@@ -178,17 +175,18 @@
 	return rc;
 }
 
-static int pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+static int
+pm8xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	int rc;
-	u8 value[NUM_8_BIT_RTC_REGS], reg;
+	u8 value[4], reg;
 	unsigned long secs;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
 
 	rc = pm8xxx_read_wrapper(rtc_dd, value, rtc_dd->rtc_read_base,
 							NUM_8_BIT_RTC_REGS);
 	if (rc < 0) {
-		dev_err(dev, "RTC read data register failed\n");
+		dev_err(dev, "RTC time read failed\n");
 		return rc;
 	}
 
@@ -198,7 +196,7 @@
 	 */
 	rc = pm8xxx_read_wrapper(rtc_dd, &reg, rtc_dd->rtc_read_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "RTC read data register failed\n");
+		dev_err(dev, "PM8xxx read failed\n");
 		return rc;
 	}
 
@@ -206,76 +204,96 @@
 		rc = pm8xxx_read_wrapper(rtc_dd, value,
 				rtc_dd->rtc_read_base, NUM_8_BIT_RTC_REGS);
 		if (rc < 0) {
-			dev_err(dev, "RTC read data register failed\n");
+			dev_err(dev, "RTC time read failed\n");
 			return rc;
 		}
 	}
 
-	secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
+	secs = value[0] | (value[1] << 8) | (value[2] << 16) \
+						| (value[3] << 24);
 
 	rtc_time_to_tm(secs, tm);
 
 	rc = rtc_valid_tm(tm);
 	if (rc < 0) {
-		dev_err(dev, "Invalid time read from RTC\n");
+		dev_err(dev, "Invalid time read from PM8xxx\n");
 		return rc;
 	}
 
 	dev_dbg(dev, "secs = %lu, h:m:s == %d:%d:%d, d/m/y = %d/%d/%d\n",
-				secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
-				tm->tm_mday, tm->tm_mon, tm->tm_year);
+			secs, tm->tm_hour, tm->tm_min, tm->tm_sec,
+			tm->tm_mday, tm->tm_mon, tm->tm_year);
 
 	return 0;
 }
 
-static int pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int
+pm8xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
-	int rc, i;
-	u8 value[NUM_8_BIT_RTC_REGS], ctrl_reg;
-	unsigned long secs, irq_flags;
+	int rc;
+	u8 value[4], ctrl_reg;
+	unsigned long secs, secs_rtc, irq_flags;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
+	struct rtc_time rtc_tm;
 
 	rtc_tm_to_time(&alarm->time, &secs);
 
-	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
-		value[i] = secs & 0xFF;
-		secs >>= 8;
+	/*
+	 * Read the current RTC time and verify if the alarm time is in the
+	 * past. If yes, return invalid.
+	 */
+	rc = pm8xxx_rtc_read_time(dev, &rtc_tm);
+	if (rc < 0) {
+		dev_err(dev, "Unamble to read RTC time\n");
+		return -EINVAL;
 	}
 
+	rtc_tm_to_time(&rtc_tm, &secs_rtc);
+	if (secs < secs_rtc) {
+		dev_err(dev, "Trying to set alarm in the past\n");
+		return -EINVAL;
+	}
+
+	value[0] = secs & 0xFF;
+	value[1] = (secs >> 8) & 0xFF;
+	value[2] = (secs >> 16) & 0xFF;
+	value[3] = (secs >> 24) & 0xFF;
+
 	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 
 	rc = pm8xxx_write_wrapper(rtc_dd, value, rtc_dd->alarm_rw_base,
 							NUM_8_BIT_RTC_REGS);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC ALARM register failed\n");
+		dev_err(dev, "Write to RTC ALARM registers failed\n");
 		goto rtc_rw_fail;
 	}
 
 	ctrl_reg = rtc_dd->ctrl_reg;
-	ctrl_reg = alarm->enabled ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
+	ctrl_reg = (alarm->enabled) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
 					(ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE);
 
 	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC control register failed\n");
+		dev_err(dev, "PM8xxx write failed\n");
 		goto rtc_rw_fail;
 	}
 
 	rtc_dd->ctrl_reg = ctrl_reg;
 
 	dev_dbg(dev, "Alarm Set for h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
-				alarm->time.tm_hour, alarm->time.tm_min,
-				alarm->time.tm_sec, alarm->time.tm_mday,
-				alarm->time.tm_mon, alarm->time.tm_year);
+			alarm->time.tm_hour, alarm->time.tm_min,
+			alarm->time.tm_sec, alarm->time.tm_mday,
+			alarm->time.tm_mon, alarm->time.tm_year);
 rtc_rw_fail:
 	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
 	return rc;
 }
 
-static int pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+static int
+pm8xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 {
 	int rc;
-	u8 value[NUM_8_BIT_RTC_REGS];
+	u8 value[4];
 	unsigned long secs;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
 
@@ -286,25 +304,28 @@
 		return rc;
 	}
 
-	secs = value[0] | (value[1] << 8) | (value[2] << 16) | (value[3] << 24);
+	secs = value[0] | (value[1] << 8) | (value[2] << 16) | \
+						 (value[3] << 24);
 
 	rtc_time_to_tm(secs, &alarm->time);
 
 	rc = rtc_valid_tm(&alarm->time);
 	if (rc < 0) {
-		dev_err(dev, "Invalid alarm time read from RTC\n");
+		dev_err(dev, "Invalid time read from PM8xxx\n");
 		return rc;
 	}
 
 	dev_dbg(dev, "Alarm set for - h:r:s=%d:%d:%d, d/m/y=%d/%d/%d\n",
-				alarm->time.tm_hour, alarm->time.tm_min,
+		alarm->time.tm_hour, alarm->time.tm_min,
 				alarm->time.tm_sec, alarm->time.tm_mday,
 				alarm->time.tm_mon, alarm->time.tm_year);
 
 	return 0;
 }
 
-static int pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+
+static int
+pm8xxx_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	int rc;
 	unsigned long irq_flags;
@@ -313,12 +334,12 @@
 
 	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 	ctrl_reg = rtc_dd->ctrl_reg;
-	ctrl_reg = (enable) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
+	ctrl_reg = (enabled) ? (ctrl_reg | PM8xxx_RTC_ALARM_ENABLE) :
 				(ctrl_reg & ~PM8xxx_RTC_ALARM_ENABLE);
 
 	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
 	if (rc < 0) {
-		dev_err(dev, "Write to RTC control register failed\n");
+		dev_err(dev, "PM8xxx write failed\n");
 		goto rtc_rw_fail;
 	}
 
@@ -354,8 +375,7 @@
 	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
 	if (rc < 0) {
 		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
-		dev_err(rtc_dd->rtc_dev, "Write to RTC control register "
-								"failed\n");
+		dev_err(rtc_dd->rtc_dev, "PM8xxx write failed!\n");
 		goto rtc_alarm_handled;
 	}
 
@@ -366,8 +386,7 @@
 	rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base +
 						PM8XXX_ALARM_CTRL_OFFSET, 1);
 	if (rc < 0) {
-		dev_err(rtc_dd->rtc_dev, "RTC Alarm control register read "
-								"failed\n");
+		dev_err(rtc_dd->rtc_dev, "PM8xxx write failed!\n");
 		goto rtc_alarm_handled;
 	}
 
@@ -375,8 +394,7 @@
 	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base +
 						PM8XXX_ALARM_CTRL_OFFSET, 1);
 	if (rc < 0)
-		dev_err(rtc_dd->rtc_dev, "Write to RTC Alarm control register"
-								" failed\n");
+		dev_err(rtc_dd->rtc_dev, "PM8xxx write failed!\n");
 
 rtc_alarm_handled:
 	return IRQ_HANDLED;
@@ -390,7 +408,7 @@
 	struct pm8xxx_rtc *rtc_dd;
 	struct resource *rtc_resource;
 	const struct pm8xxx_rtc_platform_data *pdata =
-						dev_get_platdata(&pdev->dev);
+		pdev->dev.platform_data;
 
 	if (pdata != NULL)
 		rtc_write_enable = pdata->rtc_write_enable;
@@ -401,7 +419,7 @@
 		return -ENOMEM;
 	}
 
-	/* Initialise spinlock to protect RTC control register */
+	/* Initialise spinlock to protect RTC cntrol register */
 	spin_lock_init(&rtc_dd->ctrl_reg_lock);
 
 	rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0);
@@ -426,12 +444,12 @@
 	rtc_dd->rtc_read_base = rtc_dd->rtc_base + PM8XXX_RTC_READ_OFFSET;
 	rtc_dd->alarm_rw_base = rtc_dd->rtc_base + PM8XXX_ALARM_RW_OFFSET;
 
-	rtc_dd->rtc_dev = &pdev->dev;
+	rtc_dd->rtc_dev = &(pdev->dev);
 
 	/* Check if the RTC is on, else turn it on */
 	rc = pm8xxx_read_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
 	if (rc < 0) {
-		dev_err(&pdev->dev, "RTC control register read failed!\n");
+		dev_err(&pdev->dev, "PM8xxx read failed!\n");
 		goto fail_rtc_enable;
 	}
 
@@ -440,12 +458,19 @@
 		rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base,
 									1);
 		if (rc < 0) {
-			dev_err(&pdev->dev, "Write to RTC control register "
-								"failed\n");
+			dev_err(&pdev->dev, "PM8xxx write failed!\n");
 			goto fail_rtc_enable;
 		}
 	}
 
+	/* Enable abort enable feature */
+	ctrl_reg |= PM8xxx_RTC_ABORT_ENABLE;
+	rc = pm8xxx_write_wrapper(rtc_dd, &ctrl_reg, rtc_dd->rtc_base, 1);
+	if (rc < 0) {
+		dev_err(&pdev->dev, "PM8xxx write failed!\n");
+		goto fail_rtc_enable;
+	}
+
 	rtc_dd->ctrl_reg = ctrl_reg;
 	if (rtc_write_enable == true)
 		pm8xxx_rtc_ops.set_time = pm8xxx_rtc_set_time;
@@ -485,20 +510,7 @@
 	return rc;
 }
 
-static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev)
-{
-	struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
-
-	device_init_wakeup(&pdev->dev, 0);
-	free_irq(rtc_dd->rtc_alarm_irq, rtc_dd);
-	rtc_device_unregister(rtc_dd->rtc);
-	platform_set_drvdata(pdev, NULL);
-	kfree(rtc_dd);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static int pm8xxx_rtc_resume(struct device *dev)
 {
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
@@ -518,21 +530,87 @@
 
 	return 0;
 }
-#endif
 
-static SIMPLE_DEV_PM_OPS(pm8xxx_rtc_pm_ops, pm8xxx_rtc_suspend, pm8xxx_rtc_resume);
+static const struct dev_pm_ops pm8xxx_rtc_pm_ops = {
+	.suspend = pm8xxx_rtc_suspend,
+	.resume = pm8xxx_rtc_resume,
+};
+#endif
+static int __devexit pm8xxx_rtc_remove(struct platform_device *pdev)
+{
+	struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
+
+	device_init_wakeup(&pdev->dev, 0);
+	free_irq(rtc_dd->rtc_alarm_irq, rtc_dd);
+	rtc_device_unregister(rtc_dd->rtc);
+	platform_set_drvdata(pdev, NULL);
+	kfree(rtc_dd);
+
+	return 0;
+}
+
+static void pm8xxx_rtc_shutdown(struct platform_device *pdev)
+{
+	u8 value[4] = {0, 0, 0, 0};
+	u8 reg;
+	int rc;
+	unsigned long irq_flags;
+	bool rtc_alarm_powerup = false;
+	struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
+	struct pm8xxx_rtc_platform_data *pdata = pdev->dev.platform_data;
+
+	if (pdata != NULL)
+		rtc_alarm_powerup =  pdata->rtc_alarm_powerup;
+
+	if (!rtc_alarm_powerup) {
+
+		spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
+		dev_dbg(&pdev->dev, "Disabling alarm interrupts\n");
+
+		/* Disable RTC alarms */
+		reg = rtc_dd->ctrl_reg;
+		reg &= ~PM8xxx_RTC_ALARM_ENABLE;
+		rc = pm8xxx_write_wrapper(rtc_dd, &reg, rtc_dd->rtc_base, 1);
+		if (rc < 0) {
+			dev_err(rtc_dd->rtc_dev, "PM8xxx write failed\n");
+			goto fail_alarm_disable;
+		}
+
+		/* Clear Alarm register */
+		rc = pm8xxx_write_wrapper(rtc_dd, value,
+				rtc_dd->alarm_rw_base, NUM_8_BIT_RTC_REGS);
+		if (rc < 0)
+			dev_err(rtc_dd->rtc_dev, "PM8xxx write failed\n");
+
+fail_alarm_disable:
+		spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
+	}
+}
 
 static struct platform_driver pm8xxx_rtc_driver = {
 	.probe		= pm8xxx_rtc_probe,
 	.remove		= __devexit_p(pm8xxx_rtc_remove),
+	.shutdown	= pm8xxx_rtc_shutdown,
 	.driver	= {
 		.name	= PM8XXX_RTC_DEV_NAME,
 		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
 		.pm	= &pm8xxx_rtc_pm_ops,
+#endif
 	},
 };
 
-module_platform_driver(pm8xxx_rtc_driver);
+static int __init pm8xxx_rtc_init(void)
+{
+	return platform_driver_register(&pm8xxx_rtc_driver);
+}
+module_init(pm8xxx_rtc_init);
+
+static void __exit pm8xxx_rtc_exit(void)
+{
+	platform_driver_unregister(&pm8xxx_rtc_driver);
+}
+module_exit(pm8xxx_rtc_exit);
 
 MODULE_ALIAS("platform:rtc-pm8xxx");
 MODULE_DESCRIPTION("PMIC8xxx RTC driver");