日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MTK 按键驱动流程总结

發布時間:2023/12/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 按键驱动流程总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。