mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-25 07:20:53 +07:00
ux500: add debugfs support for powerdebug
Signed-off-by: Vincent Guittot <vincent.guittot@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@stericsson.com>
This commit is contained in:
parent
abda3a24a9
commit
763eef8b5b
@ -20,6 +20,12 @@
|
|||||||
#include <mach/hardware.h>
|
#include <mach/hardware.h>
|
||||||
#include "clock.h"
|
#include "clock.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/uaccess.h> /* for copy_from_user */
|
||||||
|
static LIST_HEAD(clk_list);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PRCC_PCKEN 0x00
|
#define PRCC_PCKEN 0x00
|
||||||
#define PRCC_PCKDIS 0x04
|
#define PRCC_PCKDIS 0x04
|
||||||
#define PRCC_KCKEN 0x08
|
#define PRCC_KCKEN 0x08
|
||||||
@ -286,6 +292,7 @@ static struct clkops clk_prcc_ops = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct clk clk_32khz = {
|
static struct clk clk_32khz = {
|
||||||
|
.name = "clk_32khz",
|
||||||
.rate = 32000,
|
.rate = 32000,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -422,7 +429,9 @@ static DEFINE_PRCC_CLK_CUSTOM(7, mtu0_ed, 2, -1, NULL, clk_mtu_get_rate, 0);
|
|||||||
static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL);
|
static DEFINE_PRCC_CLK(7, wdg_ed, 1, -1, NULL);
|
||||||
static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL);
|
static DEFINE_PRCC_CLK(7, cfgreg_ed, 0, -1, NULL);
|
||||||
|
|
||||||
static struct clk clk_dummy_apb_pclk;
|
static struct clk clk_dummy_apb_pclk = {
|
||||||
|
.name = "apb_pclk",
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_lookup u8500_common_clks[] = {
|
static struct clk_lookup u8500_common_clks[] = {
|
||||||
CLK(dummy_apb_pclk, NULL, "apb_pclk"),
|
CLK(dummy_apb_pclk, NULL, "apb_pclk"),
|
||||||
@ -568,6 +577,183 @@ static struct clk_lookup u8500_v1_clks[] = {
|
|||||||
CLK(uiccclk, "uicc", NULL),
|
CLK(uiccclk, "uicc", NULL),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
/*
|
||||||
|
* debugfs support to trace clock tree hierarchy and attributes with
|
||||||
|
* powerdebug
|
||||||
|
*/
|
||||||
|
static struct dentry *clk_debugfs_root;
|
||||||
|
|
||||||
|
void __init clk_debugfs_add_table(struct clk_lookup *cl, size_t num)
|
||||||
|
{
|
||||||
|
while (num--) {
|
||||||
|
/* Check that the clock has not been already registered */
|
||||||
|
if (!(cl->clk->list.prev != cl->clk->list.next))
|
||||||
|
list_add_tail(&cl->clk->list, &clk_list);
|
||||||
|
|
||||||
|
cl++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t usecount_dbg_read(struct file *file, char __user *buf,
|
||||||
|
size_t size, loff_t *off)
|
||||||
|
{
|
||||||
|
struct clk *clk = file->f_dentry->d_inode->i_private;
|
||||||
|
char cusecount[128];
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
len = sprintf(cusecount, "%u\n", clk->enabled);
|
||||||
|
return simple_read_from_buffer(buf, size, off, cusecount, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t rate_dbg_read(struct file *file, char __user *buf,
|
||||||
|
size_t size, loff_t *off)
|
||||||
|
{
|
||||||
|
struct clk *clk = file->f_dentry->d_inode->i_private;
|
||||||
|
char crate[128];
|
||||||
|
unsigned int rate;
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
rate = clk_get_rate(clk);
|
||||||
|
len = sprintf(crate, "%u\n", rate);
|
||||||
|
return simple_read_from_buffer(buf, size, off, crate, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations usecount_fops = {
|
||||||
|
.read = usecount_dbg_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct file_operations set_rate_fops = {
|
||||||
|
.read = rate_dbg_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct dentry *clk_debugfs_register_dir(struct clk *c,
|
||||||
|
struct dentry *p_dentry)
|
||||||
|
{
|
||||||
|
struct dentry *d, *clk_d, *child, *child_tmp;
|
||||||
|
char s[255];
|
||||||
|
char *p = s;
|
||||||
|
|
||||||
|
if (c->name == NULL)
|
||||||
|
p += sprintf(p, "BUG");
|
||||||
|
else
|
||||||
|
p += sprintf(p, "%s", c->name);
|
||||||
|
|
||||||
|
clk_d = debugfs_create_dir(s, p_dentry);
|
||||||
|
if (!clk_d)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
d = debugfs_create_file("usecount", S_IRUGO,
|
||||||
|
clk_d, c, &usecount_fops);
|
||||||
|
if (!d)
|
||||||
|
goto err_out;
|
||||||
|
d = debugfs_create_file("rate", S_IRUGO,
|
||||||
|
clk_d, c, &set_rate_fops);
|
||||||
|
if (!d)
|
||||||
|
goto err_out;
|
||||||
|
/*
|
||||||
|
* TODO : not currently available in ux500
|
||||||
|
* d = debugfs_create_x32("flags", S_IRUGO, clk_d, (u32 *)&c->flags);
|
||||||
|
* if (!d)
|
||||||
|
* goto err_out;
|
||||||
|
*/
|
||||||
|
|
||||||
|
return clk_d;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
d = clk_d;
|
||||||
|
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
|
||||||
|
debugfs_remove(child);
|
||||||
|
debugfs_remove(clk_d);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clk_debugfs_remove_dir(struct dentry *cdentry)
|
||||||
|
{
|
||||||
|
struct dentry *d, *child, *child_tmp;
|
||||||
|
|
||||||
|
d = cdentry;
|
||||||
|
list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child)
|
||||||
|
debugfs_remove(child);
|
||||||
|
debugfs_remove(cdentry);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_debugfs_register_one(struct clk *c)
|
||||||
|
{
|
||||||
|
struct clk *pa = c->parent_periph;
|
||||||
|
struct clk *bpa = c->parent_cluster;
|
||||||
|
|
||||||
|
if (!(bpa && !pa)) {
|
||||||
|
c->dent = clk_debugfs_register_dir(c,
|
||||||
|
pa ? pa->dent : clk_debugfs_root);
|
||||||
|
if (!c->dent)
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bpa) {
|
||||||
|
c->dent_bus = clk_debugfs_register_dir(c,
|
||||||
|
bpa->dent_bus ? bpa->dent_bus : bpa->dent);
|
||||||
|
if ((!c->dent_bus) && (c->dent)) {
|
||||||
|
clk_debugfs_remove_dir(c->dent);
|
||||||
|
c->dent = NULL;
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_debugfs_register(struct clk *c)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct clk *pa = c->parent_periph;
|
||||||
|
struct clk *bpa = c->parent_cluster;
|
||||||
|
|
||||||
|
if (pa && (!pa->dent && !pa->dent_bus)) {
|
||||||
|
err = clk_debugfs_register(pa);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bpa && (!bpa->dent && !bpa->dent_bus)) {
|
||||||
|
err = clk_debugfs_register(bpa);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!c->dent) && (!c->dent_bus)) {
|
||||||
|
err = clk_debugfs_register_one(c);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init clk_debugfs_init(void)
|
||||||
|
{
|
||||||
|
struct clk *c;
|
||||||
|
struct dentry *d;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
d = debugfs_create_dir("clock", NULL);
|
||||||
|
if (!d)
|
||||||
|
return -ENOMEM;
|
||||||
|
clk_debugfs_root = d;
|
||||||
|
|
||||||
|
list_for_each_entry(c, &clk_list, list) {
|
||||||
|
err = clk_debugfs_register(c);
|
||||||
|
if (err)
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
err_out:
|
||||||
|
debugfs_remove_recursive(clk_debugfs_root);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
late_initcall(clk_debugfs_init);
|
||||||
|
#endif /* defined(CONFIG_DEBUG_FS) */
|
||||||
|
|
||||||
int __init clk_init(void)
|
int __init clk_init(void)
|
||||||
{
|
{
|
||||||
if (cpu_is_u8500ed()) {
|
if (cpu_is_u8500ed()) {
|
||||||
@ -588,5 +774,12 @@ int __init clk_init(void)
|
|||||||
else
|
else
|
||||||
clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
|
clkdev_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
clk_debugfs_add_table(u8500_common_clks, ARRAY_SIZE(u8500_common_clks));
|
||||||
|
if (cpu_is_u8500ed())
|
||||||
|
clk_debugfs_add_table(u8500_ed_clks, ARRAY_SIZE(u8500_ed_clks));
|
||||||
|
else
|
||||||
|
clk_debugfs_add_table(u8500_v1_clks, ARRAY_SIZE(u8500_v1_clks));
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +90,10 @@ struct clk {
|
|||||||
|
|
||||||
struct clk *parent_cluster;
|
struct clk *parent_cluster;
|
||||||
struct clk *parent_periph;
|
struct clk *parent_periph;
|
||||||
|
#if defined(CONFIG_DEBUG_FS)
|
||||||
|
struct dentry *dent; /* For visible tree hierarchy */
|
||||||
|
struct dentry *dent_bus; /* For visible tree hierarchy */
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \
|
#define DEFINE_PRCMU_CLK(_name, _cg_off, _cg_bit, _reg) \
|
||||||
|
Loading…
Reference in New Issue
Block a user