diff options
Diffstat (limited to 'arch/powerpc/platforms/iseries/setup.c')
-rw-r--r-- | arch/powerpc/platforms/iseries/setup.c | 95 |
1 files changed, 66 insertions, 29 deletions
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c index 95864146b8f0..5661bd0d4279 100644 --- a/arch/powerpc/platforms/iseries/setup.c +++ b/arch/powerpc/platforms/iseries/setup.c | |||
@@ -725,7 +725,7 @@ struct iseries_flat_dt { | |||
725 | 725 | ||
726 | static struct iseries_flat_dt iseries_dt; | 726 | static struct iseries_flat_dt iseries_dt; |
727 | 727 | ||
728 | static void dt_init(struct iseries_flat_dt *dt) | 728 | static void __init dt_init(struct iseries_flat_dt *dt) |
729 | { | 729 | { |
730 | dt->header.off_mem_rsvmap = | 730 | dt->header.off_mem_rsvmap = |
731 | offsetof(struct iseries_flat_dt, reserve_map); | 731 | offsetof(struct iseries_flat_dt, reserve_map); |
@@ -748,7 +748,7 @@ static void dt_init(struct iseries_flat_dt *dt) | |||
748 | dt->reserve_map[1] = 0; | 748 | dt->reserve_map[1] = 0; |
749 | } | 749 | } |
750 | 750 | ||
751 | static void dt_check_blob(struct blob *b) | 751 | static void __init dt_check_blob(struct blob *b) |
752 | { | 752 | { |
753 | if (b->next >= (unsigned long)&b->next) { | 753 | if (b->next >= (unsigned long)&b->next) { |
754 | DBG("Ran out of space in flat device tree blob!\n"); | 754 | DBG("Ran out of space in flat device tree blob!\n"); |
@@ -756,7 +756,7 @@ static void dt_check_blob(struct blob *b) | |||
756 | } | 756 | } |
757 | } | 757 | } |
758 | 758 | ||
759 | static void dt_push_u32(struct iseries_flat_dt *dt, u32 value) | 759 | static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value) |
760 | { | 760 | { |
761 | *((u32*)dt->dt.next) = value; | 761 | *((u32*)dt->dt.next) = value; |
762 | dt->dt.next += sizeof(u32); | 762 | dt->dt.next += sizeof(u32); |
@@ -765,7 +765,7 @@ static void dt_push_u32(struct iseries_flat_dt *dt, u32 value) | |||
765 | } | 765 | } |
766 | 766 | ||
767 | #ifdef notyet | 767 | #ifdef notyet |
768 | static void dt_push_u64(struct iseries_flat_dt *dt, u64 value) | 768 | static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value) |
769 | { | 769 | { |
770 | *((u64*)dt->dt.next) = value; | 770 | *((u64*)dt->dt.next) = value; |
771 | dt->dt.next += sizeof(u64); | 771 | dt->dt.next += sizeof(u64); |
@@ -774,7 +774,7 @@ static void dt_push_u64(struct iseries_flat_dt *dt, u64 value) | |||
774 | } | 774 | } |
775 | #endif | 775 | #endif |
776 | 776 | ||
777 | static unsigned long dt_push_bytes(struct blob *blob, char *data, int len) | 777 | static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len) |
778 | { | 778 | { |
779 | unsigned long start = blob->next - (unsigned long)blob->data; | 779 | unsigned long start = blob->next - (unsigned long)blob->data; |
780 | 780 | ||
@@ -786,7 +786,7 @@ static unsigned long dt_push_bytes(struct blob *blob, char *data, int len) | |||
786 | return start; | 786 | return start; |
787 | } | 787 | } |
788 | 788 | ||
789 | static void dt_start_node(struct iseries_flat_dt *dt, char *name) | 789 | static void __init dt_start_node(struct iseries_flat_dt *dt, char *name) |
790 | { | 790 | { |
791 | dt_push_u32(dt, OF_DT_BEGIN_NODE); | 791 | dt_push_u32(dt, OF_DT_BEGIN_NODE); |
792 | dt_push_bytes(&dt->dt, name, strlen(name) + 1); | 792 | dt_push_bytes(&dt->dt, name, strlen(name) + 1); |
@@ -794,7 +794,8 @@ static void dt_start_node(struct iseries_flat_dt *dt, char *name) | |||
794 | 794 | ||
795 | #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) | 795 | #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE) |
796 | 796 | ||
797 | static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) | 797 | static void __init dt_prop(struct iseries_flat_dt *dt, char *name, |
798 | char *data, int len) | ||
798 | { | 799 | { |
799 | unsigned long offset; | 800 | unsigned long offset; |
800 | 801 | ||
@@ -813,39 +814,42 @@ static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len) | |||
813 | dt_push_bytes(&dt->dt, data, len); | 814 | dt_push_bytes(&dt->dt, data, len); |
814 | } | 815 | } |
815 | 816 | ||
816 | static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data) | 817 | static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name, |
818 | char *data) | ||
817 | { | 819 | { |
818 | dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ | 820 | dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */ |
819 | } | 821 | } |
820 | 822 | ||
821 | static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) | 823 | static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data) |
822 | { | 824 | { |
823 | dt_prop(dt, name, (char *)&data, sizeof(u32)); | 825 | dt_prop(dt, name, (char *)&data, sizeof(u32)); |
824 | } | 826 | } |
825 | 827 | ||
826 | static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) | 828 | static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data) |
827 | { | 829 | { |
828 | dt_prop(dt, name, (char *)&data, sizeof(u64)); | 830 | dt_prop(dt, name, (char *)&data, sizeof(u64)); |
829 | } | 831 | } |
830 | 832 | ||
831 | static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n) | 833 | static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, |
834 | u64 *data, int n) | ||
832 | { | 835 | { |
833 | dt_prop(dt, name, (char *)data, sizeof(u64) * n); | 836 | dt_prop(dt, name, (char *)data, sizeof(u64) * n); |
834 | } | 837 | } |
835 | 838 | ||
836 | static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n) | 839 | static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, |
840 | u32 *data, int n) | ||
837 | { | 841 | { |
838 | dt_prop(dt, name, (char *)data, sizeof(u32) * n); | 842 | dt_prop(dt, name, (char *)data, sizeof(u32) * n); |
839 | } | 843 | } |
840 | 844 | ||
841 | #ifdef notyet | 845 | #ifdef notyet |
842 | static void dt_prop_empty(struct iseries_flat_dt *dt, char *name) | 846 | static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name) |
843 | { | 847 | { |
844 | dt_prop(dt, name, NULL, 0); | 848 | dt_prop(dt, name, NULL, 0); |
845 | } | 849 | } |
846 | #endif | 850 | #endif |
847 | 851 | ||
848 | static void dt_cpus(struct iseries_flat_dt *dt) | 852 | static void __init dt_cpus(struct iseries_flat_dt *dt) |
849 | { | 853 | { |
850 | unsigned char buf[32]; | 854 | unsigned char buf[32]; |
851 | unsigned char *p; | 855 | unsigned char *p; |
@@ -899,7 +903,7 @@ static void dt_cpus(struct iseries_flat_dt *dt) | |||
899 | dt_end_node(dt); | 903 | dt_end_node(dt); |
900 | } | 904 | } |
901 | 905 | ||
902 | static void dt_model(struct iseries_flat_dt *dt) | 906 | static void __init dt_model(struct iseries_flat_dt *dt) |
903 | { | 907 | { |
904 | char buf[16] = "IBM,"; | 908 | char buf[16] = "IBM,"; |
905 | 909 | ||
@@ -917,7 +921,7 @@ static void dt_model(struct iseries_flat_dt *dt) | |||
917 | dt_prop_str(dt, "compatible", "IBM,iSeries"); | 921 | dt_prop_str(dt, "compatible", "IBM,iSeries"); |
918 | } | 922 | } |
919 | 923 | ||
920 | static void dt_vdevices(struct iseries_flat_dt *dt) | 924 | static void __init dt_vdevices(struct iseries_flat_dt *dt) |
921 | { | 925 | { |
922 | u32 reg = 0; | 926 | u32 reg = 0; |
923 | HvLpIndexMap vlan_map; | 927 | HvLpIndexMap vlan_map; |
@@ -1006,11 +1010,32 @@ static void dt_vdevices(struct iseries_flat_dt *dt) | |||
1006 | dt_end_node(dt); | 1010 | dt_end_node(dt); |
1007 | } | 1011 | } |
1008 | 1012 | ||
1013 | struct pci_class_name { | ||
1014 | u16 code; | ||
1015 | char *name; | ||
1016 | char *type; | ||
1017 | }; | ||
1018 | |||
1019 | static struct pci_class_name __initdata pci_class_name[] = { | ||
1020 | { PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" }, | ||
1021 | }; | ||
1022 | |||
1023 | static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code) | ||
1024 | { | ||
1025 | struct pci_class_name *cp; | ||
1026 | |||
1027 | for (cp = pci_class_name; | ||
1028 | cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++) | ||
1029 | if (cp->code == class_code) | ||
1030 | return cp; | ||
1031 | return NULL; | ||
1032 | } | ||
1033 | |||
1009 | /* | 1034 | /* |
1010 | * This assumes that the node slot is always on the primary bus! | 1035 | * This assumes that the node slot is always on the primary bus! |
1011 | */ | 1036 | */ |
1012 | static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, | 1037 | static void __init scan_bridge_slot(struct iseries_flat_dt *dt, |
1013 | struct HvCallPci_BridgeInfo *bridge_info) | 1038 | HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info) |
1014 | { | 1039 | { |
1015 | HvSubBusNumber sub_bus = bridge_info->subBusNumber; | 1040 | HvSubBusNumber sub_bus = bridge_info->subBusNumber; |
1016 | u16 vendor_id; | 1041 | u16 vendor_id; |
@@ -1022,14 +1047,14 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, | |||
1022 | int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); | 1047 | int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus); |
1023 | int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); | 1048 | int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus); |
1024 | HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); | 1049 | HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function); |
1050 | u8 devfn; | ||
1051 | struct pci_class_name *cp; | ||
1025 | 1052 | ||
1026 | /* | 1053 | /* |
1027 | * Connect all functions of any device found. | 1054 | * Connect all functions of any device found. |
1028 | */ | 1055 | */ |
1029 | for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { | 1056 | for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) { |
1030 | for (function = 0; function < 8; function++) { | 1057 | for (function = 0; function < 8; function++) { |
1031 | u8 devfn; | ||
1032 | |||
1033 | HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, | 1058 | HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel, |
1034 | function); | 1059 | function); |
1035 | err = HvCallXm_connectBusUnit(bus, sub_bus, | 1060 | err = HvCallXm_connectBusUnit(bus, sub_bus, |
@@ -1070,12 +1095,20 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, | |||
1070 | 1095 | ||
1071 | devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), | 1096 | devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel), |
1072 | function); | 1097 | function); |
1073 | if (function == 0) | 1098 | cp = dt_find_pci_class_name(class_id >> 16); |
1074 | snprintf(buf, sizeof(buf), "pci@%x", | 1099 | if (cp && cp->name) |
1075 | PCI_SLOT(devfn)); | 1100 | strncpy(buf, cp->name, sizeof(buf) - 1); |
1076 | else | 1101 | else |
1077 | snprintf(buf, sizeof(buf), "pci@%x,%d", | 1102 | snprintf(buf, sizeof(buf), "pci%x,%x", |
1078 | PCI_SLOT(devfn), function); | 1103 | vendor_id, device_id); |
1104 | buf[sizeof(buf) - 1] = '\0'; | ||
1105 | snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), | ||
1106 | "@%x", PCI_SLOT(devfn)); | ||
1107 | buf[sizeof(buf) - 1] = '\0'; | ||
1108 | if (function != 0) | ||
1109 | snprintf(buf + strlen(buf), | ||
1110 | sizeof(buf) - strlen(buf), | ||
1111 | ",%x", function); | ||
1079 | dt_start_node(dt, buf); | 1112 | dt_start_node(dt, buf); |
1080 | reg[0] = (bus << 16) | (devfn << 8); | 1113 | reg[0] = (bus << 16) | (devfn << 8); |
1081 | reg[1] = 0; | 1114 | reg[1] = 0; |
@@ -1083,6 +1116,9 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, | |||
1083 | reg[3] = 0; | 1116 | reg[3] = 0; |
1084 | reg[4] = 0; | 1117 | reg[4] = 0; |
1085 | dt_prop_u32_list(dt, "reg", reg, 5); | 1118 | dt_prop_u32_list(dt, "reg", reg, 5); |
1119 | if (cp && (cp->type || cp->name)) | ||
1120 | dt_prop_str(dt, "device_type", | ||
1121 | cp->type ? cp->type : cp->name); | ||
1086 | dt_prop_u32(dt, "vendor-id", vendor_id); | 1122 | dt_prop_u32(dt, "vendor-id", vendor_id); |
1087 | dt_prop_u32(dt, "device-id", device_id); | 1123 | dt_prop_u32(dt, "device-id", device_id); |
1088 | dt_prop_u32(dt, "class-code", class_id >> 8); | 1124 | dt_prop_u32(dt, "class-code", class_id >> 8); |
@@ -1097,7 +1133,7 @@ static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus, | |||
1097 | } | 1133 | } |
1098 | } | 1134 | } |
1099 | 1135 | ||
1100 | static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, | 1136 | static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, |
1101 | HvSubBusNumber sub_bus, int id_sel) | 1137 | HvSubBusNumber sub_bus, int id_sel) |
1102 | { | 1138 | { |
1103 | struct HvCallPci_BridgeInfo bridge_info; | 1139 | struct HvCallPci_BridgeInfo bridge_info; |
@@ -1139,7 +1175,7 @@ static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus, | |||
1139 | } | 1175 | } |
1140 | } | 1176 | } |
1141 | 1177 | ||
1142 | static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) | 1178 | static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) |
1143 | { | 1179 | { |
1144 | struct HvCallPci_DeviceInfo dev_info; | 1180 | struct HvCallPci_DeviceInfo dev_info; |
1145 | const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ | 1181 | const HvSubBusNumber sub_bus = 0; /* EADs is always 0. */ |
@@ -1171,7 +1207,7 @@ static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus) | |||
1171 | } | 1207 | } |
1172 | } | 1208 | } |
1173 | 1209 | ||
1174 | static void dt_pci_devices(struct iseries_flat_dt *dt) | 1210 | static void __init dt_pci_devices(struct iseries_flat_dt *dt) |
1175 | { | 1211 | { |
1176 | HvBusNumber bus; | 1212 | HvBusNumber bus; |
1177 | char buf[32]; | 1213 | char buf[32]; |
@@ -1207,7 +1243,8 @@ static void dt_pci_devices(struct iseries_flat_dt *dt) | |||
1207 | } | 1243 | } |
1208 | } | 1244 | } |
1209 | 1245 | ||
1210 | static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size) | 1246 | static void __init build_flat_dt(struct iseries_flat_dt *dt, |
1247 | unsigned long phys_mem_size) | ||
1211 | { | 1248 | { |
1212 | u64 tmp[2]; | 1249 | u64 tmp[2]; |
1213 | 1250 | ||