More UIC stuff:

* Read daisychain interrupts from fdt
* Interrupts are now masked/unmasked correctly during handling
* Some more smaller fixes
This commit is contained in:
Jens Kehne 2010-06-30 14:30:18 +02:00
parent 7456802898
commit 75811bec07
2 changed files with 56 additions and 49 deletions

View File

@ -76,14 +76,8 @@ void SECTION (".init") intctrl_t::init_arch()
if (prop->get_word(1) != 9)
panic("Invalid number of control registers found (%d)",prop->get_word(1));
#if defined(PPC440EPx)
num_irqs=30;
#else
num_irqs=31;
#endif
TRACE_INIT("UIC0: DCR base 0x%x, %d interrupts\n",
UIC0_DCR_BASE, num_irqs);
UIC0_DCR_BASE, UIC0_NUM_IRQS);
//Controller 1
printf("Looking for interrupt controller 1... ");
@ -115,10 +109,15 @@ void SECTION (".init") intctrl_t::init_arch()
if (prop->get_word(1) != 9)
panic("UIC1: Invalid number of control registers found (%d)",prop->get_word(1));
num_irqs=32;
prop = fdt->find_property_node(hdr, "interrupts");
if (!prop)
panic("UIC1: Couldn't determine daisychain interrupts");
uic1_dchain_mask = 1 << (31 - prop->get_word(0));
uic1_dchain_mask |= 1 << (31 - prop->get_word(2));
TRACE_INIT("UIC1: DCR base 0x%x, %d interrupts\n",
UIC1_DCR_BASE, num_irqs);
UIC1_DCR_BASE, UIC1_NUM_IRQS);
//Controller 2
#if defined(PPC440EPx)
@ -151,10 +150,15 @@ void SECTION (".init") intctrl_t::init_arch()
if (prop->get_word(1) != 9)
panic("UIC2: Invalid number of control registers found (%d)",prop->get_word(1));
num_irqs=32;
prop = fdt->find_property_node(hdr, "interrupts");
if (!prop)
panic("UIC2: Couldn't determine daisychain interrupts");
uic2_dchain_mask = 1 << (31 - prop->get_word(0));
uic2_dchain_mask |= 1 << (31 - prop->get_word(2));
TRACE_INIT("UIC2: DCR base 0x%x, %d interrupts\n",
UIC2_DCR_BASE, num_irqs);
UIC2_DCR_BASE, UIC2_NUM_IRQS);
#endif //PPC440EPx
@ -305,10 +309,10 @@ void intctrl_t::mask(word_t irq)
/* really disable interrupt */
mtdcr(UIC2_ER, (~intMask) & mfdcr(UIC2_ER));
lock.unlock(); /* re-enable interrupts */
mtdcr(UIC2_SR, intMask); /* clear pending interrupts */
mtdcr(UIC0_SR, 0x0000000c); /* clear dchained UIC1 ints */
mtdcr(UIC0_SR, uic2_dchain_mask); /* clear dchained UIC1 ints */
lock.unlock(); /* re-enable interrupts */
}
else if (irq > INT_LEVEL_UIC0_MAX) /* For UIC1 */
#else
@ -329,10 +333,11 @@ void intctrl_t::mask(word_t irq)
/* really disable interrupt */
mtdcr(UIC1_ER, (~intMask) & mfdcr(UIC1_ER));
mtdcr(UIC1_SR, intMask); /* clear pending interrupts */
mtdcr(UIC0_SR, uic1_dchain_mask); /* clear dchained UIC1 ints */
lock.unlock(); /* re-enable interrupts */
mtdcr(UIC1_SR, intMask); /* clear pending interrupts */
mtdcr(UIC0_SR, 0x00000003); /* clear dchained UIC1 ints */
}
else
{
@ -349,9 +354,9 @@ void intctrl_t::mask(word_t irq)
/* really disable interrupt */
mtdcr(UIC0_ER, (~intMask) & mfdcr(UIC0_ER));
lock.unlock(); /* re-enable interrupts */
mtdcr(UIC0_SR, intMask); /* clear pending interrupts */
lock.unlock(); /* re-enable interrupts */
}
return;
@ -372,7 +377,7 @@ bool intctrl_t::unmask(word_t irq)
intMask = 1 << (31 - irq) ;
mtdcr(UIC2_SR, intMask); /* clear pending interrupts */
mtdcr(UIC0_SR, 0x0000000c); /* clear pending dchain */
mtdcr(UIC0_SR, uic2_dchain_mask); /* clear pending dchain */
/*
* enable the interrupt level
@ -385,7 +390,7 @@ bool intctrl_t::unmask(word_t irq)
mtdcr(UIC2_ER, intMask | mfdcr(UIC2_ER));
/* Enable dchain*/
mtdcr(UIC0_ER, 0x0000000c | mfdcr(UIC0_ER));
mtdcr(UIC0_ER, uic2_dchain_mask | mfdcr(UIC0_ER));
lock.unlock(); /* re-enable interrupts */
@ -398,7 +403,7 @@ bool intctrl_t::unmask(word_t irq)
irq -= INT_LEVEL_UIC1_MIN ;
intMask = 1 << (31 - irq) ;
mtdcr(UIC1_SR, intMask); /* clear pending interrupts */
mtdcr(UIC0_SR, 0x00000003); /* clear pending dchain */
mtdcr(UIC0_SR, uic1_dchain_mask); /* clear pending dchain */
/*
* enable the interrupt level
@ -411,7 +416,7 @@ bool intctrl_t::unmask(word_t irq)
mtdcr(UIC1_ER, intMask | mfdcr(UIC1_ER));
/* Enable dchain*/
mtdcr(UIC0_ER, 0x00000003 | mfdcr(UIC0_ER));
mtdcr(UIC0_ER, uic1_dchain_mask | mfdcr(UIC0_ER));
lock.unlock(); /* re-enable interrupts */
@ -562,7 +567,7 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
uic2Er = mfdcr(UIC2_ER);
newUicXEr = uic2Er \
& ~(vecToUicBit(vector - INT_LEVEL_UIC2_MIN));
& ~(vecToUicMask(vector - INT_LEVEL_UIC2_MIN));
}
else
{
@ -575,7 +580,7 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
uic2Cr = mfdcr(UIC2_CR);
uic2Er = mfdcr(UIC2_ER);
newUicXEr = ((uic2Er &
(~(vecToUicBit(vector - INT_LEVEL_UIC2_MIN)))) |
(~(vecToUicMask(vector - INT_LEVEL_UIC2_MIN)))) |
uic2Cr );
}
@ -586,7 +591,7 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
/* Clear the Status registers */
mtdcr(UIC2_SR, (1 << (31 - (vector - INT_LEVEL_UIC2_MIN)))) ;
mtdcr(UIC0_SR, 0x0000000c); /* clear daisychain */
mtdcr(UIC0_SR, uic2_dchain_Mask); /* clear daisychain */
}
else if (vector > INT_LEVEL_UIC0_MAX)
@ -611,7 +616,7 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
uic1Er = mfdcr(UIC1_ER);
newUicXEr = uic1Er \
& ~(vecToUicBit(vector - INT_LEVEL_UIC1_MIN));
& ~(vecToUicMask(vector - INT_LEVEL_UIC1_MIN));
}
else
{
@ -624,7 +629,7 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
uic1Cr = mfdcr(UIC1_CR);
uic1Er = mfdcr(UIC1_ER);
newUicXEr = ((uic1Er &
(~(vecToUicBit(vector - INT_LEVEL_UIC1_MIN)))) |
(~(vecToUicMask(vector - INT_LEVEL_UIC1_MIN)))) |
uic1Cr );
}
@ -635,7 +640,7 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
/* Clear the Status registers */
mtdcr(UIC1_SR, (1 << (31 - (vector - INT_LEVEL_UIC1_MIN)))) ;
mtdcr(UIC0_SR, 0x00000003); /* clear daisychain */
mtdcr(UIC0_SR, uic1_dchain_mask); /* clear daisychain */
}
else
{
@ -656,7 +661,7 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
uic0Er = mfdcr(UIC0_ER);
newUicXEr = uic0Er \
& ~(vecToUicBit(vector - INT_LEVEL_UIC0_MIN));
& ~(vecToUicMask(vector - INT_LEVEL_UIC0_MIN));
}
else
{
@ -668,7 +673,7 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
uic0Cr = mfdcr(UIC0_CR);
uic0Er = mfdcr(UIC0_ER);
newUicXEr = ((uic0Er &
(~(vecToUicBit(vector - INT_LEVEL_UIC0_MIN)))) |
(~(vecToUicMask(vector - INT_LEVEL_UIC0_MIN)))) |
uic0Cr);
}
@ -706,37 +711,28 @@ void intctrl_t::sysUicIntHandlerCommon (bool intIsCritical) {
*/
::handle_interrupt(vector);
#if 0
/*
* Clear this interrupt level to ensure that this interrupt level is
* disabled before re-enabling interrupts.
*/
if (intIsCritical)
vxMsrSet(vxMsrGet() & ~(_PPC_MSR_CE));
else
vxMsrSet(vxMsrGet() & ~(_PPC_MSR_EE));
//this is not done in bic.cc, so I'm assuming it's done somewhere else.
/*
* Reenable the interrupts as they were went we got called.
*/
lock.lock();
#if defined(PPC440EPx)
if (vector > INT_LEVEL_UIC1_MAX)
{
mtdcr(UIC2_ER, uic2Er );
mtdcr(UIC2_ER, uic2Er );
}
else if (vector > INT_LEVEL_UIC0_MAX)
#else
if (vector > INT_LEVEL_UIC0_MAX)
#endif
{
mtdcr(UIC1_ER, uic1Er );
mtdcr(UIC1_ER, uic1Er );
}
else
{
mtdcr(UIC0_ER, uic0Er );
mtdcr(UIC0_ER, uic0Er );
}
#endif
lock.unlock();
}
bool intctrl_t::is_masked(word_t irq) {
@ -804,9 +800,9 @@ void intctrl_t::dump() {
mfdcr(UIC1_SR),mfdcr(UIC1_ER),mfdcr(UIC1_CR),mfdcr(UIC1_PR),
mfdcr(UIC1_TR),mfdcr(UIC1_MSR),mfdcr(UIC1_VCR),mfdcr(UIC1_VR));
#if defined(PPC440EPx)
printf("UIC2:\nSR: %08x\nER: %08x\nCR: %08x\nPR: %08x\nTR: %08x\nMSR: %08x\nVCR: %08x\nVR: %08x\n",
printf("UIC2:\nSR: %08x\nER: %08x\nCR: %08x\nPR: %08x\nTR: %08x\nMSR: %08x\nVCR: %08x\nVR: %08x\n",
mfdcr(UIC2_SR),mfdcr(UIC2_ER),mfdcr(UIC2_CR),mfdcr(UIC2_PR),
mfdcr(UIC2_TR),mfdcr(UIC2_MSR),mfdcr(UIC2_VCR),mfdcr(UIC2_VR));
#endif
lock.unlock();
lock.unlock();
}

View File

@ -94,11 +94,15 @@
#define INT_LEVEL_UIC0_MIN 0 /* First interrupt level on UIC-0 */
#define INT_LEVEL_UIC0_MAX 31 /* Last interrupt level on UIC-0 */
#define UIC0_NUM_IRQS (INT_LEVEL_UIC0_MAX - INT_LEVEL_UIC0_MIN + 1)
#define INT_LEVEL_UIC1_MIN 32 /* First interrupt level on UIC-1 */
#define INT_LEVEL_UIC1_MAX 63 /* Last interrupt level on UIC-1 */
#define UIC1_NUM_IRQS (INT_LEVEL_UIC1_MAX - INT_LEVEL_UIC1_MIN + 1)
#if defined(PPC440EPx)
#define INT_LEVEL_UIC2_MIN 64 /* First interrupt level on UIC-2 */
#define INT_LEVEL_UIC2_MAX 74 /* Last interrupt level on UIC-2 */
#define UIC2_NUM_IRQS (INT_LEVEL_UIC2_MAX - INT_LEVEL_UIC2_MIN + 1)
#endif
#define INT_IS_CRT (true) /* Int. is critical (for handler) */
@ -141,7 +145,7 @@ public:
void init_cpu(int cpu);
word_t get_number_irqs()
{ return INT_LEVEL_MAX; }
{ return INT_LEVEL_MAX + 1; }
bool is_irq_available(word_t irq)
{ return (irq >= INT_LEVEL_MIN && irq <= INT_LEVEL_MAX); }
@ -164,7 +168,11 @@ public:
{ return is_masked(irq); }
void set_cpu(word_t irq, word_t cpu)
{ UNIMPLEMENTED(); }
{
set_irq_routing(irq, cpu);
if (!is_masked(irq))
unmask(irq);
}
/* handler invoked on interrupt (left for compatibility)
@ -195,7 +203,10 @@ private:
spinlock_t lock;
word_t num_irqs;
word_t mem_size;
word_t uic1_dchain_mask;
#if defined(PPC440EPx)
word_t uic2_dchain_mask;
#endif
word_t init_controllers();
word_t get_irq_routing(word_t irq)
{