aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/prom_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel/prom_init.c')
-rw-r--r--arch/ppc64/kernel/prom_init.c93
1 files changed, 59 insertions, 34 deletions
diff --git a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
index dbbe6c79d8da..122283a1d39a 100644
--- a/arch/ppc64/kernel/prom_init.c
+++ b/arch/ppc64/kernel/prom_init.c
@@ -892,7 +892,10 @@ static void __init prom_init_mem(void)
892 if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR ) 892 if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
893 RELOC(alloc_top) = RELOC(rmo_top); 893 RELOC(alloc_top) = RELOC(rmo_top);
894 else 894 else
895 RELOC(alloc_top) = RELOC(rmo_top) = min(0x40000000ul, RELOC(ram_top)); 895 /* Some RS64 machines have buggy firmware where claims up at 1GB
896 * fails. Cap at 768MB as a workaround. Still plenty of room.
897 */
898 RELOC(alloc_top) = RELOC(rmo_top) = min(0x30000000ul, RELOC(ram_top));
896 899
897 prom_printf("memory layout at init:\n"); 900 prom_printf("memory layout at init:\n");
898 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); 901 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
@@ -1534,7 +1537,8 @@ static unsigned long __init dt_find_string(char *str)
1534 */ 1537 */
1535#define MAX_PROPERTY_NAME 64 1538#define MAX_PROPERTY_NAME 64
1536 1539
1537static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start, 1540static void __init scan_dt_build_strings(phandle node,
1541 unsigned long *mem_start,
1538 unsigned long *mem_end) 1542 unsigned long *mem_end)
1539{ 1543{
1540 unsigned long offset = reloc_offset(); 1544 unsigned long offset = reloc_offset();
@@ -1547,16 +1551,21 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1547 /* get and store all property names */ 1551 /* get and store all property names */
1548 prev_name = RELOC(""); 1552 prev_name = RELOC("");
1549 for (;;) { 1553 for (;;) {
1550 int rc;
1551
1552 /* 64 is max len of name including nul. */ 1554 /* 64 is max len of name including nul. */
1553 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1); 1555 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
1554 rc = call_prom("nextprop", 3, 1, node, prev_name, namep); 1556 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
1555 if (rc != 1) {
1556 /* No more nodes: unwind alloc */ 1557 /* No more nodes: unwind alloc */
1557 *mem_start = (unsigned long)namep; 1558 *mem_start = (unsigned long)namep;
1558 break; 1559 break;
1559 } 1560 }
1561
1562 /* skip "name" */
1563 if (strcmp(namep, RELOC("name")) == 0) {
1564 *mem_start = (unsigned long)namep;
1565 prev_name = RELOC("name");
1566 continue;
1567 }
1568 /* get/create string entry */
1560 soff = dt_find_string(namep); 1569 soff = dt_find_string(namep);
1561 if (soff != 0) { 1570 if (soff != 0) {
1562 *mem_start = (unsigned long)namep; 1571 *mem_start = (unsigned long)namep;
@@ -1571,7 +1580,7 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1571 1580
1572 /* do all our children */ 1581 /* do all our children */
1573 child = call_prom("child", 1, 1, node); 1582 child = call_prom("child", 1, 1, node);
1574 while (child != (phandle)0) { 1583 while (child != 0) {
1575 scan_dt_build_strings(child, mem_start, mem_end); 1584 scan_dt_build_strings(child, mem_start, mem_end);
1576 child = call_prom("peer", 1, 1, child); 1585 child = call_prom("peer", 1, 1, child);
1577 } 1586 }
@@ -1580,16 +1589,13 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
1580static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start, 1589static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1581 unsigned long *mem_end) 1590 unsigned long *mem_end)
1582{ 1591{
1583 int l, align;
1584 phandle child; 1592 phandle child;
1585 char *namep, *prev_name, *sstart, *p, *ep; 1593 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
1586 unsigned long soff; 1594 unsigned long soff;
1587 unsigned char *valp; 1595 unsigned char *valp;
1588 unsigned long offset = reloc_offset(); 1596 unsigned long offset = reloc_offset();
1589 char pname[MAX_PROPERTY_NAME]; 1597 static char pname[MAX_PROPERTY_NAME];
1590 char *path; 1598 int l;
1591
1592 path = RELOC(prom_scratch);
1593 1599
1594 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end); 1600 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
1595 1601
@@ -1599,23 +1605,33 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1599 namep, *mem_end - *mem_start); 1605 namep, *mem_end - *mem_start);
1600 if (l >= 0) { 1606 if (l >= 0) {
1601 /* Didn't fit? Get more room. */ 1607 /* Didn't fit? Get more room. */
1602 if (l+1 > *mem_end - *mem_start) { 1608 if ((l+1) > (*mem_end - *mem_start)) {
1603 namep = make_room(mem_start, mem_end, l+1, 1); 1609 namep = make_room(mem_start, mem_end, l+1, 1);
1604 call_prom("package-to-path", 3, 1, node, namep, l); 1610 call_prom("package-to-path", 3, 1, node, namep, l);
1605 } 1611 }
1606 namep[l] = '\0'; 1612 namep[l] = '\0';
1613
1607 /* Fixup an Apple bug where they have bogus \0 chars in the 1614 /* Fixup an Apple bug where they have bogus \0 chars in the
1608 * middle of the path in some properties 1615 * middle of the path in some properties
1609 */ 1616 */
1610 for (p = namep, ep = namep + l; p < ep; p++) 1617 for (p = namep, ep = namep + l; p < ep; p++)
1611 if (*p == '\0') { 1618 if (*p == '\0') {
1612 memmove(p, p+1, ep - p); 1619 memmove(p, p+1, ep - p);
1613 ep--; l--; 1620 ep--; l--; p--;
1614 } 1621 }
1615 *mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4); 1622
1623 /* now try to extract the unit name in that mess */
1624 for (p = namep, lp = NULL; *p; p++)
1625 if (*p == '/')
1626 lp = p + 1;
1627 if (lp != NULL)
1628 memmove(namep, lp, strlen(lp) + 1);
1629 *mem_start = _ALIGN(((unsigned long) namep) +
1630 strlen(namep) + 1, 4);
1616 } 1631 }
1617 1632
1618 /* get it again for debugging */ 1633 /* get it again for debugging */
1634 path = RELOC(prom_scratch);
1619 memset(path, 0, PROM_SCRATCH_SIZE); 1635 memset(path, 0, PROM_SCRATCH_SIZE);
1620 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1); 1636 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1621 1637
@@ -1623,23 +1639,27 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1623 prev_name = RELOC(""); 1639 prev_name = RELOC("");
1624 sstart = (char *)RELOC(dt_string_start); 1640 sstart = (char *)RELOC(dt_string_start);
1625 for (;;) { 1641 for (;;) {
1626 int rc; 1642 if (call_prom("nextprop", 3, 1, node, prev_name,
1627 1643 RELOC(pname)) != 1)
1628 rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
1629 if (rc != 1)
1630 break; 1644 break;
1631 1645
1646 /* skip "name" */
1647 if (strcmp(RELOC(pname), RELOC("name")) == 0) {
1648 prev_name = RELOC("name");
1649 continue;
1650 }
1651
1632 /* find string offset */ 1652 /* find string offset */
1633 soff = dt_find_string(pname); 1653 soff = dt_find_string(RELOC(pname));
1634 if (soff == 0) { 1654 if (soff == 0) {
1635 prom_printf("WARNING: Can't find string index for <%s>, node %s\n", 1655 prom_printf("WARNING: Can't find string index for"
1636 pname, path); 1656 " <%s>, node %s\n", RELOC(pname), path);
1637 break; 1657 break;
1638 } 1658 }
1639 prev_name = sstart + soff; 1659 prev_name = sstart + soff;
1640 1660
1641 /* get length */ 1661 /* get length */
1642 l = call_prom("getproplen", 2, 1, node, pname); 1662 l = call_prom("getproplen", 2, 1, node, RELOC(pname));
1643 1663
1644 /* sanity checks */ 1664 /* sanity checks */
1645 if (l == PROM_ERROR) 1665 if (l == PROM_ERROR)
@@ -1648,7 +1668,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1648 prom_printf("WARNING: ignoring large property "); 1668 prom_printf("WARNING: ignoring large property ");
1649 /* It seems OF doesn't null-terminate the path :-( */ 1669 /* It seems OF doesn't null-terminate the path :-( */
1650 prom_printf("[%s] ", path); 1670 prom_printf("[%s] ", path);
1651 prom_printf("%s length 0x%x\n", pname, l); 1671 prom_printf("%s length 0x%x\n", RELOC(pname), l);
1652 continue; 1672 continue;
1653 } 1673 }
1654 1674
@@ -1658,17 +1678,16 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1658 dt_push_token(soff, mem_start, mem_end); 1678 dt_push_token(soff, mem_start, mem_end);
1659 1679
1660 /* push property content */ 1680 /* push property content */
1661 align = (l >= 8) ? 8 : 4; 1681 valp = make_room(mem_start, mem_end, l, 4);
1662 valp = make_room(mem_start, mem_end, l, align); 1682 call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
1663 call_prom("getprop", 4, 1, node, pname, valp, l);
1664 *mem_start = _ALIGN(*mem_start, 4); 1683 *mem_start = _ALIGN(*mem_start, 4);
1665 } 1684 }
1666 1685
1667 /* Add a "linux,phandle" property. */ 1686 /* Add a "linux,phandle" property. */
1668 soff = dt_find_string(RELOC("linux,phandle")); 1687 soff = dt_find_string(RELOC("linux,phandle"));
1669 if (soff == 0) 1688 if (soff == 0)
1670 prom_printf("WARNING: Can't find string index for <linux-phandle>" 1689 prom_printf("WARNING: Can't find string index for"
1671 " node %s\n", path); 1690 " <linux-phandle> node %s\n", path);
1672 else { 1691 else {
1673 dt_push_token(OF_DT_PROP, mem_start, mem_end); 1692 dt_push_token(OF_DT_PROP, mem_start, mem_end);
1674 dt_push_token(4, mem_start, mem_end); 1693 dt_push_token(4, mem_start, mem_end);
@@ -1679,7 +1698,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1679 1698
1680 /* do all our children */ 1699 /* do all our children */
1681 child = call_prom("child", 1, 1, node); 1700 child = call_prom("child", 1, 1, node);
1682 while (child != (phandle)0) { 1701 while (child != 0) {
1683 scan_dt_build_struct(child, mem_start, mem_end); 1702 scan_dt_build_struct(child, mem_start, mem_end);
1684 child = call_prom("peer", 1, 1, child); 1703 child = call_prom("peer", 1, 1, child);
1685 } 1704 }
@@ -1718,7 +1737,8 @@ static void __init flatten_device_tree(void)
1718 1737
1719 /* Build header and make room for mem rsv map */ 1738 /* Build header and make room for mem rsv map */
1720 mem_start = _ALIGN(mem_start, 4); 1739 mem_start = _ALIGN(mem_start, 4);
1721 hdr = make_room(&mem_start, &mem_end, sizeof(struct boot_param_header), 4); 1740 hdr = make_room(&mem_start, &mem_end,
1741 sizeof(struct boot_param_header), 4);
1722 RELOC(dt_header_start) = (unsigned long)hdr; 1742 RELOC(dt_header_start) = (unsigned long)hdr;
1723 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8); 1743 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
1724 1744
@@ -1731,11 +1751,11 @@ static void __init flatten_device_tree(void)
1731 namep = make_room(&mem_start, &mem_end, 16, 1); 1751 namep = make_room(&mem_start, &mem_end, 16, 1);
1732 strcpy(namep, RELOC("linux,phandle")); 1752 strcpy(namep, RELOC("linux,phandle"));
1733 mem_start = (unsigned long)namep + strlen(namep) + 1; 1753 mem_start = (unsigned long)namep + strlen(namep) + 1;
1734 RELOC(dt_string_end) = mem_start;
1735 1754
1736 /* Build string array */ 1755 /* Build string array */
1737 prom_printf("Building dt strings...\n"); 1756 prom_printf("Building dt strings...\n");
1738 scan_dt_build_strings(root, &mem_start, &mem_end); 1757 scan_dt_build_strings(root, &mem_start, &mem_end);
1758 RELOC(dt_string_end) = mem_start;
1739 1759
1740 /* Build structure */ 1760 /* Build structure */
1741 mem_start = PAGE_ALIGN(mem_start); 1761 mem_start = PAGE_ALIGN(mem_start);
@@ -1750,9 +1770,11 @@ static void __init flatten_device_tree(void)
1750 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start); 1770 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
1751 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start); 1771 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
1752 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start); 1772 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
1773 hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);
1753 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start); 1774 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
1754 hdr->version = OF_DT_VERSION; 1775 hdr->version = OF_DT_VERSION;
1755 hdr->last_comp_version = 1; 1776 /* Version 16 is not backward compatible */
1777 hdr->last_comp_version = 0x10;
1756 1778
1757 /* Reserve the whole thing and copy the reserve map in, we 1779 /* Reserve the whole thing and copy the reserve map in, we
1758 * also bump mem_reserve_cnt to cause further reservations to 1780 * also bump mem_reserve_cnt to cause further reservations to
@@ -1808,6 +1830,9 @@ static void __init fixup_device_tree(void)
1808 /* does it need fixup ? */ 1830 /* does it need fixup ? */
1809 if (prom_getproplen(i2c, "interrupts") > 0) 1831 if (prom_getproplen(i2c, "interrupts") > 0)
1810 return; 1832 return;
1833
1834 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
1835
1811 /* interrupt on this revision of u3 is number 0 and level */ 1836 /* interrupt on this revision of u3 is number 0 and level */
1812 interrupts[0] = 0; 1837 interrupts[0] = 0;
1813 interrupts[1] = 1; 1838 interrupts[1] = 1;