[PATCH] powermac: clean up PIC initialisation code
Johannes Berg
johannes at sipsolutions.net
Mon Feb 5 18:21:14 EST 2007
On Mon, 2007-02-05 at 12:41 +1100, Benjamin Herrenschmidt wrote:
> Not fan of having an ifdef here... I'd rather have a pmac_pic_init()
> that does the right thing, maybe in setup.c
Ok. From what I can tell it isn't necessary to call of_irq_map_init() on
newer machines that have an IBM mpic2. So how about this?
--- mb-wireless.orig/arch/powerpc/platforms/powermac/Makefile 2007-02-02 11:56:19.723225416 +0100
+++ mb-wireless/arch/powerpc/platforms/powermac/Makefile 2007-02-02 11:56:23.943225416 +0100
@@ -1,6 +1,6 @@
CFLAGS_bootx_init.o += -fPIC
-obj-y += pic.o setup.o time.o feature.o pci.o \
+obj-y += setup.o time.o feature.o pci.o \
sleep.o low_i2c.o cache.o pfunc_core.o \
pfunc_base.o
obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o
@@ -8,7 +8,7 @@ obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_3
obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o
obj-$(CONFIG_NVRAM) += nvram.o
# ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff
-obj-$(CONFIG_PPC64) += nvram.o
-obj-$(CONFIG_PPC32) += bootx_init.o
+obj-$(CONFIG_PPC64) += nvram.o mpic.o
+obj-$(CONFIG_PPC32) += bootx_init.o pic.o mpic.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PPC_MERGE) += udbg_scc.o udbg_adb.o
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ mb-wireless/arch/powerpc/platforms/powermac/mpic.c 2007-02-05 08:14:16.760498543 +0100
@@ -0,0 +1,143 @@
+/*
+ * OpenPIC initialisation for PowerMacs.
+ *
+ * Copyright (C) 1997 Paul Mackerras (paulus at samba.org)
+ * Copyright (C) 2005 Benjamin Herrenschmidt (benh at kernel.crashing.org)
+ * IBM, Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/prom.h>
+#include <asm/pmac_feature.h>
+#include <asm/mpic.h>
+
+static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
+{
+ struct mpic *mpic = desc->handler_data;
+
+ unsigned int cascade_irq = mpic_get_one_irq(mpic);
+ if (cascade_irq != NO_IRQ)
+ generic_handle_irq(cascade_irq);
+ desc->chip->eoi(irq);
+}
+
+static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
+{
+#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
+ struct device_node* pswitch;
+ int nmi_irq;
+
+ pswitch = of_find_node_by_name(NULL, "programmer-switch");
+ if (pswitch) {
+ nmi_irq = irq_of_parse_and_map(pswitch, 0);
+ if (nmi_irq != NO_IRQ) {
+ mpic_irq_set_priority(nmi_irq, 9);
+ setup_irq(nmi_irq, &xmon_action);
+ }
+ of_node_put(pswitch);
+ }
+#endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */
+}
+
+static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
+ int master)
+{
+ const char *name = master ? " MPIC 1 " : " MPIC 2 ";
+ struct resource r;
+ struct mpic *mpic;
+ unsigned int flags = master ? MPIC_PRIMARY : 0;
+ int rc;
+
+ rc = of_address_to_resource(np, 0, &r);
+ if (rc)
+ return NULL;
+
+ pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
+
+ flags |= MPIC_WANTS_RESET;
+ if (get_property(np, "big-endian", NULL))
+ flags |= MPIC_BIG_ENDIAN;
+
+ /* Primary Big Endian means HT interrupts. This is quite dodgy
+ * but works until I find a better way
+ */
+ if (master && (flags & MPIC_BIG_ENDIAN))
+ flags |= MPIC_BROKEN_U3;
+
+ mpic = mpic_alloc(np, r.start, flags, 0, 0, name);
+ if (mpic == NULL)
+ return NULL;
+
+ mpic_init(mpic);
+
+ return mpic;
+ }
+
+int __init pmac_pic_probe_mpic(void)
+{
+ struct mpic *mpic1, *mpic2;
+ struct device_node *np, *master = NULL, *slave = NULL;
+ unsigned int cascade;
+
+ /* We can have up to 2 MPICs cascaded */
+ for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
+ != NULL;) {
+ if (master == NULL &&
+ get_property(np, "interrupts", NULL) == NULL)
+ master = of_node_get(np);
+ else if (slave == NULL)
+ slave = of_node_get(np);
+ if (master && slave)
+ break;
+ }
+
+ /* Check for bogus setups */
+ if (master == NULL && slave != NULL) {
+ master = slave;
+ slave = NULL;
+ }
+
+ /* Not found, default to good old pmac pic */
+ if (master == NULL)
+ return -ENODEV;
+
+ /* Set master handler */
+ ppc_md.get_irq = mpic_get_irq;
+
+ /* Setup master */
+ mpic1 = pmac_setup_one_mpic(master, 1);
+ BUG_ON(mpic1 == NULL);
+
+ /* Install NMI if any */
+ pmac_pic_setup_mpic_nmi(mpic1);
+
+ of_node_put(master);
+
+ /* No slave, let's go out */
+ if (slave == NULL)
+ return 0;
+
+ /* Get/Map slave interrupt */
+ cascade = irq_of_parse_and_map(slave, 0);
+ if (cascade == NO_IRQ) {
+ printk(KERN_ERR "Failed to map cascade IRQ\n");
+ return 0;
+ }
+
+ mpic2 = pmac_setup_one_mpic(slave, 0);
+ if (mpic2 == NULL) {
+ printk(KERN_ERR "Failed to setup slave MPIC\n");
+ of_node_put(slave);
+ return 0;
+ }
+ set_irq_data(cascade, mpic2);
+ set_irq_chained_handler(cascade, pmac_u3_cascade);
+
+ of_node_put(slave);
+ return 0;
+}
--- mb-wireless.orig/arch/powerpc/platforms/powermac/pic.c 2007-02-02 11:56:19.773225416 +0100
+++ mb-wireless/arch/powerpc/platforms/powermac/pic.c 2007-02-05 08:14:54.710498543 +0100
@@ -15,25 +15,14 @@
*
*/
-#include <linux/stddef.h>
#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/sysdev.h>
#include <linux/adb.h>
#include <linux/pmu.h>
-#include <linux/module.h>
-#include <asm/sections.h>
-#include <asm/io.h>
#include <asm/smp.h>
#include <asm/prom.h>
-#include <asm/pci-bridge.h>
#include <asm/time.h>
#include <asm/pmac_feature.h>
-#include <asm/mpic.h>
#include "pmac.h"
@@ -44,7 +33,6 @@
*/
extern irqreturn_t xmon_irq(int, void *);
-#ifdef CONFIG_PPC32
struct pmac_irq_hw {
unsigned int event;
unsigned int enable;
@@ -438,134 +426,6 @@ static void __init pmac_pic_probe_oldsty
setup_irq(irq_create_mapping(NULL, 20), &xmon_action);
#endif
}
-#endif /* CONFIG_PPC32 */
-
-static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
-{
- struct mpic *mpic = desc->handler_data;
-
- unsigned int cascade_irq = mpic_get_one_irq(mpic);
- if (cascade_irq != NO_IRQ)
- generic_handle_irq(cascade_irq);
- desc->chip->eoi(irq);
-}
-
-static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
-{
-#if defined(CONFIG_XMON) && defined(CONFIG_PPC32)
- struct device_node* pswitch;
- int nmi_irq;
-
- pswitch = of_find_node_by_name(NULL, "programmer-switch");
- if (pswitch) {
- nmi_irq = irq_of_parse_and_map(pswitch, 0);
- if (nmi_irq != NO_IRQ) {
- mpic_irq_set_priority(nmi_irq, 9);
- setup_irq(nmi_irq, &xmon_action);
- }
- of_node_put(pswitch);
- }
-#endif /* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */
-}
-
-static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
- int master)
-{
- const char *name = master ? " MPIC 1 " : " MPIC 2 ";
- struct resource r;
- struct mpic *mpic;
- unsigned int flags = master ? MPIC_PRIMARY : 0;
- int rc;
-
- rc = of_address_to_resource(np, 0, &r);
- if (rc)
- return NULL;
-
- pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
-
- flags |= MPIC_WANTS_RESET;
- if (get_property(np, "big-endian", NULL))
- flags |= MPIC_BIG_ENDIAN;
-
- /* Primary Big Endian means HT interrupts. This is quite dodgy
- * but works until I find a better way
- */
- if (master && (flags & MPIC_BIG_ENDIAN))
- flags |= MPIC_BROKEN_U3;
-
- mpic = mpic_alloc(np, r.start, flags, 0, 0, name);
- if (mpic == NULL)
- return NULL;
-
- mpic_init(mpic);
-
- return mpic;
- }
-
-static int __init pmac_pic_probe_mpic(void)
-{
- struct mpic *mpic1, *mpic2;
- struct device_node *np, *master = NULL, *slave = NULL;
- unsigned int cascade;
-
- /* We can have up to 2 MPICs cascaded */
- for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
- != NULL;) {
- if (master == NULL &&
- get_property(np, "interrupts", NULL) == NULL)
- master = of_node_get(np);
- else if (slave == NULL)
- slave = of_node_get(np);
- if (master && slave)
- break;
- }
-
- /* Check for bogus setups */
- if (master == NULL && slave != NULL) {
- master = slave;
- slave = NULL;
- }
-
- /* Not found, default to good old pmac pic */
- if (master == NULL)
- return -ENODEV;
-
- /* Set master handler */
- ppc_md.get_irq = mpic_get_irq;
-
- /* Setup master */
- mpic1 = pmac_setup_one_mpic(master, 1);
- BUG_ON(mpic1 == NULL);
-
- /* Install NMI if any */
- pmac_pic_setup_mpic_nmi(mpic1);
-
- of_node_put(master);
-
- /* No slave, let's go out */
- if (slave == NULL)
- return 0;
-
- /* Get/Map slave interrupt */
- cascade = irq_of_parse_and_map(slave, 0);
- if (cascade == NO_IRQ) {
- printk(KERN_ERR "Failed to map cascade IRQ\n");
- return 0;
- }
-
- mpic2 = pmac_setup_one_mpic(slave, 0);
- if (mpic2 == NULL) {
- printk(KERN_ERR "Failed to setup slave MPIC\n");
- of_node_put(slave);
- return 0;
- }
- set_irq_data(cascade, mpic2);
- set_irq_chained_handler(cascade, pmac_u3_cascade);
-
- of_node_put(slave);
- return 0;
-}
-
void __init pmac_pic_init(void)
{
@@ -574,27 +434,17 @@ void __init pmac_pic_init(void)
/* 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;
if (get_property(of_chosen, "linux,bootx", NULL) != NULL)
flags |= OF_IMAP_NO_PHANDLE;
-#endif /* CONFIG_PPC_32 */
of_irq_map_init(flags);
- /* We first try to detect Apple's new Core99 chipset, since mac-io
- * is quite different on those machines and contains an IBM MPIC2.
- */
- if (pmac_pic_probe_mpic() == 0)
- return;
-
-#ifdef CONFIG_PPC32
pmac_pic_probe_oldstyle();
-#endif
}
-#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
+#ifdef CONFIG_PM
/*
* These procedures are used in implementing sleep on the powerbooks.
* sleep_save_intrs() saves the states of all interrupt enables
@@ -662,7 +512,7 @@ static int pmacpic_resume(struct sys_dev
return 0;
}
-#endif /* CONFIG_PM && CONFIG_PPC32 */
+#endif /* CONFIG_PM */
static struct sysdev_class pmacpic_sysclass = {
set_kset_name("pmac_pic"),
@@ -674,18 +524,17 @@ static struct sys_device device_pmacpic
};
static struct sysdev_driver driver_pmacpic = {
-#if defined(CONFIG_PM) && defined(CONFIG_PPC32)
+#ifdef CONFIG_PM
.suspend = &pmacpic_suspend,
.resume = &pmacpic_resume,
-#endif /* CONFIG_PM && CONFIG_PPC32 */
+#endif /* CONFIG_PM */
};
static int __init init_pmacpic_sysfs(void)
{
-#ifdef CONFIG_PPC32
if (max_irqs == 0)
return -ENODEV;
-#endif
+
printk(KERN_DEBUG "Registering pmac pic with sysfs...\n");
sysdev_class_register(&pmacpic_sysclass);
sysdev_register(&device_pmacpic);
--- mb-wireless.orig/arch/powerpc/platforms/powermac/pmac.h 2007-02-02 11:56:19.793225416 +0100
+++ mb-wireless/arch/powerpc/platforms/powermac/pmac.h 2007-02-05 08:14:41.110498543 +0100
@@ -45,5 +45,6 @@ extern void pmac_ide_init_hwif_ports(hw_
extern int pmac_nvram_init(void);
extern void pmac_pic_init(void);
+extern int pmac_pic_probe_mpic(void);
#endif /* __PMAC_H__ */
--- mb-wireless.orig/arch/powerpc/platforms/powermac/setup.c 2007-02-02 11:56:19.863225416 +0100
+++ mb-wireless/arch/powerpc/platforms/powermac/setup.c 2007-02-05 08:16:31.800498543 +0100
@@ -718,13 +718,28 @@ static int pmac_pci_probe_mode(struct pc
}
#endif
+static void __init pmac_init_irq(void)
+{
+ int ret;
+
+ /* We first try to detect Apple's new Core99 chipset, since mac-io
+ * is quite different on those machines and contains an IBM MPIC2.
+ */
+ ret = pmac_pic_probe_mpic();
+
+#ifdef CONFIG_PPC32
+ if (!ret)
+ pmac_pic_init();
+#endif
+}
+
define_machine(powermac) {
.name = "PowerMac",
.probe = pmac_probe,
.setup_arch = pmac_setup_arch,
.init_early = pmac_init_early,
.show_cpuinfo = pmac_show_cpuinfo,
- .init_IRQ = pmac_pic_init,
+ .init_IRQ = pmac_init_irq,
.get_irq = NULL, /* changed later */
.pci_irq_fixup = pmac_pci_irq_fixup,
.restart = pmac_restart,
More information about the Linuxppc-dev
mailing list