[linux-yocto] [PATCH 5/6] drivers/misc: Allow CCN Register Access
Daniel Dragomir
daniel.dragomir at windriver.com
Thu Jul 26 03:57:45 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 | 186 ++++++++++++++++++++++++++++++++++++++++++++--
include/linux/axxia-oem.h | 10 +++
2 files changed, 190 insertions(+), 6 deletions(-)
diff --git a/drivers/misc/axxia-oem.c b/drivers/misc/axxia-oem.c
index c737add..43a17f7 100644
--- a/drivers/misc/axxia-oem.c
+++ b/drivers/misc/axxia-oem.c
@@ -93,7 +93,6 @@ axxia_dspc_write(struct file *file, const char __user *buffer,
unsigned long mask;
input = kmalloc(count, __GFP_WAIT);
- memset(input, 0, count);
if (NULL == input)
return -ENOSPC;
@@ -101,7 +100,9 @@ axxia_dspc_write(struct file *file, const char __user *buffer,
if (copy_from_user(input, buffer, count))
return -EFAULT;
- mask = kstrtoul(input, 0, 0);
+ input[count] = 0;
+
+ mask = simple_strtoul(input, NULL, 0);
axxia_dspc_set_state((unsigned int)mask);
return count;
@@ -146,7 +147,6 @@ axxia_actlr_el3_write(struct file *file, const char __user *buffer,
char *input;
input = kmalloc(count, __GFP_WAIT);
- memset(input, 0, count);
if (NULL == input)
return -ENOSPC;
@@ -154,7 +154,9 @@ axxia_actlr_el3_write(struct file *file, const char __user *buffer,
if (copy_from_user(input, buffer, count))
return -EFAULT;
- axxia_actlr_el3_set(kstrtoul(input, 0, 0));
+ input[count] = 0;
+
+ axxia_actlr_el3_set(simple_strtoul(input, NULL, 0));
return count;
}
@@ -198,7 +200,6 @@ axxia_actlr_el2_write(struct file *file, const char __user *buffer,
char *input;
input = kmalloc(count, __GFP_WAIT);
- memset(input, 0, count);
if (NULL == input)
return -ENOSPC;
@@ -206,7 +207,9 @@ axxia_actlr_el2_write(struct file *file, const char __user *buffer,
if (copy_from_user(input, buffer, count))
return -EFAULT;
- axxia_actlr_el2_set(kstrtoul(input, 0, 0));
+ input[count] = 0;
+
+ axxia_actlr_el2_set(simple_strtoul(input, NULL, 0));
return count;
}
@@ -218,6 +221,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_WAIT);
+
+ 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, "lsi,axc6732")) {
+ if (0x9cff00 < new_ccn_offset)
+ pr_err("Invalid CCN Offset!\n");
+ } else if (of_find_compatible_node(NULL, NULL, "lsi,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_WAIT);
+
+ 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
@@ -355,6 +475,47 @@ 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
*/
@@ -382,6 +543,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