X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fppc%2Fsyslib%2Fcpm2_pic.c;h=fb2d5842641a34c0806dac2d009971c77f263db6;hb=refs%2Fheads%2Fvserver;hp=bd8335b84d93afe78b6e85d39f61e8e5df2b2334;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/ppc/syslib/cpm2_pic.c b/arch/ppc/syslib/cpm2_pic.c index bd8335b84..fb2d58426 100644 --- a/arch/ppc/syslib/cpm2_pic.c +++ b/arch/ppc/syslib/cpm2_pic.c @@ -32,15 +32,17 @@ static u_char irq_to_siureg[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; +/* bit numbers do not match the docs, these are precomputed so the bit for + * a given irq is (1 << irq_to_siubit[irq]) */ static u_char irq_to_siubit[] = { - 31, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, - 29, 30, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 31, - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 15, 14, 13, 12, 11, 10, 9, 8, - 7, 6, 5, 4, 3, 2, 1, 0 + 0, 15, 14, 13, 12, 11, 10, 9, + 8, 7, 6, 5, 4, 3, 2, 1, + 2, 1, 0, 14, 13, 12, 11, 10, + 9, 8, 7, 6, 5, 4, 3, 0, + 31, 30, 29, 28, 27, 26, 25, 24, + 23, 22, 21, 20, 19, 18, 17, 16, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, }; static void cpm2_mask_irq(unsigned int irq_nr) @@ -48,11 +50,13 @@ static void cpm2_mask_irq(unsigned int irq_nr) int bit, word; volatile uint *simr; + irq_nr -= CPM_IRQ_OFFSET; + bit = irq_to_siubit[irq_nr]; word = irq_to_siureg[irq_nr]; simr = &(cpm2_immr->im_intctl.ic_simrh); - ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); + ppc_cached_irq_mask[word] &= ~(1 << bit); simr[word] = ppc_cached_irq_mask[word]; } @@ -61,11 +65,13 @@ static void cpm2_unmask_irq(unsigned int irq_nr) int bit, word; volatile uint *simr; + irq_nr -= CPM_IRQ_OFFSET; + bit = irq_to_siubit[irq_nr]; word = irq_to_siureg[irq_nr]; simr = &(cpm2_immr->im_intctl.ic_simrh); - ppc_cached_irq_mask[word] |= (1 << (31 - bit)); + ppc_cached_irq_mask[word] |= 1 << bit; simr[word] = ppc_cached_irq_mask[word]; } @@ -74,14 +80,16 @@ static void cpm2_mask_and_ack(unsigned int irq_nr) int bit, word; volatile uint *simr, *sipnr; + irq_nr -= CPM_IRQ_OFFSET; + bit = irq_to_siubit[irq_nr]; word = irq_to_siureg[irq_nr]; simr = &(cpm2_immr->im_intctl.ic_simrh); sipnr = &(cpm2_immr->im_intctl.ic_sipnrh); - ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); + ppc_cached_irq_mask[word] &= ~(1 << bit); simr[word] = ppc_cached_irq_mask[word]; - sipnr[word] = 1 << (31 - bit); + sipnr[word] = 1 << bit; } static void cpm2_end_irq(unsigned int irq_nr) @@ -92,29 +100,30 @@ static void cpm2_end_irq(unsigned int irq_nr) if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && irq_desc[irq_nr].action) { + irq_nr -= CPM_IRQ_OFFSET; bit = irq_to_siubit[irq_nr]; word = irq_to_siureg[irq_nr]; simr = &(cpm2_immr->im_intctl.ic_simrh); - ppc_cached_irq_mask[word] |= (1 << (31 - bit)); + ppc_cached_irq_mask[word] |= 1 << bit; simr[word] = ppc_cached_irq_mask[word]; + /* + * Work around large numbers of spurious IRQs on PowerPC 82xx + * systems. + */ + mb(); } } -struct hw_interrupt_type cpm2_pic = { - " CPM2 SIU ", - NULL, - NULL, - cpm2_unmask_irq, - cpm2_mask_irq, - cpm2_mask_and_ack, - cpm2_end_irq, - 0 +static struct hw_interrupt_type cpm2_pic = { + .typename = " CPM2 SIU ", + .enable = cpm2_unmask_irq, + .disable = cpm2_mask_irq, + .ack = cpm2_mask_and_ack, + .end = cpm2_end_irq, }; - -int -cpm2_get_irq(struct pt_regs *regs) +int cpm2_get_irq(void) { int irq; unsigned long bits; @@ -126,5 +135,43 @@ cpm2_get_irq(struct pt_regs *regs) if (irq == 0) return(-1); - return irq; + return irq+CPM_IRQ_OFFSET; +} + +void cpm2_init_IRQ(void) +{ + int i; + + /* Clear the CPM IRQ controller, in case it has any bits set + * from the bootloader + */ + + /* Mask out everything */ + cpm2_immr->im_intctl.ic_simrh = 0x00000000; + cpm2_immr->im_intctl.ic_simrl = 0x00000000; + wmb(); + + /* Ack everything */ + cpm2_immr->im_intctl.ic_sipnrh = 0xffffffff; + cpm2_immr->im_intctl.ic_sipnrl = 0xffffffff; + wmb(); + + /* Dummy read of the vector */ + i = cpm2_immr->im_intctl.ic_sivec; + rmb(); + + /* Initialize the default interrupt mapping priorities, + * in case the boot rom changed something on us. + */ + cpm2_immr->im_intctl.ic_sicr = 0; + cpm2_immr->im_intctl.ic_scprrh = 0x05309770; + cpm2_immr->im_intctl.ic_scprrl = 0x05309770; + + + /* Enable chaining to OpenPIC, and make everything level + */ + for (i = 0; i < NR_CPM_INTS; i++) { + irq_desc[i+CPM_IRQ_OFFSET].chip = &cpm2_pic; + irq_desc[i+CPM_IRQ_OFFSET].status |= IRQ_LEVEL; + } }