hvc_dcc.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /* Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #include <linux/init.h>
  13. #include <asm/dcc.h>
  14. #include <asm/processor.h>
  15. #include "hvc_console.h"
  16. /* DCC Status Bits */
  17. #define DCC_STATUS_RX (1 << 30)
  18. #define DCC_STATUS_TX (1 << 29)
  19. static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
  20. {
  21. int i;
  22. for (i = 0; i < count; i++) {
  23. while (__dcc_getstatus() & DCC_STATUS_TX)
  24. cpu_relax();
  25. __dcc_putchar(buf[i]);
  26. }
  27. return count;
  28. }
  29. static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
  30. {
  31. int i;
  32. for (i = 0; i < count; ++i)
  33. if (__dcc_getstatus() & DCC_STATUS_RX)
  34. buf[i] = __dcc_getchar();
  35. else
  36. break;
  37. return i;
  38. }
  39. static bool hvc_dcc_check(void)
  40. {
  41. unsigned long time = jiffies + (HZ / 10);
  42. /* Write a test character to check if it is handled */
  43. __dcc_putchar('\n');
  44. while (time_is_after_jiffies(time)) {
  45. if (!(__dcc_getstatus() & DCC_STATUS_TX))
  46. return true;
  47. }
  48. return false;
  49. }
  50. static const struct hv_ops hvc_dcc_get_put_ops = {
  51. .get_chars = hvc_dcc_get_chars,
  52. .put_chars = hvc_dcc_put_chars,
  53. };
  54. static int __init hvc_dcc_console_init(void)
  55. {
  56. int ret;
  57. if (!hvc_dcc_check())
  58. return -ENODEV;
  59. /* Returns -1 if error */
  60. ret = hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
  61. return ret < 0 ? -ENODEV : 0;
  62. }
  63. console_initcall(hvc_dcc_console_init);
  64. static int __init hvc_dcc_init(void)
  65. {
  66. struct hvc_struct *p;
  67. if (!hvc_dcc_check())
  68. return -ENODEV;
  69. p = hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
  70. return PTR_ERR_OR_ZERO(p);
  71. }
  72. device_initcall(hvc_dcc_init);