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; }