diff options
| author | Stephen Rothwell <sfr@canb.auug.org.au> | 2006-05-19 02:58:13 -0400 |
|---|---|---|
| committer | Paul Mackerras <paulus@samba.org> | 2006-05-24 02:08:57 -0400 |
| commit | 9ceb19093b5e5f037c6b47df0607dd567283287d (patch) | |
| tree | 15db4f5d1eb688b7d67ca01889d0b4835d3c8707 /arch/powerpc/platforms/iseries/setup.c | |
| parent | 29629b2972467f6cc00427a89008c09d010074c8 (diff) | |
[PATCH] powerpc: give iSeries device tree nodes better names
Use the PCI class code to choose a name for the PCI device nodes and
to guess a device_type. Failing that, base the name on the vendor and
device ids as specified in the spec.
Mark just about everything __init{data}.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
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 95864146b8f..5661bd0d427 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 | ||
