ark_mcu_serial.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. unsigned char *rx_buf;
  41. spinlock_t lock;
  42. struct work_struct rx_task;
  43. };
  44. extern int mcu_serial_send(const unsigned char *buf, int len);
  45. extern void mcu_serial_register_rev_handler(void (*handler)(int ch), struct work_struct *task);
  46. extern void mcu_serial_unregister_rev_handler(void);
  47. static struct mcu_serial_info *msinfo;
  48. static void mcu_serial_get_ch(int ch)
  49. {
  50. struct mcu_serial_info *info = msinfo;
  51. unsigned long flags;
  52. spin_lock_irqsave(&info->lock, flags);
  53. info->rx_buf[info->rx_head] = ch;
  54. info->rx_head = (info->rx_head + 1) & (RX_BUF_SIZE - 1);
  55. if (info->rx_head == info->rx_tail) {
  56. printk("rev buf is full, lost ch.\n");
  57. if (--info->rx_head < 0)
  58. info->rx_head = RX_BUF_SIZE - 1;
  59. }
  60. spin_unlock_irqrestore(&info->lock, flags);
  61. }
  62. static void mcu_serial_rx_task(struct work_struct *work)
  63. {
  64. struct mcu_serial_info *info =
  65. container_of(work, struct mcu_serial_info, rx_task);
  66. int count;
  67. unsigned long flags;
  68. spin_lock_irqsave(&info->lock, flags);
  69. count = info->rx_head - info->rx_tail;
  70. spin_unlock_irqrestore(&info->lock, flags);
  71. if (count < 0)
  72. count += RX_BUF_SIZE;
  73. printk("rx count=%d.\n", count);
  74. }
  75. static int ark_mcu_serial_probe(struct platform_device *pdev)
  76. {
  77. struct mcu_serial_info *info = devm_kzalloc(&pdev->dev, sizeof(struct mcu_serial_info),
  78. GFP_KERNEL);
  79. if (!info)
  80. return -ENOMEM;
  81. info->rx_buf = devm_kzalloc(&pdev->dev, RX_BUF_SIZE, GFP_KERNEL);
  82. if (!info->rx_buf)
  83. return -ENOMEM;
  84. msinfo = info;
  85. INIT_WORK(&info->rx_task, mcu_serial_rx_task);
  86. mcu_serial_register_rev_handler(mcu_serial_get_ch, &info->rx_task);
  87. platform_set_drvdata(pdev, info);
  88. return 0;
  89. }
  90. static int ark_mcu_serial_remove(struct platform_device *pdev)
  91. {
  92. struct mcu_serial_info *info = platform_get_drvdata(pdev);
  93. cancel_work_sync(&info->rx_task);
  94. mcu_serial_unregister_rev_handler();
  95. return 0;
  96. }
  97. static const struct of_device_id ark_mcu_serial_of_match[] = {
  98. { .compatible = "arkmicro,ark-mcu-serial", },
  99. {},
  100. };
  101. static struct platform_driver ark_mcu_serial_platform_driver = {
  102. .probe = ark_mcu_serial_probe,
  103. .remove = ark_mcu_serial_remove,
  104. .driver = {
  105. .name = "ark-mcu-serial",
  106. .of_match_table = of_match_ptr(ark_mcu_serial_of_match),
  107. },
  108. };
  109. static int __init ark_mcu_serial_init(void)
  110. {
  111. return platform_driver_register(&ark_mcu_serial_platform_driver);
  112. }
  113. static void __exit ark_mcu_serial_exit(void)
  114. {
  115. platform_driver_unregister(&ark_mcu_serial_platform_driver);
  116. }
  117. /*
  118. * While this can be a module, if builtin it's most likely the console
  119. * So let's leave module_exit but move module_init to an earlier place
  120. */
  121. arch_initcall(ark_mcu_serial_init);
  122. module_exit(ark_mcu_serial_exit);
  123. MODULE_AUTHOR("Sim");
  124. MODULE_DESCRIPTION("Arkmicro mcu serial driver");
  125. MODULE_LICENSE("GPL v2");