serial.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Generic serial console support
  4. *
  5. * Author: Mark A. Greer <[email protected]>
  6. *
  7. * Code in serial_edit_cmdline() copied from <file:arch/ppc/boot/simple/misc.c>
  8. * and was written by Matt Porter <[email protected]>.
  9. *
  10. * 2001,2006 (c) MontaVista Software, Inc.
  11. */
  12. #include <stdarg.h>
  13. #include <stddef.h>
  14. #include "types.h"
  15. #include "string.h"
  16. #include "stdio.h"
  17. #include "io.h"
  18. #include "ops.h"
  19. static int serial_open(void)
  20. {
  21. struct serial_console_data *scdp = console_ops.data;
  22. return scdp->open();
  23. }
  24. static void serial_write(const char *buf, int len)
  25. {
  26. struct serial_console_data *scdp = console_ops.data;
  27. while (*buf != '\0')
  28. scdp->putc(*buf++);
  29. }
  30. static void serial_edit_cmdline(char *buf, int len, unsigned int timeout)
  31. {
  32. int timer = 0, count;
  33. char ch, *cp;
  34. struct serial_console_data *scdp = console_ops.data;
  35. cp = buf;
  36. count = strlen(buf);
  37. cp = &buf[count];
  38. count++;
  39. do {
  40. if (scdp->tstc()) {
  41. while (((ch = scdp->getc()) != '\n') && (ch != '\r')) {
  42. /* Test for backspace/delete */
  43. if ((ch == '\b') || (ch == '\177')) {
  44. if (cp != buf) {
  45. cp--;
  46. count--;
  47. printf("\b \b");
  48. }
  49. /* Test for ^x/^u (and wipe the line) */
  50. } else if ((ch == '\030') || (ch == '\025')) {
  51. while (cp != buf) {
  52. cp--;
  53. count--;
  54. printf("\b \b");
  55. }
  56. } else if (count < len) {
  57. *cp++ = ch;
  58. count++;
  59. scdp->putc(ch);
  60. }
  61. }
  62. break; /* Exit 'timer' loop */
  63. }
  64. udelay(1000); /* 1 msec */
  65. } while (timer++ < timeout);
  66. *cp = 0;
  67. }
  68. static void serial_close(void)
  69. {
  70. struct serial_console_data *scdp = console_ops.data;
  71. if (scdp->close)
  72. scdp->close();
  73. }
  74. static void *serial_get_stdout_devp(void)
  75. {
  76. void *devp;
  77. char devtype[MAX_PROP_LEN];
  78. char path[MAX_PATH_LEN];
  79. devp = finddevice("/chosen");
  80. if (devp == NULL)
  81. goto err_out;
  82. if (getprop(devp, "linux,stdout-path", path, MAX_PATH_LEN) > 0 ||
  83. getprop(devp, "stdout-path", path, MAX_PATH_LEN) > 0) {
  84. devp = finddevice(path);
  85. if (devp == NULL)
  86. goto err_out;
  87. if ((getprop(devp, "device_type", devtype, sizeof(devtype)) > 0)
  88. && !strcmp(devtype, "serial"))
  89. return devp;
  90. }
  91. err_out:
  92. return NULL;
  93. }
  94. static struct serial_console_data serial_cd;
  95. /* Node's "compatible" property determines which serial driver to use */
  96. int serial_console_init(void)
  97. {
  98. void *devp;
  99. int rc = -1;
  100. devp = serial_get_stdout_devp();
  101. if (devp == NULL)
  102. goto err_out;
  103. if (dt_is_compatible(devp, "ns16550") ||
  104. dt_is_compatible(devp, "pnpPNP,501"))
  105. rc = ns16550_console_init(devp, &serial_cd);
  106. #ifdef CONFIG_CPM
  107. else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") ||
  108. dt_is_compatible(devp, "fsl,cpm1-smc-uart") ||
  109. dt_is_compatible(devp, "fsl,cpm2-scc-uart") ||
  110. dt_is_compatible(devp, "fsl,cpm2-smc-uart"))
  111. rc = cpm_console_init(devp, &serial_cd);
  112. #endif
  113. #ifdef CONFIG_PPC_MPC52xx
  114. else if (dt_is_compatible(devp, "fsl,mpc5200-psc-uart"))
  115. rc = mpc5200_psc_console_init(devp, &serial_cd);
  116. #endif
  117. #ifdef CONFIG_PPC_POWERNV
  118. else if (dt_is_compatible(devp, "ibm,opal-console-raw"))
  119. rc = opal_console_init(devp, &serial_cd);
  120. #endif
  121. /* Add other serial console driver calls here */
  122. if (!rc) {
  123. console_ops.open = serial_open;
  124. console_ops.write = serial_write;
  125. console_ops.close = serial_close;
  126. console_ops.data = &serial_cd;
  127. if (serial_cd.getc)
  128. console_ops.edit_cmdline = serial_edit_cmdline;
  129. return 0;
  130. }
  131. err_out:
  132. return -1;
  133. }