Example #1
0
/*
 * Enable or disable interrupt on the rising edge of a event line
 */
void stm32_exti_enable_int(unsigned int line, int enable)
{
	if (line >= STM32F2_EXTI_NUM_LINES)
		goto out;

	if (enable) {
		stm32_exti_clear_pending(line);

		/* Enable trigger on rising edge */
		KINETIS_EXTI->rtsr |= (1 << line);
		/* Disable trigger on falling edge */
		KINETIS_EXTI->ftsr &= ~(1 << line);
		/* Enable interrupt for the event */
		KINETIS_EXTI->imr |= (1 << line);
	} else {
		/* Disable interrupt for the event */
		KINETIS_EXTI->imr &= ~(1 << line);
		/* Disable trigger on rising edge */
		KINETIS_EXTI->rtsr &= ~(1 << line);
		/* Disable trigger on falling edge */
		KINETIS_EXTI->ftsr &= ~(1 << line);

		stm32_exti_clear_pending(line);
	}

out:
	;
}
Example #2
0
/*
 * enable or disable interrupt
 * @line	EXTI line
 * @enable	enable(1) / disable(0)
 */
void stm32_exti_enable_int(unsigned int line, int enable)
{
	if (enable) {
		stm32_exti_clear_pending(line);

		/* Enable interrupt for the event */
		writel(readl(&STM32_EXTI->imr) | (1 << line),
			&STM32_EXTI->imr);
	} else {
		/* Disable interrupt for the event */
		writel(readl(&STM32_EXTI->imr) & ~(1 << line),
			&STM32_EXTI->imr);
		/* Disable trigger on rising edge */
		writel(readl(&STM32_EXTI->rtsr) & ~(1 << line),
			&STM32_EXTI->rtsr);
		/* Disable trigger on falling edge */
		writel(readl(&STM32_EXTI->ftsr) & ~(1 << line),
			&STM32_EXTI->ftsr);
		/* Clear pending events if any */
		stm32_exti_clear_pending(line);
	}

#if defined(DEBUG)
	printk("%s:%d,%d=%x\n",
		__func__, line, enable, readl(&STM32_EXTI->imr));
#endif
}
/*
 * Enable or disable the update interrupts
 */
static int stm32f2_rtc_update_irq_enable(
	struct device *dev, unsigned int enabled)
{
	struct stm32f2_rtc *rtc = dev_get_drvdata(dev);

	spin_lock_irq(&rtc->lock);

	if (enabled) {
		/* Use Alarm B to emulate update interrupts (1 Hz) */
		stm32f2_setup_alarm(1, -1, -1, -1, -1, -1);
		stm32f2_alarm_irq_enable(1, 1);
	} else {
		/* Disable interrupts from Alarm B */
		stm32f2_alarm_irq_enable(1, 0);

		/* Disable Alarm B */
		stm32f2_rtc_write_enable(1);
		STM32_RTC->cr &= ~STM32F2_RTC_CR_ALRBE_MSK;
		stm32f2_rtc_write_enable(0);

		stm32_exti_clear_pending(STM32F2_EXTI_LINE_RTC_ALARM);
	}

	spin_unlock_irq(&rtc->lock);
	return 0;
}
/*
 * RTC wakeup interrupt handler
 */
static irqreturn_t stm32f2_rtc_wakeup_irq(int irq, void *dev_id)
{
	struct stm32f2_rtc *rtc = (struct stm32f2_rtc *)dev_id;
	irqreturn_t rv;

	spin_lock(&rtc->lock);

	if (!(STM32_RTC->isr & STM32F2_RTC_ISR_WUTF_MSK) ||
	    !(STM32_RTC->cr & STM32F2_RTC_CR_WUTIE_MSK)) {
		rv = IRQ_NONE;
		goto out;
	}

	/* Clear event flag, otherwise new events won't be received */
	stm32f2_rtc_write_enable(1);
	STM32_RTC->isr &= ~STM32F2_RTC_ISR_WUTF_MSK;
	stm32f2_rtc_write_enable(0);

	stm32_exti_clear_pending(STM32F2_EXTI_LINE_RTC_WAKEUP);

	/* Pass periodic interrupt event to the kernel */
	rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);

	rv = IRQ_HANDLED;
out:
	spin_unlock(&rtc->lock);
	return rv;
}
Example #5
0
/**
 * @brief EXTI ISR handler
 *
 * Check EXTI lines in range @min @max for pending interrupts
 *
 * @param arg isr argument
 * @parram min low end of EXTI# range
 * @parram max low end of EXTI# range
 */
static void __stm32_exti_isr(int min, int max, void *arg)
{
	struct device *dev = arg;
	struct stm32_exti_data *data = dev->driver_data;
	int line;

	/* see which bits are set */
	for (line = min; line < max; line++) {
		/* check if interrupt is pending */
		if (stm32_exti_is_pending(line)) {
			/* clear pending interrupt */
			stm32_exti_clear_pending(line);

			/* run callback only if one is registered */
			if (!data->cb[line].cb) {
				continue;
			}

			data->cb[line].cb(line, data->cb[line].data);
		}
	}
}
/*
 * RTC alarm interrupt handler
 */
static irqreturn_t stm32f2_rtc_alarm_irq(int irq, void *dev_id)
{
	unsigned long events = 0;
	struct stm32f2_rtc *rtc = (struct stm32f2_rtc *)dev_id;
	u32 status;
	u32 enabled_irqs;

	spin_lock(&rtc->lock);

	status = STM32_RTC->isr;
	enabled_irqs = STM32_RTC->cr;

	stm32f2_rtc_write_enable(1);
	/* clear event flags, otherwise new events won't be received */
	STM32_RTC->isr &= ~(status &
		(STM32F2_RTC_ISR_ALRBF_MSK | STM32F2_RTC_ISR_ALRAF_MSK));
	stm32f2_rtc_write_enable(0);

	if ((status & STM32F2_RTC_ISR_ALRAF_MSK) &&
	    (enabled_irqs & STM32F2_RTC_CR_ALRAIE_MSK)) {
		/* Normal alarm interrupt */
		events |= (RTC_AF | RTC_IRQF);
	}

	if ((status & STM32F2_RTC_ISR_ALRBF_MSK) &&
	    (enabled_irqs & STM32F2_RTC_CR_ALRBIE_MSK)) {
		/* Update interrupt (1 Hz) */
		events |= (RTC_UF | RTC_IRQF);
	}

	if (events) {
		stm32_exti_clear_pending(STM32F2_EXTI_LINE_RTC_ALARM);
		rtc_update_irq(rtc->rtc_dev, 1, events);
	}

	spin_unlock(&rtc->lock);

	return events ? IRQ_HANDLED : IRQ_NONE;
}