/**
 * \b archIntEnable
 *
 * Enable/unmask an interrupt in the interrupt controller.
 * @param[in] int_vector Interrupt vector to enable/disable
 * @param[in] enable TRUE=enable, FALSE=disable
 *
 * @retval ATOM_OK Success
 * @retval ATOM_ERROR Error
 */
int archIntEnable (int int_vector, int enable)
{
	CRITICAL_STORE;
    int status;

    /* Check vector is valid */
    if ((int_vector < 0) || (int_vector > DM36X_INTC_MAX_VEC))
    {
        /* Invalid vector number */
        status = ATOM_ERROR;
    }
    else
    {
        /* Valid vector, mask or unmask it using RMW */
		CRITICAL_START();
		if (enable)
		{
			/* Enable/unmask the interrupt */
	    	INTC_REG(((int_vector >= 32) ? DM36X_INTC_EINT1 : DM36X_INTC_EINT0))
					|= (1 << ((int_vector >= 32) ? (int_vector - 32) : int_vector));
		}
		else
		{
			/* Disable/mask the interrupt */
	    	INTC_REG(((int_vector >= 32) ? DM36X_INTC_EINT1 : DM36X_INTC_EINT0))
					&= ~(1 << ((int_vector >= 32) ? (int_vector - 32) : int_vector));
		}
		CRITICAL_END();
        status = ATOM_OK;
    }

    return (status);
}
Example #2
0
static void intc_mask_ack(struct irq_data *data)
{
	unsigned int irq = data->irq;
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned long handle = intc_get_ack_handle(irq);
	unsigned long addr;

	intc_disable(data);

	/* read register and write zero only to the associated bit */
	if (handle) {
		unsigned int value;

		addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
		value = intc_set_field_from_handle(0, 1, handle);

		switch (_INTC_FN(handle)) {
		case REG_FN_MODIFY_BASE + 0:	/* 8bit */
			__raw_readb(addr);
			__raw_writeb(0xff ^ value, addr);
			break;
		case REG_FN_MODIFY_BASE + 1:	/* 16bit */
			__raw_readw(addr);
			__raw_writew(0xffff ^ value, addr);
			break;
		case REG_FN_MODIFY_BASE + 3:	/* 32bit */
			__raw_readl(addr);
			__raw_writel(0xffffffff ^ value, addr);
			break;
		default:
			BUG();
			break;
		}
	}
}
Example #3
0
static int intc_set_type(struct irq_data *data, unsigned int type)
{
	unsigned int irq = data->irq;
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
	struct intc_handle_int *ihp;
	unsigned long addr;

	if (!value)
		return -EINVAL;

	value &= ~SENSE_VALID_FLAG;

	ihp = intc_find_irq(d->sense, d->nr_sense, irq);
	if (ihp) {
		/* PINT has 2-bit sense registers, should fail on EDGE_BOTH */
		if (value >= (1 << _INTC_WIDTH(ihp->handle)))
			return -EINVAL;

		addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
		intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
	}

	return 0;
}
/**
 * \b __interrupt_dispatcher
 *
 * Interrupt dispatcher: determines the source of the IRQ and calls
 * the appropriate ISR.
 *
 * Note that any ISRs which call Atomthreads OS routines that can
 * cause rescheduling of threads must be surrounded by calls to
 * atomIntEnter() and atomIntExit().
 *
 */
void
__interrupt_dispatcher (void) 
{
    uint32_t vector;
    uint32_t irqentry;

    /* Read IRQENTRY register to determine the source of the interrupt */
    irqentry = INTC_REG(DM36X_INTC_IRQENTRY);

    /* Check for spurious interrupt */
    if (irqentry == 0)
    {
        /* Spurious interrupt */
        uart_write_halt ("Spurious IRQ\n");
    }
    else
    {
        /* Translate from vector address to vector number */
        vector = (INTC_REG(DM36X_INTC_IRQENTRY) / 4) - 1;

        /* Check vector number is valid */
        if ((vector > 0) && (vector <= DM36X_INTC_MAX_VEC) && (isr_handlers[vector] != NULL))
        {
            /* Ack the interrupt immediately, could get scheduled out below */
            INTC_REG(((vector >= 32) ? DM36X_INTC_IRQ1 : DM36X_INTC_IRQ0)) = (1 << ((vector >= 32) ? (vector - 32) : vector));

            /*
             * Let the Atomthreads kernel know we're about to enter an OS-aware
             * interrupt handler which could cause scheduling of threads.
             */
            atomIntEnter();

            /* Call the registered ISR */
            isr_handlers[vector](vector);

            /* Call the interrupt exit routine */
            atomIntExit(TRUE);
        }
        else
        {
            /* Unexpected vector */
            uart_write_halt ("Unexpected IRQ vector\n");
        }

    }

}
Example #5
0
void intc_balancing_disable(unsigned int irq)
{
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned long handle = dist_handle[irq];
	unsigned long addr;

	if (irq_balancing_disabled(irq) || !handle)
		return;

	addr = INTC_REG(d, _INTC_ADDR_D(handle), 0);
	intc_reg_fns[_INTC_FN(handle)](addr, handle, 0);
}
Example #6
0
static void intc_enable_disable(struct intc_desc_int *d,
				unsigned long handle, int do_enable)
{
	unsigned long addr;
	unsigned int cpu;
	unsigned long (*fn)(unsigned long, unsigned long,
		   unsigned long (*)(unsigned long, unsigned long,
				     unsigned long),
		   unsigned int);

	if (do_enable) {
		for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
			addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
			fn = intc_enable_noprio_fns[_INTC_MODE(handle)];
			fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
		}
	} else {
		for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) {
			addr = INTC_REG(d, _INTC_ADDR_D(handle), cpu);
			fn = intc_disable_fns[_INTC_MODE(handle)];
			fn(addr, handle, intc_reg_fns[_INTC_FN(handle)], 0);
		}
	}
}
Example #7
0
void _intc_enable(struct irq_data *data, unsigned long handle)
{
	unsigned int irq = data->irq;
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned long addr;
	unsigned int cpu;

	for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_E(handle)); cpu++) {
#ifdef CONFIG_SMP
		if (!cpumask_test_cpu(cpu, data->affinity))
			continue;
#endif
		addr = INTC_REG(d, _INTC_ADDR_E(handle), cpu);
		intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\
						    [_INTC_FN(handle)], irq);
	}

	intc_balancing_enable(irq);
}
Example #8
0
static int intc_set_type(struct irq_data *data, unsigned int type)
{
	unsigned int irq = data->irq;
	struct intc_desc_int *d = get_intc_desc(irq);
	unsigned char value = intc_irq_sense_table[type & IRQ_TYPE_SENSE_MASK];
	struct intc_handle_int *ihp;
	unsigned long addr;

	if (!value)
		return -EINVAL;

	ihp = intc_find_irq(d->sense, d->nr_sense, irq);
	if (ihp) {
		addr = INTC_REG(d, _INTC_ADDR_E(ihp->handle), 0);
		intc_reg_fns[_INTC_FN(ihp->handle)](addr, ihp->handle, value);
	}

	return 0;
}
/**
 * \b low_level_init
 *
 * Initializes the PIC and starts the system timer tick interrupt.
 *
 */
int
low_level_init (void)
{
    /* Initialise TIMER0 registers for interrupt 100 times per second */

    /* Reset & disable all TIMER0 timers */
    TIMER0_REG(DM36X_TIMER_INTCTL_STAT) = 0;    /* Disable interrupts */
    TIMER0_REG(DM36X_TIMER_TCR) = 0;            /* Disable all TIMER0 timers */
    TIMER0_REG(DM36X_TIMER_TGCR) = 0;           /* Put all TIMER0 timers in reset */
    TIMER0_REG(DM36X_TIMER_TIM12) = 0;          /* Clear Timer 1:2 */

    /* Set up Timer 1:2 in 32-bit unchained mode */
    TIMER0_REG(DM36X_TIMER_TGCR) = (1 << 2);    /* Select 32-bit unchained mode (TIMMODE) */
    TIMER0_REG(DM36X_TIMER_TGCR) |= (1 << 0);   /* Remove Timer 1:2 from reset (TIM12RS) */
    TIMER0_REG(DM36X_TIMER_PRD12) = (TIMER_CLK / SYSTEM_TICKS_PER_SEC) - 1;     /* Set period to 100 ticks per second (PRD12) */
    TIMER0_REG(DM36X_TIMER_TCR) |= (0 << 8);    /* Select external clock source for Timer 1:2 (CLKSRC12) */

    /* Enable interrupts */
    TIMER0_REG(DM36X_TIMER_INTCTL_STAT) = (1 << 1) | (1 << 0);  /* Enable/ack Compare/Match interrupt for Timer 1:2 */

    /* Enable timer */
    TIMER0_REG(DM36X_TIMER_TCR) |= (2 << 6);    /* Enable Timer 1:2 continuous (ENAMODE12) */

    /* Initialise INTC interrupt controller (all at lowest priority 7) */
    INTC_REG(DM36X_INTC_PRI0) = 0x77777777;
    INTC_REG(DM36X_INTC_PRI1) = 0x77777777;
    INTC_REG(DM36X_INTC_PRI2) = 0x77777777;
    INTC_REG(DM36X_INTC_PRI3) = 0x77777777;
    INTC_REG(DM36X_INTC_PRI4) = 0x77777777;
    INTC_REG(DM36X_INTC_PRI5) = 0x77777777;
    INTC_REG(DM36X_INTC_PRI6) = 0x77777777;
    INTC_REG(DM36X_INTC_PRI7) = 0x77777777;
    INTC_REG(DM36X_INTC_INTCTL) = 0;
    INTC_REG(DM36X_INTC_EABASE) = 0;
    INTC_REG(DM36X_INTC_EINT0) = 0;
    INTC_REG(DM36X_INTC_EINT1) = 0;

    /* Ack TINT0 IRQ in INTC interrupt controller */
    INTC_REG(DM36X_INTC_IRQ1) = (1 << (DM36X_INTC_VEC_TINT0 - 32));

    /* Enable TINT0 IRQ in INTC interrupt controller */
    INTC_REG(DM36X_INTC_EINT1) |= (1 << (DM36X_INTC_VEC_TINT0 - 32));

    return 0 ;
}