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); }
/******************************************************************************* * 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; }