| 
		    
                     最近因为工作需要涉及到了I2C总线。虽然我过去用过I2c,但看了 Linux kernel 后才发现,一个 layer 能被做到这样完善。 
  
1.       Linux的I2C驱动架
  
Linux中I2C总线的驱动分为两个部分,总线驱动(BUS)和设备驱动(DEVICE)。其中总线驱动的职责,是为系统中每个I2C总线增加相应的读写方法。但是总线驱动本身并不会进行任何的通讯,它只是存在在那里,等待设备驱动调用其函数。 
  
设备驱动则是与挂在I2C总线上的具体的设备通讯的驱动。通过I2C总线驱动提供的函数,设备驱动可以忽略不同总线控制器的差异,不考虑其实现细节地与硬件设备通讯。 
  
1.1.    总线驱动
  
在系统开机时,首先装载的是I2C总线驱动。一个总线驱动用于支持一条特定的I2C总线的读写。一个总线驱动通常需要两个模块,一个struct i2c_adapter和一个struct i2c_algorithm来描述: 
  
 
    
        
            | 
             static struct i2c_adapter pb1550_board_adapter =  
            { 
              name:              "pb1550 adapter", 
              id:                I2C_HW_AU1550_PSC, 
              algo:              NULL, 
              algo_data:         &pb1550_i2c_info, 
              inc_use:           pb1550_inc_use, 
              dec_use:           pb1550_dec_use, 
              client_register:   pb1550_reg, 
              client_unregister: pb1550_unreg, 
              client_count:      0, 
            }; 
             | 
         
    
 
  
这个样例挂接了一个叫做“pb1550 adapter”的驱动。但这个模块并未提供读写函数,具体的读写方法由第二个模块,struct i2c_algorithm提供。 
  
 
    
        
            | 
             static struct i2c_algorithm au1550_algo =  
            { 
             .name         = "Au1550 algorithm", 
             .id      = I2C_ALGO_AU1550, 
             .master_xfer  = au1550_xfer, 
             .functionality     = au1550_func, 
            }; 
              
            i2c_adap->algo = &au1550_algo; 
             | 
         
    
 
  
这个样例给上述总线驱动增加了读写“算法”。通常情况下每个I2C总线驱动都定义一个自己的读写算法,但鉴于有些总线使用相同的算法,因而可以共用同一套读写函数。本例中的驱动定义了自己的读写算法模块,起名叫“Au1550 algorithm”。 
  
全部填妥后,通过调用: 
  
 
    
        
            | 
             i2c_add_adapter(i2c_adap); 
             | 
         
    
 
  
将这两个模块注册到操作系统里,总线驱动就算装上了。对于AMD au1550,这部分已经由AMD提供了。 
  
1.2.    设备驱动
 
如前所述,总线驱动只是提供了对一条总线的读写机制,本身并不会去做通信。通信是由I2C设备驱动来做的,设备驱动透过I2C总线同具体的设备进行通讯。一个设备驱动有两个模块来描述,struct i2c_driver和struct i2c_client。  
 
		    
                      
		      
		      
		    |