Exemple #1
0
/*
 * Prepare interrupt subsystem for entering sleep -- phase 2.
 * Detect any pending interrupts and configure interrupt hardware.
 *
 * Return value:
 * -EAGAIN: there are pending interrupt(s); interrupt configuration
 *          is not changed.
 *       0: success
 */
int msm_irq_enter_sleep2(bool modem_wake, int from_idle)
{
	int i, limit = 10;
	uint32_t pending[VIC_NUM_REGS];

	if (from_idle && !modem_wake)
		return 0;

	/* edge triggered interrupt may get lost if this mode is used */
	WARN_ON_ONCE(!modem_wake && !from_idle);

	if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP)
		DPRINT_REGS(VIC_IRQ_STATUS, "%s change irq, pend", __func__);

	for (i = 0; i < VIC_NUM_REGS; i++) {
		pending[i] = readl(VIC_IRQ_STATUS0 + (i * 4));
		pending[i] &= msm_irq_shadow_reg[i].int_en[!from_idle];
	}

	/*
	 * Clear INT_A9_M2A_5 since requesting sleep triggers it.
	 * In some arch e.g. FSM9XXX, INT_A9_M2A_5 may not be in the first set.
	 */
	pending[INT_A9_M2A_5 / 32] &= ~(1U << (INT_A9_M2A_5 % 32));

	for (i = 0; i < VIC_NUM_REGS; i++) {
		if (pending[i]) {
			if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_ABORT)
				DPRINT_ARRAY(pending, "%s abort",
						       __func__);
			return -EAGAIN;
		}
	}

	msm_irq_write_all_regs(VIC_INT_EN0, 0);

	while (limit-- > 0) {
		int pend_irq;
		int irq = readl(VIC_IRQ_VEC_RD);
		if (irq == -1)
			break;
		pend_irq = readl(VIC_IRQ_VEC_PEND_RD);
		if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_INT)
			printk(KERN_INFO "%s cleared int %d (%d)\n",
				__func__, irq, pend_irq);
	}

	if (modem_wake) {
		msm_irq_set_type(INT_A9_M2A_6, IRQF_TRIGGER_RISING);
		__raw_writel(1U << (INT_A9_M2A_6 % 32),
			VIC_INT_TO_REG_ADDR(VIC_INT_ENSET0, INT_A9_M2A_6));
	} else {
		for (i = 0; i < VIC_NUM_REGS; i++)
			writel(msm_irq_shadow_reg[i].int_en[1],
						VIC_INT_ENSET0 + (i * 4));
	}
	dsb();

	return 0;
}
Exemple #2
0
/*
 * Restore interrupt subsystem from sleep -- phase 1.
 * Configure interrupt hardware.
 */
void msm_irq_exit_sleep1(uint32_t irq_mask, uint32_t wakeup_reason,
	uint32_t pending_irqs)
{
	int i;

	msm_irq_ack(INT_A9_M2A_6);

	for (i = 0; i < VIC_NUM_REGS; i++) {
		writel(msm_irq_shadow_reg[i].int_type,
			VIC_INT_TYPE0 + i * 4);
		writel(msm_irq_shadow_reg[i].int_polarity,
			VIC_INT_POLARITY0 + i * 4);
		writel(msm_irq_shadow_reg[i].int_en[0],
			VIC_INT_EN0 + i * 4);
		writel(msm_irq_shadow_reg[i].int_select,
			VIC_INT_SELECT0 + i * 4);
	}

	writel(3, VIC_INT_MASTEREN);
	dsb();

	if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP)
		DPRINT_REGS(VIC_IRQ_STATUS, "%s %x %x %x now",
			__func__, irq_mask, pending_irqs, wakeup_reason);
}
Exemple #3
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));
}
Exemple #4
0
/*
 * Restore interrupt subsystem from sleep -- phase 2.
 * Poke the specified pending interrupts into interrupt hardware.
 */
void msm_irq_exit_sleep2(uint32_t irq_mask, uint32_t wakeup_reason,
	uint32_t pending)
{
	int i;

	if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP)
		DPRINT_REGS(VIC_IRQ_STATUS, "%s %x %x %x now",
			__func__, irq_mask, pending, wakeup_reason);

	for (i = 0; pending && i < ARRAY_SIZE(msm_irq_to_smsm); i++) {
		unsigned reg_offset = VIC_INT_TO_REG_ADDR(0, i);
		uint32_t reg_mask = 1UL << (i & 31);
		int smsm_irq = msm_irq_to_smsm[i];
		uint32_t smsm_mask;

		if (smsm_irq == 0)
			continue;

		smsm_mask = 1U << (smsm_irq - 1);
		if (!(pending & smsm_mask))
			continue;

		pending &= ~smsm_mask;
		if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_INT)
			DPRINT_REGS(VIC_IRQ_STATUS,
				"%s: irq %d still pending %x now",
				__func__, i, pending);
#ifdef DEBUG_INTERRUPT_TRIGGER
		if (readl(VIC_IRQ_STATUS0 + reg_offset) & reg_mask)
			writel(reg_mask, VIC_INT_CLEAR0 + reg_offset);
#endif
		if (readl(VIC_IRQ_STATUS0 + reg_offset) & reg_mask)
			continue;

		writel(reg_mask, VIC_SOFTINT0 + reg_offset);

		if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_INT_TRIGGER)
			DPRINT_REGS(VIC_IRQ_STATUS,
				"%s: irq %d need trigger, now",
				__func__, i);
	}
	dsb();
}
int msm_irq_enter_sleep2(bool modem_wake, int from_idle)
{
	int i, limit = 10;
	uint32_t pending[VIC_NUM_REGS];

	if (from_idle && !modem_wake)
		return 0;

	/*                                                            */
	WARN_ON_ONCE(!modem_wake && !from_idle);

	if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP)
		DPRINT_REGS(VIC_IRQ_STATUS, "%s change irq, pend", __func__);

	for (i = 0; i < VIC_NUM_REGS; i++) {
		pending[i] = readl(VIC_IRQ_STATUS0 + (i * 4));
		pending[i] &= msm_irq_shadow_reg[i].int_en[!from_idle];
	}

	/*
                                                          
                                                                        
  */
	pending[INT_A9_M2A_5 / 32] &= ~(1U << (INT_A9_M2A_5 % 32));

	for (i = 0; i < VIC_NUM_REGS; i++) {
		if (pending[i]) {
			if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_ABORT)
				DPRINT_ARRAY(pending, "%s abort",
						       __func__);
			return -EAGAIN;
		}
	}

	msm_irq_write_all_regs(VIC_INT_EN0, 0);

	while (limit-- > 0) {
		int pend_irq;
		int irq = readl(VIC_IRQ_VEC_RD);
		if (irq == -1)
			break;
		pend_irq = readl(VIC_IRQ_VEC_PEND_RD);
		if (msm_irq_debug_mask & IRQ_DEBUG_SLEEP_INT)
			printk(KERN_INFO "%s cleared int %d (%d)\n",
				__func__, irq, pend_irq);
	}

	if (modem_wake) {
		struct irq_data d = { .irq = INT_A9_M2A_6 };
		msm_irq_set_type(&d, IRQF_TRIGGER_RISING);
		__raw_writel(1U << (INT_A9_M2A_6 % 32),
			VIC_INT_TO_REG_ADDR(VIC_INT_ENSET0, INT_A9_M2A_6));
	} else {
		for (i = 0; i < VIC_NUM_REGS; i++)