/*
* Bit COREPDRQ toggling interface
*
* Copyright (c) 2012-2013, NVIDIA CORPORATION. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
static inline uint32_t read_dbgprcr(void)
{
uint32_t ret_val = 0;
asm volatile("mrc p14, 0, %[result], c1, c4, 4"
: [result] "=r" (ret_val)
: /* no input */
: /* no clobber */
);
return ret_val;
}
static inline void write_dbgprcr(uint32_t val)
{
asm volatile("mov r8, %[val_in]\n\t"
"mcr p14, 0, r8, c1, c4, 4"
: /* no output */
: [val_in] "r" (val)
: "r8"
);
return;
}
static struct dentry *corenpdrq_debugfs_root;
static ssize_t corenpdrq_toggle_show(struct seq_file *s, void *data)
{
uint32_t ret_val = 0;
ret_val = read_dbgprcr();
seq_printf(s, "%X\n", (ret_val & 0x1));
return 0;
}
static int corenpdrq_open(struct inode *inode, struct file *file)
{
return single_open(file, corenpdrq_toggle_show, inode->i_private);
}
static int corenpdrq_write(struct file *file, const char __user *userbuf,
size_t count, loff_t *f_pos)
{
char buf[32];
unsigned long in_val = 0;
uint32_t val = 0;
if (sizeof buf <= count)
goto write_err;
if (copy_from_user(buf, userbuf, count))
goto write_err;
buf[count] = '\0';
strim(buf);
if (kstrtoul(buf, 10, &in_val) < 0)
goto write_err;
val = read_dbgprcr();
if (in_val)
val |= 1;
else
val &= ~1;
write_dbgprcr(val);
return count;
write_err:
pr_err("can't program bit CORENPDRQ\n");
return -EINVAL;
}
static const struct file_operations corenpdrq_fops = {
.open = corenpdrq_open,
.read = seq_read,
.write = corenpdrq_write,
.llseek = seq_lseek,
.release = single_release,
};
static int __init corenpdrq_debug_init(void)
{
corenpdrq_debugfs_root = debugfs_create_dir("corenpdrq", NULL);
if (!corenpdrq_debugfs_root)
return -ENOMEM;
if (!debugfs_create_file(
"core_npdrq", S_IRUGO | S_IWUSR, corenpdrq_debugfs_root, NULL,
&corenpdrq_fops))
goto err_out;
return 0;
err_out:
debugfs_remove_recursive(corenpdrq_debugfs_root);
return -ENOMEM;
}
late_initcall(corenpdrq_debug_init);