[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(&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
 */
 
 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