Commit c6039095 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] PPC32: 4xx core fixes and 440gx PIC support

From: Matt Porter <mporter@kernel.crashing.org>

Merge misc.  4xx core fixes and support for the new cascade scheme in the
440gx.
parent 8c8b5d22
...@@ -705,7 +705,7 @@ embed_config(bd_t ** bdp) ...@@ -705,7 +705,7 @@ embed_config(bd_t ** bdp)
#ifdef CONFIG_IBM_OPENBIOS #ifdef CONFIG_IBM_OPENBIOS
/* This could possibly work for all treeboot roms. /* This could possibly work for all treeboot roms.
*/ */
#if defined(CONFIG_ASH) || defined(CONFIG_BEECH) #if defined(CONFIG_ASH) || defined(CONFIG_BEECH) || defined(CONFIG_BUBINGA)
#define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */ #define BOARD_INFO_VECTOR 0xFFF80B50 /* openbios 1.19 moved this vector down - armin */
#else #else
#define BOARD_INFO_VECTOR 0xFFFE0B50 #define BOARD_INFO_VECTOR 0xFFFE0B50
...@@ -742,7 +742,7 @@ embed_config(bd_t **bdp) ...@@ -742,7 +742,7 @@ embed_config(bd_t **bdp)
*/ */
mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* 1st reset MAL */ mtdcr(DCRN_MALCR(DCRN_MAL_BASE), MALCR_MMSR); /* 1st reset MAL */
while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */ while (mfdcr(DCRN_MALCR(DCRN_MAL_BASE)) & MALCR_MMSR) {}; /* wait for the reset */
out_be32(EMAC0_BASE,0x20000000); /* then reset EMAC */ out_be32((volatile u32*)EMAC0_BASE,0x20000000); /* then reset EMAC */
#endif #endif
bd = &bdinfo; bd = &bdinfo;
......
...@@ -336,7 +336,7 @@ EXPORT_SYMBOL(debugger_fault_handler); ...@@ -336,7 +336,7 @@ EXPORT_SYMBOL(debugger_fault_handler);
EXPORT_SYMBOL(cpm_install_handler); EXPORT_SYMBOL(cpm_install_handler);
EXPORT_SYMBOL(cpm_free_handler); EXPORT_SYMBOL(cpm_free_handler);
#endif /* CONFIG_8xx */ #endif /* CONFIG_8xx */
#if defined(CONFIG_8xx) || defined(CONFIG_4xx) #if defined(CONFIG_8xx) || defined(CONFIG_40x)
EXPORT_SYMBOL(__res); EXPORT_SYMBOL(__res);
#endif #endif
#if defined(CONFIG_8xx) #if defined(CONFIG_8xx)
......
...@@ -57,14 +57,6 @@ ppc405_pcibios_fixup_resources(struct pci_dev *dev) ...@@ -57,14 +57,6 @@ ppc405_pcibios_fixup_resources(struct pci_dev *dev)
) )
) { ) {
DBG(KERN_ERR "PCI: 0x%lx <= resource[%d] <= 0x%lx"
", bus 0x%x dev 0x%2.2x.%1.1x,\n"
KERN_ERR " %s\n"
KERN_ERR " fixup will be attempted later\n",
min_host_addr, i, max_host_addr,
dev->bus->number, PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn), dev->slot.name);
/* force pcibios_assign_resources() to assign a new address */ /* force pcibios_assign_resources() to assign a new address */
res->end -= res->start; res->end -= res->start;
res->start = 0; res->start = 0;
......
...@@ -142,9 +142,12 @@ ppc403_aic_disable_and_ack(unsigned int irq) ...@@ -142,9 +142,12 @@ ppc403_aic_disable_and_ack(unsigned int irq)
#ifndef UIC1 #ifndef UIC1
#define UIC1 UIC0 #define UIC1 UIC0
#endif #endif
#ifndef UIC2
#define UIC2 UIC1
#endif
static void static void
ppc405_uic_enable(unsigned int irq) ppc4xx_uic_enable(unsigned int irq)
{ {
int bit, word; int bit, word;
irq_desc_t *desc = irq_desc + irq; irq_desc_t *desc = irq_desc + irq;
...@@ -153,7 +156,7 @@ ppc405_uic_enable(unsigned int irq) ...@@ -153,7 +156,7 @@ ppc405_uic_enable(unsigned int irq)
word = irq >> 5; word = irq >> 5;
#ifdef UIC_DEBUG #ifdef UIC_DEBUG
printk("ppc405_uic_enable - irq %d word %d bit 0x%x\n", irq, word, bit); printk("ppc4xx_uic_enable - irq %d word %d bit 0x%x\n", irq, word, bit);
#endif #endif
ppc_cached_irq_mask[word] |= 1 << (31 - bit); ppc_cached_irq_mask[word] |= 1 << (31 - bit);
switch (word) { switch (word) {
...@@ -162,38 +165,35 @@ ppc405_uic_enable(unsigned int irq) ...@@ -162,38 +165,35 @@ ppc405_uic_enable(unsigned int irq)
if ((mfdcr(DCRN_UIC_TR(UIC0)) & (1 << (31 - bit))) == 0) if ((mfdcr(DCRN_UIC_TR(UIC0)) & (1 << (31 - bit))) == 0)
desc->status |= IRQ_LEVEL; desc->status |= IRQ_LEVEL;
else else
/* lets hope this works since in linux/irq.h desc->status = desc->status & ~IRQ_LEVEL;
* there is no define for EDGE and it's assumed
* once you set status to LEVEL you would not
* want to change it - Armin
*/
desc->status = desc->status & ~IRQ_LEVEL;
break; break;
case 1: case 1:
mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]); mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]);
if ((mfdcr(DCRN_UIC_TR(UIC1)) & (1 << (31 - bit))) == 0) if ((mfdcr(DCRN_UIC_TR(UIC1)) & (1 << (31 - bit))) == 0)
desc->status |= IRQ_LEVEL; desc->status |= IRQ_LEVEL;
else else
/* lets hope this works since in linux/irq.h desc->status = desc->status & ~IRQ_LEVEL;
* there is no define for EDGE and it's assumed break;
* once you set status to LEVEL you would not case 2:
* want to change it - Armin mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]);
*/ if ((mfdcr(DCRN_UIC_TR(UIC2)) & (1 << (31 - bit))) == 0)
desc->status = desc->status & ~IRQ_LEVEL; desc->status |= IRQ_LEVEL;
else
desc->status = desc->status & ~IRQ_LEVEL;
break; break;
} }
} }
static void static void
ppc405_uic_disable(unsigned int irq) ppc4xx_uic_disable(unsigned int irq)
{ {
int bit, word; int bit, word;
bit = irq & 0x1f; bit = irq & 0x1f;
word = irq >> 5; word = irq >> 5;
#ifdef UIC_DEBUG #ifdef UIC_DEBUG
printk("ppc405_uic_disable - irq %d word %d bit 0x%x\n", irq, word, printk("ppc4xx_uic_disable - irq %d word %d bit 0x%x\n", irq, word,
bit); bit);
#endif #endif
ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
...@@ -204,11 +204,14 @@ ppc405_uic_disable(unsigned int irq) ...@@ -204,11 +204,14 @@ ppc405_uic_disable(unsigned int irq)
case 1: case 1:
mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]); mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]);
break; break;
case 2:
mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]);
break;
} }
} }
static void static void
ppc405_uic_disable_and_ack(unsigned int irq) ppc4xx_uic_disable_and_ack(unsigned int irq)
{ {
int bit, word; int bit, word;
...@@ -216,7 +219,7 @@ ppc405_uic_disable_and_ack(unsigned int irq) ...@@ -216,7 +219,7 @@ ppc405_uic_disable_and_ack(unsigned int irq)
word = irq >> 5; word = irq >> 5;
#ifdef UIC_DEBUG #ifdef UIC_DEBUG
printk("ppc405_uic_disable_and_ack - irq %d word %d bit 0x%x\n", irq, printk("ppc4xx_uic_disable_and_ack - irq %d word %d bit 0x%x\n", irq,
word, bit); word, bit);
#endif #endif
ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); ppc_cached_irq_mask[word] &= ~(1 << (31 - bit));
...@@ -224,16 +227,30 @@ ppc405_uic_disable_and_ack(unsigned int irq) ...@@ -224,16 +227,30 @@ ppc405_uic_disable_and_ack(unsigned int irq)
case 0: case 0:
mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]); mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[word]);
mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - bit))); mtdcr(DCRN_UIC_SR(UIC0), (1 << (31 - bit)));
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
#endif
break; break;
case 1: case 1:
mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]); mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]);
mtdcr(DCRN_UIC_SR(UIC1), (1 << (31 - bit))); mtdcr(DCRN_UIC_SR(UIC1), (1 << (31 - bit)));
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
#endif
break;
case 2:
mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]);
mtdcr(DCRN_UIC_SR(UIC2), (1 << (31 - bit)));
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
#endif
break; break;
} }
} }
static void static void
ppc405_uic_end(unsigned int irq) ppc4xx_uic_end(unsigned int irq)
{ {
int bit, word; int bit, word;
unsigned int tr_bits; unsigned int tr_bits;
...@@ -242,7 +259,7 @@ ppc405_uic_end(unsigned int irq) ...@@ -242,7 +259,7 @@ ppc405_uic_end(unsigned int irq)
word = irq >> 5; word = irq >> 5;
#ifdef UIC_DEBUG #ifdef UIC_DEBUG
printk("ppc405_uic_end - irq %d word %d bit 0x%x\n", irq, word, bit); printk("ppc4xx_uic_end - irq %d word %d bit 0x%x\n", irq, word, bit);
#endif #endif
switch (word) { switch (word) {
...@@ -259,9 +276,21 @@ ppc405_uic_end(unsigned int irq) ...@@ -259,9 +276,21 @@ ppc405_uic_end(unsigned int irq)
switch (word) { switch (word) {
case 0: case 0:
mtdcr(DCRN_UIC_SR(UIC0), 1 << (31 - bit)); mtdcr(DCRN_UIC_SR(UIC0), 1 << (31 - bit));
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
#endif
break; break;
case 1: case 1:
mtdcr(DCRN_UIC_SR(UIC1), 1 << (31 - bit)); mtdcr(DCRN_UIC_SR(UIC1), 1 << (31 - bit));
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
#endif
break;
case 2:
mtdcr(DCRN_UIC_SR(UIC2), 1 << (31 - bit));
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
#endif
break; break;
} }
} }
...@@ -275,11 +304,14 @@ ppc405_uic_end(unsigned int irq) ...@@ -275,11 +304,14 @@ ppc405_uic_end(unsigned int irq)
case 1: case 1:
mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]); mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[word]);
break; break;
case 2:
mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[word]);
break;
} }
} }
} }
static struct hw_interrupt_type ppc405_uic = { static struct hw_interrupt_type ppc4xx_uic = {
#if (NR_UICS == 1) #if (NR_UICS == 1)
"IBM UIC", "IBM UIC",
#else #else
...@@ -287,15 +319,15 @@ static struct hw_interrupt_type ppc405_uic = { ...@@ -287,15 +319,15 @@ static struct hw_interrupt_type ppc405_uic = {
#endif #endif
NULL, NULL,
NULL, NULL,
ppc405_uic_enable, ppc4xx_uic_enable,
ppc405_uic_disable, ppc4xx_uic_disable,
ppc405_uic_disable_and_ack, ppc4xx_uic_disable_and_ack,
ppc405_uic_end, ppc4xx_uic_end,
0 0
}; };
int int
ppc405_pic_get_irq(struct pt_regs *regs) ppc4xx_pic_get_irq(struct pt_regs *regs)
{ {
int irq, cas_irq; int irq, cas_irq;
unsigned long bits; unsigned long bits;
...@@ -305,9 +337,25 @@ ppc405_pic_get_irq(struct pt_regs *regs) ...@@ -305,9 +337,25 @@ ppc405_pic_get_irq(struct pt_regs *regs)
* enabled. * enabled.
*/ */
#if (NR_UICS > 2)
bits = mfdcr(DCRN_UIC_MSR(UICB));
#else
bits = mfdcr(DCRN_UIC_MSR(UIC0)); bits = mfdcr(DCRN_UIC_MSR(UIC0));
#endif
#if (NR_UICS > 1) #if (NR_UICS > 2)
if (bits & UICB_UIC0NC) {
bits = mfdcr(DCRN_UIC_MSR(UIC0));
irq = 32 - ffs(bits);
} else if (bits & UICB_UIC1NC) {
bits = mfdcr(DCRN_UIC_MSR(UIC1));
irq = 64 - ffs(bits);
} else if (bits & UICB_UIC2NC) {
bits = mfdcr(DCRN_UIC_MSR(UIC2));
irq = 96 - ffs(bits);
} else {
irq = -1;
}
#elif (NR_UICS > 1)
if (bits & UIC_CASCADE_MASK) { if (bits & UIC_CASCADE_MASK) {
bits = mfdcr(DCRN_UIC_MSR(UIC1)); bits = mfdcr(DCRN_UIC_MSR(UIC1));
cas_irq = 32 - ffs(bits); cas_irq = 32 - ffs(bits);
...@@ -330,7 +378,7 @@ ppc405_pic_get_irq(struct pt_regs *regs) ...@@ -330,7 +378,7 @@ ppc405_pic_get_irq(struct pt_regs *regs)
irq = -1; irq = -1;
#ifdef UIC_DEBUG #ifdef UIC_DEBUG
printk("ppc405_pic_get_irq - irq %d bit 0x%x\n", irq, bits); printk("ppc4xx_pic_get_irq - irq %d bit 0x%x\n", irq, bits);
#endif #endif
return (irq); return (irq);
...@@ -354,8 +402,10 @@ ppc4xx_extpic_init(void) ...@@ -354,8 +402,10 @@ ppc4xx_extpic_init(void)
unsigned long ppc_cached_pol_mask[NR_MASK_WORDS]; unsigned long ppc_cached_pol_mask[NR_MASK_WORDS];
ppc_cached_sense_mask[0] = 0; ppc_cached_sense_mask[0] = 0;
ppc_cached_sense_mask[1] = 0; ppc_cached_sense_mask[1] = 0;
ppc_cached_sense_mask[2] = 0;
ppc_cached_pol_mask[0] = 0; ppc_cached_pol_mask[0] = 0;
ppc_cached_pol_mask[1] = 0; ppc_cached_pol_mask[1] = 0;
ppc_cached_pol_mask[2] = 0;
for (irq = 0; irq < NR_IRQS; irq++) { for (irq = 0; irq < NR_IRQS; irq++) {
...@@ -397,6 +447,18 @@ ppc4xx_extpic_init(void) ...@@ -397,6 +447,18 @@ ppc4xx_extpic_init(void)
/* Level setting */ /* Level setting */
mtdcr(DCRN_UIC_TR(UIC1), ppc_cached_sense_mask[word]); mtdcr(DCRN_UIC_TR(UIC1), ppc_cached_sense_mask[word]);
break;
case 2:
#ifdef PPC4xx_PIC_DEBUG
printk("Pol %x ", mfdcr(DCRN_UIC_PR(UIC2)));
printk("Level %x\n", mfdcr(DCRN_UIC_TR(UIC2)));
#endif
/* polarity setting */
mtdcr(DCRN_UIC_PR(UIC2), ppc_cached_pol_mask[word]);
/* Level setting */
mtdcr(DCRN_UIC_TR(UIC2), ppc_cached_sense_mask[word]);
break; break;
} }
} }
...@@ -405,13 +467,13 @@ ppc4xx_extpic_init(void) ...@@ -405,13 +467,13 @@ ppc4xx_extpic_init(void)
void __init void __init
ppc4xx_pic_init(void) ppc4xx_pic_init(void)
{ {
/* /*
* Disable all external interrupts until they are * Disable all external interrupts until they are
* explicity requested. * explicity requested.
*/ */
ppc_cached_irq_mask[0] = 0; ppc_cached_irq_mask[0] = 0;
ppc_cached_irq_mask[1] = 0; ppc_cached_irq_mask[1] = 0;
ppc_cached_irq_mask[2] = 0;
#if defined CONFIG_403 #if defined CONFIG_403
mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]); mtdcr(DCRN_EXIER, ppc_cached_irq_mask[0]);
...@@ -419,11 +481,21 @@ ppc4xx_pic_init(void) ...@@ -419,11 +481,21 @@ ppc4xx_pic_init(void)
ppc4xx_pic = &ppc403_aic; ppc4xx_pic = &ppc403_aic;
ppc_md.get_irq = ppc403_pic_get_irq; ppc_md.get_irq = ppc403_pic_get_irq;
#else #else
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_ER(UICB), UICB_UIC0NC | UICB_UIC1NC | UICB_UIC2NC);
mtdcr(DCRN_UIC_CR(UICB), 0);
mtdcr(DCRN_UIC_ER(UIC2), ppc_cached_irq_mask[2]);
mtdcr(DCRN_UIC_CR(UIC2), 0);
#endif
#if (NR_UICS > 1) #if (NR_UICS > 1)
ppc_cached_irq_mask[0] |= 1 << (31 - UIC0_UIC1NC); /* enable cascading interrupt */ #if (NR_UICS == 2)
/* enable cascading interrupt */
ppc_cached_irq_mask[0] |= 1 << (31 - UIC0_UIC1NC);
#endif
mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[1]); mtdcr(DCRN_UIC_ER(UIC1), ppc_cached_irq_mask[1]);
mtdcr(DCRN_UIC_CR(UIC1), 0); mtdcr(DCRN_UIC_CR(UIC1), 0);
#endif #endif
mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]); mtdcr(DCRN_UIC_ER(UIC0), ppc_cached_irq_mask[0]);
mtdcr(DCRN_UIC_CR(UIC0), 0); mtdcr(DCRN_UIC_CR(UIC0), 0);
...@@ -432,13 +504,16 @@ ppc4xx_pic_init(void) ...@@ -432,13 +504,16 @@ ppc4xx_pic_init(void)
ppc4xx_extpic_init(); ppc4xx_extpic_init();
/* Clear any pending interrupts */ /* Clear any pending interrupts */
#if (NR_UICS > 2)
mtdcr(DCRN_UIC_SR(UICB), 0xffffffff);
mtdcr(DCRN_UIC_SR(UIC2), 0xffffffff);
#endif
#if (NR_UICS > 1) #if (NR_UICS > 1)
mtdcr(DCRN_UIC_SR(UIC1), 0xffffffff); mtdcr(DCRN_UIC_SR(UIC1), 0xffffffff);
#endif #endif
mtdcr(DCRN_UIC_SR(UIC0), 0xffffffff); mtdcr(DCRN_UIC_SR(UIC0), 0xffffffff);
ppc4xx_pic = &ppc405_uic; ppc4xx_pic = &ppc4xx_uic;
ppc_md.get_irq = ppc405_pic_get_irq; ppc_md.get_irq = ppc4xx_pic_get_irq;
#endif #endif
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment