LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH] powerpc: Make alignment exception always check exception table
From: Greg KH @ 2006-11-01  6:34 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <1162350571.25682.389.camel@localhost.localdomain>

On Wed, Nov 01, 2006 at 02:09:30PM +1100, Benjamin Herrenschmidt wrote:
> The alignment exception used to only check the exception table for
> -EFAULT, not for other errors. That opens an oops window if we can
> coerce the kernel into getting an alignment exception for other reasons
> in what would normally be a user-protected accessor, which can be done
> via some of the futex ops. This fixes it by always checking the
> exception tables.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
> 
> This is 2.6.19 material and should probably go into stable as well.
> (Greg: take it if paulus acks it and it applies :)

Please forward the final patch (which ever version it is :) to the
stable@kernel.org address when this goes into mainline.

thanks,

greg k-h

^ permalink raw reply

* [PATCH] powerpc: Make pci_read_irq_line the default
From: Benjamin Herrenschmidt @ 2006-11-01  5:02 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list

This patch reworks the way IRQs are fixed up on PCI for arch powerpc.

It makes pci_read_irq_line() called by default in the PCI code for
devices that are probed, and add an optional per-device fixup in
ppc_md for platforms that really need to correct what they obtain
from pci_read_irq_line().

It also removes ppc_md.irq_bus_setup which was only used by pSeries
and should not be needed anymore.

I've also removed the pSeries s7a workaround as it can't work with
the current interrupt code anyway. I'm trying to get one of these
machines working so I can test a proper fix for that problem.

I also haven't updated the old-style fixup code from 85xx_cds.c
because it's actually buggy :) It assigns pci_dev->irq hard coded
numbers which is no good with the new IRQ mapping code. It should
at least use irq_create_mapping(NULL, hard_coded_number); and possibly
also set_irq_type() to set them as level low.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

This version doesn't touch mpc7448hpc2 which is properly fixed by a
different patch from Zang Roy. Please apply to powerpc.git, it should
go early in 2.6.20.

Index: linux-work/arch/powerpc/kernel/pci_32.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_32.c	2006-10-23 14:41:37.000000000 +1000
+++ linux-work/arch/powerpc/kernel/pci_32.c	2006-10-30 12:13:32.000000000 +1100
@@ -1338,6 +1338,7 @@ void __init pcibios_fixup_bus(struct pci
 	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
 	unsigned long io_offset;
 	struct resource *res;
+	struct pci_device *dev;
 	int i;
 
 	io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
@@ -1390,8 +1391,16 @@ void __init pcibios_fixup_bus(struct pci
 		}
 	}
 
+	/* Platform specific bus fixups */
 	if (ppc_md.pcibios_fixup_bus)
 		ppc_md.pcibios_fixup_bus(bus);
+
+	/* Read default IRQs and fixup if necessary */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pci_read_irq_line(dev);
+		if (ppc_md.pci_irq_fixup)
+			ppc_md.pci_irq_fixup(dev);
+	}
 }
 
 char __init *pcibios_setup(char *str)
Index: linux-work/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_64.c	2006-10-23 14:41:37.000000000 +1000
+++ linux-work/arch/powerpc/kernel/pci_64.c	2006-10-30 12:13:32.000000000 +1100
@@ -1223,8 +1223,12 @@ static void __devinit do_bus_setup(struc
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		ppc_md.iommu_dev_setup(dev);
 
-	if (ppc_md.irq_bus_setup)
-		ppc_md.irq_bus_setup(bus);
+	/* Read default IRQs and fixup if necessary */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pci_read_irq_line(dev);
+		if (ppc_md.pci_irq_fixup)
+			ppc_md.pci_irq_fixup(dev);
+	}
 }
 
 void __devinit pcibios_fixup_bus(struct pci_bus *bus)
Index: linux-work/arch/powerpc/platforms/pseries/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/pseries/pci.c	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/pseries/pci.c	2006-10-30 12:13:32.000000000 +1100
@@ -29,8 +29,6 @@
 #include <asm/prom.h>
 #include <asm/ppc-pci.h>
 
-static int __devinitdata s7a_workaround = -1;
-
 #if 0
 void pcibios_name_device(struct pci_dev *dev)
 {
@@ -57,39 +55,6 @@ void pcibios_name_device(struct pci_dev 
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
 #endif
 
-static void __devinit check_s7a(void)
-{
-	struct device_node *root;
-	const char *model;
-
-	s7a_workaround = 0;
-	root = of_find_node_by_path("/");
-	if (root) {
-		model = get_property(root, "model", NULL);
-		if (model && !strcmp(model, "IBM,7013-S7A"))
-			s7a_workaround = 1;
-		of_node_put(root);
-	}
-}
-
-void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
-{
-	struct pci_dev *dev;
-
-	if (s7a_workaround < 0)
-		check_s7a();
-	list_for_each_entry(dev, &bus->devices, bus_list) {
-		pci_read_irq_line(dev);
-		if (s7a_workaround) {
-			if (dev->irq > 16) {
-				dev->irq -= 3;
-				pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-					dev->irq);
-			}
-		}
-	}
-}
-
 static void __init pSeries_request_regions(void)
 {
 	if (!isa_io_base)
Index: linux-work/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/pseries/setup.c	2006-10-09 12:03:33.000000000 +1000
+++ linux-work/arch/powerpc/platforms/pseries/setup.c	2006-10-30 12:13:32.000000000 +1100
@@ -553,7 +553,6 @@ define_machine(pseries) {
 	.log_error		= pSeries_log_error,
 	.pcibios_fixup		= pSeries_final_fixup,
 	.pci_probe_mode		= pSeries_pci_probe_mode,
-	.irq_bus_setup		= pSeries_irq_bus_setup,
 	.restart		= rtas_restart,
 	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
Index: linux-work/include/asm-powerpc/machdep.h
===================================================================
--- linux-work.orig/include/asm-powerpc/machdep.h	2006-10-09 12:03:34.000000000 +1000
+++ linux-work/include/asm-powerpc/machdep.h	2006-10-30 12:13:32.000000000 +1100
@@ -86,7 +86,6 @@ struct machdep_calls {
 	void		(*tce_flush)(struct iommu_table *tbl);
 	void		(*iommu_dev_setup)(struct pci_dev *dev);
 	void		(*iommu_bus_setup)(struct pci_bus *bus);
-	void		(*irq_bus_setup)(struct pci_bus *bus);
 #endif /* CONFIG_PPC64 */
 
 	int		(*probe)(void);
@@ -106,6 +105,7 @@ struct machdep_calls {
 	/* Called after scanning the bus, before allocating resources */
 	void		(*pcibios_fixup)(void);
 	int		(*pci_probe_mode)(struct pci_bus *);
+	void		(*pci_irq_fixup)(struct pci_dev *dev);
 
 	void		(*restart)(char *cmd);
 	void		(*power_off)(void);
Index: linux-work/include/asm-powerpc/ppc-pci.h
===================================================================
--- linux-work.orig/include/asm-powerpc/ppc-pci.h	2006-10-06 13:48:24.000000000 +1000
+++ linux-work/include/asm-powerpc/ppc-pci.h	2006-10-30 12:13:32.000000000 +1100
@@ -47,7 +47,6 @@ unsigned long get_phb_buid (struct devic
 
 /* From pSeries_pci.h */
 extern void pSeries_final_fixup(void);
-extern void pSeries_irq_bus_setup(struct pci_bus *bus);
 
 extern unsigned long pci_probe_only;
 
Index: linux-work/arch/powerpc/platforms/cell/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/cell/setup.c	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/cell/setup.c	2006-10-30 12:13:32.000000000 +1100
@@ -80,14 +80,6 @@ static void cell_progress(char *s, unsig
 	printk("*** %04x : %s\n", hex, s ? s : "");
 }
 
-static void __init cell_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	for_each_pci_dev(dev)
-		pci_read_irq_line(dev);
-}
-
 static void __init cell_init_irq(void)
 {
 	iic_init_IRQ();
@@ -180,7 +172,6 @@ define_machine(cell) {
 	.check_legacy_ioport	= cell_check_legacy_ioport,
 	.progress		= cell_progress,
 	.init_IRQ       	= cell_init_irq,
-	.pcibios_fixup		= cell_pcibios_fixup,
 #ifdef CONFIG_KEXEC
 	.machine_kexec		= default_machine_kexec,
 	.machine_kexec_prepare	= default_machine_kexec_prepare,
Index: linux-work/arch/powerpc/platforms/maple/maple.h
===================================================================
--- linux-work.orig/arch/powerpc/platforms/maple/maple.h	2006-01-14 14:43:22.000000000 +1100
+++ linux-work/arch/powerpc/platforms/maple/maple.h	2006-10-30 12:13:32.000000000 +1100
@@ -8,5 +8,5 @@ extern void maple_get_rtc_time(struct rt
 extern unsigned long maple_get_boot_time(void);
 extern void maple_calibrate_decr(void);
 extern void maple_pci_init(void);
-extern void maple_pcibios_fixup(void);
+extern void maple_pci_irq_fixup(struct pci_dev *dev);
 extern int maple_pci_get_legacy_ide_irq(struct pci_dev *dev, int channel);
Index: linux-work/arch/powerpc/platforms/maple/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/maple/pci.c	2006-10-13 17:23:48.000000000 +1000
+++ linux-work/arch/powerpc/platforms/maple/pci.c	2006-10-30 12:13:32.000000000 +1100
@@ -502,38 +502,29 @@ static int __init add_bridge(struct devi
 }
 
 
-void __init maple_pcibios_fixup(void)
+void __devinit maple_pci_irq_fixup(struct pci_dev *dev)
 {
-	struct pci_dev *dev = NULL;
+	DBG(" -> maple_pci_irq_fixup\n");
 
-	DBG(" -> maple_pcibios_fixup\n");
-
-	for_each_pci_dev(dev) {
-		/* Fixup IRQ for PCIe host */
-		if (u4_pcie != NULL && dev->bus->number == 0 &&
-		    pci_bus_to_host(dev->bus) == u4_pcie) {
-			printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n");
-			dev->irq = irq_create_mapping(NULL, 1);
-			if (dev->irq != NO_IRQ)
-				set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
-			continue;
-		}
-
-		/* Hide AMD8111 IDE interrupt when in legacy mode so
-		 * the driver calls pci_get_legacy_ide_irq()
-		 */
-		if (dev->vendor == PCI_VENDOR_ID_AMD &&
-		    dev->device == PCI_DEVICE_ID_AMD_8111_IDE &&
-		    (dev->class & 5) != 5) {
-			dev->irq = NO_IRQ;
-			continue;
-		}
+	/* Fixup IRQ for PCIe host */
+	if (u4_pcie != NULL && dev->bus->number == 0 &&
+	    pci_bus_to_host(dev->bus) == u4_pcie) {
+		printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n");
+		dev->irq = irq_create_mapping(NULL, 1);
+		if (dev->irq != NO_IRQ)
+			set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
+	}
 
-		/* For all others, map the interrupt from the device-tree */
-		pci_read_irq_line(dev);
+	/* Hide AMD8111 IDE interrupt when in legacy mode so
+	 * the driver calls pci_get_legacy_ide_irq()
+	 */
+	if (dev->vendor == PCI_VENDOR_ID_AMD &&
+	    dev->device == PCI_DEVICE_ID_AMD_8111_IDE &&
+	    (dev->class & 5) != 5) {
+		dev->irq = NO_IRQ;
 	}
 
-	DBG(" <- maple_pcibios_fixup\n");
+	DBG(" <- maple_pci_irq_fixup\n");
 }
 
 static void __init maple_fixup_phb_resources(void)
Index: linux-work/arch/powerpc/platforms/maple/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/maple/setup.c	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/maple/setup.c	2006-10-30 12:13:32.000000000 +1100
@@ -312,7 +312,7 @@ define_machine(maple_md) {
 	.setup_arch		= maple_setup_arch,
 	.init_early		= maple_init_early,
 	.init_IRQ		= maple_init_IRQ,
-	.pcibios_fixup		= maple_pcibios_fixup,
+	.pci_irq_fixup		= maple_pci_irq_fixup,
 	.pci_get_legacy_ide_irq	= maple_pci_get_legacy_ide_irq,
 	.restart		= maple_restart,
 	.power_off		= maple_power_off,
Index: linux-work/arch/powerpc/platforms/powermac/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/pci.c	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/powermac/pci.c	2006-10-30 12:13:32.000000000 +1100
@@ -985,30 +985,23 @@ static int __init add_bridge(struct devi
 	return 0;
 }
 
-void __init pmac_pcibios_fixup(void)
+void __devinit pmac_pci_irq_fixup(struct pci_dev *dev)
 {
-	struct pci_dev* dev = NULL;
-
-	for_each_pci_dev(dev) {
-		/* Read interrupt from the device-tree */
-		pci_read_irq_line(dev);
-
 #ifdef CONFIG_PPC32
-		/* Fixup interrupt for the modem/ethernet combo controller.
-		 * on machines with a second ohare chip.
-		 * The number in the device tree (27) is bogus (correct for
-		 * the ethernet-only board but not the combo ethernet/modem
-		 * board). The real interrupt is 28 on the second controller
-		 * -> 28+32 = 60.
-		 */
-		if (has_second_ohare &&
-		    dev->vendor == PCI_VENDOR_ID_DEC &&
-		    dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) {
-			dev->irq = irq_create_mapping(NULL, 60);
-			set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
-		}
-#endif /* CONFIG_PPC32 */
+	/* Fixup interrupt for the modem/ethernet combo controller.
+	 * on machines with a second ohare chip.
+	 * The number in the device tree (27) is bogus (correct for
+	 * the ethernet-only board but not the combo ethernet/modem
+	 * board). The real interrupt is 28 on the second controller
+	 * -> 28+32 = 60.
+	 */
+	if (has_second_ohare &&
+	    dev->vendor == PCI_VENDOR_ID_DEC &&
+	    dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) {
+		dev->irq = irq_create_mapping(NULL, 60);
+		set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
 	}
+#endif /* CONFIG_PPC32 */
 }
 
 #ifdef CONFIG_PPC64
Index: linux-work/arch/powerpc/platforms/powermac/pmac.h
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/pmac.h	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/powermac/pmac.h	2006-10-30 12:13:32.000000000 +1100
@@ -20,7 +20,7 @@ extern void pmac_get_rtc_time(struct rtc
 extern int pmac_set_rtc_time(struct rtc_time *);
 extern void pmac_read_rtc_time(void);
 extern void pmac_calibrate_decr(void);
-extern void pmac_pcibios_fixup(void);
+extern void pmac_pci_irq_fixup(struct pci_dev *);
 extern void pmac_pci_init(void);
 extern unsigned long pmac_ide_get_base(int index);
 extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
Index: linux-work/arch/powerpc/platforms/powermac/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/setup.c	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/powermac/setup.c	2006-10-30 12:13:32.000000000 +1100
@@ -727,7 +727,7 @@ define_machine(powermac) {
 	.show_cpuinfo		= pmac_show_cpuinfo,
 	.init_IRQ		= pmac_pic_init,
 	.get_irq		= NULL,	/* changed later */
-	.pcibios_fixup		= pmac_pcibios_fixup,
+	.pci_irq_fixup		= pmac_pci_irq_fixup,
 	.restart		= pmac_restart,
 	.power_off		= pmac_power_off,
 	.halt			= pmac_halt,
Index: linux-work/arch/powerpc/platforms/pasemi/pasemi.h
===================================================================
--- linux-work.orig/arch/powerpc/platforms/pasemi/pasemi.h	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/pasemi/pasemi.h	2006-10-30 12:13:32.000000000 +1100
@@ -3,6 +3,5 @@
 
 extern unsigned long pas_get_boot_time(void);
 extern void pas_pci_init(void);
-extern void pas_pcibios_fixup(void);
 
 #endif /* _PASEMI_PASEMI_H */
Index: linux-work/arch/powerpc/platforms/pasemi/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/pasemi/pci.c	2006-10-11 11:48:41.000000000 +1000
+++ linux-work/arch/powerpc/platforms/pasemi/pci.c	2006-10-30 12:13:32.000000000 +1100
@@ -148,14 +148,6 @@ static int __init add_bridge(struct devi
 }
 
 
-void __init pas_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	for_each_pci_dev(dev)
-		pci_read_irq_line(dev);
-}
-
 static void __init pas_fixup_phb_resources(void)
 {
 	struct pci_controller *hose, *tmp;
Index: linux-work/arch/powerpc/platforms/pasemi/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/pasemi/setup.c	2006-10-09 12:03:33.000000000 +1000
+++ linux-work/arch/powerpc/platforms/pasemi/setup.c	2006-10-30 12:13:32.000000000 +1100
@@ -176,7 +176,6 @@ define_machine(pas) {
 	.init_early		= pas_init_early,
 	.init_IRQ		= pas_init_IRQ,
 	.get_irq		= mpic_get_irq,
-	.pcibios_fixup		= pas_pcibios_fixup,
 	.restart		= pas_restart,
 	.power_off		= pas_power_off,
 	.halt			= pas_halt,
Index: linux-work/arch/powerpc/platforms/82xx/mpc82xx_ads.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/82xx/mpc82xx_ads.c	2006-10-11 11:48:41.000000000 +1000
+++ linux-work/arch/powerpc/platforms/82xx/mpc82xx_ads.c	2006-10-30 12:13:32.000000000 +1100
@@ -515,16 +515,6 @@ static int m82xx_pci_exclude_device(u_ch
 		return PCIBIOS_SUCCESSFUL;
 }
 
-static void
-__init mpc82xx_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	for_each_pci_dev(dev) {
-		pci_read_irq_line(dev);
-	}
-}
-
 void __init add_bridge(struct device_node *np)
 {
 	int len;
@@ -597,9 +587,6 @@ static void __init mpc82xx_ads_setup_arc
 		add_bridge(np);
 
 	of_node_put(np);
-	ppc_md.pci_map_irq = NULL;
-	ppc_md.pcibios_fixup = mpc82xx_pcibios_fixup;
-	ppc_md.pcibios_fixup_bus = NULL;
 #endif
 
 #ifdef  CONFIG_ROOT_NFS
Index: linux-work/arch/powerpc/platforms/83xx/mpc834x_itx.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/83xx/mpc834x_itx.c	2006-10-09 12:03:33.000000000 +1000
+++ linux-work/arch/powerpc/platforms/83xx/mpc834x_itx.c	2006-10-30 12:13:32.000000000 +1100
@@ -122,7 +122,4 @@ define_machine(mpc834x_itx) {
 	.time_init		= mpc83xx_time_init,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
-#ifdef CONFIG_PCI
-	.pcibios_fixup		= mpc83xx_pcibios_fixup,
-#endif
 };
Index: linux-work/arch/powerpc/platforms/83xx/mpc834x_sys.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/83xx/mpc834x_sys.c	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/83xx/mpc834x_sys.c	2006-10-30 12:13:32.000000000 +1100
@@ -137,7 +137,4 @@ define_machine(mpc834x_sys) {
 	.time_init		= mpc83xx_time_init,
 	.calibrate_decr		= generic_calibrate_decr,
 	.progress		= udbg_progress,
-#ifdef CONFIG_PCI
-	.pcibios_fixup		= mpc83xx_pcibios_fixup,
-#endif
 };
Index: linux-work/arch/powerpc/platforms/83xx/mpc83xx.h
===================================================================
--- linux-work.orig/arch/powerpc/platforms/83xx/mpc83xx.h	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/83xx/mpc83xx.h	2006-10-30 12:13:32.000000000 +1100
@@ -11,7 +11,6 @@
 
 extern int add_bridge(struct device_node *dev);
 extern int mpc83xx_exclude_device(u_char bus, u_char devfn);
-extern void mpc83xx_pcibios_fixup(void);
 extern void mpc83xx_restart(char *cmd);
 extern long mpc83xx_time_init(void);
 
Index: linux-work/arch/powerpc/platforms/83xx/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/83xx/pci.c	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/83xx/pci.c	2006-10-30 12:13:32.000000000 +1100
@@ -45,15 +45,6 @@ int mpc83xx_exclude_device(u_char bus, u
 	return PCIBIOS_SUCCESSFUL;
 }
 
-void __init mpc83xx_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	/* map all the PCI irqs */
-	for_each_pci_dev(dev)
-		pci_read_irq_line(dev);
-}
-
 int __init add_bridge(struct device_node *dev)
 {
 	int len;
Index: linux-work/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c	2006-10-09 12:03:33.000000000 +1000
+++ linux-work/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c	2006-10-30 12:13:32.000000000 +1100
@@ -398,15 +398,6 @@ mpc86xx_hpcn_show_cpuinfo(struct seq_fil
 }
 
 
-void __init mpc86xx_hpcn_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	for_each_pci_dev(dev)
-		pci_read_irq_line(dev);
-}
-
-
 /*
  * Called very early, device-tree isn't unflattened
  */
@@ -461,7 +452,6 @@ define_machine(mpc86xx_hpcn) {
 	.setup_arch		= mpc86xx_hpcn_setup_arch,
 	.init_IRQ		= mpc86xx_hpcn_init_irq,
 	.show_cpuinfo		= mpc86xx_hpcn_show_cpuinfo,
-	.pcibios_fixup		= mpc86xx_hpcn_pcibios_fixup,
 	.get_irq		= mpic_get_irq,
 	.restart		= mpc86xx_restart,
 	.time_init		= mpc86xx_time_init,
Index: linux-work/arch/powerpc/platforms/chrp/chrp.h
===================================================================
--- linux-work.orig/arch/powerpc/platforms/chrp/chrp.h	2006-09-08 17:17:10.000000000 +1000
+++ linux-work/arch/powerpc/platforms/chrp/chrp.h	2006-10-30 12:13:32.000000000 +1100
@@ -9,4 +9,3 @@ extern long chrp_time_init(void);
 
 extern void chrp_find_bridges(void);
 extern void chrp_event_scan(unsigned long);
-extern void chrp_pcibios_fixup(void);
Index: linux-work/arch/powerpc/platforms/chrp/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/chrp/setup.c	2006-10-27 15:39:09.000000000 +1000
+++ linux-work/arch/powerpc/platforms/chrp/setup.c	2006-10-30 12:13:32.000000000 +1100
@@ -600,7 +600,6 @@ define_machine(chrp) {
 	.init			= chrp_init2,
 	.show_cpuinfo		= chrp_show_cpuinfo,
 	.init_IRQ		= chrp_init_IRQ,
-	.pcibios_fixup		= chrp_pcibios_fixup,
 	.restart		= rtas_restart,
 	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
Index: linux-work/arch/powerpc/platforms/85xx/mpc85xx_ads.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/85xx/mpc85xx_ads.c	2006-10-09 12:03:33.000000000 +1000
+++ linux-work/arch/powerpc/platforms/85xx/mpc85xx_ads.c	2006-10-30 12:13:32.000000000 +1100
@@ -53,15 +53,6 @@ mpc85xx_exclude_device(u_char bus, u_cha
 	else
 		return PCIBIOS_SUCCESSFUL;
 }
-
-void __init
-mpc85xx_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	for_each_pci_dev(dev)
-		pci_read_irq_line(dev);
-}
 #endif /* CONFIG_PCI */
 
 #ifdef CONFIG_CPM2
@@ -253,8 +244,6 @@ static void __init mpc85xx_ads_setup_arc
 #ifdef CONFIG_PCI
 	for (np = NULL; (np = of_find_node_by_type(np, "pci")) != NULL;)
 		add_bridge(np);
-
-	ppc_md.pcibios_fixup = mpc85xx_pcibios_fixup;
 	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
 
Index: linux-work/arch/powerpc/platforms/chrp/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/chrp/pci.c	2006-10-06 13:47:54.000000000 +1000
+++ linux-work/arch/powerpc/platforms/chrp/pci.c	2006-10-30 12:13:32.000000000 +1100
@@ -156,15 +156,6 @@ hydra_init(void)
 	return 1;
 }
 
-void __init
-chrp_pcibios_fixup(void)
-{
-	struct pci_dev *dev = NULL;
-
-	for_each_pci_dev(dev)
-		pci_read_irq_line(dev);
-}
-
 #define PRG_CL_RESET_VALID 0x00010000
 
 static void __init

^ permalink raw reply

* [PATCH] powerpc: Xserve cpu-meter driver
From: Benjamin Herrenschmidt @ 2006-11-01  4:51 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list

This is a small driver for the Xserve G5 CPU-meter blue LEDs on the
front-panel. It might work on the Xserve G4 as well though that was
not tested. It's pretty basic and could use some improvements if
somebody cares doing them :)

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Index: linux-work/drivers/macintosh/rack-meter.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-work/drivers/macintosh/rack-meter.c	2006-11-01 15:47:35.000000000 +1100
@@ -0,0 +1,612 @@
+/*
+ * RackMac vu-meter driver
+ *
+ * (c) Copyright 2006 Benjamin Herrenschmidt, IBM Corp.
+ *                    <benh@kernel.crashing.org>
+ *
+ * Released under the term of the GNU GPL v2.
+ *
+ * Support the CPU-meter LEDs of the Xserve G5
+ *
+ * TODO: Implement PWM to do variable intensity and provide userland
+ * interface for fun. Also, the CPU-meter could be made nicer by being
+ * a bit less "immediate" but giving instead a more average load over
+ * time. Patches welcome :-)
+ *
+ */
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/dbdma.h>
+#include <asm/dbdma.h>
+#include <asm/macio.h>
+#include <asm/keylargo.h>
+
+/* Number of samples in a sample buffer */
+#define SAMPLE_COUNT		256
+
+/* CPU meter sampling rate in ms */
+#define CPU_SAMPLING_RATE	250
+
+struct rackmeter_dma {
+	struct dbdma_cmd	cmd[4]			____cacheline_aligned;
+	u32			mark			____cacheline_aligned;
+	u32			buf1[SAMPLE_COUNT]	____cacheline_aligned;
+	u32			buf2[SAMPLE_COUNT]	____cacheline_aligned;
+} ____cacheline_aligned;
+
+struct rackmeter_cpu {
+	struct work_struct	sniffer;
+	cputime64_t		prev_wall;
+	cputime64_t		prev_idle;
+	int			zero;
+} ____cacheline_aligned;
+
+struct rackmeter {
+	struct macio_dev		*mdev;
+	unsigned int			irq;
+	struct device_node		*i2s;
+	u8				*ubuf;
+	struct dbdma_regs __iomem	*dma_regs;
+	void __iomem			*i2s_regs;
+	dma_addr_t			dma_buf_p;
+	struct rackmeter_dma		*dma_buf_v;
+	int				stale_irq;
+	struct rackmeter_cpu		cpu[2];
+	int				paused;
+	struct mutex			sem;
+};
+
+/* To be set as a tunable */
+static int rackmeter_ignore_nice;
+
+/* This GPIO is whacked by the OS X driver when initializing */
+#define RACKMETER_MAGIC_GPIO	0x78
+
+/* This is copied from cpufreq_ondemand, maybe we should put it in
+ * a common header somewhere
+ */
+static inline cputime64_t get_cpu_idle_time(unsigned int cpu)
+{
+	cputime64_t retval;
+
+	retval = cputime64_add(kstat_cpu(cpu).cpustat.idle,
+			kstat_cpu(cpu).cpustat.iowait);
+
+	if (rackmeter_ignore_nice)
+		retval = cputime64_add(retval, kstat_cpu(cpu).cpustat.nice);
+
+	return retval;
+}
+
+static void rackmeter_setup_i2s(struct rackmeter *rm)
+{
+	struct macio_chip *macio = rm->mdev->bus->chip;
+
+	/* First whack magic GPIO */
+	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, RACKMETER_MAGIC_GPIO, 5);
+
+
+	/* Call feature code to enable the sound channel and the proper
+	 * clock sources
+	 */
+	pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, rm->i2s, 0, 1);
+
+	/* Power i2s and stop i2s clock. We whack MacIO FCRs directly for now.
+	 * This is a bit racy, thus we should add new platform functions to
+	 * handle that. snd-aoa needs that too
+	 */
+	MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_ENABLE);
+	MACIO_BIC(KEYLARGO_FCR1, KL1_I2S0_CLK_ENABLE_BIT);
+	(void)MACIO_IN32(KEYLARGO_FCR1);
+	udelay(10);
+
+	/* Then setup i2s. For now, we use the same magic value that
+	 * the OS X driver seems to use. We might want to play around
+	 * with the clock divisors later
+	 */
+	out_le32(rm->i2s_regs + 0x10, 0x01fa0000);
+	(void)in_le32(rm->i2s_regs + 0x10);
+	udelay(10);
+
+	/* Fully restart i2s*/
+	MACIO_BIS(KEYLARGO_FCR1, KL1_I2S0_CELL_ENABLE |
+		  KL1_I2S0_CLK_ENABLE_BIT);
+	(void)MACIO_IN32(KEYLARGO_FCR1);
+	udelay(10);
+}
+
+static void rackmeter_set_default_pattern(struct rackmeter *rm)
+{
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		if (i < 8)
+			rm->ubuf[i] = (i & 1) * 255;
+		else
+			rm->ubuf[i] = ((~i) & 1) * 255;
+	}
+}
+
+static void rackmeter_do_pause(struct rackmeter *rm, int pause)
+{
+	struct rackmeter_dma *rdma = rm->dma_buf_v;
+
+	pr_debug("rackmeter: %s\n", pause ? "paused" : "started");
+
+	rm->paused = pause;
+	if (pause) {
+		DBDMA_DO_STOP(rm->dma_regs);
+		return;
+	}
+	memset(rdma->buf1, 0, SAMPLE_COUNT & sizeof(u32));
+	memset(rdma->buf2, 0, SAMPLE_COUNT & sizeof(u32));
+
+	rm->dma_buf_v->mark = 0;
+
+	mb();
+	out_le32(&rm->dma_regs->cmdptr_hi, 0);
+	out_le32(&rm->dma_regs->cmdptr, rm->dma_buf_p);
+	out_le32(&rm->dma_regs->control, (RUN << 16) | RUN);
+}
+
+static void rackmeter_setup_dbdma(struct rackmeter *rm)
+{
+	struct rackmeter_dma *db = rm->dma_buf_v;
+	struct dbdma_cmd *cmd = db->cmd;
+
+	/* Make sure dbdma is reset */
+	DBDMA_DO_RESET(rm->dma_regs);
+
+	pr_debug("rackmeter: mark offset=0x%lx\n",
+		 offsetof(struct rackmeter_dma, mark));
+	pr_debug("rackmeter: buf1 offset=0x%lx\n",
+		 offsetof(struct rackmeter_dma, buf1));
+	pr_debug("rackmeter: buf2 offset=0x%lx\n",
+		 offsetof(struct rackmeter_dma, buf2));
+
+	/* Prepare 4 dbdma commands for the 2 buffers */
+	memset(cmd, 0, 4 * sizeof(struct dbdma_cmd));
+	st_le16(&cmd->req_count, 4);
+	st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM);
+	st_le32(&cmd->phy_addr, rm->dma_buf_p +
+		offsetof(struct rackmeter_dma, mark));
+	st_le32(&cmd->cmd_dep, 0x02000000);
+	cmd++;
+
+	st_le16(&cmd->req_count, SAMPLE_COUNT * 4);
+	st_le16(&cmd->command, OUTPUT_MORE);
+	st_le32(&cmd->phy_addr, rm->dma_buf_p +
+		offsetof(struct rackmeter_dma, buf1));
+	cmd++;
+
+	st_le16(&cmd->req_count, 4);
+	st_le16(&cmd->command, STORE_WORD | INTR_ALWAYS | KEY_SYSTEM);
+	st_le32(&cmd->phy_addr, rm->dma_buf_p +
+		offsetof(struct rackmeter_dma, mark));
+	st_le32(&cmd->cmd_dep, 0x01000000);
+	cmd++;
+
+	st_le16(&cmd->req_count, SAMPLE_COUNT * 4);
+	st_le16(&cmd->command, OUTPUT_MORE | BR_ALWAYS);
+	st_le32(&cmd->phy_addr, rm->dma_buf_p +
+		offsetof(struct rackmeter_dma, buf2));
+	st_le32(&cmd->cmd_dep, rm->dma_buf_p);
+
+	rackmeter_do_pause(rm, 0);
+}
+
+static void rackmeter_do_timer(void *data)
+{
+	struct rackmeter *rm = data;
+	unsigned int cpu = smp_processor_id();
+	struct rackmeter_cpu *rcpu = &rm->cpu[cpu];
+	cputime64_t cur_jiffies, total_idle_ticks;
+	unsigned int total_ticks, idle_ticks;
+	int i, offset, load, cumm, pause;
+
+	cur_jiffies = jiffies64_to_cputime64(get_jiffies_64());
+	total_ticks = (unsigned int)cputime64_sub(cur_jiffies,
+						  rcpu->prev_wall);
+	rcpu->prev_wall = cur_jiffies;
+
+	total_idle_ticks = get_cpu_idle_time(cpu);
+	idle_ticks = (unsigned int) cputime64_sub(total_idle_ticks,
+				rcpu->prev_idle);
+	rcpu->prev_idle = total_idle_ticks;
+
+	/* We do a very dumb calculation to update the LEDs for now,
+	 * we'll do better once we have actual PWM implemented
+	 */
+	load = (9 * (total_ticks - idle_ticks)) / total_ticks;
+
+	offset = cpu << 3;
+	cumm = 0;
+	for (i = 0; i < 8; i++) {
+		u8 ub = (load > i) ? 0xff : 0;
+		rm->ubuf[i + offset] = ub;
+		cumm |= ub;
+	}
+	rcpu->zero = (cumm == 0);
+
+	/* Now check if LEDs are all 0, we can stop DMA */
+	pause = (rm->cpu[0].zero && rm->cpu[1].zero);
+	if (pause != rm->paused) {
+		mutex_lock(&rm->sem);
+		pause = (rm->cpu[0].zero && rm->cpu[1].zero);
+		rackmeter_do_pause(rm, pause);
+		mutex_unlock(&rm->sem);
+	}
+	schedule_delayed_work_on(cpu, &rcpu->sniffer,
+				 msecs_to_jiffies(CPU_SAMPLING_RATE));
+}
+
+static void __devinit rackmeter_init_cpu_sniffer(struct rackmeter *rm)
+{
+	unsigned int cpu;
+
+	/* This driver works only with 1 or 2 CPUs numbered 0 and 1,
+	 * but that's really all we have on Apple Xserve. It doesn't
+	 * play very nice with CPU hotplug neither but we don't do that
+	 * on those machines yet
+	 */
+
+	INIT_WORK(&rm->cpu[0].sniffer, rackmeter_do_timer, rm);
+	INIT_WORK(&rm->cpu[1].sniffer, rackmeter_do_timer, rm);
+
+	for_each_online_cpu(cpu) {
+		struct rackmeter_cpu *rcpu;
+
+		if (cpu > 1)
+			continue;
+		rcpu = &rm->cpu[cpu];;
+		rcpu->prev_idle = get_cpu_idle_time(cpu);
+		rcpu->prev_wall = jiffies64_to_cputime64(get_jiffies_64());
+		schedule_delayed_work_on(cpu, &rm->cpu[cpu].sniffer,
+					 msecs_to_jiffies(CPU_SAMPLING_RATE));
+	}
+}
+
+static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
+{
+	cancel_rearming_delayed_work(&rm->cpu[0].sniffer);
+	cancel_rearming_delayed_work(&rm->cpu[1].sniffer);
+}
+
+static int rackmeter_setup(struct rackmeter *rm)
+{
+	pr_debug("rackmeter: setting up i2s..\n");
+	rackmeter_setup_i2s(rm);
+
+	pr_debug("rackmeter: setting up default pattern..\n");
+	rackmeter_set_default_pattern(rm);
+
+	pr_debug("rackmeter: setting up dbdma..\n");
+	rackmeter_setup_dbdma(rm);
+
+	pr_debug("rackmeter: start CPU measurements..\n");
+	rackmeter_init_cpu_sniffer(rm);
+
+	printk(KERN_INFO "RackMeter initialized\n");
+
+	return 0;
+}
+
+/*  XXX FIXME: No PWM yet, this is 0/1 */
+static u32 rackmeter_calc_sample(struct rackmeter *rm, unsigned int index)
+{
+	int led;
+	u32 sample = 0;
+
+	for (led = 0; led < 16; led++) {
+		sample >>= 1;
+		sample |= ((rm->ubuf[led] >= 0x80) << 15);
+	}
+	return (sample << 17) | (sample >> 15);
+}
+
+static irqreturn_t rackmeter_irq(int irq, void *arg)
+{
+	struct rackmeter *rm = arg;
+	struct rackmeter_dma *db = rm->dma_buf_v;
+	unsigned int mark, i;
+	u32 *buf;
+
+	/* Flush PCI buffers with an MMIO read. Maybe we could actually
+	 * check the status one day ... in case things go wrong, though
+	 * this never happened to me
+	 */
+	(void)in_le32(&rm->dma_regs->status);
+
+	/* Make sure the CPU gets us in order */
+	rmb();
+
+	/* Read mark */
+	mark = db->mark;
+	if (mark != 1 && mark != 2) {
+		printk(KERN_WARNING "rackmeter: Incorrect DMA mark 0x%08x\n",
+		       mark);
+		/* We allow for 3 errors like that (stale DBDMA irqs) */
+		if (++rm->stale_irq > 3) {
+			printk(KERN_ERR "rackmeter: Too many errors,"
+			       " stopping DMA\n");
+			DBDMA_DO_RESET(rm->dma_regs);
+		}
+		return IRQ_HANDLED;
+	}
+
+	/* Next buffer we need to fill is mark value */
+	buf = mark == 1 ? db->buf1 : db->buf2;
+
+	/* Fill it now. This routine converts the 8 bits depth sample array
+	 * into the PWM bitmap for each LED.
+	 */
+	for (i = 0; i < SAMPLE_COUNT; i++)
+		buf[i] = rackmeter_calc_sample(rm, i);
+
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit rackmeter_probe(struct macio_dev* mdev,
+				     const struct of_device_id *match)
+{
+	struct device_node *i2s = NULL, *np = NULL;
+	struct rackmeter *rm = NULL;
+	struct resource ri2s, rdma;
+	int rc = -ENODEV;
+
+	pr_debug("rackmeter_probe()\n");
+
+	/* Get i2s-a node */
+	while ((i2s = of_get_next_child(mdev->ofdev.node, i2s)) != NULL)
+	       if (strcmp(i2s->name, "i2s-a") == 0)
+		       break;
+	if (i2s == NULL) {
+		pr_debug("  i2s-a child not found\n");
+		goto bail;
+	}
+	/* Get lightshow or virtual sound */
+	while ((np = of_get_next_child(i2s, np)) != NULL) {
+	       if (strcmp(np->name, "lightshow") == 0)
+		       break;
+	       if ((strcmp(np->name, "sound") == 0) &&
+		   get_property(np, "virtual", NULL) != NULL)
+		       break;
+	}
+	if (np == NULL) {
+		pr_debug("  lightshow or sound+virtual child not found\n");
+		goto bail;
+	}
+
+	/* Create and initialize our instance data */
+	rm = kzalloc(sizeof(struct rackmeter), GFP_KERNEL);
+	if (rm == NULL) {
+		printk(KERN_ERR "rackmeter: failed to allocate memory !\n");
+		rc = -ENOMEM;
+		goto bail_release;
+	}
+	rm->mdev = mdev;
+	rm->i2s = i2s;
+	mutex_init(&rm->sem);
+	dev_set_drvdata(&mdev->ofdev.dev, rm);
+	/* Check resources availability. We need at least resource 0 and 1 */
+#if 0 /* Use that when i2s-a is finally an mdev per-se */
+	if (macio_resource_count(mdev) < 2 || macio_irq_count(mdev) < 2) {
+		printk(KERN_ERR
+		       "rackmeter: found match but lacks resources: %s"
+		       " (%d resources, %d interrupts)\n",
+		       mdev->ofdev.node->full_name);
+		rc = -ENXIO;
+		goto bail_free;
+	}
+	if (macio_request_resources(mdev, "rackmeter")) {
+		printk(KERN_ERR
+		       "rackmeter: failed to request resources: %s\n",
+		       mdev->ofdev.node->full_name);
+		rc = -EBUSY;
+		goto bail_free;
+	}
+	rm->irq = macio_irq(mdev, 1);
+#else
+	rm->irq = irq_of_parse_and_map(i2s, 1);
+	if (rm->irq == NO_IRQ ||
+	    of_address_to_resource(i2s, 0, &ri2s) ||
+	    of_address_to_resource(i2s, 1, &rdma)) {
+		printk(KERN_ERR
+		       "rackmeter: found match but lacks resources: %s",
+		       mdev->ofdev.node->full_name);
+		rc = -ENXIO;
+		goto bail_free;
+	}
+#endif
+
+	pr_debug("  i2s @0x%08x\n", (unsigned int)ri2s.start);
+	pr_debug("  dma @0x%08x\n", (unsigned int)rdma.start);
+	pr_debug("  irq %d\n", rm->irq);
+
+	rm->ubuf = (u8 *)__get_free_page(GFP_KERNEL);
+	if (rm->ubuf == NULL) {
+		printk(KERN_ERR
+		       "rackmeter: failed to allocate samples page !\n");
+		rc = -ENOMEM;
+		goto bail_release;
+	}
+
+	rm->dma_buf_v = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev,
+					   sizeof(struct rackmeter_dma),
+					   &rm->dma_buf_p, GFP_KERNEL);
+	if (rm->dma_buf_v == NULL) {
+		printk(KERN_ERR
+		       "rackmeter: failed to allocate dma buffer !\n");
+		rc = -ENOMEM;
+		goto bail_free_samples;
+	}
+#if 0
+	rm->i2s_regs = ioremap(macio_resource_start(mdev, 0), 0x1000);
+#else
+	rm->i2s_regs = ioremap(ri2s.start, 0x1000);
+#endif
+	if (rm->i2s_regs == NULL) {
+		printk(KERN_ERR
+		       "rackmeter: failed to map i2s registers !\n");
+		rc = -ENXIO;
+		goto bail_free_dma;
+	}
+#if 0
+	rm->dma_regs = ioremap(macio_resource_start(mdev, 1), 0x100);
+#else
+	rm->dma_regs = ioremap(rdma.start, 0x100);
+#endif
+	if (rm->dma_regs == NULL) {
+		printk(KERN_ERR
+		       "rackmeter: failed to map dma registers !\n");
+		rc = -ENXIO;
+		goto bail_unmap_i2s;
+	}
+
+	rc = rackmeter_setup(rm);
+	if (rc) {
+		printk(KERN_ERR
+		       "rackmeter: failed to initialize !\n");
+		rc = -ENXIO;
+		goto bail_unmap_dma;
+	}
+
+	rc = request_irq(rm->irq, rackmeter_irq, 0, "rackmeter", rm);
+	if (rc != 0) {
+		printk(KERN_ERR
+		       "rackmeter: failed to request interrupt !\n");
+		goto bail_stop_dma;
+	}
+	of_node_put(np);
+	return 0;
+
+ bail_stop_dma:
+	DBDMA_DO_RESET(rm->dma_regs);
+ bail_unmap_dma:
+	iounmap(rm->dma_regs);
+ bail_unmap_i2s:
+	iounmap(rm->i2s_regs);
+ bail_free_dma:
+	dma_free_coherent(&macio_get_pci_dev(mdev)->dev,
+			  sizeof(struct rackmeter_dma),
+			  rm->dma_buf_v, rm->dma_buf_p);
+ bail_free_samples:
+	free_page((unsigned long)rm->ubuf);
+ bail_release:
+#if 0
+	macio_release_resources(mdev);
+#endif
+ bail_free:
+	kfree(rm);
+ bail:
+	of_node_put(i2s);
+	of_node_put(np);
+	dev_set_drvdata(&mdev->ofdev.dev, NULL);
+	return rc;
+}
+
+static int __devexit rackmeter_remove(struct macio_dev* mdev)
+{
+	struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev);
+
+	/* Stop CPU sniffer timer & work queues */
+	rackmeter_stop_cpu_sniffer(rm);
+
+	/* Clear reference to private data */
+	dev_set_drvdata(&mdev->ofdev.dev, NULL);
+
+	/* Stop/reset dbdma */
+	DBDMA_DO_RESET(rm->dma_regs);
+
+	/* Release the IRQ */
+	free_irq(rm->irq, rm);
+
+	/* Unmap registers */
+	iounmap(rm->dma_regs);
+	iounmap(rm->i2s_regs);
+
+	/* Free DMA */
+	dma_free_coherent(&macio_get_pci_dev(mdev)->dev,
+			  sizeof(struct rackmeter_dma),
+			  rm->dma_buf_v, rm->dma_buf_p);
+
+	/* Free samples */
+	free_page((unsigned long)rm->ubuf);
+
+#if 0
+	/* Release resources */
+	macio_release_resources(mdev);
+#endif
+
+	/* Get rid of me */
+	kfree(rm);
+
+	return 0;
+}
+
+static int rackmeter_shutdown(struct macio_dev* mdev)
+{
+	struct rackmeter *rm = dev_get_drvdata(&mdev->ofdev.dev);
+
+	if (rm == NULL)
+		return -ENODEV;
+
+	/* Stop CPU sniffer timer & work queues */
+	rackmeter_stop_cpu_sniffer(rm);
+
+	/* Stop/reset dbdma */
+	DBDMA_DO_RESET(rm->dma_regs);
+
+	return 0;
+}
+
+static struct of_device_id rackmeter_match[] = {
+	{ .name = "i2s" },
+	{ }
+};
+
+static struct macio_driver rackmeter_drv = {
+	.name = "rackmeter",
+	.owner = THIS_MODULE,
+	.match_table = rackmeter_match,
+	.probe = rackmeter_probe,
+	.remove = rackmeter_remove,
+	.shutdown = rackmeter_shutdown,
+};
+
+
+static int __init rackmeter_init(void)
+{
+	pr_debug("rackmeter_init()\n");
+
+	return macio_register_driver(&rackmeter_drv);
+}
+
+static void __exit rackmeter_exit(void)
+{
+	pr_debug("rackmeter_exit()\n");
+
+	macio_unregister_driver(&rackmeter_drv);
+}
+
+module_init(rackmeter_init);
+module_exit(rackmeter_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
+MODULE_DESCRIPTION("RackMeter: Support vu-meter on XServe front panel");
Index: linux-work/drivers/macintosh/Kconfig
===================================================================
--- linux-work.orig/drivers/macintosh/Kconfig	2006-10-06 13:48:04.000000000 +1000
+++ linux-work/drivers/macintosh/Kconfig	2006-11-01 15:09:23.000000000 +1100
@@ -228,4 +228,11 @@ config ANSLCD
 	tristate "Support for ANS LCD display"
 	depends on ADB_CUDA && PPC_PMAC
 
+config PMAC_RACKMETER
+	tristate "Support for Apple XServe front panel LEDs"
+	depends on PPC_PMAC
+	help
+	  This driver procides some support to control the front panel
+          blue LEDs "vu-meter" of the XServer macs.
+
 endmenu
Index: linux-work/drivers/macintosh/Makefile
===================================================================
--- linux-work.orig/drivers/macintosh/Makefile	2006-10-06 13:48:04.000000000 +1000
+++ linux-work/drivers/macintosh/Makefile	2006-11-01 15:09:23.000000000 +1100
@@ -42,3 +42,4 @@ obj-$(CONFIG_WINDFARM_PM112)	+= windfarm
 				   windfarm_smu_sensors.o \
 				   windfarm_max6690_sensor.o \
 				   windfarm_lm75_sensor.o windfarm_pid.o
+obj-$(CONFIG_PMAC_RACKMETER)	+= rack-meter.o
Index: linux-work/include/asm-powerpc/dbdma.h
===================================================================
--- linux-work.orig/include/asm-powerpc/dbdma.h	2006-01-14 14:43:33.000000000 +1100
+++ linux-work/include/asm-powerpc/dbdma.h	2006-11-01 15:09:23.000000000 +1100
@@ -95,7 +95,13 @@ struct dbdma_cmd {
 #define DBDMA_DO_STOP(regs) do {				\
 	out_le32(&((regs)->control), (RUN|FLUSH)<<16);		\
 	while(in_le32(&((regs)->status)) & (ACTIVE|FLUSH))	\
-		;						\
+		; \
+} while(0)
+
+#define DBDMA_DO_RESET(regs) do {				\
+	out_le32(&((regs)->control), (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);\
+	while(in_le32(&((regs)->status)) & (RUN)) \
+		; \
 } while(0)
 
 #endif /* _ASM_DBDMA_H_ */

^ permalink raw reply

* [PATCH] powerpc: windfarm requests missing modules
From: Benjamin Herrenschmidt @ 2006-11-01  4:55 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list

The windfarm code, in it's current incarnation, uses request_module() to
load the various submodules it needs for a given platform so that only
the main platform control module needs to be modprobed. However, it was
missing various bits. This fixes it. In the future, we'll use some
hotplug mecanisms to try to get all of this auto-loaded on the platforms
where it matters but that isn't ready yet.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

I consider this a bug fix, could go in 2.6.19

Index: linux-work/drivers/macintosh/windfarm_pm112.c
===================================================================
--- linux-work.orig/drivers/macintosh/windfarm_pm112.c	2006-10-13 17:23:48.000000000 +1000
+++ linux-work/drivers/macintosh/windfarm_pm112.c	2006-11-01 13:52:27.000000000 +1100
@@ -685,6 +685,17 @@ static int __init wf_pm112_init(void)
 		++nr_cores;
 
 	printk(KERN_INFO "windfarm: initializing for dual-core desktop G5\n");
+
+#ifdef MODULE
+	request_module("windfarm_smu_controls");
+	request_module("windfarm_smu_sensors");
+	request_module("windfarm_smu_sat");
+	request_module("windfarm_lm75_sensor");
+	request_module("windfarm_max6690_sensor");
+	request_module("windfarm_cpufreq_clamp");
+
+#endif /* MODULE */
+
 	platform_driver_register(&wf_pm112_driver);
 	return 0;
 }
Index: linux-work/drivers/macintosh/windfarm_pm81.c
===================================================================
--- linux-work.orig/drivers/macintosh/windfarm_pm81.c	2006-11-01 13:48:52.000000000 +1100
+++ linux-work/drivers/macintosh/windfarm_pm81.c	2006-11-01 13:49:24.000000000 +1100
@@ -788,6 +788,7 @@ static int __init wf_smu_init(void)
 		request_module("windfarm_smu_controls");
 		request_module("windfarm_smu_sensors");
 		request_module("windfarm_lm75_sensor");
+		request_module("windfarm_cpufreq_clamp");
 
 #endif /* MODULE */
 		platform_driver_register(&wf_smu_driver);
Index: linux-work/drivers/macintosh/windfarm_pm91.c
===================================================================
--- linux-work.orig/drivers/macintosh/windfarm_pm91.c	2006-10-13 17:23:48.000000000 +1000
+++ linux-work/drivers/macintosh/windfarm_pm91.c	2006-11-01 13:50:03.000000000 +1100
@@ -719,6 +719,7 @@ static int __init wf_smu_init(void)
 		request_module("windfarm_smu_controls");
 		request_module("windfarm_smu_sensors");
 		request_module("windfarm_lm75_sensor");
+		request_module("windfarm_cpufreq_clamp");
 
 #endif /* MODULE */
 		platform_driver_register(&wf_smu_driver);

^ permalink raw reply

* [PATCH] powerpc: pmac_feature_call checks platform
From: Benjamin Herrenschmidt @ 2006-11-01  4:53 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list

This patch makes sure that a caller of pmac_call_feature() won't try to call
into ppc_md.feature_call of another platform which might happen if some
powermac drivers are loaded on powermac machines.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

Index: linux-work/include/asm-powerpc/pmac_feature.h
===================================================================
--- linux-work.orig/include/asm-powerpc/pmac_feature.h	2006-09-08 17:17:52.000000000 +1000
+++ linux-work/include/asm-powerpc/pmac_feature.h	2006-11-01 14:34:13.000000000 +1100
@@ -146,7 +146,7 @@ struct device_node;
 static inline long pmac_call_feature(int selector, struct device_node* node,
 					long param, long value)
 {
-	if (!ppc_md.feature_call)
+	if (!ppc_md.feature_call || !machine_is(powermac))
 		return -ENODEV;
 	return ppc_md.feature_call(selector, node, param, value);
 }

^ permalink raw reply

* [PATCH] powerpc: Make alignment exception always check exception table (#3)
From: Benjamin Herrenschmidt @ 2006-11-01  4:11 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Greg KH
In-Reply-To: <1162350571.25682.389.camel@localhost.localdomain>

The alignment exception used to only check the exception table for
-EFAULT, not for other errors. That opens an oops window if we can
coerce the kernel into getting an alignment exception for other reasons
in what would normally be a user-protected accessor, which can be done
via some of the futex ops. This fixes it by always checking the
exception tables.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

Paul: this version sets the correct si_code

This is 2.6.19 material and should probably go into stable as well.
(Greg: take it if paulus acks it and it applies :)

Index: linux-work/arch/powerpc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/traps.c	2006-11-01 14:59:07.000000000 +1100
+++ linux-work/arch/powerpc/kernel/traps.c	2006-11-01 15:01:06.000000000 +1100
@@ -843,7 +843,7 @@ void __kprobes program_check_exception(s
 
 void alignment_exception(struct pt_regs *regs)
 {
-	int fixed = 0;
+	int sig, code, fixed = 0;
 
 	/* we don't implement logging of alignment exceptions */
 	if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
@@ -857,14 +857,16 @@ void alignment_exception(struct pt_regs 
 
 	/* Operand address was bad */
 	if (fixed == -EFAULT) {
-		if (user_mode(regs))
-			_exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
-		else
-			/* Search exception table */
-			bad_page_fault(regs, regs->dar, SIGSEGV);
-		return;
+		sig = SIGSEGV;
+		code = SEGV_ACCERR;
+	} else {
+		sig = SIGBUS;
+		code = BUS_ADRALN;
 	}
-	_exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
+	if (user_mode(regs))
+		_exception(sig, regs, code, regs->dar);
+	else
+		bad_page_fault(regs, regs->dar, sig);
 }
 
 void StackOverflow(struct pt_regs *regs)
Index: linux-work/arch/ppc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/ppc/kernel/traps.c	2006-11-01 14:59:07.000000000 +1100
+++ linux-work/arch/ppc/kernel/traps.c	2006-11-01 15:01:32.000000000 +1100
@@ -708,7 +708,7 @@ void single_step_exception(struct pt_reg
 
 void alignment_exception(struct pt_regs *regs)
 {
-	int fixed;
+	int sig, code, fixed = 0;
 
 	fixed = fix_alignment(regs);
 	if (fixed == 1) {
@@ -717,14 +717,16 @@ void alignment_exception(struct pt_regs 
 		return;
 	}
 	if (fixed == -EFAULT) {
-		/* fixed == -EFAULT means the operand address was bad */
-		if (user_mode(regs))
-			_exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
-		else
-			bad_page_fault(regs, regs->dar, SIGSEGV);
-		return;
+		sig = SIGSEGV;
+		code = SEGV_ACCERR;
+	} else {
+		sig = SIGBUS;
+		code = BUS_ADRALN;
 	}
-	_exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
+	if (user_mode(regs))
+		_exception(sig, regs, code, regs->dar);
+	else
+		bad_page_fault(regs, regs->dar, sig);
 }
 
 void StackOverflow(struct pt_regs *regs)

^ permalink raw reply

* [PATCH] powerpc: Make alignment exception always check exception table (#2)
From: Benjamin Herrenschmidt @ 2006-11-01  3:42 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Greg KH
In-Reply-To: <1162350571.25682.389.camel@localhost.localdomain>

The alignment exception used to only check the exception table for
-EFAULT, not for other errors. That opens an oops window if we can
coerce the kernel into getting an alignment exception for other reasons
in what would normally be a user-protected accessor, which can be done
via some of the futex ops. This fixes it by always checking the
exception tables.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

Paul: this version also fixes arch/ppc

This is 2.6.19 material and should probably go into stable as well.
(Greg: take it if paulus acks it and it applies :)

Index: linux-work/arch/powerpc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/traps.c	2006-10-23 14:41:37.000000000 +1000
+++ linux-work/arch/powerpc/kernel/traps.c	2006-10-30 13:59:41.000000000 +1100
@@ -843,7 +843,7 @@ void __kprobes program_check_exception(s
 
 void alignment_exception(struct pt_regs *regs)
 {
-	int fixed = 0;
+	int sig, fixed = 0;
 
 	/* we don't implement logging of alignment exceptions */
 	if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
@@ -856,15 +856,11 @@ void alignment_exception(struct pt_regs 
 	}
 
 	/* Operand address was bad */
-	if (fixed == -EFAULT) {
-		if (user_mode(regs))
-			_exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
-		else
-			/* Search exception table */
-			bad_page_fault(regs, regs->dar, SIGSEGV);
-		return;
-	}
-	_exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
+	sig = fixed == -EFAULT ? SIGSEGV : SIGBUS;
+	if (user_mode(regs))
+		_exception(sig, regs, SEGV_ACCERR, regs->dar);
+	else
+		bad_page_fault(regs, regs->dar, sig);
 }
 
 void StackOverflow(struct pt_regs *regs)
Index: linux-work/arch/ppc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/ppc/kernel/traps.c	2006-10-06 13:47:55.000000000 +1000
+++ linux-work/arch/ppc/kernel/traps.c	2006-11-01 14:39:44.000000000 +1100
@@ -708,7 +708,7 @@ void single_step_exception(struct pt_reg
 
 void alignment_exception(struct pt_regs *regs)
 {
-	int fixed;
+	int sig, fixed = 0;
 
 	fixed = fix_alignment(regs);
 	if (fixed == 1) {
@@ -716,15 +716,11 @@ void alignment_exception(struct pt_regs 
 		emulate_single_step(regs);
 		return;
 	}
-	if (fixed == -EFAULT) {
-		/* fixed == -EFAULT means the operand address was bad */
-		if (user_mode(regs))
-			_exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
-		else
-			bad_page_fault(regs, regs->dar, SIGSEGV);
-		return;
-	}
-	_exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
+	sig = fixed == -EFAULT ? SIGSEGV : SIGBUS;
+	if (user_mode(regs))
+		_exception(sig, regs, SEGV_ACCERR, regs->dar);
+	else
+		bad_page_fault(regs, regs->dar, sig);
 }
 
 void StackOverflow(struct pt_regs *regs)

^ permalink raw reply

* Re: [PATCH 2/5] ppc64: make high hugepage areas preempt safe
From: David Gibson @ 2006-11-01  3:42 UTC (permalink / raw)
  To: Hugh Dickins; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <Pine.LNX.4.64.0610311839480.26470@blonde.wat.veritas.com>

On Tue, Oct 31, 2006 at 06:40:39PM +0000, Hugh Dickins wrote:
> Checking source for other get_paca()->field preemption dangers found that
> open_high_hpage_areas does a structure copy into its paca while preemption
> is enabled: unsafe however gcc accomplishes it.  Just remove that copy:
> it's done safely afterwards by on_each_cpu, as in open_low_hpage_areas.

Oops, when I fixed the other problems with the PACA loading here, I
guess I missed this redundant assignment.

> Signed-off-by: Hugh Dickins <hugh@veritas.com>
Acked-by: David Gibson <dwg@au1.ibm.com>

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH] CPM_UART: Fix non-console transmit
From: Paul Mackerras @ 2006-11-01  3:35 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: Laurent, linuxppc-embedded
In-Reply-To: <20061031180816.3d32c285@vitb.ru.mvista.com>

Vitaly Bordug writes:

> Paul: please apply. 
> 
> I am recalling addressing something like the upper, but dunno why it haven't pushed 
> upstream. Something around re-use scc/smc did not feel good with this approach, but it is 
> much less important than the odd behavior expressed.

I don't have this patch, could someone send it to me please (and if
you want it in 2.6.19, make sure the commentary explains what bug it
is fixing).

Paul.

^ permalink raw reply

* [PATCH] powerpc: Make alignment exception always check exception table
From: Benjamin Herrenschmidt @ 2006-11-01  3:09 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, Greg KH

The alignment exception used to only check the exception table for
-EFAULT, not for other errors. That opens an oops window if we can
coerce the kernel into getting an alignment exception for other reasons
in what would normally be a user-protected accessor, which can be done
via some of the futex ops. This fixes it by always checking the
exception tables.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

This is 2.6.19 material and should probably go into stable as well.
(Greg: take it if paulus acks it and it applies :)

Index: linux-work/arch/powerpc/kernel/traps.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/traps.c	2006-10-23 14:41:37.000000000 +1000
+++ linux-work/arch/powerpc/kernel/traps.c	2006-10-30 13:59:41.000000000 +1100
@@ -843,7 +843,7 @@ void __kprobes program_check_exception(s
 
 void alignment_exception(struct pt_regs *regs)
 {
-	int fixed = 0;
+	int sig, fixed = 0;
 
 	/* we don't implement logging of alignment exceptions */
 	if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS))
@@ -856,15 +856,11 @@ void alignment_exception(struct pt_regs 
 	}
 
 	/* Operand address was bad */
-	if (fixed == -EFAULT) {
-		if (user_mode(regs))
-			_exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar);
-		else
-			/* Search exception table */
-			bad_page_fault(regs, regs->dar, SIGSEGV);
-		return;
-	}
-	_exception(SIGBUS, regs, BUS_ADRALN, regs->dar);
+	sig = fixed == -EFAULT ? SIGSEGV : SIGBUS;
+	if (user_mode(regs))
+		_exception(sig, regs, SEGV_ACCERR, regs->dar);
+	else
+		bad_page_fault(regs, regs->dar, sig);
 }
 
 void StackOverflow(struct pt_regs *regs)

^ permalink raw reply

* [PATCH][kprobe] disallow kprobes on emulate_step and branch_taken
From: Gui,Jian @ 2006-11-01  2:50 UTC (permalink / raw)
  To: linuxppc-dev

Probing on emulate_step function will crash 2.6.18.1 when it is
triggered. This problem is powerpc dependent.

When kprobe is triggered, emulate_step() is on its kernel path and
will cause recursive kprobe fault. And branch_taken() is called
in emulate_step(). This patch can disallow kprobes on both of them.



diff -Nur orig/arch/powerpc/lib/sstep.c linux-2.6.18.1/arch/powerpc/lib/sstep.c
--- orig/arch/powerpc/lib/sstep.c       2006-11-01 08:45:06.000000000 -0500
+++ linux-2.6.18.1/arch/powerpc/lib/sstep.c     2006-11-01 08:50:19.000000000 -0500
@@ -9,6 +9,7 @@
   * 2 of the License, or (at your option) any later version.
   */
  #include <linux/kernel.h>
+#include <linux/kprobes.h>
  #include <linux/ptrace.h>
  #include <asm/sstep.h>
  #include <asm/processor.h>
@@ -25,7 +26,7 @@
  /*
   * Determine whether a conditional branch instruction would branch.
   */
-static int branch_taken(unsigned int instr, struct pt_regs *regs)
+static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs)
  {
         unsigned int bo = (instr >> 21) & 0x1f;
         unsigned int bi;
@@ -51,7 +52,7 @@
   * or -1 if the instruction is one that should not be stepped,
   * such as an rfid, or a mtmsrd that would clear MSR_RI.
   */
-int emulate_step(struct pt_regs *regs, unsigned int instr)
+int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
  {
         unsigned int opcode, rd;
         unsigned long int imm;

^ permalink raw reply

* Re: [PATCH 2.6.19-rc3 1/2] ehea: kzalloc GFP_ATOMIC fix
From: Jeff Garzik @ 2006-11-01  1:20 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, Jan-Bernd Themann, netdev, linux-kernel, linux-ppc,
	Christoph Raisch, Marcus Eder
In-Reply-To: <200610251311.43009.ossthema@de.ibm.com>

Jan-Bernd Themann wrote:
> This patch fixes kzalloc parameters (GFP_ATOMIC instead of GFP_KERNEL)
> 
> Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com>

applied to #upstream-fixes

In the future, please include a description of -why- patches like this 
are needed (I got the info from your replies in this case)

^ permalink raw reply

* Re: [PATCH 1/2] Add MPC52xx Interrupt controller support for ARCH=powerpc
From: Benjamin Herrenschmidt @ 2006-11-01  1:06 UTC (permalink / raw)
  To: Grant Likely; +Cc: Rigby John-R61273, sl, linuxppc-dev, linuxppc-embedded, sha
In-Reply-To: <528646bc0610311508v6d65d4b3t46135123c8e8a1bf@mail.gmail.com>

On Tue, 2006-10-31 at 16:08 -0700, Grant Likely wrote:
> On 10/31/06, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> >
> > > This definitely needs to be removed.  It's used to figure out which
> > > driver should drive a PSC (based on function).  We've got a device
> > > tree to provide this information now.
> >
> > Which means we should define how that is presented in the devie-tree and
> > Nicolas should then update his tree accordingly...
> 
> How about this:
> 
> <function> := one of [serial, spi, i2s, ac97]
> 
> <function>@<psc_offset> {
>         port-number = <logical port number>;   // so /dev/ttyPSC#
> connects to something sane
>         compatible = "mpc5200b-psb\0mpc52xx-psc";
>         ... other stuff ...
> };
> 
> Function is encoded in the node name, and the compatible property
> tells linux that it is an mpc52xx-psc in <function> mode.

Looks good to me.

Ben.

^ permalink raw reply

* [PATCH] powerpc: Eliminate "exceeds stub group size" linker warning
From: Paul Mackerras @ 2006-11-01  1:01 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: akpm, linuxppc-dev, linux-kernel

It turns out that the linker warnings on 64-bit powerpc about "section
blah exceeds stub group size" were being triggered by conditional
branches in head_64.S branching to global symbols, whether in
head_64.S or in other files.  This eliminates the warnings by making
some global symbols in head_64.S no longer global, and by rearranging
some branches.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
Linus,

If you think this is 2.6.19 material, feel free to put it in your
tree.  Otherwise I'll put it in the powerpc.git tree to go in for
2.6.20.

Paul.

diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 47fcff1..c005f15 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -505,7 +505,7 @@ BEGIN_FTR_SECTION
 	rlwimi	r13,r12,16,0x20
 	mfcr	r12
 	cmpwi	r13,0x2c
-	beq	.do_stab_bolted_pSeries
+	beq	do_stab_bolted_pSeries
 	mtcrf	0x80,r12
 	mfspr	r12,SPRN_SPRG2
 END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
@@ -635,7 +635,7 @@ masked_interrupt:
 	b	.
 
 	.align	7
-_GLOBAL(do_stab_bolted_pSeries)
+do_stab_bolted_pSeries:
 	mtcrf	0x80,r12
 	mfspr	r12,SPRN_SPRG2
 	EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
@@ -1090,7 +1090,7 @@ slb_miss_fault:
 	li	r5,0
 	std	r4,_DAR(r1)
 	std	r5,_DSISR(r1)
-	b	.handle_page_fault
+	b	handle_page_fault
 
 unrecov_user_slb:
 	EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN)
@@ -1218,12 +1218,13 @@ program_check_common:
 	.globl fp_unavailable_common
 fp_unavailable_common:
 	EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN)
-	bne	.load_up_fpu		/* if from user, just load it up */
+	bne	1f			/* if from user, just load it up */
 	bl	.save_nvgprs
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	ENABLE_INTS
 	bl	.kernel_fp_unavailable_exception
 	BUG_OPCODE
+1:	b	.load_up_fpu
 
 	.align	7
 	.globl altivec_unavailable_common
@@ -1323,10 +1324,10 @@ _GLOBAL(do_hash_page)
 	std	r4,_DSISR(r1)
 
 	andis.	r0,r4,0xa450		/* weird error? */
-	bne-	.handle_page_fault	/* if not, try to insert a HPTE */
+	bne-	handle_page_fault	/* if not, try to insert a HPTE */
 BEGIN_FTR_SECTION
 	andis.	r0,r4,0x0020		/* Is it a segment table fault? */
-	bne-	.do_ste_alloc		/* If so handle it */
+	bne-	do_ste_alloc		/* If so handle it */
 END_FTR_SECTION_IFCLR(CPU_FTR_SLB)
 
 	/*
@@ -1368,7 +1369,7 @@ BEGIN_FW_FTR_SECTION
 	 * because ret_from_except_lite will check for and handle pending
 	 * interrupts if necessary.
 	 */
-	beq	.ret_from_except_lite
+	beq	14f
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif
 BEGIN_FW_FTR_SECTION
@@ -1390,16 +1391,17 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISER
 	ld	r3,SOFTE(r1)
 	bl	.local_irq_restore
 	b	11f
+14:	b	.ret_from_except_lite
 
 /* Here we have a page fault that hash_page can't handle. */
-_GLOBAL(handle_page_fault)
+handle_page_fault:
 	ENABLE_INTS
 11:	ld	r4,_DAR(r1)
 	ld	r5,_DSISR(r1)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	bl	.do_page_fault
 	cmpdi	r3,0
-	beq+	.ret_from_except_lite
+	beq+	14b
 	bl	.save_nvgprs
 	mr	r5,r3
 	addi	r3,r1,STACK_FRAME_OVERHEAD
@@ -1417,11 +1419,11 @@ _GLOBAL(handle_page_fault)
 	b	.ret_from_except
 
 	/* here we have a segment miss */
-_GLOBAL(do_ste_alloc)
+do_ste_alloc:
 	bl	.ste_allocate		/* try to insert stab entry */
 	cmpdi	r3,0
-	beq+	fast_exception_return
-	b	.handle_page_fault
+	bne-	handle_page_fault
+	b	fast_exception_return
 
 /*
  * r13 points to the PACA, r9 contains the saved CR,

^ permalink raw reply related

* Re: How do you debug the kernel on an ML403?
From: Michael Galassi @ 2006-10-31 23:59 UTC (permalink / raw)
  To: Frank D Lombardo; +Cc: linuxppc-embedded
In-Reply-To: <4547DE29.6090708@mdivac.com>

Set a breakpoint at the end of the decompression stage of what you call
the uncompressed portion of the zImage.elf file, then single step your
way past the transition to virtual mappings, reload your symbols from
the vmlinux file and you're set to go.  Tedious but that forces you to
think about each step much harder rather than to indulge in trial and
error.

-michael

>I am using a Xilinx ML403 board with the Parallel IV JTAG cable.  I have 
>been able to use XMD and the Insight front end for GDB to debug both 
>U-Boot and the uncompressed portion of the zImage.elf file.  However, I 
>cannot set breakpoints in kernel code.  Can XMD  and the Parallel IV 
>JTAG cable be used to debug kernel code?  How do you do that?
>
>Thanks,
>Frank
>_______________________________________________
>Linuxppc-embedded mailing list
>Linuxppc-embedded@ozlabs.org
>https://ozlabs.org/mailman/listinfo/linuxppc-embedded

^ permalink raw reply

* How do you debug the kernel on an ML403?
From: Frank D Lombardo @ 2006-10-31 23:37 UTC (permalink / raw)
  To: linuxppc-embedded

I am using a Xilinx ML403 board with the Parallel IV JTAG cable.  I have 
been able to use XMD and the Insight front end for GDB to debug both 
U-Boot and the uncompressed portion of the zImage.elf file.  However, I 
cannot set breakpoints in kernel code.  Can XMD  and the Parallel IV 
JTAG cable be used to debug kernel code?  How do you do that?

Thanks,
Frank

^ permalink raw reply

* Re: [PATCH 1/2] Add MPC52xx Interrupt controller support for ARCH=powerpc
From: Grant Likely @ 2006-10-31 23:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Rigby John-R61273, sl, linuxppc-dev, linuxppc-embedded, sha
In-Reply-To: <1162332664.25682.362.camel@localhost.localdomain>

On 10/31/06, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
>
> > This definitely needs to be removed.  It's used to figure out which
> > driver should drive a PSC (based on function).  We've got a device
> > tree to provide this information now.
>
> Which means we should define how that is presented in the devie-tree and
> Nicolas should then update his tree accordingly...

How about this:

<function> := one of [serial, spi, i2s, ac97]

<function>@<psc_offset> {
        port-number = <logical port number>;   // so /dev/ttyPSC#
connects to something sane
        compatible = "mpc5200b-psb\0mpc52xx-psc";
        ... other stuff ...
};

Function is encoded in the node name, and the compatible property
tells linux that it is an mpc52xx-psc in <function> mode.

g.

-- 
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [RFC] bootwrapper: prevent fdt from being overwritten by kernel
From: Mark A. Greer @ 2006-10-31 23:02 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <17733.31929.136137.129244@cargo.ozlabs.ibm.com>

On Mon, Oct 30, 2006 at 03:16:57PM +1100, Paul Mackerras wrote:
> Mark A. Greer writes:
> > In addition, I moved the vmlinux elf header decompress code from
> > prep_kernel() to its own routine and called it before platform_init.
> > I then pass the elf header ptr into platform_init.  That way,
> > platform_init can figure out where the end of the kernel will
> > be and put the dtb beyond it.  The OF code can now change
> > claim_base in platform_init instead of needing the platform_ops.image_hdr
> > hook.
> 
> Hmmm.  What if platform_init needs to e.g. turn on caches or do other
> things that need to be done before decompressing?  I think it's
> important to provide some way for the platform code to do things
> really early on.

Good point.  I'll make a separate hook so it'll be platform_init, then
get_elfheader, then call new hook, then open console & do the rest.

Mark

^ permalink raw reply

* Re: [PATCH 1/2] Add MPC52xx Interrupt controller support for ARCH=powerpc
From: Benjamin Herrenschmidt @ 2006-10-31 22:11 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev, linuxppc-embedded, sl, sha
In-Reply-To: <528646bc0610311408i3a7a9a7ep11ad54c1779aa4bc@mail.gmail.com>


> This definitely needs to be removed.  It's used to figure out which
> driver should drive a PSC (based on function).  We've got a device
> tree to provide this information now.

Which means we should define how that is presented in the devie-tree and
Nicolas should then update his tree accordingly...

Ben.

^ permalink raw reply

* Re: [PATCH 1/2] Add MPC52xx Interrupt controller support for ARCH=powerpc
From: Grant Likely @ 2006-10-31 22:08 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linuxppc-embedded, sl, sha
In-Reply-To: <1162331943.25682.358.camel@localhost.localdomain>

On 10/31/06, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> On Tue, 2006-10-31 at 21:04 +0100, Nicolas DET wrote:
> > +     /* Matching of PSC function */
> > +struct mpc52xx_psc_func {
> > +     int id;
> > +     char *func;
> > +};
> >
> > +extern int mpc52xx_match_psc_function(int psc_idx, const char *func);
> > +extern struct mpc52xx_psc_func mpc52xx_psc_functions[];
> > +     /* This array is to be defined in platform file */
>
> The above doesn't look like it should migrate to arch/powerpc... what is
> it supposed to be ?

This definitely needs to be removed.  It's used to figure out which
driver should drive a PSC (based on function).  We've got a device
tree to provide this information now.

g.

-- 
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [PATCH 1/2] Add MPC52xx Interrupt controller support for ARCH=powerpc
From: Benjamin Herrenschmidt @ 2006-10-31 21:59 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, sl, sha, linuxppc-embedded
In-Reply-To: <4547AC30.3090208@bplan-gmbh.de>

On Tue, 2006-10-31 at 21:04 +0100, Nicolas DET wrote:

> Here is is ;-).
> As my mailer can insert a file, I copy paste. I hope it's still ok...

No, your patch got wrapped. Its damaged. I see you used Thunderbird. I
have no experience with sending patches with it, so I don't know what
the trick is to have them undamaged. With evolution, the trick is to use
the pre-defined style "preformat".

Also, next, send it with proper form, that is just the commit message,
signed-off line, and patch. If you want to add personal comments on the
mail, add --- after the signed off and insert them between that and the
patch.

Anyway, minor comments, we're getting there...

> +void rtas_indicator_progress(char *, unsigned short);

That should be in a header.

> +extern unsigned long loops_per_jiffy;

That too. In fact, the default value for that which is all you need is
set in common code. Just drop that.

> +static void efika_show_cpuinfo(struct seq_file *m)
> +{
> +	struct device_node *root;
> +	const char *revision = NULL;
> +	const char *codegendescription = NULL;
> +	const char *codegenvendor = NULL;
> +
> +	root = find_path_device("/");

Use of_find_device_by_path() and of_node_put() when done (see comments
in prom.h about old form of these being deprecated).

> +	if (root) {
> +		revision = get_property(root, "revision", NULL);
> +		codegendescription =
> +		    get_property(root, "CODEGEN,description", NULL);
> +		codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
> +	}
> +
> +	if (codegendescription)
> +		seq_printf(m, "machine\t\t: %s\n", codegendescription);
> +	else
> +		seq_printf(m, "machine\t\t: Efika\n");
> +
> +	if (revision)
> +		seq_printf(m, "revision\t: %s\n", revision);
> +
> +	if (codegenvendor)
> +		seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
> +}
> +
> +static void __init efika_setup_arch(void)
> +{
> +	/* init to some ~sane value until calibrate_delay() runs */
> +	loops_per_jiffy = 50000000 / HZ;

Above is already done in setup_32.c, just drop it.

> +	rtas_initialize();
> +
> +#ifdef CONFIG_BLK_DEV_INITRD
> +	initrd_below_start_ok = 1;
> +
> +	if (initrd_start)
> +		ROOT_DEV = Root_RAM0;
> +	else
> +#endif
> +		ROOT_DEV = Root_SDA2;	/* sda2 (sda1 is for the kernel) */
> +
> +	pci_create_OF_bus_map();

I think the OF_bus_map() thing can safely be depracated. Don't bother
with it, you won't need it anyway.

> +	efika_pcisetup();
> +
> +	if (ppc_md.progress)
> +		ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
> +}
> +
> +static void __init efika_init_IRQ(void)
> +{
> +	of_irq_map_init(0);

The above is only useful if you have special flags to pass. You don't so
just skip it.

> +	mpc52xx_init_irq();
> +}
> +
> +static void __init efika_init(void)
> +{
> +	if (ppc_md.progress)
> +		ppc_md.progress("  Have fun with your Efika!    ", 0x7777);
> +}
> +
> +static int __init efika_probe(void)
> +{
> +	char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
> +					  "model", NULL);
> +
> +	if (model == NULL)
> +		return 0;
> +	if (strcmp(model, "EFIKA5K2"))
> +		return 0;
> +
> +	ISA_DMA_THRESHOLD = ~0L;
> +	DMA_MODE_READ = 0x44;
> +	DMA_MODE_WRITE = 0x48;
> +
> +	/*
> +	 * Others values (isa_mem_base, pci_dram_base) are 0
> +	 * in CHRP for us. Only isa_io_base is changed.
> +	*/
> +	isa_io_base = CHRP_ISA_IO_BASE;

Leave it to zero for now. pci_process_bridge_OF_ranges() will set it for
you to the right address. Pre-initializing is only useful if you have
very early IO ports access -and- have an early mapping on that range.
You have neither so don't bother.

> +	return 1;
> +}
> +
> +define_machine(efika)
> +{
> +	.name = EFIKA_PLATFORM_NAME,
> +	.probe = efika_probe,
> +	.setup_arch = efika_setup_arch,
> +	.init = efika_init,
> +	.show_cpuinfo = efika_show_cpuinfo,
> +	.init_IRQ = efika_init_IRQ,
> +	.get_irq = mpc52xx_get_irq,
> +	.restart = rtas_restart,
> +	.power_off = rtas_power_off,
> +	.halt = rtas_halt,
> +	.set_rtc_time = rtas_set_rtc_time,
> +	.get_rtc_time = rtas_get_rtc_time,
> +	.progress = rtas_progress,
> +	.get_boot_time = rtas_get_boot_time,
> +	.calibrate_decr = generic_calibrate_decr,
> +	.phys_mem_access_prot = pci_phys_mem_access_prot,
> +	.pcibios_fixup = efika_pciirq_map,
> +};

The later can go away if you apply the patch I posted last week 
[PATCH] Powerpc:  Make pci_read_irq_line the default: on mpc7448hpc2
board. First.

> --- a/arch/powerpc/platforms/efika/pci.c	1970-01-01 01:00:00.000000000 +0100
> +++ b/arch/powerpc/platforms/efika/pci.c	2006-10-31 12:31:55.000000000 +0100
> @@ -0,0 +1,150 @@
> +
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/delay.h>
> +#include <linux/string.h>
> +#include <linux/init.h>
> +#include <linux/ide.h>
> +
> +#include <asm/io.h>
> +#include <asm/pgtable.h>
> +#include <asm/irq.h>
> +#include <asm/hydra.h>
> +#include <asm/prom.h>
> +#include <asm/gg2.h>
> +#include <asm/machdep.h>
> +#include <asm/sections.h>
> +#include <asm/pci-bridge.h>
> +#include <asm/grackle.h>
> +#include <asm/rtas.h>

You can trim a lot of the above #includes :)

> +#include "efika.h"
> +
> +static struct device_node *efika_pcictrl;

Not needed (the above).

> +/*
> + * Access functions for PCI config space using RTAS calls.
> + */
> +static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, 
> int offset,
> +			    int len, u32 * val)
> +{
> +	struct pci_controller *hose = bus->sysdata;
> +	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
> +	    | (((bus->number - hose->first_busno) & 0xff) << 16)
> +	    | (hose->index << 24);
> +	int ret = -1;
> +	int rval;
> +
> +	rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
> +	*val = ret;
> +	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
> +			     int offset, int len, u32 val)
> +{
> +	struct pci_controller *hose = bus->sysdata;
> +	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
> +	    | (((bus->number - hose->first_busno) & 0xff) << 16)
> +	    | (hose->index << 24);
> +	int rval;
> +
> +	rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
> +			 addr, len, val);
> +	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
> +}
> +
> +static struct pci_ops rtas_pci_ops = {
> +	rtas_read_config,
> +	rtas_write_config
> +};
> +
> +void __init efika_pcisetup(void)
> +{
> +	const int *bus_range;
> +	int len;
> +	struct pci_controller *hose;
> +	struct device_node *root;
> +	struct device_node *pcictrl;
> +
> +	root = of_find_node_by_path("/");
> +	if (root == NULL) {
> +		printk(KERN_WARNING EFIKA_PLATFORM_NAME
> +		       ": Unable to find the root node\n");
> +		return;
> +	}
> +
> +	for (pcictrl = NULL;;) {
> +		pcictrl = of_get_next_child(root, pcictrl);
> +		if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0))
> +			break;
> +	}
> +
> +	if (pcictrl == NULL) {
> +		printk(KERN_WARNING EFIKA_PLATFORM_NAME
> +		       ": Unable to find the PCI bridge node\n");
> +		return;
> +	}

of_node_put() when you are done with the result of
of_find_node_by_path() and of_get_next_child(). Note that the later does
it implicitely on its arguyment so you only need to do it if you exit
the loop early

> +	efika_pcictrl = pcictrl;

Remove that.

> +	bus_range = get_property(pcictrl, "bus-range", &len);
> +	if (bus_range == NULL || len < 2 * sizeof(int)) {
> +		printk(KERN_WARNING EFIKA_PLATFORM_NAME
> +		       ": Can't get bus-range for %s\n", pcictrl->full_name);
> +		return;
> +	}
> +	if (bus_range[1] == bus_range[0])
> +		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
> +		       bus_range[0]);
> +	else
> +		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
> +		       bus_range[0], bus_range[1]);
> +	printk(" controlled by %s", pcictrl->full_name);
> +	printk("\n");
> +
> +	hose = pcibios_alloc_controller();
> +	if (!hose) {
> +		printk(KERN_WARNING EFIKA_PLATFORM_NAME
> +		       ": Can't allocate PCI controller structure for %s\n",
> +		       pcictrl->full_name);
> +		return;
> +	}
> +
> +	hose->arch_data = pcictrl;
> +	hose->first_busno = bus_range[0];
> +	hose->last_busno = bus_range[1];
> +	hose->ops = &rtas_pci_ops;
> +
> +	pci_process_bridge_OF_ranges(hose, pcictrl, 0);
> +}
> +
> +void __init efika_pciirq_map(void)
> +{
> +	struct device_node *pcictrl = efika_pcictrl;
> +	struct pci_dev *pdev = NULL;
> +	struct device_node *ofwdev;
> +
> +	if (pcictrl == NULL)
> +		return;
> +
> +	/*
> +	 * We need to find PCI irq, create a virtual mapping, and set
> +	 * the irq number into the PCI structure (software/Linux side)
> +	 * I could to this by walking into the /pci node, do
> +	 * of_irq_map_pci(), irq_create_of_mapping(), then find
> +	 * the good 'struct pci_dev *' and update pci_dev->irq.
> +	 * However, pci_read_irq_line() should do everything correctly!
> +	*/
> +
> +	for_each_pci_dev(pdev)
> +	{
> +		if (pci_read_irq_line(pdev) < 0)
> +			continue;
> +
> +		ofwdev = pci_device_to_OF_node(pdev);
> +		if (ofwdev)
> +			printk(KERN_INFO EFIKA_PLATFORM_NAME ": got IRQ 0x%x for '%s'\n", 
> pdev->irq, ofwdev->full_name);
> +	}
> +
> +}

The whole function is not needed. Just apply my other patch first.

> --- a/arch/powerpc/platforms/efika/efika.h	1970-01-01 01:00:00.000000000 
> +0100
> +++ b/arch/powerpc/platforms/efika/efika.h	2006-10-31 12:31:55.000000000 
> +0100
> @@ -0,0 +1,20 @@
> +/*
> + * Efika 5K2 platform setup - Header file
> + *
> + * Copyright (C) 2006 bplan GmbH
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + *
> + */
> +
> +#ifndef __ARCH_POWERPC_EFIKA__
> +#define __ARCH_POWERPC_EFIKA__
> +
> +#define EFIKA_PLATFORM_NAME "Efika"
> +
> +void __init efika_pcisetup(void);
> +void __init efika_pciirq_map(void);

Use "extern" for prototypes in a .h

> +#endif
> --- a/arch/powerpc/platforms/efika/Makefile	1970-01-01 
> 01:00:00.000000000 +0100
> +++ b/arch/powerpc/platforms/efika/Makefile	2006-10-31 
> 20:03:05.000000000 +0100
> @@ -0,0 +1 @@
> +obj-y += setup.o pci.o
> --- a/arch/powerpc/platforms/Makefile	2006-10-31 20:28:06.000000000 +0100
> +++ b/arch/powerpc/platforms/Makefile	2006-10-31 12:31:55.000000000 +0100
> @@ -6,6 +6,7 @@ obj-$(CONFIG_PPC_PMAC)		+= powermac/
>   endif
>   endif
>   obj-$(CONFIG_PPC_CHRP)		+= chrp/
> +obj-$(CONFIG_PPC_EFIKA)		+= efika/
>   obj-$(CONFIG_4xx)		+= 4xx/
>   obj-$(CONFIG_PPC_83xx)		+= 83xx/
>   obj-$(CONFIG_PPC_85xx)		+= 85xx/
> --- a/arch/powerpc/boot/Makefile	2006-10-25 19:07:23.000000000 +0200
> +++ b/arch/powerpc/boot/Makefile	2006-10-31 12:31:55.000000000 +0100
> @@ -155,6 +155,7 @@ image-$(CONFIG_PPC_PSERIES)		+= zImage.p
>   image-$(CONFIG_PPC_MAPLE)		+= zImage.pseries
>   image-$(CONFIG_PPC_IBM_CELL_BLADE)	+= zImage.pseries
>   image-$(CONFIG_PPC_CHRP)		+= zImage.chrp
> +image-$(CONFIG_PPC_EFIKA)		+= zImage.chrp
>   image-$(CONFIG_PPC_PMAC)		+= zImage.pmac
>   image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
> 
> --- a/arch/powerpc/Kconfig	2006-10-31 20:28:06.000000000 +0100
> +++ b/arch/powerpc/Kconfig	2006-10-31 19:57:57.000000000 +0100
> @@ -386,6 +386,19 @@ config PPC_CHRP
>   	select PPC_UDBG_16550
>   	default y
> 
> +config PPC_MPC52xx_PIC
> +        bool
> +	default y
> +
> +config PPC_EFIKA
> +	bool "bPlan Efika 5k2. MPC5200B based computer"
> +	depends on PPC_MULTIPLATFORM && PPC32
> +	select PPC_RTAS
> +	select RTAS_PROC
> +	select PPC_MPC52xx
> +	select PPC_MPC52xx_PIC
> +	default y
> +
>   config PPC_PMAC
>   	bool "Apple PowerMac based machines"
>   	depends on PPC_MULTIPLATFORM
> 

PIC patch separate please.

> +/*
> + * Critial interrupt irq_chip
> +*/
> +static void mpc52xx_crit_mask(unsigned int virq)
> +{
> +	int irq;
> +	int l2irq;
> +
> +	irq = irq_map[virq].hwirq;
> +	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
> +
> +	pr_debug("%s: irq=%x, l2=%d\n", __func__, irq, l2irq);
> +
> +	BUG_ON(l2irq != 0);
> +
> +	io_be_clrbit(&intr->ctrl, 11);
> +}

I'm not sure you understood my previous comment... any reason why crit
and mainirq are two different sets of functions and a different level 1
since crit is just basically mainirq 0 ? And main & mainirq, on the
contrary, should be different L1s since they are ... different :)

> +	switch (l1irq) {
> +	case MPC52xx_IRQ_L1_CRIT:
> +		pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
> +
> +		BUG_ON(l2irq != 0);
> +
> +		type = mpc52xx_irqx_gettype(l2irq);
> +		good_irqchip = &mpc52xx_crit_irqchip;
> +		break;
> +
> +	case MPC52xx_IRQ_L1_MAIN:
> +		pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
> +
> +		if ((l2irq >= 0) && (l2irq <= 3)) {
> +			type = mpc52xx_irqx_gettype(l2irq);
> +			good_irqchip = &mpc52xx_mainirq_irqchip;
> +		} else {
> +			good_irqchip = &mpc52xx_main_irqchip;
> +		}
> +		break;

And doing so would have you simplify the above 2 cases

> +	mpc52xx_irqhost =
> +	    irq_alloc_host(IRQ_HOST_MAP_LINEAR, 0xd0,
> +			   &mpc52xx_irqhost_ops, -1);

I would prefer that 0xd0 to be a symbolic constant in the .h

> +	if (mpc52xx_irqhost)
> +		mpc52xx_irqhost->host_data = (void *)find_mpc52xx_picnode();

Casting to void * is fairly useless :)

> +#ifdef CONFIG_PCI
> +#define _IO_BASE        isa_io_base
> +#define _ISA_MEM_BASE   isa_mem_base
> +#define PCI_DRAM_OFFSET pci_dram_offset
> +#else
> +#define _IO_BASE        0
> +#define _ISA_MEM_BASE   0
> +#define PCI_DRAM_OFFSET 0
> +#endif

I told you several times to remove the above. The whole thing is
duplicate of io.h.

The fact that the former has a special case for CONFIG_PPC_MPC52xx is
bogus in the first place... you might want to turn -that- into a

if defined(CONFIG_PPC_MPC52xx) && !defined(CONFIG_PPC_MERGE)

> +/* 
> ======================================================================== */
> +/* Main registers/struct addresses 
>       */
> +/* 
> ======================================================================== */
> +
> +/* MBAR position */
> +#define MPC52xx_MBAR		0xf0000000	/* Phys address */
> +#define MPC52xx_MBAR_VIRT	0xf0000000	/* Virt address */
> +#define MPC52xx_MBAR_SIZE	0x00010000
> +
> +#define MPC52xx_PA(x)		((phys_addr_t)(MPC52xx_MBAR + (x)))
> +#define MPC52xx_VA(x)		((void __iomem *)(MPC52xx_MBAR_VIRT + (x)))

The above definitions are all bogus for arch/powerpc, just remove them.

> +/*
> + * 24 peripherals ints
> + * + 16 mains ints
> + * + 4 crit
> + * + 16 bestcomm task
> + * = 64
> +*/
> +#define MPC52xx_IRQ_MAXCOUNT     (64)

The above is both not correct anymore and not used. Please fix it and
use it instead of hard coding.

> +static inline struct device_node *find_mpc52xx_picnode(void)
> +{
> +	return of_find_compatible_node(NULL, "interrupt-controller",
> +				       "mpc5200-pic");
> +}

Any reason why you need that inline since it's not used anywhere else
but the PIC code ? Just put that of_find_compatible_node() statement in
the .c and be done with it.

> +	/* Matching of PSC function */
> +struct mpc52xx_psc_func {
> +	int id;
> +	char *func;
> +};
>
> +extern int mpc52xx_match_psc_function(int psc_idx, const char *func);
> +extern struct mpc52xx_psc_func mpc52xx_psc_functions[];
> +	/* This array is to be defined in platform file */

The above doesn't look like it should migrate to arch/powerpc... what is
it supposed to be ?

Ben.

^ permalink raw reply

* Re: glibc-2.5 test suite hangs/crashes the machine
From: Fabio Massimo Di Nitto @ 2006-10-31 20:44 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev, Jeff Bailey, Paul Mackerras, Ben Collins
In-Reply-To: <1162326609.25682.332.camel@localhost.localdomain>

Benjamin Herrenschmidt wrote:
> On Tue, 2006-10-31 at 10:47 +0100, Fabio Massimo Di Nitto wrote:
>> Benjamin Herrenschmidt wrote:
>>> On Mon, 2006-10-30 at 12:35 +0100, Fabio Massimo Di Nitto wrote:
>>>> Benjamin Herrenschmidt wrote:
>>>>> Does that patch fixes it ?
>>>>>
>>>> tested with kernel .17 and headers from .19 and the build hangs. Still tons of
>>>> Zl processes around.
>>>>
>>>> On the note building with kernel .19 and .19 headers it all goes smooth.
>>> Ok, so there's a different issue from what I've found. You haven't by
>>> chance noted what those processes are (which test case typically) ?
>>> Also, there's a sysrq to get a backtrace of all pending processes,
>>> though I don't remember which one off the top of my mind, might be
>>> useful to have a look though.
>>>
>>> Ben.
>>>
>> After discussing with Ben on IRC i applied 69588298188b40ed7f75c98a6fd328d82f23ca21
>> to kernel .17 and glibc does build without zombie processes and no hang whatsoever.
>>
>> I suggest to push this patch back to the stable kernel trees.
> 
> It also need the alignment bits I did though.
> 
> Ben.
> 

I did apply that one too to .17 as we agreed for the test.

Fabio

-- 
I'm going to make him an offer he can't refuse.

^ permalink raw reply

* Re: glibc-2.5 test suite hangs/crashes the machine
From: Benjamin Herrenschmidt @ 2006-10-31 20:30 UTC (permalink / raw)
  To: Fabio Massimo Di Nitto
  Cc: linuxppc-dev, Jeff Bailey, Paul Mackerras, Ben Collins
In-Reply-To: <45471B94.9070606@ubuntu.com>

On Tue, 2006-10-31 at 10:47 +0100, Fabio Massimo Di Nitto wrote:
> Benjamin Herrenschmidt wrote:
> > On Mon, 2006-10-30 at 12:35 +0100, Fabio Massimo Di Nitto wrote:
> >> Benjamin Herrenschmidt wrote:
> >>> Does that patch fixes it ?
> >>>
> >> tested with kernel .17 and headers from .19 and the build hangs. Still tons of
> >> Zl processes around.
> >>
> >> On the note building with kernel .19 and .19 headers it all goes smooth.
> > 
> > Ok, so there's a different issue from what I've found. You haven't by
> > chance noted what those processes are (which test case typically) ?
> > Also, there's a sysrq to get a backtrace of all pending processes,
> > though I don't remember which one off the top of my mind, might be
> > useful to have a look though.
> > 
> > Ben.
> > 
> 
> After discussing with Ben on IRC i applied 69588298188b40ed7f75c98a6fd328d82f23ca21
> to kernel .17 and glibc does build without zombie processes and no hang whatsoever.
> 
> I suggest to push this patch back to the stable kernel trees.

It also need the alignment bits I did though.

Ben.

^ permalink raw reply

* Re: [PATCH 1/2] Add MPC52xx Interrupt controller support for ARCH=powerpc
From: Benjamin Herrenschmidt @ 2006-10-31 20:29 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-dev, sl, sha, linuxppc-embedded
In-Reply-To: <45471B57.6040109@bplan-gmbh.de>

On Tue, 2006-10-31 at 10:46 +0100, Nicolas DET wrote:
> Benjamin Herrenschmidt wrote:
> >> Ok. that's why I suggest to keep buggy (or none) firmware board in 
> >> platform specific code.
> > 
> > Well, in that case, we have a well defined interface to set the sense
> > code, via the device-tree, and that's much better than having platform
> > code muck around the PIC hardware separately from the PIC driver don't
> > you think ?
> > 
> > Anyway, that's the way it works in Linux/powerpc so there is no need
> > debating that for ever. Just be aware that at one point, there will be a
> > set_type() implementation in this driver and that it will be called
> > based on the polarity information in the device-tree so make sure you
> > got it right.
> > 
> 
> Ok. set_type() is scheduled for later on or should it be included right now?
> What's next should be done to finally acked the driver?

Post the latest one and we'll see..

Ben

^ permalink raw reply

* Re: [PATCH 1/2] Add MPC52xx Interrupt controller support for ARCH=powerpc
From: Nicolas DET @ 2006-10-31 20:04 UTC (permalink / raw)
  To: Nicolas DET; +Cc: linuxppc-embedded, sl, sha, linuxppc-dev
In-Reply-To: <454712A4.3000501@bplan-gmbh.de>

[-- Attachment #1: Type: text/plain, Size: 35449 bytes --]

Nicolas DET wrote:
> Benjamin Herrenschmidt wrote:
>> On Tue, 2006-10-31 at 09:25 +0100, Nicolas DET wrote:
>>
>>> Ok. By the way, the mbar is include as property in our OpenFrimware. 
>>> Moreover, the G2CORE CPU has a new SPR 'MBAR' which is the MBAR ;-). 
>>> It would maybe make sense to create a new file 
>>> (arch/powerpc/sysdev/mpc52xx.c) which would contain chip specific code.
>>>
>>> Like mpc52xx_get_mbar(), mpc52xx_get_ipbfreq(), etc...
>>>
>>> I updated a bit the patches. I applied Dale requests.
>>> My kernel still compiles and boots. ;-)
>>>
>>> Should I post the new patches?
>>
>> Sure.
>>
> 
> Ok. Should be done this morning.
> 

Here is is ;-).
As my mailer can insert a file, I copy paste. I hope it's still ok...

archpowerpc_efika.patch
-----------------------
--- a/arch/powerpc/platforms/efika/setup.c	1970-01-01 01:00:00.000000000 
+0100
+++ b/arch/powerpc/platforms/efika/setup.c	2006-10-31 12:31:55.000000000 
+0100
@@ -0,0 +1,153 @@
+/*
+ *
+ * Efika 5K2 platform setup
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/utsrelease.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/console.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+#include <asm/rtas.h>
+#include <asm/mpc52xx.h>
+
+#include "efika.h"
+
+void rtas_indicator_progress(char *, unsigned short);
+
+extern unsigned long loops_per_jiffy;
+
+static void efika_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *root;
+	const char *revision = NULL;
+	const char *codegendescription = NULL;
+	const char *codegenvendor = NULL;
+
+	root = find_path_device("/");
+	if (root) {
+		revision = get_property(root, "revision", NULL);
+		codegendescription =
+		    get_property(root, "CODEGEN,description", NULL);
+		codegenvendor = get_property(root, "CODEGEN,vendor", NULL);
+	}
+
+	if (codegendescription)
+		seq_printf(m, "machine\t\t: %s\n", codegendescription);
+	else
+		seq_printf(m, "machine\t\t: Efika\n");
+
+	if (revision)
+		seq_printf(m, "revision\t: %s\n", revision);
+
+	if (codegenvendor)
+		seq_printf(m, "vendor\t\t: %s\n", codegenvendor);
+}
+
+static void __init efika_setup_arch(void)
+{
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000 / HZ;
+
+	rtas_initialize();
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	initrd_below_start_ok = 1;
+
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+		ROOT_DEV = Root_SDA2;	/* sda2 (sda1 is for the kernel) */
+
+	pci_create_OF_bus_map();
+
+	efika_pcisetup();
+
+	if (ppc_md.progress)
+		ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
+}
+
+static void __init efika_init_IRQ(void)
+{
+	of_irq_map_init(0);
+	mpc52xx_init_irq();
+}
+
+static void __init efika_init(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("  Have fun with your Efika!    ", 0x7777);
+}
+
+static int __init efika_probe(void)
+{
+	char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
+					  "model", NULL);
+
+	if (model == NULL)
+		return 0;
+	if (strcmp(model, "EFIKA5K2"))
+		return 0;
+
+	ISA_DMA_THRESHOLD = ~0L;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	/*
+	 * Others values (isa_mem_base, pci_dram_base) are 0
+	 * in CHRP for us. Only isa_io_base is changed.
+	*/
+	isa_io_base = CHRP_ISA_IO_BASE;
+
+	return 1;
+}
+
+define_machine(efika)
+{
+	.name = EFIKA_PLATFORM_NAME,
+	.probe = efika_probe,
+	.setup_arch = efika_setup_arch,
+	.init = efika_init,
+	.show_cpuinfo = efika_show_cpuinfo,
+	.init_IRQ = efika_init_IRQ,
+	.get_irq = mpc52xx_get_irq,
+	.restart = rtas_restart,
+	.power_off = rtas_power_off,
+	.halt = rtas_halt,
+	.set_rtc_time = rtas_set_rtc_time,
+	.get_rtc_time = rtas_get_rtc_time,
+	.progress = rtas_progress,
+	.get_boot_time = rtas_get_boot_time,
+	.calibrate_decr = generic_calibrate_decr,
+	.phys_mem_access_prot = pci_phys_mem_access_prot,
+	.pcibios_fixup = efika_pciirq_map,
+};
--- a/arch/powerpc/platforms/efika/pci.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/platforms/efika/pci.c	2006-10-31 12:31:55.000000000 +0100
@@ -0,0 +1,150 @@
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/hydra.h>
+#include <asm/prom.h>
+#include <asm/gg2.h>
+#include <asm/machdep.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+#include <asm/grackle.h>
+#include <asm/rtas.h>
+
+#include "efika.h"
+
+static struct device_node *efika_pcictrl;
+
+/*
+ * Access functions for PCI config space using RTAS calls.
+ */
+static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, 
int offset,
+			    int len, u32 * val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+	    | (((bus->number - hose->first_busno) & 0xff) << 16)
+	    | (hose->index << 24);
+	int ret = -1;
+	int rval;
+
+	rval = rtas_call(rtas_token("read-pci-config"), 2, 2, &ret, addr, len);
+	*val = ret;
+	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+static int rtas_write_config(struct pci_bus *bus, unsigned int devfn,
+			     int offset, int len, u32 val)
+{
+	struct pci_controller *hose = bus->sysdata;
+	unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8)
+	    | (((bus->number - hose->first_busno) & 0xff) << 16)
+	    | (hose->index << 24);
+	int rval;
+
+	rval = rtas_call(rtas_token("write-pci-config"), 3, 1, NULL,
+			 addr, len, val);
+	return rval ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops rtas_pci_ops = {
+	rtas_read_config,
+	rtas_write_config
+};
+
+void __init efika_pcisetup(void)
+{
+	const int *bus_range;
+	int len;
+	struct pci_controller *hose;
+	struct device_node *root;
+	struct device_node *pcictrl;
+
+	root = of_find_node_by_path("/");
+	if (root == NULL) {
+		printk(KERN_WARNING EFIKA_PLATFORM_NAME
+		       ": Unable to find the root node\n");
+		return;
+	}
+
+	for (pcictrl = NULL;;) {
+		pcictrl = of_get_next_child(root, pcictrl);
+		if ((pcictrl == NULL) || (strcmp(pcictrl->name, "pci") == 0))
+			break;
+	}
+
+	if (pcictrl == NULL) {
+		printk(KERN_WARNING EFIKA_PLATFORM_NAME
+		       ": Unable to find the PCI bridge node\n");
+		return;
+	}
+
+	efika_pcictrl = pcictrl;
+
+	bus_range = get_property(pcictrl, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING EFIKA_PLATFORM_NAME
+		       ": Can't get bus-range for %s\n", pcictrl->full_name);
+		return;
+	}
+	if (bus_range[1] == bus_range[0])
+		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
+		       bus_range[0]);
+	else
+		printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
+		       bus_range[0], bus_range[1]);
+	printk(" controlled by %s", pcictrl->full_name);
+	printk("\n");
+
+	hose = pcibios_alloc_controller();
+	if (!hose) {
+		printk(KERN_WARNING EFIKA_PLATFORM_NAME
+		       ": Can't allocate PCI controller structure for %s\n",
+		       pcictrl->full_name);
+		return;
+	}
+
+	hose->arch_data = pcictrl;
+	hose->first_busno = bus_range[0];
+	hose->last_busno = bus_range[1];
+	hose->ops = &rtas_pci_ops;
+
+	pci_process_bridge_OF_ranges(hose, pcictrl, 0);
+}
+
+void __init efika_pciirq_map(void)
+{
+	struct device_node *pcictrl = efika_pcictrl;
+	struct pci_dev *pdev = NULL;
+	struct device_node *ofwdev;
+
+	if (pcictrl == NULL)
+		return;
+
+	/*
+	 * We need to find PCI irq, create a virtual mapping, and set
+	 * the irq number into the PCI structure (software/Linux side)
+	 * I could to this by walking into the /pci node, do
+	 * of_irq_map_pci(), irq_create_of_mapping(), then find
+	 * the good 'struct pci_dev *' and update pci_dev->irq.
+	 * However, pci_read_irq_line() should do everything correctly!
+	*/
+
+	for_each_pci_dev(pdev)
+	{
+		if (pci_read_irq_line(pdev) < 0)
+			continue;
+
+		ofwdev = pci_device_to_OF_node(pdev);
+		if (ofwdev)
+			printk(KERN_INFO EFIKA_PLATFORM_NAME ": got IRQ 0x%x for '%s'\n", 
pdev->irq, ofwdev->full_name);
+	}
+
+}
--- a/arch/powerpc/platforms/efika/efika.h	1970-01-01 01:00:00.000000000 
+0100
+++ b/arch/powerpc/platforms/efika/efika.h	2006-10-31 12:31:55.000000000 
+0100
@@ -0,0 +1,20 @@
+/*
+ * Efika 5K2 platform setup - Header file
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef __ARCH_POWERPC_EFIKA__
+#define __ARCH_POWERPC_EFIKA__
+
+#define EFIKA_PLATFORM_NAME "Efika"
+
+void __init efika_pcisetup(void);
+void __init efika_pciirq_map(void);
+
+#endif
--- a/arch/powerpc/platforms/efika/Makefile	1970-01-01 
01:00:00.000000000 +0100
+++ b/arch/powerpc/platforms/efika/Makefile	2006-10-31 
20:03:05.000000000 +0100
@@ -0,0 +1 @@
+obj-y += setup.o pci.o
--- a/arch/powerpc/platforms/Makefile	2006-10-31 20:28:06.000000000 +0100
+++ b/arch/powerpc/platforms/Makefile	2006-10-31 12:31:55.000000000 +0100
@@ -6,6 +6,7 @@ obj-$(CONFIG_PPC_PMAC)		+= powermac/
  endif
  endif
  obj-$(CONFIG_PPC_CHRP)		+= chrp/
+obj-$(CONFIG_PPC_EFIKA)		+= efika/
  obj-$(CONFIG_4xx)		+= 4xx/
  obj-$(CONFIG_PPC_83xx)		+= 83xx/
  obj-$(CONFIG_PPC_85xx)		+= 85xx/
--- a/arch/powerpc/boot/Makefile	2006-10-25 19:07:23.000000000 +0200
+++ b/arch/powerpc/boot/Makefile	2006-10-31 12:31:55.000000000 +0100
@@ -155,6 +155,7 @@ image-$(CONFIG_PPC_PSERIES)		+= zImage.p
  image-$(CONFIG_PPC_MAPLE)		+= zImage.pseries
  image-$(CONFIG_PPC_IBM_CELL_BLADE)	+= zImage.pseries
  image-$(CONFIG_PPC_CHRP)		+= zImage.chrp
+image-$(CONFIG_PPC_EFIKA)		+= zImage.chrp
  image-$(CONFIG_PPC_PMAC)		+= zImage.pmac
  image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage

--- a/arch/powerpc/Kconfig	2006-10-31 20:28:06.000000000 +0100
+++ b/arch/powerpc/Kconfig	2006-10-31 19:57:57.000000000 +0100
@@ -386,6 +386,19 @@ config PPC_CHRP
  	select PPC_UDBG_16550
  	default y

+config PPC_MPC52xx_PIC
+        bool
+	default y
+
+config PPC_EFIKA
+	bool "bPlan Efika 5k2. MPC5200B based computer"
+	depends on PPC_MULTIPLATFORM && PPC32
+	select PPC_RTAS
+	select RTAS_PROC
+	select PPC_MPC52xx
+	select PPC_MPC52xx_PIC
+	default y
+
  config PPC_PMAC
  	bool "Apple PowerMac based machines"
  	depends on PPC_MULTIPLATFORM


archpowerpc_mpc52xx.patch
-------------------------
--- a/arch/powerpc/sysdev/mpc52xx_pic.c	1970-01-01 01:00:00.000000000 +0100
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c	2006-10-31 19:56:22.000000000 +0100
@@ -0,0 +1,511 @@
+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+static struct irq_host *mpc52xx_irqhost = NULL;
+
+static unsigned char mpc52xx_map_senses[4] = {
+	IRQ_TYPE_LEVEL_HIGH,
+	IRQ_TYPE_EDGE_FALLING,
+	IRQ_TYPE_EDGE_RISING,
+	IRQ_TYPE_LEVEL_LOW,
+};
+
+/*
+ *
+*/
+
+static inline void io_be_setbit(u32 __iomem *addr, int bitno)
+{
+	out_be32(addr, in_be32(addr) | (1 << bitno) );
+}
+
+static inline void io_be_clrbit(u32 __iomem *addr, int bitno)
+{
+	out_be32(addr, in_be32(addr) & ~(1 << bitno));
+}
+
+/*
+ * Critial interrupt irq_chip
+*/
+static void mpc52xx_crit_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x, l2=%d\n", __func__, irq, l2irq);
+
+	BUG_ON(l2irq != 0);
+
+	io_be_clrbit(&intr->ctrl, 11);
+}
+
+static void mpc52xx_crit_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	BUG_ON(l2irq != 0);
+
+	io_be_setbit(&intr->ctrl, 11);
+}
+
+static void mpc52xx_crit_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	BUG_ON(l2irq != 0);
+
+	io_be_setbit(&intr->ctrl, 27);
+}
+
+static struct irq_chip mpc52xx_crit_irqchip = {
+	.typename = "MPC52xx IRQ0",
+	.mask = mpc52xx_crit_mask,
+	.unmask = mpc52xx_crit_unmask,
+	.ack = mpc52xx_crit_ack,
+};
+
+/*
+ * IRQ[1-3] interrupt irq_chip
+*/
+
+static void mpc52xx_mainirq_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_mainirq_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_mainirq_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->ctrl, 27-l2irq);
+}
+
+static struct irq_chip mpc52xx_mainirq_irqchip = {
+	.typename = " MPC52xx IRQ[1-3] ",
+	.mask = mpc52xx_mainirq_mask,
+	.unmask = mpc52xx_mainirq_unmask,
+	.ack = mpc52xx_mainirq_ack,
+};
+
+/*
+ * Main interrupt irq_chip
+*/
+
+static void mpc52xx_main_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->main_mask, 15 - l2irq);
+}
+
+static void mpc52xx_main_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->main_mask, 15 - l2irq);
+}
+
+static struct irq_chip mpc52xx_main_irqchip = {
+	.typename = "MPC52xx Main",
+	.mask = mpc52xx_main_mask,
+	.mask_ack = mpc52xx_main_mask,
+	.unmask = mpc52xx_main_unmask,
+};
+
+/*
+ * Peripherals interrupt irq_chip
+*/
+
+static void mpc52xx_periph_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&intr->per_mask, 31 - l2irq);
+}
+
+static void mpc52xx_periph_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&intr->per_mask, 31 - l2irq);
+}
+
+static struct irq_chip mpc52xx_periph_irqchip = {
+	.typename = "MPC52xx Peripherals",
+	.mask = mpc52xx_periph_mask,
+	.mask_ack = mpc52xx_periph_mask,
+	.unmask = mpc52xx_periph_unmask,
+};
+
+/*
+ * SDMA interrupt irq_chip
+*/
+
+static void mpc52xx_sdma_mask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_setbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_unmask(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	io_be_clrbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_ack(unsigned int virq)
+{
+	int irq;
+	int l2irq;
+
+	irq = irq_map[virq].hwirq;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+	out_be32(&sdma->IntPend, 1 << l2irq);
+}
+
+static struct irq_chip mpc52xx_sdma_irqchip = {
+	.typename = "MPC52xx SDMA",
+	.mask = mpc52xx_sdma_mask,
+	.unmask = mpc52xx_sdma_unmask,
+	.ack = mpc52xx_sdma_ack,
+};
+
+/*
+ * irq_host
+*/
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node 
*node)
+{
+	pr_debug("%s: %p vs %p\n", __func__, find_mpc52xx_picnode(), node);
+	return mpc52xx_irqhost->host_data == node;
+}
+
+static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node 
*ct,
+				 u32 * intspec, unsigned int intsize,
+				 irq_hw_number_t * out_hwirq,
+				 unsigned int *out_flags)
+{
+	int intrvect_l1;
+	int intrvect_l2;
+	int intrvect_type;
+	int intrvect_linux;
+
+	if (intsize != 3)
+		return -1;
+
+	intrvect_l1 = (int)intspec[0];
+	intrvect_l2 = (int)intspec[1];
+	intrvect_type = (int)intspec[2];
+
+	intrvect_linux =
+	    (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
+	intrvect_linux |=
+	    (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
+
+	pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
+		 intrvect_l2);
+
+	*out_hwirq = intrvect_linux;
+	*out_flags = mpc52xx_map_senses[intrvect_type];
+
+	return 0;
+}
+
+/*
+ * this function retrieves the correct IRQ type out
+ * of the MPC regs
+ * Only externals IRQs needs this
+*/
+static int mpc52xx_irqx_gettype(int irq)
+{
+	int type;
+	u32 ctrl_reg;
+
+	ctrl_reg = in_be32(&intr->ctrl);
+	type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
+
+	return mpc52xx_map_senses[type];
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+			       irq_hw_number_t irq)
+{
+	int l1irq;
+	int l2irq;
+	struct irq_chip *good_irqchip;
+	void *good_handle;
+	int type;
+
+	l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+	l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+	/*
+	 * Most of ours IRQs will be level low
+	 * Only external IRQs on some platform may be others
+	 */
+	type = IRQ_TYPE_LEVEL_LOW;
+
+	switch (l1irq) {
+	case MPC52xx_IRQ_L1_CRIT:
+		pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
+
+		BUG_ON(l2irq != 0);
+
+		type = mpc52xx_irqx_gettype(l2irq);
+		good_irqchip = &mpc52xx_crit_irqchip;
+		break;
+
+	case MPC52xx_IRQ_L1_MAIN:
+		pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
+
+		if ((l2irq >= 0) && (l2irq <= 3)) {
+			type = mpc52xx_irqx_gettype(l2irq);
+			good_irqchip = &mpc52xx_mainirq_irqchip;
+		} else {
+			good_irqchip = &mpc52xx_main_irqchip;
+		}
+		break;
+
+	case MPC52xx_IRQ_L1_PERP:
+		pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
+		good_irqchip = &mpc52xx_periph_irqchip;
+		break;
+
+	case MPC52xx_IRQ_L1_SDMA:
+		pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
+		good_irqchip = &mpc52xx_sdma_irqchip;
+		break;
+
+	default:
+		pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
+		printk(KERN_ERR "Unknow IRQ!\n");
+		return -EINVAL;
+	}
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_FALLING:
+	case IRQ_TYPE_EDGE_RISING:
+		good_handle = handle_edge_irq;
+		break;
+	default:
+		good_handle = handle_level_irq;
+	}
+
+	set_irq_chip_and_handler(virq, good_irqchip, good_handle);
+
+	pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
+		 (int)irq, type);
+
+	return 0;
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+	.match = mpc52xx_irqhost_match,
+	.xlate = mpc52xx_irqhost_xlate,
+	.map = mpc52xx_irqhost_map,
+};
+
+/*
+ * init (public)
+*/
+
+void __init mpc52xx_init_irq(void)
+{
+	u32 intr_ctrl;
+
+	/* Remap the necessary zones */
+	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);
+	sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);
+
+	if ((intr == NULL) || (sdma == NULL))
+		panic("Can't ioremap PIC/SDMA register or init_irq !");
+
+	/* Disable all interrupt sources. */
+	out_be32(&sdma->IntPend, 0xffffffff);	/* 1 means clear pending */
+	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */
+	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */
+	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */
+	intr_ctrl = in_be32(&intr->ctrl);
+	intr_ctrl &= 0x00ff0000;	/* Keeps IRQ[0-3] config */
+	intr_ctrl |= 0x0f000000 |	/* clear IRQ 0-3 */
+	    0x00001000 |	/* MEE master external enable */
+	    0x00000000 |	/* 0 means disable IRQ 0-3 */
+	    0x00000001;		/* CEb route critical normally */
+	out_be32(&intr->ctrl, intr_ctrl);
+
+	/* Zero a bunch of the priority settings.  */
+	out_be32(&intr->per_pri1, 0);
+	out_be32(&intr->per_pri2, 0);
+	out_be32(&intr->per_pri3, 0);
+	out_be32(&intr->main_pri1, 0);
+	out_be32(&intr->main_pri2, 0);
+
+	/*
+	 * As last step, add an irq host to translate the real
+	 * hw irq information provided by the ofw to linux virq
+	 */
+
+	mpc52xx_irqhost =
+	    irq_alloc_host(IRQ_HOST_MAP_LINEAR, 0xd0,
+			   &mpc52xx_irqhost_ops, -1);
+
+	if (mpc52xx_irqhost)
+		mpc52xx_irqhost->host_data = (void *)find_mpc52xx_picnode();
+}
+
+/*
+ * get_irq (public)
+*/
+unsigned int mpc52xx_get_irq(void)
+{
+	u32 status;
+	int irq = NO_IRQ_IGNORE;
+
+	status = in_be32(&intr->enc_status);
+	if (status & 0x00000400) {	/* critical */
+		irq = (status >> 8) & 0x3;
+		if (irq == 2)	/* high priority peripheral */
+			goto peripheral;
+		irq |=
+		    (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
+		    MPC52xx_IRQ_L1_MASK;
+	} else if (status & 0x00200000) {	/* main */
+		irq = (status >> 16) & 0x1f;
+		if (irq == 4)	/* low priority peripheral */
+			goto peripheral;
+		irq |=
+		    (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
+		    MPC52xx_IRQ_L1_MASK;
+	} else if (status & 0x20000000) {	/* peripheral */
+	      peripheral:
+		irq = (status >> 24) & 0x1f;
+		if (irq == 0) {	/* bestcomm */
+			status = in_be32(&sdma->IntPend);
+			irq = ffs(status) - 1;
+			irq |=
+			    (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
+			    MPC52xx_IRQ_L1_MASK;
+		} else
+			irq |=
+			    (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
+			    MPC52xx_IRQ_L1_MASK;
+
+	}
+
+	pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
+		 irq_linear_revmap(mpc52xx_irqhost, irq));
+
+	return irq_linear_revmap(mpc52xx_irqhost, irq);
+}
--- a/arch/powerpc/sysdev/Makefile	2006-10-25 19:07:24.000000000 +0200
+++ b/arch/powerpc/sysdev/Makefile	2006-10-31 19:56:41.000000000 +0100
@@ -13,6 +13,7 @@ obj-$(CONFIG_FSL_SOC)		+= fsl_soc.o
  obj-$(CONFIG_PPC_TODC)		+= todc.o
  obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
  obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
+obj-$(CONFIG_PPC_MPC52xx_PIC)	+= mpc52xx_pic.o

  ifeq ($(CONFIG_PPC_MERGE),y)
  obj-$(CONFIG_PPC_I8259)		+= i8259.o
--- a/include/asm-powerpc/mpc52xx.h	1970-01-01 01:00:00.000000000 +0100
+++ b/include/asm-powerpc/mpc52xx.h	2006-10-31 12:31:55.000000000 +0100
@@ -0,0 +1,373 @@
+/*
+ *
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_POWERPC_MPC52xx_H__
+#define __ASM_POWERPC_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/prom.h>
+
+#endif				/* __ASSEMBLY__ */
+
+#ifdef CONFIG_PCI
+#define _IO_BASE        isa_io_base
+#define _ISA_MEM_BASE   isa_mem_base
+#define PCI_DRAM_OFFSET pci_dram_offset
+#else
+#define _IO_BASE        0
+#define _ISA_MEM_BASE   0
+#define PCI_DRAM_OFFSET 0
+#endif
+
+/* 
======================================================================== */
+/* Main registers/struct addresses 
      */
+/* 
======================================================================== */
+
+/* MBAR position */
+#define MPC52xx_MBAR		0xf0000000	/* Phys address */
+#define MPC52xx_MBAR_VIRT	0xf0000000	/* Virt address */
+#define MPC52xx_MBAR_SIZE	0x00010000
+
+#define MPC52xx_PA(x)		((phys_addr_t)(MPC52xx_MBAR + (x)))
+#define MPC52xx_VA(x)		((void __iomem *)(MPC52xx_MBAR_VIRT + (x)))
+
+/* Registers zone offset/size  */
+#define MPC52xx_MMAP_CTL_OFFSET		0x0000
+#define MPC52xx_MMAP_CTL_SIZE		0x068
+#define MPC52xx_SDRAM_OFFSET		0x0100
+#define MPC52xx_SDRAM_SIZE		0x010
+#define MPC52xx_CDM_OFFSET		0x0200
+#define MPC52xx_CDM_SIZE		0x038
+#define MPC52xx_INTR_OFFSET		0x0500
+#define MPC52xx_INTR_SIZE		0x04c
+#define MPC52xx_GPTx_OFFSET(x)		(0x0600 + ((x)<<4))
+#define MPC52xx_GPT_SIZE		0x010
+#define MPC52xx_RTC_OFFSET		0x0800
+#define MPC52xx_RTC_SIZE		0x024
+#define MPC52xx_GPIO_OFFSET		0x0b00
+#define MPC52xx_GPIO_SIZE		0x040
+#define MPC52xx_GPIO_WKUP_OFFSET	0x0c00
+#define MPC52xx_GPIO_WKUP_SIZE		0x028
+#define MPC52xx_PCI_OFFSET		0x0d00
+#define MPC52xx_PCI_SIZE		0x100
+#define MPC52xx_SDMA_OFFSET		0x1200
+#define MPC52xx_SDMA_SIZE		0x100
+#define MPC52xx_XLB_OFFSET		0x1f00
+#define MPC52xx_XLB_SIZE		0x100
+#define MPC52xx_PSCx_OFFSET(x)		(((x)!=6)?(0x1e00+((x)<<9)):0x2c00)
+#define MPC52xx_PSC_SIZE		0x0a0
+
+/* SRAM used for SDMA */
+#define MPC52xx_SRAM_OFFSET		0x8000
+#define MPC52xx_SRAM_SIZE		0x4000
+
+/* 
======================================================================== */
+/* IRQ mapping 
      */
+/* 
======================================================================== */
+
+#define MPC52xx_IRQ_L1_CRIT	(0)
+#define MPC52xx_IRQ_L1_MAIN	(1)
+#define MPC52xx_IRQ_L1_PERP	(2)
+#define MPC52xx_IRQ_L1_SDMA	(3)
+
+#define MPC52xx_IRQ_L1_OFFSET   (6)
+#define MPC52xx_IRQ_L1_MASK     (0x00c0)
+
+#define MPC52xx_IRQ_L2_OFFSET   (0)
+#define MPC52xx_IRQ_L2_MASK     (0x003f)
+
+/*
+ * 24 peripherals ints
+ * + 16 mains ints
+ * + 4 crit
+ * + 16 bestcomm task
+ * = 64
+*/
+#define MPC52xx_IRQ_MAXCOUNT     (64)
+
+/* 
======================================================================== */
+/* Structures mapping of some unit register set 
      */
+/* 
======================================================================== */
+
+#ifndef __ASSEMBLY__
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+	u32 mbar;		/* MMAP_CTRL + 0x00 */
+
+	u32 cs0_start;		/* MMAP_CTRL + 0x04 */
+	u32 cs0_stop;		/* MMAP_CTRL + 0x08 */
+	u32 cs1_start;		/* MMAP_CTRL + 0x0c */
+	u32 cs1_stop;		/* MMAP_CTRL + 0x10 */
+	u32 cs2_start;		/* MMAP_CTRL + 0x14 */
+	u32 cs2_stop;		/* MMAP_CTRL + 0x18 */
+	u32 cs3_start;		/* MMAP_CTRL + 0x1c */
+	u32 cs3_stop;		/* MMAP_CTRL + 0x20 */
+	u32 cs4_start;		/* MMAP_CTRL + 0x24 */
+	u32 cs4_stop;		/* MMAP_CTRL + 0x28 */
+	u32 cs5_start;		/* MMAP_CTRL + 0x2c */
+	u32 cs5_stop;		/* MMAP_CTRL + 0x30 */
+
+	u32 sdram0;		/* MMAP_CTRL + 0x34 */
+	u32 sdram1;		/* MMAP_CTRL + 0X38 */
+
+	u32 reserved[4];	/* MMAP_CTRL + 0x3c .. 0x48 */
+
+	u32 boot_start;		/* MMAP_CTRL + 0x4c */
+	u32 boot_stop;		/* MMAP_CTRL + 0x50 */
+
+	u32 ipbi_ws_ctrl;	/* MMAP_CTRL + 0x54 */
+
+	u32 cs6_start;		/* MMAP_CTRL + 0x58 */
+	u32 cs6_stop;		/* MMAP_CTRL + 0x5c */
+	u32 cs7_start;		/* MMAP_CTRL + 0x60 */
+	u32 cs7_stop;		/* MMAP_CTRL + 0x64 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+	u32 mode;		/* SDRAM + 0x00 */
+	u32 ctrl;		/* SDRAM + 0x04 */
+	u32 config1;		/* SDRAM + 0x08 */
+	u32 config2;		/* SDRAM + 0x0c */
+};
+
+/* Interrupt controller */
+struct mpc52xx_intr {
+	u32 per_mask;		/* INTR + 0x00 */
+	u32 per_pri1;		/* INTR + 0x04 */
+	u32 per_pri2;		/* INTR + 0x08 */
+	u32 per_pri3;		/* INTR + 0x0c */
+	u32 ctrl;		/* INTR + 0x10 */
+	u32 main_mask;		/* INTR + 0x14 */
+	u32 main_pri1;		/* INTR + 0x18 */
+	u32 main_pri2;		/* INTR + 0x1c */
+	u32 reserved1;		/* INTR + 0x20 */
+	u32 enc_status;		/* INTR + 0x24 */
+	u32 crit_status;	/* INTR + 0x28 */
+	u32 main_status;	/* INTR + 0x2c */
+	u32 per_status;		/* INTR + 0x30 */
+	u32 reserved2;		/* INTR + 0x34 */
+	u32 per_error;		/* INTR + 0x38 */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+	u32 taskBar;		/* SDMA + 0x00 */
+	u32 currentPointer;	/* SDMA + 0x04 */
+	u32 endPointer;		/* SDMA + 0x08 */
+	u32 variablePointer;	/* SDMA + 0x0c */
+
+	u8 IntVect1;		/* SDMA + 0x10 */
+	u8 IntVect2;		/* SDMA + 0x11 */
+	u16 PtdCntrl;		/* SDMA + 0x12 */
+
+	u32 IntPend;		/* SDMA + 0x14 */
+	u32 IntMask;		/* SDMA + 0x18 */
+
+	u16 tcr[16];		/* SDMA + 0x1c .. 0x3a */
+
+	u8 ipr[32];		/* SDMA + 0x3c .. 0x5b */
+
+	u32 cReqSelect;		/* SDMA + 0x5c */
+	u32 task_size0;		/* SDMA + 0x60 */
+	u32 task_size1;		/* SDMA + 0x64 */
+	u32 MDEDebug;		/* SDMA + 0x68 */
+	u32 ADSDebug;		/* SDMA + 0x6c */
+	u32 Value1;		/* SDMA + 0x70 */
+	u32 Value2;		/* SDMA + 0x74 */
+	u32 Control;		/* SDMA + 0x78 */
+	u32 Status;		/* SDMA + 0x7c */
+	u32 PTDDebug;		/* SDMA + 0x80 */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+	u32 mode;		/* GPTx + 0x00 */
+	u32 count;		/* GPTx + 0x04 */
+	u32 pwm;		/* GPTx + 0x08 */
+	u32 status;		/* GPTx + 0X0c */
+};
+
+/* RTC */
+struct mpc52xx_rtc {
+	u32 time_set;		/* RTC + 0x00 */
+	u32 date_set;		/* RTC + 0x04 */
+	u32 stopwatch;		/* RTC + 0x08 */
+	u32 int_enable;		/* RTC + 0x0c */
+	u32 time;		/* RTC + 0x10 */
+	u32 date;		/* RTC + 0x14 */
+	u32 stopwatch_intr;	/* RTC + 0x18 */
+	u32 bus_error;		/* RTC + 0x1c */
+	u32 dividers;		/* RTC + 0x20 */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+	u32 port_config;	/* GPIO + 0x00 */
+	u32 simple_gpioe;	/* GPIO + 0x04 */
+	u32 simple_ode;		/* GPIO + 0x08 */
+	u32 simple_ddr;		/* GPIO + 0x0c */
+	u32 simple_dvo;		/* GPIO + 0x10 */
+	u32 simple_ival;	/* GPIO + 0x14 */
+	u8 outo_gpioe;		/* GPIO + 0x18 */
+	u8 reserved1[3];	/* GPIO + 0x19 */
+	u8 outo_dvo;		/* GPIO + 0x1c */
+	u8 reserved2[3];	/* GPIO + 0x1d */
+	u8 sint_gpioe;		/* GPIO + 0x20 */
+	u8 reserved3[3];	/* GPIO + 0x21 */
+	u8 sint_ode;		/* GPIO + 0x24 */
+	u8 reserved4[3];	/* GPIO + 0x25 */
+	u8 sint_ddr;		/* GPIO + 0x28 */
+	u8 reserved5[3];	/* GPIO + 0x29 */
+	u8 sint_dvo;		/* GPIO + 0x2c */
+	u8 reserved6[3];	/* GPIO + 0x2d */
+	u8 sint_inten;		/* GPIO + 0x30 */
+	u8 reserved7[3];	/* GPIO + 0x31 */
+	u16 sint_itype;		/* GPIO + 0x34 */
+	u16 reserved8;		/* GPIO + 0x36 */
+	u8 gpio_control;	/* GPIO + 0x38 */
+	u8 reserved9[3];	/* GPIO + 0x39 */
+	u8 sint_istat;		/* GPIO + 0x3c */
+	u8 sint_ival;		/* GPIO + 0x3d */
+	u8 bus_errs;		/* GPIO + 0x3e */
+	u8 reserved10;		/* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD	4
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD	5
+#define MPC52xx_GPIO_PCI_DIS			(1<<15)
+
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+	u8 wkup_gpioe;		/* GPIO_WKUP + 0x00 */
+	u8 reserved1[3];	/* GPIO_WKUP + 0x03 */
+	u8 wkup_ode;		/* GPIO_WKUP + 0x04 */
+	u8 reserved2[3];	/* GPIO_WKUP + 0x05 */
+	u8 wkup_ddr;		/* GPIO_WKUP + 0x08 */
+	u8 reserved3[3];	/* GPIO_WKUP + 0x09 */
+	u8 wkup_dvo;		/* GPIO_WKUP + 0x0C */
+	u8 reserved4[3];	/* GPIO_WKUP + 0x0D */
+	u8 wkup_inten;		/* GPIO_WKUP + 0x10 */
+	u8 reserved5[3];	/* GPIO_WKUP + 0x11 */
+	u8 wkup_iinten;		/* GPIO_WKUP + 0x14 */
+	u8 reserved6[3];	/* GPIO_WKUP + 0x15 */
+	u16 wkup_itype;		/* GPIO_WKUP + 0x18 */
+	u8 reserved7[2];	/* GPIO_WKUP + 0x1A */
+	u8 wkup_maste;		/* GPIO_WKUP + 0x1C */
+	u8 reserved8[3];	/* GPIO_WKUP + 0x1D */
+	u8 wkup_ival;		/* GPIO_WKUP + 0x20 */
+	u8 reserved9[3];	/* GPIO_WKUP + 0x21 */
+	u8 wkup_istat;		/* GPIO_WKUP + 0x24 */
+	u8 reserved10[3];	/* GPIO_WKUP + 0x25 */
+};
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+	u8 reserved[0x40];
+	u32 config;		/* XLB + 0x40 */
+	u32 version;		/* XLB + 0x44 */
+	u32 status;		/* XLB + 0x48 */
+	u32 int_enable;		/* XLB + 0x4c */
+	u32 addr_capture;	/* XLB + 0x50 */
+	u32 bus_sig_capture;	/* XLB + 0x54 */
+	u32 addr_timeout;	/* XLB + 0x58 */
+	u32 data_timeout;	/* XLB + 0x5c */
+	u32 bus_act_timeout;	/* XLB + 0x60 */
+	u32 master_pri_enable;	/* XLB + 0x64 */
+	u32 master_priority;	/* XLB + 0x68 */
+	u32 base_address;	/* XLB + 0x6c */
+	u32 snoop_window;	/* XLB + 0x70 */
+};
+
+#define MPC52xx_XLB_CFG_PLDIS		(1 << 31)
+#define MPC52xx_XLB_CFG_SNOOP		(1 << 15)
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+	u32 jtag_id;		/* CDM + 0x00  reg0 read only */
+	u32 rstcfg;		/* CDM + 0x04  reg1 read only */
+	u32 breadcrumb;		/* CDM + 0x08  reg2 */
+
+	u8 mem_clk_sel;		/* CDM + 0x0c  reg3 byte0 */
+	u8 xlb_clk_sel;		/* CDM + 0x0d  reg3 byte1 read only */
+	u8 ipb_clk_sel;		/* CDM + 0x0e  reg3 byte2 */
+	u8 pci_clk_sel;		/* CDM + 0x0f  reg3 byte3 */
+
+	u8 ext_48mhz_en;	/* CDM + 0x10  reg4 byte0 */
+	u8 fd_enable;		/* CDM + 0x11  reg4 byte1 */
+	u16 fd_counters;	/* CDM + 0x12  reg4 byte2,3 */
+
+	u32 clk_enables;	/* CDM + 0x14  reg5 */
+
+	u8 osc_disable;		/* CDM + 0x18  reg6 byte0 */
+	u8 reserved0[3];	/* CDM + 0x19  reg6 byte1,2,3 */
+
+	u8 ccs_sleep_enable;	/* CDM + 0x1c  reg7 byte0 */
+	u8 osc_sleep_enable;	/* CDM + 0x1d  reg7 byte1 */
+	u8 reserved1;		/* CDM + 0x1e  reg7 byte2 */
+	u8 ccs_qreq_test;	/* CDM + 0x1f  reg7 byte3 */
+
+	u8 soft_reset;		/* CDM + 0x20  u8 byte0 */
+	u8 no_ckstp;		/* CDM + 0x21  u8 byte0 */
+	u8 reserved2[2];	/* CDM + 0x22  u8 byte1,2,3 */
+
+	u8 pll_lock;		/* CDM + 0x24  reg9 byte0 */
+	u8 pll_looselock;	/* CDM + 0x25  reg9 byte1 */
+	u8 pll_sm_lockwin;	/* CDM + 0x26  reg9 byte2 */
+	u8 reserved3;		/* CDM + 0x27  reg9 byte3 */
+
+	u16 reserved4;		/* CDM + 0x28  reg10 byte0,1 */
+	u16 mclken_div_psc1;	/* CDM + 0x2a  reg10 byte2,3 */
+
+	u16 reserved5;		/* CDM + 0x2c  reg11 byte0,1 */
+	u16 mclken_div_psc2;	/* CDM + 0x2e  reg11 byte2,3 */
+
+	u16 reserved6;		/* CDM + 0x30  reg12 byte0,1 */
+	u16 mclken_div_psc3;	/* CDM + 0x32  reg12 byte2,3 */
+
+	u16 reserved7;		/* CDM + 0x34  reg13 byte0,1 */
+	u16 mclken_div_psc6;	/* CDM + 0x36  reg13 byte2,3 */
+};
+
+#endif				/* __ASSEMBLY__ */
+
+/* 
========================================================================= */
+/* Prototypes for MPC52xx syslib 
       */
+/* 
========================================================================= */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
+
+static inline struct device_node *find_mpc52xx_picnode(void)
+{
+	return of_find_compatible_node(NULL, "interrupt-controller",
+				       "mpc5200-pic");
+}
+
+	/* Matching of PSC function */
+struct mpc52xx_psc_func {
+	int id;
+	char *func;
+};
+
+extern int mpc52xx_match_psc_function(int psc_idx, const char *func);
+extern struct mpc52xx_psc_func mpc52xx_psc_functions[];
+	/* This array is to be defined in platform file */
+
+#endif				/* __ASSEMBLY__ */
+
+#endif				/* _ASM_POWERPC_MPC52xx_H__ */

[-- Attachment #2: nd.vcf --]
[-- Type: text/x-vcard, Size: 249 bytes --]

begin:vcard
fn:Nicolas DET ( bplan GmbH )
n:DET;Nicolas
org:bplan GmbH
adr:;;;;;;Germany
email;internet:nd@bplan-gmbh.de
title:Software Entwicklung
tel;work:+49 6171 9187 - 31
x-mozilla-html:FALSE
url:http://www.bplan-gmbh.de
version:2.1
end:vcard


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox