Esempio n. 1
0
int thermal_data_init(void)
{
    int i = 0;
    int phy_chan;
    struct hkadc_chan_config*  chan_cfg;

    g_thermal_share_area = (struct thermal_data_area *)ioremap(MCU_HKADC_DDR_ADDR,MCU_HKADC_DDR_SIZE);

    chan_cfg = (struct hkadc_chan_config*)(&(g_thermal_share_area->chan_cfg[0]));

	g_hkadc_baseadddr = ioremap(SOC_HKADC_BASE_ADDR,0x1000);
	if (!g_hkadc_baseadddr) {
		printk("hkadc ioremap error!\n");
	}

    hkadc_fill_channel_map();
    /*1.填充ACPU每个通道的配置数据*/
    for (i=0; i < sizeof(acpu_hkadc_property)/sizeof(struct hkadc_table_data); i++) {
        /* PA0 PA1不需要配置wx206530 */
        if (acpu_hkadc_property[i].ctrlflag == 0)
            continue;

	 phy_chan = acpu_hkadc_property[i].phy_chan;
        chan_cfg[phy_chan].outcfg.out_config = acpu_hkadc_property[i].hkadc_conf.outconfig;
        chan_cfg[phy_chan].out_peroid = acpu_hkadc_property[i].hkadc_conf.outperiod;
        chan_cfg[phy_chan].temp_data_len = acpu_hkadc_property[i].table_len;
        hisi_io_memcpy(chan_cfg[phy_chan].temp_table, acpu_hkadc_property[i].temp_table,
            (sizeof(struct hkadc_tem_value) * acpu_hkadc_property[i].table_len));

        chan_cfg[phy_chan].have_config = 1;

        printk(KERN_INFO"phy [%d], out_config %x, out_period %d, temp_data_len %d\n", \
                acpu_hkadc_property[i].phy_chan, chan_cfg[acpu_hkadc_property[i].phy_chan].outcfg.out_config,  \
                chan_cfg[acpu_hkadc_property[i].phy_chan].out_peroid, chan_cfg[acpu_hkadc_property[i].phy_chan].temp_data_len);
    }

    /*2.填充g_hkadc_chan_map中的物理通道号*/
    acpu_hkadc_fill_chan_map();
#if 0
    /*3.读取并填充系统放电温保配置*/
    hisi_io_memcpy((void *)(&g_thermal_share_area->sys_temp_cfg), (void *)&default_bat_tempproc_conf, \
            sizeof(struct sys_temp_cfg));


    /*4.将电池温保的温度阀值,改成电压*/
    if (bat_tempprotect_param_init() != 0) {
        printk(KERN_ALERT"bat_tempprotect_param_init failed\n");
        //return -1;
    }
#endif

    spin_lock_init(&g_hkadc_lock);
    /*保证A、M核同时读取HKADC的互斥机制初始化*/
    g_thermal_share_area->last_slice = 0;

    /*5.设置完成标记, 与MCU同步电池温保参数配置*/
    g_thermal_share_area->magic_end = HKADC_INIT_MAGIC_CODE;

    return 0;
}
void _queue_loop_in(struct queue *q, void *element, unsigned int len)
{
    unsigned int copy = min((q->max - q->head), len);
    unsigned int omit = len;
    unsigned int left = 0;

    /*left room*/
    left = q->max - (MOD_SUB(q->head, q->tail, q->max));
    if (left > (len + 1)){
        omit = 0;
    }

    /*update tail index*/
    q->tail = MOD_ADD(q->tail, omit, q->max);

    /*copy data*/
    hisi_io_memcpy(&(q->data[q->head]), element, copy);
    if (len > copy){
        hisi_io_memcpy(&(q->data[0]), element + copy, len - copy);
    }
    q->head = MOD_ADD(q->head, len, q->max);
    q->in += len;

    return;
}
/*****************************************************************************
 函 数 名  : memcpy_local
 功能描述  : Hifi自己专用itcm 数据加载时memcpy功能,因为单字节copy hifi itcm,会导致问题(芯片zhangguoliang),
            所以不能用hisi_io_memcpy.for DTS2014061904100
 输入参数  : 
 输出参数  : 无
 返 回 值  : 目的地址
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2014年6月23日
    作    者   : 
    修改内容   : 新生成函数

*****************************************************************************/
static void *memcpy_local(void *dest, const void *src, unsigned int count)
{
/*from soc,zhangguoliang,64bit, hifi itcm不能一个字节一个字节copy!!*/
#ifdef CONFIG_ARM64
	int *tmp = dest;
	const int *s = src;
    unsigned int    cnt_local = count;
    
    if (NULL == dest || NULL == src || 0 == count)
    {
        printk(KERN_ERR "%s: param is wrong !!\n", __FUNCTION__);
        return NULL;
    }
    /*4 bytes copy*/
    if (IS_ALIGNED((unsigned long)dest, sizeof(int)) 
        && IS_ALIGNED((unsigned long)src, sizeof(int)) 
        && (count % sizeof(int) == 0))
    {   
        cnt_local = cnt_local/sizeof(int);
    	while (cnt_local > 0)
        {
            *tmp++ = *s++;
            cnt_local--;
        }   
    }
    else    /*copy one by one*/
    {
        printk(KERN_ERR "%s: param is not aligned by 4 bytes !! may make error!\n", __FUNCTION__);
        hisi_io_memcpy(dest, src, count);
    }
#else
    hisi_io_memcpy(dest, src, count);
#endif
	return dest;
}
static int kirq_proc_show(struct seq_file *m, void *v)
{
	char *mem = NULL ;
	void * __iomem exc_mem = NULL;
	struct dump_log *dump = NULL;
	struct queue *head = NULL;
	struct irq_info info;
	unsigned long flags = 0;
	u32 count = num_online_cpus();
	unsigned int i = 0;

	exc_mem = (void *)ioremap(ANDROID_DUMP_LOG_ADDR, ANDROID_DUMP_LOG_SIZE);
	if (NULL == exc_mem) {
		printk("%s : failed to ioremap memory\r\n", __FUNCTION__);
		return 0;
	}

	dump = (struct dump_log *)exc_mem;

	mem = (char *)vmalloc(EXCH_INT_SWITCH_SIZE);
	if (!mem) {
		printk("%s : failed to vmalloc memory\n",__FUNCTION__);
		goto kirq_unmap;
	}

	for (i = 0; i < count; i++) {
		head = (struct queue*)(dump->irq_trace + g_irq_record_offset[i]);
		spin_lock_irqsave(&head->lock, flags);
		hisi_io_memcpy(mem, &dump->irq_trace[0], EXCH_INT_SWITCH_SIZE);
		spin_unlock_irqrestore(&head->lock, flags);

		head = (struct queue *)(mem + g_irq_record_offset[i]);
		seq_printf(m, "IRQ Trace cpu[%d]\n", i);
		seq_printf(m, "in %u out %u size %u\n", head->in, head->out, head->max);

		do {
			if (_queue_out(head, (void *)&info, sizeof(struct irq_info)))
				break;

			if (EXCH_INT_EXIT == info.irq)
				seq_printf(m, "[ %10lu ][ %10lu ][ CPU %1d ] IRQ         OUT\n", \
							info.jiff, info.slice, info.cpu);
			else
				seq_printf(m, "[ %10lu ][ %10lu ][ CPU %1d ] IRQ [ %3d ] IN\n", \
							info.jiff, info.slice, info.cpu, info.irq);
		} while(1);

		seq_printf(m, "\n");
	}

	vfree(mem);

kirq_unmap:
	iounmap(exc_mem);
	return 0;
}
int _queue_in(struct queue *q, void *element, unsigned int len)
{
    unsigned int copy = min((q->max - q->head), len);
    unsigned int left = 0;

    /*left room*/
    left = q->max - (MOD_SUB(q->head, q->tail, q->max));
    if ((len + 1) > left){
        return -1;
    }

    hisi_io_memcpy(&(q->data[q->head]), element, copy);
    if (len > copy){
        hisi_io_memcpy(&(q->data[0]), element + copy, len - copy);
    }

    q->head = MOD_ADD(q->head, len, q->max);

    return 0;
}
int _queue_out(struct queue *q, void *element, unsigned int len)
{
    unsigned int valid;
    unsigned int copy;

    valid = MOD_SUB(q->head, q->tail, q->max);
    if (len > valid){
        return -1;
    }

    copy = min((q->max - q->tail), len);
    hisi_io_memcpy(element, &q->data[q->tail], copy);
    if (len > copy){
        hisi_io_memcpy(element + copy, &q->data[0], len - copy);
    }

    q->tail = MOD_ADD(q->tail, len, q->max);
    q->out += len;

    return 0;
}
/*****************************************************************************
* 函 数 名  : IPF_Assert
*
* 功能描述  : 异常进入dump模式
*
* 输入参数  : void
* 输出参数  : 无
* 返 回 值  : 无
*
* 修改记录  :2011年11月29日   z00212992  创建
*****************************************************************************/
static void IPF_Assert(unsigned int u32ErrNo)
{
    /* 记录IPF所有寄存器的内容 */
     hisi_io_memcpy((void*)g_32IpfDebugReg, (void*)IPF_REGBASE_ADR, sizeof(g_32IpfDebugReg));

    /* 发起复位 */
    //BSP_MNTN_SystemError(BSP_MODU_IPF, u32ErrNo, 0, 0, 0);
	while(1)
	{
        __asm__ __volatile__("nop");
	}

    return;
}
static int last_kirq_proc_show(struct seq_file *m, void *v)
{
	char *mem = NULL ;
	struct queue *head = NULL;
	struct irq_info info;
	u32 count = num_online_cpus();
	unsigned int i = 0;

	if (NULL == last_kirq) {
		printk(KERN_ERR "%s: last_kirq is null\n", __FUNCTION__);
		return 0;
	}
	mem = (char *)vmalloc(EXCH_INT_SWITCH_SIZE);
	if (!mem) {
		printk("%s : failed to vmalloc memory\n",__FUNCTION__);
		return 0;
	}

	hisi_io_memcpy(mem, last_kirq, EXCH_INT_SWITCH_SIZE);

	for (i = 0; i < count; i++) {
		head = (struct queue *)(mem + g_irq_record_offset[i]);
		seq_printf(m, "IRQ Trace cpu[%d]\n", i);
		seq_printf(m, "in %u out %u size %u\n", head->in, head->out, head->max);

		do {
			if (_queue_out(head, (void *)&info, sizeof(struct irq_info)))
				break;

			if (EXCH_INT_EXIT == info.irq)
				seq_printf(m, "[ %10lu ][ %10lu ][ CPU %1d ] IRQ         OUT\n", \
							info.jiff, info.slice, info.cpu);
			else
				seq_printf(m, "[ %10lu ][ %10lu ][ CPU %1d ] IRQ [ %3d ] IN\n", \
							info.jiff, info.slice, info.cpu, info.irq);
		} while(1);

		seq_printf(m, "\n");
	}

	vfree(mem);

	return 0;
}
static int last_ktask_proc_show(struct seq_file *m, void *v)
{
	char *mem = NULL;
	struct queue *head = NULL;
	struct task_info info;
	u32 count = num_online_cpus();
	unsigned int i = 0;

	if (NULL == last_ktask) {
		printk(KERN_ERR "%s: last_ktask is null\n", __FUNCTION__);
		return 0;
	}

	mem = (char *)vmalloc(EXCH_TASK_SWITCH_SIZE);
	if (!mem) {
		printk("%s : failed to vmalloc memory\n",__FUNCTION__);
		return 0;
	}

	hisi_io_memcpy(mem, last_ktask, EXCH_TASK_SWITCH_SIZE);

	for (i = 0; i < count; i++) {
		head = (struct queue *)(mem + g_task_record_offset[i]);
		seq_printf(m, "TASK Trace cpu[%d]\n", i);
		seq_printf(m, "in %u out %u size %u\n", head->in, head->out, head->max);

		do {
			if (_queue_out(head, (void *)&info, sizeof(struct task_info)))
				break;

			seq_printf(m, "[ %10lu ][ %10lu ] PID [ %6u ][ %18s ] scheduled in CPU [ %u ]\n", \
						info.jiff, info.slice, info.pid, info.taskname, info.cpu);
		} while(1);

		seq_printf(m, "\n");
	}

	vfree(mem);

	return 0;
}
/*****************************************************************************
 函 数 名  : drv_hifi_load_sec
 功能描述  : Hifi按每段加载到内存
 输入参数  : img_head 镜像头指针
             img_buf 镜像读到内存的指针
             share_mem 存放非单次加载段信息的内存
 输出参数  : 无
 返 回 值  : int
             成功返回 0,失败返回 -1
 调用函数  :
 被调函数  :

 修改历史      :
  1.日    期   : 2012年8月30日
    作    者   : 刘慈红 lKF71598
    修改内容   : 新生成函数

*****************************************************************************/
int drv_hifi_load_sec(void *img_buf, unsigned int* share_mem)
{
    struct drv_hifi_sec_load_info *sec_info;
    struct drv_hifi_image_head    *head;
    struct drv_hifi_sec_addr      *dynamic_sec;
    unsigned long   iviraddr     = 0;
    unsigned long   iviraddr_src = 0;

    SOC_PERI_SCTRL_SC_DSP_SUBSYS_CTRL0_UNION runstall_val;

    unsigned int  dynamic_sec_num = 0;
    unsigned long sec_data_num    = 0;

    unsigned int i = 0;
    unsigned long sctrl_off = (unsigned long)HISI_VA_ADDRESS(SOC_PERI_SCTRL_BASE_ADDR);

    int ret;

    unsigned long share_mem_base_addr = HIFI_SHARE_ADDR_BASE;
    unsigned long data_addr_offset = sizeof(struct drv_hifi_sec_addr) * HIFI_DYNAMIC_SEC_MAX_NUM + sizeof(unsigned int) * 2;

    if (NULL == img_buf) {
        printk(KERN_INFO"drv_hifi_load_sec: img_buf is NULL.\n");
    	return BSP_RESET_ERROR;
    }

    head = (struct drv_hifi_image_head *)img_buf;

    printk("drv_hifi_load_sec: sections_num = %d, image_size = %u.\n",\
                head->sections_num,head->image_size);

    /* initial share memery */
    drv_hifi_init_mem(share_mem);

    drv_hifi_power_up();

    sec_info = (struct drv_hifi_sec_load_info*)share_mem;

    for (i = 0; i < head->sections_num; i++) {
        printk("drv_hifi_load_sec:head->sections_num = %d, i = %d.\n",head->sections_num,i);

        printk("drv_hifi_load_sec:des_addr = 0x%x, load_attib = %d, size = %u, sn = %d, src_offset = %u, type = %d\n", \
                          head->sections[i].des_addr,\
                          head->sections[i].load_attib,\
                          head->sections[i].size,\
                          head->sections[i].sn,\
                          head->sections[i].src_offset,\
                          head->sections[i].type);

        /* check the sections */
        ret = drv_hifi_check_sections(head, &(head->sections[i]));
        if (ret != 0) {
        	(void)printk("drv_hifi_load_sec:Invalid hifi section.\n");
            return BSP_RESET_ERROR;
        }

        /*如果段的目的地址是在0xC0000000到0xEFFFFFFF,则进行hifi虚实地址转换*/
        drv_hifi_phy2virt((unsigned int*)(&(head->sections[i].des_addr)));

        iviraddr = (unsigned long)(ioremap_wc((head->sections[i].des_addr),head->sections[i].size));
        printk("drv_hifi_load_sec00:iviraddr is 0x%p, phy addr is 0x%p.\n",(void*)iviraddr, (void*)head->sections[i].des_addr);
        if ((unsigned char)DRV_HIFI_IMAGE_SEC_LOAD_STATIC == head->sections[i].load_attib) {

            /* copy the sections */
            hisi_io_memcpy((void*)iviraddr,
                   (void*)((char*)head + head->sections[i].src_offset),
                   head->sections[i].size);

        } else if ((unsigned char)DRV_HIFI_IMAGE_SEC_LOAD_DYNAMIC == head->sections[i].load_attib) {

            dynamic_sec = &(sec_info->sec_addr_info[dynamic_sec_num]);
            printk("drv_hifi_load_sec02:dynamic step1, head = 0x%p dynamic_sec = 0x%p\n", (void*)head,  (void*)dynamic_sec);
            /* copy the sections */
            memcpy_local((void*)iviraddr,
                       (void*)((char*)head + head->sections[i].src_offset),
                       head->sections[i].size);
            printk("drv_hifi_load_sec02:dynamic step2\n");
            /* 填充段信息头 */
            dynamic_sec->sec_source_addr
                = (unsigned long)(&(sec_info->sec_data[sec_data_num]));
            dynamic_sec->sec_length    = head->sections[i].size;
            dynamic_sec->sec_dest_addr = head->sections[i].des_addr;

            printk("drv_hifi_load_sec02:dynamic step3\n");
            /* 拷贝段数据到共享内存 */
            iviraddr_src = dynamic_sec->sec_source_addr;
            printk("drv_hifi_load_sec02:iviraddr is 0x%p phy addr is 0x%p.\n",(void*)iviraddr_src, (void*)dynamic_sec->sec_source_addr);
            hisi_io_memcpy((void*)iviraddr_src,
               (void*)((char*)head + head->sections[i].src_offset),
                head->sections[i].size);

            /*保存share_mem的段数据源地址的物理地址,供mcu使用加载hifi*/
            dynamic_sec->sec_source_addr = share_mem_base_addr + data_addr_offset;
            data_addr_offset += head->sections[i].size;
            /* 更新段数据地址 */
            sec_data_num += head->sections[i].size;

            /* 更新非单次加载段的个数 */
            dynamic_sec_num++;

        } else if ((unsigned char)DRV_HIFI_IMAGE_SEC_UNLOAD == head->sections[i].load_attib) {

            /* 不需要加载的段,填充Hifi邮箱地址信息 */
            drv_hifi_fill_mb_info(iviraddr);

            printk("drv_hifi_load_sec:hifi unload sections.\n");
        } else {
            /*just for pclint*/
        }
        iounmap((void*)iviraddr);
    }

    /* 填充段信息头,非单次加载段的个数 */
    sec_info->sec_num = dynamic_sec_num;

    /*配置系统控制器拉高HiFi的输入信号RunStall*/
    runstall_val.value             = 0x0;
    runstall_val.reg.hifi_runstall = 0x0;

    writel(runstall_val.value, (void __iomem *)SOC_PERI_SCTRL_SC_DSP_SUBSYS_CTRL0_ADDR(sctrl_off));
    return OK;

}
static int __init dump_info_init(void)
{
	void * __iomem mem = NULL;
	struct dump_log *dump = NULL;
	struct queue *task_queue[NR_CPUS] = {0};
	struct queue *irq_queue[NR_CPUS] = {0};
	unsigned int i = 0;
	int irq_flag = 0, task_flag = 0;
	unsigned int saved_length = 0;
	u32 count = num_online_cpus();

	printk("%s ANDROID_DUMP_LOG_ADDR = %#x\n", __func__, ANDROID_DUMP_LOG_ADDR);
	mem = (void *)ioremap(ANDROID_DUMP_LOG_ADDR, ANDROID_DUMP_LOG_SIZE);
	if (NULL == mem) {
		printk(KERN_ERR "%s : failed to ioremap memory\n", __func__);
		return 0;
	}

	dump = (struct dump_log *)mem;

	for (i=0; i<count; i++) {
		irq_queue[i] = (struct queue*)(dump->irq_trace + g_irq_record_offset[i]);
		if (strncmp(irq_queue[i]->name, g_irq_trace_name[i], strlen(g_irq_trace_name[i]))) {
			printk(KERN_ERR "%s : irq trace cpu[%d] section header incorrect\n", __func__, i);
			printk(KERN_ERR "irq g:%s\n", g_irq_trace_name[i]);
			goto unmap;
		}
		/* 判断max值,防止队列头长度变换*/
		if (irq_queue[i]->max != (g_irq_record_len[i] - sizeof(struct queue))) {
			printk(KERN_ERR "%s : irq trace cpu[%d] section header, max length incorrect\n", __func__, i);
			goto unmap;
		}
		/* 判断head/tail值是否异常 */
		saved_length = MOD_SUB(irq_queue[i]->head, irq_queue[i]->tail, irq_queue[i]->max);
		if (saved_length%sizeof(struct irq_info) != 0) {
			printk(KERN_ERR "%s : irq trace cpu[%d] section header, head/tail incorrect\n", __func__, i);
			goto unmap;
		}
		if (irq_queue[i]->head != irq_queue[i]->tail) {
			irq_flag++;
		}

		task_queue[i] = (struct queue*)(dump->task_trace + g_task_record_offset[i]);
		if (strncmp(task_queue[i]->name, g_task_trace_name[i], strlen(g_task_trace_name[i]))) {
			printk(KERN_ERR "%s : task trace cpu[%d] section header incorrect\n", __func__, i);
			printk(KERN_ERR "task g:%s\n", g_task_trace_name[i]);
			goto unmap;
		}
		/* 判断max值,防止队列头长度变换*/
		if (task_queue[i]->max !=  (g_task_record_len[i] - sizeof(struct queue))) {
			printk(KERN_ERR "%s : task trace cpu[%d] section header, max length incorrect\n", __func__, i);
			goto unmap;
		}
		/* 判断head/tail值是否异常 */
		saved_length = MOD_SUB(task_queue[i]->head, task_queue[i]->tail, task_queue[i]->max);
		if (saved_length%sizeof(struct task_info) != 0) {
			printk(KERN_ERR "%s : task trace cpu[%d] section header, head/tail incorrect\n", __func__, i);
			goto unmap;
		}
		if (task_queue[i]->head != task_queue[i]->tail) {
			task_flag++;
		}
	}

	if (irq_flag) {
		last_kirq = (char *)vmalloc(EXCH_INT_SWITCH_SIZE);
		if (last_kirq) {
			hisi_io_memcpy(last_kirq, &dump->irq_trace[0], EXCH_INT_SWITCH_SIZE);
		}
	}

	if (task_flag) {
		last_ktask = (char *)vmalloc(EXCH_TASK_SWITCH_SIZE);
		if (last_ktask) {
			hisi_io_memcpy(last_ktask, &dump->task_trace[0], EXCH_TASK_SWITCH_SIZE);
		}
	}

unmap:
	iounmap(mem);
	return 0;
}