aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-05-22 20:03:52 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-22 20:34:42 -0400
commit1263cc67c09bc7f913a6877f3ba0427f0b76617e (patch)
tree5b713315560487f8c288820b17061fe27016c2cc
parentb5c44c2147a447f77e07fecdb087ae288e1f4e40 (diff)
[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>
-rw-r--r--arch/ppc64/kernel/prom_init.c44
-rw-r--r--drivers/i2c/busses/i2c-keywest.c5
2 files changed, 48 insertions, 1 deletions
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index 35ec42de962e..6f79b7b9b445 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -1750,7 +1750,44 @@ static void __init flatten_device_tree(void)
1750 prom_printf("Device tree struct 0x%x -> 0x%x\n", 1750 prom_printf("Device tree struct 0x%x -> 0x%x\n",
1751 RELOC(dt_struct_start), RELOC(dt_struct_end)); 1751 RELOC(dt_struct_start), RELOC(dt_struct_end));
1752 1752
1753 } 1753}
1754
1755
1756static 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
1755static void __init prom_find_boot_cpu(void) 1792static void __init prom_find_boot_cpu(void)
1756{ 1793{
@@ -1920,6 +1957,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long
1920 } 1957 }
1921 1958
1922 /* 1959 /*
1960 * Fixup any known bugs in the device-tree
1961 */
1962 fixup_device_tree();
1963
1964 /*
1923 * Now finally create the flattened device-tree 1965 * Now finally create the flattened device-tree
1924 */ 1966 */
1925 prom_printf("copying OF device tree ...\n"); 1967 prom_printf("copying OF device tree ...\n");
diff --git a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
index dd0d4c463146..867d443e7133 100644
--- a/drivers/i2c/busses/i2c-keywest.c
+++ b/drivers/i2c/busses/i2c-keywest.c
@@ -516,6 +516,11 @@ create_iface(struct device_node *np, struct device *dev)
516 u32 *psteps, *prate; 516 u32 *psteps, *prate;
517 int rc; 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 if (pmac_low_i2c_lock(np)) 524 if (pmac_low_i2c_lock(np))
520 return -ENODEV; 525 return -ENODEV;
521 526