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