Ejemplo n.º 1
0
static int handle_rpc_call(struct msm_rpc_server *server,
			   struct rpc_request_hdr *req, unsigned len)
{
	struct timespec ts, tv;
	
	//20110813 [email protected] add period
	int64_t period = 0;

	switch (req->procedure) {
	case RPC_TIME_REMOTE_MTOA_NULL:
		return 0;

	case RPC_TIME_TOD_SET_APPS_BASES: {
		struct rpc_time_tod_set_apps_bases_args *args;
		args = (struct rpc_time_tod_set_apps_bases_args *)(req + 1);
		args->tick = be32_to_cpu(args->tick);
		args->stamp = be64_to_cpu(args->stamp);
		printk(KERN_INFO "RPC_TIME_TOD_SET_APPS_BASES:\n"
		       "\ttick = %d\n"
		       "\tstamp = %lld\n",
		       args->tick, args->stamp);

		getnstimeofday(&ts);
		if (msmrtc_is_suspended()) {
			//20110813 [email protected] add period [START]
			int64_t now, sleep, tick_at_suspend;

			// LGE_UPDATE_S
			//now = msm_timer_get_sclk_time(NULL);
			now = msm_timer_get_sclk_time(&period);
			// LGE_UPDATE_E
			tick_at_suspend = msmrtc_get_tickatsuspend();
			if (now && tick_at_suspend) {
				sleep = now - tick_at_suspend;
				// LGE_UPDATE_S
				if(sleep<0)
					sleep+=period;
				// LGE_UPDATE_E
				timespec_add_ns(&ts, sleep);
			} else
				pr_err("%s: Invalid ticks from SCLK"
					"now=%lld tick_at_suspend=%lld",
					__func__, now, tick_at_suspend);
			//20110813 [email protected] add period [END]

		}
		rtc_hctosys();
		getnstimeofday(&tv);
		/* Update the alarm information with the new time info. */
		alarm_update_timedelta(ts, tv);
		return 0;
	}

	case RPC_TIME_GET_APPS_USER_TIME:
		return read_rtc0_time(server, req, len);

	default:
		return -ENODEV;
	}
}
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;
}
Ejemplo n.º 3
0
static int64_t msm_pm_timer_enter_suspend(int64_t *period)
{
	int time = 0;

	time = msm_timer_get_sclk_time(period);
	if (!time)
		pr_err("%s: Unable to read sclk.\n", __func__);
		return time;
}
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);
/* CR 293735 - Function/Feature Failure (Partial)
 * When system was in suspend, could make invalid "elapsed system time" at AP side.
 * 
 * Problem description
 * When system is in suspend mode and if more than one network time update
 * comes while system is in suspend mode then the uptime gets corrupted.
 * 
 * Failure frequency: Occasionally
 * Scenario frequency: Uncommon
 * Change description
 * Added change to modify tick_at_suspend (variable that stores time tick
 * while entering suspend) after each update to the current time tick.
 * Setting the suspend mode variable in case alarm time expires the current
 * RTC time as in thic case also system enters suspend mode.
 * to sdcc irq handlers returning IRQ_NONE without handling the interrupt.
 * When interrupt is disabled the communication between the SDIO client and
 * SDCC host controller is stopped while a pending command is in progress
 * and hence WLAN operation is stuck forever and LOGP recovery cannot be
 * processed.
 * Files affected
 * arch/arm/mach-msm/rpc_server_time_remote.c
 * drivers/rtc/rtc-msm.c
 * include/linux/rtc-msm.h
 */
#if 1 //QCT SBA 404017
			atomic_inc(&suspend_state.state);
#endif
			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;
}
Ejemplo n.º 5
0
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);
		if (atomic_read(&suspend_state.state)) {
			int64_t now, sleep, sclk_max;
			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);
		}
		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);
}
Ejemplo n.º 6
0
static int64_t msm_pm_timer_exit_suspend(int64_t time, int64_t period)
{

	if (time != 0) {
		int64_t end_time = msm_timer_get_sclk_time(NULL);
		if (end_time != 0) {
			time = end_time - time;
			if (time < 0)
				time += period;
			} else
				time = 0;
		}
	return time;
}
Ejemplo n.º 7
0
void msmrtc_updateatsuspend(struct timespec *ts)
{
	int64_t now, sleep;

	if (atomic_read(&suspend_state.state)) {
		now = msm_timer_get_sclk_time(NULL);
		if (now && suspend_state.tick_at_suspend) {
			sleep = now - suspend_state.tick_at_suspend;
			timespec_add_ns(ts, sleep);
		} else
			pr_err("%s: Invalid ticks from SCLK now=%lld"
				"tick_at_suspend=%lld", __func__, now,
				suspend_state.tick_at_suspend);
	}

}
Ejemplo n.º 8
0
/*
 * Power collapse the Apps processor.  This function executes the handshake
 * protocol with Modem.
 *
 * Return value:
 *      -EAGAIN: modem reset occurred or early exit from power collapse
 *      -EBUSY: modem not ready for our power collapse -- no power loss
 *      -ETIMEDOUT: timed out waiting for modem's handshake -- no power loss
 *      0: success
 */
static int msm_pm_power_collapse
	(bool from_idle, uint32_t sleep_delay, uint32_t sleep_limit)
{
	struct msm_pm_polled_group state_grps[2];
	unsigned long saved_acpuclk_rate;
	int collapsed = 0;
#ifdef CONFIG_MSM_SM_EVENT
	uint64_t sclk_suspend_time = 0, sclk_resume_time, sclk_period;
#endif
	int ret;
	int val;
	int modem_early_exit = 0;

	MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
		KERN_INFO, "%s(): idle %d, delay %u, limit %u\n", __func__,
		(int)from_idle, sleep_delay, sleep_limit);

	if (!(smsm_get_state(SMSM_POWER_MASTER_DEM) & DEM_MASTER_SMSM_READY)) {
		MSM_PM_DPRINTK(
			MSM_PM_DEBUG_SUSPEND | MSM_PM_DEBUG_POWER_COLLAPSE,
			KERN_INFO, "%s(): master not ready\n", __func__);
		ret = -EBUSY;
		goto power_collapse_bail;
	}

	memset(msm_pm_smem_data, 0, sizeof(*msm_pm_smem_data));

	if (cpu_is_msm8625()) {
		/* Program the SPM */
		ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_COLLAPSE,
									false);
		WARN_ON(ret);
	}

	if (msm_cpr_ops)
		msm_cpr_ops->cpr_suspend();

	msm_pm_irq_extns->enter_sleep1(true, from_idle,
						&msm_pm_smem_data->irq_mask);
	msm_sirc_enter_sleep();
	msm_gpio_enter_sleep(from_idle);

	msm_pm_smem_data->sleep_time = sleep_delay;
	msm_pm_smem_data->resources_used = sleep_limit;

	/* Enter PWRC/PWRC_SUSPEND */

	if (from_idle)
		smsm_change_state(SMSM_APPS_DEM, DEM_SLAVE_SMSM_RUN,
			DEM_SLAVE_SMSM_PWRC);
	else
		smsm_change_state(SMSM_APPS_DEM, DEM_SLAVE_SMSM_RUN,
			DEM_SLAVE_SMSM_PWRC | DEM_SLAVE_SMSM_PWRC_SUSPEND);

	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): PWRC");
	MSM_PM_DEBUG_PRINT_SLEEP_INFO();

	memset(state_grps, 0, sizeof(state_grps));
	state_grps[0].group_id = SMSM_POWER_MASTER_DEM;
	state_grps[0].bits_all_set = DEM_MASTER_SMSM_RSA;
	state_grps[1].group_id = SMSM_MODEM_STATE;
	state_grps[1].bits_all_set = SMSM_RESET;

	ret = msm_pm_poll_state(ARRAY_SIZE(state_grps), state_grps);

	if (ret < 0) {
		printk(KERN_EMERG "%s(): power collapse entry "
			"timed out waiting for Modem's response\n", __func__);
		msm_pm_timeout();
	}

	if (ret == 1) {
		MSM_PM_DPRINTK(
			MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
			KERN_INFO,
			"%s(): msm_pm_poll_state detected Modem reset\n",
			__func__);
		goto power_collapse_early_exit;
	}

	/* DEM Master in RSA */

	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): PWRC RSA");

	ret = msm_pm_irq_extns->enter_sleep2(true, from_idle);
	if (ret < 0) {
		MSM_PM_DPRINTK(
			MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
			KERN_INFO,
			"%s(): msm_irq_enter_sleep2 aborted, %d\n", __func__,
			ret);
		goto power_collapse_early_exit;
	}

#ifdef CONFIG_MSM_SM_EVENT
	if (!from_idle)
		sclk_suspend_time = msm_timer_get_sclk_time(&sclk_period);
#endif
	msm_pm_config_hw_before_power_down();
	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): pre power down");

	saved_acpuclk_rate = acpuclk_power_collapse();
	MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO,
		"%s(): change clock rate (old rate = %lu)\n", __func__,
		saved_acpuclk_rate);

	if (saved_acpuclk_rate == 0) {
		msm_pm_config_hw_after_power_up();
		goto power_collapse_early_exit;
	}

#ifdef CONFIG_MSM_SM_EVENT
	if (!from_idle) {
		sm_add_event(SM_POWER_EVENT | SM_POWER_EVENT_SUSPEND, SM_EVENT_END, 0, 0, 0);
	}
#endif
	msm_pm_boot_config_before_pc(smp_processor_id(),
			virt_to_phys(msm_pm_collapse_exit));

#ifdef CONFIG_VFP
	if (from_idle)
		vfp_flush_context();
#endif

#ifdef CONFIG_CACHE_L2X0
	if (!cpu_is_msm8625())
		l2cc_suspend();
	else
		apps_power_collapse = 1;
#endif

	collapsed = msm_pm_collapse();

	/*
	 * TBD: Currently recognise the MODEM early exit
	 * path by reading the MPA5_GDFS_CNT_VAL register.
	 */
	if (cpu_is_msm8625()) {
		/*
		 * on system reset, default value of MPA5_GDFS_CNT_VAL
		 * is = 0x0, later modem reprogram this value to
		 * 0x00030004. Once APPS did a power collapse and
		 * coming out of it expected value of this register
		 * always be 0x00030004. Incase if APPS sees the value
		 * as 0x00030002 consider this case as a modem early
		 * exit.
		 */
		val = __raw_readl(MSM_CFG_CTL_BASE + 0x38);
		if (val != 0x00030002)
			power_collapsed = 1;
		else
			modem_early_exit = 1;
	}

#ifdef CONFIG_CACHE_L2X0
	if (!cpu_is_msm8625())
		l2cc_resume();
	else
		apps_power_collapse = 0;
#endif

	msm_pm_boot_config_after_pc(smp_processor_id());

	if (collapsed) {
#ifdef CONFIG_VFP
		if (from_idle)
			vfp_reinit();
#endif
		cpu_init();
		local_fiq_enable();
	}

	MSM_PM_DPRINTK(MSM_PM_DEBUG_SUSPEND | MSM_PM_DEBUG_POWER_COLLAPSE,
		KERN_INFO,
		"%s(): msm_pm_collapse returned %d\n", __func__, collapsed);

	MSM_PM_DPRINTK(MSM_PM_DEBUG_CLOCK, KERN_INFO,
		"%s(): restore clock rate to %lu\n", __func__,
		saved_acpuclk_rate);
	if (acpuclk_set_rate(smp_processor_id(), saved_acpuclk_rate,
			SETRATE_PC) < 0)
		printk(KERN_ERR "%s(): failed to restore clock rate(%lu)\n",
			__func__, saved_acpuclk_rate);

	msm_pm_irq_extns->exit_sleep1(msm_pm_smem_data->irq_mask,
		msm_pm_smem_data->wakeup_reason,
		msm_pm_smem_data->pending_irqs);

	msm_pm_config_hw_after_power_up();
	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): post power up");

	memset(state_grps, 0, sizeof(state_grps));
	state_grps[0].group_id = SMSM_POWER_MASTER_DEM;
	state_grps[0].bits_any_set =
		DEM_MASTER_SMSM_RSA | DEM_MASTER_SMSM_PWRC_EARLY_EXIT;
	state_grps[1].group_id = SMSM_MODEM_STATE;
	state_grps[1].bits_all_set = SMSM_RESET;

	ret = msm_pm_poll_state(ARRAY_SIZE(state_grps), state_grps);

	if (ret < 0) {
		printk(KERN_EMERG "%s(): power collapse exit "
			"timed out waiting for Modem's response\n", __func__);
		msm_pm_timeout();
	}

	if (ret == 1) {
		MSM_PM_DPRINTK(
			MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
			KERN_INFO,
			"%s(): msm_pm_poll_state detected Modem reset\n",
			__func__);
		goto power_collapse_early_exit;
	}

	/* Sanity check */
	if (collapsed && !modem_early_exit) {
		BUG_ON(!(state_grps[0].value_read & DEM_MASTER_SMSM_RSA));
	} else {
		BUG_ON(!(state_grps[0].value_read &
			DEM_MASTER_SMSM_PWRC_EARLY_EXIT));
		goto power_collapse_early_exit;
	}

	/* Enter WFPI */

	smsm_change_state(SMSM_APPS_DEM,
		DEM_SLAVE_SMSM_PWRC | DEM_SLAVE_SMSM_PWRC_SUSPEND,
		DEM_SLAVE_SMSM_WFPI);

	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): WFPI");

	memset(state_grps, 0, sizeof(state_grps));
	state_grps[0].group_id = SMSM_POWER_MASTER_DEM;
	state_grps[0].bits_all_set = DEM_MASTER_SMSM_RUN;
	state_grps[1].group_id = SMSM_MODEM_STATE;
	state_grps[1].bits_all_set = SMSM_RESET;

	ret = msm_pm_poll_state(ARRAY_SIZE(state_grps), state_grps);

	if (ret < 0) {
		printk(KERN_EMERG "%s(): power collapse WFPI "
			"timed out waiting for Modem's response\n", __func__);
		msm_pm_timeout();
	}

	if (ret == 1) {
		MSM_PM_DPRINTK(
			MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
			KERN_INFO,
			"%s(): msm_pm_poll_state detected Modem reset\n",
			__func__);
		ret = -EAGAIN;
		goto power_collapse_restore_gpio_bail;
	}

#ifdef CONFIG_MSM_SM_EVENT
	if (!from_idle) {
		int64_t time;
		sm_set_system_state (SM_STATE_RESUME);
		sclk_resume_time = msm_timer_get_sclk_time(NULL);

		time = sclk_resume_time - sclk_suspend_time;
		if (time < 0)
			time += sclk_period;
		do_div (time, 1000000);//milli-second
		sm_add_event(SM_POWER_EVENT | SM_POWER_EVENT_RESUME, SM_EVENT_START, (uint32_t)time, (void *)msm_pm_smem_data, sizeof(*msm_pm_smem_data));
	}
#endif
	/* DEM Master == RUN */

	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): WFPI RUN");
	MSM_PM_DEBUG_PRINT_SLEEP_INFO();

	msm_pm_irq_extns->exit_sleep2(msm_pm_smem_data->irq_mask,
		msm_pm_smem_data->wakeup_reason,
		msm_pm_smem_data->pending_irqs);
	msm_pm_irq_extns->exit_sleep3(msm_pm_smem_data->irq_mask,
		msm_pm_smem_data->wakeup_reason,
		msm_pm_smem_data->pending_irqs);
	msm_gpio_exit_sleep();
	msm_sirc_exit_sleep();

	smsm_change_state(SMSM_APPS_DEM,
		DEM_SLAVE_SMSM_WFPI, DEM_SLAVE_SMSM_RUN);

	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): RUN");

	smd_sleep_exit();

	if (cpu_is_msm8625()) {
		ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
									false);
		WARN_ON(ret);
	}

	if (msm_cpr_ops)
		msm_cpr_ops->cpr_resume();

	return 0;

power_collapse_early_exit:
	/* Enter PWRC_EARLY_EXIT */

	smsm_change_state(SMSM_APPS_DEM,
		DEM_SLAVE_SMSM_PWRC | DEM_SLAVE_SMSM_PWRC_SUSPEND,
		DEM_SLAVE_SMSM_PWRC_EARLY_EXIT);

	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): EARLY_EXIT");

	memset(state_grps, 0, sizeof(state_grps));
	state_grps[0].group_id = SMSM_POWER_MASTER_DEM;
	state_grps[0].bits_all_set = DEM_MASTER_SMSM_PWRC_EARLY_EXIT;
	state_grps[1].group_id = SMSM_MODEM_STATE;
	state_grps[1].bits_all_set = SMSM_RESET;

	ret = msm_pm_poll_state(ARRAY_SIZE(state_grps), state_grps);
	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): EARLY_EXIT EE");

	if (ret < 0) {
		printk(KERN_EMERG "%s(): power collapse EARLY_EXIT "
			"timed out waiting for Modem's response\n", __func__);
		msm_pm_timeout();
	}

	if (ret == 1) {
		MSM_PM_DPRINTK(
			MSM_PM_DEBUG_SUSPEND|MSM_PM_DEBUG_POWER_COLLAPSE,
			KERN_INFO,
			"%s(): msm_pm_poll_state detected Modem reset\n",
			__func__);
	}

	/* DEM Master == RESET or PWRC_EARLY_EXIT */

	ret = -EAGAIN;

power_collapse_restore_gpio_bail:
	msm_gpio_exit_sleep();
	msm_sirc_exit_sleep();

	/* Enter RUN */
	smsm_change_state(SMSM_APPS_DEM,
		DEM_SLAVE_SMSM_PWRC | DEM_SLAVE_SMSM_PWRC_SUSPEND |
		DEM_SLAVE_SMSM_PWRC_EARLY_EXIT, DEM_SLAVE_SMSM_RUN);

	MSM_PM_DEBUG_PRINT_STATE("msm_pm_power_collapse(): RUN");

	if (collapsed)
		smd_sleep_exit();

	if (msm_cpr_ops)
		msm_cpr_ops->cpr_resume();

power_collapse_bail:
	if (cpu_is_msm8625()) {
		ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING,
									false);
		WARN_ON(ret);
	}

	return ret;
}
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);

/* CR 291540 - Function/Feature Failure (Partial)
 * system uptime gets corrupted with overflow in slow clock.
 * 
 * Problem description
 * During power collapse, APPS sleep time is calculated using slow clock
 * ticks. The calculation of sleep time does not considers slow clock
 * overflow and thus If slow clock overflows during suspend state then we
 * get wrong sleep time and thus system uptime values gets corrupted.
 * earlier sleep time was calculates as follows:
 * sleep = current_sclk_tick - suspend_state_sclk_tick
 * 
 * Failure frequency: Occasionally
 * Scenario frequency: Uncommon
 * Change description
 * Modified the sleep time calculation to include slow clock overflow as follows:
 * Now sleep time is calculated as:
 * sleep = Maximum_sclk_tick_val - suspend_state_sclk_tick + current_sclk_tick.
 * Files affected
 * kernel/drivers/rtc/rtc-msm.c
 * kernel/arch/arm/mach-msm/rpc_server_time_remote.c
*/	
		if (atomic_read(&suspend_state.state)) {
#if 1 //QCT SBA 404016
			int64_t now, sleep, sclk_max;
			now = msm_timer_get_sclk_time(&sclk_max);
#else
			int64_t now, sleep;
			now = msm_timer_get_sclk_time(NULL);
#endif
			if (now && suspend_state.tick_at_suspend) {
#if 1 //QCT SBA 404016
				if (now < suspend_state.tick_at_suspend) {
					sleep = sclk_max -
							suspend_state.tick_at_suspend
							+ now;
				} else {
					sleep = now -
							suspend_state.tick_at_suspend;
				}
#else
				sleep = now -
					suspend_state.tick_at_suspend;
#endif
				timespec_add_ns(&ts, sleep);
/* CR 293735 - Function/Feature Failure (Partial)
 * When system was in suspend, could make invalid "elapsed system time" at AP side.
 * 
 * Problem description
 * When system is in suspend mode and if more than one network time update
 * comes while system is in suspend mode then the uptime gets corrupted.
 * 
 * Failure frequency: Occasionally
 * Scenario frequency: Uncommon
 * Change description
 * Added change to modify tick_at_suspend (variable that stores time tick
 * while entering suspend) after each update to the current time tick.
 * Setting the suspend mode variable in case alarm time expires the current
 * RTC time as in thic case also system enters suspend mode.
 * to sdcc irq handlers returning IRQ_NONE without handling the interrupt.
 * When interrupt is disabled the communication between the SDIO client and
 * SDCC host controller is stopped while a pending command is in progress
 * and hence WLAN operation is stuck forever and LOGP recovery cannot be
 * processed.
 * Files affected
 * arch/arm/mach-msm/rpc_server_time_remote.c
 * drivers/rtc/rtc-msm.c
 * include/linux/rtc-msm.h
 */
#if 1 //QCT SBA 404017
				suspend_state.tick_at_suspend = now;
#endif
			} else
				pr_err("%s: Invalid ticks from SCLK"
					"now=%lld tick_at_suspend=%lld",
					__func__, now,
					suspend_state.tick_at_suspend);
		}
		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);
}