MTK 按键驱动流程总结
生活随笔
收集整理的這篇文章主要介紹了
MTK 按键驱动流程总结
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
前言
簡單介紹了 Input 按鍵驅動流程
流程
位置:Kpd.c (kernel-3.18\drivers\input\keyboard\mediatek) module_init(kpd_mod_init); static int __init kpd_mod_init(void)///// static struct platform_driver kpd_pdrv = {// .probe = kpd_pdrv_probe,// .remove = kpd_pdrv_remove,// #ifndef USE_EARLY_SUSPEND// .suspend = kpd_pdrv_suspend,// .resume = kpd_pdrv_resume,// #endif// .driver = {// .name = KPD_NAME,// .owner = THIS_MODULE,// .of_match_table = kpd_of_match,// ///// // static const struct of_device_id kpd_of_match[] = {// // {.compatible = "mediatek,mt6580-keypad"},// // {.compatible = "mediatek,mt6570-keypad"},// // {.compatible = "mediatek,mt6735-keypad"},// // {.compatible = "mediatek,mt6755-keypad"},// // ...// // {},// // };// },// };/// 對應的 dts 中的配置還是蠻好玩的,貼一下// Mt6755.dtsi (kernel-3.18\arch\arm64\boot\dts)// keypad: keypad@10010000 {// compatible = "mediatek,mt6755-keypad", "mediatek,kp";// reg = <0x10010000 0x1000>;// interrupts = <GIC_SPI 164 IRQ_TYPE_EDGE_FALLING>;// };// dws 中的配置:// &keypad { // KPD@ {// compatible = "mediatek, kpd";// kpd-key-debounce = <1024>;// kpd-sw-pwrkey = <116>;// kpd-hw-pwrkey = <8>;// kpd-sw-rstkey = <102>;// kpd-hw-rstkey = <17>;// kpd-use-extend-type = <0>;// /// HW Keycode [0~71] -> Linux Keycode// kpd-hw-init-map = <114 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 >;// kpd-pwrkey-eint-gpio = <0>;// kpd-pwkey-gpio-din = <0>;// kpd-hw-dl-key0 = <1>;// kpd-hw-dl-key1 = <0>;// kpd-hw-dl-key2 = <8>;// *****************************************************************// *******************Uboot Customation***************************// *****************************************************************// kpd-hw-recovery-key = <1>;// kpd-hw-factory-key = <0>;// };// };///// 最后反匯編出來的東西:// keypad@10010000 {// compatible = "mediatek,mt6755-keypad", "mediatek,kp";// reg = <0x10010000 0x1000>;// interrupts = <0x0 0xa4 0x2>;// mediatek,kpd-key-debounce = <0x400>;// mediatek,kpd-sw-pwrkey = <0x74>;// mediatek,kpd-hw-pwrkey = <0x8>;// mediatek,kpd-sw-rstkey = <0x66>;// mediatek,kpd-hw-rstkey = <0x11>;// mediatek,kpd-use-extend-type = <0x0>;// mediatek,kpd-hw-map-num = <0x48>;// mediatek,kpd-hw-init-map = <0x72 0x73 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0>;// mediatek,kpd-pwrkey-eint-gpio = <0x0>;// mediatek,kpd-pwkey-gpio-din = <0x0>;// mediatek,kpd-hw-dl-key0 = <0x1>;// mediatek,kpd-hw-dl-key1 = <0x0>;// mediatek,kpd-hw-dl-key2 = <0x8>;// mediatek,kpd-hw-recovery-key = <0x1>;// mediatek,kpd-hw-factory-key = <0x0>;// status = "okay";// };r = platform_driver_register(&kpd_pdrv);/ // 匹配后調用: static int kpd_pdrv_probe(struct platform_device *pdev)// 獲取時鐘kpd_clk = devm_clk_get(&pdev->dev, "kpd-clk");ret_prepare = clk_prepare(kpd_clk);ret_enable = clk_enable(kpd_clk);// 地址映射 reg = <0x10010000 0x1000>;kp_base = of_iomap(pdev->dev.of_node, 0);///// 中斷申請和注冊 interrupts = <0x0 0xa4 0x2>;kp_irqnr = irq_of_parse_and_map(pdev->dev.of_node, 0);//// 分配 input 輸入設備kpd_input_dev = input_allocate_device();// 設備 input 輸入設備kpd_input_dev->name = KPD_NAME;kpd_input_dev->id.bustype = BUS_HOST;kpd_input_dev->id.vendor = 0x2454;kpd_input_dev->id.product = 0x6500;kpd_input_dev->id.version = 0x0010;kpd_input_dev->open = kpd_open;// 打開輸入設備時調用// #ifdef CONFIG_WIND_HALL_SUPPORTkpd_hall_init();#endif// // 獲得 dts 的配置信息kpd_get_dts_info(pdev->dev.of_node);of_property_read_u32(node, "mediatek,kpd-key-debounce", &kpd_dts_data.kpd_key_debounce);of_property_read_u32(node, "mediatek,kpd-sw-pwrkey", &kpd_dts_data.kpd_sw_pwrkey);of_property_read_u32(node, "mediatek,kpd-hw-pwrkey", &kpd_dts_data.kpd_hw_pwrkey);of_property_read_u32(node, "mediatek,kpd-sw-rstkey", &kpd_dts_data.kpd_sw_rstkey);of_property_read_u32(node, "mediatek,kpd-hw-rstkey", &kpd_dts_data.kpd_hw_rstkey);of_property_read_u32(node, "mediatek,kpd-use-extend-type", &kpd_dts_data.kpd_use_extend_type);of_property_read_u32(node, "mediatek,kpd-pwrkey-eint-gpio", &kpd_dts_data.kpd_pwrkey_eint_gpio);of_property_read_u32(node, "mediatek,kpd-pwrkey-gpio-din", &kpd_dts_data.kpd_pwrkey_gpio_din);of_property_read_u32(node, "mediatek,kpd-hw-dl-key1", &kpd_dts_data.kpd_hw_dl_key1);of_property_read_u32(node, "mediatek,kpd-hw-dl-key2", &kpd_dts_data.kpd_hw_dl_key2);of_property_read_u32(node, "mediatek,kpd-hw-dl-key3", &kpd_dts_data.kpd_hw_dl_key3);of_property_read_u32(node, "mediatek,kpd-hw-recovery-key", &kpd_dts_data.kpd_hw_recovery_key);of_property_read_u32(node, "mediatek,kpd-hw-factory-key", &kpd_dts_data.kpd_hw_factory_key);of_property_read_u32(node, "mediatek,kpd-hw-map-num", &kpd_dts_data.kpd_hw_map_num);ret = of_property_read_u32_array(node, "mediatek,kpd-hw-init-map", kpd_dts_data.kpd_hw_init_map,kpd_dts_data.kpd_hw_map_num);// 將 dts 中的配置寫到全局數組中kpd_memory_setting();kpd_init_keymap(kpd_keymap);kpd_init_keymap_state(kpd_keymap_state);//// 下面就是設置 input 設備上報的鍵值了,而對應的鍵值在 dts 數組中設置的if (!kpd_dts_data.kpd_use_extend_type) {for (i = 17; i < KPD_NUM_KEYS; i += 9) // only [8] works for Power key kpd_keymap[i] = 0;} for (i = 0; i < KPD_NUM_KEYS; i++) {if (kpd_keymap[i] != 0)__set_bit(kpd_keymap[i], kpd_input_dev->keybit);}// #ifdef CONFIG_WIND_HALL_SUPPORT__set_bit(EV_SW, kpd_input_dev->evbit);__set_bit(SW_LID, kpd_input_dev->swbit);kpd_input_dev->keybit[BIT_WORD(KEY_F9)] |= BIT_MASK(KEY_F9);kpd_input_dev->keybit[BIT_WORD(KEY_F10)] |= BIT_MASK(KEY_F10);#endif// kpd_input_dev->dev.parent = &pdev->dev;//// 注冊 input 輸入設備r = input_register_device(kpd_input_dev);/// 注冊一個雜項設備kpd_dev.parent = &pdev->dev;r = misc_register(&kpd_dev);wake_lock_init(&kpd_suspend_lock, WAKE_LOCK_SUSPEND, "kpd wakelock");// 注冊一個按鍵 IRQ 函數kpd_set_debounce(kpd_dts_data.kpd_key_debounce);r = request_irq(kp_irqnr, kpd_irq_handler, IRQF_TRIGGER_NONE, KPD_NAME, NULL);// 初始化了一個定時器hrtimer_init(&aee_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);aee_timer.function = aee_timer_func;/// 創建 sys 屬性節點err = kpd_create_attr(&kpd_pdrv.driver);// 當有按鍵發生時: static irqreturn_t kpd_irq_handler(int irq, void *dev_id)///// use _nosync to avoid deadlockdisable_irq_nosync(kp_irqnr);tasklet_schedule(&kpd_keymap_tasklet);static void kpd_keymap_handler(unsigned long data)/// 獲取按鍵狀態kpd_get_keymap_state(new_state);state[0] = *(volatile u16 *)KP_MEM1;state[1] = *(volatile u16 *)KP_MEM2;state[2] = *(volatile u16 *)KP_MEM3;state[3] = *(volatile u16 *)KP_MEM4;state[4] = *(volatile u16 *)KP_MEM5;wake_lock_timeout(&kpd_suspend_lock, HZ / 2);for (i = 0; i < KPD_NUM_MEMS; i++)change = new_state[i] ^ kpd_keymap_state[i];for (j = 0; j < 16; j++)mask = 1U << j;hw_keycode = (i << 4) + j;pressed = !(new_state[i] & mask);linux_keycode = kpd_keymap[hw_keycode];kpd_aee_handler(linux_keycode, pressed);input_report_key(kpd_input_dev, linux_keycode, pressed);input_sync(kpd_input_dev);memcpy(kpd_keymap_state, new_state, sizeof(new_state));enable_irq(kp_irqnr);總結
以上是生活随笔為你收集整理的MTK 按键驱动流程总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Matlab: 多项式表示及其基本运算
- 下一篇: 电脑死机蓝屏怎么办 电脑死机蓝屏原因介绍