From: John Jacques <john.jacq...@intel.com> Signed-off-by: John Jacques <john.jacq...@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 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto