/* * Function opens a tty device when called from user space */ static int ifx_spi_open(struct tty_struct *tty, struct file *filp) { int status = 0; struct ifx_spi_data *spi_data; IFX_SPI_DEBUG("[id: %d]", tty->index); if(ifx_gspi_data) { spi_data = ifx_gspi_data; spi_data->ifx_tty = tty; tty->driver_data = spi_data; ifx_spi_buffer_initialization(spi_data); spi_data->throttle = 0; IFX_SPI_PRINTK(" success!!"); } else { tty->driver_data = NULL; IFX_SPI_PRINTK("failed!!"); status = -ENODEV; } return status; }
static void ifx_spi_handle_work(struct work_struct *work) { struct ifx_spi_data *spi_data = container_of(work, struct ifx_spi_data, ifx_work); if (!ifx_master_initiated_transfer){ ifx_spi_setup_transmission(); ifx_spi_set_mrdy_signal(1); ifx_spi_send_and_receive_data(spi_data); /* Once data transmission is completed, the MRDY signal is lowered */ if((ifx_sender_buf_size == 0) && (ifx_receiver_buf_size == 0)){ ifx_spi_set_mrdy_signal(0); ifx_spi_buffer_initialization(); } /* We are processing the slave initiated transfer in the mean time Mux has requested master initiated data transfer */ /* Once Slave initiated transfer is complete then start Master initiated transfer */ if(ifx_master_initiated_transfer == 1){ /* It is a condition where Slave has initiated data transfer and both SRDY and MRDY are high and at the end of data transfer * MUX has some data to transfer. MUX initiates Master initiated transfer rising MRDY high, which will not be detected at Slave-MODEM. * So it was required to rise MRDY high again */ udelay(100);//TI JANGHAN //udelay(10);// reduce delay for performnace ifx_spi_set_mrdy_signal(1); } } else{ ifx_spi_setup_transmission(); ifx_spi_send_and_receive_data(spi_data); /* Once data transmission is completed, the MRDY signal is lowered */ if(ifx_sender_buf_size == 0){ if(ifx_receiver_buf_size == 0){ ifx_spi_set_mrdy_signal(0); udelay(100);////TI JANGHAN //udelay(10);// reduce delay for performance ifx_spi_buffer_initialization(); } ifx_master_initiated_transfer = 0; complete(&spi_data->ifx_read_write_completion); } } }
/* * Function opens a tty device when called from user space */ static int ifx_spi_open(struct tty_struct *tty, struct file *filp) { int status = 0; //20100607, [email protected], add else code [START] struct ifx_spi_data *spi_data; if(gspi_data) { spi_data = gspi_data; spi_data->ifx_tty = tty; tty->driver_data = spi_data; ifx_spi_buffer_initialization(); spi_data->throttle = 0; SPI_DEBUG_PRINT("ifx_spi_open\n"); } else { ifx_spi_buffer_initialization(); SPI_DEBUG_PRINT("ifx_spi_open failed!!\n"); } //20100607, [email protected], add else code [END] return status; }
/* * Function opens a tty device when called from user space */ static int ifx_spi_open(struct tty_struct *tty, struct file *filp) { int status = 0; struct ifx_spi_data *spi_data = gspi_data; spi_data->ifx_tty = tty; tty->driver_data = spi_data; // hgahn spi_data->ifx_spi_lock =0; ifx_spi_buffer_initialization(); spi_data->throttle = 0; return status; }
/* * Function opens a tty device when called from user space */ static int ifx_spi_open(struct tty_struct *tty, struct file *filp) { int status = 0; struct ifx_spi_data *spi_data = gspi_data; spi_data->ifx_tty = tty; tty->driver_data = spi_data; // hgahn // spi_data->ifx_spi_lock =0; ifx_spi_buffer_initialization(); spi_data->throttle = 0; printk("**** %s status %d \n",__FUNCTION__, status); return status; }
static void ifx_spi_handle_work(struct work_struct *work) { struct ifx_spi_data *spi_data = container_of(work, struct ifx_spi_data, ifx_work); int timer_result; volatile int check_resume ; volatile int check_suspend ; volatile int check_count ; if(spi_data->packet_count < SAFE_GUARD) spi_data->packet_count++; check_suspend = spi_data->is_suspend ; check_count = 0 ; while(1){ if(!check_suspend) break ; msleep(1) ; check_suspend = spi_data->is_suspend ; check_count++ ; if(check_count > 1000) break ; } if(check_count != 0) printk("%s check count %d \n", __FUNCTION__, check_count) ; if (!ifx_master_initiated_transfer){ // printk( "slave start\n"); LOCK(&spi_sync_mutex); ifx_spi_setup_transmission(); if(!gpio_get_value(TEGRA_GPIO_PO0)) ifx_spi_set_mrdy_signal(1); ifx_spi_send_and_receive_data(spi_data); /* Once data transmission is completed, the MRDY signal is lowered */ if((ifx_sender_buf_size == 0) && (ifx_receiver_buf_size == 0)){ ifx_spi_set_mrdy_signal(0); ifx_spi_buffer_initialization(); if(spi_data->packet_count < SAFE_GUARD) my_check_delay(2*MRDY_DELAY_TIME) ; else my_check_delay(MRDY_DELAY_TIME) ; // udelay(2*MRDY_DELAY_TIME) ; } UNLOCK(&spi_sync_mutex); /* We are processing the slave initiated transfer in the mean time Mux has requested master initiated data transfer */ /* Once Slave initiated transfer is complete then start Master initiated transfer */ if(ifx_master_initiated_transfer == 1){ /* It is a condition where Slave has initiated data transfer and both SRDY and MRDY are high and at the end of data transfer * MUX has some data to transfer. MUX initiates Master initiated transfer rising MRDY high, which will not be detected at Slave-MODEM. * So it was required to rise MRDY high again */ if(!gpio_get_value(TEGRA_GPIO_PO0)) ifx_spi_set_mrdy_signal(1); } //printk( "slave end\n"); } else{ //printk( "master start\n"); ifx_spi_setup_transmission(); ifx_spi_send_and_receive_data(spi_data); /* Once data transmission is completed, the MRDY signal is lowered */ if(ifx_sender_buf_size == 0){ if(ifx_receiver_buf_size == 0){ ifx_spi_set_mrdy_signal(0); ifx_spi_buffer_initialization(); if(spi_data->packet_count < SAFE_GUARD) my_check_delay(2*MRDY_DELAY_TIME) ; else my_check_delay(MRDY_DELAY_TIME) ; //udelay(2*MRDY_DELAY_TIME) ; } ifx_master_initiated_transfer = 0; complete(&spi_data->ifx_read_write_completion); } //printk( "master end\n"); } //printk( "tegra_spi_workerthread / End\n"); }
static unsigned int ifx_spi_sync_read_write(struct ifx_spi_data *spi_data, unsigned int len) { bool spi_suspend_failed; int status; int ipc_check; struct spi_message m; struct spi_transfer t = { .tx_buf = spi_data->ifx_tx_buffer, .rx_buf = spi_data->ifx_rx_buffer, .len = len, }; #ifdef IFX_SPI_TEGRA_TRANSFER_DURATION static struct timeval transfer_start_time; static struct timeval transfer_end_time; unsigned long duration_time; #endif spi_message_init(&m); spi_message_add_tail(&t, &m); IFX_SPI_DEBUG(""); if (spi_data->spi == NULL) { IFX_SPI_PRINTK("spi_data->spi = NULL"); status = -ESHUTDOWN; } else { #ifdef IFX_SPI_TEGRA_TRANSFER_DURATION IFX_SPI_PRINTK("!!! spi_transfer start !!!"); do_gettimeofday(&transfer_start_time); status = spi_sync(spi_data->spi, &m); do_gettimeofday(&transfer_end_time); duration_time = (transfer_end_time.tv_usec - transfer_start_time.tv_usec); //sec IFX_SPI_PRINTK("!!! spi_transfer end is %06d ms !!!", (duration_time/1000)); //milisec #else status = spi_sync(spi_data->spi, &m); #endif } if (status == 0) { status = m.status; if (status == 0) { status = m.actual_length; } //reset 'count_transfer_failed' to zero, if spi transter succeeds at least one out of five times count_transfer_failed = 0; } else { ipc_check = ifx_modem_communicating(); if(ipc_check == 0) { IFX_SPI_PRINTK("transmission unsuccessful, [spi_sync] status:%d, count_Failed:%d\n", status, count_transfer_failed); spi_suspend_failed = spi_tegra_suspend_failed(spi_data->spi); if (spi_suspend_failed) { IFX_SPI_PRINTK("kernel_restart!!!, spi_suspend_failed=%d \n", spi_suspend_failed); kernel_restart(NULL); } } //increase 'count_transfer_failed', when spi transter fails count_transfer_failed++; } #ifdef IFX_SPI_TX_RX_BUF IFX_SPI_PRINTK("SPI TX BUFFER: "); for(i=0;i<16;i++) { printk( "%02x ",spi_data->ifx_tx_buffer[i]); } IFX_SPI_PRINTK("\n"); IFX_SPI_PRINTK("SPI RX BUFFER : "); for(i=0;i<16;i++) { printk( "%02x ",spi_data->ifx_rx_buffer[i]); } #endif return status; } /* * Function is a Interrupt service routine, is called when SRDY signal goes HIGH. It set up transmission and * reception if it is a Slave initiated data transfer. For both the cases Master intiated/Slave intiated * transfer it starts data transfer. */ static irqreturn_t ifx_spi_handle_srdy_irq(int irq, void *handle) { struct ifx_spi_data *spi_data = (struct ifx_spi_data *)handle; int pin_val; IFX_SPI_DEBUG(""); #ifdef IFX_TEGRA_EDGE_TRIGGER pin_val = gpio_get_value(IFX_SRDY); IFX_SPI_DEBUG("pin_val = %d", pin_val); if(pin_val == 0) { printk("[SPI][SRDY_IRQ] pin value is ZERO.. Return!! \n"); IFX_SPI_DEBUG(" IRQF_TRIGGER_FALLING in the srdy irq is ignore !!! \n"); return IRQ_HANDLED; } #endif #if 0 if(spi_data && spi_data->ifx_tty) //add to prevent the irq of srdy until spi opening { IFX_SPI_DEBUG("queue_work is done!"); queue_work(spi_data->ifx_wq, &spi_data->ifx_work); } else { IFX_SPI_PRINTK("Unexpected interrupt happen!"); IFX_SPI_PRINTK("spi_data = 0x%p, 0x%p, spi_data->ifx_tty =0x%p", spi_data, spi_data->ifx_tty); } #else #ifdef WAKE_LOCK_RESUME // HZ is 1sec IFX_SPI_DEBUG("[IFX_SRDY] wake lock : 0x%lx", &ifx_gspi_data->wake_lock); wake_lock_timeout(&ifx_gspi_data->wake_lock, msecs_to_jiffies(500)); //5,, Unexpected interrupt or power consumption #endif IFX_SPI_DEBUG("queue_work is done!"); queue_work(spi_data->ifx_wq, &spi_data->ifx_work); #endif return IRQ_HANDLED; } // ifx_master_initiated_transfer = 1; --> set called by ifx_spi_write() // ifx_master_initiated_transfer = 0; --> default static void ifx_spi_handle_work(struct work_struct *work) { bool spi_tegra_suspended; struct ifx_spi_data *spi_data = container_of(work, struct ifx_spi_data, ifx_work); #ifdef IFX_SPI_SPEED_MEASUREMENT int id = 0; unsigned long diff; #endif IFX_SPI_DEBUG( " start"); // 20120904 jisil.park unsigned long reg; int pm_off_count; if(1 == spi_data->is_suspended) { pm_off_count = 1; printk("[SPI][handle_work] ifx_spi_handle_work INFO spi_data->is_suspended is (0x%x)\n", spi_data->is_suspended); //wait for ap to return to resume state with a worst case scenario of 5sec do { mdelay(1); pm_off_count++; }while((1 == spi_data->is_suspended) && (pm_off_count<(5*200))); printk("[EBS] ifx_spi_handle_work INFO EXIT is_suspend = 0x%x pm_off_count=%d\n", spi_data->is_suspended, pm_off_count); if(1 == spi_data->is_suspended) { // To Do how to handle the PM OFF state during 1sec printk("[SPI][handle_work] ifx_spi_handle_work error is_suspended is (0x%x)\n",spi_data->is_suspended); } } // 20120904 jisil.park /* add to wait tx/rx data when tegra spi is suspended*/ spi_tegra_suspended = spi_tegra_is_suspend(spi_data->spi); if (spi_tegra_suspended) { IFX_SPI_PRINTK("spi_tegra is not resume !, spi_tegra_suspended = %d\n",spi_tegra_suspended); return; } if (!spi_data->ifx_master_initiated_transfer) { IFX_SPI_TX_DEBUG("CP Start =================> \n"); #ifdef IFX_SPI_SPEED_MEASUREMENT do_gettimeofday(&ulStart[id]); #endif ifx_spi_setup_transmission(spi_data); ifx_spi_set_mrdy_signal(1); ifx_spi_send_and_receive_data(spi_data); #ifdef IFX_SPI_SPEED_MEASUREMENT do_gettimeofday(&ulEnd[id]); diff = (ulEnd[id].tv_sec - ulStart[id].tv_sec) * 1000 * 1000 ; diff = (diff + (ulEnd[id].tv_usec - ulStart[id].tv_usec)); ulRxThroughtput[id] = ((uiRxlen[id]*8*1000)/diff); IFX_SPI_PRINTK("[SPI %d] : RX time = %09d usec; %04d bytes; %06lu Kbps", id, diff, IFX_SPI_MAX_BUF_SIZE+IFX_SPI_HEADER_SIZE, ((IFX_SPI_MAX_BUF_SIZE+IFX_SPI_HEADER_SIZE)*8*1000)/diff); #endif /* Once data transmission is completed, the MRDY signal is lowered */ if((spi_data->ifx_sender_buf_size == 0) && (spi_data->ifx_receiver_buf_size == 0)) { ifx_spi_set_mrdy_signal(0); ifx_spi_buffer_initialization(spi_data); } /* We are processing the slave initiated transfer in the mean time Mux has requested master initiated data transfer */ /* Once Slave initiated transfer is complete then start Master initiated transfer */ if(spi_data->ifx_master_initiated_transfer == 1) //why check ? already ifx_master_initiated_transfer = 0 { /* It is a condition where Slave has initiated data transfer and both SRDY and MRDY are high and at the end of data transfer * MUX has some data to transfer. MUX initiates Master initiated transfer rising MRDY high, which will not be detected at Slave-MODEM. * So it was required to rise MRDY high again */ udelay(MRDY_DELAY_TIME) ; ifx_spi_set_mrdy_signal(1); } IFX_SPI_TX_DEBUG("CP End =================> \n"); } else { IFX_SPI_TX_DEBUG("Interrupt by AP25 ===========> \n"); ifx_spi_setup_transmission(spi_data); #if defined(LGE_DUMP_SPI_BUFFER) dump_spi_buffer("SPI TX", &spi_data->ifx_tx_buffer[4], COL_SIZE); #endif ifx_spi_send_and_receive_data(spi_data); /* Once data transmission is completed, the MRDY signal is lowered */ if(spi_data->ifx_sender_buf_size == 0) { if(spi_data->ifx_receiver_buf_size == 0) { ifx_spi_set_mrdy_signal(0); udelay(MRDY_DELAY_TIME) ; ifx_spi_buffer_initialization(spi_data); } IFX_SPI_TX_DEBUG("ifx_master_initiated_transfer set = 0 <============== \n"); spi_data->ifx_master_initiated_transfer = 0; complete(&spi_data->ifx_read_write_completion); } } #ifdef IFX_SPI_TX_RX_THROUGHTPUT if(uiTxlen[spi_data->mdm_tty->index] || uiRxlen[spi_data->mdm_tty->index]) { //ulEnd = getuSecTime() - ulStart; do_gettimeofday(&ulEnd[spi_data->ifx_tty->index]); uidiff[spi_data->ifx_tty->index] = (ulEnd[spi_data->ifx_tty->index].tv_sec - ulStart[spi_data->ifx_tty->index].tv_sec) * 1000 * 1000 ; uidiff[spi_data->ifx_tty->index] = uidiff[spi_data->ifx_tty->index] + (ulEnd[spi_data->ifx_tty->index].tv_usec - ulStart[spi_data->ifx_tty->index].tv_usec); ulTxThroughtput[spi_data->ifx_tty->index] = ((uiTxlen[spi_data->ifx_tty->index]*8*1000)/uidiff[spi_data->ifx_tty->index]); ulRxThroughtput[spi_data->ifx_tty->index] = ((uiRxlen[spi_data->ifx_tty->index]*8*1000)/uidiff[spi_data->ifx_tty->index]); IFX_SPI_PRINTK("[SPI %d] time = %d us, Tx(%dbytes) = %luKbps, Rx(%dbytes) = %luKbps, Max(%dbytes) = %luKbps\n", spi_data->ifx_tty->index, uidiff[spi_data->mdm_tty->index], uiTxlen[spi_data->ifx_tty->index], ulTxThroughtput[spi_data->ifx_tty->index], uiRxlen[spi_data->ifx_tty->index], ulRxThroughtput[spi_data->ifx_tty->index], IFX_SPI_MAX_BUF_SIZE+IFX_SPI_HEADER_SIZE, ((IFX_SPI_MAX_BUF_SIZE+IFX_SPI_HEADER_SIZE)*8*1000)/uidiff[spi_data->ifx_tty->index]); uiTxlen[spi_data->ifx_tty->index] = uiRxlen[spi_data->ifx_tty->index] = 0; fWrite[spi_data->ifx_tty->index] = 0; } #endif IFX_SPI_DEBUG( " end"); }