Skip to content

Commit

Permalink
[PATCH] powerpc: Experimental support for new G5 Macs (#2)
Browse files Browse the repository at this point in the history
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: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Jan 9, 2006
1 parent cd0c7f0 commit 1beb6a7
Show file tree
Hide file tree
Showing 20 changed files with 807 additions and 377 deletions.
1 change: 1 addition & 0 deletions arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
35 changes: 29 additions & 6 deletions arch/powerpc/kernel/pci_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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")) {
Expand All @@ -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); */
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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)
Expand All @@ -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",
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
26 changes: 23 additions & 3 deletions arch/powerpc/kernel/prom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
/*
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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"
Expand All @@ -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];
}

Expand All @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions arch/powerpc/kernel/udbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
4 changes: 2 additions & 2 deletions arch/powerpc/platforms/maple/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down Expand Up @@ -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;
}
Expand Down
Loading

0 comments on commit 1beb6a7

Please sign in to comment.