adckey_acts.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*
  2. * Copyright (c) 2017 Actions Semiconductor Co., Ltd
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. /**
  7. * @file
  8. * @brief ADC Keyboard driver for Actions SoC
  9. */
  10. #include <errno.h>
  11. #include <kernel.h>
  12. #include <string.h>
  13. #include <init.h>
  14. #include <irq.h>
  15. #include <drivers/adc.h>
  16. #include <drivers/input/input_dev.h>
  17. #include <sys/util.h>
  18. #include <sys/byteorder.h>
  19. #include <board.h>
  20. #include <board_cfg.h>
  21. #include <soc_pmu.h>
  22. #include <logging/log.h>
  23. #ifdef CONFIG_CFG_DRV
  24. #include <config.h>
  25. #include <drivers/cfg_drv/driver_config.h>
  26. #endif
  27. LOG_MODULE_REGISTER(keyadc, CONFIG_SYS_LOG_INPUT_DEV_LEVEL);
  28. #ifdef CONFIG_CFG_DRV
  29. struct adckey_map {
  30. uint16_t key_code;
  31. uint16_t adc_min;
  32. uint16_t adc_max;
  33. };
  34. #else
  35. struct adckey_map {
  36. uint16_t key_code;
  37. uint16_t adc_val;
  38. };
  39. #endif
  40. struct acts_adckey_data {
  41. const struct device *adc_dev;
  42. const struct device *this_dev;
  43. #ifdef CONFIG_ADCKEY_POLL_TIMER
  44. struct k_timer timer;
  45. #else
  46. struct k_delayed_work timer;
  47. #endif
  48. struct adc_sequence sequence;
  49. uint8_t adc_buf[4];
  50. int scan_count;
  51. uint16_t prev_keycode;
  52. uint16_t prev_stable_keycode;
  53. input_notify_t notify;
  54. uint32_t timestamp;
  55. uint8_t state; /* if 1 indicates the polling delay worker is runing */
  56. #ifdef CONFIG_CFG_DRV
  57. struct adckey_map adckey_keymaps[CFG_MAX_LRADC_KEYS];
  58. #endif
  59. };
  60. struct acts_adckey_config {
  61. char *adc_name;
  62. uint16_t adc_chan;
  63. uint16_t poll_interval_ms;
  64. uint16_t sample_filter_dep;
  65. uint32_t poll_total_ms;
  66. #ifndef CONFIG_CFG_DRV
  67. uint16_t key_cnt;
  68. const struct adckey_map *key_maps;
  69. #endif
  70. };
  71. static void adckey_pmu_notify(void *cb_data, int state);
  72. static void adckey_acts_disable(const struct device *dev);
  73. /* adc_val -> key_code */
  74. static uint16_t adckey_acts_get_keycode(const struct acts_adckey_config *cfg,
  75. struct acts_adckey_data *adckey,
  76. int adc_val)
  77. {
  78. #ifdef CONFIG_CFG_DRV
  79. struct adckey_map *map = adckey->adckey_keymaps;
  80. int i;
  81. if (!map)
  82. goto out;
  83. for (i = 0; i < CFG_MAX_LRADC_KEYS; i++) {
  84. if ((adc_val < map->adc_max) && (adc_val > map->adc_min))
  85. return map->key_code;
  86. map++;
  87. }
  88. out:
  89. return KEY_RESERVED;
  90. #else
  91. const struct adckey_map *map = cfg->key_maps;
  92. int i;
  93. if (!map)
  94. goto out;
  95. for (i = 0; i < cfg->key_cnt; i++) {
  96. if (adc_val < map->adc_val)
  97. return map->key_code;
  98. map++;
  99. }
  100. out:
  101. return KEY_RESERVED;
  102. #endif
  103. }
  104. static void adckey_acts_report_key(struct acts_adckey_data *adckey,
  105. int key_code, int value)
  106. {
  107. struct input_value val;
  108. if (adckey->notify) {
  109. val.keypad.type = EV_KEY;
  110. val.keypad.code = key_code;
  111. val.keypad.value = value;
  112. LOG_DBG("report key_code %d value %d",
  113. key_code, value);
  114. adckey->notify(NULL, &val);
  115. }
  116. }
  117. void adckey_acts_inquiry(const struct device *dev, struct input_value *val)
  118. {
  119. struct acts_adckey_data *adckey = dev->data;
  120. const struct device *adckeydev = adckey->this_dev;
  121. const struct acts_adckey_config *cfg = adckeydev->config;
  122. uint16_t keycode, adcval;
  123. int ret;
  124. /* get adc value */
  125. ret = adc_read(adckey->adc_dev, &adckey->sequence);
  126. if (ret) {
  127. LOG_ERR("ADC read error %d", ret);
  128. return ;
  129. }
  130. adcval = sys_get_le16(adckey->sequence.buffer);
  131. LOG_DBG("adc value: %d\n", adcval);
  132. /* get keycode */
  133. keycode = adckey_acts_get_keycode(cfg, adckey, adcval);
  134. LOG_DBG("adcval %d, keycode %d\n", adcval, keycode);
  135. if (keycode != KEY_RESERVED && val->keypad.code == keycode)
  136. {
  137. val->keypad.type = EV_KEY;
  138. val->keypad.value = 1;
  139. }
  140. }
  141. #ifdef CONFIG_ADCKEY_POLL_TIMER
  142. static void adckey_acts_poll(struct k_timer *timer)
  143. #else
  144. static void adckey_acts_poll(struct k_work *work)
  145. #endif
  146. {
  147. #ifdef CONFIG_ADCKEY_POLL_TIMER
  148. struct device *dev = k_timer_user_data_get(timer);
  149. struct acts_adckey_data *adckey = dev->data;
  150. #else
  151. struct acts_adckey_data *adckey =
  152. CONTAINER_OF(work, struct acts_adckey_data, timer);
  153. const struct device *dev = adckey->this_dev;
  154. #endif
  155. const struct acts_adckey_config *cfg = dev->config;
  156. uint16_t keycode, adcval;
  157. int ret;
  158. bool key_release = false;
  159. struct detect_param_t detect_param =
  160. {PMU_DETECT_DEV_REMOTE, adckey_pmu_notify, (void *)dev};
  161. /* get adc value */
  162. ret = adc_read(adckey->adc_dev, &adckey->sequence);
  163. if (ret) {
  164. LOG_ERR("ADC read error %d", ret);
  165. return ;
  166. }
  167. adcval = sys_get_le16(adckey->sequence.buffer);
  168. /* get keycode */
  169. keycode = adckey_acts_get_keycode(cfg, adckey, adcval);
  170. LOG_DBG("adcval 0x%x, keycode %d", adcval, keycode);
  171. /* no key is pressed or releasing */
  172. if (keycode == KEY_RESERVED &&
  173. adckey->prev_stable_keycode == KEY_RESERVED){
  174. key_release = true;
  175. goto out;
  176. }
  177. key_release = false;
  178. if (keycode == adckey->prev_keycode) {
  179. adckey->scan_count++;
  180. if (adckey->scan_count == cfg->sample_filter_dep) {
  181. /* previous key is released? */
  182. if (adckey->prev_stable_keycode != KEY_RESERVED
  183. && keycode != adckey->prev_stable_keycode)
  184. adckey_acts_report_key(adckey,
  185. adckey->prev_stable_keycode, 0);
  186. /* a new key press? */
  187. if (keycode != KEY_RESERVED)
  188. adckey_acts_report_key(adckey, keycode, 1);
  189. /* clear counter for new checking */
  190. adckey->prev_stable_keycode = keycode;
  191. adckey->scan_count = 0;
  192. }
  193. } else {
  194. /* new key pressed? */
  195. adckey->prev_keycode = keycode;
  196. adckey->scan_count = 0;
  197. }
  198. out:
  199. /* Only LRADC1 can trigger PMU interrupt */
  200. if (cfg->adc_chan != PMUADC_ID_LRADC1) {
  201. k_delayed_work_submit(&adckey->timer, K_MSEC(cfg->poll_interval_ms));
  202. } else {
  203. if (((k_uptime_get_32() - adckey->timestamp) > cfg->poll_total_ms) && key_release) {
  204. adckey_acts_disable(dev);
  205. if (soc_pmu_register_notify(&detect_param))
  206. LOG_ERR("failed to register pmu notify");
  207. } else {
  208. #ifdef CONFIG_ADCKEY_POLL_TIMER
  209. k_timer_start(&adckey->timer, K_MSEC(cfg->poll_interval_ms), K_NO_WAIT);
  210. #else
  211. k_delayed_work_submit(&adckey->timer, K_MSEC(cfg->poll_interval_ms));
  212. #endif
  213. }
  214. }
  215. }
  216. static void adckey_acts_enable(const struct device *dev)
  217. {
  218. struct acts_adckey_data *adckey = dev->data;
  219. uint32_t key;
  220. LOG_DBG("enable adckey");
  221. key = irq_lock();
  222. if (adckey->state) {
  223. irq_unlock(key);
  224. return ;
  225. }
  226. adckey->state = 1;
  227. irq_unlock(key);
  228. adckey->timestamp = k_uptime_get_32();
  229. #ifdef CONFIG_ADCKEY_POLL_TIMER
  230. const struct acts_adckey_config *cfg = dev->config;
  231. k_timer_start(&adckey->timer, K_MSEC(cfg->poll_interval_ms), K_NO_WAIT);
  232. #else
  233. k_delayed_work_submit(&adckey->timer, K_NO_WAIT);
  234. #endif
  235. }
  236. static void adckey_acts_disable(const struct device *dev)
  237. {
  238. struct acts_adckey_data *adckey = dev->data;
  239. uint32_t key;
  240. LOG_DBG("disable adckey");
  241. key = irq_lock();
  242. if (!adckey->state) {
  243. irq_unlock(key);
  244. return ;
  245. }
  246. adckey->state = 0;
  247. irq_unlock(key);
  248. adckey->timestamp = 0;
  249. #ifdef CONFIG_ADCKEY_POLL_TIMER
  250. k_timer_stop(&adckey->timer);
  251. #else
  252. k_delayed_work_cancel(&adckey->timer);
  253. #endif
  254. }
  255. static void adckey_acts_register_notify(const struct device *dev, input_notify_t notify)
  256. {
  257. struct acts_adckey_data *adckey = dev->data;
  258. LOG_DBG("register notify 0x%x", (uint32_t)notify);
  259. adckey->notify = notify;
  260. }
  261. static void adckey_acts_unregister_notify(const struct device *dev, input_notify_t notify)
  262. {
  263. struct acts_adckey_data *adckey = dev->data;
  264. LOG_DBG("unregister notify 0x%x", (uint32_t)notify);
  265. adckey->notify = NULL;
  266. }
  267. const struct input_dev_driver_api adckey_acts_driver_api = {
  268. .enable = adckey_acts_enable,
  269. .disable = adckey_acts_disable,
  270. .inquiry = adckey_acts_inquiry,
  271. .register_notify = adckey_acts_register_notify,
  272. .unregister_notify = adckey_acts_unregister_notify,
  273. };
  274. static void adckey_pmu_notify(void *cb_data, int state)
  275. {
  276. struct device *dev = (struct device *)cb_data;
  277. LOG_INF("PMU notify state:%d", state);
  278. adckey_acts_enable(dev);
  279. }
  280. #ifdef CONFIG_CFG_DRV
  281. static int adckey_acts_config_init(const struct device *dev, uint8_t *channel_id)
  282. {
  283. struct acts_adckey_data *adckey = dev->data;
  284. int ret;
  285. CFG_Type_LRADC_Key Key[CFG_MAX_LRADC_KEYS];
  286. uint32_t LRADC_Ctrl;
  287. uint8_t i;
  288. ret = cfg_get_by_key(ITEM_LRADC_KEY, Key, sizeof(Key));
  289. if (!ret) {
  290. LOG_ERR("failed to get ITEM_LRADC_KEY");
  291. return -ESRCH;
  292. }
  293. for (i = 0; i < CFG_MAX_LRADC_KEYS; i++) {
  294. adckey->adckey_keymaps[i].key_code = Key[i].Key_Value;
  295. adckey->adckey_keymaps[i].adc_max = Key[i].ADC_Max;
  296. adckey->adckey_keymaps[i].adc_min = Key[i].ADC_Min;
  297. }
  298. ret = cfg_get_by_key(ITEM_LRADC_CTRL, &LRADC_Ctrl, sizeof(LRADC_Ctrl));
  299. if (!ret) {
  300. LOG_ERR("failed to get ITEM_LRADC_CTRL");
  301. return -ESRCH;
  302. }
  303. if (ret > 0) {
  304. uint8_t channel_no = LRADC_Ctrl & 0xff;
  305. uint8_t gpio_no = (LRADC_Ctrl & 0xff00) >> 8;
  306. uint32_t mfp_sel = (LRADC_Ctrl & 0xff0000) >> 16;
  307. /* remap channel number to LRADC index */
  308. channel_no += 5;
  309. if (channel_no < GPIO_MAX_PIN_NUM)
  310. sys_write32(mfp_sel, GPIO_REG_BASE + (1 + gpio_no)*4);
  311. else if (gpio_no < (GPIO_MAX_PIN_NUM + 4))
  312. sys_write32(mfp_sel, WIO0_CTL + (gpio_no - GPIO_MAX_PIN_NUM) * 4);
  313. *channel_id = channel_no;
  314. }
  315. return 0;
  316. }
  317. #endif
  318. int adckey_acts_init(const struct device *dev)
  319. {
  320. const struct acts_adckey_config *cfg = dev->config;
  321. struct acts_adckey_data *adckey = dev->data;
  322. struct adc_channel_cfg channel_cfg = {0};
  323. struct detect_param_t detect_param = {PMU_DETECT_DEV_REMOTE, adckey_pmu_notify, (void *)dev};
  324. adckey->adc_dev = device_get_binding(cfg->adc_name);
  325. if (!adckey->adc_dev) {
  326. LOG_ERR("cannot found adc dev %s\n", cfg->adc_name);
  327. return -ENODEV;
  328. }
  329. channel_cfg.channel_id = cfg->adc_chan;
  330. #ifdef CONFIG_CFG_DRV
  331. uint8_t channel_cfg_id;
  332. if (adckey_acts_config_init(dev, &channel_cfg_id))
  333. return -ENXIO;
  334. channel_cfg.channel_id = channel_cfg_id;
  335. #endif
  336. if (adc_channel_setup(adckey->adc_dev, &channel_cfg)) {
  337. LOG_ERR("setup channel_id %d error", channel_cfg.channel_id);
  338. return -EFAULT;
  339. }
  340. adckey->sequence.channels = BIT(cfg->adc_chan);
  341. adckey->sequence.buffer = &adckey->adc_buf[0];
  342. adckey->sequence.buffer_size = sizeof(adckey->adc_buf);
  343. adckey->this_dev = dev;
  344. if (soc_pmu_register_notify(&detect_param)) {
  345. LOG_ERR("failed to register pmu notify");
  346. return -ENXIO;
  347. }
  348. #ifdef CONFIG_ADCKEY_POLL_TIMER
  349. k_timer_init(&adckey->timer, adckey_acts_poll, NULL);
  350. k_timer_user_data_set(&adckey->timer, (void *)dev);
  351. #else
  352. k_delayed_work_init(&adckey->timer, adckey_acts_poll);
  353. #endif
  354. return 0;
  355. }
  356. static struct acts_adckey_data adckey_acts_ddata;
  357. #ifndef CONFIG_CFG_DRV
  358. static const struct adckey_map adckey_acts_keymaps[] = {
  359. #ifdef BOARD_ADCKEY_KEY_MAPPINGS
  360. BOARD_ADCKEY_KEY_MAPPINGS
  361. #endif
  362. };
  363. #endif
  364. static const struct acts_adckey_config adckey_acts_cdata = {
  365. .adc_name = CONFIG_PMUADC_NAME,
  366. .adc_chan = CONFIG_ADCKEY_LRADC_CHAN,
  367. .poll_interval_ms = CONFIG_ADCKEY_POLL_INTERVAL_MS,
  368. .poll_total_ms = CONFIG_ADCKEY_POLL_TOTAL_MS,
  369. .sample_filter_dep = CONFIG_ADCKEY_SAMPLE_FILTER_CNT,
  370. #ifndef CONFIG_CFG_DRV
  371. .key_cnt = ARRAY_SIZE(adckey_acts_keymaps),
  372. .key_maps = &adckey_acts_keymaps[0],
  373. #endif
  374. };
  375. #if IS_ENABLED(CONFIG_ADCKEY)
  376. DEVICE_DEFINE(adckey_acts, CONFIG_INPUT_DEV_ACTS_ADCKEY_NAME,
  377. adckey_acts_init, NULL,
  378. &adckey_acts_ddata, &adckey_acts_cdata,
  379. PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
  380. &adckey_acts_driver_api);
  381. #endif