LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* "make xconfig" error (2.4.25 devel)
From: HappyPhot @ 2005-12-14  3:41 UTC (permalink / raw)
  To: linuxppc-embedded

Hello,
  I am trying "linuxppc_2_4_devel-2005-10-25-1440".
The "make xconfig" seems not work. ("make menuconfig" is ok)
It shows :
======================================
....
./tkparse < ../arch/ppc/config.in >> kconfig.tk
arch/ppc/8xx_io/Config.in: 312: unknown define_bool value
make[1]: *** [kconfig.tk] Error 1
....
======================================
  Does this version support "make xconfig" ?

thank you,
/HappyPhot

^ permalink raw reply

* [PATCH] powerpc: Experimental support for new G5 Macs (#2)
From: Benjamin Herrenschmidt @ 2005-12-14  2:10 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, linuxppc64-dev

his adds some very basic support for the new machines, including the
Quad G5 (tested), and other new dual core based machines and iMac G5
iSight (untested). This is still experimental !  There is no thermal
control yet, there is no proper handing of MSIs, etc.. but it
boots, I have all 4 cores up on my machine. Compared to the previous
version of this patch, this one adds DART IOMMU support for the U4
chipset and thus should work fine on setups with more than 2Gb of RAM.

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

Index: linux-work/arch/powerpc/platforms/powermac/feature.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/feature.c	2005-12-13 17:51:20.000000000 +1100
+++ linux-work/arch/powerpc/platforms/powermac/feature.c	2005-12-13 18:13:11.000000000 +1100
@@ -101,7 +101,8 @@ static const char *macio_names[] =
 	"Keylargo",
 	"Pangea",
 	"Intrepid",
-	"K2"
+	"K2",
+	"Shasta",
 };
 

@@ -119,7 +120,7 @@ static const char *macio_names[] =
 static struct device_node *uninorth_node;
 static u32 __iomem *uninorth_base;
 static u32 uninorth_rev;
-static int uninorth_u3;
+static int uninorth_maj;
 static void __iomem *u3_ht;
 
 /*
@@ -1399,8 +1400,15 @@ static long g5_fw_enable(struct device_n
 static long g5_mpic_enable(struct device_node *node, long param, long value)
 {
 	unsigned long flags;
+	struct device_node *parent = of_get_parent(node);
+	int is_u3;
 
-	if (node->parent == NULL || strcmp(node->parent->name, "u3"))
+	if (parent == NULL)
+		return 0;
+	is_u3 = strcmp(parent->name, "u3") == 0 ||
+		strcmp(parent->name, "u4") == 0;
+	of_node_put(parent);
+	if (!is_u3)
 		return 0;
 
 	LOCK(flags);
@@ -1464,7 +1472,7 @@ static long g5_i2s_enable(struct device_
 		},
 	};
 
-	if (macio->type != macio_keylargo2 /* && macio->type != macio_shasta*/)
+	if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
 		return -ENODEV;
 	if (strncmp(node->name, "i2s-", 4))
 		return -ENODEV;
@@ -1473,11 +1481,9 @@ static long g5_i2s_enable(struct device_
 	case 0:
 	case 1:
 		break;
-#if 0
 	case 2:
 		if (macio->type == macio_shasta)
 			break;
-#endif
 	default:
 		return -ENODEV;
 	}
@@ -1508,7 +1514,7 @@ static long g5_reset_cpu(struct device_n
 	struct device_node *np;
 
 	macio = &macio_chips[0];
-	if (macio->type != macio_keylargo2)
+	if (macio->type != macio_keylargo2 && macio->type != macio_shasta)
 		return -ENODEV;
 
 	np = find_path_device("/cpus");
@@ -1547,7 +1553,8 @@ static long g5_reset_cpu(struct device_n
  */
 void g5_phy_disable_cpu1(void)
 {
-	UN_OUT(U3_API_PHY_CONFIG_1, 0);
+	if (uninorth_maj == 3)
+		UN_OUT(U3_API_PHY_CONFIG_1, 0);
 }
 #endif /* CONFIG_POWER4 */
 
@@ -2462,6 +2469,14 @@ static struct pmac_mb_def pmac_mb_defs[]
 		PMAC_TYPE_POWERMAC_G5_U3L,	g5_features,
 		0,
 	},
+	{	"PowerMac11,2",			"PowerMac G5 Dual Core",
+		PMAC_TYPE_POWERMAC_G5_U3L,	g5_features,
+		0,
+	},
+	{	"PowerMac12,1",			"iMac G5 (iSight)",
+		PMAC_TYPE_POWERMAC_G5_U3L,	g5_features,
+		0,
+	},
 	{       "RackMac3,1",                   "XServe G5",
 		PMAC_TYPE_XSERVE_G5,		g5_features,
 		0,
@@ -2574,6 +2589,11 @@ static int __init probe_motherboard(void
 		pmac_mb.model_name = "Unknown K2-based";
 		pmac_mb.features = g5_features;
 		break;
+	case macio_shasta:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_SHASTA;
+		pmac_mb.model_name = "Unknown Shasta-based";
+		pmac_mb.features = g5_features;
+		break;
 #endif /* CONFIG_POWER4 */
 	default:
 		return -ENODEV;
@@ -2651,7 +2671,12 @@ static void __init probe_uninorth(void)
 	/* Locate G5 u3 */
 	if (uninorth_node == NULL) {
 		uninorth_node = of_find_node_by_name(NULL, "u3");
-		uninorth_u3 = 1;
+		uninorth_maj = 3;
+	}
+	/* Locate G5 u4 */
+	if (uninorth_node == NULL) {
+		uninorth_node = of_find_node_by_name(NULL, "u4");
+		uninorth_maj = 4;
 	}
 	if (uninorth_node == NULL)
 		return;
@@ -2664,12 +2689,13 @@ static void __init probe_uninorth(void)
 		return;
 	uninorth_base = ioremap(address, 0x40000);
 	uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
-	if (uninorth_u3)
+	if (uninorth_maj == 3 || uninorth_maj == 4)
 		u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000);
 
-	printk(KERN_INFO "Found %s memory controller & host bridge,"
-	       " revision: %d\n", uninorth_u3 ? "U3" : "UniNorth",
-	       uninorth_rev);
+	printk(KERN_INFO "Found %s memory controller & host bridge"
+	       " @ 0x%08x revision: 0x%02x\n", uninorth_maj == 3 ? "U3" :
+	       uninorth_maj == 4 ? "U4" : "UniNorth",
+	       (unsigned int)address, uninorth_rev);
 	printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base);
 
 	/* Set the arbitrer QAck delay according to what Apple does
@@ -2677,7 +2703,8 @@ static void __init probe_uninorth(void)
 	if (uninorth_rev < 0x11) {
 		actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
 		actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
-			UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+			UNI_N_ARB_CTRL_QACK_DELAY) <<
+			UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
 		UN_OUT(UNI_N_ARB_CTRL, actrl);
 	}
 
@@ -2685,7 +2712,8 @@ static void __init probe_uninorth(void)
 	 * revs 1.5 to 2.O and Pangea. Seem to toggle the UniN Maxbus/PCI
 	 * memory timeout
 	 */
-	if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) || uninorth_rev == 0xc0)
+	if ((uninorth_rev >= 0x11 && uninorth_rev <= 0x24) ||
+	    uninorth_rev == 0xc0)
 		UN_OUT(0x2160, UN_IN(0x2160) & 0x00ffffff);
 }
 
@@ -2736,12 +2764,14 @@ static void __init probe_one_macio(const
 		       node->full_name);
 		return;
 	}
-	if (type == macio_keylargo) {
+	if (type == macio_keylargo || type == macio_keylargo2) {
 		u32 *did = (u32 *)get_property(node, "device-id", NULL);
 		if (*did == 0x00000025)
 			type = macio_pangea;
 		if (*did == 0x0000003e)
 			type = macio_intrepid;
+		if (*did == 0x0000004f)
+			type = macio_shasta;
 	}
 	macio_chips[i].of_node	= node;
 	macio_chips[i].type	= type;
@@ -2840,7 +2870,8 @@ set_initial_features(void)
 	}
 
 #ifdef CONFIG_POWER4
-	if (macio_chips[0].type == macio_keylargo2) {
+	if (macio_chips[0].type == macio_keylargo2 ||
+	    macio_chips[0].type == macio_shasta) {
 #ifndef CONFIG_SMP
 		/* On SMP machines running UP, we have the second CPU eating
 		 * bus cycles. We need to take it off the bus. This is done
Index: linux-work/arch/powerpc/platforms/powermac/pic.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/pic.c	2005-12-13 17:51:20.000000000 +1100
+++ linux-work/arch/powerpc/platforms/powermac/pic.c	2005-12-13 18:13:11.000000000 +1100
@@ -524,18 +524,56 @@ static void __init pmac_pic_setup_mpic_n
 #endif	/* defined(CONFIG_XMON) && defined(CONFIG_PPC32) */
 }
 
+static struct mpic * __init pmac_setup_one_mpic(struct device_node *np,
+						int master)
+{
+	unsigned char senses[128];
+	int offset = master ? 0 : 128;
+	int count = master ? 128 : 124;
+	const char *name = master ? " MPIC 1   " : " MPIC 2   ";
+	struct resource r;
+	struct mpic *mpic;
+	unsigned int flags = master ? MPIC_PRIMARY : 0;
+	int rc;
+
+	rc = of_address_to_resource(np, 0, &r);
+	if (rc)
+		return NULL;
+
+	pmac_call_feature(PMAC_FTR_ENABLE_MPIC, np, 0, 0);
+
+	prom_get_irq_senses(senses, offset, offset + count);
+
+	flags |= MPIC_WANTS_RESET;
+	if (get_property(np, "big-endian", NULL))
+		flags |= MPIC_BIG_ENDIAN;
+
+	/* Primary Big Endian means HT interrupts. This is quite dodgy
+	 * but works until I find a better way
+	 */
+	if (master && (flags & MPIC_BIG_ENDIAN))
+		flags |= MPIC_BROKEN_U3;
+
+	mpic = mpic_alloc(r.start, flags, 0, offset, count, master ? 252 : 0,
+			  senses, count, name);
+	if (mpic == NULL)
+		return NULL;
+
+	mpic_init(mpic);
+
+	return mpic;
+ }
+
 static int __init pmac_pic_probe_mpic(void)
 {
 	struct mpic *mpic1, *mpic2;
 	struct device_node *np, *master = NULL, *slave = NULL;
-	unsigned char senses[128];
-	struct resource r;
 
 	/* We can have up to 2 MPICs cascaded */
 	for (np = NULL; (np = of_find_node_by_type(np, "open-pic"))
 		     != NULL;) {
 		if (master == NULL &&
-		    get_property(np, "interrupt-parent", NULL) != NULL)
+		    get_property(np, "interrupts", NULL) == NULL)
 			master = of_node_get(np);
 		else if (slave == NULL)
 			slave = of_node_get(np);
@@ -557,13 +595,8 @@ static int __init pmac_pic_probe_mpic(vo
 	ppc_md.get_irq = mpic_get_irq;
 
 	/* Setup master */
-	BUG_ON(of_address_to_resource(master, 0, &r));
-	pmac_call_feature(PMAC_FTR_ENABLE_MPIC, master, 0, 0);
-	prom_get_irq_senses(senses, 0, 128);
-	mpic1 = mpic_alloc(r.start, MPIC_PRIMARY | MPIC_WANTS_RESET,
-			   0, 0, 128, 252, senses, 128, " OpenPIC  ");
+	mpic1 = pmac_setup_one_mpic(master, 1);
 	BUG_ON(mpic1 == NULL);
-	mpic_init(mpic1);
 
 	/* Install NMI if any */
 	pmac_pic_setup_mpic_nmi(mpic1);
@@ -574,27 +607,12 @@ static int __init pmac_pic_probe_mpic(vo
 	if (slave == NULL || slave->n_intrs < 1)
 		return 0;
 
-	/* Setup slave, failures are non-fatal */
-	if (of_address_to_resource(slave, 0, &r)) {
-		printk(KERN_ERR "Can't get address of MPIC %s\n",
-		       slave->full_name);
-		return 0;
-	}
-	pmac_call_feature(PMAC_FTR_ENABLE_MPIC, slave, 0, 0);
-	prom_get_irq_senses(senses, 128, 128 + 124);
-
-	/* We don't need to set MPIC_BROKEN_U3 here since we don't have
-	 * hypertransport interrupts routed to it, at least not on currently
-	 * supported machines, that may change.
-	 */
-	mpic2 = mpic_alloc(r.start, MPIC_BIG_ENDIAN | MPIC_WANTS_RESET,
-			   0, 128, 124, 0, senses, 124, " U3-MPIC  ");
+	mpic2 = pmac_setup_one_mpic(slave, 0);
 	if (mpic2 == NULL) {
-		printk(KERN_ERR "Can't create slave MPIC %s\n",
-		       slave->full_name);
+		printk(KERN_ERR "Failed to setup slave MPIC\n");
+		of_node_put(slave);
 		return 0;
 	}
-	mpic_init(mpic2);
 	mpic_setup_cascade(slave->intrs[0].line, pmac_u3_cascade, mpic2);
 
 	of_node_put(slave);
Index: linux-work/include/asm-powerpc/pmac_feature.h
===================================================================
--- linux-work.orig/include/asm-powerpc/pmac_feature.h	2005-11-24 17:18:48.000000000 +1100
+++ linux-work/include/asm-powerpc/pmac_feature.h	2005-12-13 18:13:11.000000000 +1100
@@ -121,6 +121,7 @@
 #define PMAC_TYPE_IMAC_G5		0x152	/* iMac G5 */
 #define PMAC_TYPE_XSERVE_G5		0x153	/* Xserve G5 */
 #define PMAC_TYPE_UNKNOWN_K2		0x19f	/* Any other K2 based */
+#define PMAC_TYPE_UNKNOWN_SHASTA       	0x19e	/* Any other Shasta based */
 
 /*
  * Motherboard flags
@@ -341,6 +342,7 @@ enum {
 	macio_pangea,
 	macio_intrepid,
 	macio_keylargo2,
+	macio_shasta,
 };
 
 struct macio_chip
Index: linux-work/arch/powerpc/Kconfig
===================================================================
--- linux-work.orig/arch/powerpc/Kconfig	2005-12-13 15:03:21.000000000 +1100
+++ linux-work/arch/powerpc/Kconfig	2005-12-13 18:13:11.000000000 +1100
@@ -300,6 +300,7 @@ config PPC_PMAC64
 	bool
 	depends on PPC_PMAC && POWER4
 	select U3_DART
+	select MPIC_BROKEN_U3
 	select GENERIC_TBSYNC
 	default y
 
Index: linux-work/arch/powerpc/kernel/prom.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/prom.c	2005-12-13 17:51:20.000000000 +1100
+++ linux-work/arch/powerpc/kernel/prom.c	2005-12-13 18:13:11.000000000 +1100
@@ -298,6 +298,16 @@ static int __devinit finish_node_interru
 	int i, j, n, sense;
 	unsigned int *irq, virq;
 	struct device_node *ic;
+	int trace = 0;
+
+	//#define TRACE(fmt...) do { if (trace) { printk(fmt); mdelay(1000); } } while(0)
+#define TRACE(fmt...)
+
+	if (!strcmp(np->name, "smu-doorbell"))
+		trace = 1;
+
+	TRACE("Finishing SMU doorbell ! num_interrupt_controllers = %d\n",
+	      num_interrupt_controllers);
 
 	if (num_interrupt_controllers == 0) {
 		/*
@@ -332,11 +342,12 @@ static int __devinit finish_node_interru
 	}
 
 	ints = (unsigned int *) get_property(np, "interrupts", &intlen);
+	TRACE("ints=%p, intlen=%d\n", ints, intlen);
 	if (ints == NULL)
 		return 0;
 	intrcells = prom_n_intr_cells(np);
 	intlen /= intrcells * sizeof(unsigned int);
-
+	TRACE("intrcells=%d, new intlen=%d\n", intrcells, intlen);
 	np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start);
 	if (!np->intrs)
 		return -ENOMEM;
@@ -347,6 +358,7 @@ static int __devinit finish_node_interru
 	intrcount = 0;
 	for (i = 0; i < intlen; ++i, ints += intrcells) {
 		n = map_interrupt(&irq, &ic, np, ints, intrcells);
+		TRACE("map, irq=%d, ic=%p, n=%d\n", irq, ic, n);
 		if (n <= 0)
 			continue;
 
@@ -357,6 +369,7 @@ static int __devinit finish_node_interru
 			np->intrs[intrcount].sense = map_isa_senses[sense];
 		} else {
 			virq = virt_irq_create_mapping(irq[0]);
+			TRACE("virq=%d\n", virq);
 #ifdef CONFIG_PPC64
 			if (virq == NO_IRQ) {
 				printk(KERN_CRIT "Could not allocate interrupt"
@@ -366,6 +379,12 @@ static int __devinit finish_node_interru
 #endif
 			np->intrs[intrcount].line = irq_offset_up(virq);
 			sense = (n > 1)? (irq[1] & 3): 1;
+
+			/* Apple uses bits in there in a different way, let's
+			 * only keep the real sense bit on macs
+			 */
+			if (_machine == PLATFORM_POWERMAC)
+				sense &= 0x1;
 			np->intrs[intrcount].sense = map_mpic_senses[sense];
 		}
 
@@ -375,12 +394,13 @@ static int __devinit finish_node_interru
 			char *name = get_property(ic->parent, "name", NULL);
 			if (name && !strcmp(name, "u3"))
 				np->intrs[intrcount].line += 128;
-			else if (!(name && !strcmp(name, "mac-io")))
+			else if (!(name && (!strcmp(name, "mac-io") ||
+					    !strcmp(name, "u4"))))
 				/* ignore other cascaded controllers, such as
 				   the k2-sata-root */
 				break;
 		}
-#endif
+#endif /* CONFIG_PPC64 */
 		if (n > 2) {
 			printk("hmmm, got %d intr cells for %s:", n,
 			       np->full_name);
Index: linux-work/arch/powerpc/platforms/powermac/pci.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/pci.c	2005-12-13 17:51:20.000000000 +1100
+++ linux-work/arch/powerpc/platforms/powermac/pci.c	2005-12-13 18:13:12.000000000 +1100
@@ -1,7 +1,7 @@
 /*
  * Support for PCI bridges found on Power Macintoshes.
  *
- * Copyright (C) 2003 Benjamin Herrenschmuidt (benh@kernel.crashing.org)
+ * Copyright (C) 2003-2005 Benjamin Herrenschmuidt (benh@kernel.crashing.org)
  * Copyright (C) 1997 Paul Mackerras (paulus@samba.org)
  *
  * This program is free software; you can redistribute it and/or
@@ -25,7 +25,7 @@
 #include <asm/pmac_feature.h>
 #include <asm/grackle.h>
 #ifdef CONFIG_PPC64
-#include <asm/iommu.h>
+//#include <asm/iommu.h>
 #include <asm/ppc-pci.h>
 #endif
 
@@ -44,6 +44,7 @@ static int add_bridge(struct device_node
 static int has_uninorth;
 #ifdef CONFIG_PPC64
 static struct pci_controller *u3_agp;
+static struct pci_controller *u4_pcie;
 static struct pci_controller *u3_ht;
 #endif /* CONFIG_PPC64 */
 
@@ -97,11 +98,8 @@ static void __init fixup_bus_range(struc
 
 	/* Lookup the "bus-range" property for the hose */
 	bus_range = (int *) get_property(bridge, "bus-range", &len);
-	if (bus_range == NULL || len < 2 * sizeof(int)) {
-		printk(KERN_WARNING "Can't get bus-range for %s\n",
-			       bridge->full_name);
+	if (bus_range == NULL || len < 2 * sizeof(int))
 		return;
-	}
 	bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
 }
 
@@ -128,14 +126,14 @@ static void __init fixup_bus_range(struc
  */
 
 #define MACRISC_CFA0(devfn, off)	\
-	((1 << (unsigned long)PCI_SLOT(dev_fn)) \
-	| (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
-	| (((unsigned long)(off)) & 0xFCUL))
+	((1 << (unsigned int)PCI_SLOT(dev_fn)) \
+	| (((unsigned int)PCI_FUNC(dev_fn)) << 8) \
+	| (((unsigned int)(off)) & 0xFCUL))
 
 #define MACRISC_CFA1(bus, devfn, off)	\
-	((((unsigned long)(bus)) << 16) \
-	|(((unsigned long)(devfn)) << 8) \
-	|(((unsigned long)(off)) & 0xFCUL) \
+	((((unsigned int)(bus)) << 16) \
+	|(((unsigned int)(devfn)) << 8) \
+	|(((unsigned int)(off)) & 0xFCUL) \
 	|1UL)
 
 static unsigned long macrisc_cfg_access(struct pci_controller* hose,
@@ -168,7 +166,8 @@ static int macrisc_read_config(struct pc
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-
+	if (offset >= 0x100)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
 	addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -199,7 +198,8 @@ static int macrisc_write_config(struct p
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-
+	if (offset >= 0x100)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
 	addr = macrisc_cfg_access(hose, bus->number, devfn, offset);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -234,12 +234,13 @@ static struct pci_ops macrisc_pci_ops =
 /*
  * Verify that a specific (bus, dev_fn) exists on chaos
  */
-static int
-chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
+static int chaos_validate_dev(struct pci_bus *bus, int devfn, int offset)
 {
 	struct device_node *np;
 	u32 *vendor, *device;
 
+	if (offset >= 0x100)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
 	np = pci_busdev_to_OF_node(bus, devfn);
 	if (np == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -341,10 +342,10 @@ static int u3_ht_skip_device(struct pci_
 }
 
 #define U3_HT_CFA0(devfn, off)		\
-		((((unsigned long)devfn) << 8) | offset)
+		((((unsigned int)devfn) << 8) | offset)
 #define U3_HT_CFA1(bus, devfn, off)	\
 		(U3_HT_CFA0(devfn, off) \
-		+ (((unsigned long)bus) << 16) \
+		+ (((unsigned int)bus) << 16) \
 		+ 0x01000000UL)
 
 static unsigned long u3_ht_cfg_access(struct pci_controller* hose,
@@ -370,7 +371,8 @@ static int u3_ht_read_config(struct pci_
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-
+	if (offset >= 0x100)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
 	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -419,7 +421,8 @@ static int u3_ht_write_config(struct pci
 	hose = pci_bus_to_host(bus);
 	if (hose == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-
+	if (offset >= 0x100)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
 	addr = u3_ht_cfg_access(hose, bus->number, devfn, offset);
 	if (!addr)
 		return PCIBIOS_DEVICE_NOT_FOUND;
@@ -459,6 +462,112 @@ static struct pci_ops u3_ht_pci_ops =
 	u3_ht_read_config,
 	u3_ht_write_config
 };
+
+#define U4_PCIE_CFA0(devfn, off)	\
+	((1 << ((unsigned int)PCI_SLOT(dev_fn)))	\
+	 | (((unsigned int)PCI_FUNC(dev_fn)) << 8)	\
+	 | ((((unsigned int)(off)) >> 8) << 28) \
+	 | (((unsigned int)(off)) & 0xfcU))
+
+#define U4_PCIE_CFA1(bus, devfn, off)	\
+	((((unsigned int)(bus)) << 16) \
+	 |(((unsigned int)(devfn)) << 8)	\
+	 | ((((unsigned int)(off)) >> 8) << 28) \
+	 |(((unsigned int)(off)) & 0xfcU)	\
+	 |1UL)
+
+static unsigned long u4_pcie_cfg_access(struct pci_controller* hose,
+					u8 bus, u8 dev_fn, int offset)
+{
+	unsigned int caddr;
+
+	if (bus == hose->first_busno) {
+		caddr = U4_PCIE_CFA0(dev_fn, offset);
+	} else
+		caddr = U4_PCIE_CFA1(bus, dev_fn, offset);
+
+	/* Uninorth will return garbage if we don't read back the value ! */
+	do {
+		out_le32(hose->cfg_addr, caddr);
+	} while (in_le32(hose->cfg_addr) != caddr);
+
+	offset &= 0x03;
+	return ((unsigned long)hose->cfg_data) + offset;
+}
+
+static int u4_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
+			       int offset, int len, u32 *val)
+{
+	struct pci_controller *hose;
+	unsigned long addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (offset >= 0x1000)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
+	addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		*val = in_8((u8 *)addr);
+		break;
+	case 2:
+		*val = in_le16((u16 *)addr);
+		break;
+	default:
+		*val = in_le32((u32 *)addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int u4_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
+				int offset, int len, u32 val)
+{
+	struct pci_controller *hose;
+	unsigned long addr;
+
+	hose = pci_bus_to_host(bus);
+	if (hose == NULL)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (offset >= 0x1000)
+		return  PCIBIOS_BAD_REGISTER_NUMBER;
+	addr = u4_pcie_cfg_access(hose, bus->number, devfn, offset);
+	if (!addr)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	/*
+	 * Note: the caller has already checked that offset is
+	 * suitably aligned and that len is 1, 2 or 4.
+	 */
+	switch (len) {
+	case 1:
+		out_8((u8 *)addr, val);
+		(void) in_8((u8 *)addr);
+		break;
+	case 2:
+		out_le16((u16 *)addr, val);
+		(void) in_le16((u16 *)addr);
+		break;
+	default:
+		out_le32((u32 *)addr, val);
+		(void) in_le32((u32 *)addr);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops u4_pcie_pci_ops =
+{
+	u4_pcie_read_config,
+	u4_pcie_write_config
+};
+
 #endif /* CONFIG_PPC64 */
 
 #ifdef CONFIG_PPC32
@@ -628,15 +737,36 @@ static void __init setup_u3_agp(struct p
 	hose->ops = &macrisc_pci_ops;
 	hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
 	hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
-
 	u3_agp = hose;
 }
 
+static void __init setup_u4_pcie(struct pci_controller* hose)
+{
+	/* We currently only implement the "non-atomic" config space, to
+	 * be optimised later.
+	 */
+	hose->ops = &u4_pcie_pci_ops;
+	hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000);
+	hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000);
+
+	/* The bus contains a bridge from root -> device, we need to
+	 * make it visible on bus 0 so that we pick the right type
+	 * of config cycles. If we didn't, we would have to force all
+	 * config cycles to be type 1. So we override the "bus-range"
+	 * property here
+	 */
+	hose->first_busno = 0x00;
+	hose->last_busno = 0xff;
+	u4_pcie = hose;
+}
+
 static void __init setup_u3_ht(struct pci_controller* hose)
 {
 	struct device_node *np = (struct device_node *)hose->arch_data;
+	struct pci_controller *other = NULL;
 	int i, cur;
 
+
 	hose->ops = &u3_ht_pci_ops;
 
 	/* We hard code the address because of the different size of
@@ -670,11 +800,20 @@ static void __init setup_u3_ht(struct pc
 
 	u3_ht = hose;
 
-	if (u3_agp == NULL) {
-		DBG("U3 has no AGP, using full resource range\n");
+	if (u3_agp != NULL)
+		other = u3_agp;
+	else if (u4_pcie != NULL)
+		other = u4_pcie;
+
+	if (other == NULL) {
+		DBG("U3/4 has no AGP/PCIE, using full resource range\n");
 		return;
 	}
 
+	/* Fixup bus range vs. PCIE */
+	if (u4_pcie)
+		hose->last_busno = u4_pcie->first_busno - 1;
+
 	/* We "remove" the AGP resources from the resources allocated to HT,
 	 * that is we create "holes". However, that code does assumptions
 	 * that so far happen to be true (cross fingers...), typically that
@@ -682,7 +821,7 @@ static void __init setup_u3_ht(struct pc
 	 */
 	cur = 0;
 	for (i=0; i<3; i++) {
-		struct resource *res = &u3_agp->mem_resources[i];
+		struct resource *res = &other->mem_resources[i];
 		if (res->flags != IORESOURCE_MEM)
 			continue;
 		/* We don't care about "fine" resources */
@@ -777,9 +916,13 @@ static int __init add_bridge(struct devi
 		setup_u3_ht(hose);
 		disp_name = "U3-HT";
 		primary = 1;
+	} else if (device_is_compatible(dev, "u4-pcie")) {
+		setup_u4_pcie(hose);
+		disp_name = "U4-PCIE";
+		primary = 0;
 	}
-	printk(KERN_INFO "Found %s PCI host bridge.  Firmware bus number: %d->%d\n",
-		disp_name, hose->first_busno, hose->last_busno);
+	printk(KERN_INFO "Found %s PCI host bridge.  Firmware bus number:"
+	       " %d->%d\n", disp_name, hose->first_busno, hose->last_busno);
 #endif /* CONFIG_PPC64 */
 
 	/* 32 bits only bridges */
@@ -900,6 +1043,8 @@ void __init pmac_pci_init(void)
 		pci_setup_phb_io(u3_ht, 1);
 	if (u3_agp)
 		pci_setup_phb_io(u3_agp, 0);
+	if (u4_pcie)
+		pci_setup_phb_io(u4_pcie, 0);
 
 	/*
 	 * On ppc64, fixup the IO resources on our host bridges as
@@ -912,7 +1057,8 @@ void __init pmac_pci_init(void)
 
 	/* Fixup the PCI<->OF mapping for U3 AGP due to bus renumbering. We
 	 * assume there is no P2P bridge on the AGP bus, which should be a
-	 * safe assumptions hopefully.
+	 * safe assumptions for now. We should do something better in the
+	 * future though
 	 */
 	if (u3_agp) {
 		struct device_node *np = u3_agp->arch_data;
@@ -920,7 +1066,6 @@ void __init pmac_pci_init(void)
 		for (np = np->child; np; np = np->sibling)
 			PCI_DN(np)->busno = 0xf0;
 	}
-
 	/* pmac_check_ht_link(); */
 
 	/* Tell pci.c to not use the common resource allocation mechanism */
@@ -1127,7 +1272,8 @@ void pmac_pci_fixup_pciata(struct pci_de
  good:
 	pci_read_config_byte(dev, PCI_CLASS_PROG, &progif);
 	if ((progif & 5) != 5) {
-		printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n", pci_name(dev));
+		printk(KERN_INFO "Forcing PCI IDE into native mode: %s\n",
+		       pci_name(dev));
 		(void) pci_write_config_byte(dev, PCI_CLASS_PROG, progif|5);
 		if (pci_read_config_byte(dev, PCI_CLASS_PROG, &progif) ||
 		    (progif & 5) != 5)
@@ -1153,7 +1299,8 @@ static void fixup_k2_sata(struct pci_dev
 		for (i = 0; i < 6; i++) {
 			dev->resource[i].start = dev->resource[i].end = 0;
 			dev->resource[i].flags = 0;
-			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i,
+					       0);
 		}
 	} else {
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
@@ -1162,7 +1309,8 @@ static void fixup_k2_sata(struct pci_dev
 		for (i = 0; i < 5; i++) {
 			dev->resource[i].start = dev->resource[i].end = 0;
 			dev->resource[i].flags = 0;
-			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0);
+			pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i,
+					       0);
 		}
 	}
 }
Index: linux-work/arch/powerpc/sysdev/mpic.c
===================================================================
--- linux-work.orig/arch/powerpc/sysdev/mpic.c	2005-12-13 18:02:03.000000000 +1100
+++ linux-work/arch/powerpc/sysdev/mpic.c	2005-12-13 18:13:12.000000000 +1100
@@ -13,6 +13,9 @@
  */
 
 #undef DEBUG
+#undef DEBUG_IPI
+#undef DEBUG_IRQ
+#undef DEBUG_LOW
 
 #include <linux/config.h>
 #include <linux/types.h>
@@ -168,35 +171,86 @@ static void __init mpic_test_broken_ipi(
 /* Test if an interrupt is sourced from HyperTransport (used on broken U3s)
  * to force the edge setting on the MPIC and do the ack workaround.
  */
-static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source_no)
+static inline int mpic_is_ht_interrupt(struct mpic *mpic, unsigned int source)
 {
-	if (source_no >= 128 || !mpic->fixups)
+	if (source >= 128 || !mpic->fixups)
 		return 0;
-	return mpic->fixups[source_no].base != NULL;
+	return mpic->fixups[source].base != NULL;
 }
 

-static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
+static inline void mpic_ht_end_irq(struct mpic *mpic, unsigned int source)
 {
-	struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
+	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
 
-	spin_lock(&mpic->fixup_lock);
-	writeb(0x11 + 2 * fixup->irq, fixup->base + 2);
-	writel(fixup->data, fixup->base + 4);
-	spin_unlock(&mpic->fixup_lock);
+	if (fixup->applebase) {
+		unsigned int soff = (fixup->index >> 3) & ~3;
+		unsigned int mask = 1U << (fixup->index & 0x1f);
+		writel(mask, fixup->applebase + soff);
+	} else {
+		spin_lock(&mpic->fixup_lock);
+		writeb(0x11 + 2 * fixup->index, fixup->base + 2);
+		writel(fixup->data, fixup->base + 4);
+		spin_unlock(&mpic->fixup_lock);
+	}
 }
 
+static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
+				      unsigned int irqflags)
+{
+	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+	unsigned long flags;
+	u32 tmp;
+
+	if (fixup->base == NULL)
+		return;
+
+	DBG("startup_ht_interrupt(%u, %u) index: %d\n",
+	    source, irqflags, fixup->index);
+	spin_lock_irqsave(&mpic->fixup_lock, flags);
+	/* Enable and configure */
+	writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+	tmp = readl(fixup->base + 4);
+	tmp &= ~(0x23U);
+	if (irqflags & IRQ_LEVEL)
+		tmp |= 0x22;
+	writel(tmp, fixup->base + 4);
+	spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+}
+
+static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
+				       unsigned int irqflags)
+{
+	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
+	unsigned long flags;
+	u32 tmp;
+
+	if (fixup->base == NULL)
+		return;
+
+	DBG("shutdown_ht_interrupt(%u, %u)\n", source, irqflags);
+
+	/* Disable */
+	spin_lock_irqsave(&mpic->fixup_lock, flags);
+	writeb(0x10 + 2 * fixup->index, fixup->base + 2);
+	tmp = readl(fixup->base + 4);
+	tmp &= ~1U;
+	writel(tmp, fixup->base + 4);
+	spin_unlock_irqrestore(&mpic->fixup_lock, flags);
+}
 
-static void __init mpic_scan_ioapic(struct mpic *mpic, u8 __iomem *devbase)
+static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase,
+				    unsigned int devfn, u32 vdid)
 {
 	int i, irq, n;
+	u8 __iomem *base;
 	u32 tmp;
 	u8 pos;
 
-	for (pos = readb(devbase + 0x34); pos; pos = readb(devbase + pos + 1)) {
-		u8 id = readb(devbase + pos);
-
-		if (id == 0x08) {
+	for (pos = readb(devbase + PCI_CAPABILITY_LIST); pos != 0;
+	     pos = readb(devbase + pos + PCI_CAP_LIST_NEXT)) {
+		u8 id = readb(devbase + pos + PCI_CAP_LIST_ID);
+		if (id == PCI_CAP_ID_HT_IRQCONF) {
 			id = readb(devbase + pos + 3);
 			if (id == 0x80)
 				break;
@@ -205,33 +259,41 @@ static void __init mpic_scan_ioapic(stru
 	if (pos == 0)
 		return;
 
-	printk(KERN_INFO "mpic:    - Workarounds @ %p, pos = 0x%02x\n", devbase, pos);
-
-	devbase += pos;
-
-	writeb(0x01, devbase + 2);
-	n = (readl(devbase + 4) >> 16) & 0xff;
+	base = devbase + pos;
+	writeb(0x01, base + 2);
+	n = (readl(base + 4) >> 16) & 0xff;
+
+	printk(KERN_INFO "mpic:   - HT:%02x.%x [0x%02x] vendor %04x device %04x"
+	       " has %d irqs\n",
+	       devfn >> 3, devfn & 0x7, pos, vdid & 0xffff, vdid >> 16, n + 1);
 
 	for (i = 0; i <= n; i++) {
-		writeb(0x10 + 2 * i, devbase + 2);
-		tmp = readl(devbase + 4);
-		if ((tmp & 0x21) != 0x20)
-			continue;
+		writeb(0x10 + 2 * i, base + 2);
+		tmp = readl(base + 4);
 		irq = (tmp >> 16) & 0xff;
-		mpic->fixups[irq].irq = i;
-		mpic->fixups[irq].base = devbase;
-		writeb(0x11 + 2 * i, devbase + 2);
-		mpic->fixups[irq].data = readl(devbase + 4) | 0x80000000;
+		DBG("HT PIC index 0x%x, irq 0x%x, tmp: %08x\n", i, irq, tmp);
+		/* mask it , will be unmasked later */
+		tmp |= 0x1;
+		writel(tmp, base + 4);
+		mpic->fixups[irq].index = i;
+		mpic->fixups[irq].base = base;
+		/* Apple HT PIC has a non-standard way of doing EOIs */
+		if ((vdid & 0xffff) == 0x106b)
+			mpic->fixups[irq].applebase = devbase + 0x60;
+		else
+			mpic->fixups[irq].applebase = NULL;
+		writeb(0x11 + 2 * i, base + 2);
+		mpic->fixups[irq].data = readl(base + 4) | 0x80000000;
 	}
 }
  
 
-static void __init mpic_scan_ioapics(struct mpic *mpic)
+static void __init mpic_scan_ht_pics(struct mpic *mpic)
 {
 	unsigned int devfn;
 	u8 __iomem *cfgspace;
 
-	printk(KERN_INFO "mpic: Setting up IO-APICs workarounds for U3\n");
+	printk(KERN_INFO "mpic: Setting up HT PICs workarounds for U3/U4\n");
 
 	/* Allocate fixups array */
 	mpic->fixups = alloc_bootmem(128 * sizeof(struct mpic_irq_fixup));
@@ -247,13 +309,14 @@ static void __init mpic_scan_ioapics(str
 	cfgspace = ioremap(0xf2000000, 0x10000);
 	BUG_ON(cfgspace == NULL);
 
-	/* Now we scan all slots. We do a very quick scan, we read the header type,
-	 * vendor ID and device ID only, that's plenty enough
+	/* Now we scan all slots. We do a very quick scan, we read the header
+	 * type, vendor ID and device ID only, that's plenty enough
 	 */
 	for (devfn = 0; devfn < 0x100; devfn++) {
 		u8 __iomem *devbase = cfgspace + (devfn << 8);
 		u8 hdr_type = readb(devbase + PCI_HEADER_TYPE);
 		u32 l = readl(devbase + PCI_VENDOR_ID);
+		u16 s;
 
 		DBG("devfn %x, l: %x\n", devfn, l);
 
@@ -261,8 +324,12 @@ static void __init mpic_scan_ioapics(str
 		if (l == 0xffffffff || l == 0x00000000 ||
 		    l == 0x0000ffff || l == 0xffff0000)
 			goto next;
+		/* Check if is supports capability lists */
+		s = readw(devbase + PCI_STATUS);
+		if (!(s & PCI_STATUS_CAP_LIST))
+			goto next;
 
-		mpic_scan_ioapic(mpic, devbase);
+		mpic_scan_ht_pic(mpic, devbase, devfn, l);
 
 	next:
 		/* next device, if function 0 */
@@ -363,6 +430,31 @@ static void mpic_enable_irq(unsigned int
 			break;
 		}
 	} while(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK);	
+
+#ifdef CONFIG_MPIC_BROKEN_U3
+	if (mpic->flags & MPIC_BROKEN_U3) {
+		unsigned int src = irq - mpic->irq_offset;
+		if (mpic_is_ht_interrupt(mpic, src) &&
+		    (irq_desc[irq].status & IRQ_LEVEL))
+			mpic_ht_end_irq(mpic, src);
+	}
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+}
+
+static unsigned int mpic_startup_irq(unsigned int irq)
+{
+#ifdef CONFIG_MPIC_BROKEN_U3
+	struct mpic *mpic = mpic_from_irq(irq);
+	unsigned int src = irq - mpic->irq_offset;
+
+	if (mpic_is_ht_interrupt(mpic, src))
+		mpic_startup_ht_interrupt(mpic, src, irq_desc[irq].status);
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+	mpic_enable_irq(irq);
+
+	return 0;
 }
 
 static void mpic_disable_irq(unsigned int irq)
@@ -386,12 +478,27 @@ static void mpic_disable_irq(unsigned in
 	} while(!(mpic_irq_read(src, MPIC_IRQ_VECTOR_PRI) & MPIC_VECPRI_MASK));
 }
 
+static void mpic_shutdown_irq(unsigned int irq)
+{
+#ifdef CONFIG_MPIC_BROKEN_U3
+	struct mpic *mpic = mpic_from_irq(irq);
+	unsigned int src = irq - mpic->irq_offset;
+
+	if (mpic_is_ht_interrupt(mpic, src))
+		mpic_shutdown_ht_interrupt(mpic, src, irq_desc[irq].status);
+
+#endif /* CONFIG_MPIC_BROKEN_U3 */
+
+	mpic_disable_irq(irq);
+}
+
 static void mpic_end_irq(unsigned int irq)
 {
 	struct mpic *mpic = mpic_from_irq(irq);
 
+#ifdef DEBUG_IRQ
 	DBG("%s: end_irq: %d\n", mpic->name, irq);
-
+#endif
 	/* We always EOI on end_irq() even for edge interrupts since that
 	 * should only lower the priority, the MPIC should have properly
 	 * latched another edge interrupt coming in anyway
@@ -400,8 +507,9 @@ static void mpic_end_irq(unsigned int ir
 #ifdef CONFIG_MPIC_BROKEN_U3
 	if (mpic->flags & MPIC_BROKEN_U3) {
 		unsigned int src = irq - mpic->irq_offset;
-		if (mpic_is_ht_interrupt(mpic, src))
-			mpic_apic_end_irq(mpic, src);
+		if (mpic_is_ht_interrupt(mpic, src) &&
+		    (irq_desc[irq].status & IRQ_LEVEL))
+			mpic_ht_end_irq(mpic, src);
 	}
 #endif /* CONFIG_MPIC_BROKEN_U3 */
 
@@ -482,6 +590,8 @@ struct mpic * __init mpic_alloc(unsigned
 	mpic->name = name;
 
 	mpic->hc_irq.typename = name;
+	mpic->hc_irq.startup = mpic_startup_irq;
+	mpic->hc_irq.shutdown = mpic_shutdown_irq;
 	mpic->hc_irq.enable = mpic_enable_irq;
 	mpic->hc_irq.disable = mpic_disable_irq;
 	mpic->hc_irq.end = mpic_end_irq;
@@ -650,10 +760,10 @@ void __init mpic_init(struct mpic *mpic)
 		mpic->irq_count = mpic->num_sources;
 
 #ifdef CONFIG_MPIC_BROKEN_U3
-	/* Do the ioapic fixups on U3 broken mpic */
+	/* Do the HT PIC fixups on U3 broken mpic */
 	DBG("MPIC flags: %x\n", mpic->flags);
 	if ((mpic->flags & MPIC_BROKEN_U3) && (mpic->flags & MPIC_PRIMARY))
-		mpic_scan_ioapics(mpic);
+		mpic_scan_ht_pics(mpic);
 #endif /* CONFIG_MPIC_BROKEN_U3 */
 
 	for (i = 0; i < mpic->num_sources; i++) {
@@ -840,7 +950,9 @@ void mpic_send_ipi(unsigned int ipi_no, 
 
 	BUG_ON(mpic == NULL);
 
+#ifdef DEBUG_IPI
 	DBG("%s: send_ipi(ipi_no: %d)\n", mpic->name, ipi_no);
+#endif
 
 	mpic_cpu_write(MPIC_CPU_IPI_DISPATCH_0 + ipi_no * 0x10,
 		       mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
@@ -851,19 +963,28 @@ int mpic_get_one_irq(struct mpic *mpic, 
 	u32 irq;
 
 	irq = mpic_cpu_read(MPIC_CPU_INTACK) & MPIC_VECPRI_VECTOR_MASK;
+#ifdef DEBUG_LOW
 	DBG("%s: get_one_irq(): %d\n", mpic->name, irq);
-
+#endif
 	if (mpic->cascade && irq == mpic->cascade_vec) {
+#ifdef DEBUG_LOW
 		DBG("%s: cascading ...\n", mpic->name);
+#endif
 		irq = mpic->cascade(regs, mpic->cascade_data);
 		mpic_eoi(mpic);
 		return irq;
 	}
 	if (unlikely(irq == MPIC_VEC_SPURRIOUS))
 		return -1;
-	if (irq < MPIC_VEC_IPI_0) 
+	if (irq < MPIC_VEC_IPI_0) {
+#ifdef DEBUG_IRQ
+		DBG("%s: irq %d\n", mpic->name, irq + mpic->irq_offset);
+#endif
 		return irq + mpic->irq_offset;
+	}
+#ifdef DEBUG_IPI
        	DBG("%s: ipi %d !\n", mpic->name, irq - MPIC_VEC_IPI_0);
+#endif
 	return irq - MPIC_VEC_IPI_0 + mpic->ipi_offset;
 }
 
Index: linux-work/include/linux/pci_regs.h
===================================================================
--- linux-work.orig/include/linux/pci_regs.h	2005-11-24 17:18:49.000000000 +1100
+++ linux-work/include/linux/pci_regs.h	2005-12-13 18:13:12.000000000 +1100
@@ -196,6 +196,7 @@
 #define  PCI_CAP_ID_MSI		0x05	/* Message Signalled Interrupts */
 #define  PCI_CAP_ID_CHSWP	0x06	/* CompactPCI HotSwap */
 #define  PCI_CAP_ID_PCIX	0x07	/* PCI-X */
+#define  PCI_CAP_ID_HT_IRQCONF	0x08	/* HyperTransport IRQ Configuration */
 #define  PCI_CAP_ID_SHPC 	0x0C	/* PCI Standard Hot-Plug Controller */
 #define  PCI_CAP_ID_EXP 	0x10	/* PCI Express */
 #define  PCI_CAP_ID_MSIX	0x11	/* MSI-X */
Index: linux-work/arch/powerpc/kernel/pci_64.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/pci_64.c	2005-12-13 17:51:20.000000000 +1100
+++ linux-work/arch/powerpc/kernel/pci_64.c	2005-12-13 18:13:12.000000000 +1100
@@ -34,7 +34,7 @@
 
 #ifdef DEBUG
 #include <asm/udbg.h>
-#define DBG(fmt...) udbg_printf(fmt)
+#define DBG(fmt...) printk(fmt)
 #else
 #define DBG(fmt...)
 #endif
@@ -323,6 +323,7 @@ static void pci_parse_of_addrs(struct de
 	addrs = (u32 *) get_property(node, "assigned-addresses", &proplen);
 	if (!addrs)
 		return;
+	DBG("    parse addresses (%d bytes) @ %p\n", proplen, addrs);
 	for (; proplen >= 20; proplen -= 20, addrs += 5) {
 		flags = pci_parse_of_flags(addrs[0]);
 		if (!flags)
@@ -332,6 +333,9 @@ static void pci_parse_of_addrs(struct de
 		if (!size)
 			continue;
 		i = addrs[0] & 0xff;
+		DBG("  base: %llx, size: %llx, i: %x\n",
+		    (unsigned long long)base, (unsigned long long)size, i);
+
 		if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) {
 			res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2];
 		} else if (i == dev->rom_base_reg) {
@@ -362,6 +366,8 @@ struct pci_dev *of_create_pci_dev(struct
 	if (type == NULL)
 		type = "";
 
+	DBG("    create device, devfn: %x, type: %s\n", devfn, type);
+
 	memset(dev, 0, sizeof(struct pci_dev));
 	dev->bus = bus;
 	dev->sysdata = node;
@@ -375,12 +381,14 @@ struct pci_dev *of_create_pci_dev(struct
 	dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0);
 	dev->subsystem_device = get_int_prop(node, "subsystem-id", 0);
 
-	dev->cfg_size = 256; /*pci_cfg_space_size(dev);*/
+	dev->cfg_size = pci_cfg_space_size(dev);
 
 	sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
 		dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn));
 	dev->class = get_int_prop(node, "class-code", 0);
 
+	DBG("    class: 0x%x\n", dev->class);
+
 	dev->current_state = 4;		/* unknown power state */
 
 	if (!strcmp(type, "pci")) {
@@ -402,6 +410,8 @@ struct pci_dev *of_create_pci_dev(struct
 
 	pci_parse_of_addrs(node, dev);
 
+	DBG("    adding to system ...\n");
+
 	pci_device_add(dev, bus);
 
 	/* XXX pci_scan_msi_device(dev); */
@@ -418,15 +428,21 @@ void __devinit of_scan_bus(struct device
 	int reglen, devfn;
 	struct pci_dev *dev;
 
+	DBG("of_scan_bus(%s) bus no %d... \n", node->full_name, bus->number);
+
 	while ((child = of_get_next_child(node, child)) != NULL) {
+		DBG("  * %s\n", child->full_name);
 		reg = (u32 *) get_property(child, "reg", &reglen);
 		if (reg == NULL || reglen < 20)
 			continue;
 		devfn = (reg[0] >> 8) & 0xff;
+
 		/* create a new pci_dev for this device */
 		dev = of_create_pci_dev(child, bus, devfn);
 		if (!dev)
 			continue;
+		DBG("dev header type: %x\n", dev->hdr_type);
+
 		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
 		    dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
 			of_scan_pci_bridge(child, dev);
@@ -446,16 +462,18 @@ void __devinit of_scan_pci_bridge(struct
 	unsigned int flags;
 	u64 size;
 
+	DBG("of_scan_pci_bridge(%s)\n", node->full_name);
+
 	/* parse bus-range property */
 	busrange = (u32 *) get_property(node, "bus-range", &len);
 	if (busrange == NULL || len != 8) {
-		printk(KERN_ERR "Can't get bus-range for PCI-PCI bridge %s\n",
+		printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n",
 		       node->full_name);
 		return;
 	}
 	ranges = (u32 *) get_property(node, "ranges", &len);
 	if (ranges == NULL) {
-		printk(KERN_ERR "Can't get ranges for PCI-PCI bridge %s\n",
+		printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n",
 		       node->full_name);
 		return;
 	}
@@ -509,10 +527,13 @@ void __devinit of_scan_pci_bridge(struct
 	}
 	sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus),
 		bus->number);
+	DBG("    bus name: %s\n", bus->name);
 
 	mode = PCI_PROBE_NORMAL;
 	if (ppc_md.pci_probe_mode)
 		mode = ppc_md.pci_probe_mode(bus);
+	DBG("    probe mode: %d\n", mode);
+
 	if (mode == PCI_PROBE_DEVTREE)
 		of_scan_bus(node, bus);
 	else if (mode == PCI_PROBE_NORMAL)
@@ -528,6 +549,8 @@ void __devinit scan_phb(struct pci_contr
 	int i, mode;
 	struct resource *res;
 
+	DBG("Scanning PHB %s\n", node ? node->full_name : "<NO NAME>");
+
 	bus = pci_create_bus(NULL, hose->first_busno, hose->ops, node);
 	if (bus == NULL) {
 		printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
@@ -552,8 +575,9 @@ void __devinit scan_phb(struct pci_contr
 
 	mode = PCI_PROBE_NORMAL;
 #ifdef CONFIG_PPC_MULTIPLATFORM
-	if (ppc_md.pci_probe_mode)
+	if (node && ppc_md.pci_probe_mode)
 		mode = ppc_md.pci_probe_mode(bus);
+	DBG("    probe mode: %d\n", mode);
 	if (mode == PCI_PROBE_DEVTREE) {
 		bus->subordinate = hose->last_busno;
 		of_scan_bus(node, bus);
@@ -842,8 +866,7 @@ pgprot_t pci_phys_mem_access_prot(struct
  * Returns a negative error code on failure, zero on success.
  */
 int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-			enum pci_mmap_state mmap_state,
-			int write_combine)
+			enum pci_mmap_state mmap_state, int write_combine)
 {
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
 	struct resource *rp;
Index: linux-work/arch/powerpc/kernel/udbg.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/udbg.c	2005-12-06 16:17:43.000000000 +1100
+++ linux-work/arch/powerpc/kernel/udbg.c	2005-12-13 18:13:12.000000000 +1100
@@ -110,10 +110,12 @@ static int early_console_initialized;
 
 void __init disable_early_printk(void)
 {
+#if 1
 	if (!early_console_initialized)
 		return;
 	unregister_console(&udbg_console);
 	early_console_initialized = 0;
+#endif
 }
 
 /* called by setup_system */
Index: linux-work/arch/powerpc/platforms/powermac/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/setup.c	2005-12-13 17:51:20.000000000 +1100
+++ linux-work/arch/powerpc/platforms/powermac/setup.c	2005-12-14 11:42:58.000000000 +1100
@@ -345,7 +345,7 @@ void __init pmac_setup_arch(void)
 
 #ifdef CONFIG_SMP
 	/* Check for Core99 */
-	if (find_devices("uni-n") || find_devices("u3"))
+	if (find_devices("uni-n") || find_devices("u3") || find_devices("u4"))
 		smp_ops = &core99_smp_ops;
 #ifdef CONFIG_PPC32
 	else
@@ -635,7 +635,7 @@ static void __init pmac_init_early(void)
 	/* Setup interrupt mapping options */
 	ppc64_interrupt_controller = IC_OPEN_PIC;
 
-	iommu_init_early_u3();
+	iommu_init_early_dart();
 #endif
 }
 
@@ -711,7 +711,7 @@ static int __init pmac_probe(int platfor
 	 * occupies having to be broken up so the DART itself is not
 	 * part of the cacheable linar mapping
 	 */
-	alloc_u3_dart_table();
+	alloc_dart_table();
 #endif
 
 #ifdef CONFIG_PMAC_SMU
@@ -733,10 +733,11 @@ static int pmac_pci_probe_mode(struct pc
 	struct device_node *node = bus->sysdata;
 
 	/* We need to use normal PCI probing for the AGP bus,
-	   since the device for the AGP bridge isn't in the tree. */
-	if (bus->self == NULL && device_is_compatible(node, "u3-agp"))
+	 * since the device for the AGP bridge isn't in the tree.
+	 */
+	if (bus->self == NULL && (device_is_compatible(node, "u3-agp") ||
+				  device_is_compatible(node, "u4-pcie")))
 		return PCI_PROBE_NORMAL;
-
 	return PCI_PROBE_DEVTREE;
 }
 #endif
Index: linux-work/arch/powerpc/platforms/powermac/smp.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/powermac/smp.c	2005-12-13 15:03:21.000000000 +1100
+++ linux-work/arch/powerpc/platforms/powermac/smp.c	2005-12-13 18:13:12.000000000 +1100
@@ -361,7 +361,6 @@ static void __init psurge_dual_sync_tb(i
 	set_dec(tb_ticks_per_jiffy);
 	/* XXX fixme */
 	set_tb(0, 0);
-	last_jiffy_stamp(cpu_nr) = 0;
 
 	if (cpu_nr > 0) {
 		mb();
@@ -429,15 +428,62 @@ struct smp_ops_t psurge_smp_ops = {
 };
 #endif /* CONFIG_PPC32 - actually powersurge support */
 
+/*
+ * Core 99 and later support
+ */
+
+static void (*pmac_tb_freeze)(int freeze);
+static unsigned long timebase;
+static int tb_req;
+
+static void smp_core99_give_timebase(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	while(!tb_req)
+		barrier();
+	tb_req = 0;
+	(*pmac_tb_freeze)(1);
+	mb();
+	timebase = get_tb();
+	mb();
+	while (timebase)
+		barrier();
+	mb();
+	(*pmac_tb_freeze)(0);
+	mb();
+
+	local_irq_restore(flags);
+}
+
+
+static void __devinit smp_core99_take_timebase(void)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+
+	tb_req = 1;
+	mb();
+	while (!timebase)
+		barrier();
+	mb();
+	set_tb(timebase >> 32, timebase & 0xffffffff);
+	timebase = 0;
+	mb();
+	set_dec(tb_ticks_per_jiffy/2);
+
+	local_irq_restore(flags);
+}
+
 #ifdef CONFIG_PPC64
 /*
  * G5s enable/disable the timebase via an i2c-connected clock chip.
  */
 static struct device_node *pmac_tb_clock_chip_host;
 static u8 pmac_tb_pulsar_addr;
-static void (*pmac_tb_freeze)(int freeze);
-static DEFINE_SPINLOCK(timebase_lock);
-static unsigned long timebase;
 
 static void smp_core99_cypress_tb_freeze(int freeze)
 {
@@ -447,7 +493,8 @@ static void smp_core99_cypress_tb_freeze
 	/* Strangely, the device-tree says address is 0xd2, but darwin
 	 * accesses 0xd0 ...
 	 */
-	pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
+	pmac_low_i2c_setmode(pmac_tb_clock_chip_host,
+			     pmac_low_i2c_mode_combined);
 	rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
 			       0xd0 | pmac_low_i2c_read,
 			       0x81, &data, 1);
@@ -475,7 +522,8 @@ static void smp_core99_pulsar_tb_freeze(
 	u8 data;
 	int rc;
 
-	pmac_low_i2c_setmode(pmac_tb_clock_chip_host, pmac_low_i2c_mode_combined);
+	pmac_low_i2c_setmode(pmac_tb_clock_chip_host,
+			     pmac_low_i2c_mode_combined);
 	rc = pmac_low_i2c_xfer(pmac_tb_clock_chip_host,
 			       pmac_tb_pulsar_addr | pmac_low_i2c_read,
 			       0x2e, &data, 1);
@@ -496,54 +544,14 @@ static void smp_core99_pulsar_tb_freeze(
 	}
 }
 
-
-static void smp_core99_give_timebase(void)
-{
-	/* Open i2c bus for synchronous access */
-	if (pmac_low_i2c_open(pmac_tb_clock_chip_host, 0))
-		panic("Can't open i2c for TB sync !\n");
-
-	spin_lock(&timebase_lock);
-	(*pmac_tb_freeze)(1);
-	mb();
-	timebase = get_tb();
-	spin_unlock(&timebase_lock);
-
-	while (timebase)
-		barrier();
-
-	spin_lock(&timebase_lock);
-	(*pmac_tb_freeze)(0);
-	spin_unlock(&timebase_lock);
-
-	/* Close i2c bus */
-	pmac_low_i2c_close(pmac_tb_clock_chip_host);
-}
-
-
-static void __devinit smp_core99_take_timebase(void)
-{
-	while (!timebase)
-		barrier();
-	spin_lock(&timebase_lock);
-	set_tb(timebase >> 32, timebase & 0xffffffff);
-	timebase = 0;
-	spin_unlock(&timebase_lock);
-}
-
-static void __init smp_core99_setup(int ncpus)
+static void __init smp_core99_setup_i2c_hwsync(int ncpus)
 {
 	struct device_node *cc = NULL;	
 	struct device_node *p;
+	const char *name = NULL;
 	u32 *reg;
 	int ok;
 
-	/* HW sync only on these platforms */
-	if (!machine_is_compatible("PowerMac7,2") &&
-	    !machine_is_compatible("PowerMac7,3") &&
-	    !machine_is_compatible("RackMac3,1"))
-		return;
-
 	/* Look for the clock chip */
 	while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) {
 		p = of_get_parent(cc);
@@ -561,114 +569,64 @@ static void __init smp_core99_setup(int 
 			if (device_is_compatible(cc, "pulsar-legacy-slewing")) {
 				pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
 				pmac_tb_pulsar_addr = 0xd2;
-				printk(KERN_INFO "Timebase clock is Pulsar chip\n");
+				name = "Pulsar";
 			} else if (device_is_compatible(cc, "cy28508")) {
 				pmac_tb_freeze = smp_core99_cypress_tb_freeze;
-				printk(KERN_INFO "Timebase clock is Cypress chip\n");
+				name = "Cypress";
 			}
 			break;
 		case 0xd4:
 			pmac_tb_freeze = smp_core99_pulsar_tb_freeze;
 			pmac_tb_pulsar_addr = 0xd4;
-			printk(KERN_INFO "Timebase clock is Pulsar chip\n");
+			name = "Pulsar";
 			break;
 		}
-		if (pmac_tb_freeze != NULL) {
-			pmac_tb_clock_chip_host = of_get_parent(cc);
-			of_node_put(cc);
+		if (pmac_tb_freeze != NULL)
 			break;
-		}
 	}
-	if (pmac_tb_freeze == NULL) {
-		smp_ops->give_timebase = smp_generic_give_timebase;
-		smp_ops->take_timebase = smp_generic_take_timebase;
+	if (pmac_tb_freeze != NULL) {
+		struct device_node *p = of_get_parent(cc);
+		of_node_put(cc);
+		while(p && strcmp(p->type, "i2c")) {
+			cc = of_get_parent(p);
+			of_node_put(p);
+			p = cc;
+		}
+		if (p == NULL)
+			goto no_i2c_sync;
+		/* Open i2c bus for synchronous access */
+		if (pmac_low_i2c_open(p, 0)) {
+			printk(KERN_ERR "Failed top open i2c bus %s for clock"
+			       " sync, fallback to software sync !\n",
+			       p->full_name);
+			of_node_put(p);
+			goto no_i2c_sync;
+		}
+		pmac_tb_clock_chip_host = p;
+		printk(KERN_INFO "Processor timebase sync using %s i2c clock\n",
+		       name);
+		return;
 	}
+ no_i2c_sync:
+	pmac_tb_freeze = NULL;
 }
 
-/* nothing to do here, caches are already set up by service processor */
-static inline void __devinit core99_init_caches(int cpu)
-{
-}
+#endif /* CONFIG_PPC64 */
 
-#else /* CONFIG_PPC64 */
 
 /*
- * SMP G4 powermacs use a GPIO to enable/disable the timebase.
+ * SMP G4 and newer G5 use a GPIO to enable/disable the timebase.
  */
 
 static unsigned int core99_tb_gpio;	/* Timebase freeze GPIO */
 
-static unsigned int pri_tb_hi, pri_tb_lo;
-static unsigned int pri_tb_stamp;
-
-/* not __init, called in sleep/wakeup code */
-void smp_core99_give_timebase(void)
+static void smp_core99_gpio_tb_freeze(int freeze)
 {
-	unsigned long flags;
-	unsigned int t;
-
-	/* wait for the secondary to be in take_timebase */
-	for (t = 100000; t > 0 && !sec_tb_reset; --t)
-		udelay(10);
-	if (!sec_tb_reset) {
-		printk(KERN_WARNING "Timeout waiting sync on second CPU\n");
-		return;
-	}
-
-	/* freeze the timebase and read it */
-	/* disable interrupts so the timebase is disabled for the
-	   shortest possible time */
-	local_irq_save(flags);
-	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
+	if (freeze)
+		pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 4);
+	else
+		pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
 	pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
-	mb();
-	pri_tb_hi = get_tbu();
-	pri_tb_lo = get_tbl();
-	pri_tb_stamp = last_jiffy_stamp(smp_processor_id());
-	mb();
-
-	/* tell the secondary we're ready */
-	sec_tb_reset = 2;
-	mb();
-
-	/* wait for the secondary to have taken it */
-	/* note: can't use udelay here, since it needs the timebase running */
-	for (t = 10000000; t > 0 && sec_tb_reset; --t)
-		barrier();
-	if (sec_tb_reset)
-		/* XXX BUG_ON here? */
-		printk(KERN_WARNING "Timeout waiting sync(2) on second CPU\n");
-
-	/* Now, restart the timebase by leaving the GPIO to an open collector */
-       	pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, core99_tb_gpio, 0);
-        pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, core99_tb_gpio, 0);
-	local_irq_restore(flags);
-}
-
-/* not __init, called in sleep/wakeup code */
-void smp_core99_take_timebase(void)
-{
-	unsigned long flags;
-
-	/* tell the primary we're here */
-	sec_tb_reset = 1;
-	mb();
-
-	/* wait for the primary to set pri_tb_hi/lo */
-	while (sec_tb_reset < 2)
-		mb();
-
-	/* set our stuff the same as the primary */
-	local_irq_save(flags);
-	set_dec(1);
-	set_tb(pri_tb_hi, pri_tb_lo);
-	last_jiffy_stamp(smp_processor_id()) = pri_tb_stamp;
-	mb();
-
-	/* tell the primary we're done */
-       	sec_tb_reset = 0;
-	mb();
-	local_irq_restore(flags);
 }
 
 /* L2 and L3 cache settings to pass from CPU0 to CPU1 on G4 cpus */
@@ -677,6 +635,7 @@ volatile static long int core99_l3_cache
 
 static void __devinit core99_init_caches(int cpu)
 {
+#ifndef CONFIG_PPC64
 	if (!cpu_has_feature(CPU_FTR_L2CR))
 		return;
 
@@ -702,30 +661,80 @@ static void __devinit core99_init_caches
 		_set_L3CR(core99_l3_cache);
 		printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
 	}
+#endif /* !CONFIG_PPC64 */
 }
 
 static void __init smp_core99_setup(int ncpus)
 {
-	struct device_node *cpu;
-	u32 *tbprop = NULL;
-	int i;
-
-	core99_tb_gpio = KL_GPIO_TB_ENABLE;	/* default value */
-	cpu = of_find_node_by_type(NULL, "cpu");
-	if (cpu != NULL) {
-		tbprop = (u32 *)get_property(cpu, "timebase-enable", NULL);
-		if (tbprop)
-			core99_tb_gpio = *tbprop;
-		of_node_put(cpu);
-	}
-
-	/* XXX should get this from reg properties */
-	for (i = 1; i < ncpus; ++i)
-		smp_hw_index[i] = i;
-	powersave_nap = 0;
-}
+#ifdef CONFIG_PPC64
+
+	/* i2c based HW sync on some G5s */
+	if (machine_is_compatible("PowerMac7,2") ||
+	    machine_is_compatible("PowerMac7,3") ||
+	    machine_is_compatible("RackMac3,1"))
+		smp_core99_setup_i2c_hwsync(ncpus);
+
+	/* GPIO based HW sync on recent G5s */
+	if (pmac_tb_freeze == NULL) {
+		struct device_node *np =
+			of_find_node_by_name(NULL, "timebase-enable");
+		u32 *reg = (u32 *)get_property(np, "reg", NULL);
+
+		if (np && reg && !strcmp(np->type, "gpio")) {
+			core99_tb_gpio = *reg;
+			if (core99_tb_gpio < 0x50)
+				core99_tb_gpio += 0x50;
+			pmac_tb_freeze = smp_core99_gpio_tb_freeze;
+			printk(KERN_INFO "Processor timebase sync using"
+			       " GPIO 0x%02x\n", core99_tb_gpio);
+		}
+	}
+
+#else /* CONFIG_PPC64 */
+
+	/* GPIO based HW sync on ppc32 Core99 */
+	if (pmac_tb_freeze == NULL && !machine_is_compatible("MacRISC4")) {
+		struct device_node *cpu;
+		u32 *tbprop = NULL;
+
+		core99_tb_gpio = KL_GPIO_TB_ENABLE;	/* default value */
+		cpu = of_find_node_by_type(NULL, "cpu");
+		if (cpu != NULL) {
+			tbprop = (u32 *)get_property(cpu, "timebase-enable",
+						     NULL);
+			if (tbprop)
+				core99_tb_gpio = *tbprop;
+			of_node_put(cpu);
+		}
+		pmac_tb_freeze = smp_core99_gpio_tb_freeze;
+		printk(KERN_INFO "Processor timebase sync using"
+		       " GPIO 0x%02x\n", core99_tb_gpio);
+	}
+
+#endif /* CONFIG_PPC64 */
+
+	/* No timebase sync, fallback to software */
+	if (pmac_tb_freeze == NULL) {
+		smp_ops->give_timebase = smp_generic_give_timebase;
+		smp_ops->take_timebase = smp_generic_take_timebase;
+		printk(KERN_INFO "Processor timebase sync using software\n");
+	}
+
+#ifndef CONFIG_PPC64
+	{
+		int i;
+
+		/* XXX should get this from reg properties */
+		for (i = 1; i < ncpus; ++i)
+			smp_hw_index[i] = i;
+	}
 #endif
 
+	/* 32 bits SMP can't NAP */
+	if (!machine_is_compatible("MacRISC4"))
+		powersave_nap = 0;
+}
+
 static int __init smp_core99_probe(void)
 {
 	struct device_node *cpus;
@@ -803,17 +812,25 @@ static void __devinit smp_core99_setup_c
 	mpic_setup_this_cpu();
 
 	if (cpu_nr == 0) {
-#ifdef CONFIG_POWER4
+#ifdef CONFIG_PPC64
 		extern void g5_phy_disable_cpu1(void);
 
+		/* Close i2c bus if it was used for tb sync */
+		if (pmac_tb_clock_chip_host) {
+			pmac_low_i2c_close(pmac_tb_clock_chip_host);
+			pmac_tb_clock_chip_host	= NULL;
+		}
+
 		/* If we didn't start the second CPU, we must take
 		 * it off the bus
 		 */
 		if (machine_is_compatible("MacRISC4") &&
 		    num_online_cpus() < 2)		
 			g5_phy_disable_cpu1();
-#endif /* CONFIG_POWER4 */
-		if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+#endif /* CONFIG_PPC64 */
+
+		if (ppc_md.progress)
+			ppc_md.progress("core99_setup_cpu 0 done", 0x349);
 	}
 }
 
Index: linux-work/arch/powerpc/sysdev/u3_iommu.c
===================================================================
--- linux-work.orig/arch/powerpc/sysdev/u3_iommu.c	2005-11-24 17:21:41.000000000 +1100
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,327 +0,0 @@
-/*
- * arch/powerpc/sysdev/u3_iommu.c
- *
- * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
- *
- * Based on pSeries_iommu.c:
- * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
- * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
- *
- * Dynamic DMA mapping support, Apple U3 & IBM CPC925 "DART" iommu.
- *
- * 
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * 
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * 
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/vmalloc.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/iommu.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/abs_addr.h>
-#include <asm/cacheflush.h>
-#include <asm/lmb.h>
-#include <asm/ppc-pci.h>
-
-#include "dart.h"
-
-extern int iommu_force_on;
-
-/* Physical base address and size of the DART table */
-unsigned long dart_tablebase; /* exported to htab_initialize */
-static unsigned long dart_tablesize;
-
-/* Virtual base address of the DART table */
-static u32 *dart_vbase;
-
-/* Mapped base address for the dart */
-static unsigned int *dart; 
-
-/* Dummy val that entries are set to when unused */
-static unsigned int dart_emptyval;
-
-static struct iommu_table iommu_table_u3;
-static int iommu_table_u3_inited;
-static int dart_dirty;
-
-#define DBG(...)
-
-static inline void dart_tlb_invalidate_all(void)
-{
-	unsigned long l = 0;
-	unsigned int reg;
-	unsigned long limit;
-
-	DBG("dart: flush\n");
-
-	/* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the
-	 * control register and wait for it to clear.
-	 *
-	 * Gotcha: Sometimes, the DART won't detect that the bit gets
-	 * set. If so, clear it and set it again.
-	 */ 
-
-	limit = 0;
-
-retry:
-	reg = in_be32((unsigned int *)dart+DARTCNTL);
-	reg |= DARTCNTL_FLUSHTLB;
-	out_be32((unsigned int *)dart+DARTCNTL, reg);
-
-	l = 0;
-	while ((in_be32((unsigned int *)dart+DARTCNTL) & DARTCNTL_FLUSHTLB) &&
-		l < (1L<<limit)) {
-		l++;
-	}
-	if (l == (1L<<limit)) {
-		if (limit < 4) {
-			limit++;
-		        reg = in_be32((unsigned int *)dart+DARTCNTL);
-		        reg &= ~DARTCNTL_FLUSHTLB;
-		        out_be32((unsigned int *)dart+DARTCNTL, reg);
-			goto retry;
-		} else
-			panic("U3-DART: TLB did not flush after waiting a long "
-			      "time. Buggy U3 ?");
-	}
-}
-
-static void dart_flush(struct iommu_table *tbl)
-{
-	if (dart_dirty)
-		dart_tlb_invalidate_all();
-	dart_dirty = 0;
-}
-
-static void dart_build(struct iommu_table *tbl, long index, 
-		       long npages, unsigned long uaddr,
-		       enum dma_data_direction direction)
-{
-	unsigned int *dp;
-	unsigned int rpn;
-
-	DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
-
-	index <<= DART_PAGE_FACTOR;
-	npages <<= DART_PAGE_FACTOR;
-
-	dp = ((unsigned int*)tbl->it_base) + index;
-	
-	/* On U3, all memory is contigous, so we can move this
-	 * out of the loop.
-	 */
-	while (npages--) {
-		rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
-
-		*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
-
-		rpn++;
-		uaddr += DART_PAGE_SIZE;
-	}
-
-	dart_dirty = 1;
-}
-
-
-static void dart_free(struct iommu_table *tbl, long index, long npages)
-{
-	unsigned int *dp;
-	
-	/* We don't worry about flushing the TLB cache. The only drawback of
-	 * not doing it is that we won't catch buggy device drivers doing
-	 * bad DMAs, but then no 32-bit architecture ever does either.
-	 */
-
-	DBG("dart: free at: %lx, %lx\n", index, npages);
-
-	index <<= DART_PAGE_FACTOR;
-	npages <<= DART_PAGE_FACTOR;
-
-	dp  = ((unsigned int *)tbl->it_base) + index;
-		
-	while (npages--)
-		*(dp++) = dart_emptyval;
-}
-
-
-static int dart_init(struct device_node *dart_node)
-{
-	unsigned int regword;
-	unsigned int i;
-	unsigned long tmp;
-
-	if (dart_tablebase == 0 || dart_tablesize == 0) {
-		printk(KERN_INFO "U3-DART: table not allocated, using direct DMA\n");
-		return -ENODEV;
-	}
-
-	/* Make sure nothing from the DART range remains in the CPU cache
-	 * from a previous mapping that existed before the kernel took
-	 * over
-	 */
-	flush_dcache_phys_range(dart_tablebase, dart_tablebase + dart_tablesize);
-
-	/* Allocate a spare page to map all invalid DART pages. We need to do
-	 * that to work around what looks like a problem with the HT bridge
-	 * prefetching into invalid pages and corrupting data
-	 */
-	tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
-	if (!tmp)
-		panic("U3-DART: Cannot allocate spare page!");
-	dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) & DARTMAP_RPNMASK);
-
-	/* Map in DART registers. FIXME: Use device node to get base address */
-	dart = ioremap(DART_BASE, 0x7000);
-	if (dart == NULL)
-		panic("U3-DART: Cannot map registers!");
-
-	/* Set initial control register contents: table base, 
-	 * table size and enable bit
-	 */
-	regword = DARTCNTL_ENABLE | 
-		((dart_tablebase >> DART_PAGE_SHIFT) << DARTCNTL_BASE_SHIFT) |
-		(((dart_tablesize >> DART_PAGE_SHIFT) & DARTCNTL_SIZE_MASK)
-				 << DARTCNTL_SIZE_SHIFT);
-	dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
-
-	/* Fill initial table */
-	for (i = 0; i < dart_tablesize/4; i++)
-		dart_vbase[i] = dart_emptyval;
-
-	/* Initialize DART with table base and enable it. */
-	out_be32((unsigned int *)dart, regword);
-
-	/* Invalidate DART to get rid of possible stale TLBs */
-	dart_tlb_invalidate_all();
-
-	printk(KERN_INFO "U3/CPC925 DART IOMMU initialized\n");
-
-	return 0;
-}
-
-static void iommu_table_u3_setup(void)
-{
-	iommu_table_u3.it_busno = 0;
-	iommu_table_u3.it_offset = 0;
-	/* it_size is in number of entries */
-	iommu_table_u3.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR;
-
-	/* Initialize the common IOMMU code */
-	iommu_table_u3.it_base = (unsigned long)dart_vbase;
-	iommu_table_u3.it_index = 0;
-	iommu_table_u3.it_blocksize = 1;
-	iommu_init_table(&iommu_table_u3);
-
-	/* Reserve the last page of the DART to avoid possible prefetch
-	 * past the DART mapped area
-	 */
-	set_bit(iommu_table_u3.it_size - 1, iommu_table_u3.it_map);
-}
-
-static void iommu_dev_setup_u3(struct pci_dev *dev)
-{
-	struct device_node *dn;
-
-	/* We only have one iommu table on the mac for now, which makes
-	 * things simple. Setup all PCI devices to point to this table
-	 *
-	 * We must use pci_device_to_OF_node() to make sure that
-	 * we get the real "final" pointer to the device in the
-	 * pci_dev sysdata and not the temporary PHB one
-	 */
-	dn = pci_device_to_OF_node(dev);
-
-	if (dn)
-		PCI_DN(dn)->iommu_table = &iommu_table_u3;
-}
-
-static void iommu_bus_setup_u3(struct pci_bus *bus)
-{
-	struct device_node *dn;
-
-	if (!iommu_table_u3_inited) {
-		iommu_table_u3_inited = 1;
-		iommu_table_u3_setup();
-	}
-
-	dn = pci_bus_to_OF_node(bus);
-
-	if (dn)
-		PCI_DN(dn)->iommu_table = &iommu_table_u3;
-}
-
-static void iommu_dev_setup_null(struct pci_dev *dev) { }
-static void iommu_bus_setup_null(struct pci_bus *bus) { }
-
-void iommu_init_early_u3(void)
-{
-	struct device_node *dn;
-
-	/* Find the DART in the device-tree */
-	dn = of_find_compatible_node(NULL, "dart", "u3-dart");
-	if (dn == NULL)
-		return;
-
-	/* Setup low level TCE operations for the core IOMMU code */
-	ppc_md.tce_build = dart_build;
-	ppc_md.tce_free  = dart_free;
-	ppc_md.tce_flush = dart_flush;
-
-	/* Initialize the DART HW */
-	if (dart_init(dn)) {
-		/* If init failed, use direct iommu and null setup functions */
-		ppc_md.iommu_dev_setup = iommu_dev_setup_null;
-		ppc_md.iommu_bus_setup = iommu_bus_setup_null;
-
-		/* Setup pci_dma ops */
-		pci_direct_iommu_init();
-	} else {
-		ppc_md.iommu_dev_setup = iommu_dev_setup_u3;
-		ppc_md.iommu_bus_setup = iommu_bus_setup_u3;
-
-		/* Setup pci_dma ops */
-		pci_iommu_init();
-	}
-}
-
-
-void __init alloc_u3_dart_table(void)
-{
-	/* Only reserve DART space if machine has more than 2GB of RAM
-	 * or if requested with iommu=on on cmdline.
-	 */
-	if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
-		return;
-
-	/* 512 pages (2MB) is max DART tablesize. */
-	dart_tablesize = 1UL << 21;
-	/* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
-	 * will blow up an entire large page anyway in the kernel mapping
-	 */
-	dart_tablebase = (unsigned long)
-		abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
-
-	printk(KERN_INFO "U3-DART allocated at: %lx\n", dart_tablebase);
-}
Index: linux-work/drivers/ide/ppc/pmac.c
===================================================================
--- linux-work.orig/drivers/ide/ppc/pmac.c	2005-12-13 17:51:20.000000000 +1100
+++ linux-work/drivers/ide/ppc/pmac.c	2005-12-13 18:13:12.000000000 +1100
@@ -1686,7 +1686,7 @@ pmac_ide_probe(void)
 #else
 	macio_register_driver(&pmac_ide_macio_driver);
 	pci_register_driver(&pmac_ide_pci_driver);
-#endif	
+#endif
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
Index: linux-work/drivers/macintosh/smu.c
===================================================================
--- linux-work.orig/drivers/macintosh/smu.c	2005-11-24 17:18:43.000000000 +1100
+++ linux-work/drivers/macintosh/smu.c	2005-12-13 18:13:12.000000000 +1100
@@ -53,7 +53,7 @@
 #undef DEBUG_SMU
 
 #ifdef DEBUG_SMU
-#define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0)
+#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0)
 #else
 #define DPRINTK(fmt, args...) do { } while (0)
 #endif
@@ -909,10 +909,13 @@ static struct smu_sdbp_header *smu_creat
 	struct property *prop;
 
 	/* First query the partition info */
+	DPRINTK("SMU: Query partition infos ... (irq=%d)\n", smu->db_irq);
 	smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2,
 			 smu_done_complete, &comp,
 			 SMU_CMD_PARTITION_LATEST, id);
 	wait_for_completion(&comp);
+	DPRINTK("SMU: done, status: %d, reply_len: %d\n",
+		cmd.cmd.status, cmd.cmd.reply_len);
 
 	/* Partition doesn't exist (or other error) */
 	if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6)
@@ -975,6 +978,8 @@ struct smu_sdbp_header *__smu_get_sdb_pa
 
 	sprintf(pname, "sdb-partition-%02x", id);
 
+	DPRINTK("smu_get_sdb_partition(%02x)\n", id);
+
 	if (interruptible) {
 		int rc;
 		rc = down_interruptible(&smu_part_access);
@@ -986,6 +991,7 @@ struct smu_sdbp_header *__smu_get_sdb_pa
 	part = (struct smu_sdbp_header *)get_property(smu->of_node,
 						      pname, size);
 	if (part == NULL) {
+		DPRINTK("trying to extract from SMU ...\n");
 		part = smu_create_sdb_partition(id);
 		if (part != NULL && size)
 			*size = part->len << 2;
Index: linux-work/include/asm-powerpc/mpic.h
===================================================================
--- linux-work.orig/include/asm-powerpc/mpic.h	2005-12-13 18:02:03.000000000 +1100
+++ linux-work/include/asm-powerpc/mpic.h	2005-12-13 18:13:12.000000000 +1100
@@ -117,8 +117,9 @@ typedef int (*mpic_cascade_t)(struct pt_
 struct mpic_irq_fixup
 {
 	u8 __iomem	*base;
+	u8 __iomem	*applebase;
 	u32		data;
-	unsigned int	irq;
+	unsigned int	index;
 };
 #endif /* CONFIG_MPIC_BROKEN_U3 */
 
Index: linux-work/include/asm/hardirq.h
===================================================================
--- linux-work.orig/include/asm/hardirq.h	2005-11-24 17:18:48.000000000 +1100
+++ linux-work/include/asm/hardirq.h	2005-12-13 18:13:12.000000000 +1100
@@ -11,13 +11,10 @@
  */
 typedef struct {
 	unsigned int __softirq_pending;	/* set_bit is used on this */
-	unsigned int __last_jiffy_stamp;
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
 
-#define last_jiffy_stamp(cpu) __IRQ_STAT((cpu), __last_jiffy_stamp)
-
 static inline void ack_bad_irq(int irq)
 {
 	printk(KERN_CRIT "illegal vector %d received!\n", irq);
Index: linux-work/arch/powerpc/platforms/maple/setup.c
===================================================================
--- linux-work.orig/arch/powerpc/platforms/maple/setup.c	2005-12-13 15:03:21.000000000 +1100
+++ linux-work/arch/powerpc/platforms/maple/setup.c	2005-12-14 11:43:10.000000000 +1100
@@ -195,7 +195,7 @@ static void __init maple_init_early(void
 	/* Setup interrupt mapping options */
 	ppc64_interrupt_controller = IC_OPEN_PIC;
 
-	iommu_init_early_u3();
+	iommu_init_early_dart();
 
 	DBG(" <- maple_init_early\n");
 }
@@ -257,7 +257,7 @@ static int __init maple_probe(int platfo
 	 * occupies having to be broken up so the DART itself is not
 	 * part of the cacheable linar mapping
 	 */
-	alloc_u3_dart_table();
+	alloc_dart_table();
 
 	return 1;
 }
Index: linux-work/arch/powerpc/sysdev/Makefile
===================================================================
--- linux-work.orig/arch/powerpc/sysdev/Makefile	2005-11-24 17:21:41.000000000 +1100
+++ linux-work/arch/powerpc/sysdev/Makefile	2005-12-14 11:01:34.000000000 +1100
@@ -4,6 +4,6 @@ obj-$(CONFIG_PPC_I8259)		+= i8259.o
 obj-$(CONFIG_PPC_MPC106)	+= grackle.o
 obj-$(CONFIG_BOOKE)		+= dcr.o
 obj-$(CONFIG_40x)		+= dcr.o
-obj-$(CONFIG_U3_DART)		+= u3_iommu.o
+obj-$(CONFIG_U3_DART)		+= dart_iommu.o
 obj-$(CONFIG_MMIO_NVRAM)	+= mmio_nvram.o
 obj-$(CONFIG_83xx)		+= ipic.o
Index: linux-work/arch/powerpc/sysdev/dart.h
===================================================================
--- linux-work.orig/arch/powerpc/sysdev/dart.h	2005-11-24 17:21:41.000000000 +1100
+++ linux-work/arch/powerpc/sysdev/dart.h	2005-12-14 12:52:12.000000000 +1100
@@ -20,29 +20,44 @@
 #define _POWERPC_SYSDEV_DART_H
 

-/* physical base of DART registers */
-#define DART_BASE        0xf8033000UL
-
 /* Offset from base to control register */
-#define DARTCNTL   0
+#define DART_CNTL	0
+
 /* Offset from base to exception register */
-#define DARTEXCP   0x10
+#define DART_EXCP_U3	0x10
 /* Offset from base to TLB tag registers */
-#define DARTTAG    0x1000
+#define DART_TAGS_U3	0x1000
 
+/* U4 registers */
+#define DART_BASE_U4	0x10
+#define DART_SIZE_U4	0x20
+#define DART_EXCP_U4	0x30
+#define DART_TAGS_U4	0x1000
 
 /* Control Register fields */
 
-/* base address of table (pfn) */
-#define DARTCNTL_BASE_MASK    0xfffff
-#define DARTCNTL_BASE_SHIFT   12
+/* U3 registers */
+#define DART_CNTL_U3_BASE_MASK	0xfffff
+#define DART_CNTL_U3_BASE_SHIFT	12
+#define DART_CNTL_U3_FLUSHTLB	0x400
+#define DART_CNTL_U3_ENABLE	0x200
+#define DART_CNTL_U3_SIZE_MASK	0x1ff
+#define DART_CNTL_U3_SIZE_SHIFT	0
+
+/* U4 registers */
+#define DART_BASE_U4_BASE_MASK	0xffffff
+#define DART_BASE_U4_BASE_SHIFT	0
+#define DART_CNTL_U4_FLUSHTLB	0x20000000
+#define DART_CNTL_U4_ENABLE	0x80000000
+#define DART_SIZE_U4_SIZE_MASK	0x1fff
+#define DART_SIZE_U4_SIZE_SHIFT	0
+
+#define DART_REG(r)	(dart + ((r) >> 2))
+#define DART_IN(r)	(in_be32(DART_REG(r)))
+#define DART_OUT(r,v)	(out_be32(DART_REG(r), (v)))
 
-#define DARTCNTL_FLUSHTLB     0x400
-#define DARTCNTL_ENABLE       0x200
 
 /* size of table in pages */
-#define DARTCNTL_SIZE_MASK    0x1ff
-#define DARTCNTL_SIZE_SHIFT   0
 

 /* DART table fields */
Index: linux-work/arch/powerpc/sysdev/dart_iommu.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-work/arch/powerpc/sysdev/dart_iommu.c	2005-12-14 13:07:03.000000000 +1100
@@ -0,0 +1,350 @@
+/*
+ * arch/powerpc/sysdev/dart_iommu.c
+ *
+ * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ * Copyright (C) 2005 Benjamin Herrenschmidt <benh@kernel.crashing.org>,
+ *                    IBM Corporation
+ *
+ * Based on pSeries_iommu.c:
+ * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation
+ * Copyright (C) 2004 Olof Johansson <olof@lixom.net>, IBM Corporation
+ *
+ * Dynamic DMA mapping support, Apple U3, U4 & IBM CPC925 "DART" iommu.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/iommu.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/abs_addr.h>
+#include <asm/cacheflush.h>
+#include <asm/lmb.h>
+#include <asm/ppc-pci.h>
+
+#include "dart.h"
+
+extern int iommu_force_on;
+
+/* Physical base address and size of the DART table */
+unsigned long dart_tablebase; /* exported to htab_initialize */
+static unsigned long dart_tablesize;
+
+/* Virtual base address of the DART table */
+static u32 *dart_vbase;
+
+/* Mapped base address for the dart */
+static unsigned int *__iomem dart;
+
+/* Dummy val that entries are set to when unused */
+static unsigned int dart_emptyval;
+
+static struct iommu_table iommu_table_dart;
+static int iommu_table_dart_inited;
+static int dart_dirty;
+static int dart_is_u4;
+
+#define DBG(...)
+
+static inline void dart_tlb_invalidate_all(void)
+{
+	unsigned long l = 0;
+	unsigned int reg, inv_bit;
+	unsigned long limit;
+
+	DBG("dart: flush\n");
+
+	/* To invalidate the DART, set the DARTCNTL_FLUSHTLB bit in the
+	 * control register and wait for it to clear.
+	 *
+	 * Gotcha: Sometimes, the DART won't detect that the bit gets
+	 * set. If so, clear it and set it again.
+	 */
+
+	limit = 0;
+
+	inv_bit = dart_is_u4 ? DART_CNTL_U4_FLUSHTLB : DART_CNTL_U3_FLUSHTLB;
+retry:
+	l = 0;
+	reg = DART_IN(DART_CNTL);
+	reg |= inv_bit;
+	DART_OUT(DART_CNTL, reg);
+
+	while ((DART_IN(DART_CNTL) & inv_bit) && l < (1L << limit))
+		l++;
+	if (l == (1L << limit)) {
+		if (limit < 4) {
+			limit++;
+		        reg = DART_IN(DART_CNTL);
+		        reg &= ~inv_bit;
+			DART_OUT(DART_CNTL, reg);
+			goto retry;
+		} else
+			panic("DART: TLB did not flush after waiting a long "
+			      "time. Buggy U3 ?");
+	}
+}
+
+static void dart_flush(struct iommu_table *tbl)
+{
+	if (dart_dirty)
+		dart_tlb_invalidate_all();
+	dart_dirty = 0;
+}
+
+static void dart_build(struct iommu_table *tbl, long index,
+		       long npages, unsigned long uaddr,
+		       enum dma_data_direction direction)
+{
+	unsigned int *dp;
+	unsigned int rpn;
+
+	DBG("dart: build at: %lx, %lx, addr: %x\n", index, npages, uaddr);
+
+	index <<= DART_PAGE_FACTOR;
+	npages <<= DART_PAGE_FACTOR;
+
+	dp = ((unsigned int*)tbl->it_base) + index;
+
+	/* On U3, all memory is contigous, so we can move this
+	 * out of the loop.
+	 */
+	while (npages--) {
+		rpn = virt_to_abs(uaddr) >> DART_PAGE_SHIFT;
+
+		*(dp++) = DARTMAP_VALID | (rpn & DARTMAP_RPNMASK);
+
+		rpn++;
+		uaddr += DART_PAGE_SIZE;
+	}
+
+	dart_dirty = 1;
+}
+
+
+static void dart_free(struct iommu_table *tbl, long index, long npages)
+{
+	unsigned int *dp;
+
+	/* We don't worry about flushing the TLB cache. The only drawback of
+	 * not doing it is that we won't catch buggy device drivers doing
+	 * bad DMAs, but then no 32-bit architecture ever does either.
+	 */
+
+	DBG("dart: free at: %lx, %lx\n", index, npages);
+
+	index <<= DART_PAGE_FACTOR;
+	npages <<= DART_PAGE_FACTOR;
+
+	dp  = ((unsigned int *)tbl->it_base) + index;
+
+	while (npages--)
+		*(dp++) = dart_emptyval;
+}
+
+
+static int dart_init(struct device_node *dart_node)
+{
+	unsigned int i;
+	unsigned long tmp, base, size;
+	struct resource r;
+
+	if (dart_tablebase == 0 || dart_tablesize == 0) {
+		printk(KERN_INFO "DART: table not allocated, using "
+		       "direct DMA\n");
+		return -ENODEV;
+	}
+
+	if (of_address_to_resource(dart_node, 0, &r))
+		panic("DART: can't get register base ! ");
+
+	/* Make sure nothing from the DART range remains in the CPU cache
+	 * from a previous mapping that existed before the kernel took
+	 * over
+	 */
+	flush_dcache_phys_range(dart_tablebase,
+				dart_tablebase + dart_tablesize);
+
+	/* Allocate a spare page to map all invalid DART pages. We need to do
+	 * that to work around what looks like a problem with the HT bridge
+	 * prefetching into invalid pages and corrupting data
+	 */
+	tmp = lmb_alloc(DART_PAGE_SIZE, DART_PAGE_SIZE);
+	if (!tmp)
+		panic("DART: Cannot allocate spare page!");
+	dart_emptyval = DARTMAP_VALID | ((tmp >> DART_PAGE_SHIFT) &
+					 DARTMAP_RPNMASK);
+
+	/* Map in DART registers */
+	dart = ioremap(r.start, r.end - r.start + 1);
+	if (dart == NULL)
+		panic("DART: Cannot map registers!");
+
+	/* Map in DART table */
+	dart_vbase = ioremap(virt_to_abs(dart_tablebase), dart_tablesize);
+
+	/* Fill initial table */
+	for (i = 0; i < dart_tablesize/4; i++)
+		dart_vbase[i] = dart_emptyval;
+
+	/* Initialize DART with table base and enable it. */
+	base = dart_tablebase >> DART_PAGE_SHIFT;
+	size = dart_tablesize >> DART_PAGE_SHIFT;
+	if (dart_is_u4) {
+		BUG_ON(size & ~DART_SIZE_U4_SIZE_MASK);
+		DART_OUT(DART_BASE_U4, base);
+		DART_OUT(DART_SIZE_U4, size);
+		DART_OUT(DART_CNTL, DART_CNTL_U4_ENABLE);
+	} else {
+		BUG_ON(size & ~DART_CNTL_U3_SIZE_MASK);
+		DART_OUT(DART_CNTL,
+			 DART_CNTL_U3_ENABLE |
+			 (base << DART_CNTL_U3_BASE_SHIFT) |
+			 (size << DART_CNTL_U3_SIZE_SHIFT));
+	}
+
+	/* Invalidate DART to get rid of possible stale TLBs */
+	dart_tlb_invalidate_all();
+
+	printk(KERN_INFO "DART IOMMU initialized for %s type chipset\n",
+	       dart_is_u4 ? "U4" : "U3");
+
+	return 0;
+}
+
+static void iommu_table_dart_setup(void)
+{
+	iommu_table_dart.it_busno = 0;
+	iommu_table_dart.it_offset = 0;
+	/* it_size is in number of entries */
+	iommu_table_dart.it_size = (dart_tablesize / sizeof(u32)) >> DART_PAGE_FACTOR;
+
+	/* Initialize the common IOMMU code */
+	iommu_table_dart.it_base = (unsigned long)dart_vbase;
+	iommu_table_dart.it_index = 0;
+	iommu_table_dart.it_blocksize = 1;
+	iommu_init_table(&iommu_table_dart);
+
+	/* Reserve the last page of the DART to avoid possible prefetch
+	 * past the DART mapped area
+	 */
+	set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map);
+}
+
+static void iommu_dev_setup_dart(struct pci_dev *dev)
+{
+	struct device_node *dn;
+
+	/* We only have one iommu table on the mac for now, which makes
+	 * things simple. Setup all PCI devices to point to this table
+	 *
+	 * We must use pci_device_to_OF_node() to make sure that
+	 * we get the real "final" pointer to the device in the
+	 * pci_dev sysdata and not the temporary PHB one
+	 */
+	dn = pci_device_to_OF_node(dev);
+
+	if (dn)
+		PCI_DN(dn)->iommu_table = &iommu_table_dart;
+}
+
+static void iommu_bus_setup_dart(struct pci_bus *bus)
+{
+	struct device_node *dn;
+
+	if (!iommu_table_dart_inited) {
+		iommu_table_dart_inited = 1;
+		iommu_table_dart_setup();
+	}
+
+	dn = pci_bus_to_OF_node(bus);
+
+	if (dn)
+		PCI_DN(dn)->iommu_table = &iommu_table_dart;
+}
+
+static void iommu_dev_setup_null(struct pci_dev *dev) { }
+static void iommu_bus_setup_null(struct pci_bus *bus) { }
+
+void iommu_init_early_dart(void)
+{
+	struct device_node *dn;
+
+	/* Find the DART in the device-tree */
+	dn = of_find_compatible_node(NULL, "dart", "u3-dart");
+	if (dn == NULL) {
+		dn = of_find_compatible_node(NULL, "dart", "u4-dart");
+		if (dn == NULL)
+			goto bail;
+		dart_is_u4 = 1;
+	}
+
+	/* Setup low level TCE operations for the core IOMMU code */
+	ppc_md.tce_build = dart_build;
+	ppc_md.tce_free  = dart_free;
+	ppc_md.tce_flush = dart_flush;
+
+	/* Initialize the DART HW */
+	if (dart_init(dn) == 0) {
+		ppc_md.iommu_dev_setup = iommu_dev_setup_dart;
+		ppc_md.iommu_bus_setup = iommu_bus_setup_dart;
+
+		/* Setup pci_dma ops */
+		pci_iommu_init();
+
+		return;
+	}
+
+ bail:
+	/* If init failed, use direct iommu and null setup functions */
+	ppc_md.iommu_dev_setup = iommu_dev_setup_null;
+	ppc_md.iommu_bus_setup = iommu_bus_setup_null;
+
+	/* Setup pci_dma ops */
+	pci_direct_iommu_init();
+}
+
+
+void __init alloc_dart_table(void)
+{
+	/* Only reserve DART space if machine has more than 2GB of RAM
+	 * or if requested with iommu=on on cmdline.
+	 */
+	if (lmb_end_of_DRAM() <= 0x80000000ull && !iommu_force_on)
+		return;
+
+	/* 512 pages (2MB) is max DART tablesize. */
+	dart_tablesize = 1UL << 21;
+	/* 16MB (1 << 24) alignment. We allocate a full 16Mb chuck since we
+	 * will blow up an entire large page anyway in the kernel mapping
+	 */
+	dart_tablebase = (unsigned long)
+		abs_to_virt(lmb_alloc_base(1UL<<24, 1UL<<24, 0x80000000L));
+
+	printk(KERN_INFO "DART table allocated at: %lx\n", dart_tablebase);
+}
Index: linux-work/include/asm-powerpc/iommu.h
===================================================================
--- linux-work.orig/include/asm-powerpc/iommu.h	2005-11-24 17:21:41.000000000 +1100
+++ linux-work/include/asm-powerpc/iommu.h	2005-12-14 12:54:36.000000000 +1100
@@ -56,7 +56,7 @@ struct device_node;
 
 /* Walks all buses and creates iommu tables */
 extern void iommu_setup_pSeries(void);
-extern void iommu_setup_u3(void);
+extern void iommu_setup_dart(void);
 
 /* Frees table for an individual device node */
 extern void iommu_free_table(struct device_node *dn);
@@ -104,7 +104,7 @@ extern void iommu_unmap_single(struct io
 
 extern void iommu_init_early_pSeries(void);
 extern void iommu_init_early_iSeries(void);
-extern void iommu_init_early_u3(void);
+extern void iommu_init_early_dart(void);
 
 #ifdef CONFIG_PCI
 extern void pci_iommu_init(void);
@@ -113,6 +113,6 @@ extern void pci_direct_iommu_init(void);
 static inline void pci_iommu_init(void) { }
 #endif
 
-extern void alloc_u3_dart_table(void);
+extern void alloc_dart_table(void);
 
 #endif /* _ASM_IOMMU_H */

^ permalink raw reply

* Re: how to define BASE_BAUD
From: Debora Liu @ 2005-12-14  1:39 UTC (permalink / raw)
  To: HappyPhot; +Cc: Linuxppc-embedded

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 409 bytes --]

Hello, HappyPhot

In message <2005-12-14 01:19:49 happyphot@gmail.com> you wrote:

>   Can anybody tell me how to define the "BASE_BAUD" value
>for the "struct serial_state rs_table[]" ?
>  It seems has different value for each platform !!

yes, this is different for each platform.
see your crystal used by UART.

¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡Debora Liu
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡deboralh@fel.com.cn
¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡2005-12-14

^ permalink raw reply

* [PATCH 2.6 2/2] usb/input: Add Geyser 2 support to appletouch driver
From: Michael Hanselmann @ 2005-12-13 22:40 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-input, linuxppc-dev, kernel-stuff
In-Reply-To: <20051213223659.GB20017@hansmi.ch>

This patch adds support for the Geyser 2 touchpads used on Post-Oct 2005
Apple PowerBooks to the appletouch driver.

Signed-off-by: Michael Hanselmann <linux-kernel@hansmi.ch>
Acked-by: Rene Nussbaumer <linux-kernel@killerfox.forkbomb.ch>  
Acked-by: Johannes Berg <johannes@sipsolutions.net>  
---
diff -Npur linux-2.6.15-rc5.orig/Documentation/input/appletouch.txt linux-2.6.15-rc5/Documentation/input/appletouch.txt
--- linux-2.6.15-rc5.orig/Documentation/input/appletouch.txt	2005-12-13 00:09:24.000000000 +0100
+++ linux-2.6.15-rc5/Documentation/input/appletouch.txt	2005-12-13 21:28:26.000000000 +0100
@@ -3,7 +3,7 @@ Apple Touchpad Driver (appletouch)
 	Copyright (C) 2005 Stelian Pop <stelian@popies.net>
 
 appletouch is a Linux kernel driver for the USB touchpad found on post
-February 2005 Apple Alu Powerbooks.
+February 2005 and October 2005 Apple Aluminium Powerbooks.
 
 This driver is derived from Johannes Berg's appletrackpad driver[1], but it has
 been improved in some areas:
@@ -13,7 +13,8 @@ been improved in some areas:
 
 Credits go to Johannes Berg for reverse-engineering the touchpad protocol,
 Frank Arnold for further improvements, and Alex Harper for some additional
-information about the inner workings of the touchpad sensors.
+information about the inner workings of the touchpad sensors. Michael
+Hanselmann added support for the October 2005 models.
 
 Usage:
 ------

diff -Npur linux-2.6.15-rc5.orig/drivers/usb/input/appletouch.c linux-2.6.15-rc5/drivers/usb/input/appletouch.c
--- linux-2.6.15-rc5.orig/drivers/usb/input/appletouch.c	2005-12-13 22:44:36.000000000 +0100
+++ linux-2.6.15-rc5/drivers/usb/input/appletouch.c	2005-12-13 22:55:19.000000000 +0100
@@ -17,6 +17,7 @@
  * Nov/Dec 2005 - Michael Hanselmann
  *  o Compile relayfs support only if enabled in the kernel
  *  o Enable relayfs only if requested by the user
+ *  o Added support for new October 2005 PowerBooks (Geyser 2)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -51,6 +52,11 @@
 /* Apple has powerbooks which have the keyboard with different Product IDs */
 #define APPLE_VENDOR_ID		0x05AC
 
+/* These names come from Info.plist in AppleUSBTrackpad.kext */
+#define GEYSER_ANSI_PRODUCT_ID	0x0214
+#define GEYSER_ISO_PRODUCT_ID	0x0215
+#define GEYSER_JIS_PRODUCT_ID	0x0216
+
 #define ATP_DEVICE(prod)					\
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |		\
 		       USB_DEVICE_ID_MATCH_INT_CLASS |		\
@@ -66,7 +72,14 @@ static struct usb_device_id atp_table []
 	{ ATP_DEVICE(0x020F) },
 	{ ATP_DEVICE(0x030A) },
 	{ ATP_DEVICE(0x030B) },
-	{ }					/* Terminating entry */
+
+	/* PowerBooks Oct 2005 */
+	{ ATP_DEVICE(GEYSER_ANSI_PRODUCT_ID) },
+	{ ATP_DEVICE(GEYSER_ISO_PRODUCT_ID) },
+	{ ATP_DEVICE(GEYSER_JIS_PRODUCT_ID) },
+
+	/* Terminating entry */
+	{ }
 };
 MODULE_DEVICE_TABLE (usb, atp_table);
 
@@ -75,9 +88,6 @@ struct rchan* rch = NULL;
 struct rchan_callbacks* rcb = NULL;
 #endif
 
-/* size of a USB urb transfer */
-#define ATP_DATASIZE	81
-
 /*
  * number of sensors. Note that only 16 instead of 26 X (horizontal)
  * sensors exist on 12" and 15" PowerBooks. All models have 16 Y
@@ -127,6 +137,8 @@ struct atp {
 	signed char		xy_old[ATP_XSENSORS + ATP_YSENSORS];
 						/* accumulated sensors */
 	int			xy_acc[ATP_XSENSORS + ATP_YSENSORS];
+	int			overflowwarn;	/* overflow warning printed? */
+	int			datalen;	/* size of an USB urb transfer */
 };
 
 #define dbg_dump(msg, tab) \
@@ -157,6 +169,16 @@ module_param(relayfs, int, 0644);
 MODULE_PARM_DESC(relayfs, "Activate relayfs support");
 #endif
 
+/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
+static inline int atp_is_geyser_2(struct atp *dev)
+{
+	int16_t productId = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+	return (productId == GEYSER_ANSI_PRODUCT_ID) ||
+		(productId == GEYSER_ISO_PRODUCT_ID) ||
+		(productId == GEYSER_JIS_PRODUCT_ID);
+}
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -200,6 +222,13 @@ static void atp_complete(struct urb* urb
 	case 0:
 		/* success */
 		break;
+	case -EOVERFLOW:
+		if(!dev->overflowwarn) {
+			printk("appletouch: OVERFLOW with data "
+				"length %d, actual length is %d\n",
+				dev->datalen, dev->urb->actual_length);
+			dev->overflowwarn = 1;
+		}
 	case -ECONNRESET:
 	case -ENOENT:
 	case -ESHUTDOWN:
@@ -214,7 +243,7 @@ static void atp_complete(struct urb* urb
 	}
 
 	/* drop incomplete datasets */
-	if (dev->urb->actual_length != ATP_DATASIZE) {
+	if (dev->urb->actual_length != dev->datalen) {
 		dprintk("appletouch: incomplete data package.\n");
 		goto exit;
 	}
@@ -227,17 +256,72 @@ static void atp_complete(struct urb* urb
 #endif
 
 	/* reorder the sensors values */
-	for (i = 0; i < 8; i++) {
-		/* X values */
-		dev->xy_cur[i     ] = dev->data[5 * i +  2];
-		dev->xy_cur[i +  8] = dev->data[5 * i +  4];
-		dev->xy_cur[i + 16] = dev->data[5 * i + 42];
-		if (i < 2)
-			dev->xy_cur[i + 24] = dev->data[5 * i + 44];
-
-		/* Y values */
-		dev->xy_cur[i + 26] = dev->data[5 * i +  1];
-		dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+	if (atp_is_geyser_2(dev)) {
+		memset(dev->xy_cur, 0, sizeof(dev->xy_cur));
+
+		/*
+		 * The values are laid out like this:
+		 * Y1, Y2, -, Y3, Y4, -, ...
+		 * '-' is an unused value.
+		 *
+		 * The logic in a loop:
+		 * for (i = 0, j = 19; i < 20; i += 2, j += 3) {
+		 *	dev->xy_cur[i] = dev->data[j];
+		 *	dev->xy_cur[i + 1] = dev->data[j + 1];
+		 * }
+		 *
+		 * This code is called about 100 times per second because it is
+		 * called for each interrupt transfer from the touchpad.
+		 * Therefore it should be as fast as possible. Writing the
+		 * following code in a loop would take about twice the time to
+		 * run if not more.
+		 */
+
+		/* read X values */
+		dev->xy_cur[0] = dev->data[19];
+		dev->xy_cur[1] = dev->data[20];
+		dev->xy_cur[2] = dev->data[22];
+		dev->xy_cur[3] = dev->data[23];
+		dev->xy_cur[4] = dev->data[25];
+		dev->xy_cur[5] = dev->data[26];
+		dev->xy_cur[6] = dev->data[28];
+		dev->xy_cur[7] = dev->data[29];
+		dev->xy_cur[8] = dev->data[31];
+		dev->xy_cur[9] = dev->data[32];
+		dev->xy_cur[10] = dev->data[34];
+		dev->xy_cur[11] = dev->data[35];
+		dev->xy_cur[12] = dev->data[37];
+		dev->xy_cur[13] = dev->data[38];
+		dev->xy_cur[14] = dev->data[40];
+		dev->xy_cur[15] = dev->data[41];
+		dev->xy_cur[16] = dev->data[43];
+		dev->xy_cur[17] = dev->data[44];
+		dev->xy_cur[18] = dev->data[46];
+		dev->xy_cur[19] = dev->data[47];
+
+		/* read Y values */
+		dev->xy_cur[ATP_XSENSORS + 0] = dev->data[1];
+		dev->xy_cur[ATP_XSENSORS + 1] = dev->data[2];
+		dev->xy_cur[ATP_XSENSORS + 2] = dev->data[4];
+		dev->xy_cur[ATP_XSENSORS + 3] = dev->data[5];
+		dev->xy_cur[ATP_XSENSORS + 4] = dev->data[7];
+		dev->xy_cur[ATP_XSENSORS + 5] = dev->data[8];
+		dev->xy_cur[ATP_XSENSORS + 6] = dev->data[10];
+		dev->xy_cur[ATP_XSENSORS + 7] = dev->data[11];
+		dev->xy_cur[ATP_XSENSORS + 8] = dev->data[13];
+	} else {
+		for (i = 0; i < 8; i++) {
+			/* X values */
+			dev->xy_cur[i     ] = dev->data[5 * i +  2];
+			dev->xy_cur[i +  8] = dev->data[5 * i +  4];
+			dev->xy_cur[i + 16] = dev->data[5 * i + 42];
+			if (i < 2)
+				dev->xy_cur[i + 24] = dev->data[5 * i + 44];
+
+			/* Y values */
+			dev->xy_cur[i + 26] = dev->data[5 * i +  1];
+			dev->xy_cur[i + 34] = dev->data[5 * i +  3];
+		}
 	}
 
 	dbg_dump("sample", dev->xy_cur);
@@ -248,16 +332,24 @@ static void atp_complete(struct urb* urb
 		dev->x_old = dev->y_old = -1;
 		memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
 
-		/* 17" Powerbooks have 10 extra X sensors */
-		for (i = 16; i < ATP_XSENSORS; i++)
-			if (dev->xy_cur[i]) {
-				printk("appletouch: 17\" model detected.\n");
+		/* 17" Powerbooks have extra X sensors */
+		for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) {
+			if (!dev->xy_cur[i]) continue;
+
+			printk("appletouch: 17\" model detected.\n");
+			if(atp_is_geyser_2(dev))
+				input_set_abs_params(dev->input, ABS_X, 0,
+						     (20 - 1) *
+						     ATP_XFACT - 1,
+						     ATP_FUZZ, 0);
+			else
 				input_set_abs_params(dev->input, ABS_X, 0,
 						     (ATP_XSENSORS - 1) *
 						     ATP_XFACT - 1,
 						     ATP_FUZZ, 0);
-				break;
-			}
+
+			break;
+		}
 
 		goto exit;
 	}
@@ -314,7 +406,8 @@ static void atp_complete(struct urb* urb
 		memset(dev->xy_acc, 0, sizeof(dev->xy_acc));
 	}
 
-	input_report_key(dev->input, BTN_LEFT, !!dev->data[80]);
+	input_report_key(dev->input, BTN_LEFT,
+			 !!dev->data[dev->datalen - 1]);
 
 	input_sync(dev->input);
 
@@ -355,7 +448,6 @@ static int atp_probe(struct usb_interfac
 	int int_in_endpointAddr = 0;
 	int i, retval = -ENOMEM;
 
-
 	/* set up the endpoint information */
 	/* use only the first interrupt-in endpoint */
 	iface_desc = iface->cur_altsetting;
@@ -385,6 +477,8 @@ static int atp_probe(struct usb_interfac
 
 	dev->udev = udev;
 	dev->input = input_dev;
+	dev->overflowwarn = 0;
+	dev->datalen = (atp_is_geyser_2(dev)?64:81);
 
 	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!dev->urb) {
@@ -392,7 +486,7 @@ static int atp_probe(struct usb_interfac
 		goto err_free_devs;
 	}
 
-	dev->data = usb_buffer_alloc(dev->udev, ATP_DATASIZE, GFP_KERNEL,
+	dev->data = usb_buffer_alloc(dev->udev, dev->datalen, GFP_KERNEL,
 				     &dev->urb->transfer_dma);
 	if (!dev->data) {
 		retval = -ENOMEM;
@@ -401,7 +495,7 @@ static int atp_probe(struct usb_interfac
 
 	usb_fill_int_urb(dev->urb, udev,
 			 usb_rcvintpipe(udev, int_in_endpointAddr),
-			 dev->data, ATP_DATASIZE, atp_complete, dev, 1);
+			 dev->data, dev->datalen, atp_complete, dev, 1);
 
 	usb_make_path(udev, dev->phys, sizeof(dev->phys));
 	strlcat(dev->phys, "/input0", sizeof(dev->phys));
@@ -417,14 +511,25 @@ static int atp_probe(struct usb_interfac
 
 	set_bit(EV_ABS, input_dev->evbit);
 
-	/*
-	 * 12" and 15" Powerbooks only have 16 x sensors,
-	 * 17" models are detected later.
-	 */
-	input_set_abs_params(input_dev, ABS_X, 0,
-			     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0,
-			     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	if (atp_is_geyser_2(dev)) {
+		/*
+		 * Oct 2005 15" PowerBooks have 15 X sensors, 17" are detected
+		 * later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     ((15 - 1) * ATP_XFACT) - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     ((9 - 1) * ATP_YFACT) - 1, ATP_FUZZ, 0);
+	} else {
+		/*
+		 * 12" and 15" Powerbooks only have 16 x sensors,
+		 * 17" models are detected later.
+		 */
+		input_set_abs_params(input_dev, ABS_X, 0,
+				     (16 - 1) * ATP_XFACT - 1, ATP_FUZZ, 0);
+		input_set_abs_params(input_dev, ABS_Y, 0,
+				     (ATP_YSENSORS - 1) * ATP_YFACT - 1, ATP_FUZZ, 0);
+	}
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ATP_PRESSURE, 0, 0);
 
 	set_bit(EV_KEY, input_dev->evbit);
@@ -459,7 +564,7 @@ static void atp_disconnect(struct usb_in
 		usb_kill_urb(dev->urb);
 		input_unregister_device(dev->input);
 		usb_free_urb(dev->urb);
-		usb_buffer_free(dev->udev, ATP_DATASIZE,
+		usb_buffer_free(dev->udev, dev->datalen,
 				dev->data, dev->urb->transfer_dma);
 		kfree(dev);
 	}

^ permalink raw reply

* [PATCH 2.6 1/2] usb/input: Add relayfs support to appletouch driver
From: Michael Hanselmann @ 2005-12-13 22:36 UTC (permalink / raw)
  To: linux-kernel; +Cc: linux-input, linuxppc-dev, kernel-stuff

This patch adds support for relayfs to the appletouch driver to make
debugging easier.

Signed-off-by: Michael Hanselmann <linux-kernel@hansmi.ch>
Acked-by: Rene Nussbaumer <linux-kernel@killerfox.forkbomb.ch>  
Acked-by: Johannes Berg <johannes@sipsolutions.net>  
---
diff -Npur linux-2.6.15-rc5.orig/Documentation/input/appletouch.txt linux-2.6.15-rc5/Documentation/input/appletouch.txt
--- linux-2.6.15-rc5.orig/Documentation/input/appletouch.txt	2005-12-13 00:09:24.000000000 +0100
+++ linux-2.6.15-rc5/Documentation/input/appletouch.txt	2005-12-13 21:28:26.000000000 +0100
@@ -77,6 +78,8 @@ full tracing (each sample is being trace
 		or
 	echo "1" > /sys/module/appletouch/parameters/debug
 
+To make debugging easier, the driver also supports the relayfs filesystem.
+
 Links:
 ------

diff -Npur linux-2.6.15-rc5.orig/drivers/usb/input/appletouch.txt linux-2.6.15-rc5/drivers/usb/input/appletouch.txt
--- linux-2.6.15-rc5.orig/drivers/usb/input/appletouch.c	2005-12-13 00:09:24.000000000 +0100
+++ linux-2.6.15-rc5/drivers/usb/input/appletouch.c	2005-12-13 22:41:28.000000000 +0100
@@ -6,9 +6,18 @@
  * Copyright (C) 2005      Stelian Pop (stelian@popies.net)
  * Copyright (C) 2005      Frank Arnold (frank@scirocco-5v-turbo.de)
  * Copyright (C) 2005      Peter Osterlund (petero2@telia.com)
+ * Copyright (C) 2005      Parag Warudkar (parag.warudkar@gmail.com)
+ * Copyright (C) 2005      Michael Hanselmann (linux-kernel@hansmi.ch)
  *
  * Thanks to Alex Harper <basilisk@foobox.net> for his inputs.
  *
+ * Nov 2005 - Parag Warudkar 
+ *  o Added ability to export data via relayfs
+ *
+ * Nov/Dec 2005 - Michael Hanselmann
+ *  o Compile relayfs support only if enabled in the kernel
+ *  o Enable relayfs only if requested by the user
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -35,6 +44,10 @@
 #include <linux/input.h>
 #include <linux/usb_input.h>
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+#include <linux/relayfs_fs.h>
+#endif
+
 /* Apple has powerbooks which have the keyboard with different Product IDs */
 #define APPLE_VENDOR_ID		0x05AC
 
@@ -57,6 +70,11 @@ static struct usb_device_id atp_table []
 };
 MODULE_DEVICE_TABLE (usb, atp_table);
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+struct rchan* rch = NULL;
+struct rchan_callbacks* rcb = NULL;
+#endif
+
 /* size of a USB urb transfer */
 #define ATP_DATASIZE	81
 
@@ -73,6 +91,7 @@ MODULE_DEVICE_TABLE (usb, atp_table);
 
 /* maximum pressure this driver will report */
 #define ATP_PRESSURE	300
+
 /*
  * multiplication factor for the X and Y coordinates.
  * We try to keep the touchpad aspect ratio while still doing only simple
@@ -124,7 +143,7 @@ struct atp {
 		if (debug) printk(format, ##a);				\
 	} while (0)
 
-MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold");
+MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Parag Warudkar, Michael Hanselmann");
 MODULE_DESCRIPTION("Apple PowerBooks USB touchpad driver");
 MODULE_LICENSE("GPL");
 
@@ -132,6 +151,12 @@ static int debug = 1;
 module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Activate debugging output");
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+static int relayfs = 0;
+module_param(relayfs, int, 0644);
+MODULE_PARM_DESC(relayfs, "Activate relayfs support");
+#endif
+
 static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
 			     int *z, int *fingers)
 {
@@ -194,6 +219,13 @@ static void atp_complete(struct urb* urb
 		goto exit;
 	}
 
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	/* "rch" is NULL if relayfs is not enabled */
+	if (rch && dev->data) {
+		relay_write(rch, dev->data, dev->urb->actual_length);
+	}
+#endif
+
 	/* reorder the sensors values */
 	for (i = 0; i < 8; i++) {
 		/* X values */
@@ -463,11 +495,43 @@ static struct usb_driver atp_driver = {
 
 static int __init atp_init(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	rcb = NULL;
+	rch = NULL;
+
+	if (relayfs) {
+		rcb = kmalloc(sizeof(struct rchan_callbacks), GFP_KERNEL);
+		if (!rcb)
+			return -ENOMEM;
+
+		rcb->subbuf_start = NULL;
+		rcb->buf_mapped = NULL;
+		rcb->buf_unmapped = NULL;
+
+		rch = relay_open("atpdata", NULL, 256, 256, NULL);
+		if (!rch) {
+			kfree(rcb);
+			return -ENOMEM;
+		}
+
+		printk("appletouch: Relayfs enabled.\n");
+	} else {
+		printk("appletouch: Relayfs disabled.\n");
+	}
+#endif
+
 	return usb_register(&atp_driver);
 }
 
 static void __exit atp_exit(void)
 {
+#if defined(CONFIG_RELAYFS_FS) || defined(CONFIG_RELAYFS_FS_MODULE)
+	if(rch)
+		relay_close(rch);
+	if(rcb)
+		kfree(rcb);
+#endif
+
 	usb_deregister(&atp_driver);
 }
 

^ permalink raw reply

* Re: [2.6 patch] don't allow users to set CONFIG_BROKEN=y
From: Russell King @ 2005-12-13 22:01 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: tony.luck, linux-ia64, grundler, matthew, linux-kernel,
	linuxppc-dev, lethal, linux-mtd, dwmw2, kkojima, parisc-linux
In-Reply-To: <20051213201920.GT23349@stusta.de>

On Tue, Dec 13, 2005 at 09:19:20PM +0100, Adrian Bunk wrote:
> On Tue, Dec 13, 2005 at 08:01:06PM +0000, Russell King wrote:
> > That means that the original review was _worthless_.  It wasn't a
> > review at all.
> > 
> > So, what I am trying to get across is the need to show the _full_ set
> > of changes to a default configuratoin when you disable CONFIG_BROKEN,
> > which is trivially producable if you run the script I've already posted.
> > 
> > You can even use that in conjunction with your present patch to produce
> > a patch which shows _exactly_ _everything_ which changes as a result of
> > disabling CONFIG_BROKEN.  Surely giving reviewers the _full_ story is
> > far better than half a story, and should be something that any change
> > to the kernel strives for.
> > 
> > If not, what's the point of the original change?
> 
> The point is that I haven't yet heard any good reason for 
> CONFIG_BROKEN=y in a defconfig.

I'm sorry, I feel like I'm beating my head against a brick wall.  I
have said everything that needs to be said, and made my position on
this patch crystal clear.

The patch to the ARM configuration files is nacked as it stands.
Please go back and rework it along the guidelines I've pointed out
several times in this thread and maybe then it becomes acceptable.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core

^ permalink raw reply

* [PATCH] powerpc: Detect prefetchable windows in pci_process_bridge_OF_ranges
From: Kumar Gala @ 2005-12-13 20:46 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

Added the ability to determine if an outbound window in the PCI host
controller is for prefetchable memory and report it as such.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

---
commit 6a050a749ac14613057a2adec0e3dbaa7697a824
tree 254dedb89aac5444c6d387bd1b6ef20c954538a5
parent 761e102769add7e86d510f7605c06f4a82575015
author Kumar Gala <galak@kernel.crashing.org> Tue, 13 Dec 2005 14:46:34 -0600
committer Kumar Gala <galak@kernel.crashing.org> Tue, 13 Dec 2005 14:46:34 -0600

 arch/ppc/kernel/pci.c |    8 +++++++-
 1 files changed, 7 insertions(+), 1 deletions(-)

diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index df4b11c..8a58fe8 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -941,7 +941,7 @@ pci_process_bridge_OF_ranges(struct pci_
 	while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) {
 		res = NULL;
 		size = ranges[na+4];
-		switch (ranges[0] >> 24) {
+		switch ((ranges[0] >> 24) & 0x3) {
 		case 1:		/* I/O space */
 			if (ranges[2] != 0)
 				break;
@@ -955,6 +955,8 @@ pci_process_bridge_OF_ranges(struct pci_
 			res = &hose->io_resource;
 			res->flags = IORESOURCE_IO;
 			res->start = ranges[2];
+			DBG("PCI: IO 0x%lx -> 0x%lx\n",
+				    res->start, res->start + size - 1);
 			break;
 		case 2:		/* memory space */
 			memno = 0;
@@ -972,7 +974,11 @@ pci_process_bridge_OF_ranges(struct pci_
 			if (memno < 3) {
 				res = &hose->mem_resources[memno];
 				res->flags = IORESOURCE_MEM;
+				if(ranges[0] & 0x40000000)
+					res->flags |= IORESOURCE_PREFETCH;
 				res->start = ranges[na+2];
+				DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno,
+					    res->start, res->start + size - 1);
 			}
 			break;
 		}

^ permalink raw reply related

* [PATCH] powerpc: Provide PCI OF functions even if we dont have true OF
From: Kumar Gala @ 2005-12-13 20:45 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

If we are building an arch/powerpc kernel we dont neccesarily
have a full OF implementation (and thus dont set CONFIG_PPC_OF)
but can use the OF PCI functions

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

---
commit 761e102769add7e86d510f7605c06f4a82575015
tree e62bfa889a1789289e9fc031d8f883cb2291c6a4
parent 5ce33c8a0b8087f0c554a417efb907d35892e58b
author Kumar Gala <galak@kernel.crashing.org> Tue, 13 Dec 2005 14:40:11 -0600
committer Kumar Gala <galak@kernel.crashing.org> Tue, 13 Dec 2005 14:40:11 -0600

 arch/ppc/kernel/pci.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
index af36400..df4b11c 100644
--- a/arch/ppc/kernel/pci.c
+++ b/arch/ppc/kernel/pci.c
@@ -46,7 +46,7 @@ static void pcibios_fixup_resources(stru
 static void fixup_broken_pcnet32(struct pci_dev* dev);
 static int reparent_resources(struct resource *parent, struct resource *res);
 static void fixup_cpc710_pci64(struct pci_dev* dev);
-#ifdef CONFIG_PPC_OF
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_PPC_MERGE)
 static u8* pci_to_OF_bus_map;
 #endif
 
@@ -626,7 +626,7 @@ pcibios_alloc_controller(void)
 	return hose;
 }
 
-#ifdef CONFIG_PPC_OF
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_PPC_MERGE)
 /*
  * Functions below are used on OpenFirmware machines.
  */
@@ -1027,7 +1027,7 @@ void pcibios_make_OF_bus_map(void)
 /* Add sysfs properties */
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_OF
+#if defined(CONFIG_PPC_OF) || defined(CONFIG_PPC_MERGE)
 	device_create_file(&pdev->dev, &dev_attr_devspec);
 #endif /* CONFIG_PPC_OF */
 }

^ permalink raw reply related

* Re: [PATCH] powerpc: Update MPIC workarounds
From: Benjamin Herrenschmidt @ 2005-12-13 20:23 UTC (permalink / raw)
  To: Olof Johansson; +Cc: linuxppc64-dev, linuxppc-dev list
In-Reply-To: <20051213165807.GA7468@pb15.lixom.net>

On Tue, 2005-12-13 at 08:58 -0800, Olof Johansson wrote:
> On Tue, Dec 13, 2005 at 06:04:29PM +1100, Benjamin Herrenschmidt wrote:
> > From: Segher Boessenkool <segher@kernel.crashing.org>
> > 
> > Cleanup the MPIC IO-APIC workarounds, make them a bit more generic,
> > smaller and faster. 
> 
> I really don't like all the hand-coded constants in this code. They're
> all over the place, and there's no descriptions of what they are there
> for. Lots of hardcoded offsets, etc. Since this is a cleanup, wouldn't
> it be a good time to use symbolic constands and/or comment them up a
> bit?

Heh, welcome to segher world :) I'll add more comments & symbolic
constants in the other patch that applies on top of this one.

> > Index: linux-work/arch/powerpc/sysdev/mpic.c
> > ===================================================================
> > --- linux-work.orig/arch/powerpc/sysdev/mpic.c	2005-12-06 16:17:43.000000000 +1100
> > +++ linux-work/arch/powerpc/sysdev/mpic.c	2005-12-07 13:30:45.000000000 +1100
> > @@ -175,57 +175,57 @@ static inline int mpic_is_ht_interrupt(s
> >  	return mpic->fixups[source_no].base != NULL;
> >  }
> >  
> > +
> >  static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
> >  {
> >  	struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
> > -	u32 tmp;
> >  
> >  	spin_lock(&mpic->fixup_lock);
> > -	writeb(0x11 + 2 * fixup->irq, fixup->base);
> > -	tmp = readl(fixup->base + 2);
> > -	writel(tmp | 0x80000000ul, fixup->base + 2);
> > -	/* config writes shouldn't be posted but let's be safe ... */
> > -	(void)readl(fixup->base + 2);
> > +	writeb(0x11 + 2 * fixup->irq, fixup->base + 2);
> > +	writel(fixup->data, fixup->base + 4);
> 
> This seems like a functional change: Previous code wrote at base, new at
> base+2?

Hrm... I have to double check but I think the previous code hard coded
the bases for the 2 known APICs (incuding the +2) while the new code
properly scans the PCI capabilities and thus gets the capability base
instead, which is better (but needs +2 / +4). I suppose I could
pre-offset by 2 at discovery time to avoid an addition but I'm not sure
it's worth it.

Ben.

^ permalink raw reply

* Re: [2.6 patch] don't allow users to set CONFIG_BROKEN=y
From: Adrian Bunk @ 2005-12-13 20:19 UTC (permalink / raw)
  To: Simon Richter, linux-kernel, tony.luck, linux-ia64, matthew,
	grundler, parisc-linux, paulus, linuxppc-dev, lethal, kkojima,
	dwmw2, linux-mtd
In-Reply-To: <20051213200106.GC24094@flint.arm.linux.org.uk>

On Tue, Dec 13, 2005 at 08:01:06PM +0000, Russell King wrote:
> On Tue, Dec 13, 2005 at 07:05:52PM +0100, Adrian Bunk wrote:
> > On Tue, Dec 13, 2005 at 05:31:12PM +0000, Russell King wrote:
> > > The defconfig files in arch/arm/configs are for platform configurations
> > > and are provided by the platform maintainers as a _working_ configuration
> > > for their platform.  They're not "defconfigs".  They got called
> > > "defconfigs" as a result of the kbuild "cleanups".  Please don't confuse
> > > them as such.
> > > 
> > > If, in order to have a working platform configuration, they deem that
> > > CONFIG_BROKEN must be enabled, then that's the way it is.
> > 
> > if a working platform configuration configuration requires 
> > CONFIG_BROKEN=y, the problem is a bug that should be fixed properly.
> 
> Maybe they're only broken for a small subset of platforms, and someone
> added a BROKEN without properly considering whether it should be global
> or not?
> 
> I don't disagree with the overall notion that CONFIG_BROKEN should not
> be set _where_ _possible_.  However, if it needs to be set to get the
> required options, then that's what needs to happen until such time that
> the above is corrected.

Where is the bug report from the person who set CONFIG_BROKEN=y in the 
collie defconfig that the BROKEN dependency on MTD_SHARP was wrong?

> However - and now to the main bug bear - how can we tell what is really
> broken if you _just_ change the default configuration file settings for
> CONFIG_BROKEN?  What happens is that, on review, we see a simple change.
> We'd assume that it has little impact, and we accept that change.
> 
> Maybe a month or two down the line, someone whines that their platform
> doesn't work for some reason, and it's tracked down to this and the
> resulting fallout from disabling CONFIG_BROKEN.

The whining is the bug report the person who set the CONFIG_BROKEN=y in 
the defconfig didn't send.

And things would have been even worse if I had sent a patch erasing 
MTD_SHARP from the kernel because code "both marked as obsolete and 
BROKEN can clearly be removed" and the code was therefore completely 
removed two months before the first person whined?

> That means that the original review was _worthless_.  It wasn't a
> review at all.
> 
> So, what I am trying to get across is the need to show the _full_ set
> of changes to a default configuratoin when you disable CONFIG_BROKEN,
> which is trivially producable if you run the script I've already posted.
> 
> You can even use that in conjunction with your present patch to produce
> a patch which shows _exactly_ _everything_ which changes as a result of
> disabling CONFIG_BROKEN.  Surely giving reviewers the _full_ story is
> far better than half a story, and should be something that any change
> to the kernel strives for.
> 
> If not, what's the point of the original change?

The point is that I haven't yet heard any good reason for 
CONFIG_BROKEN=y in a defconfig.

No, it's not a good reason if someone used it as a workaround instead of 
sending a bug report that would result in a fixing of the wrong BROKEN 
dependency.

Where is the bug report of the person setting CONFIG_BROKEN=y in the 
collie defconfig that the MTD_SHARP dependency on BROKEN was wrong?

> Russell King

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed

^ permalink raw reply

* Re: [2.6 patch] don't allow users to set CONFIG_BROKEN=y
From: Russell King @ 2005-12-13 20:01 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: tony.luck, linux-ia64, grundler, matthew, linux-kernel,
	linuxppc-dev, lethal, linux-mtd, dwmw2, kkojima, parisc-linux
In-Reply-To: <20051213180551.GN23349@stusta.de>

On Tue, Dec 13, 2005 at 07:05:52PM +0100, Adrian Bunk wrote:
> On Tue, Dec 13, 2005 at 05:31:12PM +0000, Russell King wrote:
> > The defconfig files in arch/arm/configs are for platform configurations
> > and are provided by the platform maintainers as a _working_ configuration
> > for their platform.  They're not "defconfigs".  They got called
> > "defconfigs" as a result of the kbuild "cleanups".  Please don't confuse
> > them as such.
> > 
> > If, in order to have a working platform configuration, they deem that
> > CONFIG_BROKEN must be enabled, then that's the way it is.
> 
> if a working platform configuration configuration requires 
> CONFIG_BROKEN=y, the problem is a bug that should be fixed properly.

Maybe they're only broken for a small subset of platforms, and someone
added a BROKEN without properly considering whether it should be global
or not?

I don't disagree with the overall notion that CONFIG_BROKEN should not
be set _where_ _possible_.  However, if it needs to be set to get the
required options, then that's what needs to happen until such time that
the above is corrected.

However - and now to the main bug bear - how can we tell what is really
broken if you _just_ change the default configuration file settings for
CONFIG_BROKEN?  What happens is that, on review, we see a simple change.
We'd assume that it has little impact, and we accept that change.

Maybe a month or two down the line, someone whines that their platform
doesn't work for some reason, and it's tracked down to this and the
resulting fallout from disabling CONFIG_BROKEN.

That means that the original review was _worthless_.  It wasn't a
review at all.

So, what I am trying to get across is the need to show the _full_ set
of changes to a default configuratoin when you disable CONFIG_BROKEN,
which is trivially producable if you run the script I've already posted.

You can even use that in conjunction with your present patch to produce
a patch which shows _exactly_ _everything_ which changes as a result of
disabling CONFIG_BROKEN.  Surely giving reviewers the _full_ story is
far better than half a story, and should be something that any change
to the kernel strives for.

If not, what's the point of the original change?

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core

^ permalink raw reply

* patch pci-export-pci_cfg_space_size.patch added to gregkh-2.6 tree
From: gregkh @ 2005-12-13 19:48 UTC (permalink / raw)
  To: benh, greg, gregkh, linux-pci, linuxppc-dev, linuxppc64-dev,
	paulus
In-Reply-To: <1134457757.6989.195.camel@gaston>


This is a note to let you know that I've just added the patch titled

     Subject: [PATCH] PCI: Export pci_cfg_space_size

to my gregkh-2.6 tree.  Its filename is

     pci-export-pci_cfg_space_size.patch

This tree can be found at 
    http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/

Patches currently in gregkh-2.6 which might be from benh@kernel.crashing.org are

i2c/i2c-drop-driver-owner-and-name-04-macintosh.patch
pci/pci-export-pci_cfg_space_size.patch


>From benh@kernel.crashing.org Mon Dec 12 23:16:21 2005
Subject: [PATCH] PCI: Export pci_cfg_space_size
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: Greg KH <greg@kroah.com>, Paul Mackerras <paulus@samba.org>
Cc: linux-pci <linux-pci@atrey.karlin.mff.cuni.cz>, linuxppc64-dev <linuxppc64-dev@ozlabs.org>, linuxppc-dev list <linuxppc-dev@ozlabs.org>
Date: Tue, 13 Dec 2005 18:09:16 +1100
Message-Id: <1134457757.6989.195.camel@gaston>

The powerpc PCI code sets up the PCI tree without doing config space
accesses in most cases, from the firmware tree. However, it still wants
to call pci_cfg_space_size() under some conditions, thus it needs to
be made non-static (though I don't see a point to export it to modules).

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
 drivers/pci/probe.c |    2 +-
 include/linux/pci.h |    1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

--- gregkh-2.6.orig/drivers/pci/probe.c
+++ gregkh-2.6/drivers/pci/probe.c
@@ -717,7 +717,7 @@ static void pci_release_dev(struct devic
  * reading the dword at 0x100 which must either be 0 or a valid extended
  * capability header.
  */
-static int pci_cfg_space_size(struct pci_dev *dev)
+int pci_cfg_space_size(struct pci_dev *dev)
 {
 	int pos;
 	u32 status;
--- gregkh-2.6.orig/include/linux/pci.h
+++ gregkh-2.6/include/linux/pci.h
@@ -514,6 +514,7 @@ int pci_scan_bridge(struct pci_bus *bus,
 
 void pci_walk_bus(struct pci_bus *top, void (*cb)(struct pci_dev *, void *),
 		  void *userdata);
+int pci_cfg_space_size(struct pci_dev *dev);
 
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 

^ permalink raw reply

* Re: [2.6 patch] don't allow users to set CONFIG_BROKEN=y
From: Jesper Juhl @ 2005-12-13 18:59 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: tony.luck, linux-ia64, grundler, matthew,
	Linux Kernel Development, Adrian Bunk, Linux/PPC Development,
	lethal, linux-mtd, dwmw2, kkojima, parisc-linux
In-Reply-To: <Pine.LNX.4.62.0512131926530.17990@pademelon.sonytel.be>

On 12/13/05, Geert Uytterhoeven <geert@linux-m68k.org> wrote:
> On Tue, 13 Dec 2005, Adrian Bunk wrote:
> > Do not allow people to create configurations with CONFIG_BROKEN=3Dy.
> >
> > The sole reason for CONFIG_BROKEN=3Dy would be if you are working on
> > fixing a broken driver, but in this case editing the Kconfig file is
> > trivial.
> >
> > Never ever should a user enable CONFIG_BROKEN.
>                       ^^^^
> OK, a user, not an expert. Let's assume users don't enable EXPERIMENTAL.
>
> But I'd like to at least have the possibility to enable broken drivers, e=
ven if
> it's just for compile regression tests.
>
I agree, and it's very convenient to be able to enable it in
menuconfig etc. Perhaps CONFIG_BROKEN should just be moved to kernel
hacking instead...?

--
Jesper Juhl <jesper.juhl@gmail.com>
Don't top-post  http://www.catb.org/~esr/jargon/html/T/top-post.html
Plain text mails only, please      http://www.expita.com/nomime.html

^ permalink raw reply

* Re: [2.6 patch] don't allow users to set CONFIG_BROKEN=y
From: Adrian Bunk @ 2005-12-13 18:51 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: tony.luck, linux-ia64, grundler, matthew,
	Linux Kernel Development, Linux/PPC Development, lethal,
	linux-mtd, dwmw2, kkojima, parisc-linux
In-Reply-To: <Pine.LNX.4.62.0512131926530.17990@pademelon.sonytel.be>

On Tue, Dec 13, 2005 at 07:28:41PM +0100, Geert Uytterhoeven wrote:
> On Tue, 13 Dec 2005, Adrian Bunk wrote:
> > Do not allow people to create configurations with CONFIG_BROKEN=y.
> > 
> > The sole reason for CONFIG_BROKEN=y would be if you are working on 
> > fixing a broken driver, but in this case editing the Kconfig file is 
> > trivial.
> > 
> > Never ever should a user enable CONFIG_BROKEN.
>                       ^^^^
> OK, a user, not an expert. Let's assume users don't enable EXPERIMENTAL.

Let's assume users don't have any hardware (e.g. several SATA drivers) 
that requires EXPERIMENTAL...

> But I'd like to at least have the possibility to enable broken drivers, even if
> it's just for compile regression tests.

If a kernel developer really wants to enable BROKEN drivers, my patch 
still gives them the possibility to do so with a trivial edit of
init/Kconfig.

> Gr{oetje,eeting}s,
> 
> 						Geert

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed

^ permalink raw reply

* Re: [2.6 patch] don't allow users to set CONFIG_BROKEN=y
From: Geert Uytterhoeven @ 2005-12-13 18:28 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: tony.luck, linux-ia64, grundler, matthew,
	Linux Kernel Development, Linux/PPC Development, lethal,
	linux-mtd, dwmw2, kkojima, parisc-linux
In-Reply-To: <20051213180551.GN23349@stusta.de>

On Tue, 13 Dec 2005, Adrian Bunk wrote:
> Do not allow people to create configurations with CONFIG_BROKEN=y.
> 
> The sole reason for CONFIG_BROKEN=y would be if you are working on 
> fixing a broken driver, but in this case editing the Kconfig file is 
> trivial.
> 
> Never ever should a user enable CONFIG_BROKEN.
                      ^^^^
OK, a user, not an expert. Let's assume users don't enable EXPERIMENTAL.

But I'd like to at least have the possibility to enable broken drivers, even if
it's just for compile regression tests.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
							    -- Linus Torvalds

^ permalink raw reply

* MPC5200 RTC
From: bennett78 @ 2005-12-13 18:10 UTC (permalink / raw)
  To: Wolfgang Denk; +Cc: linuxppc-embedded
In-Reply-To: <20051207195112.06457353A66@atlas.denx.de>


[-- Attachment #1.1: Type: text/plain, Size: 1147 bytes --]

 *  The /dev/rtc interface will block on reads until an interrupt
 *  has been received. If a RTC interrupt has already happened,
 *  it will output an unsigned long and then block.

Paul Gortmaker's  rtctest (included below) works really well on my x86
machine  (driver/char/rtc.c) as a nice way for a user process to wait on 
ticks
of a programable frequency (via ioctl).

Under Denx linuxppc_2_4_devel MPC5200 I've tried:
    driver/char/rtc.c - kernel panics
       seems to need a RTC_IRQ to be defined
       include/linux/mc14681rtc.h mentions #define RTC_IRQ 8 ?
    CONFIG_PPC_RTC also panics
    driver/char/genrtc.c (with #define CONFIG_GEN_RTC_X)
       sort of works but I get the following:
       gen_rtc_interrupt: system delaying clock ticks?

The internal MPC5200 RTC doesn't seem supported.
I see a lot of references to external RTCs, probably because
the standby power for the 5200 is high. I would like to
use a timer as the RTC interrupt and add an external RTC
later as a time reference (none on Lite5200 dev brd).
How best can I assign a GPTx as an interrupt? other than re-write
genrtc.c?

thanks,
Frank Bennett




*//*


[-- Attachment #1.2: Type: text/html, Size: 1820 bytes --]

[-- Attachment #2: rtctest.c --]
[-- Type: text/x-c, Size: 4562 bytes --]

/*
 *	Real Time Clock Driver Test/Example Program
 *
 *	Compile with:
 *		gcc -s -Wall -Wstrict-prototypes rtctest.c -o rtctest
 *
 *	Copyright (C) 1996, Paul Gortmaker.
 *
 *	Released under the GNU General Public License, version 2,
 *	included herein by reference.
 *
 */
#define spinlock_t int

#include <stdio.h>
#include <linux/mc146818rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

void main(void) {

int i, fd, retval, irqcount = 0;
unsigned long tmp, data;
struct rtc_time rtc_tm;

fd = open ("/dev/rtc", O_RDONLY);

if (fd ==  -1) {
	perror("/dev/rtc");
	exit(errno);
}

fprintf(stderr, "\n\t\t\tRTC Driver Test Example.\n\n");

/* Turn on update interrupts (one per second) */
retval = ioctl(fd, RTC_UIE_ON, 0);
if (retval == -1) {
	perror("ioctl");
	exit(errno);
}

fprintf(stderr, "Counting 5 update (1/sec) interrupts from reading /dev/rtc:");
fflush(stderr);
for (i=1; i<6; i++) {
	/* This read will block */
	retval = read(fd, &data, sizeof(unsigned long));
	if (retval == -1) {
		perror("read");
		exit(errno);
	}
	fprintf(stderr, " %d",i);
	fflush(stderr);
	irqcount++;
}

fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
fflush(stderr);
for (i=1; i<6; i++) {
	struct timeval tv = {5, 0};	/* 5 second timeout on select */
	fd_set readfds;

	FD_ZERO(&readfds);
	FD_SET(fd, &readfds);
	/* The select will wait until an RTC interrupt happens. */
	retval = select(fd+1, &readfds, NULL, NULL, &tv);
	if (retval == -1) {
		perror("select");
		exit(errno);
	}
	/* This read won't block unlike the select-less case above. */
	retval = read(fd, &data, sizeof(unsigned long));
	if (retval == -1) {
		perror("read");
		exit(errno);
	}
	fprintf(stderr, " %d",i);
	fflush(stderr);
	irqcount++;
}

/* Turn off update interrupts */
retval = ioctl(fd, RTC_UIE_OFF, 0);
if (retval == -1) {
	perror("ioctl");
	exit(errno);
}

/* Read the RTC time/date */
retval = ioctl(fd, RTC_RD_TIME, &rtc_tm);
if (retval == -1) {
	perror("ioctl");
	exit(errno);
}

fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
	rtc_tm.tm_mday, rtc_tm.tm_mon + 1, rtc_tm.tm_year + 1900,
	rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);

/* Set the alarm to 5 sec in the future, and check for rollover */
rtc_tm.tm_sec += 5;
if (rtc_tm.tm_sec >= 60) {
	rtc_tm.tm_sec %= 60;
	rtc_tm.tm_min++;
}
if  (rtc_tm.tm_min == 60) {
	rtc_tm.tm_min = 0;
	rtc_tm.tm_hour++;
}
if  (rtc_tm.tm_hour == 24)
	rtc_tm.tm_hour = 0;

retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
if (retval == -1) {
	perror("ioctl");
	exit(errno);
}

/* Read the current alarm settings */
retval = ioctl(fd, RTC_ALM_READ, &rtc_tm);
if (retval == -1) {
	perror("ioctl");
	exit(errno);
}

fprintf(stderr, "Alarm time now set to %02d:%02d:%02d.\n",
	rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);

/* Enable alarm interrupts */
retval = ioctl(fd, RTC_AIE_ON, 0);
if (retval == -1) {
	perror("ioctl");
	exit(errno);
}

fprintf(stderr, "Waiting 5 seconds for alarm...");
fflush(stderr);
/* This blocks until the alarm ring causes an interrupt */
retval = read(fd, &data, sizeof(unsigned long));
if (retval == -1) {
	perror("read");
	exit(errno);
}
irqcount++;
fprintf(stderr, " okay. Alarm rang.\n");

/* Disable alarm interrupts */
retval = ioctl(fd, RTC_AIE_OFF, 0);
if (retval == -1) {
	perror("ioctl");
	exit(errno);
}

/* Read periodic IRQ rate */
retval = ioctl(fd, RTC_IRQP_READ, &tmp);
if (retval == -1) {
	perror("ioctl");
	exit(errno);
}
fprintf(stderr, "\nPeriodic IRQ rate was %ldHz.\n", tmp);

fprintf(stderr, "Counting 20 interrupts at:");
fflush(stderr);

/* The frequencies 128Hz, 256Hz, ... 8192Hz are only allowed for root. */
for (tmp=2; tmp<=64; tmp*=2) {

	retval = ioctl(fd, RTC_IRQP_SET, tmp);
	if (retval == -1) {
		perror("ioctl");
		exit(errno);
	}

	fprintf(stderr, "\n%ldHz:\t", tmp);
	fflush(stderr);

	/* Enable periodic interrupts */
	retval = ioctl(fd, RTC_PIE_ON, 0);
	if (retval == -1) {
		perror("ioctl");
		exit(errno);
	}

	for (i=1; i<21; i++) {
		/* This blocks */
		retval = read(fd, &data, sizeof(unsigned long));
		if (retval == -1) {
			perror("read");
			exit(errno);
		}
		fprintf(stderr, " %d",i);
		fflush(stderr);
		irqcount++;
	}

	/* Disable periodic interrupts */
	retval = ioctl(fd, RTC_PIE_OFF, 0);
	if (retval == -1) {
		perror("ioctl");
		exit(errno);
	}
}

fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
fprintf(stderr, "\nTyping \"cat /proc/interrupts\" will show %d more events on IRQ 8.\n\n",
								 irqcount);

close(fd);

} /* end main */


^ permalink raw reply

* [2.6 patch] don't allow users to set CONFIG_BROKEN=y
From: Adrian Bunk @ 2005-12-13 18:05 UTC (permalink / raw)
  To: Simon Richter, linux-kernel, tony.luck, linux-ia64, matthew,
	grundler, parisc-linux, paulus, linuxppc-dev, lethal, kkojima,
	dwmw2, linux-mtd
In-Reply-To: <20051213173112.GA24094@flint.arm.linux.org.uk>

On Tue, Dec 13, 2005 at 05:31:12PM +0000, Russell King wrote:
> On Tue, Dec 13, 2005 at 03:00:01PM +0100, Adrian Bunk wrote:
> > defconfig files are virtually never a configuration for the kernel they 
> > are shipped with since they aren't updated every time some configuration 
> > option is changed.
> > 
> > Consider a defconfig with CONFIG_BROKEN=n, and a driver that is enabled 
> > in this defconfig gets for some reason marked as broken in the Kconfig 
> > file - this will give exactly the same result as the one you describe.
> 
> Adrian,

Hi Russell,

> The defconfig files in arch/arm/configs are for platform configurations
> and are provided by the platform maintainers as a _working_ configuration
> for their platform.  They're not "defconfigs".  They got called
> "defconfigs" as a result of the kbuild "cleanups".  Please don't confuse
> them as such.
> 
> If, in order to have a working platform configuration, they deem that
> CONFIG_BROKEN must be enabled, then that's the way it is.

if a working platform configuration configuration requires 
CONFIG_BROKEN=y, the problem is a bug that should be fixed properly.

We are talking about a class of bugs that can usually be easily fixed if 
reported - so why aren't they reported?

The MTD_SHARP case is a good example, because otherwise I might have 
soon sent a patch that would have removed this driver with the rationale
"both marked as obsolete and BROKEN can clearly be removed".

> Therefore, I request that either you leave the ARM platform configurations
> well alone, or follow the advice I've given so that we can _properly_
> assess the impact of your changes.

Unless someone can tell me a valid case for enabling BROKEN that does 
both create a working configuration and not hide real issues it seems 
the approch below might be the way to go.

Yes, you might dislike this at the first sight.

But if you consider that although this might result in a short-term 
breakage of some configurations, this will also result in proper bug 
reports and fixing of the wrong BROKEN dependency bugs, I hope you agree 
that this will actually improve the situation.

> Thanks.

cu
Adrian


<--  snip  -->


Do not allow people to create configurations with CONFIG_BROKEN=y.

The sole reason for CONFIG_BROKEN=y would be if you are working on 
fixing a broken driver, but in this case editing the Kconfig file is 
trivial.

Never ever should a user enable CONFIG_BROKEN.


Signed-off-by: Adrian Bunk <bunk@stusta.de>

--- linux-2.6.15-rc5-mm2-full/init/Kconfig.old	2005-12-13 18:48:40.000000000 +0100
+++ linux-2.6.15-rc5-mm2-full/init/Kconfig	2005-12-13 18:48:52.000000000 +0100
@@ -31,19 +31,8 @@
 	  you say Y here, you will be offered the choice of using features or
 	  drivers that are currently considered to be in the alpha-test phase.
 
-config CLEAN_COMPILE
-	bool "Select only drivers expected to compile cleanly" if EXPERIMENTAL
-	default y
-	help
-	  Select this option if you don't even want to see the option
-	  to configure known-broken drivers.
-
-	  If unsure, say Y
-
 config BROKEN
 	bool
-	depends on !CLEAN_COMPILE
-	default y
 
 config BROKEN_ON_SMP
 	bool

^ permalink raw reply

* Re: ibm emac driver update
From: Simon Haynes @ 2005-12-13 18:44 UTC (permalink / raw)
  To: Eugene Surovegin; +Cc: linuxppc-embedded
In-Reply-To: <20051212181457.GA30505@gate.ebshome.net>

On Monday 12 December 2005 18:14, Eugene Surovegin wrote:
> On Mon, Dec 12, 2005 at 05:26:34PM +0000, Simon Haynes wrote:
> > I am running a Ebony board with linux-2.6.12-rc1 and I amd having
> > intermittent network problems. Having searched the archives it would seem
> > that the driver for the IBM EMAC is buggy ?
> >
> > I have tried to patch my kernel with
> >
> > http://kernel.ebsname.net/emac/4xx_napi_emac.diff
> >
> > I believe this is almost a total driver re-write. Is this correct ?
> >
> > After having a couple of problems applying the patch, Kconfig and
> > ibm_emac_core.c. I fixed up the original code and applied the patch.
> >
> > On compilation the build fails with missing references to kzalloc,
> > which I guess I could easily fix with kmalloc and memset.
> >
> > However there is also an undefined field,  dcr_base, in the
> > ocp_func_mal_data structure.  This structure appears to be defined in
> > include/asm/ibm_ocp.h and this file does not appear to be changed by the
> > patch. I guess this patch is for a later kernel.
> >
> > Can anyone point me in the direction of a suitable patch for this kernel
> > ?
>
> I'm not sure about 2.6.12-rc1, but you can try GIT tree/patches at
> http://kernel.ebshome.net.
>
> Hint: you can assume that in addition to emac_3-2.6-28.diff, there are
> also emac_3-2.6-NN.diff (NN < 28) on my website which were made for
> earlier kernel versions :).
>
> Alternatively, you can backport all relevant stuff from current 2.6 or
> you can pay someone to do this for you.


I have eventually got git going. I am not familiar with it but following a 
tutorial I did

git clone rsync://kernel.ebshome.net/linux-2.6-emac.git
cd linux-2.6-emac
git checkout

I then ran find looking for a patches dir and could not find one.

Could you please tell me how to locate the emac_3-2.6-NN.diff files.

Cheers

Simon
 

^ permalink raw reply

* Re: [2.6 patch] defconfig's shouldn't set CONFIG_BROKEN=y
From: Russell King @ 2005-12-13 17:31 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: tony.luck, linux-ia64, grundler, matthew, linux-kernel,
	linuxppc-dev, lethal, linux-mtd, dwmw2, kkojima, parisc-linux
In-Reply-To: <20051213140001.GG23349@stusta.de>

On Tue, Dec 13, 2005 at 03:00:01PM +0100, Adrian Bunk wrote:
> defconfig files are virtually never a configuration for the kernel they 
> are shipped with since they aren't updated every time some configuration 
> option is changed.
> 
> Consider a defconfig with CONFIG_BROKEN=n, and a driver that is enabled 
> in this defconfig gets for some reason marked as broken in the Kconfig 
> file - this will give exactly the same result as the one you describe.

Adrian,

The defconfig files in arch/arm/configs are for platform configurations
and are provided by the platform maintainers as a _working_ configuration
for their platform.  They're not "defconfigs".  They got called
"defconfigs" as a result of the kbuild "cleanups".  Please don't confuse
them as such.

If, in order to have a working platform configuration, they deem that
CONFIG_BROKEN must be enabled, then that's the way it is.

Therefore, I request that either you leave the ARM platform configurations
well alone, or follow the advice I've given so that we can _properly_
assess the impact of your changes.

Thanks.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 Serial core

^ permalink raw reply

* how to define BASE_BAUD
From: HappyPhot @ 2005-12-13 17:19 UTC (permalink / raw)
  To: linuxppc-embedded

Hi,
   Can anybody tell me how to define the "BASE_BAUD" value
for the "struct serial_state rs_table[]" ?
  It seems has different value for each platform !!

thank you,
/HappyPhot

^ permalink raw reply

* Re: [PATCH] powerpc: Update MPIC workarounds
From: Olof Johansson @ 2005-12-13 16:58 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc64-dev, linuxppc-dev list
In-Reply-To: <1134457469.6989.189.camel@gaston>

On Tue, Dec 13, 2005 at 06:04:29PM +1100, Benjamin Herrenschmidt wrote:
> From: Segher Boessenkool <segher@kernel.crashing.org>
> 
> Cleanup the MPIC IO-APIC workarounds, make them a bit more generic,
> smaller and faster. 

I really don't like all the hand-coded constants in this code. They're
all over the place, and there's no descriptions of what they are there
for. Lots of hardcoded offsets, etc. Since this is a cleanup, wouldn't
it be a good time to use symbolic constands and/or comment them up a
bit?

> Index: linux-work/arch/powerpc/sysdev/mpic.c
> ===================================================================
> --- linux-work.orig/arch/powerpc/sysdev/mpic.c	2005-12-06 16:17:43.000000000 +1100
> +++ linux-work/arch/powerpc/sysdev/mpic.c	2005-12-07 13:30:45.000000000 +1100
> @@ -175,57 +175,57 @@ static inline int mpic_is_ht_interrupt(s
>  	return mpic->fixups[source_no].base != NULL;
>  }
>  
> +
>  static inline void mpic_apic_end_irq(struct mpic *mpic, unsigned int source_no)
>  {
>  	struct mpic_irq_fixup *fixup = &mpic->fixups[source_no];
> -	u32 tmp;
>  
>  	spin_lock(&mpic->fixup_lock);
> -	writeb(0x11 + 2 * fixup->irq, fixup->base);
> -	tmp = readl(fixup->base + 2);
> -	writel(tmp | 0x80000000ul, fixup->base + 2);
> -	/* config writes shouldn't be posted but let's be safe ... */
> -	(void)readl(fixup->base + 2);
> +	writeb(0x11 + 2 * fixup->irq, fixup->base + 2);
> +	writel(fixup->data, fixup->base + 4);

This seems like a functional change: Previous code wrote at base, new at
base+2?


-Olof

^ permalink raw reply

* Re: chrdevs[] explained
From: Kumar Gala @ 2005-12-13 14:40 UTC (permalink / raw)
  To: Gabe.Johnson; +Cc: linuxppc-embedded
In-Reply-To: <OFDEA31089.DE015378-ON862570D5.005B4F12-862570D5.005B7940@microware.com>


On Dec 12, 2005, at 10:38 AM, Gabe.Johnson@radisys.com wrote:

>
> Could someone explain to me the chrdevs array found in fs/ 
> char_dev.c how does that get populated and with what does it get  
> populated?

This is a pretty generic kernel question, I would suggest posting to  
linux-kernel as it not really powerpc specific.

- kumar

^ permalink raw reply

* Re: [2.6 patch] defconfig's shouldn't set CONFIG_BROKEN=y
From: Adrian Bunk @ 2005-12-13 14:00 UTC (permalink / raw)
  To: Simon Richter
  Cc: tony.luck, linux-ia64, grundler, matthew, linux-kernel,
	linuxppc-dev, lethal, linux-mtd, dwmw2, kkojima, parisc-linux
In-Reply-To: <439ECDCC.80707@hogyros.de>

On Tue, Dec 13, 2005 at 02:34:04PM +0100, Simon Richter wrote:

> Hi,

Hi Simon,

> Adrian Bunk wrote:
> 
> >>It's a problem introduced by your patch because the resulting defconfig
> >>file becomes _wrong_ by your change, and other changes in the defconfig
> >>are thereby hidden.
> >>...
> 
> >No, CONFIG_BROKEN=y in a defconfig file is a bug.
> 
> Indeed, but that's not the point. A defconfig file should be the result 
> of running one of the various configuration targets; yours are 
> hand-patched. If you run the defconfig target, it will copy the config 
> file and run oldconfig, thus resulting in a different configuration file 
> (because options may now be gone and hence disabled) than what was in 
> the defconfig, and thus people may come to the wrong conclusion that if 
> a driver is enabled in a defconfig file, it will be built.

defconfig files are virtually never a configuration for the kernel they 
are shipped with since they aren't updated every time some configuration 
option is changed.

Consider a defconfig with CONFIG_BROKEN=n, and a driver that is enabled 
in this defconfig gets for some reason marked as broken in the Kconfig 
file - this will give exactly the same result as the one you describe.

>    Simon

cu
Adrian

-- 

       "Is there not promise of rain?" Ling Tan asked suddenly out
        of the darkness. There had been need of rain for many days.
       "Only a promise," Lao Er said.
                                       Pearl S. Buck - Dragon Seed

^ permalink raw reply

* Re: ibm emac driver update
From: Simon Haynes @ 2005-12-13 14:35 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <20051212181457.GA30505@gate.ebshome.net>

Eugine,

Thanks for the reply. I am not familiar with git and I do not
have it installed on my system. I have looked for rpms and
tried to build git. It seems that I will need to make a lot of changes
to my system to get this going.

In a response from Wolfgang he lists a url which can be used to access 
his git tree via a browser. I can not find these patch files on his git tree
but I was wondering if you made the files available in a similar way.

Alternatively can you mail the file to me ?

Or can you tell me if the files are somewhere on

http://www.denx.de/cgi-bin/gitweb.cgi?p=linux-2.6-denx.git

If not I guess I will just have to get all the bits together to run
git and learn how to drive it.

Many Thanks

Simon.


On Monday 12 December 2005 18:14, Eugene Surovegin wrote:
> On Mon, Dec 12, 2005 at 05:26:34PM +0000, Simon Haynes wrote:
> > I am running a Ebony board with linux-2.6.12-rc1 and I amd having
> > intermittent network problems. Having searched the archives it would seem
> > that the driver for the IBM EMAC is buggy ?
> >
> > I have tried to patch my kernel with
> >
> > http://kernel.ebsname.net/emac/4xx_napi_emac.diff
> >
> > I believe this is almost a total driver re-write. Is this correct ?
> >
> > After having a couple of problems applying the patch, Kconfig and
> > ibm_emac_core.c. I fixed up the original code and applied the patch.
> >
> > On compilation the build fails with missing references to kzalloc,
> > which I guess I could easily fix with kmalloc and memset.
> >
> > However there is also an undefined field,  dcr_base, in the
> > ocp_func_mal_data structure.  This structure appears to be defined in
> > include/asm/ibm_ocp.h and this file does not appear to be changed by the
> > patch. I guess this patch is for a later kernel.
> >
> > Can anyone point me in the direction of a suitable patch for this kernel
> > ?
>
> I'm not sure about 2.6.12-rc1, but you can try GIT tree/patches at
> http://kernel.ebshome.net.
>
> Hint: you can assume that in addition to emac_3-2.6-28.diff, there are
> also emac_3-2.6-NN.diff (NN < 28) on my website which were made for
> earlier kernel versions :).
>
> Alternatively, you can backport all relevant stuff from current 2.6 or
> you can pay someone to do this for you.

^ permalink raw reply

* Re: [2.6 patch] defconfig's shouldn't set CONFIG_BROKEN=y
From: Simon Richter @ 2005-12-13 13:34 UTC (permalink / raw)
  To: Adrian Bunk
  Cc: tony.luck, linux-ia64, grundler, matthew, linux-kernel,
	linuxppc-dev, lethal, linux-mtd, dwmw2, kkojima, parisc-linux
In-Reply-To: <20051213001028.GS23349@stusta.de>

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

Hi,

Adrian Bunk wrote:

>>It's a problem introduced by your patch because the resulting defconfig
>>file becomes _wrong_ by your change, and other changes in the defconfig
>>are thereby hidden.
>>...

> No, CONFIG_BROKEN=y in a defconfig file is a bug.

Indeed, but that's not the point. A defconfig file should be the result 
of running one of the various configuration targets; yours are 
hand-patched. If you run the defconfig target, it will copy the config 
file and run oldconfig, thus resulting in a different configuration file 
(because options may now be gone and hence disabled) than what was in 
the defconfig, and thus people may come to the wrong conclusion that if 
a driver is enabled in a defconfig file, it will be built.

    Simon

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 307 bytes --]

^ 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