コード例 #1
0
/*
 * init_qtime
 * 
 * Initialize the qtime entry. The timer to use has been added to the HWINFO
 * section as "qtimer"
*/
void init_qtime()
{
	struct qtime_entry	*qtime = alloc_qtime();		// alloc_qtime() call rtc_time()
	unsigned hwi_off = hwi_find_device("qtimer", 0);
    hwiattr_timer_t qtimer_attr;
    int r = hwiattr_get_timer(hwi_off, &qtimer_attr);
    long best_freq;
    unsigned hires_timer;
    unsigned i;

    /* both asserts tells us which operation failed */
    ASSERT(hwi_off != HWI_NULL_OFF);
    ASSERT(r == EOK);
    ASSERT(qtimer_attr.common.location.len > 0);
    ASSERT(qtimer_attr.common.location.base != NULL);
    ASSERT(qtimer_attr.num_clks > 0);

	qtime->intr = hwitag_find_ivec(hwi_off, NULL);
	ASSERT(qtime->intr != HWI_ILLEGAL_VECTOR);
	
	/* if multiple clock sources have been provided, choose the highest resolution */
	best_freq = 0;
	hires_timer = 0;	// we already know there is at least 1 clock source (see ASSERT above)
	for (i=0; i<qtimer_attr.num_clks; i++)
	{
		long freq = hwitag_find_clkfreq(hwi_off, &i);
		if ((i > 0) && (freq > best_freq)) {
			hires_timer = i;
			best_freq = freq;
		}
	}
	ASSERT(hires_timer <= 1);	// I know CLKSEL is only 1 bit (ie. only 2 clock sources)

	qtime->timer_scale = -15;
	i = hires_timer;
	qtime->cycles_per_sec = (uint64_t)hwitag_find_clkfreq(hwi_off, &i);	// don't pass hires_timer as its changed by the call
	ASSERT(qtime->cycles_per_sec > 0);
	qtime->timer_rate = QTIME_CLK_RATE(qtime->timer_scale, qtime->cycles_per_sec);
// kprintf("cps = %x %x, rate = %d\n", ((uint32_t *)&qtime->cycles_per_sec)[0], ((uint32_t *)&qtime->cycles_per_sec)[1], qtime->timer_rate);
	/* Map the registers (timer_base) and select the hires_timer clock source and periodic mode */
	timer_base = startup_io_map(qtimer_attr.common.location.len, qtimer_attr.common.location.base);
	ASSERT(timer_base != NULL);
	out32(timer_base + EP93xx_TIMER_LOAD, UINT32_MAX);	// preset the LOAD register
// kprintf("clksel(%d) = 0x%x\n", hires_timer, EP93xx_TIMER_CTRL_CLKSEL(hires_timer));
	out32(timer_base + EP93xx_TIMER_CTRL,
			EP93xx_TIMER_CTRL_CLKSEL(hires_timer) |		// hires_timer holds which clock to select
			EP93xx_TIMER_CTRL_CLKMODE_PERIODIC);

	timer_start = timer_start_ep93xx;
	timer_diff  = timer_diff_ep93xx;

	add_callout_array(timer_callouts, sizeof(timer_callouts));
	
	/* start the timer */
	timer_start();
}
コード例 #2
0
ファイル: pic_ep9301.c プロジェクト: nguyenvuhung/SDP_QNX_BBB
/*******************************************************************************
 * ep9301_config_pic
 *
 * This routine will initialize the 2 Vectored Interrupt Controllers in the
 * Cirrus Logic EP93xx family of processors.
 *
 * In order to handle the number of interrupts within the EP93xx, 2 separate
 * interrupt controllers are cascaded together to form 1 larger controller.
 * There is not much documentation on how this cascading of interrupts works as
 * it is not a true cascade. There is some logic which allows the second
 * controller to be daisy chained through the first controller which is actually
 * connected to the processor. There is no documentation on how prioritization
 * works for non vectored interrupts or the prioritization of the second
 * controller relative to the first. The only remote suggestion that they are
 * handled as 32 priority interrupts starting with controller 1 followed by
 * controller 2 is on page 118 of the User Guide which says ...
 *
 * 		"Vector Control Registers. The 32 VICxVectCntl0 through VICxVectCnt15
 * 		 registers select the interrupt source for the vectored interrupt."
 *
 * My interpretation is that vector 0 through 15 on controller 1 followed by
 * vector 0 through 15 on controller 2 is the prioritization.
 *
 * This still leaves the problem that we don't know which controller to look
 * at first without looking at the status register for each ... which implies
 * that the prioritization is completely under software control. In other words,
 * software must decide to either read controller 1 or 2 status first, effectively
 * prioritizing one set of 32 interrupts over the other 32. Then, because some of
 * the interrupts are not vectored, we must choose bits in the status register.
 * However, if the vector address read when none of the interrupts programmed as
 * vectored interrupts is the default vector, then the sequence can flow as
 * follows (I will prioritize controller 1 interrupts over controller 2)
 *
 * 		if (vic1_status != 0)
 * 		{
 * 			if (vic1_vector != default vector)
 * 				id = vect_table[vic1_vector]
 * 			else
 * 				id = first bit set in vic1_status
 * 		}
 * 		else if (vic2_status != 0)
 * 		{
 * 			if (vic1_vector != default vector)
 * 				id = vect_table[vic2_vector]
 * 			else
 * 				id = first bit set in vic2_status
 * 		}
 * 		else
 * 			spurious interrupt
 *
 * 		return id
 *
 * This is all greatly complicated by the fact that only 1/2 of the interrupts
 * in each controller are vectored and prioritized not to mention the
 * prioritization between IRQ and FIQ interrupts.
 * To properly support prioritized interrupts and decouple them from the assigned
 * internal id's is going to require some more thought so for now I am not going
 * to use the hardware prioritization of the vectored interrupts and instead
 * simply do a first bit set prioritization of interrupts as follows
 *
 * 			VIC1, 31 -> 0
 * 			VIC2, 31 -> 0
 *
 * implying that in the case of multiple occurring interrupts, VIC1, interrupt
 * 31 (documented interrupt source 31) is the highest in the system and VIC2,
 * interrupt 0 (documented interrupt source 32) is the lowest.
 *
 * Additionally, FIQ is not going to be used for now.
 *
 * Returns: the number of interrupt vectors assigned
 *
 * Implementation Note:
 *
*/
uint32_t ep9301_config_pic(uint32_t os_vector_base, uint32_t pic_vector_base, vector_tbl_t *reg_vectors)
{
	uintptr_t base = startup_io_map((EP93xx_VIC_CTRL2_BASE - EP93xx_VIC_CTRL1_BASE) + EP93xx_VIC_CTRL2_SIZE, EP93xx_VIC_CTRL1_BASE);
	unsigned hwi_off;
	unsigned i;

	/*
	 * check the peripheral ID registers. We will assert on the truth of valid_pic_id() since a change
	 * may suggest a difference in the device behaviour which may need to be reflected in a
	 * code change
	*/
	ASSERT(valid_pic_id());
	ASSERT(pic_vector_base == os_vector_base);	// re-mapping not supported (yet)

	reg_vectors->start = pic_vector_base;
	reg_vectors->num = 0;

	/* set all the vector bases */
	intrs[0].vector_base = os_vector_base;
	ASSERT(intrs[0].num_vectors > 0);
	reg_vectors->num += intrs[0].num_vectors;
	for (i=1; i<NUM_ELTS(intrs); i++)
	{
		intrs[i].vector_base = intrs[i - 1].vector_base + intrs[i - 1].num_vectors;
		ASSERT(intrs[i].num_vectors > 0);
		reg_vectors->num += intrs[i].num_vectors;
	}
	/* add the interrupt info section */
	add_interrupt_array(intrs, sizeof(intrs));

	/* disable and clear all interrupts. Note that we do not check EP93xx_VIC_INT_RAW because
	 * some devices do actually have interrupts asserted and this is reflected in the RAW register(s) */
	out32(VIC1(EP93xx_VIC_INT_CLEAR), 0xFFFFFFFFU);
	out32(VIC1(EP93xx_VIC_SWINT_CLEAR), 0xFFFFFFFFU);
	ASSERT(in32(VIC1(EP93xx_VIC_INT_ENABLE)) == 0);
	ASSERT(in32(VIC1(EP93xx_VIC_SWINT_ENABLE)) == 0);
	ASSERT(in32(VIC1(EP93xx_VIC_IRQ_STATUS)) == 0);
	ASSERT(in32(VIC1(EP93xx_VIC_FIQ_STATUS)) == 0);

	out32(VIC2(EP93xx_VIC_INT_CLEAR), 0xFFFFFFFFU);
	out32(VIC2(EP93xx_VIC_SWINT_CLEAR), 0xFFFFFFFFU);
	ASSERT(in32(VIC2(EP93xx_VIC_INT_ENABLE)) == 0);
	ASSERT(in32(VIC2(EP93xx_VIC_SWINT_ENABLE)) == 0);
	ASSERT(in32(VIC2(EP93xx_VIC_IRQ_STATUS)) == 0);
	ASSERT(in32(VIC2(EP93xx_VIC_FIQ_STATUS)) == 0);

	/* set privileged access to interrupt controller registers */
	out32(VIC1(EP93xx_VIC_PROTECTION), 0x0);
	out32(VIC2(EP93xx_VIC_PROTECTION), 0x0);

	/* by default, all interrupts will generate an IRQ (FIQ not used) */
	out32(VIC1(EP93xx_VIC_INT_SELECT), 0);
	out32(VIC2(EP93xx_VIC_INT_SELECT), 0);

	/* place HWI_ILLEGAL_VECTOR into the default vector(s) */
	out32(VIC1(EP93xx_VIC_VEC_ADDR_DFLT), HWI_ILLEGAL_VECTOR);
	out32(VIC2(EP93xx_VIC_VEC_ADDR_DFLT), HWI_ILLEGAL_VECTOR);

	/* disable the use of vectored interrupts for now */
	in32(VIC1(EP93xx_VIC_VEC_ADDR_CURR));
	out32(VIC1(EP93xx_VIC_VEC_ADDR_CURR), 0);
	in32(VIC2(EP93xx_VIC_VEC_ADDR_CURR));
	out32(VIC2(EP93xx_VIC_VEC_ADDR_CURR), 0);
	for (i=0; i<16; i++)
	{
		out32(VIC1(EP93xx_VIC_VEC_ADDR(i)), HWI_ILLEGAL_VECTOR);
		out32(VIC1(EP93xx_VIC_VEC_CTRL(i)), 0);
		out32(VIC2(EP93xx_VIC_VEC_ADDR(i)), HWI_ILLEGAL_VECTOR);
		out32(VIC2(EP93xx_VIC_VEC_CTRL(i)), 0);
	}

	/* TIMER1 - interrupt 4 */
	hwitag_set_avail_ivec(hwi_find_device(EP93xx_HWI_TIMER, 0), -1, 4);

	/* TIMER2 - interrupt 5 */
	hwitag_set_avail_ivec(hwi_find_device(EP93xx_HWI_TIMER, 1), -1, 5);

	/* TIMER3 - interrupt 51 */
	hwitag_set_avail_ivec(hwi_find_device(EP93xx_HWI_TIMER, 2), -1, 51);

	/* WATCHDOG TIMER - interrupt 36 */
	hwitag_set_avail_ivec(hwi_find_device(EP93xx_HWI_WDOG, 0), -1, 36);

	/* DMA channels - Note that the order of vector assignment in the HWINFO section will be
	 * memory to memory 0 - 17
	 * memory to memory 1 - 18
	 * memory to peripheral 0 - 7
	 * memory to peripheral 1 - 8
	 * memory to peripheral 2 - 9
	 * memory to peripheral 3 - 10
	 * memory to peripheral 4 - 11
	 * memory to peripheral 5 - 12
	 * memory to peripheral 6 - 13
	 * memory to peripheral 7 - 14
	 * memory to peripheral 8 - 15
	 * memory to peripheral 9 - 16
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_DMA, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 17);
		hwitag_set_ivec(hwi_off, 1, 18);
		hwitag_set_ivec(hwi_off, 2, 7);
		hwitag_set_ivec(hwi_off, 3, 8);
		hwitag_set_ivec(hwi_off, 4, 9);
		hwitag_set_ivec(hwi_off, 5, 10);
		hwitag_set_ivec(hwi_off, 6, 11);
		hwitag_set_ivec(hwi_off, 7, 12);
		hwitag_set_ivec(hwi_off, 8, 13);
		hwitag_set_ivec(hwi_off, 9, 14);
		hwitag_set_ivec(hwi_off, 10, 15);
		hwitag_set_ivec(hwi_off, 11, 16);
	}

	/* GPIO
	 * 19 of the EP9301 GPIO ports are interruptible and are handled via a
	 * cascaded interrupt entry. In order for devices specifically connected to
	 * those GPIO pins to have a driver InterruptAttach() we provide the assigned
	 * vector ranges with 3 irqrange tags corresponding to the PORTA, PORTB and
	 * PORTF interrupting port pins respectively. Within the range tag assignments,
	 * the 'irq' field corresponds to the LSb (pin 0 of the port) and 'irq' + 'num' - 1
	 * corresponds to the MSb (pin 7 of the port).
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_GPIO, 0)) != HWI_NULL_OFF)
	{
		const unsigned num_pAB_vectors = intrs[1].num_vectors / 2;
		const unsigned num_pF_vectors = intrs[2].num_vectors + intrs[3].num_vectors + intrs[4].num_vectors;
		hwitag_set_ivecrange(hwi_off, 0, intrs[1].vector_base, num_pAB_vectors);	// PORT A
		hwitag_set_ivecrange(hwi_off, 1, intrs[1].vector_base + num_pAB_vectors, num_pAB_vectors);	// PORT B
		hwitag_set_ivecrange(hwi_off, 2, intrs[2].vector_base, num_pF_vectors);	// PORT F
	}

	/* UART1 - Note that the order of vector assignment in the HWINFO section will be
	 * combined - 52
	 * Rx - 23
	 * Tx - 24
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_UART, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 52);
		hwitag_set_ivec(hwi_off, 1, 23);
		hwitag_set_ivec(hwi_off, 2, 24);
	}

	/* UART2 - Note that the order of vector assignment in the HWINFO section will be
	 * combined - 54
	 * Rx - 25
	 * Tx - 26
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_UART, 1)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 54);
		hwitag_set_ivec(hwi_off, 1, 25);
		hwitag_set_ivec(hwi_off, 2, 26);
	}

	/* EXTERNAL IRQ - 2 interrupts 32, 33 and 40 for IQR0, IRQ1 and IRQ2 respectively */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_EXT_IRQ, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 32);
		hwitag_set_ivec(hwi_off, 1, 33);
		hwitag_set_ivec(hwi_off, 2, 40);
	}

	/* RTC - Note that the order of vector assignment in the HWINFO section will be
	 * rtc - 37
	 * 64 Hz clock - 35
	 * 1 Hz clock - 42 (edge sensitive)
	*/
	if ((hwi_off = hwi_find_device(EP93xx_HWI_RTC, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 37);
		hwitag_set_ivec(hwi_off, 1, 35);
		hwitag_set_ivec(hwi_off, 2, 42);
	}

	/* IrDA Device - 38 */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_IrDA, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 38);
	}

	/* Ethernet Device */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_ENET, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 39);
	}

	/* SSP - Note that the order of vector assignment in the HWINFO section will be
	 * combined - 53
	 * Rx - 45
	 * Tx - 46
	*/
	if ((hwi_off = hwi_find_bus(EP93xx_HWI_SSP, 0)) != HWI_NULL_OFF)
	{
		hwitag_set_ivec(hwi_off, 0, 53);
		hwitag_set_ivec(hwi_off, 1, 45);
		hwitag_set_ivec(hwi_off, 2, 46);
	}

	/* USB host controller - 56 */
	if ((hwi_off = hwi_find_bus(EP93xx_HWI_USB, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 56);
	}

	/* I2S device - 60 */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_I2S, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 60);
	}

	/* ACC (AC97) device - 6 */
	if ((hwi_off = hwi_find_device(EP93xx_HWI_AUDIO, 0)) != HWI_NULL_OFF) {
		hwitag_set_avail_ivec(hwi_off, 0, 6);
	}

	startup_io_unmap(base);

	return reg_vectors->num;
}
コード例 #3
0
ファイル: hwi_imx51.c プロジェクト: nguyenvuhung/SDP_QNX_BBB
void hwi_imx51()
{
        unsigned hwi_bus_internal = 0;

        /* add I2C (unless directed not to) */
        {
                unsigned hwi_off;
                hwiattr_i2c_t attr = HWIATTR_I2C_T_INITIALIZER;
              
                HWIATTR_I2C_SET_NUM_IRQ(&attr, 1);
             
                /* create i2c0 and set the clock source */
                HWIATTR_I2C_SET_LOCATION(&attr, MX51_I2C1_BASE, MX51_I2C_SIZE, 0, hwi_find_as(MX51_I2C1_BASE, 1));
                hwi_off = hwibus_add_i2c(hwi_bus_internal, &attr);
                ASSERT(hwi_find_unit(hwi_off) == 0);
		hwitag_set_ivec(hwi_off, 0, MX51_I2C1_IRQ);


                /* create i2c1 and set the clock source */
                HWIATTR_I2C_SET_LOCATION(&attr, MX51_I2C2_BASE, MX51_I2C_SIZE, 0, hwi_find_as(MX51_I2C2_BASE, 1));
                hwi_off = hwibus_add_i2c(hwi_bus_internal, &attr);
                ASSERT(hwi_find_unit(hwi_off) == 1);
		hwitag_set_ivec(hwi_off, 0, MX51_I2C2_IRQ);
        }

	/* add  UART */
        {
                unsigned hwi_off;
                hwiattr_uart_t attr = HWIATTR_UART_T_INITIALIZER;
				struct hwi_inputclk clksrc = {.clk = uart_clock, .div = 16};
				
                HWIATTR_UART_SET_NUM_IRQ(&attr, 1);
				HWIATTR_UART_SET_NUM_CLK(&attr, 1);

                /* create uart0 */
                HWIATTR_UART_SET_LOCATION(&attr, MX51_UART1_BASE, MX51_UART_SIZE, 0, hwi_find_as(MX51_UART1_BASE, 1));
                hwi_off = hwidev_add_uart(IMX51_HWI_UART, &attr, hwi_bus_internal);
                ASSERT(hwi_find_unit(hwi_off) == 0);
		hwitag_set_ivec(hwi_off, 0, MX51_UART1_INTR);
		hwitag_set_inputclk(hwi_off, 0, &clksrc);

                /* historically the UART's were called 'mxl' so add these synonyms */
                hwi_add_synonym(hwi_find_device(IMX51_HWI_UART, 0), "sermxl");
        }

	/*add the FEC */
	{
		unsigned hwi_off;
		hwiattr_enet_t attr = HWIATTR_ENET_T_INITIALIZER;
		
		HWIATTR_USB_SET_NUM_IRQ(&attr, 1);
        	/* create eTSEC0 and set the PHY address */
		HWIATTR_ENET_SET_LOCATION(&attr, MX51_FEC_BASE, 0x4000, 0, hwi_find_as(MX51_FEC_BASE, 1));
		hwi_off = hwidev_add_enet("fec", &attr, hwi_bus_internal);
		ASSERT(hwi_find_unit(hwi_off) == 0);
		hwitag_set_avail_ivec(hwi_off, 0, MX51_FEC_INTR);
   }


	/* add 1 USB controller */
	{
                unsigned hwi_off;
                hwiattr_usb_t attr = HWIATTR_USB_T_INITIALIZER;

                HWIATTR_USB_SET_NUM_IRQ(&attr, 1);
               
                /* create usb0 */
                HWIATTR_USB_SET_LOCATION(&attr, MX51_USBH1_BASE, MX51_USB_SIZE, 0, hwi_find_as(MX51_USBH1_BASE, 1));
                hwi_off = hwibus_add_usb(hwi_bus_internal, &attr);
                ASSERT(hwi_off != HWI_NULL_OFF);
		hwitag_set_avail_ivec(hwi_off, 0, MX51_USB_INTR);

        }

	/* add 1 sdma controllers */
        {
                unsigned hwi_off;
                hwiattr_dma_t attr = HWIATTR_DMA_T_INITIALIZER;

                HWIATTR_DMA_SET_NUM_IRQ(&attr, 1);

                /* create DMA controller 0 */
                HWIATTR_USB_SET_LOCATION(&attr, MX51_SDMA_BASE, MX51_SDMA_SIZE, 0, hwi_find_as(MX51_SDMA_BASE, 1));
                hwi_off = hwidev_add_dma(IMX51_HWI_DMA, &attr, hwi_bus_internal);
                ASSERT(hwi_find_unit(hwi_off) == 0);
		hwitag_set_avail_ivec(hwi_off, 0, MX51_SDMA_INTRU);

	     }

	/* add the SSI device */
	{
		unsigned hwi_off = hwidev_add("ssi", hwi_devclass_NONE, HWI_NULL_OFF);
		hwiattr_common_t attr = HWIATTR_COMMON_INITIALIZER;

		ASSERT(hwi_off != HWI_NULL_OFF);

		HWIATTR_SET_LOCATION(&attr, MX51_SSI1_BASE, MX51_SSI_SIZE, 0, hwi_find_as(MX51_SSI1_BASE, 1));
		hwitag_add_common(hwi_off, &attr);
	}

	/*add the SDRAM */
	{
		unsigned hwi_off = hwidev_add("sdram", hwi_devclass_NONE, HWI_NULL_OFF);
		hwiattr_common_t attr = HWIATTR_COMMON_INITIALIZER;

		ASSERT(hwi_off != HWI_NULL_OFF);

		HWIATTR_SET_LOCATION(&attr, MX51_SDRAM_BASE, MX51_SDRAM_SIZE, 0, hwi_find_as(MX51_SDRAM_BASE, 1));
		hwitag_add_common(hwi_off, &attr);
	}


       	/* add the WATCHDOG device */
	{
		unsigned hwi_off;
		hwiattr_timer_t attr = HWIATTR_TIMER_T_INITIALIZER;
		const struct hwi_inputclk clksrc_kick = {.clk = 10, .div = 1};
	
		HWIATTR_TIMER_SET_NUM_CLK(&attr, 1);

		HWIATTR_TIMER_SET_LOCATION(&attr, MX51_WDOG1_BASE, MX51_WDOG_SIZE, 0, hwi_find_as(MX51_WDOG1_BASE, 1));
		hwi_off = hwidev_add_timer("wdog", &attr,  HWI_NULL_OFF);
		ASSERT(hwi_off != HWI_NULL_OFF);
		hwitag_set_inputclk(hwi_off, 0, (struct hwi_inputclk *)&clksrc_kick);		
	}
		
}

#if defined(__QNXNTO__) && defined(__USESRCVERSION)
#include <sys/srcversion.h>
__SRCVERSION("$URL: http://svn/product/branches/6.6.0/trunk/hardware/startup/lib/arm/hwi_imx51.c $ $Rev: 680332 $")