diff options
author | Pantelis Antoniou <pantelis.antoniou@konsulko.com> | 2015-01-12 12:02:49 -0500 |
---|---|---|
committer | Rob Herring <robh@kernel.org> | 2015-02-04 11:43:14 -0500 |
commit | d5e75500ca401d3128c82c5b0dee2f9b259d5b5c (patch) | |
tree | c4a7cf26e96b68c585b2a59222a1a79537ceab5e /drivers/of | |
parent | 962a70d05edac2e2eb53cd077715930083964b9e (diff) |
of: unitest: Add I2C overlay unit tests.
Introduce I2C device tree overlay tests.
Tests insertion and removal of i2c adapters, i2c devices, and muxes.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Rob Herring <robh@kernel.org>
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/unittest-data/tests-overlay.dtsi | 94 | ||||
-rw-r--r-- | drivers/of/unittest.c | 512 |
2 files changed, 556 insertions, 50 deletions
diff --git a/drivers/of/unittest-data/tests-overlay.dtsi b/drivers/of/unittest-data/tests-overlay.dtsi index a2b687d5f324..244226cbb5a3 100644 --- a/drivers/of/unittest-data/tests-overlay.dtsi +++ b/drivers/of/unittest-data/tests-overlay.dtsi | |||
@@ -68,6 +68,48 @@ | |||
68 | status = "disabled"; | 68 | status = "disabled"; |
69 | reg = <8>; | 69 | reg = <8>; |
70 | }; | 70 | }; |
71 | |||
72 | i2c-test-bus { | ||
73 | compatible = "selftest-i2c-bus"; | ||
74 | status = "okay"; | ||
75 | reg = <50>; | ||
76 | |||
77 | #address-cells = <1>; | ||
78 | #size-cells = <0>; | ||
79 | |||
80 | test-selftest12 { | ||
81 | reg = <8>; | ||
82 | compatible = "selftest-i2c-dev"; | ||
83 | status = "disabled"; | ||
84 | }; | ||
85 | |||
86 | test-selftest13 { | ||
87 | reg = <9>; | ||
88 | compatible = "selftest-i2c-dev"; | ||
89 | status = "okay"; | ||
90 | }; | ||
91 | |||
92 | test-selftest14 { | ||
93 | reg = <10>; | ||
94 | compatible = "selftest-i2c-mux"; | ||
95 | status = "okay"; | ||
96 | |||
97 | #address-cells = <1>; | ||
98 | #size-cells = <0>; | ||
99 | |||
100 | i2c@0 { | ||
101 | #address-cells = <1>; | ||
102 | #size-cells = <0>; | ||
103 | reg = <0>; | ||
104 | |||
105 | test-mux-dev { | ||
106 | reg = <32>; | ||
107 | compatible = "selftest-i2c-dev"; | ||
108 | status = "okay"; | ||
109 | }; | ||
110 | }; | ||
111 | }; | ||
112 | }; | ||
71 | }; | 113 | }; |
72 | }; | 114 | }; |
73 | 115 | ||
@@ -231,5 +273,57 @@ | |||
231 | }; | 273 | }; |
232 | }; | 274 | }; |
233 | }; | 275 | }; |
276 | |||
277 | /* test enable using absolute target path (i2c) */ | ||
278 | overlay12 { | ||
279 | fragment@0 { | ||
280 | target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-selftest12"; | ||
281 | __overlay__ { | ||
282 | status = "okay"; | ||
283 | }; | ||
284 | }; | ||
285 | }; | ||
286 | |||
287 | /* test disable using absolute target path (i2c) */ | ||
288 | overlay13 { | ||
289 | fragment@0 { | ||
290 | target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus/test-selftest13"; | ||
291 | __overlay__ { | ||
292 | status = "disabled"; | ||
293 | }; | ||
294 | }; | ||
295 | }; | ||
296 | |||
297 | /* test mux overlay */ | ||
298 | overlay15 { | ||
299 | fragment@0 { | ||
300 | target-path = "/testcase-data/overlay-node/test-bus/i2c-test-bus"; | ||
301 | __overlay__ { | ||
302 | #address-cells = <1>; | ||
303 | #size-cells = <0>; | ||
304 | test-selftest15 { | ||
305 | reg = <11>; | ||
306 | compatible = "selftest-i2c-mux"; | ||
307 | status = "okay"; | ||
308 | |||
309 | #address-cells = <1>; | ||
310 | #size-cells = <0>; | ||
311 | |||
312 | i2c@0 { | ||
313 | #address-cells = <1>; | ||
314 | #size-cells = <0>; | ||
315 | reg = <0>; | ||
316 | |||
317 | test-mux-dev { | ||
318 | reg = <32>; | ||
319 | compatible = "selftest-i2c-dev"; | ||
320 | status = "okay"; | ||
321 | }; | ||
322 | }; | ||
323 | }; | ||
324 | }; | ||
325 | }; | ||
326 | }; | ||
327 | |||
234 | }; | 328 | }; |
235 | }; | 329 | }; |
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 12cdbc1e3042..e86213b0e7e5 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c | |||
@@ -20,6 +20,9 @@ | |||
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/of_platform.h> | 21 | #include <linux/of_platform.h> |
22 | 22 | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/i2c-mux.h> | ||
25 | |||
23 | #include "of_private.h" | 26 | #include "of_private.h" |
24 | 27 | ||
25 | static struct selftest_results { | 28 | static struct selftest_results { |
@@ -991,17 +994,94 @@ static int of_path_platform_device_exists(const char *path) | |||
991 | return pdev != NULL; | 994 | return pdev != NULL; |
992 | } | 995 | } |
993 | 996 | ||
994 | static const char *selftest_path(int nr) | 997 | #if IS_ENABLED(CONFIG_I2C) |
998 | |||
999 | /* get the i2c client device instantiated at the path */ | ||
1000 | static struct i2c_client *of_path_to_i2c_client(const char *path) | ||
1001 | { | ||
1002 | struct device_node *np; | ||
1003 | struct i2c_client *client; | ||
1004 | |||
1005 | np = of_find_node_by_path(path); | ||
1006 | if (np == NULL) | ||
1007 | return NULL; | ||
1008 | |||
1009 | client = of_find_i2c_device_by_node(np); | ||
1010 | of_node_put(np); | ||
1011 | |||
1012 | return client; | ||
1013 | } | ||
1014 | |||
1015 | /* find out if a i2c client device exists at that path */ | ||
1016 | static int of_path_i2c_client_exists(const char *path) | ||
1017 | { | ||
1018 | struct i2c_client *client; | ||
1019 | |||
1020 | client = of_path_to_i2c_client(path); | ||
1021 | if (client) | ||
1022 | put_device(&client->dev); | ||
1023 | return client != NULL; | ||
1024 | } | ||
1025 | #else | ||
1026 | static int of_path_i2c_client_exists(const char *path) | ||
1027 | { | ||
1028 | return 0; | ||
1029 | } | ||
1030 | #endif | ||
1031 | |||
1032 | enum overlay_type { | ||
1033 | PDEV_OVERLAY, | ||
1034 | I2C_OVERLAY | ||
1035 | }; | ||
1036 | |||
1037 | static int of_path_device_type_exists(const char *path, | ||
1038 | enum overlay_type ovtype) | ||
995 | { | 1039 | { |
1040 | switch (ovtype) { | ||
1041 | case PDEV_OVERLAY: | ||
1042 | return of_path_platform_device_exists(path); | ||
1043 | case I2C_OVERLAY: | ||
1044 | return of_path_i2c_client_exists(path); | ||
1045 | } | ||
1046 | return 0; | ||
1047 | } | ||
1048 | |||
1049 | static const char *selftest_path(int nr, enum overlay_type ovtype) | ||
1050 | { | ||
1051 | const char *base; | ||
996 | static char buf[256]; | 1052 | static char buf[256]; |
997 | 1053 | ||
998 | snprintf(buf, sizeof(buf) - 1, | 1054 | switch (ovtype) { |
999 | "/testcase-data/overlay-node/test-bus/test-selftest%d", nr); | 1055 | case PDEV_OVERLAY: |
1056 | base = "/testcase-data/overlay-node/test-bus"; | ||
1057 | break; | ||
1058 | case I2C_OVERLAY: | ||
1059 | base = "/testcase-data/overlay-node/test-bus/i2c-test-bus"; | ||
1060 | break; | ||
1061 | default: | ||
1062 | buf[0] = '\0'; | ||
1063 | return buf; | ||
1064 | } | ||
1065 | snprintf(buf, sizeof(buf) - 1, "%s/test-selftest%d", base, nr); | ||
1000 | buf[sizeof(buf) - 1] = '\0'; | 1066 | buf[sizeof(buf) - 1] = '\0'; |
1001 | |||
1002 | return buf; | 1067 | return buf; |
1003 | } | 1068 | } |
1004 | 1069 | ||
1070 | static int of_selftest_device_exists(int selftest_nr, enum overlay_type ovtype) | ||
1071 | { | ||
1072 | const char *path; | ||
1073 | |||
1074 | path = selftest_path(selftest_nr, ovtype); | ||
1075 | |||
1076 | switch (ovtype) { | ||
1077 | case PDEV_OVERLAY: | ||
1078 | return of_path_platform_device_exists(path); | ||
1079 | case I2C_OVERLAY: | ||
1080 | return of_path_i2c_client_exists(path); | ||
1081 | } | ||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1005 | static const char *overlay_path(int nr) | 1085 | static const char *overlay_path(int nr) |
1006 | { | 1086 | { |
1007 | static char buf[256]; | 1087 | static char buf[256]; |
@@ -1050,16 +1130,15 @@ out: | |||
1050 | 1130 | ||
1051 | /* apply an overlay while checking before and after states */ | 1131 | /* apply an overlay while checking before and after states */ |
1052 | static int of_selftest_apply_overlay_check(int overlay_nr, int selftest_nr, | 1132 | static int of_selftest_apply_overlay_check(int overlay_nr, int selftest_nr, |
1053 | int before, int after) | 1133 | int before, int after, enum overlay_type ovtype) |
1054 | { | 1134 | { |
1055 | int ret; | 1135 | int ret; |
1056 | 1136 | ||
1057 | /* selftest device must not be in before state */ | 1137 | /* selftest device must not be in before state */ |
1058 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | 1138 | if (of_selftest_device_exists(selftest_nr, ovtype) != before) { |
1059 | != before) { | ||
1060 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | 1139 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", |
1061 | overlay_path(overlay_nr), | 1140 | overlay_path(overlay_nr), |
1062 | selftest_path(selftest_nr), | 1141 | selftest_path(selftest_nr, ovtype), |
1063 | !before ? "enabled" : "disabled"); | 1142 | !before ? "enabled" : "disabled"); |
1064 | return -EINVAL; | 1143 | return -EINVAL; |
1065 | } | 1144 | } |
@@ -1071,11 +1150,10 @@ static int of_selftest_apply_overlay_check(int overlay_nr, int selftest_nr, | |||
1071 | } | 1150 | } |
1072 | 1151 | ||
1073 | /* selftest device must be to set to after state */ | 1152 | /* selftest device must be to set to after state */ |
1074 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | 1153 | if (of_selftest_device_exists(selftest_nr, ovtype) != after) { |
1075 | != after) { | ||
1076 | selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", | 1154 | selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", |
1077 | overlay_path(overlay_nr), | 1155 | overlay_path(overlay_nr), |
1078 | selftest_path(selftest_nr), | 1156 | selftest_path(selftest_nr, ovtype), |
1079 | !after ? "enabled" : "disabled"); | 1157 | !after ? "enabled" : "disabled"); |
1080 | return -EINVAL; | 1158 | return -EINVAL; |
1081 | } | 1159 | } |
@@ -1085,16 +1163,16 @@ static int of_selftest_apply_overlay_check(int overlay_nr, int selftest_nr, | |||
1085 | 1163 | ||
1086 | /* apply an overlay and then revert it while checking before, after states */ | 1164 | /* apply an overlay and then revert it while checking before, after states */ |
1087 | static int of_selftest_apply_revert_overlay_check(int overlay_nr, | 1165 | static int of_selftest_apply_revert_overlay_check(int overlay_nr, |
1088 | int selftest_nr, int before, int after) | 1166 | int selftest_nr, int before, int after, |
1167 | enum overlay_type ovtype) | ||
1089 | { | 1168 | { |
1090 | int ret, ov_id; | 1169 | int ret, ov_id; |
1091 | 1170 | ||
1092 | /* selftest device must be in before state */ | 1171 | /* selftest device must be in before state */ |
1093 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | 1172 | if (of_selftest_device_exists(selftest_nr, ovtype) != before) { |
1094 | != before) { | ||
1095 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | 1173 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", |
1096 | overlay_path(overlay_nr), | 1174 | overlay_path(overlay_nr), |
1097 | selftest_path(selftest_nr), | 1175 | selftest_path(selftest_nr, ovtype), |
1098 | !before ? "enabled" : "disabled"); | 1176 | !before ? "enabled" : "disabled"); |
1099 | return -EINVAL; | 1177 | return -EINVAL; |
1100 | } | 1178 | } |
@@ -1107,11 +1185,10 @@ static int of_selftest_apply_revert_overlay_check(int overlay_nr, | |||
1107 | } | 1185 | } |
1108 | 1186 | ||
1109 | /* selftest device must be in after state */ | 1187 | /* selftest device must be in after state */ |
1110 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | 1188 | if (of_selftest_device_exists(selftest_nr, ovtype) != after) { |
1111 | != after) { | ||
1112 | selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", | 1189 | selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", |
1113 | overlay_path(overlay_nr), | 1190 | overlay_path(overlay_nr), |
1114 | selftest_path(selftest_nr), | 1191 | selftest_path(selftest_nr, ovtype), |
1115 | !after ? "enabled" : "disabled"); | 1192 | !after ? "enabled" : "disabled"); |
1116 | return -EINVAL; | 1193 | return -EINVAL; |
1117 | } | 1194 | } |
@@ -1120,16 +1197,15 @@ static int of_selftest_apply_revert_overlay_check(int overlay_nr, | |||
1120 | if (ret != 0) { | 1197 | if (ret != 0) { |
1121 | selftest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", | 1198 | selftest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", |
1122 | overlay_path(overlay_nr), | 1199 | overlay_path(overlay_nr), |
1123 | selftest_path(selftest_nr)); | 1200 | selftest_path(selftest_nr, ovtype)); |
1124 | return ret; | 1201 | return ret; |
1125 | } | 1202 | } |
1126 | 1203 | ||
1127 | /* selftest device must be again in before state */ | 1204 | /* selftest device must be again in before state */ |
1128 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | 1205 | if (of_selftest_device_exists(selftest_nr, PDEV_OVERLAY) != before) { |
1129 | != before) { | ||
1130 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | 1206 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", |
1131 | overlay_path(overlay_nr), | 1207 | overlay_path(overlay_nr), |
1132 | selftest_path(selftest_nr), | 1208 | selftest_path(selftest_nr, ovtype), |
1133 | !before ? "enabled" : "disabled"); | 1209 | !before ? "enabled" : "disabled"); |
1134 | return -EINVAL; | 1210 | return -EINVAL; |
1135 | } | 1211 | } |
@@ -1143,7 +1219,7 @@ static void of_selftest_overlay_0(void) | |||
1143 | int ret; | 1219 | int ret; |
1144 | 1220 | ||
1145 | /* device should enable */ | 1221 | /* device should enable */ |
1146 | ret = of_selftest_apply_overlay_check(0, 0, 0, 1); | 1222 | ret = of_selftest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY); |
1147 | if (ret != 0) | 1223 | if (ret != 0) |
1148 | return; | 1224 | return; |
1149 | 1225 | ||
@@ -1156,7 +1232,7 @@ static void of_selftest_overlay_1(void) | |||
1156 | int ret; | 1232 | int ret; |
1157 | 1233 | ||
1158 | /* device should disable */ | 1234 | /* device should disable */ |
1159 | ret = of_selftest_apply_overlay_check(1, 1, 1, 0); | 1235 | ret = of_selftest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY); |
1160 | if (ret != 0) | 1236 | if (ret != 0) |
1161 | return; | 1237 | return; |
1162 | 1238 | ||
@@ -1169,7 +1245,7 @@ static void of_selftest_overlay_2(void) | |||
1169 | int ret; | 1245 | int ret; |
1170 | 1246 | ||
1171 | /* device should enable */ | 1247 | /* device should enable */ |
1172 | ret = of_selftest_apply_overlay_check(2, 2, 0, 1); | 1248 | ret = of_selftest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY); |
1173 | if (ret != 0) | 1249 | if (ret != 0) |
1174 | return; | 1250 | return; |
1175 | 1251 | ||
@@ -1182,7 +1258,7 @@ static void of_selftest_overlay_3(void) | |||
1182 | int ret; | 1258 | int ret; |
1183 | 1259 | ||
1184 | /* device should disable */ | 1260 | /* device should disable */ |
1185 | ret = of_selftest_apply_overlay_check(3, 3, 1, 0); | 1261 | ret = of_selftest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY); |
1186 | if (ret != 0) | 1262 | if (ret != 0) |
1187 | return; | 1263 | return; |
1188 | 1264 | ||
@@ -1195,7 +1271,7 @@ static void of_selftest_overlay_4(void) | |||
1195 | int ret; | 1271 | int ret; |
1196 | 1272 | ||
1197 | /* device should disable */ | 1273 | /* device should disable */ |
1198 | ret = of_selftest_apply_overlay_check(4, 4, 0, 1); | 1274 | ret = of_selftest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY); |
1199 | if (ret != 0) | 1275 | if (ret != 0) |
1200 | return; | 1276 | return; |
1201 | 1277 | ||
@@ -1208,7 +1284,7 @@ static void of_selftest_overlay_5(void) | |||
1208 | int ret; | 1284 | int ret; |
1209 | 1285 | ||
1210 | /* device should disable */ | 1286 | /* device should disable */ |
1211 | ret = of_selftest_apply_revert_overlay_check(5, 5, 0, 1); | 1287 | ret = of_selftest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY); |
1212 | if (ret != 0) | 1288 | if (ret != 0) |
1213 | return; | 1289 | return; |
1214 | 1290 | ||
@@ -1225,12 +1301,12 @@ static void of_selftest_overlay_6(void) | |||
1225 | 1301 | ||
1226 | /* selftest device must be in before state */ | 1302 | /* selftest device must be in before state */ |
1227 | for (i = 0; i < 2; i++) { | 1303 | for (i = 0; i < 2; i++) { |
1228 | if (of_path_platform_device_exists( | 1304 | if (of_selftest_device_exists(selftest_nr + i, PDEV_OVERLAY) |
1229 | selftest_path(selftest_nr + i)) | ||
1230 | != before) { | 1305 | != before) { |
1231 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | 1306 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", |
1232 | overlay_path(overlay_nr + i), | 1307 | overlay_path(overlay_nr + i), |
1233 | selftest_path(selftest_nr + i), | 1308 | selftest_path(selftest_nr + i, |
1309 | PDEV_OVERLAY), | ||
1234 | !before ? "enabled" : "disabled"); | 1310 | !before ? "enabled" : "disabled"); |
1235 | return; | 1311 | return; |
1236 | } | 1312 | } |
@@ -1257,12 +1333,12 @@ static void of_selftest_overlay_6(void) | |||
1257 | 1333 | ||
1258 | for (i = 0; i < 2; i++) { | 1334 | for (i = 0; i < 2; i++) { |
1259 | /* selftest device must be in after state */ | 1335 | /* selftest device must be in after state */ |
1260 | if (of_path_platform_device_exists( | 1336 | if (of_selftest_device_exists(selftest_nr + i, PDEV_OVERLAY) |
1261 | selftest_path(selftest_nr + i)) | ||
1262 | != after) { | 1337 | != after) { |
1263 | selftest(0, "overlay @\"%s\" failed @\"%s\" %s\n", | 1338 | selftest(0, "overlay @\"%s\" failed @\"%s\" %s\n", |
1264 | overlay_path(overlay_nr + i), | 1339 | overlay_path(overlay_nr + i), |
1265 | selftest_path(selftest_nr + i), | 1340 | selftest_path(selftest_nr + i, |
1341 | PDEV_OVERLAY), | ||
1266 | !after ? "enabled" : "disabled"); | 1342 | !after ? "enabled" : "disabled"); |
1267 | return; | 1343 | return; |
1268 | } | 1344 | } |
@@ -1273,19 +1349,20 @@ static void of_selftest_overlay_6(void) | |||
1273 | if (ret != 0) { | 1349 | if (ret != 0) { |
1274 | selftest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", | 1350 | selftest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", |
1275 | overlay_path(overlay_nr + i), | 1351 | overlay_path(overlay_nr + i), |
1276 | selftest_path(selftest_nr + i)); | 1352 | selftest_path(selftest_nr + i, |
1353 | PDEV_OVERLAY)); | ||
1277 | return; | 1354 | return; |
1278 | } | 1355 | } |
1279 | } | 1356 | } |
1280 | 1357 | ||
1281 | for (i = 0; i < 2; i++) { | 1358 | for (i = 0; i < 2; i++) { |
1282 | /* selftest device must be again in before state */ | 1359 | /* selftest device must be again in before state */ |
1283 | if (of_path_platform_device_exists( | 1360 | if (of_selftest_device_exists(selftest_nr + i, PDEV_OVERLAY) |
1284 | selftest_path(selftest_nr + i)) | ||
1285 | != before) { | 1361 | != before) { |
1286 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | 1362 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", |
1287 | overlay_path(overlay_nr + i), | 1363 | overlay_path(overlay_nr + i), |
1288 | selftest_path(selftest_nr + i), | 1364 | selftest_path(selftest_nr + i, |
1365 | PDEV_OVERLAY), | ||
1289 | !before ? "enabled" : "disabled"); | 1366 | !before ? "enabled" : "disabled"); |
1290 | return; | 1367 | return; |
1291 | } | 1368 | } |
@@ -1327,7 +1404,8 @@ static void of_selftest_overlay_8(void) | |||
1327 | if (ret == 0) { | 1404 | if (ret == 0) { |
1328 | selftest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", | 1405 | selftest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", |
1329 | overlay_path(overlay_nr + 0), | 1406 | overlay_path(overlay_nr + 0), |
1330 | selftest_path(selftest_nr)); | 1407 | selftest_path(selftest_nr, |
1408 | PDEV_OVERLAY)); | ||
1331 | return; | 1409 | return; |
1332 | } | 1410 | } |
1333 | 1411 | ||
@@ -1337,7 +1415,8 @@ static void of_selftest_overlay_8(void) | |||
1337 | if (ret != 0) { | 1415 | if (ret != 0) { |
1338 | selftest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", | 1416 | selftest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", |
1339 | overlay_path(overlay_nr + i), | 1417 | overlay_path(overlay_nr + i), |
1340 | selftest_path(selftest_nr)); | 1418 | selftest_path(selftest_nr, |
1419 | PDEV_OVERLAY)); | ||
1341 | return; | 1420 | return; |
1342 | } | 1421 | } |
1343 | } | 1422 | } |
@@ -1352,16 +1431,17 @@ static void of_selftest_overlay_10(void) | |||
1352 | char *child_path; | 1431 | char *child_path; |
1353 | 1432 | ||
1354 | /* device should disable */ | 1433 | /* device should disable */ |
1355 | ret = of_selftest_apply_overlay_check(10, 10, 0, 1); | 1434 | ret = of_selftest_apply_overlay_check(10, 10, 0, 1, PDEV_OVERLAY); |
1356 | if (selftest(ret == 0, "overlay test %d failed; overlay application\n", 10)) | 1435 | if (selftest(ret == 0, |
1436 | "overlay test %d failed; overlay application\n", 10)) | ||
1357 | return; | 1437 | return; |
1358 | 1438 | ||
1359 | child_path = kasprintf(GFP_KERNEL, "%s/test-selftest101", | 1439 | child_path = kasprintf(GFP_KERNEL, "%s/test-selftest101", |
1360 | selftest_path(10)); | 1440 | selftest_path(10, PDEV_OVERLAY)); |
1361 | if (selftest(child_path, "overlay test %d failed; kasprintf\n", 10)) | 1441 | if (selftest(child_path, "overlay test %d failed; kasprintf\n", 10)) |
1362 | return; | 1442 | return; |
1363 | 1443 | ||
1364 | ret = of_path_platform_device_exists(child_path); | 1444 | ret = of_path_device_type_exists(child_path, PDEV_OVERLAY); |
1365 | kfree(child_path); | 1445 | kfree(child_path); |
1366 | if (selftest(ret, "overlay test %d failed; no child device\n", 10)) | 1446 | if (selftest(ret, "overlay test %d failed; no child device\n", 10)) |
1367 | return; | 1447 | return; |
@@ -1373,11 +1453,331 @@ static void of_selftest_overlay_11(void) | |||
1373 | int ret; | 1453 | int ret; |
1374 | 1454 | ||
1375 | /* device should disable */ | 1455 | /* device should disable */ |
1376 | ret = of_selftest_apply_revert_overlay_check(11, 11, 0, 1); | 1456 | ret = of_selftest_apply_revert_overlay_check(11, 11, 0, 1, |
1377 | if (selftest(ret == 0, "overlay test %d failed; overlay application\n", 11)) | 1457 | PDEV_OVERLAY); |
1458 | if (selftest(ret == 0, | ||
1459 | "overlay test %d failed; overlay application\n", 11)) | ||
1460 | return; | ||
1461 | } | ||
1462 | |||
1463 | #if IS_ENABLED(CONFIG_I2C) && IS_ENABLED(CONFIG_OF_OVERLAY) | ||
1464 | |||
1465 | struct selftest_i2c_bus_data { | ||
1466 | struct platform_device *pdev; | ||
1467 | struct i2c_adapter adap; | ||
1468 | }; | ||
1469 | |||
1470 | static int selftest_i2c_master_xfer(struct i2c_adapter *adap, | ||
1471 | struct i2c_msg *msgs, int num) | ||
1472 | { | ||
1473 | struct selftest_i2c_bus_data *std = i2c_get_adapdata(adap); | ||
1474 | |||
1475 | (void)std; | ||
1476 | |||
1477 | return num; | ||
1478 | } | ||
1479 | |||
1480 | static u32 selftest_i2c_functionality(struct i2c_adapter *adap) | ||
1481 | { | ||
1482 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
1483 | } | ||
1484 | |||
1485 | static const struct i2c_algorithm selftest_i2c_algo = { | ||
1486 | .master_xfer = selftest_i2c_master_xfer, | ||
1487 | .functionality = selftest_i2c_functionality, | ||
1488 | }; | ||
1489 | |||
1490 | static int selftest_i2c_bus_probe(struct platform_device *pdev) | ||
1491 | { | ||
1492 | struct device *dev = &pdev->dev; | ||
1493 | struct device_node *np = dev->of_node; | ||
1494 | struct selftest_i2c_bus_data *std; | ||
1495 | struct i2c_adapter *adap; | ||
1496 | int ret; | ||
1497 | |||
1498 | if (np == NULL) { | ||
1499 | dev_err(dev, "No OF data for device\n"); | ||
1500 | return -EINVAL; | ||
1501 | |||
1502 | } | ||
1503 | |||
1504 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
1505 | |||
1506 | std = devm_kzalloc(dev, sizeof(*std), GFP_KERNEL); | ||
1507 | if (!std) { | ||
1508 | dev_err(dev, "Failed to allocate selftest i2c data\n"); | ||
1509 | return -ENOMEM; | ||
1510 | } | ||
1511 | |||
1512 | /* link them together */ | ||
1513 | std->pdev = pdev; | ||
1514 | platform_set_drvdata(pdev, std); | ||
1515 | |||
1516 | adap = &std->adap; | ||
1517 | i2c_set_adapdata(adap, std); | ||
1518 | adap->nr = -1; | ||
1519 | strlcpy(adap->name, pdev->name, sizeof(adap->name)); | ||
1520 | adap->class = I2C_CLASS_DEPRECATED; | ||
1521 | adap->algo = &selftest_i2c_algo; | ||
1522 | adap->dev.parent = dev; | ||
1523 | adap->dev.of_node = dev->of_node; | ||
1524 | adap->timeout = 5 * HZ; | ||
1525 | adap->retries = 3; | ||
1526 | |||
1527 | ret = i2c_add_numbered_adapter(adap); | ||
1528 | if (ret != 0) { | ||
1529 | dev_err(dev, "Failed to add I2C adapter\n"); | ||
1530 | return ret; | ||
1531 | } | ||
1532 | |||
1533 | return 0; | ||
1534 | } | ||
1535 | |||
1536 | static int selftest_i2c_bus_remove(struct platform_device *pdev) | ||
1537 | { | ||
1538 | struct device *dev = &pdev->dev; | ||
1539 | struct device_node *np = dev->of_node; | ||
1540 | struct selftest_i2c_bus_data *std = platform_get_drvdata(pdev); | ||
1541 | |||
1542 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
1543 | i2c_del_adapter(&std->adap); | ||
1544 | |||
1545 | return 0; | ||
1546 | } | ||
1547 | |||
1548 | static struct of_device_id selftest_i2c_bus_match[] = { | ||
1549 | { .compatible = "selftest-i2c-bus", }, | ||
1550 | {}, | ||
1551 | }; | ||
1552 | |||
1553 | static struct platform_driver selftest_i2c_bus_driver = { | ||
1554 | .probe = selftest_i2c_bus_probe, | ||
1555 | .remove = selftest_i2c_bus_remove, | ||
1556 | .driver = { | ||
1557 | .name = "selftest-i2c-bus", | ||
1558 | .of_match_table = of_match_ptr(selftest_i2c_bus_match), | ||
1559 | }, | ||
1560 | }; | ||
1561 | |||
1562 | static int selftest_i2c_dev_probe(struct i2c_client *client, | ||
1563 | const struct i2c_device_id *id) | ||
1564 | { | ||
1565 | struct device *dev = &client->dev; | ||
1566 | struct device_node *np = client->dev.of_node; | ||
1567 | |||
1568 | if (!np) { | ||
1569 | dev_err(dev, "No OF node\n"); | ||
1570 | return -EINVAL; | ||
1571 | } | ||
1572 | |||
1573 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
1574 | |||
1575 | return 0; | ||
1576 | }; | ||
1577 | |||
1578 | static int selftest_i2c_dev_remove(struct i2c_client *client) | ||
1579 | { | ||
1580 | struct device *dev = &client->dev; | ||
1581 | struct device_node *np = client->dev.of_node; | ||
1582 | |||
1583 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
1584 | return 0; | ||
1585 | } | ||
1586 | |||
1587 | static const struct i2c_device_id selftest_i2c_dev_id[] = { | ||
1588 | { .name = "selftest-i2c-dev" }, | ||
1589 | { } | ||
1590 | }; | ||
1591 | |||
1592 | static struct i2c_driver selftest_i2c_dev_driver = { | ||
1593 | .driver = { | ||
1594 | .name = "selftest-i2c-dev", | ||
1595 | .owner = THIS_MODULE, | ||
1596 | }, | ||
1597 | .probe = selftest_i2c_dev_probe, | ||
1598 | .remove = selftest_i2c_dev_remove, | ||
1599 | .id_table = selftest_i2c_dev_id, | ||
1600 | }; | ||
1601 | |||
1602 | #if IS_ENABLED(CONFIG_I2C_MUX) | ||
1603 | |||
1604 | struct selftest_i2c_mux_data { | ||
1605 | int nchans; | ||
1606 | struct i2c_adapter *adap[]; | ||
1607 | }; | ||
1608 | |||
1609 | static int selftest_i2c_mux_select_chan(struct i2c_adapter *adap, | ||
1610 | void *client, u32 chan) | ||
1611 | { | ||
1612 | return 0; | ||
1613 | } | ||
1614 | |||
1615 | static int selftest_i2c_mux_probe(struct i2c_client *client, | ||
1616 | const struct i2c_device_id *id) | ||
1617 | { | ||
1618 | int ret, i, nchans, size; | ||
1619 | struct device *dev = &client->dev; | ||
1620 | struct i2c_adapter *adap = to_i2c_adapter(dev->parent); | ||
1621 | struct device_node *np = client->dev.of_node, *child; | ||
1622 | struct selftest_i2c_mux_data *stm; | ||
1623 | u32 reg, max_reg; | ||
1624 | |||
1625 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
1626 | |||
1627 | if (!np) { | ||
1628 | dev_err(dev, "No OF node\n"); | ||
1629 | return -EINVAL; | ||
1630 | } | ||
1631 | |||
1632 | max_reg = (u32)-1; | ||
1633 | for_each_child_of_node(np, child) { | ||
1634 | ret = of_property_read_u32(child, "reg", ®); | ||
1635 | if (ret) | ||
1636 | continue; | ||
1637 | if (max_reg == (u32)-1 || reg > max_reg) | ||
1638 | max_reg = reg; | ||
1639 | } | ||
1640 | nchans = max_reg == (u32)-1 ? 0 : max_reg + 1; | ||
1641 | if (nchans == 0) { | ||
1642 | dev_err(dev, "No channels\n"); | ||
1643 | return -EINVAL; | ||
1644 | } | ||
1645 | |||
1646 | size = offsetof(struct selftest_i2c_mux_data, adap[nchans]); | ||
1647 | stm = devm_kzalloc(dev, size, GFP_KERNEL); | ||
1648 | if (!stm) { | ||
1649 | dev_err(dev, "Out of memory\n"); | ||
1650 | return -ENOMEM; | ||
1651 | } | ||
1652 | stm->nchans = nchans; | ||
1653 | for (i = 0; i < nchans; i++) { | ||
1654 | stm->adap[i] = i2c_add_mux_adapter(adap, dev, client, | ||
1655 | 0, i, 0, selftest_i2c_mux_select_chan, NULL); | ||
1656 | if (!stm->adap[i]) { | ||
1657 | dev_err(dev, "Failed to register mux #%d\n", i); | ||
1658 | for (i--; i >= 0; i--) | ||
1659 | i2c_del_mux_adapter(stm->adap[i]); | ||
1660 | return -ENODEV; | ||
1661 | } | ||
1662 | } | ||
1663 | |||
1664 | i2c_set_clientdata(client, stm); | ||
1665 | |||
1666 | return 0; | ||
1667 | }; | ||
1668 | |||
1669 | static int selftest_i2c_mux_remove(struct i2c_client *client) | ||
1670 | { | ||
1671 | struct device *dev = &client->dev; | ||
1672 | struct device_node *np = client->dev.of_node; | ||
1673 | struct selftest_i2c_mux_data *stm = i2c_get_clientdata(client); | ||
1674 | int i; | ||
1675 | |||
1676 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
1677 | for (i = stm->nchans - 1; i >= 0; i--) | ||
1678 | i2c_del_mux_adapter(stm->adap[i]); | ||
1679 | return 0; | ||
1680 | } | ||
1681 | |||
1682 | static const struct i2c_device_id selftest_i2c_mux_id[] = { | ||
1683 | { .name = "selftest-i2c-mux" }, | ||
1684 | { } | ||
1685 | }; | ||
1686 | |||
1687 | static struct i2c_driver selftest_i2c_mux_driver = { | ||
1688 | .driver = { | ||
1689 | .name = "selftest-i2c-mux", | ||
1690 | .owner = THIS_MODULE, | ||
1691 | }, | ||
1692 | .probe = selftest_i2c_mux_probe, | ||
1693 | .remove = selftest_i2c_mux_remove, | ||
1694 | .id_table = selftest_i2c_mux_id, | ||
1695 | }; | ||
1696 | |||
1697 | #endif | ||
1698 | |||
1699 | static int of_selftest_overlay_i2c_init(void) | ||
1700 | { | ||
1701 | int ret; | ||
1702 | |||
1703 | ret = i2c_add_driver(&selftest_i2c_dev_driver); | ||
1704 | if (selftest(ret == 0, | ||
1705 | "could not register selftest i2c device driver\n")) | ||
1706 | return ret; | ||
1707 | |||
1708 | ret = platform_driver_register(&selftest_i2c_bus_driver); | ||
1709 | if (selftest(ret == 0, | ||
1710 | "could not register selftest i2c bus driver\n")) | ||
1711 | return ret; | ||
1712 | |||
1713 | #if IS_ENABLED(CONFIG_I2C_MUX) | ||
1714 | ret = i2c_add_driver(&selftest_i2c_mux_driver); | ||
1715 | if (selftest(ret == 0, | ||
1716 | "could not register selftest i2c mux driver\n")) | ||
1717 | return ret; | ||
1718 | #endif | ||
1719 | |||
1720 | return 0; | ||
1721 | } | ||
1722 | |||
1723 | static void of_selftest_overlay_i2c_cleanup(void) | ||
1724 | { | ||
1725 | #if IS_ENABLED(CONFIG_I2C_MUX) | ||
1726 | i2c_del_driver(&selftest_i2c_mux_driver); | ||
1727 | #endif | ||
1728 | platform_driver_unregister(&selftest_i2c_bus_driver); | ||
1729 | i2c_del_driver(&selftest_i2c_dev_driver); | ||
1730 | } | ||
1731 | |||
1732 | static void of_selftest_overlay_i2c_12(void) | ||
1733 | { | ||
1734 | int ret; | ||
1735 | |||
1736 | /* device should enable */ | ||
1737 | ret = of_selftest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY); | ||
1738 | if (ret != 0) | ||
1739 | return; | ||
1740 | |||
1741 | selftest(1, "overlay test %d passed\n", 12); | ||
1742 | } | ||
1743 | |||
1744 | /* test deactivation of device */ | ||
1745 | static void of_selftest_overlay_i2c_13(void) | ||
1746 | { | ||
1747 | int ret; | ||
1748 | |||
1749 | /* device should disable */ | ||
1750 | ret = of_selftest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY); | ||
1751 | if (ret != 0) | ||
1378 | return; | 1752 | return; |
1753 | |||
1754 | selftest(1, "overlay test %d passed\n", 13); | ||
1755 | } | ||
1756 | |||
1757 | /* just check for i2c mux existence */ | ||
1758 | static void of_selftest_overlay_i2c_14(void) | ||
1759 | { | ||
1379 | } | 1760 | } |
1380 | 1761 | ||
1762 | static void of_selftest_overlay_i2c_15(void) | ||
1763 | { | ||
1764 | int ret; | ||
1765 | |||
1766 | /* device should enable */ | ||
1767 | ret = of_selftest_apply_overlay_check(16, 15, 0, 1, I2C_OVERLAY); | ||
1768 | if (ret != 0) | ||
1769 | return; | ||
1770 | |||
1771 | selftest(1, "overlay test %d passed\n", 15); | ||
1772 | } | ||
1773 | |||
1774 | #else | ||
1775 | |||
1776 | static inline void of_selftest_overlay_i2c_14(void) { } | ||
1777 | static inline void of_selftest_overlay_i2c_15(void) { } | ||
1778 | |||
1779 | #endif | ||
1780 | |||
1381 | static void __init of_selftest_overlay(void) | 1781 | static void __init of_selftest_overlay(void) |
1382 | { | 1782 | { |
1383 | struct device_node *bus_np = NULL; | 1783 | struct device_node *bus_np = NULL; |
@@ -1402,15 +1802,15 @@ static void __init of_selftest_overlay(void) | |||
1402 | goto out; | 1802 | goto out; |
1403 | } | 1803 | } |
1404 | 1804 | ||
1405 | if (!of_path_platform_device_exists(selftest_path(100))) { | 1805 | if (!of_selftest_device_exists(100, PDEV_OVERLAY)) { |
1406 | selftest(0, "could not find selftest0 @ \"%s\"\n", | 1806 | selftest(0, "could not find selftest0 @ \"%s\"\n", |
1407 | selftest_path(100)); | 1807 | selftest_path(100, PDEV_OVERLAY)); |
1408 | goto out; | 1808 | goto out; |
1409 | } | 1809 | } |
1410 | 1810 | ||
1411 | if (of_path_platform_device_exists(selftest_path(101))) { | 1811 | if (of_selftest_device_exists(101, PDEV_OVERLAY)) { |
1412 | selftest(0, "selftest1 @ \"%s\" should not exist\n", | 1812 | selftest(0, "selftest1 @ \"%s\" should not exist\n", |
1413 | selftest_path(101)); | 1813 | selftest_path(101, PDEV_OVERLAY)); |
1414 | goto out; | 1814 | goto out; |
1415 | } | 1815 | } |
1416 | 1816 | ||
@@ -1429,6 +1829,18 @@ static void __init of_selftest_overlay(void) | |||
1429 | of_selftest_overlay_10(); | 1829 | of_selftest_overlay_10(); |
1430 | of_selftest_overlay_11(); | 1830 | of_selftest_overlay_11(); |
1431 | 1831 | ||
1832 | #if IS_ENABLED(CONFIG_I2C) | ||
1833 | if (selftest(of_selftest_overlay_i2c_init() == 0, "i2c init failed\n")) | ||
1834 | goto out; | ||
1835 | |||
1836 | of_selftest_overlay_i2c_12(); | ||
1837 | of_selftest_overlay_i2c_13(); | ||
1838 | of_selftest_overlay_i2c_14(); | ||
1839 | of_selftest_overlay_i2c_15(); | ||
1840 | |||
1841 | of_selftest_overlay_i2c_cleanup(); | ||
1842 | #endif | ||
1843 | |||
1432 | out: | 1844 | out: |
1433 | of_node_put(bus_np); | 1845 | of_node_put(bus_np); |
1434 | } | 1846 | } |