hifi-dsp: Load HiFi DSP firmware Image from AP
1.1 Notify lpm3 to reset hifi 1.2 read hifi firmware image from /data/hifi.img 1.3 load sections on to dsp instruction memory 1.4 Added read_hifi_shared_addr() to read and log value at 0x8B300000 addr. ExampleUsage: Copy hifi.img (hifi dsp firmware) to /data/hifi.img then run $adb shell cat /proc/hifidebug/resetsystem to load hifi firmware onto dsp, to start dsp go to adb shell,then $cd /proc/hifidebug, echo write_mem 0x8B300000 0x5a5a5a5a >dspfaultinject Signed-off-by: Li Wanpeng <liwanpeng1@hisilicon.com> Signed-off-by: Niranjan Yadla <nyadla@cadence.com>
This commit is contained in:
committed by
Dmitry Shmidt
parent
79318ad740
commit
2e58200e88
@@ -31,4 +31,5 @@ endif
|
||||
|
||||
obj-$(CONFIG_HIFI_DSP_ONE_TRACK) += hifi_lpp.o
|
||||
obj-$(CONFIG_HIFI_DSP_ONE_TRACK) += hifi_om.o
|
||||
obj-$(CONFIG_HIFI_DSP_ONE_TRACK) += memcpy_opt.o
|
||||
|
||||
|
||||
@@ -902,6 +902,7 @@ static int hifi_dsp_write_param(unsigned long arg)
|
||||
static int hifi_misc_open(struct inode *finode, struct file *fd)
|
||||
{
|
||||
logi("open device.\n");
|
||||
load_hifi_img_by_misc();
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,10 +39,10 @@ extern "C" {
|
||||
#define SIZE_LIMIT_PARAM (512)
|
||||
#endif
|
||||
|
||||
#define NVPARAM_COUNT 400 /*HIFI NV size is 400*/
|
||||
#define NVPARAM_NUMBER 258 /*256+2, nv_data(256) + nv_id(2)*/
|
||||
#define NVPARAM_START 2 /*head protect_number 0x5a5a5a5a*/
|
||||
#define NVPARAM_TAIL 2 /*tail protect_number 0x5a5a5a5a*/
|
||||
#define NVPARAM_COUNT 400 /*HIFI NV size is 400 */
|
||||
#define NVPARAM_NUMBER 258 /*256+2, nv_data(256) + nv_id(2) */
|
||||
#define NVPARAM_START 2 /*head protect_number 0x5a5a5a5a */
|
||||
#define NVPARAM_TAIL 2 /*tail protect_number 0x5a5a5a5a */
|
||||
#define NVPARAM_TOTAL_SIZE ((NVPARAM_NUMBER * NVPARAM_COUNT + NVPARAM_START + NVPARAM_TAIL) * sizeof(unsigned short))
|
||||
|
||||
#ifdef CONFIG_HISI_FAMA
|
||||
@@ -178,6 +178,14 @@ extern "C" {
|
||||
|
||||
#define HIFI_OCRAM_BASE_ADDR (0xE8000000)
|
||||
#define HIFI_TCM_BASE_ADDR (0xE8058000)
|
||||
#define HIFI_RUN_DDR_REMAP_BASE (0xC0000000)
|
||||
#define HIFI_TCM_PHY_BEGIN_ADDR (HIFI_TCM_BASE_ADDR)
|
||||
#define HIFI_TCM_PHY_END_ADDR (HIFI_TCM_PHY_BEGIN_ADDR + HIFI_TCM_SIZE - 1)
|
||||
#define HIFI_TCM_SIZE (HIFI_RUN_ITCM_SIZE + HIFI_RUN_DTCM_SIZE)
|
||||
|
||||
#define HIFI_OCRAM_PHY_BEGIN_ADDR (HIFI_OCRAM_BASE_ADDR)
|
||||
#define HIFI_OCRAM_PHY_END_ADDR (HIFI_OCRAM_PHY_BEGIN_ADDR + HIFI_OCRAM_SIZE - 1)
|
||||
#define HIFI_OCRAM_SIZE (HIFI_IMAGE_OCRAMBAK_SIZE)
|
||||
|
||||
#define SIZE_PARAM_PRIV (206408) /*refer from function dsp_nv_init in dsp_soc_para_ctl.c */
|
||||
#define HIFI_SYS_MEM_ADDR (HIFI_RUN_LOCATION)
|
||||
|
||||
@@ -32,8 +32,11 @@
|
||||
#include "hifi_lpp.h"
|
||||
#include "hifi_om.h"
|
||||
#include "drv_mailbox_msg.h"
|
||||
#include <linux/hisi/hisi_rproc.h>
|
||||
#include <dsm/dsm_pub.h>
|
||||
#include <linux/hisi/rdr_pub.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#define HI_DECLARE_SEMAPHORE(name) \
|
||||
struct semaphore name = __SEMAPHORE_INITIALIZER(name, 0)
|
||||
@@ -728,7 +731,7 @@ static int hifi_send_str_todsp(const char *cmd_str, size_t size)
|
||||
|
||||
BUG_ON(cmd_str == NULL);
|
||||
|
||||
msg_len = sizeof(hifi_str_cmd) + size + 1; /*add 1 for last \0*/
|
||||
msg_len = sizeof(hifi_str_cmd) + size + 1; /*add 1 for last \0 */
|
||||
|
||||
pcmd = (hifi_str_cmd *) kmalloc(msg_len, GFP_ATOMIC);
|
||||
if (!pcmd) {
|
||||
@@ -832,6 +835,160 @@ static const struct file_operations hifi_dspfaultinject_proc_ops = {
|
||||
.write = hifi_dsp_fault_inject_store,
|
||||
};
|
||||
|
||||
struct image_partition_table addr_remap_tables[] = {
|
||||
{HIFI_RUN_DDR_REMAP_BASE, HIFI_RUN_DDR_REMAP_BASE + HIFI_RUN_SIZE,
|
||||
HIFI_RUN_SIZE, HIFI_RUN_LOCATION},
|
||||
{HIFI_TCM_PHY_BEGIN_ADDR, HIFI_TCM_PHY_END_ADDR, HIFI_TCM_SIZE,
|
||||
HIFI_IMAGE_TCMBAK_LOCATION},
|
||||
{HIFI_OCRAM_PHY_BEGIN_ADDR, HIFI_OCRAM_PHY_END_ADDR, HIFI_OCRAM_SIZE,
|
||||
HIFI_IMAGE_OCRAMBAK_LOCATION}
|
||||
};
|
||||
|
||||
extern void *memcpy64(void *dst, const void *src, unsigned len);
|
||||
extern void *memcpy128(void *dst, const void *src, unsigned len);
|
||||
|
||||
void *memcpy_aligned(void *_dst, const void *_src, unsigned len)
|
||||
{
|
||||
unsigned char *dst = _dst;
|
||||
const unsigned char *src = _src;
|
||||
unsigned int length = len;
|
||||
unsigned int cpy_len;
|
||||
|
||||
if (((unsigned long)dst % 16 == 0) && ((unsigned long)src % 16 == 0)
|
||||
&& (length >= 16)) {
|
||||
cpy_len = length & 0xFFFFFFF0;
|
||||
memcpy128(dst, src, cpy_len);
|
||||
length = length % 16;
|
||||
dst = dst + cpy_len;
|
||||
src = src + cpy_len;
|
||||
|
||||
if (length == 0)
|
||||
return _dst;
|
||||
}
|
||||
|
||||
if (((unsigned long)dst % 8 == 0) && ((unsigned long)src % 8 == 0)
|
||||
&& (length >= 8)) {
|
||||
cpy_len = length & 0xFFFFFFF8;
|
||||
memcpy64(dst, src, cpy_len);
|
||||
length = length % 8;
|
||||
dst = dst + cpy_len;
|
||||
src = src + cpy_len;
|
||||
if (length == 0)
|
||||
return _dst;
|
||||
}
|
||||
|
||||
if (((unsigned long)dst % 4 == 0) && ((unsigned long)src % 4 == 0)) {
|
||||
cpy_len = length >> 2;
|
||||
while (cpy_len-- > 0) {
|
||||
*(unsigned int *)dst = *(unsigned int *)src;
|
||||
dst += 4;
|
||||
src += 4;
|
||||
}
|
||||
length = length % 4;
|
||||
if (length == 0)
|
||||
return _dst;
|
||||
}
|
||||
|
||||
while (length-- > 0)
|
||||
*dst++ = *src++;
|
||||
|
||||
return _dst;
|
||||
}
|
||||
|
||||
static int read_hifi_shared_addr(void)
|
||||
{
|
||||
unsigned int *read_hifi_shared_addr = NULL;
|
||||
int ret = 0;
|
||||
|
||||
loge(" Enter %s\n", __func__);
|
||||
read_hifi_shared_addr = ioremap_wc(0x8B300000, 50);
|
||||
if (read_hifi_shared_addr == NULL) {
|
||||
loge(" %s(): read_hifi_shared_addr ioremap_wc failed\n",
|
||||
__func__);
|
||||
} else {
|
||||
loge(" 0x8B300000:0x%x \n", readl(read_hifi_shared_addr));
|
||||
iounmap(read_hifi_shared_addr);
|
||||
read_hifi_shared_addr = NULL;
|
||||
}
|
||||
loge(" %s():Exit\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int load_hifi_img_by_misc(void)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
char *img_buf = NULL;
|
||||
struct drv_hifi_image_head *hifi_img = NULL;
|
||||
const struct firmware *hifi_firmware;
|
||||
|
||||
if (g_om_data.dsp_loaded == true)
|
||||
return 0;
|
||||
|
||||
loge("load hifi image now\n");
|
||||
|
||||
if (request_firmware(&hifi_firmware, "hifi/hifi.img", g_om_data.dev) < 0) {
|
||||
loge("could not find firmware file hifi/hifi.img\n");
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
img_buf = (char *)hifi_firmware->data;
|
||||
|
||||
hifi_img = (struct drv_hifi_image_head *)img_buf;
|
||||
logi("sections_num:%u, image_size:%u\n", hifi_img->sections_num,
|
||||
hifi_img->image_size);
|
||||
|
||||
for (i = 0; i < hifi_img->sections_num; i++) {
|
||||
unsigned int index = 0;
|
||||
unsigned long remap_dest_addr = 0;
|
||||
|
||||
logi("sections_num:%u, i:%u\n", hifi_img->sections_num, i);
|
||||
logi("des_addr:0x%x, load_attib:%u, size:%u, sn:%hu, src_offset:%x, type:%u\n", hifi_img->sections[i].des_addr, hifi_img->sections[i].load_attib, hifi_img->sections[i].size, hifi_img->sections[i].sn, hifi_img->sections[i].src_offset, hifi_img->sections[i].type);
|
||||
|
||||
remap_dest_addr = (unsigned long)hifi_img->sections[i].des_addr;
|
||||
if (remap_dest_addr >= HIFI_OCRAM_PHY_BEGIN_ADDR
|
||||
&& remap_dest_addr <= HIFI_OCRAM_PHY_END_ADDR) {
|
||||
index = 2;
|
||||
} else if (remap_dest_addr >= HIFI_TCM_PHY_BEGIN_ADDR
|
||||
&& remap_dest_addr <= HIFI_TCM_PHY_END_ADDR) {
|
||||
index = 1;
|
||||
} else { /*(remap_addr >= HIFI_DDR_PHY_BEGIN_ADDR && remap_addr <= HIFI_DDR_PHY_END_ADDR) */
|
||||
index = 0;
|
||||
}
|
||||
remap_dest_addr -=
|
||||
addr_remap_tables[index].phy_addr_start -
|
||||
addr_remap_tables[index].remap_addr;
|
||||
|
||||
if (hifi_img->sections[i].type != DRV_HIFI_IMAGE_SEC_TYPE_BSS) {
|
||||
unsigned int *iomap_dest_addr = NULL;
|
||||
|
||||
if (hifi_img->sections[i].load_attib ==
|
||||
(unsigned char)DRV_HIFI_IMAGE_SEC_UNLOAD) {
|
||||
logi("unload section\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
iomap_dest_addr =
|
||||
(unsigned int *)ioremap(remap_dest_addr,
|
||||
hifi_img->sections[i].size);
|
||||
if (!iomap_dest_addr) {
|
||||
loge("ioremap failed\n");
|
||||
release_firmware(hifi_firmware);
|
||||
return -1;
|
||||
}
|
||||
memcpy_aligned((void *)(iomap_dest_addr),
|
||||
(void *)((char *)hifi_img +
|
||||
hifi_img->sections[i].
|
||||
src_offset),
|
||||
hifi_img->sections[i].size);
|
||||
iounmap(iomap_dest_addr);
|
||||
}
|
||||
}
|
||||
|
||||
g_om_data.dsp_loaded = true;
|
||||
release_firmware(hifi_firmware);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RESET_OPTION_LEN 100
|
||||
|
||||
static ssize_t hifi_dsp_reset_option_show(struct file *file, char __user *buf,
|
||||
@@ -843,7 +1000,11 @@ static ssize_t hifi_dsp_reset_option_show(struct file *file, char __user *buf,
|
||||
loge("Input param buf is invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (load_hifi_img_by_misc() == 0) {
|
||||
g_om_data.dsp_loaded = true;
|
||||
read_hifi_shared_addr();
|
||||
loge("g_om_data.dsp_loaded:%d\n", (int)g_om_data.dsp_loaded);
|
||||
}
|
||||
snprintf(reset_option, RESET_OPTION_LEN,
|
||||
"reset_option: 0(reset mediasever) 1(reset system) current:%d.\n",
|
||||
g_om_data.reset_system);
|
||||
@@ -1126,7 +1287,7 @@ void hifi_om_init(struct platform_device *pdev,
|
||||
g_om_data.dsp_time_stamp =
|
||||
(unsigned int *)ioremap(SYS_TIME_STAMP_REG, 0x4);
|
||||
if (NULL == g_om_data.dsp_time_stamp) {
|
||||
pr_err("time stamp reg ioremap Error.\n"); /*can't use logx*/
|
||||
pr_err("time stamp reg ioremap Error.\n"); /*can't use logx */
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1288,8 +1449,8 @@ void hifi_om_effect_mcps_info_show(struct hifi_om_effect_mcps_stru
|
||||
ID_EFFECT_ALGO_BUTT
|
||||
&& hifi_mcps_info->effect_mcps_info[i].effect_algo_id >
|
||||
ID_EFFECT_ALGO_START) {
|
||||
switch (hifi_mcps_info->effect_mcps_info[i].
|
||||
effect_stream_id) {
|
||||
switch (hifi_mcps_info->
|
||||
effect_mcps_info[i].effect_stream_id) {
|
||||
case AUDIO_STREAM_PCM_OUTPUT:
|
||||
logw("Algorithm: %s, Mcps: %d, Stream: PCM_OUTPUT \n", effect_algo[hifi_mcps_info->effect_mcps_info[i].effect_algo_id - 1].effect_name, hifi_mcps_info->effect_mcps_info[i].effect_algo_mcps);
|
||||
break;
|
||||
|
||||
@@ -47,6 +47,7 @@ extern "C" {
|
||||
#define HIFI_OM_FILE_LIMIT 0640
|
||||
#define HIFI_OM_LOG_SIZE_MAX 0x400000 /* 4*1024*1024 = 4M */
|
||||
#define HIFI_OM_FILE_BUFFER_SIZE_MAX (1024)
|
||||
#define HIFI_SEC_MAX_NUM 64
|
||||
|
||||
typedef enum {
|
||||
DUMP_DSP_LOG,
|
||||
@@ -69,21 +70,21 @@ extern "C" {
|
||||
} DUMP_DSP_INDEX;
|
||||
|
||||
enum HIFI_CPU_LOAD_INFO_ENUM {
|
||||
HIFI_CPU_LOAD_REPORT = 0,
|
||||
HIFI_CPU_LOAD_VOTE_UP,
|
||||
HIFI_CPU_LOAD_VOTE_DOWN,
|
||||
HIFI_CPU_LOAD_LACK_PERFORMANCE,
|
||||
HIFI_CPU_LOAD_REPORT = 0,
|
||||
HIFI_CPU_LOAD_VOTE_UP,
|
||||
HIFI_CPU_LOAD_VOTE_DOWN,
|
||||
HIFI_CPU_LOAD_LACK_PERFORMANCE,
|
||||
HIFI_CPU_LOAD_INFO_BUTT
|
||||
};
|
||||
|
||||
enum HIFI_CPU_OM_INFO_ENUM {
|
||||
HIFI_CPU_OM_LOAD_INFO = 0,
|
||||
HIFI_CPU_OM_ALGO_MCPS_INFO,
|
||||
HIFI_CPU_OM_UPDATE_BUFF_DELAY_INFO,
|
||||
HIFI_CPU_OM_LOAD_INFO = 0,
|
||||
HIFI_CPU_OM_ALGO_MCPS_INFO,
|
||||
HIFI_CPU_OM_UPDATE_BUFF_DELAY_INFO, /* audio pcm play or capture update buff delay */
|
||||
HIFI_CPU_OM_INFO_BUTT
|
||||
};
|
||||
enum EFFECT_ALGO_ENUM {
|
||||
ID_EFFECT_ALGO_START = 0,
|
||||
enum EFFECT_ALGO_ENUM {
|
||||
ID_EFFECT_ALGO_START = 0,
|
||||
ID_EFFECT_ALGO_FORMATER,
|
||||
ID_EFFECT_ALGO_FORTE_VOICE_SPKOUT,
|
||||
ID_EFFECT_ALGO_FORTE_VOICE_MICIN,
|
||||
@@ -138,6 +139,46 @@ extern "C" {
|
||||
AUDIO_STREAM_INPUT_CNT,
|
||||
};
|
||||
|
||||
enum DRV_HIFI_IMAGE_SEC_LOAD_ENUM {
|
||||
DRV_HIFI_IMAGE_SEC_LOAD_STATIC = 0,
|
||||
DRV_HIFI_IMAGE_SEC_LOAD_DYNAMIC,
|
||||
DRV_HIFI_IMAGE_SEC_UNLOAD,
|
||||
DRV_HIFI_IMAGE_SEC_UNINIT,
|
||||
DRV_HIFI_IMAGE_SEC_LOAD_BUTT,
|
||||
};
|
||||
typedef unsigned char DRV_HIFI_IMAGE_SEC_LOAD_ENUM_UINT8;
|
||||
|
||||
enum DRV_HIFI_IMAGE_SEC_TYPE_ENUM {
|
||||
DRV_HIFI_IMAGE_SEC_TYPE_CODE = 0,
|
||||
DRV_HIFI_IMAGE_SEC_TYPE_DATA,
|
||||
DRV_HIFI_IMAGE_SEC_TYPE_BSS,
|
||||
DRV_HIFI_IMAGE_SEC_TYPE_BUTT,
|
||||
};
|
||||
typedef unsigned char DRV_HIFI_IMAGE_SEC_TYPE_ENUM_UINT8;
|
||||
|
||||
struct drv_hifi_image_sec {
|
||||
unsigned short sn;
|
||||
DRV_HIFI_IMAGE_SEC_TYPE_ENUM_UINT8 type;
|
||||
DRV_HIFI_IMAGE_SEC_LOAD_ENUM_UINT8 load_attib;
|
||||
unsigned int src_offset;
|
||||
unsigned int des_addr;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct drv_hifi_image_head {
|
||||
char time_stamp[24];
|
||||
unsigned int image_size;
|
||||
unsigned int sections_num;
|
||||
struct drv_hifi_image_sec sections[HIFI_SEC_MAX_NUM];
|
||||
};
|
||||
|
||||
struct image_partition_table {
|
||||
unsigned long phy_addr_start;
|
||||
unsigned long phy_addr_end;
|
||||
unsigned int size;
|
||||
unsigned long remap_addr;
|
||||
};
|
||||
|
||||
struct hifi_om_s {
|
||||
struct task_struct *kdumpdsp_task;
|
||||
struct semaphore dsp_dump_sema;
|
||||
@@ -331,6 +372,7 @@ do {\
|
||||
int hifi_om_get_voice_bsd_param(void __user *uaddr);
|
||||
void hifi_om_rev_data_handle(int type, const unsigned char *addr,
|
||||
unsigned int len);
|
||||
int load_hifi_img_by_misc(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
|
||||
.global memcpy128
|
||||
.global memcpy64
|
||||
|
||||
memcpy128:
|
||||
add x2, x0, x2
|
||||
memcpy_align_128:
|
||||
ldp x3, x4, [x1], #16
|
||||
stp x3, x4, [x0], #16
|
||||
cmp x0, x2
|
||||
b.ne memcpy_align_128
|
||||
ret
|
||||
|
||||
memcpy64:
|
||||
add x2, x0, x2
|
||||
memcpy_align_64:
|
||||
ldr x3, [x1], #8
|
||||
str x3, [x0], #8
|
||||
cmp x0, x2
|
||||
b.ne memcpy_align_64
|
||||
ret
|
||||
Reference in New Issue
Block a user