ark_mcu_serial.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * Arkmicro mcu serial driver
  3. *
  4. * Licensed under GPLv2 or later.
  5. */
  6. #include <linux/module.h>
  7. #include <linux/ioport.h>
  8. #include <linux/init.h>
  9. #include <linux/console.h>
  10. #include <linux/sysrq.h>
  11. #include <linux/device.h>
  12. #include <linux/tty.h>
  13. #include <linux/tty_flip.h>
  14. #include <linux/serial_core.h>
  15. #include <linux/serial.h>
  16. #include <linux/amba/bus.h>
  17. #include <linux/amba/serial.h>
  18. #include <linux/clk.h>
  19. #include <linux/slab.h>
  20. #include <linux/dmaengine.h>
  21. #include <linux/dma-mapping.h>
  22. #include <linux/scatterlist.h>
  23. #include <linux/delay.h>
  24. #include <linux/types.h>
  25. #include <linux/of.h>
  26. #include <linux/of_device.h>
  27. #include <linux/pinctrl/consumer.h>
  28. #include <linux/sizes.h>
  29. #include <linux/io.h>
  30. #include <linux/acpi.h>
  31. #include <linux/module.h>
  32. #include <linux/init.h>
  33. #include <linux/device.h>
  34. #include <linux/spinlock.h>
  35. #include <linux/workqueue.h>
  36. #define RX_BUF_SIZE PAGE_SIZE
  37. struct mcu_serial_info {
  38. int rx_head;
  39. int rx_tail;
  40. int carback_ready;
  41. unsigned char *rx_buf;
  42. spinlock_t lock;
  43. struct work_struct rx_task;
  44. };
  45. extern int mcu_serial_send(const unsigned char *buf, int len);
  46. extern void mcu_serial_register_rev_handler(void (*handler)(unsigned char ch), struct work_struct *task);
  47. extern void mcu_serial_unregister_rev_handler(void);
  48. extern void get_mcu_carback_data(unsigned char ch);
  49. static struct mcu_serial_info *msinfo;
  50. void ark_set_track_ready(void)
  51. {
  52. msinfo->carback_ready = 1;
  53. }
  54. EXPORT_SYMBOL(ark_set_track_ready);
  55. void ark_set_track_noready(void)
  56. {
  57. msinfo->carback_ready = 0;
  58. }
  59. EXPORT_SYMBOL(ark_set_track_noready);
  60. static void mcu_serial_get_ch(unsigned char ch)
  61. {
  62. struct mcu_serial_info *info = msinfo;
  63. unsigned long flags;
  64. spin_lock_irqsave(&info->lock, flags);
  65. //printk(KERN_ALERT "++++++ mcu_serial_get_ch rev ch = %d\n",ch);
  66. info->rx_buf[info->rx_head] = ch;
  67. if(info->carback_ready)
  68. get_mcu_carback_data(info->rx_buf[info->rx_head]);
  69. info->rx_head = (info->rx_head + 1) & (RX_BUF_SIZE - 1);
  70. if (info->rx_head == info->rx_tail) {
  71. printk("rev buf is full, lost ch.\n");
  72. if (--info->rx_head < 0)
  73. info->rx_head = RX_BUF_SIZE - 1;
  74. }
  75. spin_unlock_irqrestore(&info->lock, flags);
  76. }
  77. static void mcu_serial_rx_task(struct work_struct *work)
  78. {
  79. struct mcu_serial_info *info =
  80. container_of(work, struct mcu_serial_info, rx_task);
  81. int count;
  82. unsigned long flags;
  83. spin_lock_irqsave(&info->lock, flags);
  84. count = info->rx_head - info->rx_tail;
  85. spin_unlock_irqrestore(&info->lock, flags);
  86. if (count < 0)
  87. count += RX_BUF_SIZE;
  88. printk("rx count=%d.\n", count);
  89. }
  90. static int ark_mcu_serial_probe(struct platform_device *pdev)
  91. {
  92. struct mcu_serial_info *info = devm_kzalloc(&pdev->dev, sizeof(struct mcu_serial_info),
  93. GFP_KERNEL);
  94. if (!info)
  95. return -ENOMEM;
  96. info->rx_buf = devm_kzalloc(&pdev->dev, RX_BUF_SIZE, GFP_KERNEL);
  97. if (!info->rx_buf)
  98. return -ENOMEM;
  99. msinfo = info;
  100. info->carback_ready = 0;
  101. INIT_WORK(&info->rx_task, mcu_serial_rx_task);
  102. mcu_serial_register_rev_handler(mcu_serial_get_ch, &info->rx_task);
  103. platform_set_drvdata(pdev, info);
  104. printk(KERN_ALERT "enable get mcu data\n");
  105. return 0;
  106. }
  107. static int ark_mcu_serial_remove(struct platform_device *pdev)
  108. {
  109. struct mcu_serial_info *info = platform_get_drvdata(pdev);
  110. cancel_work_sync(&info->rx_task);
  111. mcu_serial_unregister_rev_handler();
  112. return 0;
  113. }
  114. static const struct of_device_id ark_mcu_serial_of_match[] = {
  115. { .compatible = "arkmicro,ark-mcu-serial", },
  116. {},
  117. };
  118. static struct platform_driver ark_mcu_serial_platform_driver = {
  119. .probe = ark_mcu_serial_probe,
  120. .remove = ark_mcu_serial_remove,
  121. .driver = {
  122. .name = "ark-mcu-serial",
  123. .of_match_table = of_match_ptr(ark_mcu_serial_of_match),
  124. },
  125. };
  126. static int __init ark_mcu_serial_init(void)
  127. {
  128. return platform_driver_register(&ark_mcu_serial_platform_driver);
  129. }
  130. static void __exit ark_mcu_serial_exit(void)
  131. {
  132. platform_driver_unregister(&ark_mcu_serial_platform_driver);
  133. }
  134. /*
  135. * While this can be a module, if builtin it's most likely the console
  136. * So let's leave module_exit but move module_init to an earlier place
  137. */
  138. arch_initcall(ark_mcu_serial_init);
  139. module_exit(ark_mcu_serial_exit);
  140. MODULE_AUTHOR("Sim");
  141. MODULE_DESCRIPTION("Arkmicro mcu serial driver");
  142. MODULE_LICENSE("GPL v2");