Reproduced in front of a lot of articles on I2C, to finish a project, but also to write their own points I2C experience, I this is a pure application angle, want to see the principle, to see reprinted articles, people write a lot better.
For a I2C device, the device file is the simplest and most complex, saying it's simple because it's very easy to provide code under Linux, but there are a lot of vendors that don't provide or do not provide Linux code, which is complicated. Then this I now do not say, the following said a few I2C equipment (take ISA1200 as an example) after discovering that no matter how the device files are always to do some things themselves, this is probably the so-called transplant bar.
Of course, this work is done in the board file. Take mach-s5pv210.c for example:
First of all, with the board of their own I2C implementation drive loading:
First, create ISA1200 information in the board file:
static int isa1200_power (int on)
{
if (ON) {
Gpio_direction_output (S5PV210_GPJ3 (1), 1);
Gpio_direction_output (s5pv210_gpj3 (0), 1);
}else{
Gpio_direction_output (S5PV210_GPJ3 (1), 0);
Gpio_direction_output (s5pv210_gpj3 (0), 0);
}
return 0;
}
static struct Isa1200_platform_data Isa1200_1_pdata = {
. Name = "Isa1200",
. power_on = Isa1200_power,
. pwm_ch_id = 1,
. Hap_en_gpio = S5pv210_gph3 (1),
. Max_timeout = 60000,
};
static void Isa1200_init (void)
{
Gpio_direction_output (S5PV210_GPJ3 (7), 1);
Gpio_direction_output (S5PV210_GPJ3 (1), 1);
Gpio_direction_output (s5pv210_gpj3 (0), 1);
/*i2c_register_board_info (3, Isa1200_board_info,
Array_size (Isa1200_board_info));
Return
}
and I2c_board_info structure:
{
I2c_board_info ("Isa1200_1", 0x90>>1),/* This is the I2C device's address from the machine * *
. Platform_data = &isa1200_1_pdata,
},
Then find one of the following three I2C buses such as i2c_devs1[]
* I2C0 * *
static struct I2c_board_info i2c_devs0[] __initdata = {
{
I2c_board_info ("act8937", 0x5b),
. Platform_data = &act8937_platform_data,
},
{
I2c_board_info ("wm8580", 0x1b),
},
};
* I2C1 * *
static struct I2c_board_info i2c_devs1[] __initdata = {
#ifdef CONFIG_VIDEO_TV20
{
I2c_board_info ("S5P_DDC", (0x74>>1)),
},
#endif
};
* I2C2 * *
static struct I2c_board_info i2c_devs2[] __initdata = {
#ifdef config_regulator_max8698
{
/* The address is 0xCC used since Srad = 0 * *
I2c_board_info ("max8698", (0xCC >> 1)),
. Platform_data = &max8698_platform_data,
},
#endif
Fill in the I2c_board_info
* I2C1 * *
static struct I2c_board_info i2c_devs1[] __initdata = {
#ifdef CONFIG_VIDEO_TV20
{
I2c_board_info ("S5P_DDC", (0x74>>1)),
},
{
I2c_board_info ("Isa1200_1", 0x90>>1),/* This is the I2C device's address from the machine * *
. Platform_data = &isa1200_1_pdata,
},
#endif
};
This is to put the ISA1200 on the i2c1, the things they do is completed. The next thing is the bus itself:
First it adds itself to the Platform_device, which is registered on the Platform_device bus:
static struct Platform_device *smdkv210_devices[] __initdata = {
......
&S3C_DEVICE_I2C1,
......
}
Adding the I2C1 bus to the device initialization i2c_register_board_info Let it add the i2c_devs1[list to the devices on the bus i2c1 (that is, all devices registered to I2c_board_info i2c1).
static void __init smdkv210_machine_init (void)
{
......
I2c_register_board_info (1, I2C_DEVS1, Array_size (I2C_DEVS1));
......
}
Let's talk about the Gpio analog I2C implementation driver loading:
The most important here is of course the successful registration of a i2c_gpio_w380:
The first is to find the CLK and SDA corresponding to the GPIO port:
CLK:GPA1[3]
SDA:GPA1[2]
Then build the I2C-GPIO platform_device structure:
static struct I2c_gpio_platform_data I2c_gpio_w380_data = {
. Scl_pin = S5PV210_GPA1 (3),
. Sda_pin = S5PV210_GPA1 (2),
};
static struct Platform_device i2c_gpio_w380= {
. Name = "I2c-gpio", * This name should be consistent with the name in I2c-gpio.c Platform_driver, in other words, the I2C to be used for this GPIO driver is defined in I2c-gpio.
. id = 3,/* This number to the system's original 0,1,2 write down, and then one to use 4, according to this recursive * *
. Dev = {
. Platform_data = &i2c_gpio_w380_data,
},
};
This completes the work of registering two gpio ports as a I2C bus.
The next step is to implement the driver loading method with the I2C of the board itself:
The first is to create ISA1200 information in the board file:
static int isa1200_power (int on)
{
if (ON) {
Gpio_direction_output (S5PV210_GPJ3 (1), 1);
Gpio_direction_output (s5pv210_gpj3 (0), 1);
}else{
Gpio_direction_output (S5PV210_GPJ3 (1), 0);
Gpio_direction_output (s5pv210_gpj3 (0), 0);
}
return 0;
}
static struct Isa1200_platform_data Isa1200_1_pdata = {
. Name = "Isa1200",
. power_on = Isa1200_power,
. pwm_ch_id = 1,
. Hap_en_gpio = S5pv210_gph3 (1),
. Max_timeout = 60000,
};
static void Isa1200_init (void)
{
Gpio_direction_output (S5PV210_GPJ3 (1), 1);
Gpio_direction_output (s5pv210_gpj3 (0), 1);
/*i2c_register_board_info (3, Isa1200_board_info,
Array_size (Isa1200_board_info));
Return
}
and I2c_board_info structure:
{
I2c_board_info ("Isa1200_1", 0x90>>1),/* This is the I2C device's address from the machine * *
. Platform_data = &isa1200_1_pdata,
},
Then add a isa1200 i2c_board_info[to the i2c_gpio_w380 bus]
/* i2c-gpio*/
static struct I2c_board_info i2c_devs3[] __initdata= {
{
I2c_board_info ("Isa1200_1", 0x90>>1),
. Platform_data = &isa1200_1_pdata,
},
};
This is to put the ISA1200 on the i2c_gpio_w380, the things they do is completed. The next thing is the bus itself:
First of all, it will add its own i2c_gpio_w380 to the Platform_device, that is, register to the Platform_device bus:
static struct Platform_device *smdkv210_devices[] __initdata = {
......
&i2c_gpio_w380,
......
}
Then add the i2c_gpio_w380 bus to the device initialization i2c_register_board_info Let it put the bus i2c_gpio_w380 on the device (that is, register to I2c_board_info i2c_devs3[] Adds a list of i2c_gpio_w380 to all devices on the
static void __init smdkv210_machine_init (void)
{
......
I2c_register_board_info (3, I2C_DEVS3, Array_size (I2C_DEVS3));
......
}
The above is the end of a device ISA1200 hook on the Gpio analog I2C bus i2c_gpio_w380. Here the device ISA1200 device file isa1200.c can be called I2C i2c_smbus_write_byte_data,i2c_smbus_read_byte_data functions.
If you want to make two gpio mouth again into the I2C bus register into a i2c_gpio_w380_1:
The first is to find the CLK and SDA corresponding to the GPIO port:
CLK:GPC0[1]
SDA:GPC0[2],
You can do this:
static struct I2c_gpio_platform_data I2c_gpio_w380_1_data= {
. Sda_pin = s5pv210_gpc0 (2),
. Scl_pin = s5pv210_gpc0 (1),
};
static struct Platform_device i2c_gpio_w380_1= {
. Name = "I2c-gpio",///I2c-gpio driver/*
. ID = 4,/* above registered 3, postponed to the 4*/
. Dev = {
. Platform_data = &i2c_gpio_w380_1_data,
}
};
static struct I2c_board_info i2c_devs4[] __initdata= {
{
I2c_board_info ("al3000", address),
},
};
static struct Platform_device *smdkv210_devices[] __initdata = {
......
&i2c_gpio_w380_1,
......
}
static void __init smdkv210_machine_init (void)
{
......
I2c_register_board_info (4, I2C_DEVS4, Array_size (I2C_DEVS4));
......
}
another is the use of Gpio to simulate the I2C time series, which is done separately in the device file. such as:
/*****stop previous seccession and generate START seccession *********************/
void I2c_start (void)
{Set_i2c_scl_high ();
Set_i2c_sda_low ();
Set_i2c_sda_output (); SDA = 0;
Set_i2c_sda_high (); SDA = 1, Stop previous I2C r/w action
Set_i2c_sda_low (); I2C Start Condition
}
/***************** generate I2C Repeat Start **************/
void Repeatstart (void)
{Set_i2c_scl_low ();
Set_i2c_sda_high ();
Set_i2c_sda_output ();
Set_i