Linux内核---31.按键驱动分析(未完成)

一. device的注册
1.0 按键设备的注册

按键设备的定义在arch/arm/mach-s3c64xx中

  1. /* gpio buttons */
  2. static struct gpio_keys_button gpio_buttons[] = {
  3.     {
  4.         .gpio        = S3C64XX_GPN(0),
  5.         //.code        = 25,
  6.         .code        = KEY_UP,
  7.         .desc        = \"BUTTON1\",
  8.         .active_low    = 1,
  9.         .wakeup        = 0,
  10.     },
  11.     {
  12.         .gpio        = S3C64XX_GPN(1),
  13.         //.code        = 42,
  14.         .code        = KEY_DOWN,
  15.         .desc        = \"BUTTON2\",
  16.         .active_low    = 1,
  17.         .wakeup        = 0,
  18.     },
  19.     {
  20.         .gpio        = S3C64XX_GPN(2),
  21.         //.code        = 50,
  22.         .code        = KEY_LEFT,
  23.         .desc        = \"BUTTON3\",
  24.         .active_low    = 1,
  25.         .wakeup        = 0,
  26.     },
  27.     {
  28.         .gpio        = S3C64XX_GPN(3),
  29.         //.code        = 10,
  30.         .code        = KEY_RIGHT,
  31.         .desc        = \"BUTTON4\",
  32.         .active_low    = 1,
  33.         .wakeup        = 0,
  34.     },
  35.     {
  36.         .gpio        = S3C64XX_GPN(4),
  37.         //.code        = 24,
  38.         .code        = KEY_ENTER,
  39.         .desc        = \"BUTTON5\",
  40.         .active_low    = 1,
  41.         .wakeup        = 0,
  42.     },
  43.     {
  44.         .gpio        = S3C64XX_GPN(5),
  45.         //.code        = 38,
  46.         .code        = KEY_ESC,
  47.         .desc        = \"BUTTON6\",
  48.         .active_low    = 1,
  49.         .wakeup        = 0,
  50.     }
  51. };

  52. static struct gpio_keys_platform_data gpio_button_data = {
  53.     .buttons    = gpio_buttons,
  54.     .nbuttons    = ARRAY_SIZE(gpio_buttons),
  55. };

  56. static struct platform_device gpio_button_device = {
  57.     .name        = \"gpio-keys\",
  58.     .id        = -1,
  59.     .num_resources    = 0,
  60.     .dev        = {
  61.         .platform_data    = &gpio_button_data,
  62.     }
  63. };
  64. static struct platform_device *smdk6410_devices[] __initdata = {
  65.     &gpio_button_device,        //把key_button添加到总的设备列表中
  66. }

  67. //在arch/arm/mach-s3c64xx/mach-smdk6410.c中
  68. static void __init smdk6410_machine_init(void)
  69. {
  70.     //在driver/base/platform.c中一起注册
  71.     platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
  72. }


二. device_driver
 Device Drivers  --->
          Input device support  --->
               [*]   Keyboards  --->
                    <*>   GPIO Buttons 
                    <*>   Samsung keypad support
2.0 两个宏
  1. #define WAIT4INT(x)              //只是针对于S3C_ADCTSC寄存器
  2.         (((x)<<8) |              //<bit8> 0->down 1->up interrupt signal
  3.         S3C_ADCTSC_YM_SEN |      //<bit7> 1 = Switch enable (YM = VSSA_ADC)
  4.         S3C_ADCTSC_YP_SEN |      //<bit6> 1 = Switch disable (YP=AIN5, Hi-z) 
  5.         //XM_SEN                //<bit5> 0 = Switch disable (XM = AIN6, Hi-z)
  6.         S3C_ADCTSC_XP_SEN |      //<bit4> 1 = Switch disable (XP=AIN7, Hi-z)
  7.         //PULL_UP               //<bit3> 0 = XP Pull-up Enable.
  8.         //AUTO_PST              //<bit2> 0 = Normal ADC conversion.         
  9.         S3C_ADCTSC_XY_PST(3))    //<bit1-0> 3: Waiting for Interrupt Mode 

  10. #define AUTOPST     
  11.     (S3C_ADCTSC_YM_SEN |        //= Switch enable (YM = VSSA_ADC)
  12.     S3C_ADCTSC_YP_SEN |         //= Switch disable (YP=AIN5, Hi-z) 
  13.     S3C_ADCTSC_XP_SEN |         //= Switch disable (XP=AIN7, Hi-z) 
  14.     S3C_ADCTSC_AUTO_PST |       //= Auto Sequential measurement of X-position, Y-position
  15.     S3C_ADCTSC_XY_PST(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
函数
  1. static struct platform_driver s3c_ts_driver = {
  2.     .probe = s3c_ts_probe,
  3.     .remove = s3c_ts_remove,
  4.     .suspend = s3c_ts_suspend,
  5.     .resume = s3c_ts_resume,
  6.     .driver        = {
  7.         .owner    = THIS_MODULE,
  8.         .name    = "s3c-ts",
  9.     },
  10. };

  11. static int __init s3c_ts_init(void)
  12. {
  13.     return platform_driver_register(&s3c_ts_driver);
  14. }

  15. static void __exit s3c_ts_exit(void)
  16. {
  17.     platform_driver_unregister(&s3c_ts_driver);
  18. }

  19. module_init(s3c_ts_init);
  20. module_exit(s3c_ts_exit);
2.2 probe函数
  1. static int __init s3c_ts_probe(struct platform_device *pdev)
  2. {
  3.     struct resource *res;
  4.     struct device *dev;
  5.     struct input_dev *input_dev;
  6.     struct s3c_ts_mach_info * s3c_ts_cfg;
  7.     int ret, size;

  8.     dev = &pdev->dev;

  9.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);                //获取ts寄存器地址
  10.     size = (res->end - res->start) + 1;
  11.     ts_mem = request_mem_region(res->start, size, pdev->name);           //申请I/O内存

  12.     ts_base = ioremap(res->start, size);                                 //request_mem_region申请的内存在使用前要调用ioremap

  13.     ts_clock = clk_get(&pdev->dev, "adc");                               //获取clock    

  14.     clk_enable(ts_clock);                                                //在初始化时disable了ts_clock,这个地方要enable
  15.     
  16.                                                                 //下面这几行是要把ts的配置信息写到寄存器中去
  17.     s3c_ts_cfg = s3c_ts_get_platdata(&pdev->dev);                        //获取ts的配置信息,
  18.                                                                          //ts的私有信息:在arch/arm/mach-s3c64xx/mach-smdk6410.c中
  19.     //enable prescaler && 设置prescaler_value=s3c_ts_cfg->presc
  20.     writel(S3C_ADCCON_PRSCEN | S3C_ADCCON_PRSCVL(s3c_ts_cfg->presc&0xff), ts_base+S3C_ADCCON);
  21.    
  22.    //s3c_ts_cfg->delay=0x10000 --> External input clock 
  23.     writel(s3c_ts_cfg->delay & 0xffff, ts_base+S3C_ADCDLY);
  24.     
  25.     //A/D converter resolution selection--> 12-bit A/D conversion
  26.     writel(readl(ts_base+S3C_ADCCON)|S3C_ADCCON_RESSEL_12BIT, ts_base+S3C_ADCCON);
  27.     //设为等侍down中断模式
  28.     writel(WAIT4INT(0), ts_base+S3C_ADCTSC);
  1.     ts = kzalloc(sizeof(struct s3c_ts_info), GFP_KERNEL);           //下面这几行是要初始化s3c_ts_info结构体
  2.     input_dev = input_allocate_device();
  3.    
  4.     ts->dev = input_dev;
  5.     ts->dev->evbit[0] = ts->dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
  6.     ts->dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);

  7.     if (s3c_ts_cfg->resol_bit==12) {
  8.         input_set_abs_params(ts->dev, ABS_X, 0, 0xFFF, 0, 0);                //设置x轴的最大最小值
  9.         input_set_abs_params(ts->dev, ABS_Y, 0, 0xFFF, 0, 0);                //设置y轴的最大最小值
  10.     } 

  11.     input_set_abs_params(ts->dev, ABS_PRESSURE, 0, 1, 0, 0);                 //设置Press状态的最大最小值(按下或空闲)   

  12.     sprintf(ts->phys, "input(ts)");

  13.     ts->dev->name = s3c_ts_name;
  14.     ts->dev->phys = ts->phys;
  15.     ts->dev->id.bustype = BUS_RS232;
  16.     ts->dev->id.vendor = 0xDEAD;
  17.     ts->dev->id.product = 0xBEEF;
  18.     ts->dev->id.version = S3C_TSVERSION;

  19.     ts->shift = s3c_ts_cfg->oversampling_shift;
  20.     ts->resol_bit = s3c_ts_cfg->resol_bit;
  21.     ts->s3c_adc_con = s3c_ts_cfg->s3c_adc_con;

  22.     /* For IRQ_PENDUP */
  23.     ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);                //获取中断号
  24.     //申请中断,RANDOM表示设备可以看作随机的发生源
  25.     ret = request_irq(ts_irq->start, stylus_updown, IRQF_SAMPLE_RANDOM, "s3c_updown", ts); //申请中断
  26.    
  27.     /* For IRQ_ADC */
  28.     ts_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 1);               //获取中断号
  29.     ret = request_irq(ts_irq->start, stylus_action, IRQF_SAMPLE_RANDOM | IRQF_SHARED, "s3c_action", ts); //申请共享中断
  30.     
  31.     /* All went ok, so register to the input system */
  32.     ret = input_register_device(ts->dev);                                    //把这个input_dev添加到input系统中
  33. }
ts底板图:

ts连到核心板图:

TSXP --> AIN7
TSYP --> AIN5


2.3 IRQ_PENDN
  1. static irqreturn_t stylus_updown(int irqno, void *param)
  2. {
  3.     unsigned long data0;
  4.     unsigned long data1;

  5.     if (!ADC_locked4TS())                              //进入中断函数,如果没有加锁,则加上锁
  6.         if (s3c_ts_adc_lock(LOCK_TS))                  //如果加锁失败,则直接返回       
  7.             return IRQ_HANDLED;        

  8.     data0 = readl(ts_base+S3C_ADCDAT0);
  9.     data1 = readl(ts_base+S3C_ADCDAT1);

  10.     touch_timer_fire(0);

  11.     if(ts->s3c_adc_con==ADC_TYPE_2) {
  12.          //ADCCLRINTPNDNUPINT_PNDNUP interrupt clear
  13.         __raw_writel(0x0, ts_base+S3C_ADCCLRWK);    
  14.         //ADCCLRINTClear ADC Interrupt
  15.         __raw_writel(0x0, ts_base+S3C_ADCCLRINT);   
  16.     }

  17.     return IRQ_HANDLED;
  18. }

2.3.1 fire
  1. static void touch_timer_fire(unsigned long data)
  2. {
  3.     unsigned long data0;
  4.     unsigned long data1;
  5.     int pendown;

  6.     if (!ADC_locked4TS())                       //如果当前状态是free,说明加锁失败,直接返回
  7.         return;
  8.     
  9.     //这儿的数据读取,是为了判断是down还是up状态
  10.     data0 = readl(ts_base+S3C_ADCDAT0);         //读
  11.     data1 = readl(ts_base+S3C_ADCDAT1);         //读   
  12.     //data0的bit15: 0->按下状态; 1->松开状态
  13.     //如果data0与data1都不为松开状态,就是按下状态
  14.     pendown = (!(data0 & S3C_ADCDAT0_UPDOWN)) && (!(data1 & S3C_ADCDAT1_UPDOWN));

  15.     if (pendown) <
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值