From c3d31210f8ff706658ebacf89ee74a071ba76c8b Mon Sep 17 00:00:00 2001 From: Alex Frid Date: Sat, 23 Aug 2014 00:59:10 -0700 Subject: gpu: nvgpu: Add debugfs access to GM20b GPCPLL Added direct read and write debugfs access to GM20b GPCPLL registers. Change-Id: I203621906ee094991eecd5c18fd5b6c70b20a4c1 Signed-off-by: Alex Frid Reviewed-on: http://git-master/r/487314 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Bo Yan --- drivers/gpu/nvgpu/gm20b/clk_gm20b.c | 87 +++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c index ee4103fa..74a5cb96 100644 --- a/drivers/gpu/nvgpu/gm20b/clk_gm20b.c +++ b/drivers/gpu/nvgpu/gm20b/clk_gm20b.c @@ -20,6 +20,7 @@ #include /* for mdelay */ #include #include +#include #include #include "gk20a/gk20a.h" @@ -881,6 +882,87 @@ static const struct file_operations pll_reg_fops = { .release = single_release, }; +static int pll_reg_raw_show(struct seq_file *s, void *data) +{ + struct gk20a *g = s->private; + u32 reg; + + mutex_lock(&g->clk.clk_mutex); + if (!g->clk.clk_hw_on) { + seq_puts(s, "gk20a powered down - no access to registers\n"); + mutex_unlock(&g->clk.clk_mutex); + return 0; + } + + seq_puts(s, "GPCPLL REGISTERS:\n"); + for (reg = trim_sys_gpcpll_cfg_r(); reg <= trim_sys_gpcpll_dvfs2_r(); + reg += sizeof(u32)) + seq_printf(s, "[0x%02x] = 0x%08x\n", reg, gk20a_readl(g, reg)); + + seq_puts(s, "\nGPC CLK OUT REGISTERS:\n"); + + reg = trim_sys_sel_vco_r(); + seq_printf(s, "[0x%02x] = 0x%08x\n", reg, gk20a_readl(g, reg)); + reg = trim_sys_gpc2clk_out_r(); + seq_printf(s, "[0x%02x] = 0x%08x\n", reg, gk20a_readl(g, reg)); + reg = trim_sys_bypassctrl_r(); + seq_printf(s, "[0x%02x] = 0x%08x\n", reg, gk20a_readl(g, reg)); + + mutex_unlock(&g->clk.clk_mutex); + return 0; +} + +static int pll_reg_raw_open(struct inode *inode, struct file *file) +{ + return single_open(file, pll_reg_raw_show, inode->i_private); +} + +static ssize_t pll_reg_raw_write(struct file *file, + const char __user *userbuf, size_t count, loff_t *ppos) +{ + struct gk20a *g = file->f_path.dentry->d_inode->i_private; + char buf[80]; + u32 reg, val; + + if (sizeof(buf) <= count) + return -EINVAL; + + if (copy_from_user(buf, userbuf, count)) + return -EFAULT; + + /* terminate buffer and trim - white spaces may be appended + * at the end when invoked from shell command line */ + buf[count] = '\0'; + strim(buf); + + if (sscanf(buf, "[0x%x] = 0x%x", ®, &val) != 2) + return -EINVAL; + + if (((reg < trim_sys_gpcpll_cfg_r()) || + (reg > trim_sys_gpcpll_dvfs2_r())) && + (reg != trim_sys_sel_vco_r()) && + (reg != trim_sys_gpc2clk_out_r()) && + (reg != trim_sys_bypassctrl_r())) + return -EPERM; + + mutex_lock(&g->clk.clk_mutex); + if (!g->clk.clk_hw_on) { + mutex_unlock(&g->clk.clk_mutex); + return -EBUSY; + } + gk20a_writel(g, reg, val); + mutex_unlock(&g->clk.clk_mutex); + return count; +} + +static const struct file_operations pll_reg_raw_fops = { + .open = pll_reg_raw_open, + .read = seq_read, + .write = pll_reg_raw_write, + .llseek = seq_lseek, + .release = single_release, +}; + static int monitor_get(void *data, u64 *val) { struct gk20a *g = (struct gk20a *)data; @@ -953,6 +1035,11 @@ static int clk_gm20b_debugfs_init(struct gk20a *g) if (!d) goto err_out; + d = debugfs_create_file("pll_reg_raw", + S_IRUGO, platform->debugfs, g, &pll_reg_raw_fops); + if (!d) + goto err_out; + d = debugfs_create_file( "monitor", S_IRUGO, platform->debugfs, g, &monitor_fops); if (!d) -- cgit v1.2.2