MTK hall霍尔传感器

本文详细介绍了MTK平台下霍尔传感器的配置流程,包括dws配置、dts配置、驱动代码修改等内容,并提供了三个实际的调试案例。
  1. 2. dws配中断脚和使能脚

  2. (根据原理图中“09_CAMERA_SENSOR”页中, "HALL"部分【OUT】引脚所连接 - 使能脚GPIO12)

  3. v666为例

  4. dws配置pin脚: - 由于硬件上拉->dws也要配成上拉

  5. EintMode|Def.Mode M0|M1|M2|M3|M4|M5|M6|M7|InPull En|InPull SelHigh|Def.Dir|In|Out|OutHigh|VarName1

  6. GPIO12 1 0:GPIO12 1 1 IN GPIO_HALL_1_PIN

  7. dws配置EINT:

  8. EINTVar|Debounce Time(ms)|Polarity|Sensitive_Level|Debounce En

  9. EINT12 HALL_1 0 Low Level Disable

  10.  
  11. dts:

  12. * HALL GPIO standardization */

  13. &pio {

  14. hall_pin_default: halldefaultcfg {

  15. };

  16. hall_pin_as_int: hallint@12 {

  17. pins_cmd_dat {

  18. pins = <PINMUX_GPIO12__FUNC_GPIO12>;

  19. slew-rate = <0>;

  20. bias-pull-up = <00>;

  21. };

  22. };

  23. };

  24.  
  25. &keypad {

  26. pinctrl-names = "default", "hall_pin_as_int";

  27. pinctrl-0 = <&hall_pin_default>;

  28. pinctrl-1 = <&hall_pin_as_int>;

  29. status = "okay";

  30. };

  31. /* HALL GPIO end */

  32.  
  33. 一、 查看是否有键值上报

  34. getevent -i

  35. add device 8: /dev/input/event1

  36. bus: 0019

  37. vendor 2454

  38. product 6500

  39. version 0010

  40. name: "mtk-kpd" // 与音量加减键、电源键、hall同一个event

  41. location: ""

  42. id: ""

  43. version: 1.0.1

  44.  
  45. getevent -t /dev/input/event1 // 打印出来的是16进制

  46. [70.169911] 0001 0085 00000001 // 85 -> 133 远离

  47. [70.169911] 0000 0000 00000000

  48. [70.352126] 0001 0085 00000000

  49. [70.352126] 0000 0000 00000000

  50.  
  51. 二、查看代码确定上报键值

  52. 1. alps\kernel-3.18\drivers\input\keyboard\mediatek\kpd.c

  53. #define KEY_HALL_F3 133 //for hall eint report key far // 磁铁远离

  54. #define KEY_HALL_F4 134 //for hall eint report key close // 磁铁靠近

  55.  
  56. 2. alps/device/magcomm/magc6580_we_c_m/mtk-kpd.kl , 映射给上层

  57. key 114 0x72 VOLUME_DOWN // 侧键

  58. key 115 0x73 VOLUME_UP

  59. key 116 0x74 POWER

  60.  
  61. + key 133 F3 // 霍尔

  62. + key 134 F4

  63.  
  64. 注:修改此文件,可以用push的方式先试验

  65. find /system -name mtk-kpd.kl

  66. /system/usr/keylayout/mtk-kpd.kl

  67. adb push ... /system/usr/keylayout/

  68.  
  69. 三、添加权限

  70. alps/device/mediatek/common/sepolicy/basic/system_app.te

  71. # add permission for hall

  72. allow system_app sysfs_keypad_file:dir { search read write };

  73. allow system_app sysfs_keypad_file:file { read write getattr setattr open create };

  74.  
  75. alps/device/mediatek/common/sepolicy/full/platform_app.te

  76. # add permission for hall

  77. allow platform_app sysfs_keypad_file:dir { search read write };

  78. allow platform_app sysfs_keypad_file:file { read write getattr setattr open create };

  79.  
  80. alps/device/mediatek/common/sepolicy/full/priv_app.te

  81. # add permission for hall

  82. allow priv_app sysfs_keypad_file:dir { search read write };

  83. allow priv_app sysfs_keypad_file:file { read write getattr setattr open create };

  84.  
  85.  
  86. 四、手写笔插入与拔出 - 用hall来实现,手写笔尖有磁性(以80 5.1为例)

  87. 1. 修改alps/device/haocheng/hct6580_weg_a_l/mtk-kpd.kl ,映射给上层

  88. key 133 F3

  89. key 134 F4

  90.  
  91. + key 136 F6

  92. + key 137 F7

  93.  
  94. 2. 修改alps\kernel-3.10\drivers\misc\mediatek\keypad\kpd.c,仿造hall_1添加hall_2的代码:

  95. + #ifdef GPIO_HALL_2_PIN

  96. #define CUSTOM_HALL_2_SUPPORT

  97. #define GPIO_HALL_2_EINT_PIN GPIO_HALL_2_PIN

  98. #define GPIO_HALL_2_EINT_PIN_M_EINT GPIO_HALL_2_PIN_M_EINT

  99. static unsigned int hall_2_irq;

  100. #define HALL_2_TAG "hall: "

  101. #define HALL_2_DBG(fmt, args...) printk(HALL_2_TAG fmt, ##args)

  102. struct work_struct hall_2_eint_work;

  103. static int hall_2_state_flag = 0;

  104. static bool hall_2_state = 1; //0: close 1:far

  105. #define KEY_HALL_F6 136 //for hall eint report key far

  106. #define KEY_HALL_F7 137 //for hall eint report key close

  107. + #endif

  108.  
  109. + #ifdef CUSTOM_HALL_2_SUPPORT // 提供给上层调用接口: /sys/bus/...

  110. static volatile int hall_2_status = 0;

  111. static ssize_t store_hall_2_state(struct device_driver *ddri, const char *buf, size_t count)

  112. {

  113. if (sscanf(buf, "%u", &hall_2_status) != 1) {

  114. kpd_print("kpd call state: Invalid values\n");

  115. return -EINVAL;

  116. }

  117. hall_2_state = (bool)hall_2_status;

  118. return count;

  119. }

  120. static ssize_t show_hall_2_state(struct device_driver *ddri, char *buf)

  121. {

  122. ssize_t res;

  123. res = snprintf(buf, PAGE_SIZE, "%d\n", hall_2_state);

  124. return res;

  125. }

  126. static DRIVER_ATTR(hall_2_state, S_IWUSR | S_IALLUGO, show_hall_2_state, store_hall_2_state);

  127. + #endif

  128.  
  129. static struct driver_attribute *kpd_attr_list[] = {

  130. &driver_attr_kpd_call_state,

  131. #ifdef CUSTOM_HALL_SUPPORT

  132. &driver_attr_hall_state,

  133. #endif

  134. + #ifdef CUSTOM_HALL_2_SUPPORT // 提供给上层调用接口: /sys/bus/...

  135. + &driver_attr_hall_2_state,

  136. + #endif

  137. };

  138.  
  139.  
  140. + #ifdef CUSTOM_HALL_2_SUPPORT

  141. + void kpd_hall_2_key_handler(unsigned long pressed, u16 linux_keycode)

  142. {

  143. if(!kpd_input_dev) {

  144. printk("KPD input device not ready\n");

  145. return;

  146. }

  147. input_report_key(kpd_input_dev, linux_keycode, pressed);

  148. input_sync(kpd_input_dev);

  149.  
  150. if (kpd_show_hw_keycode) {

  151. printk(KPD_SAY "(%s) KEY_HALL keycode =%d \n", pressed ? "pressed" : "released", linux_keycode);

  152. }

  153. }

  154.  
  155. static void hall_2_work_func(struct work_struct *work)

  156. {

  157. if(hall_2_state == 1) {

  158. kpd_hall_key_handler(1, KEY_HALL_F6);

  159. kpd_hall_key_handler(0, KEY_HALL_F6);

  160. } else if(hall_2_state == 0) {

  161. kpd_hall_key_handler(1, KEY_HALL_F7);

  162. kpd_hall_key_handler(0, KEY_HALL_F7);

  163. }

  164. }

  165. bool get_hall_2_state()

  166. {

  167. return hall_2_state;

  168. }

  169. EXPORT_SYMBOL(get_hall_2_state);

  170.  
  171. void hall_2_eint_func(void)

  172. {

  173. disable_irq_nosync(hall_2_irq);

  174. if(hall_2_state_flag)

  175. {

  176. hall_2_state_flag = 0;

  177. hall_2_state = 1;

  178. irq_set_irq_type(hall_2_irq,IRQ_TYPE_LEVEL_LOW);

  179. }

  180. else{

  181. hall_2_state_flag = 1;

  182. hall_2_state = 0;

  183. irq_set_irq_type(hall_2_irq,IRQ_TYPE_LEVEL_HIGH);

  184. }

  185. enable_irq(hall_2_irq);

  186. schedule_work(&hall_2_eint_work);

  187. }

  188.  
  189. static irqreturn_t hall_2_irq_handler(int irq, void *dev_id)

  190. {

  191. hall_2_eint_func();

  192. return IRQ_HANDLED;

  193. }

  194.  
  195. int hall_2_setup_eint(void)

  196. {

  197. struct device_node *hall_node;

  198. u32 ints[2] = {0, 0};

  199.  
  200. mt_set_gpio_dir(GPIO_HALL_2_EINT_PIN, GPIO_DIR_IN);

  201. mt_set_gpio_mode(GPIO_HALL_2_EINT_PIN, GPIO_HALL_2_EINT_PIN_M_EINT);

  202. mt_set_gpio_pull_enable(GPIO_HALL_2_EINT_PIN, 0);

  203.  
  204. hall_node = of_find_compatible_node(NULL,NULL,"mediatek, HALL_2-eint");

  205.  
  206. if(hall_node){

  207. printk("hall_irq has find!\n");

  208. of_property_read_u32_array(hall_node, "debounce", ints, ARRAY_SIZE(ints));

  209. mt_gpio_set_debounce(ints[0], ints[1]);

  210. hall_2_irq= irq_of_parse_and_map(hall_node, 0);

  211. if (!hall_2_irq)

  212. {

  213. printk("irq_of_parse_and_map hall fail!!\n");

  214. return -EINVAL;

  215. }

  216. if(request_irq(hall_2_irq, hall_2_irq_handler, IRQF_TRIGGER_NONE, "HALL_2-eint", NULL)) {

  217. printk("HALL IRQ NOT AVAILABLE!!\n");

  218. return -EINVAL;

  219. }

  220. }

  221. else{

  222. printk("null hall_irq node!\n");

  223. return -EINVAL;

  224. }

  225. return 0;

  226. }

  227. #endif

  228.  
  229. static int kpd_pdrv_probe(struct platform_device *pdev)

  230. {

  231. #ifdef CUSTOM_HALL_SUPPORT

  232. __set_bit(KEY_HALL_F3, kpd_input_dev->keybit);

  233. __set_bit(KEY_HALL_F4, kpd_input_dev->keybit);

  234. #endif

  235. + #ifdef CUSTOM_HALL_2_SUPPORT

  236. + __set_bit(KEY_HALL_F6, kpd_input_dev->keybit); // 使能input上报键值

  237. + __set_bit(KEY_HALL_F7, kpd_input_dev->keybit);

  238. + #endif

  239. ...

  240. #ifdef CUSTOM_HALL_SUPPORT

  241. INIT_WORK(&hall_eint_work, hall_work_func);

  242. hall_setup_eint();

  243. #endif

  244. + #ifdef CUSTOM_HALL_2_SUPPORT

  245. + INIT_WORK(&hall_2_eint_work, hall_2_work_func); // 中断中唤醒工作,工作中上报key

  246. + hall_2_setup_eint(); // 设置GPIO口状态,从dts获取中断信息,注册中断

  247. + #endif

  248. ...

  249. }

  250.  
  251. 3. 修改dws,配置GPIO口为中断模式,配置中断的触发方式(电平or边沿)

  252.  
  253. 五、39平台:

  254. 1. device/mediateksample/k39tv1_bsp_1g/mtk-kpd.kl

  255. + key 133 F3

  256. + key 134 F4

  257.  
  258. 2. mt6739.dts

  259. + hall_1: hall_1 {

  260. + compatible = "mediatek, hall_1-eint";

  261. + status = "disabled";

  262. + };

  263.  
  264. 3. k39tv1_bsp_1g.dts

  265. + /* HALL GPIO standardization */

  266. + &keypad {

  267. pinctrl-names = "default", "hall_pin_as_int";

  268. pinctrl-0 = <&hall_pin_default>;

  269. pinctrl-1 = <&hall_pin_as_int>;

  270. status = "okay";

  271. };

  272.  
  273. &pio {

  274. hall_pin_default: halldefaultcfg {

  275. };

  276. hall_pin_as_int: hallint@14 {

  277. pins_cmd_dat {

  278. pins = <PINMUX_GPIO14__FUNC_GPIO14>;

  279. slew-rate = <0>;

  280. bias-pull-up = <00>;

  281. };

  282. };

  283. + };

  284. + /* HALL GPIO end */

  285.  
  286. 4. codegen.dws

  287. EINT:

  288. ID EINTVar|Debounce Time(ms)|Polarity|Sensitive_Level|Debounce En

  289. EINT14 HALL_1 0 Low Level Disable

  290.  
  291. GPIO:

  292. ID EintMode|Def.Mode M0|M1|M2|M3|M4|M5|M6|M7|InPull En|InPull SelHigh|Def.Dir|In|Out|OutHigh|VarName1

  293. GPIO14 1 0:GPIO14 1 1 1 IN 1 GPIO_HALL_1_PIN

  294.  
  295. 5. kernel-4.4/drivers/input/keyboard/mediatek/kpd.c

  296.  
  297. + #ifdef CONFIG_KST_HALL_SUPPORT

  298. + #define CUSTOM_HALL_SUPPORT

  299. #define GPIO_HALL_EINT_PIN GPIO_HALL_1_PIN

  300. #define GPIO_HALL_EINT_PIN_M_EINT GPIO_HALL_1_PIN_M_EINT

  301. static unsigned int hall_irq;

  302. #define HALL_TAG "hall: "

  303. #define HALL_DBG(fmt, args...) printk(HALL_TAG fmt, ##args)

  304. struct work_struct hall_eint_work;

  305. static int hall_state_flag = 0;

  306. static bool hall_state = 1; //0: close 1:far

  307. #define KEY_HALL_F3 133 //116 //for hall eint report key far

  308. #define KEY_HALL_F4 134 //62 //for hall eint report key close

  309. struct pinctrl *hallpinctrl;

  310. + struct pinctrl_state *hall_pin_as_int;

  311. + #endif

  312.  
  313. + #ifdef CUSTOM_HALL_SUPPORT

  314. + static volatile int hall_status = 0;

  315. static ssize_t store_hall_state(struct device_driver *ddri, const char *buf, size_t count)

  316. {

  317. if (sscanf(buf, "%u", &hall_status) != 1) {

  318. kpd_print("kpd call state: Invalid values\n");

  319. return -EINVAL;

  320. }

  321. hall_state = (bool)hall_status;

  322. return count;

  323. }

  324. static ssize_t show_hall_state(struct device_driver *ddri, char *buf)

  325. {

  326. ssize_t res;

  327. res = snprintf(buf, PAGE_SIZE, "%d\n", hall_state);

  328. return res;

  329. }

  330. + static DRIVER_ATTR(hall_state, S_IWUSR | S_IRUGO, show_hall_state, store_hall_state);

  331. + #endif

  332.  
  333. static struct driver_attribute *kpd_attr_list[] = {

  334. &driver_attr_kpd_call_state,

  335. + #ifdef CUSTOM_HALL_SUPPORT

  336. + &driver_attr_hall_state,

  337. + #endif

  338. };

  339.  
  340. + #ifdef CUSTOM_HALL_SUPPORT

  341. + void kpd_hall_key_handler(unsigned long pressed, u16 linux_keycode)

  342. {

  343. if(!kpd_input_dev) {

  344. printk("KPD input device not ready\n");

  345. return;

  346. }

  347. input_report_key(kpd_input_dev, linux_keycode, pressed);

  348. input_sync(kpd_input_dev);

  349. if (kpd_show_hw_keycode) {

  350. printk(KPD_SAY "(%s) KEY_HALL keycode =%d \n", pressed ? "pressed" : "released", linux_keycode);

  351. }

  352. }

  353. static void hall_work_func(struct work_struct *work)

  354. {

  355. printk("key hall_work_func not ready\n"); //add

  356. if(hall_state == 1) {

  357. kpd_hall_key_handler(1, KEY_HALL_F3);

  358. kpd_hall_key_handler(0, KEY_HALL_F3);

  359. }

  360. else if(hall_state == 0) {

  361. kpd_hall_key_handler(1, KEY_HALL_F4);

  362. kpd_hall_key_handler(0, KEY_HALL_F4);

  363. }

  364. }

  365. void hall_eint_func(void)

  366. {

  367. disable_irq_nosync(hall_irq);

  368. if(hall_state_flag)

  369. {

  370. hall_state_flag = 0;

  371. hall_state = 1;

  372. irq_set_irq_type(hall_irq,IRQ_TYPE_LEVEL_LOW);

  373. }

  374. else

  375. {

  376. hall_state_flag = 1;

  377. hall_state = 0;

  378. irq_set_irq_type(hall_irq,IRQ_TYPE_LEVEL_HIGH);

  379. }

  380. enable_irq(hall_irq);

  381. schedule_work(&hall_eint_work);

  382. }

  383. static irqreturn_t hall_irq_handler(int irq, void *dev_id)

  384. {

  385. hall_eint_func();

  386. return IRQ_HANDLED;

  387. }

  388. int hall_setup_eint(void)

  389. {

  390. struct device_node *hall_node;

  391. u32 ints[2] = {0, 0};

  392. hall_node = of_find_compatible_node(NULL,NULL,"mediatek, hall_1-eint");

  393. if(hall_node){

  394. printk("hall_irq has find!\n");

  395. of_property_read_u32_array(hall_node, "debounce", ints, ARRAY_SIZE(ints));

  396. gpio_set_debounce(ints[0], ints[1]);

  397. hall_irq= irq_of_parse_and_map(hall_node, 0);

  398. if (!hall_irq)

  399. {

  400. printk("irq_of_parse_and_map hall fail!!\n");

  401. return -EINVAL;

  402. }

  403. if(request_irq(hall_irq, hall_irq_handler, IRQF_TRIGGER_NONE, "hall_1-eint", NULL)) {

  404. printk("HALL IRQ NOT AVAILABLE!!\n");

  405. return -EINVAL;

  406. }

  407. }

  408. else

  409. {

  410. printk("null hall_irq node!\n");

  411. return -EINVAL;

  412. }

  413. return 0;

  414. + }

  415. + #endif

  416.  
  417. + #ifdef CUSTOM_HALL_SUPPORT

  418. + int hall_get_gpio_info(struct platform_device *pdev)

  419. {

  420. int ret;

  421. hallpinctrl = devm_pinctrl_get(&pdev->dev);

  422. if (IS_ERR(hallpinctrl)) {

  423. ret = PTR_ERR(hallpinctrl);

  424. dev_err(&pdev->dev, "hallpinctrl err!\n");

  425. return ret;

  426. }

  427. hall_pin_as_int = pinctrl_lookup_state(hallpinctrl, "hall_pin_as_int");

  428. if (IS_ERR(hall_pin_as_int)) {

  429. ret = PTR_ERR(hall_pin_as_int);

  430. dev_err(&pdev->dev, "hall_pin_as_int err!\n");

  431. return ret;

  432. }

  433. pinctrl_select_state(hallpinctrl, hall_pin_as_int);

  434. return 0;

  435. + }

  436. + #endif

  437.  
  438. static int kpd_pdrv_probe(struct platform_device *pdev)

  439. {

  440. __set_bit(KPD_KEY_MAP, kpd_input_dev->keybit);

  441. + #ifdef CUSTOM_HALL_SUPPORT

  442. + __set_bit(KEY_HALL_F3, kpd_input_dev->keybit);

  443. + __set_bit(KEY_HALL_F4, kpd_input_dev->keybit);

  444. + #endif

  445. ...

  446. hrtimer_init(&aee_timer_5s, CLOCK_MONOTONIC, HRTIMER_MODE_REL);

  447. aee_timer_5s.function = aee_timer_5s_func;

  448. + #ifdef CUSTOM_HALL_SUPPORT

  449. + INIT_WORK(&hall_eint_work, hall_work_func);

  450. + hall_get_gpio_info(pdev);

  451. + hall_setup_eint();

  452. + #endif

  453. err = kpd_create_attr(&kpd_pdrv.driver);

  454. ...

  455. }

  456.  
  457. 调试案例

  458. 案例一 : hall不通 - 电容贴错

  459. 现象 :

  460. 平台 : androidN,MTK6737

  461. 排查过程: 1. 查看是否有键值上报 - 拿磁铁靠近

  462. getevent -t /dev/input/event1 - 无键值上报

  463.  
  464. 2. 检查dws中的gpio口配置&中断配置、dts中断配置均ok(根据原理图得知EINT12 即 GPIO12)

  465.  
  466. 3. 接示波器量中断脚 - 磁铁靠近时 中断脚无高低电平变化

  467.  
  468. 4. 交给硬件同事检查 -> 一个电容贴错,替换后ok

  469.  
  470. 处理方案: 换料 改bom

  471.  
  472. 案例二 : hall不通 - hall芯片贴反

  473. 现象 :

  474. 平台 : androidN,MTK6737

  475. 排查过程: 1. 查看是否有键值上报 - 拿磁铁靠近

  476. getevent -t /dev/input/event1 - 无键值上报

  477.  
  478. 2. 检查dws中的gpio口配置&中断配置、dts中断配置均ok

  479.  
  480. 3. hall芯片贴反了 -> 改正ok

  481.  
  482. 案例三 : hall不通 - 硬件短路

  483. 现象 :

  484. 平台 : androidN,MTK6737

  485. 排查过程: 1. 查看是否有键值上报 - 拿磁铁靠近

  486. getevent -t /dev/input/event1 - 无键值上报

  487.  
  488. 2. 用镊子将hall中断脚短地(平常上拉为高电平,低电平为中断) - 有键值上报

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值