ºìÁªLinuxÃÅ»§
Linux°ïÖú

LinuxµÄ²Ù×÷ϵͳI2CÇý¶¯¼Ü¹¹½â˵

·¢²¼Ê±¼ä:2006-12-08 01:02:36À´Ô´:ºìÁª×÷Õß:pinkfirex
×î½üÒòΪ¹¤×÷ÐèÒªÉæ¼°µ½ÁË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¡£

µ±ÏµÍ³¿ª»ú¡¢I2C×ÜÏßÇý¶¯×°ÈëÍê³Éºó£¬¾Í¿ÉÒÔ×°ÈëÉ豸Çý¶¯ÁË¡£Ê×ÏÈ×°ÈëÈçϽṹ£º


static struct i2c_driver driver =

{

.name = "i2c TV tuner driver",

.id = I2C_DRIVERID_TUNER,

.flags = I2C_DF_NOTIFY,

.attach_adapter = tuner_probe,

.detach_client = tuner_detach,

.command = tuner_command,

};


i2c_add_driver(&driver);


Õâ¸öi2c_driverÒ»µ©×°ÈëÍê³É£¬ÆäÖеÄattach_adapterº¯Êý¾Í»á±»µ÷Óá£ÔÚÆäÖпÉÒÔ±éÀúϵͳÖеÄÿ¸öi2c×ÜÏßÇý¶¯£¬Ì½²âÏëÒª·ÃÎʵÄÉ豸£º


static int tuner_probe(struct i2c_adapter *adap)

{

¡¡return i2c_probe(adap, &addr_data, tuner_attach);

}


×¢Òâ̽²â¿ÉÄÜ»áÕÒµ½¶à¸öÉ豸£¬Òò¶ø²»½öÒ»¸öI2C×ÜÏß¿ÉÒÔ¹Ò¶à¸ö²»Í¬ÀàÐ͵ÄÉ豸£¬Ò»¸öÉ豸Çý¶¯Ò²¿ÉÒÔͬʱΪ¹ÒÔÚ¶à¸ö²»Í¬I2C×ÜÏßÉϵÄÉ豸·þÎñ¡£

ÿµ±É豸Çý¶¯Ì½²âµ½ÁËÒ»¸öËüÄÜÖ§³ÖµÄÉ豸£¬Ëü¾Í´´½¨Ò»¸östruct i2c_clientÀ´±êʶÕâ¸öÉ豸£º


new_client->addr = address;

new_client->adapter = adapter;

new_client->driver = &driver;


/* Tell the I2C layer a new client has arrived */

err = i2c_attach_client(new_client);

if (err)

goto error;


¿É¼û£¬Ò»¸öi2c_client´ú±í×ÅλÓÚadapter×ÜÏßÉÏ£¬µØַΪaddress£¬Ê¹ÓÃdriverÀ´Çý¶¯µÄÒ»¸öÉ豸¡£Ëü½«×ÜÏßÇý¶¯ÓëÉ豸Çý¶¯£¬ÒÔ¼°É豸µØÖ·°ó¶¨ÔÚÁËÒ»Æð¡£Ò»¸öi2c_client¾Í´ú±í×ÅÒ»¸öI2CÉ豸¡£

µ±µÃµ½I2CÉ豸ºó£¬¾Í¿ÉÒÔÖ±½Ó¶Ô´ËÉ豸½øÐжÁд£º


/*

* The master routines are the ones normally used to transmit data to devices

* on a bus (or read from them). Apart from two basic transfer functions to

* transmit one message at a time, a more complex version can be used to

* transmit an arbitrary number of messages without interruption.

*/


extern int i2c_master_send(struct i2c_client *,const char* ,int);

extern int i2c_master_recv(struct i2c_client *,char* ,int);


Óëͨ³£ÒâÒåÉϵĶÁдº¯ÊýÒ»Ñù£¬ÕâÁ½¸öº¯Êý¶Ôi2c_clientÖ¸ÕëÖ¸¶¨µÄÉ豸£¬¶Áдint¸öchar¡£·µ»ØֵΪ¶ÁдµÄ×Ö½ÚÊý¡£¶ÔÓÚÎÒÃÇÏÖÓеÄSLICµÄÇý¶¯£¬Ö»Òª½«×îºóÒªÍù×ÜÏßÉϽøÐжÁдµÄÊý¾ÝÒý³ö´«Êäµ½ÕâÁ½¸öº¯ÊýÖУ¬ÒÆÖ²¹¤×÷¾ÍËãÍê³ÉÁË£¬ÎÒÃǽ«µÃµ½Ò»¸öLinux°æµÄI2CÉ豸Çý¶¯¡£
ÎÄÕÂÆÀÂÛ

¹²ÓÐ 0 ÌõÆÀÂÛ