diff options
Diffstat (limited to 'arch/ppc64/kernel/prom_init.c')
-rw-r--r-- | arch/ppc64/kernel/prom_init.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c index 35ec42de962e..3de950de3671 100644 --- a/arch/ppc64/kernel/prom_init.c +++ b/arch/ppc64/kernel/prom_init.c | |||
@@ -1566,7 +1566,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
1566 | { | 1566 | { |
1567 | int l, align; | 1567 | int l, align; |
1568 | phandle child; | 1568 | phandle child; |
1569 | char *namep, *prev_name, *sstart; | 1569 | char *namep, *prev_name, *sstart, *p, *ep; |
1570 | unsigned long soff; | 1570 | unsigned long soff; |
1571 | unsigned char *valp; | 1571 | unsigned char *valp; |
1572 | unsigned long offset = reloc_offset(); | 1572 | unsigned long offset = reloc_offset(); |
@@ -1588,6 +1588,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, | |||
1588 | call_prom("package-to-path", 3, 1, node, namep, l); | 1588 | call_prom("package-to-path", 3, 1, node, namep, l); |
1589 | } | 1589 | } |
1590 | namep[l] = '\0'; | 1590 | namep[l] = '\0'; |
1591 | /* Fixup an Apple bug where they have bogus \0 chars in the | ||
1592 | * middle of the path in some properties | ||
1593 | */ | ||
1594 | for (p = namep, ep = namep + l; p < ep; p++) | ||
1595 | if (*p == '\0') { | ||
1596 | memmove(p, p+1, ep - p); | ||
1597 | ep--; l--; | ||
1598 | } | ||
1591 | *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); | 1599 | *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); |
1592 | } | 1600 | } |
1593 | 1601 | ||
@@ -1750,7 +1758,44 @@ static void __init flatten_device_tree(void) | |||
1750 | prom_printf("Device tree struct 0x%x -> 0x%x\n", | 1758 | prom_printf("Device tree struct 0x%x -> 0x%x\n", |
1751 | RELOC(dt_struct_start), RELOC(dt_struct_end)); | 1759 | RELOC(dt_struct_start), RELOC(dt_struct_end)); |
1752 | 1760 | ||
1753 | } | 1761 | } |
1762 | |||
1763 | |||
1764 | static void __init fixup_device_tree(void) | ||
1765 | { | ||
1766 | unsigned long offset = reloc_offset(); | ||
1767 | phandle u3, i2c, mpic; | ||
1768 | u32 u3_rev; | ||
1769 | u32 interrupts[2]; | ||
1770 | u32 parent; | ||
1771 | |||
1772 | /* Some G5s have a missing interrupt definition, fix it up here */ | ||
1773 | u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000")); | ||
1774 | if ((long)u3 <= 0) | ||
1775 | return; | ||
1776 | i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000")); | ||
1777 | if ((long)i2c <= 0) | ||
1778 | return; | ||
1779 | mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000")); | ||
1780 | if ((long)mpic <= 0) | ||
1781 | return; | ||
1782 | |||
1783 | /* check if proper rev of u3 */ | ||
1784 | if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0) | ||
1785 | return; | ||
1786 | if (u3_rev != 0x35) | ||
1787 | return; | ||
1788 | /* does it need fixup ? */ | ||
1789 | if (prom_getproplen(i2c, "interrupts") > 0) | ||
1790 | return; | ||
1791 | /* interrupt on this revision of u3 is number 0 and level */ | ||
1792 | interrupts[0] = 0; | ||
1793 | interrupts[1] = 1; | ||
1794 | prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts)); | ||
1795 | parent = (u32)mpic; | ||
1796 | prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent)); | ||
1797 | } | ||
1798 | |||
1754 | 1799 | ||
1755 | static void __init prom_find_boot_cpu(void) | 1800 | static void __init prom_find_boot_cpu(void) |
1756 | { | 1801 | { |
@@ -1844,6 +1889,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long | |||
1844 | &getprop_rval, sizeof(getprop_rval)); | 1889 | &getprop_rval, sizeof(getprop_rval)); |
1845 | 1890 | ||
1846 | /* | 1891 | /* |
1892 | * On pSeries, inform the firmware about our capabilities | ||
1893 | */ | ||
1894 | if (RELOC(of_platform) & PLATFORM_PSERIES) | ||
1895 | prom_send_capabilities(); | ||
1896 | |||
1897 | /* | ||
1847 | * On pSeries, copy the CPU hold code | 1898 | * On pSeries, copy the CPU hold code |
1848 | */ | 1899 | */ |
1849 | if (RELOC(of_platform) & PLATFORM_PSERIES) | 1900 | if (RELOC(of_platform) & PLATFORM_PSERIES) |
@@ -1920,6 +1971,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long | |||
1920 | } | 1971 | } |
1921 | 1972 | ||
1922 | /* | 1973 | /* |
1974 | * Fixup any known bugs in the device-tree | ||
1975 | */ | ||
1976 | fixup_device_tree(); | ||
1977 | |||
1978 | /* | ||
1923 | * Now finally create the flattened device-tree | 1979 | * Now finally create the flattened device-tree |
1924 | */ | 1980 | */ |
1925 | prom_printf("copying OF device tree ...\n"); | 1981 | prom_printf("copying OF device tree ...\n"); |