Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[PATCH] ppc64: Fix booting on latest G5 models

The latest speedbumped Apple G5 models have a "bug" in the Open Firmware
device tree that lacks the proper interrupt routing information for the
northbridge i2c controller. Apple's driver silently falls back into a
sub-optimal "polled" mode (heh, maybe they didn't even notice the bug
because of that :), our driver didn't properly check and crashes :(

This patch fixes our driver to not crash, and adds code to the
prom_init() OF trampoline code that detects the "bug" and adds the
missing information back for this chipset revision. This fixes booting
and thermal control on these models.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Benjamin Herrenschmidt and committed by
Linus Torvalds
1263cc67 b5c44c21

+48 -1
+43 -1
arch/ppc64/kernel/prom_init.c
··· 1750 1750 prom_printf("Device tree struct 0x%x -> 0x%x\n", 1751 1751 RELOC(dt_struct_start), RELOC(dt_struct_end)); 1752 1752 1753 - } 1753 + } 1754 + 1755 + 1756 + static void __init fixup_device_tree(void) 1757 + { 1758 + unsigned long offset = reloc_offset(); 1759 + phandle u3, i2c, mpic; 1760 + u32 u3_rev; 1761 + u32 interrupts[2]; 1762 + u32 parent; 1763 + 1764 + /* Some G5s have a missing interrupt definition, fix it up here */ 1765 + u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); 1766 + if ((long)u3 <= 0) 1767 + return; 1768 + i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); 1769 + if ((long)i2c <= 0) 1770 + return; 1771 + mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); 1772 + if ((long)mpic <= 0) 1773 + return; 1774 + 1775 + /* check if proper rev of u3 */ 1776 + if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0) 1777 + return; 1778 + if (u3_rev != 0x35) 1779 + return; 1780 + /* does it need fixup ? */ 1781 + if (prom_getproplen(i2c, "interrupts") > 0) 1782 + return; 1783 + /* interrupt on this revision of u3 is number 0 and level */ 1784 + interrupts[0] = 0; 1785 + interrupts[1] = 1; 1786 + prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); 1787 + parent = (u32)mpic; 1788 + prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); 1789 + } 1790 + 1754 1791 1755 1792 static void __init prom_find_boot_cpu(void) 1756 1793 { ··· 1955 1918 prom_setprop(_prom->chosen, "linux,tce-alloc-end", 1956 1919 PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end))); 1957 1920 } 1921 + 1922 + /* 1923 + * Fixup any known bugs in the device-tree 1924 + */ 1925 + fixup_device_tree(); 1958 1926 1959 1927 /* 1960 1928 * Now finally create the flattened device-tree
+5
drivers/i2c/busses/i2c-keywest.c
··· 516 516 u32 *psteps, *prate; 517 517 int rc; 518 518 519 + if (np->n_intrs < 1 || np->n_addrs < 1) { 520 + printk(KERN_ERR "%s: Missing interrupt or address !\n", 521 + np->full_name); 522 + return -ENODEV; 523 + } 519 524 if (pmac_low_i2c_lock(np)) 520 525 return -ENODEV; 521 526