static int __ccif_v1_write_phy_ch_data(ccif_t* ccif, unsigned int buf[], int retry_en) { int ret = 0; unsigned int busy; unsigned long flag; unsigned int retry_count = 200; unsigned int ch; ccif_msg_t *tx_msg; int md_id = ccif->m_md_id; CCCI_FUNC_ENTRY(md_id); if(retry_en == 0) retry_count = 1; do{ spin_lock_irqsave(&ccif->m_lock, flag); busy=ccci_read32(CCIF_BUSY(ccif->m_reg_base)); ch = ccif->m_tx_idx; if (busy&(1<<ch)) { ret = -CCCI_ERR_CCIF_NO_PHYSICAL_CHANNEL; if (busy != 0xff) { CCCI_DBG_MSG(md_id, "cci", "Wrong Busy value: 0x%X\n", busy); } spin_unlock_irqrestore(&ccif->m_lock,flag); udelay(1); retry_count--; } else { ccci_write32(CCIF_BUSY(ccif->m_reg_base), 1<<ch); ccif->m_tx_idx++; ccif->m_tx_idx &= (CCIF_STD_V1_MAX_CH_NUM-1); //spin_unlock_irqrestore(&ccif->m_lock,flag); //mb(); // Note here, make sure data has write to memory be really send tx_msg = (ccif_msg_t*)(CCIF_TXCHDATA(ccif->m_reg_base)); ccci_write32(&(tx_msg[ch].data[0]), buf[0]); ccci_write32(&(tx_msg[ch].data[1]), buf[1]); ccci_write32(&(tx_msg[ch].channel), buf[2]); ccci_write32(&(tx_msg[ch].reserved), buf[3]); //mb(); ccci_write32(CCIF_TCHNUM(ccif->m_reg_base), ch); spin_unlock_irqrestore(&ccif->m_lock,flag); ret = sizeof(ccif_msg_t); break; } }while(retry_count>0); if(lg_ch_tx_debug_enable[md_id] & (1<< buf[2])) CCCI_MSG_INF(md_id, "cci", "[TX]: %08X, %08X, %02d, %08X (%02d)\n", buf[0], buf[1], buf[2], buf[3], ch); return ret; }
static void __ccif_v1_dis_intr(ccif_t* ccif) { unsigned long flag; CCCI_FUNC_ENTRY(ccif->m_md_id); spin_lock_irqsave(&ccif->m_lock,flag); if(ccif->m_irq_dis_cnt == 0) { disable_irq(ccif->m_irq_id); ccif->m_irq_dis_cnt++; } spin_unlock_irqrestore(&ccif->m_lock,flag); }
static int __ccif_v1_en_intr(ccif_t* ccif) { unsigned long flag; CCCI_FUNC_ENTRY(ccif->m_md_id); spin_lock_irqsave(&ccif->m_lock,flag); if(ccif->m_irq_dis_cnt) { enable_irq(ccif->m_irq_id); ccif->m_irq_dis_cnt--; } spin_unlock_irqrestore(&ccif->m_lock,flag); return 0; }
int ccci_logic_ctlb_init(int md_id) { int ret = 0; ccif_t *ccif; logic_channel_info_t *ch_info; int ch_id, ch_attr, i; logic_dispatch_ctl_block_t *ctl_b; char ccci_name[CCCI_WAKEUP_LOCK_NAME_LEN]; ccif_hw_info_t ccif_hw_inf; CCCI_FUNC_ENTRY(md_id); // Channel number check if((sizeof(logic_ch_static_info_tab)/sizeof(logic_channel_static_info_t)) != CCCI_MAX_CH_NUM) { CCCI_MSG_INF(md_id, "cci", "%s: channel max number mis-match fail\n", __FUNCTION__); return -CCCI_ERR_CHANNEL_NUM_MIS_MATCH; } // Allocate ctl block memory ctl_b = (logic_dispatch_ctl_block_t*)kzalloc(sizeof(logic_dispatch_ctl_block_t), GFP_KERNEL); if(ctl_b == NULL) { CCCI_MSG_INF(md_id, "cci", "%s: alloc memory fail for logic_dispatch_ctlb\n", __FUNCTION__); return -CCCI_ERR_ALLOCATE_MEMORY_FAIL; } logic_dispatch_ctlb[md_id] = ctl_b; // Get CCIF HW info if(get_ccif_hw_info(md_id, &ccif_hw_inf) < 0) { CCCI_MSG_INF(md_id, "cci", "%s: get ccif%d hw info fail\n", __FUNCTION__, md_id+1); ret = -CCCI_ERR_CCIF_GET_HW_INFO_FAIL; goto _ccif_instance_create_fail; } // Create ccif instance ccif = ccif_create_instance(&ccif_hw_inf, ctl_b, md_id); if(ccif == NULL) { CCCI_MSG_INF(md_id, "cci", "%s: create ccif instance fail\n", __FUNCTION__); ret = -CCCI_ERR_CREATE_CCIF_INSTANCE_FAIL; goto _ccif_instance_create_fail; } ccif->ccif_init(ccif); ctl_b->m_ccif = ccif; // Initialize logic channel and its kfifo///???anny // Step1, set all runtime channel id to CCCI_INVALID_CH_ID means default state // So, even if static channel table is out of order, we can make sure logic_dispatch_ctlb's channel // table is in order for(i = 0; i < CCCI_MAX_CH_NUM; i++) { ch_info = &ctl_b->m_logic_ch_table[i]; ch_info->m_ch_id = CCCI_INVALID_CH_ID; } // Step2, set all runtime channel info according to static channel info, make it in order for(i = 0; i < CCCI_MAX_CH_NUM; i++) { ch_id = logic_ch_static_info_tab[i].m_ch_id; ch_info = &ctl_b->m_logic_ch_table[ch_id]; if (ch_info->m_ch_id != CCCI_INVALID_CH_ID) { CCCI_MSG_INF(md_id, "cci", "[Error]%s: ch%d has registered\n", __FUNCTION__, ch_id); ret = -CCCI_ERR_REPEAT_CHANNEL_ID; goto _ccif_logic_channel_init_fail; } else { ch_info->m_ch_id = ch_id; ch_info->m_attrs = logic_ch_static_info_tab[i].m_attrs; ch_info->m_ch_name = logic_ch_static_info_tab[i].m_ch_name; ch_info->m_call_back = NULL; if(logic_ch_static_info_tab[i].m_kfifo_size) { if (0 != kfifo_alloc(&ch_info->m_kfifo, sizeof(ccif_msg_t)*logic_ch_static_info_tab[i].m_kfifo_size, GFP_KERNEL)) { CCCI_MSG_INF(md_id, "cci", "%s: alloc kfifo fail for %s(ch%d) \n", \ __FUNCTION__, ch_info->m_ch_name, ch_id); ch_info->m_kfifo_ready = 0; ret = CCCI_ERR_ALLOCATE_MEMORY_FAIL; goto _ccif_logic_channel_init_fail; } else { ch_info->m_kfifo_ready = 1; ch_info->m_md_id = md_id; } } else { ch_info->m_kfifo_ready = 0; } spin_lock_init(&ch_info->m_lock); } //initial channel recording info if(logic_ch_static_info_tab[i].m_attrs&L_CH_ATTR_TX) ch_attr = CCCI_LOG_TX; else ch_attr = CCCI_LOG_RX; statistics_init_ch_dir(md_id, ch_id, ch_attr); } // Init logic_dispatch_ctlb tasklet_init(&ctl_b->m_dispatch_tasklet,__logic_layer_tasklet,(unsigned long)ctl_b); ctl_b->m_has_pending_data = 0; ctl_b->m_freezed = 0; ctl_b->m_running = 0; //ctl_b->m_privilege = MD_BOOT_STAGE_0; ctl_b->m_md_id = md_id; snprintf(ccci_name, CCCI_WAKEUP_LOCK_NAME_LEN, "ccci_wk%d", md_id); wake_lock_init(&ctl_b->m_wakeup_wake_lock, WAKE_LOCK_SUSPEND, ccci_name); ctl_b->m_send_notify_cb = NULL; spin_lock_init(&ctl_b->m_lock); // Init CCIF now ccif->register_call_back_func(ccif, __logic_dispatch_push, __let_logic_dispatch_tasklet_run); //ccif->ccif_register_intr(ccif); // Init done //CCCI_DBG_MSG(md_id, "cci", "ccci_logic_ctlb_init success!\n"); return ret; _ccif_logic_channel_init_fail: for(i = 0; i < CCCI_MAX_CH_NUM; i++) { ch_info = &ctl_b->m_logic_ch_table[i]; if(ch_info->m_kfifo_ready){ kfifo_free(&ch_info->m_kfifo); ch_info->m_kfifo_ready = 0; } } _ccif_instance_create_fail: kfree(ctl_b); logic_dispatch_ctlb[md_id] = NULL; return ret; }
static int __ccif_v1_intr_handler(ccif_t *ccif) { ccif_msg_t phy_ch_data; int re_enter_cnt = 0; int r_ch_val; int i; int rx_ch; int md_id = ccif->m_md_id; bool reg_err = FALSE; unsigned int msg[4]; CCCI_FUNC_ENTRY(md_id); set_bit(CCIF_TOP_HALF_RUNNING,&ccif->m_status); //CCCI_DBG_MSG(md_id, "cci", "ISR\n"); if(ccif->isr_notify) ccif->isr_notify(md_id); rx_ch = ccif->m_rx_idx; while( (r_ch_val = ccif->ccif_get_rx_ch(ccif)) && (re_enter_cnt<CCIF_INTR_MAX_RE_ENTER_CNT) ) { for(i=0; i<CCIF_STD_V1_MAX_CH_NUM; i++) { if (r_ch_val&(1<<rx_ch)) { // We suppose always read success ccif->ccif_read_phy_ch_data(ccif, rx_ch, (unsigned int*)&phy_ch_data); #ifdef CCIF_DEBUG if (phy_ch_data.channel >= CCCI_MAX_CH_NUM) { if (!reg_err) { reg_err = TRUE; __ccif_v1_dump_reg(ccif, NULL, 0); CCCI_MSG_INF(md_id, "cci", "[CCIF Register Error]RX: %08X, %08X, %02d, %08X (%02d)\n", phy_ch_data.data[0], \ phy_ch_data.data[1], phy_ch_data.channel, phy_ch_data.reserved, rx_ch); } } #endif if((lg_ch_rx_debug_enable[md_id] & ENABLE_ALL_RX_LOG) || (lg_ch_rx_debug_enable[md_id] & (1<< phy_ch_data.channel))) { CCCI_DBG_MSG(md_id, "cci", "[RX]: %08X, %08X, %02d, %08X (%02d)\n", phy_ch_data.data[0], \ phy_ch_data.data[1], phy_ch_data.channel, phy_ch_data.reserved, rx_ch); } // push ccif message to up layer if (unlikely(ccif->push_msg == NULL)) { CCCI_DBG_MSG(md_id, "cci", "push_msg func not registered:0x%08x, 0x%08x, %02d, 0x%08x\n", \ phy_ch_data.data[0], phy_ch_data.data[1], phy_ch_data.channel, phy_ch_data.reserved); } else { if ( ccif->push_msg(&phy_ch_data, ccif->m_logic_ctl_block) != sizeof(ccif_msg_t) ) { //CCCI_DBG_MSG(md_id, "cci", "push data fail(ch%d)\n", phy_ch_data.channel); } } // Ack modem side ccif ccci_write32(CCIF_ACK(ccif->m_reg_base), (1<<rx_ch)); r_ch_val &=~(1<<rx_ch); } else { if (r_ch_val != 0) { // We suppose rx channel usage should be fifo mode CCCI_DBG_MSG(md_id, "cci", "rx channel error(rx>%02x : %d<curr)\n", r_ch_val, rx_ch); __ccif_v1_dump_reg(ccif, NULL, 0); } else { break; } } ++rx_ch; rx_ch = rx_ch&(CCIF_STD_V1_MAX_CH_NUM-1); } re_enter_cnt++; } if( (re_enter_cnt>=CCIF_INTR_MAX_RE_ENTER_CNT) && (r_ch_val!=0) ) { CCCI_DBG_MSG(md_id, "cci", "too much message to process\n"); __ccif_v1_dump_reg(ccif, NULL, 0); } // Store latest rx channel index ccif->m_rx_idx = rx_ch; // Notify uplayer begin to process data if (unlikely(ccif->notify_push_done == NULL)) { //CCCI_DBG_MSG(md_id, "cci", "notify_push_done not registered!\n"); } else { ccif->notify_push_done(ccif->m_logic_ctl_block); } clear_bit(CCIF_TOP_HALF_RUNNING,&ccif->m_status); #ifdef CCIF_DEBUG if (reg_err) { reg_err = FALSE; msg[0] = 0xFFFFFFFF; msg[1] = 0x5B5B5B5B; msg[2] = CCCI_FORCE_ASSERT_CH; msg[3] = 0xB5B5B5B5; __ccif_v1_write_phy_ch_data(ccif, msg, 0); } #endif return 0; }