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

📄 i2c-old-porting

📁 I2C总线LINUX驱动程序
💻
📖 第 1 页 / 共 2 页
字号:
I2C Conversion Guide for I2C-old to the current I2C APIJuly 2002For Linux Kernel v2.5.xFrank Davis <fdavis@si.rr.com>-------------------------------------------------------There exists several kernel drivers that are using an old version of the I2CAPI. These drivers need to be converted to the current (kernel 2.5.x) version.The following document provides a guideline to make the appropriate changes tothe affected drivers. There maybe slight modifications to this guide that are specific to the driver you are working on. If you see {driver_name}, replace that with the respective name of the driver, such as saa7110.c , {driver_name} = saa7110.-------------------------------------------------------Step 1: Include the right header file Perform the following change within the driver #include <linux/i2c-old.h> --> #include <linux/i2c.h>Step 2: Add and set the i2c modesAdd the following code near the top of the driverstatic unsigned short normal_i2c[] = {34>>1, I2C_CLIENT_END };static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };static unsigned short probe[2] = { I2C_CLIENT_END , I2C_CLIENT_END };static unsigned short probe_range[2] = { I2C_CLIENT_END , I2C_CLIENT_END };	static unsigned short ignore[2] = { I2C_CLIENT_END , I2C_CLIENT_END };static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };static unsigned short force[2] = { I2C_CLIENT_END , I2C_CLIENT_END };static struct i2c_client_address_data addr_data  = {	normal_i2c , normal_i2c_range,	probe , probe_range,	ignore , ignore_range,	force};static struct i2c_client client_template;Step 3: Modify the driver info structWithin the struct for the driver , such as struct {driver_name}  ,  make the following change ,struct i2c_bus *bus --> struct i2c_client *clientMake changes where this change affects references within the file.Add a semaphore to the driver struct (as above)struct semaphore lock Step 5: Remove specific read and write functionsRemove the driver specific write and read functions, usually in the form:{driver_name}_write , {driver_name}_read , {driver_name}_write_block , etc.Step 6: Update the write and read functions for the current I2C APIReplace all references of {driver_name}_write with i2c_smbus_write_byte_dataReplace all references of {driver_name}_read with i2c_smbus_read_byte_data ori2c_smbus_read_byte , depending on args passed in.** Ensure that these functions pass in the i2c_client *client , NOT thedecoder/encoder that was passed in the driver specific write and readfunctions.  Step 7: Modify the driver's attach functionChange the driver attach function prototype :{driver_name}_attach(struct i2c_device *device) --> {driver_name}_attach(struct i2c_adapter *adap, int addr , unsigned short flags, int kind)Create a i2c_client client...Add the following (where "decoder" is a reference to a struct for the driverinfo:struct i2c_client *client;client = kmalloc(sizeof(*client), GFP_KERNEL);if(client == NULL)	return -ENOMEM;client_template.adapter = adap;client_template.addr  = addr;memcpy(client, &client_template, sizeof(*client));strcpy(client->name , "{driver_name}");decoder->client = client;client->data = decoder;decoder->addr = addr;Towards the end of the function, add:init_MUTEX(&decoder->lock);i2c_attach_client(client);Step 8: Modify the driver's detach functionChange the driver detach function prototype :{driver_name}_detach(struct i2c_device *device) --> {driver_name}_detach(struct i2c_client *client)In the beginning of the detach function, add:i2c_detach_client(client);Towards the end of the detach function, add:kfree(client->data);kfree(client);Step 9: Modify the driver's command functionChange the driver command function prototype :Step 10: Add the probe function after the driver's attach function.Add the following code:static int {driver_name}_probe(struct i2c_adapter *adap){	return i2c_probe(adap, &addr_data, {driver_name}_attach);}Step 11: Modify the driver's i2c_driverFind the i2c_driver , such asstatic struct i2c_driver i2c_driver_saa7110It is usually located towards the end of the driver Replace the values from I2C_DRIVERID_{something} to {driver_name}_attach, and add the followingI2C_DRIVERID_{driver_name} , // verify by looking in include/linux/i2c-id.h I2C_DF_NOTIFY,{driver_name}_probe, ....Step 12: Adding the i2c_client Add the i2c_client to the driver. Add the following code:static struct i2c_client client_template = {	"{driver_name}_client",	-1,	0,	0,	NULL,	{i2c_driver reference}};Step 13: Registering and UnregisteringReplace i2c_register_driver with i2c_add_driverReplace i2c_unregister_driver with i2c_del_driver-------------------------------------------------------Example:The following patch provides the i2c coversion patch for the saa7110 driverbased on the above guide (for clarity).--- drivers/media/video/saa7110.c.old	Fri Jun 28 10:22:52 2002+++ drivers/media/video/saa7110.c	Thu Jul  4 16:51:08 2002@@ -26,7 +26,7 @@ #include <asm/io.h> #include <asm/uaccess.h> -#include <linux/i2c-old.h>+#include <linux/i2c.h> #include <linux/videodev.h> #include "linux/video_decoder.h" @@ -37,13 +37,31 @@  #define	I2C_SAA7110		0x9C	/* or 0x9E */ +#define IF_NAME	"saa7110" #define	I2C_DELAY		10	/* 10 us or 100khz */ +static unsigned short normal_i2c[] = {34>>1, I2C_CLIENT_END };+static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };+static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };+static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };+static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };+static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };++static struct i2c_client_address_data addr_data = {+	normal_i2c, normal_i2c_range,+	probe, probe_range,+	ignore, ignore_range,+	force+};++static struct i2c_client client_template;+ struct saa7110 {-	struct	i2c_bus	*bus;+	struct i2c_client *client; 	int		addr; 	unsigned char	reg[36];-+	struct semaphore lock; 	int		norm; 	int		input; 	int		enable;@@ -54,67 +72,10 @@ };  /* ----------------------------------------------------------------------- */-/* I2C support functions						   */-/* ----------------------------------------------------------------------- */-static-int saa7110_write(struct saa7110 *decoder, unsigned char subaddr, unsigned char data)-{-	int ack;--	LOCK_I2C_BUS(decoder->bus);-	i2c_start(decoder->bus);-	i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);-	i2c_sendbyte(decoder->bus, subaddr, I2C_DELAY);-	ack = i2c_sendbyte(decoder->bus, data, I2C_DELAY);-	i2c_stop(decoder->bus);-	decoder->reg[subaddr] = data;-	UNLOCK_I2C_BUS(decoder->bus);-	return ack;-}--static-int saa7110_write_block(struct saa7110* decoder, unsigned const char *data, unsigned int len)-{-	unsigned subaddr = *data;--	LOCK_I2C_BUS(decoder->bus);-        i2c_start(decoder->bus);-        i2c_sendbyte(decoder->bus,decoder->addr,I2C_DELAY);-	while (len-- > 0) {-                if (i2c_sendbyte(decoder->bus,*data,0)) {-                        i2c_stop(decoder->bus);-                        UNLOCK_I2C_BUS(decoder->bus);-                        return -EAGAIN;-                }-		decoder->reg[subaddr++] = *data++;-        }-	i2c_stop(decoder->bus);-	UNLOCK_I2C_BUS(decoder->bus);--	return 0;-}--static-int saa7110_read(struct saa7110* decoder)-{-	int data;--	LOCK_I2C_BUS(decoder->bus);-	i2c_start(decoder->bus);-	i2c_sendbyte(decoder->bus, decoder->addr, I2C_DELAY);-	i2c_start(decoder->bus);-	i2c_sendbyte(decoder->bus, decoder->addr | 1, I2C_DELAY);-	data = i2c_readbyte(decoder->bus, 1);-	i2c_stop(decoder->bus);-	UNLOCK_I2C_BUS(decoder->bus);-	return data;-}--/* ----------------------------------------------------------------------- */ /* SAA7110 functions							   */ /* ----------------------------------------------------------------------- */ static-int saa7110_selmux(struct i2c_device *device, int chan)+int saa7110_selmux(struct i2c_client *client, int chan) { static	const unsigned char modes[9][8] = { /* mode 0 */	{ 0x00, 0xD9, 0x17, 0x40, 0x03, 0x44, 0x75, 0x16 },@@ -126,61 +87,59 @@ /* mode 6 */	{ 0x80, 0x59, 0x17, 0x42, 0xA3, 0x44, 0x75, 0x12 }, /* mode 7 */	{ 0x80, 0x9A, 0x17, 0xB1, 0x13, 0x60, 0xB5, 0x14 }, /* mode 8 */	{ 0x80, 0x3C, 0x27, 0xC1, 0x23, 0x44, 0x75, 0x21 } };-	struct saa7110* decoder = device->data; 	const unsigned char* ptr = modes[chan]; -	saa7110_write(decoder,0x06,ptr[0]);	/* Luminance control	*/-	saa7110_write(decoder,0x20,ptr[1]);	/* Analog Control #1	*/-	saa7110_write(decoder,0x21,ptr[2]);	/* Analog Control #2	*/-	saa7110_write(decoder,0x22,ptr[3]);	/* Mixer Control #1	*/-	saa7110_write(decoder,0x2C,ptr[4]);	/* Mixer Control #2	*/-	saa7110_write(decoder,0x30,ptr[5]);	/* ADCs gain control	*/-	saa7110_write(decoder,0x31,ptr[6]);	/* Mixer Control #3	*/-	saa7110_write(decoder,0x21,ptr[7]);	/* Analog Control #2	*/+	i2c_smbus_write_byte_data(client,0x06,ptr[0]);	/* Luminance control	*/+	i2c_smbus_write_byte_data(client,0x20,ptr[1]);	/* Analog Control #1	*/+	i2c_smbus_write_byte_data(client,0x21,ptr[2]);	/* Analog Control #2	*/+	i2c_smbus_write_byte_data(client,0x22,ptr[3]);	/* Mixer Control #1	*/+	i2c_smbus_write_byte_data(client,0x2C,ptr[4]);	/* Mixer Control #2	*/+	i2c_smbus_write_byte_data(client,0x30,ptr[5]);	/* ADCs gain control	*/+	i2c_smbus_write_byte_data(client,0x31,ptr[6]);	/* Mixer Control #3	*/+	i2c_smbus_write_byte_data(client,0x21,ptr[7]);	/* Analog Control #2	*/  	return 0; }  static-int determine_norm(struct i2c_device* dev)+int determine_norm(struct i2c_client* client) {-	struct	saa7110* decoder = dev->data; 	int	status;  	/* mode changed, start automatic detection */-	status = saa7110_read(decoder);+	status = i2c_smbus_read_byte(client);

⌨️ 快捷键说明

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