⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2c-samsung.c

📁 II2c driver for uclinux
💻 C
📖 第 1 页 / 共 2 页
字号:
          /* Send byte address: LSB */
          IICBUF = iic_txmit.BYTE_ADDR_LSB;
          iic_txmit.FLAG |= (U32)iic_byte_addr_lsb; 
         }
         else if(iic_txmit.BuffByteCnt < iic_txmit.WriteDataSize) {
          IICBUF = iic_txmit.PAGE_BUFFER[iic_txmit.BuffByteCnt++]; 
         }
         else { 
            /* STOP IIC Controller */
            IICCON = STOP;
            /* byte data or page data transmit done */
            iic_txmit.FLAG |= (U32)iic_page_tx_done;
         }
        }

	else{
	    if(!(iic_recv.FLAG & (U32)iic_byte_addr_msb)) { 
     		//else if(!(iic_recv.FLAG & (U32)iic_byte_addr_msb)) { 
          	/* Send byte address: MSB */
          	IICBUF = iic_recv.BYTE_ADDR_MSB;
          	iic_recv.FLAG |= (U32)iic_byte_addr_msb; /* send msb byte addr */
     		}
     	    else if(!(iic_recv.FLAG & (U32)iic_byte_addr_lsb)) {
         	/* Send byte address: LSB */
          	IICBUF = iic_recv.BYTE_ADDR_LSB;
          	iic_recv.FLAG |= (U32)iic_byte_addr_lsb; /* send lsb byte addr */
     		}
     	    else if(!(iic_recv.FLAG & (U32)iic_repeat_start)) {
          	/* Repeat Start */
          	IICCON = RESTART; 
          	IICCON = START|ACK|IEN;
          	IICBUF = iic_recv.SLAVE_ADDR|S_READ;
          	iic_recv.FLAG |= (U32)iic_repeat_start;
     		}
     	    else if(!(iic_recv.FLAG & (U32)iic_multi_recv)) {
          	/* Receive multiple data */
          	IICCON = ACK|IEN;
          	iic_recv.FLAG |= (U32)iic_multi_recv;
     		}
     	    else if(iic_recv.ByteReadCnt < iic_recv.ReadDataSize) {
          	*(iic_recv.RCV_BUFFER)++ = IICBUF;
          	iic_recv.ByteReadCnt++;
     		}
     	    else if(!(iic_recv.FLAG & (U32)iic_no_more_recv)) { 
            	/* Now,no more received data is required from slave */
            	IICCON = NOACK|IEN;
            	iic_recv.FLAG |= (U32)iic_no_more_recv;
     		}
     	    else { /* Receive last data and STOP */
            	*(iic_recv.RCV_BUFFER)++ = IICBUF;

            	/* STOP IIC Controller */
            	IICCON = STOP;

            	/* byte data receive done */
            	iic_recv.FLAG |= (U32)iic_byte_rx_done;
    		 }
	}
	
	spin_unlock(&i2c_priv.lock);

}

#ifdef MODULE
/*===============================================*/
/*	 install module				 */
/*===============================================*/
int  init_module(void)
{
	return i2c_samsung_init();
}
/*================================================*/
/*	 uninstall module			  */
/*================================================*/
void cleanup_module( void )
{
	
	free_irq(INT_IIC, NULL);	
	
	devfs_unregister_chrdev( I2C_MAJOR, DEVICE_NAME );	
	devfs_unregister( dev_handle );	

	DBG( "s34510: unload i2c device ......\n");
	
}
#endif

int __init i2c_samsung_init( void )
{
	int result;

	DBG( "s34510: install hardware I2C device ......\n" );


	disable_irq(INT_IIC);

	// register i2c isr
        if(request_irq(INT_IIC, &s3c4510_i2c, SA_INTERRUPT, "i2c isr", NULL)
) {
                printk(KERN_ERR DEVICE_NAME " s34510: can't get irq %d\n", INT_IIC );
                return -EAGAIN;
        }
	else    DBG(KERN_ERR DEVICE_NAME " s34510: get i2c irq %d\n", INT_IIC );
	
	result = devfs_register_chrdev(I2C_MAJOR, DEVICE_NAME, &i2c_ops);  		

	if( result < 0 ){
		printk (KERN_ERR DEVICE_NAME " s34510: init_module failed with %d\n", result);	
		return result;
	}	
	
	printk (KERN_INFO "Samsung S3C4510 I2c hardware driver version 0.3 with mutex (2003.11.16 ) <honeyandy@thunis.com>\n");	
	

//	dev_handle = devfs_register( NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
//			I2C_MAJOR, 0, S_IFCHR, &i2c_ops, NULL);

//	if( i2c_major == 0)
//		i2c_major = result;

        iic_priv.i2c_speed = CFG_I2C_SPEED;
	iic_priv.i2c_slave = CFG_I2C_SLAVE;
	iic_priv.i2c_addrlen = IICADDR2;
	iic_priv.i2c_operate = IICREAD;
	iic_priv.i2c_pagesize = 0;
	
	i2c_init( iic_priv.i2c_speed);
	
	DBG( "OK\n" );
	
	spin_lock_init(&i2c_priv.lock);
	sema_init(&i2c_samsung_sem, 1);	
	return 0;

}	

/*================================================================*/
/*     SETUP IIC PRESCALER VALUE FROM SERIAL CLOCK FREQUENCY      */
/*================================================================*/
static int  SetSpeed(int sclk) 
{  
     volatile U32 value ;
	
     DBG("s34510: set i2c IICPS slck  %d Hz\n",(U32)sclk);  
     
     value = ( U32 ) (fMCLK_MHz)/sclk;  /** fMCLK in MHz, fMCLK_MHz in Hz, this is uClinux defined */
     value = value-3;
     value = value/16;
     value = value - 1;    //support upto 100KHz	
	
     DBG("s34510: set i2c IICPS want set %08x\n",(U32)value );  
		
     IICPS = value&0xFFFF;	//LSB 16bit valuable	
     
     DBG("s34510: set i2c IICPS %08x\n",(U32)IICPS);  
   
     
}
/*=====================================================================*/
/*	 `speed' and `slaveaddr' not implemented		       */
/*=====================================================================*/

static void i2c_init (int speed)
{
	
	IICCON = IICRESET;
	SetSpeed(speed); 
}


/* --------------------------------------------------------------
 * 	bellow is I2C operation functions body 
 * 	 
 * --------------------------------------------------------------
 *
 *---------------------------------------------------------------
 * Definitions
 */

/*-----------------------------------------------------------------------
 *
 * W/RAddr:	Array of address bytes; for instance, to read from
 *              EEPROM with 8 bit page addresses you have to write 2
 *              address bytes: the block number, and the block
 *              offset.
 * AddrLen:	Number of address bytes in "addr"
 * data:	where to store the read data in
 * SizeOfData:	number of bytes to read
 *              Warning: it is expected that the device is really
 *              capable of reading `len' sequential bytes; no
 *              checking is done here
 */
static void i2c_chain_write (U32 WriteAddr, U8 *data, int SizeOfData )
{

    int page,j;
    int no_of_page;      /* Number of page */
    int remain_byte;      
    U32 PageAccessAddr; 

    PageAccessAddr = WriteAddr;
    iic_txmit.SLAVE_ADDR = iic_priv.i2c_slave;

    no_of_page = (int)(SizeOfData/(U32)iic_priv.i2c_pagesize);
    remain_byte = (int)(SizeOfData%(U32)iic_priv.i2c_pagesize);

    for(page=0; page <= no_of_page;page++)
    {
        if(SizeOfData < iic_priv.i2c_pagesize) { 
           for(j=0; j < SizeOfData; j++)
               iic_txmit.PAGE_BUFFER[j] = *data++;
           iic_txmit.WriteDataSize = SizeOfData;
        }
        else {
               if(page == no_of_page) {
                   for(j=0; j < remain_byte; j++)
                       iic_txmit.PAGE_BUFFER[j] = *data++;
                   iic_txmit.WriteDataSize = remain_byte;
               }
               else {
                    for(j=0; j < iic_priv.i2c_pagesize; j++)
                        iic_txmit.PAGE_BUFFER[j] = *data++;
                    iic_txmit.WriteDataSize = iic_priv.i2c_pagesize;
               }
        }

    	i2c_init( iic_priv.i2c_speed);
    	iic_priv.i2c_operate = IICWRITE;
    	enable_irq(INT_IIC) ;			
        
	iic_txmit.FLAG = 0x0;
	
	if(iic_priv.i2c_addrlen == IICADDR1)
	iic_txmit.FLAG |= (U32)iic_byte_addr_msb;
	
	iic_txmit.BuffByteCnt = 0x0;
        iic_txmit.BYTE_ADDR_MSB = (U8)((PageAccessAddr>>8) & 0xff);
        iic_txmit.BYTE_ADDR_LSB = (U8)(PageAccessAddr & 0xff);
	
        /* Step 1: Setup IICON register for transmit start */
        while(IICCON & BUSY);   /* Wait! the iic bus is busy */
        IICCON = START|ACK|IEN; /* Now, Start to transmit */

        /* Send Slave Address and Write command */
        IICBUF = iic_txmit.SLAVE_ADDR|S_WRITE;

        while(!(iic_txmit.FLAG & iic_page_tx_done));
        PageAccessAddr += iic_priv.i2c_pagesize;
        udelay(7000);  /* for 5ms write cycle */
    }


    disable_irq(INT_IIC) ;			
}

static void i2c_chain_read (U32 ReadAddr , U8 *data , int SizeOfData)
{

	
    i2c_init( iic_priv.i2c_speed);
    
    iic_priv.i2c_operate = IICREAD;
    enable_irq(INT_IIC) ;			
		

    /*Memory alloc for receive data */
   
    iic_recv.RCV_BUFFER = data;

    iic_recv.FLAG = 0x0;
    
    if(iic_priv.i2c_addrlen == IICADDR1)
	iic_txmit.FLAG |= (U32)iic_byte_addr_msb;
    
    iic_recv.ByteReadCnt = 0x0;
    iic_recv.ReadDataSize = SizeOfData;
    iic_recv.SLAVE_ADDR = iic_priv.i2c_slave;
    iic_recv.BYTE_ADDR_MSB = (U8)((ReadAddr>>8) & 0xff);
    iic_recv.BYTE_ADDR_LSB = (U8)(ReadAddr & 0xff);

    /* Step 1: Setup IICON register for receive start */
    while(IICCON & BUSY);   /* Wait! the iic bus is busy */
    IICCON = START|ACK|IEN;

    /* Send Slave Address and Write command */
    IICBUF = iic_recv.SLAVE_ADDR|S_WRITE;

    while(!(iic_recv.FLAG & iic_byte_rx_done));
	
    
    disable_irq(INT_IIC) ;			
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -