shf_kernel.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. #include <asm/atomic.h>
  2. #include <asm/uaccess.h>
  3. #include <cust_acc.h>
  4. #include <mach/md32_ipi.h>
  5. #include <mach/mt_gpio.h>
  6. #include <mach/mt_pm_ldo.h>
  7. #include <mach/mt_typedefs.h>
  8. #include <linux/delay.h>
  9. #include <linux/earlysuspend.h>
  10. #include <linux/i2c.h>
  11. #include <linux/input.h>
  12. #include <linux/interrupt.h>
  13. #include <linux/ioctl.h>
  14. #include <linux/irq.h>
  15. #include <linux/kobject.h>
  16. #include <linux/miscdevice.h>
  17. #include <linux/mutex.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/sched.h>
  20. #include <linux/slab.h>
  21. #include <linux/wakelock.h>
  22. #include <linux/workqueue.h>
  23. #include "shf_kernel.h"
  24. /*----------------------------------------------------------------------------*/
  25. #define SHF_TAG "[shf_kernel] "
  26. #define SHF_FUN(f) pr_debug(SHF_TAG"%s\n", __func__)
  27. #define SHF_ERR(fmt, args...) pr_err("%s %d : "fmt, __func__, __LINE__, ##args)
  28. #define SHF_LOG(fmt, args...) pr_debug(SHF_TAG fmt, ##args)
  29. /*----------------------------------------------------------------------------*/
  30. /* static bool shf_ring_buffer_empty = true; */
  31. static int shf_init_flag = -1; /* 0->ok, -1->fail */
  32. static struct platform_driver shf_driver;
  33. struct wake_lock shf_suspend_lock;
  34. static DEFINE_SPINLOCK(shf_spinlock);
  35. bool ring_buffer_poll(struct ipi_buffer_t *buffer, struct ipi_data_t *data)
  36. {
  37. unsigned long flags = 0;
  38. spin_lock_irqsave(&shf_spinlock, flags);
  39. SHF_LOG("poll: head=%zu, tail=%zu\n", buffer->head, buffer->tail);
  40. if (data && buffer->head != buffer->tail) {
  41. memcpy(data, buffer->data + buffer->head, sizeof(struct ipi_data_t));
  42. buffer->head = (buffer->head + 1) % buffer->size;
  43. spin_unlock_irqrestore(&shf_spinlock, flags);
  44. return true;
  45. }
  46. spin_unlock_irqrestore(&shf_spinlock, flags);
  47. return false;
  48. }
  49. bool ring_buffer_push(struct ipi_buffer_t *buffer, void *data, size_t size)
  50. {
  51. unsigned long flags = 0;
  52. spin_lock_irqsave(&shf_spinlock, flags);
  53. SHF_LOG("push: head=%zu, tail=%zu, size=%zu\n", buffer->head, buffer->tail, size);
  54. if ((buffer->tail + 1) % buffer->size != buffer->head) {
  55. struct ipi_data_t *dst = buffer->data + buffer->tail;
  56. memcpy((void *)dst, data, size);
  57. dst->size = size;
  58. buffer->tail = (buffer->tail + 1) % buffer->size;
  59. spin_unlock_irqrestore(&shf_spinlock, flags);
  60. return true;
  61. }
  62. spin_unlock_irqrestore(&shf_spinlock, flags);
  63. return false;
  64. }
  65. /******************************************************************/
  66. /* cach ipi message to buffer, so ipi callback will return quickly. */
  67. #define IPI_TRIGGER_BUFFER_COUNT (32)
  68. static struct ipi_data_t trigger_data[IPI_TRIGGER_BUFFER_COUNT];
  69. static struct ipi_buffer_t trigger_buffer = {
  70. .head = 0,
  71. .tail = 0,
  72. .size = IPI_TRIGGER_BUFFER_COUNT,
  73. .data = trigger_data,
  74. };
  75. /******************************************************************/
  76. static DECLARE_WAIT_QUEUE_HEAD(data_wq);
  77. static void event_init(void)
  78. {
  79. init_waitqueue_head(&data_wq);
  80. }
  81. static void event_destroy(void)
  82. {
  83. /* event_destroy(&shf_event); */
  84. }
  85. static int wait(void)
  86. {
  87. int ret;
  88. ret = wait_event_interruptible(data_wq, trigger_buffer.head != trigger_buffer.tail);
  89. if (ret) {
  90. SHF_ERR("wait: head=0x%zx, tail=0x%zx, ret=%d\n", trigger_buffer.head,
  91. trigger_buffer.tail, ret);
  92. }
  93. return ret;
  94. }
  95. static void notify(void)
  96. {
  97. wake_up(&data_wq);
  98. wake_lock_timeout(&shf_suspend_lock, HZ / 2);
  99. }
  100. /******************************************************************************
  101. * Function Configuration
  102. ******************************************************************************/
  103. static ssize_t show_chipinfo_value(struct device_driver *ddri, char *buf)
  104. {
  105. return 0;
  106. }
  107. /*----------------------------------------------------------------------------*/
  108. static ssize_t show_buffer_value(struct device_driver *ddri, char *buf)
  109. {
  110. return 0;
  111. }
  112. /*----------------------------------------------------------------------------*/
  113. static DRIVER_ATTR(chipinfo, S_IWUSR | S_IRUGO, show_chipinfo_value, NULL);
  114. static DRIVER_ATTR(buffer, S_IWUSR | S_IRUGO, show_buffer_value, NULL);
  115. /*----------------------------------------------------------------------------*/
  116. static struct driver_attribute *shf_attr_list[] = {
  117. &driver_attr_chipinfo, /*chip information */
  118. &driver_attr_buffer, /*dump buffer data */
  119. };
  120. /*----------------------------------------------------------------------------*/
  121. static int shf_create_attr(struct device_driver *driver)
  122. {
  123. int idx, err = 0;
  124. int num = (int)(sizeof(shf_attr_list) / sizeof(shf_attr_list[0]));
  125. if (driver == NULL)
  126. return -EINVAL;
  127. for (idx = 0; idx < num; idx++) {
  128. err = driver_create_file(driver, shf_attr_list[idx]);
  129. if (err != 0) {
  130. SHF_ERR("driver_create_file (%s) = %d\n", shf_attr_list[idx]->attr.name,
  131. err);
  132. break;
  133. }
  134. }
  135. return err;
  136. }
  137. /*----------------------------------------------------------------------------*/
  138. static int shf_delete_attr(struct device_driver *driver)
  139. {
  140. int idx, err = 0;
  141. int num = (int)(sizeof(shf_attr_list) / sizeof(shf_attr_list[0]));
  142. if (driver == NULL)
  143. return -EINVAL;
  144. for (idx = 0; idx < num; idx++)
  145. driver_remove_file(driver, shf_attr_list[idx]);
  146. return err;
  147. }
  148. /*----------------------------------------------------------------------------*/
  149. static int shf_open(struct inode *inode, struct file *file)
  150. {
  151. SHF_FUN();
  152. /* Now, we don't hava any private data */
  153. file->private_data = NULL;
  154. return nonseekable_open(inode, file);
  155. }
  156. /*----------------------------------------------------------------------------*/
  157. static int shf_release(struct inode *inode, struct file *file)
  158. {
  159. file->private_data = NULL;
  160. return 0;
  161. }
  162. /*----------------------------------------------------------------------------*/
  163. /*
  164. static void shf_print_bytes(void* buffer, size_t size) {
  165. uint8_t* data;
  166. int i;
  167. if (!buffer) {
  168. SHF_ERR("print: null\n");
  169. return;
  170. }
  171. data = (uint8_t*)buffer;
  172. SHF_LOG("print: size=%d. ", size);
  173. for (i = 0; i < size; i++) {
  174. SHF_LOG("0x%.2x ", *(data + i));
  175. }
  176. SHF_LOG("\n");
  177. }
  178. */
  179. /*----------------------------------------------------------------------------*/
  180. static long shf_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
  181. {
  182. struct ipi_data_t in_data;
  183. struct ipi_data_t out_data;
  184. void __user *data;
  185. long err = 0;
  186. ipi_status status = DONE;
  187. ipi_status pre_status = DONE;
  188. if (shf_init_flag != 0) {
  189. SHF_ERR("IOCTL: initflag=%d\n", shf_init_flag);
  190. return -EFAULT; /* TODO should check error no */
  191. }
  192. /*
  193. if(_IOC_DIR(cmd) & _IOC_READ) {
  194. err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
  195. }
  196. else if(_IOC_DIR(cmd) & _IOC_WRITE) {
  197. err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
  198. }
  199. if(err) {
  200. SHF_ERR("access error: %08X, (%2d, %2d)\n", cmd, _IOC_DIR(cmd), _IOC_SIZE(cmd));
  201. return -EFAULT;
  202. }
  203. */
  204. switch (cmd) {
  205. case SHF_IPI_SEND:
  206. /* SHF_LOG("IOCTL: SHF_IPI_SEND\n"); */
  207. data = (void __user *)arg;
  208. if (copy_from_user((void *)&in_data, data, sizeof(struct ipi_data_t))) {
  209. err = -EFAULT;
  210. SHF_ERR("SHF_IPI_SEND: copy failed!\n");
  211. break;
  212. }
  213. /* shf_print_bytes(in_data.data, in_data.size); */
  214. do {
  215. status = md32_ipi_send(IPI_SHF, in_data.data, in_data.size, 0);
  216. if (status != pre_status || DONE == pre_status)
  217. SHF_LOG("SHF_IPI_SEND: size=%zu, status=%d\n", in_data.size,
  218. status);
  219. err = status;
  220. pre_status = status;
  221. } while (DONE != status);
  222. mdelay(10);
  223. /* SHF_LOG("SHF_IPI_SEND: delayed 10ms.\n"); */
  224. break;
  225. case SHF_IPI_POLL:
  226. /* SHF_LOG("IOCTL: SHF_IPI_POLL\n"); */
  227. data = (void __user *)arg;
  228. if (data == NULL) {
  229. err = -EINVAL;
  230. break;
  231. }
  232. memset(&out_data, 0, sizeof(struct ipi_data_t));
  233. if (trigger_buffer.head == trigger_buffer.tail) {
  234. if (wait()) {
  235. err = -EINTR;
  236. break;
  237. }
  238. }
  239. if (!ring_buffer_poll(&trigger_buffer, &out_data)) {
  240. err = -EFAULT;
  241. SHF_ERR("SHF_IPI_POLL: failed!\n");
  242. break;
  243. }
  244. if (copy_to_user(data, &out_data, sizeof(struct ipi_data_t))) {
  245. err = -EFAULT;
  246. SHF_ERR("SHF_IPI_POLL: copy failed!\n");
  247. break;
  248. }
  249. break;
  250. case SHF_GESTURE_ENABLE:
  251. /* SHF_LOG("IOCTL: SHF_GESTURE_ENABLE. enable=%d\n", arg); */
  252. #ifdef CONFIG_MTK_SENSOR_HUB_SUPPORT
  253. tpd_scp_wakeup_enable(arg);
  254. #endif
  255. break;
  256. default:
  257. SHF_ERR("unknown IOCTL: 0x%08x\n", cmd);
  258. err = -ENOIOCTLCMD;
  259. break;
  260. }
  261. return err;
  262. }
  263. /*----------------------------------------------------------------------------*/
  264. static const struct file_operations shf_fops = {
  265. .owner = THIS_MODULE,
  266. .open = shf_open,
  267. .release = shf_release,
  268. .unlocked_ioctl = shf_unlocked_ioctl,
  269. /* .ioctl = shf_ioctl, */
  270. };
  271. /*----------------------------------------------------------------------------*/
  272. static struct miscdevice shf_device = {
  273. .minor = MISC_DYNAMIC_MINOR,
  274. .name = "shf",
  275. .fops = &shf_fops,
  276. };
  277. /*----------------------------------------------------------------------------*/
  278. static void shf_ipi_receive_handler(int id, void *data, uint size)
  279. {
  280. if (id == IPI_SHF) {
  281. /* shf_print_bytes(data, size); */
  282. SHF_LOG("IPI_SHF\n");
  283. ring_buffer_push(&trigger_buffer, data, size);
  284. notify();
  285. }
  286. }
  287. /*----------------------------------------------------------------------------*/
  288. static int shf_driver_probe(struct platform_device *pdev)
  289. {
  290. int err = 0;
  291. event_init(); /* init event for wait/notify */
  292. err = misc_register(&shf_device);
  293. if (err != 0) {
  294. SHF_ERR("register device failed!\n");
  295. goto exit_misc_device_register_failed;
  296. }
  297. err = shf_create_attr(&shf_driver.driver);
  298. if (err != 0) {
  299. SHF_ERR("create attribute err=%d\n", err);
  300. goto exit_create_attr_failed;
  301. }
  302. err = md32_ipi_registration(IPI_SHF, shf_ipi_receive_handler, "shf_ipi_receive_handler");
  303. if (DONE != err)
  304. goto exit_ipi_receive_register_failed;
  305. shf_init_flag = 0;
  306. SHF_LOG("register device succeed.\n");
  307. return 0;
  308. exit_ipi_receive_register_failed:
  309. exit_create_attr_failed:
  310. misc_deregister(&shf_device);
  311. exit_misc_device_register_failed:
  312. SHF_ERR("%s: err=%d\n", __func__, err);
  313. shf_init_flag = -1;
  314. return err;
  315. }
  316. /*----------------------------------------------------------------------------*/
  317. static int shf_driver_remove(struct platform_device *pdev)
  318. {
  319. int err = 0;
  320. SHF_FUN();
  321. err = shf_delete_attr(&shf_driver.driver);
  322. if (err != 0)
  323. SHF_ERR("shf_delete_attr fail: %d\n", err);
  324. err = misc_deregister(&shf_device);
  325. if (err != 0)
  326. SHF_ERR("misc_deregister shf_device fail: %d\n", err);
  327. md32_ipi_registration(IPI_SHF, NULL, NULL);
  328. event_destroy(); /* destroy event for wait/notify */
  329. return 0;
  330. }
  331. /*----------------------------------------------------------------------------*/
  332. /*
  333. static struct platform_driver shf_driver = {
  334. .probe = shf_driver_probe,
  335. .remove = shf_driver_remove,
  336. .driver = {
  337. .name = "shf",
  338. .owner = THIS_MODULE,
  339. }
  340. };
  341. */
  342. /*----------------------------------------------------------------------------*/
  343. #ifdef CONFIG_OF
  344. static const struct of_device_id shf_of_match[] = {
  345. {.compatible = "mediatek,shf",},
  346. {},
  347. };
  348. #endif
  349. static struct platform_driver shf_driver = {
  350. .probe = shf_driver_probe,
  351. .remove = shf_driver_remove,
  352. .driver = {
  353. .name = "shf",
  354. #ifdef CONFIG_OF
  355. .of_match_table = shf_of_match,
  356. #endif
  357. }
  358. };
  359. /*----------------------------------------------------------------------------*/
  360. static int __init shf_driver_init(void)
  361. {
  362. SHF_FUN();
  363. if (platform_driver_register(&shf_driver)) {
  364. SHF_ERR("failed to register shf driver");
  365. return -ENODEV;
  366. }
  367. wake_lock_init(&shf_suspend_lock, WAKE_LOCK_SUSPEND, "shf_wakelock");
  368. return 0;
  369. }
  370. /*----------------------------------------------------------------------------*/
  371. static void __exit shf_driver_exit(void)
  372. {
  373. SHF_FUN();
  374. platform_driver_unregister(&shf_driver);
  375. }
  376. /*----------------------------------------------------------------------------*/
  377. module_init(shf_driver_init);
  378. module_exit(shf_driver_exit);
  379. /*----------------------------------------------------------------------------*/
  380. MODULE_LICENSE("GPL");
  381. MODULE_DESCRIPTION("sensor hub framework driver");
  382. MODULE_AUTHOR("mediatek.inc.");
  383. /*----------------------------------------------------------------------------*/