diff options
Diffstat (limited to 'drivers/soc/qcom')
-rw-r--r-- | drivers/soc/qcom/Kconfig | 10 | ||||
-rw-r--r-- | drivers/soc/qcom/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/qcom/scm.c | 102 | ||||
-rw-r--r-- | drivers/soc/qcom/shenqi_nv.c | 195 |
4 files changed, 247 insertions, 61 deletions
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 81db4fe93dbc..6bb3162bf13c 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -178,16 +178,6 @@ config MSM_SMP2P 32-bit values by specifying a unique string and remote processor ID. -config MSM_SMP2P_TEST - bool "SMSM Point-to-Point Test" - depends on MSM_SMP2P - help - Enables loopback and unit testing support for - SMP2P. Loopback support is used by other - processors to do unit testing. Unit tests - are used to verify the local and remote - implementations. - config MSM_QMI_INTERFACE depends on IPC_ROUTER depends on QMI_ENCDEC diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 12482ee2aa79..b421fd71a7b1 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -113,3 +113,4 @@ obj-$(CONFIG_MSM_CACHE_M4M_ERP64) += cache_m4m_erp64.o obj-$(CONFIG_MSM_HAB) += hab/ obj-$(CONFIG_QCOM_QDSS_BRIDGE) += qdss_bridge.o obj-$(CONFIG_MFSE_QMI) += mfse_qmi_v01.o mfse_qmi.o +obj-y += shenqi_nv.o diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c index f4125113efff..96a2f962734f 100644 --- a/drivers/soc/qcom/scm.c +++ b/drivers/soc/qcom/scm.c @@ -194,9 +194,9 @@ static int scm_remap_error(int err) static u32 smc(u32 cmd_addr) { int context_id; - register u32 r0 asm("r0") = 1; - register u32 r1 asm("r1") = (uintptr_t)&context_id; - register u32 r2 asm("r2") = cmd_addr; + register u32 r0 asm(R0_STR) = 1; + register u32 r1 asm(R1_STR) = (uintptr_t)&context_id; + register u32 r2 asm(R2_STR) = cmd_addr; do { asm volatile( __asmeq("%0", R0_STR) @@ -209,7 +209,7 @@ static u32 smc(u32 cmd_addr) "smc #0\n" : "=r" (r0) : "r" (r0), "r" (r1), "r" (r2) - : "r3"); + : R3_STR); } while (r0 == SCM_INTERRUPTED); return r0; @@ -382,13 +382,13 @@ int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf, static int __scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, u64 *ret1, u64 *ret2, u64 *ret3) { - register u64 r0 asm("r0") = x0; - register u64 r1 asm("r1") = x1; - register u64 r2 asm("r2") = x2; - register u64 r3 asm("r3") = x3; - register u64 r4 asm("r4") = x4; - register u64 r5 asm("r5") = x5; - register u64 r6 asm("r6") = 0; + register u64 r0 asm("x0") = x0; + register u64 r1 asm("x1") = x1; + register u64 r2 asm("x2") = x2; + register u64 r3 asm("x3") = x3; + register u64 r4 asm("x4") = x4; + register u64 r5 asm("x5") = x5; + register u64 r6 asm("x6") = 0; do { asm volatile( @@ -431,13 +431,13 @@ static int __scm_call_armv8_64(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, static int __scm_call_armv8_32(u32 w0, u32 w1, u32 w2, u32 w3, u32 w4, u32 w5, u64 *ret1, u64 *ret2, u64 *ret3) { - register u32 r0 asm("r0") = w0; - register u32 r1 asm("r1") = w1; - register u32 r2 asm("r2") = w2; - register u32 r3 asm("r3") = w3; - register u32 r4 asm("r4") = w4; - register u32 r5 asm("r5") = w5; - register u32 r6 asm("r6") = 0; + register u32 r0 asm("w0") = w0; + register u32 r1 asm("w1") = w1; + register u32 r2 asm("w2") = w2; + register u32 r3 asm("w3") = w3; + register u32 r4 asm("w4") = w4; + register u32 r5 asm("w5") = w5; + register u32 r6 asm("w6") = 0; do { asm volatile( @@ -843,9 +843,9 @@ EXPORT_SYMBOL(scm_call); s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) { int context_id; - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1); - register u32 r1 asm("r1") = (uintptr_t)&context_id; - register u32 r2 asm("r2") = arg1; + register u32 r0 asm(R0_STR) = SCM_ATOMIC(svc, cmd, 1); + register u32 r1 asm(R1_STR) = (uintptr_t)&context_id; + register u32 r2 asm(R2_STR) = arg1; asm volatile( __asmeq("%0", R0_STR) @@ -858,7 +858,7 @@ s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1) "smc #0\n" : "=r" (r0) : "r" (r0), "r" (r1), "r" (r2) - : "r3"); + : R3_STR); return r0; } EXPORT_SYMBOL(scm_call_atomic1); @@ -876,9 +876,9 @@ EXPORT_SYMBOL(scm_call_atomic1); s32 scm_call_atomic1_1(u32 svc, u32 cmd, u32 arg1, u32 *ret1) { int context_id; - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 1); - register u32 r1 asm("r1") = (uintptr_t)&context_id; - register u32 r2 asm("r2") = arg1; + register u32 r0 asm(R0_STR) = SCM_ATOMIC(svc, cmd, 1); + register u32 r1 asm(R1_STR) = (uintptr_t)&context_id; + register u32 r2 asm(R2_STR) = arg1; asm volatile( __asmeq("%0", R0_STR) @@ -892,7 +892,7 @@ s32 scm_call_atomic1_1(u32 svc, u32 cmd, u32 arg1, u32 *ret1) "smc #0\n" : "=r" (r0), "=r" (r1) : "r" (r0), "r" (r1), "r" (r2) - : "r3"); + : R3_STR); if (ret1) *ret1 = r1; return r0; @@ -912,10 +912,10 @@ EXPORT_SYMBOL(scm_call_atomic1_1); s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) { int context_id; - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 2); - register u32 r1 asm("r1") = (uintptr_t)&context_id; - register u32 r2 asm("r2") = arg1; - register u32 r3 asm("r3") = arg2; + register u32 r0 asm(R0_STR) = SCM_ATOMIC(svc, cmd, 2); + register u32 r1 asm(R1_STR) = (uintptr_t)&context_id; + register u32 r2 asm(R2_STR) = arg1; + register u32 r3 asm(R3_STR) = arg2; asm volatile( __asmeq("%0", R0_STR) @@ -947,11 +947,11 @@ EXPORT_SYMBOL(scm_call_atomic2); s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3) { int context_id; - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 3); - register u32 r1 asm("r1") = (uintptr_t)&context_id; - register u32 r2 asm("r2") = arg1; - register u32 r3 asm("r3") = arg2; - register u32 r4 asm("r4") = arg3; + register u32 r0 asm(R0_STR) = SCM_ATOMIC(svc, cmd, 3); + register u32 r1 asm(R1_STR) = (uintptr_t)&context_id; + register u32 r2 asm(R2_STR) = arg1; + register u32 r3 asm(R3_STR) = arg2; + register u32 r4 asm(R4_STR) = arg3; asm volatile( __asmeq("%0", R0_STR) @@ -975,12 +975,12 @@ s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, { int ret; int context_id; - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 4); - register u32 r1 asm("r1") = (uintptr_t)&context_id; - register u32 r2 asm("r2") = arg1; - register u32 r3 asm("r3") = arg2; - register u32 r4 asm("r4") = arg3; - register u32 r5 asm("r5") = arg4; + register u32 r0 asm(R0_STR) = SCM_ATOMIC(svc, cmd, 4); + register u32 r1 asm(R1_STR) = (uintptr_t)&context_id; + register u32 r2 asm(R2_STR) = arg1; + register u32 r3 asm(R3_STR) = arg2; + register u32 r4 asm(R4_STR) = arg3; + register u32 r5 asm(R5_STR) = arg4; asm volatile( __asmeq("%0", R0_STR) @@ -1026,13 +1026,13 @@ s32 scm_call_atomic5_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, { int ret; int context_id; - register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 5); - register u32 r1 asm("r1") = (uintptr_t)&context_id; - register u32 r2 asm("r2") = arg1; - register u32 r3 asm("r3") = arg2; - register u32 r4 asm("r4") = arg3; - register u32 r5 asm("r5") = arg4; - register u32 r6 asm("r6") = arg5; + register u32 r0 asm(R0_STR) = SCM_ATOMIC(svc, cmd, 5); + register u32 r1 asm(R1_STR) = (uintptr_t)&context_id; + register u32 r2 asm(R2_STR) = arg1; + register u32 r3 asm(R3_STR) = arg2; + register u32 r4 asm(R4_STR) = arg3; + register u32 r5 asm(R5_STR) = arg4; + register u32 r6 asm(R6_STR) = arg5; asm volatile( __asmeq("%0", R0_STR) @@ -1066,8 +1066,8 @@ u32 scm_get_version(void) { int context_id; static u32 version = -1; - register u32 r0 asm("r0"); - register u32 r1 asm("r1"); + register u32 r0 asm(R0_STR); + register u32 r1 asm(R1_STR); if (version != -1) return version; @@ -1088,7 +1088,7 @@ u32 scm_get_version(void) "smc #0\n" : "=r" (r0), "=r" (r1) : "r" (r0), "r" (r1) - : "r2", "r3"); + : R2_STR, R3_STR); } while (r0 == SCM_INTERRUPTED); version = r1; diff --git a/drivers/soc/qcom/shenqi_nv.c b/drivers/soc/qcom/shenqi_nv.c new file mode 100644 index 000000000000..596837758db6 --- /dev/null +++ b/drivers/soc/qcom/shenqi_nv.c @@ -0,0 +1,195 @@ +/* +* Based on the work of Tony Sun +* Zhenglq : Add for Get nv data from modem using SMEM. +*/ + +#include <linux/types.h> +#include <linux/proc_fs.h> +#include "smd_private.h" +#include <linux/module.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/uaccess.h> +#include <linux/slab.h> + +#define NV_WIFI_ADDR_SIZE 6 +#define NV_BT_ADDR_SIZE 6 +#define NV_MAX_SIZE 512 + +struct smem_nv { + unsigned char nv_wifi[NV_WIFI_ADDR_SIZE]; + unsigned char nv_bt[NV_BT_ADDR_SIZE]; +}; + +static struct smem_nv *psmem_nv = NULL; + +static int smem_read_nv(void) +{ + struct smem_nv *buf; + + buf = smem_alloc(SMEM_ID_VENDOR_READ_NV, NV_MAX_SIZE,SMEM_APPS, 2); + if (!buf) { + printk(KERN_ERR "SMEM_ID_VENDOR_READ_NV smem_alloc failed\n"); + return 1; + } + + psmem_nv = kzalloc(sizeof(struct smem_nv), GFP_KERNEL); + if (!psmem_nv) { + printk(KERN_ERR "++++++++++++++++++++++=malloc psmem_nv fail\n"); + return 1; + } + + memcpy(psmem_nv, buf, sizeof(struct smem_nv)); + + return 0; +} + +static long dump_wifi_addr(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + loff_t pos = *f_pos; + int ret; + + ret = smem_read_nv(); + if (ret) { + pr_info("%s: smem_read_nv() failed", __func__); + return ret; + } + + if (!psmem_nv) + { + printk(KERN_ERR "Could not get smem for wlan mac nv\n"); + return 0; + } + + if (pos >= NV_WIFI_ADDR_SIZE) { + count = 0; + goto out; + } + + if (count > (NV_WIFI_ADDR_SIZE - pos)) + count = NV_WIFI_ADDR_SIZE - pos; + + pos += count; + + if (copy_to_user(buf, psmem_nv->nv_wifi + *f_pos,count)) { + count = -EFAULT; + goto out; + } + + *f_pos = pos; + +out: + return count; +} + +int wlan_get_nv_mac(char* buf) +{ + int ret; + + ret = smem_read_nv(); + if (ret) { + pr_info("%s: smem_read_nv() failed", __func__); + return ret; + } + + if (!psmem_nv){ + printk(KERN_ERR "Could not get smem for wlan mac nv\n"); + return -1; + } + + memcpy(buf, psmem_nv->nv_wifi, NV_WIFI_ADDR_SIZE); + return 0; +} +EXPORT_SYMBOL_GPL(wlan_get_nv_mac); + +#define DECLARE_FOPS(name) static const struct file_operations name## _fops = { \ + .read = name, \ +}; + +static long dump_bt_addr(struct file *filp, char __user *buf, + size_t count, loff_t *f_pos) +{ + loff_t pos = *f_pos; + size_t len; + + if (!psmem_nv) + smem_read_nv(); + + if (!psmem_nv) { + printk(KERN_ERR "Could not get smem for bt mac nv\n"); + return 0; + } + + len = sizeof(psmem_nv->nv_bt); + + if(pos >= len ) { + count = 0; + goto out; + } + + if(count > (len - pos)) + count = len - pos; + + pos += count; + + if(copy_to_user(buf,psmem_nv->nv_bt + (*f_pos),count)){ + count = -EFAULT; + goto out; + } + + *f_pos = pos; + +out: + return count; +} + +DECLARE_FOPS(dump_wifi_addr) +DECLARE_FOPS(dump_bt_addr) + +static int show_nv(void) +{ + struct proc_dir_entry *wifi_addr_entry; + struct proc_dir_entry *bt_addr_entry; + + wifi_addr_entry = proc_create("mac_wifi", 0, NULL, &dump_wifi_addr_fops); + bt_addr_entry = proc_create("mac_bt", 0, NULL, &dump_bt_addr_fops); + + if (!wifi_addr_entry) { + pr_info("%s: failed to create mac_wifi entry", __func__); + remove_proc_entry("mac_wifi", NULL); + return 1; + } + + if (!bt_addr_entry) { + pr_info("%s: failed to create mac_bt entry", __func__); + remove_proc_entry("mac_bt", NULL); + return 1; + } + + return 0; +} + +static int __init shenqi_nv_init(void) +{ + int ret = 0; + printk("%s(),%d\n" ,__func__, __LINE__); + + ret = show_nv(); + if (ret) { + pr_info("%s: show_nv() failed", __func__); + return 0; + } + + return 1; +} + +static void __exit shenqi_nv_exit(void) +{ + printk("%s(),%d\n", __func__, __LINE__); + kfree(psmem_nv); + psmem_nv = NULL; +} + +late_initcall(shenqi_nv_init); +module_exit(shenqi_nv_exit); |