u32 sdhci_disconnect(u32 status) { DBG("[SDIO_IPC]sdhci_disconnect: %s\r\n", status ? "SDHCI_TRANSFER_ERROR" : "SDHCI_TRANSFER_OK"); _DisableSleep(); #ifdef SDHCI_RESEND_SUPPORT if(SDHCI_TRANSFER_OK == status) { set_ap_status(); /* success */ } else { clear_ap_status();/* fail */ } ap2cp_rts_disable();/* end */ if(!wait_event_timeout(s_gpio_cp_ready_wq, !cp2ap_rdy(), MAX_MIPC_WAIT_TIMEOUT/HZ)) { printk("[MIPC] SDIO Disconnect Timeout!\r\n"); return SDHCI_TIMEOUT; } #else ap2cp_rts_disable();/* end */ #endif return SDHCI_SUCCESS; }
u32 sdhci_connect(u32 direction) { _DisableSleep(); if(SDHCI_TRANSFER_DIRECT_WRITE == direction) { clear_ap_status(); /* send */ } else { set_ap_status(); /* receive */ } ap2cp_rts_enable(); /* start */ if(!wait_event_timeout(s_gpio_cp_ready_wq, cp2ap_rdy(), MAX_MIPC_WAIT_TIMEOUT/HZ)) { printk("[MIPC] SDIO %s Connect Timeout!\r\n", direction ? "Read" : "Write" ); return SDHCI_TIMEOUT; } return SDHCI_SUCCESS; }
static int mux_ipc_rx_thread(void *data) { struct sched_param param = {.sched_priority = 25}; printk(KERN_INFO "mux_ipc_rx_thread enter\r\n"); sched_setscheduler(current, SCHED_FIFO, ¶m); wait_cp_bootup(); msleep(500); printk(KERN_INFO "mux_ipc_rx_thread start----\r\n"); //check CP status when start up if(0 == cp2ap_rdy()) { s_mipc_rx_event_flags = 1; } //working loop while (!kthread_should_stop()) { wait_event(s_mux_ipc_rx_wq, s_mipc_rx_event_flags); process_modem_packet(0); } return 0; } static int mux_ipc_create_rx_thread(void) { printk("mux_ipc_rx_create_thread enter.\n"); init_waitqueue_head(&s_mux_ipc_rx_wq); s_mux_ipc_rx_thread = kthread_create(mux_ipc_rx_thread, NULL, "mipc_rx_thread"); if (IS_ERR(s_mux_ipc_rx_thread)) { printk("ipc_sdio.c:mux_ipc_rx_thread error!.\n"); return -1; } wake_up_process(s_mux_ipc_rx_thread); return 0; }
static int mux_ipc_sdio_thread(void *data) { int rval; struct sched_param param = {.sched_priority = 35}; u32 continue_tx_cnt = 0; printk(KERN_INFO "mux_ipc_sdio_thread enter\r\n"); sched_setscheduler(current, SCHED_FIFO, ¶m); sdhci_hal_gpio_init(); //while(1) msleep(500); wait_cp_bootup(); do { rval = sprd_sdio_channel_open(); printk(KERN_INFO "%s() sdio channel opened %d\n", __func__, rval); } while(rval); sdhci_hal_gpio_irq_init(); printk(KERN_INFO "mux_ipc_sdio_thread start----\r\n"); while (!kthread_should_stop()) { bool force_tx = false; wait_event_timeout(s_mux_ipc_sdio_wq, (s_mipc_rx_req_flag || MIPC_TX_REQ_FLAG), msecs_to_jiffies(MAX_SDIO_SLEEP_TIMEOUT)); if(!(s_mipc_rx_req_flag || MIPC_TX_REQ_FLAG)) { //set ap inactive to let cp sleep ap2cp_rts_enable(); set_cp_awake(false); //wait for requests wait_event(s_mux_ipc_sdio_wq, (s_mipc_rx_req_flag || MIPC_TX_REQ_FLAG)); } //got sdio request //check modem status if(!_is_mux_ipc_enable()) { printk("[mipc] ipc reset free all tx data!\r\n"); _FreeAllTxTransferFrame(); while(!_is_mux_ipc_enable()) { printk("mux ipc tx Thread Wait enable!\r\n"); msleep(40); } printk("mux ipc tx Thread Wait enable Finished!\r\n"); } //make sure cp is awake if(!get_cp_awake()) { ap2cp_rts_disable(); //wait cp ack if(!wait_cp_awake(msecs_to_jiffies(MAX_SDIO_CP_ACK_TIMEOUT))) { printk("[MIPC] SDIO wait cp awake fail!\r\n"); //cp no ack, just discard a request ap2cp_rts_enable(); msleep(2); continue; } set_cp_awake(true); if(MIPC_TX_REQ_FLAG) { force_tx = true; } } //do rx first, if not force to do tx if(s_mipc_rx_req_flag && !force_tx) { int result; result = do_sdio_rx(&s_tx_flow_info, &s_acked_tx_frame); s_mipc_rx_req_flag = 0; continue_tx_cnt = 0; if(SDHCI_TRANSFER_OK == result) { if(s_mipc_tx_ctrl.last_ack_frame != s_acked_tx_frame) { ack_tx_frame_num(s_acked_tx_frame); } if(s_acked_tx_frame != s_last_tx_frame) { nack_tx_frame_num(); } if(s_tx_flow_info == 0) { ipc_info_error_status(IPC_TX_CHANNEL, IPC_STATUS_FLOW_STOP); } } } //do tx if(MIPC_TX_REQ_FLAG) { MIPC_TRANSF_FRAME_T* frame = get_from_sdio_tx_fifo(); if(frame) { do_sdio_tx(frame); continue_tx_cnt++; } force_tx = false; } //check cp read request after one cmd53 if(0 == cp2ap_rdy()) { continue_tx_cnt = 0; if(have_buffer_to_read()) { s_mipc_rx_req_flag = 1; } else { wake_up_mipc_rx_thread(1); } } if(continue_tx_cnt >= 2) { continue_tx_cnt--; implicit_ack_tx_frame(); } } return 0; } static int mux_ipc_create_sdio_thread(void) { printk("mux_ipc_create_sdio_thread enter.\n"); init_waitqueue_head(&s_mux_ipc_sdio_wq); s_mux_ipc_sdio_thread = kthread_create(mux_ipc_sdio_thread, NULL, "mipc_sdio_thread"); if (IS_ERR(s_mux_ipc_sdio_thread)) { printk("ipc_sdio.c:s_mux_ipc_sdio_thread error!.\n"); return -1; } wake_up_process(s_mux_ipc_sdio_thread); return 0; }
static irqreturn_t cp_to_ap_rdy_handle(int irq, void *handle) { DBG("[SDIO_IPC]cp_to_ap_rdy_handle:%d\r\n ", cp2ap_rdy()); wake_up(&s_gpio_cp_ready_wq); return IRQ_HANDLED; }