[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(&parameters);
+
+	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(&parameters);
+
+	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