sh_bios.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * C interface for trapping into the standard LinuxSH BIOS.
  4. *
  5. * Copyright (C) 2000 Greg Banks, Mitch Davis
  6. * Copyright (C) 1999, 2000 Niibe Yutaka
  7. * Copyright (C) 2002 M. R. Brown
  8. * Copyright (C) 2004 - 2010 Paul Mundt
  9. */
  10. #include <linux/module.h>
  11. #include <linux/console.h>
  12. #include <linux/tty.h>
  13. #include <linux/init.h>
  14. #include <linux/io.h>
  15. #include <linux/delay.h>
  16. #include <asm/sh_bios.h>
  17. #define BIOS_CALL_CONSOLE_WRITE 0
  18. #define BIOS_CALL_ETH_NODE_ADDR 10
  19. #define BIOS_CALL_SHUTDOWN 11
  20. #define BIOS_CALL_GDB_DETACH 0xff
  21. void *gdb_vbr_vector = NULL;
  22. static inline long sh_bios_call(long func, long arg0, long arg1, long arg2,
  23. long arg3)
  24. {
  25. register long r0 __asm__("r0") = func;
  26. register long r4 __asm__("r4") = arg0;
  27. register long r5 __asm__("r5") = arg1;
  28. register long r6 __asm__("r6") = arg2;
  29. register long r7 __asm__("r7") = arg3;
  30. if (!gdb_vbr_vector)
  31. return -ENOSYS;
  32. __asm__ __volatile__("trapa #0x3f":"=z"(r0)
  33. :"0"(r0), "r"(r4), "r"(r5), "r"(r6), "r"(r7)
  34. :"memory");
  35. return r0;
  36. }
  37. void sh_bios_console_write(const char *buf, unsigned int len)
  38. {
  39. sh_bios_call(BIOS_CALL_CONSOLE_WRITE, (long)buf, (long)len, 0, 0);
  40. }
  41. void sh_bios_gdb_detach(void)
  42. {
  43. sh_bios_call(BIOS_CALL_GDB_DETACH, 0, 0, 0, 0);
  44. }
  45. EXPORT_SYMBOL_GPL(sh_bios_gdb_detach);
  46. void sh_bios_get_node_addr(unsigned char *node_addr)
  47. {
  48. sh_bios_call(BIOS_CALL_ETH_NODE_ADDR, 0, (long)node_addr, 0, 0);
  49. }
  50. EXPORT_SYMBOL_GPL(sh_bios_get_node_addr);
  51. void sh_bios_shutdown(unsigned int how)
  52. {
  53. sh_bios_call(BIOS_CALL_SHUTDOWN, how, 0, 0, 0);
  54. }
  55. /*
  56. * Read the old value of the VBR register to initialise the vector
  57. * through which debug and BIOS traps are delegated by the Linux trap
  58. * handler.
  59. */
  60. void sh_bios_vbr_init(void)
  61. {
  62. unsigned long vbr;
  63. if (unlikely(gdb_vbr_vector))
  64. return;
  65. __asm__ __volatile__ ("stc vbr, %0" : "=r" (vbr));
  66. if (vbr) {
  67. gdb_vbr_vector = (void *)(vbr + 0x100);
  68. printk(KERN_NOTICE "Setting GDB trap vector to %p\n",
  69. gdb_vbr_vector);
  70. } else
  71. printk(KERN_NOTICE "SH-BIOS not detected\n");
  72. }
  73. /**
  74. * sh_bios_vbr_reload - Re-load the system VBR from the BIOS vector.
  75. *
  76. * This can be used by save/restore code to reinitialize the system VBR
  77. * from the fixed BIOS VBR. A no-op if no BIOS VBR is known.
  78. */
  79. void sh_bios_vbr_reload(void)
  80. {
  81. if (gdb_vbr_vector)
  82. __asm__ __volatile__ (
  83. "ldc %0, vbr"
  84. :
  85. : "r" (((unsigned long) gdb_vbr_vector) - 0x100)
  86. : "memory"
  87. );
  88. }
  89. #ifdef CONFIG_EARLY_PRINTK
  90. /*
  91. * Print a string through the BIOS
  92. */
  93. static void sh_console_write(struct console *co, const char *s,
  94. unsigned count)
  95. {
  96. sh_bios_console_write(s, count);
  97. }
  98. /*
  99. * Setup initial baud/bits/parity. We do two things here:
  100. * - construct a cflag setting for the first rs_open()
  101. * - initialize the serial port
  102. * Return non-zero if we didn't find a serial port.
  103. */
  104. static int __init sh_console_setup(struct console *co, char *options)
  105. {
  106. int cflag = CREAD | HUPCL | CLOCAL;
  107. /*
  108. * Now construct a cflag setting.
  109. * TODO: this is a totally bogus cflag, as we have
  110. * no idea what serial settings the BIOS is using, or
  111. * even if its using the serial port at all.
  112. */
  113. cflag |= B115200 | CS8 | /*no parity*/0;
  114. co->cflag = cflag;
  115. return 0;
  116. }
  117. static struct console bios_console = {
  118. .name = "bios",
  119. .write = sh_console_write,
  120. .setup = sh_console_setup,
  121. .flags = CON_PRINTBUFFER,
  122. .index = -1,
  123. };
  124. static int __init setup_early_printk(char *buf)
  125. {
  126. int keep_early = 0;
  127. if (!buf)
  128. return 0;
  129. if (strstr(buf, "keep"))
  130. keep_early = 1;
  131. if (!strncmp(buf, "bios", 4))
  132. early_console = &bios_console;
  133. if (likely(early_console)) {
  134. if (keep_early)
  135. early_console->flags &= ~CON_BOOT;
  136. else
  137. early_console->flags |= CON_BOOT;
  138. register_console(early_console);
  139. }
  140. return 0;
  141. }
  142. early_param("earlyprintk", setup_early_printk);
  143. #endif