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) { |
