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:
Niranjan Yadla
2017-06-12 16:07:56 -07:00
committed by Dmitry Shmidt
parent 79318ad740
commit 2e58200e88
6 changed files with 252 additions and 18 deletions
+1
View File
@@ -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
+1
View File
@@ -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;
}
+12 -4
View File
@@ -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)
+166 -5
View File
@@ -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;
+51 -9
View File
@@ -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
+21
View File
@@ -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