From 797ca58e55590364285a851cb24020f94bed7fe7 Mon Sep 17 00:00:00 2001 From: Zhongfu Luo Date: Thu, 12 Jul 2018 14:50:48 +0800 Subject: [PATCH] efuse: support EFUSE pattern burning PD#168568: G12A need to support EFUSE burning 1.add child node amlogic_set in efuse 2.node amlogic_set support EFUSE pattern burning Change-Id: Ie20a8b61678e351cf32418879d4b40228e1d365f Signed-off-by: Zhongfu Luo --- drivers/amlogic/efuse/efuse.h | 5 +++ drivers/amlogic/efuse/efuse64.c | 39 +++++++++++++++++++++++ drivers/amlogic/efuse/efuse_hw64.c | 50 ++++++++++++++++++++++++++++++ drivers/amlogic/secmon/secmon.c | 9 ++++++ include/linux/amlogic/secmon.h | 3 ++ 5 files changed, 106 insertions(+) diff --git a/drivers/amlogic/efuse/efuse.h b/drivers/amlogic/efuse/efuse.h index acd5378d283a..4642dc38bfa8 100644 --- a/drivers/amlogic/efuse/efuse.h +++ b/drivers/amlogic/efuse/efuse.h @@ -46,6 +46,10 @@ #define EFUSE_HAL_API_WRITE 1 #define EFUSE_HAL_API_USER_MAX 3 +#define AML_DATA_PROCESS (0x820000FF) +#define AML_D_P_W_EFUSE_AMLOGIC (0x20) +#define GXB_EFUSE_PATTERN_SIZE (0x400) + #define ASSIST_HW_REV 0x1f53 extern int efuseinfo_num; @@ -97,6 +101,7 @@ extern struct clk *efuse_clk; ssize_t efuse_get_max(void); ssize_t efuse_read_usr(char *buf, size_t count, loff_t *ppos); ssize_t efuse_write_usr(char *buf, size_t count, loff_t *ppos); +unsigned long efuse_amlogic_set(char *buf, size_t count); #endif diff --git a/drivers/amlogic/efuse/efuse64.c b/drivers/amlogic/efuse/efuse64.c index 175c99f270a5..de552e7ec680 100644 --- a/drivers/amlogic/efuse/efuse64.c +++ b/drivers/amlogic/efuse/efuse64.c @@ -483,6 +483,43 @@ static ssize_t userdata_write(struct class *cla, } #endif +static ssize_t amlogic_set_store(struct class *cla, + struct class_attribute *attr, const char *buf, size_t count) +{ + int i; + int ret; + char *op = NULL; + + if (count != GXB_EFUSE_PATTERN_SIZE) { + pr_err("efuse: bad size, only support size %d!\n", + GXB_EFUSE_PATTERN_SIZE); + return -EINVAL; + } + + op = kzalloc((sizeof(char)*count), GFP_KERNEL); + if (!op) { + ret = -ENOMEM; + pr_err("efuse: failed to allocate memory!\n"); + return ret; + } + + memset(op, 0, count); + for (i = 0; i < count; i++) + op[i] = buf[i]; + + ret = efuse_amlogic_set(op, count); + kfree(op); + + if (ret) { + pr_err("EFUSE pattern programming fail! ret: %d\n", ret); + return -EINVAL; + } + + pr_info("EFUSE pattern programming success!\n"); + + return count; +} + static struct class_attribute efuse_class_attrs[] = { #ifndef EFUSE_READ_ONLY @@ -502,6 +539,8 @@ static struct class_attribute efuse_class_attrs[] = { __ATTR(usid, 0700, show_usid, store_usid), + __ATTR_WO(amlogic_set), + __ATTR_NULL }; diff --git a/drivers/amlogic/efuse/efuse_hw64.c b/drivers/amlogic/efuse/efuse_hw64.c index 0e93454bff32..6da11f489755 100644 --- a/drivers/amlogic/efuse/efuse_hw64.c +++ b/drivers/amlogic/efuse/efuse_hw64.c @@ -31,6 +31,7 @@ #endif #include #include +#include static long meson_efuse_fn_smc(struct efuse_hal_api_arg *arg) { @@ -83,6 +84,55 @@ int meson_trustzone_efuse(struct efuse_hal_api_arg *arg) return ret; } +unsigned long efuse_aml_sec_boot_check(unsigned long nType, + unsigned long pBuffer, + unsigned long nLength, + unsigned long nOption) +{ + struct arm_smccc_res res; + long sharemem_phy_base; + + sharemem_phy_base = get_secmon_phy_input_base(); + if ((!sharemem_input_base) || (!sharemem_phy_base)) + return -1; + + sharemem_mutex_lock(); + + memcpy((void *)sharemem_input_base, + (const void *)pBuffer, nLength); + + __flush_dcache_area(sharemem_input_base, nLength); + + asm __volatile__("" : : : "memory"); + + do { + arm_smccc_smc((unsigned long)AML_DATA_PROCESS, + (unsigned long)nType, + (unsigned long)sharemem_phy_base, + (unsigned long)nLength, + (unsigned long)nOption, + 0, 0, 0, &res); + } while (0); + + sharemem_mutex_unlock(); + + return res.a0; +} + +unsigned long efuse_amlogic_set(char *buf, size_t count) +{ + unsigned long ret; + + set_cpus_allowed_ptr(current, cpumask_of(0)); + + ret = efuse_aml_sec_boot_check(AML_D_P_W_EFUSE_AMLOGIC, + (unsigned long)buf, (unsigned long)count, 0); + + set_cpus_allowed_ptr(current, cpu_all_mask); + + return ret; +} + ssize_t meson_trustzone_efuse_get_max(struct efuse_hal_api_arg *arg) { ssize_t ret; diff --git a/drivers/amlogic/secmon/secmon.c b/drivers/amlogic/secmon/secmon.c index 99704a31fc0e..c24a866d38c9 100644 --- a/drivers/amlogic/secmon/secmon.c +++ b/drivers/amlogic/secmon/secmon.c @@ -148,3 +148,12 @@ void __iomem *get_secmon_sharemem_output_base(void) { return sharemem_out_base; } + +long get_secmon_phy_input_base(void) +{ + return phy_in_base; +} +long get_secmon_phy_output_base(void) +{ + return phy_out_base; +} diff --git a/include/linux/amlogic/secmon.h b/include/linux/amlogic/secmon.h index 21db071213e8..07bc94aef038 100644 --- a/include/linux/amlogic/secmon.h +++ b/include/linux/amlogic/secmon.h @@ -20,6 +20,9 @@ void __iomem *get_secmon_sharemem_input_base(void); void __iomem *get_secmon_sharemem_output_base(void); +long get_secmon_phy_input_base(void); +long get_secmon_phy_output_base(void); + void sharemem_mutex_lock(void); void sharemem_mutex_unlock(void);