firmware/br-ext-chip-allwinner/board/v83x/kernel/patches/00000-drivers_clk_sunxi_clk...

596 lines
16 KiB
Diff

diff -drupN a/drivers/clk/sunxi/clk-debugfs.c b/drivers/clk/sunxi/clk-debugfs.c
--- a/drivers/clk/sunxi/clk-debugfs.c 1970-01-01 03:00:00.000000000 +0300
+++ b/drivers/clk/sunxi/clk-debugfs.c 2022-06-12 05:28:14.000000000 +0300
@@ -0,0 +1,591 @@
+/*
+ * Copyright (C) 2013 Allwinnertech, kevin.z.m <kevin@allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <asm/uaccess.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/sunxi.h>
+#include <linux/clk.h>
+#include "clk-factors.h"
+#include "clk-periph.h"
+#include "clk-debugfs.h"
+
+static struct dentry *my_ccudbg_root;
+static struct testclk_data testclk_priv;
+static void clktest_reg_dump(void)
+{
+ unsigned int i;
+ char dumpline[256];
+
+ pr_info("Dump Base 0x%lx Regs %d as Follow:\n",
+ (unsigned long __force)sunxi_clk_base,
+ (unsigned int __force)sunxi_clk_maxreg);
+ for (i = 0; i <= sunxi_clk_maxreg;) {
+ if (i + 12 <= sunxi_clk_maxreg)
+ sprintf(
+ dumpline, "[Reg %08x] %08x %08x %08x %08x ", i,
+ *((unsigned int *)((char *)sunxi_clk_base + i)),
+ *((unsigned int *)((char *)sunxi_clk_base + i + 4)),
+ *((unsigned int *)((char *)sunxi_clk_base + i + 8)),
+ *((unsigned int *)((char *)sunxi_clk_base + i +
+ 12)));
+ else if (i + 8 <= sunxi_clk_maxreg)
+ sprintf(
+ dumpline, "[Reg %08x] %08x %08x %08x ", i,
+ *((unsigned int *)((char *)sunxi_clk_base + i)),
+ *((unsigned int *)((char *)sunxi_clk_base + i + 4)),
+ *((unsigned int *)((char *)sunxi_clk_base + i +
+ 8)));
+ else if (i + 4 <= sunxi_clk_maxreg)
+ sprintf(dumpline, "[Reg %08x] %08x %08x ", i,
+ *((unsigned int *)((char *)sunxi_clk_base + i)),
+ *((unsigned int *)((char *)sunxi_clk_base + i +
+ 4)));
+ else
+ sprintf(
+ dumpline, "[Reg %08x] %08x ", i,
+ *((unsigned int *)((char *)sunxi_clk_base + i)));
+ pr_info("%s\n", dumpline);
+ i = i + 16;
+ }
+ pr_info("\n");
+
+ if (cpus_clk_maxreg) {
+ pr_info("Dump CPUS Base 0x%lx Regs %d as Follow:\n",
+ (unsigned long __force)sunxi_clk_cpus_base,
+ (unsigned int)cpus_clk_maxreg);
+ for (i = 0; i <= cpus_clk_maxreg;) {
+ if (i + 12 <= cpus_clk_maxreg)
+ sprintf(
+ dumpline, "[Reg %08x] %08x %08x %08x %08x ",
+ i,
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i)),
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i + 4)),
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i + 8)),
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i + 12)));
+ else if (i + 8 <= cpus_clk_maxreg)
+ sprintf(
+ dumpline, "[Reg %08x] %08x %08x %08x ", i,
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i)),
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i + 4)),
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i + 8)));
+ else if (i + 4 <= cpus_clk_maxreg)
+ sprintf(
+ dumpline, "[Reg %08x] %08x %08x ", i,
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i)),
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i + 4)));
+ else
+ sprintf(
+ dumpline, "[Reg %08x] %08x ", i,
+ *((unsigned int *)((char *)sunxi_clk_cpus_base +
+ i)));
+ pr_info("%s\n", dumpline);
+ i = i + 16;
+ }
+ }
+ pr_info("\n");
+}
+static void clktest_process(void)
+{
+ int i, j, enabled, command = 0xff;
+ unsigned long rate;
+ struct clk *cur_clk = NULL;
+ struct clk *parent_clk = NULL;
+ int ret;
+ unsigned long start = 0;
+
+ ret = kstrtoul(testclk_priv.start, 0, (unsigned long *)&start);
+
+ if (start == 1) {
+ if (!strcmp(testclk_priv.command, "getparents"))
+ command = 1;
+ else if (!strcmp(testclk_priv.command, "getparent"))
+ command = 2;
+ else if (!strcmp(testclk_priv.command, "setparent"))
+ command = 3;
+ else if (!strcmp(testclk_priv.command, "getrate"))
+ command = 4;
+ else if (!strcmp(testclk_priv.command, "setrate"))
+ command = 5;
+ else if (!strcmp(testclk_priv.command, "is_enabled"))
+ command = 6;
+ else if (!strcmp(testclk_priv.command, "disable"))
+ command = 7;
+ else if (!strcmp(testclk_priv.command, "enable"))
+ command = 8;
+ else if (!strcmp(testclk_priv.command, "dumpreg"))
+ command = 9;
+ else if (!strcmp(testclk_priv.command, "assert"))
+ command = 10;
+ else if (!strcmp(testclk_priv.command, "deassert"))
+ command = 11;
+ else {
+ pr_info("Error Not support command %s\n",
+ testclk_priv.command);
+ command = 0xff;
+ }
+ if ((command != 0xff) && (command != 9)) {
+ cur_clk = clk_get(NULL, testclk_priv.name);
+ if (!cur_clk || IS_ERR(cur_clk)) {
+ cur_clk = NULL;
+ pr_info("Error Found clk %s\n",
+ testclk_priv.name);
+ strcpy(testclk_priv.info, "Error");
+ return;
+ }
+ switch (command) {
+ case 1: /* getparents */
+ {
+ j = 0;
+ memset(testclk_priv.info, 0x0,
+ sizeof(testclk_priv.info));
+ for (i = 0; i < cur_clk->core->num_parents;
+ i++) {
+ memcpy(&testclk_priv.info[j],
+ cur_clk->core->parent_names[i],
+ strlen(cur_clk->core
+ ->parent_names[i]));
+ j += strlen(
+ cur_clk->core->parent_names[i]);
+ testclk_priv.info[j] = ' ';
+ j++;
+ }
+ testclk_priv.info[j] = 0;
+ break;
+ }
+ case 2: /* getparent */
+ {
+
+ parent_clk = clk_get_parent(cur_clk);
+ if (!parent_clk || IS_ERR(parent_clk)) {
+ pr_info("Error Found parent of %s\n",
+ cur_clk->core->name);
+ strcpy(testclk_priv.info, "Error");
+ } else
+ strcpy(testclk_priv.info,
+ parent_clk->core->name);
+ break;
+ }
+ case 3: /* setparent */
+ {
+ if (cur_clk->core->parent) {
+ parent_clk =
+ clk_get(NULL, testclk_priv.param);
+ if (!parent_clk || IS_ERR(parent_clk)) {
+ pr_info(
+ "Error Found parent %s\n",
+ testclk_priv.param);
+ strcpy(testclk_priv.info,
+ "Error");
+ } else {
+ clk_set_parent(cur_clk,
+ parent_clk);
+ strcpy(testclk_priv.info,
+ cur_clk->core->parent
+ ->name);
+ clk_put(parent_clk);
+ }
+ } else
+ strcpy(testclk_priv.info, "Error");
+ break;
+ }
+ case 4: /* getrate */
+ {
+ rate = clk_get_rate(cur_clk);
+ if (rate)
+
+ sprintf(testclk_priv.info, "%d",
+ (unsigned int)rate);
+ else
+ strcpy(testclk_priv.info, "Error");
+ break;
+ }
+ case 5: /* setrate */
+ {
+ ret = kstrtoul(testclk_priv.param, 0,
+ (unsigned long *)&rate);
+ if (rate) {
+ clk_set_rate(cur_clk, rate);
+ sprintf(testclk_priv.info, "%d",
+ (unsigned int)rate);
+ } else
+ strcpy(testclk_priv.info, "Error");
+ break;
+ }
+ case 6: /* is_enabled */
+ {
+ if (!cur_clk->core->ops->is_enabled)
+ enabled =
+ cur_clk->core->enable_count ? 1 : 0;
+ else
+ enabled =
+ cur_clk->core->ops->is_enabled(
+ cur_clk->core->hw);
+ if (enabled)
+ strcpy(testclk_priv.info, "enabled");
+ else
+ strcpy(testclk_priv.info, "disabled");
+ break;
+ }
+ case 7: /* disable */
+ {
+ if (!cur_clk->core->ops->is_enabled)
+ enabled =
+ cur_clk->core->enable_count ? 1 : 0;
+ else
+ enabled =
+ cur_clk->core->ops->is_enabled(
+ cur_clk->core->hw);
+ if (enabled)
+ clk_disable_unprepare(cur_clk);
+ strcpy(testclk_priv.info, "disabled");
+ break;
+ }
+ case 8: /* enable */
+ {
+ clk_prepare_enable(cur_clk);
+ strcpy(testclk_priv.info, "enabled");
+ break;
+ }
+ case 10: /* assert */
+ {
+ if (!sunxi_periph_reset_assert(cur_clk))
+ strcpy(testclk_priv.info, "asserted");
+ else
+ strcpy(testclk_priv.info, "failed");
+ break;
+ }
+ case 11: /* deassert */
+ {
+ if (!sunxi_periph_reset_deassert(cur_clk))
+ strcpy(testclk_priv.info, "deasserted");
+ else
+ strcpy(testclk_priv.info, "failed");
+ break;
+ }
+ default:
+ break;
+ }
+ if (cur_clk)
+ clk_put(cur_clk);
+ } else if (command == 9) {
+ clktest_reg_dump();
+ strcpy(testclk_priv.info, "OK");
+ }
+ }
+}
+/*##########command###############*/
+static int ccudbg_command_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static int ccudbg_command_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static ssize_t ccudbg_command_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int len = strlen(testclk_priv.command);
+
+ strcpy(testclk_priv.tmpbuf, testclk_priv.command);
+ testclk_priv.tmpbuf[len] = 0x0A;
+ testclk_priv.tmpbuf[len + 1] = 0x0;
+ len = strlen(testclk_priv.tmpbuf);
+ if (len) {
+ if (*ppos >= len)
+ return 0;
+ if (count >= len)
+ count = len;
+ if (count > (len - *ppos))
+ count = (len - *ppos);
+ if (copy_to_user((void __user *)buf,
+ (const void *)testclk_priv.tmpbuf,
+ (unsigned long)len))
+ return -EFAULT;
+ *ppos += count;
+ } else
+ count = 0;
+ return count;
+}
+
+static ssize_t ccudbg_command_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count >= sizeof(testclk_priv.command))
+ return 0;
+ if (copy_from_user(testclk_priv.command, buf, count))
+ return -EFAULT;
+ if (testclk_priv.command[count - 1] == 0x0A)
+ testclk_priv.command[count - 1] = 0;
+ else
+ testclk_priv.command[count] = 0;
+ return count;
+}
+/*##########name###############*/
+static int ccudbg_name_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static int ccudbg_name_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static ssize_t ccudbg_name_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int len = strlen(testclk_priv.name);
+
+ strcpy(testclk_priv.tmpbuf, testclk_priv.name);
+ testclk_priv.tmpbuf[len] = 0x0A;
+ testclk_priv.tmpbuf[len + 1] = 0x0;
+ len = strlen(testclk_priv.tmpbuf);
+ if (len) {
+ if (*ppos >= len)
+ return 0;
+ if (count >= len)
+ count = len;
+ if (count > (len - *ppos))
+ count = (len - *ppos);
+ if (copy_to_user((void __user *)buf,
+ (const void *)testclk_priv.tmpbuf,
+ (unsigned long)len))
+ return -EFAULT;
+ *ppos += count;
+ } else
+ count = 0;
+ return count;
+}
+
+static ssize_t ccudbg_name_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count >= sizeof(testclk_priv.name))
+ return 0;
+ if (copy_from_user(testclk_priv.name, buf, count))
+ return -EFAULT;
+ if (testclk_priv.name[count - 1] == 0x0A)
+ testclk_priv.name[count - 1] = 0;
+ else
+ testclk_priv.name[count] = 0;
+ return count;
+}
+/*##########start###############*/
+static int ccudbg_start_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static int ccudbg_start_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static ssize_t ccudbg_start_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int len = strlen(testclk_priv.start);
+
+ strcpy(testclk_priv.tmpbuf, testclk_priv.start);
+ testclk_priv.tmpbuf[len] = 0x0A;
+ testclk_priv.tmpbuf[len + 1] = 0x0;
+ len = strlen(testclk_priv.tmpbuf);
+ if (len) {
+ if (*ppos >= len)
+ return 0;
+ if (count >= len)
+ count = len;
+ if (count > (len - *ppos))
+ count = (len - *ppos);
+ if (copy_to_user((void __user *)buf,
+ (const void *)testclk_priv.tmpbuf,
+ (unsigned long)len))
+ return -EFAULT;
+ *ppos += count;
+ } else
+ count = 0;
+ return count;
+}
+static ssize_t ccudbg_start_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count >= sizeof(testclk_priv.start))
+ return 0;
+ if (copy_from_user(testclk_priv.start, buf, count))
+ return -EFAULT;
+ if (testclk_priv.start[count - 1] == 0x0A)
+ testclk_priv.start[count - 1] = 0;
+ else
+ testclk_priv.start[count] = 0;
+ clktest_process();
+ return count;
+}
+/*##########param###############*/
+static int ccudbg_param_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static int ccudbg_param_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static ssize_t ccudbg_param_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int len = strlen(testclk_priv.param);
+
+ strcpy(testclk_priv.tmpbuf, testclk_priv.param);
+ testclk_priv.tmpbuf[len] = 0x0A;
+ testclk_priv.tmpbuf[len + 1] = 0x0;
+ len = strlen(testclk_priv.tmpbuf);
+ if (len) {
+ if (*ppos >= len)
+ return 0;
+ if (count >= len)
+ count = len;
+ if (count > (len - *ppos))
+ count = (len - *ppos);
+ if (copy_to_user((void __user *)buf,
+ (const void *)testclk_priv.tmpbuf,
+ (unsigned long)len))
+ return -EFAULT;
+ *ppos += count;
+ } else
+ count = 0;
+ return count;
+}
+static ssize_t ccudbg_param_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count >= sizeof(testclk_priv.param))
+ return 0;
+ if (copy_from_user(testclk_priv.param, buf, count))
+ return -EFAULT;
+ if (testclk_priv.param[count - 1] == 0x0A)
+ testclk_priv.param[count - 1] = 0;
+ else
+ testclk_priv.param[count] = 0;
+ return count;
+}
+/*##########info###############*/
+static int ccudbg_info_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static int ccudbg_info_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+static ssize_t ccudbg_info_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int len = strlen(testclk_priv.info);
+
+ strcpy(testclk_priv.tmpbuf, testclk_priv.info);
+ testclk_priv.tmpbuf[len] = 0x0A;
+ testclk_priv.tmpbuf[len + 1] = 0x0;
+ len = strlen(testclk_priv.tmpbuf);
+ if (len) {
+ if (*ppos >= len)
+ return 0;
+ if (count >= len)
+ count = len;
+ if (count > (len - *ppos))
+ count = (len - *ppos);
+ if (copy_to_user((void __user *)buf,
+ (const void *)testclk_priv.tmpbuf,
+ (unsigned long)len))
+ return -EFAULT;
+ *ppos += count;
+ } else
+ count = 0;
+ return count;
+}
+static ssize_t ccudbg_info_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ if (count >= sizeof(testclk_priv.info))
+ return 0;
+ if (copy_from_user(testclk_priv.info, buf, count))
+ return -EFAULT;
+ if (testclk_priv.info[count - 1] == 0x0A)
+ testclk_priv.info[count - 1] = 0;
+ else
+ testclk_priv.info[count] = 0;
+ return count;
+}
+static const struct file_operations command_ops = {
+ .write = ccudbg_command_write,
+ .read = ccudbg_command_read,
+ .open = ccudbg_command_open,
+ .release = ccudbg_command_release,
+};
+static const struct file_operations name_ops = {
+ .write = ccudbg_name_write,
+ .read = ccudbg_name_read,
+ .open = ccudbg_name_open,
+ .release = ccudbg_name_release,
+};
+static const struct file_operations start_ops = {
+ .write = ccudbg_start_write,
+ .read = ccudbg_start_read,
+ .open = ccudbg_start_open,
+ .release = ccudbg_start_release,
+};
+static const struct file_operations param_ops = {
+ .write = ccudbg_param_write,
+ .read = ccudbg_param_read,
+ .open = ccudbg_param_open,
+ .release = ccudbg_param_release,
+};
+static const struct file_operations info_ops = {
+ .write = ccudbg_info_write,
+ .read = ccudbg_info_read,
+ .open = ccudbg_info_open,
+ .release = ccudbg_info_release,
+};
+static int __init debugfs_test_init(void)
+{
+ my_ccudbg_root = debugfs_create_dir("ccudbg", NULL);
+ if (!debugfs_create_file("command", 0644, my_ccudbg_root, NULL,
+ &command_ops))
+ goto Fail;
+ if (!debugfs_create_file("name", 0644, my_ccudbg_root, NULL, &name_ops))
+ goto Fail;
+ if (!debugfs_create_file("start", 0644, my_ccudbg_root, NULL,
+ &start_ops))
+ goto Fail;
+ if (!debugfs_create_file("param", 0644, my_ccudbg_root, NULL,
+ &param_ops))
+ goto Fail;
+ if (!debugfs_create_file("info", 0644, my_ccudbg_root, NULL, &info_ops))
+ goto Fail;
+ return 0;
+
+Fail:
+ debugfs_remove_recursive(my_ccudbg_root);
+ my_ccudbg_root = NULL;
+ return -ENOENT;
+}
+
+late_initcall(debugfs_test_init);