Skip to content

Commit

Permalink
of/powerpc: Move Powermac irq quirk code into powermac pic driver code
Browse files Browse the repository at this point in the history
The code that figures out what is wrong with the powermac irq device
tree data belongs with the rest of the powermac irq code.  This patch
moves it out of prom_parse.c and into powermac/pic.c so that it is only
compiled in when actually needed.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
  • Loading branch information
Grant Likely committed Jul 5, 2010
1 parent b6295c8 commit b83da29
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 100 deletions.
24 changes: 15 additions & 9 deletions arch/powerpc/include/asm/prom.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,24 @@ extern const void *of_get_mac_address(struct device_node *np);
* OF interrupt mapping
*/

/**
* of_irq_map_init - Initialize the irq remapper
* @flags: flags defining workarounds to enable
*
* Some machines have bugs in the device-tree which require certain workarounds
* to be applied. Call this before any interrupt mapping attempts to enable
* those workarounds.
*/
#define OF_IMAP_OLDWORLD_MAC 0x00000001
#define OF_IMAP_NO_PHANDLE 0x00000002

extern void of_irq_map_init(unsigned int flags);
#if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
/* Workarounds only needed for 32bit powermac machines */
extern unsigned int of_irq_workarounds;
extern struct device_node *of_irq_dflt_pic;
extern int of_irq_map_oldworld(struct device_node *device, int index,
struct of_irq *out_irq);
#else
#define of_irq_workarounds (0)
#define of_irq_dflt_pic (NULL)
static inline int of_irq_map_oldworld(struct device_node *device, int index,
struct of_irq *out_irq)
{
return -EINVAL;
}
#endif

/**
* of_irq_map_raw - Low level interrupt tree parsing
Expand Down
85 changes: 0 additions & 85 deletions arch/powerpc/kernel/prom_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -682,9 +682,6 @@ void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
* Interrupt remapper
*/

static unsigned int of_irq_workarounds;
static struct device_node *of_irq_dflt_pic;

static struct device_node *of_irq_find_parent(struct device_node *child)
{
struct device_node *p;
Expand All @@ -710,44 +707,6 @@ static struct device_node *of_irq_find_parent(struct device_node *child)
return p;
}

/* This doesn't need to be called if you don't have any special workaround
* flags to pass
*/
void of_irq_map_init(unsigned int flags)
{
of_irq_workarounds = flags;

/* OldWorld, don't bother looking at other things */
if (flags & OF_IMAP_OLDWORLD_MAC)
return;

/* If we don't have phandles, let's try to locate a default interrupt
* controller (happens when booting with BootX). We do a first match
* here, hopefully, that only ever happens on machines with one
* controller.
*/
if (flags & OF_IMAP_NO_PHANDLE) {
struct device_node *np;

for_each_node_with_property(np, "interrupt-controller") {
/* Skip /chosen/interrupt-controller */
if (strcmp(np->name, "chosen") == 0)
continue;
/* It seems like at least one person on this planet wants
* to use BootX on a machine with an AppleKiwi controller
* which happens to pretend to be an interrupt
* controller too.
*/
if (strcmp(np->name, "AppleKiwi") == 0)
continue;
/* I think we found one ! */
of_irq_dflt_pic = np;
break;
}
}

}

int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
const u32 *addr, struct of_irq *out_irq)
{
Expand Down Expand Up @@ -922,50 +881,6 @@ int of_irq_map_raw(struct device_node *parent, const u32 *intspec, u32 ointsize,
}
EXPORT_SYMBOL_GPL(of_irq_map_raw);

#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)
static int of_irq_map_oldworld(struct device_node *device, int index,
struct of_irq *out_irq)
{
const u32 *ints = NULL;
int intlen;

/*
* Old machines just have a list of interrupt numbers
* and no interrupt-controller nodes. We also have dodgy
* cases where the APPL,interrupts property is completely
* missing behind pci-pci bridges and we have to get it
* from the parent (the bridge itself, as apple just wired
* everything together on these)
*/
while (device) {
ints = of_get_property(device, "AAPL,interrupts", &intlen);
if (ints != NULL)
break;
device = device->parent;
if (device && strcmp(device->type, "pci") != 0)
break;
}
if (ints == NULL)
return -EINVAL;
intlen /= sizeof(u32);

if (index >= intlen)
return -EINVAL;

out_irq->controller = NULL;
out_irq->specifier[0] = ints[index];
out_irq->size = 1;

return 0;
}
#else /* defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) */
static int of_irq_map_oldworld(struct device_node *device, int index,
struct of_irq *out_irq)
{
return -EINVAL;
}
#endif /* !(defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)) */

int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq)
{
struct device_node *p;
Expand Down
72 changes: 66 additions & 6 deletions arch/powerpc/platforms/powermac/pic.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ struct pmac_irq_hw {
unsigned int level;
};

/* Workaround flags for 32bit powermac machines */
unsigned int of_irq_workarounds;
struct device_node *of_irq_dflt_pic;

/* Default addresses */
static volatile struct pmac_irq_hw __iomem *pmac_irq_hw[4];

Expand Down Expand Up @@ -428,6 +432,42 @@ static void __init pmac_pic_probe_oldstyle(void)
setup_irq(irq_create_mapping(NULL, 20), &xmon_action);
#endif
}

int of_irq_map_oldworld(struct device_node *device, int index,
struct of_irq *out_irq)
{
const u32 *ints = NULL;
int intlen;

/*
* Old machines just have a list of interrupt numbers
* and no interrupt-controller nodes. We also have dodgy
* cases where the APPL,interrupts property is completely
* missing behind pci-pci bridges and we have to get it
* from the parent (the bridge itself, as apple just wired
* everything together on these)
*/
while (device) {
ints = of_get_property(device, "AAPL,interrupts", &intlen);
if (ints != NULL)
break;
device = device->parent;
if (device && strcmp(device->type, "pci") != 0)
break;
}
if (ints == NULL)
return -EINVAL;
intlen /= sizeof(u32);

if (index >= intlen)
return -EINVAL;

out_irq->controller = NULL;
out_irq->specifier[0] = ints[index];
out_irq->size = 1;

return 0;
}
#endif /* CONFIG_PPC32 */

static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
Expand Down Expand Up @@ -559,19 +599,39 @@ static int __init pmac_pic_probe_mpic(void)

void __init pmac_pic_init(void)
{
unsigned int flags = 0;

/* We configure the OF parsing based on our oldworld vs. newworld
* platform type and wether we were booted by BootX.
*/
#ifdef CONFIG_PPC32
if (!pmac_newworld)
flags |= OF_IMAP_OLDWORLD_MAC;
of_irq_workarounds |= OF_IMAP_OLDWORLD_MAC;
if (of_get_property(of_chosen, "linux,bootx", NULL) != NULL)
flags |= OF_IMAP_NO_PHANDLE;
#endif /* CONFIG_PPC_32 */
of_irq_workarounds |= OF_IMAP_NO_PHANDLE;

of_irq_map_init(flags);
/* If we don't have phandles on a newworld, then try to locate a
* default interrupt controller (happens when booting with BootX).
* We do a first match here, hopefully, that only ever happens on
* machines with one controller.
*/
if (pmac_newworld && (of_irq_workarounds & OF_IMAP_NO_PHANDLE)) {
struct device_node *np;

for_each_node_with_property(np, "interrupt-controller") {
/* Skip /chosen/interrupt-controller */
if (strcmp(np->name, "chosen") == 0)
continue;
/* It seems like at least one person wants
* to use BootX on a machine with an AppleKiwi
* controller which happens to pretend to be an
* interrupt controller too. */
if (strcmp(np->name, "AppleKiwi") == 0)
continue;
/* I think we found one ! */
of_irq_dflt_pic = np;
break;
}
}
#endif /* CONFIG_PPC32 */

/* We first try to detect Apple's new Core99 chipset, since mac-io
* is quite different on those machines and contains an IBM MPIC2.
Expand Down

0 comments on commit b83da29

Please sign in to comment.