Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1beb6a7d authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Paul Mackerras
Browse files

[PATCH] powerpc: Experimental support for new G5 Macs (#2)



This 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: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent cd0c7f06
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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

+29 −6
Original line number Diff line number Diff line
@@ -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 device_node *node, struct pci_dev *dev)
	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 device_node *node, struct pci_dev *dev)
		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 device_node *node,
	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;
@@ -381,6 +387,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node,
		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 device_node *node,

	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_node *node,
	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 device_node *node,
	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 device_node *node,
	}
	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_controller *hose)
	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_controller *hose)

	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 file *file,
 * 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;
+23 −3
Original line number Diff line number Diff line
@@ -298,6 +298,16 @@ static int __devinit finish_node_interrupts(struct device_node *np,
	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_interrupts(struct device_node *np,
	}

	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_interrupts(struct device_node *np,
	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_interrupts(struct device_node *np,
			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_interrupts(struct device_node *np,
#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_interrupts(struct device_node *np,
			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);
+2 −0
Original line number Diff line number Diff line
@@ -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 */
+2 −2
Original line number Diff line number Diff line
@@ -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 platform)
	 * 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;
}
Loading