转载于:http://blog.youkuaiyun.com/may627/article/details/8213068
1.首先,分析下FT5406的基本电路接口
- External Interface
- I2C/SPI: an interface for data exchange with host
- INT: an interrupt signal to inform the host processor that touch data is ready for read
- WAKE: an interrupt signal for the host to change F5x06 from Hibernate to Active mode
- /RST: an external low signal reset the chip.
WAKE:主要靠cpu发送一个唤醒指令给FT5406。
INT:GPIO0_A2。
/RST:复位,先输出低后输出高电平。
2.需确认FT5406的从地址,以便于I2C访问得到。这个可以根据FT5406数据手册查找到——0x38
首先配置 i2c_board_info,把从地址提供过去。
i2c_board_info用于构建信息表来列出存在的I2C设备。这一信息用于增长新型I2C驱动的驱动模型树。对于主板,它使用i2c_register_board_info()来静态创建。对于子板,利用已知的适配器使用i2c_new_device()动态创建。
//I2C 设备创建模板
- //mach-rk29/board-rk29-ddr3sdk.c
- struct i2c_board_info {
- char type[I2C_NAME_SIZE]; //芯片类型,用于初始化i2c_client.name
- unsigned short flags; //用于初始化i2c_client.flags
- unsigned short addr; //存储于i2c_client.addr
- void *platform_data; //存储于i2c_client.dev.platform_data
- struct dev_archdata *archdata; //拷贝至i2c_client.dev.archdata
- int irq; //存储于i2c_client.irq
- };
//使用Linux I2C驱动栈,系统可以在初始化时宣告板载信息表。这些应该在靠近arch_initcall()时的板子相关的初始化代码或同等情况时,在I2C适配器驱动被注册之前被执行。例如,主板初始化代码可以定义几个设备,也可以在叠板的每个子板初始化代码中定义。
//I2C设备会在相关的总线适配器被注册后创建。此后,标准驱动模型工具通常绑定新型I2C驱动至I2C设备。对于使用这一函数宣告的设备,在动态分配的情况下总线号是不可用的。
//传递的板子信息可以安全的是__initdata,但是由于不能拷贝,要小心嵌入式指针(如platform_data,functions等)
//静态的宣告I2C设备
在你对应的machine配置里会执行“i2c_register_board_info”一个函数,它会将一个i2c_board_info的结构体注册进系统,可以发现,在目录/sys/bus/i2c/devices下的设备就是这个i2c_board_info结构体里所描述的I2C设备,而/sys/bus/i2c/devices下的设备名字就是根据i2c_board_info结构体中定义的I2C Address来命名的。
所以添加一个I2C设备时,除了需要编写这个I2C设备的驱动之外,还需要在machine里面加入I2C设备的i2c_board_info内容。
- int i2c_register_board_info(int busnum, struct i2c_board_info const *info, unsigned len);
- @busnum: 指定这些设备属于哪个总线
- @info: I2C设备描述符向量
- @len: 向量中描述符的数量;为了预留特定的总线号,可以是0。
- i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
- static struct i2c_board_info __initdata board_i2c0_devices[] = {
- #if defined (CONFIG_TOUCHSCREEN_FT5406)
- {
- .type ="ft5x0x_ts",
- .addr = 0x38, //0x70,
- .flags =0,
- .irq =RK29_PIN0_PA2, // support goodix tp detect, 20110706
- .platform_data = &ft5406_info,
- },
- }
- struct ft5406_platform_data ft5406_info = {
- .init_platform_hw= ft5406_init_platform_hw, // TOUCH_RESET_PIN为输出,并先置高后置低;TOUCH_INT_PIN为输入IO。
- .exit_platform_hw= ft5406_exit_platform_hw,
- .platform_sleep = ft5406_platform_sleep,
- .platform_wakeup = ft5406_platform_wakeup,
- };
内核配置项中:
CONFIG_TOUCHSCREEN_FT5406:
\kernel\drivers\input\touchscreen
obj-$(CONFIG_TOUCHSCREEN_FT5406) += ft5x0x_i2c_ts.o
- fts_ts_probe(,)
- pdata->init_platform_hw(); //初始化IO口
- gpio_to_irq(client->irq); //设置IO口为IRQ
- request_irq(_sui_irq_num, fts_ts_irq, GPIOEdgelFalling, client->dev.driver->name, ft5x0x_ts);
- // 中断号 中断处理函数 下降沿触发
- disable_irq(_sui_irq_num); //关中断
- input_allocate_device(); //分配输入子系统
- __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); //配置响应的事件类型
- __set_bit(EV_ABS, input_dev->evbit);
- input_set_abs_params(input_dev,
- ABS_MT_POSITION_X, 0, SCREEN_MAX_X/* + SCREEN_BOUNDARY_ADJUST_VALUE*/, 0, 0);
- input_set_abs_params(input_dev,
- ABS_MT_POSITION_Y, 0, SCREEN_MAX_Y/* + SCREEN_BOUNDARY_ADJUST_VALUE*/, 0, 0);
- input_mt_init_slots(input_dev, CFG_MAX_POINT_NUM);
- input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
- input_register_device(input_dev); //注册输入设备
- ft5x0x_ts->early_suspend.suspend = ft5x0x_ts_early_suspend;
- ft5x0x_ts->early_suspend.resume = ft5x0x_ts_late_resume;
- init_timer(&ft5x0x_ts_timer);
- ft5x0x_ts_timer.function = ft5x0x_ts_do_timer; //fts_ts_release();超时未释放则释放中断
- enable_irq(_sui_irq_num);
- irqreturn_t fts_ts_irq(int irq, void *dev_id)
- queue_work(ft5x0x_ts->ts_workqueue, &ft5x0x_ts->pen_event_work); //具体任务是fts_work_func
- //fts_work_func(,)
- mod_timer(&ft5x0x_ts_timer ,jiffies + 6);
- fts_read_data();
- enable_irq(this_client->irq);