diff options
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r-- | arch/powerpc/kernel/prom.c | 167 |
1 files changed, 47 insertions, 120 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 8d52b23348bd..caef555f2dc0 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -390,18 +390,19 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, | |||
390 | if (allnextpp) { | 390 | if (allnextpp) { |
391 | pp->name = "name"; | 391 | pp->name = "name"; |
392 | pp->length = sz; | 392 | pp->length = sz; |
393 | pp->value = (unsigned char *)(pp + 1); | 393 | pp->value = pp + 1; |
394 | *prev_pp = pp; | 394 | *prev_pp = pp; |
395 | prev_pp = &pp->next; | 395 | prev_pp = &pp->next; |
396 | memcpy(pp->value, ps, sz - 1); | 396 | memcpy(pp->value, ps, sz - 1); |
397 | ((char *)pp->value)[sz - 1] = 0; | 397 | ((char *)pp->value)[sz - 1] = 0; |
398 | DBG("fixed up name for %s -> %s\n", pathp, pp->value); | 398 | DBG("fixed up name for %s -> %s\n", pathp, |
399 | (char *)pp->value); | ||
399 | } | 400 | } |
400 | } | 401 | } |
401 | if (allnextpp) { | 402 | if (allnextpp) { |
402 | *prev_pp = NULL; | 403 | *prev_pp = NULL; |
403 | np->name = get_property(np, "name", NULL); | 404 | np->name = of_get_property(np, "name", NULL); |
404 | np->type = get_property(np, "device_type", NULL); | 405 | np->type = of_get_property(np, "device_type", NULL); |
405 | 406 | ||
406 | if (!np->name) | 407 | if (!np->name) |
407 | np->name = "<NULL>"; | 408 | np->name = "<NULL>"; |
@@ -719,6 +720,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
719 | const char *uname, int depth, void *data) | 720 | const char *uname, int depth, void *data) |
720 | { | 721 | { |
721 | unsigned long *lprop; | 722 | unsigned long *lprop; |
723 | u32 *prop; | ||
722 | unsigned long l; | 724 | unsigned long l; |
723 | char *p; | 725 | char *p; |
724 | 726 | ||
@@ -760,6 +762,22 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
760 | crashk_res.end = crashk_res.start + *lprop - 1; | 762 | crashk_res.end = crashk_res.start + *lprop - 1; |
761 | #endif | 763 | #endif |
762 | 764 | ||
765 | #ifdef CONFIG_BLK_DEV_INITRD | ||
766 | DBG("Looking for initrd properties... "); | ||
767 | prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l); | ||
768 | if (prop) { | ||
769 | initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4)); | ||
770 | prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l); | ||
771 | if (prop) { | ||
772 | initrd_end = (unsigned long)__va(of_read_ulong(prop, l/4)); | ||
773 | initrd_below_start_ok = 1; | ||
774 | } else { | ||
775 | initrd_start = 0; | ||
776 | } | ||
777 | } | ||
778 | DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end); | ||
779 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
780 | |||
763 | /* Retreive command line */ | 781 | /* Retreive command line */ |
764 | p = of_get_flat_dt_prop(node, "bootargs", &l); | 782 | p = of_get_flat_dt_prop(node, "bootargs", &l); |
765 | if (p != NULL && l > 0) | 783 | if (p != NULL && l > 0) |
@@ -926,6 +944,12 @@ static void __init early_reserve_mem(void) | |||
926 | self_size = initial_boot_params->totalsize; | 944 | self_size = initial_boot_params->totalsize; |
927 | lmb_reserve(self_base, self_size); | 945 | lmb_reserve(self_base, self_size); |
928 | 946 | ||
947 | #ifdef CONFIG_BLK_DEV_INITRD | ||
948 | /* then reserve the initrd, if any */ | ||
949 | if (initrd_start && (initrd_end > initrd_start)) | ||
950 | lmb_reserve(__pa(initrd_start), initrd_end - initrd_start); | ||
951 | #endif /* CONFIG_BLK_DEV_INITRD */ | ||
952 | |||
929 | #ifdef CONFIG_PPC32 | 953 | #ifdef CONFIG_PPC32 |
930 | /* | 954 | /* |
931 | * Handle the case where we might be booting from an old kexec | 955 | * Handle the case where we might be booting from an old kexec |
@@ -954,9 +978,6 @@ static void __init early_reserve_mem(void) | |||
954 | size = *(reserve_map++); | 978 | size = *(reserve_map++); |
955 | if (size == 0) | 979 | if (size == 0) |
956 | break; | 980 | break; |
957 | /* skip if the reservation is for the blob */ | ||
958 | if (base == self_base && size == self_size) | ||
959 | continue; | ||
960 | DBG("reserving: %llx -> %llx\n", base, size); | 981 | DBG("reserving: %llx -> %llx\n", base, size); |
961 | lmb_reserve(base, size); | 982 | lmb_reserve(base, size); |
962 | } | 983 | } |
@@ -1021,102 +1042,46 @@ void __init early_init_devtree(void *params) | |||
1021 | 1042 | ||
1022 | #undef printk | 1043 | #undef printk |
1023 | 1044 | ||
1024 | int | 1045 | int of_n_addr_cells(struct device_node* np) |
1025 | prom_n_addr_cells(struct device_node* np) | ||
1026 | { | 1046 | { |
1027 | const int *ip; | 1047 | const int *ip; |
1028 | do { | 1048 | do { |
1029 | if (np->parent) | 1049 | if (np->parent) |
1030 | np = np->parent; | 1050 | np = np->parent; |
1031 | ip = get_property(np, "#address-cells", NULL); | 1051 | ip = of_get_property(np, "#address-cells", NULL); |
1032 | if (ip != NULL) | 1052 | if (ip != NULL) |
1033 | return *ip; | 1053 | return *ip; |
1034 | } while (np->parent); | 1054 | } while (np->parent); |
1035 | /* No #address-cells property for the root node, default to 1 */ | 1055 | /* No #address-cells property for the root node, default to 1 */ |
1036 | return 1; | 1056 | return 1; |
1037 | } | 1057 | } |
1038 | EXPORT_SYMBOL(prom_n_addr_cells); | 1058 | EXPORT_SYMBOL(of_n_addr_cells); |
1039 | 1059 | ||
1040 | int | 1060 | int of_n_size_cells(struct device_node* np) |
1041 | prom_n_size_cells(struct device_node* np) | ||
1042 | { | 1061 | { |
1043 | const int* ip; | 1062 | const int* ip; |
1044 | do { | 1063 | do { |
1045 | if (np->parent) | 1064 | if (np->parent) |
1046 | np = np->parent; | 1065 | np = np->parent; |
1047 | ip = get_property(np, "#size-cells", NULL); | 1066 | ip = of_get_property(np, "#size-cells", NULL); |
1048 | if (ip != NULL) | 1067 | if (ip != NULL) |
1049 | return *ip; | 1068 | return *ip; |
1050 | } while (np->parent); | 1069 | } while (np->parent); |
1051 | /* No #size-cells property for the root node, default to 1 */ | 1070 | /* No #size-cells property for the root node, default to 1 */ |
1052 | return 1; | 1071 | return 1; |
1053 | } | 1072 | } |
1054 | EXPORT_SYMBOL(prom_n_size_cells); | 1073 | EXPORT_SYMBOL(of_n_size_cells); |
1055 | |||
1056 | /** | ||
1057 | * Construct and return a list of the device_nodes with a given name. | ||
1058 | */ | ||
1059 | struct device_node *find_devices(const char *name) | ||
1060 | { | ||
1061 | struct device_node *head, **prevp, *np; | ||
1062 | |||
1063 | prevp = &head; | ||
1064 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1065 | if (np->name != 0 && strcasecmp(np->name, name) == 0) { | ||
1066 | *prevp = np; | ||
1067 | prevp = &np->next; | ||
1068 | } | ||
1069 | } | ||
1070 | *prevp = NULL; | ||
1071 | return head; | ||
1072 | } | ||
1073 | EXPORT_SYMBOL(find_devices); | ||
1074 | |||
1075 | /** | ||
1076 | * Construct and return a list of the device_nodes with a given type. | ||
1077 | */ | ||
1078 | struct device_node *find_type_devices(const char *type) | ||
1079 | { | ||
1080 | struct device_node *head, **prevp, *np; | ||
1081 | |||
1082 | prevp = &head; | ||
1083 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1084 | if (np->type != 0 && strcasecmp(np->type, type) == 0) { | ||
1085 | *prevp = np; | ||
1086 | prevp = &np->next; | ||
1087 | } | ||
1088 | } | ||
1089 | *prevp = NULL; | ||
1090 | return head; | ||
1091 | } | ||
1092 | EXPORT_SYMBOL(find_type_devices); | ||
1093 | |||
1094 | /** | ||
1095 | * Returns all nodes linked together | ||
1096 | */ | ||
1097 | struct device_node *find_all_nodes(void) | ||
1098 | { | ||
1099 | struct device_node *head, **prevp, *np; | ||
1100 | |||
1101 | prevp = &head; | ||
1102 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1103 | *prevp = np; | ||
1104 | prevp = &np->next; | ||
1105 | } | ||
1106 | *prevp = NULL; | ||
1107 | return head; | ||
1108 | } | ||
1109 | EXPORT_SYMBOL(find_all_nodes); | ||
1110 | 1074 | ||
1111 | /** Checks if the given "compat" string matches one of the strings in | 1075 | /** Checks if the given "compat" string matches one of the strings in |
1112 | * the device's "compatible" property | 1076 | * the device's "compatible" property |
1113 | */ | 1077 | */ |
1114 | int device_is_compatible(const struct device_node *device, const char *compat) | 1078 | int of_device_is_compatible(const struct device_node *device, |
1079 | const char *compat) | ||
1115 | { | 1080 | { |
1116 | const char* cp; | 1081 | const char* cp; |
1117 | int cplen, l; | 1082 | int cplen, l; |
1118 | 1083 | ||
1119 | cp = get_property(device, "compatible", &cplen); | 1084 | cp = of_get_property(device, "compatible", &cplen); |
1120 | if (cp == NULL) | 1085 | if (cp == NULL) |
1121 | return 0; | 1086 | return 0; |
1122 | while (cplen > 0) { | 1087 | while (cplen > 0) { |
@@ -1129,7 +1094,7 @@ int device_is_compatible(const struct device_node *device, const char *compat) | |||
1129 | 1094 | ||
1130 | return 0; | 1095 | return 0; |
1131 | } | 1096 | } |
1132 | EXPORT_SYMBOL(device_is_compatible); | 1097 | EXPORT_SYMBOL(of_device_is_compatible); |
1133 | 1098 | ||
1134 | 1099 | ||
1135 | /** | 1100 | /** |
@@ -1143,51 +1108,13 @@ int machine_is_compatible(const char *compat) | |||
1143 | 1108 | ||
1144 | root = of_find_node_by_path("/"); | 1109 | root = of_find_node_by_path("/"); |
1145 | if (root) { | 1110 | if (root) { |
1146 | rc = device_is_compatible(root, compat); | 1111 | rc = of_device_is_compatible(root, compat); |
1147 | of_node_put(root); | 1112 | of_node_put(root); |
1148 | } | 1113 | } |
1149 | return rc; | 1114 | return rc; |
1150 | } | 1115 | } |
1151 | EXPORT_SYMBOL(machine_is_compatible); | 1116 | EXPORT_SYMBOL(machine_is_compatible); |
1152 | 1117 | ||
1153 | /** | ||
1154 | * Construct and return a list of the device_nodes with a given type | ||
1155 | * and compatible property. | ||
1156 | */ | ||
1157 | struct device_node *find_compatible_devices(const char *type, | ||
1158 | const char *compat) | ||
1159 | { | ||
1160 | struct device_node *head, **prevp, *np; | ||
1161 | |||
1162 | prevp = &head; | ||
1163 | for (np = allnodes; np != 0; np = np->allnext) { | ||
1164 | if (type != NULL | ||
1165 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) | ||
1166 | continue; | ||
1167 | if (device_is_compatible(np, compat)) { | ||
1168 | *prevp = np; | ||
1169 | prevp = &np->next; | ||
1170 | } | ||
1171 | } | ||
1172 | *prevp = NULL; | ||
1173 | return head; | ||
1174 | } | ||
1175 | EXPORT_SYMBOL(find_compatible_devices); | ||
1176 | |||
1177 | /** | ||
1178 | * Find the device_node with a given full_name. | ||
1179 | */ | ||
1180 | struct device_node *find_path_device(const char *path) | ||
1181 | { | ||
1182 | struct device_node *np; | ||
1183 | |||
1184 | for (np = allnodes; np != 0; np = np->allnext) | ||
1185 | if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) | ||
1186 | return np; | ||
1187 | return NULL; | ||
1188 | } | ||
1189 | EXPORT_SYMBOL(find_path_device); | ||
1190 | |||
1191 | /******* | 1118 | /******* |
1192 | * | 1119 | * |
1193 | * New implementation of the OF "find" APIs, return a refcounted | 1120 | * New implementation of the OF "find" APIs, return a refcounted |
@@ -1280,7 +1207,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, | |||
1280 | if (type != NULL | 1207 | if (type != NULL |
1281 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) | 1208 | && !(np->type != 0 && strcasecmp(np->type, type) == 0)) |
1282 | continue; | 1209 | continue; |
1283 | if (device_is_compatible(np, compatible) && of_node_get(np)) | 1210 | if (of_device_is_compatible(np, compatible) && of_node_get(np)) |
1284 | break; | 1211 | break; |
1285 | } | 1212 | } |
1286 | of_node_put(from); | 1213 | of_node_put(from); |
@@ -1527,8 +1454,8 @@ static int of_finish_dynamic_node(struct device_node *node) | |||
1527 | int err = 0; | 1454 | int err = 0; |
1528 | const phandle *ibm_phandle; | 1455 | const phandle *ibm_phandle; |
1529 | 1456 | ||
1530 | node->name = get_property(node, "name", NULL); | 1457 | node->name = of_get_property(node, "name", NULL); |
1531 | node->type = get_property(node, "device_type", NULL); | 1458 | node->type = of_get_property(node, "device_type", NULL); |
1532 | 1459 | ||
1533 | if (!parent) { | 1460 | if (!parent) { |
1534 | err = -ENODEV; | 1461 | err = -ENODEV; |
@@ -1542,7 +1469,7 @@ static int of_finish_dynamic_node(struct device_node *node) | |||
1542 | return -ENODEV; | 1469 | return -ENODEV; |
1543 | 1470 | ||
1544 | /* fix up new node's linux_phandle field */ | 1471 | /* fix up new node's linux_phandle field */ |
1545 | if ((ibm_phandle = get_property(node, "ibm,phandle", NULL))) | 1472 | if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) |
1546 | node->linux_phandle = *ibm_phandle; | 1473 | node->linux_phandle = *ibm_phandle; |
1547 | 1474 | ||
1548 | out: | 1475 | out: |
@@ -1605,13 +1532,13 @@ EXPORT_SYMBOL(of_find_property); | |||
1605 | * Find a property with a given name for a given node | 1532 | * Find a property with a given name for a given node |
1606 | * and return the value. | 1533 | * and return the value. |
1607 | */ | 1534 | */ |
1608 | const void *get_property(const struct device_node *np, const char *name, | 1535 | const void *of_get_property(const struct device_node *np, const char *name, |
1609 | int *lenp) | 1536 | int *lenp) |
1610 | { | 1537 | { |
1611 | struct property *pp = of_find_property(np,name,lenp); | 1538 | struct property *pp = of_find_property(np,name,lenp); |
1612 | return pp ? pp->value : NULL; | 1539 | return pp ? pp->value : NULL; |
1613 | } | 1540 | } |
1614 | EXPORT_SYMBOL(get_property); | 1541 | EXPORT_SYMBOL(of_get_property); |
1615 | 1542 | ||
1616 | /* | 1543 | /* |
1617 | * Add a property to a node | 1544 | * Add a property to a node |
@@ -1742,10 +1669,10 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | |||
1742 | /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist | 1669 | /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist |
1743 | * fallback to "reg" property and assume no threads | 1670 | * fallback to "reg" property and assume no threads |
1744 | */ | 1671 | */ |
1745 | intserv = get_property(np, "ibm,ppc-interrupt-server#s", | 1672 | intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", |
1746 | &plen); | 1673 | &plen); |
1747 | if (intserv == NULL) { | 1674 | if (intserv == NULL) { |
1748 | const u32 *reg = get_property(np, "reg", NULL); | 1675 | const u32 *reg = of_get_property(np, "reg", NULL); |
1749 | if (reg == NULL) | 1676 | if (reg == NULL) |
1750 | continue; | 1677 | continue; |
1751 | if (*reg == hardid) { | 1678 | if (*reg == hardid) { |