Beispiel #1
0
void
pcnet_reset(paddr_t base, int mem_mapped) {
	uintptr_t	io_base;

	io_base = startup_io_map(0x100, base);

	outle16(io_base + PCNET_RAP, PCNET_CSR0);
	outle16(io_base + PCNET_RDP, PCNET_CSR0_STOP);

	startup_io_unmap(io_base);
}
Beispiel #2
0
/*******************************************************************************
 * 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;
}