diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index 992575f1e976..fa2ae6f63352 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -154,6 +154,7 @@ static void conf_message(const char *fmt, ...)
 
 static const char *conf_filename;
 static int conf_lineno, conf_warnings;
+const char *verbose;
 
 static void conf_warning(const char *fmt, ...)
 {
@@ -226,7 +227,7 @@ static const char *conf_get_rustccfg_name(void)
 static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
 {
 	char *p2;
-
+	static const char * const type[] = {"unknown", "bool", "tristate", "int", "hex", "string"};
 	switch (sym->type) {
 	case S_TRISTATE:
 		if (p[0] == 'm') {
@@ -246,9 +247,14 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
 			sym->flags |= def_flags;
 			break;
 		}
-		if (def != S_DEF_AUTO)
-			conf_warning("symbol value '%s' invalid for %s",
+		if (def != S_DEF_AUTO) {
+			if (verbose)
+				conf_warning("symbol value '%s' invalid for %s\n due to its type is %s",
+				     p, sym->name, type[sym->type]);
+			else
+				conf_warning("symbol value '%s' invalid for %s",
 				     p, sym->name);
+		}
 		return 1;
 	case S_STRING:
 		/* No escaping for S_DEF_AUTO (include/config/auto.conf) */
@@ -274,9 +280,14 @@ static int conf_set_sym_val(struct symbol *sym, int def, int def_flags, char *p)
 			sym->def[def].val = xstrdup(p);
 			sym->flags |= def_flags;
 		} else {
-			if (def != S_DEF_AUTO)
-				conf_warning("symbol value '%s' invalid for %s",
-					     p, sym->name);
+			if (def != S_DEF_AUTO) {
+				if (verbose)
+					conf_warning("symbol value '%s' invalid for %s\n due to its type is %s",
+						p, sym->name, type[sym->type]);
+				else
+					conf_warning("symbol value '%s' invalid for %s",
+						p, sym->name);
+			}
 			return 1;
 		}
 		break;
@@ -528,6 +539,7 @@ int conf_read(const char *name)
 	int conf_unsaved = 0;
 	int i;
 
+	verbose = getenv("KCONFIG_VERBOSE");
 	conf_set_changed(false);
 
 	if (conf_read_simple(name, S_DEF_USER)) {
@@ -559,6 +571,103 @@ int conf_read(const char *name)
 			continue;
 		conf_unsaved++;
 		/* maybe print value in verbose mode... */
+		if (verbose) {
+			if (sym_is_choice_value(sym)) {
+				struct property *prop = sym_get_choice_prop(sym);
+				struct symbol *defsym = prop_get_symbol(prop)->curr.val;
+
+				if (defsym && defsym != sym) {
+					struct gstr gs = str_new();
+
+					str_printf(&gs,
+						"\nERROR : %s[%c => %c] value is invalid\n",
+						sym->name,
+						tristate2char[sym->def[S_DEF_USER].tri],
+						tristate2char[sym->curr.tri]);
+					str_printf(&gs,
+						" due to its not the choice default symbol\n");
+					str_printf(&gs,
+						" the default symbol is %s\n",
+						defsym->name);
+					fputs(str_get(&gs), stderr);
+				}
+			} else {
+				switch (sym->type) {
+				case S_BOOLEAN:
+				case S_TRISTATE:
+					if (sym->dir_dep.tri == no &&
+						sym->def[S_DEF_USER].tri != no) {
+						struct gstr gs = str_new();
+
+						str_printf(&gs,
+							"\nERROR: unmet direct dependencies detected for %s[%c => %c]\n",
+							sym->name,
+							tristate2char[sym->def[S_DEF_USER].tri],
+							tristate2char[sym->curr.tri]);
+						str_printf(&gs,
+							"  Depends on [%c]: ",
+							sym->dir_dep.tri == mod ? 'm' : 'n');
+						expr_gstr_print(sym->dir_dep.expr, &gs);
+						str_printf(&gs, "\n");
+						fputs(str_get(&gs), stderr);
+					} else if (sym->rev_dep.tri != no) {
+						struct gstr gs = str_new();
+
+						str_printf(&gs,
+							"\nERROR : %s[%c => %c] value is invalid\n",
+							sym->name,
+							tristate2char[sym->def[S_DEF_USER].tri],
+							tristate2char[sym->curr.tri]);
+						str_printf(&gs,
+							" due to its invisible and it is selected\n");
+						expr_gstr_print_revdep(sym->rev_dep.expr, &gs, yes,
+									"  Selected by [y]:\n");
+						expr_gstr_print_revdep(sym->rev_dep.expr, &gs, mod,
+									"  Selected by [m]:\n");
+						fputs(str_get(&gs), stderr);
+					} else {
+						sym_validate_default(sym);
+					}
+					break;
+				case S_INT:
+				case S_HEX:
+					if (sym->dir_dep.tri == no &&
+					strcmp((char *)(sym->def[S_DEF_USER].val), "") != 0) {
+						struct gstr gs = str_new();
+
+						str_printf(&gs,
+							"\nERROR: unmet direct dependencies detected for %s\n",
+							sym->name);
+						str_printf(&gs,
+							"  Depends on [%c]: ",
+							sym->dir_dep.tri == mod ? 'm' : 'n');
+						expr_gstr_print(sym->dir_dep.expr, &gs);
+						str_printf(&gs, "\n");
+						fputs(str_get(&gs), stderr);
+					} else {
+						sym_validate_default(sym);
+					}
+					break;
+				case S_STRING:
+					if (sym->dir_dep.tri == no &&
+					strcmp((char *)(sym->def[S_DEF_USER].val), "") != 0) {
+						struct gstr gs = str_new();
+
+						str_printf(&gs,
+							"\nERROR: unmet direct dependencies detected for %s\n",
+							sym->name);
+						str_printf(&gs,
+							"  Depends on [%c]: ",
+							sym->dir_dep.tri == mod ? 'm' : 'n');
+						expr_gstr_print(sym->dir_dep.expr, &gs);
+						str_printf(&gs, "\n");
+						fputs(str_get(&gs), stderr);
+					}
+				default:
+					break;
+				}
+			}
+		}
 	}
 
 	for_all_symbols(i, sym) {
diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h
index 471a59acecec..820a47fb4968 100644
--- a/scripts/kconfig/lkc.h
+++ b/scripts/kconfig/lkc.h
@@ -38,6 +38,8 @@ void zconf_initscan(const char *name);
 void zconf_nextfile(const char *name);
 int zconf_lineno(void);
 const char *zconf_curname(void);
+extern const char *verbose;
+static const char tristate2char[3] = {'n', 'm', 'y'};
 
 /* confdata.c */
 const char *conf_get_configname(void);
@@ -112,6 +114,7 @@ struct property *sym_get_range_prop(struct symbol *sym);
 const char *sym_get_string_default(struct symbol *sym);
 struct symbol *sym_check_deps(struct symbol *sym);
 struct symbol *prop_get_symbol(struct property *prop);
+void sym_validate_default(struct symbol *sym);
 
 static inline tristate sym_get_tristate_value(struct symbol *sym)
 {
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 0572330bf8a7..8b11d6ea1d30 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -91,6 +91,53 @@ static struct property *sym_get_default_prop(struct symbol *sym)
 	return NULL;
 }
 
+void sym_validate_default(struct symbol *sym)
+{
+	if (sym->visible == no) {
+		struct gstr gs = str_new();
+		const char *value = sym_get_string_default(sym);
+
+		switch (sym->type) {
+		case S_BOOLEAN:
+		case S_TRISTATE:
+			if (strcmp(value, "n") != 0) {
+				str_printf(&gs,
+					"\nERROR : %s[%c => %c] value is invalid\n due to it has default value\n",
+					sym->name,
+					tristate2char[sym->def[S_DEF_USER].tri],
+					tristate2char[sym->curr.tri]);
+			} else if (sym->implied.tri != no) {
+				str_printf(&gs,
+					"\nERROR : %s[%c => %c] value is invalid\n due to its invisible and has imply value\n",
+					sym->name,
+					tristate2char[sym->def[S_DEF_USER].tri],
+					tristate2char[sym->curr.tri]);
+				str_printf(&gs,
+					" Imply : ");
+				expr_gstr_print(sym->implied.expr, &gs);
+				str_printf(&gs, "\n");
+			}
+			break;
+		case S_STRING:
+		case S_INT:
+		case S_HEX:
+			if (strcmp(value, "") != 0) {
+				str_printf(&gs,
+					"\nERROR : %s[%s => %s] value is invalid\n",
+					sym->name,
+					(char *)(sym->def[S_DEF_USER].val),
+					(char *)(sym->curr.val));
+				str_printf(&gs,
+					" due to it has default value\n");
+			}
+			break;
+		default:
+			break;
+		}
+		fputs(str_get(&gs), stderr);
+	}
+}
+
 struct property *sym_get_range_prop(struct symbol *sym)
 {
 	struct property *prop;
@@ -600,7 +647,8 @@ bool sym_string_valid(struct symbol *sym, const char *str)
 bool sym_string_within_range(struct symbol *sym, const char *str)
 {
 	struct property *prop;
-	long long val;
+	long long val, left, right;
+	struct gstr gs = str_new();
 
 	switch (sym->type) {
 	case S_STRING:
@@ -612,8 +660,20 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
 		if (!prop)
 			return true;
 		val = strtoll(str, NULL, 10);
-		return val >= sym_get_range_val(prop->expr->left.sym, 10) &&
-		       val <= sym_get_range_val(prop->expr->right.sym, 10);
+		left = sym_get_range_val(prop->expr->left.sym, 10);
+		right = sym_get_range_val(prop->expr->right.sym, 10);
+		if (val >= left && val <= right)
+			return true;
+		if (verbose) {
+			str_printf(&gs,
+				"\nERROR: unmet range detected for %s\n",
+				sym->name);
+			str_printf(&gs,
+				" symbol value is %lld, the range is (%lld %lld)\n",
+				val, left, right);
+			fputs(str_get(&gs), stderr);
+		}
+		return false;
 	case S_HEX:
 		if (!sym_string_valid(sym, str))
 			return false;
@@ -621,8 +681,20 @@ bool sym_string_within_range(struct symbol *sym, const char *str)
 		if (!prop)
 			return true;
 		val = strtoll(str, NULL, 16);
-		return val >= sym_get_range_val(prop->expr->left.sym, 16) &&
-		       val <= sym_get_range_val(prop->expr->right.sym, 16);
+		left = sym_get_range_val(prop->expr->left.sym, 16);
+		right = sym_get_range_val(prop->expr->right.sym, 16);
+		if (val >= left && val <= right)
+			return true;
+		if (verbose) {
+			str_printf(&gs,
+				"\nERROR: unmet range detected for %s\n",
+				sym->name);
+			str_printf(&gs,
+				" symbol value is 0x%llx, the range is (0x%llx 0x%llx)\n",
+				val, left, right);
+			fputs(str_get(&gs), stderr);
+		}
+		return false;
 	case S_BOOLEAN:
 	case S_TRISTATE:
 		switch (str[0]) {
