当前位置首页 > Linux知识

Linux的I2C设备驱动--mini2440上i2c接口触摸屏驱动2

阅读次数:298 次  来源:admin  发布时间:

本篇记录在友善之臂 mini2440 平台上挂载I2C接口触摸屏的驱动开发过程。

内核版本linux-2.6.32.2,

平台是ARM9 S3C2440+I2C接口的触摸屏

如上篇Linux的I2C驱动体系结构讲述

http://www.lupaworld.com/273398/viewspace-204237.html

要挂载新的I2C设备,需要实现3部分:

1) 适配器的硬件驱动:

内核中已经实现mini2440,i2c适配器驱动,可以在如下目录i2c-s3c2410.c中看到相关代码

linux-2.6.32.2/drivers/i2c/busses/i2c-s3c2410.c

2) I2C 设配器的algorithm

同样在inux-2.6.32.2/drivers/i2c/busses/i2c-s3c2410.c文件中实现。

以上两部分无须做任何更改

3) I2C设备驱动,可以以linux-2.6.32.2/drivers/input/touchscreen/migor_ts.c为例,分析如下:

//-------------------------------------------------------------------//

#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 */

truct i2c_ts_priv {

truct i2c_client *client

truct input_dev *input

truct delayed_work work

int irq

}

tatic void i2c_ts_poscheck(struct work_struct *work)

{

truct i2c_ts_priv *priv = container_of(work, struct i2c_ts_priv, work.work)

/* buffer for storing data */

char buf[6]

int number

int xpos, ypo

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 */

umber = 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 */

tatic irqreturn_t i2c_ts_isr(int irq, void *dev_id)

{

truct i2c_ts_priv *priv = dev_id

/* disable irq */

disable_irq_nosync(irq)

chedule_delayed_work(&priv->work, HZ/100)

return IRQ_HANDLED

}

tatic int i2c_ts_open(struct input_dev *dev)

{

return 0

}

tatic void i2c_ts_close(struct input_dev *dev)

{

}

tatic int i2c_ts_probe(struct i2c_client *client,

const struct i2c_device_id *idp)

{

truct i2c_ts_priv *priv

truct input_dev *input

int error

char buf[2]

riv = kzalloc(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_ope

input->close = i2c_ts_close

input_set_drvdata(input, priv)

riv->client = client

riv->input = input

INIT_DELAYED_WORK(&priv->work, i2c_ts_poscheck)

riv->irq = client->irq

error = input_register_device(input)

if (error)

goto err1

error = request_irq(priv->irq, i2c_ts_isr, IRQF_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

}

tatic int i2c_ts_remove(struct i2c_client *client)

{

truct 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

}

tatic int i2c_ts_suspend(struct i2c_client *client, pm_message_t mesg)

{

truct i2c_ts_priv *priv = dev_get_drvdata(&client->dev)

if(device_may_wakeup(&client->dev))

enable_irq_wake(priv->irq)

return 0

}

tatic int i2c_ts_resume(struct i2c_client *client)

{

truct i2c_ts_priv *priv = dev_get_drvdata(&client->dev)

if(device_may_wakeup(&client->dev))

disable_irq_wake(priv->irq)

return 0

}

tatic const struct i2c_device_id i2c_ts_id[] = {

{ "i2c-ts", 0 },

{ }

}

MODULE_DEVICE_TABLE(i2c, i2c_ts_id)

tatic 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,

}

tatic int __init i2c_ts_init(void)

{

return i2c_add_driver(&i2c_ts_driver)

}

tatic 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).实现如上步骤后,还需要创建和配置I2C 设备,设置文件位于

linux-2.6.32.2/arch/arm/mach-s3c2440/mach-mini2440.c中,

添加如下代码:

..................................................

+/* I2C touch screen devices. */

+/* bus configuration */

+static struct s3c2410_platform_i2c i2c_touchscreen_cfg __initdata = {

+ .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,

+ },

+}

...................................................

tatic void __init mini2440_machine_init(void)

{

..................................................

+ /* i2c touch screen devices */

+ s3c_i2c0_set_platdata(&i2c_touchscreen_cfg)

+ i2c_register_board_info(0, touchscreen_i2c_devs, +ARRAY_SIZE(touchscreen_i2c_devs))

...................................................

}

此处I2C_BOARD_INFO("i2c-ts",0x5c), “i2c-ts” 要和i2c设备驱动中i2c_ts_id一致。

才能保证i2c设备驱动成功加载。

上一篇:Linux基础-配置网络、集群内主机名设定、ssh登入、bash命令、通配符(元字符)
下一篇:Linux下安装JDK1.8