^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include "dtc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "srcpos.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #ifdef TRACE_CHECKS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #define TRACE(c, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) fprintf(stderr, "=== %s: ", (c)->name); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) fprintf(stderr, __VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) fprintf(stderr, "\n"); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define TRACE(c, fmt, ...) do { } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) enum checkstatus {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) UNCHECKED = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) PREREQ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) PASSED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) FAILED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct check;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) typedef void (*check_fn)(struct check *c, struct dt_info *dti, struct node *node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct check {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) check_fn fn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) void *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) bool warn, error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) enum checkstatus status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) bool inprogress;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) int num_prereqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct check **prereq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CHECK_ENTRY(nm_, fn_, d_, w_, e_, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static struct check *nm_##_prereqs[] = { __VA_ARGS__ }; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static struct check nm_ = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .name = #nm_, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .fn = (fn_), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .data = (d_), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .warn = (w_), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .error = (e_), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .status = UNCHECKED, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .num_prereqs = ARRAY_SIZE(nm_##_prereqs), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .prereq = nm_##_prereqs, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define WARNING(nm_, fn_, d_, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) CHECK_ENTRY(nm_, fn_, d_, true, false, __VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define ERROR(nm_, fn_, d_, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) CHECK_ENTRY(nm_, fn_, d_, false, true, __VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define CHECK(nm_, fn_, d_, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) CHECK_ENTRY(nm_, fn_, d_, false, false, __VA_ARGS__)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static inline void PRINTF(5, 6) check_msg(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct property *prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) const char *fmt, ...)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) va_list ap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) char *str = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct srcpos *pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) char *file_str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!(c->warn && (quiet < 1)) && !(c->error && (quiet < 2)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (prop && prop->srcpos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) pos = prop->srcpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) else if (node && node->srcpos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) pos = node->srcpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) file_str = srcpos_string(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) xasprintf(&str, "%s", file_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) free(file_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) } else if (streq(dti->outname, "-")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) xasprintf(&str, "<stdout>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) xasprintf(&str, "%s", dti->outname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) xasprintf_append(&str, ": %s (%s): ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) (c->error) ? "ERROR" : "Warning", c->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) xasprintf_append(&str, "%s:%s: ", node->fullpath, prop->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) xasprintf_append(&str, "%s: ", node->fullpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) va_start(ap, fmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) xavsprintf_append(&str, fmt, ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) va_end(ap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) xasprintf_append(&str, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!prop && pos) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) pos = node->srcpos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) while (pos->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) pos = pos->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) file_str = srcpos_string(pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) xasprintf_append(&str, " also defined at %s\n", file_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) free(file_str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) fputs(str, stderr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #define FAIL(c, dti, node, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) (c)->status = FAILED; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) check_msg((c), dti, node, NULL, __VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) #define FAIL_PROP(c, dti, node, prop, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) (c)->status = FAILED; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) check_msg((c), dti, node, prop, __VA_ARGS__); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) static void check_nodes_props(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) TRACE(c, "%s", node->fullpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (c->fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) c->fn(c, dti, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) for_each_child(node, child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) check_nodes_props(c, dti, child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static bool run_check(struct check *c, struct dt_info *dti)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct node *dt = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) bool error = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) assert(!c->inprogress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (c->status != UNCHECKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) c->inprogress = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) for (i = 0; i < c->num_prereqs; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) struct check *prq = c->prereq[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) error = error || run_check(prq, dti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (prq->status != PASSED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) c->status = PREREQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) check_msg(c, dti, NULL, NULL, "Failed prerequisite '%s'",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) c->prereq[i]->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (c->status != UNCHECKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) check_nodes_props(c, dti, dt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if (c->status == UNCHECKED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) c->status = PASSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) TRACE(c, "\tCompleted, status %d", c->status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) c->inprogress = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if ((c->status != PASSED) && (c->error))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) error = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * Utility check functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* A check which always fails, for testing purposes only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static inline void check_always_fail(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) FAIL(c, dti, node, "always_fail check");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) CHECK(always_fail, check_always_fail, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static void check_is_string(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) char *propname = c->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) prop = get_property(node, propname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return; /* Not present, assumed ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (!data_is_one_string(prop->val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) FAIL_PROP(c, dti, node, prop, "property is not a string");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #define WARNING_IF_NOT_STRING(nm, propname) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) WARNING(nm, check_is_string, (propname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #define ERROR_IF_NOT_STRING(nm, propname) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ERROR(nm, check_is_string, (propname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static void check_is_string_list(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) int rem, l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) char *propname = c->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) prop = get_property(node, propname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) return; /* Not present, assumed ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) str = prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) rem = prop->val.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) while (rem > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) l = strnlen(str, rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (l == rem) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) FAIL_PROP(c, dti, node, prop, "property is not a string list");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) rem -= l + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) str += l + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #define WARNING_IF_NOT_STRING_LIST(nm, propname) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) WARNING(nm, check_is_string_list, (propname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) #define ERROR_IF_NOT_STRING_LIST(nm, propname) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ERROR(nm, check_is_string_list, (propname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static void check_is_cell(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) char *propname = c->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) prop = get_property(node, propname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return; /* Not present, assumed ok */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) if (prop->val.len != sizeof(cell_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) FAIL_PROP(c, dti, node, prop, "property is not a single cell");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) #define WARNING_IF_NOT_CELL(nm, propname) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) WARNING(nm, check_is_cell, (propname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) #define ERROR_IF_NOT_CELL(nm, propname) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) ERROR(nm, check_is_cell, (propname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * Structural check functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static void check_duplicate_node_names(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) struct node *child, *child2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) for_each_child(node, child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) for (child2 = child->next_sibling;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) child2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) child2 = child2->next_sibling)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (streq(child->name, child2->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) FAIL(c, dti, child2, "Duplicate node name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) ERROR(duplicate_node_names, check_duplicate_node_names, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static void check_duplicate_property_names(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) struct property *prop, *prop2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) for (prop2 = prop->next; prop2; prop2 = prop2->next) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (prop2->deleted)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) if (streq(prop->name, prop2->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) FAIL_PROP(c, dti, node, prop, "Duplicate property name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ERROR(duplicate_property_names, check_duplicate_property_names, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) #define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) #define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) #define DIGITS "0123456789"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) #define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #define PROPNODECHARSSTRICT LOWERCASE UPPERCASE DIGITS ",-"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) static void check_node_name_chars(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) int n = strspn(node->name, c->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (n < strlen(node->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) FAIL(c, dti, node, "Bad character '%c' in node name",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) node->name[n]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) ERROR(node_name_chars, check_node_name_chars, PROPNODECHARS "@");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static void check_node_name_chars_strict(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) int n = strspn(node->name, c->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (n < node->basenamelen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) FAIL(c, dti, node, "Character '%c' not recommended in node name",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) node->name[n]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) CHECK(node_name_chars_strict, check_node_name_chars_strict, PROPNODECHARSSTRICT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static void check_node_name_format(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (strchr(get_unitname(node), '@'))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) FAIL(c, dti, node, "multiple '@' characters in node name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) ERROR(node_name_format, check_node_name_format, NULL, &node_name_chars);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) static void check_unit_address_vs_reg(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) const char *unitname = get_unitname(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct property *prop = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (get_subnode(node, "__overlay__")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* HACK: Overlay fragments are a special case */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (!prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) prop = get_property(node, "ranges");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (prop && !prop->val.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) prop = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (!unitname[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) FAIL(c, dti, node, "node has a reg or ranges property, but no unit name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (unitname[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) FAIL(c, dti, node, "node has a unit name, but no reg or ranges property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) WARNING(unit_address_vs_reg, check_unit_address_vs_reg, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static void check_property_name_chars(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) int n = strspn(prop->name, c->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) if (n < strlen(prop->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) FAIL_PROP(c, dti, node, prop, "Bad character '%c' in property name",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) prop->name[n]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) ERROR(property_name_chars, check_property_name_chars, PROPNODECHARS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) static void check_property_name_chars_strict(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) const char *name = prop->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) int n = strspn(name, c->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (n == strlen(prop->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Certain names are whitelisted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) if (streq(name, "device_type"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) * # is only allowed at the beginning of property names not counting
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) * the vendor prefix.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (name[n] == '#' && ((n == 0) || (name[n-1] == ','))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) name += n + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) n = strspn(name, c->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (n < strlen(name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) FAIL_PROP(c, dti, node, prop, "Character '%c' not recommended in property name",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) name[n]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) CHECK(property_name_chars_strict, check_property_name_chars_strict, PROPNODECHARSSTRICT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) #define DESCLABEL_FMT "%s%s%s%s%s"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) #define DESCLABEL_ARGS(node,prop,mark) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) ((mark) ? "value of " : ""), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) ((prop) ? "'" : ""), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) ((prop) ? (prop)->name : ""), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) ((prop) ? "' in " : ""), (node)->fullpath
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) static void check_duplicate_label(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) const char *label, struct node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) struct property *prop, struct marker *mark)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct node *dt = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct node *othernode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct property *otherprop = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct marker *othermark = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) othernode = get_node_by_label(dt, label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) if (!othernode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) otherprop = get_property_by_label(dt, label, &othernode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if (!othernode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) othermark = get_marker_label(dt, label, &othernode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) &otherprop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (!othernode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if ((othernode != node) || (otherprop != prop) || (othermark != mark))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) FAIL(c, dti, node, "Duplicate label '%s' on " DESCLABEL_FMT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) " and " DESCLABEL_FMT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) label, DESCLABEL_ARGS(node, prop, mark),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) DESCLABEL_ARGS(othernode, otherprop, othermark));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) static void check_duplicate_label_node(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) struct label *l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) for_each_label(node->labels, l)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) check_duplicate_label(c, dti, l->label, node, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) struct marker *m = prop->val.markers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) for_each_label(prop->labels, l)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) check_duplicate_label(c, dti, l->label, node, prop, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) for_each_marker_of_type(m, LABEL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) check_duplicate_label(c, dti, m->ref, node, prop, m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) ERROR(duplicate_label, check_duplicate_label_node, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) static cell_t check_phandle_prop(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) struct node *node, const char *propname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) struct node *root = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct marker *m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) cell_t phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) prop = get_property(node, propname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) if (prop->val.len != sizeof(cell_t)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) FAIL_PROP(c, dti, node, prop, "bad length (%d) %s property",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) prop->val.len, prop->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) m = prop->val.markers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) for_each_marker_of_type(m, REF_PHANDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) assert(m->offset == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (node != get_node_by_ref(root, m->ref))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) /* "Set this node's phandle equal to some
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) * other node's phandle". That's nonsensical
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) * by construction. */ {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) FAIL(c, dti, node, "%s is a reference to another node",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) prop->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* But setting this node's phandle equal to its own
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * phandle is allowed - that means allocate a unique
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * phandle for this node, even if it's not otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * referenced. The value will be filled in later, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * we treat it as having no phandle data for now. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) phandle = propval_cell(prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if ((phandle == 0) || (phandle == -1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) FAIL_PROP(c, dti, node, prop, "bad value (0x%x) in %s property",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) phandle, prop->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) return phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) static void check_explicit_phandles(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) struct node *root = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) struct node *other;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) cell_t phandle, linux_phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) /* Nothing should have assigned phandles yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) assert(!node->phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) phandle = check_phandle_prop(c, dti, node, "phandle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) linux_phandle = check_phandle_prop(c, dti, node, "linux,phandle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) if (!phandle && !linux_phandle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* No valid phandles; nothing further to check */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) if (linux_phandle && phandle && (phandle != linux_phandle))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) FAIL(c, dti, node, "mismatching 'phandle' and 'linux,phandle'"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) " properties");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) if (linux_phandle && !phandle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) phandle = linux_phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) other = get_node_by_phandle(root, phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) if (other && (other != node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) FAIL(c, dti, node, "duplicated phandle 0x%x (seen before at %s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) phandle, other->fullpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) node->phandle = phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) ERROR(explicit_phandles, check_explicit_phandles, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) static void check_name_properties(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct property **pp, *prop = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) for (pp = &node->proplist; *pp; pp = &((*pp)->next))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) if (streq((*pp)->name, "name")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) prop = *pp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return; /* No name property, that's fine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if ((prop->val.len != node->basenamelen+1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) FAIL(c, dti, node, "\"name\" property is incorrect (\"%s\" instead"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) " of base node name)", prop->val.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* The name property is correct, and therefore redundant.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) * Delete it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) *pp = prop->next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) free(prop->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) data_free(prop->val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) free(prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) ERROR_IF_NOT_STRING(name_is_string, "name");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) ERROR(name_properties, check_name_properties, NULL, &name_is_string);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * Reference fixup functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static void fixup_phandle_references(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) struct node *dt = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) struct marker *m = prop->val.markers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) struct node *refnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) cell_t phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) for_each_marker_of_type(m, REF_PHANDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) assert(m->offset + sizeof(cell_t) <= prop->val.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) refnode = get_node_by_ref(dt, m->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) if (! refnode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (!(dti->dtsflags & DTSF_PLUGIN))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) FAIL(c, dti, node, "Reference to non-existent node or "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) "label \"%s\"\n", m->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) else /* mark the entry as unresolved */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) *((fdt32_t *)(prop->val.val + m->offset)) =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) cpu_to_fdt32(0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) phandle = get_node_phandle(dt, refnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) *((fdt32_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) reference_node(refnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ERROR(phandle_references, fixup_phandle_references, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) &duplicate_node_names, &explicit_phandles);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) static void fixup_path_references(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) struct node *dt = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) struct marker *m = prop->val.markers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) struct node *refnode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) char *path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) for_each_marker_of_type(m, REF_PATH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) assert(m->offset <= prop->val.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) refnode = get_node_by_ref(dt, m->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) if (!refnode) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) FAIL(c, dti, node, "Reference to non-existent node or label \"%s\"\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) m->ref);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) path = refnode->fullpath;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) prop->val = data_insert_at_marker(prop->val, m, path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) strlen(path) + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) reference_node(refnode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) ERROR(path_references, fixup_path_references, NULL, &duplicate_node_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) static void fixup_node_disabled(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) struct property *prop = get_property(node, "status");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) const char *status = prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (strcmp(status, "ok") && strcmp(status, "okay"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) omit_node_if_unused(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) CHECK(node_disabled, fixup_node_disabled, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) static void fixup_node_empty(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) if (!node->proplist && !node->children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) omit_node_if_unused(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) CHECK(node_empty, fixup_node_empty, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) static void fixup_omit_unused_nodes(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) if (generate_symbols && node->labels)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) if (node->omit_if_unused && !node->is_referenced)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) delete_node(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (node->deleted) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) struct node *parent = node->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) struct node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) struct label *label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) for_each_label(parent->labels, label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) for_each_property(parent, prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) for_each_child(parent, child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) delete_node(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) ERROR(omit_unused_nodes, fixup_omit_unused_nodes, NULL, &phandle_references, &path_references);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) * Semantic checks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) WARNING_IF_NOT_STRING(model_is_string, "model");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) WARNING_IF_NOT_STRING(status_is_string, "status");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) WARNING_IF_NOT_STRING(label_is_string, "label");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) WARNING_IF_NOT_STRING_LIST(compatible_is_string_list, "compatible");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static void check_names_is_string_list(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) const char *s = strrchr(prop->name, '-');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (!s || !streq(s, "-names"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) c->data = prop->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) check_is_string_list(c, dti, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) WARNING(names_is_string_list, check_names_is_string_list, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) static void check_alias_paths(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) if (!streq(node->name, "aliases"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) if (streq(prop->name, "phandle")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) || streq(prop->name, "linux,phandle")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) prop->val.val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) if (strspn(prop->name, LOWERCASE DIGITS "-") != strlen(prop->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) FAIL(c, dti, node, "aliases property name must include only lowercase and '-'");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) WARNING(alias_paths, check_alias_paths, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) static void fixup_addr_size_cells(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) node->addr_cells = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) node->size_cells = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) prop = get_property(node, "#address-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) node->addr_cells = propval_cell(prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) prop = get_property(node, "#size-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) node->size_cells = propval_cell(prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) WARNING(addr_size_cells, fixup_addr_size_cells, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) &address_cells_is_cell, &size_cells_is_cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) #define node_addr_cells(n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) #define node_size_cells(n) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) (((n)->size_cells == -1) ? 1 : (n)->size_cells)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) static void check_reg_format(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) int addr_cells, size_cells, entrylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) prop = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) return; /* No "reg", that's fine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) if (!node->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) FAIL(c, dti, node, "Root node has a \"reg\" property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) if (prop->val.len == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) FAIL_PROP(c, dti, node, prop, "property is empty");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) addr_cells = node_addr_cells(node->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) size_cells = node_size_cells(node->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) entrylen = (addr_cells + size_cells) * sizeof(cell_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) if (!entrylen || (prop->val.len % entrylen) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) FAIL_PROP(c, dti, node, prop, "property has invalid length (%d bytes) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) "(#address-cells == %d, #size-cells == %d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) prop->val.len, addr_cells, size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) WARNING(reg_format, check_reg_format, NULL, &addr_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) static void check_ranges_format(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) const char *ranges = c->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) prop = get_property(node, ranges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (!node->parent) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) FAIL_PROP(c, dti, node, prop, "Root node has a \"%s\" property",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) ranges);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) p_addr_cells = node_addr_cells(node->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) p_size_cells = node_size_cells(node->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) c_addr_cells = node_addr_cells(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) c_size_cells = node_size_cells(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (prop->val.len == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (p_addr_cells != c_addr_cells)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) "#address-cells (%d) differs from %s (%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) ranges, c_addr_cells, node->parent->fullpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) p_addr_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (p_size_cells != c_size_cells)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) FAIL_PROP(c, dti, node, prop, "empty \"%s\" property but its "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) "#size-cells (%d) differs from %s (%d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) ranges, c_size_cells, node->parent->fullpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) p_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) } else if ((prop->val.len % entrylen) != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) FAIL_PROP(c, dti, node, prop, "\"%s\" property has invalid length (%d bytes) "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) "(parent #address-cells == %d, child #address-cells == %d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) "#size-cells == %d)", ranges, prop->val.len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) p_addr_cells, c_addr_cells, c_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) WARNING(ranges_format, check_ranges_format, "ranges", &addr_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) WARNING(dma_ranges_format, check_ranges_format, "dma-ranges", &addr_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) static const struct bus_type pci_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) .name = "PCI",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static void check_pci_bridge(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) cell_t *cells;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) prop = get_property(node, "device_type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) if (!prop || !streq(prop->val.val, "pci"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) node->bus = &pci_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) if (!strprefixeq(node->name, node->basenamelen, "pci") &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) !strprefixeq(node->name, node->basenamelen, "pcie"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) FAIL(c, dti, node, "node name is not \"pci\" or \"pcie\"");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) prop = get_property(node, "ranges");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) FAIL(c, dti, node, "missing ranges for PCI bridge (or not a bridge)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (node_addr_cells(node) != 3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) FAIL(c, dti, node, "incorrect #address-cells for PCI bridge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (node_size_cells(node) != 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) FAIL(c, dti, node, "incorrect #size-cells for PCI bridge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) prop = get_property(node, "bus-range");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) if (prop->val.len != (sizeof(cell_t) * 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) FAIL_PROP(c, dti, node, prop, "value must be 2 cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) cells = (cell_t *)prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) if (fdt32_to_cpu(cells[0]) > fdt32_to_cpu(cells[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) FAIL_PROP(c, dti, node, prop, "1st cell must be less than or equal to 2nd cell");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (fdt32_to_cpu(cells[1]) > 0xff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) FAIL_PROP(c, dti, node, prop, "maximum bus number must be less than 256");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) WARNING(pci_bridge, check_pci_bridge, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) &device_type_is_string, &addr_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) static void check_pci_device_bus_num(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) unsigned int bus_num, min_bus, max_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) cell_t *cells;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) if (!node->parent || (node->parent->bus != &pci_bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) prop = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) cells = (cell_t *)prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) bus_num = (fdt32_to_cpu(cells[0]) & 0x00ff0000) >> 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) prop = get_property(node->parent, "bus-range");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) if (!prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) min_bus = max_bus = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) cells = (cell_t *)prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) min_bus = fdt32_to_cpu(cells[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) max_bus = fdt32_to_cpu(cells[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) if ((bus_num < min_bus) || (bus_num > max_bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) FAIL_PROP(c, dti, node, prop, "PCI bus number %d out of range, expected (%d - %d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) bus_num, min_bus, max_bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) WARNING(pci_device_bus_num, check_pci_device_bus_num, NULL, ®_format, &pci_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) const char *unitname = get_unitname(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) char unit_addr[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) unsigned int dev, func, reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) cell_t *cells;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (!node->parent || (node->parent->bus != &pci_bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) prop = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) cells = (cell_t *)prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (cells[1] || cells[2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) FAIL_PROP(c, dti, node, prop, "PCI reg config space address cells 2 and 3 must be 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) reg = fdt32_to_cpu(cells[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) dev = (reg & 0xf800) >> 11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) func = (reg & 0x700) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (reg & 0xff000000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) FAIL_PROP(c, dti, node, prop, "PCI reg address is not configuration space");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) if (reg & 0x000000ff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) FAIL_PROP(c, dti, node, prop, "PCI reg config space address register number must be 0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) if (func == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) snprintf(unit_addr, sizeof(unit_addr), "%x", dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (streq(unitname, unit_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) snprintf(unit_addr, sizeof(unit_addr), "%x,%x", dev, func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (streq(unitname, unit_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) FAIL(c, dti, node, "PCI unit address format error, expected \"%s\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) unit_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) WARNING(pci_device_reg, check_pci_device_reg, NULL, ®_format, &pci_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) static const struct bus_type simple_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) .name = "simple-bus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static bool node_is_compatible(struct node *node, const char *compat)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) const char *str, *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) prop = get_property(node, "compatible");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) for (str = prop->val.val, end = str + prop->val.len; str < end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) str += strnlen(str, end - str) + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (streq(str, compat))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) static void check_simple_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) if (node_is_compatible(node, "simple-bus"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) node->bus = &simple_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) WARNING(simple_bus_bridge, check_simple_bus_bridge, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) &addr_size_cells, &compatible_is_string_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) const char *unitname = get_unitname(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) char unit_addr[17];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) unsigned int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) uint64_t reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) cell_t *cells = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (!node->parent || (node->parent->bus != &simple_bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) prop = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) cells = (cell_t *)prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) prop = get_property(node, "ranges");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) if (prop && prop->val.len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) /* skip of child address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) cells = ((cell_t *)prop->val.val) + node_addr_cells(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (!cells) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) if (node->parent->parent && !(node->bus == &simple_bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) FAIL(c, dti, node, "missing or empty reg/ranges property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) size = node_addr_cells(node->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) while (size--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) reg = (reg << 32) | fdt32_to_cpu(*(cells++));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) snprintf(unit_addr, sizeof(unit_addr), "%"PRIx64, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (!streq(unitname, unit_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) FAIL(c, dti, node, "simple-bus unit address format error, expected \"%s\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) unit_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) WARNING(simple_bus_reg, check_simple_bus_reg, NULL, ®_format, &simple_bus_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static const struct bus_type i2c_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .name = "i2c-bus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) static void check_i2c_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (strprefixeq(node->name, node->basenamelen, "i2c-bus") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) strprefixeq(node->name, node->basenamelen, "i2c-arb")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) node->bus = &i2c_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) } else if (strprefixeq(node->name, node->basenamelen, "i2c")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) struct node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) for_each_child(node, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (strprefixeq(child->name, node->basenamelen, "i2c-bus"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) node->bus = &i2c_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) if (!node->children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (node_addr_cells(node) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) FAIL(c, dti, node, "incorrect #address-cells for I2C bus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) if (node_size_cells(node) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) FAIL(c, dti, node, "incorrect #size-cells for I2C bus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) WARNING(i2c_bus_bridge, check_i2c_bus_bridge, NULL, &addr_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) #define I2C_OWN_SLAVE_ADDRESS (1U << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) #define I2C_TEN_BIT_ADDRESS (1U << 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) static void check_i2c_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) const char *unitname = get_unitname(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) char unit_addr[17];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) uint32_t reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) cell_t *cells = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (!node->parent || (node->parent->bus != &i2c_bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) prop = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) cells = (cell_t *)prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) if (!cells) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) FAIL(c, dti, node, "missing or empty reg property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) reg = fdt32_to_cpu(*cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /* Ignore I2C_OWN_SLAVE_ADDRESS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) reg &= ~I2C_OWN_SLAVE_ADDRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) if (!streq(unitname, unit_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) FAIL(c, dti, node, "I2C bus unit address format error, expected \"%s\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) unit_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) for (len = prop->val.len; len > 0; len -= 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) reg = fdt32_to_cpu(*(cells++));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) /* Ignore I2C_OWN_SLAVE_ADDRESS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) reg &= ~I2C_OWN_SLAVE_ADDRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if ((reg & I2C_TEN_BIT_ADDRESS) && ((reg & ~I2C_TEN_BIT_ADDRESS) > 0x3ff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) FAIL_PROP(c, dti, node, prop, "I2C address must be less than 10-bits, got \"0x%x\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) else if (reg > 0x7f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 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",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) WARNING(i2c_bus_reg, check_i2c_bus_reg, NULL, ®_format, &i2c_bus_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) static const struct bus_type spi_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) .name = "spi-bus",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) static void check_spi_bus_bridge(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) int spi_addr_cells = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) if (strprefixeq(node->name, node->basenamelen, "spi")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) node->bus = &spi_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) /* Try to detect SPI buses which don't have proper node name */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) struct node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (node_addr_cells(node) != 1 || node_size_cells(node) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) for_each_child(node, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) for_each_property(child, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) if (strprefixeq(prop->name, 4, "spi-")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) node->bus = &spi_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (node->bus == &spi_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) if (node->bus == &spi_bus && get_property(node, "reg"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) FAIL(c, dti, node, "node name for SPI buses should be 'spi'");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) if (node->bus != &spi_bus || !node->children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) if (get_property(node, "spi-slave"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) spi_addr_cells = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (node_addr_cells(node) != spi_addr_cells)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) FAIL(c, dti, node, "incorrect #address-cells for SPI bus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) if (node_size_cells(node) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) FAIL(c, dti, node, "incorrect #size-cells for SPI bus");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) WARNING(spi_bus_bridge, check_spi_bus_bridge, NULL, &addr_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) static void check_spi_bus_reg(struct check *c, struct dt_info *dti, struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) const char *unitname = get_unitname(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) char unit_addr[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) uint32_t reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) cell_t *cells = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) if (!node->parent || (node->parent->bus != &spi_bus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) if (get_property(node->parent, "spi-slave"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) prop = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) cells = (cell_t *)prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) if (!cells) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) FAIL(c, dti, node, "missing or empty reg property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) reg = fdt32_to_cpu(*cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) snprintf(unit_addr, sizeof(unit_addr), "%x", reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) if (!streq(unitname, unit_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) FAIL(c, dti, node, "SPI bus unit address format error, expected \"%s\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) unit_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) WARNING(spi_bus_reg, check_spi_bus_reg, NULL, ®_format, &spi_bus_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static void check_unit_address_format(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) const char *unitname = get_unitname(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) if (node->parent && node->parent->bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) if (!unitname[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) if (!strncmp(unitname, "0x", 2)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) FAIL(c, dti, node, "unit name should not have leading \"0x\"");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) /* skip over 0x for next test */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) unitname += 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) if (unitname[0] == '0' && isxdigit(unitname[1]))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) FAIL(c, dti, node, "unit name should not have leading 0s");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) WARNING(unit_address_format, check_unit_address_format, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) &node_name_format, &pci_bridge, &simple_bus_bridge);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) * Style checks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) static void check_avoid_default_addr_size(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) struct property *reg, *ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) if (!node->parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) return; /* Ignore root node */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) reg = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) ranges = get_property(node, "ranges");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) if (!reg && !ranges)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) if (node->parent->addr_cells == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) FAIL(c, dti, node, "Relying on default #address-cells value");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) if (node->parent->size_cells == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) FAIL(c, dti, node, "Relying on default #size-cells value");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) WARNING(avoid_default_addr_size, check_avoid_default_addr_size, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) &addr_size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static void check_avoid_unnecessary_addr_size(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) struct node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) bool has_reg = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (!node->parent || node->addr_cells < 0 || node->size_cells < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) if (get_property(node, "ranges") || !node->children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) for_each_child(node, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) prop = get_property(child, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) has_reg = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) if (!has_reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) FAIL(c, dti, node, "unnecessary #address-cells/#size-cells without \"ranges\" or child \"reg\" property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) WARNING(avoid_unnecessary_addr_size, check_avoid_unnecessary_addr_size, NULL, &avoid_default_addr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) static bool node_is_disabled(struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) prop = get_property(node, "status");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) if (prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) char *str = prop->val.val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) if (streq("disabled", str))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) static void check_unique_unit_address_common(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) struct node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) bool disable_check)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct node *childa;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (node->addr_cells < 0 || node->size_cells < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) if (!node->children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) for_each_child(node, childa) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) struct node *childb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) const char *addr_a = get_unitname(childa);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) if (!strlen(addr_a))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) if (disable_check && node_is_disabled(childa))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) for_each_child(node, childb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) const char *addr_b = get_unitname(childb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (childa == childb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (disable_check && node_is_disabled(childb))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (streq(addr_a, addr_b))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) FAIL(c, dti, childb, "duplicate unit-address (also used in node %s)", childa->fullpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) static void check_unique_unit_address(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) check_unique_unit_address_common(c, dti, node, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) WARNING(unique_unit_address, check_unique_unit_address, NULL, &avoid_default_addr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) static void check_unique_unit_address_if_enabled(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) check_unique_unit_address_common(c, dti, node, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) CHECK_ENTRY(unique_unit_address_if_enabled, check_unique_unit_address_if_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) NULL, false, false, &avoid_default_addr_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) static void check_obsolete_chosen_interrupt_controller(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) struct node *dt = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) struct node *chosen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) if (node != dt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) chosen = get_node_by_path(dt, "/chosen");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) if (!chosen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) prop = get_property(chosen, "interrupt-controller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) FAIL_PROP(c, dti, node, prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) "/chosen has obsolete \"interrupt-controller\" property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) WARNING(obsolete_chosen_interrupt_controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) check_obsolete_chosen_interrupt_controller, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) static void check_chosen_node_is_root(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) if (!streq(node->name, "chosen"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) if (node->parent != dti->dt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) FAIL(c, dti, node, "chosen node must be at root node");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) WARNING(chosen_node_is_root, check_chosen_node_is_root, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) static void check_chosen_node_bootargs(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) if (!streq(node->name, "chosen"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) prop = get_property(node, "bootargs");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) c->data = prop->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) check_is_string(c, dti, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) WARNING(chosen_node_bootargs, check_chosen_node_bootargs, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) static void check_chosen_node_stdout_path(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) if (!streq(node->name, "chosen"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) prop = get_property(node, "stdout-path");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) if (!prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) prop = get_property(node, "linux,stdout-path");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) FAIL_PROP(c, dti, node, prop, "Use 'stdout-path' instead");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) c->data = prop->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) check_is_string(c, dti, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) WARNING(chosen_node_stdout_path, check_chosen_node_stdout_path, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) struct provider {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) const char *prop_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) const char *cell_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) bool optional;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) static void check_property_phandle_args(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) struct node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) struct property *prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) const struct provider *provider)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) struct node *root = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) int cell, cellsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) if (prop->val.len % sizeof(cell_t)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) FAIL_PROP(c, dti, node, prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) "property size (%d) is invalid, expected multiple of %zu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) prop->val.len, sizeof(cell_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) for (cell = 0; cell < prop->val.len / sizeof(cell_t); cell += cellsize + 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) struct node *provider_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) struct property *cellprop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) int phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) phandle = propval_cell_n(prop, cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) * Some bindings use a cell value 0 or -1 to skip over optional
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) * entries when each index position has a specific definition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) if (phandle == 0 || phandle == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) /* Give up if this is an overlay with external references */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) if (dti->dtsflags & DTSF_PLUGIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) cellsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) /* If we have markers, verify the current cell is a phandle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) if (prop->val.markers) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) struct marker *m = prop->val.markers;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) for_each_marker_of_type(m, REF_PHANDLE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) if (m->offset == (cell * sizeof(cell_t)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) if (!m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) FAIL_PROP(c, dti, node, prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) "cell %d is not a phandle reference",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) provider_node = get_node_by_phandle(root, phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) if (!provider_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) FAIL_PROP(c, dti, node, prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) "Could not get phandle node for (cell %d)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) cellprop = get_property(provider_node, provider->cell_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) if (cellprop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461) cellsize = propval_cell(cellprop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) } else if (provider->optional) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) cellsize = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) FAIL(c, dti, node, "Missing property '%s' in node %s or bad phandle (referred from %s[%d])",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) provider->cell_name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) provider_node->fullpath,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) prop->name, cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) if (prop->val.len < ((cell + cellsize + 1) * sizeof(cell_t))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) FAIL_PROP(c, dti, node, prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) "property size (%d) too small for cell size %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) prop->val.len, cellsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) static void check_provider_cells_property(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) struct provider *provider = c->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) prop = get_property(node, provider->prop_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) check_property_phandle_args(c, dti, node, prop, provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) #define WARNING_PROPERTY_PHANDLE_CELLS(nm, propname, cells_name, ...) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494) static struct provider nm##_provider = { (propname), (cells_name), __VA_ARGS__ }; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) WARNING(nm##_property, check_provider_cells_property, &nm##_provider, &phandle_references);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) WARNING_PROPERTY_PHANDLE_CELLS(clocks, "clocks", "#clock-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) WARNING_PROPERTY_PHANDLE_CELLS(cooling_device, "cooling-device", "#cooling-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) WARNING_PROPERTY_PHANDLE_CELLS(dmas, "dmas", "#dma-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) WARNING_PROPERTY_PHANDLE_CELLS(hwlocks, "hwlocks", "#hwlock-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) WARNING_PROPERTY_PHANDLE_CELLS(interrupts_extended, "interrupts-extended", "#interrupt-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) WARNING_PROPERTY_PHANDLE_CELLS(io_channels, "io-channels", "#io-channel-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) WARNING_PROPERTY_PHANDLE_CELLS(iommus, "iommus", "#iommu-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) WARNING_PROPERTY_PHANDLE_CELLS(mboxes, "mboxes", "#mbox-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) WARNING_PROPERTY_PHANDLE_CELLS(msi_parent, "msi-parent", "#msi-cells", true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) WARNING_PROPERTY_PHANDLE_CELLS(mux_controls, "mux-controls", "#mux-control-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) WARNING_PROPERTY_PHANDLE_CELLS(phys, "phys", "#phy-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) WARNING_PROPERTY_PHANDLE_CELLS(power_domains, "power-domains", "#power-domain-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) WARNING_PROPERTY_PHANDLE_CELLS(pwms, "pwms", "#pwm-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) WARNING_PROPERTY_PHANDLE_CELLS(resets, "resets", "#reset-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) WARNING_PROPERTY_PHANDLE_CELLS(sound_dai, "sound-dai", "#sound-dai-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) WARNING_PROPERTY_PHANDLE_CELLS(thermal_sensors, "thermal-sensors", "#thermal-sensor-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514) static bool prop_is_gpio(struct property *prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) * *-gpios and *-gpio can appear in property names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) * so skip over any false matches (only one known ATM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) if (strstr(prop->name, "nr-gpio"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) str = strrchr(prop->name, '-');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) if (str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) str++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) str = prop->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) if (!(streq(str, "gpios") || streq(str, "gpio")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) static void check_gpios_property(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) /* Skip GPIO hog nodes which have 'gpios' property */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) if (get_property(node, "gpio-hog"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) struct provider provider;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) if (!prop_is_gpio(prop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) provider.prop_name = prop->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) provider.cell_name = "#gpio-cells";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) provider.optional = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) check_property_phandle_args(c, dti, node, prop, &provider);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) WARNING(gpios_property, check_gpios_property, NULL, &phandle_references);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) static void check_deprecated_gpio_property(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) for_each_property(node, prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) char *str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) if (!prop_is_gpio(prop))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) str = strstr(prop->name, "gpio");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) if (!streq(str, "gpio"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) FAIL_PROP(c, dti, node, prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) "'[*-]gpio' is deprecated, use '[*-]gpios' instead");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) CHECK(deprecated_gpio_property, check_deprecated_gpio_property, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) static bool node_is_interrupt_provider(struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) prop = get_property(node, "interrupt-controller");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) prop = get_property(node, "interrupt-map");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) if (prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) static void check_interrupt_provider(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) if (!node_is_interrupt_provider(node))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) prop = get_property(node, "#interrupt-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) FAIL(c, dti, node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611) "Missing #interrupt-cells in interrupt provider");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) prop = get_property(node, "#address-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) FAIL(c, dti, node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) "Missing #address-cells in interrupt provider");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) WARNING(interrupt_provider, check_interrupt_provider, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) static void check_interrupts_property(struct check *c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) struct node *root = dti->dt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) struct node *irq_node = NULL, *parent = node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) struct property *irq_prop, *prop = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627) int irq_cells, phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) irq_prop = get_property(node, "interrupts");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) if (!irq_prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) if (irq_prop->val.len % sizeof(cell_t))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) FAIL_PROP(c, dti, node, irq_prop, "size (%d) is invalid, expected multiple of %zu",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) irq_prop->val.len, sizeof(cell_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) while (parent && !prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) if (parent != node && node_is_interrupt_provider(parent)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) irq_node = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) prop = get_property(parent, "interrupt-parent");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) if (prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) phandle = propval_cell(prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) if ((phandle == 0) || (phandle == -1)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) /* Give up if this is an overlay with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) * external references */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) if (dti->dtsflags & DTSF_PLUGIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) FAIL_PROP(c, dti, parent, prop, "Invalid phandle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) irq_node = get_node_by_phandle(root, phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) if (!irq_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) FAIL_PROP(c, dti, parent, prop, "Bad phandle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) if (!node_is_interrupt_provider(irq_node))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) FAIL(c, dti, irq_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) "Missing interrupt-controller or interrupt-map property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) parent = parent->parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670) if (!irq_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) FAIL(c, dti, node, "Missing interrupt-parent");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) prop = get_property(irq_node, "#interrupt-cells");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676) if (!prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) /* We warn about that already in another test. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) irq_cells = propval_cell(prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) if (irq_prop->val.len % (irq_cells * sizeof(cell_t))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683) FAIL_PROP(c, dti, node, prop,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) "size is (%d), expected multiple of %d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) irq_prop->val.len, (int)(irq_cells * sizeof(cell_t)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) WARNING(interrupts_property, check_interrupts_property, &phandle_references);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) static const struct bus_type graph_port_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) .name = "graph-port",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) static const struct bus_type graph_ports_bus = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) .name = "graph-ports",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) static void check_graph_nodes(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) struct node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703) for_each_child(node, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) if (!(strprefixeq(child->name, child->basenamelen, "endpoint") ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) get_property(child, "remote-endpoint")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) node->bus = &graph_port_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) /* The parent of 'port' nodes can be either 'ports' or a device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) if (!node->parent->bus &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) (streq(node->parent->name, "ports") || get_property(node, "reg")))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) node->parent->bus = &graph_ports_bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) WARNING(graph_nodes, check_graph_nodes, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) static void check_graph_child_address(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) int cnt = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725) struct node *child;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) if (node->bus != &graph_ports_bus && node->bus != &graph_port_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) for_each_child(node, child) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731) struct property *prop = get_property(child, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) /* No error if we have any non-zero unit address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) if (prop && propval_cell(prop) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) if (cnt == 1 && node->addr_cells != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) FAIL(c, dti, node, "graph node has single child node '%s', #address-cells/#size-cells are not necessary",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) node->children->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744) WARNING(graph_child_address, check_graph_child_address, NULL, &graph_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) static void check_graph_reg(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) char unit_addr[9];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) const char *unitname = get_unitname(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1753) prop = get_property(node, "reg");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1754) if (!prop || !unitname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1755) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1757) if (!(prop->val.val && prop->val.len == sizeof(cell_t))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1758) FAIL(c, dti, node, "graph node malformed 'reg' property");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1759) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1761)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1762) snprintf(unit_addr, sizeof(unit_addr), "%x", propval_cell(prop));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1763) if (!streq(unitname, unit_addr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1764) FAIL(c, dti, node, "graph node unit address error, expected \"%s\"",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1765) unit_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1767) if (node->parent->addr_cells != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1768) FAIL_PROP(c, dti, node, get_property(node, "#address-cells"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1769) "graph node '#address-cells' is %d, must be 1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1770) node->parent->addr_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1771) if (node->parent->size_cells != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1772) FAIL_PROP(c, dti, node, get_property(node, "#size-cells"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1773) "graph node '#size-cells' is %d, must be 0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1774) node->parent->size_cells);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1777) static void check_graph_port(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1778) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1779) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1780) if (node->bus != &graph_port_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1781) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1783) if (!strprefixeq(node->name, node->basenamelen, "port"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1784) FAIL(c, dti, node, "graph port node name should be 'port'");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1786) check_graph_reg(c, dti, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1787) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1788) WARNING(graph_port, check_graph_port, NULL, &graph_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1790) static struct node *get_remote_endpoint(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1791) struct node *endpoint)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1792) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1793) int phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1794) struct node *node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1795) struct property *prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1797) prop = get_property(endpoint, "remote-endpoint");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1798) if (!prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1799) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1801) phandle = propval_cell(prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1802) /* Give up if this is an overlay with external references */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1803) if (phandle == 0 || phandle == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1804) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1806) node = get_node_by_phandle(dti->dt, phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1807) if (!node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1808) FAIL_PROP(c, dti, endpoint, prop, "graph phandle is not valid");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1810) return node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1811) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1813) static void check_graph_endpoint(struct check *c, struct dt_info *dti,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1814) struct node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1815) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1816) struct node *remote_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1818) if (!node->parent || node->parent->bus != &graph_port_bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1819) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1821) if (!strprefixeq(node->name, node->basenamelen, "endpoint"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1822) FAIL(c, dti, node, "graph endpoint node name should be 'endpoint'");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1824) check_graph_reg(c, dti, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1826) remote_node = get_remote_endpoint(c, dti, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1827) if (!remote_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1828) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1829)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1830) if (get_remote_endpoint(c, dti, remote_node) != node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1831) FAIL(c, dti, node, "graph connection to node '%s' is not bidirectional",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1832) remote_node->fullpath);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1833) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1834) WARNING(graph_endpoint, check_graph_endpoint, NULL, &graph_nodes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1835)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1836) static struct check *check_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1837) &duplicate_node_names, &duplicate_property_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1838) &node_name_chars, &node_name_format, &property_name_chars,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1839) &name_is_string, &name_properties,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1841) &duplicate_label,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1842)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1843) &explicit_phandles,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1844) &phandle_references, &path_references,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1845) &node_disabled, &node_empty,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1846) &omit_unused_nodes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1848) &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1849) &device_type_is_string, &model_is_string, &status_is_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1850) &label_is_string,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1852) &compatible_is_string_list, &names_is_string_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1854) &property_name_chars_strict,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1855) &node_name_chars_strict,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1857) &addr_size_cells, ®_format, &ranges_format, &dma_ranges_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1859) &unit_address_vs_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1860) &unit_address_format,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1862) &pci_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1863) &pci_device_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1864) &pci_device_bus_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1866) &simple_bus_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1867) &simple_bus_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1869) &i2c_bus_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1870) &i2c_bus_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1872) &spi_bus_bridge,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1873) &spi_bus_reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1874)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1875) &avoid_default_addr_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1876) &avoid_unnecessary_addr_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1877) &unique_unit_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1878) &unique_unit_address_if_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1879) &obsolete_chosen_interrupt_controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1880) &chosen_node_is_root, &chosen_node_bootargs, &chosen_node_stdout_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1882) &clocks_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1883) &cooling_device_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1884) &dmas_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1885) &hwlocks_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1886) &interrupts_extended_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1887) &io_channels_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1888) &iommus_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1889) &mboxes_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1890) &msi_parent_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1891) &mux_controls_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1892) &phys_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1893) &power_domains_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1894) &pwms_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1895) &resets_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1896) &sound_dai_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1897) &thermal_sensors_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1899) &deprecated_gpio_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1900) &gpios_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1901) &interrupts_property,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1902) &interrupt_provider,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1904) &alias_paths,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1906) &graph_nodes, &graph_child_address, &graph_port, &graph_endpoint,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1908) &always_fail,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1909) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1910)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1911) static void enable_warning_error(struct check *c, bool warn, bool error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1912) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1913) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1914)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1915) /* Raising level, also raise it for prereqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1916) if ((warn && !c->warn) || (error && !c->error))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1917) for (i = 0; i < c->num_prereqs; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1918) enable_warning_error(c->prereq[i], warn, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1919)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1920) c->warn = c->warn || warn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1921) c->error = c->error || error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1922) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1924) static void disable_warning_error(struct check *c, bool warn, bool error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1926) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1928) /* Lowering level, also lower it for things this is the prereq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1929) * for */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1930) if ((warn && c->warn) || (error && c->error)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1931) for (i = 0; i < ARRAY_SIZE(check_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1932) struct check *cc = check_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1933) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1935) for (j = 0; j < cc->num_prereqs; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1936) if (cc->prereq[j] == c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1937) disable_warning_error(cc, warn, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1938) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1939) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1941) c->warn = c->warn && !warn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1942) c->error = c->error && !error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1944)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1945) void parse_checks_option(bool warn, bool error, const char *arg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1946) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1947) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1948) const char *name = arg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1949) bool enable = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1951) if ((strncmp(arg, "no-", 3) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1952) || (strncmp(arg, "no_", 3) == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1953) name = arg + 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1954) enable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1955) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1957) for (i = 0; i < ARRAY_SIZE(check_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1958) struct check *c = check_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1960) if (streq(c->name, name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1961) if (enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1962) enable_warning_error(c, warn, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1963) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1964) disable_warning_error(c, warn, error);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1965) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1966) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1969) die("Unrecognized check name \"%s\"\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1970) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1971)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1972) void process_checks(bool force, struct dt_info *dti)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1973) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1974) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1975) int error = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1977) for (i = 0; i < ARRAY_SIZE(check_table); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1978) struct check *c = check_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1980) if (c->warn || c->error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1981) error = error || run_check(c, dti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1984) if (error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1985) if (!force) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1986) fprintf(stderr, "ERROR: Input tree has errors, aborting "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1987) "(use -f to force output)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1988) exit(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1989) } else if (quiet < 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1990) fprintf(stderr, "Warning: Input tree has errors, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1991) "output forced\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1994) }