예제 #1
0
/*
 * 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;
}
예제 #2
0
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);
		}
	}
}
예제 #3
0
/*
 * 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;
}
예제 #4
0
/*
 * 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");
}
예제 #7
0
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");
}