Linux I2C Device Driver-I2C interface touch screen driver on mini2440

Source: Internet
Author: User

This document describes how to develop an I2C interface touch screen driver mounted on the friendly mini-2440 platform.

Kernel edition linux-2.6.32.2,
The platform is a touch screen with the arm9-s3c2440 + I2C interface.

For exampleLinux I2C driver architectureDescription
Http://www.lupaworld.com/273398/viewspace-204237.html

To mount a new I2C device, you need to implement three parts:

1) adapter hardware driver:
The kernel has implemented the mini2440, I2C Adapter Driver, you can see the relevant in the following directory i2c-s3c2410.cCode
Linux-2.6.32.2/Drivers/I2C/busses/i2c-s3c2410.c

2) algorithm with memory configured for I2C
Also implemented in inux-2.6.32.2/Drivers/I2C/busses/i2c-s3c2410.c files.

No changes are required for the above two parts.

3) I2C Device Driver, can take linux-2.6.32.2/Drivers/input/touchscreen/migor_ts.c as an example, the analysis is as follows:
//-------------------------------------------------------------------//
# Include <Linux/module. h>
# Include <Linux/kernel. h>
# Include <Linux/input. h>
# Include <Linux/interrupt. h>
# Include <ASM/IO. h>
# Include <Linux/I2C. h>
# Include <Linux/Timer. h>
# Include <Linux/delay. h>

/* Resolution definion according to touch screen */
# Define min_x_coordinate 0
# Define max_x_coordinate 1024
# Define min_y_coordinate 0
# Define max_y_coordinate 768

/* Touch Screen Data Structure */
Struct i2c_ts_priv {
Struct i2c_client * client;
Struct input_dev * input;
Struct delayed_work work;
Int IRQ;
};

Static void i2c_ts_poscheck (struct work_struct * Work)
{
Struct i2c_ts_priv * priv = container_of (work, struct i2c_ts_priv, work. Work );
/* Buffer for storing data */
Char Buf [6];
Int number;
Int xpos, ypos;

Memset (BUF, 0, sizeof (BUF ));

/* Now do page read */
If (i2c_master_recv (priv-> client, Buf, 6 )! = 6 ){
Dev_err (& priv-> client-> Dev, "unable to read I2C Page \ n ");
Goto out;
}

/* Convert coordinate */
Number = Buf [0] & 0x07;
Xpos = (BUF [3] <8) | Buf [2]);
Ypos = (BUF [5] <8) | Buf [4]);

/* Report input event */
If (number! = 0) & (xpos! = 0) & (ypos! = 0 )){
Input_report_key (priv-> input, btn_touch, 1 );
Input_report_abs (priv-> input, abs_x, xpos );
Input_report_abs (priv-> input, abs_y, ypos );
Input_sync (priv-> input );
} Else if (number = 0 ){
Input_report_key (priv-> input, btn_touch, 0 );
Input_sync (priv-> input );
}

Out:
Enable_irq (priv-> IRQ );
}

/* Read finger numbers and coordinate and report input event */
Static irqreturn_t i2c_ts_isr (int irq, void * dev_id)
{
Struct i2c_ts_priv * priv = dev_id;

/* Disable IRQ */
Disable_irq_nosync (IRQ );
Schedule_delayed_work (& priv-> Work, Hz/100 );
Return irq_handled;
}

Static int i2c_ts_open (struct input_dev * Dev)
{
Return 0;
}

Static void i2c_ts_close (struct input_dev * Dev)
{

}

Static int i2c_ts_probe (struct i2c_client * client,
Const struct i2c_device_id * IDP)
{
Struct i2c_ts_priv * priv;
Struct input_dev * input;
Int error;
Char Buf [2];

Priv = kzarloc (sizeof (* priv), gfp_kernel );
If (! Priv ){
Dev_err (& client-> Dev, "failed to allocate driver data \ n ");
Error =-enomem;
Goto err0;
}

Dev_set_drvdata (& client-> Dev, priv );

Input = input_allocate_device ();
If (! Input ){
Dev_err (& client-> Dev, "failed to allocate input device. \ n ");
Error =-enomem;
Goto err1;
}

Input-> evbit [0] = bit_mask (ev_key) | bit_mask (ev_abs );
Input-> keybit [bit_word (btn_touch)] = bit_mask (btn_touch );

Input_set_abs_params (input, abs_x, min_x_coordinate, max_x_coordinate, 0, 0 );
Input_set_abs_params (input, abs_y, min_y_coordinate, max_y_coordinate, 0, 0 );

Input-> name = client-> name;
Input-> ID. bustype = bus_i2c;
Input-> Dev. Parent = & client-> dev;

Input-> open = i2c_ts_open;
Input-> close = i2c_ts_close;

Input_set_drvdata (input, priv );

Priv-> client = client;
Priv-> input = input;
Init_delayed_work (& priv-> Work, i2c_ts_poscheck );
Priv-> IRQ = client-> IRQ;

Error = input_register_device (input );
If (error)
Goto err1;

Error = request_irq (priv-> IRQ, i2c_ts_isr, ir1__trigger_falling,
Client-> name, priv );
If (error ){
Dev_err (& client-> Dev, "unable to request touchscreen IRQ. \ n ");
Goto err2;
}

Device_init_wakeup (& client-> Dev, 1 );

Return 0;

Err2:
Input_unregister_device (input );
Input = NULL;/* so we dont try to free it below */
Err1:
Input_free_device (input );
Kfree (priv );
Err0:
Dev_set_drvdata (& client-> Dev, null );
Return Error;
}

Static int i2c_ts_remove (struct i2c_client * client)
{
Struct i2c_ts_priv * priv = dev_get_drvdata (& client-> Dev );

Free_irq (priv-> IRQ, priv );
Input_unregister_device (priv-> input );
Kfree (priv );

Dev_set_drvdata (& client-> Dev, null );

Return 0;
}

Static int i2c_ts_suspend (struct i2c_client * client, pm_message_t mesg)
{
Struct i2c_ts_priv * priv = dev_get_drvdata (& client-> Dev );
If (device_may_wakeup (& client-> Dev ))
Enable_irq_wake (priv-> IRQ );
Return 0;
}

Static int i2c_ts_resume (struct i2c_client * client)
{
Struct i2c_ts_priv * priv = dev_get_drvdata (& client-> Dev );
If (device_may_wakeup (& client-> Dev ))
Disable_irq_wake (priv-> IRQ );
Return 0;
}

Static const struct i2c_device_id i2c_ts_id [] = {
{"I2c-ts", 0 },
{}
};
Module_device_table (I2C, i2c_ts_id );

Static struct i2c_driver i2c_ts_driver = {
. Driver = {
. Name = "i2c-ts ",
},
. Probe = i2c_ts_probe,
. Remove = i2c_ts_remove,
. Suspend = i2c_ts_suspend,
. Resume = i2c_ts_resume,
. Id_table = i2c_ts_id,
};

Static int _ init i2c_ts_init (void)
{
Return i2c_add_driver (& i2c_ts_driver );
}

Static void _ exit i2c_ts_exit (void)
{
I2c_del_driver (& i2c_ts_driver );
}

Module_description ("I2C touchscreen driver ");
Module_author ("Allen <allen.p.wang@gmail.com> ");
Module_license ("GPL ");

Module_init (i2c_ts_init );
Module_exit (i2c_ts_exit );

4 ). after completing this step, you also need to create and configure the I2C device where the setup file is located in
linux-2.6.32.2/ARCH/ARM/mach-s3c2440/mach-mini2440.c,
Add the following code:
................................. .................
+/* I2C touch screen devices. */
+/* bus configuration */
+ static struct s3c2410_platform_i2c i2c_touchscreen_cfg _ initdata ={< br> +. flags = 0,
+. slave_addr = 0x5c,
+. frequency = 100*1000,
+. sda_delay = 2,
+};

+/* I2C device name is "i2c_ts", address is 0x5c, interrupt is eint20 */
+ Static struct i2c_board_info touchscreen_i2c_devs [] _ initdata = {
+ {
+ I2c_board_info ("i2c-ts", 0x5c ),
+. IRQ = irq_eint20,
+ },
+ };
........................................ ...........

Static void _ init mini2440_machine_init (void)
{
........................................ ..........
+/* I2C touch screen devices */
+ Maid (& i2c_touchscreen_cfg );
+ I2c_register_board_info (0, touchscreen_i2c_devs, + array_size (touchscreen_i2c_devs ));
........................................ ...........
}

Here i2c_board_info ("i2c-ts", 0x5c), "i2c-ts" should be consistent with i2c_ts_id In the I2C device driver.
In order to ensure that the I2C device driver is loaded successfully.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.