[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/kernel/linux/v4.14/drivers/clk/mediatek/clkchk.c b/src/kernel/linux/v4.14/drivers/clk/mediatek/clkchk.c
new file mode 100644
index 0000000..d50110a
--- /dev/null
+++ b/src/kernel/linux/v4.14/drivers/clk/mediatek/clkchk.c
@@ -0,0 +1,188 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2018 MediaTek Inc.
+// Author: Weiyi Lu <weiyi.lu@mediatek.com>
+
+#define pr_fmt(fmt) "[clkchk] " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/syscore_ops.h>
+#include "clkchk.h"
+
+#define AEE_EXCP_CHECK_PLL_FAIL	0
+#define CLKDBG_CCF_API_4_4	1
+#define MAX_PLLS		32
+
+#if AEE_EXCP_CHECK_PLL_FAIL
+#include <mt-plat/aee.h>
+#endif
+
+#if !CLKDBG_CCF_API_4_4
+
+/* backward compatible */
+
+static const char *clk_hw_get_name(const struct clk_hw *hw)
+{
+	return __clk_get_name(hw->clk);
+}
+
+static bool clk_hw_is_prepared(const struct clk_hw *hw)
+{
+	return __clk_is_prepared(hw->clk);
+}
+
+static bool clk_hw_is_enabled(const struct clk_hw *hw)
+{
+	return __clk_is_enabled(hw->clk);
+}
+
+static unsigned long clk_hw_get_rate(const struct clk_hw *hw)
+{
+	return __clk_get_rate(hw->clk);
+}
+
+static struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw)
+{
+	return __clk_get_hw(clk_get_parent(hw->clk));
+}
+
+#endif /* !CLKDBG_CCF_API_4_4 */
+
+static struct clkchk_cfg_t *clkchk_cfg;
+
+static const char *ccf_state(struct clk_hw *hw)
+{
+	if (__clk_get_enable_count(hw->clk))
+		return "enabled";
+
+	if (clk_hw_is_prepared(hw))
+		return "prepared";
+
+	return "disabled";
+}
+
+static void print_enabled_clks(void)
+{
+	const char * const *cn = clkchk_cfg->all_clk_names;
+
+	pr_warn("enabled clks:\n");
+
+	for (; *cn != NULL; cn++) {
+		struct clk *c = __clk_lookup(*cn);
+		struct clk_hw *c_hw = __clk_get_hw(c);
+		struct clk_hw *p_hw;
+
+		if (IS_ERR_OR_NULL(c) || c_hw == NULL)
+			continue;
+
+		p_hw = clk_hw_get_parent(c_hw);
+
+		if (p_hw == NULL)
+			continue;
+
+		if (!clk_hw_is_prepared(c_hw) &&
+			__clk_get_enable_count(c) <= 0U)
+			continue;
+
+		pr_warn("[%-17s: %8s, %3d, %3d, %10ld, %17s]\n",
+			clk_hw_get_name(c_hw),
+			ccf_state(c_hw),
+			clk_hw_is_prepared(c_hw),
+			__clk_get_enable_count(c),
+			clk_hw_get_rate(c_hw),
+			p_hw != NULL ? clk_hw_get_name(p_hw) : "- ");
+	}
+}
+
+static void check_pll_off(void)
+{
+	static struct clk *off_plls[MAX_PLLS];
+
+	struct clk **c;
+	int invalid = 0;
+	char buf[128] = {0};
+	int n = 0;
+
+	if (off_plls[0] == NULL) {
+		const char * const *pn = clkchk_cfg->off_pll_names;
+		struct clk **end = off_plls + MAX_PLLS - 1;
+
+		for (c = off_plls; *pn != NULL && c < end; pn++, c++)
+			*c = __clk_lookup(*pn);
+	}
+
+	for (c = off_plls; *c != NULL; c++) {
+		struct clk_hw *c_hw = __clk_get_hw(*c);
+
+		if (c_hw == NULL)
+			continue;
+
+		if (!clk_hw_is_prepared(c_hw) && !clk_hw_is_enabled(c_hw))
+			continue;
+
+		n += snprintf(buf + n, sizeof(buf) - (size_t)n, "%s ",
+				clk_hw_get_name(c_hw));
+
+		invalid++;
+	}
+
+	if (invalid == 0)
+		return;
+
+	/* invalid. output debug info */
+
+	pr_warn("unexpected unclosed PLL: %s\n", buf);
+	print_enabled_clks();
+
+#if AEE_EXCP_CHECK_PLL_FAIL
+	if (clkchk_cfg->aee_excp_on_fail)
+		aee_kernel_exception("clkchk", "unclosed PLL: %s\n", buf);
+#endif
+
+	if (clkchk_cfg->warn_on_fail)
+		WARN_ON(true);
+}
+
+static int clkchk_syscore_suspend(void)
+{
+	check_pll_off();
+
+	return 0;
+}
+
+static void clkchk_syscore_resume(void)
+{
+}
+
+static struct syscore_ops clkchk_syscore_ops = {
+	.suspend = clkchk_syscore_suspend,
+	.resume = clkchk_syscore_resume,
+};
+
+int clkchk_init(struct clkchk_cfg_t *cfg)
+{
+	const char * const *c;
+	bool match = false;
+
+	if (cfg == NULL || cfg->compatible == NULL
+		|| cfg->all_clk_names == NULL || cfg->off_pll_names == NULL) {
+		pr_warn("Invalid clkchk_cfg.\n");
+		return -EINVAL;
+	}
+
+	clkchk_cfg = cfg;
+
+	for (c = cfg->compatible; *c != NULL; c++) {
+		if (of_machine_is_compatible(*c) != 0) {
+			match = true;
+			break;
+		}
+	}
+
+	if (!match)
+		return -ENODEV;
+
+	register_syscore_ops(&clkchk_syscore_ops);
+
+	return 0;
+}