sunhv.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /* sunhv.c: Serial driver for SUN4V hypervisor console.
  2. *
  3. * Copyright (C) 2006 David S. Miller (davem@davemloft.net)
  4. */
  5. #include <linux/module.h>
  6. #include <linux/kernel.h>
  7. #include <linux/errno.h>
  8. #include <linux/tty.h>
  9. #include <linux/tty_flip.h>
  10. #include <linux/major.h>
  11. #include <linux/circ_buf.h>
  12. #include <linux/serial.h>
  13. #include <linux/sysrq.h>
  14. #include <linux/console.h>
  15. #include <linux/spinlock.h>
  16. #include <linux/slab.h>
  17. #include <linux/delay.h>
  18. #include <linux/init.h>
  19. #include <asm/hypervisor.h>
  20. #include <asm/spitfire.h>
  21. #include <asm/vdev.h>
  22. #include <asm/irq.h>
  23. #if defined(CONFIG_MAGIC_SYSRQ)
  24. #define SUPPORT_SYSRQ
  25. #endif
  26. #include <linux/serial_core.h>
  27. #include "suncore.h"
  28. #define CON_BREAK ((long)-1)
  29. #define CON_HUP ((long)-2)
  30. static inline long hypervisor_con_getchar(long *status)
  31. {
  32. register unsigned long func asm("%o5");
  33. register unsigned long arg0 asm("%o0");
  34. register unsigned long arg1 asm("%o1");
  35. func = HV_FAST_CONS_GETCHAR;
  36. arg0 = 0;
  37. arg1 = 0;
  38. __asm__ __volatile__("ta %6"
  39. : "=&r" (func), "=&r" (arg0), "=&r" (arg1)
  40. : "0" (func), "1" (arg0), "2" (arg1),
  41. "i" (HV_FAST_TRAP));
  42. *status = arg0;
  43. return (long) arg1;
  44. }
  45. static inline long hypervisor_con_putchar(long ch)
  46. {
  47. register unsigned long func asm("%o5");
  48. register unsigned long arg0 asm("%o0");
  49. func = HV_FAST_CONS_PUTCHAR;
  50. arg0 = ch;
  51. __asm__ __volatile__("ta %4"
  52. : "=&r" (func), "=&r" (arg0)
  53. : "0" (func), "1" (arg0), "i" (HV_FAST_TRAP));
  54. return (long) arg0;
  55. }
  56. #define IGNORE_BREAK 0x1
  57. #define IGNORE_ALL 0x2
  58. static int hung_up = 0;
  59. static struct tty_struct *receive_chars(struct uart_port *port, struct pt_regs *regs)
  60. {
  61. struct tty_struct *tty = NULL;
  62. int saw_console_brk = 0;
  63. int limit = 10000;
  64. if (port->info != NULL) /* Unopened serial console */
  65. tty = port->info->tty;
  66. while (limit-- > 0) {
  67. long status;
  68. long c = hypervisor_con_getchar(&status);
  69. unsigned char flag;
  70. if (status == HV_EWOULDBLOCK)
  71. break;
  72. if (c == CON_BREAK) {
  73. saw_console_brk = 1;
  74. c = 0;
  75. }
  76. if (c == CON_HUP) {
  77. hung_up = 1;
  78. uart_handle_dcd_change(port, 0);
  79. } else if (hung_up) {
  80. hung_up = 0;
  81. uart_handle_dcd_change(port, 1);
  82. }
  83. if (tty == NULL) {
  84. uart_handle_sysrq_char(port, c, regs);
  85. continue;
  86. }
  87. flag = TTY_NORMAL;
  88. port->icount.rx++;
  89. if (c == CON_BREAK) {
  90. port->icount.brk++;
  91. if (uart_handle_break(port))
  92. continue;
  93. flag = TTY_BREAK;
  94. }
  95. if (uart_handle_sysrq_char(port, c, regs))
  96. continue;
  97. if ((port->ignore_status_mask & IGNORE_ALL) ||
  98. ((port->ignore_status_mask & IGNORE_BREAK) &&
  99. (c == CON_BREAK)))
  100. continue;
  101. tty_insert_flip_char(tty, c, flag);
  102. }
  103. if (saw_console_brk)
  104. sun_do_break();
  105. return tty;
  106. }
  107. static void transmit_chars(struct uart_port *port)
  108. {
  109. struct circ_buf *xmit = &port->info->xmit;
  110. if (uart_circ_empty(xmit) || uart_tx_stopped(port))
  111. return;
  112. while (!uart_circ_empty(xmit)) {
  113. long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
  114. if (status != HV_EOK)
  115. break;
  116. xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  117. port->icount.tx++;
  118. }
  119. if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
  120. uart_write_wakeup(port);
  121. }
  122. static irqreturn_t sunhv_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  123. {
  124. struct uart_port *port = dev_id;
  125. struct tty_struct *tty;
  126. unsigned long flags;
  127. spin_lock_irqsave(&port->lock, flags);
  128. tty = receive_chars(port, regs);
  129. transmit_chars(port);
  130. spin_unlock_irqrestore(&port->lock, flags);
  131. if (tty)
  132. tty_flip_buffer_push(tty);
  133. return IRQ_HANDLED;
  134. }
  135. /* port->lock is not held. */
  136. static unsigned int sunhv_tx_empty(struct uart_port *port)
  137. {
  138. /* Transmitter is always empty for us. If the circ buffer
  139. * is non-empty or there is an x_char pending, our caller
  140. * will do the right thing and ignore what we return here.
  141. */
  142. return TIOCSER_TEMT;
  143. }
  144. /* port->lock held by caller. */
  145. static void sunhv_set_mctrl(struct uart_port *port, unsigned int mctrl)
  146. {
  147. return;
  148. }
  149. /* port->lock is held by caller and interrupts are disabled. */
  150. static unsigned int sunhv_get_mctrl(struct uart_port *port)
  151. {
  152. return TIOCM_DSR | TIOCM_CAR | TIOCM_CTS;
  153. }
  154. /* port->lock held by caller. */
  155. static void sunhv_stop_tx(struct uart_port *port)
  156. {
  157. return;
  158. }
  159. /* port->lock held by caller. */
  160. static void sunhv_start_tx(struct uart_port *port)
  161. {
  162. struct circ_buf *xmit = &port->info->xmit;
  163. unsigned long flags;
  164. spin_lock_irqsave(&port->lock, flags);
  165. while (!uart_circ_empty(xmit)) {
  166. long status = hypervisor_con_putchar(xmit->buf[xmit->tail]);
  167. if (status != HV_EOK)
  168. break;
  169. xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
  170. port->icount.tx++;
  171. }
  172. spin_unlock_irqrestore(&port->lock, flags);
  173. }
  174. /* port->lock is not held. */
  175. static void sunhv_send_xchar(struct uart_port *port, char ch)
  176. {
  177. unsigned long flags;
  178. int limit = 10000;
  179. spin_lock_irqsave(&port->lock, flags);
  180. while (limit-- > 0) {
  181. long status = hypervisor_con_putchar(ch);
  182. if (status == HV_EOK)
  183. break;
  184. }
  185. spin_unlock_irqrestore(&port->lock, flags);
  186. }
  187. /* port->lock held by caller. */
  188. static void sunhv_stop_rx(struct uart_port *port)
  189. {
  190. }
  191. /* port->lock held by caller. */
  192. static void sunhv_enable_ms(struct uart_port *port)
  193. {
  194. }
  195. /* port->lock is not held. */
  196. static void sunhv_break_ctl(struct uart_port *port, int break_state)
  197. {
  198. if (break_state) {
  199. unsigned long flags;
  200. int limit = 10000;
  201. spin_lock_irqsave(&port->lock, flags);
  202. while (limit-- > 0) {
  203. long status = hypervisor_con_putchar(CON_BREAK);
  204. if (status == HV_EOK)
  205. break;
  206. }
  207. spin_unlock_irqrestore(&port->lock, flags);
  208. }
  209. }
  210. /* port->lock is not held. */
  211. static int sunhv_startup(struct uart_port *port)
  212. {
  213. return 0;
  214. }
  215. /* port->lock is not held. */
  216. static void sunhv_shutdown(struct uart_port *port)
  217. {
  218. }
  219. /* port->lock is not held. */
  220. static void sunhv_set_termios(struct uart_port *port, struct termios *termios,
  221. struct termios *old)
  222. {
  223. unsigned int baud = uart_get_baud_rate(port, termios, old, 0, 4000000);
  224. unsigned int quot = uart_get_divisor(port, baud);
  225. unsigned int iflag, cflag;
  226. unsigned long flags;
  227. spin_lock_irqsave(&port->lock, flags);
  228. iflag = termios->c_iflag;
  229. cflag = termios->c_cflag;
  230. port->ignore_status_mask = 0;
  231. if (iflag & IGNBRK)
  232. port->ignore_status_mask |= IGNORE_BREAK;
  233. if ((cflag & CREAD) == 0)
  234. port->ignore_status_mask |= IGNORE_ALL;
  235. /* XXX */
  236. uart_update_timeout(port, cflag,
  237. (port->uartclk / (16 * quot)));
  238. spin_unlock_irqrestore(&port->lock, flags);
  239. }
  240. static const char *sunhv_type(struct uart_port *port)
  241. {
  242. return "SUN4V HCONS";
  243. }
  244. static void sunhv_release_port(struct uart_port *port)
  245. {
  246. }
  247. static int sunhv_request_port(struct uart_port *port)
  248. {
  249. return 0;
  250. }
  251. static void sunhv_config_port(struct uart_port *port, int flags)
  252. {
  253. }
  254. static int sunhv_verify_port(struct uart_port *port, struct serial_struct *ser)
  255. {
  256. return -EINVAL;
  257. }
  258. static struct uart_ops sunhv_pops = {
  259. .tx_empty = sunhv_tx_empty,
  260. .set_mctrl = sunhv_set_mctrl,
  261. .get_mctrl = sunhv_get_mctrl,
  262. .stop_tx = sunhv_stop_tx,
  263. .start_tx = sunhv_start_tx,
  264. .send_xchar = sunhv_send_xchar,
  265. .stop_rx = sunhv_stop_rx,
  266. .enable_ms = sunhv_enable_ms,
  267. .break_ctl = sunhv_break_ctl,
  268. .startup = sunhv_startup,
  269. .shutdown = sunhv_shutdown,
  270. .set_termios = sunhv_set_termios,
  271. .type = sunhv_type,
  272. .release_port = sunhv_release_port,
  273. .request_port = sunhv_request_port,
  274. .config_port = sunhv_config_port,
  275. .verify_port = sunhv_verify_port,
  276. };
  277. static struct uart_driver sunhv_reg = {
  278. .owner = THIS_MODULE,
  279. .driver_name = "serial",
  280. .devfs_name = "tts/",
  281. .dev_name = "ttyS",
  282. .major = TTY_MAJOR,
  283. };
  284. static struct uart_port *sunhv_port;
  285. static inline void sunhv_console_putchar(struct uart_port *port, char c)
  286. {
  287. unsigned long flags;
  288. int limit = 10000;
  289. spin_lock_irqsave(&port->lock, flags);
  290. while (limit-- > 0) {
  291. long status = hypervisor_con_putchar(c);
  292. if (status == HV_EOK)
  293. break;
  294. }
  295. spin_unlock_irqrestore(&port->lock, flags);
  296. }
  297. static void sunhv_console_write(struct console *con, const char *s, unsigned n)
  298. {
  299. struct uart_port *port = sunhv_port;
  300. int i;
  301. for (i = 0; i < n; i++) {
  302. if (*s == '\n')
  303. sunhv_console_putchar(port, '\r');
  304. sunhv_console_putchar(port, *s++);
  305. }
  306. }
  307. static int sunhv_console_setup(struct console *con, char *options)
  308. {
  309. return 0;
  310. }
  311. static struct console sunhv_console = {
  312. .name = "ttyS",
  313. .write = sunhv_console_write,
  314. .device = uart_console_device,
  315. .setup = sunhv_console_setup,
  316. .flags = CON_PRINTBUFFER,
  317. .index = -1,
  318. .data = &sunhv_reg,
  319. };
  320. static void __init sunhv_console_init(void)
  321. {
  322. if (con_is_present())
  323. return;
  324. sunhv_console.index = 0;
  325. register_console(&sunhv_console);
  326. }
  327. static int __init hv_console_compatible(char *buf, int len)
  328. {
  329. while (len) {
  330. int this_len;
  331. if (!strcmp(buf, "qcn"))
  332. return 1;
  333. this_len = strlen(buf) + 1;
  334. buf += this_len;
  335. len -= this_len;
  336. }
  337. return 0;
  338. }
  339. static unsigned int __init get_interrupt(void)
  340. {
  341. const char *cons_str = "console";
  342. const char *compat_str = "compatible";
  343. int node = prom_getchild(sun4v_vdev_root);
  344. unsigned int irq;
  345. char buf[64];
  346. int err, len;
  347. node = prom_searchsiblings(node, cons_str);
  348. if (!node)
  349. return 0;
  350. len = prom_getproplen(node, compat_str);
  351. if (len == 0 || len == -1)
  352. return 0;
  353. err = prom_getproperty(node, compat_str, buf, 64);
  354. if (err == -1)
  355. return 0;
  356. if (!hv_console_compatible(buf, len))
  357. return 0;
  358. /* Ok, the this is the OBP node for the sun4v hypervisor
  359. * console device. Decode the interrupt.
  360. */
  361. err = prom_getproperty(node, "interrupts",
  362. (char *) &irq, sizeof(irq));
  363. if (err == -1)
  364. return 0;
  365. return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0);
  366. }
  367. static u32 sunhv_irq;
  368. static int __init sunhv_init(void)
  369. {
  370. struct uart_port *port;
  371. int ret;
  372. if (tlb_type != hypervisor)
  373. return -ENODEV;
  374. sunhv_irq = get_interrupt();
  375. if (!sunhv_irq)
  376. return -ENODEV;
  377. port = kmalloc(sizeof(struct uart_port), GFP_KERNEL);
  378. if (unlikely(!port))
  379. return -ENOMEM;
  380. port->line = 0;
  381. port->ops = &sunhv_pops;
  382. port->type = PORT_SUNHV;
  383. port->uartclk = ( 29491200 / 16 ); /* arbitrary */
  384. if (request_irq(sunhv_irq, sunhv_interrupt,
  385. SA_SHIRQ, "serial(sunhv)", port)) {
  386. printk("sunhv: Cannot get IRQ %x\n", sunhv_irq);
  387. kfree(port);
  388. return -ENODEV;
  389. }
  390. printk("SUNHV: SUN4V virtual console, IRQ[%08x]\n",
  391. sunhv_irq);
  392. sunhv_reg.minor = sunserial_current_minor;
  393. sunhv_reg.nr = 1;
  394. sunhv_reg.cons = &sunhv_console;
  395. ret = uart_register_driver(&sunhv_reg);
  396. if (ret < 0) {
  397. free_irq(sunhv_irq, up);
  398. kfree(port);
  399. return ret;
  400. }
  401. sunhv_port = port;
  402. sunserial_current_minor += 1;
  403. sunhv_console_init();
  404. uart_add_one_port(&sunhv_reg, port);
  405. return 0;
  406. }
  407. static void __exit sunhv_exit(void)
  408. {
  409. struct uart_port *port = sunhv_port;
  410. BUG_ON(!port);
  411. uart_remove_one_port(&sunhv_reg, port);
  412. free_irq(sunhv_irq, port);
  413. sunserial_current_minor -= 1;
  414. uart_unregister_driver(&sunhv_reg);
  415. kfree(sunhv_port);
  416. sunhv_port = NULL;
  417. }
  418. module_init(sunhv_init);
  419. module_exit(sunhv_exit);
  420. MODULE_AUTHOR("David S. Miller");
  421. MODULE_DESCRIPTION("SUN4V Hypervisor console driver")
  422. MODULE_LICENSE("GPL");