Linux内核---31.按键驱动分析(未完成)
1.0 按键设备的注册
按键设备的定义在arch/arm/mach-s3c64xx中
- /* gpio buttons */
- static struct gpio_keys_button gpio_buttons[] = {
- {
- .gpio = S3C64XX_GPN(0),
- //.code = 25,
- .code = KEY_UP,
- .desc = \"BUTTON1\",
- .active_low = 1,
- .wakeup = 0,
- },
- {
- .gpio = S3C64XX_GPN(1),
- //.code = 42,
- .code = KEY_DOWN,
- .desc = \"BUTTON2\",
- .active_low = 1,
- .wakeup = 0,
- },
- {
- .gpio = S3C64XX_GPN(2),
- //.code = 50,
- .code = KEY_LEFT,
- .desc = \"BUTTON3\",
- .active_low = 1,
- .wakeup = 0,
- },
- {
- .gpio = S3C64XX_GPN(3),
- //.code = 10,
- .code = KEY_RIGHT,
- .desc = \"BUTTON4\",
- .active_low = 1,
- .wakeup = 0,
- },
- {
- .gpio = S3C64XX_GPN(4),
- //.code = 24,
- .code = KEY_ENTER,
- .desc = \"BUTTON5\",
- .active_low = 1,
- .wakeup = 0,
- },
- {
- .gpio = S3C64XX_GPN(5),
- //.code = 38,
- .code = KEY_ESC,
- .desc = \"BUTTON6\",
- .active_low = 1,
- .wakeup = 0,
- }
- };
- static struct gpio_keys_platform_data gpio_button_data = {
- .buttons = gpio_buttons,
- .nbuttons = ARRAY_SIZE(gpio_buttons),
- };
- static struct platform_device gpio_button_device = {
- .name = \"gpio-keys\",
- .id = -1,
- .num_resources = 0,
- .dev = {
- .platform_data = &gpio_button_data,
- }
- };
- static struct platform_device *smdk6410_devices[] __initdata = {
- &gpio_button_device, //把key_button添加到总的设备列表中
- }
- //在arch/arm/mach-s3c64xx/mach-smdk6410.c中
- static void __init smdk6410_machine_init(void)
- {
- //在driver/base/platform.c中一起注册
- platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
- }
二. device_driver
Device Drivers --->
Input device support --->
[*] Keyboards --->
<*> GPIO Buttons
<*> Samsung keypad support
2.0 两个宏
- #define WAIT4INT(x) //只是针对于S3C_ADCTSC寄存器
- (((x)<<8) | //<bit8> 0->down 1->up interrupt signal
- S3C_ADCTSC_YM_SEN | //<bit7> 1 = Switch enable (YM = VSSA_ADC)
- S3C_ADCTSC_YP_SEN | //<bit6> 1 = Switch disable (YP=AIN5, Hi-z)
- //XM_SEN //<bit5> 0 = Switch disable (XM = AIN6, Hi-z)
- S3C_ADCTSC_XP_SEN | //<bit4> 1 = Switch disable (XP=AIN7, Hi-z)
- //PULL_UP //<bit3> 0 = XP Pull-up Enable.
- //AUTO_PST //<bit2> 0 = Normal ADC conversion.
- S3C_ADCTSC_XY_PST(3)) //<bit1-0> 3: Waiting for Interrupt Mode
- #define AUTOPST
- (S3C_ADCTSC_YM_SEN | //1 = Switch enable (YM = VSSA_ADC)
- S3C_ADCTSC_YP_SEN | //1 = Switch disable (YP=AIN5, Hi-z)
- S3C_ADCTSC_XP_SEN | //1 = Switch disable (XP=AIN7, Hi-z)
- S3C_ADCTSC_AUTO_PST | //1 = Auto Sequential measurement of X-position, Y-position
- S3C_ADCTSC_XY_PST(0)) //0 = No operation mode
WAIT4INT(x) :
当x=0时,设为等侍down中断
当x=1时,设为等侍up中断
2.1 初始化
ok6410的touchscreen在内核源码的位置:driver/input/touchscreen/s3c-ts.c
device 与 device_driver按名字s3c-ts匹配之后,就进入s3c_ts_probe 函数
- static struct platform_driver s3c_ts_driver = {
- .probe = s3c_ts_probe,
- .remove = s3c_ts_remove,
- .suspend = s3c_ts_suspend,
- .resume = s3c_ts_resume,
- .driver = {
- .owner = THIS_MODULE,
- .name = "s3c-ts",
- },
- };
- static int __init s3c_ts_init(void)
- {
- return platform_driver_register(&s3c_ts_driver);
- }
- static void __exit s3c_ts_exit(void)
- {
- platform_driver_unregister(&s3c_ts_driver);
- }
- module_init(s3c_ts_init);
- module_exit(s3c_ts_exit);
2.2 probe函数
- static int __init s3c_ts_probe(struct platform_device *pdev)
- {
- struct resource *res;
- struct device *dev;
- struct input_dev *input_dev;
- struct s3c_ts_mach_info * s3c_ts_cfg;
- int ret, size;
- dev = &pdev->dev;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取ts寄存器地址
- size = (res->end - res->start) + 1;
- ts_mem = request_mem_region(res->start, size, pdev->name); //申请I/O内存
- ts_base = ioremap(res->start, size); //request_mem_region申请的内存在使用前要调用ioremap
- ts_clock = clk_get(&pdev->dev, "adc"); //获取clock
- clk_enable(ts_clock); //在初始化时disable了ts_clock,这个地方要enable
- //下面这几行是要把ts的配置信息写到寄存器中去
- s3c_ts_cfg = s3c_ts_get_platdata(&pdev->dev); //获取ts的配置信息,
- //ts的私有信息:在arch/arm/mach-s3c64xx/mach-smdk6410.c中
- //enable prescaler && 设置prescaler_value=s3c_ts_cfg->presc
- writel(S3C_ADCCON_PRSCEN | S3C_ADCCON_PRSCVL(s3c_ts_cfg->presc&0xff), ts_base+S3C_ADCCON);
- //s3c_ts_cfg->delay=0x10000 --> External input clock
- writel(s3c_ts_cfg->delay & 0xffff, ts_base+S3C_ADCDLY);
- //A/D converter resolution selection--> 12-bit A/D conversion
- writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT, ts_base+S3C_ADCCON);
- //设为等侍down中断模式
- writel(WAIT4INT(0), ts_base+S3C_ADCTSC);
- ts = kzalloc(sizeof(struct s3c_ts_info), GFP_KERNEL); //下面这几行是要初始化s3c_ts_info结构体
- input_dev = input_allocate_device();
- ts->dev = input_dev;
- ts->dev->evbit[0] = ts->dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
- ts->dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
- if (s3c_ts_cfg->resol_bit==12) {
- input_set_abs_params(ts->dev, ABS_X, 0, 0xFFF, 0, 0); //设置x轴的最大最小值
- input_set_abs_params(ts->dev, ABS_Y, 0, 0xFFF, 0, 0); //设置y轴的最大最小值
- }
- input_set_abs_params(ts->dev, ABS_PRESSURE, 0, 1, 0, 0); //设置Press状态的最大最小值(按下或空闲)
- sprintf(ts->phys, "input(ts)");
- ts->dev->name = s3c_ts_name;
- ts->dev->phys = ts->phys;
- ts->dev->id.bustype = BUS_RS232;
- ts->dev->id.vendor = 0xDEAD;
- ts->dev->id.product = 0xBEEF;
- ts->dev->id.version = S3C_TSVERSION;
- ts->shift = s3c_ts_cfg->oversampling_shift;
- ts->resol_bit = s3c_ts_cfg->resol_bit;
- ts->s3c_adc_con = s3c_ts_cfg->s3c_adc_con;
- /* For IRQ_PENDUP */
- ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); //获取中断号
- //申请中断,RANDOM表示设备可以看作随机的发生源
- ret = request_irq(ts_irq->start, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c_updown", ts); //申请中断
- /* For IRQ_ADC */
- ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1); //获取中断号
- ret = request_irq(ts_irq->start, stylus_action, IRQF_SAMPLE_RANDOM | IRQF_SHARED, "s3c_action", ts); //申请共享中断
- /* All went ok, so register to the input system */
- ret = input_register_device(ts->dev); //把这个input_dev添加到input系统中
- }
ts底板图:
ts连到核心板图:
TSXP --> AIN7
TSYP --> AIN5
2.3 IRQ_PENDN
- static irqreturn_t stylus_updown(int irqno, void *param)
- {
- unsigned long data0;
- unsigned long data1;
- if (!ADC_locked4TS()) //进入中断函数,如果没有加锁,则加上锁
- if (s3c_ts_adc_lock(LOCK_TS)) //如果加锁失败,则直接返回
- return IRQ_HANDLED;
- data0 = readl(ts_base+S3C_ADCDAT0);
- data1 = readl(ts_base+S3C_ADCDAT1);
- touch_timer_fire(0);
- if(ts->s3c_adc_con==ADC_TYPE_2) {
- //ADCCLRINTPNDNUP: INT_PNDNUP interrupt clear
- __raw_writel(0x0, ts_base+S3C_ADCCLRWK);
- //ADCCLRINT: Clear ADC Interrupt
- __raw_writel(0x0, ts_base+S3C_ADCCLRINT);
- }
- return IRQ_HANDLED;
- }
2.3.1 fire
- static void touch_timer_fire(unsigned long data)
- {
- unsigned long data0;
- unsigned long data1;
- int pendown;
- if (!ADC_locked4TS()) //如果当前状态是free,说明加锁失败,直接返回
- return;
- //这儿的数据读取,是为了判断是down还是up状态
- data0 = readl(ts_base+S3C_ADCDAT0); //读
- data1 = readl(ts_base+S3C_ADCDAT1); //读
- //data0的bit15: 0->按下状态; 1->松开状态
- //如果data0与data1都不为松开状态,就是按下状态
- pendown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN));
- if (pendown) <
Linux内核---31.按键驱动分析(未完成)相关推荐
- linux内核SPI总线驱动分析(一)
下面有两个大的模块: 一个是SPI总线驱动的分析 (研究了具体实现的过程) 另一个是SPI总线驱动的编写(不用研究具体的实现过程) SPI总线驱动分析 1 SPI概述 ...
- linux内核spi总线驱动分析,Linux下的SPI总线驱动(三)
版权所有,转载请说明转自 原创作者:南京邮电大学 通信与信息系统专业 研二 魏清 五.SPI测试代码 对于SPI总线驱动,我们可以分为SPI控制设备驱动和SPI接口设备驱动.而作为驱动开发人员主要是 ...
- Linux内核---30.触摸屏驱动分析
查看input系统 root@OK6410:~# cat /proc/bus/input/devices I: Bus=0013 Vendor=dead Product=beef Version=01 ...
- 【Linux驱动开发】Linux 自带按键驱动
一.基础 1.以下介绍了 input 子系统的基础,使用的自己编的按键驱动.实际上内核自带了按键驱动(一般默认使能). [Linux驱动开发]INPUT 子系统实验 2.内核自带按键驱动简介 Linu ...
- Linux内核的Nand驱动流程分析
最近在做Linux内核移植,总体的感觉是这样的,想要彻底的阅读Linux内核代码几乎是不可能的,至少这还不是嵌入式学期初期的重要任务.内核代码解压后有250M左右,据统计,有400多万行,而且涉及到了 ...
- Linux keypad 设备树,matrix_keypad 矩阵按键驱动分析
matrix_keypad 矩阵按键驱动分析 //主要函数调用过程 matrix_keypad_probe matrix_keypad_parse_dt //根据设备树构造 pdata pdata-& ...
- 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Linux内核抢占实现机制分析
Linux内核抢占实现机制分析 Sailor_forever sailing_9806@163.com 转载请注明 http://blog.csdn.net/sailor_8318/archive/ ...
- 【usb】linux内核USB键盘驱动解析--普通键值上报及转化
一.概况 建议阅读前置文章[usb]linux内核USB键盘驱动解析–特殊键值上报及转化 以Linux5.10内核中USB键盘驱动为例进行解析:https://mirrors.edge.kernel. ...
- linux pl320 mbox控制器驱动分析 - (1) pl320手册分析
linux pl320 mbox控制器驱动分析 1 pl320简介 1.1 pl320用途 1.2 pl320 IPCM 由以下部分组成: 1.3 pl320 IPCM可配置的参数 1.4 功能操作 ...
最新文章
- 使用leangoo做多团队敏捷开发项目管理
- B树和B+树分别是什么?区别在哪里?MySQL使用的是哪一种树?
- servlet知识点
- 图像降噪算法——时域降噪算法
- 项目进度管理:规划项目进度管理
- 软设考试笔记--数据库系统
- 【源码】net_device结构
- 论文浅尝 | PairRE: 通过成对的关系向量实现知识图谱嵌入
- 如何正确地使用#region指令
- 世界质量大师登场,告诉你质量的最大秘密!【优思学院】
- imx6ul pinctrl 驱动浅析
- cad转图片格式后不清晰怎么办?三步即可解决
- 平面向量内积坐标公式推导_向量的数量积的坐标运算公式是如何推导出的 两个向量的向量积公式是怎...
- IK如何实现同义词搜索
- oracle中todate函数实例,pl/sql to_date 函数使用实例讲解
- hexo+yilia添加背景特效
- 新手怎样才能快速的学会建网站
- docker创建CentOS云主机(docker实践)
- 变焦 焦距 等效焦距
- Kettle 实现数据同步
热门文章
- 手把手教你实现在Monaco Editor中使用VSCode主题
- 【Java案例】图形的面积与周长计算程序
- 手机中微信无法直接打开棋牌游戏类app下载链怎么办?
- oracle 索引 种类,详解 Navicat for Oracle 索引类型
- 降噪音质好的耳机推荐,2021年降噪耳机排行!
- matlab画图 legend的位置
- HTML表格无法保存图片,怎样将EXCLE表格或HTML保存为图片形式? | excle怎么存成图片的格式...
- Selenium基础 — 键盘操作
- selenium实现12306火车购票网站滑块自动验证登录
- Java基于springmvc实现文档预览(openoffice+swftools+flexpaper)(排坑记录)