ssize_t INNODev_sync(struct INNODev_data *INNODevS, struct spi_message *message) { int ret; if(!flag_spi_ok){ inno_msg("Warning:spi_sync timeout,should not to use spi"); return -1; } // spin_lock_irq(&INNODevS->spi_lock); mutex_lock(&inno_mtkspi_mutex); //inno_msg("**s"); if (INNODevS->spi == NULL){ inno_err("spi ==NULL"); ret = -ESHUTDOWN; } else ret = spi_sync(INNODevS->spi, message); // inno_msg("**e"); mutex_unlock(&inno_mtkspi_mutex); // spin_unlock_irq(&INNODevS->spi_lock); /* if (ret == 0) { ret = message->status; if (ret == 0) ret = message->actual_length; } */ if(ret){ inno_err("spi_sync fail ret=%d,should check",ret); if(ret == -ETIME){ flag_spi_ok = 0; } } return ret; }
INNO_RET INNO_SPI_Mode(int mode) { struct mt_chip_conf* spi_par; spi_par =&spi_conf; if(!spi_par){ inno_err("spi config fail"); return INNO_GENERAL_ERROR; } if(1 == mode) { spi_par->com_mod = DMA_TRANSFER; //inno_msg("change to dma mode"); } else { spi_par->com_mod = FIFO_TRANSFER; //inno_msg("change to fifo mode"); } if(spi_setup(INNODev->spi)){ inno_err("spi_setup fail"); return INNO_GENERAL_ERROR; } return INNO_NO_ERROR; }
/* * Init and Deinit SPI interface * * Parameter: * enable <in> : enable or disable SPI interface * * Example: * INNO_SPI_Init(1); // Enable SPI interface * INNO_SPI_Init(0); // Enable SPI interface */ INNO_RET INNO_SPI_Init(int enable) { mutex_lock(&inno_spi_mutex); if(enable){ struct mt6575_chip_conf* spi_par; cmmb_spi_src_buffer_all = kmalloc(CMMB_SPI_INTERFACE_MAX_PKT_LENGTH_PER_TIMES,GFP_KERNEL); if(cmmb_spi_src_buffer_all== NULL){ inno_err("error kmalloc fail cmmb_spi_src_buffer_all"); mutex_unlock(&inno_spi_mutex); return INNO_GENERAL_ERROR; } INNODev->spi->controller_data =(void*)&spi_conf; spi_par =&spi_conf; if(!spi_par){ inno_err("spi config fail"); mutex_unlock(&inno_spi_mutex); return INNO_GENERAL_ERROR; } spi_par->setuptime = 15; spi_par->holdtime = 15; spi_par->high_time = 10; //10--6m 15--4m 20--3m 30--2m [ 60--1m 120--0.5m 300--0.2m] spi_par->low_time = 10; spi_par->cs_idletime = 20; spi_par->rx_mlsb = 1; spi_par->tx_mlsb = 1; spi_par->tx_endian = 0; spi_par->rx_endian = 0; spi_par->cpol = 0; spi_par->cpha = 0; spi_par->com_mod = DMA_TRANSFER; spi_par->pause = 0; spi_par->finish_intr = 1; spi_par->deassert = 0; if(spi_setup(INNODev->spi)){ inno_err("spi_setup fail"); mutex_unlock(&inno_spi_mutex); return INNO_GENERAL_ERROR; } #if 0 //check spi register spi_cfg0 = (int*)ioremap(0x700B2000,4); spi_cfg1 = (int*)ioremap(0x700B2000+0x4,4); spi_cmd = (int*)ioremap(0x700B2000+0x18,4); inno_msg("SPI CFG0:%08x, SPI_CFG1:%08x, SPI_CMD:%08x\n",*spi_cfg0,*spi_cfg1,*spi_cmd); iounmap(spi_cfg0); iounmap(spi_cfg1); iounmap(spi_cmd); #endif } else{ kfree(cmmb_spi_src_buffer_all); cmmb_spi_src_buffer_all =NULL; } mutex_unlock(&inno_spi_mutex); return INNO_NO_ERROR; }
bool spi_mode_setting(SPI_MODE_T pSetMode) { struct mt6575_chip_conf* spi_par; switch (pSetMode.mode) { case SPI_MODE_DEASSERT: // deassert mode is conflict with pause mode. spi_par= (struct mt6575_chip_conf*)(INNODev->spi->controller_data); if(!spi_par){ inno_err("config fail"); return -1; } if (pSetMode.bEnable){ // Note:pause mode and deassert mode can't use togther // Enable deassert mode. spi_par->deassert=1; } else{ spi_par->deassert=0; } spi_setup(INNODev->spi); break; case SPI_MODE_PAUSE: // pause mode is conflict with deassert mode. spi_par= (struct mt6575_chip_conf *)(INNODev->spi->controller_data); if(!spi_par){ inno_err("spi config fail"); return -1; } if (pSetMode.bEnable){ // ASSERT(spi_internal_state.pause_mode == false); // Enable deassert mode. spi_par->pause=1; } else{ spi_par->pause=0; } spi_setup(INNODev->spi); break; case SPI_MODE_GET_TICK: break; case SPI_MODE_ULTRA_HIGH: break; case SPI_MODE_SLOW_DOWN: break; default: //ASSERT(0); break; } return 0; }
static void check_block_thread(void *arg) { inno_msg("runing for check block status\n"); int oldcount=intCount; msleep(1000*60); //wait 60s for to get mfs int version=0; INNO_GetFirmwareVersion(&version); inno_msg("version =%d",version); while(1){ if (intCount ==oldcount) { inno_msg("error over 20 second no interrup,then gerversion"); #if 1 //xingyu debug get firmware the first 8 bytes inno_msg("INNO_GetFirmwareBytes for get the first 8 bytes"); int ret =INNO_GetFirmwareBytes(); if(ret != INNO_NO_ERROR) { inno_err("INNO_GetFirmwareBytes fail"); } #else INNO_GetFirmwareVersion(&version); inno_msg("version =%d",version); #endif break; } else oldcount = intCount; msleep(1000*10); } msleep(1000*3); inno_msg("exit"); }
/* * Write CMD and read response. between the two transfer need release CS one times * * Parameter: * cmd <in> : the data write to SPI bus * rsp < out> : the data of the chip response * */ INNO_RET INNO_SPI_Write_cmd_rsp(unsigned char cmd,unsigned char *rsp) { INNO_RET ret = INNO_NO_ERROR; // cmmb_spi_src_buffer_all[0]=cmd; ret =INNO_SPI_Write_One_Byte_NoCS(cmd); if(ret != INNO_NO_ERROR){ inno_err("INNO_SPI_Write_One_Byte_NoCS fail"); return ret; } udelay(100); ret =INNO_SPI_Read_One_Byte_NoCS(rsp); if(ret != INNO_NO_ERROR){ inno_err("INNO_SPI_Read_One_Byte_NoCSfail"); return ret; } return INNO_NO_ERROR; }
static ssize_t lgx_read(struct file* filp, char* buffer, size_t count, loff_t* offset) { DECLARE_WAITQUEUE(wait, current); int ret = 0; int err = 0; //int i=0; struct inno_lgx* lgx = (struct inno_lgx*)filp->private_data; struct inno_buffer* inno_buf = &lgx->inno_buffer; //char temp[5]; inno_dbg("[CMMB]%s+\n",__FUNCTION__); add_wait_queue(&lgx->read_wait, &wait); while(1){ err = -ERESTARTSYS; if(signal_pending(current)) break; if(inno_buf->valid && inno_buf->own_id==lgx->ids->id) { down(&inno_buf->sem); inno_dbg("inno_buf->valid_size: %d,count: %d\n",inno_buf->valid_size,count); ret = min(inno_buf->valid_size, count); if(ret<=0){ inno_err("inno_buf->valid_size <0"); up(&inno_buf->sem); return 0; } err = copy_to_user(buffer, &(inno_buf->own_id), 1); err = copy_to_user(buffer+1, inno_buf->start, ret); #if 0 //check copy to user mfs memcpy(temp,inno_buf->start, 5); inno_dbg("check copy to user mfs len:%d,buf\n",ret); for(i=0;i<6;i++) printk(" %02x",temp[i]); printk("\n"); #endif inno_buf->valid = 0; up(&inno_buf->sem); //inno_msg("[lgx_read] dump to /local/log/%d.cmmb, size:%d\n",ind_log,ret); //write_file(inno_buf->start, ret); break; } set_current_state(TASK_INTERRUPTIBLE); err = -EAGAIN; if(filp->f_flags & O_NONBLOCK) break; schedule(); } set_current_state(TASK_RUNNING); remove_wait_queue(&lgx->read_wait, &wait); inno_dbg("[CMMB]%s-",__FUNCTION__); return ret; }
//static int lgx_ioctl(struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg) static long lgx_ioctl(struct file* filp, unsigned int cmd, unsigned long arg) { long retval = 0; long val; // inno_device_t* inno_dev = &g_inno_dev; /* FIHTDC, ALXiao, add cmmb ftm test function, 20101008 { */ if(_IOC_TYPE(cmd) != INNO_IOC_MAGIC) return -ENOTTY; /* FIHTDC, ALXiao, add cmmb ftm test function, 20101008 } */ inno_msg("[CMMB]%s+",__FUNCTION__); // ASUS_BSP+++ JimmyLin "[CMMB] avoid UI hang" // msleep(100); // ASUS_BSP--- switch(cmd){ case INNO_STOP_POLL: // stop polling,avoid poll block,then driver can't deinit { cancle_wait =(u8)arg; inno_msg("[lgx_ioctl] INNO_STOP_POLL cancle_wait =%d",cancle_wait); if(cancle_wait){ struct inno_lgx* lgx0 = g_inno_dev.lgxs[0]; struct inno_lgx* lgx1 = g_inno_dev.lgxs[1]; struct inno_lgx* lgx2 = g_inno_dev.lgxs[2]; struct inno_lgx* lgx3 = g_inno_dev.lgxs[3]; wake_up_interruptible(&lgx0->read_wait); wake_up_interruptible(&lgx1->read_wait); wake_up_interruptible(&lgx2->read_wait); wake_up_interruptible(&lgx3->read_wait); } break; } case INNO_MEMSET_MFS: // memset mfs buffer before fetch mfs data { flag_memset= (u8)arg; inno_msg("[lgx_ioctl] INNO_MEMSET_MFS flag_memset =%d",flag_memset); break; } #if 0 case INNO_GET_INTR_TYPE: //no use inno_msg("[lgx_ioctl] INNO_GET_INTR_TYPE"); val = inno_dev->cfg.intr_type; put_user(val, (long*)arg); break; case INNO_READ_REG: //no use { struct inno_reg_data* reg_data; inno_msg("[lgx_ioctl] INNO_READ_REG"); reg_data = kmalloc(sizeof(struct inno_reg_data), GFP_KERNEL); retval = copy_from_user(reg_data, (void*)arg, sizeof(struct inno_reg_data)); if(retval == 0){ /* down(&inno_iic_mutex); g_inno_dev.i2c_driver->read(reg_data->reg, (unsigned char*)®_data->data); up(&inno_iic_mutex); retval = copy_to_user((void*)arg, reg_data, sizeof(struct inno_reg_data)); */ } kfree(reg_data); break; } case INNO_WRITE_REG: //no use { struct inno_reg_data* reg_data; inno_msg("[lgx_ioctl] INNO_WRITE_REG"); reg_data = kmalloc(sizeof(struct inno_reg_data), GFP_KERNEL); retval = copy_from_user(reg_data, (void*)arg, sizeof(struct inno_reg_data)); if(retval == 0){ /* down(&inno_iic_mutex); g_inno_dev.i2c_driver->write(reg_data->reg, reg_data->data); up(&inno_iic_mutex); retval = copy_to_user((void*)arg, reg_data, sizeof(struct inno_reg_data)); */ } kfree(reg_data); break; } case INNO_MMIS_READ: //no use { u8 reg = (u8)arg; u8 value; inno_msg("[lgx_ioctl] INNO_MMIS_READ"); mutex_lock(&inno_spi_mutex); inno_spi_drive_cs(0); g_inno_dev.spi_driver->write(®, 1); inno_spi_drive_cs(1); inno_spi_drive_cs(0); g_inno_dev.spi_driver->read(&value, 1); inno_spi_drive_cs(1); retval = value; mutex_unlock(&inno_spi_mutex); break; } case INNO_MMIS_CMD: //no use { u8 value = (u8)arg; inno_msg("[lgx_ioctl] INNO_MMIS_CMD"); mutex_lock(&inno_spi_mutex); inno_spi_drive_cs(0); g_inno_dev.spi_driver->write(&value,1); inno_spi_drive_cs(1); mutex_unlock(&inno_spi_mutex); break; } case INNO_MMIS_WRITE: //pass value mmis_cmd|value no use { u8 cmd, value; inno_msg("[lgx_ioctl] INNO_MMIS_WRITE"); val = arg; cmd = (val & 0xFF00)>>8; value = (val & 0x00FF); mutex_lock(&inno_spi_mutex); inno_spi_drive_cs(0); g_inno_dev.spi_driver->write(&cmd, 1); inno_spi_drive_cs(1); inno_spi_drive_cs(0); g_inno_dev.spi_driver->write(&value, 1); inno_spi_drive_cs(1); mutex_unlock(&inno_spi_mutex); break; } case INNO_SCAN_FREQUENCY: // if228 not support scan function no use { struct inno_freq_scan_area* scan_area; inno_msg("[lgx_ioctl] INNO_SCAN_FREQUENCY"); scan_area = kmalloc(sizeof(struct inno_freq_scan_area), GFP_KERNEL); retval = copy_from_user(scan_area, (void*)arg, sizeof(struct inno_freq_scan_area)); if(retval == 0) ;//retval = inno_scan_frequency(scan_area->start, scan_area->end); kfree(scan_area); break; } case INNO_SCAN_FREQUENCY_DOT: // if228 not support scan function no use { struct inno_freq_scan_area* scan_area; inno_msg("[lgx_ioctl] INNO_SCAN_FREQUENCY_DOT"); scan_area = kmalloc(sizeof(struct inno_freq_scan_area), GFP_KERNEL); retval = copy_from_user(scan_area, (void*)arg, sizeof(struct inno_freq_scan_area)); if(retval == 0) ;//retval = inno_scan_frequency_dot((u8)scan_area->start, (u8)scan_area->end); kfree(scan_area); break; } #endif #if 0 case INNO_SET_FREQUENCY: // unit:MHZ { inno_msg("[lgx_ioctl] INNO_SET_FREQUENCY"); retval = copy_from_user(&val, (void*)arg, sizeof(unsigned long)); inno_msg("[inno-ioctl]: INNO_SET_FREQUENCY, val=%ld", val); if(retval == 0) retval = inno_set_frequency((u16)val); break; } #endif case INNO_SET_FREQUENCY_DOT: { inno_msg("[lgx_ioctl] INNO_SET_FREQUENCY_DOT"); retval = copy_from_user(&val, (void*)arg, sizeof(unsigned long)); inno_msg("[inno-ioctl]: INNO_SET_FREQUENCY_DOT, val=%ld", val); if(retval == 0) retval = inno_set_frequency_dot((u8)val); if(retval) retval = -1; break; } #if 0 case INNO_SET_CP_TYPE: // no use { inno_msg("[lgx_ioctl] INNO_SET_CP_TYPE"); retval = copy_from_user(&val, (void*)arg, sizeof(unsigned long)); if(retval == 0) retval = inno_set_cp_type((u8)val); break; } #endif case INNO_GET_CHANNEL_CONFIG: { struct inno_channel_config* cfg; inno_msg("[lgx_ioctl] INNO_GET_CHANNEL_CONFIG"); cfg = kmalloc(sizeof(struct inno_channel_config), GFP_KERNEL); if(!cfg ){ inno_err("kmalloc cfg ==NULL"); retval =-1; break; } retval = copy_from_user(cfg, (void*)arg, sizeof(struct inno_channel_config)); if(retval == 0) retval =INNO_GetChannelConfig(cfg); if(!retval){ retval = copy_to_user((void*)arg, cfg, sizeof(struct inno_channel_config)); inno_msg("[lgx_ioctl] INNO_Get_CHANNEL_CONFIG:cid(%d),close(%d),start(%d),count(%d),ldpc(%d),itlv(%d),rs(%d),mod(%d) " ,cfg->ch_id,cfg->ch_close,cfg->ts_start,cfg->ts_count,cfg->ldpc,cfg->itlv,cfg->rs,cfg->modulate); } else retval =-1; kfree(cfg); break; } case INNO_SET_CHANNEL_CONFIG: { struct inno_channel_config* cfg; cfg = kmalloc(sizeof(struct inno_channel_config), GFP_KERNEL); if(!cfg ){ inno_err("kmalloc cfg ==NULL"); retval =-1; break; } inno_msg("[inno-ioctl]: INNO_SET_CHANNEL_CONFIG"); retval = copy_from_user(cfg, (void*)arg, sizeof(struct inno_channel_config)); inno_msg("[lgx_ioctl] INNO_SET_CHANNEL_CONFIG:cid(%d),close(%d),start(%d),count(%d),ldpc(%d),itlv(%d),rs(%d),mod(%d),subframeID(%d) " ,cfg->ch_id,cfg->ch_close,cfg->ts_start,cfg->ts_count,cfg->ldpc,cfg->itlv,cfg->rs,cfg->modulate,cfg->subframe_ID); if(retval == 0) retval = inno_set_channel_config(cfg); kfree(cfg); break; } case INNO_GET_SYS_STATE: { struct inno_sys_state* sys_state; inno_msg("[lgx_ioctl] INNO_GET_SYS_STATE"); sys_state = kmalloc(sizeof(struct inno_sys_state), GFP_KERNEL); if(!sys_state){ inno_err("kmalloc fail sys_state = null"); retval =1; break; } retval = copy_from_user(sys_state, (void*)arg, sizeof(struct inno_sys_state)); if(retval == 0) retval = inno_get_system_state(sys_state); if(!retval) retval = copy_to_user((void*)arg, sys_state, sizeof(struct inno_sys_state)); else retval = -1; kfree(sys_state); break; } #if 0 // no use case INNO_SET_PM: // no use { struct inno_pm_control* pmctl; inno_msg("[lgx_ioctl] INNO_SET_PM"); pmctl = kmalloc(sizeof(struct inno_pm_control), GFP_KERNEL); retval = copy_from_user(pmctl, (void*)arg, sizeof(struct inno_pm_control)); if(retval == 0) retval = inno_set_pm(pmctl); kfree(pmctl); break; } case INNO_GET_FW_VER: //no use { struct inno_fw_ver ver = {0, 0}; inno_msg("[lgx_ioctl] INNO_GET_FW_VER"); inno_get_fireware_version(&ver); retval = copy_to_user((void*)arg, &ver, sizeof(struct inno_fw_ver)); break; } #endif case INNO_FW_DOWNLOAD: { int retry=0; // struct INNOCHAR_FW_DATA *up = (struct INNOCHAR_FW_DATA *)arg; unsigned char* fwbuf =NULL; //inno_msg("check up->fw_size =%d",up->fw_size); //unsigned char* fwbuf = kmalloc(up->fw_size, GFP_KERNEL| GFP_DMA); inno_msg("download using h file in kernel"); if(FIRMWARE_BUF_DATA_SIZE < 40960) fwbuf =3*INNO_BUFFER_SIZE+g_inno_buffer; else{ inno_err("fw_size >40k fail"); retval = -1; break; } //int pass=0; //INNO_RET ret_tmp = INNO_NO_ERROR; inno_msg("[lgx_ioctl] INNO_FW_DOWNLOAD"); memset(fwbuf,0,FIRMWARE_BUF_DATA_SIZE); // memset(fwbuf, 0, up->fw_size); // retval = copy_from_user(fwbuf, (void*)up->fwbuf, up->fw_size); memcpy(fwbuf,fw_buf,FIRMWARE_BUF_DATA_SIZE); #if 0 //check copy fw int i; inno_msg("check copy_from_user fw_bu"); for(i=0;i<4;i++) inno_msg(" %02x",fwbuf[i]); inno_msg("end"); for(i=0;i<4;i++) inno_msg(" %02x",fwbuf[up->fw_size-i-1]); inno_msg("end"); //mtk_spi_test(); //break; //inno_msg("******** sleep 1s for download fw"); //msleep(5000); #endif if(retval == 0){ for(retry=0;retry<1;retry++){ retval = inno_download_fireware(fwbuf,FIRMWARE_BUF_DATA_SIZE); if(retval){ inno_err("firmware download failed retval =%d!",(int)retval); retval = -EIO; continue; } #if 0 // mdelay(100); //no need delay,refer to innofidei code inno_msg("inno_download_fireware OK,then check FW"); ret_tmp = INNO_CheckFWDownload(fw_buf,up->fw_size,&pass); if(ret_tmp){ inno_err("INNO_CheckFWDownload fail ret =%d",ret_tmp); retval = -1; continue; } if(!pass){ inno_err("FW Download Fail, checksum no pass =%d!",pass); } else{ inno_msg("INNO_CheckFWDownload success"); break; } #else else{ inno_msg("inno_download_fireware ok"); break; } #endif } if(retry ==5){ inno_err("inno_download_fireware timeout"); retval = -1; } } //kfree(fwbuf); break; } #if 0 // no use case INNO_UPDATE_FW: // no use { inno_msg("[lgx_ioctl] INNO_UPDATE_FW"); inno_update_fireware(); break; } #endif case INNO_GET_FW_BYTES: { int ret =INNO_Chip_errHandle(); if(ret != INNO_NO_ERROR) { inno_err("INNO_Chip_errHandle fail"); retval =-1; } break; } case INNO_ENABLE_IRQ: inno_msg("[lgx_ioctl] INNO_ENABLE_IRQ"); break; case INNO_DISABLE_IRQ: inno_msg("[lgx_ioctl] INNO_DISABLE_IRQ"); break; #if 0 case INNO_SHUTDOWN_IRQ: // no use { //NOTE: cleanup all (i2c, spi, power down) mannually while, NOT the device itself inno_msg("[lgx_ioctl] INNO_SHUTDOWN_IRQ"); if(!g_inno_dev.use_count) { inno_msg("shutdown innodev. %d", g_inno_dev.use_count); innodev_shutdown(&g_inno_dev); g_inno_dev.use_count = 0; //unrefer all reference counter } break; } case INNO_GET_BUFFERLEN: //xingyu getbufferlen val = INNO_BUFFER_SIZE; put_user(val, (long*)arg); inno_msg("[lgx_ioctl] INNO_GET_BUFFERLEN:%ld",val); break; #endif //////////////////////////// uam /////////////////////////// case INNO_UAM_TRANSFER: { struct inno_uam_parameter *uam_para_tmp; inno_msg("[lgx_ioctl] INNO_UAM_TRANSFER"); uam_para_tmp = kmalloc(sizeof(struct inno_uam_parameter), GFP_KERNEL); if(!uam_para_tmp){ inno_msg("uam_para_tmp kmalloc fail"); retval = -1; break; } retval = copy_from_user(uam_para_tmp, (void*)arg, sizeof(struct inno_uam_parameter)); if(retval == 0) retval = inno_uam_transfer(uam_para_tmp); if(!retval) retval = copy_to_user((void*)arg, uam_para_tmp, sizeof(struct inno_uam_parameter)); else retval = -1; kfree(uam_para_tmp); uam_para_tmp=NULL; } break; case INNO_UAM_INIT: inno_msg("[lgx_ioctl] INNO_UAM_INIT"); retval = inno_init_uam(); if(retval !=0){ retval =-1; //tell user space fail inno_err("init uam fail"); } break; case INNO_SEND_UAM_CMD: { unsigned char* cmd_tmp0; struct uam_cmd_par* up0 = (struct uam_cmd_par*)arg; inno_msg("[lgx_ioctl] INNO_SEND_UAM_CMD"); cmd_tmp0= kmalloc(up0->len, GFP_KERNEL); if(cmd_tmp0 == NULL){ inno_msg("cmd_tmp0 kmalloc fail"); retval = -1; break; } memset(cmd_tmp0, 0, up0->len); retval = copy_from_user(cmd_tmp0, (void*)up0->cmd, up0->len); if(retval ==0) retval = INNO_Send_UAM_Cmd(cmd_tmp0,up0->len); if(retval) retval = -1; kfree(cmd_tmp0); cmd_tmp0 =NULL; } break; case INNO_SEND_CMD: { unsigned char *cmd_tmp; inno_msg("[lgx_ioctl] INNO_SEND_CMD"); cmd_tmp = kmalloc(8,GFP_KERNEL); if(!cmd_tmp){ inno_err("kmalloc fail,cmd_tmp==null"); retval=-1; break; } retval = copy_from_user(cmd_tmp, (void*)arg, 8); if(retval ==0){ mutex_lock(&inno_spi_mutex); //xingyu 2011-06-24 retval = INNO_Send_Cmd(cmd_tmp); mutex_unlock(&inno_spi_mutex); } if(retval) retval =-1; kfree(cmd_tmp); cmd_tmp =NULL; break; } #if 0 // no use case INNO_UAM_SET_CMD: //no use //inno_msg("we are in kernel ioctl^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); inno_msg("[lgx_ioctl] INNO_UAM_SET_CMD"); retval = copy_from_user(&uam_para.pBufIn, (void*)arg, uam_cmd_len); if(retval == 0){ inno_dbg("IOCTL: INNO_UAM_TRANSFER"); } uam_para.bufInLen = uam_cmd_len; inno_uam_transfer(&uam_para); break; case INNO_UAM_SET_CMDL: // no use inno_msg("[lgx_ioctl] INNO_UAM_SET_CMDL"); retval = copy_from_user((void *)&uam_cmd_len, (void*)arg, sizeof(unsigned int)); inno_dbg("INNO_UAM_SET_CMDL - uam_cmd_len: %d", uam_cmd_len); break; case INNO_UAM_READ_RES: // no use inno_msg("[lgx_ioctl] INNO_UAM_READ_RES"); inno_dbg("INNO_UAM_READ_RES - return response len: %d", uam_para.pBufOutLen); return copy_to_user((void *)arg, uam_para.pBufOut, uam_para.pBufOutLen); case INNO_UAM_READ_STATUS: // no sue inno_msg("[lgx_ioctl] INNO_UAM_READ_STATUS"); inno_dbg("INNO_UAM_READ_STATUS - return status: 0x%x", uam_para.sw); return put_user(uam_para.sw, (unsigned long *)arg); case INNO_UAM_READ_STATUS_LEN: // no use inno_msg("[lgx_ioctl] INNO_UAM_READ_STATUS_LEN"); inno_dbg("INNO_UAM_READ_STATUS_LEN - return response len: 0x%x", uam_para.pBufOutLen); return put_user(uam_para.pBufOutLen, (unsigned long *)arg); #endif default: return -ENOTTY; }
/*==================================== * character device file operations *===================================*/ static int lgx_open(struct inode* inode, struct file* filp) { struct inno_lgx* lgx; unsigned int lg_num = iminor(inode); int i; inno_msg("+++++++++++++++++++++++++++++++++++++++++"); inno_msg("CMMB IF208 open [%s]", lgx_ids_table[lg_num].name); inno_msg("+++++++++++++++++++++++++++++++++++++++++"); if(lg_num >= LG_END){ inno_err("minor error, should be [%d-%d]", LG0, UAM); return -1; } if(g_inno_dev.lgxs[lg_num]){ //already opened, just increase reference count down(&g_inno_dev.lgxs[lg_num]->sem); g_inno_dev.lgxs[lg_num]->use_count++; //g_inno_dev.lgxs[lg_num]->use_count = 1; inno_msg("reopen"); up(&g_inno_dev.lgxs[lg_num]->sem); filp->private_data = g_inno_dev.lgxs[lg_num]; return 0; } /* OK, it's not open, Create it */ lgx = (struct inno_lgx*)kmalloc(sizeof(struct inno_lgx), GFP_KERNEL); if(!lgx){ inno_err("kmalloc lgx ==NULL"); return -1; } else memset(lgx, 0, sizeof(struct inno_lgx)); for(i=0; lgx_ids_table[i].name!=NULL; i++){ if(lg_num == lgx_ids_table[i].id){ lgx->ids = &lgx_ids_table[i]; break; } } //allocat memory for get mfs file if (lgx_alloc_buffer(lgx)){ kfree(lgx); lgx = NULL; return -1; } //********** global flag set ******************// cancle_wait = 0; //xingyu 0328 add solve poll wait flag_memset = 0; // memset the bitstream buffer once_closeirq=0; // control close irq lgx->use_count = 1; sema_init(&lgx->sem,1); init_waitqueue_head(&lgx->read_wait); #ifndef UAM_COMPLETE init_waitqueue_head(&lgx->uam_wait); #else // if(lg_num==2){ // open uam if(strcmp(lgx->ids->name, "UAM") == 0){ //if(lgx->ids->name =="UAM") { //xing 0922 use uamcomplete function inno_msg("uam_complete init"); init_completion(&lgx->uam_complete); } #endif g_inno_dev.lgxs[lg_num] = lgx; //inno_msg("open file for inno_num: %d\n", lg_num); if( innodev_startup(&g_inno_dev) ){ inno_err("startup fail, free lgx"); g_inno_dev.lgxs[lg_num] = NULL; lgx_free_buffer(lgx); kfree(lgx); return -1; } filp->private_data = lgx; #ifdef _check_block_time //printk rxbuf static int onetime =0; if (onetime ==0){ // when open file create better than module init for time onetime++; inno_msg("use thread to watch the block time"); check_block_wq = create_singlethread_workqueue("siano work wq"); INIT_WORK(&check_block_work,check_block_thread); queue_work(check_block_wq,&check_block_work); } #endif inno_msg("use single thread for workqueue"); return 0; }
static int lgx_alloc_buffer(struct inno_lgx *lgx) { //int i,j; //int page_num; //struct page *page = NULL; int i; struct inno_buffer *inno_buf = &lgx->inno_buffer; //int ret = 0; memset(inno_buf, 0, sizeof(struct inno_buffer)); sema_init(&inno_buf->sem,1); down(&inno_buf->sem); // alloc buffer #if 0 //xingyu buffer issue page_num = PAGE_ALIGN(INNO_BUFFER_SIZE) / PAGE_SIZE; inno_buf->pages = (struct page **)kzalloc(page_num * sizeof(struct page *), GFP_KERNEL); if (!inno_buf->pages) { inno_err("lgx_alloc_buffer:No enough memory"); ret = -ENOMEM; goto alloc_node_error; } for (i = 0; i < page_num; i++) { page = alloc_page(GFP_KERNEL); if (!page) { inno_err("lgx_alloc_buffer:No enough page"); ret = -ENOMEM; goto alloc_pages_error; } //SetPageReserved(page); inno_buf->pages[i] = page; } inno_buf->page_num = page_num; inno_buf->bufsize = page_num * PAGE_SIZE; inno_buf->vaddr = vmap(inno_buf->pages, page_num, VM_MAP, PAGE_KERNEL); /* check if the memory map is OK. */ if (!inno_buf->vaddr) { inno_err("lgx_alloc_buffer:vmap() failure"); ret = -EFAULT; goto vmap_error; } memset(inno_buf->vaddr, 0, inno_buf->bufsize); inno_buf->start = inno_buf->vaddr; #else #ifndef _buffer_global // buffer alloc modify xingyu 0714 inno_buf->vaddr = kmalloc(INNO_BUFFER_SIZE, GFP_KERNEL| GFP_DMA); if(inno_buf->vaddr == NULL || (int)inno_buf->vaddr %4 !=0){ inno_err("inno_buf->vaddr kmalloc fail"); up(&inno_buf->sem); return -1; } #else for(i=0; lgx_ids_table[i].name!=NULL; i++){ if(lgx->ids == &lgx_ids_table[i]){ inno_buf->vaddr =i*INNO_BUFFER_SIZE+g_inno_buffer; inno_msg("use global mem"); break; } } #endif inno_buf->start = inno_buf->vaddr; inno_buf->bufsize = INNO_BUFFER_SIZE; #endif up(&inno_buf->sem); return 0; #if 0 //xingyu buffer issue //vmap_error: //alloc_pages_error: for (j = 0; j < i; j++) { page = inno_buf->pages[j]; //ClearPageReserved(page); __free_page(page); } kfree(inno_buf->pages); //alloc_node_error: return ret; #endif }