.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007. |
---|
3 | | - * |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or |
---|
6 | | - * modify it under the terms of the GNU General Public License as |
---|
7 | | - * published by the Free Software Foundation; either version 2 of the |
---|
8 | | - * License, or (at your option) any later version. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
13 | | - * General Public License for more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License |
---|
16 | | - * along with this program; if not, write to the Free Software |
---|
17 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
---|
18 | | - * USA |
---|
19 | 4 | */ |
---|
20 | 5 | |
---|
21 | 6 | #include "dtc.h" |
---|
| 7 | +#include "srcpos.h" |
---|
22 | 8 | |
---|
23 | 9 | #ifdef TRACE_CHECKS |
---|
24 | 10 | #define TRACE(c, ...) \ |
---|
.. | .. |
---|
78 | 64 | const char *fmt, ...) |
---|
79 | 65 | { |
---|
80 | 66 | va_list ap; |
---|
81 | | - va_start(ap, fmt); |
---|
| 67 | + char *str = NULL; |
---|
| 68 | + struct srcpos *pos = NULL; |
---|
| 69 | + char *file_str; |
---|
82 | 70 | |
---|
83 | | - if ((c->warn && (quiet < 1)) |
---|
84 | | - || (c->error && (quiet < 2))) { |
---|
85 | | - fprintf(stderr, "%s: %s (%s): ", |
---|
86 | | - strcmp(dti->outname, "-") ? dti->outname : "<stdout>", |
---|
87 | | - (c->error) ? "ERROR" : "Warning", c->name); |
---|
88 | | - if (node) { |
---|
89 | | - fprintf(stderr, "%s", node->fullpath); |
---|
90 | | - if (prop) |
---|
91 | | - fprintf(stderr, ":%s", prop->name); |
---|
92 | | - fputs(": ", stderr); |
---|
93 | | - } |
---|
94 | | - vfprintf(stderr, fmt, ap); |
---|
95 | | - fprintf(stderr, "\n"); |
---|
| 71 | + if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2))) |
---|
| 72 | + return; |
---|
| 73 | + |
---|
| 74 | + if (prop && prop->srcpos) |
---|
| 75 | + pos = prop->srcpos; |
---|
| 76 | + else if (node && node->srcpos) |
---|
| 77 | + pos = node->srcpos; |
---|
| 78 | + |
---|
| 79 | + if (pos) { |
---|
| 80 | + file_str = srcpos_string(pos); |
---|
| 81 | + xasprintf(&str, "%s", file_str); |
---|
| 82 | + free(file_str); |
---|
| 83 | + } else if (streq(dti->outname, "-")) { |
---|
| 84 | + xasprintf(&str, "<stdout>"); |
---|
| 85 | + } else { |
---|
| 86 | + xasprintf(&str, "%s", dti->outname); |
---|
96 | 87 | } |
---|
| 88 | + |
---|
| 89 | + xasprintf_append(&str, ": %s (%s): ", |
---|
| 90 | + (c->error) ? "ERROR" : "Warning", c->name); |
---|
| 91 | + |
---|
| 92 | + if (node) { |
---|
| 93 | + if (prop) |
---|
| 94 | + xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name); |
---|
| 95 | + else |
---|
| 96 | + xasprintf_append(&str, "%s: ", node->fullpath); |
---|
| 97 | + } |
---|
| 98 | + |
---|
| 99 | + va_start(ap, fmt); |
---|
| 100 | + xavsprintf_append(&str, fmt, ap); |
---|
97 | 101 | va_end(ap); |
---|
| 102 | + |
---|
| 103 | + xasprintf_append(&str, "\n"); |
---|
| 104 | + |
---|
| 105 | + if (!prop && pos) { |
---|
| 106 | + pos = node->srcpos; |
---|
| 107 | + while (pos->next) { |
---|
| 108 | + pos = pos->next; |
---|
| 109 | + |
---|
| 110 | + file_str = srcpos_string(pos); |
---|
| 111 | + xasprintf_append(&str, " also defined at %s\n", file_str); |
---|
| 112 | + free(file_str); |
---|
| 113 | + } |
---|
| 114 | + } |
---|
| 115 | + |
---|
| 116 | + fputs(str, stderr); |
---|
98 | 117 | } |
---|
99 | 118 | |
---|
100 | 119 | #define FAIL(c, dti, node, ...) \ |
---|
.. | .. |
---|
333 | 352 | FAIL(c, dti, node, "node has a reg or ranges property, but no unit name"); |
---|
334 | 353 | } else { |
---|
335 | 354 | if (unitname[0]) |
---|
336 | | - FAIL(c, dti, node, "node has a unit name, but no reg property"); |
---|
| 355 | + FAIL(c, dti, node, "node has a unit name, but no reg or ranges property"); |
---|
337 | 356 | } |
---|
338 | 357 | } |
---|
339 | 358 | WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL); |
---|
.. | .. |
---|
648 | 667 | static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti, |
---|
649 | 668 | struct node *node) |
---|
650 | 669 | { |
---|
| 670 | + if (generate_symbols && node->labels) |
---|
| 671 | + return; |
---|
651 | 672 | if (node->omit_if_unused && !node->is_referenced) |
---|
652 | 673 | delete_node(node); |
---|
653 | 674 | |
---|
.. | .. |
---|
710 | 731 | return; |
---|
711 | 732 | |
---|
712 | 733 | for_each_property(node, prop) { |
---|
| 734 | + if (streq(prop->name, "phandle") |
---|
| 735 | + || streq(prop->name, "linux,phandle")) { |
---|
| 736 | + continue; |
---|
| 737 | + } |
---|
| 738 | + |
---|
713 | 739 | if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) { |
---|
714 | 740 | FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)", |
---|
715 | 741 | prop->val.val); |
---|
.. | .. |
---|
779 | 805 | { |
---|
780 | 806 | struct property *prop; |
---|
781 | 807 | int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen; |
---|
| 808 | + const char *ranges = c->data; |
---|
782 | 809 | |
---|
783 | | - prop = get_property(node, "ranges"); |
---|
| 810 | + prop = get_property(node, ranges); |
---|
784 | 811 | if (!prop) |
---|
785 | 812 | return; |
---|
786 | 813 | |
---|
787 | 814 | if (!node->parent) { |
---|
788 | | - FAIL_PROP(c, dti, node, prop, "Root node has a \"ranges\" property"); |
---|
| 815 | + FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property", |
---|
| 816 | + ranges); |
---|
789 | 817 | return; |
---|
790 | 818 | } |
---|
791 | 819 | |
---|
.. | .. |
---|
797 | 825 | |
---|
798 | 826 | if (prop->val.len == 0) { |
---|
799 | 827 | if (p_addr_cells != c_addr_cells) |
---|
800 | | - FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " |
---|
| 828 | + FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its " |
---|
801 | 829 | "#address-cells (%d) differs from %s (%d)", |
---|
802 | | - c_addr_cells, node->parent->fullpath, |
---|
| 830 | + ranges, c_addr_cells, node->parent->fullpath, |
---|
803 | 831 | p_addr_cells); |
---|
804 | 832 | if (p_size_cells != c_size_cells) |
---|
805 | | - FAIL_PROP(c, dti, node, prop, "empty \"ranges\" property but its " |
---|
| 833 | + FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its " |
---|
806 | 834 | "#size-cells (%d) differs from %s (%d)", |
---|
807 | | - c_size_cells, node->parent->fullpath, |
---|
| 835 | + ranges, c_size_cells, node->parent->fullpath, |
---|
808 | 836 | p_size_cells); |
---|
809 | 837 | } else if ((prop->val.len % entrylen) != 0) { |
---|
810 | | - FAIL_PROP(c, dti, node, prop, "\"ranges\" property has invalid length (%d bytes) " |
---|
| 838 | + FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) " |
---|
811 | 839 | "(parent #address-cells == %d, child #address-cells == %d, " |
---|
812 | | - "#size-cells == %d)", prop->val.len, |
---|
| 840 | + "#size-cells == %d)", ranges, prop->val.len, |
---|
813 | 841 | p_addr_cells, c_addr_cells, c_size_cells); |
---|
814 | 842 | } |
---|
815 | 843 | } |
---|
816 | | -WARNING(ranges_format, check_ranges_format, NULL, &addr_size_cells); |
---|
| 844 | +WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells); |
---|
| 845 | +WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells); |
---|
817 | 846 | |
---|
818 | 847 | static const struct bus_type pci_bus = { |
---|
819 | 848 | .name = "PCI", |
---|
.. | .. |
---|
902 | 931 | return; |
---|
903 | 932 | |
---|
904 | 933 | prop = get_property(node, "reg"); |
---|
905 | | - if (!prop) { |
---|
906 | | - FAIL(c, dti, node, "missing PCI reg property"); |
---|
| 934 | + if (!prop) |
---|
907 | 935 | return; |
---|
908 | | - } |
---|
909 | 936 | |
---|
910 | 937 | cells = (cell_t *)prop->val.val; |
---|
911 | 938 | if (cells[1] || cells[2]) |
---|
.. | .. |
---|
950 | 977 | |
---|
951 | 978 | for (str = prop->val.val, end = str + prop->val.len; str < end; |
---|
952 | 979 | str += strnlen(str, end - str) + 1) { |
---|
953 | | - if (strprefixeq(str, end - str, compat)) |
---|
| 980 | + if (streq(str, compat)) |
---|
954 | 981 | return true; |
---|
955 | 982 | } |
---|
956 | 983 | return false; |
---|
.. | .. |
---|
961 | 988 | if (node_is_compatible(node, "simple-bus")) |
---|
962 | 989 | node->bus = &simple_bus; |
---|
963 | 990 | } |
---|
964 | | -WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, &addr_size_cells); |
---|
| 991 | +WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL, |
---|
| 992 | + &addr_size_cells, &compatible_is_string_list); |
---|
965 | 993 | |
---|
966 | 994 | static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node) |
---|
967 | 995 | { |
---|
.. | .. |
---|
1001 | 1029 | unit_addr); |
---|
1002 | 1030 | } |
---|
1003 | 1031 | WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge); |
---|
| 1032 | + |
---|
| 1033 | +static const struct bus_type i2c_bus = { |
---|
| 1034 | + .name = "i2c-bus", |
---|
| 1035 | +}; |
---|
| 1036 | + |
---|
| 1037 | +static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) |
---|
| 1038 | +{ |
---|
| 1039 | + if (strprefixeq(node->name, node->basenamelen, "i2c-bus") || |
---|
| 1040 | + strprefixeq(node->name, node->basenamelen, "i2c-arb")) { |
---|
| 1041 | + node->bus = &i2c_bus; |
---|
| 1042 | + } else if (strprefixeq(node->name, node->basenamelen, "i2c")) { |
---|
| 1043 | + struct node *child; |
---|
| 1044 | + for_each_child(node, child) { |
---|
| 1045 | + if (strprefixeq(child->name, node->basenamelen, "i2c-bus")) |
---|
| 1046 | + return; |
---|
| 1047 | + } |
---|
| 1048 | + node->bus = &i2c_bus; |
---|
| 1049 | + } else |
---|
| 1050 | + return; |
---|
| 1051 | + |
---|
| 1052 | + if (!node->children) |
---|
| 1053 | + return; |
---|
| 1054 | + |
---|
| 1055 | + if (node_addr_cells(node) != 1) |
---|
| 1056 | + FAIL(c, dti, node, "incorrect #address-cells for I2C bus"); |
---|
| 1057 | + if (node_size_cells(node) != 0) |
---|
| 1058 | + FAIL(c, dti, node, "incorrect #size-cells for I2C bus"); |
---|
| 1059 | + |
---|
| 1060 | +} |
---|
| 1061 | +WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells); |
---|
| 1062 | + |
---|
| 1063 | +#define I2C_OWN_SLAVE_ADDRESS (1U << 30) |
---|
| 1064 | +#define I2C_TEN_BIT_ADDRESS (1U << 31) |
---|
| 1065 | + |
---|
| 1066 | +static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node) |
---|
| 1067 | +{ |
---|
| 1068 | + struct property *prop; |
---|
| 1069 | + const char *unitname = get_unitname(node); |
---|
| 1070 | + char unit_addr[17]; |
---|
| 1071 | + uint32_t reg = 0; |
---|
| 1072 | + int len; |
---|
| 1073 | + cell_t *cells = NULL; |
---|
| 1074 | + |
---|
| 1075 | + if (!node->parent || (node->parent->bus != &i2c_bus)) |
---|
| 1076 | + return; |
---|
| 1077 | + |
---|
| 1078 | + prop = get_property(node, "reg"); |
---|
| 1079 | + if (prop) |
---|
| 1080 | + cells = (cell_t *)prop->val.val; |
---|
| 1081 | + |
---|
| 1082 | + if (!cells) { |
---|
| 1083 | + FAIL(c, dti, node, "missing or empty reg property"); |
---|
| 1084 | + return; |
---|
| 1085 | + } |
---|
| 1086 | + |
---|
| 1087 | + reg = fdt32_to_cpu(*cells); |
---|
| 1088 | + /* Ignore I2C_OWN_SLAVE_ADDRESS */ |
---|
| 1089 | + reg &= ~I2C_OWN_SLAVE_ADDRESS; |
---|
| 1090 | + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); |
---|
| 1091 | + if (!streq(unitname, unit_addr)) |
---|
| 1092 | + FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"", |
---|
| 1093 | + unit_addr); |
---|
| 1094 | + |
---|
| 1095 | + for (len = prop->val.len; len > 0; len -= 4) { |
---|
| 1096 | + reg = fdt32_to_cpu(*(cells++)); |
---|
| 1097 | + /* Ignore I2C_OWN_SLAVE_ADDRESS */ |
---|
| 1098 | + reg &= ~I2C_OWN_SLAVE_ADDRESS; |
---|
| 1099 | + |
---|
| 1100 | + if ((reg & I2C_TEN_BIT_ADDRESS) && ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff)) |
---|
| 1101 | + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"", |
---|
| 1102 | + reg); |
---|
| 1103 | + else if (reg > 0x7f) |
---|
| 1104 | + FAIL_PROP(c, dti, node, prop, "I2C address must be less than 7-bits, got \"0x%x\". Set I2C_TEN_BIT_ADDRESS for 10 bit addresses or fix the property", |
---|
| 1105 | + reg); |
---|
| 1106 | + } |
---|
| 1107 | +} |
---|
| 1108 | +WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge); |
---|
| 1109 | + |
---|
| 1110 | +static const struct bus_type spi_bus = { |
---|
| 1111 | + .name = "spi-bus", |
---|
| 1112 | +}; |
---|
| 1113 | + |
---|
| 1114 | +static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node) |
---|
| 1115 | +{ |
---|
| 1116 | + int spi_addr_cells = 1; |
---|
| 1117 | + |
---|
| 1118 | + if (strprefixeq(node->name, node->basenamelen, "spi")) { |
---|
| 1119 | + node->bus = &spi_bus; |
---|
| 1120 | + } else { |
---|
| 1121 | + /* Try to detect SPI buses which don't have proper node name */ |
---|
| 1122 | + struct node *child; |
---|
| 1123 | + |
---|
| 1124 | + if (node_addr_cells(node) != 1 || node_size_cells(node) != 0) |
---|
| 1125 | + return; |
---|
| 1126 | + |
---|
| 1127 | + for_each_child(node, child) { |
---|
| 1128 | + struct property *prop; |
---|
| 1129 | + for_each_property(child, prop) { |
---|
| 1130 | + if (strprefixeq(prop->name, 4, "spi-")) { |
---|
| 1131 | + node->bus = &spi_bus; |
---|
| 1132 | + break; |
---|
| 1133 | + } |
---|
| 1134 | + } |
---|
| 1135 | + if (node->bus == &spi_bus) |
---|
| 1136 | + break; |
---|
| 1137 | + } |
---|
| 1138 | + |
---|
| 1139 | + if (node->bus == &spi_bus && get_property(node, "reg")) |
---|
| 1140 | + FAIL(c, dti, node, "node name for SPI buses should be 'spi'"); |
---|
| 1141 | + } |
---|
| 1142 | + if (node->bus != &spi_bus || !node->children) |
---|
| 1143 | + return; |
---|
| 1144 | + |
---|
| 1145 | + if (get_property(node, "spi-slave")) |
---|
| 1146 | + spi_addr_cells = 0; |
---|
| 1147 | + if (node_addr_cells(node) != spi_addr_cells) |
---|
| 1148 | + FAIL(c, dti, node, "incorrect #address-cells for SPI bus"); |
---|
| 1149 | + if (node_size_cells(node) != 0) |
---|
| 1150 | + FAIL(c, dti, node, "incorrect #size-cells for SPI bus"); |
---|
| 1151 | + |
---|
| 1152 | +} |
---|
| 1153 | +WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells); |
---|
| 1154 | + |
---|
| 1155 | +static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node) |
---|
| 1156 | +{ |
---|
| 1157 | + struct property *prop; |
---|
| 1158 | + const char *unitname = get_unitname(node); |
---|
| 1159 | + char unit_addr[9]; |
---|
| 1160 | + uint32_t reg = 0; |
---|
| 1161 | + cell_t *cells = NULL; |
---|
| 1162 | + |
---|
| 1163 | + if (!node->parent || (node->parent->bus != &spi_bus)) |
---|
| 1164 | + return; |
---|
| 1165 | + |
---|
| 1166 | + if (get_property(node->parent, "spi-slave")) |
---|
| 1167 | + return; |
---|
| 1168 | + |
---|
| 1169 | + prop = get_property(node, "reg"); |
---|
| 1170 | + if (prop) |
---|
| 1171 | + cells = (cell_t *)prop->val.val; |
---|
| 1172 | + |
---|
| 1173 | + if (!cells) { |
---|
| 1174 | + FAIL(c, dti, node, "missing or empty reg property"); |
---|
| 1175 | + return; |
---|
| 1176 | + } |
---|
| 1177 | + |
---|
| 1178 | + reg = fdt32_to_cpu(*cells); |
---|
| 1179 | + snprintf(unit_addr, sizeof(unit_addr), "%x", reg); |
---|
| 1180 | + if (!streq(unitname, unit_addr)) |
---|
| 1181 | + FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"", |
---|
| 1182 | + unit_addr); |
---|
| 1183 | +} |
---|
| 1184 | +WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge); |
---|
1004 | 1185 | |
---|
1005 | 1186 | static void check_unit_address_format(struct check *c, struct dt_info *dti, |
---|
1006 | 1187 | struct node *node) |
---|
.. | .. |
---|
1074 | 1255 | } |
---|
1075 | 1256 | WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size); |
---|
1076 | 1257 | |
---|
1077 | | -static void check_unique_unit_address(struct check *c, struct dt_info *dti, |
---|
1078 | | - struct node *node) |
---|
| 1258 | +static bool node_is_disabled(struct node *node) |
---|
| 1259 | +{ |
---|
| 1260 | + struct property *prop; |
---|
| 1261 | + |
---|
| 1262 | + prop = get_property(node, "status"); |
---|
| 1263 | + if (prop) { |
---|
| 1264 | + char *str = prop->val.val; |
---|
| 1265 | + if (streq("disabled", str)) |
---|
| 1266 | + return true; |
---|
| 1267 | + } |
---|
| 1268 | + |
---|
| 1269 | + return false; |
---|
| 1270 | +} |
---|
| 1271 | + |
---|
| 1272 | +static void check_unique_unit_address_common(struct check *c, |
---|
| 1273 | + struct dt_info *dti, |
---|
| 1274 | + struct node *node, |
---|
| 1275 | + bool disable_check) |
---|
1079 | 1276 | { |
---|
1080 | 1277 | struct node *childa; |
---|
1081 | 1278 | |
---|
.. | .. |
---|
1092 | 1289 | if (!strlen(addr_a)) |
---|
1093 | 1290 | continue; |
---|
1094 | 1291 | |
---|
| 1292 | + if (disable_check && node_is_disabled(childa)) |
---|
| 1293 | + continue; |
---|
| 1294 | + |
---|
1095 | 1295 | for_each_child(node, childb) { |
---|
1096 | 1296 | const char *addr_b = get_unitname(childb); |
---|
1097 | 1297 | if (childa == childb) |
---|
1098 | 1298 | break; |
---|
| 1299 | + |
---|
| 1300 | + if (disable_check && node_is_disabled(childb)) |
---|
| 1301 | + continue; |
---|
1099 | 1302 | |
---|
1100 | 1303 | if (streq(addr_a, addr_b)) |
---|
1101 | 1304 | FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath); |
---|
1102 | 1305 | } |
---|
1103 | 1306 | } |
---|
1104 | 1307 | } |
---|
| 1308 | + |
---|
| 1309 | +static void check_unique_unit_address(struct check *c, struct dt_info *dti, |
---|
| 1310 | + struct node *node) |
---|
| 1311 | +{ |
---|
| 1312 | + check_unique_unit_address_common(c, dti, node, false); |
---|
| 1313 | +} |
---|
1105 | 1314 | WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size); |
---|
| 1315 | + |
---|
| 1316 | +static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti, |
---|
| 1317 | + struct node *node) |
---|
| 1318 | +{ |
---|
| 1319 | + check_unique_unit_address_common(c, dti, node, true); |
---|
| 1320 | +} |
---|
| 1321 | +CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled, |
---|
| 1322 | + NULL, false, false, &avoid_default_addr_size); |
---|
1106 | 1323 | |
---|
1107 | 1324 | static void check_obsolete_chosen_interrupt_controller(struct check *c, |
---|
1108 | 1325 | struct dt_info *dti, |
---|
.. | .. |
---|
1378 | 1595 | |
---|
1379 | 1596 | return false; |
---|
1380 | 1597 | } |
---|
| 1598 | + |
---|
| 1599 | +static void check_interrupt_provider(struct check *c, |
---|
| 1600 | + struct dt_info *dti, |
---|
| 1601 | + struct node *node) |
---|
| 1602 | +{ |
---|
| 1603 | + struct property *prop; |
---|
| 1604 | + |
---|
| 1605 | + if (!node_is_interrupt_provider(node)) |
---|
| 1606 | + return; |
---|
| 1607 | + |
---|
| 1608 | + prop = get_property(node, "#interrupt-cells"); |
---|
| 1609 | + if (!prop) |
---|
| 1610 | + FAIL(c, dti, node, |
---|
| 1611 | + "Missing #interrupt-cells in interrupt provider"); |
---|
| 1612 | + |
---|
| 1613 | + prop = get_property(node, "#address-cells"); |
---|
| 1614 | + if (!prop) |
---|
| 1615 | + FAIL(c, dti, node, |
---|
| 1616 | + "Missing #address-cells in interrupt provider"); |
---|
| 1617 | +} |
---|
| 1618 | +WARNING(interrupt_provider, check_interrupt_provider, NULL); |
---|
| 1619 | + |
---|
1381 | 1620 | static void check_interrupts_property(struct check *c, |
---|
1382 | 1621 | struct dt_info *dti, |
---|
1383 | 1622 | struct node *node) |
---|
.. | .. |
---|
1404 | 1643 | prop = get_property(parent, "interrupt-parent"); |
---|
1405 | 1644 | if (prop) { |
---|
1406 | 1645 | phandle = propval_cell(prop); |
---|
1407 | | - /* Give up if this is an overlay with external references */ |
---|
1408 | | - if ((phandle == 0 || phandle == -1) && |
---|
1409 | | - (dti->dtsflags & DTSF_PLUGIN)) |
---|
| 1646 | + if ((phandle == 0) || (phandle == -1)) { |
---|
| 1647 | + /* Give up if this is an overlay with |
---|
| 1648 | + * external references */ |
---|
| 1649 | + if (dti->dtsflags & DTSF_PLUGIN) |
---|
1410 | 1650 | return; |
---|
| 1651 | + FAIL_PROP(c, dti, parent, prop, "Invalid phandle"); |
---|
| 1652 | + continue; |
---|
| 1653 | + } |
---|
1411 | 1654 | |
---|
1412 | 1655 | irq_node = get_node_by_phandle(root, phandle); |
---|
1413 | 1656 | if (!irq_node) { |
---|
.. | .. |
---|
1431 | 1674 | |
---|
1432 | 1675 | prop = get_property(irq_node, "#interrupt-cells"); |
---|
1433 | 1676 | if (!prop) { |
---|
1434 | | - FAIL(c, dti, irq_node, "Missing #interrupt-cells in interrupt-parent"); |
---|
| 1677 | + /* We warn about that already in another test. */ |
---|
1435 | 1678 | return; |
---|
1436 | 1679 | } |
---|
1437 | 1680 | |
---|
.. | .. |
---|
1576 | 1819 | return; |
---|
1577 | 1820 | |
---|
1578 | 1821 | if (!strprefixeq(node->name, node->basenamelen, "endpoint")) |
---|
1579 | | - FAIL(c, dti, node, "graph endpont node name should be 'endpoint'"); |
---|
| 1822 | + FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'"); |
---|
1580 | 1823 | |
---|
1581 | 1824 | check_graph_reg(c, dti, node); |
---|
1582 | 1825 | |
---|
.. | .. |
---|
1611 | 1854 | &property_name_chars_strict, |
---|
1612 | 1855 | &node_name_chars_strict, |
---|
1613 | 1856 | |
---|
1614 | | - &addr_size_cells, ®_format, &ranges_format, |
---|
| 1857 | + &addr_size_cells, ®_format, &ranges_format, &dma_ranges_format, |
---|
1615 | 1858 | |
---|
1616 | 1859 | &unit_address_vs_reg, |
---|
1617 | 1860 | &unit_address_format, |
---|
.. | .. |
---|
1623 | 1866 | &simple_bus_bridge, |
---|
1624 | 1867 | &simple_bus_reg, |
---|
1625 | 1868 | |
---|
| 1869 | + &i2c_bus_bridge, |
---|
| 1870 | + &i2c_bus_reg, |
---|
| 1871 | + |
---|
| 1872 | + &spi_bus_bridge, |
---|
| 1873 | + &spi_bus_reg, |
---|
| 1874 | + |
---|
1626 | 1875 | &avoid_default_addr_size, |
---|
1627 | 1876 | &avoid_unnecessary_addr_size, |
---|
1628 | 1877 | &unique_unit_address, |
---|
| 1878 | + &unique_unit_address_if_enabled, |
---|
1629 | 1879 | &obsolete_chosen_interrupt_controller, |
---|
1630 | 1880 | &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path, |
---|
1631 | 1881 | |
---|
.. | .. |
---|
1649 | 1899 | &deprecated_gpio_property, |
---|
1650 | 1900 | &gpios_property, |
---|
1651 | 1901 | &interrupts_property, |
---|
| 1902 | + &interrupt_provider, |
---|
1652 | 1903 | |
---|
1653 | 1904 | &alias_paths, |
---|
1654 | 1905 | |
---|