phyp_console.c revision 258615
1255643Snwhitehorn/*- 2255643Snwhitehorn * Copyright (C) 2011 by Nathan Whitehorn. All rights reserved. 3255643Snwhitehorn * 4255643Snwhitehorn * Redistribution and use in source and binary forms, with or without 5255643Snwhitehorn * modification, are permitted provided that the following conditions 6255643Snwhitehorn * are met: 7255643Snwhitehorn * 1. Redistributions of source code must retain the above copyright 8255643Snwhitehorn * notice, this list of conditions and the following disclaimer. 9255643Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 10255643Snwhitehorn * notice, this list of conditions and the following disclaimer in the 11255643Snwhitehorn * documentation and/or other materials provided with the distribution. 12255643Snwhitehorn * 13255643Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14255643Snwhitehorn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15255643Snwhitehorn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16255643Snwhitehorn * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 17255643Snwhitehorn * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18255643Snwhitehorn * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 19255643Snwhitehorn * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 20255643Snwhitehorn * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 21255643Snwhitehorn * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 22255643Snwhitehorn * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23255643Snwhitehorn */ 24255643Snwhitehorn 25255643Snwhitehorn#include <sys/cdefs.h> 26255643Snwhitehorn__FBSDID("$FreeBSD: head/sys/powerpc/pseries/phyp_console.c 258615 2013-11-26 05:26:10Z andreast $"); 27255643Snwhitehorn 28255643Snwhitehorn#include <sys/param.h> 29255643Snwhitehorn#include <sys/kdb.h> 30255643Snwhitehorn#include <sys/kernel.h> 31255643Snwhitehorn#include <sys/priv.h> 32255643Snwhitehorn#include <sys/systm.h> 33255643Snwhitehorn#include <sys/module.h> 34255643Snwhitehorn#include <sys/types.h> 35255643Snwhitehorn#include <sys/conf.h> 36255643Snwhitehorn#include <sys/cons.h> 37255643Snwhitehorn#include <sys/tty.h> 38255643Snwhitehorn#include <machine/bus.h> 39255643Snwhitehorn 40255643Snwhitehorn#include <dev/ofw/openfirm.h> 41255643Snwhitehorn#include <dev/ofw/ofw_bus.h> 42255643Snwhitehorn#include <dev/ofw/ofw_bus_subr.h> 43255643Snwhitehorn#include <dev/uart/uart.h> 44255643Snwhitehorn#include <dev/uart/uart_cpu.h> 45255643Snwhitehorn#include <dev/uart/uart_bus.h> 46255643Snwhitehorn 47255643Snwhitehorn#include "phyp-hvcall.h" 48255643Snwhitehorn#include "uart_if.h" 49255643Snwhitehorn 50255643Snwhitehornstruct uart_phyp_softc { 51255643Snwhitehorn device_t dev; 52255643Snwhitehorn phandle_t node; 53255643Snwhitehorn int vtermid; 54255643Snwhitehorn 55255643Snwhitehorn struct tty *tp; 56255643Snwhitehorn struct resource *irqres; 57255643Snwhitehorn int irqrid; 58255643Snwhitehorn struct callout callout; 59255643Snwhitehorn void *sc_icookie; 60255643Snwhitehorn int polltime; 61255643Snwhitehorn 62255643Snwhitehorn struct mtx sc_mtx; 63255643Snwhitehorn int protocol; 64255643Snwhitehorn 65255643Snwhitehorn union { 66255643Snwhitehorn uint64_t u64[2]; 67255643Snwhitehorn char str[16]; 68255643Snwhitehorn } phyp_inbuf; 69255643Snwhitehorn uint64_t inbuflen; 70255643Snwhitehorn uint8_t outseqno; 71255643Snwhitehorn}; 72255643Snwhitehorn 73255643Snwhitehornstatic struct uart_phyp_softc *console_sc = NULL; 74255643Snwhitehorn#if defined(KDB) 75255643Snwhitehornstatic int alt_break_state; 76255643Snwhitehorn#endif 77255643Snwhitehorn 78255643Snwhitehornenum { 79255643Snwhitehorn HVTERM1, HVTERMPROT 80255643Snwhitehorn}; 81255643Snwhitehorn 82255643Snwhitehorn#define VS_DATA_PACKET_HEADER 0xff 83255643Snwhitehorn#define VS_CONTROL_PACKET_HEADER 0xfe 84255643Snwhitehorn#define VSV_SET_MODEM_CTL 0x01 85255643Snwhitehorn#define VSV_MODEM_CTL_UPDATE 0x02 86255643Snwhitehorn#define VSV_RENEGOTIATE_CONNECTION 0x03 87255643Snwhitehorn#define VS_QUERY_PACKET_HEADER 0xfd 88255643Snwhitehorn#define VSV_SEND_VERSION_NUMBER 0x01 89255643Snwhitehorn#define VSV_SEND_MODEM_CTL_STATUS 0x02 90255643Snwhitehorn#define VS_QUERY_RESPONSE_PACKET_HEADER 0xfc 91255643Snwhitehorn 92255643Snwhitehornstatic int uart_phyp_probe(device_t dev); 93255643Snwhitehornstatic int uart_phyp_attach(device_t dev); 94255643Snwhitehornstatic void uart_phyp_intr(void *v); 95255643Snwhitehorn 96255643Snwhitehornstatic device_method_t uart_phyp_methods[] = { 97255643Snwhitehorn /* Device interface */ 98255643Snwhitehorn DEVMETHOD(device_probe, uart_phyp_probe), 99255643Snwhitehorn DEVMETHOD(device_attach, uart_phyp_attach), 100255643Snwhitehorn 101255643Snwhitehorn DEVMETHOD_END 102255643Snwhitehorn}; 103255643Snwhitehorn 104255643Snwhitehornstatic driver_t uart_phyp_driver = { 105255643Snwhitehorn "uart", 106255643Snwhitehorn uart_phyp_methods, 107255643Snwhitehorn sizeof(struct uart_phyp_softc), 108255643Snwhitehorn}; 109255643Snwhitehorn 110255643SnwhitehornDRIVER_MODULE(uart_phyp, vdevice, uart_phyp_driver, uart_devclass, 0, 0); 111255643Snwhitehorn 112255643Snwhitehornstatic cn_probe_t uart_phyp_cnprobe; 113255643Snwhitehornstatic cn_init_t uart_phyp_cninit; 114255643Snwhitehornstatic cn_term_t uart_phyp_cnterm; 115255643Snwhitehornstatic cn_getc_t uart_phyp_cngetc; 116255643Snwhitehornstatic cn_putc_t uart_phyp_cnputc; 117255643Snwhitehornstatic cn_grab_t uart_phyp_cngrab; 118255643Snwhitehornstatic cn_ungrab_t uart_phyp_cnungrab; 119255643Snwhitehorn 120255643SnwhitehornCONSOLE_DRIVER(uart_phyp); 121255643Snwhitehorn 122255643Snwhitehornstatic void uart_phyp_ttyoutwakeup(struct tty *tp); 123255643Snwhitehorn 124255643Snwhitehornstatic struct ttydevsw uart_phyp_tty_class = { 125255643Snwhitehorn .tsw_flags = TF_INITLOCK|TF_CALLOUT, 126255643Snwhitehorn .tsw_outwakeup = uart_phyp_ttyoutwakeup, 127255643Snwhitehorn}; 128255643Snwhitehorn 129255643Snwhitehornstatic int 130255643Snwhitehornuart_phyp_probe_node(struct uart_phyp_softc *sc) 131255643Snwhitehorn{ 132255643Snwhitehorn phandle_t node = sc->node; 133255643Snwhitehorn uint32_t reg; 134255643Snwhitehorn char buf[64]; 135255643Snwhitehorn 136255643Snwhitehorn sc->inbuflen = 0; 137255643Snwhitehorn sc->outseqno = 0; 138255643Snwhitehorn 139255643Snwhitehorn if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0) 140255643Snwhitehorn return (ENXIO); 141255643Snwhitehorn if (strcmp(buf, "vty") != 0) 142255643Snwhitehorn return (ENXIO); 143255643Snwhitehorn 144255643Snwhitehorn if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0) 145255643Snwhitehorn return (ENXIO); 146255643Snwhitehorn if (strcmp(buf, "serial") != 0) 147255643Snwhitehorn return (ENXIO); 148255643Snwhitehorn 149255643Snwhitehorn reg = -1; 150255643Snwhitehorn OF_getprop(node, "reg", ®, sizeof(reg)); 151255643Snwhitehorn if (reg == -1) 152255643Snwhitehorn return (ENXIO); 153255895Snwhitehorn sc->vtermid = reg; 154255643Snwhitehorn sc->node = node; 155255643Snwhitehorn 156255643Snwhitehorn if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0) 157255643Snwhitehorn return (ENXIO); 158255643Snwhitehorn if (strcmp(buf, "hvterm1") == 0) { 159255643Snwhitehorn sc->protocol = HVTERM1; 160255643Snwhitehorn return (0); 161255643Snwhitehorn } else if (strcmp(buf, "hvterm-protocol") == 0) { 162255643Snwhitehorn sc->protocol = HVTERMPROT; 163255643Snwhitehorn return (0); 164255643Snwhitehorn } 165255643Snwhitehorn 166255643Snwhitehorn return (ENXIO); 167255643Snwhitehorn} 168255643Snwhitehorn 169255643Snwhitehornstatic int 170255643Snwhitehornuart_phyp_probe(device_t dev) 171255643Snwhitehorn{ 172255643Snwhitehorn const char *name; 173255643Snwhitehorn struct uart_phyp_softc sc; 174255643Snwhitehorn int err; 175255643Snwhitehorn 176255643Snwhitehorn name = ofw_bus_get_name(dev); 177255643Snwhitehorn if (name == NULL || strcmp(name, "vty") != 0) 178255643Snwhitehorn return (ENXIO); 179255643Snwhitehorn 180255643Snwhitehorn sc.node = ofw_bus_get_node(dev); 181255643Snwhitehorn err = uart_phyp_probe_node(&sc); 182255643Snwhitehorn if (err != 0) 183255643Snwhitehorn return (err); 184255643Snwhitehorn 185255643Snwhitehorn device_set_desc(dev, "POWER Hypervisor Virtual Serial Port"); 186255643Snwhitehorn 187255643Snwhitehorn return (err); 188255643Snwhitehorn} 189255643Snwhitehorn 190255643Snwhitehornstatic void 191255643Snwhitehornuart_phyp_cnprobe(struct consdev *cp) 192255643Snwhitehorn{ 193255643Snwhitehorn char buf[64]; 194255643Snwhitehorn ihandle_t stdout; 195255643Snwhitehorn phandle_t input, opts, chosen; 196255643Snwhitehorn static struct uart_phyp_softc sc; 197255643Snwhitehorn 198255643Snwhitehorn if ((opts = OF_finddevice("/options")) == -1) 199255643Snwhitehorn goto fail; 200255643Snwhitehorn if ((chosen = OF_finddevice("/chosen")) == -1) 201255643Snwhitehorn goto fail; 202255643Snwhitehorn 203255643Snwhitehorn /* Check if OF has an active stdin/stdout */ 204255643Snwhitehorn input = -1; 205255643Snwhitehorn if (OF_getprop(chosen, "stdout", &stdout, 206255643Snwhitehorn sizeof(stdout)) == sizeof(stdout) && stdout != 0) 207255643Snwhitehorn input = OF_instance_to_package(stdout); 208255643Snwhitehorn if (input == -1) 209255643Snwhitehorn goto fail; 210255643Snwhitehorn 211255643Snwhitehorn if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1) 212255643Snwhitehorn goto fail; 213255643Snwhitehorn if (strcmp(buf, "serial") != 0) 214255643Snwhitehorn goto fail; 215255643Snwhitehorn 216255643Snwhitehorn sc.node = input; 217255643Snwhitehorn if (uart_phyp_probe_node(&sc) != 0) 218255643Snwhitehorn goto fail; 219255643Snwhitehorn mtx_init(&sc.sc_mtx, "uart_phyp", NULL, MTX_SPIN | MTX_QUIET | 220255643Snwhitehorn MTX_NOWITNESS); 221255643Snwhitehorn 222255643Snwhitehorn cp->cn_pri = CN_NORMAL; 223255643Snwhitehorn console_sc = ≻ 224255643Snwhitehorn return; 225255643Snwhitehorn 226255643Snwhitehornfail: 227255643Snwhitehorn cp->cn_pri = CN_DEAD; 228255643Snwhitehorn return; 229255643Snwhitehorn} 230255643Snwhitehorn 231255643Snwhitehornstatic int 232255643Snwhitehornuart_phyp_attach(device_t dev) 233255643Snwhitehorn{ 234255643Snwhitehorn struct uart_phyp_softc *sc; 235255643Snwhitehorn int unit; 236255643Snwhitehorn 237255643Snwhitehorn sc = device_get_softc(dev); 238255643Snwhitehorn sc->dev = dev; 239255643Snwhitehorn sc->node = ofw_bus_get_node(dev); 240255643Snwhitehorn uart_phyp_probe_node(sc); 241255643Snwhitehorn 242255643Snwhitehorn unit = device_get_unit(dev); 243255643Snwhitehorn sc->tp = tty_alloc(&uart_phyp_tty_class, sc); 244255643Snwhitehorn mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, 245255643Snwhitehorn MTX_SPIN | MTX_QUIET | MTX_NOWITNESS); 246255643Snwhitehorn 247255643Snwhitehorn if (console_sc != NULL && console_sc->vtermid == sc->vtermid) { 248255643Snwhitehorn sc->outseqno = console_sc->outseqno; 249255643Snwhitehorn console_sc = sc; 250255643Snwhitehorn sprintf(uart_phyp_consdev.cn_name, "ttyu%r", unit); 251255643Snwhitehorn tty_init_console(sc->tp, 0); 252255643Snwhitehorn } 253255643Snwhitehorn 254255643Snwhitehorn sc->irqrid = 0; 255255643Snwhitehorn sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid, 256255643Snwhitehorn RF_ACTIVE | RF_SHAREABLE); 257255643Snwhitehorn if (sc->irqres != NULL) { 258255643Snwhitehorn bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE, 259255643Snwhitehorn NULL, uart_phyp_intr, sc, &sc->sc_icookie); 260255643Snwhitehorn } else { 261255643Snwhitehorn callout_init(&sc->callout, CALLOUT_MPSAFE); 262255643Snwhitehorn sc->polltime = hz / 20; 263255643Snwhitehorn if (sc->polltime < 1) 264255643Snwhitehorn sc->polltime = 1; 265255643Snwhitehorn callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc); 266255643Snwhitehorn } 267255643Snwhitehorn 268255643Snwhitehorn tty_makedev(sc->tp, NULL, "u%r", unit); 269255643Snwhitehorn 270255643Snwhitehorn return (0); 271255643Snwhitehorn} 272255643Snwhitehorn 273255643Snwhitehornstatic void 274255643Snwhitehornuart_phyp_cninit(struct consdev *cp) 275255643Snwhitehorn{ 276255643Snwhitehorn 277255643Snwhitehorn strcpy(cp->cn_name, "phypcons"); 278255643Snwhitehorn} 279255643Snwhitehorn 280255643Snwhitehornstatic void 281255643Snwhitehornuart_phyp_cnterm(struct consdev *cp) 282255643Snwhitehorn{ 283255643Snwhitehorn} 284255643Snwhitehorn 285255643Snwhitehornstatic int 286255643Snwhitehornuart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) 287255643Snwhitehorn{ 288255643Snwhitehorn int err; 289258615Sandreast int hdr = 0; 290255643Snwhitehorn 291255643Snwhitehorn uart_lock(&sc->sc_mtx); 292255643Snwhitehorn if (sc->inbuflen == 0) { 293255643Snwhitehorn err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid, 294255643Snwhitehorn 0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0], 295255643Snwhitehorn &sc->phyp_inbuf.u64[1]); 296255643Snwhitehorn if (err != H_SUCCESS) { 297255643Snwhitehorn uart_unlock(&sc->sc_mtx); 298255643Snwhitehorn return (-1); 299255643Snwhitehorn } 300258615Sandreast hdr = 1; 301255643Snwhitehorn } 302255643Snwhitehorn 303255643Snwhitehorn if (sc->inbuflen == 0) { 304255643Snwhitehorn uart_unlock(&sc->sc_mtx); 305255643Snwhitehorn return (0); 306255643Snwhitehorn } 307255643Snwhitehorn 308255643Snwhitehorn if (bufsize > sc->inbuflen) 309255643Snwhitehorn bufsize = sc->inbuflen; 310258615Sandreast 311258615Sandreast if ((sc->protocol == HVTERMPROT) && (hdr == 1)) { 312258615Sandreast sc->inbuflen = sc->inbuflen - 4; 313258615Sandreast /* The VTERM protocol has a 4 byte header, skip it here. */ 314258615Sandreast memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[4], 315258615Sandreast sc->inbuflen); 316258615Sandreast } 317258615Sandreast 318255643Snwhitehorn memcpy(buffer, sc->phyp_inbuf.str, bufsize); 319255643Snwhitehorn sc->inbuflen -= bufsize; 320255643Snwhitehorn if (sc->inbuflen > 0) 321255643Snwhitehorn memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize], 322255643Snwhitehorn sc->inbuflen); 323255643Snwhitehorn 324255643Snwhitehorn uart_unlock(&sc->sc_mtx); 325255643Snwhitehorn return (bufsize); 326255643Snwhitehorn} 327255643Snwhitehorn 328255643Snwhitehornstatic int 329255643Snwhitehornuart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize) 330255643Snwhitehorn{ 331255643Snwhitehorn uint16_t seqno; 332255643Snwhitehorn uint64_t len = 0; 333258615Sandreast int err; 334258615Sandreast 335255643Snwhitehorn union { 336258615Sandreast uint64_t u64[2]; 337258615Sandreast char bytes[16]; 338255643Snwhitehorn } cbuf; 339255643Snwhitehorn 340255643Snwhitehorn uart_lock(&sc->sc_mtx); 341255643Snwhitehorn switch (sc->protocol) { 342255643Snwhitehorn case HVTERM1: 343258615Sandreast if (bufsize > 16) 344258615Sandreast bufsize = 16; 345255643Snwhitehorn memcpy(&cbuf, buffer, bufsize); 346255643Snwhitehorn len = bufsize; 347255643Snwhitehorn break; 348255643Snwhitehorn case HVTERMPROT: 349258615Sandreast if (bufsize > 12) 350258615Sandreast bufsize = 12; 351255643Snwhitehorn seqno = sc->outseqno++; 352255643Snwhitehorn cbuf.bytes[0] = VS_DATA_PACKET_HEADER; 353258615Sandreast cbuf.bytes[1] = 4 + bufsize; /* total length, max 16 bytes */ 354255643Snwhitehorn cbuf.bytes[2] = (seqno >> 8) & 0xff; 355255643Snwhitehorn cbuf.bytes[3] = seqno & 0xff; 356255643Snwhitehorn memcpy(&cbuf.bytes[4], buffer, bufsize); 357255643Snwhitehorn len = 4 + bufsize; 358255643Snwhitehorn break; 359255643Snwhitehorn } 360258615Sandreast 361258615Sandreast do { 362258615Sandreast err = phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64[0], 363258615Sandreast cbuf.u64[1]); 364258615Sandreast DELAY(100); 365258615Sandreast } while (err == H_BUSY); 366258615Sandreast 367255643Snwhitehorn uart_unlock(&sc->sc_mtx); 368255643Snwhitehorn 369255643Snwhitehorn return (bufsize); 370255643Snwhitehorn} 371255643Snwhitehorn 372255643Snwhitehornstatic int 373255643Snwhitehornuart_phyp_cngetc(struct consdev *cp) 374255643Snwhitehorn{ 375255643Snwhitehorn unsigned char c; 376255643Snwhitehorn int retval; 377255643Snwhitehorn 378255643Snwhitehorn retval = uart_phyp_get(console_sc, &c, 1); 379255643Snwhitehorn if (retval != 1) 380255643Snwhitehorn return (-1); 381255643Snwhitehorn#if defined(KDB) 382255643Snwhitehorn kdb_alt_break(c, &alt_break_state); 383255643Snwhitehorn#endif 384255643Snwhitehorn 385255643Snwhitehorn return (c); 386255643Snwhitehorn} 387255643Snwhitehorn 388255643Snwhitehornstatic void 389255643Snwhitehornuart_phyp_cnputc(struct consdev *cp, int c) 390255643Snwhitehorn{ 391255643Snwhitehorn unsigned char ch = c; 392255643Snwhitehorn uart_phyp_put(console_sc, &ch, 1); 393255643Snwhitehorn} 394255643Snwhitehorn 395255643Snwhitehornstatic void 396255643Snwhitehornuart_phyp_cngrab(struct consdev *cp) 397255643Snwhitehorn{ 398255643Snwhitehorn} 399255643Snwhitehorn 400255643Snwhitehornstatic void 401255643Snwhitehornuart_phyp_cnungrab(struct consdev *cp) 402255643Snwhitehorn{ 403255643Snwhitehorn} 404255643Snwhitehorn 405255643Snwhitehornstatic void 406255643Snwhitehornuart_phyp_ttyoutwakeup(struct tty *tp) 407255643Snwhitehorn{ 408255643Snwhitehorn struct uart_phyp_softc *sc; 409255643Snwhitehorn char buffer[8]; 410255643Snwhitehorn int len; 411255643Snwhitehorn 412255643Snwhitehorn sc = tty_softc(tp); 413255643Snwhitehorn 414255643Snwhitehorn while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0) 415255643Snwhitehorn uart_phyp_put(sc, buffer, len); 416255643Snwhitehorn} 417255643Snwhitehorn 418255643Snwhitehornstatic void 419255643Snwhitehornuart_phyp_intr(void *v) 420255643Snwhitehorn{ 421255643Snwhitehorn struct uart_phyp_softc *sc = v; 422255643Snwhitehorn struct tty *tp = sc->tp; 423255643Snwhitehorn unsigned char c; 424255643Snwhitehorn int len; 425255643Snwhitehorn 426255643Snwhitehorn tty_lock(tp); 427255643Snwhitehorn while ((len = uart_phyp_get(sc, &c, 1)) > 0) 428255643Snwhitehorn ttydisc_rint(tp, c, 0); 429255643Snwhitehorn ttydisc_rint_done(tp); 430255643Snwhitehorn tty_unlock(tp); 431255643Snwhitehorn 432255643Snwhitehorn if (sc->irqres == NULL) 433255643Snwhitehorn callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc); 434255643Snwhitehorn} 435255643Snwhitehorn 436