Example #1
0
static void modem_fatal_fn(struct work_struct *work)
{
	u32 modem_state;
	u32 panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
	u32 reset_smsm_states = SMSM_SYSTEM_REBOOT_USR | SMSM_SYSTEM_PWRDWN_USR;
	struct modem_data *drv;

	drv = container_of(work, struct modem_data, fatal_work);

	pr_err("Watchdog bite received from modem!\n");

	modem_state = smsm_get_state(SMSM_MODEM_STATE);
	pr_err("Modem SMSM state = 0x%x!\n", modem_state);

	if (modem_state == 0 || modem_state & panic_smsm_states) {
		subsystem_restart_dev(drv->subsys);
		enable_irq(drv->irq);
	} else if (modem_state & reset_smsm_states) {
		pr_err("User-invoked system reset/powerdown.");
		kernel_restart(NULL);
	} else {
		unsigned long timeout = msecs_to_jiffies(6000);

		pr_err("Modem AHB locked up. Trying to free up modem!\n");

		writel_relaxed(0x3, drv->cbase + MSS_MODEM_RESET);
		/*
		 * If we are still alive (allowing for the 5 second
		 * delayed-panic-reboot), the modem is either still wedged or
		 * SMSM didn't come through. Force panic in that case.
		 */
		schedule_delayed_work(&drv->unlock_work, timeout);
	}
}
Example #2
0
/*
 * Poll the shared memory states as indicated by the poll groups.
 *
 * nr_grps: number of groups in the array
 * grps: array of groups
 *
 * The function returns when conditions specified by any of the poll
 * groups become true.  The conditions specified by a poll group are
 * deemed true when 1) at least one bit from bits_any_set is set OR one
 * bit from bits_any_clear is cleared; and 2) all bits in bits_all_set
 * are set; and 3) all bits in bits_all_clear are cleared.
 *
 * Return value:
 *      >=0: index of the poll group whose conditions have become true
 *      -ETIMEDOUT: timed out
 */
static int msm_pm_poll_state(int nr_grps, struct msm_pm_polled_group *grps)
{
	int i, k;
    KDEBUG_FUNC();
	for (i = 0; i < 500000; i++)
		for (k = 0; k < nr_grps; k++) {
			bool all_set, all_clear;
			bool any_set, any_clear;

			grps[k].value_read = smsm_get_state(grps[k].group_id);

			all_set = msm_pm_all_set(grps[k].value_read,
					grps[k].bits_all_set);
			all_clear = msm_pm_all_clear(grps[k].value_read,
					grps[k].bits_all_clear);
			any_set = msm_pm_any_set(grps[k].value_read,
					grps[k].bits_any_set);
			any_clear = msm_pm_any_clear(grps[k].value_read,
					grps[k].bits_any_clear);

			if (all_set && all_clear && (any_set || any_clear))
				return k;
		}

	printk(KERN_ERR "%s failed:\n", __func__);
	for (k = 0; k < nr_grps; k++)
		printk(KERN_ERR "(%x, %x, %x, %x) %x\n",
			grps[k].bits_all_set, grps[k].bits_all_clear,
			grps[k].bits_any_set, grps[k].bits_any_clear,
			grps[k].value_read);

	return -ETIMEDOUT;
}
Example #3
0
static int modem_shutdown(const struct subsys_desc *subsys)
{
	struct modem_data *drv;

	drv = container_of(subsys, struct modem_data, subsys_desc);
	/*
	 * If the modem didn't already crash, setting SMSM_RESET here will help
	 * flush caches etc. The ignore_smsm_ack flag is set to ignore the
	 * SMSM_RESET notification that is generated due to the modem settings
	 * its own SMSM_RESET bit in response to the apps setting the apps
	 * SMSM_RESET bit.
	 */
	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
		drv->ignore_smsm_ack = 1;
		smsm_reset_modem(SMSM_RESET);
	}

	/* Disable the modem watchdog to allow clean modem bootup */
	writel_relaxed(0x0, drv->wdog + 0x8);
	/*
	 * The write above needs to go through before the modem is powered up
	 * again.
	 */
	mb();
	/* Wait here to allow the modem to clean up caches, etc. */
	msleep(20);

	pil_shutdown(&drv->pil_desc);
	disable_irq_nosync(drv->irq);

	return 0;
}
Example #4
0
static void modem_sw_fatal_fn(struct work_struct *work)
{
	uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
	uint32_t reset_smsm_states = SMSM_SYSTEM_REBOOT_USR |
					SMSM_SYSTEM_PWRDWN_USR;
	uint32_t modem_state;

	pr_err("Watchdog bite received from modem SW!\n");

	modem_state = smsm_get_state(SMSM_MODEM_STATE);

	if (modem_state & panic_smsm_states) {

		pr_err("Modem SMSM state changed to SMSM_RESET.\n"
			"Probable err_fatal on the modem. "
			"Calling subsystem restart...\n");
		subsystem_restart("modem");

	} else if (modem_state & reset_smsm_states) {

		pr_err("%s: User-invoked system reset/powerdown. "
			"Resetting the SoC now.\n",
			__func__);
		kernel_restart(NULL);
	} else {
		/* TODO: Bus unlock code/sequence goes _here_ */
		subsystem_restart("modem");
	}
}
Example #5
0
/*
 * Restore interrupt subsystem from sleep -- phase 3.
 * Print debug information.
 */
void msm_irq_exit_sleep3(uint32_t irq_mask, uint32_t wakeup_reason,
	uint32_t pending_irqs)
{
	if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP)
		DPRINT_REGS(VIC_IRQ_STATUS, "%s %x %x %x state %x now",
			__func__, irq_mask, pending_irqs, wakeup_reason,
			smsm_get_state(SMSM_MODEM_STATE));
}
Example #6
0
static uint32_t is_modem_smsm_inited(void)
{
	uint32_t modem_state;
	uint32_t ready_state = (SMSM_INIT | SMSM_SMDINIT);

	modem_state = smsm_get_state(SMSM_MODEM_STATE);
	return (modem_state & ready_state) == ready_state;
}
 /*
  * Restore interrupt subsystem from sleep -- phase 3
  * Print debug information
  */
void msm_gic_irq_exit_sleep3(uint32_t irq_mask, uint32_t wakeup_reason,
		uint32_t pending_irqs)
{
	if (msm_gic_irq_debug_mask & IRQ_DEBUG_SLEEP)
		pr_info("%s, irq_mask %x pending_irqs %x, wakeup_reason %x,"
				"state %x now\n", __func__, irq_mask,
				pending_irqs, wakeup_reason,
				smsm_get_state(SMSM_MODEM_STATE));
}
Example #8
0
/*
 * Restore interrupt subsystem from sleep -- phase 3.
 * Print debug information.
 */
void msm_irq_exit_sleep3(uint32_t irq_mask, uint32_t wakeup_reason,
	uint32_t pending_irqs)
{
	if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP)
		printk(KERN_INFO "%s %x %x %x now %x %x state %x\n",
			__func__, irq_mask, pending_irqs, wakeup_reason,
			readl(VIC_IRQ_STATUS0), readl(VIC_IRQ_STATUS1),
			smsm_get_state(SMSM_MODEM_STATE));
}
static int msm_pm_modem_busy(void)
{
	if (!(smsm_get_state(SMSM_POWER_MASTER_DEM) & DEM_MASTER_SMSM_READY)) {
		MSM_PM_DPRINTK(MSM_PM_DEBUG_POWER_COLLAPSE,
			KERN_INFO, "%s(): master not ready\n", __func__);
		return -EBUSY;
	}

	return 0;
}
Example #10
0
static void modem_crash_shutdown(const struct subsys_desc *subsys)
{
	struct modem_data *drv;

	/* If modem hasn't already crashed, send SMSM_RESET. */
	drv = container_of(subsys, struct modem_data, subsys_desc);
	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
		modem_unregister_notifier(&drv->notifier);
		smsm_reset_modem(SMSM_RESET);
	}

	/* Wait to allow the modem to clean up caches etc. */
	mdelay(5);
}
Example #11
0
static void modem_crash_shutdown(const struct subsys_desc *subsys)
{
	struct modem_data *drv;

	
	drv = container_of(subsys, struct modem_data, subsys_desc);
	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
		modem_unregister_notifier(&drv->notifier);
		smsm_reset_modem(SMSM_RESET);
	}

	
	mdelay(5);
}
Example #12
0
void msm_irq_exit_sleep3(void)
{
	if (!smsm_int_info) {
		printk(KERN_ERR "msm_irq_exit_sleep <SM NO INT_INFO>\n");
		return;
	}
	if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP)
		printk(KERN_INFO "msm_irq_exit_sleep3 %x %x %x now %x %x "
		       "state %x\n", smsm_int_info->interrupt_mask,
		       smsm_int_info->pending_interrupts,
		       smsm_int_info->wakeup_reason, readl(VIC_IRQ_STATUS0),
		       readl(VIC_IRQ_STATUS1),
		       smsm_get_state(SMSM_STATE_MODEM));
}
Example #13
0
static int modem_shutdown(const struct subsys_data *subsys)
{
	void __iomem *q6_fw_wdog_addr;
	void __iomem *q6_sw_wdog_addr;
	int smsm_notif_unregistered = 0;

	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
		smsm_state_cb_deregister(SMSM_MODEM_STATE, SMSM_RESET,
			smsm_state_cb, 0);
		smsm_notif_unregistered = 1;
		smsm_reset_modem(SMSM_RESET);
	}

	/*
	 * Cancel any pending wdog_check work items, since we're shutting
	 * down anyway.
	 */
	cancel_delayed_work(&modem_wdog_check_work);

	/*
	 * Disable the modem watchdog since it keeps running even after the
	 * modem is shutdown.
	 */
	q6_fw_wdog_addr = ioremap_nocache(Q6_FW_WDOG_ENABLE, 4);
	if (!q6_fw_wdog_addr)
		return -ENOMEM;

	q6_sw_wdog_addr = ioremap_nocache(Q6_SW_WDOG_ENABLE, 4);
	if (!q6_sw_wdog_addr) {
		iounmap(q6_fw_wdog_addr);
		return -ENOMEM;
	}

	writel_relaxed(0x0, q6_fw_wdog_addr);
	writel_relaxed(0x0, q6_sw_wdog_addr);
	mb();
	iounmap(q6_sw_wdog_addr);
	iounmap(q6_fw_wdog_addr);

	pil_force_shutdown("modem");
	pil_force_shutdown("modem_fw");
	disable_irq_nosync(Q6FW_WDOG_EXPIRED_IRQ);
	disable_irq_nosync(Q6SW_WDOG_EXPIRED_IRQ);

	if (smsm_notif_unregistered)
		smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
			smsm_state_cb, 0);

	return 0;
}
Example #14
0
void msm_irq_exit_sleep3(void)
{
	if (!smsm_int_info) {
		printk(KERN_ERR "msm_irq_exit_sleep <SM NO INT_INFO>\n");
		return;
	}
	if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP) {
		printk(KERN_INFO "%s %x %x %x state %x now", __func__,
		       smsm_int_info->interrupt_mask,
		       smsm_int_info->pending_interrupts,
		       smsm_int_info->wakeup_reason,
		       smsm_get_state(SMSM_STATE_MODEM));
		print_vic_irq_stat();
	}
}
static void modem_fatal_fn(struct work_struct *work)
{
	uint32_t modem_state;
	uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
	uint32_t reset_smsm_states = SMSM_SYSTEM_REBOOT_USR |
					SMSM_SYSTEM_PWRDWN_USR;

	pr_err("%s: Watchdog bite received from modem!\n", MODULE_NAME);

	modem_state = smsm_get_state(SMSM_MODEM_STATE);
	pr_err("%s: Modem SMSM state = 0x%x!", MODULE_NAME, modem_state);

	if (modem_state == 0 || modem_state & panic_smsm_states) {

		subsystem_restart("modem");
		enable_irq(MARM_WDOG_EXPIRED);

	} else if (modem_state & reset_smsm_states) {

		pr_err("%s: User-invoked system reset/powerdown.",
			MODULE_NAME);
		soc_restart(RESTART_MODE_MODEM_WATCHDOG_BITE, "MODEM DOG!");
	} else {

		int ret;
		void *hwio_modem_reset_addr =
				ioremap_nocache(MODEM_HWIO_MSS_RESET_ADDR, 8);

		pr_err("%s: Modem AHB locked up.\n", MODULE_NAME);
		pr_err("%s: Trying to free up modem!\n", MODULE_NAME);

		/* We don't want it happens */
		BUG_ON(!hwio_modem_reset_addr);

		writel(0x3, hwio_modem_reset_addr);

		/* If we are still alive after 6 seconds (allowing for
		 * the 5-second-delayed-panic-reboot), modem is either
		 * still wedged or SMSM didn't come through. Force panic
		 * in that case.
		*/
		ret = schedule_delayed_work(&modem_unlock_timeout_work,
					msecs_to_jiffies(6000));

		iounmap(hwio_modem_reset_addr);
	}
}
Example #16
0
/**
 *  Fatal error handler
 *  Resets DSPS.
 */
static void dsps_fatal_handler(struct work_struct *work)
{
	uint32_t dsps_state;

	dsps_state = smsm_get_state(SMSM_DSPS_STATE);

	pr_debug("%s: DSPS state 0x%x\n", __func__, dsps_state);

	if (dsps_state & SMSM_RESET) {
		pr_err("%s: DSPS fatal error detected. Resetting\n",
		       __func__);
		panic(MODULE_NAME "DSPS fatal error detected.");
	} else {
		pr_debug("%s: User-initiated DSPS reset. Resetting\n",
			 __func__);
		panic(MODULE_NAME "User-initiated DSPS reset.");
	}
}
Example #17
0
static int
msm_pm_wait_state(uint32_t wait_all_set, uint32_t wait_all_clear,
                  uint32_t wait_any_set, uint32_t wait_any_clear)
{
    int i;
    uint32_t state;

    for (i = 0; i < 100000; i++) {
        state = smsm_get_state(PM_SMSM_READ_STATE);
        if (((wait_all_set || wait_all_clear) &&
                !(~state & wait_all_set) && !(state & wait_all_clear)) ||
                (state & wait_any_set) || (~state & wait_any_clear))
            return 0;
        udelay(1);
    }
    pr_err("msm_pm_wait_state(%x, %x, %x, %x) failed %x\n",	wait_all_set,
           wait_all_clear, wait_any_set, wait_any_clear, state);
    return -ETIMEDOUT;
}
static void modem_fatal_fn(struct work_struct *work)
{
    uint32_t modem_state;
    uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
    uint32_t reset_smsm_states = SMSM_SYSTEM_REBOOT_USR |
                                 SMSM_SYSTEM_PWRDWN_USR;

    pr_err("%s: Watchdog bite received from modem!\n", MODULE_NAME);

    modem_state = smsm_get_state(SMSM_MODEM_STATE);
    pr_err("%s: Modem SMSM state = 0x%x!", MODULE_NAME, modem_state);

    if (modem_state == 0 || modem_state & panic_smsm_states) {

        subsystem_restart("modem");

    } else if (modem_state & reset_smsm_states) {

        pr_err("%s: User-invoked system reset/powerdown.",
               MODULE_NAME);
        do_soc_restart();

    } else {

        int ret;

        pr_err("%s: Modem AHB locked up.\n", MODULE_NAME);
        pr_err("%s: Trying to free up modem!\n", MODULE_NAME);

        if ( hwio_modem_reset_addr )
            writel(0x3, hwio_modem_reset_addr);

        /* If we are still alive after 6 seconds (allowing for
         * the 5-second-delayed-panic-reboot), modem is either
         * still wedged or SMSM didn't come through. Force panic
         * in that case.
        */
        ret = schedule_delayed_work(&modem_unlock_timeout_work,
                                    msecs_to_jiffies(6000));

        iounmap(hwio_modem_reset_addr);
    }
}
Example #19
0
static int modem_shutdown(const struct subsys_desc *subsys)
{
	struct modem_data *drv;

	drv = container_of(subsys, struct modem_data, subsys_desc);
	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
		drv->ignore_smsm_ack = 1;
		smsm_reset_modem(SMSM_RESET);
	}

	
	writel_relaxed(0x0, drv->wdog + 0x8);
	mb();
	
	msleep(20);

	pil_shutdown(&drv->pil_desc);
	disable_irq_nosync(drv->irq);

	return 0;
}
Example #20
0
/**
 *  Fatal error handler
 *  Resets DSPS.
 */
static void dsps_restart_handler(struct work_struct *work)
{
	uint32_t dsps_state;
	int restart_level;
	char *smem_reset_reason;
	unsigned smem_reset_size;
	const char dflt_reason[] = "Died too early due to unknown reason";

	dsps_state = smsm_get_state(SMSM_DSPS_STATE);
	restart_level = get_restart_level();

	pr_debug("%s: DSPS state 0x%x. Restart lvl %d\n",
		__func__, dsps_state, restart_level);

	if ((dsps_state & SMSM_RESET) ||
	    (atomic_read(&drv->wd_crash) == 1)) {
		smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_DSPS0,
			&smem_reset_size);
		if (smem_reset_reason != NULL && smem_reset_reason[0] != 0) {
			smem_reset_reason[smem_reset_size-1] = 0;
			pr_err("%s: DSPS failure: %s\nResetting DSPS\n",
				__func__, smem_reset_reason);
			memset(smem_reset_reason, 0, smem_reset_size);
			wmb();
		} else
			pr_err("%s: DSPS failure: %s\nResetting DSPS\n",
				__func__, dflt_reason);
	} else
		pr_err("%s: User-initiated DSPS reset.\nResetting DSPS\n",
		       __func__);

	if (atomic_add_return(1, &drv->crash_in_progress) > 1) {
		pr_err("%s: DSPS already resetting. Count %d\n", __func__,
		       atomic_read(&drv->crash_in_progress));
	} else {
		subsystem_restart("dsps");
	}
}
Example #21
0
static void modem_sw_fatal_fn(struct work_struct *work)
{
	uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
	uint32_t reset_smsm_states = SMSM_SYSTEM_REBOOT_USR |
					SMSM_SYSTEM_PWRDWN_USR;
	uint32_t modem_state;

	pr_err("Watchdog bite received from modem SW!\n");

	modem_state = smsm_get_state(SMSM_MODEM_STATE);

	if (modem_state & panic_smsm_states) {

		pr_err("Modem SMSM state changed to SMSM_RESET.\n"
			"Probable err_fatal on the modem. "
			"Calling subsystem restart...\n");
#ifdef FEATURE_PANTECH_WLAN_QCOM_PATCH //lee.eunsuk 20120423, SSR
		panic(MODULE_NAME "Modem crashed.");
#else
		subsystem_restart("modem");
#endif

	} else if (modem_state & reset_smsm_states) {

		pr_err("%s: User-invoked system reset/powerdown. "
			"Resetting the SoC now.\n",
			__func__);
		kernel_restart(NULL);
	} else {
		/* TODO: Bus unlock code/sequence goes _here_ */
#ifdef FEATURE_PANTECH_WLAN_QCOM_PATCH //lee.eunsuk 20120423, SSR
		panic(MODULE_NAME "Modem crashed.");
#else
		subsystem_restart("modem");
#endif
	}
}
Example #22
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;
	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);
	}

	/* Call CPR suspend only for "idlePC" case */
	if (msm_cpr_ops && from_idle)
		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;
	}

	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;
	}

	msm_pm_boot_config_before_pc(smp_processor_id(),
			virt_to_phys(msm_pm_collapse_exit));

#ifdef CONFIG_VFP
	if (from_idle)
		vfp_pm_suspend();
#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_pm_resume();
#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;
	}

	/* 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);
	}

	/* Call CPR resume only for "idlePC" case */
	if (msm_cpr_ops && from_idle)
		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();

	/* Call CPR resume only for "idlePC" case */
	if (msm_cpr_ops && from_idle)
		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;
}
Example #23
0
	/* Time Slave State Bits */
	#define SLAVE_TIME_REQUEST         0x0400
	#define SLAVE_TIME_POLL            0x0800
	#define SLAVE_TIME_INIT            0x1000

	uint32_t *smem_clock;
	uint32_t smem_clock_val;
	uint32_t state;

	smem_clock = smem_alloc(SMEM_SMEM_SLOW_CLOCK_VALUE, sizeof(uint32_t));
	if (smem_clock == NULL) {
		printk(KERN_ERR "no smem clock\n");
		return 0;
	}

	state = smsm_get_state(SMSM_MODEM_STATE);
	if ((state & SMSM_INIT) == 0) {
		printk(KERN_ERR "smsm not initialized\n");
		return 0;
	}

	time_start(data);
	while ((state = smsm_get_state(SMSM_TIME_MASTER_DEM)) &
		MASTER_TIME_PENDING) {
		if (time_expired(data)) {
			printk(KERN_INFO "get_smem_clock: timeout 1 still "
				"invalid state %x\n", state);
			return 0;
		}
	}

	smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_POLL | SLAVE_TIME_INIT,
		SLAVE_TIME_REQUEST);

	time_start(data);
	while (!((state = smsm_get_state(SMSM_TIME_MASTER_DEM)) &
		MASTER_TIME_PENDING)) {
		if (time_expired(data)) {
			printk(KERN_INFO "get_smem_clock: timeout 2 still "
				"invalid state %x\n", state);
			smem_clock_val = 0;
			goto sync_sclk_exit;
		}
	}

	smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_REQUEST, SLAVE_TIME_POLL);

	time_start(data);
	do {
		smem_clock_val = *smem_clock;
	} while (smem_clock_val == 0 && !time_expired(data));

	state = smsm_get_state(SMSM_TIME_MASTER_DEM);

	if (smem_clock_val) {
		if (update != NULL)
			update(data, smem_clock_val);

		if (msm_timer_debug_mask & MSM_TIMER_DEBUG_SYNC)
			printk(KERN_INFO
				"get_smem_clock: state %x clock %u\n",
				state, smem_clock_val);
	} else {
		printk(KERN_INFO "get_smem_clock: timeout state %x clock %u\n",
			state, smem_clock_val);
	}

sync_sclk_exit:
	smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_REQUEST | SLAVE_TIME_POLL,
		SLAVE_TIME_INIT);
	return smem_clock_val;
}
#else /* CONFIG_MSM_N_WAY_SMSM */
static uint32_t msm_timer_sync_sclk(
	void (*time_start)(struct msm_timer_sync_data_t *data),
	bool (*time_expired)(struct msm_timer_sync_data_t *data),
	void (*update)(struct msm_timer_sync_data_t *data, uint32_t clk_val),
	struct msm_timer_sync_data_t *data)
{
	uint32_t *smem_clock;
	uint32_t smem_clock_val;
	uint32_t last_state;
	uint32_t state;

	smem_clock = smem_alloc(SMEM_SMEM_SLOW_CLOCK_VALUE,
				sizeof(uint32_t));

	if (smem_clock == NULL) {
		printk(KERN_ERR "no smem clock\n");
		return 0;
	}

	last_state = state = smsm_get_state(SMSM_MODEM_STATE);
	smem_clock_val = *smem_clock;
	if (smem_clock_val) {
		printk(KERN_INFO "get_smem_clock: invalid start state %x "
			"clock %u\n", state, smem_clock_val);
		smsm_change_state(SMSM_APPS_STATE,
				  SMSM_TIMEWAIT, SMSM_TIMEINIT);

		time_start(data);
		while (*smem_clock != 0 && !time_expired(data))
			;

		smem_clock_val = *smem_clock;
		if (smem_clock_val) {
			printk(KERN_INFO "get_smem_clock: timeout still "
				"invalid state %x clock %u\n",
				state, smem_clock_val);
			return 0;
		}
	}

	time_start(data);
	smsm_change_state(SMSM_APPS_STATE, SMSM_TIMEINIT, SMSM_TIMEWAIT);
	do {
		smem_clock_val = *smem_clock;
		state = smsm_get_state(SMSM_MODEM_STATE);
		if (state != last_state) {
			last_state = state;
			if (msm_timer_debug_mask & MSM_TIMER_DEBUG_SYNC)
				printk(KERN_INFO
					"get_smem_clock: state %x clock %u\n",
					state, smem_clock_val);
		}
	} while (smem_clock_val == 0 && !time_expired(data));

	if (smem_clock_val) {
		if (update != NULL)
			update(data, smem_clock_val);
	} else {
		printk(KERN_INFO "get_smem_clock: timeout state %x clock %u\n",
			state, smem_clock_val);
	}

	smsm_change_state(SMSM_APPS_STATE, SMSM_TIMEWAIT, SMSM_TIMEINIT);
	time_start(data);
	while (*smem_clock != 0 && !time_expired(data))
		;

	if (*smem_clock)
		printk(KERN_INFO "get_smem_clock: exit timeout state %x "
			"clock %u\n", state, *smem_clock);
	return smem_clock_val;
}
Example #24
0
static int check_modem_smsm_stat(void)
{
	return (smsm_get_state(SMSM_MODEM_STATE) & SMSM_SYSTEM_PWRDWN_USR);
}
Example #25
0
static uint32_t msm_timer_sync_sclk(
	void (*time_start)(struct msm_timer_sync_data_t *data),
	bool (*time_expired)(struct msm_timer_sync_data_t *data),
	void (*update)(struct msm_timer_sync_data_t *data, uint32_t clk_val),
	struct msm_timer_sync_data_t *data)
{
	/* Time Master State Bits */
	#define MASTER_BITS_PER_CPU        1
	#define MASTER_TIME_PENDING \
		(0x01UL << (MASTER_BITS_PER_CPU * SMSM_APPS_STATE))

	/* Time Slave State Bits */
	#define SLAVE_TIME_REQUEST         0x0400
	#define SLAVE_TIME_POLL            0x0800
	#define SLAVE_TIME_INIT            0x1000

	uint32_t *smem_clock;
	uint32_t smem_clock_val;
	uint32_t state;

	smem_clock = smem_alloc(SMEM_SMEM_SLOW_CLOCK_VALUE, sizeof(uint32_t));
	if (smem_clock == NULL) {
		printk(KERN_ERR "no smem clock\n");
		return 0;
	}

	state = smsm_get_state(SMSM_MODEM_STATE);
	if ((state & SMSM_INIT) == 0) {
		printk(KERN_ERR "smsm not initialized\n");
		return 0;
	}

	time_start(data);
	while ((state = smsm_get_state(SMSM_TIME_MASTER_DEM)) &
		MASTER_TIME_PENDING) {
		if (time_expired(data)) {
			printk(KERN_INFO "get_smem_clock: timeout 1 still "
				"invalid state %x\n", state);
			return 0;
		}
	}

	smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_POLL | SLAVE_TIME_INIT,
		SLAVE_TIME_REQUEST);

	time_start(data);
	while (!((state = smsm_get_state(SMSM_TIME_MASTER_DEM)) &
		MASTER_TIME_PENDING)) {
		if (time_expired(data)) {
			printk(KERN_INFO "get_smem_clock: timeout 2 still "
				"invalid state %x\n", state);
			smem_clock_val = 0;
			goto sync_sclk_exit;
		}
	}

	smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_REQUEST, SLAVE_TIME_POLL);

	time_start(data);
	do {
		smem_clock_val = *smem_clock;
	} while (smem_clock_val == 0 && !time_expired(data));

	state = smsm_get_state(SMSM_TIME_MASTER_DEM);

	if (smem_clock_val) {
		if (update != NULL)
			update(data, smem_clock_val);

		if (msm_timer_debug_mask & MSM_TIMER_DEBUG_SYNC)
			printk(KERN_INFO
				"get_smem_clock: state %x clock %u\n",
				state, smem_clock_val);
	} else {
		printk(KERN_INFO "get_smem_clock: timeout state %x clock %u\n",
			state, smem_clock_val);
	}

sync_sclk_exit:
	smsm_change_state(SMSM_APPS_DEM, SLAVE_TIME_REQUEST | SLAVE_TIME_POLL,
		SLAVE_TIME_INIT);
	return smem_clock_val;
}
Example #26
0
static void apps_sleep(void) {
    uint32_t saved_vector[2];
    unsigned int sleep_delay;
    static uint32_t *msm_pm_reset_vector;
    uint32_t enter_state;
    uint32_t enter_wait_set = 0;
    uint32_t enter_wait_clear = 0;
    uint32_t exit_state;
//	uint32_t exit_wait_clear = 0;
    uint32_t exit_wait_any_set = 0;

    int ret;
    int collapsed = 0;

    enter_state = DEM_SLAVE_SMSM_SLEEP;
    enter_wait_set = DEM_MASTER_SMSM_SLEEP;
    exit_state = DEM_SLAVE_SMSM_SLEEP_EXIT;
    exit_wait_any_set = DEM_MASTER_SMSM_SLEEP_EXIT;

    msm_irq_enter_sleep1(1, 0);
    msm_gpio_enter_sleep(0);

    sleep_delay = 192000*5; /* APPS_SLEEP does not allow infinite timeout */
    ret = smsm_set_sleep_duration(sleep_delay);
    printk("smsm_set_sleep_duration result: %d\n", ret);

    ret = smsm_change_state(PM_SMSM_WRITE_STATE, PM_SMSM_WRITE_RUN, enter_state);
    printk("smsm_change_state result: %d\n", ret);

    msm_irq_enter_sleep2(1, 0);

    // APPS_SLEEP

    //ret = smsm_change_state(PM_SMSM_WRITE_STATE, PM_SMSM_WRITE_RUN, enter_state);
    //printk("smsm_change_state result: %d\n", ret);

    ret = msm_pm_wait_state(enter_wait_set, enter_wait_clear, 0, 0);
    printk("msm_pm_wait_state result: %d\n", ret);

//    msm_enter_prep_hw();
    writel(1, A11S_PWRDOWN);
    writel(4, A11S_SECOP);
    printk("A11S_PWRDOWN: %.8x\n", readl(A11S_PWRDOWN));
    printk("A11S_SECOP: %.8x\n", readl(A11S_SECOP));

    printk("msm_sleep(): enter "
           "A11S_CLK_SLEEP_EN %x, A11S_PWRDOWN %x, "
           "smsm_get_state %x\n", readl(A11S_CLK_SLEEP_EN),
           readl(A11S_PWRDOWN), smsm_get_state(PM_SMSM_READ_STATE));

    magic_num = 0xAAAA1111;
    writel(magic_num, HTC_POWER_COLLAPSE_MAGIC_NUM);

    msm_pm_reset_vector = ioremap(0x0, PAGE_SIZE);

//    smsm_print_sleep_info(0);
    saved_vector[0] = msm_pm_reset_vector[0];
    saved_vector[1] = msm_pm_reset_vector[1];
    msm_pm_reset_vector[0] = 0xE51FF004; /* ldr pc, 4 */
    msm_pm_reset_vector[1] = virt_to_phys(msm_pm_collapse_exit);
    printk(KERN_INFO "msm_sleep(): vector %x %x -> "
           "%x %x\n", saved_vector[0], saved_vector[1],
           msm_pm_reset_vector[0], msm_pm_reset_vector[1]);

    collapsed = msm_pm_collapse();
    printk("pmmod: collapsed: %d\n", collapsed);
};