[linux-yocto] [PATCH 6/7] drivers/misc: Allow CCN Register Access
Daniel Dragomir
daniel.dragomir at windriver.com
Thu Jul 26 03:59:00 PDT 2018
From: John Jacques <john.jacques at intel.com>
Signed-off-by: John Jacques <john.jacques at intel.com>
---
drivers/misc/axxia-oem.c | 209 +++++++++++++++++++++++++++++++++++++++-------
include/linux/axxia-oem.h | 10 +++
2 files changed, 191 insertions(+), 28 deletions(-)
diff --git a/drivers/misc/axxia-oem.c b/drivers/misc/axxia-oem.c
index bcd1a8c..5f787cd 100644
--- a/drivers/misc/axxia-oem.c
+++ b/drivers/misc/axxia-oem.c
@@ -90,11 +90,8 @@ axxia_dspc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
char *input;
- unsigned long mask;
- int ret;
input = kmalloc(count, __GFP_RECLAIMABLE);
- memset(input, 0, count);
if (NULL == input)
return -ENOSPC;
@@ -102,13 +99,10 @@ axxia_dspc_write(struct file *file, const char __user *buffer,
if (copy_from_user(input, buffer, count))
return -EFAULT;
- ret = kstrtoul(input, 0, &mask);
- if (ret) {
- pr_err("Failed axxia_dspc_write mask conversion\n");
- return -EFAULT;
- }
+ input[count] = 0;
+
+ axxia_dspc_set_state(simple_strtoul(input, NULL, 0));
- axxia_dspc_set_state((unsigned int)mask);
return count;
}
@@ -149,11 +143,8 @@ axxia_actlr_el3_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
char *input;
- unsigned long data = 0;
- int ret = 0;
input = kmalloc(count, __GFP_RECLAIMABLE);
- memset(input, 0, count);
if (NULL == input)
return -ENOSPC;
@@ -161,12 +152,9 @@ axxia_actlr_el3_write(struct file *file, const char __user *buffer,
if (copy_from_user(input, buffer, count))
return -EFAULT;
- ret = kstrtoul(input, 0, &data);
- if (ret) {
- pr_err("axxia_actlr_el3_write failed conversion\n");
- return ret;
- }
- axxia_actlr_el3_set(data);
+ input[count] = 0;
+
+ axxia_actlr_el3_set(simple_strtoul(input, NULL, 0));
return count;
}
@@ -208,11 +196,8 @@ axxia_actlr_el2_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
char *input;
- unsigned long data = 0;
- int ret = 0;
input = kmalloc(count, __GFP_RECLAIMABLE);
- memset(input, 0, count);
if (NULL == input)
return -ENOSPC;
@@ -220,12 +205,9 @@ axxia_actlr_el2_write(struct file *file, const char __user *buffer,
if (copy_from_user(input, buffer, count))
return -EFAULT;
- ret = kstrtoul(input, 0, &data);
- if (ret) {
- pr_err("axxia_actlr_el2_write failed conversion\n");
- return ret;
- }
- axxia_actlr_el2_set(data);
+ input[count] = 0;
+
+ axxia_actlr_el2_set(simple_strtoul(input, NULL, 0));
return count;
}
@@ -237,6 +219,123 @@ static const struct file_operations axxia_actlr_el2_proc_ops = {
};
/*
+ CCN Access
+*/
+
+static unsigned long ccn_offset;
+
+static ssize_t
+axxia_ccn_offset_read(struct file *filp, char *buffer, size_t length,
+ loff_t *offset)
+{
+ static int finished;
+ char return_buffer[80];
+
+ if (0 != finished) {
+ finished = 0;
+
+ return 0;
+ }
+
+ finished = 1;
+ sprintf(return_buffer, "0x%lx\n", ccn_offset);
+
+ if (copy_to_user(buffer, return_buffer, strlen(return_buffer)))
+ return -EFAULT;
+
+ return strlen(return_buffer);
+}
+
+static ssize_t
+axxia_ccn_offset_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ char *input;
+ unsigned int new_ccn_offset;
+
+ input = kmalloc(count, __GFP_RECLAIMABLE);
+
+ if (NULL == input)
+ return -ENOSPC;
+
+ if (copy_from_user(input, buffer, count))
+ return -EFAULT;
+
+ input[count] = 0;
+
+ new_ccn_offset = (unsigned int)simple_strtoul(input, NULL, 0);
+
+ if (of_find_compatible_node(NULL, NULL, "axxia,axc6732")) {
+ if (0x9cff00 < new_ccn_offset)
+ pr_err("Invalid CCN Offset!\n");
+ } else if (of_find_compatible_node(NULL, NULL, "axxia,axm5616")) {
+ if (0x94ff00 < new_ccn_offset)
+ pr_err("Invalid CCN Offset!\n");
+ } else {
+ pr_err("Internal Error!\n");
+ }
+
+ ccn_offset = (unsigned int)new_ccn_offset;
+
+ return count;
+}
+
+static const struct file_operations axxia_ccn_offset_proc_ops = {
+ .read = axxia_ccn_offset_read,
+ .write = axxia_ccn_offset_write,
+ .llseek = noop_llseek,
+};
+
+static ssize_t
+axxia_ccn_value_read(struct file *filp, char *buffer, size_t length,
+ loff_t *offset)
+{
+ static int finished;
+ char return_buffer[80];
+
+ if (0 != finished) {
+ finished = 0;
+
+ return 0;
+ }
+
+ finished = 1;
+ sprintf(return_buffer, "0x%lx\n", axxia_ccn_get(ccn_offset));
+
+ if (copy_to_user(buffer, return_buffer, strlen(return_buffer)))
+ return -EFAULT;
+
+ return strlen(return_buffer);
+}
+
+static ssize_t
+axxia_ccn_value_write(struct file *file, const char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ char *input;
+
+ input = kmalloc(count, __GFP_RECLAIMABLE);
+
+ if (NULL == input)
+ return -ENOSPC;
+
+ if (copy_from_user(input, buffer, count))
+ return -EFAULT;
+
+ input[count] = 0;
+
+ axxia_ccn_set(ccn_offset, simple_strtoul(input, NULL, 0));
+
+ return count;
+}
+
+static const struct file_operations axxia_ccn_value_proc_ops = {
+ .read = axxia_ccn_value_read,
+ .write = axxia_ccn_value_write,
+ .llseek = noop_llseek,
+};
+
+/*
==============================================================================
==============================================================================
Public
@@ -374,13 +473,54 @@ EXPORT_SYMBOL(axxia_actlr_el2_set);
/*
------------------------------------------------------------------------------
+ axxia_ccn_get
+*/
+
+unsigned long
+axxia_ccn_get(unsigned int offset)
+{
+ struct oem_parameters parameters;
+
+ parameters.reg0 = 0xc3000006;
+ parameters.reg1 = offset;
+ invoke_oem_fn(¶meters);
+
+ if (0 != parameters.reg0)
+ pr_warn("Getting CCN Register Failed!\n");
+
+ return parameters.reg1;
+}
+EXPORT_SYMBOL(axxia_ccn_get);
+
+/*
+ ------------------------------------------------------------------------------
+ axxia_ccn_set
+*/
+
+void
+axxia_ccn_set(unsigned int offset, unsigned long value)
+{
+ struct oem_parameters parameters;
+
+ parameters.reg0 = 0xc3000007;
+ parameters.reg1 = offset;
+ parameters.reg2 = value;
+ invoke_oem_fn(¶meters);
+
+ if (0 != parameters.reg0)
+ pr_warn("Getting CCN Register Failed!\n");
+}
+EXPORT_SYMBOL(axxia_ccn_set);
+
+/*
+ ------------------------------------------------------------------------------
axxia_dspc_init
*/
static int
axxia_oem_init(void)
{
- if (of_find_compatible_node(NULL, NULL, "lsi,axc6732")) {
+ if (of_find_compatible_node(NULL, NULL, "axxia,axc6732")) {
/* Only applicable to the 6700. */
if (NULL == proc_create("driver/axxia_dspc", S_IWUSR, NULL,
&axxia_dspc_proc_ops))
@@ -401,6 +541,19 @@ axxia_oem_init(void)
else
pr_info("Axxia ACTLR_EL3 Control Initialized\n");
+ /* For CCN access, create two files, offset and value. */
+
+ ccn_offset = 0;
+
+ if (NULL == proc_create("driver/axxia_ccn_offset", S_IWUSR, NULL,
+ &axxia_ccn_offset_proc_ops))
+ pr_err("Could not create /proc/driver/axxia_ccn_offset!\n");
+ else if (NULL == proc_create("driver/axxia_ccn_value", S_IWUSR, NULL,
+ &axxia_ccn_value_proc_ops))
+ pr_err("Could not create /proc/driver/axxia_ccn_value!\n");
+ else
+ pr_info("Axxia CCN Initialized\n");
+
return 0;
}
diff --git a/include/linux/axxia-oem.h b/include/linux/axxia-oem.h
index b3721a8..101cf71 100644
--- a/include/linux/axxia-oem.h
+++ b/include/linux/axxia-oem.h
@@ -31,4 +31,14 @@ void axxia_actlr_el3_set(unsigned long);
unsigned long axxia_actlr_el2_get(void);
void axxia_actlr_el2_set(unsigned long);
+/*
+ CCN504 (5600)
+ CCN512 (6700)
+
+ 64 bit registers.
+*/
+
+unsigned long axxia_ccn_get(unsigned int);
+void axxia_ccn_set(unsigned int, unsigned long);
+
#endif /* __DRIVERS_MISC_AXXIA_DSPC_H */
--
2.7.4
More information about the linux-yocto
mailing list